summaryrefslogtreecommitdiffstats
path: root/src/libs/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/client')
-rw-r--r--src/libs/client/ConnectionModel.cpp6
-rw-r--r--src/libs/client/OSCClientReceiver.cpp21
-rw-r--r--src/libs/client/OSCEngineSender.cpp20
-rw-r--r--src/libs/client/OSCEngineSender.h4
-rw-r--r--src/libs/client/ObjectModel.cpp12
-rw-r--r--src/libs/client/PatchLibrarian.cpp377
-rw-r--r--src/libs/client/PatchLibrarian.h22
-rw-r--r--src/libs/client/PatchModel.cpp24
-rw-r--r--src/libs/client/PluginModel.h41
-rw-r--r--src/libs/client/SigClientInterface.h40
-rw-r--r--src/libs/client/Store.cpp222
-rw-r--r--src/libs/client/Store.h20
-rw-r--r--src/libs/client/ThreadedSigClientInterface.h12
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;