diff options
Diffstat (limited to 'src/libs/client')
-rw-r--r-- | src/libs/client/ConnectionModel.cpp | 6 | ||||
-rw-r--r-- | src/libs/client/OSCClientReceiver.cpp | 21 | ||||
-rw-r--r-- | src/libs/client/OSCEngineSender.cpp | 20 | ||||
-rw-r--r-- | src/libs/client/OSCEngineSender.h | 4 | ||||
-rw-r--r-- | src/libs/client/ObjectModel.cpp | 12 | ||||
-rw-r--r-- | src/libs/client/PatchLibrarian.cpp | 377 | ||||
-rw-r--r-- | src/libs/client/PatchLibrarian.h | 22 | ||||
-rw-r--r-- | src/libs/client/PatchModel.cpp | 24 | ||||
-rw-r--r-- | src/libs/client/PluginModel.h | 41 | ||||
-rw-r--r-- | src/libs/client/SigClientInterface.h | 40 | ||||
-rw-r--r-- | src/libs/client/Store.cpp | 222 | ||||
-rw-r--r-- | src/libs/client/Store.h | 20 | ||||
-rw-r--r-- | src/libs/client/ThreadedSigClientInterface.h | 12 |
13 files changed, 449 insertions, 372 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; |