summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2018-10-27 21:11:27 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2018-10-27 22:22:02 +0200
commitdfe71a21e5a190e5228964265c62416779454bec (patch)
tree4c1444986481394799bd06499e0eb105b9d83c0c
parent7f84f53bad767dfe2d1a2900b58c4dc32e9a8059 (diff)
Prototype LV2 midname extension
-rw-r--r--midnam_lv2.h37
-rw-r--r--pluginlv2.cc89
-rw-r--r--pluginlv2.h12
3 files changed, 138 insertions, 0 deletions
diff --git a/midnam_lv2.h b/midnam_lv2.h
new file mode 100644
index 0000000..a8e3f8e
--- /dev/null
+++ b/midnam_lv2.h
@@ -0,0 +1,37 @@
+#define LV2_MIDNAM_URI "http://ardour.org/lv2/midnam"
+#define LV2_MIDNAM_PREFIX LV2_MIDNAM_URI "#"
+#define LV2_MIDNAM__interface LV2_MIDNAM_PREFIX "interface"
+#define LV2_MIDNAM__update LV2_MIDNAM_PREFIX "update"
+
+typedef void* LV2_Midnam_Handle;
+
+/** a LV2 Feature provided by the Host to the plugin */
+typedef struct {
+ /** Opaque host data */
+ LV2_Midnam_Handle handle;
+ /** Request from run() that the host should re-read the midnam */
+ void (*update)(LV2_Midnam_Handle handle);
+} LV2_Midnam;
+
+typedef struct {
+ /** Query midnam document. The plugin
+ * is expected to return a null-terminated XML
+ * text which is a valid midnam desciption
+ * (or NULL in case of error).
+ *
+ * The midnam <Model> must be unique and
+ * specific for the given plugin-instance.
+ */
+ char* (*midnam)(LV2_Handle instance);
+
+ /** The unique model id used ith the midnam,
+ * (or NULL).
+ */
+ char* (*model)(LV2_Handle instance);
+
+ /** free allocated strings. The host
+ * calls this for every value returned by
+ * \ref midnam and \ref model.
+ */
+ void (*free)(char*);
+} LV2_Midnam_Interface;
diff --git a/pluginlv2.cc b/pluginlv2.cc
index 7593ff4..fd0bfbf 100644
--- a/pluginlv2.cc
+++ b/pluginlv2.cc
@@ -27,6 +27,7 @@
#include "pluginlv2.h"
#include <iostream>
+#include <sstream>
#include <assert.h>
#include "midievent.h"
@@ -121,6 +122,13 @@ LV2_Handle PluginLV2::instantiate(const struct _LV2_Descriptor* descriptor,
}
#endif
+#ifdef DISPLAY_INTERFACE
+ if(uri == LV2_MIDNAM__update)
+ {
+ plugin_lv2->midnam = (LV2_Midnam*)data;
+ }
+#endif
+
++features;
}
@@ -355,6 +363,13 @@ void PluginLV2::run(LV2_Handle instance, uint32_t sample_count)
plugin_lv2->pos += sample_count;
+#ifdef MIDNAME_INTERFACE
+ if (0) // XXX drumkit changed
+ {
+ plugin_lv2->midnam->update (plugin_lv2->midnam->handle);
+ }
+#endif
+
#ifdef DISPLAY_INTERFACE
if(plugin_lv2->queue_draw)
{
@@ -470,6 +485,72 @@ LV2_Inline_Display_Image_Surface* PluginLV2::inlineRender(LV2_Handle instance,
return &plugin_lv2->surf;
}
+#ifdef MIDNAME_INTERFACE
+char* PluginLV2::MidnamFile (LV2_Handle instance)
+{
+ PluginLV2* plugin_lv2 = (PluginLV2*)instance;
+ std::stringstream ss;
+ ss <<
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!DOCTYPE MIDINameDocument PUBLIC \"-//MIDI Manufacturers Association//DTD MIDINameDocument 1.0//EN\" \"http://dev.midi.org/dtds/MIDINameDocument10.dtd\">\n"
+ "<MIDINameDocument>\n"
+ " <Author/>\n"
+ " <MasterDeviceNames>\n"
+ " <Manufacturer>The Drum Gizmo Foundation</Manufacturer>\n"
+ " <Model>Drumgizmo:" << ((const void *) instance) << "</Model>\n"; //<< needs to match MidnamModel()
+
+ ss << " <CustomDeviceMode Name=\"Default\">\n";
+ ss << " <ChannelNameSetAssignments>\n";
+ for (int c = 0; c < 16; ++c)
+ {
+ ss << " <ChannelNameSetAssign Channel=\"" << (c + 1) << "\" NameSet=\"Presets\"/>\n";
+ }
+ ss << " </ChannelNameSetAssignments>\n";
+ ss << " </CustomDeviceMode>\n";
+
+
+ ss <<
+ " <ChannelNameSet Name=\"Presets\">\n"
+ " <AvailableForChannels>\n";
+ for (int c = 0; c < 16; ++c) {
+ ss << " <AvailableChannel Channel=\"" << (c + 1) << "\" Available=\"true\"/>\n";
+ }
+ ss <<
+ " </AvailableForChannels>\n"
+ " <UsesNoteNameList Name=\"Notes\"/>\n"
+ " <PatchBank Name=\"User Patches\">\n"
+ " <PatchNameList Name=\"User Patches\"/>\n"
+ " </PatchBank>\n"
+ " </ChannelNameSet>\n"
+ " <NoteNameList Name=\"Notes\">\n";
+
+ // XXX TODO ask plugin_lv2, iterate over mapped samples
+ ss << " <Note Number=\"36\" Name=\"KickDrum\"/>\n";
+ ss << " <Note Number=\"38\" Name=\"Snare\"/>\n";
+ // XXX
+
+ ss <<
+ " </NoteNameList>\n"
+ " </MasterDeviceNames>\n"
+ "</MIDINameDocument>";
+
+ return strdup (ss.str().c_str());
+}
+
+char* PluginLV2::MidnamModel (LV2_Handle instance)
+{
+ char* rv = (char*) malloc (64 * sizeof (char));
+ snprintf (rv, 64, "Drumgizmo:%p", (void*) instance);
+ rv[63] = 0;
+ return rv;
+}
+
+void PluginLV2::MidnamFree (char* v)
+{
+ free (v);
+}
+#endif
+
const void* PluginLV2::extensionData(const char *uri)
{
if(!strcmp(uri, LV2_STATE__interface))
@@ -485,6 +566,14 @@ const void* PluginLV2::extensionData(const char *uri)
}
#endif
+#ifdef MIDNAME_INTERFACE
+ static const LV2_Midnam_Interface midnam = { MidnamFile, MidnamModel, MidnamFree };
+ if (!strcmp (uri, LV2_MIDNAM__interface))
+ {
+ return &midnam;
+ }
+#endif
+
return nullptr;
}
diff --git a/pluginlv2.h b/pluginlv2.h
index 86a661e..10f816e 100644
--- a/pluginlv2.h
+++ b/pluginlv2.h
@@ -36,11 +36,16 @@
#include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
#define DISPLAY_INTERFACE
+#define MIDNAME_INTERFACE
#ifdef DISPLAY_INTERFACE
#include "inline-display.h"
#endif
+#ifdef MIDNAME_INTERFACE
+#include "midnam_lv2.h"
+#endif
+
enum class LV2Ports
{
FreeWheel = 0,
@@ -256,6 +261,13 @@ private:
uint32_t max_h);
#endif
+#ifdef MIDNAME_INTERFACE
+ LV2_Midnam* midnam{nullptr};
+ static char* MidnamFile (LV2_Handle instance);
+ static char* MidnamModel (LV2_Handle instance);
+ static void MidnamFree (char*);
+#endif
+
bool active{false};
//