diff options
author | David Robillard <d@drobilla.net> | 2006-09-18 06:24:53 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2006-09-18 06:24:53 +0000 |
commit | 6f93b3d7c80f9dee2d95fac1bbc4f781a6f45979 (patch) | |
tree | 82b27a4802198215546558c006f7ac4228ab0599 /src/libs | |
parent | d520692eb49ff9e5aded38061a204713571b095b (diff) | |
download | ingen-6f93b3d7c80f9dee2d95fac1bbc4f781a6f45979.tar.gz ingen-6f93b3d7c80f9dee2d95fac1bbc4f781a6f45979.tar.bz2 ingen-6f93b3d7c80f9dee2d95fac1bbc4f781a6f45979.zip |
Work on loading old (deprecated) patches.
More error tolerance in Store, related bugfixes.
Patch port adding (threading) bug fixed (made event blocking).
Better PatchView cacheing.
Moved generic things from engine to util (shared)
Bug fixes, features, etc.
git-svn-id: http://svn.drobilla.net/lad/ingen@142 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/libs')
43 files changed, 907 insertions, 659 deletions
diff --git a/src/libs/client/ConnectionModel.cpp b/src/libs/client/ConnectionModel.cpp index 421b620d..e120207d 100644 --- a/src/libs/client/ConnectionModel.cpp +++ b/src/libs/client/ConnectionModel.cpp @@ -14,6 +14,7 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <cassert> #include "ConnectionModel.h" #include "PortModel.h" #include "PatchModel.h" @@ -38,6 +39,11 @@ ConnectionModel::ConnectionModel(CountedPtr<PortModel> src, CountedPtr<PortModel _src_port(src), _dst_port(dst) { + assert(_src_port); + assert(_dst_port); + assert(_src_port->parent()); + assert(_dst_port->parent()); + // Be sure connection is within one patch //assert(_src_port_path.parent().parent() // == _dst_port_path.parent().parent()); diff --git a/src/libs/client/OSCClientReceiver.cpp b/src/libs/client/OSCClientReceiver.cpp index e5a2ccc3..0ae41e75 100644 --- a/src/libs/client/OSCClientReceiver.cpp +++ b/src/libs/client/OSCClientReceiver.cpp @@ -67,7 +67,7 @@ OSCClientReceiver::start() } // Print all incoming messages - lo_server_thread_add_method(_st, NULL, NULL, generic_cb, NULL); + //lo_server_thread_add_method(_st, NULL, NULL, generic_cb, NULL); //lo_server_thread_add_method(_st, "/om/response/ok", "i", om_response_ok_cb, this); //lo_server_thread_add_method(_st, "/om/response/error", "is", om_responseerror_cb, this); @@ -139,7 +139,7 @@ OSCClientReceiver::setup_callbacks() { lo_server_thread_add_method(_st, "/om/response", "iis", response_cb, this); lo_server_thread_add_method(_st, "/om/num_plugins", "i", num_plugins_cb, this); - lo_server_thread_add_method(_st, "/om/plugin", "sss", plugin_cb, this); + lo_server_thread_add_method(_st, "/om/plugin", "ss", plugin_cb, this); lo_server_thread_add_method(_st, "/om/new_patch", "si", new_patch_cb, this); lo_server_thread_add_method(_st, "/om/destroyed", "s", destroyed_cb, this); lo_server_thread_add_method(_st, "/om/patch_enabled", "s", patch_enabled_cb, this); @@ -148,7 +148,7 @@ OSCClientReceiver::setup_callbacks() lo_server_thread_add_method(_st, "/om/object_renamed", "ss", object_renamed_cb, this); lo_server_thread_add_method(_st, "/om/new_connection", "ss", connection_cb, this); lo_server_thread_add_method(_st, "/om/disconnection", "ss", disconnection_cb, this); - lo_server_thread_add_method(_st, "/om/new_node", "sssii", new_node_cb, this); + lo_server_thread_add_method(_st, "/om/new_node", "ssii", new_node_cb, this); lo_server_thread_add_method(_st, "/om/new_port", "ssi", new_port_cb, this); lo_server_thread_add_method(_st, "/om/metadata/update", NULL, metadata_update_cb, this); lo_server_thread_add_method(_st, "/om/control_change", "sf", control_change_cb, this); @@ -246,13 +246,12 @@ OSCClientReceiver::m_disconnection_cb(const char* path, const char* types, lo_ar int OSCClientReceiver::m_new_node_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { - const char* type = &argv[0]->s; - const char* uri = &argv[1]->s; - const char* node_path = &argv[2]->s; - const int32_t poly = argv[3]->i; - const int32_t num_ports = argv[4]->i; + const char* uri = &argv[0]->s; + const char* node_path = &argv[1]->s; + const int32_t poly = argv[2]->i; + const int32_t num_ports = argv[3]->i; - new_node(type, uri, node_path, poly, num_ports); + new_node(uri, node_path, poly, num_ports); /*_receiving_node_model = new NodeModel(node_path); _receiving_node_model->polyphonic((poly == 1)); @@ -386,8 +385,8 @@ OSCClientReceiver::m_num_plugins_cb(const char* path, const char* types, lo_arg* int OSCClientReceiver::m_plugin_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { - assert(argc == 3 && !strcmp(types, "sss")); - new_plugin(&argv[0]->s, &argv[1]->s, &argv[2]->s); // type, uri + assert(argc == 2 && !strcmp(types, "ss")); + new_plugin(&argv[0]->s, &argv[1]->s); // type, uri return 0; } diff --git a/src/libs/client/OSCEngineSender.cpp b/src/libs/client/OSCEngineSender.cpp index 7bc67aa0..826b53b2 100644 --- a/src/libs/client/OSCEngineSender.cpp +++ b/src/libs/client/OSCEngineSender.cpp @@ -397,6 +397,26 @@ OSCEngineSender::ping() void +OSCEngineSender::request_plugin(const string& uri) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/request/plugin", "is", + next_id(), + uri.c_str()); +} + + +void +OSCEngineSender::request_object(const string& path) +{ + assert(_engine_addr); + lo_send(_engine_addr, "/om/request/object", "is", + next_id(), + path.c_str()); +} + + +void OSCEngineSender::request_port_value(const string& port_path) { assert(_engine_addr); diff --git a/src/libs/client/OSCEngineSender.h b/src/libs/client/OSCEngineSender.h index 1a4fa0e5..fb133706 100644 --- a/src/libs/client/OSCEngineSender.h +++ b/src/libs/client/OSCEngineSender.h @@ -131,6 +131,10 @@ public: void ping(); + void request_plugin(const string& uri); + + void request_object(const string& path); + void request_port_value(const string& port_path); void request_plugins(); diff --git a/src/libs/client/ObjectModel.cpp b/src/libs/client/ObjectModel.cpp index 6e18e680..e50882ca 100644 --- a/src/libs/client/ObjectModel.cpp +++ b/src/libs/client/ObjectModel.cpp @@ -66,11 +66,13 @@ ObjectModel::assimilate(CountedPtr<ObjectModel> model) { assert(_path == model->path()); - for (MetadataMap::const_iterator i = model->metadata().begin(); - i != model->metadata().end(); ++i) { - MetadataMap::const_iterator i = _metadata.find(i->first); - if (i == _metadata.end()) - _metadata[i->first] = i->second; + for (MetadataMap::const_iterator other = model->metadata().begin(); + other != model->metadata().end(); ++other) { + + MetadataMap::const_iterator mine = _metadata.find(other->first); + + if (mine == _metadata.end()) + _metadata[other->first] = other->second; } } diff --git a/src/libs/client/PatchLibrarian.cpp b/src/libs/client/PatchLibrarian.cpp index ebc33f36..00687993 100644 --- a/src/libs/client/PatchLibrarian.cpp +++ b/src/libs/client/PatchLibrarian.cpp @@ -117,6 +117,7 @@ PatchLibrarian::translate_load_path(const string& path) * - The filename does not have an extension (ie contain a ".") * - The patch_model has no (Ingen) path */ +#if 0 void PatchLibrarian::save_patch(CountedPtr<PatchModel> patch_model, const string& filename, bool recursive) { @@ -360,6 +361,7 @@ PatchLibrarian::save_patch(CountedPtr<PatchModel> patch_model, const string& fil xmlFreeDoc(xml_doc); xmlCleanupParser(); } +#endif /** Load a patch in to the engine (and client) from a patch file. @@ -369,47 +371,52 @@ PatchLibrarian::save_patch(CountedPtr<PatchModel> patch_model, const string& fil * is 0, it will be loaded from file. Otherwise the given values will * be used. * - * If @a wait is set, the patch will be checked for existence before + * @param wait If true the patch will be checked for existence before * loading everything in to it (to prevent messing up existing patches * that exist at the path this one should load as). * - * If the @a existing parameter is true, the patch will be loaded into a - * currently existing patch (ie a merging will take place). Errors will - * result if Nodes of conflicting names exist. + * @param existing If true, the patch will be loaded into a currently + * existing patch (ie a merging will take place). Errors will result + * if Nodes of conflicting names exist. + * + * @param parent_path Patch to load this patch as a child of (empty string to load + * to the root patch) + * + * @param name Name of this patch (loaded/generated if the empty string) + * + * @param initial_data will be set last, so values passed there will override + * any values loaded from the patch file. * * Returns the path of the newly created patch. */ string -PatchLibrarian::load_patch(CountedPtr<PatchModel> pm, bool wait, bool existing) +PatchLibrarian::load_patch(const string& filename, + const string& parent_path, + const string& name, + size_t poly, + MetadataMap initial_data, + bool existing) { - string filename = pm->filename(); + cerr << "[PatchLibrarian] Loading patch " << filename << "" << endl; - string additional_path = (!pm->parent()) - ? "" : ((PatchModel*)pm->parent().get())->filename(); - additional_path = additional_path.substr(0, additional_path.find_last_of("/")); + Path path = "/"; // path of the new patch - filename = find_file(pm->filename(), additional_path); - - size_t poly = pm->poly(); - - //cerr << "[PatchLibrarian] Loading patch " << filename << "" << endl; - - //const size_t temp_buf_length = 255; - //char temp_buf[temp_buf_length]; - - bool load_name = (pm->path() == ""); - bool load_poly = (poly == 0); + const bool load_name = (name == ""); + const bool load_poly = (poly == 0); + if (initial_data.find("filename") == initial_data.end()) + initial_data["filename"] = Atom(filename.c_str()); // FIXME: URL? + xmlDocPtr doc = xmlParseFile(filename.c_str()); - if (doc == NULL ) { + if (!doc) { cerr << "Unable to parse patch file." << endl; return ""; } xmlNodePtr cur = xmlDocGetRootElement(doc); - if (cur == NULL) { + if (!cur) { cerr << "Empty document." << endl; xmlFreeDoc(doc); return ""; @@ -423,10 +430,6 @@ PatchLibrarian::load_patch(CountedPtr<PatchModel> pm, bool wait, bool existing) xmlChar* key = NULL; cur = cur->xmlChildrenNode; - string path; - - cerr << "FIXME: patch filename" << endl; - //pm->filename(filename); // Load Patch attributes while (cur != NULL) { @@ -435,21 +438,12 @@ PatchLibrarian::load_patch(CountedPtr<PatchModel> pm, bool wait, bool existing) if ((!xmlStrcmp(cur->name, (const xmlChar*)"name"))) { if (load_name) { assert(key != NULL); - if (pm->parent()) { - path = pm->parent()->path().base() + string((char*)key); - } else { - path = string("/") + string((char*)key); - } - assert(path.find("//") == string::npos); - assert(path.length() > 0); - cerr << "FIXME: patch path (2)" << endl; - //pm->set_path(path); + if (parent_path != "") + path = Path(parent_path).base() + Path::nameify((char*)key); } } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"polyphony"))) { if (load_poly) { poly = atoi((char*)key); - cerr << "FIXME: patch poly" << endl; - //pm->poly(poly); } } else if (xmlStrcmp(cur->name, (const xmlChar*)"connection") && xmlStrcmp(cur->name, (const xmlChar*)"node") @@ -458,12 +452,9 @@ PatchLibrarian::load_patch(CountedPtr<PatchModel> pm, bool wait, bool existing) && xmlStrcmp(cur->name, (const xmlChar*)"preset")) { // Don't know what this tag is, add it as metadata without overwriting // (so caller can set arbitrary parameters which will be preserved) - if (key != NULL) - cerr << "FIXME: save metadata\n"; - /* - if (pm->get_metadata((const char*)cur->name) == "") - pm->set_metadata((const char*)cur->name, (const char*)key); - */ + if (key) + if (initial_data.find((const char*)cur->name) == initial_data.end()) + initial_data[(const char*)cur->name] = (const char*)key; } xmlFree(key); @@ -472,57 +463,19 @@ PatchLibrarian::load_patch(CountedPtr<PatchModel> pm, bool wait, bool existing) cur = cur->next; } - if (poly == 0) poly = 1; - - if (!existing) { - // Wait until the patch is created or the node creations may fail - if (wait) { - //int id = _engine->get_next_request_id(); - //_engine->set_wait_response_id(id); - cerr << "FIXME: create patch\n"; - //_engine->create_patch_from_model(pm.get()); - //bool succeeded = _engine->wait_for_response(); - - // If creating the patch failed, bail out so we don't load all these nodes - // into an already existing patch - /*if (!succeeded) { - cerr << "[PatchLibrarian] Patch load failed (patch already exists)" << endl; - return ""; - }*/ // FIXME - } else { - cerr << "FIXME: create patch (2)\n"; - //_engine->create_patch_from_model(pm.get()); - } - } - + if (poly == 0) + poly = 1; - // Set the filename metadata. (FIXME) - // This isn't so good, considering multiple clients on multiple machines, and - // absolute filesystem paths obviously aren't going to be correct. But for now - // this is all I can figure out to have Save/Save As work properly for subpatches - _engine->set_metadata(pm->path(), "filename", Atom(pm->filename().c_str())); + // Create it, if we're not merging + if (!existing) + _engine->create_patch_with_data(path, poly, initial_data); // Load nodes cur = xmlDocGetRootElement(doc)->xmlChildrenNode; - while (cur != NULL) { - if ((!xmlStrcmp(cur->name, (const xmlChar*)"node"))) { - CountedPtr<NodeModel> nm = parse_node(pm, doc, cur); - if (nm) { - cerr << "FIXME: load node\n"; - //_engine->create_node_from_model(nm.get()); - //_engine->set_all_metadata(nm.get()); - - /* - //for (PortModelList::const_iterator j = nm->ports().begin(); j != nm->ports().end(); ++j) { - // FIXME: ew - snprintf(temp_buf, temp_buf_length, "%f", (*j)->user_min()); - _engine->set_metadata((*j)->path(), "user-min", temp_buf); - snprintf(temp_buf, temp_buf_length, "%f", (*j)->user_max()); - _engine->set_metadata((*j)->path(), "user-max", temp_buf); - }*/ - } - } + if ((!xmlStrcmp(cur->name, (const xmlChar*)"node"))) + load_node(path, doc, cur); + cur = cur->next; } @@ -530,84 +483,87 @@ PatchLibrarian::load_patch(CountedPtr<PatchModel> pm, bool wait, bool existing) cur = xmlDocGetRootElement(doc)->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar*)"subpatch"))) { - load_subpatch(pm, doc, cur); + load_subpatch(path, doc, cur); } cur = cur->next; } - ConnectionModel* cm = NULL; // Load connections cur = xmlDocGetRootElement(doc)->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar*)"connection"))) { - cm = parse_connection(pm, doc, cur); - if (cm != NULL) { - _engine->connect(cm->src_port_path(), cm->dst_port_path()); - } + load_connection(path, doc, cur); } cur = cur->next; } // Load presets (control values) - PresetModel* preset_model = NULL; - cur = xmlDocGetRootElement(doc)->xmlChildrenNode; + cerr << "FIXME: load preset\n"; + /*cur = xmlDocGetRootElement(doc)->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar*)"preset"))) { - preset_model = parse_preset(pm, doc, cur); + load_preset(pm, doc, cur); assert(preset_model != NULL); if (preset_model->name() == "default") _engine->set_preset(pm->path(), preset_model); } cur = cur->next; } + */ xmlFreeDoc(doc); xmlCleanupParser(); - _engine->set_metadata_map(pm->path(), pm->metadata()); + // Done above.. late enough? + //_engine->set_metadata_map(path, initial_data); if (!existing) - _engine->enable_patch(pm->path()); + _engine->enable_patch(path); _load_path_translations.clear(); - string ret = pm->path(); - return ret; + return path; } /** Build a NodeModel given a pointer to a Node in a patch file. */ -CountedPtr<NodeModel> -PatchLibrarian::parse_node(const CountedPtr<const PatchModel> parent, xmlDocPtr doc, const xmlNodePtr node) +bool +PatchLibrarian::load_node(const Path& parent, xmlDocPtr doc, const xmlNodePtr node) { -cerr << "FIXME: load node\n"; -#if 0 - CountedPtr<PluginModel> plugin(new PluginModel()); - xmlChar* key; xmlNodePtr cur = node->xmlChildrenNode; - string path = ""' + string path = ""; bool polyphonic = false; + string plugin_uri; + + string plugin_type; // deprecated + string library_name; // deprecated + string plugin_label; // deprecated + + MetadataMap initial_data; + while (cur != NULL) { key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if ((!xmlStrcmp(cur->name, (const xmlChar*)"name"))) { - path = parent->path().base() + Path::nameify((char*)key)); + path = parent.base() + Path::nameify((char*)key); } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"polyphonic"))) { polyphonic = !strcmp((char*)key, "true"); } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"type"))) { - plugin->set_type((const char*)key); + plugin_type = (const char*)key; } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"library-name"))) { - plugin->lib_name((char*)key); + library_name = (char*)key; } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"plugin-label"))) { - plugin->plug_label((char*)key); + plugin_label = (char*)key; } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"plugin-uri"))) { - plugin->uri((char*)key); + plugin_uri = (char*)key; } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"port"))) { + cerr << "FIXME: load port\n"; +#if 0 xmlNodePtr child = cur->xmlChildrenNode; string port_name; @@ -640,12 +596,15 @@ cerr << "FIXME: load node\n"; 0.0, user_min, user_max)); //pm->set_parent(nm); nm->add_port(pm); +#endif // DSSI hacks. Stored in the patch files as special elements, but sent to // the engine as normal metadata with specially formatted key/values. Not // sure if this is the best way to go about this, but it's the least damaging // right now } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"dssi-program"))) { + cerr << "FIXME: load dssi program\n"; +#if 0 xmlNodePtr child = cur->xmlChildrenNode; string bank; @@ -665,8 +624,11 @@ cerr << "FIXME: load node\n"; child = child->next; } nm->set_metadata("dssi-program", Atom(bank.append("/").append(program).c_str())); +#endif } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"dssi-configure"))) { + cerr << "FIXME: load dssi configure\n"; +#if 0 xmlNodePtr child = cur->xmlChildrenNode; string dssi_key; @@ -687,10 +649,18 @@ cerr << "FIXME: load node\n"; child = child->next; } nm->set_metadata(string("dssi-configure--").append(dssi_key), Atom(dssi_value.c_str())); - +#endif } else { // Don't know what this tag is, add it as metadata - if (key != NULL) - nm->set_metadata((const char*)cur->name, (const char*)key); + if (key) { + + // Hack to make module-x and module-y set as floats + char* endptr = NULL; + float fval = strtof((const char*)key, &endptr); + if (endptr != (char*)key && *endptr == '\0') + initial_data[(const char*)cur->name] = Atom(fval); + else + initial_data[(const char*)cur->name] = Atom((const char*)key); + } } xmlFree(key); key = NULL; @@ -698,37 +668,41 @@ cerr << "FIXME: load node\n"; cur = cur->next; } - if (nm->path() == "") { + if (path == "") { cerr << "[PatchLibrarian] Malformed patch file (node tag has empty children)" << endl; cerr << "[PatchLibrarian] Node ignored." << endl; - return CountedPtr<NodeModel>(); + return false; + } - // Compatibility hacks for old patches - } else if (plugin->type() == PluginModel::Internal) { + // Compatibility hacks for old patches that represent patch ports as nodes + if (plugin_uri == "") { + cerr << "WARNING: Loading deprecated Node. Resave! " << path << endl; bool is_port = false; - const string path = Path::pathify(nm->path()); - if (plugin->plug_label() == "audio_input") { - _engine->create_port(path, "AUDIO", false); - is_port = true; - } else if ( plugin->plug_label() == "audio_output") { - _engine->create_port(path, "AUDIO", true); - is_port = true; - } else if ( plugin->plug_label() == "control_input") { - _engine->create_port(path, "CONTROL", false); - is_port = true; - } else if ( plugin->plug_label() == "control_output" ) { - _engine->create_port(path, "CONTROL", true); - is_port = true; - } else if ( plugin->plug_label() == "midi_input") { - _engine->create_port(path, "MIDI", false); - is_port = true; - } else if ( plugin->plug_label() == "midi_output" ) { - _engine->create_port(path, "MIDI", true); - is_port = true; + + if (plugin_type == "Internal") { + if (plugin_label == "audio_input") { + _engine->create_port(path, "AUDIO", false); + is_port = true; + } else if (plugin_label == "audio_output") { + _engine->create_port(path, "AUDIO", true); + is_port = true; + } else if (plugin_label == "control_input") { + _engine->create_port(path, "CONTROL", false); + is_port = true; + } else if (plugin_label == "control_output" ) { + _engine->create_port(path, "CONTROL", true); + is_port = true; + } else if (plugin_label == "midi_input") { + _engine->create_port(path, "MIDI", false); + is_port = true; + } else if (plugin_label == "midi_output" ) { + _engine->create_port(path, "MIDI", true); + is_port = true; + } } if (is_port) { - const string old_path = nm->path(); + const string old_path = path; const string new_path = Path::pathify(old_path); // Set up translations (for connections etc) to alias both the old @@ -737,58 +711,71 @@ cerr << "FIXME: load node\n"; _load_path_translations[old_path + "/in"] = new_path; _load_path_translations[old_path + "/out"] = new_path; - nm->set_path(new_path); - _engine->set_all_metadata(nm.get()); + path = new_path; + + _engine->set_metadata_map(path, initial_data); + return CountedPtr<NodeModel>(); + } else { - if (plugin->uri() == "") { - if (plugin->plug_label() == "note_in") { - plugin->uri("ingen:note_node"); - } else if (plugin->plug_label() == "control_input") { - plugin->uri("ingen:control_node"); - } else if (plugin->plug_label() == "transport") { - plugin->uri("ingen:transport_node"); - } else if (plugin->plug_label() == "trigger_in") { - plugin->uri("ingen:trigger_node"); - } + if (plugin_label == "note_in") { + plugin_uri = "ingen:note_node"; + } else if (plugin_label == "control_input") { + plugin_uri = "ingen:control_node"; + } else if (plugin_label == "transport") { + plugin_uri = "ingen:transport_node"; + } else if (plugin_label == "trigger_in") { + plugin_uri = "ingen:trigger_node"; + } else { + cerr << "WARNING: Unknown deprecated node (label " << plugin_label + << ")." << endl; } + + if (plugin_uri != "") + _engine->create_node(path, plugin_uri, polyphonic); + else + _engine->create_node(path, plugin_type, library_name, plugin_label, polyphonic); + + _engine->set_metadata_map(path, initial_data); + + return true; } + + // Not deprecated + } else { + _engine->create_node(path, plugin_uri, polyphonic); + _engine->set_metadata_map(path, initial_data); + return true; } - //nm->plugin(plugin); - - return nm; -#endif - return CountedPtr<NodeModel>(); + // (shouldn't get here) } -void -PatchLibrarian::load_subpatch(const CountedPtr<PatchModel> parent, xmlDocPtr doc, const xmlNodePtr subpatch) +bool +PatchLibrarian::load_subpatch(const Path& parent, xmlDocPtr doc, const xmlNodePtr subpatch) { - //xmlChar *key; - //xmlNodePtr cur = subpatch->xmlChildrenNode; + xmlChar *key; + xmlNodePtr cur = subpatch->xmlChildrenNode; - cerr << "FIXME: load subpatch" << endl; - -#if 0 - //CountedPtr<PatchModel> pm(new PatchModel("/UNINITIALIZED", 1)); // FIXME: ew + string name = ""; + string filename = ""; + size_t poly = 0; + MetadataMap initial_data; + while (cur != NULL) { key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if ((!xmlStrcmp(cur->name, (const xmlChar*)"name"))) { - if (parent == NULL) - pm->set_path(string("/") + (const char*)key); - else - pm->set_path(parent->path().base() + (const char*)key); + name = (const char*)key; } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"polyphony"))) { - pm->poly(atoi((const char*)key)); + poly = atoi((const char*)key); } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"filename"))) { - pm->filename((const char*)key); + filename = (const char*)key; } else { // Don't know what this tag is, add it as metadata if (key != NULL && strlen((const char*)key) > 0) - pm->set_metadata((const char*)cur->name, (const char*)key); + initial_data[(const char*)cur->name] = Atom((const char*)key); } xmlFree(key); key = NULL; @@ -796,25 +783,19 @@ PatchLibrarian::load_subpatch(const CountedPtr<PatchModel> parent, xmlDocPtr doc cur = cur->next; } - // This needs to be done after setting the path above, to prevent - // NodeModel::set_path from calling it's parent's rename_node with - // an invalid (nonexistant) name - pm->set_parent(parent); - - load_patch(pm, false); -#endif + // load_patch sets the passed metadata last, so values stored in the parent + // will override values stored in the child patch file + string path = load_patch(filename, parent, name, poly, initial_data, false); + + return false; } /** Build a ConnectionModel given a pointer to a connection in a patch file. */ -ConnectionModel* -PatchLibrarian::parse_connection(const CountedPtr<const PatchModel> parent, xmlDocPtr doc, const xmlNodePtr node) +bool +PatchLibrarian::load_connection(const Path& parent, xmlDocPtr doc, const xmlNodePtr node) { - //cerr << "[PatchLibrarian] Parsing connection..." << endl; - - cerr << "FIXME: load connection" << endl; -#if 0 xmlChar *key; xmlNodePtr cur = node->xmlChildrenNode; @@ -840,9 +821,9 @@ PatchLibrarian::parse_connection(const CountedPtr<const PatchModel> parent, xmlD } if (source_node == "" || source_port == "" || dest_node == "" || dest_port == "") { - cerr << "[PatchLibrarian] Malformed patch file (connection tag has empty children)" << endl; - cerr << "[PatchLibrarian] Connection ignored." << endl; - return NULL; + cerr << "ERROR: Malformed patch file (connection tag has empty children)" << endl; + cerr << "ERROR: Connection ignored." << endl; + return false; } // Compatibility fixes for old (fundamentally broken) patches @@ -851,21 +832,21 @@ PatchLibrarian::parse_connection(const CountedPtr<const PatchModel> parent, xmlD dest_node = Path::nameify(dest_node); dest_port = Path::nameify(dest_port); - ConnectionModel* cm = new ConnectionModel( - translate_load_path(parent->path().base() + source_node +"/"+ source_port), - translate_load_path(parent->path().base() + dest_node +"/"+ dest_port)); + _engine->connect( + translate_load_path(parent.base() + source_node +"/"+ source_port), + translate_load_path(parent.base() + dest_node +"/"+ dest_port)); - return cm; -#endif - return 0; + return true; } /** Build a PresetModel given a pointer to a preset in a patch file. */ -PresetModel* -PatchLibrarian::parse_preset(const CountedPtr<const PatchModel> patch, xmlDocPtr doc, const xmlNodePtr node) +bool +PatchLibrarian::load_preset(const Path& parent, xmlDocPtr doc, const xmlNodePtr node) { + cerr << "FIXME: load preset\n"; +#if 0 xmlNodePtr cur = node->xmlChildrenNode; xmlChar* key; @@ -929,6 +910,8 @@ PatchLibrarian::parse_preset(const CountedPtr<const PatchModel> patch, xmlDocPtr } return pm; +#endif + return false; } } // namespace Client diff --git a/src/libs/client/PatchLibrarian.h b/src/libs/client/PatchLibrarian.h index cf90d876..893d5cdc 100644 --- a/src/libs/client/PatchLibrarian.h +++ b/src/libs/client/PatchLibrarian.h @@ -23,6 +23,8 @@ #include <libxml/tree.h> #include <cassert> #include "util/CountedPtr.h" +#include "util/Path.h" +#include "ObjectModel.h" using std::string; @@ -43,8 +45,6 @@ class ModelEngineInterface; class PatchLibrarian { public: - // FIXME: return booleans and set an errstr that can be checked or something? - PatchLibrarian(CountedPtr<ModelEngineInterface> engine) : _patch_search_path("."), _engine(engine) { @@ -56,8 +56,14 @@ public: string find_file(const string& filename, const string& additional_path = ""); - void save_patch(CountedPtr<PatchModel> patch_model, const string& filename, bool recursive); - string load_patch(CountedPtr<PatchModel> pm, bool wait = true, bool existing = false); + //void save_patch(CountedPtr<PatchModel> patch_model, const string& filename, bool recursive); + + string load_patch(const string& filename, + const string& parent_path, + const string& name, + size_t poly, + MetadataMap initial_data, + bool existing = false); private: string translate_load_path(const string& path); @@ -68,10 +74,10 @@ private: /// Translations of paths from the loading file to actual paths (for deprecated patches) std::map<string, string> _load_path_translations; - CountedPtr<NodeModel> parse_node(const CountedPtr<const PatchModel> parent, xmlDocPtr doc, const xmlNodePtr cur); - ConnectionModel* parse_connection(const CountedPtr<const PatchModel> parent, xmlDocPtr doc, const xmlNodePtr cur); - PresetModel* parse_preset(const CountedPtr<const PatchModel> parent, xmlDocPtr doc, const xmlNodePtr cur); - void load_subpatch(const CountedPtr<PatchModel> parent, xmlDocPtr doc, const xmlNodePtr cur); + bool load_node(const Path& parent, xmlDocPtr doc, const xmlNodePtr cur); + bool load_connection(const Path& parent, xmlDocPtr doc, const xmlNodePtr cur); + bool load_preset(const Path& parent, xmlDocPtr doc, const xmlNodePtr cur); + bool load_subpatch(const Path& parent, xmlDocPtr doc, const xmlNodePtr cur); }; diff --git a/src/libs/client/PatchModel.cpp b/src/libs/client/PatchModel.cpp index a0e94ba4..a8cdf4ef 100644 --- a/src/libs/client/PatchModel.cpp +++ b/src/libs/client/PatchModel.cpp @@ -107,14 +107,11 @@ PatchModel::add_node(CountedPtr<NodeModel> nm) NodeModelMap::iterator existing = m_nodes.find(nm->path().name()); - if (existing != m_nodes.end()) { - cerr << "Warning: node clash, assimilating old node " << _path << endl; - nm->assimilate((*existing).second); - (*existing).second = nm; - } else { - m_nodes[nm->path().name()] = nm; - new_node_sig.emit(nm); - } + // Store should have handled this by merging the two + assert(existing == m_nodes.end()); + + m_nodes[nm->path().name()] = nm; + new_node_sig.emit(nm); } @@ -235,10 +232,13 @@ PatchModel::add_connection(CountedPtr<ConnectionModel> cm) assert(cm); assert(cm->patch_path() == path()); assert(cm->src_port()); - assert(cm->src_port()->parent()->parent().get() == this - || cm->src_port()->parent().get() == this); - assert(cm->dst_port()->parent()->parent().get() == this - || cm->dst_port()->parent().get() == this); + assert(cm->dst_port()); + assert(cm->src_port()->parent()); + assert(cm->dst_port()->parent()); + assert(cm->src_port()->parent().get() == this + || cm->src_port()->parent()->parent().get() == this); + assert(cm->dst_port()->parent().get() == this + || cm->dst_port()->parent()->parent().get() == this); CountedPtr<ConnectionModel> existing = get_connection(cm->src_port_path(), cm->dst_port_path()); assert(!existing); // Store should have handled this diff --git a/src/libs/client/PluginModel.h b/src/libs/client/PluginModel.h index 5174db76..74eee7cb 100644 --- a/src/libs/client/PluginModel.h +++ b/src/libs/client/PluginModel.h @@ -18,7 +18,9 @@ #define PLUGINMODEL_H #include <string> -using std::string; +#include <iostream> +#include "util/Path.h" +using std::string; using std::cerr; using std::endl; namespace Ingen { namespace Client { @@ -33,40 +35,17 @@ class PluginModel public: enum Type { LV2, LADSPA, DSSI, Internal, Patch }; - // FIXME: remove - PluginModel() {} - - PluginModel(const string& type_string, const string& uri) - : m_uri(uri) - { set_type(type_string); } - - PluginModel(Type type) - : m_type(type) - {} - - PluginModel(Type type, const string& uri, const string& name) - : m_type(type), - m_uri(uri), + PluginModel(const string& uri, const string& name) + : m_uri(uri), m_name(name) - {} + { + cerr << "FIXME: plugin type" << endl; + } - PluginModel(Type type, const string& lib_name, const string& plug_label, const string& name) - : m_type(type), - m_lib_name(lib_name), - m_plug_label(plug_label), - m_name(name) - {} - - //PluginModel() {} - Type type() const { return m_type; } void type(Type t) { m_type = t; } const string& uri() const { return m_uri; } void uri(const string& s) { m_uri = s; } - const string& lib_name() const { return m_lib_name; } - void lib_name(const string& s) { m_lib_name = s; } - const string& plug_label() const { return m_plug_label; } - void plug_label(const string& s) { m_plug_label = s; } const string& name() const { return m_name; } void name(const string& s) { m_name = s; } @@ -87,6 +66,8 @@ public: else if (type_string == "Patch") m_type = Patch; } + string default_node_name() { return Path::nameify(m_name); } + private: // Prevent copies PluginModel(const PluginModel& copy); @@ -94,8 +75,6 @@ private: Type m_type; string m_uri; - string m_lib_name; - string m_plug_label; string m_name; }; diff --git a/src/libs/client/SigClientInterface.h b/src/libs/client/SigClientInterface.h index cab1fd78..1f24ad40 100644 --- a/src/libs/client/SigClientInterface.h +++ b/src/libs/client/SigClientInterface.h @@ -42,26 +42,26 @@ public: // Signal parameters math up directly with ClientInterface calls - sigc::signal<void, int32_t, bool, string> response_sig; - sigc::signal<void> bundle_begin_sig; - sigc::signal<void> bundle_end_sig; - sigc::signal<void, string> error_sig; - sigc::signal<void, uint32_t> num_plugins_sig; - sigc::signal<void, string, string, string> new_plugin_sig; - sigc::signal<void, string, uint32_t> new_patch_sig; - sigc::signal<void, string, string, string, bool, uint32_t> new_node_sig; - sigc::signal<void, string, string, bool> new_port_sig; - sigc::signal<void, string> patch_enabled_sig; - sigc::signal<void, string> patch_disabled_sig; - sigc::signal<void, string> patch_cleared_sig; - sigc::signal<void, string, string> object_renamed_sig; - sigc::signal<void, string> object_destroyed_sig; - sigc::signal<void, string, string> connection_sig; - sigc::signal<void, string, string> disconnection_sig; - sigc::signal<void, string, string, Atom> metadata_update_sig; - sigc::signal<void, string, float> control_change_sig; - sigc::signal<void, string, uint32_t, uint32_t, string> program_add_sig; - sigc::signal<void, string, uint32_t, uint32_t> program_remove_sig; + sigc::signal<void, int32_t, bool, string> response_sig; + sigc::signal<void> bundle_begin_sig; + sigc::signal<void> bundle_end_sig; + sigc::signal<void, string> error_sig; + sigc::signal<void, uint32_t> num_plugins_sig; + sigc::signal<void, string, string> new_plugin_sig; + sigc::signal<void, string, uint32_t> new_patch_sig; + sigc::signal<void, string, string, bool, uint32_t> new_node_sig; + sigc::signal<void, string, string, bool> new_port_sig; + sigc::signal<void, string> patch_enabled_sig; + sigc::signal<void, string> patch_disabled_sig; + sigc::signal<void, string> patch_cleared_sig; + sigc::signal<void, string, string> object_renamed_sig; + sigc::signal<void, string> object_destroyed_sig; + sigc::signal<void, string, string> connection_sig; + sigc::signal<void, string, string> disconnection_sig; + sigc::signal<void, string, string, Atom> metadata_update_sig; + sigc::signal<void, string, float> control_change_sig; + sigc::signal<void, string, uint32_t, uint32_t, string> program_add_sig; + sigc::signal<void, string, uint32_t, uint32_t> program_remove_sig; protected: SigClientInterface() {} diff --git a/src/libs/client/Store.cpp b/src/libs/client/Store.cpp index f30240fb..f6662422 100644 --- a/src/libs/client/Store.cpp +++ b/src/libs/client/Store.cpp @@ -28,9 +28,10 @@ namespace Client { -Store::Store(CountedPtr<SigClientInterface> emitter) +Store::Store(CountedPtr<EngineInterface> engine, CountedPtr<SigClientInterface> emitter) +: _engine(engine) +, _emitter(emitter) { - //emitter.new_plugin_sig.connect(sigc::mem_fun(this, &Store::add_plugin)); emitter->object_destroyed_sig.connect(sigc::mem_fun(this, &Store::destruction_event)); emitter->new_plugin_sig.connect(sigc::mem_fun(this, &Store::new_plugin_event)); emitter->new_patch_sig.connect(sigc::mem_fun(this, &Store::new_patch_event)); @@ -64,6 +65,8 @@ Store::add_plugin_orphan(CountedPtr<NodeModel> node) map<string, list<CountedPtr<NodeModel> > >::iterator spawn = m_plugin_orphans.find(node->plugin_uri()); + _engine->request_plugin(node->plugin_uri()); + if (spawn != m_plugin_orphans.end()) { spawn->second.push_back(node); } else { @@ -77,11 +80,19 @@ Store::add_plugin_orphan(CountedPtr<NodeModel> node) void Store::resolve_plugin_orphans(CountedPtr<PluginModel> plugin) { - map<string, list<CountedPtr<NodeModel> > >::iterator spawn + map<string, list<CountedPtr<NodeModel> > >::iterator n = m_plugin_orphans.find(plugin->uri()); - if (spawn != m_plugin_orphans.end()) { - cerr << "XXXXXXXXXX PLUGIN-ORPHAN PLUGIN FOUND!! XXXXXXXXXXXXXXXXX" << endl; + if (n != m_plugin_orphans.end()) { + + list<CountedPtr<NodeModel> > spawn = n->second; // take a copy + + m_plugin_orphans.erase(plugin->uri()); // prevent infinite recursion + + for (list<CountedPtr<NodeModel> >::iterator i = spawn.begin(); + i != spawn.end(); ++i) { + add_object(*i); + } } } @@ -89,39 +100,42 @@ Store::resolve_plugin_orphans(CountedPtr<PluginModel> plugin) void Store::add_connection_orphan(CountedPtr<ConnectionModel> connection) { - cerr << "WARNING: Orphan connection received." << endl; + cerr << "WARNING: Orphan connection " << connection->src_port_path() + << " -> " << connection->dst_port_path() << " received." << endl; - cerr << "FIXME (add_connection_orphan)" << endl; - - throw; // FIXME: (lazy) -#if 0 - map<string, list<CountedPtr<ConnectionModel> > >::iterator spawn - = m_connection_orphans.find(node->connection_uri()); - - if (spawn != m_connection_orphans.end()) { - spawn->second.push_back(node); - } else { - list<CountedPtr<ConnectionModel> > l; - l.push_back(node); - m_connection_orphans[node->connection_uri()] = l; - } -#endif + m_connection_orphans.push_back(connection); } void Store::resolve_connection_orphans(CountedPtr<PortModel> port) { - cerr << "FIXME (add_connection_orphan)" << endl; - throw; // FIXME: (lazy) -#if 0 - map<string, list<CountedPtr<ConnectionModel> > >::iterator spawn - = m_connection_orphans.find(connection->uri()); - - if (spawn != m_connection_orphans.end()) { - cerr << "XXXXXXXXXX PLUGIN-ORPHAN PLUGIN FOUND!! XXXXXXXXXXXXXXXXX" << endl; + assert(port->parent()); + + for (list<CountedPtr<ConnectionModel> >::iterator c = m_connection_orphans.begin(); + c != m_connection_orphans.end(); ) { + + if ((*c)->src_port_path() == port->path()) + (*c)->set_src_port(port); + + if ((*c)->dst_port_path() == port->path()) + (*c)->set_dst_port(port); + + list<CountedPtr<ConnectionModel> >::iterator next = c; + ++next; + + if ((*c)->src_port() && (*c)->dst_port()) { + CountedPtr<PatchModel> patch = PtrCast<PatchModel>(this->object((*c)->patch_path())); + if (patch) { + cerr << "Resolved orphan connection " << (*c)->src_port_path() << + (*c)->dst_port_path() << endl; + patch->add_connection(*c); + m_connection_orphans.erase(c); + } + } + + c = next; } -#endif } @@ -133,6 +147,8 @@ Store::add_orphan(CountedPtr<ObjectModel> child) map<Path, list<CountedPtr<ObjectModel> > >::iterator children = m_orphans.find(child->path().parent()); + _engine->request_object(child->path().parent()); + if (children != m_orphans.end()) { children->second.push_back(child); } else { @@ -144,35 +160,66 @@ Store::add_orphan(CountedPtr<ObjectModel> child) void -Store::resolve_orphans(CountedPtr<ObjectModel> parent) +Store::add_metadata_orphan(const Path& subject_path, const string& predicate, const Atom& value) { - map<Path, list<CountedPtr<ObjectModel> > >::iterator children - = m_orphans.find(parent->path()); + map<Path, list<std::pair<string, Atom> > >::iterator orphans + = m_metadata_orphans.find(subject_path); - if (children != m_orphans.end()) { - cerr << "XXXXXXXXXXXXX ORPHAN PARENT FOUND!! XXXXXXXXXXXXXXXXX" << endl; + _engine->request_object(subject_path); + + if (orphans != m_metadata_orphans.end()) { + orphans->second.push_back(std::pair<string, Atom>(predicate, value)); + } else { + list<std::pair<string, Atom> > l; + l.push_back(std::pair<string, Atom>(predicate, value)); + m_metadata_orphans[subject_path] = l; } } void -Store::add_object(CountedPtr<ObjectModel> object) +Store::resolve_metadata_orphans(CountedPtr<ObjectModel> subject) { - assert(object->path() != ""); - assert(m_objects.find(object->path()) == m_objects.end()); - - if (object->path() != "/") { - CountedPtr<ObjectModel> parent = this->object(object->path().parent()); - if (parent) { - assert(object->path().is_child_of(parent->path())); - object->set_parent(parent); - parent->add_child(object); - assert(object->parent() == parent); - } else { - add_orphan(object); + map<Path, list<std::pair<string, Atom> > >::iterator v + = m_metadata_orphans.find(subject->path()); + + if (v != m_metadata_orphans.end()) { + + list<std::pair<string, Atom> > values = v->second; // take a copy + + m_metadata_orphans.erase(subject->path()); + + for (list<std::pair<string, Atom> >::iterator i = values.begin(); + i != values.end(); ++i) { + subject->set_metadata(i->first, i->second); + } + } +} + + +void +Store::resolve_orphans(CountedPtr<ObjectModel> parent) +{ + map<Path, list<CountedPtr<ObjectModel> > >::iterator c + = m_orphans.find(parent->path()); + + if (c != m_orphans.end()) { + + list<CountedPtr<ObjectModel> > children = c->second; // take a copy + + m_orphans.erase(parent->path()); // prevent infinite recursion + + for (list<CountedPtr<ObjectModel> >::iterator i = children.begin(); + i != children.end(); ++i) { + add_object(*i); } } +} + +void +Store::add_object(CountedPtr<ObjectModel> object) +{ // If we already have "this" object, merge the existing one into the new // one (with precedence to the new values). ObjectMap::iterator existing = m_objects.find(object->path()); @@ -180,14 +227,31 @@ Store::add_object(CountedPtr<ObjectModel> object) cerr << "[Store] Warning: Assimilating " << object->path() << endl; object->assimilate(existing->second); existing->second = object; - } - - m_objects[object->path()] = object; + } else { - // FIXME: emit this when we already had one? - new_object_sig.emit(object); + if (object->path() != "/") { + CountedPtr<ObjectModel> parent = this->object(object->path().parent()); + if (parent) { + assert(object->path().is_child_of(parent->path())); + object->set_parent(parent); + parent->add_child(object); + assert(parent && (object->parent() == parent)); + + m_objects[object->path()] = object; + new_object_sig.emit(object); + + resolve_metadata_orphans(parent); + resolve_orphans(parent); + + } else { + add_orphan(object); + } + } else { + m_objects[object->path()] = object; + new_object_sig.emit(object); + } - resolve_orphans(object); + } //cout << "[Store] Added " << object->path() << endl; } @@ -208,6 +272,8 @@ Store::remove_object(const Path& path) result->destroyed_sig.emit(); if (result->path() != "/") { + assert(result->parent()); + CountedPtr<ObjectModel> parent = this->object(result->path().parent()); if (parent) { parent->remove_child(result); @@ -248,7 +314,7 @@ Store::object(const Path& path) void Store::add_plugin(CountedPtr<PluginModel> pm) { - // FIXME: dupes? + // FIXME: dupes? assimilate? m_plugins[pm->uri()] = pm; } @@ -270,10 +336,9 @@ Store::destruction_event(const Path& path) } void -Store::new_plugin_event(const string& type, const string& uri, const string& name) +Store::new_plugin_event(const string& uri, const string& name) { - CountedPtr<PluginModel> p(new PluginModel(type, uri)); - p->name(name); + CountedPtr<PluginModel> p(new PluginModel(uri, name)); add_plugin(p); resolve_plugin_orphans(p); } @@ -288,7 +353,7 @@ Store::new_patch_event(const Path& path, uint32_t poly) void -Store::new_node_event(const string& plugin_type, const string& plugin_uri, const Path& node_path, bool is_polyphonic, uint32_t num_ports) +Store::new_node_event(const string& plugin_uri, const Path& node_path, bool is_polyphonic, uint32_t num_ports) { // FIXME: num_ports unused @@ -318,6 +383,8 @@ Store::new_port_event(const Path& path, const string& type, bool is_output) CountedPtr<PortModel> p(new PortModel(path, ptype, pdir)); add_object(p); + if (p->parent()) + resolve_connection_orphans(p); } @@ -356,10 +423,13 @@ void Store::metadata_update_event(const Path& subject_path, const string& predicate, const Atom& value) { CountedPtr<ObjectModel> subject = object(subject_path); - if (subject) + + if (subject) { subject->set_metadata(predicate, value); - else - cerr << "ERROR: metadata for nonexistant object." << endl; + } else { + add_metadata_orphan(subject_path, predicate, value); + cerr << "WARNING: metadata for unknown object." << endl; + } } @@ -380,30 +450,24 @@ Store::connection_event(const Path& src_port_path, const Path& dst_port_path) CountedPtr<PortModel> src_port = PtrCast<PortModel>(object(src_port_path)); CountedPtr<PortModel> dst_port = PtrCast<PortModel>(object(dst_port_path)); - assert(src_port); - assert(dst_port); + CountedPtr<ConnectionModel> dangling_cm(new ConnectionModel(src_port_path, dst_port_path)); - src_port->connected_to(dst_port); - dst_port->connected_to(src_port); + if (src_port && src_port->parent() && dst_port && dst_port->parent()) { + + CountedPtr<PatchModel> patch = PtrCast<PatchModel>(this->object(dangling_cm->patch_path())); + assert(patch); - CountedPtr<ConnectionModel> cm(new ConnectionModel(src_port, dst_port)); + CountedPtr<ConnectionModel> cm(new ConnectionModel(src_port, dst_port)); + + src_port->connected_to(dst_port); + dst_port->connected_to(src_port); - CountedPtr<PatchModel> patch = PtrCast<PatchModel>(this->object(cm->patch_path())); + patch->add_connection(cm); - CountedPtr<ObjectModel> src_obj = this->object(src_port_path); - CountedPtr<ObjectModel> dst_obj = this->object(dst_port_path); - - if (!src_obj || !dst_obj || !patch) { - add_connection_orphan(cm); } else { - CountedPtr<PortModel> src_port = PtrCast<PortModel>(src_obj); - CountedPtr<PortModel> dst_port = PtrCast<PortModel>(dst_obj); - assert(src_port && dst_port); - cm->set_src_port(src_port); - cm->set_dst_port(dst_port); + add_connection_orphan(dangling_cm); - patch->add_connection(cm); } } diff --git a/src/libs/client/Store.h b/src/libs/client/Store.h index ff617d37..a2083ba2 100644 --- a/src/libs/client/Store.h +++ b/src/libs/client/Store.h @@ -25,7 +25,9 @@ #include <sigc++/sigc++.h> #include "util/Path.h" #include "util/Atom.h" +#include "interface/EngineInterface.h" using std::string; using std::map; using std::list; +using Ingen::Shared::EngineInterface; namespace Ingen { namespace Client { @@ -45,7 +47,7 @@ class ConnectionModel; */ class Store : public sigc::trackable { // FIXME: is trackable necessary? public: - Store(CountedPtr<SigClientInterface> emitter); + Store(CountedPtr<EngineInterface> engine, CountedPtr<SigClientInterface> emitter); CountedPtr<PluginModel> plugin(const string& uri); CountedPtr<ObjectModel> object(const Path& path); @@ -74,12 +76,15 @@ private: void add_plugin_orphan(CountedPtr<NodeModel> orphan); void resolve_plugin_orphans(CountedPtr<PluginModel> plugin); + + void add_metadata_orphan(const Path& subject, const string& predicate, const Atom& value); + void resolve_metadata_orphans(CountedPtr<ObjectModel> subject); // Slots for SigClientInterface signals void destruction_event(const Path& path); - void new_plugin_event(const string& type, const string& uri, const string& name); + void new_plugin_event(const string& uri, const string& name); void new_patch_event(const Path& path, uint32_t poly); - void new_node_event(const string& plugin_type, const string& plugin_uri, const Path& node_path, bool is_polyphonic, uint32_t num_ports); + void new_node_event(const string& plugin_uri, const Path& node_path, bool is_polyphonic, uint32_t num_ports); void new_port_event(const Path& path, const string& data_type, bool is_output); void patch_enabled_event(const Path& path); void patch_disabled_event(const Path& path); @@ -89,6 +94,9 @@ private: void connection_event(const Path& src_port_path, const Path& dst_port_path); void disconnection_event(const Path& src_port_path, const Path& dst_port_path); + CountedPtr<EngineInterface> _engine; + CountedPtr<SigClientInterface> _emitter; + typedef map<Path, CountedPtr<ObjectModel> > ObjectMap; ObjectMap m_objects; ///< Keyed by Ingen path @@ -101,6 +109,12 @@ private: /** Same idea, except with plugins instead of parents. * It's unfortunate everything doesn't just have a URI and this was the same.. ahem.. */ map<string, list<CountedPtr<NodeModel> > > m_plugin_orphans; + + /** Not orphans OF metadata like the above, but orphans which are metadata */ + map<Path, list<std::pair<string, Atom> > > m_metadata_orphans; + + /** Ditto */ + list<CountedPtr<ConnectionModel> > m_connection_orphans; }; diff --git a/src/libs/client/ThreadedSigClientInterface.h b/src/libs/client/ThreadedSigClientInterface.h index 981b038d..f29d3cc4 100644 --- a/src/libs/client/ThreadedSigClientInterface.h +++ b/src/libs/client/ThreadedSigClientInterface.h @@ -82,14 +82,14 @@ public: void error(string msg) { push_sig(sigc::bind(error_slot, msg)); } - void new_plugin(string type, string uri, string name) - { push_sig(sigc::bind(new_plugin_slot, type, uri, name)); } + void new_plugin(string uri, string name) + { push_sig(sigc::bind(new_plugin_slot, uri, name)); } void new_patch(string path, uint32_t poly) { push_sig(sigc::bind(new_patch_slot, path, poly)); } - void new_node(string plugin_type, string plugin_uri, string node_path, bool is_polyphonic, uint32_t num_ports) - { push_sig(sigc::bind(new_node_slot, plugin_type, plugin_uri, node_path, is_polyphonic, num_ports)); } + void new_node(string plugin_uri, string node_path, bool is_polyphonic, uint32_t num_ports) + { push_sig(sigc::bind(new_node_slot, plugin_uri, node_path, is_polyphonic, num_ports)); } void new_port(string path, string data_type, bool is_output) { push_sig(sigc::bind(new_port_slot, path, data_type, is_output)); } @@ -141,9 +141,9 @@ private: sigc::slot<void, uint32_t> num_plugins_slot; sigc::slot<void, int32_t, bool, string> response_slot; sigc::slot<void, string> error_slot; - sigc::slot<void, string, string, string> new_plugin_slot; + sigc::slot<void, string, string> new_plugin_slot; sigc::slot<void, string, uint32_t> new_patch_slot; - sigc::slot<void, string, string, string, bool, int> new_node_slot; + sigc::slot<void, string, string, bool, int> new_node_slot; sigc::slot<void, string, string, bool> new_port_slot; sigc::slot<void, string, string> connection_slot; sigc::slot<void, string> patch_enabled_slot; 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 |