diff options
Diffstat (limited to 'src/libs/engine')
30 files changed, 458 insertions, 287 deletions
diff --git a/src/libs/engine/ClientBroadcaster.cpp b/src/libs/engine/ClientBroadcaster.cpp index 7a21c38b..a214131a 100644 --- a/src/libs/engine/ClientBroadcaster.cpp +++ b/src/libs/engine/ClientBroadcaster.cpp @@ -175,7 +175,7 @@ ClientBroadcaster::send_plugins_to(CountedPtr<ClientInterface> client, const lis for (list<Plugin*>::const_iterator i = plugin_list.begin(); i != plugin_list.end(); ++i) { const Plugin* const plugin = *i; - client->new_plugin(plugin->type_string(), plugin->uri(), plugin->name()); + client->new_plugin(plugin->uri(), plugin->name()); } client->transfer_end(); @@ -191,10 +191,10 @@ ClientBroadcaster::send_plugins(const list<Plugin*>& plugin_list) void -ClientBroadcaster::send_node(const Node* node) +ClientBroadcaster::send_node(const Node* node, bool recursive) { for (ClientList::const_iterator i = _clients.begin(); i != _clients.end(); ++i) - ObjectSender::send_node((*i).second.get(), node); + ObjectSender::send_node((*i).second.get(), node, recursive); } @@ -300,10 +300,10 @@ ClientBroadcaster::send_program_remove(const string& node_path, int bank, int pr * Sends all objects underneath Patch - contained Nodes, etc. */ void -ClientBroadcaster::send_patch(const Patch* const p) +ClientBroadcaster::send_patch(const Patch* const p, bool recursive) { for (ClientList::const_iterator i = _clients.begin(); i != _clients.end(); ++i) - ObjectSender::send_patch((*i).second.get(), p); + ObjectSender::send_patch((*i).second.get(), p, recursive); } diff --git a/src/libs/engine/ClientBroadcaster.h b/src/libs/engine/ClientBroadcaster.h index 47ad75b4..97f2abf2 100644 --- a/src/libs/engine/ClientBroadcaster.h +++ b/src/libs/engine/ClientBroadcaster.h @@ -41,6 +41,7 @@ namespace Shared { class ClientKey; } using Shared::ClientKey; using Shared::ClientInterface; + /** Broadcaster for all clients. * * This sends messages to all client simultaneously through the opaque @@ -71,8 +72,8 @@ public: //void send_node_creation_messages(const Node* const node); void send_plugins(const list<Plugin*>& plugin_list); - void send_patch(const Patch* const p); - void send_node(const Node* const node); + void send_patch(const Patch* const p, bool recursive); + void send_node(const Node* const node, bool recursive); void send_port(const Port* port); void send_destroyed(const string& path); void send_patch_cleared(const string& patch_path); diff --git a/src/libs/engine/Engine.h b/src/libs/engine/Engine.h index 1f84d867..a8d110ca 100644 --- a/src/libs/engine/Engine.h +++ b/src/libs/engine/Engine.h @@ -72,7 +72,7 @@ public: MidiDriver* midi_driver() const { return m_midi_driver; } Maid* maid() const { return m_maid; } PostProcessor* post_processor() const { return m_post_processor; } - ClientBroadcaster* broadcaster() const { return m_broadcaster; } + ClientBroadcaster* broadcaster() const { return m_broadcaster; } ObjectStore* object_store() const { return m_object_store; } NodeFactory* node_factory() const { return m_node_factory; } LashDriver* lash_driver() const { return m_lash_driver; } diff --git a/src/libs/engine/Makefile.am b/src/libs/engine/Makefile.am index 99679932..3747515b 100644 --- a/src/libs/engine/Makefile.am +++ b/src/libs/engine/Makefile.am @@ -72,9 +72,6 @@ libingen_la_SOURCES = \ Plugin.cpp \ Array.h \ List.h \ - Slave.h \ - Thread.h \ - Thread.cpp \ PostProcessor.h \ PostProcessor.cpp \ Connection.h \ @@ -133,6 +130,10 @@ libingen_la_SOURCES = \ events/SetMetadataEvent.cpp \ events/RequestMetadataEvent.h \ events/RequestMetadataEvent.cpp \ + events/RequestPluginEvent.h \ + events/RequestPluginEvent.cpp \ + events/RequestObjectEvent.h \ + events/RequestObjectEvent.cpp \ events/RequestPortValueEvent.h \ events/RequestPortValueEvent.cpp \ events/RequestAllObjectsEvent.h \ diff --git a/src/libs/engine/NodeFactory.cpp b/src/libs/engine/NodeFactory.cpp index ca762678..1cbabaeb 100644 --- a/src/libs/engine/NodeFactory.cpp +++ b/src/libs/engine/NodeFactory.cpp @@ -95,7 +95,6 @@ NodeFactory::~NodeFactory() const Plugin* NodeFactory::plugin(const string& uri) { - // FIXME: this needs.. well, fixing for (list<Plugin*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i) if ((*i)->uri() == uri) return (*i); @@ -104,6 +103,24 @@ NodeFactory::plugin(const string& uri) } +/** DEPRECATED: Find a plugin by type, lib, label. + * + * Do not use. + */ +const Plugin* +NodeFactory::plugin(const string& type, const string& lib, const string& label) +{ + if (type == "" || lib == "" || label == "") + return NULL; + + for (list<Plugin*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i) + if ((*i)->type_string() == type && (*i)->lib_name() == lib && (*i)->plug_label() == label) + return (*i); + + return NULL; +} + + void NodeFactory::load_plugins() { diff --git a/src/libs/engine/NodeFactory.h b/src/libs/engine/NodeFactory.h index 1fd6c2d4..573c6808 100644 --- a/src/libs/engine/NodeFactory.h +++ b/src/libs/engine/NodeFactory.h @@ -57,6 +57,7 @@ public: const list<Plugin*>& plugins() { return _plugins; } const Plugin* plugin(const string& uri); + const Plugin* plugin(const string& type, const string& lib, const string& label); // DEPRECATED private: #ifdef HAVE_LADSPA diff --git a/src/libs/engine/OSCClientSender.cpp b/src/libs/engine/OSCClientSender.cpp index 538630c0..17b730fb 100644 --- a/src/libs/engine/OSCClientSender.cpp +++ b/src/libs/engine/OSCClientSender.cpp @@ -217,13 +217,14 @@ OSCClientSender::plugins() * this one (/om/new_node), followed by a series of /om/new_port commands, * followed by /om/new_node_end. </p> \n \n */ -void OSCClientSender::new_node(string plugin_type, - string plugin_uri, - string node_path, - bool is_polyphonic, - uint32_t num_ports) +void OSCClientSender::new_node(string plugin_uri, + string node_path, + bool is_polyphonic, + uint32_t num_ports) { - lo_send(_address, "/om/new_node", "sssii", plugin_type.c_str(), plugin_uri.c_str(), + //cerr << "Sending node " << node_path << endl; + + lo_send(_address, "/om/new_node", "ssii", plugin_uri.c_str(), node_path.c_str(), is_polyphonic ? 1 : 0, num_ports); #if 0 /* @@ -453,10 +454,9 @@ OSCClientSender::control_change(string port_path, float value) * \arg \b name (string) - Descriptive human-readable name of plugin (ie "ADSR Envelope") */ void -OSCClientSender::new_plugin(string type, string uri, string name) +OSCClientSender::new_plugin(string uri, string name) { lo_message m = lo_message_new(); - lo_message_add_string(m, type.c_str()); lo_message_add_string(m, uri.c_str()); lo_message_add_string(m, name.c_str()); diff --git a/src/libs/engine/OSCClientSender.h b/src/libs/engine/OSCClientSender.h index 260dba63..a2ee9e26 100644 --- a/src/libs/engine/OSCClientSender.h +++ b/src/libs/engine/OSCClientSender.h @@ -72,14 +72,12 @@ public: void error(string msg); - virtual void new_plugin(string type, - string uri, + virtual void new_plugin(string uri, string name); virtual void new_patch(string path, uint32_t poly); - virtual void new_node(string plugin_type, - string plugin_uri, + virtual void new_node(string plugin_uri, string node_path, bool is_polyphonic, uint32_t num_ports); diff --git a/src/libs/engine/OSCEngineReceiver.cpp b/src/libs/engine/OSCEngineReceiver.cpp index 92ab08f0..50876850 100644 --- a/src/libs/engine/OSCEngineReceiver.cpp +++ b/src/libs/engine/OSCEngineReceiver.cpp @@ -88,7 +88,7 @@ OSCEngineReceiver::OSCEngineReceiver(CountedPtr<Engine> engine, size_t queue_siz lo_server_add_method(_server, "/om/synth/disable_patch", "is", disable_patch_cb, this); lo_server_add_method(_server, "/om/synth/clear_patch", "is", clear_patch_cb, this); lo_server_add_method(_server, "/om/synth/create_port", "issi", create_port_cb, this); - lo_server_add_method(_server, "/om/synth/create_node", "isssi", create_node_cb, this); + lo_server_add_method(_server, "/om/synth/create_node", "issssi", create_node_cb, this); lo_server_add_method(_server, "/om/synth/create_node", "issi", create_node_by_uri_cb, this); lo_server_add_method(_server, "/om/synth/destroy", "is", destroy_cb, this); lo_server_add_method(_server, "/om/synth/rename", "iss", rename_cb, this); @@ -110,9 +110,12 @@ OSCEngineReceiver::OSCEngineReceiver(CountedPtr<Engine> engine, size_t queue_siz lo_server_add_method(_server, "/om/metadata/set", NULL, metadata_set_cb, this); // Queries + lo_server_add_method(_server, "/om/request/plugin", "is", request_plugin_cb, this); + lo_server_add_method(_server, "/om/request/object", "is", request_object_cb, this); + lo_server_add_method(_server, "/om/request/port_value", "is", request_port_value_cb, this); lo_server_add_method(_server, "/om/request/plugins", "i", request_plugins_cb, this); lo_server_add_method(_server, "/om/request/all_objects", "i", request_all_objects_cb, this); - lo_server_add_method(_server, "/om/request/port_value", "is", request_port_value_cb, this); + // DSSI support #ifdef HAVE_DSSI @@ -799,29 +802,37 @@ OSCEngineReceiver::m_metadata_get_cb(const char* path, const char* types, lo_arg /** \page engine_osc_namespace - * <p> \b /om/responder/plugins - Requests the engine send a list of all known plugins. + * <p> \b /om/responder/plugin - Requests the engine send the value of a port. * \arg \b response-id (integer) + * \arg \b port-path (string) - Full path of port to send the value of </p> \n \n * * \li Reply will be sent to client registered with the source address of this message.</p> \n \n */ int -OSCEngineReceiver::m_request_plugins_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +OSCEngineReceiver::m_request_plugin_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { - request_plugins(); + const char* uri = &argv[1]->s; + + request_plugin(uri); + return 0; } /** \page engine_osc_namespace - * <p> \b /om/responder/all_objects - Requests the engine send information about \em all objects (patches, nodes, etc) + * <p> \b /om/responder/object - Requests the engine send the value of a port. * \arg \b response-id (integer) - * + * \arg \b port-path (string) - Full path of port to send the value of </p> \n \n + * * \li Reply will be sent to client registered with the source address of this message.</p> \n \n */ int -OSCEngineReceiver::m_request_all_objects_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +OSCEngineReceiver::m_request_object_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { - request_all_objects(); + const char* object_path = &argv[1]->s; + + request_object(object_path); + return 0; } @@ -843,6 +854,34 @@ OSCEngineReceiver::m_request_port_value_cb(const char* path, const char* types, } +/** \page engine_osc_namespace + * <p> \b /om/responder/plugins - Requests the engine send a list of all known plugins. + * \arg \b response-id (integer) + * + * \li Reply will be sent to client registered with the source address of this message.</p> \n \n + */ +int +OSCEngineReceiver::m_request_plugins_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + request_plugins(); + return 0; +} + + +/** \page engine_osc_namespace + * <p> \b /om/responder/all_objects - Requests the engine send information about \em all objects (patches, nodes, etc) + * \arg \b response-id (integer) + * + * \li Reply will be sent to client registered with the source address of this message.</p> \n \n + */ +int +OSCEngineReceiver::m_request_all_objects_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) +{ + request_all_objects(); + return 0; +} + + #ifdef HAVE_DSSI int OSCEngineReceiver::m_dssi_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) diff --git a/src/libs/engine/OSCEngineReceiver.h b/src/libs/engine/OSCEngineReceiver.h index 793286d4..c31587e6 100644 --- a/src/libs/engine/OSCEngineReceiver.h +++ b/src/libs/engine/OSCEngineReceiver.h @@ -107,9 +107,12 @@ private: LO_HANDLER(midi_learn); LO_HANDLER(metadata_get); LO_HANDLER(metadata_set); + LO_HANDLER(request_plugin); + LO_HANDLER(request_object); + LO_HANDLER(request_port_value); LO_HANDLER(request_plugins); LO_HANDLER(request_all_objects); - LO_HANDLER(request_port_value); + #ifdef HAVE_DSSI LO_HANDLER(dssi); #endif diff --git a/src/libs/engine/ObjectSender.cpp b/src/libs/engine/ObjectSender.cpp index 1e6b93c5..f7b4790f 100644 --- a/src/libs/engine/ObjectSender.cpp +++ b/src/libs/engine/ObjectSender.cpp @@ -28,41 +28,35 @@ namespace Ingen { void -ObjectSender::send_patch(ClientInterface* client, const Patch* patch) +ObjectSender::send_patch(ClientInterface* client, const Patch* patch, bool recursive) { client->new_patch(patch->path(), patch->internal_poly()); - for (List<Node*>::const_iterator j = patch->nodes().begin(); - j != patch->nodes().end(); ++j) { - const Node* const node = (*j); + if (recursive) { - send_node(client, node); - } - - // Send port information - for (size_t i=0; i < patch->num_ports(); ++i) { - Port* const port = patch->ports().at(i); - send_port(client, port); -/* - // Send metadata - const GraphObject::MetadataMap& data = port->metadata(); - for (GraphObject::MetadataMap::const_iterator i = data.begin(); i != data.end(); ++i) - client->metadata_update(port->path(), (*i).first, (*i).second); - - // Control port, send value - if (port->type() == DataType::FLOAT && port->buffer_size() == 1) - client->control_change(port->path(), - dynamic_cast<TypedPort<Sample>*>(port)->buffer(0)->value_at(0)); -*/ - } + // Send nodes + for (List<Node*>::const_iterator j = patch->nodes().begin(); + j != patch->nodes().end(); ++j) { + + const Node* const node = (*j); + send_node(client, node, true); + } + // Send ports + for (size_t i=0; i < patch->num_ports(); ++i) { + + Port* const port = patch->ports().at(i); + send_port(client, port); + + } + + // Send connections + for (List<Connection*>::const_iterator j = patch->connections().begin(); + j != patch->connections().end(); ++j) + client->connection((*j)->src_port()->path(), (*j)->dst_port()->path()); + + } - // Send connections - for (List<Connection*>::const_iterator j = patch->connections().begin(); - j != patch->connections().end(); ++j) - client->connection((*j)->src_port()->path(), (*j)->dst_port()->path()); - - // Send metadata const GraphObject::MetadataMap& data = patch->metadata(); for (GraphObject::MetadataMap::const_iterator j = data.begin(); j != data.end(); ++j) @@ -75,7 +69,7 @@ ObjectSender::send_patch(ClientInterface* client, const Patch* patch) /** Sends a node or a patch */ void -ObjectSender::send_node(ClientInterface* client, const Node* node) +ObjectSender::send_node(ClientInterface* client, const Node* node, bool recursive) { const Plugin* const plugin = node->plugin(); @@ -87,7 +81,7 @@ ObjectSender::send_node(ClientInterface* client, const Node* node) assert(node->path().length() > 0); if (plugin->type() == Plugin::Patch) { - send_patch(client, (Patch*)node); + send_patch(client, (Patch*)node, recursive); return; } @@ -95,32 +89,30 @@ ObjectSender::send_node(ClientInterface* client, const Node* node) cerr << "Node " << node->path() << " plugin has no URI! Not sending." << endl; return; } - - client->bundle_begin(); - // FIXME: bundleify + //client->bundle_begin(); const Array<Port*>& ports = node->ports(); - client->new_node(node->plugin()->type_string(), node->plugin()->uri(), - node->path(), polyphonic, ports.size()); + client->new_node(node->plugin()->uri(), node->path(), polyphonic, ports.size()); - // Send ports - for (size_t j=0; j < ports.size(); ++j) { - Port* const port = ports.at(j); - assert(port); - - send_port(client, port); - //client->new_port(port->path(), port->type().uri(), port->is_output()); + if (recursive) { + // Send ports + for (size_t j=0; j < ports.size(); ++j) { + Port* const port = ports.at(j); + assert(port); + + send_port(client, port); + } } - client->bundle_end(); - // Send metadata const GraphObject::MetadataMap& data = node->metadata(); for (GraphObject::MetadataMap::const_iterator j = data.begin(); j != data.end(); ++j) client->metadata_update(node->path(), (*j).first, (*j).second); + + //client->bundle_end(); } @@ -128,6 +120,8 @@ void ObjectSender::send_port(ClientInterface* client, const Port* port) { assert(port); + + //cerr << "Sending port " << port->path(); // FIXME: temporary compatibility hack string type = port->type().uri(); @@ -137,7 +131,9 @@ ObjectSender::send_port(ClientInterface* client, const Port* port) else type = "AUDIO"; } - + + //cerr << ", type = " << type << endl; + client->new_port(port->path(), type, port->is_output()); // Send control value @@ -171,7 +167,7 @@ ObjectSender::send_plugins(ClientInterface* client, const list<Plugin*>& plugs) */ for (list<Plugin*>::const_iterator j = plugs.begin(); j != plugs.end(); ++j) { const Plugin* const p = *j; - client->new_plugin(p->type_string(), p->uri(), p->name()); + client->new_plugin(p->uri(), p->name()); } /* plugin = (*j); diff --git a/src/libs/engine/ObjectSender.h b/src/libs/engine/ObjectSender.h index 38b1577f..ddd72dd7 100644 --- a/src/libs/engine/ObjectSender.h +++ b/src/libs/engine/ObjectSender.h @@ -45,8 +45,8 @@ public: // FIXME: Make all object parameters const - static void send_patch(ClientInterface* client, const Patch* patch); - static void send_node(ClientInterface* client, const Node* node); + static void send_patch(ClientInterface* client, const Patch* patch, bool recursive); + static void send_node(ClientInterface* client, const Node* node, bool recursive); static void send_port(ClientInterface* client, const Port* port); static void send_plugins(ClientInterface* client, const std::list<Plugin*>& plugs); }; diff --git a/src/libs/engine/Plugin.h b/src/libs/engine/Plugin.h index bdb5a748..a841d6ee 100644 --- a/src/libs/engine/Plugin.h +++ b/src/libs/engine/Plugin.h @@ -53,6 +53,11 @@ public: Plugin(Type type, const string& uri) : _type(type) , _uri(uri) + , _id(0) + , _library(NULL) +#ifdef HAVE_SLV2 + , _slv2_plugin(NULL) +#endif {} // FIXME: remove @@ -71,10 +76,12 @@ public: if (copy->_type != Internal) exit(EXIT_FAILURE); _type = copy->_type; - _lib_path = copy->_lib_path; _uri = copy->_uri; + _lib_path = copy->_lib_path; + _lib_name = copy->_lib_name; _plug_label = copy->_plug_label; _name = copy->_name; + _id = _id; _library = copy->_library; } diff --git a/src/libs/engine/PostProcessor.h b/src/libs/engine/PostProcessor.h index e29175ee..212e3797 100644 --- a/src/libs/engine/PostProcessor.h +++ b/src/libs/engine/PostProcessor.h @@ -20,7 +20,7 @@ #include <pthread.h> #include "types.h" #include "util/Queue.h" -#include "Slave.h" +#include "util/Slave.h" class Maid; diff --git a/src/libs/engine/QueuedEngineInterface.cpp b/src/libs/engine/QueuedEngineInterface.cpp index f8fc4827..53c5668c 100644 --- a/src/libs/engine/QueuedEngineInterface.cpp +++ b/src/libs/engine/QueuedEngineInterface.cpp @@ -135,7 +135,7 @@ void QueuedEngineInterface::create_port(const string& path, const string& data_type, bool direction) { - push_queued(new AddPortEvent(*_engine.get(), _responder, now(), path, data_type, direction)); + push_queued(new AddPortEvent(*_engine.get(), _responder, now(), path, data_type, direction, this)); } @@ -144,7 +144,8 @@ QueuedEngineInterface::create_node(const string& path, const string& plugin_uri, bool polyphonic) { - push_queued(new AddNodeEvent(*_engine.get(), _responder, now(), path, plugin_uri, polyphonic)); + push_queued(new AddNodeEvent(*_engine.get(), _responder, now(), + path, plugin_uri, polyphonic)); } @@ -155,18 +156,8 @@ QueuedEngineInterface::create_node(const string& path, const string& plugin_label, bool polyphonic) { - cerr << "FIXME: deprecated create_node\n"; - throw; -#if 0 - // FIXME: ew - - Plugin* plugin = new Plugin(); - plugin->set_type(plugin_type); - plugin->lib_name(plugin_lib); - plugin->plug_label(plugin_label); - - push_queued(new AddNodeEvent(*_engine.get(), _responder, now(), path, plugin, polyphonic)); -#endif + push_queued(new AddNodeEvent(*_engine.get(), _responder, now(), + path, plugin_type, plugin_lib, plugin_label, polyphonic)); } void @@ -295,6 +286,20 @@ QueuedEngineInterface::ping() void +QueuedEngineInterface::request_plugin(const string& uri) +{ + push_queued(new RequestPluginEvent(*_engine.get(), _responder, now(), uri)); +} + + +void +QueuedEngineInterface::request_object(const string& path) +{ + push_queued(new RequestObjectEvent(*_engine.get(), _responder, now(), path)); +} + + +void QueuedEngineInterface::request_port_value(const string& port_path) { push_queued(new RequestPortValueEvent(*_engine.get(), _responder, now(), port_path)); diff --git a/src/libs/engine/QueuedEngineInterface.h b/src/libs/engine/QueuedEngineInterface.h index 10b120e8..2a922acd 100644 --- a/src/libs/engine/QueuedEngineInterface.h +++ b/src/libs/engine/QueuedEngineInterface.h @@ -142,6 +142,10 @@ public: virtual void ping(); + virtual void request_plugin(const string& uri); + + virtual void request_object(const string& path); + virtual void request_port_value(const string& port_path); virtual void request_plugins(); diff --git a/src/libs/engine/QueuedEventSource.h b/src/libs/engine/QueuedEventSource.h index f6be92d7..fddb61ab 100644 --- a/src/libs/engine/QueuedEventSource.h +++ b/src/libs/engine/QueuedEventSource.h @@ -22,7 +22,7 @@ #include "types.h" #include "util/Semaphore.h" #include "util/Queue.h" -#include "Slave.h" +#include "util/Slave.h" #include "Event.h" #include "EventSource.h" diff --git a/src/libs/engine/Thread.cpp b/src/libs/engine/Thread.cpp deleted file mode 100644 index 45c27ec4..00000000 --- a/src/libs/engine/Thread.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. - * - * Ingen 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 Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "Thread.h" -#include <cassert> -#include <iostream> -#include <pthread.h> - -using std::cerr; using std::cout; using std::endl; - -namespace Ingen { - - -Thread::Thread() -: _pthread_exists(false) -{ -} - - -Thread::~Thread() -{ - stop(); -} - - -/** Start the process thread. - */ -void -Thread::start() -{ - cout << "[" << _name << " Thread] Starting." << endl; - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, 1500000); - - pthread_create(&_pthread, &attr, _static_run, this); - _pthread_exists = true; -} - - -/** Stop the process thread. - */ -void -Thread::stop() -{ - if (_pthread_exists) { - pthread_cancel(_pthread); - pthread_join(_pthread, NULL); - _pthread_exists = false; - } -} - - -/** Set the scheduling policy for this thread. - * - * @param must be one of SCHED_FIFO, SCHED_RR, or SCHED_OTHER. - */ -void -Thread::set_scheduling(int policy, unsigned int priority) -{ - sched_param sp; - sp.sched_priority = priority; - int result = pthread_setschedparam(_pthread, SCHED_FIFO, &sp); - if (!result) { - cout << "[" << _name << " Thread] Set scheduling policy to "; - switch (policy) { - case SCHED_FIFO: cout << "SCHED_FIFO"; break; - case SCHED_RR: cout << "SCHED_RR"; break; - case SCHED_OTHER: cout << "SCHED_OTHER"; break; - default: cout << "UNKNOWN"; break; - } - cout << ", priority " << sp.sched_priority << endl; - } else { - cout << "[" << _name << " Thread] Unable to set scheduling policy (" - << strerror(result) << ")" << endl; - } -} - - -void* -Thread::_static_run(void* me) -{ - Thread* myself = (Thread*)me; - myself->_run(); - // and I - return NULL; -} - -} // namespace Ingen - diff --git a/src/libs/engine/events.h b/src/libs/engine/events.h index 9db13bc7..056c302d 100644 --- a/src/libs/engine/events.h +++ b/src/libs/engine/events.h @@ -34,6 +34,8 @@ #include "DestroyEvent.h" #include "SetMetadataEvent.h" #include "RequestMetadataEvent.h" +#include "RequestObjectEvent.h" +#include "RequestPluginEvent.h" #include "RequestPortValueEvent.h" #include "RequestAllObjectsEvent.h" #include "RequestPluginsEvent.h" diff --git a/src/libs/engine/events/AddNodeEvent.cpp b/src/libs/engine/events/AddNodeEvent.cpp index 6e42ef82..1a317e39 100644 --- a/src/libs/engine/events/AddNodeEvent.cpp +++ b/src/libs/engine/events/AddNodeEvent.cpp @@ -33,23 +33,31 @@ namespace Ingen { -/*AddNodeEvent::AddNodeEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path, Plugin* plugin, bool poly) +AddNodeEvent::AddNodeEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path, + const string& plugin_uri, bool poly) : QueuedEvent(engine, responder, timestamp), m_path(path), - m_plugin(plugin), + m_plugin_uri(plugin_uri), m_poly(poly), m_patch(NULL), m_node(NULL), m_process_order(NULL), m_node_already_exists(false) { -}*/ +} + +/** DEPRECATED: Construct from type, library name, and plugin label. + * + * Do not use. + */ AddNodeEvent::AddNodeEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path, - const string& plugin_uri, bool poly) + const string& plugin_type, const string& plugin_lib, const string& plugin_label, bool poly) : QueuedEvent(engine, responder, timestamp), m_path(path), - m_plugin_uri(plugin_uri), + m_plugin_type(plugin_type), + m_plugin_lib(plugin_lib), + m_plugin_label(plugin_label), m_poly(poly), m_patch(NULL), m_node(NULL), @@ -59,11 +67,6 @@ AddNodeEvent::AddNodeEvent(Engine& engine, CountedPtr<Responder> responder, Samp } -AddNodeEvent::~AddNodeEvent() -{ -} - - void AddNodeEvent::pre_process() { @@ -74,7 +77,10 @@ AddNodeEvent::pre_process() } m_patch = _engine.object_store()->find_patch(m_path.parent()); - const Plugin* plugin = _engine.node_factory()->plugin(m_plugin_uri); + + const Plugin* plugin = (m_plugin_uri != "") + ? _engine.node_factory()->plugin(m_plugin_uri) + : _engine.node_factory()->plugin(m_plugin_type, m_plugin_lib, m_plugin_label); if (m_patch && plugin) { if (m_poly) @@ -130,8 +136,7 @@ AddNodeEvent::post_process() _responder->respond_error(msg); } else { _responder->respond_ok(); - //_engine.broadcaster()->send_node_creation_messages(m_node); - _engine.broadcaster()->send_node(m_node); + _engine.broadcaster()->send_node(m_node, true); // yes, send ports } } diff --git a/src/libs/engine/events/AddNodeEvent.h b/src/libs/engine/events/AddNodeEvent.h index b4345f90..22e164ea 100644 --- a/src/libs/engine/events/AddNodeEvent.h +++ b/src/libs/engine/events/AddNodeEvent.h @@ -39,15 +39,22 @@ class Plugin; class AddNodeEvent : public QueuedEvent { public: - //AddNodeEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path, Plugin* plugin, bool poly); AddNodeEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& node_path, const string& plugin_uri, bool poly); - - ~AddNodeEvent(); + + // DEPRECATED + AddNodeEvent(Engine& engine, + CountedPtr<Responder> responder, + SampleCount timestamp, + const string& node_path, + const string& plugin_type, + const string& lib_name, + const string& plugin_label, + bool poly); void pre_process(); void execute(SampleCount nframes, FrameTime start, FrameTime end); @@ -56,7 +63,10 @@ public: private: string m_patch_name; Path m_path; - string m_plugin_uri; + string m_plugin_uri; ///< If nonempty then type, library, label, are ignored + string m_plugin_type; + string m_plugin_lib; + string m_plugin_label; bool m_poly; Patch* m_patch; Node* m_node; diff --git a/src/libs/engine/events/AddPortEvent.cpp b/src/libs/engine/events/AddPortEvent.cpp index 06ddae94..ae692b1b 100644 --- a/src/libs/engine/events/AddPortEvent.cpp +++ b/src/libs/engine/events/AddPortEvent.cpp @@ -23,6 +23,7 @@ #include "Patch.h" #include "Maid.h" #include "util/Path.h" +#include "QueuedEventSource.h" #include "ObjectStore.h" #include "ClientBroadcaster.h" #include "util/Path.h" @@ -32,12 +33,13 @@ #include "List.h" #include "Driver.h" #include "DuplexPort.h" +#include "Array.h" namespace Ingen { -AddPortEvent::AddPortEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path, const string& type, bool is_output) -: QueuedEvent(engine, responder, timestamp), +AddPortEvent::AddPortEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path, const string& type, bool is_output, QueuedEventSource* source) +: QueuedEvent(engine, responder, timestamp, true, source), _path(path), _type(type), _is_output(is_output), @@ -46,6 +48,14 @@ AddPortEvent::AddPortEvent(Engine& engine, CountedPtr<Responder> responder, Samp _patch_port(NULL), _driver_port(NULL) { + /* This is blocking because of the two different sets of Patch ports, the array used in the + * audio thread (inherited from NodeBase), and the arrays used in the pre processor thread. + * If two add port events arrive in the same cycle and the second pre processes before the + * first executes, bad things happen (ports are lost). + * + * FIXME: fix this using RCU + */ + string type_str; if (type == "CONTROL" || type == "AUDIO") _data_type = DataType::FLOAT; @@ -73,17 +83,22 @@ AddPortEvent::pre_process() if (_type == "AUDIO" || _type == "MIDI") buffer_size = _engine.audio_driver()->buffer_size(); + const size_t old_num_ports = _patch->num_ports(); + _patch_port = _patch->create_port(_path.name(), _data_type, buffer_size, _is_output); + if (_patch_port) { + if (_is_output) _patch->add_output(new ListNode<Port*>(_patch_port)); else _patch->add_input(new ListNode<Port*>(_patch_port)); if (_patch->external_ports()) - _ports_array = new Array<Port*>(_patch->num_ports() + 1, *_patch->external_ports()); + _ports_array = new Array<Port*>(old_num_ports + 1, *_patch->external_ports()); else - _ports_array = new Array<Port*>(_patch->num_ports() + 1, NULL); + _ports_array = new Array<Port*>(old_num_ports + 1, NULL); + _ports_array->at(_patch->num_ports()) = _patch_port; _engine.object_store()->add(_patch_port); @@ -96,6 +111,9 @@ AddPortEvent::pre_process() _driver_port = _engine.midi_driver()->create_port( dynamic_cast<DuplexPort<MidiMessage>*>(_patch_port)); } + + assert(_patch->num_ports() == old_num_ports); + assert(_ports_array->size() == _patch->num_ports() + 1); } } QueuedEvent::pre_process(); @@ -108,8 +126,10 @@ AddPortEvent::execute(SampleCount nframes, FrameTime start, FrameTime end) QueuedEvent::execute(nframes, start, end); if (_patch_port) { + _engine.maid()->push(_patch->external_ports()); //_patch->add_port(_port); + _patch->external_ports(_ports_array); } @@ -121,6 +141,9 @@ AddPortEvent::execute(SampleCount nframes, FrameTime start, FrameTime end) void AddPortEvent::post_process() { + if (_source) + _source->unblock(); + if (!_patch_port) { const string msg = string("Could not create port - ").append(_path); _responder->respond_error(msg); diff --git a/src/libs/engine/events/AddPortEvent.h b/src/libs/engine/events/AddPortEvent.h index 070d07df..0ef33515 100644 --- a/src/libs/engine/events/AddPortEvent.h +++ b/src/libs/engine/events/AddPortEvent.h @@ -41,7 +41,7 @@ class DriverPort; class AddPortEvent : public QueuedEvent { public: - AddPortEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path, const string& type, bool is_output); + AddPortEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path, const string& type, bool is_output, QueuedEventSource* source); void pre_process(); void execute(SampleCount nframes, FrameTime start, FrameTime end); diff --git a/src/libs/engine/events/CreatePatchEvent.cpp b/src/libs/engine/events/CreatePatchEvent.cpp index 7532291b..97be5557 100644 --- a/src/libs/engine/events/CreatePatchEvent.cpp +++ b/src/libs/engine/events/CreatePatchEvent.cpp @@ -120,11 +120,9 @@ CreatePatchEvent::post_process() _responder->respond_ok(); - // Don't want to send nodes that have been added since prepare() - //_engine.broadcaster()->send_node_creation_messages(m_patch); - - // Patches are always empty on creation, so this is fine - _engine.broadcaster()->send_patch(m_patch); + // Don't send ports/nodes that have been added since prepare() + // (otherwise they would be sent twice) + _engine.broadcaster()->send_patch(m_patch, false); } else if (m_error == OBJECT_EXISTS) { string msg = "Unable to create patch: "; diff --git a/src/libs/engine/events/Makefile.am b/src/libs/engine/events/Makefile.am index 5b29e12b..a1760738 100644 --- a/src/libs/engine/events/Makefile.am +++ b/src/libs/engine/events/Makefile.am @@ -36,6 +36,10 @@ EXTRA_DIST = \ events/SetMetadataEvent.cpp \ events/RequestMetadataEvent.h \ events/RequestMetadataEvent.cpp \ + events/RequestPluginEvent.h \ + events/RequestPluginEvent.cpp \ + events/RequestObjectEvent.h \ + events/RequestObjectEvent.cpp \ events/RequestPortValueEvent.h \ events/RequestPortValueEvent.cpp \ events/RequestAllObjectsEvent.h \ diff --git a/src/libs/engine/events/RequestAllObjectsEvent.cpp b/src/libs/engine/events/RequestAllObjectsEvent.cpp index f51a514e..893aa5df 100644 --- a/src/libs/engine/events/RequestAllObjectsEvent.cpp +++ b/src/libs/engine/events/RequestAllObjectsEvent.cpp @@ -48,7 +48,7 @@ RequestAllObjectsEvent::post_process() // Everything is a child of the root patch, so this sends it all Patch* root = _engine.object_store()->find_patch("/"); if (root) - ObjectSender::send_patch(m_client.get(), root); + ObjectSender::send_patch(m_client.get(), root, true); } else { _responder->respond_error("Unable to find client to send all objects"); diff --git a/src/libs/engine/events/RequestObjectEvent.cpp b/src/libs/engine/events/RequestObjectEvent.cpp new file mode 100644 index 00000000..3b0dc6fd --- /dev/null +++ b/src/libs/engine/events/RequestObjectEvent.cpp @@ -0,0 +1,97 @@ +/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. + * + * Ingen 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 Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "RequestObjectEvent.h" +#include <string> +#include "Responder.h" +#include "Engine.h" +#include "interface/ClientInterface.h" +#include "TypedPort.h" +#include "ObjectStore.h" +#include "ClientBroadcaster.h" +#include "Patch.h" +#include "Node.h" +#include "ObjectSender.h" + +using std::string; + +namespace Ingen { + + +RequestObjectEvent::RequestObjectEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& path) +: QueuedEvent(engine, responder, timestamp), + m_path(path), + m_object(NULL) +{ +} + + +void +RequestObjectEvent::pre_process() +{ + m_client = _engine.broadcaster()->client(_responder->client_key()); + m_object = _engine.object_store()->find(m_path); + + QueuedEvent::pre_process(); +} + + +void +RequestObjectEvent::execute(SampleCount nframes, FrameTime start, FrameTime end) +{ + QueuedEvent::execute(nframes, start, end); + assert(_time >= start && _time <= end); +} + + +void +RequestObjectEvent::post_process() +{ + if (!m_object) { + _responder->respond_error("Unable to find object requested."); + + } else if (m_client) { + Patch* const patch = dynamic_cast<Patch*>(m_object); + if (patch) { + _responder->respond_ok(); + ObjectSender::send_patch(m_client.get(), patch, true); + return; + } + + Node* const node = dynamic_cast<Node*>(m_object); + if (node) { + _responder->respond_ok(); + ObjectSender::send_node(m_client.get(), node, true); + return; + } + + Port* const port = dynamic_cast<Port*>(m_object); + if (port) { + _responder->respond_ok(); + ObjectSender::send_port(m_client.get(), port); + return; + } + + _responder->respond_error("Object of unknown type requested."); + + } else { + _responder->respond_error("Unable to find client to send object."); + } +} + + +} // namespace Ingen + diff --git a/src/libs/engine/Slave.h b/src/libs/engine/events/RequestObjectEvent.h index b48a3ab7..276b60fa 100644 --- a/src/libs/engine/Slave.h +++ b/src/libs/engine/events/RequestObjectEvent.h @@ -14,48 +14,42 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef SLAVE_H -#define SLAVE_H +#ifndef REQUESTOBJECTEVENT_H +#define REQUESTOBJECTEVENT_H -#include <pthread.h> -#include "util/Semaphore.h" -#include "Thread.h" +#include <string> +#include "QueuedEvent.h" +#include "types.h" + +using std::string; namespace Ingen { + +class GraphObject; +namespace Shared { class ClientInterface; } +using Shared::ClientInterface; -/** Thread driven by (realtime safe) signals. +/** A request from a client to send the value of a port. * * \ingroup engine */ -class Slave : public Thread +class RequestObjectEvent : public QueuedEvent { public: - Slave() : _whip(0) {} - - /** Tell the slave to do whatever work it does. Realtime safe. */ - inline void whip() { _whip.post(); } - -protected: - virtual void _whipped() = 0; + RequestObjectEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& port_path); - Semaphore _whip; + void pre_process(); + void execute(SampleCount nframes, FrameTime start, FrameTime end); + void post_process(); private: - // Prevent copies - Slave(const Slave&); - Slave& operator=(const Slave&); - - inline void _run() - { - while (true) { - _whip.wait(); - _whipped(); - } - } + string m_path; + GraphObject* m_object; + CountedPtr<ClientInterface> m_client; }; } // namespace Ingen -#endif // SLAVE_H +#endif // REQUESTOBJECTEVENT_H diff --git a/src/libs/engine/events/RequestPluginEvent.cpp b/src/libs/engine/events/RequestPluginEvent.cpp new file mode 100644 index 00000000..95141226 --- /dev/null +++ b/src/libs/engine/events/RequestPluginEvent.cpp @@ -0,0 +1,78 @@ +/* This file is part of Ingen. Copyright (C) 2006 Dave Robillard. + * + * Ingen 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 Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "RequestPluginEvent.h" +#include <string> +#include "Responder.h" +#include "Engine.h" +#include "interface/ClientInterface.h" +#include "TypedPort.h" +#include "ObjectStore.h" +#include "ClientBroadcaster.h" +#include "NodeFactory.h" +#include "Plugin.h" + +using std::string; + +namespace Ingen { + + +RequestPluginEvent::RequestPluginEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& uri) +: QueuedEvent(engine, responder, timestamp), + m_uri(uri), + m_plugin(NULL) +{ +} + + +void +RequestPluginEvent::pre_process() +{ + m_client = _engine.broadcaster()->client(_responder->client_key()); + m_plugin = _engine.node_factory()->plugin(m_uri); + + QueuedEvent::pre_process(); +} + + +void +RequestPluginEvent::execute(SampleCount nframes, FrameTime start, FrameTime end) +{ + QueuedEvent::execute(nframes, start, end); + assert(_time >= start && _time <= end); +} + + +void +RequestPluginEvent::post_process() +{ + if (!m_plugin) { + _responder->respond_error("Unable to find plugin requested."); + + } else if (m_client) { + + _responder->respond_ok(); + assert(m_plugin->uri() == m_uri); + m_client->new_plugin(m_uri, m_plugin->name()); + + } else { + _responder->respond_error("Unable to find client to send plugin."); + } +} + + +} // namespace Ingen + diff --git a/src/libs/engine/Thread.h b/src/libs/engine/events/RequestPluginEvent.h index 52423844..1c12c78e 100644 --- a/src/libs/engine/Thread.h +++ b/src/libs/engine/events/RequestPluginEvent.h @@ -14,50 +14,42 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef THREAD_H -#define THREAD_H +#ifndef REQUESTPLUGINEVENT_H +#define REQUESTPLUGINEVENT_H #include <string> -#include <pthread.h> - -namespace Ingen { +#include "QueuedEvent.h" +#include "types.h" +using std::string; -/* FIXME: This isn't Ingen specific at all. Move it to util. */ +namespace Ingen { + +class Plugin; +namespace Shared { class ClientInterface; } +using Shared::ClientInterface; -/** Abstract base class for all threads. +/** A request from a client to send the value of a port. * * \ingroup engine */ -class Thread +class RequestPluginEvent : public QueuedEvent { public: - Thread(); - virtual ~Thread(); - - virtual void start(); - virtual void stop(); + RequestPluginEvent(Engine& engine, CountedPtr<Responder> responder, SampleCount timestamp, const string& uri); - void set_name(const std::string& name) { _name = name; } - void set_scheduling(int policy, unsigned int priority); - -protected: - virtual void _run() = 0; - - std::string _name; - pthread_t _pthread; - bool _pthread_exists; + void pre_process(); + void execute(SampleCount nframes, FrameTime start, FrameTime end); + void post_process(); private: - // Prevent copies - Thread(const Thread&); - Thread& operator=(const Thread&); - - static void* _static_run(void* me); + string m_uri; + const Plugin* m_plugin; + CountedPtr<ClientInterface> m_client; }; } // namespace Ingen -#endif // THREAD_H +#endif // REQUESTPLUGINEVENT_H |