From 239825b92b1d4c79ebd67cb3766355bf8e699bc7 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 19 May 2008 23:52:44 +0000 Subject: Better global (engine/client) LV2 feature sharing. Provide URI map extension to plugin UIs. git-svn-id: http://svn.drobilla.net/lad/ingen@1217 a436a847-0d15-0410-975c-d299462d15a1 --- configure.ac | 2 ++ src/common/lv2ext/lv2_uri_map.h | 1 + src/libs/Makefile.am | 2 +- src/libs/client/PluginModel.cpp | 4 +-- src/libs/client/PluginModel.hpp | 5 +-- src/libs/client/PluginUI.cpp | 23 ++++++------- src/libs/client/PluginUI.hpp | 25 +++++++------- src/libs/engine/LV2Info.cpp | 74 +++++++++++------------------------------ src/libs/engine/LV2Info.hpp | 25 +++++--------- src/libs/engine/LV2Node.cpp | 3 +- src/libs/engine/Makefile.am | 1 + src/libs/engine/NodeFactory.cpp | 2 +- src/libs/gui/NodeModule.cpp | 4 +-- src/libs/module/Makefile.am | 15 +++++++-- src/libs/module/World.hpp | 5 ++- src/libs/module/global.cpp | 2 ++ src/progs/ingen/Makefile.am | 19 +++++++++-- 17 files changed, 102 insertions(+), 110 deletions(-) create mode 120000 src/common/lv2ext/lv2_uri_map.h diff --git a/configure.ac b/configure.ac index 3e5a57bb..3c175ab6 100644 --- a/configure.ac +++ b/configure.ac @@ -10,6 +10,7 @@ AC_CONFIG_AUX_DIR([config]) AC_CONFIG_SRCDIR([src/common/interface/EngineInterface.hpp]) AC_CONFIG_SRCDIR([src/common/lv2ext/lv2-miditype.h]) AC_CONFIG_SRCDIR([src/libs/module/Module.cpp]) +AC_CONFIG_SRCDIR([src/libs/shared/LV2URIMap.cpp]) AC_CONFIG_SRCDIR([src/libs/engine/JackAudioDriver.cpp]) AC_CONFIG_SRCDIR([src/libs/serialisation/Loader.cpp]) AC_CONFIG_SRCDIR([src/libs/client/OSCController.cpp]) @@ -292,6 +293,7 @@ AC_CONFIG_FILES([src/common/interface/Makefile]) AC_CONFIG_FILES([src/common/lv2ext/Makefile]) AC_CONFIG_FILES([src/libs/Makefile]) AC_CONFIG_FILES([src/libs/module/Makefile]) +AC_CONFIG_FILES([src/libs/shared/Makefile]) AC_CONFIG_FILES([src/libs/engine/Makefile]) AC_CONFIG_FILES([src/libs/engine/events/Makefile]) AC_CONFIG_FILES([src/libs/serialisation/Makefile]) diff --git a/src/common/lv2ext/lv2_uri_map.h b/src/common/lv2ext/lv2_uri_map.h new file mode 120000 index 00000000..9b67092f --- /dev/null +++ b/src/common/lv2ext/lv2_uri_map.h @@ -0,0 +1 @@ +../../../../lv2/lv2/uri_map/lv2_uri_map.h \ No newline at end of file diff --git a/src/libs/Makefile.am b/src/libs/Makefile.am index 9e80a248..50249976 100644 --- a/src/libs/Makefile.am +++ b/src/libs/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = module engine serialisation client gui +SUBDIRS = shared module engine serialisation client gui diff --git a/src/libs/client/PluginModel.cpp b/src/libs/client/PluginModel.cpp index 1f11cc21..9e4df473 100644 --- a/src/libs/client/PluginModel.cpp +++ b/src/libs/client/PluginModel.cpp @@ -97,14 +97,14 @@ lv2_ui_write(LV2UI_Controller controller, #ifdef HAVE_SLV2 SharedPtr -PluginModel::ui(SharedPtr engine, SharedPtr node) const +PluginModel::ui(Ingen::Shared::World* world, SharedPtr node) const { if (_type != LV2) return SharedPtr(); Glib::Mutex::Lock(_rdf_world->mutex()); - return PluginUI::create(engine, node, _slv2_world, _slv2_plugin); + return PluginUI::create(world, node, _slv2_plugin); } diff --git a/src/libs/client/PluginModel.hpp b/src/libs/client/PluginModel.hpp index f5ac71f4..e19d1691 100644 --- a/src/libs/client/PluginModel.hpp +++ b/src/libs/client/PluginModel.hpp @@ -29,6 +29,7 @@ #endif #include "interface/EngineInterface.hpp" #include "interface/Plugin.hpp" +#include "module/World.hpp" using std::string; @@ -96,8 +97,8 @@ public: _slv2_plugins = slv2_world_get_all_plugins(_slv2_world); } - SharedPtr ui(SharedPtr engine, - SharedPtr node) const; + SharedPtr ui(Ingen::Shared::World* world, + SharedPtr node) const; const string& icon_path() const; static string get_lv2_icon_path(SLV2Plugin plugin); diff --git a/src/libs/client/PluginUI.cpp b/src/libs/client/PluginUI.cpp index 54ee0009..5215de25 100644 --- a/src/libs/client/PluginUI.cpp +++ b/src/libs/client/PluginUI.cpp @@ -33,7 +33,7 @@ lv2_ui_write(LV2UI_Controller controller, uint32_t format, const void* buffer) { - cerr << "********* LV2 UI WRITE (FORMAT " << format << ":" << endl; + cerr << "********* LV2 UI WRITE (FORMAT " << format << "):" << endl; /*lv2_osc_message_print((const LV2Message*)buffer);*/ fprintf(stderr, "RAW:\n"); @@ -51,16 +51,16 @@ lv2_ui_write(LV2UI_Controller controller, SharedPtr port = ui->node()->ports()[port_index]; if (format == 0) { - ui->engine()->set_port_value_immediate(port->path(), + ui->world()->engine->set_port_value_immediate(port->path(), port->type().uri(), buffer_size, buffer); } } -PluginUI::PluginUI(SharedPtr engine, - SharedPtr node) - : _engine(engine) +PluginUI::PluginUI(Ingen::Shared::World* world, + SharedPtr node) + : _world(world) , _node(node) , _instance(NULL) { @@ -74,14 +74,13 @@ PluginUI::~PluginUI() SharedPtr -PluginUI::create(SharedPtr engine, - SharedPtr node, - SLV2World world, - SLV2Plugin plugin) +PluginUI::create(Ingen::Shared::World* world, + SharedPtr node, + SLV2Plugin plugin) { SharedPtr ret; - SLV2Value gtk_gui_uri = slv2_value_new_uri(world, + SLV2Value gtk_gui_uri = slv2_value_new_uri(world->slv2_world, "http://lv2plug.in/ns/extensions/ui#GtkUI"); SLV2UIs uis = slv2_plugin_get_uis(plugin); @@ -99,9 +98,9 @@ PluginUI::create(SharedPtr engine, if (ui) { cout << "Found GTK Plugin UI: " << slv2_ui_get_uri(ui) << endl; - ret = SharedPtr(new PluginUI(engine, node)); + ret = SharedPtr(new PluginUI(world, node)); SLV2UIInstance inst = slv2_ui_instantiate( - plugin, ui, lv2_ui_write, ret.get(), NULL); + plugin, ui, lv2_ui_write, ret.get(), world->lv2_features->lv2_features()); if (inst) { ret->set_instance(inst); diff --git a/src/libs/client/PluginUI.hpp b/src/libs/client/PluginUI.hpp index fc14d5c9..d20dd16a 100644 --- a/src/libs/client/PluginUI.hpp +++ b/src/libs/client/PluginUI.hpp @@ -20,6 +20,7 @@ #include #include +#include "module/World.hpp" namespace Ingen { namespace Shared { class EngineInterface; } @@ -36,25 +37,23 @@ class PluginUI { public: ~PluginUI(); - static SharedPtr - create(SharedPtr engine, - SharedPtr node, - SLV2World world, - SLV2Plugin plugin); + static SharedPtr create(Ingen::Shared::World* world, + SharedPtr node, + SLV2Plugin plugin); - SharedPtr engine() { return _engine; } - SharedPtr node() { return _node; } - SLV2UIInstance instance() { return _instance; } + Ingen::Shared::World* world() const { return _world; } + SharedPtr node() const { return _node; } + SLV2UIInstance instance() const { return _instance; } private: - PluginUI(SharedPtr engine, - SharedPtr node); + PluginUI(Ingen::Shared::World* world, + SharedPtr node); void set_instance(SLV2UIInstance instance) { _instance = instance; } - SharedPtr _engine; - SharedPtr _node; - SLV2UIInstance _instance; + Ingen::Shared::World* _world; + SharedPtr _node; + SLV2UIInstance _instance; }; diff --git a/src/libs/engine/LV2Info.cpp b/src/libs/engine/LV2Info.cpp index df8dd1f9..e5e9dde2 100644 --- a/src/libs/engine/LV2Info.cpp +++ b/src/libs/engine/LV2Info.cpp @@ -20,40 +20,32 @@ #include #include #include "LV2Info.hpp" +#include using namespace std; namespace Ingen { -LV2Info::LV2Info(SLV2World world) - : input_class(slv2_value_new_uri(world, SLV2_PORT_CLASS_INPUT)) - , output_class(slv2_value_new_uri(world, SLV2_PORT_CLASS_OUTPUT)) - , control_class(slv2_value_new_uri(world, SLV2_PORT_CLASS_CONTROL)) - , audio_class(slv2_value_new_uri(world, SLV2_PORT_CLASS_AUDIO)) - , event_class(slv2_value_new_uri(world, SLV2_PORT_CLASS_EVENT)) - , next_uri_id(1) - , lv2_features(new LV2_Feature*[3]) +LV2Info::LV2Info(Ingen::Shared::World* world) + : input_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_INPUT)) + , output_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_OUTPUT)) + , control_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_CONTROL)) + , audio_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_AUDIO)) + , event_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_EVENT)) + , _world(world) { - uri_map_feature_data.uri_to_id = &LV2Info::uri_map_uri_to_id; - uri_map_feature_data.callback_data = this; - uri_map_feature.URI = LV2_URI_MAP_URI; - uri_map_feature.data = &uri_map_feature_data; - - event_feature_data.lv2_event_ref= &LV2Info::event_ref; - event_feature_data.lv2_event_unref= &LV2Info::event_ref; - event_feature_data.callback_data = this; - event_feature.URI = LV2_EVENT_URI; - event_feature.data = &event_feature_data; - - lv2_features[0] = &uri_map_feature; - lv2_features[1] = &event_feature; - lv2_features[2] = NULL; - - /* this is needed so we get a fixed type ID for MIDI, it would - probably be better to make the type map accessible from any - JackMidiPort. */ - next_uri_id++; - uri_map.insert(make_pair(string("http://lv2plug.in/ns/ext/midi#MidiEvent"), 1)); + // Client would never add the event referencing feature + assert( ! world->lv2_features->feature(LV2_EVENT_URI)); + + LV2_Event_Feature* ev_data = (LV2_Event_Feature*)malloc(sizeof(LV2_Event_Feature)); + ev_data->lv2_event_ref = &LV2Info::event_ref; + ev_data->lv2_event_unref = &LV2Info::event_ref; + ev_data->callback_data = this; + LV2_Feature* ev_feature = (LV2_Feature*)malloc(sizeof(LV2_Event_Feature)); + ev_feature->URI = LV2_EVENT_URI; + ev_feature->data = ev_data; + + world->lv2_features->add_feature(LV2_EVENT_URI, ev_feature, ev_data); } @@ -67,32 +59,6 @@ LV2Info::~LV2Info() } - -uint32_t -LV2Info::uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data, - const char* map, - const char* uri) -{ - // TODO: map ignored, < UINT16_MAX assumed - - LV2Info* me = (LV2Info*)callback_data; - uint32_t ret = 0; - - URIMap::iterator i = me->uri_map.find(uri); - if (i != me->uri_map.end()) { - ret = i->second; - } else { - ret = me->next_uri_id++; - me->uri_map.insert(make_pair(string(uri), ret)); - } - - cout << "URI MAP (" << map << "): " << uri << " -> " << ret << endl; - - assert(ret <= UINT16_MAX); - return ret; -} - - uint32_t LV2Info::event_ref(LV2_Event_Callback_Data callback_data, LV2_Event* event) diff --git a/src/libs/engine/LV2Info.hpp b/src/libs/engine/LV2Info.hpp index 09865784..1fff0b92 100644 --- a/src/libs/engine/LV2Info.hpp +++ b/src/libs/engine/LV2Info.hpp @@ -27,18 +27,19 @@ #include #include #include "module/global.hpp" +#include "module/World.hpp" +#include "shared/LV2URIMap.hpp" #include "lv2/uri_map/lv2_uri_map.h" #include "lv2/event/lv2_event.h" - namespace Ingen { /** Stuff that may need to be passed to an LV2 plugin (i.e. LV2 features). */ -class LV2Info { +class LV2Info : public Shared::LV2URIMap { public: - LV2Info(SLV2World world); + LV2Info(Ingen::Shared::World* world); ~LV2Info(); SLV2Value input_class; @@ -47,23 +48,13 @@ public: SLV2Value audio_class; SLV2Value event_class; - LV2_Feature uri_map_feature; - LV2_URI_Map_Feature uri_map_feature_data; - LV2_Feature event_feature; - LV2_Event_Feature event_feature_data; - - typedef std::map URIMap; - URIMap uri_map; - uint32_t next_uri_id; - - static uint32_t uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data, - const char* map, - const char* uri); - static uint32_t event_ref(LV2_Event_Callback_Data callback_data, LV2_Event* event); - LV2_Feature** lv2_features; + LV2_Feature** lv2_features() const { return _world->lv2_features->lv2_features(); } + +private: + Ingen::Shared::World* _world; }; diff --git a/src/libs/engine/LV2Node.cpp b/src/libs/engine/LV2Node.cpp index bdeca701..9bb05f98 100644 --- a/src/libs/engine/LV2Node.cpp +++ b/src/libs/engine/LV2Node.cpp @@ -75,6 +75,7 @@ LV2Node::prepare_poly(uint32_t poly) _prepared_instances = new Raul::Array(poly, *_instances); for (uint32_t i = _polyphony; i < _prepared_instances->size(); ++i) { + // FIXME: features array (in NodeFactory) must be passed! _prepared_instances->at(i) = slv2_plugin_instantiate( _lv2_plugin->slv2_plugin(), _srate, NULL); @@ -137,7 +138,7 @@ LV2Node::instantiate() uint32_t port_buffer_size = 0; for (uint32_t i=0; i < _polyphony; ++i) { - (*_instances)[i] = slv2_plugin_instantiate(plug, _srate, info->lv2_features); + (*_instances)[i] = slv2_plugin_instantiate(plug, _srate, info->lv2_features()); if ((*_instances)[i] == NULL) { cerr << "Failed to instantiate plugin!" << endl; return false; diff --git a/src/libs/engine/Makefile.am b/src/libs/engine/Makefile.am index 8fa561ac..b53b28e1 100644 --- a/src/libs/engine/Makefile.am +++ b/src/libs/engine/Makefile.am @@ -18,6 +18,7 @@ libingen_engine_la_CXXFLAGS = \ libingen_engine_la_LDFLAGS = -no-undefined -module -avoid-version libingen_engine_la_LIBADD = \ + ../shared/libingen_shared.la \ @GLIBMM_LIBS@ \ @JACK_LIBS@ \ @LASH_LIBS@ \ diff --git a/src/libs/engine/NodeFactory.cpp b/src/libs/engine/NodeFactory.cpp index e86f9a2d..733dc6b1 100644 --- a/src/libs/engine/NodeFactory.cpp +++ b/src/libs/engine/NodeFactory.cpp @@ -49,7 +49,7 @@ NodeFactory::NodeFactory(Ingen::Shared::World* world) : _world(world) , _has_loaded(false) #ifdef HAVE_SLV2 - , _lv2_info(new LV2Info(world->slv2_world)) + , _lv2_info(new LV2Info(world)) #endif { } diff --git a/src/libs/gui/NodeModule.cpp b/src/libs/gui/NodeModule.cpp index 0e4ce18b..b3b191d1 100644 --- a/src/libs/gui/NodeModule.cpp +++ b/src/libs/gui/NodeModule.cpp @@ -138,7 +138,7 @@ NodeModule::embed_gui(bool embed) const PluginModel* const plugin = dynamic_cast(_node->plugin()); assert(plugin); - _plugin_ui = plugin->ui(App::instance().engine(), _node); + _plugin_ui = plugin->ui(App::instance().world(), _node); if (_plugin_ui) { c_widget = (GtkWidget*)slv2_ui_instance_get_widget(_plugin_ui->instance()); @@ -281,7 +281,7 @@ NodeModule::popup_gui() const PluginModel* const plugin = dynamic_cast(_node->plugin()); assert(plugin); - _plugin_ui = plugin->ui(App::instance().engine(), _node); + _plugin_ui = plugin->ui(App::instance().world(), _node); if (_plugin_ui) { GtkWidget* c_widget = (GtkWidget*)slv2_ui_instance_get_widget(_plugin_ui->instance()); diff --git a/src/libs/module/Makefile.am b/src/libs/module/Makefile.am index a4b22986..31a327da 100644 --- a/src/libs/module/Makefile.am +++ b/src/libs/module/Makefile.am @@ -1,8 +1,19 @@ noinst_LTLIBRARIES = libingen_module.la -libingen_module_la_CXXFLAGS = @GLIBMM_CFLAGS@ @REDLANDMM_CFLAGS@ @RAUL_CFLAGS@ @SLV2_CFLAGS@ -DINGEN_MODULE_DIR=\"$(libdir)/ingen\" +libingen_module_la_CXXFLAGS = \ + @INGEN_CFLAGS@ \ + @GLIBMM_CFLAGS@ \ + @REDLANDMM_CFLAGS@ \ + @RAUL_CFLAGS@ \ + @SLV2_CFLAGS@ \ + -DINGEN_MODULE_DIR=\"$(libdir)/ingen\" -libingen_module_la_LIBADD = @GLIBMM_LIBS@ @REDLANDMM_LIBS@ @RAUL_LIBS@ @SLV2_LIBS@ +libingen_module_la_LIBADD = \ + ../shared/libingen_shared.la \ + @GLIBMM_LIBS@ \ + @REDLANDMM_LIBS@ \ + @RAUL_LIBS@ \ + @SLV2_LIBS@ libingen_module_la_SOURCES = \ global.hpp \ diff --git a/src/libs/module/World.hpp b/src/libs/module/World.hpp index b61fe2af..a1ca9a68 100644 --- a/src/libs/module/World.hpp +++ b/src/libs/module/World.hpp @@ -24,6 +24,7 @@ #include #include #include +#include "shared/LV2Features.hpp" #ifdef HAVE_SLV2 #include @@ -50,8 +51,10 @@ class EngineInterface; */ struct World { #ifdef HAVE_SLV2 - SLV2World slv2_world; + SLV2World slv2_world; + LV2Features* lv2_features; #endif + Redland::World* rdf_world; EngineInterface* engine; diff --git a/src/libs/module/global.cpp b/src/libs/module/global.cpp index 6cd54685..21c36575 100644 --- a/src/libs/module/global.cpp +++ b/src/libs/module/global.cpp @@ -47,6 +47,7 @@ get_world() world->rdf_world = new Redland::World(); #ifdef HAVE_SLV2 world->slv2_world = slv2_world_new_using_rdf_world(world->rdf_world->world()); + world->lv2_features = new LV2Features(); slv2_world_load_all(world->slv2_world); #endif world->engine = NULL; @@ -68,6 +69,7 @@ destroy_world() if (world) { #ifdef HAVE_SLV2 slv2_world_free(world->slv2_world); + delete world->lv2_features; #endif delete world->rdf_world; delete world; diff --git a/src/progs/ingen/Makefile.am b/src/progs/ingen/Makefile.am index 0e265eca..c48a47a2 100644 --- a/src/progs/ingen/Makefile.am +++ b/src/progs/ingen/Makefile.am @@ -1,4 +1,11 @@ -AM_CXXFLAGS = @GTHREAD_CFLAGS@ @GLIBMM_CFLAGS@ @REDLANDMM_CFLAGS@ @RAUL_CFLAGS@ @SLV2_CFLAGS@ @INGEN_CFLAGS@ -DINGEN_MODULE_DIR=\"$(libdir)/ingen\" +AM_CXXFLAGS = \ + -DINGEN_MODULE_DIR=\"$(libdir)/ingen\" \ + @GTHREAD_CFLAGS@ \ + @GLIBMM_CFLAGS@ \ + @REDLANDMM_CFLAGS@ \ + @RAUL_CFLAGS@ \ + @SLV2_CFLAGS@ \ + @INGEN_CFLAGS@ MAINTAINERCLEANFILES = Makefile.in @@ -6,7 +13,15 @@ desktopfilesdir = $(datadir)/applications dist_desktopfiles_DATA = ingen.desktop bin_PROGRAMS = ingen -ingen_LDADD = @SLV2_LIBS@ @REDLANDMM_LIBS@ @RAUL_LIBS@ @GTHREAD_LIBS@ @GLIBMM_LIBS@ ../../libs/module/libingen_module.la +ingen_LDADD = \ + ../../libs/module/libingen_module.la \ + ../../libs/shared/libingen_shared.la \ + @SLV2_LIBS@ \ + @REDLANDMM_LIBS@ \ + @RAUL_LIBS@ \ + @GTHREAD_LIBS@ \ + @GLIBMM_LIBS@ + ingen_DEPENDENCIES = ../../libs/module/libingen_module.la ingen_SOURCES = \ -- cgit v1.2.1