From 9d7c1e971d51561c4bb28fa1064503e5f266908f Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 24 Feb 2015 09:20:22 +0000 Subject: Demodularize Parser and Serialiser. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5606 a436a847-0d15-0410-975c-d299462d15a1 --- doc/reference.doxygen.in | 1 - ingen/Parser.hpp | 67 ++++ ingen/Serialiser.hpp | 99 ++++++ ingen/World.hpp | 28 +- ingen/serialisation/Parser.hpp | 74 ---- ingen/serialisation/Serialiser.hpp | 102 ------ src/Parser.cpp | 653 +++++++++++++++++++++++++++++++++++ src/Serialiser.cpp | 545 ++++++++++++++++++++++++++++++ src/World.cpp | 65 ++-- src/gui/App.cpp | 5 +- src/gui/App.hpp | 6 +- src/gui/GraphCanvas.cpp | 16 +- src/gui/Style.cpp | 2 +- src/gui/ThreadedLoader.cpp | 11 +- src/gui/ThreadedLoader.hpp | 6 +- src/gui/wscript | 2 +- src/ingen/ingen.cpp | 7 +- src/serialisation/Parser.cpp | 655 ------------------------------------ src/serialisation/Serialiser.cpp | 547 ------------------------------ src/serialisation/serialisation.cpp | 43 --- src/serialisation/wscript | 30 -- src/server/JackDriver.cpp | 4 +- src/server/ingen_lv2.cpp | 8 +- src/wscript | 2 + tests/ingen_test.cpp | 5 +- wscript | 6 +- 26 files changed, 1435 insertions(+), 1554 deletions(-) create mode 100644 ingen/Parser.hpp create mode 100644 ingen/Serialiser.hpp delete mode 100644 ingen/serialisation/Parser.hpp delete mode 100644 ingen/serialisation/Serialiser.hpp create mode 100644 src/Parser.cpp create mode 100644 src/Serialiser.cpp delete mode 100644 src/serialisation/Parser.cpp delete mode 100644 src/serialisation/Serialiser.cpp delete mode 100644 src/serialisation/serialisation.cpp delete mode 100644 src/serialisation/wscript diff --git a/doc/reference.doxygen.in b/doc/reference.doxygen.in index 049c2fc1..e37a58d2 100644 --- a/doc/reference.doxygen.in +++ b/doc/reference.doxygen.in @@ -756,7 +756,6 @@ WARN_LOGFILE = INPUT = @INGEN_SRCDIR@/ingen \ @INGEN_SRCDIR@/ingen/client \ - @INGEN_SRCDIR@/ingen/serialisation \ @INGEN_SRCDIR@/src/server/events/ # This tag can be used to specify the character encoding of the source files diff --git a/ingen/Parser.hpp b/ingen/Parser.hpp new file mode 100644 index 00000000..b4977c90 --- /dev/null +++ b/ingen/Parser.hpp @@ -0,0 +1,67 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#ifndef INGEN_PARSER_HPP +#define INGEN_PARSER_HPP + +#include +#include + +#include + +#include "ingen/Node.hpp" +#include "raul/Path.hpp" +#include "raul/URI.hpp" + +namespace Ingen { + +class Interface; +class World; + +/** + Read Ingen objects from Turtle files or strings. + + @ingroup Ingen +*/ +class Parser { +public: + explicit Parser() {} + + virtual ~Parser() {} + + typedef Node::Properties Properties; + + virtual bool parse_file( + World* world, + Interface* target, + const std::string& path, + boost::optional parent = boost::optional(), + boost::optional symbol = boost::optional(), + boost::optional data = boost::optional()); + + virtual boost::optional parse_string( + World* world, + Interface* target, + const std::string& str, + const std::string& base_uri, + boost::optional parent = boost::optional(), + boost::optional symbol = boost::optional(), + boost::optional data = boost::optional()); +}; + +} // namespace Ingen + +#endif // INGEN_PARSER_HPP diff --git a/ingen/Serialiser.hpp b/ingen/Serialiser.hpp new file mode 100644 index 00000000..8c82634a --- /dev/null +++ b/ingen/Serialiser.hpp @@ -0,0 +1,99 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#ifndef INGEN_SERIALISER_HPP +#define INGEN_SERIALISER_HPP + +#include +#include + +#include "raul/Path.hpp" + +#include "sord/sordmm.hpp" + +#include "ingen/Node.hpp" + +namespace Ingen { + +class Arc; +class Node; +class Store; +class World; + +/** + Write Ingen objects to Turtle files or strings. + + @ingroup Ingen +*/ +class Serialiser +{ +public: + explicit Serialiser(World& world); + virtual ~Serialiser(); + + /** Write a graph and all its contents as a complete bundle. */ + virtual void write_bundle(SPtr graph, + const std::string& path); + + /** Begin a serialization to a string. + * + * This must be called before any serializing methods. + * + * The results of the serialization will be returned by the finish() method after + * the desired objects have been serialised. + * + * All serialized paths will have the root path chopped from their prefix + * (therefore all serialized paths must be descendants of the root) + */ + virtual void start_to_string(const Raul::Path& root, + const std::string& base_uri); + + /** Begin a serialization to a file. + * + * This must be called before any serializing methods. + * + * All serialized paths will have the root path chopped from their prefix + * (therefore all serialized paths must be descendants of the root) + */ + virtual void start_to_file(const Raul::Path& root, + const std::string& filename); + + /** Serialize an object (graph, block, or port). */ + virtual void serialise(SPtr object) + throw (std::logic_error); + + /** Serialize an arc. */ + virtual void serialise_arc(const Sord::Node& parent, + SPtr arc) + throw (std::logic_error); + + /** Finish serialization. + * + * If this is a file serialization, this must be called to finish and close + * the output file, and the empty string is returned. + * + * If this is a string serialization, the serialized result is returned. + */ + virtual std::string finish(); + +private: + struct Impl; + Impl* me; +}; + +} // namespace Ingen + +#endif // INGEN_SERIALISER_HPP diff --git a/ingen/World.hpp b/ingen/World.hpp index a7c224ac..d803a4a9 100644 --- a/ingen/World.hpp +++ b/ingen/World.hpp @@ -31,18 +31,14 @@ namespace Sord { class World; } namespace Ingen { +class Configuration; class EngineBase; +class Forge; class Interface; +class LV2Features; class Log; - -namespace Serialisation { class Parser; class Serialiser; -} - -class Configuration; -class Forge; -class LV2Features; class Store; class URIMap; class URIs; @@ -53,11 +49,9 @@ class URIs; * contains all necessary shared data (including the world for libraries like * Sord and Lilv) and holds references to components. * - * Most functionality in Ingen is implemented in dynamically loaded modules, + * Some functionality in Ingen is implemented in dynamically loaded modules, * which are loaded using this interface. When loaded, those modules add - * facilities to the World which can then be used throughout the code. For - * example loading the "ingen_serialisation" module will set World::serialiser - * and World::parser to valid objects. + * facilities to the World which can then be used throughout the code. * * The world is used in any process which uses the Ingen as a library, both * client and server (e.g. the world may not actually contain an Engine, since @@ -116,15 +110,13 @@ public: virtual void set_engine(SPtr e); virtual void set_interface(SPtr e); - virtual void set_parser(SPtr p); - virtual void set_serialiser(SPtr s); virtual void set_store(SPtr s); - virtual SPtr engine(); - virtual SPtr interface(); - virtual SPtr parser(); - virtual SPtr serialiser(); - virtual SPtr store(); + virtual SPtr engine(); + virtual SPtr interface(); + virtual SPtr parser(); + virtual SPtr serialiser(); + virtual SPtr store(); virtual int& argc(); virtual char**& argv(); diff --git a/ingen/serialisation/Parser.hpp b/ingen/serialisation/Parser.hpp deleted file mode 100644 index 446b3988..00000000 --- a/ingen/serialisation/Parser.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -/** - @defgroup IngenSerialisation Turtle Serialisation -*/ - -#ifndef INGEN_SERIALISATION_PARSER_HPP -#define INGEN_SERIALISATION_PARSER_HPP - -#include -#include - -#include - -#include "ingen/Node.hpp" -#include "raul/Path.hpp" -#include "raul/URI.hpp" - -namespace Ingen { - -class Interface; -class World; - -namespace Serialisation { - -/** - Read Ingen objects from Turtle files or strings. - - @ingroup IngenSerialisation -*/ -class Parser { -public: - explicit Parser() {} - - virtual ~Parser() {} - - typedef Node::Properties Properties; - - virtual bool parse_file( - World* world, - Interface* target, - const std::string& path, - boost::optional parent = boost::optional(), - boost::optional symbol = boost::optional(), - boost::optional data = boost::optional()); - - virtual boost::optional parse_string( - World* world, - Interface* target, - const std::string& str, - const std::string& base_uri, - boost::optional parent = boost::optional(), - boost::optional symbol = boost::optional(), - boost::optional data = boost::optional()); -}; - -} // namespace Serialisation -} // namespace Ingen - -#endif // INGEN_SERIALISATION_PARSER_HPP diff --git a/ingen/serialisation/Serialiser.hpp b/ingen/serialisation/Serialiser.hpp deleted file mode 100644 index 80a01b89..00000000 --- a/ingen/serialisation/Serialiser.hpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#ifndef INGEN_SERIALISATION_SERIALISER_HPP -#define INGEN_SERIALISATION_SERIALISER_HPP - -#include -#include - -#include "raul/Path.hpp" - -#include "sord/sordmm.hpp" - -#include "ingen/Node.hpp" - -namespace Ingen { - -class Arc; -class Node; -class Store; -class World; - -namespace Serialisation { - -/** - Write Ingen objects to Turtle files or strings. - - @ingroup IngenSerialisation -*/ -class Serialiser -{ -public: - explicit Serialiser(World& world); - virtual ~Serialiser(); - - /** Write a graph and all its contents as a complete bundle. */ - virtual void write_bundle(SPtr graph, - const std::string& path); - - /** Begin a serialization to a string. - * - * This must be called before any serializing methods. - * - * The results of the serialization will be returned by the finish() method after - * the desired objects have been serialised. - * - * All serialized paths will have the root path chopped from their prefix - * (therefore all serialized paths must be descendants of the root) - */ - virtual void start_to_string(const Raul::Path& root, - const std::string& base_uri); - - /** Begin a serialization to a file. - * - * This must be called before any serializing methods. - * - * All serialized paths will have the root path chopped from their prefix - * (therefore all serialized paths must be descendants of the root) - */ - virtual void start_to_file(const Raul::Path& root, - const std::string& filename); - - /** Serialize an object (graph, block, or port). */ - virtual void serialise(SPtr object) - throw (std::logic_error); - - /** Serialize an arc. */ - virtual void serialise_arc(const Sord::Node& parent, - SPtr arc) - throw (std::logic_error); - - /** Finish serialization. - * - * If this is a file serialization, this must be called to finish and close - * the output file, and the empty string is returned. - * - * If this is a string serialization, the serialized result is returned. - */ - virtual std::string finish(); - -private: - struct Impl; - Impl* me; -}; - -} // namespace Serialisation -} // namespace Ingen - -#endif // INGEN_SERIALISATION_SERIALISER_HPP diff --git a/src/Parser.cpp b/src/Parser.cpp new file mode 100644 index 00000000..b0bf88e6 --- /dev/null +++ b/src/Parser.cpp @@ -0,0 +1,653 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#include +#include +#include +#include + +#include +#include +#include + +#include "ingen/Atom.hpp" +#include "ingen/Interface.hpp" +#include "ingen/Log.hpp" +#include "ingen/Parser.hpp" +#include "ingen/URIMap.hpp" +#include "ingen/URIs.hpp" +#include "ingen/World.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" +#include "serd/serd.h" +#include "sord/sordmm.hpp" +#include "sratom/sratom.h" + +using namespace std; + +typedef set RDFNodes; + +namespace Ingen { + +static std::string +relative_uri(const std::string& base, const std::string& uri, bool leading_slash) +{ + std::string ret; + if (uri != base) { + SerdURI base_uri; + serd_uri_parse((const uint8_t*)base.c_str(), &base_uri); + + SerdURI normal_base_uri; + SerdNode normal_base_uri_node = serd_node_new_uri_from_string( + (const uint8_t*)".", &base_uri, &normal_base_uri); + + std::string normal_base_str((const char*)normal_base_uri_node.buf); + + ret = uri; + if (uri.length() >= normal_base_str.length() + && uri.substr(0, normal_base_str.length()) == normal_base_str) { + ret = uri.substr(normal_base_str.length()); + } + + serd_node_free(&normal_base_uri_node); + } + + if (leading_slash && ret[0] != '/') { + ret = std::string("/").append(ret); + } + return ret; +} + +static std::string +get_basename(const std::string& uri) +{ + std::string ret = Glib::path_get_basename(uri); + ret = ret.substr(0, ret.find_last_of('.')); + return ret; +} + +static bool +skip_property(Ingen::URIs& uris, const Sord::Node& predicate) +{ + return (predicate.to_string() == INGEN__file || + predicate.to_string() == uris.ingen_arc || + predicate.to_string() == uris.ingen_block || + predicate.to_string() == uris.lv2_port); +} + +static Resource::Properties +get_properties(Ingen::World* world, + Sord::Model& model, + const Sord::Node& subject) +{ + SerdChunk out = { NULL, 0 }; + LV2_URID_Map* map = &world->uri_map().urid_map_feature()->urid_map; + LV2_URID_Unmap* unmap = &world->uri_map().urid_unmap_feature()->urid_unmap; + Sratom* sratom = sratom_new(map); + + LV2_Atom_Forge forge; + lv2_atom_forge_init(&forge, map); + lv2_atom_forge_set_sink(&forge, sratom_forge_sink, sratom_forge_deref, &out); + + const Sord::Node nil; + Resource::Properties props; + for (Sord::Iter i = model.find(subject, nil, nil); !i.end(); ++i) { + if (!skip_property(world->uris(), i.get_predicate())) { + out.len = 0; + sratom_read(sratom, &forge, world->rdf_world()->c_obj(), + model.c_obj(), i.get_object().c_obj()); + const LV2_Atom* atom = (const LV2_Atom*)out.buf; + Atom atomm; + // FIXME: Don't bloat out all URIs + if (atom->type == forge.URID) { + atomm = world->forge().alloc_uri( + unmap->unmap(unmap->handle, + ((const LV2_Atom_URID*)atom)->body)); + } else { + atomm = world->forge().alloc( + atom->size, atom->type, LV2_ATOM_BODY_CONST(atom)); + } + props.insert(make_pair(Raul::URI(i.get_predicate().to_string()), + atomm)); + } + } + + free((uint8_t*)out.buf); + sratom_free(sratom); + return props; +} + +typedef std::pair PortRecord; + +static boost::optional +get_port(Ingen::World* world, + Sord::Model& model, + const Sord::Node& subject, + const Raul::Path& parent, + uint32_t* index) +{ + const URIs& uris = world->uris(); + + // Get all properties + Resource::Properties props = get_properties(world, model, subject); + + // Get index if requested (for Graphs) + if (index) { + Resource::Properties::const_iterator i = props.find(uris.lv2_index); + if (i == props.end() + || i->second.type() != world->forge().Int + || i->second.get() < 0) { + world->log().error(fmt("Port %1% has no valid index\n") % subject); + return boost::optional(); + } + *index = i->second.get(); + } + + // Get symbol + Resource::Properties::const_iterator s = props.find(uris.lv2_symbol); + std::string sym; + if (s != props.end()) { + sym = s->second.ptr(); + } else { + const std::string subject_str = subject.to_string(); + const size_t last_slash = subject_str.find_last_of("/"); + + sym = ((last_slash == string::npos) + ? subject_str + : subject_str.substr(last_slash + 1)); + } + + if (!Raul::Symbol::is_valid(sym)) { + world->log().error(fmt("Port %1% has invalid symbol `%2%'\n") + % subject % sym); + return boost::optional(); + } + + const Raul::Symbol port_sym(sym); + const Raul::Path port_path(parent.child(port_sym)); + + return make_pair(port_path, props); +} + +static boost::optional +parse( + World* world, + Interface* target, + Sord::Model& model, + const std::string& base_uri, + Sord::Node& subject, + boost::optional parent = boost::optional(), + boost::optional symbol = boost::optional(), + boost::optional data = boost::optional()); + +static boost::optional +parse_graph( + World* world, + Interface* target, + Sord::Model& model, + const std::string& base_uri, + const Sord::Node& subject, + boost::optional parent = boost::optional(), + boost::optional symbol = boost::optional(), + boost::optional data = boost::optional()); + +static boost::optional +parse_block( + World* world, + Interface* target, + Sord::Model& model, + const std::string& base_uri, + const Sord::Node& subject, + const Raul::Path& path, + boost::optional data = boost::optional()); + +static bool +parse_properties( + World* world, + Interface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::URI& uri, + boost::optional data = boost::optional()); + +static bool +parse_arcs( + World* world, + Interface* target, + Sord::Model& model, + const std::string& base_uri, + const Sord::Node& subject, + const Raul::Path& graph); + +static boost::optional +parse_block(Ingen::World* world, + Ingen::Interface* target, + Sord::Model& model, + const std::string& base_uri, + const Sord::Node& subject, + const Raul::Path& path, + boost::optional data) +{ + const URIs& uris = world->uris(); + + const Sord::URI ingen_prototype(*world->rdf_world(), uris.ingen_prototype); + const Sord::Node nil; + + Sord::Iter i = model.find(subject, ingen_prototype, nil); + if (i.end() || i.get_object().type() != Sord::Node::URI) { + if (!i.end()) { + std::cerr << "type: " << i.get_object().type() << std::endl; + } + world->log().error( + fmt("Block %1% (%2%) missing mandatory ingen:prototype\n") % + subject.to_string() % path); + return boost::optional(); + } + + const std::string type_uri = relative_uri(base_uri, + i.get_object().to_string(), + false); + + if (!serd_uri_string_has_scheme((const uint8_t*)type_uri.c_str())) { + SerdURI base_uri_parts; + serd_uri_parse((const uint8_t*)base_uri.c_str(), &base_uri_parts); + + SerdURI ignored; + SerdNode sub_uri = serd_node_new_uri_from_string( + i.get_object().to_u_string(), + &base_uri_parts, + &ignored); + + const std::string sub_uri_str = (const char*)sub_uri.buf; + const std::string basename = get_basename(sub_uri_str); + const std::string sub_file = sub_uri_str + '/' + basename + ".ttl"; + + const SerdNode sub_base = serd_node_from_string( + SERD_URI, (const uint8_t*)sub_file.c_str()); + + Sord::Model sub_model(*world->rdf_world(), sub_file); + SerdEnv* env = serd_env_new(&sub_base); + sub_model.load_file(env, SERD_TURTLE, sub_file); + serd_env_free(env); + + Sord::URI sub_node(*world->rdf_world(), sub_file); + parse_graph(world, target, sub_model, (const char*)sub_base.buf, sub_node, + path.parent(), Raul::Symbol(path.symbol())); + + parse_graph(world, target, model, base_uri, subject, + path.parent(), Raul::Symbol(path.symbol())); + } else { + Resource::Properties props = get_properties(world, model, subject); + props.insert(make_pair(uris.rdf_type, + uris.forge.alloc_uri(uris.ingen_Block))); + target->put(Node::path_to_uri(path), props); + } + return path; +} + +static boost::optional +parse_graph(Ingen::World* world, + Ingen::Interface* target, + Sord::Model& model, + const std::string& base_uri, + const Sord::Node& subject_node, + boost::optional parent, + boost::optional a_symbol, + boost::optional data) +{ + const URIs& uris = world->uris(); + + const Sord::URI ingen_block(*world->rdf_world(), uris.ingen_block); + const Sord::URI ingen_polyphony(*world->rdf_world(), uris.ingen_polyphony); + const Sord::URI lv2_port(*world->rdf_world(), LV2_CORE__port); + + const Sord::Node& graph = subject_node; + const Sord::Node nil; + + Raul::Symbol symbol("_"); + if (a_symbol) { + symbol = *a_symbol; + } + + string graph_path_str = relative_uri(base_uri, subject_node.to_string(), true); + if (parent && a_symbol) { + graph_path_str = parent->child(*a_symbol); + } else if (parent) { + graph_path_str = *parent; + } + + if (!Raul::Path::is_valid(graph_path_str)) { + world->log().error(fmt("Graph %1% has invalid path\n") + % graph_path_str); + return boost::optional(); + } + + // Create graph + Raul::Path graph_path(graph_path_str); + Resource::Properties props = get_properties(world, model, subject_node); + target->put(Node::path_to_uri(graph_path), props); + + // For each block in this graph + for (Sord::Iter n = model.find(subject_node, ingen_block, nil); !n.end(); ++n) { + Sord::Node node = n.get_object(); + const Raul::Path block_path = graph_path.child( + Raul::Symbol(get_basename(node.to_string()))); + + // Parse and create block + parse_block(world, target, model, base_uri, node, block_path, + boost::optional()); + + // For each port on this block + for (Sord::Iter p = model.find(node, lv2_port, nil); !p.end(); ++p) { + Sord::Node port = p.get_object(); + + // Get all properties + boost::optional port_record = get_port( + world, model, port, block_path, NULL); + if (!port_record) { + world->log().error(fmt("Invalid port %1%\n") % port); + return boost::optional(); + } + + // Create port and/or set all port properties + target->put(Node::path_to_uri(port_record->first), + port_record->second); + } + } + + // For each port on this graph + typedef std::map PortRecords; + PortRecords ports; + for (Sord::Iter p = model.find(graph, lv2_port, nil); !p.end(); ++p) { + Sord::Node port = p.get_object(); + + // Get all properties + uint32_t index = 0; + boost::optional port_record = get_port( + world, model, port, graph_path, &index); + if (!port_record) { + world->log().error(fmt("Invalid port %1%\n") % port); + return boost::optional(); + } + + // Store port information in ports map + ports[index] = *port_record; + } + + // Create ports in order by index + for (const auto& p : ports) { + target->put(Node::path_to_uri(p.second.first), + p.second.second); + } + + parse_arcs(world, target, model, base_uri, subject_node, graph_path); + + return graph_path; +} + +static bool +parse_arc(Ingen::World* world, + Ingen::Interface* target, + Sord::Model& model, + const std::string& base_uri, + const Sord::Node& subject, + const Raul::Path& graph) +{ + const URIs& uris = world->uris(); + + const Sord::URI ingen_tail(*world->rdf_world(), uris.ingen_tail); + const Sord::URI ingen_head(*world->rdf_world(), uris.ingen_head); + const Sord::Node nil; + + Sord::Iter t = model.find(subject, ingen_tail, nil); + Sord::Iter h = model.find(subject, ingen_head, nil); + + if (t.end()) { + world->log().error("Arc has no tail"); + return false; + } else if (h.end()) { + world->log().error("Arc has no head"); + return false; + } + + const std::string tail_str = relative_uri( + base_uri, t.get_object().to_string(), true); + if (!Raul::Path::is_valid(tail_str)) { + world->log().error("Arc tail has invalid URI"); + return false; + } + + const std::string head_str = relative_uri( + base_uri, h.get_object().to_string(), true); + if (!Raul::Path::is_valid(head_str)) { + world->log().error("Arc head has invalid URI"); + return false; + } + + if (!(++t).end()) { + world->log().error("Arc has multiple tails"); + return false; + } else if (!(++h).end()) { + world->log().error("Arc has multiple heads"); + return false; + } + + target->connect(graph.child(Raul::Path(tail_str)), + graph.child(Raul::Path(head_str))); + + return true; +} + +static bool +parse_arcs(Ingen::World* world, + Ingen::Interface* target, + Sord::Model& model, + const std::string& base_uri, + const Sord::Node& subject, + const Raul::Path& graph) +{ + const Sord::URI ingen_arc(*world->rdf_world(), world->uris().ingen_arc); + const Sord::Node nil; + + for (Sord::Iter i = model.find(subject, ingen_arc, nil); !i.end(); ++i) { + parse_arc(world, target, model, base_uri, i.get_object(), graph); + } + + return true; +} + +static bool +parse_properties(Ingen::World* world, + Ingen::Interface* target, + Sord::Model& model, + const Sord::Node& subject, + const Raul::URI& uri, + boost::optional data) +{ + Resource::Properties properties = get_properties(world, model, subject); + + target->put(uri, properties); + + // Set passed properties last to override any loaded values + if (data) + target->put(uri, data.get()); + + return true; +} + +static boost::optional +parse(Ingen::World* world, + Ingen::Interface* target, + Sord::Model& model, + const std::string& base_uri, + Sord::Node& subject, + boost::optional parent, + boost::optional symbol, + boost::optional data) +{ + const URIs& uris = world->uris(); + + const Sord::URI graph_class (*world->rdf_world(), uris.ingen_Graph); + const Sord::URI block_class (*world->rdf_world(), uris.ingen_Block); + const Sord::URI arc_class (*world->rdf_world(), uris.ingen_Arc); + const Sord::URI internal_class(*world->rdf_world(), uris.ingen_Internal); + const Sord::URI in_port_class (*world->rdf_world(), LV2_CORE__InputPort); + const Sord::URI out_port_class(*world->rdf_world(), LV2_CORE__OutputPort); + const Sord::URI lv2_class (*world->rdf_world(), LV2_CORE__Plugin); + const Sord::URI rdf_type (*world->rdf_world(), uris.rdf_type); + const Sord::Node nil; + + // Parse explicit subject graph + if (subject.is_valid()) { + return parse_graph(world, target, model, base_uri, subject, parent, symbol, data); + } + + // Get all subjects and their types (?subject a ?type) + typedef std::map< Sord::Node, std::set > Subjects; + Subjects subjects; + for (Sord::Iter i = model.find(subject, rdf_type, nil); !i.end(); ++i) { + const Sord::Node& subject = i.get_subject(); + const Sord::Node& rdf_class = i.get_object(); + + assert(rdf_class.is_uri()); + Subjects::iterator s = subjects.find(subject); + if (s == subjects.end()) { + std::set types; + types.insert(rdf_class); + subjects.insert(make_pair(subject, types)); + } else { + s->second.insert(rdf_class); + } + } + + // Parse and create each subject + for (const auto& i : subjects) { + const Sord::Node& s = i.first; + const std::set& types = i.second; + boost::optional ret; + const Raul::Path rel_path(relative_uri(base_uri, s.to_string(), true)); + const Raul::Path path = parent ? parent->child(rel_path) : rel_path; + if (types.find(graph_class) != types.end()) { + ret = parse_graph(world, target, model, base_uri, s, parent, symbol, data); + } else if (types.find(block_class) != types.end()) { + ret = parse_block(world, target, model, base_uri, s, path, data); + } else if (types.find(in_port_class) != types.end() || + types.find(out_port_class) != types.end()) { + parse_properties( + world, target, model, s, Node::path_to_uri(path), data); + ret = path; + } else if (types.find(arc_class) != types.end()) { + Raul::Path parent_path(parent ? parent.get() : Raul::Path("/")); + parse_arc(world, target, model, base_uri, s, parent_path); + } else { + world->log().error("Subject has no known types\n"); + } + } + + return boost::optional(); +} + +/** Parse a graph from RDF into a Interface (engine or client). + * @return whether or not load was successful. + */ +bool +Parser::parse_file(Ingen::World* world, + Ingen::Interface* target, + const std::string& path, + boost::optional parent, + boost::optional symbol, + boost::optional data) +{ + std::string file_path = path; + if (!Glib::path_is_absolute(file_path)) { + file_path = Glib::build_filename(Glib::get_current_dir(), file_path); + } + if (Glib::file_test(file_path, Glib::FILE_TEST_IS_DIR)) { + // This is a bundle, append "/name.ttl" to get graph file path + file_path = Glib::build_filename(path, get_basename(path) + ".ttl"); + } + + std::string uri; + try { + uri = Glib::filename_to_uri(file_path, ""); + } catch (const Glib::ConvertError& e) { + world->log().error(fmt("Path to URI conversion error: %1%\n") + % e.what()); + return false; + } + + const uint8_t* uri_c_str = (const uint8_t*)uri.c_str(); + SerdNode base_node = serd_node_from_string(SERD_URI, uri_c_str); + SerdEnv* env = serd_env_new(&base_node); + + // Load graph file into model + Sord::Model model(*world->rdf_world(), uri, SORD_SPO|SORD_PSO, false); + model.load_file(env, SERD_TURTLE, uri); + + serd_env_free(env); + + world->log().info(fmt("Parsing %1%\n") % file_path); + if (parent) + world->log().info(fmt("Parent: %1%\n") % parent->c_str()); + if (symbol) + world->log().info(fmt("Symbol: %1%\n") % symbol->c_str()); + + Sord::Node subject(*world->rdf_world(), Sord::Node::URI, uri); + boost::optional parsed_path + = parse(world, target, model, model.base_uri().to_string(), + subject, parent, symbol, data); + + if (parsed_path) { + target->set_property(Node::path_to_uri(*parsed_path), + Raul::URI(INGEN__file), + world->forge().alloc_uri(uri)); + return true; + } else { + world->log().warn("Document URI lost\n"); + return false; + } +} + +boost::optional +Parser::parse_string(Ingen::World* world, + Ingen::Interface* target, + const std::string& str, + const std::string& base_uri, + boost::optional parent, + boost::optional symbol, + boost::optional data) +{ + // Load string into model + Sord::Model model(*world->rdf_world(), base_uri, SORD_SPO|SORD_PSO, false); + + SerdEnv* env = serd_env_new(NULL); + if (!base_uri.empty()) { + const SerdNode base = serd_node_from_string( + SERD_URI, (const uint8_t*)base_uri.c_str()); + serd_env_set_base_uri(env, &base); + } + model.load_string(env, SERD_TURTLE, str.c_str(), str.length(), base_uri); + + Raul::URI actual_base((const char*)serd_env_get_base_uri(env, NULL)->buf); + serd_env_free(env); + + world->log().info(fmt("Parsing string (base %1%)\n") % base_uri); + + Sord::Node subject; + parse(world, target, model, actual_base, subject, parent, symbol, data); + return actual_base; +} + +} // namespace Ingen diff --git a/src/Serialiser.cpp b/src/Serialiser.cpp new file mode 100644 index 00000000..2114cc00 --- /dev/null +++ b/src/Serialiser.cpp @@ -0,0 +1,545 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ingen/Arc.hpp" +#include "ingen/Interface.hpp" +#include "ingen/Log.hpp" +#include "ingen/Node.hpp" +#include "ingen/Plugin.hpp" +#include "ingen/Resource.hpp" +#include "ingen/Serialiser.hpp" +#include "ingen/Store.hpp" +#include "ingen/URIMap.hpp" +#include "ingen/URIs.hpp" +#include "ingen/World.hpp" +#include "lv2/lv2plug.in/ns/ext/state/state.h" +#include "lv2/lv2plug.in/ns/extensions/ui/ui.h" +#include "raul/Path.hpp" +#include "sord/sordmm.hpp" +#include "sratom/sratom.h" + +using namespace std; +using namespace Sord; +using namespace Ingen; + +namespace Ingen { + +struct Serialiser::Impl { + typedef Resource::Properties Properties; + + explicit Impl(World& world) + : _root_path("/") + , _world(world) + , _model(NULL) + , _sratom(sratom_new(&_world.uri_map().urid_map_feature()->urid_map)) + {} + + ~Impl() { + sratom_free(_sratom); + } + + enum class Mode { TO_FILE, TO_STRING }; + + void start_to_filename(const std::string& filename); + + void serialise_graph(SPtr p, + const Sord::Node& id); + + void serialise_block(SPtr n, + const Sord::Node& class_id, + const Sord::Node& id); + + void serialise_port(const Node* p, + Resource::Graph context, + const Sord::Node& id); + + void serialise_properties(Sord::Node id, + const Resource::Properties& props); + + void write_bundle(SPtr graph, + const std::string& uri); + + Sord::Node path_rdf_node(const Raul::Path& path); + + void write_manifest(const std::string& bundle_path, + SPtr graph, + const std::string& graph_symbol); + + void serialise_arc(const Sord::Node& parent, + SPtr a) + throw (std::logic_error); + + std::string finish(); + + Raul::Path _root_path; + Mode _mode; + std::string _base_uri; + World& _world; + Sord::Model* _model; + Sratom* _sratom; +}; + +Serialiser::Serialiser(World& world) + : me(new Impl(world)) +{} + +Serialiser::~Serialiser() +{ + delete me; +} + +void +Serialiser::Impl::write_manifest(const std::string& bundle_path, + SPtr graph, + const std::string& graph_symbol) +{ + const string manifest_path(Glib::build_filename(bundle_path, "manifest.ttl")); + const string binary_path(Glib::Module::build_path("", "ingen_lv2")); + + start_to_filename(manifest_path); + + Sord::World& world = _model->world(); + const URIs& uris = _world.uris(); + + const string filename(graph_symbol + ".ttl"); + const Sord::URI subject(world, filename, _base_uri); + + _model->add_statement(subject, + Sord::URI(world, uris.rdf_type), + Sord::URI(world, uris.ingen_Graph)); + _model->add_statement(subject, + Sord::URI(world, uris.rdf_type), + Sord::URI(world, uris.lv2_Plugin)); + _model->add_statement(subject, + Sord::URI(world, uris.rdfs_seeAlso), + Sord::URI(world, filename, _base_uri)); + _model->add_statement(subject, + Sord::URI(world, uris.lv2_prototype), + Sord::URI(world, uris.ingen_GraphPrototype)); + + finish(); +} + +void +Serialiser::write_bundle(SPtr graph, + const std::string& path) +{ + me->write_bundle(graph, path); +} + +void +Serialiser::Impl::write_bundle(SPtr graph, + const std::string& a_path) +{ + std::string path = Glib::filename_from_uri(a_path); + if (Glib::file_test(path, Glib::FILE_TEST_EXISTS) + && !Glib::file_test(path, Glib::FILE_TEST_IS_DIR)) { + path = Glib::path_get_dirname(path); + } + + _world.log().info(fmt("Writing bundle %1%\n") % path); + + if (path[path.length() - 1] != '/') + path.append("/"); + + g_mkdir_with_parents(path.c_str(), 0744); + + string symbol = Glib::path_get_basename(path); + symbol = symbol.substr(0, symbol.find(".")); + + const string root_file = Glib::build_filename(path, symbol + ".ttl"); + + start_to_filename(root_file); + const Raul::Path old_root_path = _root_path; + _root_path = graph->path(); + serialise_graph(graph, Sord::URI(_model->world(), root_file, _base_uri)); + _root_path = old_root_path; + finish(); + + write_manifest(path, graph, symbol); +} + +/** Begin a serialization to a file. + * + * This must be called before any serializing methods. + */ +void +Serialiser::Impl::start_to_filename(const string& filename) +{ + assert(filename.find(":") == string::npos || filename.substr(0, 5) == "file:"); + if (filename.find(":") == string::npos) { + _base_uri = "file://" + filename; + } else { + _base_uri = filename; + } + + _model = new Sord::Model(*_world.rdf_world(), _base_uri); + _mode = Mode::TO_FILE; +} + +void +Serialiser::start_to_string(const Raul::Path& root, const string& base_uri) +{ + me->_root_path = root; + me->_base_uri = base_uri; + me->_model = new Sord::Model(*me->_world.rdf_world(), base_uri); + me->_mode = Impl::Mode::TO_STRING; +} + +void +Serialiser::start_to_file(const Raul::Path& root, const string& filename) +{ + me->_root_path = root; + me->start_to_filename(filename); +} + +std::string +Serialiser::finish() +{ + return me->finish(); +} + +std::string +Serialiser::Impl::finish() +{ + string ret = ""; + if (_mode == Mode::TO_FILE) { + SerdStatus st = _model->write_to_file(_base_uri, SERD_TURTLE); + if (st) { + _world.log().error(fmt("Error writing file %1% (%2%)\n") + % _base_uri % serd_strerror(st)); + } + } else { + ret = _model->write_to_string(_base_uri, SERD_TURTLE); + } + + delete _model; + _model = NULL; + _base_uri = ""; + + return ret; +} + +Sord::Node +Serialiser::Impl::path_rdf_node(const Raul::Path& path) +{ + assert(_model); + assert(path == _root_path || path.is_child_of(_root_path)); + return Sord::URI(_model->world(), + path.substr(_root_path.base().length()), + _base_uri); +} + +void +Serialiser::serialise(SPtr object) throw (std::logic_error) +{ + if (!me->_model) + throw std::logic_error("serialise called without serialisation in progress"); + + if (object->graph_type() == Node::GraphType::GRAPH) { + me->serialise_graph(object, me->path_rdf_node(object->path())); + } else if (object->graph_type() == Node::GraphType::BLOCK) { + const Sord::URI plugin_id(me->_model->world(), object->plugin()->uri()); + me->serialise_block(object, plugin_id, me->path_rdf_node(object->path())); + } else if (object->graph_type() == Node::GraphType::PORT) { + me->serialise_port(object.get(), + Resource::Graph::DEFAULT, + me->path_rdf_node(object->path())); + } else { + me->serialise_properties(me->path_rdf_node(object->path()), + object->properties()); + } +} + +void +Serialiser::Impl::serialise_graph(SPtr graph, + const Sord::Node& graph_id) +{ + Sord::World& world = _model->world(); + const URIs& uris = _world.uris(); + + _model->add_statement(graph_id, + Sord::URI(world, uris.rdf_type), + Sord::URI(world, uris.ingen_Graph)); + + _model->add_statement(graph_id, + Sord::URI(world, uris.rdf_type), + Sord::URI(world, uris.lv2_Plugin)); + + _model->add_statement(graph_id, + Sord::URI(world, uris.lv2_extensionData), + Sord::URI(world, LV2_STATE__interface)); + + _model->add_statement(graph_id, + Sord::URI(world, LV2_UI__ui), + Sord::URI(world, "http://drobilla.net/ns/ingen#GraphUIGtk2")); + + // Always write a symbol (required by Ingen) + Raul::Symbol symbol("_"); + Node::Properties::const_iterator s = graph->properties().find(uris.lv2_symbol); + if (s == graph->properties().end() + || s->second.type() != _world.forge().String + || !Raul::Symbol::is_valid(s->second.ptr())) { + const std::string base = Glib::path_get_basename( + _model->base_uri().to_c_string()); + symbol = Raul::Symbol::symbolify(base.substr(0, base.find('.'))); + _model->add_statement( + graph_id, + Sord::URI(world, uris.lv2_symbol), + Sord::Literal(world, symbol.c_str())); + } else { + symbol = Raul::Symbol::symbolify(s->second.ptr()); + } + + // If the graph has no doap:name (required by LV2), use the symbol + if (graph->properties().find(uris.doap_name) == graph->properties().end()) + _model->add_statement(graph_id, + Sord::URI(world, uris.doap_name), + Sord::Literal(world, symbol.c_str())); + + const Node::Properties props = graph->properties(Resource::Graph::INTERNAL); + serialise_properties(graph_id, props); + + const Store::const_range kids = _world.store()->children_range(graph); + for (Store::const_iterator n = kids.first; n != kids.second; ++n) { + if (n->first.parent() != graph->path()) + continue; + + if (n->second->graph_type() == Node::GraphType::GRAPH) { + SPtr subgraph = n->second; + + SerdURI base_uri; + serd_uri_parse((const uint8_t*)_base_uri.c_str(), &base_uri); + + const string sub_bundle_path = subgraph->path().substr(1) + ".ingen"; + + SerdURI subgraph_uri; + SerdNode subgraph_node = serd_node_new_uri_from_string( + (const uint8_t*)sub_bundle_path.c_str(), + &base_uri, + &subgraph_uri); + + const Sord::URI subgraph_id(world, (const char*)subgraph_node.buf); + + // Save our state + std::string my_base_uri = _base_uri; + Sord::Model* my_model = _model; + + // Write child bundle within this bundle + write_bundle(subgraph, subgraph_id.to_string()); + + // Restore our state + _base_uri = my_base_uri; + _model = my_model; + + // Serialise reference to graph block + const Sord::Node block_id(path_rdf_node(subgraph->path())); + _model->add_statement(graph_id, + Sord::URI(world, uris.ingen_block), + block_id); + serialise_block(subgraph, subgraph_id, block_id); + } else if (n->second->graph_type() == Node::GraphType::BLOCK) { + SPtr block = n->second; + + const Sord::URI class_id(world, block->plugin()->uri()); + const Sord::Node block_id(path_rdf_node(n->second->path())); + _model->add_statement(graph_id, + Sord::URI(world, uris.ingen_block), + block_id); + serialise_block(block, class_id, block_id); + } + } + + for (uint32_t i = 0; i < graph->num_ports(); ++i) { + Node* p = graph->port(i); + const Sord::Node port_id = path_rdf_node(p->path()); + + // Ensure lv2:name always exists so Graph is a valid LV2 plugin + if (p->properties().find(uris.lv2_name) == p->properties().end()) + p->set_property(uris.lv2_name, + _world.forge().alloc(p->symbol().c_str())); + + _model->add_statement(graph_id, + Sord::URI(world, LV2_CORE__port), + port_id); + serialise_port(p, Resource::Graph::INTERNAL, port_id); + } + + for (const auto& a : graph->arcs()) { + serialise_arc(graph_id, a.second); + } +} + +void +Serialiser::Impl::serialise_block(SPtr block, + const Sord::Node& class_id, + const Sord::Node& block_id) +{ + const URIs& uris = _world.uris(); + + _model->add_statement(block_id, + Sord::URI(_model->world(), uris.rdf_type), + Sord::URI(_model->world(), uris.ingen_Block)); + _model->add_statement(block_id, + Sord::URI(_model->world(), uris.ingen_prototype), + class_id); + + const Node::Properties props = block->properties(Resource::Graph::EXTERNAL); + serialise_properties(block_id, props); + + for (uint32_t i = 0; i < block->num_ports(); ++i) { + Node* const p = block->port(i); + const Sord::Node port_id = path_rdf_node(p->path()); + serialise_port(p, Resource::Graph::EXTERNAL, port_id); + _model->add_statement(block_id, + Sord::URI(_model->world(), uris.lv2_port), + port_id); + } +} + +void +Serialiser::Impl::serialise_port(const Node* port, + Resource::Graph context, + const Sord::Node& port_id) +{ + URIs& uris = _world.uris(); + Sord::World& world = _model->world(); + Node::Properties props = port->properties(context); + + if (context == Resource::Graph::INTERNAL) { + // Always write lv2:symbol for Graph ports (required for lv2:Plugin) + _model->add_statement(port_id, + Sord::URI(world, uris.lv2_symbol), + Sord::Literal(world, port->path().symbol())); + } else { + // Never write lv2:index for plugin instances (not persistent/stable) + props.erase(uris.lv2_index); + } + + if (context == Resource::Graph::INTERNAL && + port->has_property(uris.rdf_type, uris.lv2_ControlPort) && + port->has_property(uris.rdf_type, uris.lv2_InputPort)) + { + const Atom& val = port->get_property(uris.ingen_value); + if (val.is_valid()) { + props.insert(make_pair(uris.lv2_default, val)); + } else { + _world.log().warn("Control input has no value, lv2:default omitted.\n"); + } + } else if (context != Resource::Graph::INTERNAL && + !port->has_property(uris.rdf_type, uris.lv2_InputPort)) { + props.erase(uris.ingen_value); + } + + serialise_properties(port_id, props); +} + +void +Serialiser::serialise_arc(const Sord::Node& parent, + SPtr arc) + throw (std::logic_error) +{ + return me->serialise_arc(parent, arc); +} + +void +Serialiser::Impl::serialise_arc(const Sord::Node& parent, + SPtr arc) + throw (std::logic_error) +{ + if (!_model) + throw std::logic_error( + "serialise_arc called without serialisation in progress"); + + Sord::World& world = _model->world(); + const URIs& uris = _world.uris(); + + const Sord::Node src = path_rdf_node(arc->tail_path()); + const Sord::Node dst = path_rdf_node(arc->head_path()); + const Sord::Node arc_id = Sord::Node::blank_id(*_world.rdf_world()); + _model->add_statement(arc_id, + Sord::URI(world, uris.ingen_tail), + src); + _model->add_statement(arc_id, + Sord::URI(world, uris.ingen_head), + dst); + + if (parent.is_valid()) { + _model->add_statement(parent, + Sord::URI(world, uris.ingen_arc), + arc_id); + } else { + _model->add_statement(arc_id, + Sord::URI(world, uris.rdf_type), + Sord::URI(world, uris.ingen_Arc)); + } +} + +static bool +skip_property(Ingen::URIs& uris, const Sord::Node& predicate) +{ + return (predicate.to_string() == INGEN__file || + predicate.to_string() == uris.ingen_arc || + predicate.to_string() == uris.ingen_block || + predicate.to_string() == uris.lv2_port); +} + +void +Serialiser::Impl::serialise_properties(Sord::Node id, + const Node::Properties& props) +{ + LV2_URID_Unmap* unmap = &_world.uri_map().urid_unmap_feature()->urid_unmap; + SerdNode base = serd_node_from_string(SERD_URI, + (const uint8_t*)_base_uri.c_str()); + SerdEnv* env = serd_env_new(&base); + SordInserter* inserter = sord_inserter_new(_model->c_obj(), env); + + sratom_set_sink(_sratom, _base_uri.c_str(), + (SerdStatementSink)sord_inserter_write_statement, NULL, + inserter); + + sratom_set_pretty_numbers(_sratom, true); + + for (const auto& p : props) { + const Sord::URI key(_model->world(), p.first); + if (!skip_property(_world.uris(), key)) { + sratom_write(_sratom, unmap, 0, + sord_node_to_serd_node(id.c_obj()), + sord_node_to_serd_node(key.c_obj()), + p.second.type(), p.second.size(), p.second.get_body()); + } + } + + sord_inserter_free(inserter); + serd_env_free(env); +} + +} // namespace Ingen diff --git a/src/World.cpp b/src/World.cpp index badbf353..615c761d 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -26,6 +26,8 @@ #include "ingen/LV2Features.hpp" #include "ingen/Log.hpp" #include "ingen/Module.hpp" +#include "ingen/Parser.hpp" +#include "ingen/Serialiser.hpp" #include "ingen/URIMap.hpp" #include "ingen/URIs.hpp" #include "ingen/World.hpp" @@ -40,12 +42,9 @@ namespace Ingen { class EngineBase; class Interface; -class Store; - -namespace Serialisation { class Parser; class Serialiser; -} +class Store; /** Load a dynamic module from the default path. * @@ -53,7 +52,7 @@ class Serialiser; * INGEN_MODULE_PATH (typical colon delimited format), then the default module * installation directory (ie /usr/local/lib/ingen), in that order. * - * \param name The base name of the module, e.g. "ingen_serialisation" + * \param name The base name of the module, e.g. "ingen_jack" */ static Glib::Module* ingen_load_module(Log& log, const string& name) @@ -202,23 +201,23 @@ public: typedef std::map ScriptRunners; ScriptRunners script_runners; - int& argc; - char**& argv; - LV2Features* lv2_features; - Sord::World* rdf_world; - URIMap* uri_map; - Forge* forge; - URIs* uris; - LV2_Log_Log* lv2_log; - Log log; - Configuration conf; - SPtr interface; - SPtr engine; - SPtr serialiser; - SPtr parser; - SPtr store; - LilvWorld* lilv_world; - std::string jack_uuid; + int& argc; + char**& argv; + LV2Features* lv2_features; + Sord::World* rdf_world; + URIMap* uri_map; + Forge* forge; + URIs* uris; + LV2_Log_Log* lv2_log; + Log log; + Configuration conf; + SPtr interface; + SPtr engine; + SPtr serialiser; + SPtr parser; + SPtr store; + LilvWorld* lilv_world; + std::string jack_uuid; }; World::World(int& argc, @@ -228,6 +227,8 @@ World::World(int& argc, LV2_Log_Log* log) : _impl(new Impl(argc, argv, map, unmap, log)) { + _impl->serialiser = SPtr(new Serialiser(*this)); + _impl->parser = SPtr(new Parser()); } World::~World() @@ -235,17 +236,15 @@ World::~World() delete _impl; } -void World::set_engine(SPtr e) { _impl->engine = e; } -void World::set_interface(SPtr i) { _impl->interface = i; } -void World::set_parser(SPtr p) { _impl->parser = p; } -void World::set_serialiser(SPtr s) { _impl->serialiser = s; } -void World::set_store(SPtr s) { _impl->store = s; } - -SPtr World::engine() { return _impl->engine; } -SPtr World::interface() { return _impl->interface; } -SPtr World::parser() { return _impl->parser; } -SPtr World::serialiser() { return _impl->serialiser; } -SPtr World::store() { return _impl->store; } +void World::set_engine(SPtr e) { _impl->engine = e; } +void World::set_interface(SPtr i) { _impl->interface = i; } +void World::set_store(SPtr s) { _impl->store = s; } + +SPtr World::engine() { return _impl->engine; } +SPtr World::interface() { return _impl->interface; } +SPtr World::parser() { return _impl->parser; } +SPtr World::serialiser() { return _impl->serialiser; } +SPtr World::store() { return _impl->store; } int& World::argc() { return _impl->argc; } char**& World::argv() { return _impl->argv; } diff --git a/src/gui/App.cpp b/src/gui/App.cpp index 730243a7..b0f6f28b 100644 --- a/src/gui/App.cpp +++ b/src/gui/App.cpp @@ -188,12 +188,9 @@ App::request_plugins_if_necessary() } } -SPtr +SPtr App::serialiser() { - if (!_world->serialiser()) - _world->load_module("serialisation"); - return _world->serialiser(); } diff --git a/src/gui/App.hpp b/src/gui/App.hpp index f875c7c6..0ce37ebd 100644 --- a/src/gui/App.hpp +++ b/src/gui/App.hpp @@ -37,6 +37,7 @@ namespace Ingen { class Interface; class Log; class Port; +class Serialiser; class World; namespace Client { class ClientStore; @@ -45,9 +46,6 @@ class PluginModel; class PortModel; class SigClientInterface; } -namespace Serialisation { -class Serialiser; -} } namespace Ingen { @@ -116,7 +114,7 @@ public: SPtr store() const { return _store; } SPtr loader() const { return _loader; } - SPtr serialiser(); + SPtr serialiser(); static SPtr create(Ingen::World* world); void run(); diff --git a/src/gui/GraphCanvas.cpp b/src/gui/GraphCanvas.cpp index 12c60638..c3b8b937 100644 --- a/src/gui/GraphCanvas.cpp +++ b/src/gui/GraphCanvas.cpp @@ -29,13 +29,13 @@ #include "ingen/Configuration.hpp" #include "ingen/Interface.hpp" #include "ingen/Log.hpp" +#include "ingen/Serialiser.hpp" #include "ingen/World.hpp" #include "ingen/client/BlockModel.hpp" #include "ingen/client/ClientStore.hpp" #include "ingen/client/GraphModel.hpp" #include "ingen/client/PluginModel.hpp" #include "ingen/ingen.h" -#include "ingen/serialisation/Serialiser.hpp" #include "lv2/lv2plug.in/ns/ext/atom/atom.h" #include "App.hpp" @@ -563,7 +563,7 @@ GraphCanvas::destroy_selection() static void serialise_node(GanvNode* node, void* data) { - Serialisation::Serialiser* serialiser = (Serialisation::Serialiser*)data; + Serialiser* serialiser = (Serialiser*)data; if (!GANV_IS_MODULE(node)) { return; } @@ -584,7 +584,7 @@ serialise_node(GanvNode* node, void* data) static void serialise_arc(GanvEdge* arc, void* data) { - Serialisation::Serialiser* serialiser = (Serialisation::Serialiser*)data; + Serialiser* serialiser = (Serialiser*)data; if (!GANV_IS_EDGE(arc)) { return; } @@ -598,7 +598,7 @@ serialise_arc(GanvEdge* arc, void* data) void GraphCanvas::copy_selection() { - Serialisation::Serialiser serialiser(*_app.world()); + Serialiser serialiser(*_app.world()); serialiser.start_to_string(_graph->path(), _graph->base_uri()); for_each_selected_node(serialise_node, &serialiser); @@ -614,10 +614,10 @@ GraphCanvas::paste() { typedef Node::Properties::const_iterator PropIter; - const Glib::ustring str = Gtk::Clipboard::get()->wait_for_text(); - SPtr parser = _app.loader()->parser(); - const URIs& uris = _app.uris(); - const Raul::Path& parent = _graph->path(); + const Glib::ustring str = Gtk::Clipboard::get()->wait_for_text(); + SPtr parser = _app.loader()->parser(); + const URIs& uris = _app.uris(); + const Raul::Path& parent = _graph->path(); if (!parser) { _app.log().error("Unable to load parser, paste unavailable\n"); return; diff --git a/src/gui/Style.cpp b/src/gui/Style.cpp index 342cb142..699398e4 100644 --- a/src/gui/Style.cpp +++ b/src/gui/Style.cpp @@ -22,9 +22,9 @@ #include "ganv/Port.hpp" #include "ingen/Log.hpp" +#include "ingen/Parser.hpp" #include "ingen/client/PluginModel.hpp" #include "ingen/client/PortModel.hpp" -#include "ingen/serialisation/Parser.hpp" #include "App.hpp" #include "Style.hpp" diff --git a/src/gui/ThreadedLoader.cpp b/src/gui/ThreadedLoader.cpp index 93cccdf1..6e57c383 100644 --- a/src/gui/ThreadedLoader.cpp +++ b/src/gui/ThreadedLoader.cpp @@ -49,15 +49,10 @@ ThreadedLoader::~ThreadedLoader() _thread.join(); } -SPtr +SPtr ThreadedLoader::parser() { - Ingen::World* world = _app.world(); - - if (!world->parser()) - world->load_module("serialisation"); - - return world->parser(); + return _app.world()->parser(); } void @@ -95,7 +90,7 @@ ThreadedLoader::load_graph(bool merge, _events.push_back( sigc::hide_return( sigc::bind(sigc::mem_fun(world->parser().get(), - &Ingen::Serialisation::Parser::parse_file), + &Ingen::Parser::parse_file), _app.world(), _app.world()->interface().get(), document_uri, diff --git a/src/gui/ThreadedLoader.hpp b/src/gui/ThreadedLoader.hpp index 68f6a3f1..c197a605 100644 --- a/src/gui/ThreadedLoader.hpp +++ b/src/gui/ThreadedLoader.hpp @@ -27,8 +27,8 @@ #include #include "ingen/Interface.hpp" -#include "ingen/serialisation/Parser.hpp" -#include "ingen/serialisation/Serialiser.hpp" +#include "ingen/Parser.hpp" +#include "ingen/Serialiser.hpp" #include "raul/Semaphore.hpp" namespace Ingen { @@ -62,7 +62,7 @@ public: void save_graph(SPtr model, const std::string& filename); - SPtr parser(); + SPtr parser(); private: void save_graph_event(SPtr model, diff --git a/src/gui/wscript b/src/gui/wscript index 9ca90ee6..e75b064b 100644 --- a/src/gui/wscript +++ b/src/gui/wscript @@ -31,7 +31,7 @@ def build(bld): name = 'libingen_gui', target = 'ingen_gui', install_path = '${LIBDIR}', - use = 'libingen libingen_client libingen_serialisation') + use = 'libingen libingen_client') autowaf.use_lib(bld, obj, ''' GANV GLADEMM diff --git a/src/ingen/ingen.cpp b/src/ingen/ingen.cpp index e6aea823..3f68369c 100644 --- a/src/ingen/ingen.cpp +++ b/src/ingen/ingen.cpp @@ -31,10 +31,10 @@ #include "ingen/EngineBase.hpp" #include "ingen/Interface.hpp" #include "ingen/Log.hpp" +#include "ingen/Parser.hpp" #include "ingen/World.hpp" #include "ingen/client/ThreadedSigClientInterface.hpp" #include "ingen/runtime_paths.hpp" -#include "ingen/serialisation/Parser.hpp" #include "ingen/types.hpp" #ifdef WITH_BINDINGS #include "bindings/ingen_bindings.hpp" @@ -145,11 +145,6 @@ main(int argc, char** argv) // Load necessary modules before activating engine (and Jack driver) - if (conf.option("load").is_valid() || !conf.files().empty()) { - ingen_try(world->load_module("serialisation"), - "Unable to load serialisation module"); - } - if (conf.option("gui").get()) { ingen_try(world->load_module("gui"), "Unable to load GUI module"); diff --git a/src/serialisation/Parser.cpp b/src/serialisation/Parser.cpp deleted file mode 100644 index 663a7833..00000000 --- a/src/serialisation/Parser.cpp +++ /dev/null @@ -1,655 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include -#include -#include - -#include -#include -#include - -#include "ingen/Atom.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "ingen/serialisation/Parser.hpp" -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "serd/serd.h" -#include "sord/sordmm.hpp" -#include "sratom/sratom.h" - -using namespace std; - -typedef set RDFNodes; - -namespace Ingen { -namespace Serialisation { - -static std::string -relative_uri(const std::string& base, const std::string& uri, bool leading_slash) -{ - std::string ret; - if (uri != base) { - SerdURI base_uri; - serd_uri_parse((const uint8_t*)base.c_str(), &base_uri); - - SerdURI normal_base_uri; - SerdNode normal_base_uri_node = serd_node_new_uri_from_string( - (const uint8_t*)".", &base_uri, &normal_base_uri); - - std::string normal_base_str((const char*)normal_base_uri_node.buf); - - ret = uri; - if (uri.length() >= normal_base_str.length() - && uri.substr(0, normal_base_str.length()) == normal_base_str) { - ret = uri.substr(normal_base_str.length()); - } - - serd_node_free(&normal_base_uri_node); - } - - if (leading_slash && ret[0] != '/') { - ret = std::string("/").append(ret); - } - return ret; -} - -static std::string -get_basename(const std::string& uri) -{ - std::string ret = Glib::path_get_basename(uri); - ret = ret.substr(0, ret.find_last_of('.')); - return ret; -} - -static bool -skip_property(Ingen::URIs& uris, const Sord::Node& predicate) -{ - return (predicate.to_string() == INGEN__file || - predicate.to_string() == uris.ingen_arc || - predicate.to_string() == uris.ingen_block || - predicate.to_string() == uris.lv2_port); -} - -static Resource::Properties -get_properties(Ingen::World* world, - Sord::Model& model, - const Sord::Node& subject) -{ - SerdChunk out = { NULL, 0 }; - LV2_URID_Map* map = &world->uri_map().urid_map_feature()->urid_map; - LV2_URID_Unmap* unmap = &world->uri_map().urid_unmap_feature()->urid_unmap; - Sratom* sratom = sratom_new(map); - - LV2_Atom_Forge forge; - lv2_atom_forge_init(&forge, map); - lv2_atom_forge_set_sink(&forge, sratom_forge_sink, sratom_forge_deref, &out); - - const Sord::Node nil; - Resource::Properties props; - for (Sord::Iter i = model.find(subject, nil, nil); !i.end(); ++i) { - if (!skip_property(world->uris(), i.get_predicate())) { - out.len = 0; - sratom_read(sratom, &forge, world->rdf_world()->c_obj(), - model.c_obj(), i.get_object().c_obj()); - const LV2_Atom* atom = (const LV2_Atom*)out.buf; - Atom atomm; - // FIXME: Don't bloat out all URIs - if (atom->type == forge.URID) { - atomm = world->forge().alloc_uri( - unmap->unmap(unmap->handle, - ((const LV2_Atom_URID*)atom)->body)); - } else { - atomm = world->forge().alloc( - atom->size, atom->type, LV2_ATOM_BODY_CONST(atom)); - } - props.insert(make_pair(Raul::URI(i.get_predicate().to_string()), - atomm)); - } - } - - free((uint8_t*)out.buf); - sratom_free(sratom); - return props; -} - -typedef std::pair PortRecord; - -static boost::optional -get_port(Ingen::World* world, - Sord::Model& model, - const Sord::Node& subject, - const Raul::Path& parent, - uint32_t* index) -{ - const URIs& uris = world->uris(); - - // Get all properties - Resource::Properties props = get_properties(world, model, subject); - - // Get index if requested (for Graphs) - if (index) { - Resource::Properties::const_iterator i = props.find(uris.lv2_index); - if (i == props.end() - || i->second.type() != world->forge().Int - || i->second.get() < 0) { - world->log().error(fmt("Port %1% has no valid index\n") % subject); - return boost::optional(); - } - *index = i->second.get(); - } - - // Get symbol - Resource::Properties::const_iterator s = props.find(uris.lv2_symbol); - std::string sym; - if (s != props.end()) { - sym = s->second.ptr(); - } else { - const std::string subject_str = subject.to_string(); - const size_t last_slash = subject_str.find_last_of("/"); - - sym = ((last_slash == string::npos) - ? subject_str - : subject_str.substr(last_slash + 1)); - } - - if (!Raul::Symbol::is_valid(sym)) { - world->log().error(fmt("Port %1% has invalid symbol `%2%'\n") - % subject % sym); - return boost::optional(); - } - - const Raul::Symbol port_sym(sym); - const Raul::Path port_path(parent.child(port_sym)); - - return make_pair(port_path, props); -} - -static boost::optional -parse( - World* world, - Interface* target, - Sord::Model& model, - const std::string& base_uri, - Sord::Node& subject, - boost::optional parent = boost::optional(), - boost::optional symbol = boost::optional(), - boost::optional data = boost::optional()); - -static boost::optional -parse_graph( - World* world, - Interface* target, - Sord::Model& model, - const std::string& base_uri, - const Sord::Node& subject, - boost::optional parent = boost::optional(), - boost::optional symbol = boost::optional(), - boost::optional data = boost::optional()); - -static boost::optional -parse_block( - World* world, - Interface* target, - Sord::Model& model, - const std::string& base_uri, - const Sord::Node& subject, - const Raul::Path& path, - boost::optional data = boost::optional()); - -static bool -parse_properties( - World* world, - Interface* target, - Sord::Model& model, - const Sord::Node& subject, - const Raul::URI& uri, - boost::optional data = boost::optional()); - -static bool -parse_arcs( - World* world, - Interface* target, - Sord::Model& model, - const std::string& base_uri, - const Sord::Node& subject, - const Raul::Path& graph); - -static boost::optional -parse_block(Ingen::World* world, - Ingen::Interface* target, - Sord::Model& model, - const std::string& base_uri, - const Sord::Node& subject, - const Raul::Path& path, - boost::optional data) -{ - const URIs& uris = world->uris(); - - const Sord::URI ingen_prototype(*world->rdf_world(), uris.ingen_prototype); - const Sord::Node nil; - - Sord::Iter i = model.find(subject, ingen_prototype, nil); - if (i.end() || i.get_object().type() != Sord::Node::URI) { - if (!i.end()) { - std::cerr << "type: " << i.get_object().type() << std::endl; - } - world->log().error( - fmt("Block %1% (%2%) missing mandatory ingen:prototype\n") % - subject.to_string() % path); - return boost::optional(); - } - - const std::string type_uri = relative_uri(base_uri, - i.get_object().to_string(), - false); - - if (!serd_uri_string_has_scheme((const uint8_t*)type_uri.c_str())) { - SerdURI base_uri_parts; - serd_uri_parse((const uint8_t*)base_uri.c_str(), &base_uri_parts); - - SerdURI ignored; - SerdNode sub_uri = serd_node_new_uri_from_string( - i.get_object().to_u_string(), - &base_uri_parts, - &ignored); - - const std::string sub_uri_str = (const char*)sub_uri.buf; - const std::string basename = get_basename(sub_uri_str); - const std::string sub_file = sub_uri_str + '/' + basename + ".ttl"; - - const SerdNode sub_base = serd_node_from_string( - SERD_URI, (const uint8_t*)sub_file.c_str()); - - Sord::Model sub_model(*world->rdf_world(), sub_file); - SerdEnv* env = serd_env_new(&sub_base); - sub_model.load_file(env, SERD_TURTLE, sub_file); - serd_env_free(env); - - Sord::URI sub_node(*world->rdf_world(), sub_file); - parse_graph(world, target, sub_model, (const char*)sub_base.buf, sub_node, - path.parent(), Raul::Symbol(path.symbol())); - - parse_graph(world, target, model, base_uri, subject, - path.parent(), Raul::Symbol(path.symbol())); - } else { - Resource::Properties props = get_properties(world, model, subject); - props.insert(make_pair(uris.rdf_type, - uris.forge.alloc_uri(uris.ingen_Block))); - target->put(Node::path_to_uri(path), props); - } - return path; -} - -static boost::optional -parse_graph(Ingen::World* world, - Ingen::Interface* target, - Sord::Model& model, - const std::string& base_uri, - const Sord::Node& subject_node, - boost::optional parent, - boost::optional a_symbol, - boost::optional data) -{ - const URIs& uris = world->uris(); - - const Sord::URI ingen_block(*world->rdf_world(), uris.ingen_block); - const Sord::URI ingen_polyphony(*world->rdf_world(), uris.ingen_polyphony); - const Sord::URI lv2_port(*world->rdf_world(), LV2_CORE__port); - - const Sord::Node& graph = subject_node; - const Sord::Node nil; - - Raul::Symbol symbol("_"); - if (a_symbol) { - symbol = *a_symbol; - } - - string graph_path_str = relative_uri(base_uri, subject_node.to_string(), true); - if (parent && a_symbol) { - graph_path_str = parent->child(*a_symbol); - } else if (parent) { - graph_path_str = *parent; - } - - if (!Raul::Path::is_valid(graph_path_str)) { - world->log().error(fmt("Graph %1% has invalid path\n") - % graph_path_str); - return boost::optional(); - } - - // Create graph - Raul::Path graph_path(graph_path_str); - Resource::Properties props = get_properties(world, model, subject_node); - target->put(Node::path_to_uri(graph_path), props); - - // For each block in this graph - for (Sord::Iter n = model.find(subject_node, ingen_block, nil); !n.end(); ++n) { - Sord::Node node = n.get_object(); - const Raul::Path block_path = graph_path.child( - Raul::Symbol(get_basename(node.to_string()))); - - // Parse and create block - parse_block(world, target, model, base_uri, node, block_path, - boost::optional()); - - // For each port on this block - for (Sord::Iter p = model.find(node, lv2_port, nil); !p.end(); ++p) { - Sord::Node port = p.get_object(); - - // Get all properties - boost::optional port_record = get_port( - world, model, port, block_path, NULL); - if (!port_record) { - world->log().error(fmt("Invalid port %1%\n") % port); - return boost::optional(); - } - - // Create port and/or set all port properties - target->put(Node::path_to_uri(port_record->first), - port_record->second); - } - } - - // For each port on this graph - typedef std::map PortRecords; - PortRecords ports; - for (Sord::Iter p = model.find(graph, lv2_port, nil); !p.end(); ++p) { - Sord::Node port = p.get_object(); - - // Get all properties - uint32_t index = 0; - boost::optional port_record = get_port( - world, model, port, graph_path, &index); - if (!port_record) { - world->log().error(fmt("Invalid port %1%\n") % port); - return boost::optional(); - } - - // Store port information in ports map - ports[index] = *port_record; - } - - // Create ports in order by index - for (const auto& p : ports) { - target->put(Node::path_to_uri(p.second.first), - p.second.second); - } - - parse_arcs(world, target, model, base_uri, subject_node, graph_path); - - return graph_path; -} - -static bool -parse_arc(Ingen::World* world, - Ingen::Interface* target, - Sord::Model& model, - const std::string& base_uri, - const Sord::Node& subject, - const Raul::Path& graph) -{ - const URIs& uris = world->uris(); - - const Sord::URI ingen_tail(*world->rdf_world(), uris.ingen_tail); - const Sord::URI ingen_head(*world->rdf_world(), uris.ingen_head); - const Sord::Node nil; - - Sord::Iter t = model.find(subject, ingen_tail, nil); - Sord::Iter h = model.find(subject, ingen_head, nil); - - if (t.end()) { - world->log().error("Arc has no tail"); - return false; - } else if (h.end()) { - world->log().error("Arc has no head"); - return false; - } - - const std::string tail_str = relative_uri( - base_uri, t.get_object().to_string(), true); - if (!Raul::Path::is_valid(tail_str)) { - world->log().error("Arc tail has invalid URI"); - return false; - } - - const std::string head_str = relative_uri( - base_uri, h.get_object().to_string(), true); - if (!Raul::Path::is_valid(head_str)) { - world->log().error("Arc head has invalid URI"); - return false; - } - - if (!(++t).end()) { - world->log().error("Arc has multiple tails"); - return false; - } else if (!(++h).end()) { - world->log().error("Arc has multiple heads"); - return false; - } - - target->connect(graph.child(Raul::Path(tail_str)), - graph.child(Raul::Path(head_str))); - - return true; -} - -static bool -parse_arcs(Ingen::World* world, - Ingen::Interface* target, - Sord::Model& model, - const std::string& base_uri, - const Sord::Node& subject, - const Raul::Path& graph) -{ - const Sord::URI ingen_arc(*world->rdf_world(), world->uris().ingen_arc); - const Sord::Node nil; - - for (Sord::Iter i = model.find(subject, ingen_arc, nil); !i.end(); ++i) { - parse_arc(world, target, model, base_uri, i.get_object(), graph); - } - - return true; -} - -static bool -parse_properties(Ingen::World* world, - Ingen::Interface* target, - Sord::Model& model, - const Sord::Node& subject, - const Raul::URI& uri, - boost::optional data) -{ - Resource::Properties properties = get_properties(world, model, subject); - - target->put(uri, properties); - - // Set passed properties last to override any loaded values - if (data) - target->put(uri, data.get()); - - return true; -} - -static boost::optional -parse(Ingen::World* world, - Ingen::Interface* target, - Sord::Model& model, - const std::string& base_uri, - Sord::Node& subject, - boost::optional parent, - boost::optional symbol, - boost::optional data) -{ - const URIs& uris = world->uris(); - - const Sord::URI graph_class (*world->rdf_world(), uris.ingen_Graph); - const Sord::URI block_class (*world->rdf_world(), uris.ingen_Block); - const Sord::URI arc_class (*world->rdf_world(), uris.ingen_Arc); - const Sord::URI internal_class(*world->rdf_world(), uris.ingen_Internal); - const Sord::URI in_port_class (*world->rdf_world(), LV2_CORE__InputPort); - const Sord::URI out_port_class(*world->rdf_world(), LV2_CORE__OutputPort); - const Sord::URI lv2_class (*world->rdf_world(), LV2_CORE__Plugin); - const Sord::URI rdf_type (*world->rdf_world(), uris.rdf_type); - const Sord::Node nil; - - // Parse explicit subject graph - if (subject.is_valid()) { - return parse_graph(world, target, model, base_uri, subject, parent, symbol, data); - } - - // Get all subjects and their types (?subject a ?type) - typedef std::map< Sord::Node, std::set > Subjects; - Subjects subjects; - for (Sord::Iter i = model.find(subject, rdf_type, nil); !i.end(); ++i) { - const Sord::Node& subject = i.get_subject(); - const Sord::Node& rdf_class = i.get_object(); - - assert(rdf_class.is_uri()); - Subjects::iterator s = subjects.find(subject); - if (s == subjects.end()) { - std::set types; - types.insert(rdf_class); - subjects.insert(make_pair(subject, types)); - } else { - s->second.insert(rdf_class); - } - } - - // Parse and create each subject - for (const auto& i : subjects) { - const Sord::Node& s = i.first; - const std::set& types = i.second; - boost::optional ret; - const Raul::Path rel_path(relative_uri(base_uri, s.to_string(), true)); - const Raul::Path path = parent ? parent->child(rel_path) : rel_path; - if (types.find(graph_class) != types.end()) { - ret = parse_graph(world, target, model, base_uri, s, parent, symbol, data); - } else if (types.find(block_class) != types.end()) { - ret = parse_block(world, target, model, base_uri, s, path, data); - } else if (types.find(in_port_class) != types.end() || - types.find(out_port_class) != types.end()) { - parse_properties( - world, target, model, s, Node::path_to_uri(path), data); - ret = path; - } else if (types.find(arc_class) != types.end()) { - Raul::Path parent_path(parent ? parent.get() : Raul::Path("/")); - parse_arc(world, target, model, base_uri, s, parent_path); - } else { - world->log().error("Subject has no known types\n"); - } - } - - return boost::optional(); -} - -/** Parse a graph from RDF into a Interface (engine or client). - * @return whether or not load was successful. - */ -bool -Parser::parse_file(Ingen::World* world, - Ingen::Interface* target, - const std::string& path, - boost::optional parent, - boost::optional symbol, - boost::optional data) -{ - std::string file_path = path; - if (!Glib::path_is_absolute(file_path)) { - file_path = Glib::build_filename(Glib::get_current_dir(), file_path); - } - if (Glib::file_test(file_path, Glib::FILE_TEST_IS_DIR)) { - // This is a bundle, append "/name.ttl" to get graph file path - file_path = Glib::build_filename(path, get_basename(path) + ".ttl"); - } - - std::string uri; - try { - uri = Glib::filename_to_uri(file_path, ""); - } catch (const Glib::ConvertError& e) { - world->log().error(fmt("Path to URI conversion error: %1%\n") - % e.what()); - return false; - } - - const uint8_t* uri_c_str = (const uint8_t*)uri.c_str(); - SerdNode base_node = serd_node_from_string(SERD_URI, uri_c_str); - SerdEnv* env = serd_env_new(&base_node); - - // Load graph file into model - Sord::Model model(*world->rdf_world(), uri, SORD_SPO|SORD_PSO, false); - model.load_file(env, SERD_TURTLE, uri); - - serd_env_free(env); - - world->log().info(fmt("Parsing %1%\n") % file_path); - if (parent) - world->log().info(fmt("Parent: %1%\n") % parent->c_str()); - if (symbol) - world->log().info(fmt("Symbol: %1%\n") % symbol->c_str()); - - Sord::Node subject(*world->rdf_world(), Sord::Node::URI, uri); - boost::optional parsed_path - = parse(world, target, model, model.base_uri().to_string(), - subject, parent, symbol, data); - - if (parsed_path) { - target->set_property(Node::path_to_uri(*parsed_path), - Raul::URI(INGEN__file), - world->forge().alloc_uri(uri)); - return true; - } else { - world->log().warn("Document URI lost\n"); - return false; - } -} - -boost::optional -Parser::parse_string(Ingen::World* world, - Ingen::Interface* target, - const std::string& str, - const std::string& base_uri, - boost::optional parent, - boost::optional symbol, - boost::optional data) -{ - // Load string into model - Sord::Model model(*world->rdf_world(), base_uri, SORD_SPO|SORD_PSO, false); - - SerdEnv* env = serd_env_new(NULL); - if (!base_uri.empty()) { - const SerdNode base = serd_node_from_string( - SERD_URI, (const uint8_t*)base_uri.c_str()); - serd_env_set_base_uri(env, &base); - } - model.load_string(env, SERD_TURTLE, str.c_str(), str.length(), base_uri); - - Raul::URI actual_base((const char*)serd_env_get_base_uri(env, NULL)->buf); - serd_env_free(env); - - world->log().info(fmt("Parsing string (base %1%)\n") % base_uri); - - Sord::Node subject; - parse(world, target, model, actual_base, subject, parent, symbol, data); - return actual_base; -} - -} // namespace Serialisation -} // namespace Ingen diff --git a/src/serialisation/Serialiser.cpp b/src/serialisation/Serialiser.cpp deleted file mode 100644 index 775736ae..00000000 --- a/src/serialisation/Serialiser.cpp +++ /dev/null @@ -1,547 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "ingen/Arc.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/Node.hpp" -#include "ingen/Plugin.hpp" -#include "ingen/Resource.hpp" -#include "ingen/Store.hpp" -#include "ingen/URIMap.hpp" -#include "ingen/URIs.hpp" -#include "ingen/World.hpp" -#include "ingen/serialisation/Serialiser.hpp" -#include "lv2/lv2plug.in/ns/ext/state/state.h" -#include "lv2/lv2plug.in/ns/extensions/ui/ui.h" -#include "raul/Path.hpp" -#include "sord/sordmm.hpp" -#include "sratom/sratom.h" - -using namespace std; -using namespace Sord; -using namespace Ingen; - -namespace Ingen { -namespace Serialisation { - -struct Serialiser::Impl { - typedef Resource::Properties Properties; - - explicit Impl(World& world) - : _root_path("/") - , _world(world) - , _model(NULL) - , _sratom(sratom_new(&_world.uri_map().urid_map_feature()->urid_map)) - {} - - ~Impl() { - sratom_free(_sratom); - } - - enum class Mode { TO_FILE, TO_STRING }; - - void start_to_filename(const std::string& filename); - - void serialise_graph(SPtr p, - const Sord::Node& id); - - void serialise_block(SPtr n, - const Sord::Node& class_id, - const Sord::Node& id); - - void serialise_port(const Node* p, - Resource::Graph context, - const Sord::Node& id); - - void serialise_properties(Sord::Node id, - const Resource::Properties& props); - - void write_bundle(SPtr graph, - const std::string& uri); - - Sord::Node path_rdf_node(const Raul::Path& path); - - void write_manifest(const std::string& bundle_path, - SPtr graph, - const std::string& graph_symbol); - - void serialise_arc(const Sord::Node& parent, - SPtr a) - throw (std::logic_error); - - std::string finish(); - - Raul::Path _root_path; - Mode _mode; - std::string _base_uri; - World& _world; - Sord::Model* _model; - Sratom* _sratom; -}; - -Serialiser::Serialiser(World& world) - : me(new Impl(world)) -{} - -Serialiser::~Serialiser() -{ - delete me; -} - -void -Serialiser::Impl::write_manifest(const std::string& bundle_path, - SPtr graph, - const std::string& graph_symbol) -{ - const string manifest_path(Glib::build_filename(bundle_path, "manifest.ttl")); - const string binary_path(Glib::Module::build_path("", "ingen_lv2")); - - start_to_filename(manifest_path); - - Sord::World& world = _model->world(); - const URIs& uris = _world.uris(); - - const string filename(graph_symbol + ".ttl"); - const Sord::URI subject(world, filename, _base_uri); - - _model->add_statement(subject, - Sord::URI(world, uris.rdf_type), - Sord::URI(world, uris.ingen_Graph)); - _model->add_statement(subject, - Sord::URI(world, uris.rdf_type), - Sord::URI(world, uris.lv2_Plugin)); - _model->add_statement(subject, - Sord::URI(world, uris.rdfs_seeAlso), - Sord::URI(world, filename, _base_uri)); - _model->add_statement(subject, - Sord::URI(world, uris.lv2_prototype), - Sord::URI(world, uris.ingen_GraphPrototype)); - - finish(); -} - -void -Serialiser::write_bundle(SPtr graph, - const std::string& path) -{ - me->write_bundle(graph, path); -} - -void -Serialiser::Impl::write_bundle(SPtr graph, - const std::string& a_path) -{ - std::string path = Glib::filename_from_uri(a_path); - if (Glib::file_test(path, Glib::FILE_TEST_EXISTS) - && !Glib::file_test(path, Glib::FILE_TEST_IS_DIR)) { - path = Glib::path_get_dirname(path); - } - - _world.log().info(fmt("Writing bundle %1%\n") % path); - - if (path[path.length() - 1] != '/') - path.append("/"); - - g_mkdir_with_parents(path.c_str(), 0744); - - string symbol = Glib::path_get_basename(path); - symbol = symbol.substr(0, symbol.find(".")); - - const string root_file = Glib::build_filename(path, symbol + ".ttl"); - - start_to_filename(root_file); - const Raul::Path old_root_path = _root_path; - _root_path = graph->path(); - serialise_graph(graph, Sord::URI(_model->world(), root_file, _base_uri)); - _root_path = old_root_path; - finish(); - - write_manifest(path, graph, symbol); -} - -/** Begin a serialization to a file. - * - * This must be called before any serializing methods. - */ -void -Serialiser::Impl::start_to_filename(const string& filename) -{ - assert(filename.find(":") == string::npos || filename.substr(0, 5) == "file:"); - if (filename.find(":") == string::npos) { - _base_uri = "file://" + filename; - } else { - _base_uri = filename; - } - - _model = new Sord::Model(*_world.rdf_world(), _base_uri); - _mode = Mode::TO_FILE; -} - -void -Serialiser::start_to_string(const Raul::Path& root, const string& base_uri) -{ - me->_root_path = root; - me->_base_uri = base_uri; - me->_model = new Sord::Model(*me->_world.rdf_world(), base_uri); - me->_mode = Impl::Mode::TO_STRING; -} - -void -Serialiser::start_to_file(const Raul::Path& root, const string& filename) -{ - me->_root_path = root; - me->start_to_filename(filename); -} - -std::string -Serialiser::finish() -{ - return me->finish(); -} - -std::string -Serialiser::Impl::finish() -{ - string ret = ""; - if (_mode == Mode::TO_FILE) { - SerdStatus st = _model->write_to_file(_base_uri, SERD_TURTLE); - if (st) { - _world.log().error(fmt("Error writing file %1% (%2%)\n") - % _base_uri % serd_strerror(st)); - } - } else { - ret = _model->write_to_string(_base_uri, SERD_TURTLE); - } - - delete _model; - _model = NULL; - _base_uri = ""; - - return ret; -} - -Sord::Node -Serialiser::Impl::path_rdf_node(const Raul::Path& path) -{ - assert(_model); - assert(path == _root_path || path.is_child_of(_root_path)); - return Sord::URI(_model->world(), - path.substr(_root_path.base().length()), - _base_uri); -} - -void -Serialiser::serialise(SPtr object) throw (std::logic_error) -{ - if (!me->_model) - throw std::logic_error("serialise called without serialisation in progress"); - - if (object->graph_type() == Node::GraphType::GRAPH) { - me->serialise_graph(object, me->path_rdf_node(object->path())); - } else if (object->graph_type() == Node::GraphType::BLOCK) { - const Sord::URI plugin_id(me->_model->world(), object->plugin()->uri()); - me->serialise_block(object, plugin_id, me->path_rdf_node(object->path())); - } else if (object->graph_type() == Node::GraphType::PORT) { - me->serialise_port(object.get(), - Resource::Graph::DEFAULT, - me->path_rdf_node(object->path())); - } else { - me->serialise_properties(me->path_rdf_node(object->path()), - object->properties()); - } -} - -void -Serialiser::Impl::serialise_graph(SPtr graph, - const Sord::Node& graph_id) -{ - Sord::World& world = _model->world(); - const URIs& uris = _world.uris(); - - _model->add_statement(graph_id, - Sord::URI(world, uris.rdf_type), - Sord::URI(world, uris.ingen_Graph)); - - _model->add_statement(graph_id, - Sord::URI(world, uris.rdf_type), - Sord::URI(world, uris.lv2_Plugin)); - - _model->add_statement(graph_id, - Sord::URI(world, uris.lv2_extensionData), - Sord::URI(world, LV2_STATE__interface)); - - _model->add_statement(graph_id, - Sord::URI(world, LV2_UI__ui), - Sord::URI(world, "http://drobilla.net/ns/ingen#GraphUIGtk2")); - - // Always write a symbol (required by Ingen) - Raul::Symbol symbol("_"); - Node::Properties::const_iterator s = graph->properties().find(uris.lv2_symbol); - if (s == graph->properties().end() - || s->second.type() != _world.forge().String - || !Raul::Symbol::is_valid(s->second.ptr())) { - const std::string base = Glib::path_get_basename( - _model->base_uri().to_c_string()); - symbol = Raul::Symbol::symbolify(base.substr(0, base.find('.'))); - _model->add_statement( - graph_id, - Sord::URI(world, uris.lv2_symbol), - Sord::Literal(world, symbol.c_str())); - } else { - symbol = Raul::Symbol::symbolify(s->second.ptr()); - } - - // If the graph has no doap:name (required by LV2), use the symbol - if (graph->properties().find(uris.doap_name) == graph->properties().end()) - _model->add_statement(graph_id, - Sord::URI(world, uris.doap_name), - Sord::Literal(world, symbol.c_str())); - - const Node::Properties props = graph->properties(Resource::Graph::INTERNAL); - serialise_properties(graph_id, props); - - const Store::const_range kids = _world.store()->children_range(graph); - for (Store::const_iterator n = kids.first; n != kids.second; ++n) { - if (n->first.parent() != graph->path()) - continue; - - if (n->second->graph_type() == Node::GraphType::GRAPH) { - SPtr subgraph = n->second; - - SerdURI base_uri; - serd_uri_parse((const uint8_t*)_base_uri.c_str(), &base_uri); - - const string sub_bundle_path = subgraph->path().substr(1) + ".ingen"; - - SerdURI subgraph_uri; - SerdNode subgraph_node = serd_node_new_uri_from_string( - (const uint8_t*)sub_bundle_path.c_str(), - &base_uri, - &subgraph_uri); - - const Sord::URI subgraph_id(world, (const char*)subgraph_node.buf); - - // Save our state - std::string my_base_uri = _base_uri; - Sord::Model* my_model = _model; - - // Write child bundle within this bundle - write_bundle(subgraph, subgraph_id.to_string()); - - // Restore our state - _base_uri = my_base_uri; - _model = my_model; - - // Serialise reference to graph block - const Sord::Node block_id(path_rdf_node(subgraph->path())); - _model->add_statement(graph_id, - Sord::URI(world, uris.ingen_block), - block_id); - serialise_block(subgraph, subgraph_id, block_id); - } else if (n->second->graph_type() == Node::GraphType::BLOCK) { - SPtr block = n->second; - - const Sord::URI class_id(world, block->plugin()->uri()); - const Sord::Node block_id(path_rdf_node(n->second->path())); - _model->add_statement(graph_id, - Sord::URI(world, uris.ingen_block), - block_id); - serialise_block(block, class_id, block_id); - } - } - - for (uint32_t i = 0; i < graph->num_ports(); ++i) { - Node* p = graph->port(i); - const Sord::Node port_id = path_rdf_node(p->path()); - - // Ensure lv2:name always exists so Graph is a valid LV2 plugin - if (p->properties().find(uris.lv2_name) == p->properties().end()) - p->set_property(uris.lv2_name, - _world.forge().alloc(p->symbol().c_str())); - - _model->add_statement(graph_id, - Sord::URI(world, LV2_CORE__port), - port_id); - serialise_port(p, Resource::Graph::INTERNAL, port_id); - } - - for (const auto& a : graph->arcs()) { - serialise_arc(graph_id, a.second); - } -} - -void -Serialiser::Impl::serialise_block(SPtr block, - const Sord::Node& class_id, - const Sord::Node& block_id) -{ - const URIs& uris = _world.uris(); - - _model->add_statement(block_id, - Sord::URI(_model->world(), uris.rdf_type), - Sord::URI(_model->world(), uris.ingen_Block)); - _model->add_statement(block_id, - Sord::URI(_model->world(), uris.ingen_prototype), - class_id); - - const Node::Properties props = block->properties(Resource::Graph::EXTERNAL); - serialise_properties(block_id, props); - - for (uint32_t i = 0; i < block->num_ports(); ++i) { - Node* const p = block->port(i); - const Sord::Node port_id = path_rdf_node(p->path()); - serialise_port(p, Resource::Graph::EXTERNAL, port_id); - _model->add_statement(block_id, - Sord::URI(_model->world(), uris.lv2_port), - port_id); - } -} - -void -Serialiser::Impl::serialise_port(const Node* port, - Resource::Graph context, - const Sord::Node& port_id) -{ - URIs& uris = _world.uris(); - Sord::World& world = _model->world(); - Node::Properties props = port->properties(context); - - if (context == Resource::Graph::INTERNAL) { - // Always write lv2:symbol for Graph ports (required for lv2:Plugin) - _model->add_statement(port_id, - Sord::URI(world, uris.lv2_symbol), - Sord::Literal(world, port->path().symbol())); - } else { - // Never write lv2:index for plugin instances (not persistent/stable) - props.erase(uris.lv2_index); - } - - if (context == Resource::Graph::INTERNAL && - port->has_property(uris.rdf_type, uris.lv2_ControlPort) && - port->has_property(uris.rdf_type, uris.lv2_InputPort)) - { - const Atom& val = port->get_property(uris.ingen_value); - if (val.is_valid()) { - props.insert(make_pair(uris.lv2_default, val)); - } else { - _world.log().warn("Control input has no value, lv2:default omitted.\n"); - } - } else if (context != Resource::Graph::INTERNAL && - !port->has_property(uris.rdf_type, uris.lv2_InputPort)) { - props.erase(uris.ingen_value); - } - - serialise_properties(port_id, props); -} - -void -Serialiser::serialise_arc(const Sord::Node& parent, - SPtr arc) - throw (std::logic_error) -{ - return me->serialise_arc(parent, arc); -} - -void -Serialiser::Impl::serialise_arc(const Sord::Node& parent, - SPtr arc) - throw (std::logic_error) -{ - if (!_model) - throw std::logic_error( - "serialise_arc called without serialisation in progress"); - - Sord::World& world = _model->world(); - const URIs& uris = _world.uris(); - - const Sord::Node src = path_rdf_node(arc->tail_path()); - const Sord::Node dst = path_rdf_node(arc->head_path()); - const Sord::Node arc_id = Sord::Node::blank_id(*_world.rdf_world()); - _model->add_statement(arc_id, - Sord::URI(world, uris.ingen_tail), - src); - _model->add_statement(arc_id, - Sord::URI(world, uris.ingen_head), - dst); - - if (parent.is_valid()) { - _model->add_statement(parent, - Sord::URI(world, uris.ingen_arc), - arc_id); - } else { - _model->add_statement(arc_id, - Sord::URI(world, uris.rdf_type), - Sord::URI(world, uris.ingen_Arc)); - } -} - -static bool -skip_property(Ingen::URIs& uris, const Sord::Node& predicate) -{ - return (predicate.to_string() == INGEN__file || - predicate.to_string() == uris.ingen_arc || - predicate.to_string() == uris.ingen_block || - predicate.to_string() == uris.lv2_port); -} - -void -Serialiser::Impl::serialise_properties(Sord::Node id, - const Node::Properties& props) -{ - LV2_URID_Unmap* unmap = &_world.uri_map().urid_unmap_feature()->urid_unmap; - SerdNode base = serd_node_from_string(SERD_URI, - (const uint8_t*)_base_uri.c_str()); - SerdEnv* env = serd_env_new(&base); - SordInserter* inserter = sord_inserter_new(_model->c_obj(), env); - - sratom_set_sink(_sratom, _base_uri.c_str(), - (SerdStatementSink)sord_inserter_write_statement, NULL, - inserter); - - sratom_set_pretty_numbers(_sratom, true); - - for (const auto& p : props) { - const Sord::URI key(_model->world(), p.first); - if (!skip_property(_world.uris(), key)) { - sratom_write(_sratom, unmap, 0, - sord_node_to_serd_node(id.c_obj()), - sord_node_to_serd_node(key.c_obj()), - p.second.type(), p.second.size(), p.second.get_body()); - } - } - - sord_inserter_free(inserter); - serd_env_free(env); -} - -} // namespace Serialisation -} // namespace Ingen diff --git a/src/serialisation/serialisation.cpp b/src/serialisation/serialisation.cpp deleted file mode 100644 index b335845e..00000000 --- a/src/serialisation/serialisation.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2012 David Robillard - - Ingen is free software: you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free - Software Foundation, either version 3 of the License, or any later version. - - Ingen is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. - - You should have received a copy of the GNU Affero General Public License - along with Ingen. If not, see . -*/ - -#include "ingen/Module.hpp" -#include "ingen/World.hpp" - -#include "ingen/serialisation/Parser.hpp" -#include "ingen/serialisation/Serialiser.hpp" - -using namespace Ingen; - -struct IngenSerialisationModule : public Ingen::Module { - virtual void load(Ingen::World* world) { - world->set_parser( - SPtr( - new Serialisation::Parser())); - world->set_serialiser( - SPtr( - new Serialisation::Serialiser(*world))); - } -}; - -extern "C" { - -Ingen::Module* -ingen_module_load() { - return new IngenSerialisationModule(); -} - -} // extern "C" diff --git a/src/serialisation/wscript b/src/serialisation/wscript deleted file mode 100644 index 82aeffd4..00000000 --- a/src/serialisation/wscript +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python -from waflib.extras import autowaf as autowaf - -def build(bld): - obj = bld(features = 'c cshlib cxx cxxshlib', - source = ['Parser.cpp', - 'Serialiser.cpp', - 'serialisation.cpp'], - export_includes = ['../..'], - includes = ['.', '../..'], - name = 'libingen_serialisation', - target = 'ingen_serialisation', - install_path = '${LIBDIR}', - use = 'libingen') - autowaf.use_lib(bld, obj, 'GLIBMM LV2 LILV RAUL SERD SORD SRATOM') - - if bld.env.BUILD_TESTS: - obj = bld(features = 'c cshlib cxx cxxshlib', - source = ['Parser.cpp', - 'Serialiser.cpp', - 'serialisation.cpp'], - export_includes = ['../..'], - includes = ['.', '../..'], - name = 'libingen_serialisation_profiled', - target = 'ingen_serialisation_profiled', - install_path = '', - use = 'libingen_profiled', - lib = bld.env.INGEN_TEST_LIBS, - cxxflags = bld.env.INGEN_TEST_CXXFLAGS) - autowaf.use_lib(bld, obj, 'GLIBMM LV2 LILV RAUL SERD SORD SRATOM') diff --git a/src/server/JackDriver.cpp b/src/server/JackDriver.cpp index 3452c163..efe19169 100644 --- a/src/server/JackDriver.cpp +++ b/src/server/JackDriver.cpp @@ -23,7 +23,7 @@ #ifdef INGEN_JACK_SESSION #include #include -#include "ingen/serialisation/Serialiser.hpp" +#include "ingen/Serialiser.hpp" #endif #ifdef HAVE_JACK_METADATA #include @@ -525,7 +525,7 @@ JackDriver::_session_cb(jack_session_event_t* event) % jack_get_client_name(_client) % event->client_uuid).str(); - SPtr serialiser = _engine.world()->serialiser(); + SPtr serialiser = _engine.world()->serialiser(); if (serialiser) { SPtr root(_engine.root_graph(), NullDeleter); serialiser->write_bundle(root, string("file://") + event->session_dir); diff --git a/src/server/ingen_lv2.cpp b/src/server/ingen_lv2.cpp index cf81fd73..596e24e6 100644 --- a/src/server/ingen_lv2.cpp +++ b/src/server/ingen_lv2.cpp @@ -34,12 +34,12 @@ #include "ingen/Configuration.hpp" #include "ingen/Interface.hpp" #include "ingen/Log.hpp" +#include "ingen/Parser.hpp" +#include "ingen/Serialiser.hpp" #include "ingen/Store.hpp" #include "ingen/World.hpp" #include "ingen/ingen.h" #include "ingen/runtime_paths.hpp" -#include "ingen/serialisation/Parser.hpp" -#include "ingen/serialisation/Serialiser.hpp" #include "ingen/types.hpp" #include "raul/Semaphore.hpp" @@ -539,10 +539,6 @@ ingen_instantiate(const LV2_Descriptor* descriptor, plugin->map = map; plugin->world = new Ingen::World( plugin->argc, plugin->argv, map, unmap, log); - if (!plugin->world->load_module("serialisation")) { - delete plugin->world; - return NULL; - } LV2_URID bufsz_max = map->map(map->handle, LV2_BUF_SIZE__maxBlockLength); LV2_URID bufsz_seq = map->map(map->handle, LV2_BUF_SIZE__sequenceSize); diff --git a/src/wscript b/src/wscript index fbca8fe9..02ad63c3 100644 --- a/src/wscript +++ b/src/wscript @@ -10,7 +10,9 @@ def build(bld): 'Forge.cpp', 'LV2Features.cpp', 'Log.cpp', + 'Parser.cpp', 'Resource.cpp', + 'Serialiser.cpp', 'Store.cpp', 'URIMap.cpp', 'URIs.cpp', diff --git a/tests/ingen_test.cpp b/tests/ingen_test.cpp index f29fc964..a9c561a0 100644 --- a/tests/ingen_test.cpp +++ b/tests/ingen_test.cpp @@ -41,11 +41,11 @@ #include "ingen/Configuration.hpp" #include "ingen/EngineBase.hpp" #include "ingen/Interface.hpp" +#include "ingen/Parser.hpp" #include "ingen/URIMap.hpp" #include "ingen/World.hpp" #include "ingen/client/ThreadedSigClientInterface.hpp" #include "ingen/runtime_paths.hpp" -#include "ingen/serialisation/Parser.hpp" #include "ingen/types.hpp" #ifdef WITH_BINDINGS #include "bindings/ingen_bindings.hpp" @@ -157,9 +157,6 @@ main(int argc, char** argv) ingen_try(world->load_module("server_profiled"), "Unable to load server module"); - ingen_try(world->load_module("serialisation_profiled"), - "Unable to load serialisation module"); - // Initialise engine ingen_try(bool(world->engine()), "Unable to create engine"); diff --git a/wscript b/wscript index 4164744c..39894088 100644 --- a/wscript +++ b/wscript @@ -173,7 +173,7 @@ def build(bld): opts.moduledir = opts.moduledir or bld.env.PREFIX + 'lib/ingen' # Headers - for i in ['', 'client', 'serialisation']: + for i in ['', 'client']: bld.install_files('${INCLUDEDIR}/ingen/%s' % i, bld.path.ant_glob('ingen/%s/*' % i)) @@ -183,7 +183,6 @@ def build(bld): # Modules bld.recurse('src') - bld.recurse('src/serialisation') bld.recurse('src/server') if bld.env.INGEN_BUILD_CLIENT: @@ -263,8 +262,7 @@ def test(ctx): os.environ['PATH'] = 'tests' + os.pathsep + os.getenv('PATH') os.environ['LD_LIBRARY_PATH'] = os.path.join('src') os.environ['INGEN_MODULE_PATH'] = os.pathsep.join([ - os.path.join('src', 'server') , - os.path.join('src', 'serialisation')]) + os.path.join('src', 'server')]) autowaf.pre_test(ctx, APPNAME, dirs=['.', 'src', 'tests']) for i in ctx.path.ant_glob('tests/*.ttl'): -- cgit v1.2.1