diff options
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 |