diff options
author | David Robillard <d@drobilla.net> | 2008-07-28 21:56:03 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2008-07-28 21:56:03 +0000 |
commit | a6fb6a0289ea47692d87f3e0200532a426f8e60d (patch) | |
tree | 0e497255eb8a263ff9cca87b2ed125b71144cacb | |
parent | 8e2ba26101828dcf310e0a43ace7aa68dafd3b16 (diff) | |
download | ingen-a6fb6a0289ea47692d87f3e0200532a426f8e60d.tar.gz ingen-a6fb6a0289ea47692d87f3e0200532a426f8e60d.tar.bz2 ingen-a6fb6a0289ea47692d87f3e0200532a426f8e60d.zip |
Simply global memory management crap by using shared_ptr in the World struct (it's not C anyway, might as well).
Properly support LV2 events from plugin UIs over OSC and directly (w/ monolithic UI/engine).
Fix crashes on node destruction with monolithic UI/engine.
Resolves ticket #177.
git-svn-id: http://svn.drobilla.net/lad/ingen@1293 a436a847-0d15-0410-975c-d299462d15a1
42 files changed, 409 insertions, 319 deletions
diff --git a/src/bindings/ingen_bindings.cpp b/src/bindings/ingen_bindings.cpp index 0f96feda..91832faf 100644 --- a/src/bindings/ingen_bindings.cpp +++ b/src/bindings/ingen_bindings.cpp @@ -32,7 +32,8 @@ run(Ingen::Shared::World* world, const char* filename) void -script_iteration(Ingen::Shared::World* world) { +script_iteration(Ingen::Shared::World* world) +{ if (world->local_engine) world->local_engine->main_iteration(); } diff --git a/src/common/interface/ClientInterface.hpp b/src/common/interface/ClientInterface.hpp index 0da613c7..931e267b 100644 --- a/src/common/interface/ClientInterface.hpp +++ b/src/common/interface/ClientInterface.hpp @@ -44,7 +44,6 @@ public: inline const std::string& uri() const { return _uri; } virtual void response_ok(int32_t id) = 0; - virtual void response_error(int32_t id, const std::string& msg) = 0; virtual void enable() = 0; diff --git a/src/common/interface/EngineInterface.hpp b/src/common/interface/EngineInterface.hpp index c8fd08a9..41406ca8 100644 --- a/src/common/interface/EngineInterface.hpp +++ b/src/common/interface/EngineInterface.hpp @@ -49,13 +49,16 @@ public: virtual void register_client(ClientInterface* client) = 0; virtual void unregister_client(const string& uri) = 0; - // Engine commands virtual void load_plugins() = 0; virtual void activate() = 0; virtual void deactivate() = 0; virtual void quit() = 0; + // Bundles + virtual void bundle_begin() = 0; + virtual void bundle_end() = 0; + // Object commands virtual void create_patch(const string& path, @@ -136,7 +139,7 @@ public: const string& predicate, const Raul::Atom& value) = 0; - // Requests // + // Requests virtual void ping() = 0; diff --git a/src/libs/client/DeprecatedLoader.cpp b/src/libs/client/DeprecatedLoader.cpp index 4897137c..77d743eb 100644 --- a/src/libs/client/DeprecatedLoader.cpp +++ b/src/libs/client/DeprecatedLoader.cpp @@ -269,7 +269,7 @@ DeprecatedLoader::load_patch(const Glib::ustring& filename, list<ControlModel>::const_iterator i = pm->controls().begin(); for ( ; i != pm->controls().end(); ++i) { const float value = i->value(); - _engine->set_port_value(i->port_path(), "ingen:control", sizeof(float), &value); + _engine->set_port_value(i->port_path(), "ingen:Float", sizeof(float), &value); } } else { cerr << "WARNING: Unknown preset: \"" << pm->name() << endl; diff --git a/src/libs/client/OSCClientReceiver.cpp b/src/libs/client/OSCClientReceiver.cpp index 8cad1754..3f5447d0 100644 --- a/src/libs/client/OSCClientReceiver.cpp +++ b/src/libs/client/OSCClientReceiver.cpp @@ -35,7 +35,7 @@ OSCClientReceiver::OSCClientReceiver(int listen_port) , _listen_port(listen_port) , _st(NULL) { - start(true); // true = dump, false = shutup + start(false); // true = dump, false = shutup } diff --git a/src/libs/client/OSCEngineSender.cpp b/src/libs/client/OSCEngineSender.cpp index 20070ff9..48fee877 100644 --- a/src/libs/client/OSCEngineSender.cpp +++ b/src/libs/client/OSCEngineSender.cpp @@ -124,6 +124,28 @@ OSCEngineSender::unregister_client(const string& uri) } +// Bundles + +void +OSCEngineSender::bundle_begin() +{ + //cerr << "BUNDLE {" << endl; + /*assert(!_bundle); + _bundle = lo_bundle_new(LO_TT_IMMEDIATE);*/ +} + + +void +OSCEngineSender::bundle_end() +{ + //cerr << "} BUNDLE" << endl; + /*assert(_bundle); + lo_send_bundle(_address, _bundle); + lo_bundle_free(_bundle); + _bundle = NULL;*/ +} + + // Engine commands void @@ -358,19 +380,23 @@ OSCEngineSender::set_port_value(const string& port_path, const void* data) { assert(_engine_addr); - if (type_uri == "ingen:control") { + if (type_uri == "ingen:Float") { assert(data_size == 4); lo_send(_engine_addr, "/ingen/set_port_value", "isf", next_id(), port_path.c_str(), *(float*)data); - } else { + } else if (type_uri == "lv2_midi:MidiEvent") { lo_blob b = lo_blob_new(data_size, (void*)data); - lo_send(_engine_addr, "/ingen/set_port_value", "isb", + lo_send(_engine_addr, "/ingen/set_port_value", "issb", next_id(), port_path.c_str(), + type_uri.c_str(), b); lo_blob_free(b); + // FIXME: support atomic bundles of events here + } else { + cerr << "ERROR: Unknown value type '" << type_uri << "', ignoring" << endl; } } @@ -383,19 +409,22 @@ OSCEngineSender::set_port_value(const string& port_path, const void* data) { assert(_engine_addr); - if (type_uri == "ingen:control") { + if (type_uri == "ingen:Float") { assert(data_size == 4); lo_send(_engine_addr, "/ingen/set_port_value", "isf", next_id(), port_path.c_str(), *(float*)data); - } else { + } else if (type_uri == "lv2_midi:MidiEvent") { lo_blob b = lo_blob_new(data_size, (void*)data); - lo_send(_engine_addr, "/ingen/set_port_value", "isb", + lo_send(_engine_addr, "/ingen/set_port_value", "issb", next_id(), port_path.c_str(), + type_uri.c_str(), b); lo_blob_free(b); + } else { + cerr << "ERROR: Unknown value type '" << type_uri << "', ignoring" << endl; } } @@ -408,19 +437,22 @@ OSCEngineSender::set_port_value_immediate(const string& port_path, { assert(_engine_addr); - if (type_uri == "ingen:control") { + if (type_uri == "ingen:Float") { assert(data_size == 4); lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isf", next_id(), port_path.c_str(), *(float*)data); - } else { + } else if (type_uri == "lv2_midi:MidiEvent") { lo_blob b = lo_blob_new(data_size, (void*)data); - lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isb", + lo_send(_engine_addr, "/ingen/set_port_value_immediate", "issb", next_id(), port_path.c_str(), + type_uri.c_str(), b); lo_blob_free(b); + } else { + cerr << "ERROR: Unknown value type '" << type_uri << "', ignoring" << endl; } } @@ -434,21 +466,24 @@ OSCEngineSender::set_port_value_immediate(const string& port_path, { assert(_engine_addr); - if (type_uri == "ingen:control") { + if (type_uri == "ingen:Float") { assert(data_size == 4); lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isif", next_id(), port_path.c_str(), voice, *(float*)data); - } else { + } else if (type_uri == "lv2_midi:MidiEvent") { lo_blob b = lo_blob_new(data_size, (void*)data); - lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isib", + lo_send(_engine_addr, "/ingen/set_port_value_immediate", "isisb", next_id(), port_path.c_str(), voice, + type_uri.c_str(), b); lo_blob_free(b); + } else { + cerr << "ERROR: Unknown value type '" << type_uri << "', ignoring" << endl; } } diff --git a/src/libs/client/OSCEngineSender.hpp b/src/libs/client/OSCEngineSender.hpp index 6bd088ec..dfbdff62 100644 --- a/src/libs/client/OSCEngineSender.hpp +++ b/src/libs/client/OSCEngineSender.hpp @@ -61,14 +61,16 @@ public: void register_client(ClientInterface* client); void unregister_client(const string& uri); - // Engine commands void load_plugins(); void activate(); void deactivate(); void quit(); - + // Bundles + void bundle_begin(); + void bundle_end(); + // Object commands void create_patch(const string& path, @@ -165,6 +167,7 @@ public: void request_all_objects(); protected: + lo_bundle _bundle; string _engine_url; lo_address _engine_addr; int _client_port; diff --git a/src/libs/client/PluginModel.cpp b/src/libs/client/PluginModel.cpp index 9e4df473..fa39c0e3 100644 --- a/src/libs/client/PluginModel.cpp +++ b/src/libs/client/PluginModel.cpp @@ -57,44 +57,6 @@ PluginModel::default_node_name(SharedPtr<PatchModel> parent) } -#if 0 -struct NodeController { - EngineInterface* engine; - NodeModel* node; -}; - - -void -lv2_ui_write(LV2UI_Controller controller, - uint32_t port_index, - uint32_t buffer_size, - const void* buffer) -{ - /*cerr << "********* LV2 UI WRITE:" << endl; - lv2_osc_message_print((const LV2Message*)buffer); - - fprintf(stderr, "RAW:\n"); - for (uint32_t i=0; i < buffer_size; ++i) { - unsigned char byte = ((unsigned char*)buffer)[i]; - if (byte >= 32 && byte <= 126) - fprintf(stderr, "%c ", ((unsigned char*)buffer)[i]); - else - fprintf(stderr, "%2X ", ((unsigned char*)buffer)[i]); - } - - fprintf(stderr, "\n"); - */ - - NodeController* nc = (NodeController*)controller; - - SharedPtr<PortModel> port = nc->node->ports()[port_index]; - - nc->engine->set_port_value_immediate(port->path(), - port->type().uri(), buffer_size, buffer); -} -#endif - - #ifdef HAVE_SLV2 SharedPtr<PluginUI> PluginModel::ui(Ingen::Shared::World* world, SharedPtr<NodeModel> node) const diff --git a/src/libs/client/PluginUI.cpp b/src/libs/client/PluginUI.cpp index c7c3ffc5..b341bb0f 100644 --- a/src/libs/client/PluginUI.cpp +++ b/src/libs/client/PluginUI.cpp @@ -25,6 +25,7 @@ using namespace std; using Ingen::Shared::EngineInterface; using Ingen::Shared::LV2URIMap; +using Ingen::Shared::LV2Features; namespace Ingen { namespace Client { @@ -53,7 +54,8 @@ lv2_ui_write(LV2UI_Controller controller, SharedPtr<PortModel> port = ui->node()->ports()[port_index]; - LV2URIMap* map = (LV2URIMap*)ui->world()->lv2_features->feature(LV2_URI_MAP_URI); + const LV2Features::Feature* f = ui->world()->lv2_features->feature(LV2_URI_MAP_URI); + LV2URIMap* map = (LV2URIMap*)f->controller; assert(map); // float (special case, always 0) @@ -66,25 +68,31 @@ lv2_ui_write(LV2UI_Controller controller, port->type().uri(), buffer_size, buffer); - // FIXME: assumes event - } else { + // FIXME: slow, need to cache ID + } else if (format == map->uri_to_id(NULL, "http://lv2plug.in/ns/extensions/ui#Events")) { + uint32_t midi_event_type = map->uri_to_id(NULL, "http://lv2plug.in/ns/ext/midi#MidiEvent"); LV2_Event_Buffer* buf = (LV2_Event_Buffer*)buffer; LV2_Event_Iterator iter; uint8_t* data; lv2_event_begin(&iter, buf); while (lv2_event_is_valid(&iter)) { LV2_Event* const ev = lv2_event_get(&iter, &data); - - // FIXME: bundle multiple events - ui->world()->engine->set_port_value_immediate(port->path(), - port->type().uri(), - ev->size, data); + if (ev->type == midi_event_type) { + // FIXME: bundle multiple events by writing an entire buffer here + ui->world()->engine->set_port_value_immediate(port->path(), + "lv2_midi:MidiEvent", ev->size, data); + } else { + cerr << "WARNING: Unable to send event type " << ev->type << + " over OSC, ignoring event" << endl; + } lv2_event_increment(&iter); } + } else { + cerr << "WARNING: Unknown value format " << format + << ", either plugin " << ui->node()->plugin()->uri() << " is broken" + << " or this is an Ingen bug" << endl; } - - } diff --git a/src/libs/engine/Engine.cpp b/src/libs/engine/Engine.cpp index 41ae9a43..6b98566d 100644 --- a/src/libs/engine/Engine.cpp +++ b/src/libs/engine/Engine.cpp @@ -177,7 +177,10 @@ Engine::start_osc_driver(int port) SharedPtr<QueuedEngineInterface> Engine::new_queued_interface() { - assert(!_event_source); + if (_event_source) { + cerr << "WARNING: Replacing event source" << endl; + _event_source.reset(); + } SharedPtr<QueuedEngineInterface> result(new QueuedEngineInterface( *this, Ingen::event_queue_size, Ingen::event_queue_size)); diff --git a/src/libs/engine/Event.cpp b/src/libs/engine/Event.cpp index 1db466ce..8e5c33da 100644 --- a/src/libs/engine/Event.cpp +++ b/src/libs/engine/Event.cpp @@ -40,7 +40,8 @@ Event::execute(ProcessContext& context) void Event::post_process() { - assert(ThreadManager::current_thread_id() == THREAD_POST_PROCESS); + // FIXME: Not true witn monolithic GUI/engine + //assert(ThreadManager::current_thread_id() == THREAD_POST_PROCESS); } diff --git a/src/libs/engine/EventBuffer.cpp b/src/libs/engine/EventBuffer.cpp index 9985e2b7..dfeff610 100644 --- a/src/libs/engine/EventBuffer.cpp +++ b/src/libs/engine/EventBuffer.cpp @@ -178,6 +178,9 @@ EventBuffer::append(uint32_t frames, } #endif + /*cout << "Appending event type " << type << ", size " << size + << " @ " << frames << "." << subframes << endl;*/ + bool ret = lv2_event_write(&_iter, frames, subframes, type, size, data); if (!ret) @@ -190,6 +193,43 @@ EventBuffer::append(uint32_t frames, } +/** Append a buffer of events to the buffer. + * + * \a timestamp must be >= the latest event in the buffer, + * and < this_nframes() + * + * \return true on success + */ +bool +EventBuffer::append(const LV2_Event_Buffer* buf) +{ + uint8_t** data; + bool ret = true; + + LV2_Event_Iterator iter; + for (lv2_event_begin(&iter, _buf); lv2_event_is_valid(&iter); lv2_event_increment(&iter)) { + LV2_Event* ev = lv2_event_get(&iter, data); + +#ifndef NDEBUG + assert((ev->frames > _latest_frames) + || (ev->frames == _latest_frames + && ev->subframes >= _latest_subframes)); +#endif + + if (!(ret = append(ev->frames, ev->subframes, ev->type, ev->size, *data))) { + cerr << "ERROR: Failed to write event." << endl; + break; + } else { + } + + _latest_frames = ev->frames; + _latest_subframes = ev->subframes; + } + + return ret; +} + + /** Read an event from the current position in the buffer * * \return true if read was successful, or false if end of buffer reached diff --git a/src/libs/engine/EventBuffer.hpp b/src/libs/engine/EventBuffer.hpp index 148b5420..20fde057 100644 --- a/src/libs/engine/EventBuffer.hpp +++ b/src/libs/engine/EventBuffer.hpp @@ -83,6 +83,8 @@ public: uint16_t size, const uint8_t* data); + bool append(const LV2_Event_Buffer* buf); + bool merge(const EventBuffer& a, const EventBuffer& b); private: diff --git a/src/libs/engine/LV2Info.cpp b/src/libs/engine/LV2Info.cpp index e5e9dde2..4d934855 100644 --- a/src/libs/engine/LV2Info.cpp +++ b/src/libs/engine/LV2Info.cpp @@ -34,9 +34,6 @@ LV2Info::LV2Info(Ingen::Shared::World* world) , event_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_EVENT)) , _world(world) { - // 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; diff --git a/src/libs/engine/NodeBase.cpp b/src/libs/engine/NodeBase.cpp index 54217aae..a6bfa9ce 100644 --- a/src/libs/engine/NodeBase.cpp +++ b/src/libs/engine/NodeBase.cpp @@ -91,7 +91,8 @@ NodeBase::activate() void NodeBase::deactivate() { - assert(ThreadManager::current_thread_id() == THREAD_POST_PROCESS); + // FIXME: Not true witn monolithic GUI/engine + //assert(ThreadManager::current_thread_id() == THREAD_POST_PROCESS); assert(_activated); _activated = false; } diff --git a/src/libs/engine/OSCClientSender.cpp b/src/libs/engine/OSCClientSender.cpp index aff7fa50..98164de7 100644 --- a/src/libs/engine/OSCClientSender.cpp +++ b/src/libs/engine/OSCClientSender.cpp @@ -98,7 +98,7 @@ void OSCClientSender::send_message(const char* path, lo_message msg) { // FIXME: size? liblo doesn't export this. - // Don't want to exceed max UDP packet size (1500 bytes?}) + // Don't want to exceed max UDP packet size (1500 bytes?) static const size_t MAX_BUNDLE_SIZE = 1500 - 32*5; if (!_enabled) diff --git a/src/libs/engine/OSCEngineReceiver.cpp b/src/libs/engine/OSCEngineReceiver.cpp index 5308a2f2..d9cebba4 100644 --- a/src/libs/engine/OSCEngineReceiver.cpp +++ b/src/libs/engine/OSCEngineReceiver.cpp @@ -610,12 +610,14 @@ OSCEngineReceiver::_disconnect_all_cb(const char* path, const char* types, lo_ar * <p> \b /ingen/set_port_value_immediate - Sets the value of a port for all voices (both AR and CR) * \arg \b response-id (integer) * \arg \b port-path (string) - Name of port + * \arg \b type (string (URI or QName)) - Type of value being set (ingen:Float or ingen:EventBuffer) * \arg \b value (float or blob) - Value to set port to </p> \n \n */ /** \page engine_osc_namespace * <p> \b /ingen/set_port_value_immediate - Sets the value of a port for a specific voice (both AR and CR) * \arg \b response-id (integer) * \arg \b port-path (string) - Name of port + * \arg \b type (string (URI or QName)) - Type of value being set (ingen:Float or ingen:Event) * \arg \b voice (integer) - Voice to set port value for * \arg \b value (float or blob) - Value to set port to </p> \n \n * @@ -624,39 +626,29 @@ OSCEngineReceiver::_disconnect_all_cb(const char* path, const char* types, lo_ar int OSCEngineReceiver::_set_port_value_immediate_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { - if (argc < 3 || argc > 4 || strncmp(types, "is", 2)) + if (argc < 3 || argc > 5 || strncmp(types, "is", 2)) return 1; const char* port_path = &argv[1]->s; - if (argc == 3) { - if (types[2] == 'f') { - const float value = argv[2]->f; - set_port_value_immediate(port_path, "", sizeof(float), &value); - return 0; - } else if (types[2] == 'b') { - lo_blob b = argv[2]; - size_t data_size = lo_blob_datasize(b); - void* data = lo_blob_dataptr(b); - set_port_value_immediate(port_path, "", data_size, data); - return 0; - } else { - return 1; - } + if (!strcmp(types, "isf")) { // float, all voices + const float value = argv[2]->f; + set_port_value_immediate(port_path, "ingen:Float", sizeof(float), &value); + } else if (!strcmp(types, "isif")) { // float, specific voice + const float value = argv[3]->f; + set_port_value_immediate(port_path, "ingen:Float", argv[2]->i, sizeof(float), &value); + } else if (!strcmp(types, "issb")) { // blob (event), all voices + lo_blob b = argv[3]; + size_t data_size = lo_blob_datasize(b); + void* data = lo_blob_dataptr(b); + set_port_value_immediate(port_path, &argv[2]->s, data_size, data); + } else if (!strcmp(types, "isisb")) { // blob (event), specific voice + lo_blob b = argv[4]; + size_t data_size = lo_blob_datasize(b); + void* data = lo_blob_dataptr(b); + set_port_value_immediate(port_path, &argv[3]->s, argv[2]->i, data_size, data); } else { - if (types[3] == 'f') { - const float value = argv[3]->f; - set_port_value_immediate(port_path, "", argv[2]->i, sizeof(float), &value); - return 0; - } else if (types[3] == 'b') { - lo_blob b = argv[3]; - size_t data_size = lo_blob_datasize(b); - void* data = lo_blob_dataptr(b); - set_port_value_immediate(port_path, "", argv[2]->i, data_size, data); - return 0; - } else { - return 1; - } + return 1; } return 0; @@ -694,39 +686,29 @@ OSCEngineReceiver::_set_port_value_immediate_cb(const char* path, const char* ty int OSCEngineReceiver::_set_port_value_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { - if (argc < 3 || argc > 4 || strncmp(types, "is", 2)) + if (argc < 3 || argc > 5 || strncmp(types, "is", 2)) return 1; const char* port_path = &argv[1]->s; - if (argc == 3) { - if (types[2] == 'f') { - const float value = argv[2]->f; - set_port_value(port_path, "who cares", sizeof(float), &value); - return 0; - } else if (types[2] == 'b') { - lo_blob b = argv[2]; - size_t data_size = lo_blob_datasize(b); - void* data = lo_blob_dataptr(b); - set_port_value(port_path, "who cares", data_size, data); - return 0; - } else { - return 1; - } + if (!strcmp(types, "isf")) { // float, all voices + const float value = argv[2]->f; + set_port_value_immediate(port_path, "ingen:Float", sizeof(float), &value); + } else if (!strcmp(types, "isif")) { // float, specific voice + const float value = argv[3]->f; + set_port_value_immediate(port_path, "ingen:Float", argv[2]->i, sizeof(float), &value); + } else if (!strcmp(types, "issb")) { // blob (event), all voices + lo_blob b = argv[3]; + size_t data_size = lo_blob_datasize(b); + void* data = lo_blob_dataptr(b); + set_port_value_immediate(port_path, &argv[2]->s, data_size, data); + } else if (!strcmp(types, "isisb")) { // blob (event), specific voice + lo_blob b = argv[4]; + size_t data_size = lo_blob_datasize(b); + void* data = lo_blob_dataptr(b); + set_port_value_immediate(port_path, &argv[3]->s, argv[2]->i, data_size, data); } else { - if (types[3] == 'f') { - const float value = argv[3]->f; - set_port_value(port_path, "who cares", argv[2]->i, sizeof(float), &value); - return 0; - } else if (types[3] == 'b') { - lo_blob b = argv[3]; - size_t data_size = lo_blob_datasize(b); - void* data = lo_blob_dataptr(b); - set_port_value(port_path, "who cares", argv[2]->i, data_size, data); - return 0; - } else { - return 1; - } + return 1; } return 0; diff --git a/src/libs/engine/QueuedEngineInterface.cpp b/src/libs/engine/QueuedEngineInterface.cpp index feb08c9c..08ab781a 100644 --- a/src/libs/engine/QueuedEngineInterface.cpp +++ b/src/libs/engine/QueuedEngineInterface.cpp @@ -29,6 +29,7 @@ QueuedEngineInterface::QueuedEngineInterface(Engine& engine, size_t queued_size, : QueuedEventSource(queued_size, stamped_size) , _responder(new Responder(NULL, 0)) , _engine(engine) + , _in_bundle(false) { } @@ -116,8 +117,23 @@ QueuedEngineInterface::quit() _responder->respond_ok(); _engine.quit(); } + + +// Bundle commands + +void +QueuedEngineInterface::bundle_begin() +{ + _in_bundle = true; +} +void +QueuedEngineInterface::bundle_end() +{ + _in_bundle = false; +} + // Object commands @@ -126,7 +142,6 @@ QueuedEngineInterface::create_patch(const string& path, uint32_t poly) { push_queued(new CreatePatchEvent(_engine, _responder, now(), path, poly)); - } @@ -240,7 +255,7 @@ QueuedEngineInterface::set_port_value(const string& port_path, uint32_t data_size, const void* data) { - push_queued(new SetPortValueQueuedEvent(_engine, _responder, now(), port_path, data_size, data)); + push_queued(new SetPortValueQueuedEvent(_engine, _responder, now(), port_path, type_uri, data_size, data)); } @@ -251,7 +266,7 @@ QueuedEngineInterface::set_port_value(const string& port_path, uint32_t data_size, const void* data) { - push_queued(new SetPortValueQueuedEvent(_engine, _responder, now(), voice, port_path, data_size, data)); + push_queued(new SetPortValueQueuedEvent(_engine, _responder, now(), voice, port_path, type_uri, data_size, data)); } @@ -261,7 +276,7 @@ QueuedEngineInterface::set_port_value_immediate(const string& port_path, uint32_t data_size, const void* data) { - push_stamped(new SetPortValueEvent(_engine, _responder, now(), port_path, data_size, data)); + push_stamped(new SetPortValueEvent(_engine, _responder, now(), port_path, type_uri, data_size, data)); } @@ -272,7 +287,7 @@ QueuedEngineInterface::set_port_value_immediate(const string& port_path, uint32_t data_size, const void* data) { - push_stamped(new SetPortValueEvent(_engine, _responder, now(), voice, port_path, data_size, data)); + push_stamped(new SetPortValueEvent(_engine, _responder, now(), voice, port_path, type_uri, data_size, data)); } diff --git a/src/libs/engine/QueuedEngineInterface.hpp b/src/libs/engine/QueuedEngineInterface.hpp index 54b3b5fd..adf6d263 100644 --- a/src/libs/engine/QueuedEngineInterface.hpp +++ b/src/libs/engine/QueuedEngineInterface.hpp @@ -74,6 +74,10 @@ public: virtual void activate(); virtual void deactivate(); virtual void quit(); + + // Bundles + virtual void bundle_begin(); + virtual void bundle_end(); // Object commands @@ -177,6 +181,7 @@ protected: SharedPtr<Responder> _responder; ///< NULL if responding disabled Engine& _engine; + bool _in_bundle; ///< True iff a bundle is currently being received private: SampleCount now() const; diff --git a/src/libs/engine/events/CreatePortEvent.cpp b/src/libs/engine/events/CreatePortEvent.cpp index 7c7d671b..272ef561 100644 --- a/src/libs/engine/events/CreatePortEvent.cpp +++ b/src/libs/engine/events/CreatePortEvent.cpp @@ -85,7 +85,7 @@ CreatePortEvent::pre_process() assert(_patch->path() == _path.parent()); size_t buffer_size = 1; - if (_type != "ingen:control") + if (_type != "ingen:Float") buffer_size = _engine.audio_driver()->buffer_size(); const uint32_t old_num_ports = _patch->num_ports(); diff --git a/src/libs/engine/events/SetPortValueEvent.cpp b/src/libs/engine/events/SetPortValueEvent.cpp index 36f60809..cf9e60c3 100644 --- a/src/libs/engine/events/SetPortValueEvent.cpp +++ b/src/libs/engine/events/SetPortValueEvent.cpp @@ -38,12 +38,14 @@ SetPortValueEvent::SetPortValueEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& port_path, + const string& data_type, uint32_t data_size, const void* data) : Event(engine, responder, timestamp) , _omni(true) , _voice_num(0) , _port_path(port_path) + , _data_type(data_type) , _data_size(data_size) , _data(malloc(data_size)) , _port(NULL) @@ -59,12 +61,13 @@ SetPortValueEvent::SetPortValueEvent(Engine& engine, SampleCount timestamp, uint32_t voice_num, const string& port_path, + const string& data_type, uint32_t data_size, const void* data) : Event(engine, responder, timestamp) , _omni(false) , _voice_num(voice_num) - , _port_path(port_path) + , _data_type(data_type) , _data_size(data_size) , _data(malloc(data_size)) , _port(NULL) @@ -109,14 +112,23 @@ SetPortValueEvent::execute(ProcessContext& context) } EventBuffer* const ebuf = dynamic_cast<EventBuffer*>(buf); - if (ebuf) { + // FIXME: eliminate string comparisons + if (ebuf && _data_type == "lv2_midi:MidiEvent") { + const LV2Features::Feature* f = _engine.world()->lv2_features->feature(LV2_URI_MAP_URI); + LV2URIMap* map = (LV2URIMap*)f->controller; + const uint32_t type_id = map->uri_to_id(NULL, "http://lv2plug.in/ns/ext/midi#MidiEvent"); const uint32_t frames = std::max((uint32_t)(_time - context.start()), ebuf->latest_frames()); - // FIXME: type ebuf->prepare_write(context.nframes()); - ebuf->append(frames, 0, 0, _data_size, (const unsigned char*)_data); + // FIXME: how should this work? binary over OSC, ick + // Message is an event: + ebuf->append(frames, 0, type_id, _data_size, (const unsigned char*)_data); + // Message is an event buffer: + //ebuf->append((LV2_Event_Buffer*)_data); _port->raise_set_by_user_flag(); return; } + + cerr << "WARNING: Unknown value type " << _data_type << ", ignoring" << endl; } } diff --git a/src/libs/engine/events/SetPortValueEvent.hpp b/src/libs/engine/events/SetPortValueEvent.hpp index e6497aa5..d814a55b 100644 --- a/src/libs/engine/events/SetPortValueEvent.hpp +++ b/src/libs/engine/events/SetPortValueEvent.hpp @@ -39,6 +39,7 @@ public: SharedPtr<Responder> responder, SampleCount timestamp, const string& port_path, + const string& data_type, uint32_t data_size, const void* data); @@ -47,6 +48,7 @@ public: SampleCount timestamp, uint32_t voice_num, const string& port_path, + const string& data_type, uint32_t data_size, const void* data); @@ -61,6 +63,7 @@ private: bool _omni; uint32_t _voice_num; const string _port_path; + const string _data_type; uint32_t _data_size; void* _data; PortImpl* _port; diff --git a/src/libs/engine/events/SetPortValueQueuedEvent.cpp b/src/libs/engine/events/SetPortValueQueuedEvent.cpp index 28bb6df1..14060134 100644 --- a/src/libs/engine/events/SetPortValueQueuedEvent.cpp +++ b/src/libs/engine/events/SetPortValueQueuedEvent.cpp @@ -16,6 +16,7 @@ */ #include <sstream> +#include <iostream> #include "SetPortValueQueuedEvent.hpp" #include "Responder.hpp" #include "Engine.hpp" @@ -28,6 +29,8 @@ #include "EventBuffer.hpp" #include "ProcessContext.hpp" +using namespace std; + namespace Ingen { @@ -36,16 +39,18 @@ SetPortValueQueuedEvent::SetPortValueQueuedEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& port_path, + const string& data_type, uint32_t data_size, const void* data) -: QueuedEvent(engine, responder, timestamp), - _omni(true), - _voice_num(0), - _port_path(port_path), - _data_size(data_size), - _data(malloc(data_size)), - _port(NULL), - _error(NO_ERROR) + : QueuedEvent(engine, responder, timestamp) + , _omni(true) + , _voice_num(0) + , _port_path(port_path) + , _data_type(data_type) + , _data_size(data_size) + , _data(malloc(data_size)) + , _port(NULL) + , _error(NO_ERROR) { memcpy(_data, data, data_size); } @@ -57,16 +62,18 @@ SetPortValueQueuedEvent::SetPortValueQueuedEvent(Engine& engine, SampleCount timestamp, uint32_t voice_num, const string& port_path, + const string& data_type, uint32_t data_size, const void* data) -: QueuedEvent(engine, responder, timestamp), - _omni(false), - _voice_num(voice_num), - _port_path(port_path), - _data_size(data_size), - _data(malloc(data_size)), - _port(NULL), - _error(NO_ERROR) + : QueuedEvent(engine, responder, timestamp) + , _omni(false) + , _voice_num(voice_num) + , _port_path(port_path) + , _data_type(data_type) + , _data_size(data_size) + , _data(malloc(data_size)) + , _port(NULL) + , _error(NO_ERROR) { memcpy(_data, data, data_size); } @@ -112,11 +119,23 @@ SetPortValueQueuedEvent::execute(ProcessContext& context) } EventBuffer* const ebuf = dynamic_cast<EventBuffer*>(buf); - if (ebuf) { + // FIXME: eliminate string comparisons + if (ebuf && _data_type == "lv2_midi:MidiEvent") { + const LV2Features::Feature* f = _engine.world()->lv2_features->feature(LV2_URI_MAP_URI); + LV2URIMap* map = (LV2URIMap*)f->controller; + const uint32_t type_id = map->uri_to_id(NULL, "http://lv2plug.in/ns/ext/midi#MidiEvent"); const uint32_t frames = std::max((uint32_t)(_time - context.start()), ebuf->latest_frames()); - // FIXME: type - ebuf->append(frames, 0, 0, _data_size, (const unsigned char*)_data); + ebuf->prepare_write(context.nframes()); + // FIXME: how should this work? binary over OSC, ick + // Message is an event: + ebuf->append(frames, 0, type_id, _data_size, (const unsigned char*)_data); + // Message is an event buffer: + //ebuf->append((LV2_Event_Buffer*)_data); + _port->raise_set_by_user_flag(); + return; } + + cerr << "WARNING: Unknown value type " << _data_type << ", ignoring" << endl; } } diff --git a/src/libs/engine/events/SetPortValueQueuedEvent.hpp b/src/libs/engine/events/SetPortValueQueuedEvent.hpp index 382a574e..937a3ad8 100644 --- a/src/libs/engine/events/SetPortValueQueuedEvent.hpp +++ b/src/libs/engine/events/SetPortValueQueuedEvent.hpp @@ -39,6 +39,7 @@ public: SharedPtr<Responder> responder, SampleCount timestamp, const string& port_path, + const string& data_type, uint32_t data_size, const void* data); @@ -47,6 +48,7 @@ public: SampleCount timestamp, uint32_t voice_num, const string& port_path, + const string& data_type, uint32_t data_size, const void* data); @@ -57,13 +59,14 @@ public: private: enum ErrorType { NO_ERROR, PORT_NOT_FOUND, NO_SPACE }; - bool _omni; - uint32_t _voice_num; - string _port_path; - uint32_t _data_size; - void* _data; - PortImpl* _port; - ErrorType _error; + bool _omni; + uint32_t _voice_num; + string _port_path; + const string _data_type; + uint32_t _data_size; + void* _data; + PortImpl* _port; + ErrorType _error; }; diff --git a/src/libs/gui/App.cpp b/src/libs/gui/App.cpp index 736ec4bb..dc919b20 100644 --- a/src/libs/gui/App.cpp +++ b/src/libs/gui/App.cpp @@ -104,6 +104,7 @@ App::App(Ingen::Shared::World* world) rdf_world.add_prefix("ingen", "http://drobilla.net/ns/ingen#"); rdf_world.add_prefix("ingenuity", "http://drobilla.net/ns/ingenuity#"); rdf_world.add_prefix("lv2", "http://lv2plug.in/ns/lv2core#"); + rdf_world.add_prefix("lv2_midi", "http://lv2plug.in/ns/ext/midi"); rdf_world.add_prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); rdf_world.add_prefix("doap", "http://usefulinc.com/ns/doap#"); rdf_world.add_prefix("dc", "http://purl.org/dc/elements/1.1/"); @@ -121,10 +122,7 @@ App::~App() } void -App::run(int argc, char** argv, - Ingen::Shared::World* world, - SharedPtr<Engine> engine, - SharedPtr<Shared::EngineInterface> interface) +App::run(int argc, char** argv, Ingen::Shared::World* world) { Gnome::Canvas::init(); Gtk::Main main(argc, argv); @@ -163,7 +161,7 @@ App::run(int argc, char** argv, Gtk::RC::parse_string(rc_style); - App::instance().connect_window()->start(engine, interface); + App::instance().connect_window()->start(world); main.run(); @@ -172,19 +170,17 @@ App::run(int argc, char** argv, void -App::attach(SharedPtr<EngineInterface> engine, SharedPtr<SigClientInterface> client) +App::attach(SharedPtr<SigClientInterface> client) { - assert( ! _engine); assert( ! _client); assert( ! _store); assert( ! _loader); - engine->register_client(client.get()); + _world->engine->register_client(client.get()); - _engine = engine; _client = client; - _store = SharedPtr<Store>(new Store(engine, client)); - _loader = SharedPtr<ThreadedLoader>(new ThreadedLoader(engine)); + _store = SharedPtr<Store>(new Store(_world->engine, client)); + _loader = SharedPtr<ThreadedLoader>(new ThreadedLoader(_world->engine)); _patch_tree_window->init(*_store); @@ -196,14 +192,14 @@ App::attach(SharedPtr<EngineInterface> engine, SharedPtr<SigClientInterface> cli void App::detach() { - if (_engine) { + if (_world->engine) { _window_factory->clear(); _store->clear(); _loader.reset(); _store.reset(); _client.reset(); - _engine.reset(); + _world->engine.reset(); } } diff --git a/src/libs/gui/App.hpp b/src/libs/gui/App.hpp index 6bb7083b..44878925 100644 --- a/src/libs/gui/App.hpp +++ b/src/libs/gui/App.hpp @@ -28,6 +28,7 @@ #include <libglademm.h> #include <raul/SharedPtr.hpp> #include <redlandmm/World.hpp> +#include <module/World.hpp> using namespace std; @@ -83,9 +84,7 @@ public: void error_message(const string& msg); - void attach(SharedPtr<EngineInterface> engine, - SharedPtr<SigClientInterface> client); - + void attach(SharedPtr<SigClientInterface> client); void detach(); bool gtk_main_iteration(); @@ -102,7 +101,7 @@ public: Glib::RefPtr<Gdk::Pixbuf> icon_from_path(const string& path, int size); - const SharedPtr<EngineInterface>& engine() const { return _engine; } + const SharedPtr<EngineInterface> engine() const { return _world->engine; } const SharedPtr<SigClientInterface>& client() const { return _client; } const SharedPtr<Store>& store() const { return _store; } const SharedPtr<ThreadedLoader>& loader() const { return _loader; } @@ -112,10 +111,7 @@ public: static inline App& instance() { assert(_instance); return *_instance; } - static void run(int argc, char** argv, - Ingen::Shared::World* world, - SharedPtr<Ingen::Engine> engine, - SharedPtr<Shared::EngineInterface> interface); + static void run(int argc, char** argv, Ingen::Shared::World* world); Ingen::Shared::World* world() { return _world; } @@ -144,7 +140,6 @@ protected: SharedPtr<Glib::Module> _serialisation_module; - SharedPtr<EngineInterface> _engine; SharedPtr<SigClientInterface> _client; SharedPtr<Store> _store; SharedPtr<ThreadedLoader> _loader; diff --git a/src/libs/gui/ConnectWindow.cpp b/src/libs/gui/ConnectWindow.cpp index 7bf34c01..288b30cc 100644 --- a/src/libs/gui/ConnectWindow.cpp +++ b/src/libs/gui/ConnectWindow.cpp @@ -106,15 +106,14 @@ ConnectWindow::ConnectWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome:: void -ConnectWindow::start(SharedPtr<Ingen::Engine> engine, SharedPtr<Shared::EngineInterface> interface) +ConnectWindow::start(Ingen::Shared::World* world) { - set_connected_to(interface); - - if (engine) { - _engine = engine; + if (world->local_engine) { _mode = INTERNAL; _internal_radio->set_active(true); } + + set_connected_to(world->engine); show(); connect(); @@ -156,7 +155,7 @@ ConnectWindow::set_connected_to(SharedPtr<Shared::EngineInterface> engine) _progress_label->set_text(string("Disconnected")); } - App::instance().world()->engine = engine.get(); + App::instance().world()->engine = engine; } @@ -169,7 +168,6 @@ void ConnectWindow::connect() { assert(!_attached); - assert(!App::instance().engine()); assert(!App::instance().client()); _connect_button->set_sensitive(false); @@ -184,14 +182,16 @@ ConnectWindow::connect() _port_spinbutton->set_sensitive(false); _connect_stage = 0; + + Ingen::Shared::World* world = App::instance().world(); if (_mode == CONNECT_REMOTE) { - SharedPtr<EngineInterface> engine( - new OSCEngineSender(_url_entry->get_text())); + world->engine = SharedPtr<EngineInterface>( + new OSCEngineSender(_url_entry->get_text())); OSCSigEmitter* ose = new OSCSigEmitter(1024, 16181); // FIXME: args SharedPtr<ThreadedSigClientInterface> client(ose); - App::instance().attach(engine, client); + App::instance().attach(client); Glib::signal_timeout().connect( sigc::mem_fun(App::instance(), &App::gtk_main_iteration), 40, G_PRIORITY_DEFAULT); @@ -207,36 +207,38 @@ ConnectWindow::connect() const string cmd = string("ingen -e --engine-port=").append(port_str); if (Raul::Process::launch(cmd)) { - SharedPtr<EngineInterface> engine( - new OSCEngineSender(string("osc.udp://localhost:").append(port_str))); + world->engine = SharedPtr<EngineInterface>( + new OSCEngineSender(string("osc.udp://localhost:").append(port_str))); - OSCSigEmitter* ose = new OSCSigEmitter(1024, 16181); // FIXME: args - SharedPtr<ThreadedSigClientInterface> client(ose); - App::instance().attach(engine, client); - - Glib::signal_timeout().connect( - sigc::mem_fun(App::instance(), &App::gtk_main_iteration), 40, G_PRIORITY_DEFAULT); + OSCSigEmitter* ose = new OSCSigEmitter(1024, 16181); // FIXME: args + SharedPtr<ThreadedSigClientInterface> client(ose); + App::instance().attach(client); - Glib::signal_timeout().connect( - sigc::mem_fun(this, &ConnectWindow::gtk_callback), 100); + Glib::signal_timeout().connect( + sigc::mem_fun(App::instance(), &App::gtk_main_iteration), 40, G_PRIORITY_DEFAULT); + + Glib::signal_timeout().connect( + sigc::mem_fun(this, &ConnectWindow::gtk_callback), 100); } else { cerr << "Failed to launch ingen process." << endl; } } else if (_mode == INTERNAL) { + Ingen::Shared::World* world = App::instance().world(); assert(_new_engine); - _engine = SharedPtr<Ingen::Engine>(_new_engine(App::instance().world())); - App::instance().world()->local_engine = _engine.get(); + if ( ! world->local_engine) + world->local_engine = SharedPtr<Engine>(_new_engine(world)); + + if ( ! world->engine) + world->engine = world->local_engine->new_queued_interface(); - SharedPtr<Ingen::EngineInterface> engine_interface = _engine->new_queued_interface(); - SharedPtr<SigClientInterface> client(new SigClientInterface()); - _engine->start_jack_driver(); - _engine->activate(1); // FIXME: parallelism + world->local_engine->start_jack_driver(); + world->local_engine->activate(1); // FIXME: parallelism - App::instance().attach(engine_interface, client); + App::instance().attach(client); Glib::signal_timeout().connect( sigc::mem_fun(App::instance(), &App::gtk_main_iteration), 40, G_PRIORITY_DEFAULT); @@ -258,8 +260,7 @@ ConnectWindow::disconnect() _disconnect_button->set_sensitive(false); App::instance().detach(); - - set_connected_to(); + set_connected_to(SharedPtr<Ingen::Shared::EngineInterface>()); _connect_button->set_sensitive(true); _disconnect_button->set_sensitive(false); diff --git a/src/libs/gui/ConnectWindow.hpp b/src/libs/gui/ConnectWindow.hpp index 315ae0b2..53d0ccd5 100644 --- a/src/libs/gui/ConnectWindow.hpp +++ b/src/libs/gui/ConnectWindow.hpp @@ -51,8 +51,8 @@ class ConnectWindow : public Gtk::Dialog public: ConnectWindow(BaseObjectType* cobject, const Glib::RefPtr<Gnome::Glade::Xml>& xml); - void set_connected_to(SharedPtr<Shared::EngineInterface> e=SharedPtr<Shared::EngineInterface>()); - void start(SharedPtr<Ingen::Engine> engine, SharedPtr<Shared::EngineInterface> interface); + void set_connected_to(SharedPtr<Shared::EngineInterface> engine); + void start(Ingen::Shared::World* world); void response_ok_received(int32_t id) { if ((id) == _ping_id) _attached = true; } private: @@ -77,8 +77,6 @@ private: SharedPtr<Glib::Module> _engine_module; Ingen::Engine* (*_new_engine)(Ingen::Shared::World* world); - SharedPtr<Ingen::Engine> _engine; - Gtk::Image* _icon; Gtk::ProgressBar* _progress_bar; Gtk::Label* _progress_label; diff --git a/src/libs/gui/ControlPanel.cpp b/src/libs/gui/ControlPanel.cpp index a59a15f6..7e82c7dc 100644 --- a/src/libs/gui/ControlPanel.cpp +++ b/src/libs/gui/ControlPanel.cpp @@ -233,12 +233,12 @@ ControlPanel::value_changed(SharedPtr<PortModel> port, float val) if (_callback_enabled) { if (_all_voices_radio->get_active()) { - App::instance().engine()->set_port_value_immediate(port->path(), "ingen:control", + App::instance().engine()->set_port_value_immediate(port->path(), "ingen:Float", sizeof(float), &val); port->value(val); } else { int voice = _voice_spinbutton->get_value_as_int(); - App::instance().engine()->set_port_value_immediate(port->path(), "ingen:control", + App::instance().engine()->set_port_value_immediate(port->path(), "ingen:Float", voice, sizeof(float), &val); port->value(val); } diff --git a/src/libs/gui/Port.cpp b/src/libs/gui/Port.cpp index 36a010bb..7508a47f 100644 --- a/src/libs/gui/Port.cpp +++ b/src/libs/gui/Port.cpp @@ -116,7 +116,7 @@ Port::set_control(float value, bool signal) return; if (signal) - App::instance().engine()->set_port_value_immediate(_port_model->path(), "ingen:control", + App::instance().engine()->set_port_value_immediate(_port_model->path(), "ingen:Float", sizeof(float), &value); FlowCanvas::Port::set_control(value); diff --git a/src/libs/gui/ThreadedLoader.cpp b/src/libs/gui/ThreadedLoader.cpp index a037a711..949cde1a 100644 --- a/src/libs/gui/ThreadedLoader.cpp +++ b/src/libs/gui/ThreadedLoader.cpp @@ -95,8 +95,7 @@ ThreadedLoader::load_patch(bool merge, } else { _events.push_back(sigc::hide_return(sigc::bind( sigc::mem_fun(_loader.get(), &Ingen::Serialisation::Loader::load), - App::instance().engine(), - App::instance().world()->rdf_world, + App::instance().world(), data_base_uri, engine_parent, (engine_name) ? engine_name.get() : "", diff --git a/src/libs/gui/gui.cpp b/src/libs/gui/gui.cpp index ca160e00..10af6d9b 100644 --- a/src/libs/gui/gui.cpp +++ b/src/libs/gui/gui.cpp @@ -24,12 +24,9 @@ namespace Ingen { namespace GUI { -void run(int argc, char** argv, - Ingen::Shared::World* world, - SharedPtr<Ingen::Engine> engine, - SharedPtr<Shared::EngineInterface> interface) +void run(int argc, char** argv, Ingen::Shared::World* world) { - App::run(argc, argv, world, engine, interface); + App::run(argc, argv, world); } diff --git a/src/libs/gui/gui.hpp b/src/libs/gui/gui.hpp index fa31fe8d..a959f17a 100644 --- a/src/libs/gui/gui.hpp +++ b/src/libs/gui/gui.hpp @@ -33,10 +33,7 @@ namespace GUI { extern "C" { - void run(int argc, char** argv, - Ingen::Shared::World* world, - SharedPtr<Ingen::Engine> engine, - SharedPtr<Shared::EngineInterface> interface); + void run(int argc, char** argv, Ingen::Shared::World* world); } diff --git a/src/libs/module/World.hpp b/src/libs/module/World.hpp index a1ca9a68..29434069 100644 --- a/src/libs/module/World.hpp +++ b/src/libs/module/World.hpp @@ -57,9 +57,8 @@ struct World { Redland::World* rdf_world; - EngineInterface* engine; - - Engine* local_engine; + SharedPtr<EngineInterface> engine; + SharedPtr<Engine> local_engine; }; diff --git a/src/libs/module/global.cpp b/src/libs/module/global.cpp index 21c36575..a8a2720d 100644 --- a/src/libs/module/global.cpp +++ b/src/libs/module/global.cpp @@ -50,8 +50,8 @@ get_world() world->lv2_features = new LV2Features(); slv2_world_load_all(world->slv2_world); #endif - world->engine = NULL; - world->local_engine = NULL; + world->engine.reset(); + world->local_engine.reset(); } return world; diff --git a/src/libs/serialisation/Loader.cpp b/src/libs/serialisation/Loader.cpp index 84b935d9..da2e6507 100644 --- a/src/libs/serialisation/Loader.cpp +++ b/src/libs/serialisation/Loader.cpp @@ -42,13 +42,12 @@ namespace Serialisation { * @return whether or not load was successful. */ bool -Loader::load(SharedPtr<EngineInterface> engine, - Redland::World* rdf_world, - const Glib::ustring& document_uri, - boost::optional<Path> parent, - string patch_name, - Glib::ustring patch_uri, - GraphObject::Variables data) +Loader::load(Ingen::Shared::World* world, + const Glib::ustring& document_uri, + boost::optional<Raul::Path> parent, + std::string patch_name, + Glib::ustring patch_uri, + GraphObject::Variables data) { setlocale(LC_NUMERIC, "C"); @@ -56,7 +55,7 @@ Loader::load(SharedPtr<EngineInterface> engine, std::set<Path> created; - Redland::Model model(*rdf_world, document_uri, document_uri); + Redland::Model model(*world->rdf_world, document_uri, document_uri); if (patch_uri == "") patch_uri = string("<") + document_uri + ">"; @@ -75,11 +74,11 @@ Loader::load(SharedPtr<EngineInterface> engine, /* Get polyphony from file (mandatory if not specified in parameters) */ } else { // FIXME: polyphony datatype? - Redland::Query query(*rdf_world, Glib::ustring( + Redland::Query query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?poly WHERE {\n") + patch_uri + " ingen:polyphony ?poly\n }"); - Redland::Query::Results results = query.run(*rdf_world, model); + Redland::Query::Results results = query.run(*world->rdf_world, model); if (results.size() == 0) { cerr << "[Loader] ERROR: No polyphony found!" << endl; @@ -98,11 +97,11 @@ Loader::load(SharedPtr<EngineInterface> engine, if (patch_name.substr(patch_name.length()-10) == ".ingen.ttl") patch_name = patch_name.substr(0, patch_name.length()-10); - Redland::Query query(*rdf_world, Glib::ustring( + Redland::Query query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?name WHERE {\n") + patch_uri + " ingen:name ?name\n}"); - Redland::Query::Results results = query.run(*rdf_world, model); + Redland::Query::Results results = query.run(*world->rdf_world, model); if (results.size() > 0) patch_name = (*results.begin())["name"].to_string(); @@ -113,15 +112,15 @@ Loader::load(SharedPtr<EngineInterface> engine, cout << " as " << patch_path << endl; if (patch_path != "/") - engine->create_patch(patch_path, patch_poly); + world->engine->create_patch(patch_path, patch_poly); /* Set document metadata (so File->Save doesn't prompt) * FIXME: This needs some thinking for multiple clients... */ - engine->set_variable(patch_path, "ingen:document", Atom(document_uri.c_str())); + world->engine->set_variable(patch_path, "ingen:document", Atom(document_uri.c_str())); /* Load (plugin) nodes */ - Redland::Query query(*rdf_world, Glib::ustring( + Redland::Query query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?name ?plugin ?varkey ?varval ?poly WHERE {\n") + patch_uri + " ingen:node ?node .\n" "?node ingen:name ?name ;\n" @@ -133,11 +132,11 @@ Loader::load(SharedPtr<EngineInterface> engine, " }" "}"); - Redland::Query::Results results = query.run(*rdf_world, model); + Redland::Query::Results results = query.run(*world->rdf_world, model); map<const string, const Atom> variable; - rdf_world->mutex().lock(); + world->rdf_world->mutex().lock(); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { @@ -145,37 +144,37 @@ Loader::load(SharedPtr<EngineInterface> engine, const Path node_path = patch_path.base() + node_name; if (created.find(node_path) == created.end()) { - const string node_plugin = rdf_world->qualify((*i)["plugin"].to_string()); + const string node_plugin = world->rdf_world->qualify((*i)["plugin"].to_string()); bool node_polyphonic = false; Redland::Node poly_node = (*i)["poly"]; if (poly_node.is_bool() && poly_node.to_bool() == true) node_polyphonic = true; - engine->create_node(node_path, node_plugin, node_polyphonic); + world->engine->create_node(node_path, node_plugin, node_polyphonic); created.insert(node_path); } - const string key = rdf_world->prefixes().qualify((*i)["varkey"].to_string()); + const string key = world->rdf_world->prefixes().qualify((*i)["varkey"].to_string()); Redland::Node val_node = (*i)["varval"]; if (key != "") - engine->set_variable(node_path, key, AtomRDF::node_to_atom(val_node)); + world->engine->set_variable(node_path, key, AtomRDF::node_to_atom(val_node)); } - rdf_world->mutex().unlock(); + world->rdf_world->mutex().unlock(); /* Load subpatches */ - query = Redland::Query(*rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?patch ?name WHERE {\n") + patch_uri + " ingen:node ?patch .\n" "?patch a ingen:Patch ;\n" " ingen:name ?name .\n" "}"); - results = query.run(*rdf_world, model); + results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { @@ -186,7 +185,7 @@ Loader::load(SharedPtr<EngineInterface> engine, if (created.find(subpatch_path) == created.end()) { created.insert(subpatch_path); - load(engine, rdf_world, document_uri, patch_path, name, patch); + load(world, document_uri, patch_path, name, patch); } } @@ -195,7 +194,7 @@ Loader::load(SharedPtr<EngineInterface> engine, /* Set node port control values */ - query = Redland::Query(*rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?nodename ?portname ?portval WHERE {\n") + patch_uri + " ingen:node ?node .\n" "?node ingen:name ?nodename ;\n" @@ -205,7 +204,7 @@ Loader::load(SharedPtr<EngineInterface> engine, "FILTER ( datatype(?portval) = xsd:decimal )\n" "}\n"); - results = query.run(*rdf_world, model); + results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { @@ -216,13 +215,13 @@ Loader::load(SharedPtr<EngineInterface> engine, const Path port_path = patch_path.base() + Path::nameify(node_name) +"/"+ Path::nameify(port_name); - engine->set_port_value(port_path, "ingen:control", sizeof(float), &val); + world->engine->set_port_value(port_path, "ingen:Float", sizeof(float), &val); } /* Load this patch's ports */ - query = Redland::Query(*rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?port ?type ?name ?datatype ?varkey ?varval ?portval WHERE {\n") + patch_uri + " ingen:port ?port .\n" "?port a ?type ;\n" @@ -237,32 +236,32 @@ Loader::load(SharedPtr<EngineInterface> engine, " }" "}"); - results = query.run(*rdf_world, model); + results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { const string name = (*i)["name"].to_string(); - const string type = rdf_world->qualify((*i)["type"].to_string()); - const string datatype = rdf_world->qualify((*i)["datatype"].to_string()); + const string type = world->rdf_world->qualify((*i)["type"].to_string()); + const string datatype = world->rdf_world->qualify((*i)["datatype"].to_string()); const Path port_path = patch_path.base() + (string)name; if (created.find(port_path) == created.end()) { bool is_output = (type == "ingen:OutputPort"); // FIXME: check validity - engine->create_port(port_path, datatype, is_output); + world->engine->create_port(port_path, datatype, is_output); created.insert(port_path); } const Redland::Node val_node = (*i)["portval"]; if (val_node.is_float()) { const float val = val_node.to_float(); - engine->set_port_value(patch_path.base() + name, "ingen:control", sizeof(float), &val); + world->engine->set_port_value(patch_path.base() + name, "ingen:Float", sizeof(float), &val); } - const string key = rdf_world->prefixes().qualify((*i)["varkey"].to_string()); + const string key = world->rdf_world->prefixes().qualify((*i)["varkey"].to_string()); const Redland::Node var_val_node = (*i)["varval"]; if (key != "") - engine->set_variable(patch_path.base() + name, key, AtomRDF::node_to_atom(var_val_node)); + world->engine->set_variable(patch_path.base() + name, key, AtomRDF::node_to_atom(var_val_node)); } created.clear(); @@ -270,7 +269,7 @@ Loader::load(SharedPtr<EngineInterface> engine, /* Node -> Node connections */ - query = Redland::Query(*rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?srcnodename ?srcname ?dstnodename ?dstname WHERE {\n") + patch_uri + "ingen:node ?srcnode ;\n" " ingen:node ?dstnode .\n" @@ -283,7 +282,7 @@ Loader::load(SharedPtr<EngineInterface> engine, " ingen:name ?dstname .\n" "}\n"); - results = query.run(*rdf_world, model); + results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { Path src_node = patch_path.base() + Path::nameify((*i)["srcnodename"].to_string()); @@ -293,13 +292,13 @@ Loader::load(SharedPtr<EngineInterface> engine, //cerr << patch_path << " 1 CONNECTION: " << src_port << " -> " << dst_port << endl; - engine->connect(src_port, dst_port); + world->engine->connect(src_port, dst_port); } /* This Patch -> Node connections */ - query = Redland::Query(*rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?srcname ?dstnodename ?dstname WHERE {\n") + patch_uri + " ingen:port ?src ;\n" " ingen:node ?dstnode .\n" @@ -310,7 +309,7 @@ Loader::load(SharedPtr<EngineInterface> engine, "?src ingen:name ?srcname .\n" "}\n"); - results = query.run(*rdf_world, model); + results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { Path src_port = patch_path.base() + Path::nameify((*i)["srcname"].to_string()); @@ -319,13 +318,13 @@ Loader::load(SharedPtr<EngineInterface> engine, //cerr << patch_path << " 2 CONNECTION: " << src_port << " -> " << dst_port << endl; - engine->connect(src_port, dst_port); + world->engine->connect(src_port, dst_port); } /* Node -> This Patch connections */ - query = Redland::Query(*rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?srcnodename ?srcname ?dstname WHERE {\n") + patch_uri + " ingen:port ?dst ;\n" " ingen:node ?srcnode .\n" @@ -336,7 +335,7 @@ Loader::load(SharedPtr<EngineInterface> engine, "?src ingen:name ?srcname .\n" "}\n"); - results = query.run(*rdf_world, model); + results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { Path dst_port = patch_path.base() + Path::nameify((*i)["dstname"].to_string()); @@ -345,13 +344,13 @@ Loader::load(SharedPtr<EngineInterface> engine, //cerr << patch_path << " 3 CONNECTION: " << src_port << " -> " << dst_port << endl; - engine->connect(src_port, dst_port); + world->engine->connect(src_port, dst_port); } /* This Patch -> This Patch connections */ - query = Redland::Query(*rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?srcname ?dstname WHERE {\n") + patch_uri + " ingen:port ?src ;\n" " ingen:port ?dst .\n" @@ -360,7 +359,7 @@ Loader::load(SharedPtr<EngineInterface> engine, "?src ingen:name ?srcname .\n" "}\n"); - results = query.run(*rdf_world, model); + results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { Path src_port = patch_path.base() + Path::nameify((*i)["srcname"].to_string()); @@ -368,51 +367,51 @@ Loader::load(SharedPtr<EngineInterface> engine, //cerr << patch_path << " 4 CONNECTION: " << src_port << " -> " << dst_port << endl; - engine->connect(src_port, dst_port); + world->engine->connect(src_port, dst_port); } /* Load variables */ - query = Redland::Query(*rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?varkey ?varval WHERE {\n") + patch_uri + " ingen:variable ?variable .\n" "?variable ingen:key ?varkey ;\n" " ingen:value ?varval .\n" "}"); - results = query.run(*rdf_world, model); + results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { - const string key = rdf_world->prefixes().qualify(string((*i)["varkey"])); + const string key = world->rdf_world->prefixes().qualify(string((*i)["varkey"])); Redland::Node val_node = (*i)["varval"]; if (key != "") - engine->set_variable(patch_path, key, AtomRDF::node_to_atom(val_node)); + world->engine->set_variable(patch_path, key, AtomRDF::node_to_atom(val_node)); } // Set passed variables last to override any loaded values for (GraphObject::Variables::const_iterator i = data.begin(); i != data.end(); ++i) - engine->set_variable(patch_path, i->first, i->second); + world->engine->set_variable(patch_path, i->first, i->second); /* Enable */ - query = Redland::Query(*rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?enabled WHERE {\n") + patch_uri + " ingen:enabled ?enabled .\n" "}"); - results = query.run(*rdf_world, model); + results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { Redland::Node enabled_node = (*i)["enabled"]; if (enabled_node.is_bool() && enabled_node) { - engine->enable_patch(patch_path); + world->engine->enable_patch(patch_path); break; } } diff --git a/src/libs/serialisation/Loader.hpp b/src/libs/serialisation/Loader.hpp index a1d4e302..1f9328d2 100644 --- a/src/libs/serialisation/Loader.hpp +++ b/src/libs/serialisation/Loader.hpp @@ -25,6 +25,7 @@ #include <raul/Path.hpp> #include <raul/Table.hpp> #include "interface/GraphObject.hpp" +#include "module/World.hpp" namespace Redland { class World; } namespace Ingen { namespace Shared { class EngineInterface; } } @@ -39,14 +40,12 @@ class Loader { public: virtual ~Loader() {} - virtual bool - load(SharedPtr<Ingen::Shared::EngineInterface> engine, - Redland::World* world, - const Glib::ustring& uri, - boost::optional<Raul::Path> parent, - std::string patch_name, - Glib::ustring patch_uri = "", - GraphObject::Variables data = GraphObject::Variables()); + virtual bool load(Ingen::Shared::World* world, + const Glib::ustring& uri, + boost::optional<Raul::Path> parent, + std::string patch_name, + Glib::ustring patch_uri = "", + GraphObject::Variables data = GraphObject::Variables()); }; diff --git a/src/libs/shared/LV2Features.cpp b/src/libs/shared/LV2Features.cpp index 7b57d209..2e7eb10e 100644 --- a/src/libs/shared/LV2Features.cpp +++ b/src/libs/shared/LV2Features.cpp @@ -31,7 +31,7 @@ LV2Features::LV2Features() _lv2_features[0] = NULL; LV2URIMap* controller = new LV2URIMap(); - add_feature(LV2_URI_MAP_URI, &controller->uri_map_feature, controller); + add_feature(LV2_URI_MAP_URI, controller->feature(), controller); } diff --git a/src/libs/shared/LV2URIMap.cpp b/src/libs/shared/LV2URIMap.cpp index 3c38886f..c01dfea0 100644 --- a/src/libs/shared/LV2URIMap.cpp +++ b/src/libs/shared/LV2URIMap.cpp @@ -36,6 +36,14 @@ LV2URIMap::LV2URIMap() uri_map_feature.data = &uri_map_feature_data; } + +uint32_t +LV2URIMap::uri_to_id(const char* map, + const char* uri) +{ + return uri_map_uri_to_id(this, map, uri); +} + uint32_t LV2URIMap::uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data, @@ -55,7 +63,8 @@ LV2URIMap::uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data, me->uri_map.insert(make_pair(string(uri), ret)); } - cout << "URI MAP (" << map << "): " << uri << " -> " << ret << endl; + /*cout << "URI MAP (" << (map ? (void*)map : NULL) + << "): " << uri << " -> " << ret << endl;*/ assert(ret <= UINT16_MAX); return ret; diff --git a/src/libs/shared/LV2URIMap.hpp b/src/libs/shared/LV2URIMap.hpp index 0c947560..35130066 100644 --- a/src/libs/shared/LV2URIMap.hpp +++ b/src/libs/shared/LV2URIMap.hpp @@ -25,6 +25,7 @@ #include <map> #include <string> +#include <boost/utility.hpp> #include <slv2/slv2.h> #include "common/lv2ext/lv2_uri_map.h" @@ -32,22 +33,28 @@ namespace Ingen { namespace Shared { -/** Stuff that may need to be passed to an LV2 plugin (i.e. LV2 features). +/** Implementation of the LV2 URI Map extension */ -class LV2URIMap { +class LV2URIMap : public boost::noncopyable { public: LV2URIMap(); + + LV2_Feature* feature() { return &uri_map_feature; } + + uint32_t uri_to_id(const char* map, + const char* uri); +private: typedef std::map<std::string, uint32_t> URIMap; + static uint32_t uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data, + const char* map, + const char* uri); + LV2_Feature uri_map_feature; LV2_URI_Map_Feature uri_map_feature_data; 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); }; diff --git a/src/libs/shared/Makefile.am b/src/libs/shared/Makefile.am index 4b7c62d4..e6cbee60 100644 --- a/src/libs/shared/Makefile.am +++ b/src/libs/shared/Makefile.am @@ -1,6 +1,6 @@ noinst_LTLIBRARIES = libingen_shared.la -libingen_shared_la_CXXFLAGS = @INGEN_CFLAGS@ @REDLANDMM_CFLAGS@ +libingen_shared_la_CXXFLAGS = @INGEN_CFLAGS@ @REDLANDMM_CFLAGS@ @SLV2_CFLAGS@ libingen_shared_la_SOURCES = \ LV2Features.hpp \ diff --git a/src/progs/ingen/main.cpp b/src/progs/ingen/main.cpp index cf526da5..64cfd36b 100644 --- a/src/progs/ingen/main.cpp +++ b/src/progs/ingen/main.cpp @@ -104,7 +104,7 @@ main(int argc, char** argv) Engine* (*new_engine)(Ingen::Shared::World* world) = NULL; if (engine_module->get_symbol("new_engine", (void*&)new_engine)) { engine = SharedPtr<Engine>(new_engine(world)); - world->local_engine = engine.get(); + world->local_engine = engine; } else { engine_module.reset(); } @@ -152,7 +152,7 @@ main(int argc, char** argv) engine->activate(args.parallelism_arg); } - world->engine = engine_interface.get(); + world->engine = engine_interface; /* Load a patch */ if (args.load_given && engine_interface) { @@ -182,7 +182,7 @@ main(int argc, char** argv) Glib::get_current_dir(), args.load_arg)); } - loader->load(engine_interface, world->rdf_world, uri, parent_path, ""); + loader->load(world, uri, parent_path, ""); } else { cerr << "Unable to load serialisation module, aborting." << endl; @@ -196,12 +196,12 @@ main(int argc, char** argv) bool ran_gui = false; if (args.gui_given) { gui_module = Ingen::Shared::load_module("ingen_gui"); - void (*run)(int, char**, Ingen::Shared::World*, SharedPtr<Ingen::Engine>, SharedPtr<Shared::EngineInterface>) = NULL; + void (*run)(int, char**, Ingen::Shared::World*); bool found = gui_module->get_symbol("run", (void*&)run); if (found) { ran_gui = true; - run(argc, argv, world, engine, engine_interface); + run(argc, argv, world); } else { cerr << "Unable to find GUI module, GUI not loaded." << endl; cerr << "Try using src/set_dev_environment.sh, or setting INGEN_MODULE_PATH." << endl; |