From df7a87fe043440d99b23378efc6664b5deed8b42 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 17 Feb 2011 03:11:41 +0000 Subject: Fix "Ingen as an LV2", i.e. make Ingen bundles working LV2 plugins. Fix module loading/unloading (don't use statics). git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2973 a436a847-0d15-0410-975c-d299462d15a1 --- src/bindings/ingen_bindings.cpp | 10 +-- src/client/ingen_client.cpp | 10 +-- src/engine/ingen_engine.cpp | 10 +-- src/engine/ingen_http.cpp | 10 +-- src/engine/ingen_jack.cpp | 10 +-- src/engine/ingen_lv2.cpp | 161 ++++++++++++++++-------------------- src/engine/ingen_osc.cpp | 10 +-- src/gui/ingen_gui.cpp | 10 +-- src/serialisation/serialisation.cpp | 9 +- src/shared/runtime_paths.cpp | 14 ++-- 10 files changed, 103 insertions(+), 151 deletions(-) diff --git a/src/bindings/ingen_bindings.cpp b/src/bindings/ingen_bindings.cpp index a16890cd..fa365571 100644 --- a/src/bindings/ingen_bindings.cpp +++ b/src/bindings/ingen_bindings.cpp @@ -28,16 +28,12 @@ struct IngenBindingsModule : public Ingen::Shared::Module { } }; -static IngenBindingsModule* module = NULL; - extern "C" { Ingen::Shared::Module* -ingen_module_load() { - if (!module) - module = new IngenBindingsModule(); - - return module; +ingen_module_load() +{ + return new IngenBindingsModule(); } void diff --git a/src/client/ingen_client.cpp b/src/client/ingen_client.cpp index 693b981c..db98d54a 100644 --- a/src/client/ingen_client.cpp +++ b/src/client/ingen_client.cpp @@ -60,16 +60,12 @@ struct IngenClientModule : public Ingen::Shared::Module { } }; -static IngenClientModule* module = NULL; - extern "C" { Ingen::Shared::Module* -ingen_module_load() { - if (!module) - module = new IngenClientModule(); - - return module; +ingen_module_load() +{ + return new IngenClientModule(); } } // extern "C" diff --git a/src/engine/ingen_engine.cpp b/src/engine/ingen_engine.cpp index 5d278803..2c728603 100644 --- a/src/engine/ingen_engine.cpp +++ b/src/engine/ingen_engine.cpp @@ -37,16 +37,12 @@ struct IngenEngineModule : public Ingen::Shared::Module { } }; -static IngenEngineModule* module = NULL; - extern "C" { Ingen::Shared::Module* -ingen_module_load() { - if (!module) - module = new IngenEngineModule(); - - return module; +ingen_module_load() +{ + return new IngenEngineModule(); } } // extern "C" diff --git a/src/engine/ingen_http.cpp b/src/engine/ingen_http.cpp index 878c8f6b..6eb5cd9f 100644 --- a/src/engine/ingen_http.cpp +++ b/src/engine/ingen_http.cpp @@ -33,16 +33,12 @@ struct IngenHTTPModule : public Ingen::Shared::Module { } }; -static IngenHTTPModule* module = NULL; - extern "C" { Ingen::Shared::Module* -ingen_module_load() { - if (!module) - module = new IngenHTTPModule(); - - return module; +ingen_module_load() +{ + return new IngenHTTPModule(); } } // extern "C" diff --git a/src/engine/ingen_jack.cpp b/src/engine/ingen_jack.cpp index 05a6b673..77dfff55 100644 --- a/src/engine/ingen_jack.cpp +++ b/src/engine/ingen_jack.cpp @@ -32,16 +32,12 @@ struct IngenJackModule : public Ingen::Shared::Module { } }; -static IngenJackModule* module = NULL; - extern "C" { Ingen::Shared::Module* -ingen_module_load() { - if (!module) - module = new IngenJackModule(); - - return module; +ingen_module_load() +{ + return new IngenJackModule(); } } // extern "C" diff --git a/src/engine/ingen_lv2.cpp b/src/engine/ingen_lv2.cpp index 1c5db44c..3b62eca9 100644 --- a/src/engine/ingen_lv2.cpp +++ b/src/engine/ingen_lv2.cpp @@ -1,5 +1,5 @@ /* Ingen.LV2 - A thin wrapper which allows Ingen to run as an LV2 plugin. - * Copyright (C) 2008-2009 David Robillard + * Copyright (C) 2008-2011 David Robillard * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -16,11 +16,12 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include #include #include #include + +#include #include #include @@ -47,12 +48,7 @@ #include "ingen-config.h" -using namespace Ingen; - -namespace Ingen { -namespace LV2 { - -/** Record of a patch found in this LV2 bundle */ +/** Record of a patch in this Ingen LV2 bundle */ struct LV2Patch { LV2Patch(const std::string& u, const std::string& f); @@ -61,16 +57,24 @@ struct LV2Patch { LV2_Descriptor descriptor; }; +class Lib { +public: + Lib(); + ~Lib(); + + typedef std::vector< SharedPtr > Patches; + + Patches patches; + Ingen::Configuration conf; + int argc; + char** argv; +}; -/* Static library data */ -typedef std::vector< SharedPtr > LV2Patches; -static bool initialised = false; -static LV2Patches patches; -static Configuration conf; -static int argc = 0; -static char** argv = NULL; -static Shared::World* world = NULL; +/** Library state (constructed/destructed on library load/unload) */ +Lib lib; +namespace Ingen { +namespace LV2 { struct LV2Driver; @@ -120,7 +124,6 @@ private: void* _buffer; }; - struct LV2Driver : public Driver { private: typedef std::vector Ports; @@ -177,7 +180,6 @@ public: return NULL; } - virtual bool supports(Shared::PortType port_type, Shared::EventType event_type) { return true; } @@ -217,29 +219,33 @@ private: } // namespace LV2 } // namespace Ingen - -/* LV2 Plugin Interface */ - extern "C" { +/** LV2 plugin library entry point */ +LV2_SYMBOL_EXPORT +const LV2_Descriptor* +lv2_descriptor(uint32_t index) +{ + return index < lib.patches.size() ? &lib.patches[index]->descriptor : NULL; +} struct IngenPlugin { Ingen::Shared::World* world; }; - static LV2_Handle ingen_instantiate(const LV2_Descriptor* descriptor, double rate, const char* bundle_path, const LV2_Feature*const* features) { - Shared::set_bundle_path(bundle_path); - + using namespace Ingen; using namespace LV2; + Shared::set_bundle_path(bundle_path); + const LV2Patch* patch = NULL; - for (LV2Patches::iterator i = patches.begin(); i != patches.end(); ++i) { + for (Lib::Patches::iterator i = lib.patches.begin(); i != lib.patches.end(); ++i) { if (&(*i)->descriptor == descriptor) { patch = (*i).get(); break; @@ -252,14 +258,19 @@ ingen_instantiate(const LV2_Descriptor* descriptor, } IngenPlugin* plugin = (IngenPlugin*)malloc(sizeof(IngenPlugin)); - //plugin->world = ingen_world_new(&conf, argc, argv); - plugin->world = LV2::world; + plugin->world = ingen_world_new(&lib.conf, lib.argc, lib.argv); + if (!plugin->world->load("ingen_serialisation")) { + ingen_world_free(plugin->world); + return NULL; + } SharedPtr engine(new Engine(plugin->world)); plugin->world->set_local_engine(engine); SharedPtr interface( - new Ingen::QueuedEngineInterface(*plugin->world->local_engine(), event_queue_size)); + new Ingen::QueuedEngineInterface(*plugin->world->local_engine(), + event_queue_size)); + plugin->world->set_engine(interface); plugin->world->local_engine()->add_event_source(interface); @@ -283,7 +294,8 @@ ingen_instantiate(const LV2_Descriptor* descriptor, engine->post_processor()->process(); plugin->world->parser()->parse_document(plugin->world, - plugin->world->engine().get(), patch->filename); + plugin->world->engine().get(), + patch->filename); while (!interface->empty()) { interface->process(*engine->post_processor(), context, false); @@ -295,12 +307,12 @@ ingen_instantiate(const LV2_Descriptor* descriptor, return (LV2_Handle)plugin; } - static void ingen_connect_port(LV2_Handle instance, uint32_t port, void* data) { - IngenPlugin* me = (IngenPlugin*)instance; - LV2::LV2Driver* driver = (LV2::LV2Driver*)me->world->local_engine()->driver(); + IngenPlugin* me = (IngenPlugin*)instance; + SharedPtr engine = me->world->local_engine(); + Ingen::LV2::LV2Driver* driver = (Ingen::LV2::LV2Driver*)engine->driver(); if (port < driver->ports().size()) { driver->ports().at(port)->set_buffer(data); assert(driver->ports().at(port)->patch_port()->index() == port); @@ -309,7 +321,6 @@ ingen_connect_port(LV2_Handle instance, uint32_t port, void* data) } } - static void ingen_activate(LV2_Handle instance) { @@ -317,17 +328,15 @@ ingen_activate(LV2_Handle instance) me->world->local_engine()->activate(); } - static void ingen_run(LV2_Handle instance, uint32_t sample_count) { IngenPlugin* me = (IngenPlugin*)instance; // FIXME: don't do this every call - Raul::Thread::get().set_context(THREAD_PROCESS); - ((LV2::LV2Driver*)me->world->local_engine()->driver())->run(sample_count); + Raul::Thread::get().set_context(Ingen::THREAD_PROCESS); + ((Ingen::LV2::LV2Driver*)me->world->local_engine()->driver())->run(sample_count); } - static void ingen_deactivate(LV2_Handle instance) { @@ -335,32 +344,25 @@ ingen_deactivate(LV2_Handle instance) me->world->local_engine()->deactivate(); } - static void ingen_cleanup(LV2_Handle instance) { IngenPlugin* me = (IngenPlugin*)instance; - me->world->set_local_engine(SharedPtr()); - me->world->set_engine(SharedPtr()); - //ingen_world_free(me->world); + me->world->set_local_engine(SharedPtr()); + me->world->set_engine(SharedPtr()); + ingen_world_free(me->world); free(instance); } - static const void* ingen_extension_data(const char* uri) { return NULL; } - -/* Library Code */ - -namespace Ingen { -namespace LV2 { - LV2Patch::LV2Patch(const std::string& u, const std::string& f) - : uri(u), filename(f) + : uri(u) + , filename(f) { descriptor.URI = uri.c_str(); descriptor.instantiate = ingen_instantiate; @@ -372,63 +374,44 @@ LV2Patch::LV2Patch(const std::string& u, const std::string& f) descriptor.extension_data = ingen_extension_data; } -} // namespace LV2 -} // namespace Ingen - - -static void -init() +/** Library constructor (called on shared library load) */ +Lib::Lib() + : argc(0) + , argv(NULL) { - Shared::set_bundle_path_from_code((void*)&init); + if (!Glib::thread_supported()) + Glib::thread_init(); + using namespace Ingen; using namespace LV2; - //Shared::World* world = ingen_world_new(&conf, argc, argv); + Ingen::Shared::set_bundle_path_from_code((void*)&lv2_descriptor); - world = ingen_world_new(&conf, argc, argv); + Ingen::Shared::World* world = ingen_world_new(&conf, argc, argv); if (!world->load("ingen_serialisation")) { - Raul::error << "Unable to load serialisation module" << std::endl; - //ingen_world_free(world); + ingen_world_free(world); return; } + assert(world->parser()); + + typedef Serialisation::Parser::PatchRecords Records; - Serialisation::Parser::PatchRecords records( - world->parser()->find_patches(world, - Glib::filename_to_uri(Shared::bundle_file_path("manifest.ttl")))); + Records records(world->parser()->find_patches( + world, Glib::filename_to_uri( + Shared::bundle_file_path("manifest.ttl")))); - for (Serialisation::Parser::PatchRecords::iterator i = records.begin(); - i != records.end(); ++i) { + for (Records::iterator i = records.begin(); i != records.end(); ++i) { patches.push_back(SharedPtr( - new LV2Patch(i->uri.str(), i->filename))); + new LV2Patch(i->uri.str(), i->filename))); } - - //ingen_world_free(world); - - initialised = true; + ingen_world_free(world); } - -/* LV2 Library Interface */ - -extern "C" { - -LV2_SYMBOL_EXPORT -const LV2_Descriptor* -lv2_descriptor(uint32_t index) +/** Library destructor (called on shared library unload) */ +Lib::~Lib() { - if (!LV2::initialised) - init(); - - if (index >= LV2::patches.size()) - return NULL; - else - return &LV2::patches[index]->descriptor; } -} - - } // extern "C" - diff --git a/src/engine/ingen_osc.cpp b/src/engine/ingen_osc.cpp index 30958833..d5cffdce 100644 --- a/src/engine/ingen_osc.cpp +++ b/src/engine/ingen_osc.cpp @@ -34,16 +34,12 @@ struct IngenOSCModule : public Ingen::Shared::Module { } }; -static IngenOSCModule* module = NULL; - extern "C" { Ingen::Shared::Module* -ingen_module_load() { - if (!module) - module = new IngenOSCModule(); - - return module; +ingen_module_load() +{ + return new IngenOSCModule(); } } // extern "C" diff --git a/src/gui/ingen_gui.cpp b/src/gui/ingen_gui.cpp index 37bbadc3..9d0e995b 100644 --- a/src/gui/ingen_gui.cpp +++ b/src/gui/ingen_gui.cpp @@ -25,16 +25,12 @@ struct IngenGUIModule : public Ingen::Shared::Module { } }; -static IngenGUIModule* module = NULL; - extern "C" { Ingen::Shared::Module* -ingen_module_load() { - if (!module) - module = new IngenGUIModule(); - - return module; +ingen_module_load() +{ + return new IngenGUIModule(); } } // extern "C" diff --git a/src/serialisation/serialisation.cpp b/src/serialisation/serialisation.cpp index 91c435e3..e6780ed6 100644 --- a/src/serialisation/serialisation.cpp +++ b/src/serialisation/serialisation.cpp @@ -22,7 +22,7 @@ using namespace Ingen; -struct IngenModule : public Shared::Module { +struct IngenSerialisationModule : public Shared::Module { void load(Shared::World* world) { world->set_parser(SharedPtr( new Serialisation::Parser())); @@ -31,16 +31,11 @@ struct IngenModule : public Shared::Module { } }; -static IngenModule* module = NULL; - extern "C" { Shared::Module* ingen_module_load() { - if (!module) - module = new IngenModule(); - - return module; + return new IngenSerialisationModule(); } } // extern "C" diff --git a/src/shared/runtime_paths.cpp b/src/shared/runtime_paths.cpp index f4ddd897..b92529a1 100644 --- a/src/shared/runtime_paths.cpp +++ b/src/shared/runtime_paths.cpp @@ -15,11 +15,16 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include #include + +#include + #include #include + +#include "raul/log.hpp" + #include "ingen-config.h" #include "runtime_paths.hpp" @@ -30,7 +35,6 @@ namespace Shared { static std::string bundle_path; - /** Must be called once at startup, and passed a pointer to a function * that lives in the 'top level' of the bundle (e.g. the executable). * Passing a function defined in a module etc. will not work! @@ -48,19 +52,19 @@ set_bundle_path_from_code(void* function) const char* bin_loc = dli.dli_fname; #endif + Raul::info << "[Module] Binary location: " << bin_loc << std::endl; + string bundle = bin_loc; bundle = bundle.substr(0, bundle.find_last_of(G_DIR_SEPARATOR)); bundle_path = bundle; } - void set_bundle_path(const char* path) { bundle_path = path; } - /** Return the absolute path of a file in an Ingen LV2 bundle */ std::string @@ -81,7 +85,6 @@ data_file_path(const std::string& name) #endif } - /** Return the absolute path of a module (dynamically loaded shared library). */ std::string @@ -106,7 +109,6 @@ module_path(const std::string& name, std::string dir) return ret; } - } // namespace Ingen } // namespace Shared -- cgit v1.2.1