[SCM] calf/master: + Framework: separated midi_mixin into event_mixin and midi_mixin which is dependent on it + LV2: updated lv2_event.h + Small modules: removed notefilter_e and notefilter2_e, added a bunch of trivial inflexible MIDI filters for different classes of messages (plus some base class to make future, more complex filter easier to write), added a new utility category (MIDI)
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:37:43 UTC 2013
The following commit has been merged in the master branch:
commit b298843d3b34cb603b7b4bdca848c959713d2da9
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date: Fri Oct 10 20:46:59 2008 +0000
+ Framework: separated midi_mixin into event_mixin and midi_mixin which is dependent on it
+ LV2: updated lv2_event.h
+ Small modules: removed notefilter_e and notefilter2_e, added a bunch of trivial inflexible MIDI filters for different classes of messages (plus some base class to make future, more complex filter easier to write), added a new utility category (MIDI)
git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@327 78b06b96-2940-0410-b7fc-879d825d01d8
diff --git a/src/calf/lv2_event.h b/src/calf/lv2_event.h
index ed306f9..6ea90c8 100644
--- a/src/calf/lv2_event.h
+++ b/src/calf/lv2_event.h
@@ -84,13 +84,13 @@ typedef struct {
* There are special rules which must be followed depending on the type
* of an event. If the plugin recognizes an event type, the definition
* of that event type will describe how to interpret the event, and
- * any required behaviour. Otherwise (if the plugin does not understand
- * the event type), lv2_event_drop must be called if the event is 'dropped'
- * (see above). Even if the plugin does not understand an event, it may
- * pass the event through to an output by simply copying (and NOT calling
- * lv2_event_drop). These rules are designed to allow for generic event
- * handling plugins and large non-POD events, but with minimal hassle on
- * simple plugins that "don't care" about these more advanced features.
+ * any required behaviour. Otherwise, if the type is 0, this event is a
+ * non-POD event and lv2_event_unref MUST be called if the event is
+ * 'dropped' (see above). Even if the plugin does not understand an event,
+ * it may pass the event through to an output by simply copying (and NOT
+ * calling lv2_event_unref). These rules are designed to allow for generic
+ * event handling plugins and large non-POD events, but with minimal hassle
+ * on simple plugins that "don't care" about these more advanced features.
*/
uint16_t type;
@@ -209,6 +209,29 @@ typedef struct {
*/
LV2_Event_Callback_Data callback_data;
+ /** Take a reference to a non-POD event.
+ *
+ * If a plugin receives an event with type 0, it means the event is a
+ * pointer to some object in memory and not a flat sequence of bytes
+ * in the buffer. When receiving a non-POD event, the plugin already
+ * has an implicit reference to the event. If the event is stored AND
+ * passed to an output, lv2_event_ref MUST be called on that event.
+ * If the event is only stored OR passed through, this is not necessary
+ * (as the plugin already has 1 implicit reference).
+ *
+ * @param event An event received at an input that will not be copied to
+ * an output or stored in any way.
+ * @param context The calling context. (Like event types) this is a mapped
+ * URI, see lv2_context.h. Simple plugin with just a run()
+ * method should pass 0 here (the ID of the 'standard' LV2
+ * run context). The host guarantees that this function is
+ * realtime safe iff @a context is realtime safe.
+ *
+ * PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS.
+ */
+ uint32_t (*lv2_event_ref)(LV2_Event_Callback_Data callback_data,
+ LV2_Event* event);
+
/** Drop a reference to a non-POD event.
*
* If a plugin receives an event with type 0, it means the event is a
@@ -227,9 +250,8 @@ typedef struct {
*
* PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS.
*/
- uint32_t (*lv2_event_drop)(LV2_Event_Callback_Data callback_data,
- LV2_Event* event,
- uint32_t context);
+ uint32_t (*lv2_event_unref)(LV2_Event_Callback_Data callback_data,
+ LV2_Event* event);
} LV2_Event_Feature;
diff --git a/src/calf/lv2helpers.h b/src/calf/lv2helpers.h
index 565e8de..deae345 100644
--- a/src/calf/lv2helpers.h
+++ b/src/calf/lv2helpers.h
@@ -23,15 +23,35 @@
#if USE_LV2
-/// A mixin for adding the event feature, URI map and MIDI event type retrieval to small plugins
-/// @todo refactor into separate event feature, URI map and MIDI event type mixins some day
+/// A mixin for adding the event feature to the small plugin
template<class T>
-class midi_mixin: public T
+class event_mixin: public T
{
public:
+ /// Event feature pointer
+ LV2_Event_Feature *event_feature;
+ virtual void use_feature(const char *URI, void *data) {
+ if (!strcmp(URI, LV2_EVENT_URI))
+ {
+ event_feature = (LV2_Event_Feature *)data;
+ }
+ T::use_feature(URI, data);
+ }
+ /// Create a reference
+ inline void ref_event(LV2_Event *event) { event_feature->lv2_event_ref(event_feature->callback_data, event); }
+ /// Destroy a reference
+ inline void unref_event(LV2_Event *event) { event_feature->lv2_event_unref(event_feature->callback_data, event); }
+};
+
+/// A mixin for adding the URI map and MIDI event type retrieval to small plugins
+template<class T>
+class midi_mixin: public event_mixin<T>
+{
+public:
+ /// URI map feature pointer
LV2_URI_Map_Feature *uri_map;
+ /// MIDI event ID, as resolved using the URI map feature
uint32_t midi_event_type;
- LV2_Event_Feature *event_feature;
virtual void use_feature(const char *URI, void *data) {
if (!strcmp(URI, LV2_URI_MAP_URI))
{
@@ -40,11 +60,7 @@ public:
"http://lv2plug.in/ns/ext/event",
"http://lv2plug.in/ns/ext/midi#MidiEvent");
}
- else if (!strcmp(URI, LV2_EVENT_URI))
- {
- event_feature = (LV2_Event_Feature *)data;
- }
- T::use_feature(URI, data);
+ event_mixin<T>::use_feature(URI, data);
}
};
diff --git a/src/calf/modulelist.h b/src/calf/modulelist.h
index b7e2dae..bd2eda0 100644
--- a/src/calf/modulelist.h
+++ b/src/calf/modulelist.h
@@ -40,8 +40,12 @@
PER_SMALL_MODULE_ITEM(print_e, "print_e")
PER_SMALL_MODULE_ITEM(print_em, "print_em")
PER_SMALL_MODULE_ITEM(copy_em, "copy_em")
- PER_SMALL_MODULE_ITEM(notefilter_e, "notefilter_e")
- PER_SMALL_MODULE_ITEM(notefilter2_e, "notefilter2_e")
+ PER_SMALL_MODULE_ITEM(notefilter_m, "notefilter_m")
+ PER_SMALL_MODULE_ITEM(ccfilter_m, "ccfilter_m")
+ PER_SMALL_MODULE_ITEM(pcfilter_m, "pcfilter_m")
+ PER_SMALL_MODULE_ITEM(pressurefilter_m, "pressurefilter_m")
+ PER_SMALL_MODULE_ITEM(pitchbendfilter_m, "pitchbendfilter_m")
+ PER_SMALL_MODULE_ITEM(systemfilter_m, "systemfilter_m")
PER_SMALL_MODULE_ITEM(eventmerge_e, "eventmerge_e")
PER_SMALL_MODULE_ITEM(quadpower_a, "quadpower_a")
PER_SMALL_MODULE_ITEM(quadpower_c, "quadpower_c")
diff --git a/src/makerdf.cpp b/src/makerdf.cpp
index c3cfa70..c947540 100644
--- a/src/makerdf.cpp
+++ b/src/makerdf.cpp
@@ -491,9 +491,10 @@ void make_manifest()
"@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n"
"@prefix kf: <http://foltman.com/ns/> .\n"
"\n"
- "kf:BooleanPlugin a rdfs:Class ; rdfs:label \"Boolean-oriented\" ; rdfs:subClassOf lv2:UtilityPlugin ; rdfs:comment \"\"\"Modules heavily inspired by digital electronics (gates, flip-flops)\"\"\" .\n"
+ "kf:BooleanPlugin a rdfs:Class ; rdfs:label \"Boolean-oriented\" ; rdfs:subClassOf lv2:UtilityPlugin ; rdfs:comment \"\"\"Modules heavily inspired by digital electronics (gates, flip-flops etc.)\"\"\" .\n"
"kf:MathOperatorPlugin a rdfs:Class ; rdfs:label \"Math operators\" ; rdfs:subClassOf lv2:UtilityPlugin ; rdfs:comment \"\"\"Mathematical operators and utility functions\"\"\" .\n"
- "kf:IntegerPlugin a rdfs:Class ; rdfs:label \"Integer-oriented\" ; rdfs:subClassOf lv2:UtilityPlugin ; rdfs:comment \"\"\"Operations using integer values (counters, multiplexers)\"\"\" .\n"
+ "kf:IntegerPlugin a rdfs:Class ; rdfs:label \"Integer-oriented\" ; rdfs:subClassOf lv2:UtilityPlugin ; rdfs:comment \"\"\"Operations using integer values (counters, multiplexers etc.)\"\"\" .\n"
+ "kf:MIDIPlugin a rdfs:Class ; rdfs:label \"MIDI\" ; rdfs:subClassOf lv2:UtilityPlugin ; rdfs:comment \"\"\"Operations on MIDI streams (filters, transposers, mappers etc.)\"\"\" .\n"
;
vector<synth::giface_plugin_info> plugins;
diff --git a/src/modules_small.cpp b/src/modules_small.cpp
index 3e05d5d..fcabfb7 100644
--- a/src/modules_small.cpp
+++ b/src/modules_small.cpp
@@ -1306,36 +1306,23 @@ public:
}
};
-class notefilter_e_audio_module: public midi_mixin<small_audio_module_base<1, 1> >
+template<class Range>
+class miditypefilter_m_audio_module: public midi_mixin<small_audio_module_base<1, 2> >
{
public:
- static void plugin_info(plugin_info_iface *pii)
+ static inline void extra_inputs(plugin_info_iface *pii)
{
- pii->names("notefilter_e", "Note Filter (M)", "lv2:UtilityPlugin");
- pii->event_port("in", "In").input();
- pii->event_port("out", "Out").output();
}
- void process(uint32_t)
- {
- event_port_read_iterator ri((LV2_Event_Buffer *)ins[0]);
- event_port_write_iterator wi((LV2_Event_Buffer *)outs[0]);
- while(ri)
- {
- const lv2_event &event = *ri++;
- if (event.type == midi_event_type && event.size && event.data[0] >= 0x80 && event.data[0] <= 0x9F)
- *wi++ = event;
- }
- }
-};
-
-class notefilter2_e_audio_module: public midi_mixin<small_audio_module_base<1, 2> >
-{
-public:
+ static inline const char *plugin_symbol() { return Range::strings()[0]; }
+ static inline const char *plugin_name() { return Range::strings()[1]; }
+ static inline const char *port_symbol() { return Range::strings()[2]; }
+ static inline const char *port_name() { return Range::strings()[3]; }
static void plugin_info(plugin_info_iface *pii)
{
- pii->names("notefilter2_e", "Note Filter 2 (M)", "lv2:UtilityPlugin");
+ pii->names(Range::plugin_symbol(), Range::plugin_name(), "kf:MIDIPlugin");
pii->event_port("in", "In").input();
- pii->event_port("notes", "Notes").output();
+ Range::extra_inputs(pii);
+ pii->event_port(Range::port_symbol(), Range::port_name()).output();
pii->event_port("others", "Others").output();
}
void process(uint32_t)
@@ -1346,7 +1333,7 @@ public:
while(ri)
{
const lv2_event &event = *ri++;
- if (event.type == midi_event_type && event.size && event.data[0] >= 0x80 && event.data[0] <= 0x9F)
+ if (event.type == midi_event_type && event.size && Range::is_in_range(event.data, ins))
*wi++ = event;
else
*wi2++ = event;
@@ -1354,14 +1341,56 @@ public:
}
};
-class eventmerge_e_audio_module: public midi_mixin<small_audio_module_base<2, 1> >
+class notefilter_m_audio_module: public miditypefilter_m_audio_module<notefilter_m_audio_module>
+{
+public:
+ static inline bool is_in_range(const uint8_t *data, float **) { return data[0] >= 0x80 && data[0] <= 0x9F; }
+ static inline const char **strings() { static const char *s[] = { "notefilter_m", "Note Filter", "note", "Note" }; return s;}
+};
+
+class pcfilter_m_audio_module: public miditypefilter_m_audio_module<pcfilter_m_audio_module>
+{
+public:
+ static inline bool is_in_range(const uint8_t *data, float **) { return data[0] >= 0xA0 && data[0] <= 0xAF; }
+ static inline const char **strings() { static const char *s[] = { "pcfilter_m", "Program Change Filter", "pc", "PC" }; return s;}
+};
+
+class ccfilter_m_audio_module: public miditypefilter_m_audio_module<ccfilter_m_audio_module>
+{
+public:
+ static inline bool is_in_range(const uint8_t *data, float **) { return data[0] >= 0xB0 && data[0] <= 0xBF; }
+ static inline const char **strings() { static const char *s[] = { "ccfilter_m", "Control Change Filter", "cc", "CC" }; return s;}
+};
+
+class pressurefilter_m_audio_module: public miditypefilter_m_audio_module<pressurefilter_m_audio_module>
+{
+public:
+ static inline bool is_in_range(const uint8_t *data, float **) { return data[0] >= 0xC0 && data[0] <= 0xDF; }
+ static inline const char **strings() { static const char *s[] = { "pressurefilter_m", "Pressure Filter", "pressure", "Pressure" }; return s;}
+};
+
+class pitchbendfilter_m_audio_module: public miditypefilter_m_audio_module<pitchbendfilter_m_audio_module>
+{
+public:
+ static inline bool is_in_range(const uint8_t *data, float **) { return data[0] >= 0xE0 && data[0] <= 0xEF; }
+ static inline const char **strings() { static const char *s[] = { "pitchbendfilter_m", "Pitch Bend Filter", "pbend", "Pitch Bend" }; return s;}
+};
+
+class systemfilter_m_audio_module: public miditypefilter_m_audio_module<systemfilter_m_audio_module>
+{
+public:
+ static inline bool is_in_range(const uint8_t *data, float **) { return data[0] >= 0xF0 && data[0] <= 0xFF; }
+ static inline const char **strings() { static const char *s[] = { "systemfilter_m", "System Msg Filter", "system", "System" }; return s;}
+};
+
+class eventmerge_e_audio_module: public event_mixin<small_audio_module_base<2, 1> >
{
public:
static void plugin_info(plugin_info_iface *pii)
{
- pii->names("eventmerge_e", "Event Merge (M)", "lv2:UtilityPlugin");
- pii->event_port("in_1", "In").input();
- pii->event_port("in_2", "In").input();
+ pii->names("eventmerge_e", "Event Merge (E)", "lv2:UtilityPlugin");
+ pii->event_port("in_1", "In 1").input();
+ pii->event_port("in_2", "In 2").input();
pii->event_port("out", "Out").output();
}
void process(uint32_t)
@@ -1369,10 +1398,7 @@ public:
event_port_merge_iterator<event_port_read_iterator, event_port_read_iterator> ri((const LV2_Event_Buffer *)ins[0], (const LV2_Event_Buffer *)ins[1]);
event_port_write_iterator wi((LV2_Event_Buffer *)outs[0]);
while(ri)
- {
- const lv2_event &event = *ri++;
- *wi++ = event;
- }
+ *wi++ = *ri++;
}
};
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list