From cb42d2cc4daa09c7d1db5515e39e94b9a5a43447 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 2 Dec 2008 05:49:41 +0000 Subject: Rewrite pretty much everything to do with paths in Serialiser to actually make an ounce of sense. Fix various things with nested patches (fix tickets #286 #289). Cascade successive pastes nicely. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@1840 a436a847-0d15-0410-975c-d299462d15a1 --- src/client/HTTPClientReceiver.cpp | 2 +- src/engine/events/CreatePortEvent.cpp | 18 ++- src/engine/events/CreatePortEvent.hpp | 3 +- src/gui/LoadPatchWindow.cpp | 15 +- src/gui/LoadRemotePatchWindow.cpp | 6 +- src/gui/LoadSubpatchWindow.cpp | 3 +- src/gui/PatchCanvas.cpp | 46 ++++-- src/gui/PatchCanvas.hpp | 1 + src/gui/ThreadedLoader.cpp | 27 ++-- src/gui/ThreadedLoader.hpp | 14 +- src/ingen/main.cpp | 17 ++- src/serialisation/Parser.cpp | 262 +++++++++++++++++----------------- src/serialisation/Parser.hpp | 46 +++--- src/shared/Builder.cpp | 44 +++--- src/shared/Builder.hpp | 7 +- src/shared/ClashAvoider.cpp | 51 +++---- src/shared/ClashAvoider.hpp | 6 +- 17 files changed, 309 insertions(+), 259 deletions(-) diff --git a/src/client/HTTPClientReceiver.cpp b/src/client/HTTPClientReceiver.cpp index cee7eac4..520c1e9d 100644 --- a/src/client/HTTPClientReceiver.cpp +++ b/src/client/HTTPClientReceiver.cpp @@ -97,7 +97,7 @@ HTTPClientReceiver::Listener::Listener(HTTPClientReceiver* receiver, const std:: void HTTPClientReceiver::update(const std::string& str) { - cout << _parser->parse_update(_world, _target.get(), str, "/", "/"); + cout << _parser->parse_update(_world, _target.get(), str, "/"); } void diff --git a/src/engine/events/CreatePortEvent.cpp b/src/engine/events/CreatePortEvent.cpp index 8cb30a4b..0e0dabd2 100644 --- a/src/engine/events/CreatePortEvent.cpp +++ b/src/engine/events/CreatePortEvent.cpp @@ -117,6 +117,8 @@ CreatePortEvent::pre_process() assert(_ports_array->size() == _patch->num_ports()); + } else { + _error = CREATION_FAILED; } } QueuedEvent::pre_process(); @@ -149,12 +151,20 @@ CreatePortEvent::execute(ProcessContext& context) void CreatePortEvent::post_process() { - if (_error != NO_ERROR || !_patch_port) { - const string msg = string("Could not create port - ").append(_path); - _responder->respond_error(msg); - } else { + string msg; + switch (_error) { + case NO_ERROR: _responder->respond_ok(); _engine.broadcaster()->send_object(_patch_port, true); + break; + case UNKNOWN_TYPE: + msg = string("Could not create port ") + _path + " (Unknown type)"; + _responder->respond_error(msg); + break; + case CREATION_FAILED: + msg = string("Could not create port ") + _path + " (Creation failed)"; + _responder->respond_error(msg); + break; } } diff --git a/src/engine/events/CreatePortEvent.hpp b/src/engine/events/CreatePortEvent.hpp index c350d301..4a8233b7 100644 --- a/src/engine/events/CreatePortEvent.hpp +++ b/src/engine/events/CreatePortEvent.hpp @@ -51,7 +51,8 @@ private: enum ErrorType { NO_ERROR, - UNKNOWN_TYPE + UNKNOWN_TYPE, + CREATION_FAILED }; ErrorType _error; diff --git a/src/gui/LoadPatchWindow.cpp b/src/gui/LoadPatchWindow.cpp index 5da4b459..0373ee80 100644 --- a/src/gui/LoadPatchWindow.cpp +++ b/src/gui/LoadPatchWindow.cpp @@ -137,15 +137,16 @@ LoadPatchWindow::ok_clicked() if (_replace) App::instance().engine()->clear_patch(_patch->path()); - //if (_patch->path() != "/") - // parent = _patch->path().parent(); - parent = _patch->path(); - + if (_patch->path() != "/") { + parent = _patch->path().parent(); + symbol = _patch->symbol(); + } + _patch.reset(); hide(); - - App::instance().loader()->load_patch(true, get_uri(), "/", - _initial_data, parent, symbol); + + App::instance().loader()->load_patch(true, get_uri(), Path("/"), + parent, symbol, _initial_data); } diff --git a/src/gui/LoadRemotePatchWindow.cpp b/src/gui/LoadRemotePatchWindow.cpp index c2979e80..dab1cd0e 100644 --- a/src/gui/LoadRemotePatchWindow.cpp +++ b/src/gui/LoadRemotePatchWindow.cpp @@ -134,8 +134,6 @@ LoadRemotePatchWindow::open_clicked() { Glib::ustring uri = _uri_entry->get_text(); - cerr << "OPEN URI: " << uri << endl; - // If unset load_patch will load values optional parent; optional symbol; @@ -146,8 +144,8 @@ LoadRemotePatchWindow::open_clicked() if (_patch->path() != "/") parent = _patch->path().parent(); - App::instance().loader()->load_patch(true, uri, "/", - _initial_data, parent, symbol); + App::instance().loader()->load_patch(true, uri, Path("/"), + parent, symbol, _initial_data); hide(); } diff --git a/src/gui/LoadSubpatchWindow.cpp b/src/gui/LoadSubpatchWindow.cpp index 5bdd8ea6..f6ec41d2 100644 --- a/src/gui/LoadSubpatchWindow.cpp +++ b/src/gui/LoadSubpatchWindow.cpp @@ -169,7 +169,8 @@ LoadSubpatchWindow::ok_clicked() Atom& y = _initial_data["ingenuity:canvas-y"]; y = Atom(y.get_float() + 20.0f); - App::instance().loader()->load_patch(false, *i, "/", _initial_data, _patch->path(), symbol); + App::instance().loader()->load_patch(false, *i, Path("/"), + _patch->path(), symbol, _initial_data); } hide(); diff --git a/src/gui/PatchCanvas.cpp b/src/gui/PatchCanvas.cpp index 852aca5e..8a580b88 100644 --- a/src/gui/PatchCanvas.cpp +++ b/src/gui/PatchCanvas.cpp @@ -58,6 +58,7 @@ PatchCanvas::PatchCanvas(SharedPtr patch, int width, int height) , _patch(patch) , _last_click_x(0) , _last_click_y(0) + , _paste_count(0) , _refresh_menu(false) , _human_names(true) , _show_port_names(true) @@ -632,6 +633,7 @@ PatchCanvas::copy_selection() } string result = serialiser.finish(); + _paste_count = 0; Glib::RefPtr clipboard = Gtk::Clipboard::get(); clipboard->set_text(result); @@ -649,30 +651,51 @@ PatchCanvas::paste() } clear_selection(); + ++_paste_count; Builder builder(*App::instance().engine()); ClientStore clipboard; clipboard.set_plugins(App::instance().store()->plugins()); + + // mkdir -p + string to_create = _patch->path().substr(1); + string created = "/"; clipboard.new_patch("/", _patch->poly()); + size_t first_slash; + while (to_create != "/" && to_create != "" + && (first_slash = to_create.find("/")) != string::npos) { + created += to_create.substr(0, first_slash); + assert(Path::is_valid(created)); + clipboard.new_patch(created, _patch->poly()); + to_create = to_create.substr(first_slash + 1); + } + + if (_patch->path() != "/") + clipboard.new_patch(_patch->path(), _patch->poly()); - ClashAvoider avoider(*App::instance().store().get(), _patch->path(), clipboard, &clipboard); - parser->parse_string(App::instance().world(), &avoider, str, "/", _patch->path()); + boost::optional data_path; + boost::optional parent; + boost::optional symbol; + + if (_patch->path() != "/") { + parent = _patch->path(); + } + + ClashAvoider avoider(*App::instance().store().get(), clipboard, &clipboard); + parser->parse_string(App::instance().world(), &avoider, str, "", data_path, + parent, symbol); for (Store::iterator i = clipboard.begin(); i != clipboard.end(); ++i) { - //cout << "************ OBJECT: " << i->first << endl; if (_patch->path() == "/" && i->first == "/") { - //cout << "SKIPPING ROOT " << _patch->path() << " :: " << i->first << endl; - continue; - } else if (i->first.parent() != "/") { - //cout << "SKIPPING NON ROOTED OBJECT " << i->first << endl; + //cout << "Skipping root" << endl; continue; } GraphObject::Variables::iterator x = i->second->variables().find("ingenuity:canvas-x"); if (x != i->second->variables().end()) - x->second = x->second.get_float() + 20.0f; + x->second = x->second.get_float() + (20.0f * _paste_count); GraphObject::Variables::iterator y = i->second->variables().find("ingenuity:canvas-y"); if (y != i->second->variables().end()) - y->second = y->second.get_float() + 20.0f; + y->second = y->second.get_float() + (20.0f * _paste_count); if (i->first.parent() == "/") { GraphObject::Properties::iterator s = i->second->properties().find("ingen:selected"); if (s != i->second->properties().end()) @@ -680,11 +703,11 @@ PatchCanvas::paste() else i->second->properties().insert(make_pair("ingen:selected", true)); } - builder.build(_patch->path(), i->second); + builder.build(i->second); } // Successful connections - SharedPtr root = PtrCast(clipboard.object("/")); + SharedPtr root = PtrCast(clipboard.object(_patch->path())); assert(root); for (Patch::Connections::const_iterator i = root->connections().begin(); i != root->connections().end(); ++i) { @@ -694,6 +717,7 @@ PatchCanvas::paste() // Orphan connections (just in case...) for (ClientStore::ConnectionRecords::const_iterator i = clipboard.connection_records().begin(); i != clipboard.connection_records().end(); ++i) { + cout << "WARNING: Orphan connection paste: " << i->first << " -> " << i->second << endl; App::instance().engine()->connect(i->first, i->second); } } diff --git a/src/gui/PatchCanvas.hpp b/src/gui/PatchCanvas.hpp index 67553284..f257da4e 100644 --- a/src/gui/PatchCanvas.hpp +++ b/src/gui/PatchCanvas.hpp @@ -128,6 +128,7 @@ private: int _last_click_x; int _last_click_y; + int _paste_count; typedef std::multimap ClassMenus; ClassMenus _class_menus; diff --git a/src/gui/ThreadedLoader.cpp b/src/gui/ThreadedLoader.cpp index d2bfec76..ec39abf3 100644 --- a/src/gui/ThreadedLoader.cpp +++ b/src/gui/ThreadedLoader.cpp @@ -81,12 +81,12 @@ ThreadedLoader::_whipped() } void -ThreadedLoader::load_patch(bool merge, - const Glib::ustring& data_base_uri, - const Path& data_path, - GraphObject::Variables engine_data, - optional engine_parent, - optional engine_symbol) +ThreadedLoader::load_patch(bool merge, + const Glib::ustring& document_uri, + optional data_path, + optional engine_parent, + optional engine_symbol, + optional engine_data) { _mutex.lock(); @@ -99,26 +99,23 @@ ThreadedLoader::load_patch(bool merge, } // Filthy hack to load deprecated patches based on file extension - if (data_base_uri.substr(data_base_uri.length()-3) == ".om") { + if (document_uri.substr(document_uri.length()-3) == ".om") { _events.push_back(sigc::hide_return(sigc::bind( sigc::mem_fun(_deprecated_loader, &DeprecatedLoader::load_patch), - data_base_uri, + document_uri, merge, engine_parent, engine_symbol, - engine_data, + *engine_data, false))); } else { - if (merge && (!engine_parent || engine_parent.get() == "/")) - engine_base = engine_base.substr(0, engine_base.find_last_of("/")); - _events.push_back(sigc::hide_return(sigc::bind( sigc::mem_fun(_parser.get(), &Ingen::Serialisation::Parser::parse_document), App::instance().world(), App::instance().world()->engine.get(), - data_base_uri, // document - data_base_uri + data_path.substr(1), // object URI document - engine_base, + document_uri, + data_path, + engine_parent, engine_symbol, engine_data))); } diff --git a/src/gui/ThreadedLoader.hpp b/src/gui/ThreadedLoader.hpp index fee298d8..50e5deb1 100644 --- a/src/gui/ThreadedLoader.hpp +++ b/src/gui/ThreadedLoader.hpp @@ -57,13 +57,13 @@ class ThreadedLoader : public Raul::Slave public: ThreadedLoader(SharedPtr engine); - void load_patch(bool merge, - const Glib::ustring& data_base_uri, - const Path& data_path, - GraphObject::Variables engine_data, - optional engine_parent = optional(), - optional engine_symbol = optional()); - + void load_patch(bool merge, + const Glib::ustring& document_uri, + optional data_path, + optional engine_parent, + optional engine_symbol, + optional engine_data); + void save_patch(SharedPtr model, const string& filename); SharedPtr parser(); diff --git a/src/ingen/main.cpp b/src/ingen/main.cpp index 51e98079..1861f212 100644 --- a/src/ingen/main.cpp +++ b/src/ingen/main.cpp @@ -242,9 +242,18 @@ main(int argc, char** argv) /* Load a patch */ if (args.load_given && engine_interface) { - Glib::ustring engine_base = "/"; - if (args.path_given) - engine_base = string(args.path_arg) + "/"; + boost::optional data_path; + boost::optional parent; + boost::optional symbol; + + const Glib::ustring path = (args.path_given ? args.path_arg : "/"); + if (Path::is_valid(path)) { + const Path p(path); + parent = p.parent(); + symbol = p.name(); + } else { + cerr << "Invalid path: '" << path << endl; + } bool found = false; if (!world->serialisation_module) @@ -269,7 +278,7 @@ main(int argc, char** argv) } engine_interface->load_plugins(); - parser->parse_document(world, engine_interface.get(), uri, engine_base, uri); + parser->parse_document(world, engine_interface.get(), uri, data_path, parent, symbol); } else { cerr << "Unable to load serialisation module, aborting." << endl; diff --git a/src/serialisation/Parser.cpp b/src/serialisation/Parser.cpp index 9b165e03..bd30abbf 100644 --- a/src/serialisation/Parser.cpp +++ b/src/serialisation/Parser.cpp @@ -40,17 +40,17 @@ namespace Serialisation { #define NS_LV2EV "http://lv2plug.in/ns/ext/event#" Glib::ustring -Parser::uri_relative_to_base(Glib::ustring base, const Glib::ustring uri) +Parser::relative_uri(Glib::ustring base, const Glib::ustring uri) { - //cout << "BASE: " << base << endl; + //cout << base; base = base.substr(0, base.find_last_of("/")+1); - //cout << uri << " RELATIVE TO " << base << endl; + //cout << " # " << uri; Glib::ustring ret; if (uri.length() >= base.length() && uri.substr(0, base.length()) == base) ret = uri.substr(base.length()); else ret = uri; - //cout << " => " << ret << endl; + //cout << " = " << ret << endl; return ret; } @@ -72,32 +72,30 @@ Parser::parse_document( Ingen::Shared::World* world, Ingen::Shared::CommonInterface* target, Glib::ustring document_uri, - Glib::ustring object_uri, - Glib::ustring engine_base, + boost::optional data_path, + boost::optional parent, boost::optional symbol, boost::optional data) { normalise_uri(document_uri); - normalise_uri(object_uri); - normalise_uri(engine_base); Redland::Model model(*world->rdf_world, document_uri, document_uri); - cout << "[Parser] Parsing " << object_uri << " from " << document_uri << endl; - cout << "[Parser] Base: " << engine_base << endl; + cout << "[Parser] Parsing document " << document_uri << endl; + if (data_path) + cout << "[Parser] Document path: " << *data_path << endl; + if (parent) + cout << "[Parser] Parent: " << *parent << endl; if (symbol) - cout << "[Parser] Symbol: " << symbol.get() << endl; + cout << "[Parser] Symbol: " << *symbol << endl; boost::optional parsed_path - = parse(world, target, model, document_uri, engine_base, object_uri, symbol, data); + = parse(world, target, model, document_uri, data_path, parent, symbol, data); - const string object_path = (document_uri == object_uri) ? "/" - : uri_relative_to_base(document_uri, object_uri); - if (parsed_path) { target->set_variable(*parsed_path, "ingen:document", Atom(document_uri.c_str())); } else { - cerr << "WARNING: " << object_path << " is not a valid path, document URI lost" << endl; + cerr << "WARNING: document URI lost" << endl; } return parsed_path; @@ -110,23 +108,20 @@ Parser::parse_string( Ingen::Shared::CommonInterface* target, const Glib::ustring& str, const Glib::ustring& base_uri, - Glib::ustring engine_base, - boost::optional object_uri, + boost::optional data_path, + boost::optional parent, boost::optional symbol, boost::optional data) { Redland::Model model(*world->rdf_world, str.c_str(), str.length(), base_uri); - if (object_uri) - cout << "Parsing " << object_uri.get() << " (base " << base_uri << ")" << endl; - //else - // cout << "Parsing all objects found in string (base " << base_uri << ")" << endl; + cout << "Parsing " << (data_path ? (string)*data_path : "*") + << " from string (base " << base_uri << ")" << endl; - bool ret = parse(world, target, model, base_uri, engine_base, object_uri, symbol, data); + cout << "Parent: " << (parent ? *parent : "/no/bo/dy") << endl;; + bool ret = parse(world, target, model, base_uri, data_path, parent, symbol, data); const Glib::ustring subject = Glib::ustring("<") + base_uri + Glib::ustring(">"); - //const Glib::ustring subject("<>"); - parse_connections(world, target, model, base_uri, subject, - Path((engine_base == "") ? "/" : engine_base)); + parse_connections(world, target, model, subject, parent ? *parent : "/"); return ret; } @@ -138,8 +133,8 @@ Parser::parse_update( Shared::CommonInterface* target, const Glib::ustring& str, const Glib::ustring& base_uri, - Glib::ustring engine_base, - boost::optional object_uri, + boost::optional data_path, + boost::optional parent, boost::optional symbol, boost::optional data) { @@ -178,7 +173,7 @@ Parser::parse_update( // Connections - parse_connections(world, target, model, base_uri, "", "/"); + parse_connections(world, target, model, base_uri, "/"); // Port values query = Redland::Query(*world->rdf_world, @@ -197,7 +192,7 @@ Parser::parse_update( target->set_port_value(obj_path, a); } - return parse(world, target, model, base_uri, engine_base, object_uri, symbol, data); + return parse(world, target, model, base_uri, data_path, parent, symbol, data); } @@ -206,57 +201,49 @@ Parser::parse( Ingen::Shared::World* world, Ingen::Shared::CommonInterface* target, Redland::Model& model, - Glib::ustring base_uri, - Glib::ustring engine_base, - boost::optional object_uri, + Glib::ustring document_uri, + boost::optional data_path, + boost::optional parent, boost::optional symbol, boost::optional data) { const Redland::Node::Type res = Redland::Node::RESOURCE; - Glib::ustring query_str; - if (object_uri && object_uri.get()[0] == '/') - object_uri = object_uri.get().substr(1); - if (object_uri) - query_str = Glib::ustring("SELECT DISTINCT ?class WHERE { <") + object_uri.get() + "> a ?class . }"; - else - query_str = Glib::ustring("SELECT DISTINCT ?subject ?class WHERE { ?subject a ?class . }"); + const Glib::ustring query_str = data_path + ? Glib::ustring("SELECT DISTINCT ?t WHERE { <") + data_path->substr(1) + "> a ?t . }" + : Glib::ustring("SELECT DISTINCT ?s ?t WHERE { ?s a ?t . }"); Redland::Query query(*world->rdf_world, query_str); - Redland::Query::Results results(query.run(*world->rdf_world, model, base_uri)); + Redland::Query::Results results(query.run(*world->rdf_world, model, document_uri)); - const Redland::Node patch_class(*world->rdf_world, res, NS_INGEN "Patch"); - const Redland::Node node_class(*world->rdf_world, res, NS_INGEN "Node"); - const Redland::Node internal_class(*world->rdf_world, res, NS_INGEN "Internal"); - const Redland::Node ladspa_class(*world->rdf_world, res, NS_INGEN "LADSPAPlugin"); - const Redland::Node in_port_class(*world->rdf_world, res, NS_LV2 "InputPort"); - const Redland::Node out_port_class(*world->rdf_world, res, NS_LV2 "OutputPort"); - const Redland::Node lv2_class(*world->rdf_world, res, NS_LV2 "Plugin"); + const Redland::Node patch_class (*world->rdf_world, res, NS_INGEN "Patch"); + const Redland::Node node_class (*world->rdf_world, res, NS_INGEN "Node"); + const Redland::Node internal_class (*world->rdf_world, res, NS_INGEN "Internal"); + const Redland::Node ladspa_class (*world->rdf_world, res, NS_INGEN "LADSPAPlugin"); + const Redland::Node in_port_class (*world->rdf_world, res, NS_LV2 "InputPort"); + const Redland::Node out_port_class (*world->rdf_world, res, NS_LV2 "OutputPort"); + const Redland::Node lv2_class (*world->rdf_world, res, NS_LV2 "Plugin"); - string subject_str = ((object_uri && object_uri.get() != "") ? object_uri.get() : base_uri); - if (subject_str[0] == '/') - subject_str = subject_str.substr(1); - if (subject_str == "") - subject_str = base_uri; - - const Redland::Node subject_uri(*world->rdf_world, res, subject_str); + const Redland::Node subject_node = (data_path && *data_path != "/") + ? Redland::Node(*world->rdf_world, res, data_path->substr(1)) + : model.base_uri(); - std::string path_str; + std::string path_str; boost::optional ret; boost::optional root_path; for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { - const Redland::Node& subject = (object_uri ? subject_uri : (*i)["subject"]); - const Redland::Node& rdf_class = (*i)["class"]; + const Redland::Node& subject = (data_path ? subject_node : (*i)["s"]); + const Redland::Node& rdf_class = (*i)["t"]; //cout << "SUBJECT: " << subject.to_c_string() << endl; - //cout << "CLASS: " << rdf_class.to_c_string() << endl; + //cout << "CLASS: " << rdf_class.to_c_string() << endl; - if (!object_uri) - path_str = uri_relative_to_base(base_uri, subject.to_c_string()); + if (!data_path) + path_str = relative_uri(document_uri, subject.to_c_string()); if (path_str[0] != '/') - path_str = string("/").append(path_str); + path_str = "/" + path_str; if (!Path::is_valid(path_str)) { cerr << "WARNING: Invalid path '" << path_str << "', object skipped" << endl; @@ -272,24 +259,37 @@ Parser::parse( || (rdf_class == in_port_class) || (rdf_class == out_port_class); + const Glib::ustring subject_uri_tok = Glib::ustring("<").append(subject).append(">"); + if (is_object) { - Raul::Path path(path_str == "" ? "/" : path_str); + + string path; + if (parent && symbol) { + path = parent->base() + *symbol; + } else { + const string parent_base = parent ? parent->base() : "/"; + path = parent_base + path_str.substr(1); + } + + if (!Path::is_valid(path)) { + cerr << "WARNING: Invalid path '" << path << "' transformed to /" << endl; + path = "/"; + } if (rdf_class == patch_class) { - ret = parse_patch(world, target, model, base_uri, engine_base, path_str, data); + ret = parse_patch(world, target, model, subject, parent, symbol, data); } else if (rdf_class == node_class) { - ret = parse_node(world, target, model, - base_uri, Glib::ustring("<") + subject.to_c_string() + ">", path, data); + ret = parse_node(world, target, model, subject, path, data); } else if (rdf_class == in_port_class || rdf_class == out_port_class) { - ret = parse_port(world, target, model, - base_uri, Glib::ustring("<") + subject.to_c_string() + ">", path, data); - } else if (rdf_class == ladspa_class || rdf_class == lv2_class || rdf_class == internal_class) + ret = parse_port(world, target, model, subject, path, data); + } + if (!ret) { - cerr << "Failed to parse object " << object_uri << endl; + cerr << "Failed to parse object " << path << endl; return boost::optional(); } - if (object_uri && subject.to_string() == *object_uri) + if (data_path && subject.to_string() == *data_path) root_path = ret; } else if (is_plugin) { @@ -308,10 +308,10 @@ Parser::parse_patch( Ingen::Shared::World* world, Ingen::Shared::CommonInterface* target, Redland::Model& model, - const Glib::ustring& base_uri, - Glib::ustring engine_base, - const Glib::ustring& object_uri, - boost::optional data=boost::optional()) + const Redland::Node& subject_node, + boost::optional parent, + boost::optional a_symbol, + boost::optional data) { std::set created; uint32_t patch_poly = 0; @@ -323,21 +323,16 @@ Parser::parse_patch( patch_poly = poly_param->second.get_int32(); } - Glib::ustring subject = ((object_uri[0] == '<') - ? object_uri : Glib::ustring("<") + object_uri + ">"); + const Glib::ustring subject = subject_node.to_turtle_token(); - if (subject[0] == '<' && subject[1] == '/') - subject = string("<").append(subject.substr(2)); - - //cout << "Parse patch URI: " << object_uri << ", Subject: " << subject - // << ", Engine Base: " << engine_base << endl; + cout << "Parse patch " << subject << endl; /* Get polyphony from file (mandatory if not specified in parameters) */ if (patch_poly == 0) { Redland::Query query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?poly WHERE { ") + subject + " ingen:polyphony ?poly }"); - Redland::Query::Results results = query.run(*world->rdf_world, model, base_uri); + Redland::Query::Results results = query.run(*world->rdf_world, model); if (results.size() == 0) { cerr << "[Parser] ERROR: No polyphony found!" << endl; @@ -349,29 +344,29 @@ Parser::parse_patch( assert(poly_node.is_int()); patch_poly = static_cast(poly_node.to_int()); } + + const Glib::ustring base_uri = model.base_uri().to_string(); string symbol; - if (object_uri != "") { - symbol = uri_relative_to_base(base_uri, object_uri); + if (a_symbol) { + symbol = *a_symbol; } else { + // Guess symbol from base URI (filename) if we need one symbol = base_uri.substr(base_uri.find_last_of("/") + 1); symbol = symbol.substr(0, symbol.find(".")); + if (symbol != "") + symbol = Path::nameify(symbol); + + /*if (symbol == "" && engine_base != "") { + size_t l = base_uri.find_last_of("/"); + l = (l == string::npos) ? 0 : l + 1; + symbol = base_uri.substr(l); + symbol = symbol.substr(0, symbol.find(".")); + }*/ } - - Path patch_path("/"); - if (engine_base == "") - patch_path = "/"; - else if (engine_base[engine_base.length()-1] == '/') - patch_path = Path(engine_base + Path::nameify(symbol)); - else if (Path::is_valid(engine_base)) - patch_path = (Path)engine_base; - else if (Path::is_valid(string("/").append(engine_base))) - patch_path = (Path)(string("/").append(engine_base)); - else - cerr << "WARNING: Illegal engine base path '" << engine_base << "', loading patch to root" << endl; - - //if (patch_path != "/") - target->new_patch(patch_path, patch_poly); + + const Path patch_path(parent ? parent->base() + symbol : "/"); + target->new_patch(patch_path, patch_poly); /* Plugin nodes */ @@ -432,6 +427,8 @@ Parser::parse_patch( results = query.run(*world->rdf_world, model, base_uri); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { + cout << "FIXME: SUBPATCH" << endl; +#if 0 world->rdf_world->mutex().lock(); const string symbol = (*i)["symbol"].to_string(); const string subpatch = (*i)["subpatch"].to_string(); @@ -440,7 +437,7 @@ Parser::parse_patch( const Path subpatch_path = patch_path.base() + symbol; if (created.find(subpatch_path) == created.end()) { - string subpatch_rel = uri_relative_to_base(base_uri, subpatch); + const string subpatch_rel = relative_uri(base_uri, subpatch); string sub_base = engine_base; if (sub_base[sub_base.length()-1] == '/') sub_base = sub_base.substr(sub_base.length()-1); @@ -448,6 +445,7 @@ Parser::parse_patch( created.insert(subpatch_path); parse_patch(world, target, model, base_uri, subpatch_rel, sub_base); } +#endif } @@ -506,8 +504,8 @@ Parser::parse_patch( const Path port_path = patch_path.base() + name; if (created.find(port_path) == created.end()) { - bool is_output = (type == "lv2:OutputPort"); // FIXME: check validity - // FIXME: read index + // TODO: read index for plugin wrapper + bool is_output = (type == "lv2:OutputPort"); target->new_port(port_path, datatype, 0, is_output); created.insert(port_path); } @@ -530,8 +528,8 @@ Parser::parse_patch( created.clear(); - parse_connections(world, target, model, base_uri, subject, patch_path); - parse_variables(world, target, model, base_uri, subject, patch_path, data); + parse_connections(world, target, model, subject, patch_path); + parse_variables(world, target, model, subject_node, patch_path, data); /* Enable */ query = Redland::Query(*world->rdf_world, Glib::ustring( @@ -559,16 +557,16 @@ Parser::parse_node( Ingen::Shared::World* world, Ingen::Shared::CommonInterface* target, Redland::Model& model, - const Glib::ustring& base_uri, - const Glib::ustring& subject, + const Redland::Node& subject, const Raul::Path& path, - boost::optional data=boost::optional()) + boost::optional data) { /* Get plugin */ Redland::Query query(*world->rdf_world, Glib::ustring( - "SELECT DISTINCT ?plug WHERE { ") + subject + " rdf:instanceOf ?plug }"); + "SELECT DISTINCT ?plug WHERE { ") + subject.to_turtle_token() + + " rdf:instanceOf ?plug }"); - Redland::Query::Results results = query.run(*world->rdf_world, model, base_uri); + Redland::Query::Results results = query.run(*world->rdf_world, model); if (results.size() == 0) { cerr << "[Parser] ERROR: Node missing mandatory rdf:instanceOf property" << endl; @@ -582,7 +580,7 @@ Parser::parse_node( } target->new_node(path, world->rdf_world->expand_uri(plugin_node.to_c_string())); - parse_variables(world, target, model, base_uri, subject, path, data); + parse_variables(world, target, model, subject, path, data); return path; } @@ -592,11 +590,12 @@ Parser::parse_port( Ingen::Shared::World* world, Ingen::Shared::CommonInterface* target, Redland::Model& model, - const Glib::ustring& base_uri, - const Glib::ustring& subject, + const Redland::Node& subject_node, const Raul::Path& path, boost::optional data) { + const Glib::ustring subject = subject_node.to_turtle_token(); + Redland::Query query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?type ?datatype ?value WHERE {\n") + subject + " a ?type ;\n" @@ -605,15 +604,15 @@ Parser::parse_port( "OPTIONAL { " + subject + " ingen:value ?value . }\n" "}"); - Redland::Query::Results results = query.run(*world->rdf_world, model, base_uri); + Redland::Query::Results results = query.run(*world->rdf_world, model); world->rdf_world->mutex().lock(); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { const string type = world->rdf_world->qualify((*i)["type"].to_string()); const string datatype = world->rdf_world->qualify((*i)["datatype"].to_string()); + // TODO: read index for plugin wrapper bool is_output = (type == "lv2:OutputPort"); - // FIXME: read index target->new_port(path, datatype, 0, is_output); const Redland::Node& val_node = (*i)["value"]; @@ -622,19 +621,18 @@ Parser::parse_port( } world->rdf_world->mutex().unlock(); - parse_variables(world, target, model, base_uri, subject, path, data); + parse_variables(world, target, model, subject_node, path, data); return path; } bool Parser::parse_connections( - Ingen::Shared::World* world, - Ingen::Shared::CommonInterface* target, - Redland::Model& model, - const Glib::ustring& base_uri, - const Glib::ustring& subject, - const Raul::Path& parent) + Ingen::Shared::World* world, + Ingen::Shared::CommonInterface* target, + Redland::Model& model, + const Glib::ustring& subject, + const Raul::Path& parent) { Redland::Query query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?src ?dst WHERE {\n") @@ -643,17 +641,18 @@ Parser::parse_connections( " ingen:destination ?dst .\n" "}"); - const string parent_base = (subject != "<>") ? "/" : parent.base(); + const string parent_base = (parent == "/") ? "" : parent.base().substr(1); + const Glib::ustring& base_uri = model.base_uri().to_string(); - Redland::Query::Results results = query.run(*world->rdf_world, model, base_uri); + Redland::Query::Results results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { - const string src_path = parent_base + uri_relative_to_base(base_uri, (*i)["src"].to_string()); + const string src_path = parent.base() + relative_uri(base_uri, (*i)["src"].to_string()); if (!Path::is_valid(src_path)) { cerr << "ERROR: Invalid path in connection: " << src_path << endl; continue; } - const string dst_path = parent_base + uri_relative_to_base(base_uri, (*i)["dst"].to_string()); + const string dst_path = parent.base() + relative_uri(base_uri, (*i)["dst"].to_string()); if (!Path::is_valid(dst_path)) { cerr << "ERROR: Invalid path in connection: " << dst_path << endl; continue; @@ -671,11 +670,12 @@ Parser::parse_variables( Ingen::Shared::World* world, Ingen::Shared::CommonInterface* target, Redland::Model& model, - const Glib::ustring& base_uri, - const Glib::ustring& subject, + const Redland::Node& subject_node, const Raul::Path& path, - boost::optional data=boost::optional()) + boost::optional data) { + const Glib::ustring& subject = subject_node.to_turtle_token(); + Redland::Query query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?varkey ?varval WHERE {\n") + subject + " lv2var:variable ?variable .\n" @@ -683,7 +683,7 @@ Parser::parse_variables( " rdf:value ?varval .\n" "}"); - Redland::Query::Results results = query.run(*world->rdf_world, model, base_uri); + Redland::Query::Results results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { const string key = world->rdf_world->prefixes().qualify(string((*i)["varkey"])); const Redland::Node& val_node = (*i)["varval"]; @@ -698,7 +698,7 @@ Parser::parse_variables( " rdf:value ?val .\n" "}"); - results = query.run(*world->rdf_world, model, base_uri); + results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { const string key = world->rdf_world->prefixes().qualify(string((*i)["key"])); const Redland::Node& val_node = (*i)["val"]; diff --git a/src/serialisation/Parser.hpp b/src/serialisation/Parser.hpp index a5db7c0d..0d5c4f7e 100644 --- a/src/serialisation/Parser.hpp +++ b/src/serialisation/Parser.hpp @@ -27,7 +27,7 @@ #include "interface/GraphObject.hpp" #include "module/World.hpp" -namespace Redland { class World; class Model; } +namespace Redland { class World; class Model; class Node; } namespace Ingen { namespace Shared { class CommonInterface; } } using namespace Ingen::Shared; @@ -44,8 +44,8 @@ public: Ingen::Shared::World* world, Shared::CommonInterface* target, Glib::ustring document_uri, - Glib::ustring engine_base, - Glib::ustring object_uri, + boost::optional data_path=boost::optional(), + boost::optional parent=boost::optional(), boost::optional symbol=boost::optional(), boost::optional data=boost::optional()); @@ -54,8 +54,8 @@ public: Shared::CommonInterface* target, const Glib::ustring& str, const Glib::ustring& base_uri, - Glib::ustring engine_base, - boost::optional object_uri=boost::optional(), + boost::optional data_path=boost::optional(), + boost::optional parent=boost::optional(), boost::optional symbol=boost::optional(), boost::optional data=boost::optional()); @@ -64,22 +64,22 @@ public: Shared::CommonInterface* target, const Glib::ustring& str, const Glib::ustring& base_uri, - Glib::ustring engine_base, - boost::optional object_uri=boost::optional(), + boost::optional data_path=boost::optional(), + boost::optional parent=boost::optional(), boost::optional symbol=boost::optional(), boost::optional data=boost::optional()); private: - Glib::ustring uri_relative_to_base(Glib::ustring base, const Glib::ustring uri); + Glib::ustring relative_uri(Glib::ustring base, const Glib::ustring uri); boost::optional parse( Ingen::Shared::World* world, Shared::CommonInterface* target, Redland::Model& model, - Glib::ustring base_uri, - Glib::ustring engine_base, - boost::optional object_uri=boost::optional(), + Glib::ustring document_uri, + boost::optional data_path=boost::optional(), + boost::optional parent=boost::optional(), boost::optional symbol=boost::optional(), boost::optional data=boost::optional()); @@ -87,26 +87,24 @@ private: Ingen::Shared::World* world, Ingen::Shared::CommonInterface* target, Redland::Model& model, - const Glib::ustring& base_uri, - Glib::ustring engine_base, - const Glib::ustring& object_uri, - boost::optional data); + const Redland::Node& subject, + boost::optional parent=boost::optional(), + boost::optional symbol=boost::optional(), + boost::optional data=boost::optional()); boost::optional parse_node( Ingen::Shared::World* world, Ingen::Shared::CommonInterface* target, Redland::Model& model, - const Glib::ustring& base_uri, - const Glib::ustring& subject, + const Redland::Node& subject, const Raul::Path& path, - boost::optional data); + boost::optional data=boost::optional()); boost::optional parse_port( Ingen::Shared::World* world, Ingen::Shared::CommonInterface* target, Redland::Model& model, - const Glib::ustring& base_uri, - const Glib::ustring& subject, + const Redland::Node& subject, const Raul::Path& path, boost::optional data=boost::optional()); @@ -114,18 +112,16 @@ private: Ingen::Shared::World* world, Ingen::Shared::CommonInterface* target, Redland::Model& model, - const Glib::ustring& base_uri, - const Glib::ustring& subject, + const Redland::Node& subject, const Raul::Path& path, - boost::optional data); + boost::optional data=boost::optional()); bool parse_connections( Ingen::Shared::World* world, Ingen::Shared::CommonInterface* target, Redland::Model& model, - const Glib::ustring& base_uri, const Glib::ustring& subject, - const Raul::Path& parent); + const Raul::Path& patch); }; diff --git a/src/shared/Builder.cpp b/src/shared/Builder.cpp index 28833fc9..3bd9e75a 100644 --- a/src/shared/Builder.cpp +++ b/src/shared/Builder.cpp @@ -36,56 +36,68 @@ Builder::Builder(CommonInterface& interface) void -Builder::build(const Raul::Path& prefix, SharedPtr object) +Builder::build(SharedPtr object) { SharedPtr patch = PtrCast(object); if (patch) { if (object->path() != "/") { - const string path_str = prefix.base() + object->path().substr(1); + const string path_str = object->path(); _interface.new_patch(path_str, patch->internal_polyphony()); } - build_object(prefix, object); - for (Patch::Connections::const_iterator i = patch->connections().begin(); + build_object(object); + /*for (Patch::Connections::const_iterator i = patch->connections().begin(); i != patch->connections().end(); ++i) { - string base = prefix.base() + object->path().substr(1); - _interface.connect(base + (*i)->src_port_path().substr(1), - base + (*i)->dst_port_path().substr(1)); - } + _interface.connect((*i)->src_port_path(), (*i)->dst_port_path()); + }*/ return; } SharedPtr node = PtrCast(object); if (node) { - Raul::Path path = prefix.base() + node->path().substr(1); + Raul::Path path = node->path(); _interface.new_node(path, node->plugin()->uri()); - build_object(prefix, object); + build_object(object); return; } SharedPtr port = PtrCast(object); if (port) { - Raul::Path path = prefix.base() + port->path().substr(1); + Raul::Path path = port->path(); _interface.new_port(path, port->type().uri(), port->index(), !port->is_input()); - build_object(prefix, object); + build_object(object); + return; + } +} + + +void +Builder::connect(SharedPtr object) +{ + SharedPtr patch = PtrCast(object); + if (patch) { + for (Patch::Connections::const_iterator i = patch->connections().begin(); + i != patch->connections().end(); ++i) { + _interface.connect((*i)->src_port_path(), (*i)->dst_port_path()); + } return; } } void -Builder::build_object(const Raul::Path& prefix, SharedPtr object) +Builder::build_object(SharedPtr object) { for (GraphObject::Variables::const_iterator i = object->variables().begin(); i != object->variables().end(); ++i) - _interface.set_variable(prefix.base() + object->path().substr(1), i->first, i->second); + _interface.set_variable(object->path(), i->first, i->second); for (GraphObject::Properties::const_iterator i = object->properties().begin(); i != object->properties().end(); ++i) { if (object->path() == "/") continue; - string path_str = prefix.base() + object->path().substr(1); - _interface.set_property(prefix.base() + object->path().substr(1), i->first, i->second); + string path_str = object->path(); + _interface.set_property(object->path(), i->first, i->second); } } diff --git a/src/shared/Builder.hpp b/src/shared/Builder.hpp index f4b33538..c49937fe 100644 --- a/src/shared/Builder.hpp +++ b/src/shared/Builder.hpp @@ -39,12 +39,11 @@ public: Builder(CommonInterface& interface); virtual ~Builder() {} - void build(const Raul::Path& prefix, - SharedPtr object); + void build(SharedPtr object); + void connect(SharedPtr object); private: - void build_object(const Raul::Path& prefix, - SharedPtr object); + void build_object(SharedPtr object); CommonInterface& _interface; }; diff --git a/src/shared/ClashAvoider.cpp b/src/shared/ClashAvoider.cpp index 637872ef..10d22d5d 100644 --- a/src/shared/ClashAvoider.cpp +++ b/src/shared/ClashAvoider.cpp @@ -28,7 +28,8 @@ namespace Shared { const Raul::Path ClashAvoider::map_path(const Raul::Path& in) { - //cout << "MAP PATH: " << in << endl; + //cout << "MAP PATH: " << in; + //cout << endl << "**** MAP PATH: " << in << endl; unsigned offset = 0; bool has_offset = false; @@ -38,14 +39,14 @@ ClashAvoider::map_path(const Raul::Path& in) has_offset = (sscanf(trailing.c_str(), "%u", &offset) > 0); } - //cout << "HAS OFFSET: " << offset << endl; + //cout << "OFFSET: " << offset << endl; // Path without _n suffix Path base_path = in; if (has_offset) base_path = base_path.substr(0, base_path.find_last_of("_")); - //cout << "\tBASE: " << base_path << endl; + //cout << "BASE: " << base_path << endl; SymbolMap::iterator m = _symbol_map.find(in); if (m != _symbol_map.end()) { @@ -53,36 +54,36 @@ ClashAvoider::map_path(const Raul::Path& in) return m->second; } else { typedef std::pair InsertRecord; + + // See if parent is mapped + Path parent = in.parent(); + do { + //cout << "CHECK: " << parent << endl; + SymbolMap::iterator p = _symbol_map.find(parent); + if (p != _symbol_map.end()) { + const Path mapped = p->second.base() + in.substr(parent.base().length()); + InsertRecord i = _symbol_map.insert(make_pair(in, mapped)); + //cout << " (2) " << i.first->second << endl; + return i.first->second; + } + parent = parent.parent(); + } while (parent != "/"); // No clash, use symbol unmodified if (!exists(in) && _symbol_map.find(in) == _symbol_map.end()) { InsertRecord i = _symbol_map.insert(make_pair(in, in)); assert(i.second); - //cout << " (2) " << i.first->second << endl;; + //cout << " (3) " << i.first->second << endl;; return i.first->second; + + // Append _2 _3 etc until an unused symbol is found } else { - - // See if the parent is mapped - // FIXME: do this the other way around - Path parent = in.parent(); - do { - SymbolMap::iterator p = _symbol_map.find(parent); - if (p != _symbol_map.end()) { - const Path mapped = p->second.base() + in.substr(parent.base().length()); - InsertRecord i = _symbol_map.insert(make_pair(in, mapped)); - //cout << " (3) " << _prefix.base() + i.first->second.substr(1) << endl; - return i.first->second; - } - parent = parent.parent(); - } while (parent != "/"); - - // Append _2 _3 etc until an unused symbol is found while (true) { Offsets::iterator o = _offsets.find(base_path); if (o != _offsets.end()) { offset = ++o->second; } else { - string parent_str = _prefix.base() + in.parent().base().substr(1); + string parent_str = in.parent().base(); parent_str = parent_str.substr(0, parent_str.find_last_of("/")); if (parent_str == "") parent_str = "/"; @@ -95,10 +96,11 @@ ClashAvoider::map_path(const Raul::Path& in) std::stringstream ss; ss << base_path << "_" << offset; if (!exists(ss.str())) { + const string name = (base_path.length() > 1) ? base_path.name() : "_"; string str = ss.str(); InsertRecord i = _symbol_map.insert(make_pair(in, str)); //cout << "HIT: offset = " << offset << ", str = " << str << endl; - offset = _store.child_name_offset(in.parent(), base_path.name(), false); + offset = _store.child_name_offset(in.parent(), name, false); _offsets.insert(make_pair(base_path, offset)); //cout << " (4) " << i.first->second << endl;; return i.first->second; @@ -118,7 +120,7 @@ ClashAvoider::map_path(const Raul::Path& in) bool ClashAvoider::exists(const Raul::Path& path) const { - bool exists = (_store.find(_prefix.base() + path.substr(1)) != _store.end()); + bool exists = (_store.find(path) != _store.end()); if (exists) return true; @@ -140,7 +142,8 @@ void ClashAvoider::new_patch(const std::string& path, uint32_t poly) { - _target.new_patch(map_path(path), poly); + if (path != "/") + _target.new_patch(map_path(path), poly); } diff --git a/src/shared/ClashAvoider.hpp b/src/shared/ClashAvoider.hpp index efdebf98..91c58c0e 100644 --- a/src/shared/ClashAvoider.hpp +++ b/src/shared/ClashAvoider.hpp @@ -37,9 +37,8 @@ class Store; class ClashAvoider : public CommonInterface { public: - ClashAvoider(Store& store, const Raul::Path& prefix, CommonInterface& target, - Store* also_avoid=NULL) - : _prefix(prefix), _store(store), _target(target), _also_avoid(also_avoid) {} + ClashAvoider(Store& store, CommonInterface& target, Store* also_avoid=NULL) + : _store(store), _target(target), _also_avoid(also_avoid) {} void set_target(CommonInterface& target) { _target = target; } @@ -88,7 +87,6 @@ public: private: const Raul::Path map_path(const Raul::Path& in); - const Raul::Path& _prefix; Store& _store; CommonInterface& _target; -- cgit v1.2.1