summaryrefslogtreecommitdiffstats
path: root/src/libs/client
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2006-09-18 06:24:53 +0000
committerDavid Robillard <d@drobilla.net>2006-09-18 06:24:53 +0000
commit6f93b3d7c80f9dee2d95fac1bbc4f781a6f45979 (patch)
tree82b27a4802198215546558c006f7ac4228ab0599 /src/libs/client
parentd520692eb49ff9e5aded38061a204713571b095b (diff)
downloadingen-6f93b3d7c80f9dee2d95fac1bbc4f781a6f45979.tar.gz
ingen-6f93b3d7c80f9dee2d95fac1bbc4f781a6f45979.tar.bz2
ingen-6f93b3d7c80f9dee2d95fac1bbc4f781a6f45979.zip
Work on loading old (deprecated) patches.
More error tolerance in Store, related bugfixes. Patch port adding (threading) bug fixed (made event blocking). Better PatchView cacheing. Moved generic things from engine to util (shared) Bug fixes, features, etc. git-svn-id: http://svn.drobilla.net/lad/ingen@142 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/libs/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;