From 254b434f0a79fea54bd963e8ff2e845a5b0cd3a6 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 19 Mar 2012 20:16:46 +0000 Subject: Partially functioning communication between Ingen LV2 plugin and UI. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4078 a436a847-0d15-0410-975c-d299462d15a1 --- ingen.lv2/manifest.ttl | 16 +- ingen/serialisation/Parser.hpp | 3 +- ingen/serialisation/Serialiser.hpp | 3 +- ingen/shared/AtomReader.hpp | 55 +++ ingen/shared/Configuration.hpp | 2 +- ingen/shared/Forge.hpp | 36 ++ ingen/shared/LV2Atom.hpp | 45 --- ingen/shared/LV2URIMap.hpp | 26 -- ingen/shared/ResourceImpl.hpp | 2 - ingen/shared/URIs.hpp | 19 +- ingen/shared/World.hpp | 5 +- src/bindings/test_ingen.py | 2 +- src/client/ClientStore.cpp | 15 +- src/client/NodeModel.cpp | 4 +- src/client/ObjectModel.cpp | 2 +- src/client/PluginModel.cpp | 9 +- src/client/PluginUI.cpp | 40 +- src/client/PortModel.cpp | 8 +- src/gui/App.cpp | 4 +- src/gui/App.hpp | 5 +- src/gui/Configuration.cpp | 2 +- src/gui/Controls.cpp | 23 +- src/gui/LoadPluginWindow.cpp | 8 +- src/gui/NodeModule.cpp | 31 +- src/gui/ObjectMenu.cpp | 2 +- src/gui/PatchBox.cpp | 10 +- src/gui/PatchCanvas.cpp | 43 ++- src/gui/PatchPortModule.cpp | 12 +- src/gui/PatchTreeWindow.cpp | 2 +- src/gui/PatchView.cpp | 11 +- src/gui/PatchWindow.cpp | 1 + src/gui/Port.cpp | 8 +- src/gui/PortMenu.cpp | 2 +- src/gui/PortPropertiesWindow.cpp | 2 +- src/gui/PropertiesWindow.cpp | 72 ++-- src/gui/PropertiesWindow.hpp | 6 +- src/gui/RenameWindow.cpp | 2 +- src/gui/WindowFactory.cpp | 8 +- src/gui/ingen_gui_lv2.cpp | 18 +- src/ingen/main.cpp | 9 +- src/serialisation/Parser.cpp | 87 +++-- src/serialisation/Serialiser.cpp | 92 ++--- src/serialisation/sratom/sratom.c | 731 ++++++++++++++++++++++++++++++++++++ src/serialisation/sratom/sratom.h | 176 +++++++++ src/serialisation/wscript | 9 +- src/server/AudioBuffer.cpp | 37 +- src/server/AudioBuffer.hpp | 15 +- src/server/Buffer.cpp | 164 ++++++++ src/server/Buffer.hpp | 46 ++- src/server/BufferFactory.cpp | 77 ++-- src/server/BufferFactory.hpp | 35 +- src/server/ConnectionImpl.cpp | 56 ++- src/server/ControlBindings.cpp | 110 ++---- src/server/ControlBindings.hpp | 9 +- src/server/DuplexPort.cpp | 9 +- src/server/DuplexPort.hpp | 1 + src/server/Engine.cpp | 17 +- src/server/EventBuffer.cpp | 217 ----------- src/server/EventBuffer.hpp | 86 ----- src/server/InputPort.cpp | 10 +- src/server/InputPort.hpp | 1 + src/server/JackDriver.cpp | 64 ++-- src/server/LV2Info.cpp | 2 - src/server/LV2Info.hpp | 1 - src/server/LV2Node.cpp | 64 ++-- src/server/NodeImpl.cpp | 4 +- src/server/NodeImpl.hpp | 4 +- src/server/Notification.cpp | 2 +- src/server/ObjectBuffer.cpp | 151 -------- src/server/ObjectBuffer.hpp | 56 --- src/server/OutputPort.cpp | 3 +- src/server/OutputPort.hpp | 1 + src/server/PatchImpl.cpp | 9 +- src/server/PatchImpl.hpp | 7 +- src/server/PortImpl.cpp | 74 ++-- src/server/PortImpl.hpp | 5 +- src/server/PortType.hpp | 9 +- src/server/ServerInterfaceImpl.cpp | 2 +- src/server/ServerInterfaceImpl.hpp | 2 + src/server/events/CreateNode.cpp | 2 +- src/server/events/CreatePort.cpp | 40 +- src/server/events/CreatePort.hpp | 9 +- src/server/events/SetMetadata.cpp | 14 +- src/server/events/SetPortValue.cpp | 45 +-- src/server/ingen_jack.cpp | 7 +- src/server/ingen_lv2.cpp | 129 ++++++- src/server/internals/Controller.cpp | 52 ++- src/server/internals/Controller.hpp | 3 +- src/server/internals/Delay.cpp | 13 +- src/server/internals/Note.cpp | 75 ++-- src/server/internals/Trigger.cpp | 60 ++- src/server/mix.hpp | 40 +- src/server/wscript | 3 +- src/shared/AtomReader.cpp | 83 ++++ src/shared/AtomWriter.cpp | 18 +- src/shared/Builder.cpp | 6 +- src/shared/Configuration.cpp | 34 +- src/shared/Forge.cpp | 53 +++ src/shared/LV2Atom.cpp | 96 ----- src/shared/LV2URIMap.cpp | 88 +---- src/shared/ResourceImpl.cpp | 15 +- src/shared/URIs.cpp | 150 ++++---- src/shared/World.cpp | 7 +- src/shared/wscript | 3 +- wscript | 4 - 105 files changed, 2312 insertions(+), 1755 deletions(-) create mode 100644 ingen/shared/AtomReader.hpp create mode 100644 ingen/shared/Forge.hpp delete mode 100644 ingen/shared/LV2Atom.hpp create mode 100644 src/serialisation/sratom/sratom.c create mode 100644 src/serialisation/sratom/sratom.h create mode 100644 src/server/Buffer.cpp delete mode 100644 src/server/EventBuffer.cpp delete mode 100644 src/server/EventBuffer.hpp delete mode 100644 src/server/ObjectBuffer.cpp delete mode 100644 src/server/ObjectBuffer.hpp create mode 100644 src/shared/AtomReader.cpp create mode 100644 src/shared/Forge.cpp delete mode 100644 src/shared/LV2Atom.cpp diff --git a/ingen.lv2/manifest.ttl b/ingen.lv2/manifest.ttl index da4adeac..9b188e90 100644 --- a/ingen.lv2/manifest.ttl +++ b/ingen.lv2/manifest.ttl @@ -4,36 +4,40 @@ @prefix ui: . @prefix urid: . - +ingen:ui a ui:GtkUI ; ui:binary ; lv2:requiredFeature urid:map , - urid:unmap . + urid:unmap ; + ui:portNotification [ + lv2:symbol "conrol_out" ; + ui:notifyType ; + ] . a lv2:Plugin , ingen:Patch ; rdfs:seeAlso ; - ui:ui ; + ui:ui ingen:ui ; lv2:binary . a lv2:Plugin , ingen:Patch ; rdfs:seeAlso ; - ui:ui ; + ui:ui ingen:ui ; lv2:binary . a lv2:Plugin , ingen:Patch ; rdfs:seeAlso ; - ui:ui ; + ui:ui ingen:ui ; lv2:binary . a lv2:Plugin , ingen:Patch ; rdfs:seeAlso ; - ui:ui ; + ui:ui ingen:ui ; lv2:binary . diff --git a/ingen/serialisation/Parser.hpp b/ingen/serialisation/Parser.hpp index f242108b..48fd59f0 100644 --- a/ingen/serialisation/Parser.hpp +++ b/ingen/serialisation/Parser.hpp @@ -24,9 +24,8 @@ #include #include -#include "raul/Path.hpp" - #include "ingen/GraphObject.hpp" +#include "raul/Path.hpp" namespace Ingen { diff --git a/ingen/serialisation/Serialiser.hpp b/ingen/serialisation/Serialiser.hpp index 8d5805e1..f317d04c 100644 --- a/ingen/serialisation/Serialiser.hpp +++ b/ingen/serialisation/Serialiser.hpp @@ -60,8 +60,7 @@ public: const std::string& path); virtual std::string to_string(SharedPtr object, - const std::string& base_uri, - const Properties& extra_rdf); + const std::string& base_uri); virtual void start_to_string(const Raul::Path& root, const std::string& base_uri); diff --git a/ingen/shared/AtomReader.hpp b/ingen/shared/AtomReader.hpp new file mode 100644 index 00000000..76b5ff92 --- /dev/null +++ b/ingen/shared/AtomReader.hpp @@ -0,0 +1,55 @@ +/* This file is part of Ingen. + * Copyright 2012 David Robillard + * + * Ingen is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef INGEN_SHARED_ATOM_READER_HPP +#define INGEN_SHARED_ATOM_READER_HPP + +#include "ingen/Interface.hpp" +#include "ingen/shared/AtomSink.hpp" +#include "ingen/shared/LV2URIMap.hpp" +#include "ingen/shared/URIs.hpp" +#include "serd/serd.h" + +namespace Ingen { + +class Forge; + +namespace Shared { + +class AtomSink; + +/** An AtomSink that calls methods on an Interface. */ +class AtomReader : public AtomSink +{ +public: + AtomReader(LV2URIMap& map, URIs& uris, Forge& forge, Interface& iface); + ~AtomReader() {} + + void write(const LV2_Atom* msg); + +private: + LV2URIMap& _map; + URIs& _uris; + Forge& _forge; + Interface& _iface; +}; + +} // namespace Shared +} // namespace Ingen + +#endif // INGEN_SHARED_ATOM_READER_HPP + diff --git a/ingen/shared/Configuration.hpp b/ingen/shared/Configuration.hpp index 21bc5737..e51bdc71 100644 --- a/ingen/shared/Configuration.hpp +++ b/ingen/shared/Configuration.hpp @@ -25,7 +25,7 @@ namespace Shared { class Configuration : public Raul::Configuration { public: - Configuration(Raul::Forge* forge); + Configuration(); }; } // namespace Shared diff --git a/ingen/shared/Forge.hpp b/ingen/shared/Forge.hpp new file mode 100644 index 00000000..273742c9 --- /dev/null +++ b/ingen/shared/Forge.hpp @@ -0,0 +1,36 @@ +/* This file is part of Ingen. + * Copyright 2012 David Robillard + * + * Ingen is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef INGEN_FORGE_HPP +#define INGEN_FORGE_HPP + +#include "ingen/shared/Forge.hpp" +#include "ingen/shared/LV2URIMap.hpp" +#include "raul/Atom.hpp" + +namespace Ingen { + +class Forge : public Raul::Forge { +public: + Forge(Shared::LV2URIMap& map); + + std::string str(const Raul::Atom& atom); +}; + +} // namespace Ingen + +#endif // INGEN_FORGE_HPP diff --git a/ingen/shared/LV2Atom.hpp b/ingen/shared/LV2Atom.hpp deleted file mode 100644 index 0aa35889..00000000 --- a/ingen/shared/LV2Atom.hpp +++ /dev/null @@ -1,45 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2009-2011 David Robillard - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_SHARED_LV2ATOM_HPP -#define INGEN_SHARED_LV2ATOM_HPP - -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" - -namespace Raul { class Atom; } - -namespace Ingen { -namespace Shared { - -class URIs; - -namespace LV2Atom { - -bool to_atom(const URIs& uris, - const LV2_Atom* object, - Raul::Atom& atom); - -bool from_atom(const URIs& uris, - const Raul::Atom& atom, - LV2_Atom* object); - -} // namespace LV2Atom - -} // namespace Shared -} // namespace Ingen - -#endif // INGEN_SHARED_LV2ATOM_HPP diff --git a/ingen/shared/LV2URIMap.hpp b/ingen/shared/LV2URIMap.hpp index 01bbfb7d..5375ed51 100644 --- a/ingen/shared/LV2URIMap.hpp +++ b/ingen/shared/LV2URIMap.hpp @@ -24,7 +24,6 @@ #include #include "ingen/shared/LV2Features.hpp" -#include "lv2/lv2plug.in/ns/ext/uri-map/uri-map.h" #include "lv2/lv2plug.in/ns/ext/urid/urid.h" #include "raul/URI.hpp" @@ -55,11 +54,6 @@ public: LV2_Feature _feature; }; - struct URIMapFeature : public Feature { - URIMapFeature(LV2URIMap* map); - LV2_URI_Map_Feature uri_map; - }; - struct URIDMapFeature : public Feature { URIDMapFeature(LV2URIMap* map, LV2_URID_Map* urid_map); LV2_URID map(const char* uri); @@ -74,32 +68,12 @@ public: LV2_URID_Unmap urid_unmap; }; - SharedPtr uri_map_feature() { return _uri_map_feature; } SharedPtr urid_map_feature() { return _urid_map_feature; } SharedPtr urid_unmap_feature() { return _urid_unmap_feature; } - virtual uint32_t uri_to_id(const char* map, const char* uri); - virtual const char* id_to_uri(const char* map, uint32_t id); - - std::pair event_to_global(uint16_t event_id) const; - std::pair global_to_event(uint32_t global_id) const; - private: - static uint32_t uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data, - const char* map, - const char* uri); - - static LV2_URID urid_map(LV2_URID_Map_Handle handle, const char* uri); - static const char* urid_unmap(LV2_URID_Unmap_Handle handle, LV2_URID urid); - - typedef std::map EventToGlobal; - typedef std::map GlobalToEvent; - - SharedPtr _uri_map_feature; SharedPtr _urid_map_feature; SharedPtr _urid_unmap_feature; - EventToGlobal _event_to_global; - GlobalToEvent _global_to_event; }; } // namespace Shared diff --git a/ingen/shared/ResourceImpl.hpp b/ingen/shared/ResourceImpl.hpp index 8069c480..fe8d3017 100644 --- a/ingen/shared/ResourceImpl.hpp +++ b/ingen/shared/ResourceImpl.hpp @@ -67,8 +67,6 @@ public: void add_properties(const Properties& p); void remove_properties(const Properties& p); - void dump(std::ostream& os) const; - /** Get the ingen type from a set of Properties. * If some coherent ingen type is found, true is returned and the appropriate * output parameter set to true. Otherwise false is returned. diff --git a/ingen/shared/URIs.hpp b/ingen/shared/URIs.hpp index 4f95c6c7..a23b32d4 100644 --- a/ingen/shared/URIs.hpp +++ b/ingen/shared/URIs.hpp @@ -21,6 +21,8 @@ #include #include "ingen/shared/LV2URIMap.hpp" +#include "ingen/shared/Forge.hpp" +#include "raul/Atom.hpp" #include "raul/URI.hpp" namespace Raul { @@ -32,23 +34,29 @@ namespace Shared { class URIs : public boost::noncopyable { public: - URIs(Raul::Forge& forge, LV2URIMap* map); + URIs(Ingen::Forge& forge, LV2URIMap* map); struct Quark : public Raul::URI { - Quark(LV2URIMap* map, const char* str); - operator LV2_URID() const { return id; } - uint32_t id; + Quark(Ingen::Forge& forge, LV2URIMap* map, const char* str); + operator LV2_URID() const { return id; } + operator Raul::Atom() const { return atom; } + uint32_t id; + Raul::Atom atom; }; - Raul::Forge& forge; + Ingen::Forge& forge; + const Quark atom_Blank; const Quark atom_Bool; const Quark atom_Float; const Quark atom_Int; const Quark atom_MessagePort; + const Quark atom_Sequence; + const Quark atom_Sound; const Quark atom_String; const Quark atom_ValuePort; const Quark atom_Vector; + const Quark atom_bufferType; const Quark atom_eventTransfer; const Quark atom_supports; const Quark ctx_audioContext; @@ -56,7 +64,6 @@ public: const Quark ctx_messageContext; const Quark cv_CVPort; const Quark doap_name; - const Quark ev_EventPort; const Quark ingen_Connection; const Quark ingen_Internal; const Quark ingen_Node; diff --git a/ingen/shared/World.hpp b/ingen/shared/World.hpp index aa308efd..114be857 100644 --- a/ingen/shared/World.hpp +++ b/ingen/shared/World.hpp @@ -23,8 +23,9 @@ #include #include +#include "ingen/shared/Forge.hpp" #include "lv2/lv2plug.in/ns/ext/urid/urid.h" - +#include "raul/Atom.hpp" #include "raul/Configuration.hpp" #include "raul/SharedPtr.hpp" @@ -108,7 +109,7 @@ public: virtual Raul::Configuration* conf(); virtual void set_conf(Raul::Configuration* c); - virtual Raul::Forge& forge(); + virtual Ingen::Forge& forge(); virtual LV2Features* lv2_features(); diff --git a/src/bindings/test_ingen.py b/src/bindings/test_ingen.py index 921bdd1b..da90b988 100755 --- a/src/bindings/test_ingen.py +++ b/src/bindings/test_ingen.py @@ -26,7 +26,7 @@ e.activate() c.subscribe(e) -e.create_port("/dynamic_port", "http://lv2plug.in/ns/ext/event#EventPort", False) +e.create_port("/dynamic_port", "http://lv2plug.in/ns/lv2core#AudioPort", False) while True: world.iteration() diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp index ecf03dad..54aea125 100644 --- a/src/client/ClientStore.cpp +++ b/src/client/ClientStore.cpp @@ -277,7 +277,7 @@ ClientStore::put(const URI& uri, #ifdef INGEN_CLIENT_STORE_DUMP LOG(info) << "PUT " << uri << " {" << endl; for (Iterator i = properties.begin(); i != properties.end(); ++i) - LOG(info) << '\t' << i->first << " = " << i->second + LOG(info) << '\t' << i->first << " = " << _uris->forge.str(i->second) << " :: " << i->second.type() << endl; LOG(info) << "}" << endl; #endif @@ -288,7 +288,7 @@ ClientStore::put(const URI& uri, // Check if uri is a plugin const Atom& type = properties.find(_uris->rdf_type)->second; - if (type.type() == Atom::URI) { + if (type.type() == _uris->forge.URI) { const URI& type_uri = type.get_uri(); const Plugin::Type plugin_type = Plugin::type_from_uri(type_uri); if (plugin_type == Plugin::Patch) { @@ -324,7 +324,7 @@ ClientStore::put(const URI& uri, } else if (is_node) { const Iterator p = properties.find(_uris->rdf_instanceOf); SharedPtr plug; - if (p->second.is_valid() && p->second.type() == Atom::URI) { + if (p->second.is_valid() && p->second.type() == _uris->forge.URI) { if (!(plug = _plugin(p->second.get_uri()))) { LOG(warn) << "Unable to find plugin " << p->second.get_uri() << endl; plug = SharedPtr( @@ -344,7 +344,7 @@ ClientStore::put(const URI& uri, } else if (is_port) { PortModel::Direction pdir = is_output ? PortModel::OUTPUT : PortModel::INPUT; const Iterator i = properties.find(_uris->lv2_index); - if (i != properties.end() && i->second.type() == Atom::INT) { + if (i != properties.end() && i->second.type() == _uris->forge.Int) { const uint32_t index = i->second.get_int32(); SharedPtr p( new PortModel(uris(), path, index, pdir)); @@ -368,10 +368,10 @@ ClientStore::delta(const URI& uri, #ifdef INGEN_CLIENT_STORE_DUMP LOG(info) << "DELTA " << uri << " {" << endl; for (iterator i = remove.begin(); i != remove.end(); ++i) - LOG(info) << " - " << i->first << " = " << i->second + LOG(info) << " - " << i->first << " = " << _uris->forge.str(i->second) << " :: " << i->second.type() << endl; for (iterator i = add.begin(); i != add.end(); ++i) - LOG(info) << " + " << i->first << " = " << i->second + LOG(info) << " + " << i->first << " = " << _uris->forge.str(i->second) << " :: " << i->second.type() << endl; LOG(info) << "}" << endl; #endif @@ -396,7 +396,8 @@ void ClientStore::set_property(const URI& subject_uri, const URI& predicate, const Atom& value) { if (subject_uri == _uris->ingen_engine) { - LOG(info) << "Engine property " << predicate << " = " << value << endl; + LOG(info) << "Engine property " << predicate + << " = " << _uris->forge.str(value) << endl; return; } SharedPtr subject = _resource(subject_uri); diff --git a/src/client/NodeModel.cpp b/src/client/NodeModel.cpp index 56ff1fdc..34bc7a13 100644 --- a/src/client/NodeModel.cpp +++ b/src/client/NodeModel.cpp @@ -205,9 +205,9 @@ NodeModel::port_value_range(SharedPtr port, // Possibly overriden const Atom& min_atom = port->get_property(_uris.lv2_minimum); const Atom& max_atom = port->get_property(_uris.lv2_maximum); - if (min_atom.type() == Atom::FLOAT) + if (min_atom.type() == _uris.forge.Float) min = min_atom.get_float(); - if (max_atom.type() == Atom::FLOAT) + if (max_atom.type() == _uris.forge.Float) max = max_atom.get_float(); if (max <= min) diff --git a/src/client/ObjectModel.cpp b/src/client/ObjectModel.cpp index 642df732..fbd79315 100644 --- a/src/client/ObjectModel.cpp +++ b/src/client/ObjectModel.cpp @@ -51,7 +51,7 @@ ObjectModel::~ObjectModel() bool ObjectModel::is_a(const Raul::URI& type) const { - return has_property(_uris.rdf_type, type); + return has_property(_uris.rdf_type, _uris.forge.alloc_uri(type.str())); } void diff --git a/src/client/PluginModel.cpp b/src/client/PluginModel.cpp index 09a5abfb..bd5e591c 100644 --- a/src/client/PluginModel.cpp +++ b/src/client/PluginModel.cpp @@ -52,7 +52,7 @@ PluginModel::PluginModel(Shared::URIs& uris, assert(_rdf_world); add_property("http://www.w3.org/1999/02/22-rdf-syntax-ns#type", - this->type_uri()); + uris.forge.alloc_uri(this->type_uri().str())); LilvNode* plugin_uri = lilv_new_uri(_lilv_world, uri.c_str()); _lilv_plugin = lilv_plugins_get_by_uri(_lilv_plugins, plugin_uri); lilv_node_free(plugin_uri); @@ -108,8 +108,7 @@ PluginModel::get_property(const URI& key) const LILV_FOREACH(nodes, i, values) { const LilvNode* val = lilv_nodes_get(values, i); if (lilv_node_is_uri(val)) { - ret = set_property( - key, _uris.forge.alloc(Atom::URI, lilv_node_as_uri(val))); + ret = set_property(key, _uris.forge.alloc_uri(lilv_node_as_uri(val))); break; } else if (lilv_node_is_string(val)) { ret = set_property(key, @@ -155,7 +154,7 @@ Symbol PluginModel::default_node_symbol() const { const Atom& name_atom = get_property("http://lv2plug.in/ns/lv2core#symbol"); - if (name_atom.is_valid() && name_atom.type() == Atom::STRING) + if (name_atom.is_valid() && name_atom.type() == _uris.forge.String) return Symbol::symbolify(name_atom.get_string()); else return "_"; @@ -165,7 +164,7 @@ string PluginModel::human_name() const { const Atom& name_atom = get_property("http://usefulinc.com/ns/doap#name"); - if (name_atom.type() == Atom::STRING) + if (name_atom.type() == _uris.forge.String) return name_atom.get_string(); else return default_node_symbol().c_str(); diff --git a/src/client/PluginUI.cpp b/src/client/PluginUI.cpp index c20d41b1..8a8759fa 100644 --- a/src/client/PluginUI.cpp +++ b/src/client/PluginUI.cpp @@ -24,8 +24,6 @@ #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" #include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "lv2/lv2plug.in/ns/ext/event/event-helpers.h" -#include "lv2/lv2plug.in/ns/ext/event/event.h" using namespace std; using namespace Raul; @@ -53,8 +51,7 @@ lv2_ui_write(SuilController controller, SharedPtr port = ports[port_index]; - const Shared::URIs& uris = *ui->world()->uris().get(); - const Shared::LV2URIMap& uri_map = *ui->world()->lv2_uri_map().get(); + const Shared::URIs& uris = *ui->world()->uris().get(); // float (special case, always 0) if (format == 0) { @@ -67,40 +64,11 @@ lv2_ui_write(SuilController controller, uris.ingen_value, ui->world()->forge().make(*(float*)buffer)); - } else if (format == uris.ui_Events.id) { - LV2_Event_Buffer* buf = (LV2_Event_Buffer*)buffer; - LV2_Event_Iterator iter; - uint8_t* data; - lv2_event_begin(&iter, buf); - while (lv2_event_is_valid(&iter)) { - LV2_Event* const ev = lv2_event_get(&iter, &data); - std::pair midi_id = - uri_map.global_to_event(uris.midi_MidiEvent.id); - if (midi_id.first && ev->type == midi_id.second) { - // FIXME - /* - ui->world()->engine()->set_property( - port->path(), - uris.ingen_value, - Atom("http://lv2plug.in/ns/ext/midi#MidiEvent", ev->size, - data)); - */ - } else { - warn << "Unable to serialise UI event type " << ev->type - << ", event lost" << endl; - } - - lv2_event_increment(&iter); - } - } else if (format == uris.atom_eventTransfer.id) { - std::cerr << "FIXME: atom event transfer" << std::endl; - #if 0 - LV2_Atom* buf = (LV2_Atom*)buffer; - Raul::Atom val; - Shared::LV2Atom::to_atom(uris, buf, val); + LV2_Atom* atom = (LV2_Atom*)buffer; + Raul::Atom val = ui->world()->forge().alloc( + atom->size, atom->type, LV2_ATOM_BODY(atom)); ui->world()->engine()->set_property(port->path(), uris.ingen_value, val); - #endif } else { warn << "Unknown value format " << format diff --git a/src/client/PortModel.cpp b/src/client/PortModel.cpp index afd28816..ba335ce9 100644 --- a/src/client/PortModel.cpp +++ b/src/client/PortModel.cpp @@ -35,13 +35,15 @@ PortModel::on_property(const Raul::URI& uri, const Raul::Atom& value) bool PortModel::supports(const Raul::URI& value_type) const { - return has_property(_uris.atom_supports, value_type); + return has_property(_uris.atom_supports, + _uris.forge.alloc_uri(value_type.str())); } bool PortModel::port_property(const Raul::URI& uri) const { - return has_property(_uris.lv2_portProperty, uri); + return has_property(_uris.lv2_portProperty, + _uris.forge.alloc_uri(uri.str())); } void @@ -66,7 +68,7 @@ PortModel::has_context(const Raul::URI& uri) const if (uri == _uris.ctx_audioContext && !context.is_valid()) return true; else - return context == uri; + return context == _uris.forge.alloc_uri(uri.str()); } } // namespace Client diff --git a/src/gui/App.cpp b/src/gui/App.cpp index ad70a7f9..431b144c 100644 --- a/src/gui/App.cpp +++ b/src/gui/App.cpp @@ -225,8 +225,8 @@ App::property_change(const Raul::URI& subject, const Raul::Atom& value) { if (subject == uris().ingen_engine && key == uris().ingen_sampleRate) { - if (value.type() == Atom::INT) { - LOG(info) << "Sample rate: " << value << std::endl; + if (value.type() == forge().Int) { + LOG(info) << "Sample rate: " << uris().forge.str(value) << std::endl; _sample_rate = value.get_int32(); } else { error << "Engine sample rate property is not an integer" << std::endl; diff --git a/src/gui/App.hpp b/src/gui/App.hpp index 7b45a6e8..7f66c629 100644 --- a/src/gui/App.hpp +++ b/src/gui/App.hpp @@ -25,8 +25,9 @@ #include -#include "raul/SharedPtr.hpp" #include "raul/Deletable.hpp" +#include "raul/SharedPtr.hpp" +#include "raul/URI.hpp" #include "ingen/Status.hpp" #include "ingen/shared/World.hpp" @@ -101,7 +102,7 @@ public: Glib::RefPtr icon_from_path(const std::string& path, int size); - Raul::Forge& forge() const { return _world->forge(); } + Ingen::Forge& forge() const { return _world->forge(); } SharedPtr engine() const { return _world->engine(); } SharedPtr client() const { return _client; } SharedPtr store() const { return _store; } diff --git a/src/gui/Configuration.cpp b/src/gui/Configuration.cpp index 2d8cf2e6..b85a997c 100644 --- a/src/gui/Configuration.cpp +++ b/src/gui/Configuration.cpp @@ -91,7 +91,7 @@ Configuration::get_port_color(const PortModel* p) return _string_port_color; } else if (_app.can_control(p)) { return _control_port_color; - } else if (p->is_a(uris.ev_EventPort) || p->is_a(uris.atom_MessagePort)) { + } else if (p->is_a(uris.atom_MessagePort)) { return _event_port_color; } diff --git a/src/gui/Controls.cpp b/src/gui/Controls.cpp index c3fe2658..87903f8e 100644 --- a/src/gui/Controls.cpp +++ b/src/gui/Controls.cpp @@ -218,9 +218,9 @@ SliderControl::port_property_changed(const URI& key, const Atom& value) _enable_signal = false; const Shared::URIs& uris = _app->uris(); - if (key == uris.lv2_minimum && value.type() == Atom::FLOAT) + if (key == uris.lv2_minimum && value.type() == uris.forge.Float) set_range(value.get_float(), _slider->get_adjustment()->get_upper()); - else if (key == uris.lv2_maximum && value.type() == Atom::FLOAT) + else if (key == uris.lv2_maximum && value.type() == uris.forge.Float) set_range(_slider->get_adjustment()->get_lower(), value.get_float()); _enable_signal = true; @@ -320,18 +320,15 @@ ToggleControl::init(App& app, ControlPanel* panel, SharedPtr pm void ToggleControl::set_value(const Atom& val) { - bool enable = false; - switch (val.type()) { - case Atom::FLOAT: + const Shared::URIs& uris = _app->uris(); + bool enable = false; + if (val.type() == uris.forge.Float) { enable = (val.get_float() != 0.0f); - break; - case Atom::INT: + } else if (val.type() == uris.forge.Int) { enable = (val.get_int32() != 0); - break; - case Atom::BOOL: + } else if (val.type() == uris.forge.Bool) { enable = (val.get_bool()); - break; - default: + } else { error << "Unsupported value type for toggle control" << endl; } @@ -380,7 +377,7 @@ void StringControl::set_value(const Atom& val) { _enable_signal = false; - if (val.type() == Atom::STRING) + if (val.type() == _app->forge().String) _entry->set_text(val.get_string()); else error << "Non-string value for string port " << _port_model->path() << endl; @@ -393,7 +390,7 @@ StringControl::activated() if (_enable_signal) _control_panel->value_changed_atom( _port_model, - _app->forge().make(_entry->get_text().c_str())); + _app->forge().alloc(_entry->get_text().c_str())); } } // namespace GUI diff --git a/src/gui/LoadPluginWindow.cpp b/src/gui/LoadPluginWindow.cpp index 95bbc0b6..3b8b1c44 100644 --- a/src/gui/LoadPluginWindow.cpp +++ b/src/gui/LoadPluginWindow.cpp @@ -226,7 +226,7 @@ LoadPluginWindow::set_row(Gtk::TreeModel::Row& row, { const URIs& uris = _app->uris(); const Atom& name = plugin->get_property(uris.doap_name); - if (name.is_valid() && name.type() == Atom::STRING) + if (name.is_valid() && name.type() == uris.forge.String) row[_plugins_columns._col_name] = name.get_string(); switch (plugin->type()) { @@ -344,7 +344,7 @@ LoadPluginWindow::load_plugin(const Gtk::TreeModel::iterator& iter) Path path = _patch->path().base() + Path::nameify(name); Resource::Properties props = _initial_data; props.insert(make_pair(uris.rdf_type, uris.ingen_Node)); - props.insert(make_pair(uris.rdf_instanceOf, plugin->uri())); + props.insert(make_pair(uris.rdf_instanceOf, _app->forge().alloc_uri(plugin->uri().str()))); props.insert(make_pair(uris.ingen_polyphonic, _app->forge().make(polyphonic))); _app->engine()->put(path, props); @@ -395,7 +395,7 @@ LoadPluginWindow::filter_changed() switch (criteria) { case CriteriaColumns::NAME: - if (name.is_valid() && name.type() == Atom::STRING) + if (name.is_valid() && name.type() == uris.forge.String) field = name.get_string(); break; case CriteriaColumns::TYPE: @@ -441,7 +441,7 @@ LoadPluginWindow::plugin_property_changed(const URI& plugin, const URIs& uris = _app->uris(); if (predicate == uris.doap_name) { Rows::const_iterator i = _rows.find(plugin); - if (i != _rows.end() && value.type() == Atom::STRING) + if (i != _rows.end() && value.type() == uris.forge.String) (*i->second)[_plugins_columns._col_name] = value.get_string(); } } diff --git a/src/gui/NodeModule.cpp b/src/gui/NodeModule.cpp index 697961db..7ab0be5f 100644 --- a/src/gui/NodeModule.cpp +++ b/src/gui/NodeModule.cpp @@ -138,7 +138,7 @@ NodeModule::show_human_names(bool b) if (b && node()->plugin()) { const Raul::Atom& name_property = node()->get_property(uris.lv2_name); - if (name_property.type() == Atom::STRING) + if (name_property.type() == uris.forge.String) set_label(name_property.get_string()); else set_label(node()->plugin_model()->human_name().c_str()); @@ -152,7 +152,7 @@ NodeModule::show_human_names(bool b) Glib::ustring label(port->model()->symbol().c_str()); if (b) { const Raul::Atom& name_property = port->model()->get_property(uris.lv2_name); - if (name_property.type() == Atom::STRING) { + if (name_property.type() == uris.forge.String) { label = name_property.get_string(); } else { Glib::ustring hn = node()->plugin_model()->port_human_name( @@ -171,18 +171,15 @@ NodeModule::value_changed(uint32_t index, const Atom& value) if (!_plugin_ui) return; - float float_val = 0.0f; + float float_val = 0.0f; + const URIs& uris = app().uris(); - switch (value.type()) { - case Atom::FLOAT: + if (value.type() == uris.forge.Float) { float_val = value.get_float(); _plugin_ui->port_event(index, 4, 0, &float_val); - break; - case Atom::STRING: - _plugin_ui->port_event(index, strlen(value.get_string()), 0, value.get_string()); - break; - default: - break; + } else if (value.type() == uris.forge.String) { + _plugin_ui->port_event( + index, strlen(value.get_string()), 0, value.get_string()); } } @@ -397,15 +394,13 @@ void NodeModule::property_changed(const URI& key, const Atom& value) { const Shared::URIs& uris = app().uris(); - switch (value.type()) { - case Atom::FLOAT: + if (value.type() == uris.forge.Float) { if (key == uris.ingen_canvasX) { move_to(value.get_float(), get_y()); } else if (key == uris.ingen_canvasY) { move_to(get_x(), value.get_float()); } - break; - case Atom::BOOL: + } else if (value.type() == uris.forge.Bool) { if (key == uris.ingen_polyphonic) { set_stacked(value.get_bool()); } else if (key == uris.ingen_selected) { @@ -413,13 +408,11 @@ NodeModule::property_changed(const URI& key, const Atom& value) set_selected(value.get_bool()); } } - break; - case Atom::STRING: + } else if (value.type() == uris.forge.String) { if (key == uris.lv2_name - && app().configuration()->name_style() == Configuration::HUMAN) { + && app().configuration()->name_style() == Configuration::HUMAN) { set_label(value.get_string()); } - default: break; } } diff --git a/src/gui/ObjectMenu.cpp b/src/gui/ObjectMenu.cpp index 76607559..a5ffa845 100644 --- a/src/gui/ObjectMenu.cpp +++ b/src/gui/ObjectMenu.cpp @@ -124,7 +124,7 @@ ObjectMenu::property_changed(const URI& predicate, const Atom& value) { const URIs& uris = _app->uris(); _enable_signal = false; - if (predicate == uris.ingen_polyphonic && value.type() == Atom::BOOL) + if (predicate == uris.ingen_polyphonic && value.type() == uris.forge.Bool) _polyphonic_menuitem->set_active(value.get_bool()); _enable_signal = true; } diff --git a/src/gui/PatchBox.cpp b/src/gui/PatchBox.cpp index 127da746..1a38e027 100644 --- a/src/gui/PatchBox.cpp +++ b/src/gui/PatchBox.cpp @@ -22,8 +22,6 @@ #include #include -#include "raul/AtomRDF.hpp" - #include "ingen/Interface.hpp" #include "ingen/client/ClientStore.hpp" #include "ingen/client/PatchModel.hpp" @@ -359,7 +357,7 @@ PatchBox::show_port_status(const PortModel* port, const Raul::Atom& value) } if (value.is_valid()) { - msg << " = " << value; + msg << " = " << _app->forge().str(value); } _status_bar->pop(STATUS_CONTEXT_HOVER); @@ -421,7 +419,7 @@ void PatchBox::event_save() { const Raul::Atom& document = _patch->get_property(_app->uris().ingen_document); - if (!document.is_valid() || document.type() != Raul::Atom::URI) { + if (!document.is_valid() || document.type() != _app->uris().forge.URI) { event_save_as(); } else { _app->loader()->save_patch(_patch, document.get_uri()); @@ -467,7 +465,7 @@ PatchBox::event_save_as() // Set current folder to most sensible default const Raul::Atom& document = _patch->get_property(uris.ingen_document); - if (document.type() == Raul::Atom::URI) + if (document.type() == uris.forge.URI) dialog.set_uri(document.get_uri()); else if (_app->configuration()->patch_folder().length() > 0) dialog.set_current_folder(_app->configuration()->patch_folder()); @@ -536,7 +534,7 @@ PatchBox::event_save_as() _app->loader()->save_patch(_patch, uri); const_cast(_patch.get())->set_property( uris.ingen_document, - _app->forge().alloc(Atom::URI, uri.c_str()), + _app->forge().alloc_uri(uri.c_str()), Resource::EXTERNAL); _status_bar->push( (boost::format("Saved %1% to %2%") % _patch->path().chop_scheme() diff --git a/src/gui/PatchCanvas.cpp b/src/gui/PatchCanvas.cpp index 64c7df66..070a1da2 100644 --- a/src/gui/PatchCanvas.cpp +++ b/src/gui/PatchCanvas.cpp @@ -18,33 +18,37 @@ #include #include #include + #include -#include "raul/log.hpp" + #include "ganv/Canvas.hpp" #include "ganv/Circle.hpp" #include "ingen/Interface.hpp" -#include "ingen/shared/LV2URIMap.hpp" +#include "ingen/client/ClientStore.hpp" +#include "ingen/client/NodeModel.hpp" +#include "ingen/client/PatchModel.hpp" +#include "ingen/client/PluginModel.hpp" +#include "ingen/serialisation/Serialiser.hpp" #include "ingen/shared/Builder.hpp" #include "ingen/shared/ClashAvoider.hpp" -#include "ingen/serialisation/Serialiser.hpp" -#include "ingen/client/PluginModel.hpp" -#include "ingen/client/PatchModel.hpp" -#include "ingen/client/NodeModel.hpp" -#include "ingen/client/ClientStore.hpp" +#include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/World.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" +#include "raul/log.hpp" + #include "App.hpp" -#include "PatchCanvas.hpp" -#include "PatchWindow.hpp" -#include "PatchPortModule.hpp" +#include "Connection.hpp" #include "LoadPluginWindow.hpp" #include "NewSubpatchWindow.hpp" -#include "Port.hpp" -#include "Connection.hpp" #include "NodeModule.hpp" +#include "PatchCanvas.hpp" +#include "PatchPortModule.hpp" +#include "PatchWindow.hpp" +#include "Port.hpp" #include "SubpatchModule.hpp" +#include "ThreadedLoader.hpp" #include "WidgetFactory.hpp" #include "WindowFactory.hpp" -#include "ThreadedLoader.hpp" #define LOG(s) s << "[PatchCanvas] " @@ -108,10 +112,10 @@ PatchCanvas::PatchCanvas(App& app, "control_out", "Control Out", LV2_CORE__ControlPort, true)); _menu_add_event_input->signal_activate().connect( sigc::bind(sigc::mem_fun(this, &PatchCanvas::menu_add_port), - "event_in", "Event In", "http://lv2plug.in/ns/ext/event#EventPort", false)); + "event_in", "Event In", LV2_ATOM__MessagePort, false)); _menu_add_event_output->signal_activate().connect( sigc::bind(sigc::mem_fun(this, &PatchCanvas::menu_add_port), - "event_out", "Event Out", "http://lv2plug.in/ns/ext/event#EventPort", true)); + "event_out", "Event Out", LV2_ATOM__MessagePort, true)); signal_event.connect( sigc::mem_fun(this, &PatchCanvas::on_event)); @@ -792,13 +796,13 @@ PatchCanvas::menu_add_port(const string& sym_base, const string& name_base, Resource::Properties props = get_initial_data(); props.insert(make_pair(uris.rdf_type, - type)); + _app.forge().alloc_uri(type.str()))); props.insert(make_pair(uris.rdf_type, is_output ? uris.lv2_OutputPort : uris.lv2_InputPort)); props.insert(make_pair(uris.lv2_index, _app.forge().make(int32_t(_patch->num_ports())))); props.insert(make_pair(uris.lv2_name, - _app.forge().make(name.c_str()))); + _app.forge().alloc(name.c_str()))); _app.engine()->put(path, props); } @@ -818,12 +822,13 @@ PatchCanvas::load_plugin(WeakPtr weak_plugin) } const URIs& uris = _app.uris(); + const Path path = _patch->path().child(symbol); - const Path path = _patch->path().child(symbol); // FIXME: polyphony? GraphObject::Properties props = get_initial_data(); props.insert(make_pair(uris.rdf_type, uris.ingen_Node)); - props.insert(make_pair(uris.rdf_instanceOf, plugin->uri())); + props.insert(make_pair(uris.rdf_instanceOf, + uris.forge.alloc_uri(plugin->uri().str()))); _app.engine()->put(path, props); } diff --git a/src/gui/PatchPortModule.cpp b/src/gui/PatchPortModule.cpp index 1e5b1d5a..9ad1fe9a 100644 --- a/src/gui/PatchPortModule.cpp +++ b/src/gui/PatchPortModule.cpp @@ -114,7 +114,7 @@ PatchPortModule::show_human_names(bool b) { const URIs& uris = app().uris(); const Atom& name = _model->get_property(uris.lv2_name); - if (b && name.type() == Atom::STRING) + if (b && name.type() == uris.forge.String) set_name(name.get_string()); else set_name(_model->symbol().c_str()); @@ -131,15 +131,13 @@ void PatchPortModule::property_changed(const URI& key, const Atom& value) { const URIs& uris = app().uris(); - switch (value.type()) { - case Atom::FLOAT: + if (value.type() == uris.forge.Float) { if (key == uris.ingen_canvasX) { move_to(value.get_float(), get_y()); } else if (key == uris.ingen_canvasY) { move_to(get_x(), value.get_float()); } - break; - case Atom::STRING: + } else if (value.type() == uris.forge.String) { if (key == uris.lv2_name && app().configuration()->name_style() == Configuration::HUMAN) { set_name(value.get_string()); @@ -147,8 +145,7 @@ PatchPortModule::property_changed(const URI& key, const Atom& value) && app().configuration()->name_style() == Configuration::PATH) { set_name(value.get_string()); } - break; - case Atom::BOOL: + } else if (value.type() == uris.forge.Bool) { if (key == uris.ingen_polyphonic) { set_stacked(value.get_bool()); } else if (key == uris.ingen_selected) { @@ -156,7 +153,6 @@ PatchPortModule::property_changed(const URI& key, const Atom& value) set_selected(value.get_bool()); } } - default: break; } } diff --git a/src/gui/PatchTreeWindow.cpp b/src/gui/PatchTreeWindow.cpp index 41d82899..486107ce 100644 --- a/src/gui/PatchTreeWindow.cpp +++ b/src/gui/PatchTreeWindow.cpp @@ -198,7 +198,7 @@ PatchTreeWindow::patch_property_changed(const URI& key, const Atom& value, { const URIs& uris = _app->uris(); _enable_signal = false; - if (key == uris.ingen_enabled && value.type() == Atom::BOOL) { + if (key == uris.ingen_enabled && value.type() == uris.forge.Bool) { Gtk::TreeModel::iterator i = find_patch(_patch_treestore->children(), patch); if (i != _patch_treestore->children().end()) { Gtk::TreeModel::Row row = *i; diff --git a/src/gui/PatchView.cpp b/src/gui/PatchView.cpp index 4506a651..a5932a23 100644 --- a/src/gui/PatchView.cpp +++ b/src/gui/PatchView.cpp @@ -207,6 +207,8 @@ void PatchView::refresh_clicked() { _app->engine()->get(_patch->path()); + Raul::warn << "Refresh plugins" << std::endl; + _app->engine()->get("ingen:plugins"); } void @@ -214,10 +216,11 @@ PatchView::property_changed(const Raul::URI& predicate, const Raul::Atom& value) { _enable_signal = false; if (predicate == _app->uris().ingen_enabled) { - if (value.type() == Atom::BOOL) - _process_but->set_active(value.get_bool()); - else - warn << "Bad type for ingen:enabled variable: " << value.type() << endl; + if (value.type() == _app->uris().forge.Bool) { + _process_but->set_active(value.get_bool()); + } else { + warn << "Bad type for ingen:enabled variable: " << value.type() << endl; + } } _enable_signal = true; } diff --git a/src/gui/PatchWindow.cpp b/src/gui/PatchWindow.cpp index f555ff37..6d29d532 100644 --- a/src/gui/PatchWindow.cpp +++ b/src/gui/PatchWindow.cpp @@ -53,6 +53,7 @@ PatchWindow::init_window(App& app) { Window::init_window(app); _box->init_box(app); + _box->set_window(this); } void diff --git a/src/gui/Port.cpp b/src/gui/Port.cpp index aa3786e3..d61724d6 100644 --- a/src/gui/Port.cpp +++ b/src/gui/Port.cpp @@ -50,7 +50,7 @@ Port::create(App& app, Glib::ustring label(human_name ? "" : pm->path().symbol()); if (human_name) { const Raul::Atom& name = pm->get_property(app.uris().lv2_name); - if (name.type() == Raul::Atom::STRING) { + if (name.type() == app.forge().String) { label = name.get_string(); } else { const SharedPtr parent(PtrCast(pm->parent())); @@ -163,7 +163,7 @@ Port::on_value_changed(const Glib::VariantBase& value) void Port::value_changed(const Atom& value) { - if (!_pressed && value.type() == Atom::FLOAT) { + if (!_pressed && value.type() == _app.forge().Float) { Ganv::Port::set_control_value(value.get_float()); } } @@ -278,7 +278,7 @@ void Port::property_changed(const URI& key, const Atom& value) { const URIs& uris = _app.uris(); - if (value.type() == Atom::FLOAT) { + if (value.type() == uris.forge.Float) { float val = value.get_float(); if (key == uris.ingen_value && !_pressed) { Ganv::Port::set_control_value(val); @@ -299,7 +299,7 @@ Port::property_changed(const URI& key, const Atom& value) } else if (key == uris.ctx_context) { Raul::info << "TODO: Visual indication of port context?" << std::endl; } else if (key == uris.lv2_name) { - if (value.type() == Atom::STRING + if (value.type() == uris.forge.String && _app.configuration()->name_style() == Configuration::HUMAN) { set_label(value.get_string()); } diff --git a/src/gui/PortMenu.cpp b/src/gui/PortMenu.cpp index 60d419f6..dbd5890f 100644 --- a/src/gui/PortMenu.cpp +++ b/src/gui/PortMenu.cpp @@ -63,7 +63,7 @@ PortMenu::init(App& app, SharedPtr port, bool patch_port) _destroy_menuitem->set_sensitive(false); } - if (port->is_a(uris.ev_EventPort)) + if (port->is_a(uris.atom_MessagePort)) _polyphonic_menuitem->hide(); const bool is_control = app.can_control(port.get()) diff --git a/src/gui/PortPropertiesWindow.cpp b/src/gui/PortPropertiesWindow.cpp index dd138b12..8c4530de 100644 --- a/src/gui/PortPropertiesWindow.cpp +++ b/src/gui/PortPropertiesWindow.cpp @@ -98,7 +98,7 @@ PortPropertiesWindow::property_changed(const URI& key, const Atom& value) { const Shared::URIs& uris = _app->uris(); - if (value.type() == Atom::FLOAT) { + if (value.type() == uris.forge.Float) { if (key == uris.lv2_minimum) _min_spinner->set_value(value.get_float()); else if (key == uris.lv2_maximum) diff --git a/src/gui/PropertiesWindow.cpp b/src/gui/PropertiesWindow.cpp index 1543398b..42ff5e8b 100644 --- a/src/gui/PropertiesWindow.cpp +++ b/src/gui/PropertiesWindow.cpp @@ -35,6 +35,7 @@ namespace GUI { PropertiesWindow::PropertiesWindow(BaseObjectType* cobject, const Glib::RefPtr& xml) : Window(cobject) + , _initialised(false) { xml->get_widget("properties_vbox", _vbox); xml->get_widget("properties_scrolledwindow", _scrolledwindow); @@ -43,15 +44,6 @@ PropertiesWindow::PropertiesWindow(BaseObjectType* cobject, xml->get_widget("properties_apply_button", _apply_button); xml->get_widget("properties_ok_button", _ok_button); - _type_choices = Gtk::ListStore::create(_type_cols); - for (int i = Raul::Atom::INT; i <= Raul::Atom::BLOB; ++i) { - Gtk::TreeModel::Row row = *_type_choices->append(); - row[_type_cols.type] = static_cast(i); - ostringstream ss; - ss << static_cast(i); - row[_type_cols.choice] = ss.str(); - } - _cancel_button->signal_clicked().connect( sigc::mem_fun(this, &PropertiesWindow::cancel_clicked)); @@ -62,6 +54,33 @@ PropertiesWindow::PropertiesWindow(BaseObjectType* cobject, sigc::mem_fun(this, &PropertiesWindow::ok_clicked)); } +void +PropertiesWindow::init() +{ + Forge& forge = _app->forge(); + Gtk::TreeModel::Row row = *_type_choices->append(); + row[_type_cols.type] = forge.Int; + row[_type_cols.choice] = "Int"; + + row = *_type_choices->append(); + row[_type_cols.type] = forge.Float; + row[_type_cols.choice] = "Float"; + + row = *_type_choices->append(); + row[_type_cols.type] = forge.Bool; + row[_type_cols.choice] = "Bool"; + + row = *_type_choices->append(); + row[_type_cols.type] = forge.URI; + row[_type_cols.choice] = "URI"; + + row = *_type_choices->append(); + row[_type_cols.type] = forge.String; + row[_type_cols.choice] = "String"; + + _initialised = true; +} + void PropertiesWindow::reset() { @@ -137,7 +156,8 @@ PropertiesWindow::set_object(SharedPtr model) Gtk::Widget* PropertiesWindow::create_value_widget(const Raul::URI& uri, const Raul::Atom& value) { - if (value.type() == Atom::INT) { + Ingen::Forge& forge = _app->forge(); + if (value.type() == forge.Int) { Gtk::SpinButton* widget = manage(new Gtk::SpinButton(0.0, 0)); widget->property_numeric() = true; widget->set_value(value.get_int32()); @@ -148,7 +168,7 @@ PropertiesWindow::create_value_widget(const Raul::URI& uri, const Raul::Atom& va sigc::mem_fun(this, &PropertiesWindow::value_edited), uri)); return widget; - } else if (value.type() == Atom::FLOAT) { + } else if (value.type() == forge.Float) { Gtk::SpinButton* widget = manage(new Gtk::SpinButton(0.0, 4)); widget->property_numeric() = true; widget->set_snap_to_ticks(false); @@ -159,21 +179,21 @@ PropertiesWindow::create_value_widget(const Raul::URI& uri, const Raul::Atom& va sigc::mem_fun(this, &PropertiesWindow::value_edited), uri)); return widget; - } else if (value.type() == Atom::BOOL) { + } else if (value.type() == forge.Bool) { Gtk::CheckButton* widget = manage(new Gtk::CheckButton()); widget->set_active(value.get_bool()); widget->signal_toggled().connect(sigc::bind( sigc::mem_fun(this, &PropertiesWindow::value_edited), uri)); return widget; - } else if (value.type() == Atom::URI) { + } else if (value.type() == forge.URI) { Gtk::Entry* widget = manage(new Gtk::Entry()); widget->set_text(value.get_uri()); widget->signal_changed().connect(sigc::bind( sigc::mem_fun(this, &PropertiesWindow::value_edited), uri)); return widget; - } else if (value.type() == Atom::STRING) { + } else if (value.type() == forge.String) { Gtk::Entry* widget = manage(new Gtk::Entry()); widget->set_text(value.get_string()); widget->signal_changed().connect(sigc::bind( @@ -182,7 +202,7 @@ PropertiesWindow::create_value_widget(const Raul::URI& uri, const Raul::Atom& va return widget; } - LOG(error) << "Unable to create widget for value " << value << endl; + LOG(error) << "Unable to create widget for value " << forge.str(value) << endl; return NULL; } @@ -242,28 +262,29 @@ PropertiesWindow::value_edited(const Raul::URI& predicate) return; } - Record& record = r->second; - Raul::Atom::Type type = (*record.type_widget->get_active())[_type_cols.type]; - if (type == Atom::INT) { + Forge& forge = _app->forge(); + Record& record = r->second; + Raul::Atom::TypeID type = (*record.type_widget->get_active())[_type_cols.type]; + if (type == forge.Int) { Gtk::SpinButton* widget = dynamic_cast(record.value_widget->get_child()); if (!widget) goto bad_type; record.value = _app->forge().make(widget->get_value_as_int()); - } else if (type == Atom::FLOAT) { + } else if (type == forge.Float) { Gtk::SpinButton* widget = dynamic_cast(record.value_widget->get_child()); if (!widget) goto bad_type; record.value = _app->forge().make(static_cast(widget->get_value())); - } else if (type == Atom::BOOL) { + } else if (type == forge.Bool) { Gtk::CheckButton* widget = dynamic_cast(record.value_widget->get_child()); if (!widget) goto bad_type; record.value = _app->forge().make(widget->get_active()); - } else if (type == Atom::URI) { + } else if (type == forge.URI) { Gtk::Entry* widget = dynamic_cast(record.value_widget->get_child()); if (!widget) goto bad_type; - record.value = _app->forge().alloc(Atom::URI, widget->get_text()); - } else if (type == Atom::STRING) { + record.value = _app->forge().alloc_uri(widget->get_text()); + } else if (type == forge.String) { Gtk::Entry* widget = dynamic_cast(record.value_widget->get_child()); if (!widget) goto bad_type; - record.value = _app->forge().alloc(Atom::URI, widget->get_text()); + record.value = _app->forge().alloc_uri(widget->get_text()); } return; @@ -290,8 +311,7 @@ PropertiesWindow::apply_clicked() const Record& record = r->second; if (!_model->has_property(uri, record.value)) { LOG(debug) << "\t" << uri - << " = " << record.value - << " :: " << record.value.type() << endl; + << " = " << _app->forge().str(record.value) << endl; properties.insert(make_pair(uri, record.value)); } } diff --git a/src/gui/PropertiesWindow.hpp b/src/gui/PropertiesWindow.hpp index 43ed4023..58c4c8a0 100644 --- a/src/gui/PropertiesWindow.hpp +++ b/src/gui/PropertiesWindow.hpp @@ -63,12 +63,13 @@ private: public: TypeColumns() { add(type); add(choice); } - Gtk::TreeModelColumn type; - Gtk::TreeModelColumn choice; + Gtk::TreeModelColumn type; + Gtk::TreeModelColumn choice; }; Gtk::Widget* create_value_widget(const Raul::URI& uri, const Raul::Atom& value); + void init(); void reset(); void on_show(); @@ -94,6 +95,7 @@ private: Gtk::Button* _cancel_button; Gtk::Button* _apply_button; Gtk::Button* _ok_button; + bool _initialised : 1; }; } // namespace GUI diff --git a/src/gui/RenameWindow.cpp b/src/gui/RenameWindow.cpp index 49323c4e..18c1e236 100644 --- a/src/gui/RenameWindow.cpp +++ b/src/gui/RenameWindow.cpp @@ -65,7 +65,7 @@ RenameWindow::set_object(SharedPtr object) _symbol_entry->set_text(object->path().symbol()); const Atom& name_atom = object->get_property("http://lv2plug.in/ns/lv2core#name"); _label_entry->set_text( - (name_atom.type() == Atom::STRING) ? name_atom.get_string() : ""); + (name_atom.type() == _app->forge().String) ? name_atom.get_string() : ""); } void diff --git a/src/gui/WindowFactory.cpp b/src/gui/WindowFactory.cpp index 811e697e..abbc4357 100644 --- a/src/gui/WindowFactory.cpp +++ b/src/gui/WindowFactory.cpp @@ -259,9 +259,11 @@ WindowFactory::present_load_plugin(SharedPtr patch, _load_plugin_win->set_modal(false); _load_plugin_win->set_type_hint(Gdk::WINDOW_TYPE_HINT_DIALOG); - int width, height; - w->second->get_size(width, height); - _load_plugin_win->set_default_size(width - width / 8, height / 2); + if (w->second) { + int width, height; + w->second->get_size(width, height); + _load_plugin_win->set_default_size(width - width / 8, height / 2); + } _load_plugin_win->set_title( string("Load Plugin - ") + patch->path().chop_scheme() + " - Ingen"); _load_plugin_win->present(patch, data); diff --git a/src/gui/ingen_gui_lv2.cpp b/src/gui/ingen_gui_lv2.cpp index 9898005e..0004b935 100644 --- a/src/gui/ingen_gui_lv2.cpp +++ b/src/gui/ingen_gui_lv2.cpp @@ -18,6 +18,7 @@ #include "ingen/client/ClientStore.hpp" #include "ingen/client/PatchModel.hpp" #include "ingen/client/SigClientInterface.hpp" +#include "ingen/shared/AtomReader.hpp" #include "ingen/shared/AtomSink.hpp" #include "ingen/shared/AtomWriter.hpp" #include "ingen/shared/Configuration.hpp" @@ -55,20 +56,21 @@ struct IngenLV2AtomSink : public Ingen::Shared::AtomSink { struct IngenLV2UI { IngenLV2UI() - : conf(&forge) + : conf() , sink(NULL) { } int argc; char** argv; - Raul::Forge forge; + Ingen::Forge* forge; Ingen::Shared::Configuration conf; Ingen::Shared::World* world; IngenLV2AtomSink* sink; SharedPtr app; SharedPtr view; SharedPtr engine; + SharedPtr reader; SharedPtr client; }; @@ -98,6 +100,8 @@ instantiate(const LV2UI_Descriptor* descriptor, ui->world = new Ingen::Shared::World( &ui->conf, ui->argc, ui->argv, map, unmap); + ui->forge = new Ingen::Forge(*ui->world->lv2_uri_map().get()); + if (!ui->world->load_module("client")) { delete ui; return NULL; @@ -120,6 +124,13 @@ instantiate(const LV2UI_Descriptor* descriptor, new Ingen::Client::SigClientInterface()); ui->app->attach(ui->client); + ui->reader = SharedPtr( + new Ingen::Shared::AtomReader(*ui->world->lv2_uri_map().get(), + *ui->world->uris().get(), + ui->world->forge(), + *ui->client.get())); + + // Create empty root patch model Ingen::Resource::Properties props; props.insert(std::make_pair(ui->app->uris().rdf_type, @@ -150,6 +161,9 @@ port_event(LV2UI_Handle handle, uint32_t format, const void* buffer) { + IngenLV2UI* ui = (IngenLV2UI*)handle; + LV2_Atom* atom = (LV2_Atom*)buffer; + ui->reader->write(atom); } const void* diff --git a/src/ingen/main.cpp b/src/ingen/main.cpp index 2a9645af..5460aee0 100644 --- a/src/ingen/main.cpp +++ b/src/ingen/main.cpp @@ -84,8 +84,7 @@ ingen_try(bool cond, const char* msg) int main(int argc, char** argv) { - Raul::Forge forge; - Shared::Configuration conf(&forge); + Shared::Configuration conf; // Parse command line options try { @@ -116,7 +115,7 @@ main(int argc, char** argv) world = new Ingen::Shared::World(&conf, argc, argv, NULL, NULL); - if (conf.option("uuid").get_string()) { + if (conf.option("uuid").is_valid()) { world->set_jack_uuid(conf.option("uuid").get_string()); } @@ -186,8 +185,8 @@ main(int argc, char** argv) if (conf.option("load").is_valid() || !conf.files().empty()) { boost::optional parent; boost::optional symbol; - const Raul::Atom& path_option = conf.option("path"); - + + const Raul::Configuration::Value& path_option = conf.option("path"); if (path_option.is_valid()) { if (Path::is_valid(path_option.get_string())) { const Path p(path_option.get_string()); diff --git a/src/serialisation/Parser.cpp b/src/serialisation/Parser.cpp index 9acd460c..19c1f957 100644 --- a/src/serialisation/Parser.cpp +++ b/src/serialisation/Parser.cpp @@ -15,30 +15,23 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include - #include -#include - #include #include #include #include +#include "ingen/Interface.hpp" +#include "ingen/serialisation/Parser.hpp" +#include "ingen/shared/LV2URIMap.hpp" +#include "ingen/shared/URIs.hpp" +#include "ingen/shared/World.hpp" #include "raul/Atom.hpp" -#include "raul/AtomRDF.hpp" #include "raul/log.hpp" - #include "serd/serd.h" #include "sord/sordmm.hpp" - -#include "ingen/Interface.hpp" -#include "ingen/shared/World.hpp" -#include "ingen/shared/LV2URIMap.hpp" -#include "ingen/shared/URIs.hpp" - -#include "ingen/serialisation/Parser.hpp" +#include "sratom/sratom.h" #define LOG(s) s << "[Parser] " @@ -103,18 +96,46 @@ skip_property(const Sord::Node& predicate) } static Resource::Properties -get_properties(Raul::Forge& forge, - Sord::Model& model, - const Sord::Node& subject) +get_properties(Ingen::Shared::World* world, + Sord::Model& model, + const Sord::Node& subject) { + SerdChunk out = { NULL, 0 }; + LV2_URID_Map* map = &world->lv2_uri_map()->urid_map_feature()->urid_map; + LV2_URID_Unmap* unmap = &world->lv2_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); + Resource::Properties props; for (Sord::Iter i = model.find(subject, nil, nil); !i.end(); ++i) { if (!skip_property(i.get_predicate())) { - props.insert( - make_pair(i.get_predicate().to_string(), - AtomRDF::node_to_atom(forge, model, i.get_object()))); + out.len = 0; + sratom_read(sratom, &forge, world->rdf_world()->c_obj(), + model.c_obj(), i.get_object().c_obj()); + LV2_Atom* atom = (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, *(uint32_t*)LV2_ATOM_BODY(atom))); + } else { + atomm = world->forge().alloc( + atom->size, atom->type, LV2_ATOM_BODY(atom)); + } + /* + std::cerr << "READ PROPERTY " << i.get_predicate() + << " = " << world->forge().str(atomm) + << " :: " << unmap->unmap(unmap->handle, atom->type) + << std::endl; + */ + props.insert(make_pair(i.get_predicate().to_string(), atomm)); } } + + sratom_free(sratom); return props; } @@ -130,12 +151,12 @@ get_port(Ingen::Shared::World* world, const URIs& uris = *world->uris().get(); // Get all properties - Resource::Properties props = get_properties(world->forge(), model, subject); + Resource::Properties props = get_properties(world, model, subject); // Get index Resource::Properties::const_iterator i = props.find(uris.lv2_index); if (i == props.end() - || i->second.type() != Atom::INT + || i->second.type() != world->forge().Int || i->second.get_int32() < 0) { LOG(error) << "Port " << subject << " has no valid lv2:index" << endl; return -1; @@ -254,9 +275,9 @@ parse_node(Ingen::Shared::World* world, parse_patch(world, target, model, subject, path.parent(), Raul::Symbol(path.symbol())); } else { - Resource::Properties props = get_properties(world->forge(), model, subject); + Resource::Properties props = get_properties(world, model, subject); props.insert(make_pair(uris.rdf_type, - Raul::URI(uris.ingen_Node))); + uris.forge.alloc_uri(uris.ingen_Node.str()))); target->put(path, props); } return path; @@ -275,7 +296,6 @@ parse_patch(Ingen::Shared::World* world, const Sord::URI ingen_polyphony(*world->rdf_world(), NS_INGEN "polyphony"); const Sord::URI lv2_port(*world->rdf_world(), NS_LV2 "port"); - Raul::Forge& forge = world->forge(); const URIs& uris = *world->uris().get(); const Sord::Node& patch = subject_node; @@ -284,8 +304,10 @@ parse_patch(Ingen::Shared::World* world, // Use parameter overridden polyphony, if given if (data) { GraphObject::Properties::iterator poly_param = data.get().find(uris.ingen_polyphony); - if (poly_param != data.get().end() && poly_param->second.type() == Atom::INT) + if (poly_param != data.get().end() && + poly_param->second.type() == world->forge().Int) { patch_poly = poly_param->second.get_int32(); + } } // Load polyphony from file if necessary @@ -324,7 +346,7 @@ parse_patch(Ingen::Shared::World* world, // Create patch Path patch_path(patch_path_str); - Resource::Properties props = get_properties(forge, model, subject_node); + Resource::Properties props = get_properties(world, model, subject_node); target->put(patch_path, props); // For each node in this patch @@ -438,16 +460,7 @@ parse_properties(Ingen::Shared::World* world, const Raul::URI& uri, boost::optional data) { - Resource::Properties properties; - for (Sord::Iter i = model.find(subject, nil, nil); !i.end(); ++i) { - const Sord::Node& key = i.get_predicate(); - const Sord::Node& val = i.get_object(); - if (!skip_property(key)) { - properties.insert( - make_pair(key.to_string(), - AtomRDF::node_to_atom(world->forge(), model, val))); - } - } + Resource::Properties properties = get_properties(world, model, subject); target->put(uri, properties); @@ -588,7 +601,7 @@ Parser::parse_file(Ingen::Shared::World* world, if (parsed_path) { target->set_property(*parsed_path, "http://drobilla.net/ns/ingen#document", - world->forge().alloc(Atom::URI, uri.c_str())); + world->forge().alloc_uri(uri)); } else { LOG(warn) << "Document URI lost" << endl; } diff --git a/src/serialisation/Serialiser.cpp b/src/serialisation/Serialiser.cpp index 2ea07af3..224785b6 100644 --- a/src/serialisation/Serialiser.cpp +++ b/src/serialisation/Serialiser.cpp @@ -15,19 +15,12 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include - #include #include #include #include #include -#include -#include -#include #include -#include -#include #include #include @@ -36,26 +29,23 @@ #include #include -#include "raul/Atom.hpp" -#include "raul/AtomRDF.hpp" -#include "raul/Path.hpp" -#include "raul/log.hpp" - -#include "sord/sordmm.hpp" - #include "ingen/Connection.hpp" +#include "ingen/Interface.hpp" #include "ingen/Node.hpp" #include "ingen/Patch.hpp" #include "ingen/Plugin.hpp" #include "ingen/Port.hpp" -#include "ingen/Interface.hpp" +#include "ingen/serialisation/Serialiser.hpp" #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/ResourceImpl.hpp" #include "ingen/shared/Store.hpp" #include "ingen/shared/URIs.hpp" #include "ingen/shared/World.hpp" - -#include "ingen/serialisation/Serialiser.hpp" +#include "raul/Atom.hpp" +#include "raul/Path.hpp" +#include "raul/log.hpp" +#include "sord/sordmm.hpp" +#include "sratom/sratom.h" #define LOG(s) s << "[Serialiser] " @@ -227,21 +217,11 @@ Serialiser::Impl::write_bundle(SharedPtr patch, } string -Serialiser::to_string(SharedPtr object, - const string& base_uri, - const GraphObject::Properties& extra_rdf) +Serialiser::to_string(SharedPtr object, + const string& base_uri) { start_to_string(object->path(), base_uri); serialise(object); - - Sord::URI base_rdf_node(me->_model->world(), base_uri); - for (GraphObject::Properties::const_iterator v = extra_rdf.begin(); - v != extra_rdf.end(); ++v) { - me->_model->add_statement(base_rdf_node, - AtomRDF::atom_to_node(*me->_model, v->first), - AtomRDF::atom_to_node(*me->_model, v->second)); - } - return finish(); } @@ -252,8 +232,6 @@ Serialiser::to_string(SharedPtr object, void Serialiser::Impl::start_to_filename(const string& filename) { - setlocale(LC_NUMERIC, "C"); - assert(filename.find(":") == string::npos || filename.substr(0, 5) == "file:"); if (filename.find(":") == string::npos) { _base_uri = "file://" + filename; @@ -278,8 +256,6 @@ Serialiser::Impl::start_to_filename(const string& filename) void Serialiser::start_to_string(const Raul::Path& root, const string& base_uri) { - setlocale(LC_NUMERIC, "C"); - me->_root_path = root; me->_base_uri = base_uri; me->_model = new Sord::Model(*me->_world.rdf_world(), base_uri); @@ -328,7 +304,7 @@ void Serialiser::serialise(SharedPtr object) throw (std::logic_error) { if (!me->_model) - throw std::logic_error("serialise called without serialization in progress"); + throw std::logic_error("serialise called without serialisation in progress"); SharedPtr patch = PtrCast(object); if (patch) { @@ -372,13 +348,17 @@ Serialiser::Impl::serialise_patch(SharedPtr patch, Sord::Curie(world, "lv2:extensionData"), Sord::URI(world, "http://lv2plug.in/ns/ext/state#Interface")); + _model->add_statement(patch_id, + Sord::URI(world, "http://lv2plug.in/ns/extensions/ui#ui"), + Sord::URI(world, "http://drobilla.net/ns/ingen#ui")); + const URIs& uris = *_world.uris().get(); // Always write a symbol (required by Ingen) string symbol; GraphObject::Properties::const_iterator s = patch->properties().find(uris.lv2_symbol); if (s == patch->properties().end() - || !s->second.type() == Atom::STRING + || !s->second.type() == _world.forge().String || !Symbol::is_valid(s->second.get_string())) { symbol = Glib::path_get_basename(_model->base_uri().to_c_string()); symbol = Symbol::symbolify(symbol.substr(0, symbol.find('.'))); @@ -393,7 +373,7 @@ Serialiser::Impl::serialise_patch(SharedPtr patch, // If the patch has no doap:name (required by LV2), use the symbol if (patch->properties().find(uris.doap_name) == patch->properties().end()) _model->add_statement(patch_id, - AtomRDF::atom_to_node(*_model, uris.doap_name), + Sord::URI(world, uris.doap_name.str()), Sord::Literal(world, symbol)); serialise_properties(patch.get(), Resource::INTERNAL, patch_id); @@ -455,7 +435,7 @@ Serialiser::Impl::serialise_patch(SharedPtr patch, // Ensure lv2:name always exists so Patch is a valid LV2 plugin if (p->properties().find(NS_LV2 "name") == p->properties().end()) p->set_property(NS_LV2 "name", - _world.forge().make(p->symbol().c_str())); + _world.forge().alloc(p->symbol().c_str())); _model->add_statement(patch_id, Sord::URI(world, NS_LV2 "port"), @@ -518,13 +498,6 @@ Serialiser::Impl::serialise_port(const Port* port, Sord::Literal(world, port->path().symbol())); serialise_properties(port, context, port_id); - - if (context == Resource::INTERNAL) { - _model->add_statement( - port_id, - Sord::Curie(world, "lv2:index"), - AtomRDF::atom_to_node(*_model, _world.forge().make((int)port->index()))); - } } void @@ -542,7 +515,7 @@ Serialiser::Impl::serialise_connection(const Sord::Node& parent, { if (!_model) throw std::logic_error( - "serialise_connection called without serialization in progress"); + "serialise_connection called without serialisation in progress"); Sord::World& world = _model->world(); @@ -575,19 +548,32 @@ Serialiser::Impl::serialise_properties(const GraphObject* o, { const GraphObject::Properties props = o->properties(context); + LV2_URID_Map* map = &_world.lv2_uri_map()->urid_map_feature()->urid_map; + LV2_URID_Unmap* unmap = &_world.lv2_uri_map()->urid_unmap_feature()->urid_unmap; + Sratom* sratom = sratom_new(map); + 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, true); + typedef GraphObject::Properties::const_iterator iterator; for (iterator v = props.begin(); v != props.end(); ++v) { - const Sord::URI key(_model->world(), v->first.str()); - const Sord::Node value(AtomRDF::atom_to_node(*_model, v->second)); + const Sord::URI key(_model->world(), v->first.str()); if (!skip_property(key)) { - if (value.is_valid()) { - _model->add_statement(id, key, value); - } else { - LOG(warn) << "Can not serialise variable '" << v->first << "' :: " - << (int)v->second.type() << endl; - } + sratom_write(sratom, unmap, 0, + sord_node_to_serd_node(id.c_obj()), + sord_node_to_serd_node(key.c_obj()), + v->second.type(), v->second.size(), v->second.get_body()); } } + + sord_inserter_free(inserter); + serd_env_free(env); + sratom_free(sratom); } } // namespace Serialisation diff --git a/src/serialisation/sratom/sratom.c b/src/serialisation/sratom/sratom.c new file mode 100644 index 00000000..646d4623 --- /dev/null +++ b/src/serialisation/sratom/sratom.c @@ -0,0 +1,731 @@ +/* + Copyright 2012 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include +#include +#include +#include + +#include "lv2/lv2plug.in/ns/ext/atom/forge.h" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" + +#include "sratom/sratom.h" + +#define NS_MIDI (const uint8_t*)"http://lv2plug.in/ns/ext/midi#" +#define NS_RDF (const uint8_t*)"http://www.w3.org/1999/02/22-rdf-syntax-ns#" +#define NS_XSD (const uint8_t*)"http://www.w3.org/2001/XMLSchema#" + +#define USTR(str) ((const uint8_t*)(str)) + +typedef enum { + MODE_NORMAL, + MODE_SEQUENCE, +} ReadMode; + +struct SratomImpl { + LV2_URID_Map* map; + LV2_Atom_Forge forge; + LV2_URID atom_Event; + LV2_URID midi_MidiEvent; + unsigned next_id; + SerdNode base_uri; + SerdStatementSink write_statement; + SerdEndSink end_anon; + void* handle; + bool pretty_numbers; + struct { + SordNode* atom_childType; + SordNode* atom_frameTime; + SordNode* rdf_first; + SordNode* rdf_rest; + SordNode* rdf_type; + SordNode* rdf_value; + SordNode* xsd_base64Binary; + } nodes; +}; + +static void +read_node(Sratom* sratom, + LV2_Atom_Forge* forge, + SordWorld* world, + SordModel* model, + const SordNode* node, + ReadMode mode); + +SRATOM_API +Sratom* +sratom_new(LV2_URID_Map* map) +{ + Sratom* sratom = (Sratom*)malloc(sizeof(Sratom)); + sratom->map = map; + sratom->atom_Event = map->map(map->handle, LV2_ATOM__Event); + sratom->midi_MidiEvent = map->map(map->handle, + (const char*)NS_MIDI "MidiEvent"); + sratom->next_id = 0; + sratom->base_uri = SERD_NODE_NULL; + sratom->pretty_numbers = false; + memset(&sratom->nodes, 0, sizeof(sratom->nodes)); + lv2_atom_forge_init(&sratom->forge, map); + return sratom; +} + +SRATOM_API +void +sratom_free(Sratom* sratom) +{ + free(sratom); +} + +SRATOM_API +void +sratom_set_sink(Sratom* sratom, + const char* base_uri, + SerdStatementSink write_statement, + SerdEndSink end_anon, + void* handle, + bool pretty_numbers) +{ + if (base_uri) { + serd_node_free(&sratom->base_uri); + sratom->base_uri = serd_node_new_uri_from_string( + USTR(base_uri), NULL, NULL); + } + sratom->write_statement = write_statement; + sratom->end_anon = end_anon; + sratom->handle = handle; + sratom->pretty_numbers = pretty_numbers; +} + +static void +gensym(SerdNode* out, char c, unsigned num) +{ + out->n_bytes = out->n_chars = snprintf( + (char*)out->buf, 10, "%c%u", c, num); +} + +static void +list_append(Sratom* sratom, + LV2_URID_Unmap* unmap, + unsigned* flags, + SerdNode* s, + SerdNode* p, + SerdNode* node, + uint32_t size, + uint32_t type, + void* body) +{ + // Generate a list node + gensym(node, 'l', sratom->next_id); + sratom->write_statement(sratom->handle, *flags, NULL, + s, p, node, NULL, NULL); + + // _:node rdf:first value + *flags = SERD_LIST_CONT; + *p = serd_node_from_string(SERD_URI, NS_RDF "first"); + sratom_write(sratom, unmap, *flags, node, p, type, size, body); + + // Set subject to node and predicate to rdf:rest for next time + gensym(node, 'l', ++sratom->next_id); + *s = *node; + *p = serd_node_from_string(SERD_URI, NS_RDF "rest"); +} + +static void +list_end(SerdStatementSink sink, + void* handle, + unsigned* flags, + SerdNode* s, + SerdNode* p) +{ + // _:node rdf:rest rdf:nil + const SerdNode nil = serd_node_from_string(SERD_URI, NS_RDF "nil"); + sink(handle, *flags, NULL, s, p, &nil, NULL, NULL); +} + +static void +start_object(Sratom* sratom, + uint32_t flags, + const SerdNode* subject, + const SerdNode* predicate, + const SerdNode* node, + const char* type) +{ + sratom->write_statement(sratom->handle, flags|SERD_ANON_O_BEGIN, NULL, + subject, predicate, node, NULL, NULL); + if (type) { + SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "type"); + SerdNode o = serd_node_from_string(SERD_URI, USTR(type)); + sratom->write_statement(sratom->handle, SERD_ANON_CONT, NULL, + node, &p, &o, NULL, NULL); + } +} + +static bool +path_is_absolute(const char* path) +{ + return (path[0] == '/' + || (isalpha(path[0]) && path[1] == ':' + && (path[2] == '/' || path[2] == '\\'))); +} + +SRATOM_API +int +sratom_write(Sratom* sratom, + LV2_URID_Unmap* unmap, + uint32_t flags, + const SerdNode* subject, + const SerdNode* predicate, + uint32_t type_urid, + uint32_t size, + const void* body) +{ + const char* const type = unmap->unmap(unmap->handle, type_urid); + uint8_t idbuf[12] = "b0000000000"; + SerdNode id = serd_node_from_string(SERD_BLANK, idbuf); + uint8_t nodebuf[12] = "b0000000000"; + SerdNode node = serd_node_from_string(SERD_BLANK, nodebuf); + SerdNode object = SERD_NODE_NULL; + SerdNode datatype = SERD_NODE_NULL; + SerdNode language = SERD_NODE_NULL; + bool new_node = false; + if (type_urid == 0 && size == 0) { + object = serd_node_from_string(SERD_URI, USTR(NS_RDF "nil")); + } else if (type_urid == sratom->forge.String) { + object = serd_node_from_string(SERD_LITERAL, (const uint8_t*)body); + } else if (type_urid == sratom->forge.Literal) { + LV2_Atom_Literal_Body* lit = (LV2_Atom_Literal_Body*)body; + const uint8_t* str = USTR(lit + 1); + object = serd_node_from_string(SERD_LITERAL, str); + if (lit->datatype) { + datatype = serd_node_from_string( + SERD_URI, USTR(unmap->unmap(unmap->handle, lit->datatype))); + } else if (lit->lang) { + const char* lang = unmap->unmap(unmap->handle, lit->lang); + const char* prefix = "http://lexvo.org/id/iso639-3/"; + const size_t prefix_len = strlen(prefix); + if (lang && !strncmp(lang, prefix, prefix_len)) { + language = serd_node_from_string( + SERD_LITERAL, USTR(lang + prefix_len)); + } else { + fprintf(stderr, "Unknown language URI <%s>\n", lang); + } + } + } else if (type_urid == sratom->forge.URID) { + const uint32_t id = *(const uint32_t*)body; + const uint8_t* str = USTR(unmap->unmap(unmap->handle, id)); + object = serd_node_from_string(SERD_URI, str); + } else if (type_urid == sratom->forge.Path) { + const uint8_t* str = USTR(body); + if (path_is_absolute((const char*)str)) { + new_node = true; + object = serd_node_new_file_uri(str, NULL, NULL, false); + } else { + SerdURI base_uri = SERD_URI_NULL; + if (!sratom->base_uri.buf || + strncmp((const char*)sratom->base_uri.buf, "file://", 7)) { + fprintf(stderr, "warning: Relative path but base is not a file URI.\n"); + fprintf(stderr, "warning: Writing ambiguous atom:Path literal.\n"); + object = serd_node_from_string(SERD_LITERAL, str); + datatype = serd_node_from_string(SERD_URI, USTR(LV2_ATOM__Path)); + } else { + if (sratom->base_uri.buf) { + serd_uri_parse(sratom->base_uri.buf, &base_uri); + } + new_node = true; + SerdNode rel = serd_node_new_file_uri(str, NULL, NULL, false); + object = serd_node_new_uri_from_node(&rel, &base_uri, NULL); + serd_node_free(&rel); + } + } + } else if (type_urid == sratom->forge.URI) { + const uint8_t* str = USTR(body); + object = serd_node_from_string(SERD_URI, str); + } else if (type_urid == sratom->forge.Int) { + new_node = true; + object = serd_node_new_integer(*(int32_t*)body); + datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers) + ? NS_XSD "integer" : NS_XSD "int"); + } else if (type_urid == sratom->forge.Long) { + new_node = true; + object = serd_node_new_integer(*(int64_t*)body); + datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers) + ? NS_XSD "integer" : NS_XSD "long"); + } else if (type_urid == sratom->forge.Float) { + new_node = true; + object = serd_node_new_decimal(*(float*)body, 8); + datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers) + ? NS_XSD "decimal" : NS_XSD "float"); + } else if (type_urid == sratom->forge.Double) { + new_node = true; + object = serd_node_new_decimal(*(double*)body, 16); + datatype = serd_node_from_string(SERD_URI, (sratom->pretty_numbers) + ? NS_XSD "decimal" : NS_XSD "double"); + } else if (type_urid == sratom->forge.Bool) { + const int32_t val = *(const int32_t*)body; + datatype = serd_node_from_string(SERD_URI, NS_XSD "boolean"); + object = serd_node_from_string(SERD_LITERAL, + USTR(val ? "true" : "false")); + } else if (type_urid == sratom->midi_MidiEvent) { + new_node = true; + datatype = serd_node_from_string(SERD_URI, NS_MIDI "MidiEvent"); + uint8_t* str = calloc(size * 2 + 1, 1); + for (uint32_t i = 0; i < size; ++i) { + snprintf((char*)str + (2 * i), size * 2 + 1, "%02X", + (unsigned)(uint8_t)*((uint8_t*)body + i)); + } + object = serd_node_from_string(SERD_LITERAL, USTR(str)); + } else if (type_urid == sratom->atom_Event) { + const LV2_Atom_Event* ev = (const LV2_Atom_Event*)body; + gensym(&id, 'e', sratom->next_id++); + start_object(sratom, flags, subject, predicate, &id, NULL); + // TODO: beat time + SerdNode time = serd_node_new_integer(ev->time.frames); + SerdNode p = serd_node_from_string(SERD_URI, + USTR(LV2_ATOM__frameTime)); + datatype = serd_node_from_string(SERD_URI, NS_XSD "decimal"); + sratom->write_statement(sratom->handle, SERD_ANON_CONT, NULL, + &id, &p, &time, &datatype, &language); + serd_node_free(&time); + + p = serd_node_from_string(SERD_URI, NS_RDF "value"); + sratom_write(sratom, unmap, SERD_ANON_CONT, &id, &p, + ev->body.type, ev->body.size, LV2_ATOM_BODY(&ev->body)); + if (sratom->end_anon) { + sratom->end_anon(sratom->handle, &id); + } + } else if (type_urid == sratom->forge.Tuple) { + gensym(&id, 't', sratom->next_id++); + start_object(sratom, flags, subject, predicate, &id, type); + SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value"); + flags |= SERD_LIST_O_BEGIN; + LV2_TUPLE_BODY_FOREACH(body, size, i) { + list_append(sratom, unmap, &flags, &id, &p, &node, + i->size, i->type, LV2_ATOM_BODY(i)); + } + list_end(sratom->write_statement, sratom->handle, &flags, &id, &p); + if (sratom->end_anon) { + sratom->end_anon(sratom->handle, &id); + } + } else if (type_urid == sratom->forge.Vector) { + const LV2_Atom_Vector_Body* vec = (const LV2_Atom_Vector_Body*)body; + gensym(&id, 'v', sratom->next_id++); + start_object(sratom, flags, subject, predicate, &id, type); + SerdNode p = serd_node_from_string(SERD_URI, (const uint8_t*)LV2_ATOM__childType); + SerdNode child_type = serd_node_from_string( + SERD_URI, (const uint8_t*)unmap->unmap(unmap->handle, vec->child_type)); + sratom->write_statement(sratom->handle, flags, NULL, &id, &p, &child_type, NULL, NULL); + p = serd_node_from_string(SERD_URI, NS_RDF "value"); + flags |= SERD_LIST_O_BEGIN; + for (char* i = (char*)(vec + 1); + i < (char*)vec + size; + i += vec->child_size) { + list_append(sratom, unmap, &flags, &id, &p, &node, + vec->child_size, vec->child_type, i); + } + list_end(sratom->write_statement, sratom->handle, &flags, &id, &p); + if (sratom->end_anon) { + sratom->end_anon(sratom->handle, &id); + } + } else if (type_urid == sratom->forge.Blank) { + const LV2_Atom_Object_Body* obj = (const LV2_Atom_Object_Body*)body; + const char* otype = unmap->unmap(unmap->handle, + obj->otype); + gensym(&id, 'b', sratom->next_id++); + start_object(sratom, flags, subject, predicate, &id, otype); + LV2_OBJECT_BODY_FOREACH(obj, size, i) { + const LV2_Atom_Property_Body* prop = lv2_object_iter_get(i); + const char* const key = unmap->unmap(unmap->handle, prop->key); + SerdNode pred = serd_node_from_string(SERD_URI, USTR(key)); + sratom_write(sratom, unmap, flags|SERD_ANON_CONT, &id, &pred, + prop->value.type, prop->value.size, + LV2_ATOM_BODY(&prop->value)); + } + if (sratom->end_anon) { + sratom->end_anon(sratom->handle, &id); + } + } else if (type_urid == sratom->forge.Sequence) { + const LV2_Atom_Sequence_Body* seq = (const LV2_Atom_Sequence_Body*)body; + gensym(&id, 'v', sratom->next_id++); + start_object(sratom, flags, subject, predicate, &id, type); + SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value"); + flags |= SERD_LIST_O_BEGIN; + LV2_SEQUENCE_BODY_FOREACH(seq, size, i) { + LV2_Atom_Event* ev = lv2_sequence_iter_get(i); + list_append(sratom, unmap, &flags, &id, &p, &node, + sizeof(LV2_Atom_Event) + ev->body.size, + sratom->atom_Event, + ev); + } + list_end(sratom->write_statement, sratom->handle, &flags, &id, &p); + if (sratom->end_anon) { + sratom->end_anon(sratom->handle, &id); + } + } else { + gensym(&id, 'b', sratom->next_id++); + start_object(sratom, flags, subject, predicate, &id, type); + SerdNode p = serd_node_from_string(SERD_URI, NS_RDF "value"); + SerdNode o = serd_node_new_blob(body, size, true); + datatype = serd_node_from_string(SERD_URI, NS_XSD "base64Binary"); + sratom->write_statement(sratom->handle, flags, NULL, &id, &p, &o, &datatype, NULL); + if (sratom->end_anon) { + sratom->end_anon(sratom->handle, &id); + } + serd_node_free(&o); + } + + if (object.buf) { + sratom->write_statement(sratom->handle, flags, NULL, + subject, predicate, &object, &datatype, &language); + } + + if (new_node) { + serd_node_free(&object); + } + + return 0; +} + +SRATOM_API +char* +sratom_to_turtle(Sratom* sratom, + LV2_URID_Unmap* unmap, + const char* base_uri, + const SerdNode* subject, + const SerdNode* predicate, + uint32_t type, + uint32_t size, + const void* body) +{ + SerdURI buri = SERD_URI_NULL; + SerdNode base = serd_node_new_uri_from_string(USTR(base_uri), NULL, &buri); + SerdEnv* env = serd_env_new(&base); + SerdChunk str = { NULL, 0 }; + + serd_env_set_prefix_from_strings(env, USTR("midi"), NS_MIDI); + serd_env_set_prefix_from_strings(env, USTR("atom"), + USTR(LV2_ATOM_URI "#")); + serd_env_set_prefix_from_strings(env, USTR("rdf"), NS_RDF); + serd_env_set_prefix_from_strings(env, USTR("xsd"), NS_XSD); + serd_env_set_prefix_from_strings(env, USTR("eg"), + USTR("http://example.org/")); + + SerdWriter* writer = serd_writer_new( + SERD_TURTLE, + SERD_STYLE_ABBREVIATED|SERD_STYLE_RESOLVED|SERD_STYLE_CURIED, + env, &buri, serd_chunk_sink, &str); + + // Write @prefix directives + serd_env_foreach(env, + (SerdPrefixSink)serd_writer_set_prefix, + writer); + + sratom_set_sink(sratom, base_uri, + (SerdStatementSink)serd_writer_write_statement, + (SerdEndSink)serd_writer_end_anon, + writer, + false); + sratom_write(sratom, unmap, SERD_EMPTY_S, + subject, predicate, type, size, body); + serd_writer_finish(writer); + + serd_writer_free(writer); + serd_env_free(env); + return (char*)serd_chunk_sink_finish(&str); +} + +static const SordNode* +get_object(SordModel* model, + const SordNode* subject, + const SordNode* predicate) +{ + const SordNode* object = NULL; + SordQuad q = { subject, predicate, 0, 0 }; + SordIter* i = sord_find(model, q); + if (!sord_iter_end(i)) { + SordQuad quad; + sord_iter_get(i, quad); + object = quad[SORD_OBJECT]; + } + sord_iter_free(i); + return object; +} + +static void +read_list_value(Sratom* sratom, + LV2_Atom_Forge* forge, + SordWorld* world, + SordModel* model, + const SordNode* node, + ReadMode mode) +{ + const SordNode* first = get_object(model, node, sratom->nodes.rdf_first); + const SordNode* rest = get_object(model, node, sratom->nodes.rdf_rest); + if (first && rest) { + read_node(sratom, forge, world, model, first, mode); + read_list_value(sratom, forge, world, model, rest, mode); + } +} + +static uint32_t +atom_size(Sratom* sratom, uint32_t type_urid) +{ + if (type_urid == sratom->forge.Int) { + return sizeof(int32_t); + } else if (type_urid == sratom->forge.Long) { + return sizeof(int64_t); + } else if (type_urid == sratom->forge.Float) { + return sizeof(float); + } else if (type_urid == sratom->forge.Double) { + return sizeof(double); + } else if (type_urid == sratom->forge.Bool) { + return sizeof(int32_t); + } else if (type_urid == sratom->forge.URID) { + return sizeof(uint32_t); + } else { + return 0; + } +} + +static void +read_node(Sratom* sratom, + LV2_Atom_Forge* forge, + SordWorld* world, + SordModel* model, + const SordNode* node, + ReadMode mode) +{ + LV2_URID_Map* map = sratom->map; + size_t len = 0; + const char* str = (const char*)sord_node_get_string_counted(node, &len); + if (sord_node_get_type(node) == SORD_LITERAL) { + char* endptr; + SordNode* datatype = sord_node_get_datatype(node); + const char* language = sord_node_get_language(node); + if (datatype) { + const char* type_uri = (const char*)sord_node_get_string(datatype); + if (!strcmp(type_uri, (char*)NS_XSD "int") || + !strcmp(type_uri, (char*)NS_XSD "integer")) { + lv2_atom_forge_int(forge, strtol(str, &endptr, 10)); + } else if (!strcmp(type_uri, (char*)NS_XSD "long")) { + lv2_atom_forge_long(forge, strtol(str, &endptr, 10)); + } else if (!strcmp(type_uri, (char*)NS_XSD "float") || + !strcmp(type_uri, (char*)NS_XSD "decimal")) { + lv2_atom_forge_float(forge, serd_strtod(str, &endptr)); + } else if (!strcmp(type_uri, (char*)NS_XSD "double")) { + lv2_atom_forge_double(forge, serd_strtod(str, &endptr)); + } else if (!strcmp(type_uri, (char*)NS_XSD "boolean")) { + lv2_atom_forge_bool(forge, !strcmp(str, "true")); + } else if (!strcmp(type_uri, LV2_ATOM__Path)) { + lv2_atom_forge_path(forge, str, len); + } else if (!strcmp(type_uri, (char*)NS_MIDI "MidiEvent")) { + lv2_atom_forge_atom(forge, len / 2, sratom->midi_MidiEvent); + for (const char* s = str; s < str + len; s += 2) { + unsigned num; + sscanf(s, "%2X", &num); + assert(num < UINT8_MAX); + const uint8_t c = num; + lv2_atom_forge_raw(forge, &c, 1); + } + lv2_atom_forge_pad(forge, len / 2); + } else { + lv2_atom_forge_literal( + forge, str, len, + sratom->map->map(sratom->map->handle, type_uri), + 0); + } + } else if (language) { + const char* prefix = "http://lexvo.org/id/iso639-3/"; + const size_t lang_len = strlen(prefix) + strlen(language); + char* lang_uri = calloc(lang_len + 1, 1); + snprintf(lang_uri, lang_len + 1, "%s%s", prefix, language); + lv2_atom_forge_literal( + forge, str, len, 0, + sratom->map->map(sratom->map->handle, lang_uri)); + free(lang_uri); + } else { + lv2_atom_forge_string(forge, str, len); + } + } else if (sord_node_get_type(node) == SORD_URI) { + if (!strcmp(str, (const char*)NS_RDF "nil")) { + lv2_atom_forge_atom(forge, 0, 0); + } else if (!strncmp(str, "file://", 7)) { + uint8_t* path = serd_file_uri_parse((const uint8_t*)str, NULL); + lv2_atom_forge_path(forge, (const char*)path, strlen((const char*)path)); + free(path); + } else { + lv2_atom_forge_urid(forge, map->map(map->handle, str)); + } + } else { + const SordNode* type = get_object(model, node, sratom->nodes.rdf_type); + const SordNode* value = get_object(model, node, sratom->nodes.rdf_value); + + const uint8_t* type_uri = NULL; + uint32_t type_urid = 0; + if (type) { + type_uri = sord_node_get_string(type); + type_urid = map->map(map->handle, (const char*)type_uri); + } + + LV2_Atom_Forge_Frame frame = { 0, 0 }; + if (mode == MODE_SEQUENCE) { + const SordNode* frame_time = get_object( + model, node, sratom->nodes.atom_frameTime); + const char* frame_time_str = frame_time + ? (const char*)sord_node_get_string(frame_time) + : ""; + lv2_atom_forge_frame_time(forge, serd_strtod(frame_time_str, NULL)); + read_node(sratom, forge, world, model, value, MODE_NORMAL); + } else if (type_urid == sratom->forge.Tuple) { + lv2_atom_forge_tuple(forge, &frame); + read_list_value(sratom, forge, world, model, value, MODE_NORMAL); + } else if (type_urid == sratom->forge.Sequence) { + lv2_atom_forge_sequence_head(forge, &frame, 0); + read_list_value(sratom, forge, world, model, value, MODE_SEQUENCE); + } else if (type_urid == sratom->forge.Vector) { + const SordNode* child_type_node = get_object( + model, node, sratom->nodes.atom_childType); + uint32_t child_type = map->map( + map->handle, (const char*)sord_node_get_string(child_type_node)); + uint32_t child_size = atom_size(sratom, child_type); + if (child_size > 0) { + lv2_atom_forge_vector_head(forge, &frame, child_size, child_type); + read_list_value(sratom, forge, world, model, value, MODE_NORMAL); + } + } else if (value && sord_node_equals(sord_node_get_datatype(value), + sratom->nodes.xsd_base64Binary)) { + size_t vlen = 0; + const uint8_t* vstr = sord_node_get_string_counted(value, &vlen); + size_t size = 0; + void* body = serd_base64_decode(vstr, vlen, &size); + lv2_atom_forge_atom(forge, size, type_urid); + lv2_atom_forge_write(forge, body, size); + free(body); + } else { + lv2_atom_forge_blank(forge, &frame, sratom->next_id++, type_urid); + SordQuad match; + + SordQuad q2 = { node, 0, 0, 0 }; + SordIter* i = sord_find(model, q2); + for (;!sord_iter_end(i); sord_iter_next(i)) { + sord_iter_get(i, match); + const SordNode* p = match[SORD_PREDICATE]; + const char* p_uri = (const char*)sord_node_get_string(p); + uint32_t p_urid = map->map(map->handle, p_uri); + if (!sord_node_equals(p, sratom->nodes.rdf_type)) { + // TODO: This will lose multiple rdf:type properties + lv2_atom_forge_property_head(forge, p_urid, 0); + read_node(sratom, forge, world, model, + match[SORD_OBJECT], MODE_NORMAL); + } + } + sord_iter_free(i); + } + if (frame.ref) { + lv2_atom_forge_pop(forge, &frame); + } + } +} + +SRATOM_API +void +sratom_read(Sratom* sratom, + LV2_Atom_Forge* forge, + SordWorld* world, + SordModel* model, + const SordNode* node) +{ + sratom->nodes.atom_childType = sord_new_uri(world, USTR(LV2_ATOM__childType)); + sratom->nodes.atom_frameTime = sord_new_uri(world, USTR(LV2_ATOM__frameTime)); + sratom->nodes.rdf_first = sord_new_uri(world, NS_RDF "first"); + sratom->nodes.rdf_rest = sord_new_uri(world, NS_RDF "rest"); + sratom->nodes.rdf_type = sord_new_uri(world, NS_RDF "type"); + sratom->nodes.rdf_value = sord_new_uri(world, NS_RDF "value"); + sratom->nodes.xsd_base64Binary = sord_new_uri(world, NS_XSD "base64Binary"); + + sratom->next_id = 1; + read_node(sratom, forge, world, model, node, MODE_NORMAL); + + sord_node_free(world, sratom->nodes.xsd_base64Binary); + sord_node_free(world, sratom->nodes.rdf_value); + sord_node_free(world, sratom->nodes.rdf_type); + sord_node_free(world, sratom->nodes.rdf_rest); + sord_node_free(world, sratom->nodes.rdf_first); + sord_node_free(world, sratom->nodes.atom_frameTime); + sord_node_free(world, sratom->nodes.atom_childType); + memset(&sratom->nodes, 0, sizeof(sratom->nodes)); +} + +SRATOM_API +LV2_Atom_Forge_Ref +sratom_forge_sink(LV2_Atom_Forge_Sink_Handle handle, + const void* buf, + uint32_t size) +{ + SerdChunk* chunk = (SerdChunk*)handle; + const LV2_Atom_Forge_Ref ref = chunk->len + 1; + serd_chunk_sink(buf, size, chunk); + return ref; +} + +SRATOM_API +LV2_Atom* +sratom_forge_deref(LV2_Atom_Forge_Sink_Handle handle, LV2_Atom_Forge_Ref ref) +{ + SerdChunk* chunk = (SerdChunk*)handle; + return (LV2_Atom*)(chunk->buf + ref - 1); +} + +SRATOM_API +LV2_Atom* +sratom_from_turtle(Sratom* sratom, + const char* base_uri, + const SerdNode* subject, + const SerdNode* predicate, + const char* str) +{ + SerdChunk out = { NULL, 0 }; + SerdNode base = serd_node_new_uri_from_string(USTR(base_uri), NULL, NULL); + SordWorld* world = sord_world_new(); + SordModel* model = sord_new(world, SORD_SPO, false); + SerdEnv* env = serd_env_new(&base); + SerdReader* reader = sord_new_reader(model, env, SERD_TURTLE, NULL); + + if (!serd_reader_read_string(reader, (const uint8_t*)str)) { + SordNode* s = sord_node_from_serd_node(world, env, subject, 0, 0); + SordNode* p = sord_node_from_serd_node(world, env, predicate, 0, 0); + SordQuad q = { s, p, 0, 0 }; + SordIter* i = sord_find(model, q); + if (!sord_iter_end(i)) { + SordQuad result; + sord_iter_get(i, result); + lv2_atom_forge_set_sink( + &sratom->forge, sratom_forge_sink, sratom_forge_deref, &out); + sratom_read(sratom, &sratom->forge, world, model, result[SORD_OBJECT]); + } else { + fprintf(stderr, "Failed to find node\n"); + } + sord_iter_free(i); + } else { + fprintf(stderr, "Failed to read Turtle\n"); + } + + serd_reader_free(reader); + serd_env_free(env); + sord_free(model); + sord_world_free(world); + + return (LV2_Atom*)out.buf; +} diff --git a/src/serialisation/sratom/sratom.h b/src/serialisation/sratom/sratom.h new file mode 100644 index 00000000..bd4a5721 --- /dev/null +++ b/src/serialisation/sratom/sratom.h @@ -0,0 +1,176 @@ +/* + Copyright 2012 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file sratom.h API for Sratom, an LV2 Atom RDF serialisation library. +*/ + +#ifndef SRATOM_SRATOM_H +#define SRATOM_SRATOM_H + +#include + +#include "lv2/lv2plug.in/ns/ext/urid/urid.h" +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" +#include "lv2/lv2plug.in/ns/ext/atom/forge.h" +#include "serd/serd.h" +#include "sord/sord.h" + +#ifdef SRATOM_SHARED +# ifdef _WIN32 +# define SRATOM_LIB_IMPORT __declspec(dllimport) +# define SRATOM_LIB_EXPORT __declspec(dllexport) +# else +# define SRATOM_LIB_IMPORT __attribute__((visibility("default"))) +# define SRATOM_LIB_EXPORT __attribute__((visibility("default"))) +# endif +# ifdef SRATOM_INTERNAL +# define SRATOM_API SRATOM_LIB_EXPORT +# else +# define SRATOM_API SRATOM_LIB_IMPORT +# endif +#else +# define SRATOM_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + @defgroup sratom Sratom + An LV2 Atom RDF serialisation library. + @{ +*/ + +/** + Atom serialiser. +*/ +typedef struct SratomImpl Sratom; + +/** + Create a new Atom serialiser. +*/ +SRATOM_API +Sratom* +sratom_new(LV2_URID_Map* map); + +/** + Free an Atom serialisation. +*/ +SRATOM_API +void +sratom_free(Sratom* sratom); + +/** + Set the sink(s) where sratom will write its output. + + This must be called before calling sratom_write(). If @p pretty_numbers is + true, numbers will be written as pretty Turtle literals, rather than string + literals with precise types. The cost of this is the types might get + fudged on a round-trip to RDF and back. +*/ +SRATOM_API +void +sratom_set_sink(Sratom* sratom, + const char* base_uri, + SerdStatementSink sink, + SerdEndSink end_sink, + void* handle, + bool pretty_numbers); + +/** + Write an Atom to RDF. + The serialised atom is written to the sink set by sratom_set_sink(). + @return 0 on success, or a non-zero error code otherwise. +*/ +SRATOM_API +int +sratom_write(Sratom* sratom, + LV2_URID_Unmap* unmap, + uint32_t flags, + const SerdNode* subject, + const SerdNode* predicate, + uint32_t type, + uint32_t size, + const void* body); + +/** + Read an Atom from RDF. + The resulting atom will be written to @p forge. +*/ +SRATOM_API +void +sratom_read(Sratom* sratom, + LV2_Atom_Forge* forge, + SordWorld* world, + SordModel* model, + const SordNode* node); + +/** + Serialise an Atom to a Turtle string. + The returned string must be free()'d by the caller. +*/ +SRATOM_API +char* +sratom_to_turtle(Sratom* sratom, + LV2_URID_Unmap* unmap, + const char* base_uri, + const SerdNode* subject, + const SerdNode* predicate, + uint32_t type, + uint32_t size, + const void* body); + +/** + Read an Atom from a Turtle string. + The returned atom must be free()'d by the caller. +*/ +SRATOM_API +LV2_Atom* +sratom_from_turtle(Sratom* sratom, + const char* base_uri, + const SerdNode* subject, + const SerdNode* predicate, + const char* str); + +/** + A convenient resizing sink for LV2_Atom_Forge. + The handle must point to an initialized SerdChunk. +*/ +SRATOM_API +LV2_Atom_Forge_Ref +sratom_forge_sink(LV2_Atom_Forge_Sink_Handle handle, + const void* buf, + uint32_t size); + +/** + The corresponding deref function for sratom_forge_sink. +*/ +SRATOM_API +LV2_Atom* +sratom_forge_deref(LV2_Atom_Forge_Sink_Handle handle, + LV2_Atom_Forge_Ref ref); + +/** + @} +*/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SRATOM_SRATOM_H */ diff --git a/src/serialisation/wscript b/src/serialisation/wscript index abc1dd46..58c56f60 100644 --- a/src/serialisation/wscript +++ b/src/serialisation/wscript @@ -2,10 +2,13 @@ from waflib.extras import autowaf as autowaf def build(bld): - obj = bld(features = 'cxx cxxshlib', - source = 'Parser.cpp Serialiser.cpp serialisation.cpp', + obj = bld(features = 'c cshlib cxx cxxshlib', + source = ['Parser.cpp', + 'Serialiser.cpp', + 'serialisation.cpp', + 'sratom/sratom.c'], export_includes = ['../..'], - includes = ['../..'], + includes = ['.', '../..'], name = 'libingen_serialisation', target = 'ingen_serialisation', install_path = '${LIBDIR}', diff --git a/src/server/AudioBuffer.cpp b/src/server/AudioBuffer.cpp index fc73f9d7..2b837d0b 100644 --- a/src/server/AudioBuffer.cpp +++ b/src/server/AudioBuffer.cpp @@ -35,46 +35,31 @@ using namespace Raul; namespace Ingen { namespace Server { -AudioBuffer::AudioBuffer(BufferFactory& bufs, PortType type, size_t size) - : ObjectBuffer(bufs, size) +AudioBuffer::AudioBuffer(BufferFactory& bufs, LV2_URID type, uint32_t size) + : Buffer(bufs, type, size) , _state(OK) , _set_value(0) , _set_time(0) { assert(size >= sizeof(LV2_Atom) + sizeof(Sample)); - assert(this->size() >= size); + assert(this->capacity() >= size); assert(data()); - _type = type; - // Control port / Single float object - if (type == PortType::CONTROL) { - atom()->type = 0;//map->float_type; - - // Audio port / Vector of float - } else { - assert(type == PortType::AUDIO || type == PortType::CV); - atom()->type = 0;//map->vector_type; + if (type == bufs.uris().atom_Sound) { + // Audio port (Vector of float) LV2_Atom_Vector* body = (LV2_Atom_Vector*)atom(); - body->body.child_size = sizeof(Sample); - body->body.child_type = 0;//map->float_type; + body->body.child_size = sizeof(float); + body->body.child_type = bufs.uris().atom_Float; } - /*debug << "Created Audio Buffer" << endl - << "\tobject @ " << (void*)atom() << endl - << "\tbody @ " << (void*)atom()->body - << "\t(offset " << (char*)atom()->body - (char*)atom() << ")" << endl - << "\tdata @ " << (void*)data() - << "\t(offset " << (char*)data() - (char*)atom() << ")" - << endl;*/ + _atom->type = type; clear(); } void -AudioBuffer::resize(size_t size) +AudioBuffer::resize(uint32_t size) { - if (_type == PortType::AUDIO) { - ObjectBuffer::resize(size + sizeof(LV2_Atom_Vector)); - } + Buffer::resize(size); clear(); } @@ -164,7 +149,7 @@ AudioBuffer::copy(Context& context, const Buffer* src) // Control => Control if (src_abuf->is_control() == is_control()) { - ObjectBuffer::copy(context, src); + Buffer::copy(context, src); // Audio => Audio } else if (!src_abuf->is_control() && !is_control()) { diff --git a/src/server/AudioBuffer.hpp b/src/server/AudioBuffer.hpp index 262b03c1..eda5c3a3 100644 --- a/src/server/AudioBuffer.hpp +++ b/src/server/AudioBuffer.hpp @@ -24,8 +24,11 @@ #include +#include "ingen/shared/URIs.hpp" + +#include "Buffer.hpp" +#include "BufferFactory.hpp" #include "Context.hpp" -#include "ObjectBuffer.hpp" #include "types.hpp" using namespace std; @@ -33,10 +36,10 @@ using namespace std; namespace Ingen { namespace Server { -class AudioBuffer : public ObjectBuffer +class AudioBuffer : public Buffer { public: - AudioBuffer(BufferFactory& bufs, PortType type, size_t capacity); + AudioBuffer(BufferFactory& bufs, LV2_URID type, uint32_t size); void clear(); @@ -48,7 +51,7 @@ public: float peak(Context& context) const; - inline bool is_control() const { return _type.symbol() == PortType::CONTROL; } + inline bool is_control() const { return _type == _factory.uris().atom_Float; } inline Sample* data() const { return (is_control()) @@ -59,7 +62,7 @@ public: inline SampleCount nframes() const { return (is_control()) ? 1 - : (_size - sizeof(LV2_Atom_Vector)) / sizeof(Sample); + : (_capacity - sizeof(LV2_Atom_Vector)) / sizeof(Sample); } inline Sample& value_at(size_t offset) const @@ -68,7 +71,7 @@ public: void prepare_read(Context& context); void prepare_write(Context& context) {} - void resize(size_t size); + void resize(uint32_t size); private: enum State { OK, HALF_SET_CYCLE_1, HALF_SET_CYCLE_2 }; diff --git a/src/server/Buffer.cpp b/src/server/Buffer.cpp new file mode 100644 index 00000000..a52b62eb --- /dev/null +++ b/src/server/Buffer.cpp @@ -0,0 +1,164 @@ +/* This file is part of Ingen. + * Copyright 2009-2012 David Robillard + * + * Ingen is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define __STDC_LIMIT_MACROS 1 + +#include +#include + +#include + +#include "ingen/shared/LV2Features.hpp" +#include "ingen/shared/LV2URIMap.hpp" +#include "ingen/shared/URIs.hpp" +#include "ingen/shared/World.hpp" +#include "ingen_config.h" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" +#include "raul/log.hpp" + +#include "Buffer.hpp" +#include "Engine.hpp" + +namespace Ingen { +namespace Server { + +Buffer::Buffer(BufferFactory& bufs, LV2_URID type, uint32_t capacity) + : _factory(bufs) + , _type(type) + , _capacity(capacity) + , _next(NULL) + , _refs(0) +{ + if (capacity > UINT32_MAX) { + Raul::error << "Event buffer size " << capacity << " too large, aborting." + << std::endl; + throw std::bad_alloc(); + } + +#ifdef HAVE_POSIX_MEMALIGN + int ret = posix_memalign((void**)&_atom, 16, capacity); +#else + _atom = (LV2_Atom_Sequence*)malloc(capacity); + int ret = (_atom != NULL) ? 0 : -1; +#endif + + if (ret != 0) { + Raul::error << "Failed to allocate event buffer." << std::endl; + throw std::bad_alloc(); + } + + memset(_atom, 0, capacity); + _atom->type = type; + assert(_atom->type != 1); + + clear(); +} + +Buffer::~Buffer() +{ + free(_atom); +} + +void +Buffer::clear() +{ + _atom->size = 0; +} + +void +Buffer::copy(Context& context, const Buffer* src) +{ + // Copy only if src is a POD object that fits + if (src->_atom->type != 0 && sizeof(LV2_Atom) + src->_atom->size <= capacity()) { + memcpy(_atom, src->_atom, sizeof(LV2_Atom) + src->_atom->size); + } + assert(_atom->type != 1); +} + +void +Buffer::resize(uint32_t capacity) +{ + _atom = (LV2_Atom*)realloc(_atom, capacity); + _capacity = capacity; + clear(); +} + +void* +Buffer::port_data(PortType port_type, SampleCount offset) +{ + switch (port_type.symbol()) { + case PortType::CONTROL: + case PortType::CV: + case PortType::AUDIO: + assert(_atom->type == _type); + if (_atom->type == _factory.uris().atom_Float) { + return (float*)LV2_ATOM_BODY(_atom); + } else if (_atom->type == _factory.uris().atom_Sound) { + return (float*)LV2_ATOM_CONTENTS(LV2_Atom_Vector, _atom) + offset; + } else { + Raul::warn << "Audio data requested from non-audio buffer " << this << " :: " + << _atom->type << " - " + << _factory.engine().world()->lv2_uri_map()->unmap_uri(_atom->type) + << std::endl; + assert(false); + return NULL; + } + break; + default: + return _atom; + } +} + +const void* +Buffer::port_data(PortType port_type, SampleCount offset) const +{ + return const_cast( + const_cast(this)->port_data(port_type, offset)); +} + +void +Buffer::prepare_write(Context& context) +{ + _atom->size = 0; +} + +bool +Buffer::append_event(int64_t frames, + uint32_t size, + uint32_t type, + const uint8_t* data) +{ + if (sizeof(LV2_Atom) + _atom->size + lv2_atom_pad_size(size) > _capacity) { + return false; + } + + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)_atom; + LV2_Atom_Event* ev = (LV2_Atom_Event*)( + (uint8_t*)seq + sizeof(LV2_Atom) + lv2_atom_pad_size(seq->atom.size)); + + ev->time.frames = frames; + ev->body.size = size; + ev->body.type = type; + memcpy(LV2_ATOM_BODY(&ev->body), data, size); + + _atom->size += lv2_atom_pad_size(size); + + return true; +} + +} // namespace Server +} // namespace Ingen diff --git a/src/server/Buffer.hpp b/src/server/Buffer.hpp index 0b3c9348..c2d5ac05 100644 --- a/src/server/Buffer.hpp +++ b/src/server/Buffer.hpp @@ -24,6 +24,7 @@ #include #include +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" #include "raul/AtomicInt.hpp" #include "raul/Deletable.hpp" #include "raul/SharedPtr.hpp" @@ -42,32 +43,28 @@ class BufferFactory; class Buffer : public boost::noncopyable, public Raul::Deletable { public: - Buffer(BufferFactory& bufs, PortType type, size_t size) - : _factory(bufs) - , _type(type) - , _size(size) - , _next(NULL) - , _refs(0) - {} + Buffer(BufferFactory& bufs, LV2_URID type, uint32_t capacity); - /** Clear contents and reset state */ - virtual void clear() = 0; - - virtual void resize(size_t size) { _size = size; } - - virtual void* port_data(PortType port_type, SampleCount offset=0) = 0; - virtual const void* port_data(PortType port_type, SampleCount offset=0) const = 0; + virtual void clear(); + virtual void resize(uint32_t size); + virtual void copy(Context& context, const Buffer* src); + virtual void prepare_read(Context& context) {} + virtual void prepare_write(Context& context); - /** Rewind (ie reset read pointer), but leave contents unchanged */ - virtual void rewind() const {} + void* port_data(PortType port_type, SampleCount offset); + const void* port_data(PortType port_type, SampleCount offset) const; - virtual void copy(Context& context, const Buffer* src) = 0; + LV2_URID type() const { return _type; } + uint32_t capacity() const { return _capacity; } - virtual void prepare_read(Context& context) {} - virtual void prepare_write(Context& context) {} + /// Sequence buffers only + bool append_event(int64_t frames, + uint32_t size, + uint32_t type, + const uint8_t* data); - PortType type() const { return _type; } - size_t size() const { return _size; } + LV2_Atom* atom() { return _atom; } + const LV2_Atom* atom() const { return _atom; } inline void ref() { ++_refs; } @@ -78,11 +75,12 @@ public: protected: BufferFactory& _factory; - PortType _type; - size_t _size; + LV2_Atom* _atom; + LV2_URID _type; + uint32_t _capacity; friend class BufferFactory; - virtual ~Buffer() {} + virtual ~Buffer(); private: Buffer* _next; ///< Intrusive linked list for BufferFactory diff --git a/src/server/BufferFactory.cpp b/src/server/BufferFactory.cpp index f24f7270..6be8b2ea 100644 --- a/src/server/BufferFactory.cpp +++ b/src/server/BufferFactory.cpp @@ -16,15 +16,15 @@ */ #include -#include "raul/log.hpp" + #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" +#include "raul/log.hpp" + #include "AudioBuffer.hpp" -#include "EventBuffer.hpp" -#include "ObjectBuffer.hpp" #include "BufferFactory.hpp" -#include "Engine.hpp" #include "Driver.hpp" +#include "Engine.hpp" #include "ThreadManager.hpp" using namespace Raul; @@ -48,11 +48,10 @@ BufferFactory::~BufferFactory() _silent_buffer.reset(); free_list(_free_audio.get()); free_list(_free_control.get()); - free_list(_free_event.get()); free_list(_free_object.get()); } -Raul::Forge& +Ingen::Forge& BufferFactory::forge() { return _engine.world()->forge(); @@ -71,33 +70,31 @@ BufferFactory::free_list(Buffer* head) void BufferFactory::set_block_length(SampleCount block_length) { - _silent_buffer = create(PortType::AUDIO, audio_buffer_size(block_length)); + _silent_buffer = create(_uris->atom_Sound, audio_buffer_size(block_length)); } -size_t +uint32_t BufferFactory::audio_buffer_size(SampleCount nframes) { return sizeof(LV2_Atom_Vector) + (nframes * sizeof(float)); } -size_t -BufferFactory::default_buffer_size(PortType type) +uint32_t +BufferFactory::default_buffer_size(LV2_URID type) { - switch (type.symbol()) { - case PortType::AUDIO: - case PortType::CV: - return audio_buffer_size(_engine.driver()->block_length()); - case PortType::CONTROL: - return sizeof(LV2_Atom) + sizeof(float); - case PortType::EVENTS: - return _engine.driver()->block_length() * EVENT_BYTES_PER_FRAME; - default: - return 1024; // Who knows + if (type == _uris->atom_Float) { + return sizeof(LV2_Atom_Float); + } else if (type == _uris->atom_Sound) { + return audio_buffer_size(_engine.driver()->block_length()); + } else if (type == _uris->atom_Sequence) { + return _engine.driver()->block_length() * EVENT_BYTES_PER_FRAME; + } else { + return 0; } } BufferFactory::Ref -BufferFactory::get(PortType type, size_t size, bool force_create) +BufferFactory::get(LV2_URID type, uint32_t capacity, bool force_create) { Raul::AtomicPtr& head_ptr = free_list(type); Buffer* try_head = NULL; @@ -114,7 +111,7 @@ BufferFactory::get(PortType type, size_t size, bool force_create) if (!try_head) { if (!ThreadManager::thread_is(THREAD_PROCESS)) { - return create(type, size); + return create(type, capacity); } else { assert(false); error << "Failed to obtain buffer" << endl; @@ -133,33 +130,31 @@ BufferFactory::silent_buffer() } BufferFactory::Ref -BufferFactory::create(PortType type, size_t size) +BufferFactory::create(LV2_URID type, uint32_t capacity) { ThreadManager::assert_not_thread(THREAD_PROCESS); Buffer* buffer = NULL; - if (size == 0) - size = default_buffer_size(type); - - if (type.is_control()) { - AudioBuffer* ret = new AudioBuffer(*this, type, audio_buffer_size(size)); - ret->atom()->type = _uris->atom_Float.id; - buffer = ret; - } else if (type.is_audio() || type.is_cv()) { - AudioBuffer* ret = new AudioBuffer(*this, type, audio_buffer_size(size)); - ret->atom()->type = _uris->atom_Vector.id; - ((LV2_Atom_Vector*)ret->atom())->body.child_type = _uris->atom_Float.id; - buffer = ret; - } else if (type.is_events()) { - buffer = new EventBuffer(*this, size); - } else if (type.is_value() || type.is_message()) { - buffer = new ObjectBuffer(*this, std::max(size, sizeof(LV2_Atom) + sizeof(void*))); + if (capacity == 0) { + capacity = default_buffer_size(type); + } + + if (type == _uris->atom_Float) { + assert(capacity >= sizeof(LV2_Atom_Float)); + buffer = new AudioBuffer(*this, type, capacity); + info << "NEW FLOAT BUFFER " << buffer << " :: " << type << std::endl; + } else if (type == _uris->atom_Sound) { + assert(capacity >= default_buffer_size(_uris->atom_Sound)); + buffer = new AudioBuffer(*this, type, capacity); + info << "NEW AUDIO BUFFER " << buffer << " :: " << type << std::endl; } else { - error << "Failed to create buffer of unknown type" << endl; - return Ref(); + buffer = new Buffer(*this, type, capacity); + info << "NEW ATOM BUFFER " << buffer << " :: " << type << std::endl; } + buffer->atom()->type = type; + assert(buffer); return Ref(buffer); } diff --git a/src/server/BufferFactory.hpp b/src/server/BufferFactory.hpp index 15d5ebb8..6f700fce 100644 --- a/src/server/BufferFactory.hpp +++ b/src/server/BufferFactory.hpp @@ -25,9 +25,12 @@ #undef nil #include +#include "raul/Atom.hpp" #include "raul/AtomicPtr.hpp" #include "raul/RingBuffer.hpp" #include "raul/SharedPtr.hpp" +#include "ingen/shared/Forge.hpp" +#include "ingen/shared/URIs.hpp" #include "PortType.hpp" #include "types.hpp" @@ -50,33 +53,32 @@ public: typedef boost::intrusive_ptr Ref; - static size_t audio_buffer_size(SampleCount nframes); - size_t default_buffer_size(PortType type); + static uint32_t audio_buffer_size(SampleCount nframes); + uint32_t default_buffer_size(LV2_URID type); - Ref get(PortType type, size_t size=0, bool force_create=false); + Ref get(LV2_URID type, uint32_t capacity, bool force_create=false); Ref silent_buffer(); void set_block_length(SampleCount block_length); - Raul::Forge& forge(); - Ingen::Shared::URIs& uris() { assert(_uris); return *_uris.get(); } + Ingen::Forge& forge(); + Ingen::Shared::URIs& uris() { assert(_uris); return *_uris.get(); } + Engine& engine() { return _engine; } private: friend class Buffer; void recycle(Buffer* buf); - Ref create(PortType type, size_t size=0); - - inline Raul::AtomicPtr& free_list(PortType type) { - switch (type.symbol()) { - case PortType::AUDIO: - case PortType::CV: return _free_audio; - case PortType::CONTROL: return _free_control; - case PortType::EVENTS: return _free_event; - case PortType::VALUE: - case PortType::MESSAGE: return _free_object; - default: throw; + Ref create(LV2_URID type, uint32_t capacity=0); + + inline Raul::AtomicPtr& free_list(LV2_URID type) { + if (type == _uris->atom_Float) { + return _free_control; + } else if (type == _uris->atom_Sound) { + return _free_audio; + } else { + return _free_object; } } @@ -84,7 +86,6 @@ private: Raul::AtomicPtr _free_audio; Raul::AtomicPtr _free_control; - Raul::AtomicPtr _free_event; Raul::AtomicPtr _free_object; Glib::Mutex _mutex; diff --git a/src/server/ConnectionImpl.cpp b/src/server/ConnectionImpl.cpp index bc0a5c53..7a4d7dda 100644 --- a/src/server/ConnectionImpl.cpp +++ b/src/server/ConnectionImpl.cpp @@ -17,15 +17,17 @@ #include #include -#include "raul/log.hpp" -#include "raul/Maid.hpp" + #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" +#include "raul/Maid.hpp" +#include "raul/log.hpp" + #include "AudioBuffer.hpp" #include "BufferFactory.hpp" #include "ConnectionImpl.hpp" #include "Engine.hpp" -#include "EventBuffer.hpp" #include "InputPort.hpp" #include "MessageContext.hpp" #include "OutputPort.hpp" @@ -109,27 +111,21 @@ ConnectionImpl::queue(Context& context) if (!must_queue()) return; - boost::intrusive_ptr src_buf = - boost::dynamic_pointer_cast(_src_port->buffer(0)); - if (!src_buf) { - error << "Queued connection but source is not an EventBuffer" << endl; + const Ingen::Shared::URIs& uris = _src_port->bufs().uris(); + + boost::intrusive_ptr src_buf = _src_port->buffer(0); + if (src_buf->atom()->type != uris.atom_Sequence) { + error << "Queued connection but source is not a Sequence" << endl; return; } - for (src_buf->rewind(); src_buf->is_valid(); src_buf->increment()) { - error << "Queued connections currently unsupported" << endl; - #if 0 - LV2_Event* ev = src_buf->get_event(); - LV2_Atom* obj = LV2_ATOM_FROM_EVENT(ev); - /*debug << _src_port->path() << " -> " << _dst_port->path() - << " QUEUE OBJECT TYPE " << obj->type << ":"; - for (size_t i = 0; i < obj->size; ++i) - debug << " " << std::hex << (int)obj->body[i]; - debug << endl;*/ - - _queue->write(sizeof(LV2_Atom) + obj->size, obj); - context.engine().message_context()->run(_dst_port->parent_node(), context.start() + ev->frames); - #endif + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)src_buf->atom(); + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); + _queue->write(sizeof(LV2_Atom) + ev->body.size, &ev->body); + context.engine().message_context()->run( + _dst_port->parent_node(), context.start() + ev->time.frames); + } } @@ -171,25 +167,21 @@ ConnectionImpl::can_connect(const OutputPort* src, const InputPort* dst) || dst->is_a(PortType::AUDIO) || dst->is_a(PortType::CV))) - // (Events | Message) => (Events | Message) - || ( (src->is_a(PortType::EVENTS) || src->is_a(PortType::MESSAGE)) - && (dst->is_a(PortType::EVENTS) || dst->is_a(PortType::MESSAGE))) - - // (Message | Value) => (Message | Value) - || ( (src->is_a(PortType::MESSAGE) || src->is_a(PortType::VALUE)) - && (dst->is_a(PortType::MESSAGE) || dst->is_a(PortType::VALUE))) + // Equal types + || (src->type() == dst->type() && + src->buffer_type() == dst->buffer_type()) // Control => atom:Float Value || (src->is_a(PortType::CONTROL) && dst->supports(uris.atom_Float)) - // Audio => atom:Vector Value - || (src->is_a(PortType::AUDIO) && dst->supports(uris.atom_Vector)) + // Audio => atom:Sound Value + || (src->is_a(PortType::AUDIO) && dst->supports(uris.atom_Sound)) // atom:Float Value => Control || (src->supports(uris.atom_Float) && dst->is_a(PortType::CONTROL)) - // atom:Vector Value => Audio - || (src->supports(uris.atom_Vector) && dst->is_a(PortType::AUDIO))); + // atom:Sound Value => Audio + || (src->supports(uris.atom_Sound) && dst->is_a(PortType::AUDIO))); } } // namespace Server diff --git a/src/server/ControlBindings.cpp b/src/server/ControlBindings.cpp index d8d0ec07..0394226f 100644 --- a/src/server/ControlBindings.cpp +++ b/src/server/ControlBindings.cpp @@ -16,16 +16,17 @@ */ #include -#include "raul/log.hpp" -#include "raul/midi_events.h" -#include "ingen/shared/URIs.hpp" + #include "ingen/shared/LV2URIMap.hpp" +#include "ingen/shared/URIs.hpp" #include "ingen/shared/World.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" +#include "raul/log.hpp" +#include "raul/midi_events.h" #include "AudioBuffer.hpp" #include "ControlBindings.hpp" #include "Engine.hpp" -#include "EventBuffer.hpp" #include "Notification.hpp" #include "PortImpl.hpp" #include "ProcessContext.hpp" @@ -43,13 +44,15 @@ ControlBindings::ControlBindings(Engine& engine) : _engine(engine) , _learn_port(NULL) , _bindings(new Bindings()) - , _feedback(new EventBuffer(*_engine.buffer_factory(), 1024)) // FIXME: size + , _feedback(new Buffer(*_engine.buffer_factory(), + engine.world()->uris()->atom_Sequence, + 4096)) // FIXME: capacity? { } ControlBindings::~ControlBindings() { - delete _feedback; + _feedback.reset(); } ControlBindings::Key @@ -66,7 +69,7 @@ ControlBindings::binding_key(const Raul::Atom& binding) const { const Ingen::Shared::URIs& uris = *_engine.world()->uris().get(); Key key; - if (binding.type() == Atom::DICT) { + if (binding.type() == _engine.world()->forge().Dict) { const Atom::DictValue& dict = binding.get_dict(); Atom::DictValue::const_iterator t = dict.find(uris.rdf_type); Atom::DictValue::const_iterator n; @@ -88,7 +91,7 @@ ControlBindings::binding_key(const Raul::Atom& binding) const } ControlBindings::Key -ControlBindings::midi_event_key(uint16_t size, uint8_t* buf, uint16_t& value) +ControlBindings::midi_event_key(uint16_t size, const uint8_t* buf, uint16_t& value) { switch (buf[0] & 0xF0) { case MIDI_CMD_CONTROL: @@ -125,9 +128,8 @@ ControlBindings::port_value_changed(ProcessContext& context, Key key, const Raul::Atom& value_atom) { - Ingen::Shared::World* world = context.engine().world(); - const Ingen::Shared::URIs& uris = *world->uris().get(); - const Ingen::Shared::LV2URIMap& uri_map = *world->lv2_uri_map().get(); + Ingen::Shared::World* world = context.engine().world(); + const Ingen::Shared::URIs& uris = *world->uris().get(); if (key) { int16_t value = port_value_to_control( port, key.type, value_atom, port->minimum(), port->maximum()); @@ -164,9 +166,7 @@ ControlBindings::port_value_changed(ProcessContext& context, break; } if (size > 0) { - _feedback->append(0, 0, - uri_map.global_to_event(uris.midi_MidiEvent.id).second, - size, buf); + _feedback->append_event(0, size, uris.midi_MidiEvent.id, buf); } } } @@ -218,7 +218,7 @@ ControlBindings::port_value_to_control(PortImpl* port, const Raul::Atom& min_atom, const Raul::Atom& max_atom) const { - if (value_atom.type() != Atom::FLOAT) + if (value_atom.type() != port->bufs().forge().Float) return 0; const float min = min_atom.get_float(); @@ -262,7 +262,7 @@ ControlBindings::set_port_value(ProcessContext& context, port->set_value(port_value); - assert(port_value.type() == Atom::FLOAT); + assert(port_value.type() == port->bufs().forge().Float); assert(dynamic_cast(port->buffer(0).get())); for (uint32_t v = 0; v < port->poly(); ++v) @@ -341,71 +341,43 @@ ControlBindings::remove(PortImpl* port) } void -ControlBindings::pre_process(ProcessContext& context, EventBuffer* buffer) +ControlBindings::pre_process(ProcessContext& context, Buffer* buffer) { - uint32_t frames = 0; - uint32_t subframes = 0; - uint16_t type = 0; - uint16_t size = 0; - uint8_t* buf = NULL; - uint16_t value = 0; - + uint16_t value = 0; SharedPtr bindings = _bindings; _feedback->clear(); - Ingen::Shared::World* world = context.engine().world(); - const Ingen::Shared::URIs& uris = *world->uris().get(); - const Ingen::Shared::LV2URIMap& uri_map = *world->lv2_uri_map().get(); - - // TODO: cache - const uint32_t midi_event_type = uri_map.global_to_event( - uris.midi_MidiEvent.id).second; - - // Learn from input if necessary - if (_learn_port) { - for (buffer->rewind(); - buffer->get_event(&frames, &subframes, &type, &size, &buf); - buffer->increment()) { - if (type != midi_event_type) - continue; - - const Key key = midi_event_key(size, buf, value); - if (key && bind(context, key)) - break; - } - } + Ingen::Shared::World* world = context.engine().world(); + const Ingen::Shared::URIs& uris = *world->uris().get(); - // If bindings are empty, no sense reading input - if (bindings->empty()) + if (!_learn_port && bindings->empty()) { + // Don't bother reading input return; + } - // Read input and apply control values - for (buffer->rewind(); - buffer->get_event(&frames, &subframes, &type, &size, &buf); - buffer->increment()) { - if (type != midi_event_type) - continue; - - const Key key = midi_event_key(size, buf, value); - if (!key) - continue; - - Bindings::const_iterator i = bindings->find(key); - if (i == bindings->end()) - continue; - - set_port_value(context, i->second, key.type, value); + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)buffer->atom(); + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); + if (ev->body.type == uris.midi_MidiEvent) { + const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); + const Key key = midi_event_key(ev->body.size, buf, value); + if (_learn_port && key) { + bind(context, key); + } + + Bindings::const_iterator i = bindings->find(key); + if (i != bindings->end()) { + set_port_value(context, i->second, key.type, value); + } + } } } void -ControlBindings::post_process(ProcessContext& context, EventBuffer* buffer) +ControlBindings::post_process(ProcessContext& context, Buffer* buffer) { - if (_feedback->event_count() > 0) { - // TODO: merge buffer's existing contents (anything send to it in the patch) - _feedback->rewind(); - buffer->copy(context, _feedback); - } + // TODO: merge buffer's existing contents (anything send to it in the patch) + buffer->copy(context, _feedback.get()); } } // namespace Server diff --git a/src/server/ControlBindings.hpp b/src/server/ControlBindings.hpp index f0858853..1e61bdcb 100644 --- a/src/server/ControlBindings.hpp +++ b/src/server/ControlBindings.hpp @@ -33,7 +33,6 @@ namespace Server { class Engine; class ProcessContext; -class EventBuffer; class PortImpl; class ControlBindings { @@ -77,8 +76,8 @@ public: Key key, const Raul::Atom& value); - void pre_process(ProcessContext& context, EventBuffer* control_in); - void post_process(ProcessContext& context, EventBuffer* control_out); + void pre_process(ProcessContext& context, Buffer* control_in); + void post_process(ProcessContext& context, Buffer* control_out); /** Remove all bindings for @a path or children of @a path. * The caller must safely drop the returned reference in the @@ -93,7 +92,7 @@ public: SharedPtr remove(PortImpl* port); private: - Key midi_event_key(uint16_t size, uint8_t* buf, uint16_t& value); + Key midi_event_key(uint16_t size, const uint8_t* buf, uint16_t& value); void set_port_value(ProcessContext& context, PortImpl* port, Type type, int16_t value); bool bind(ProcessContext& context, Key key); @@ -113,7 +112,7 @@ private: PortImpl* _learn_port; SharedPtr _bindings; - EventBuffer* _feedback; + BufferFactory::Ref _feedback; }; } // namespace Server diff --git a/src/server/DuplexPort.cpp b/src/server/DuplexPort.cpp index f2c2763b..01fc43f3 100644 --- a/src/server/DuplexPort.cpp +++ b/src/server/DuplexPort.cpp @@ -22,9 +22,9 @@ #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" +#include "Buffer.hpp" #include "ConnectionImpl.hpp" #include "DuplexPort.hpp" -#include "EventBuffer.hpp" #include "NodeImpl.hpp" #include "OutputPort.hpp" #include "ProcessContext.hpp" @@ -43,12 +43,13 @@ DuplexPort::DuplexPort( bool polyphonic, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size, bool is_output) - : PortImpl(bufs, parent, name, index, poly, type, value, buffer_size) - , InputPort(bufs, parent, name, index, poly, type, value, buffer_size) - , OutputPort(bufs, parent, name, index, poly, type, value, buffer_size) + : PortImpl(bufs, parent, name, index, poly, type, buffer_type, value, buffer_size) + , InputPort(bufs, parent, name, index, poly, type, buffer_type, value, buffer_size) + , OutputPort(bufs, parent, name, index, poly, type, buffer_type, value, buffer_size) , _is_output(is_output) { assert(PortImpl::_parent == parent); diff --git a/src/server/DuplexPort.hpp b/src/server/DuplexPort.hpp index 3b715130..1c543608 100644 --- a/src/server/DuplexPort.hpp +++ b/src/server/DuplexPort.hpp @@ -46,6 +46,7 @@ public: bool polyphonic, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size, bool is_output); diff --git a/src/server/Engine.cpp b/src/server/Engine.cpp index 3d5e981b..d4904f0c 100644 --- a/src/server/Engine.cpp +++ b/src/server/Engine.cpp @@ -22,7 +22,6 @@ #include "raul/Deletable.hpp" #include "raul/Maid.hpp" #include "raul/SharedPtr.hpp" -#include "lv2/lv2plug.in/ns/ext/uri-map/uri-map.h" #include "events/CreatePatch.hpp" #include "events/CreatePort.hpp" #include "ingen/shared/World.hpp" @@ -57,7 +56,7 @@ bool ThreadManager::single_threaded = true; Engine::Engine(Ingen::Shared::World* a_world) : _world(a_world) , _broadcaster(new ClientBroadcaster()) - , _control_bindings(new ControlBindings(*this)) + , _control_bindings(NULL) , _maid(new Raul::Maid(event_queue_size())) , _message_context(new MessageContext(*this)) , _node_factory(new NodeFactory(a_world)) @@ -73,6 +72,8 @@ Engine::Engine(Ingen::Shared::World* a_world) SharedPtr( new EngineStore(SharedPtr(_buffer_factory)))); } + + _control_bindings = new ControlBindings(*this); } Engine::~Engine() @@ -104,7 +105,7 @@ Engine::engine_store() const size_t Engine::event_queue_size() const { - return world()->conf()->option("queue-size").get_int32(); + return world()->conf()->option("queue-size").get_int(); } void @@ -153,7 +154,7 @@ Engine::activate() _message_context->Thread::start(); const Ingen::Shared::URIs& uris = *world()->uris().get(); - Raul::Forge& forge = world()->forge(); + Ingen::Forge& forge = world()->forge(); // Create root patch PatchImpl* root_patch = _driver->root_patch(); @@ -173,14 +174,15 @@ Engine::activate() Resource::Properties control_properties; control_properties.insert(make_pair(uris.lv2_name, - forge.make("Control"))); + forge.alloc("Control"))); control_properties.insert(make_pair(uris.rdf_type, - uris.ev_EventPort)); + uris.atom_MessagePort)); + control_properties.insert(make_pair(uris.atom_bufferType, + uris.atom_Sequence)); // Add control input Resource::Properties in_properties(control_properties); in_properties.insert(make_pair(uris.rdf_type, uris.lv2_InputPort)); - in_properties.insert(make_pair(uris.rdf_type, uris.ev_EventPort)); in_properties.insert(make_pair(uris.lv2_index, forge.make(0))); in_properties.insert(make_pair(uris.lv2_portProperty, uris.lv2_connectionOptional)); @@ -198,7 +200,6 @@ Engine::activate() // Add control out Resource::Properties out_properties(control_properties); out_properties.insert(make_pair(uris.rdf_type, uris.lv2_OutputPort)); - out_properties.insert(make_pair(uris.rdf_type, uris.ev_EventPort)); out_properties.insert(make_pair(uris.lv2_index, forge.make(1))); in_properties.insert(make_pair(uris.lv2_portProperty, uris.lv2_connectionOptional)); diff --git a/src/server/EventBuffer.cpp b/src/server/EventBuffer.cpp deleted file mode 100644 index 7f3c2b37..00000000 --- a/src/server/EventBuffer.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define __STDC_LIMIT_MACROS 1 -#include -#include "raul/log.hpp" -#include "lv2/lv2plug.in/ns/ext/event/event.h" -#include "lv2/lv2plug.in/ns/ext/event/event-helpers.h" -#include "ingen_config.h" -#include "EventBuffer.hpp" -#include "ProcessContext.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Server { - -/** Allocate a new event buffer. - * \a capacity is in bytes (not number of events). - */ -EventBuffer::EventBuffer(BufferFactory& bufs, size_t capacity) - : Buffer(bufs, PortType(PortType::EVENTS), capacity) - , _latest_frames(0) - , _latest_subframes(0) -{ - if (capacity > UINT32_MAX) { - error << "Event buffer size " << capacity << " too large, aborting." << endl; - throw std::bad_alloc(); - } - -#ifdef HAVE_POSIX_MEMALIGN - int ret = posix_memalign((void**)&_data, 16, sizeof(LV2_Event_Buffer) + capacity); -#else - _data = (LV2_Event_Buffer*)malloc(sizeof(LV2_Event_Buffer) + capacity); - int ret = (_data != NULL) ? 0 : -1; -#endif - - if (ret != 0) { - error << "Failed to allocate event buffer. Aborting." << endl; - exit(EXIT_FAILURE); - } - - _data->header_size = sizeof(LV2_Event_Buffer); - _data->data = reinterpret_cast(_data + _data->header_size); - _data->stamp_type = 0; - _data->event_count = 0; - _data->capacity = (uint32_t)capacity; - _data->size = 0; - - clear(); -} - -EventBuffer::~EventBuffer() -{ - free(_data); -} - -void -EventBuffer::prepare_read(Context& context) -{ - rewind(); -} - -void -EventBuffer::prepare_write(Context& context) -{ - if (context.offset() == 0) - clear(); -} - -void -EventBuffer::copy(Context& context, const Buffer* src_buf) -{ - const EventBuffer* src = dynamic_cast(src_buf); - if (src->_data == _data) - return; - - assert(src->_data->header_size == _data->header_size); - assert(capacity() >= _data->header_size + src->_data->size); - - rewind(); - - memcpy(_data, src->_data, _data->header_size + src->_data->size); - - _iter = src->_iter; - _iter.buf = _data; - - _latest_frames = src->_latest_frames; - _latest_subframes = src->_latest_subframes; - - assert(event_count() == src->event_count()); -} - -/** Increment the read position by one event. - * - * \return true if increment was successful, or false if end of buffer reached. - */ -bool -EventBuffer::increment() const -{ - if (lv2_event_is_valid(&_iter)) { - lv2_event_increment(&_iter); - return true; - } else { - return false; - } -} - -/** \return true iff the cursor is valid (ie get_event is safe) - */ -bool -EventBuffer::is_valid() const -{ - return lv2_event_is_valid(&_iter); -} - -/** Read an event from the current position in the buffer - * - * \return true if read was successful, or false if end of buffer reached - */ -bool -EventBuffer::get_event(uint32_t* frames, - uint32_t* subframes, - uint16_t* type, - uint16_t* size, - uint8_t** data) const -{ - if (lv2_event_is_valid(&_iter)) { - LV2_Event* ev = lv2_event_get(&_iter, data); - *frames = ev->frames; - *subframes = ev->subframes; - *type = ev->type; - *size = ev->size; - return true; - } else { - return false; - } -} - -#if 0 -/** Get the object currently pointed to, or NULL if invalid. - */ -LV2_Atom* -EventBuffer::get_atom() const -{ - if (lv2_event_is_valid(&_iter)) { - uint8_t* data; - LV2_Event* ev = lv2_event_get(&_iter, &data); - return LV2_ATOM_FROM_EVENT(ev); - } - return NULL; -} -#endif - -/** Get the event currently pointed to, or NULL if invalid. - */ -LV2_Event* -EventBuffer::get_event() const -{ - if (lv2_event_is_valid(&_iter)) { - uint8_t* data; - return lv2_event_get(&_iter, &data); - } - return NULL; -} - -/** Append an event to the buffer. - * - * \a timestamp must be >= the latest event in the buffer. - * - * \return true on success - */ -bool -EventBuffer::append(uint32_t frames, - uint32_t subframes, - uint16_t type, - uint16_t size, - const uint8_t* data) -{ -#ifndef NDEBUG - if (lv2_event_is_valid(&_iter)) { - LV2_Event* last_event = lv2_event_get(&_iter, NULL); - assert(last_event->frames < frames - || (last_event->frames == frames && last_event->subframes <= subframes)); - } -#endif - - /*debug << "Appending event type " << type << ", size " << size - << " @ " << frames << "." << subframes << endl;*/ - - if (!lv2_event_write(&_iter, frames, subframes, type, size, data)) { - error << "Failed to write event." << endl; - return false; - } else { - _latest_frames = frames; - _latest_subframes = subframes; - return true; - } -} - -} // namespace Server -} // namespace Ingen diff --git a/src/server/EventBuffer.hpp b/src/server/EventBuffer.hpp deleted file mode 100644 index 52125ffd..00000000 --- a/src/server/EventBuffer.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2007-2011 David Robillard - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_EVENTBUFFER_HPP -#define INGEN_ENGINE_EVENTBUFFER_HPP - -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "lv2/lv2plug.in/ns/ext/event/event.h" -#include "lv2/lv2plug.in/ns/ext/event/event-helpers.h" - -#include "Buffer.hpp" - -namespace Ingen { -namespace Server { - -class EventBuffer : public Buffer { -public: - EventBuffer(BufferFactory& bufs, size_t capacity); - ~EventBuffer(); - - void* port_data(PortType port_type, SampleCount offset=0) { return _data; } - const void* port_data(PortType port_type, SampleCount offset=0) const { return _data; } - - inline void rewind() const { lv2_event_begin(&_iter, _data); } - - inline void clear() { - _latest_frames = 0; - _latest_subframes = 0; - _data->event_count = 0; - _data->size = 0; - rewind(); - } - - void prepare_read(Context& context); - void prepare_write(Context& context); - - void copy(Context& context, const Buffer* src); - - inline size_t event_count() const { return _data->event_count; } - inline uint32_t capacity() const { return _data->capacity; } - inline uint32_t latest_frames() const { return _latest_frames; } - inline uint32_t latest_subframes() const { return _latest_subframes; } - - bool increment() const; - bool is_valid() const; - - bool get_event(uint32_t* frames, - uint32_t* subframes, - uint16_t* type, - uint16_t* size, - uint8_t** data) const; - - //LV2_Atom* get_atom() const; - LV2_Event* get_event() const; - - bool append(uint32_t frames, - uint32_t subframes, - uint16_t type, - uint16_t size, - const uint8_t* data); - -private: - LV2_Event_Buffer* _data; ///< Contents - mutable LV2_Event_Iterator _iter; ///< Iterator into _data - uint32_t _latest_frames; ///< Latest time of all events (frames) - uint32_t _latest_subframes; ///< Latest time of all events (subframes) -}; - -} // namespace Server -} // namespace Ingen - -#endif // INGEN_ENGINE_EVENTBUFFER_HPP diff --git a/src/server/InputPort.cpp b/src/server/InputPort.cpp index a07ef183..42d6c83d 100644 --- a/src/server/InputPort.cpp +++ b/src/server/InputPort.cpp @@ -23,16 +23,15 @@ #include "AudioBuffer.hpp" #include "BufferFactory.hpp" #include "ConnectionImpl.hpp" -#include "EventBuffer.hpp" #include "InputPort.hpp" #include "NodeImpl.hpp" #include "Notification.hpp" #include "OutputPort.hpp" #include "ProcessContext.hpp" #include "ThreadManager.hpp" -#include "mix.hpp" #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" +#include "mix.hpp" #include "util.hpp" using namespace std; @@ -46,9 +45,10 @@ InputPort::InputPort(BufferFactory& bufs, uint32_t index, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size) - : PortImpl(bufs, parent, symbol, index, poly, type, value, buffer_size) + : PortImpl(bufs, parent, symbol, index, poly, type, buffer_type, value, buffer_size) , _num_connections(0) { const Ingen::Shared::URIs& uris = bufs.uris(); @@ -203,7 +203,7 @@ InputPort::pre_process(Context& context) c->get_sources(context, v, srcs, max_num_srcs, num_srcs); } - mix(context, buffer(v).get(), srcs, num_srcs); + mix(context, bufs().uris(), buffer(v).get(), srcs, num_srcs); buffer(v)->prepare_read(context); } } @@ -216,7 +216,7 @@ void InputPort::post_process(Context& context) { if (_set_by_user) { - if (is_a(PortType::EVENTS)) { + if (_buffer_type == _bufs.uris().atom_Sequence) { // Clear events received via a SetPortValue for (uint32_t v = 0; v < _poly; ++v) { buffer(v)->clear(); diff --git a/src/server/InputPort.hpp b/src/server/InputPort.hpp index 542c3dd1..6c790c9f 100644 --- a/src/server/InputPort.hpp +++ b/src/server/InputPort.hpp @@ -58,6 +58,7 @@ public: uint32_t index, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size=0); diff --git a/src/server/JackDriver.cpp b/src/server/JackDriver.cpp index 2979a449..b81a25a6 100644 --- a/src/server/JackDriver.cpp +++ b/src/server/JackDriver.cpp @@ -27,17 +27,16 @@ #include "ingen/serialisation/Serialiser.hpp" #endif -#include "raul/log.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" #include "raul/List.hpp" - -#include "lv2/lv2plug.in/ns/ext/event/event.h" +#include "raul/log.hpp" #include "AudioBuffer.hpp" #include "ControlBindings.hpp" #include "DuplexPort.hpp" #include "Engine.hpp" #include "Event.hpp" -#include "EventBuffer.hpp" +#include "Event.hpp" #include "EventSource.hpp" #include "JackDriver.hpp" #include "MessageContext.hpp" @@ -45,11 +44,10 @@ #include "PortImpl.hpp" #include "PostProcessor.hpp" #include "ProcessSlave.hpp" -#include "Event.hpp" #include "ThreadManager.hpp" -#include "ingen/shared/World.hpp" #include "ingen/shared/LV2Features.hpp" #include "ingen/shared/LV2URIMap.hpp" +#include "ingen/shared/World.hpp" #include "util.hpp" #define LOG(s) s << "[JackDriver] " @@ -126,9 +124,9 @@ JackPort::pre_process(ProcessContext& context) patch_buf->copy(jack_buf, 0, nframes - 1); - } else if (_patch_port->is_a(PortType::EVENTS)) { - void* jack_buf = jack_port_get_buffer(_jack_port, nframes); - EventBuffer* patch_buf = (EventBuffer*)_patch_port->buffer(0).get(); + } else if (_patch_port->buffer_type() == _patch_port->bufs().uris().atom_Sequence) { + void* jack_buf = jack_port_get_buffer(_jack_port, nframes); + Buffer* patch_buf = (Buffer*)_patch_port->buffer(0).get(); const jack_nframes_t event_count = jack_midi_get_event_count(jack_buf); @@ -139,10 +137,10 @@ JackPort::pre_process(ProcessContext& context) jack_midi_event_t ev; jack_midi_event_get(&ev, jack_buf, i); - if (!patch_buf->append(ev.time, 0, - _driver->_midi_event_type, - ev.size, ev.buffer)) + if (!patch_buf->append_event( + ev.time, ev.size, _driver->_midi_event_type, ev.buffer)) { LOG(warn) << "Failed to write MIDI to port buffer, event(s) lost!" << endl; + } } } } @@ -161,23 +159,20 @@ JackPort::post_process(ProcessContext& context) memcpy(jack_buf, patch_buf->data(), nframes * sizeof(Sample)); - } else if (_patch_port->is_a(PortType::EVENTS)) { - void* jack_buf = jack_port_get_buffer(_jack_port, context.nframes()); - EventBuffer* patch_buf = (EventBuffer*)_patch_port->buffer(0).get(); + } else if (_patch_port->buffer_type() == _patch_port->bufs().uris().atom_Sequence) { + void* jack_buf = jack_port_get_buffer(_jack_port, context.nframes()); + Buffer* patch_buf = (Buffer*)_patch_port->buffer(0).get(); patch_buf->prepare_read(context); jack_midi_clear_buffer(jack_buf); - uint32_t frames = 0; - uint32_t subframes = 0; - uint16_t type = 0; - uint16_t size = 0; - uint8_t* data = NULL; - - // Copy events from Jack port buffer into patch port buffer - for (patch_buf->rewind(); patch_buf->is_valid(); patch_buf->increment()) { - patch_buf->get_event(&frames, &subframes, &type, &size, &data); - jack_midi_event_write(jack_buf, frames, data, size); + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)patch_buf->atom(); + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); + const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); + if (ev->body.type == _patch_port->bufs().uris().midi_MidiEvent) { + jack_midi_event_write(jack_buf, ev->time.frames, buf, ev->body.size); + } } } } @@ -195,8 +190,7 @@ JackDriver::JackDriver(Engine& engine) , _process_context(engine) , _root_patch(NULL) { - _midi_event_type = _engine.world()->lv2_uri_map()->uri_to_id( - LV2_EVENT_URI, "http://lv2plug.in/ns/ext/midi#MidiEvent"); + _midi_event_type = _engine.world()->uris()->midi_MidiEvent; } JackDriver::~JackDriver() @@ -286,7 +280,7 @@ JackDriver::activate() _is_activated = true; - _process_context.activate(world->conf()->option("parallelism").get_int32(), + _process_context.activate(world->conf()->option("parallelism").get_int(), is_realtime()); if (jack_activate(_client)) { @@ -376,10 +370,12 @@ JackDriver::create_port(DuplexPort* patch_port) { try { if (patch_port->is_a(PortType::AUDIO) - || patch_port->is_a(PortType::EVENTS)) + || (patch_port->is_a(PortType::MESSAGE) && + patch_port->buffer_type() == patch_port->bufs().uris().atom_Sequence)) { return new JackPort(this, patch_port); - else + } else { return NULL; + } } catch (...) { return NULL; } @@ -434,8 +430,8 @@ JackDriver::_process_cb(jack_nframes_t nframes) (*i)->pre_process(_process_context); // Apply control bindings to input - _engine.control_bindings()->pre_process(_process_context, - PtrCast(_root_patch->port_impl(0)->buffer(0)).get()); + _engine.control_bindings()->pre_process( + _process_context, _root_patch->port_impl(0)->buffer(0).get()); _engine.post_processor()->set_end_time(_process_context.end()); @@ -459,8 +455,8 @@ JackDriver::_process_cb(jack_nframes_t nframes) } // Emit control binding feedback - _engine.control_bindings()->post_process(_process_context, - PtrCast(_root_patch->port_impl(1)->buffer(0)).get()); + _engine.control_bindings()->post_process( + _process_context, _root_patch->port_impl(1)->buffer(0).get()); // Signal message context to run if necessary if (_engine.message_context()->has_requests()) diff --git a/src/server/LV2Info.cpp b/src/server/LV2Info.cpp index 4fff9647..130d5dfe 100644 --- a/src/server/LV2Info.cpp +++ b/src/server/LV2Info.cpp @@ -42,7 +42,6 @@ LV2Info::LV2Info(Ingen::Shared::World* world) , control_class(lilv_new_uri(world->lilv_world(), LV2_CORE__ControlPort)) , cv_class(lilv_new_uri(world->lilv_world(), "http://lv2plug.in/ns/ext/cv-port#CVPort")) , audio_class(lilv_new_uri(world->lilv_world(), LV2_CORE__AudioPort)) - , event_class(lilv_new_uri(world->lilv_world(), LILV_URI_EVENT_PORT)) , value_port_class(lilv_new_uri(world->lilv_world(), LV2_ATOM__ValuePort)) , message_port_class(lilv_new_uri(world->lilv_world(), LV2_ATOM__MessagePort)) , _world(world) @@ -62,7 +61,6 @@ LV2Info::~LV2Info() lilv_node_free(control_class); lilv_node_free(cv_class); lilv_node_free(audio_class); - lilv_node_free(event_class); lilv_node_free(value_port_class); lilv_node_free(message_port_class); } diff --git a/src/server/LV2Info.hpp b/src/server/LV2Info.hpp index 297f3742..17132bcc 100644 --- a/src/server/LV2Info.hpp +++ b/src/server/LV2Info.hpp @@ -42,7 +42,6 @@ public: LilvNode* control_class; LilvNode* cv_class; LilvNode* audio_class; - LilvNode* event_class; LilvNode* value_port_class; LilvNode* message_port_class; diff --git a/src/server/LV2Node.cpp b/src/server/LV2Node.cpp index a22b0232..4dc9de0c 100644 --- a/src/server/LV2Node.cpp +++ b/src/server/LV2Node.cpp @@ -30,7 +30,6 @@ #include "ingen/shared/URIs.hpp" #include "AudioBuffer.hpp" -#include "EventBuffer.hpp" #include "InputPort.hpp" #include "LV2Node.hpp" #include "LV2Plugin.hpp" @@ -142,7 +141,7 @@ LV2Node::instantiate(BufferFactory& bufs) const Ingen::Shared::URIs& uris = bufs.uris(); SharedPtr info = _lv2_plugin->lv2_info(); const LilvPlugin* plug = _lv2_plugin->lilv_plugin(); - Raul::Forge& forge = bufs.forge(); + Ingen::Forge& forge = bufs.forge(); uint32_t num_ports = lilv_plugin_get_num_ports(plug); assert(num_ports > 0); @@ -207,6 +206,9 @@ LV2Node::instantiate(BufferFactory& bufs) LilvNode* supports_pred = lilv_new_uri(info->lv2_world(), "http://lv2plug.in/ns/ext/atom#supports"); + LilvNode* bufferType_pred = lilv_new_uri(info->lv2_world(), + "http://lv2plug.in/ns/ext/atom#bufferType"); + //LilvNode as_large_as_pred = lilv_new_uri(info->lv2_world(), // "http://lv2plug.in/ns/ext/resize-port#asLargeAs"); @@ -228,24 +230,40 @@ LV2Node::instantiate(BufferFactory& bufs) port_path = path().child(port_name); Raul::Atom val; - PortType data_type = PortType::UNKNOWN; + PortType port_type = PortType::UNKNOWN; + LV2_URID buffer_type = 0; if (lilv_port_is_a(plug, id, info->control_class)) { - data_type = PortType::CONTROL; + port_type = PortType::CONTROL; + buffer_type = uris.atom_Float; } else if (lilv_port_is_a(plug, id, info->cv_class)) { - data_type = PortType::CV; + port_type = PortType::CV; + buffer_type = uris.atom_Sound; } else if (lilv_port_is_a(plug, id, info->audio_class)) { - data_type = PortType::AUDIO; - } else if (lilv_port_is_a(plug, id, info->event_class)) { - data_type = PortType::EVENTS; + port_type = PortType::AUDIO; + buffer_type = uris.atom_Sound; } else if (lilv_port_is_a(plug, id, info->value_port_class)) { - data_type = PortType::VALUE; + port_type = PortType::VALUE; } else if (lilv_port_is_a(plug, id, info->message_port_class)) { - data_type = PortType::MESSAGE; + port_type = PortType::MESSAGE; + } + + // Get buffer type if necessary (value and message ports) + if (!buffer_type) { + LilvNodes* types = lilv_port_get_value(plug, id, bufferType_pred); + LILV_FOREACH(nodes, i, types) { + const LilvNode* type = lilv_nodes_get(types, i); + if (lilv_node_is_uri(type)) { + port->add_property(uris.atom_bufferType, + forge.alloc_uri(lilv_node_as_uri(type))); + buffer_type = bufs.engine().world()->lv2_uri_map()->map_uri( + lilv_node_as_uri(type)); + } + } } - port_buffer_size = bufs.default_buffer_size(data_type); + port_buffer_size = bufs.default_buffer_size(buffer_type); - if (data_type == PortType::VALUE || data_type == PortType::MESSAGE) { + if (port_type == PortType::VALUE || port_type == PortType::MESSAGE) { // Get default value, and its length LilvNodes* defaults = lilv_port_get_value(plug, id, default_pred); LILV_FOREACH(nodes, i, defaults) { @@ -253,7 +271,7 @@ LV2Node::instantiate(BufferFactory& bufs) if (lilv_node_is_string(d)) { const char* str_val = lilv_node_as_string(d); const size_t str_val_len = strlen(str_val); - val = forge.make(str_val); + val = forge.alloc(str_val); port_buffer_size = str_val_len; } } @@ -276,23 +294,23 @@ LV2Node::instantiate(BufferFactory& bufs) direction = OUTPUT; } - if (data_type == PortType::UNKNOWN || direction == UNKNOWN) { + if (port_type == PortType::UNKNOWN || direction == UNKNOWN) { warn << "Unknown type or direction for port `" << port_name << "'" << endl; ret = false; break; } - if (val.type() == Atom::NIL) + if (!val.type()) val = forge.make(isnan(def_values[j]) ? 0.0f : def_values[j]); // TODO: set buffer size when necessary if (direction == INPUT) - port = new InputPort(bufs, this, port_name, j, _polyphony, data_type, val); + port = new InputPort(bufs, this, port_name, j, _polyphony, port_type, buffer_type, val); else - port = new OutputPort(bufs, this, port_name, j, _polyphony, data_type, val); + port = new OutputPort(bufs, this, port_name, j, _polyphony, port_type, buffer_type, val); - if (direction == INPUT && (data_type == PortType::CONTROL - || data_type == PortType::CV)) { + if (direction == INPUT && (port_type == PortType::CONTROL + || port_type == PortType::CV)) { port->set_value(val); if (!isnan(min_values[j])) { port->set_property(uris.lv2_minimum, forge.make(min_values[j])); @@ -309,7 +327,8 @@ LV2Node::instantiate(BufferFactory& bufs) LILV_FOREACH(nodes, i, properties) { const LilvNode* p = lilv_nodes_get(properties, i); if (lilv_node_is_uri(p)) { - port->add_property(uris.lv2_portProperty, Raul::URI(lilv_node_as_uri(p))); + port->add_property(uris.lv2_portProperty, + forge.alloc_uri(lilv_node_as_uri(p))); } } @@ -318,7 +337,8 @@ LV2Node::instantiate(BufferFactory& bufs) LILV_FOREACH(nodes, i, types) { const LilvNode* type = lilv_nodes_get(types, i); if (lilv_node_is_uri(type)) { - port->add_property(uris.atom_supports, Raul::URI(lilv_node_as_uri(type))); + port->add_property(uris.atom_supports, + forge.alloc_uri(lilv_node_as_uri(type))); } } @@ -411,7 +431,7 @@ LV2Node::set_port_buffer(uint32_t voice, uint32_t port_num, { NodeImpl::set_port_buffer(voice, port_num, buf, offset); lilv_instance_connect_port(instance(voice), port_num, - buf ? buf->port_data(_ports->at(port_num)->buffer_type(), offset) : NULL); + buf ? buf->port_data(_ports->at(port_num)->type(), offset) : NULL); } } // namespace Server diff --git a/src/server/NodeImpl.cpp b/src/server/NodeImpl.cpp index cee1cc0a..12cf2d61 100644 --- a/src/server/NodeImpl.cpp +++ b/src/server/NodeImpl.cpp @@ -155,8 +155,8 @@ NodeImpl::apply_poly(Raul::Maid& maid, uint32_t poly) void NodeImpl::set_buffer_size(Context& context, BufferFactory& bufs, - PortType type, - size_t size) + LV2_URID type, + uint32_t size) { if (_ports) { for (size_t i = 0; i < _ports->size(); ++i) { diff --git a/src/server/NodeImpl.hpp b/src/server/NodeImpl.hpp index d0d7b14e..a5c619fa 100644 --- a/src/server/NodeImpl.hpp +++ b/src/server/NodeImpl.hpp @@ -183,8 +183,8 @@ public: virtual void set_buffer_size(Context& context, BufferFactory& bufs, - PortType type, - size_t size); + LV2_URID type, + uint32_t size); /** The Patch this Node belongs to. */ inline PatchImpl* parent_patch() const { return (PatchImpl*)_parent; } diff --git a/src/server/Notification.cpp b/src/server/Notification.cpp index 44d21a2f..f661337e 100644 --- a/src/server/Notification.cpp +++ b/src/server/Notification.cpp @@ -30,7 +30,7 @@ Notification::post_process(Notification& note, Engine& engine) { const Ingen::Shared::URIs& uris = *engine.world()->uris().get(); - Raul::Forge& forge = engine.world()->forge(); + Ingen::Forge& forge = engine.world()->forge(); switch (note.type) { case PORT_VALUE: engine.broadcaster()->set_property(note.port->path(), diff --git a/src/server/ObjectBuffer.cpp b/src/server/ObjectBuffer.cpp deleted file mode 100644 index 407333d3..00000000 --- a/src/server/ObjectBuffer.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2009-2011 David Robillard - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define __STDC_LIMIT_MACROS 1 -#include -#include -#include -#include "raul/log.hpp" -#include "lv2/lv2plug.in/ns/ext/uri-map/uri-map.h" -#include "ingen_config.h" -#include "ingen/shared/LV2Features.hpp" -#include "ingen/shared/LV2URIMap.hpp" -#include "ObjectBuffer.hpp" -#include "Engine.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Server { - -/** Allocate a new object buffer. - * \a capacity is in bytes, including LV2_Atom header - */ -ObjectBuffer::ObjectBuffer(BufferFactory& bufs, size_t capacity) - : Buffer(bufs, PortType(PortType::VALUE), capacity) -{ - capacity += sizeof(LV2_Atom); - -#ifdef HAVE_POSIX_MEMALIGN - const int ret = posix_memalign((void**)&_buf, 16, capacity); -#else - _buf = (LV2_Atom*)malloc(capacity); - const int ret = (_buf != NULL) ? 0 : -1; -#endif - - if (ret != 0) { - error << "Failed to allocate object buffer. Aborting." << endl; - exit(EXIT_FAILURE); - } - - clear(); -} - -ObjectBuffer::~ObjectBuffer() -{ - free(_buf); -} - -void -ObjectBuffer::clear() -{ - // null - _buf->type = 0; - _buf->size = 0; -} - -void -ObjectBuffer::copy(Context& context, const Buffer* src_buf) -{ - const ObjectBuffer* src = dynamic_cast(src_buf); - if (!src || src == this || src->_buf == _buf) - return; - - // Copy only if src is a POD object that fits - if (src->_buf->type != 0 && src_buf->size() <= size()) - memcpy(_buf, src->_buf, sizeof(LV2_Atom) + src_buf->size()); -} - -void -ObjectBuffer::resize(size_t size) -{ - const uint32_t contents_size = sizeof(LV2_Atom) + _buf->size; - - _buf = (LV2_Atom*)realloc(_buf, sizeof(LV2_Atom) + size); - _size = size + sizeof(LV2_Atom); - - // If we shrunk and chopped the current contents, clear corrupt data - if (size < contents_size) - clear(); -} - -void* -ObjectBuffer::port_data(PortType port_type, SampleCount offset) -{ - switch (port_type.symbol()) { - case PortType::CONTROL: - case PortType::CV: - case PortType::AUDIO: - switch (_type.symbol()) { - case PortType::CONTROL: - return (float*)LV2_ATOM_BODY(atom()); - case PortType::CV: - case PortType::AUDIO: - return (float*)LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom()) + offset; - default: - warn << "Audio data requested from non-audio buffer" << endl; - return NULL; - } - break; - default: - return _buf; - } -} - -const void* -ObjectBuffer::port_data(PortType port_type, SampleCount offset) const -{ - switch (port_type.symbol()) { - case PortType::CONTROL: - case PortType::CV: - case PortType::AUDIO: - switch (_type.symbol()) { - case PortType::CONTROL: - return (float*)LV2_ATOM_BODY(atom()); - case PortType::CV: - case PortType::AUDIO: - return (float*)LV2_ATOM_CONTENTS(LV2_Atom_Vector, atom()) + offset; - default: - warn << "Audio data requested from non-audio buffer" << endl; - return NULL; - } - break; - default: - return _buf; - } -} - -void -ObjectBuffer::prepare_write(Context& context) -{ - _buf->size = _size - sizeof(LV2_Atom); -} - -} // namespace Server -} // namespace Ingen - diff --git a/src/server/ObjectBuffer.hpp b/src/server/ObjectBuffer.hpp deleted file mode 100644 index 93dc746b..00000000 --- a/src/server/ObjectBuffer.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2009-2011 David Robillard - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef INGEN_ENGINE_OBJECTBUFFER_HPP -#define INGEN_ENGINE_OBJECTBUFFER_HPP - -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" - -#include "Buffer.hpp" - -namespace Ingen { -namespace Server { - -class Context; - -class ObjectBuffer : public Buffer { -public: - ObjectBuffer(BufferFactory& bufs, size_t capacity); - ~ObjectBuffer(); - - void clear(); - - void* port_data(PortType port_type, SampleCount offset); - const void* port_data(PortType port_type, SampleCount offset) const; - - void prepare_write(Context& context); - - void copy(Context& context, const Buffer* src); - - void resize(size_t size); - - LV2_Atom* atom() { return _buf; } - const LV2_Atom* atom() const { return _buf; } - -private: - LV2_Atom* _buf; ///< Contents -}; - -} // namespace Server -} // namespace Ingen - -#endif // INGEN_ENGINE_OBJECTBUFFER_HPP diff --git a/src/server/OutputPort.cpp b/src/server/OutputPort.cpp index 11f637b3..8d454201 100644 --- a/src/server/OutputPort.cpp +++ b/src/server/OutputPort.cpp @@ -35,9 +35,10 @@ OutputPort::OutputPort(BufferFactory& bufs, uint32_t index, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size) - : PortImpl(bufs, parent, symbol, index, poly, type, value, buffer_size) + : PortImpl(bufs, parent, symbol, index, poly, type, buffer_type, value, buffer_size) { if (!dynamic_cast(parent)) add_property(bufs.uris().rdf_type, bufs.uris().lv2_OutputPort); diff --git a/src/server/OutputPort.hpp b/src/server/OutputPort.hpp index 168ab7c4..906c9c64 100644 --- a/src/server/OutputPort.hpp +++ b/src/server/OutputPort.hpp @@ -46,6 +46,7 @@ public: uint32_t index, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size=0); diff --git a/src/server/PatchImpl.cpp b/src/server/PatchImpl.cpp index c2d97d41..dca7f2ae 100644 --- a/src/server/PatchImpl.cpp +++ b/src/server/PatchImpl.cpp @@ -258,8 +258,8 @@ PatchImpl::process_single(ProcessContext& context) void PatchImpl::set_buffer_size(Context& context, BufferFactory& bufs, - PortType type, - size_t size) + LV2_URID type, + uint32_t size) { NodeImpl::set_buffer_size(context, bufs, type, size); @@ -346,7 +346,8 @@ PortImpl* PatchImpl::create_port(BufferFactory& bufs, const string& name, PortType type, - size_t buffer_size, + LV2_URID buffer_type, + uint32_t buffer_size, bool is_output, bool polyphonic) { @@ -360,7 +361,7 @@ PatchImpl::create_port(BufferFactory& bufs, value = bufs.forge().make(0.0f); return new DuplexPort(bufs, this, name, num_ports(), polyphonic, _polyphony, - type, value, buffer_size, is_output); + type, buffer_type, value, buffer_size, is_output); } /** Remove port from ports list used in pre-processing thread. diff --git a/src/server/PatchImpl.hpp b/src/server/PatchImpl.hpp index 004eb0cb..5704fad0 100644 --- a/src/server/PatchImpl.hpp +++ b/src/server/PatchImpl.hpp @@ -69,8 +69,8 @@ public: void set_buffer_size(Context& context, BufferFactory& bufs, - PortType type, - size_t size); + LV2_URID type, + uint32_t size); /** Prepare for a new (internal) polyphony value. * @@ -111,7 +111,8 @@ public: PortImpl* create_port(BufferFactory& bufs, const std::string& name, PortType type, - size_t buffer_size, + LV2_URID buffer_type, + uint32_t buffer_size, bool is_output, bool polyphonic); diff --git a/src/server/PortImpl.cpp b/src/server/PortImpl.cpp index 67255e5f..3cc8082c 100644 --- a/src/server/PortImpl.cpp +++ b/src/server/PortImpl.cpp @@ -27,10 +27,8 @@ #include "AudioBuffer.hpp" #include "BufferFactory.hpp" #include "Engine.hpp" -#include "EventBuffer.hpp" #include "NodeImpl.hpp" #include "Notification.hpp" -#include "ObjectBuffer.hpp" #include "PortImpl.hpp" #include "PortType.hpp" #include "ThreadManager.hpp" @@ -47,6 +45,7 @@ PortImpl::PortImpl(BufferFactory& bufs, uint32_t index, uint32_t poly, PortType type, + LV2_URID buffer_type, const Atom& value, size_t buffer_size) : GraphObjectImpl(bufs.uris(), node, name) @@ -55,6 +54,7 @@ PortImpl::PortImpl(BufferFactory& bufs, , _poly(poly) , _buffer_size(buffer_size) , _type(type) + , _buffer_type(buffer_type) , _value(value) , _min(bufs.forge().make(0.0f)) , _max(bufs.forge().make(1.0f)) @@ -68,11 +68,27 @@ PortImpl::PortImpl(BufferFactory& bufs, assert(node != NULL); assert(_poly > 0); - if (_buffer_size == 0) - _buffer_size = bufs.default_buffer_size(type); - const Ingen::Shared::URIs& uris = bufs.uris(); - add_property(uris.rdf_type, type.uri()); + + if (_buffer_size == 0) { + _buffer_size = bufs.default_buffer_size(buffer_type); + } + + if (_buffer_type == 0) { + switch (_type.symbol()) { + case PortType::CONTROL: + _buffer_type = uris.atom_Float; + break; + case PortType::AUDIO: + case PortType::CV: + _buffer_type = uris.atom_Sound; + break; + default: + break; + } + } + + add_property(uris.rdf_type, bufs.forge().alloc_uri(type.uri().str())); set_property(uris.lv2_index, bufs.forge().make((int32_t)index)); set_context(_context); } @@ -85,7 +101,8 @@ PortImpl::~PortImpl() bool PortImpl::supports(const Raul::URI& value_type) const { - return has_property(_bufs.uris().atom_supports, value_type); + return has_property(_bufs.uris().atom_supports, + _bufs.forge().alloc_uri(value_type.str())); } Raul::Array* @@ -108,9 +125,9 @@ bool PortImpl::prepare_poly(BufferFactory& bufs, uint32_t poly) { ThreadManager::assert_thread(THREAD_PRE_PROCESS); - if (buffer_type() != PortType::CONTROL && - buffer_type() != PortType::CV && - buffer_type() != PortType::AUDIO) { + if (_type != PortType::CONTROL && + _type != PortType::CV && + _type != PortType::AUDIO) { return false; } @@ -140,9 +157,9 @@ bool PortImpl::apply_poly(Maid& maid, uint32_t poly) { ThreadManager::assert_thread(THREAD_PROCESS); - if (buffer_type() != PortType::CONTROL && - buffer_type() != PortType::CV && - buffer_type() != PortType::AUDIO) { + if (_type != PortType::CONTROL && + _type != PortType::CV && + _type != PortType::AUDIO) { return false; } @@ -207,8 +224,8 @@ PortImpl::clear_buffers() void PortImpl::broadcast_value(Context& context, bool force) { - Raul::Forge& forge = context.engine().world()->forge(); - Raul::Atom val; + Ingen::Forge& forge = context.engine().world()->forge(); + Raul::Atom val; switch (_type.symbol()) { case PortType::UNKNOWN: break; @@ -224,21 +241,16 @@ PortImpl::broadcast_value(Context& context, bool force) case PortType::CV: val = forge.make(((AudioBuffer*)buffer(0).get())->value_at(0)); break; - case PortType::EVENTS: - if (((EventBuffer*)buffer(0).get())->event_count() > 0) { - const Notification note = Notification::make( - Notification::PORT_ACTIVITY, context.start(), this, forge.make(true)); - context.event_sink().write(sizeof(note), ¬e); - } - break; case PortType::VALUE: case PortType::MESSAGE: - std::cerr << "FIXME: Atom value" << std::endl; - /* - Ingen::Shared::LV2Atom::to_atom(_bufs.uris(), - ((ObjectBuffer*)buffer(0).get())->atom(), - val); - */ + if (_buffer_type == _bufs.uris().atom_Sequence) { + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)buffer(0)->atom(); + if (seq->atom.size > sizeof(LV2_Atom_Sequence_Body)) { + const Notification note = Notification::make( + Notification::PORT_ACTIVITY, context.start(), this, forge.make(true)); + context.event_sink().write(sizeof(note), ¬e); + } + } break; } @@ -265,11 +277,5 @@ PortImpl::set_context(Context::ID c) } } -PortType -PortImpl::buffer_type() const -{ - return _type; -} - } // namespace Server } // namespace Ingen diff --git a/src/server/PortImpl.hpp b/src/server/PortImpl.hpp index 2316a1d9..c67be49b 100644 --- a/src/server/PortImpl.hpp +++ b/src/server/PortImpl.hpp @@ -124,7 +124,8 @@ public: inline bool is_a(PortType type) const { return _type == type; } - PortType buffer_type() const; + PortType type() const { return _type; } + LV2_URID buffer_type() const { return _buffer_type; } bool supports(const Raul::URI& value_type) const; @@ -158,6 +159,7 @@ protected: uint32_t index, uint32_t poly, PortType type, + LV2_URID buffer_type, const Raul::Atom& value, size_t buffer_size); @@ -166,6 +168,7 @@ protected: uint32_t _poly; uint32_t _buffer_size; PortType _type; + LV2_URID _buffer_type; Raul::Atom _value; Raul::Atom _min; Raul::Atom _max; diff --git a/src/server/PortType.hpp b/src/server/PortType.hpp index b8fd747e..a2eac676 100644 --- a/src/server/PortType.hpp +++ b/src/server/PortType.hpp @@ -35,9 +35,8 @@ public: AUDIO = 1, CONTROL = 2, CV = 3, - EVENTS = 4, - VALUE = 5, - MESSAGE = 6, + VALUE = 4, + MESSAGE = 5, }; PortType(const Raul::URI& uri) @@ -49,8 +48,6 @@ public: _symbol = CONTROL; } else if (uri == type_uri(CV)) { _symbol = CV; - } else if (uri == type_uri(EVENTS)) { - _symbol = EVENTS; } else if (uri == type_uri(VALUE)) { _symbol = VALUE; } else if (uri == type_uri(MESSAGE)) { @@ -74,7 +71,6 @@ public: inline bool is_audio() { return _symbol == AUDIO; } inline bool is_control() { return _symbol == CONTROL; } inline bool is_cv() { return _symbol == CV; } - inline bool is_events() { return _symbol == EVENTS; } inline bool is_value() { return _symbol == VALUE; } inline bool is_message() { return _symbol == MESSAGE; } @@ -86,7 +82,6 @@ private: "http://lv2plug.in/ns/lv2core#AudioPort", "http://lv2plug.in/ns/lv2core#ControlPort", "http://lv2plug.in/ns/ext/cv-port#CVPort", - "http://lv2plug.in/ns/ext/event#EventPort", "http://lv2plug.in/ns/ext/atom#ValuePort", "http://lv2plug.in/ns/ext/atom#MessagePort" }; diff --git a/src/server/ServerInterfaceImpl.cpp b/src/server/ServerInterfaceImpl.cpp index f03294b2..69b26141 100644 --- a/src/server/ServerInterfaceImpl.cpp +++ b/src/server/ServerInterfaceImpl.cpp @@ -161,7 +161,7 @@ ServerInterfaceImpl::set_property(const URI& uri, const Atom& value) { if (uri == "ingen:engine" && predicate == "ingen:enabled" - && value.type() == Atom::BOOL) { + && value.type() == _engine.world()->forge().Bool) { if (value.get_bool()) { _engine.activate(); push_queued(new Events::Ping(_engine, _request_client, _request_id, now())); diff --git a/src/server/ServerInterfaceImpl.hpp b/src/server/ServerInterfaceImpl.hpp index 0ba3a1b9..21100222 100644 --- a/src/server/ServerInterfaceImpl.hpp +++ b/src/server/ServerInterfaceImpl.hpp @@ -51,6 +51,8 @@ public: Raul::URI uri() const { return "http://drobilla.net/ns/ingen#internal"; } + void set_response_interface(Interface* iface) { _request_client = iface; } + virtual void set_response_id(int32_t id); virtual void bundle_begin(); diff --git a/src/server/events/CreateNode.cpp b/src/server/events/CreateNode.cpp index d74b0b6c..7098196a 100644 --- a/src/server/events/CreateNode.cpp +++ b/src/server/events/CreateNode.cpp @@ -61,7 +61,7 @@ CreateNode::CreateNode(Engine& engine, { const Resource::Properties::const_iterator p = properties.find( engine.world()->uris()->ingen_polyphonic); - if (p != properties.end() && p->second.type() == Raul::Atom::BOOL + if (p != properties.end() && p->second.type() == engine.world()->forge().Bool && p->second.get_bool()) _polyphonic = true; } diff --git a/src/server/events/CreatePort.cpp b/src/server/events/CreatePort.cpp index 6fa4a6bf..cc6f7e93 100644 --- a/src/server/events/CreatePort.cpp +++ b/src/server/events/CreatePort.cpp @@ -49,7 +49,8 @@ CreatePort::CreatePort(Engine& engine, const Resource::Properties& properties) : Event(engine, client, id, timestamp) , _path(path) - , _data_type(PortType::UNKNOWN) + , _port_type(PortType::UNKNOWN) + , _buffer_type(0) , _patch(NULL) , _patch_port(NULL) , _ports_array(NULL) @@ -61,30 +62,31 @@ CreatePort::CreatePort(Engine& engine, typedef Resource::Properties::const_iterator Iterator; typedef std::pair Range; + const Range types = properties.equal_range(uris.rdf_type); for (Iterator i = types.first; i != types.second; ++i) { const Raul::Atom& type = i->second; - if (type.type() != Atom::URI) { - warn << "Non-URI port type " << type << endl; - continue; - } - if (type == uris.lv2_AudioPort) { - _data_type = PortType::AUDIO; + _port_type = PortType::AUDIO; } else if (type == uris.lv2_ControlPort) { - _data_type = PortType::CONTROL; + _port_type = PortType::CONTROL; } else if (type == uris.cv_CVPort) { - _data_type = PortType::CV; - } else if (type == uris.ev_EventPort) { - _data_type = PortType::EVENTS; + _port_type = PortType::CV; } else if (type == uris.atom_ValuePort) { - _data_type = PortType::VALUE; + _port_type = PortType::VALUE; } else if (type == uris.atom_MessagePort) { - _data_type = PortType::MESSAGE; + _port_type = PortType::MESSAGE; + } + } + + const Range buffer_types = properties.equal_range(uris.atom_bufferType); + for (Iterator i = buffer_types.first; i != buffer_types.second; ++i) { + if (i->second.type() == _engine.world()->forge().URI) { + _buffer_type = _engine.world()->lv2_uri_map()->map_uri(i->second.get_uri()); } } - if (_data_type == PortType::UNKNOWN) { + if (_port_type == PortType::UNKNOWN) { _status = UNKNOWN_TYPE; } } @@ -104,7 +106,7 @@ CreatePort::pre_process() if (_patch != NULL) { assert(_patch->path() == _path.parent()); - size_t buffer_size = _engine.buffer_factory()->default_buffer_size(_data_type); + size_t buffer_size = _engine.buffer_factory()->default_buffer_size(_buffer_type); const uint32_t old_num_ports = (_patch->external_ports()) ? _patch->external_ports()->size() @@ -115,7 +117,7 @@ CreatePort::pre_process() index_i = _properties.insert( make_pair(uris.lv2_index, _engine.world()->forge().make(int32_t(old_num_ports)))); - } else if (index_i->second.type() != Atom::INT + } else if (index_i->second.type() != uris.forge.Int || index_i->second.get_int32() != static_cast(old_num_ports)) { Event::pre_process(); _status = BAD_INDEX; @@ -123,10 +125,12 @@ CreatePort::pre_process() } Resource::Properties::const_iterator poly_i = _properties.find(uris.ingen_polyphonic); - bool polyphonic = (poly_i != _properties.end() && poly_i->second.type() == Atom::BOOL + bool polyphonic = (poly_i != _properties.end() && poly_i->second.type() == uris.forge.Bool && poly_i->second.get_bool()); - _patch_port = _patch->create_port(*_engine.buffer_factory(), _path.symbol(), _data_type, buffer_size, _is_output, polyphonic); + _patch_port = _patch->create_port(*_engine.buffer_factory(), _path.symbol(), + _port_type, _buffer_type, buffer_size, + _is_output, polyphonic); _patch_port->properties().insert(_properties.begin(), _properties.end()); diff --git a/src/server/events/CreatePort.hpp b/src/server/events/CreatePort.hpp index 331a1252..45fedebc 100644 --- a/src/server/events/CreatePort.hpp +++ b/src/server/events/CreatePort.hpp @@ -18,13 +18,13 @@ #ifndef INGEN_EVENTS_CREATEPORT_HPP #define INGEN_EVENTS_CREATEPORT_HPP +#include "ingen/Resource.hpp" +#include "lv2/lv2plug.in/ns/ext/urid/urid.h" #include "raul/Array.hpp" #include "raul/Path.hpp" -#include "ingen/Resource.hpp" - -#include "PortType.hpp" #include "Event.hpp" +#include "PortType.hpp" namespace Ingen { namespace Server { @@ -57,7 +57,8 @@ public: private: Raul::Path _path; Raul::URI _type; - PortType _data_type; + PortType _port_type; + LV2_URID _buffer_type; PatchImpl* _patch; PortImpl* _patch_port; Raul::Array* _ports_array; ///< New (external) ports array for Patch diff --git a/src/server/events/SetMetadata.cpp b/src/server/events/SetMetadata.cpp index e2621fae..1c4ac0e6 100644 --- a/src/server/events/SetMetadata.cpp +++ b/src/server/events/SetMetadata.cpp @@ -129,7 +129,7 @@ SetMetadata::pre_process() if (is_patch) { uint32_t poly = 1; iterator p = _properties.find(uris.ingen_polyphony); - if (p != _properties.end() && p->second.is_valid() && p->second.type() == Atom::INT) + if (p != _properties.end() && p->second.is_valid() && p->second.type() == uris.forge.Int) poly = p->second.get_int32(); _create_event = new CreatePatch(_engine, _request_client, _request_id, _time, path, poly, _properties); @@ -186,7 +186,7 @@ SetMetadata::pre_process() PortImpl* port = dynamic_cast(_object); if (port) { if (key == uris.ingen_broadcast) { - if (value.type() == Atom::BOOL) { + if (value.type() == uris.forge.Bool) { op = ENABLE_BROADCAST; } else { _status = BAD_VALUE_TYPE; @@ -200,7 +200,7 @@ SetMetadata::pre_process() if (port->is_a(PortType::CONTROL) || port->is_a(PortType::CV)) { if (value == uris.wildcard) { _engine.control_bindings()->learn(port); - } else if (value.type() == Atom::DICT) { + } else if (value.type() == uris.forge.Dict) { op = CONTROL_BINDING; } else { _status = BAD_VALUE_TYPE; @@ -211,7 +211,7 @@ SetMetadata::pre_process() } } else if ((_patch = dynamic_cast(_object))) { if (key == uris.ingen_enabled) { - if (value.type() == Atom::BOOL) { + if (value.type() == uris.forge.Bool) { op = ENABLE; // FIXME: defer this until all other metadata has been processed if (value.get_bool() && !_patch->enabled()) @@ -220,7 +220,7 @@ SetMetadata::pre_process() _status = BAD_VALUE_TYPE; } } else if (key == uris.ingen_polyphony) { - if (value.type() == Atom::INT) { + if (value.type() == uris.forge.Int) { op = POLYPHONY; _patch->prepare_internal_poly(*_engine.buffer_factory(), value.get_int32()); } else { @@ -230,7 +230,7 @@ SetMetadata::pre_process() } else if (key == uris.ingen_polyphonic) { PatchImpl* parent = dynamic_cast(obj->parent()); if (parent) { - if (value.type() == Atom::BOOL) { + if (value.type() == uris.forge.Bool) { op = POLYPHONIC; obj->set_property(key, value, value.context()); NodeImpl* node = dynamic_cast(obj); @@ -288,7 +288,7 @@ SetMetadata::execute(ProcessContext& context) std::vector::const_iterator t = _types.begin(); for (Properties::const_iterator p = _properties.begin(); p != _properties.end(); ++p, ++t) { - const Raul::Atom& key = p->first; + const Raul::URI& key = p->first; const Raul::Atom& value = p->second; switch (*t) { case ENABLE_BROADCAST: diff --git a/src/server/events/SetPortValue.cpp b/src/server/events/SetPortValue.cpp index ecf9416e..00f72a51 100644 --- a/src/server/events/SetPortValue.cpp +++ b/src/server/events/SetPortValue.cpp @@ -22,7 +22,6 @@ #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" #include "ingen/shared/World.hpp" -#include "lv2/lv2plug.in/ns/ext/event/event.h" #include "raul/log.hpp" #include "AudioBuffer.hpp" @@ -31,10 +30,8 @@ #include "Driver.hpp" #include "Engine.hpp" #include "EngineStore.hpp" -#include "EventBuffer.hpp" #include "MessageContext.hpp" #include "NodeImpl.hpp" -#include "ObjectBuffer.hpp" #include "PortImpl.hpp" #include "ProcessContext.hpp" #include "SetPortValue.hpp" @@ -129,6 +126,8 @@ SetPortValue::apply(Context& context) if (_status == SUCCESS && !_port) _port = _engine.engine_store()->find_port(_port_path); + Ingen::Shared::URIs& uris = *_engine.world()->uris().get(); + if (!_port) { if (_status == SUCCESS) _status = PORT_NOT_FOUND; @@ -138,7 +137,7 @@ SetPortValue::apply(Context& context) Buffer* const buf = _port->buffer(0).get(); AudioBuffer* const abuf = dynamic_cast(buf); if (abuf) { - if (_value.type() != Atom::FLOAT) { + if (_value.type() != uris.forge.Float) { _status = TYPE_MISMATCH; return; } @@ -150,44 +149,6 @@ SetPortValue::apply(Context& context) return; } - Ingen::Shared::URIs& uris = *_engine.world()->uris().get(); - Ingen::Shared::LV2URIMap& uri_map = *_engine.world()->lv2_uri_map().get(); - - EventBuffer* const ebuf = dynamic_cast(buf); - if (ebuf && _value.type() == Atom::BLOB) { - const uint32_t frames = std::max(uint32_t(_time - start), ebuf->latest_frames()); - - // Size 0 event, pass it along to the plugin as a typed but empty event - if (_value.data_size() == 0) { - const uint32_t type_id = uri_map.uri_to_id(NULL, _value.get_blob_type()); - ebuf->append(frames, 0, type_id, 0, NULL); - _port->raise_set_by_user_flag(); - return; - - } else if (!strcmp(_value.get_blob_type(), - "http://lv2plug.in/ns/ext/midi#MidiEvent")) { - ebuf->prepare_write(context); - ebuf->append(frames, 0, - uri_map.global_to_event(uris.midi_MidiEvent.id).second, - _value.data_size(), - (const uint8_t*)_value.get_blob()); - _port->raise_set_by_user_flag(); - return; - } - } - - ObjectBuffer* const obuf = dynamic_cast(buf); - if (obuf) { - obuf->atom()->size = obuf->size() - sizeof(LV2_Atom); - if (Ingen::Shared::LV2Atom::from_atom(uris, _value, obuf->atom())) { - debug << "Converted atom " << _value << " :: " << obuf->atom()->type - << " * " << obuf->atom()->size << " @ " << obuf->atom() << endl; - return; - } else { - warn << "Failed to convert atom to LV2 object" << endl; - } - } - warn << "Unknown value type " << (int)_value.type() << endl; } } diff --git a/src/server/ingen_jack.cpp b/src/server/ingen_jack.cpp index 267b13aa..fd80d804 100644 --- a/src/server/ingen_jack.cpp +++ b/src/server/ingen_jack.cpp @@ -34,8 +34,11 @@ struct IngenJackModule : public Ingen::Shared::Module { Server::JackDriver* driver = new Server::JackDriver( *(Server::Engine*)world->local_engine().get()); - driver->attach(world->conf()->option("jack-server").get_string(), - world->conf()->option("jack-client").get_string(), NULL); + const Raul::Configuration::Value& s = world->conf()->option("jack-server"); + const std::string server_name = s.is_valid() ? s.get_string() : ""; + driver->attach(server_name, + world->conf()->option("jack-client").get_string(), + NULL); ((Server::Engine*)world->local_engine().get())->set_driver( SharedPtr(driver)); } diff --git a/src/server/ingen_lv2.cpp b/src/server/ingen_lv2.cpp index 3e9366ae..e6552e69 100644 --- a/src/server/ingen_lv2.cpp +++ b/src/server/ingen_lv2.cpp @@ -29,10 +29,13 @@ #include "lv2/lv2plug.in/ns/lv2core/lv2.h" #include "lv2/lv2plug.in/ns/ext/state/state.h" #include "lv2/lv2plug.in/ns/ext/urid/urid.h" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" #include "ingen/Interface.hpp" #include "ingen/serialisation/Parser.hpp" #include "ingen/serialisation/Serialiser.hpp" +#include "ingen/shared/AtomReader.hpp" +#include "ingen/shared/AtomWriter.hpp" #include "ingen/shared/Configuration.hpp" #include "ingen/shared/Store.hpp" #include "ingen/shared/World.hpp" @@ -54,7 +57,7 @@ #define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" #define NS_RDFS "http://www.w3.org/2000/01/rdf-schema#" -/** Record of a patch in this Ingen LV2 bundle */ +/** Record of a patch in this bundle. */ struct LV2Patch { LV2Patch(const std::string& u, const std::string& f); @@ -63,6 +66,7 @@ struct LV2Patch { LV2_Descriptor descriptor; }; +/** Ingen LV2 library. */ class Lib { public: Lib(const char* bundle_path); @@ -77,6 +81,8 @@ namespace Server { class LV2Driver; +void handle_message(LV2Driver* driver, const LV2_Atom* msg); + class LV2Port : public DriverPort { public: @@ -92,26 +98,31 @@ public: void move(const Raul::Path& path) {} void pre_process(ProcessContext& context) { - if (!is_input() || !_buffer) + if (!is_input() || !_buffer) { return; + } if (_patch_port->is_a(PortType::AUDIO)) { AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0).get(); patch_buf->copy((Sample*)_buffer, 0, context.nframes() - 1); - } else if (_patch_port->is_a(PortType::EVENTS)) { - //Raul::warn << "TODO: LV2 event I/O" << std::endl; + } else { + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)_buffer; + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* ev = lv2_sequence_iter_get(i); + // FIXME: Not RT safe, need to send these through a ring + handle_message(_driver, &ev->body); + } } } void post_process(ProcessContext& context) { - if (is_input() || !_buffer) + if (is_input() || !_buffer) { return; + } if (_patch_port->is_a(PortType::AUDIO)) { AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0).get(); memcpy((Sample*)_buffer, patch_buf->data(), context.nframes() * sizeof(Sample)); - } else if (_patch_port->is_a(PortType::EVENTS)) { - //Raul::warn << "TODO: LV2 event I/O" << std::endl; } } @@ -123,13 +134,23 @@ private: void* _buffer; }; -class LV2Driver : public Ingen::Server::Driver { +class LV2Driver : public Ingen::Server::Driver + , public Ingen::Shared::AtomSink +{ private: typedef std::vector Ports; public: LV2Driver(Engine& engine, SampleCount buffer_size, SampleCount sample_rate) : _context(engine) + , _reader(*engine.world()->lv2_uri_map().get(), + *engine.world()->uris().get(), + engine.world()->forge(), + *engine.world()->engine().get()) + , _writer(*engine.world()->lv2_uri_map().get(), + *engine.world()->uris().get(), + *this) + , _to_ui(8192) // FIXME: size , _root_patch(NULL) , _buffer_size(buffer_size) , _sample_rate(sample_rate) @@ -147,6 +168,8 @@ public: if (_root_patch) _root_patch->process(_context); + flush_to_ui(); + for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) (*i)->post_process(_context); @@ -194,24 +217,88 @@ public: return NULL; } + void write(const LV2_Atom* atom) { + // Called from post-processor in main thread + if (_to_ui.write(lv2_atom_total_size(atom), atom) == 0) { + Raul::error << "To-UI ring overflow" << std::endl; + } + } + + void flush_to_ui() { + assert(ThreadManager::thread_is(THREAD_PROCESS)); + assert(_ports.size() >= 2); + + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)_ports[1]->buffer(); + if (!seq) { + Raul::warn << "Control out port not connected" << std::endl; + return; + } + + // Output port buffer is a Chunk with size set to the available space + const uint32_t capacity = seq->atom.size; + + // Initialise output port buffer to an empty Sequence + seq->atom.type = _context.engine().world()->uris()->atom_Sequence; + seq->atom.size = sizeof(LV2_Atom_Sequence_Body); + + const uint32_t read_space = _to_ui.read_space(); + for (uint32_t read = 0; read < read_space;) { + LV2_Atom atom; + if (!_to_ui.peek(sizeof(LV2_Atom), &atom)) { + Raul::error << "Error reading head from to-UI ring" << std::endl; + break; + } + + if (seq->atom.size + sizeof(LV2_Atom) + atom.size > capacity) { + break; // Output port buffer full, resume next time + } + + LV2_Atom_Event* ev = (LV2_Atom_Event*)( + (uint8_t*)seq + lv2_atom_total_size(&seq->atom)); + + ev->time.frames = 0; // TODO: Time? + ev->body = atom; + + _to_ui.skip(sizeof(LV2_Atom)); + if (!_to_ui.read(ev->body.size, LV2_ATOM_BODY(&ev->body))) { + Raul::error << "Error reading body from to-UI ring" << std::endl; + break; + } + + read += lv2_atom_total_size(&ev->body); + seq->atom.size += sizeof(LV2_Atom_Event) + ev->body.size; + } + } + virtual SampleCount block_length() const { return _buffer_size; } virtual SampleCount sample_rate() const { return _sample_rate; } virtual SampleCount frame_time() const { return _frame_time;} virtual bool is_realtime() const { return true; } virtual ProcessContext& context() { return _context; } + Shared::AtomReader& reader() { return _reader; } + Shared::AtomWriter& writer() { return _writer; } Ports& ports() { return _ports; } private: - ProcessContext _context; - PatchImpl* _root_patch; - SampleCount _buffer_size; - SampleCount _sample_rate; - SampleCount _frame_time; - Ports _ports; + ProcessContext _context; + Shared::AtomReader _reader; + Shared::AtomWriter _writer; + Raul::RingBuffer _to_ui; + PatchImpl* _root_patch; + SampleCount _buffer_size; + SampleCount _sample_rate; + SampleCount _frame_time; + Ports _ports; }; +void +handle_message(LV2Driver* driver, const LV2_Atom* msg) +{ + driver->reader().write(msg); +} + } // namespace Server } // namespace Ingen @@ -236,7 +323,7 @@ private: }; struct IngenPlugin { - Raul::Forge forge; + Ingen::Forge forge; Ingen::Shared::Configuration* conf; Ingen::Shared::World* world; MainThread* main; @@ -304,7 +391,7 @@ ingen_instantiate(const LV2_Descriptor* descriptor, } IngenPlugin* plugin = (IngenPlugin*)malloc(sizeof(IngenPlugin)); - plugin->conf = new Ingen::Shared::Configuration(&plugin->forge); + plugin->conf = new Ingen::Shared::Configuration(); plugin->main = NULL; plugin->map = NULL; LV2_URID_Unmap* unmap = NULL; @@ -341,6 +428,10 @@ ingen_instantiate(const LV2_Descriptor* descriptor, LV2Driver* driver = new LV2Driver(*engine.get(), rate, 4096); engine->set_driver(SharedPtr(driver)); + interface->set_response_interface(&driver->writer()); + engine->register_client("http://drobilla.net/ns/ingen#internal", + &driver->writer()); + engine->activate(); Server::ThreadManager::single_threaded = true; @@ -350,7 +441,7 @@ ingen_instantiate(const LV2_Descriptor* descriptor, engine->post_processor()->set_end_time(UINT_MAX); // TODO: Load only necessary plugins - plugin->world->engine()->get("ingen:plugins"); + //plugin->world->engine()->get("ingen:plugins"); interface->process(*engine->post_processor(), context, false); engine->post_processor()->process(); @@ -365,7 +456,7 @@ ingen_instantiate(const LV2_Descriptor* descriptor, engine->deactivate(); - plugin->world->load_module("osc_server"); + //plugin->world->load_module("osc_server"); return (LV2_Handle)plugin; } @@ -381,6 +472,7 @@ ingen_connect_port(LV2_Handle instance, uint32_t port, void* data) if (port < driver->ports().size()) { driver->ports().at(port)->set_buffer(data); assert(driver->ports().at(port)->patch_port()->index() == port); + assert(driver->ports().at(port)->buffer() == data); } else { Raul::warn << "Connect to non-existent port " << port << std::endl; } @@ -391,6 +483,7 @@ ingen_activate(LV2_Handle instance) { IngenPlugin* me = (IngenPlugin*)instance; me->world->local_engine()->activate(); + ((ServerInterfaceImpl*)me->world->engine().get())->start(); me->main->start(); } diff --git a/src/server/internals/Controller.cpp b/src/server/internals/Controller.cpp index e93d5f27..3c29edd3 100644 --- a/src/server/internals/Controller.cpp +++ b/src/server/internals/Controller.cpp @@ -20,10 +20,10 @@ #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" #include "internals/Controller.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" #include "raul/midi_events.h" #include "AudioBuffer.hpp" -#include "EventBuffer.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" #include "Notification.hpp" @@ -54,37 +54,38 @@ ControllerNode::ControllerNode(InternalPlugin* plugin, const Ingen::Shared::URIs& uris = bufs.uris(); _ports = new Raul::Array(6); - _midi_in_port = new InputPort(bufs, this, "input", 0, 1, PortType::EVENTS, Raul::Atom()); - _midi_in_port->set_property(uris.lv2_name, bufs.forge().make("Input")); + _midi_in_port = new InputPort(bufs, this, "input", 0, 1, + PortType::MESSAGE, uris.atom_Sequence, Raul::Atom()); + _midi_in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); _ports->at(0) = _midi_in_port; _param_port = new InputPort(bufs, this, "controller", 1, 1, - PortType::CONTROL, bufs.forge().make(0.0f)); + PortType::CONTROL, 0, bufs.forge().make(0.0f)); _param_port->set_property(uris.lv2_minimum, bufs.forge().make(0.0f)); _param_port->set_property(uris.lv2_maximum, bufs.forge().make(127.0f)); _param_port->set_property(uris.lv2_integer, bufs.forge().make(true)); - _param_port->set_property(uris.lv2_name, bufs.forge().make("Controller")); + _param_port->set_property(uris.lv2_name, bufs.forge().alloc("Controller")); _ports->at(1) = _param_port; _log_port = new InputPort(bufs, this, "logarithmic", 2, 1, - PortType::CONTROL, bufs.forge().make(0.0f)); + PortType::CONTROL, 0, bufs.forge().make(0.0f)); _log_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _log_port->set_property(uris.lv2_name, bufs.forge().make("Logarithmic")); + _log_port->set_property(uris.lv2_name, bufs.forge().alloc("Logarithmic")); _ports->at(2) = _log_port; _min_port = new InputPort(bufs, this, "minimum", 3, 1, - PortType::CONTROL, bufs.forge().make(0.0f)); - _min_port->set_property(uris.lv2_name, bufs.forge().make("Minimum")); + PortType::CONTROL, 0, bufs.forge().make(0.0f)); + _min_port->set_property(uris.lv2_name, bufs.forge().alloc("Minimum")); _ports->at(3) = _min_port; _max_port = new InputPort(bufs, this, "maximum", 4, 1, - PortType::CONTROL, bufs.forge().make(1.0f)); - _max_port->set_property(uris.lv2_name, bufs.forge().make("Maximum")); + PortType::CONTROL, 0, bufs.forge().make(1.0f)); + _max_port->set_property(uris.lv2_name, bufs.forge().alloc("Maximum")); _ports->at(4) = _max_port; _audio_port = new OutputPort(bufs, this, "ar_output", 5, 1, - PortType::AUDIO, bufs.forge().make(0.0f)); - _audio_port->set_property(uris.lv2_name, bufs.forge().make("Output")); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); + _audio_port->set_property(uris.lv2_name, bufs.forge().alloc("Output")); _ports->at(5) = _audio_port; } @@ -93,22 +94,15 @@ ControllerNode::process(ProcessContext& context) { NodeImpl::pre_process(context); - uint32_t frames = 0; - uint32_t subframes = 0; - uint16_t type = 0; - uint16_t size = 0; - uint8_t* buf = NULL; - - EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0).get(); - - midi_in->rewind(); - - while (midi_in->get_event(&frames, &subframes, &type, &size, &buf)) { - // FIXME: type - if (size >= 3 && (buf[0] & 0xF0) == MIDI_CMD_CONTROL) - control(context, buf[1], buf[2], frames + context.start()); - - midi_in->increment(); + Buffer* const midi_in = _midi_in_port->buffer(0).get(); + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)midi_in->atom(); + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); + const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); + if (ev->body.type == _midi_in_port->bufs().uris().midi_MidiEvent && + ev->body.size >= 3 && (buf[0] & 0xF0) == MIDI_CMD_CONTROL) { + control(context, buf[1], buf[2], ev->time.frames + context.start()); + } } NodeImpl::post_process(context); diff --git a/src/server/internals/Controller.hpp b/src/server/internals/Controller.hpp index d664bf55..ac412c10 100644 --- a/src/server/internals/Controller.hpp +++ b/src/server/internals/Controller.hpp @@ -57,14 +57,13 @@ public: static InternalPlugin* internal_plugin(Shared::URIs& uris); private: - bool _learning; - InputPort* _midi_in_port; InputPort* _param_port; InputPort* _log_port; InputPort* _min_port; InputPort* _max_port; OutputPort* _audio_port; + bool _learning; }; } // namespace Server diff --git a/src/server/internals/Delay.cpp b/src/server/internals/Delay.cpp index 21cc23d5..dc55355e 100644 --- a/src/server/internals/Delay.cpp +++ b/src/server/internals/Delay.cpp @@ -28,7 +28,6 @@ #include "internals/Delay.hpp" #include "AudioBuffer.hpp" #include "Driver.hpp" -#include "EventBuffer.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" #include "OutputPort.hpp" @@ -75,22 +74,22 @@ DelayNode::DelayNode( _delay_samples = default_delay; _delay_port = new InputPort(bufs, this, "delay", 1, _polyphony, - PortType::CONTROL, bufs.forge().make(default_delay)); - _delay_port->set_property(uris.lv2_name, bufs.forge().make("Delay")); + PortType::CONTROL, 0, bufs.forge().make(default_delay)); + _delay_port->set_property(uris.lv2_name, bufs.forge().alloc("Delay")); _delay_port->set_property(uris.lv2_default, bufs.forge().make(default_delay)); _delay_port->set_property(uris.lv2_minimum, bufs.forge().make((float)(1.0/(double)srate))); _delay_port->set_property(uris.lv2_maximum, bufs.forge().make(MAX_DELAY_SECONDS)); _ports->at(0) = _delay_port; _in_port = new InputPort(bufs, this, "in", 0, 1, - PortType::AUDIO, bufs.forge().make(0.0f)); - _in_port->set_property(uris.lv2_name, bufs.forge().make("Input")); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); + _in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); _ports->at(1) = _in_port; _out_port = new OutputPort(bufs, this, "out", 0, 1, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _out_port->set_property(uris.lv2_name, - bufs.forge().make("Output")); + bufs.forge().alloc("Output")); _ports->at(2) = _out_port; //_buffer = bufs.get(PortType::AUDIO, bufs.audio_buffer_size(buffer_length_frames), true); diff --git a/src/server/internals/Note.cpp b/src/server/internals/Note.cpp index a44c0c36..e591bfd8 100644 --- a/src/server/internals/Note.cpp +++ b/src/server/internals/Note.cpp @@ -19,22 +19,22 @@ #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" #include "raul/Array.hpp" #include "raul/Maid.hpp" #include "raul/log.hpp" #include "raul/midi_events.h" -#include "internals/Note.hpp" #include "AudioBuffer.hpp" #include "Driver.hpp" -#include "EventBuffer.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" #include "OutputPort.hpp" #include "PatchImpl.hpp" #include "ProcessContext.hpp" -#include "util.hpp" #include "ingen_config.h" +#include "internals/Note.hpp" +#include "util.hpp" #define LOG(s) s << "[NoteNode] " @@ -65,32 +65,32 @@ NoteNode::NoteNode( _ports = new Raul::Array(5); _midi_in_port = new InputPort(bufs, this, "input", 0, 1, - PortType::EVENTS, Raul::Atom()); - _midi_in_port->set_property(uris.lv2_name, bufs.forge().make("Input")); + PortType::MESSAGE, uris.atom_Sequence, Raul::Atom()); + _midi_in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); _ports->at(0) = _midi_in_port; _freq_port = new OutputPort(bufs, this, "frequency", 1, _polyphony, - PortType::AUDIO, bufs.forge().make(440.0f)); - _freq_port->set_property(uris.lv2_name, bufs.forge().make("Frequency")); + PortType::AUDIO, 0, bufs.forge().make(440.0f)); + _freq_port->set_property(uris.lv2_name, bufs.forge().alloc("Frequency")); _ports->at(1) = _freq_port; _vel_port = new OutputPort(bufs, this, "velocity", 2, _polyphony, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _vel_port->set_property(uris.lv2_minimum, bufs.forge().make(0.0f)); _vel_port->set_property(uris.lv2_maximum, bufs.forge().make(1.0f)); - _vel_port->set_property(uris.lv2_name, bufs.forge().make("Velocity")); + _vel_port->set_property(uris.lv2_name, bufs.forge().alloc("Velocity")); _ports->at(2) = _vel_port; _gate_port = new OutputPort(bufs, this, "gate", 3, _polyphony, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _gate_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _gate_port->set_property(uris.lv2_name, bufs.forge().make("Gate")); + _gate_port->set_property(uris.lv2_name, bufs.forge().alloc("Gate")); _ports->at(3) = _gate_port; _trig_port = new OutputPort(bufs, this, "trigger", 4, _polyphony, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _trig_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _trig_port->set_property(uris.lv2_name, bufs.forge().make("Trigger")); + _trig_port->set_property(uris.lv2_name, bufs.forge().alloc("Trigger")); _ports->at(4) = _trig_port; } @@ -135,42 +135,24 @@ NoteNode::apply_poly(Raul::Maid& maid, uint32_t poly) void NoteNode::process(ProcessContext& context) { - EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0).get(); NodeImpl::pre_process(context); - - uint32_t frames = 0; - uint32_t subframes = 0; - uint16_t type = 0; - uint16_t size = 0; - uint8_t* buf = NULL; - - midi_in->rewind(); - - if (midi_in->event_count() > 0) - for (midi_in->rewind(); midi_in->get_event(&frames, &subframes, &type, &size, &buf); - midi_in->increment()) { - -#ifdef RAUL_LOG_DEBUG - LOG(debug) << "EVENT TYPE " << type << " @ " << frames << "." << subframes << ": "; - for (uint16_t i = 0; i < size; ++i) - debug << (int)((char)buf[i]) << " "; - debug << endl; -#endif - - if (frames < context.offset()) - continue; - if (frames > context.nframes()) - break; - - const FrameTime time = context.start() + (FrameTime)frames; - - if (size >= 3) { + + Buffer* const midi_in = _midi_in_port->buffer(0).get(); + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)midi_in->atom(); + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); + const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); + const FrameTime time = context.start() + (FrameTime)ev->time.frames; + + if (ev->body.type == _midi_in_port->bufs().uris().midi_MidiEvent && + ev->body.size >= 3) { switch (buf[0] & 0xF0) { case MIDI_CMD_NOTE_ON: - if (buf[2] == 0) + if (buf[2] == 0) { note_off(context, buf[1], time); - else + } else { note_on(context, buf[1], buf[2], time); + } break; case MIDI_CMD_NOTE_OFF: note_off(context, buf[1], time); @@ -182,10 +164,11 @@ NoteNode::process(ProcessContext& context) all_notes_off(context, time); break; case MIDI_CTL_SUSTAIN: - if (buf[2] > 63) + if (buf[2] > 63) { sustain_on(context, time); - else + } else { sustain_off(context, time); + } break; case MIDI_CMD_BENDER: // ? diff --git a/src/server/internals/Trigger.cpp b/src/server/internals/Trigger.cpp index 885144fe..3ccc44d7 100644 --- a/src/server/internals/Trigger.cpp +++ b/src/server/internals/Trigger.cpp @@ -19,11 +19,11 @@ #include "ingen/shared/LV2URIMap.hpp" #include "ingen/shared/URIs.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" #include "raul/log.hpp" #include "raul/midi_events.h" #include "AudioBuffer.hpp" -#include "EventBuffer.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" #include "OutputPort.hpp" @@ -58,35 +58,36 @@ TriggerNode::TriggerNode( const Ingen::Shared::URIs& uris = bufs.uris(); _ports = new Raul::Array(5); - _midi_in_port = new InputPort(bufs, this, "input", 0, 1, PortType::EVENTS, Raul::Atom()); - _midi_in_port->set_property(uris.lv2_name, bufs.forge().make("Input")); + _midi_in_port = new InputPort(bufs, this, "input", 0, 1, + PortType::MESSAGE, uris.atom_Sequence, Raul::Atom()); + _midi_in_port->set_property(uris.lv2_name, bufs.forge().alloc("Input")); _ports->at(0) = _midi_in_port; _note_port = new InputPort(bufs, this, "note", 1, 1, - PortType::CONTROL, bufs.forge().make(60.0f)); + PortType::CONTROL, 0, bufs.forge().make(60.0f)); _note_port->set_property(uris.lv2_minimum, bufs.forge().make(0.0f)); _note_port->set_property(uris.lv2_maximum, bufs.forge().make(127.0f)); _note_port->set_property(uris.lv2_integer, bufs.forge().make(true)); - _note_port->set_property(uris.lv2_name, bufs.forge().make("Note")); + _note_port->set_property(uris.lv2_name, bufs.forge().alloc("Note")); _ports->at(1) = _note_port; _gate_port = new OutputPort(bufs, this, "gate", 2, 1, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _gate_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _gate_port->set_property(uris.lv2_name, bufs.forge().make("Gate")); + _gate_port->set_property(uris.lv2_name, bufs.forge().alloc("Gate")); _ports->at(2) = _gate_port; _trig_port = new OutputPort(bufs, this, "trigger", 3, 1, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _trig_port->set_property(uris.lv2_portProperty, uris.lv2_toggled); - _trig_port->set_property(uris.lv2_name, bufs.forge().make("Trigger")); + _trig_port->set_property(uris.lv2_name, bufs.forge().alloc("Trigger")); _ports->at(3) = _trig_port; _vel_port = new OutputPort(bufs, this, "velocity", 4, 1, - PortType::AUDIO, bufs.forge().make(0.0f)); + PortType::AUDIO, 0, bufs.forge().make(0.0f)); _vel_port->set_property(uris.lv2_minimum, bufs.forge().make(0.0f)); _vel_port->set_property(uris.lv2_maximum, bufs.forge().make(1.0f)); - _vel_port->set_property(uris.lv2_name, bufs.forge().make("Velocity")); + _vel_port->set_property(uris.lv2_name, bufs.forge().alloc("Velocity")); _ports->at(4) = _vel_port; } @@ -95,40 +96,35 @@ TriggerNode::process(ProcessContext& context) { NodeImpl::pre_process(context); - uint32_t frames = 0; - uint32_t subframes = 0; - uint16_t type = 0; - uint16_t size = 0; - uint8_t* buf = NULL; - - EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0).get(); - - midi_in->rewind(); - - while (midi_in->get_event(&frames, &subframes, &type, &size, &buf)) { - const FrameTime time = context.start() + (FrameTime)frames; - - if (size >= 3) { + Buffer* const midi_in = _midi_in_port->buffer(0).get(); + LV2_Atom_Sequence* seq = (LV2_Atom_Sequence*)midi_in->atom(); + LV2_SEQUENCE_FOREACH(seq, i) { + LV2_Atom_Event* const ev = lv2_sequence_iter_get(i); + const uint8_t* buf = (const uint8_t*)LV2_ATOM_BODY(&ev->body); + if (ev->body.type == _midi_in_port->bufs().uris().midi_MidiEvent && + ev->body.size >= 3) { + const FrameTime time = context.start() + ev->time.frames; switch (buf[0] & 0xF0) { case MIDI_CMD_NOTE_ON: - if (buf[2] == 0) + if (buf[2] == 0) { note_off(context, buf[1], time); - else + } else { note_on(context, buf[1], buf[2], time); + } break; case MIDI_CMD_NOTE_OFF: note_off(context, buf[1], time); break; case MIDI_CMD_CONTROL: - if (buf[1] == MIDI_CTL_ALL_NOTES_OFF - || buf[1] == MIDI_CTL_ALL_SOUNDS_OFF) - ((AudioBuffer*)_gate_port->buffer(0).get())->set_value(0.0f, context.start(), time); + if (buf[1] == MIDI_CTL_ALL_NOTES_OFF || + buf[1] == MIDI_CTL_ALL_SOUNDS_OFF) { + ((AudioBuffer*)_gate_port->buffer(0).get())->set_value( + 0.0f, context.start(), time); + } default: break; } } - - midi_in->increment(); } NodeImpl::post_process(context); diff --git a/src/server/mix.hpp b/src/server/mix.hpp index 21040c52..54f80dfc 100644 --- a/src/server/mix.hpp +++ b/src/server/mix.hpp @@ -20,36 +20,45 @@ #include +#include "ingen/shared/URIs.hpp" #include "raul/log.hpp" #include "Buffer.hpp" #include "Context.hpp" -#include "PortType.hpp" using namespace Raul; namespace Ingen { namespace Server { +inline bool +is_audio(Shared::URIs& uris, LV2_URID type) +{ + return type == uris.atom_Float || type == uris.atom_Sound; +} + inline void -mix(Context& context, Buffer* dst, const boost::intrusive_ptr* srcs, uint32_t num_srcs) +mix(Context& context, + Shared::URIs& uris, + Buffer* dst, + const boost::intrusive_ptr* srcs, + uint32_t num_srcs) { - using Ingen::PortType; - switch (dst->type().symbol()) { - case PortType::AUDIO: - case PortType::CONTROL: - case PortType::CV: + if (num_srcs == 1) { + dst->copy(context, srcs[0].get()); + } else if (is_audio(uris, dst->type())) { // Copy the first source dst->copy(context, srcs[0].get()); // Mix in the rest for (uint32_t i = 1; i < num_srcs; ++i) { - assert(srcs[i]->type() == PortType::AUDIO || - srcs[i]->type() == PortType::CONTROL || - srcs[i]->type() == PortType::CV); + assert(is_audio(uris, srcs[i]->type())); ((AudioBuffer*)dst)->accumulate(context, (AudioBuffer*)srcs[i].get()); } - break; + } else { + std::cerr << "FIXME: event mix" << std::endl; + } +#if 0 case PortType::EVENTS: dst->clear(); for (uint32_t i = 0; i < num_srcs; ++i) { @@ -77,14 +86,7 @@ mix(Context& context, Buffer* dst, const boost::intrusive_ptr* srcs, uin } } dst->rewind(); - break; - default: - if (num_srcs == 1) - dst->copy(context, srcs[0].get()); - else - error << "Mix of unsupported buffer types" << std::endl; - return; - } +#endif } } // namespace Server diff --git a/src/server/wscript b/src/server/wscript index 33ffc58a..58a3918a 100644 --- a/src/server/wscript +++ b/src/server/wscript @@ -4,6 +4,7 @@ from waflib.extras import autowaf as autowaf def build(bld): core_source = ''' AudioBuffer.cpp + Buffer.cpp BufferFactory.cpp ClientBroadcaster.cpp ConnectionImpl.cpp @@ -12,7 +13,6 @@ def build(bld): Engine.cpp EngineStore.cpp Event.cpp - EventBuffer.cpp EventSource.cpp GraphObjectImpl.cpp InputPort.cpp @@ -24,7 +24,6 @@ def build(bld): NodeFactory.cpp NodeImpl.cpp Notification.cpp - ObjectBuffer.cpp ObjectSender.cpp OutputPort.cpp PatchImpl.cpp diff --git a/src/shared/AtomReader.cpp b/src/shared/AtomReader.cpp new file mode 100644 index 00000000..009aace6 --- /dev/null +++ b/src/shared/AtomReader.cpp @@ -0,0 +1,83 @@ +/* This file is part of Ingen. + * Copyright 2012 David Robillard + * + * Ingen is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "ingen/shared/AtomReader.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/util.h" +#include "raul/log.hpp" + +namespace Ingen { +namespace Shared { + +AtomReader::AtomReader(LV2URIMap& map, URIs& uris, Forge& forge, Interface& iface) + : _map(map) + , _uris(uris) + , _forge(forge) + , _iface(iface) +{ +} + +void +AtomReader::write(const LV2_Atom* msg) +{ + if (msg->type != _uris.atom_Blank) { + Raul::warn << "Unknown message type " << msg->type << std::endl; + return; + } + + const LV2_Atom_Object* obj = (const LV2_Atom_Object*)msg; + const LV2_Atom* subject = NULL; + + lv2_object_get(obj, (LV2_URID)_uris.patch_subject, &subject, NULL); + const char* subject_uri = subject ? (const char*)LV2_ATOM_BODY(subject) : NULL; + if (obj->body.otype == _uris.patch_Get) { + Raul::warn << "ATOM GET " << subject_uri << std::endl; + _iface.set_response_id(1); + _iface.get(subject_uri); + } else if (obj->body.otype == _uris.patch_Put) { + Raul::warn << "PUT" << std::endl; + const LV2_Atom_Object* body = NULL; + lv2_object_get(obj, (LV2_URID)_uris.patch_body, &body, 0); + if (!body) { + Raul::warn << "NO BODY" << std::endl; + return; + } + + Ingen::Resource::Properties props; + LV2_OBJECT_FOREACH(body, i) { + LV2_Atom_Property_Body* p = lv2_object_iter_get(i); + props.insert(std::make_pair(_map.unmap_uri(p->key), + _forge.alloc(p->value.size, + p->value.type, + LV2_ATOM_BODY(&p->value)))); + } + + if (subject_uri) { + _iface.put(subject_uri, props); + } else { + Raul::warn << "Put message has no subject, ignored" << std::endl; + } + + } else { + Raul::warn << "HANDLE MESSAGE TYPE " << obj->body.otype << std::endl; + } +} + +} // namespace Shared +} // namespace Ingen diff --git a/src/shared/AtomWriter.cpp b/src/shared/AtomWriter.cpp index c86ac96f..81a9d9ba 100644 --- a/src/shared/AtomWriter.cpp +++ b/src/shared/AtomWriter.cpp @@ -88,7 +88,21 @@ AtomWriter::put(const Raul::URI& uri, { LV2_Atom_Forge_Frame msg; lv2_atom_forge_blank(&_forge, &msg, next_id(), _uris.patch_Put); - // ... + lv2_atom_forge_property_head(&_forge, _uris.patch_subject, 0); + lv2_atom_forge_uri(&_forge, uri.c_str(), uri.length()); + lv2_atom_forge_property_head(&_forge, _uris.patch_body, 0); + + LV2_Atom_Forge_Frame body; + lv2_atom_forge_blank(&_forge, &body, 0, 0); + + for (Resource::Properties::const_iterator i = properties.begin(); + i != properties.end(); ++i) { + lv2_atom_forge_property_head(&_forge, _map.map_uri(i->first.c_str()), 0); + lv2_atom_forge_atom(&_forge, i->second.size(), i->second.type()); + lv2_atom_forge_write(&_forge, i->second.get_body(), i->second.size()); + } + + lv2_atom_forge_pop(&_forge, &body); lv2_atom_forge_pop(&_forge, &msg); finish_msg(); } @@ -173,7 +187,7 @@ AtomWriter::response(int32_t id, Status status) LV2_Atom_Forge_Frame msg; lv2_atom_forge_blank(&_forge, &msg, next_id(), _uris.patch_Response); lv2_atom_forge_property_head(&_forge, _uris.patch_request, 0); - lv2_atom_forge_int32(&_forge, id); + lv2_atom_forge_int(&_forge, id); lv2_atom_forge_pop(&_forge, &msg); finish_msg(); } diff --git a/src/shared/Builder.cpp b/src/shared/Builder.cpp index 3b49bd41..8c51d50e 100644 --- a/src/shared/Builder.cpp +++ b/src/shared/Builder.cpp @@ -48,7 +48,8 @@ Builder::build(SharedPtr object) if (patch) { if (!object->path().is_root()) { Resource::Properties props; - props.insert(make_pair(uris.rdf_type, uris.ingen_Patch)); + props.insert(make_pair(uris.rdf_type, + _uris->forge.alloc_uri(uris.ingen_Patch.str()))); props.insert(make_pair(uris.ingen_polyphony, _uris->forge.make(int32_t(patch->internal_poly())))); _interface.put(object->path(), props); @@ -66,7 +67,8 @@ Builder::build(SharedPtr object) if (node) { Resource::Properties props; props.insert(make_pair(uris.rdf_type, uris.ingen_Node)); - props.insert(make_pair(uris.rdf_instanceOf, node->plugin()->uri())); + props.insert(make_pair(uris.rdf_instanceOf, + _uris->forge.alloc_uri(node->plugin()->uri().str()))); _interface.put(node->path(), props); build_object(object); return; diff --git a/src/shared/Configuration.cpp b/src/shared/Configuration.cpp index 300c7f1d..df539115 100644 --- a/src/shared/Configuration.cpp +++ b/src/shared/Configuration.cpp @@ -22,8 +22,8 @@ using namespace Raul; namespace Ingen { namespace Shared { -Configuration::Configuration(Raul::Forge* forge) - : Raul::Configuration(forge, +Configuration::Configuration() + : Raul::Configuration( "A realtime modular audio processor.", "Ingen is a flexible modular system that be used in various ways.\n" "The engine can run as a stand-alone server controlled via a network protocol\n" @@ -37,21 +37,21 @@ Configuration::Configuration(Raul::Forge* forge) " ingen -eg patch.ttl # Run an engine and a GUI and load a patch file\n" " ingen -eg patch.ingen # Run an engine and a GUI and load a patch bundle") { - add("client-port", 'C', "Client OSC port", Atom::INT, forge->make()); - add("connect", 'c', "Connect to engine URI", Atom::STRING, forge->make("osc.udp://localhost:16180")); - add("engine", 'e', "Run (JACK) engine", Atom::BOOL, forge->make(false)); - add("engine-port", 'E', "Engine listen port", Atom::INT, forge->make(16180)); - add("gui", 'g', "Launch the GTK graphical interface", Atom::BOOL, forge->make(false)); - add("help", 'h', "Print this help message", Atom::BOOL, forge->make(false)); - add("jack-client", 'n', "JACK client name", Atom::STRING, forge->make("ingen")); - add("jack-server", 's', "JACK server name", Atom::STRING, forge->make("")); - add("uuid", 'u', "JACK session UUID", Atom::STRING, forge->make("")); - add("load", 'l', "Load patch", Atom::STRING, forge->make()); - add("packet-size", 'k', "Maximum UDP packet size", Atom::INT, forge->make(4096)); - add("parallelism", 'p', "Number of concurrent process threads", Atom::INT, forge->make(1)); - add("path", 'L', "Target path for loaded patch", Atom::STRING, forge->make()); - add("queue-size", 'q', "Event queue size", Atom::INT, forge->make(4096)); - add("run", 'r', "Run script", Atom::STRING, forge->make()); + add("client-port", 'C', "Client OSC port", INT, Value()); + add("connect", 'c', "Connect to engine URI", STRING, Value("osc.udp://localhost:16180")); + add("engine", 'e', "Run (JACK) engine", BOOL, Value(false)); + add("engine-port", 'E', "Engine listen port", INT, Value(16180)); + add("gui", 'g', "Launch the GTK graphical interface", BOOL, Value(false)); + add("help", 'h', "Print this help message", BOOL, Value(false)); + add("jack-client", 'n', "JACK client name", STRING, Value("ingen")); + add("jack-server", 's', "JACK server name", STRING, Value("")); + add("uuid", 'u', "JACK session UUID", STRING, Value()); + add("load", 'l', "Load patch", STRING, Value()); + add("packet-size", 'k', "Maximum UDP packet size", INT, Value(4096)); + add("parallelism", 'p', "Number of concurrent process threads", INT, Value(1)); + add("path", 'L', "Target path for loaded patch", STRING, Value()); + add("queue-size", 'q', "Event queue size", INT, Value(4096)); + add("run", 'r', "Run script", STRING, Value()); } } // namespace Shared diff --git a/src/shared/Forge.cpp b/src/shared/Forge.cpp new file mode 100644 index 00000000..bf7eb3e8 --- /dev/null +++ b/src/shared/Forge.cpp @@ -0,0 +1,53 @@ +/* This file is part of Ingen. + * Copyright 2008-2011 David Robillard + * + * Ingen is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "ingen/shared/Forge.hpp" +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" + +namespace Ingen { + +Forge::Forge(Shared::LV2URIMap& map) +{ + Int = map.map_uri(LV2_ATOM__Int); + Float = map.map_uri(LV2_ATOM__Float); + Bool = map.map_uri(LV2_ATOM__Bool); + URI = map.map_uri(LV2_ATOM__URI); + String = map.map_uri(LV2_ATOM__String); + Dict = map.map_uri(LV2_ATOM__Object); +} + +std::string +Forge::str(const Raul::Atom& atom) +{ + std::ostringstream ss; + if (atom.type() == Int) { + ss << atom.get_int32(); + } else if (atom.type() == Float) { + ss << atom.get_float(); + } else if (atom.type() == Bool) { + ss << (atom.get_bool() ? "true" : "false"); + } else if (atom.type() == URI) { + ss << "<" << atom.get_uri() << ">"; + } else if (atom.type() == String) { + ss << "\"" << atom.get_string() << "\""; + } + return ss.str(); +} + +} // namespace Ingen diff --git a/src/shared/LV2Atom.cpp b/src/shared/LV2Atom.cpp deleted file mode 100644 index ccd5f352..00000000 --- a/src/shared/LV2Atom.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* This file is part of Ingen. - * Copyright 2009-2011 David Robillard - * - * Ingen is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) 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 General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "ingen/shared/LV2Atom.hpp" -#include "ingen/shared/LV2Features.hpp" -#include "ingen/shared/LV2URIMap.hpp" -#include "ingen/shared/URIs.hpp" -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "lv2/lv2plug.in/ns/ext/uri-map/uri-map.h" -#include "raul/Atom.hpp" -#include "raul/log.hpp" - -using namespace std; -using namespace Raul; - -namespace Ingen { -namespace Shared { -namespace LV2Atom { - -bool -to_atom(Raul::Forge* forge, - const Shared::URIs& uris, - const LV2_Atom* object, - Raul::Atom& atom) -{ - if (object->type == uris.atom_String.id) { - atom = forge->make((char*)(object + 1)); - return true; - } else if (object->type == uris.atom_Bool.id) { - atom = forge->make((bool)(int32_t*)(object + 1)); - return true; - } else if (object->type == uris.atom_Int.id) { - atom = forge->make((int32_t*)(object + 1)); - return true; - } else if (object->type == uris.atom_Float.id) { - atom = forge->make((float*)(object + 1)); - return true; - } - return false; -} - -/** Convert an atom to an LV2 object, if possible. - * object->size should be the capacity of the object (not including header) - */ -bool -from_atom(const Shared::URIs& uris, const Raul::Atom& atom, LV2_Atom* object) -{ - char* str; - switch (atom.type()) { - case Raul::Atom::FLOAT: - object->type = uris.atom_Float.id; - object->size = sizeof(float); - *(float*)(object + 1) = atom.get_float(); - break; - case Raul::Atom::INT: - object->type = uris.atom_Int.id; - object->size = sizeof(int32_t); - *(int32_t*)(object + 1) = atom.get_int32(); - break; - case Raul::Atom::STRING: - object->type = uris.atom_String.id; - object->size = std::min((uint16_t)object->size, (uint16_t)(strlen(atom.get_string()) + 1)); - str = ((char*)(object + 1)); - str[object->size - 1] = '\0'; - strncpy(str, atom.get_string(), object->size); - break; - case Raul::Atom::BLOB: - error << "TODO: Blob support" << endl; - /*object->type = uris.atom_String; - *(uint16_t*)(object + 1) = uris.uri_to_id(NULL, atom.get_blob_type()); - memcpy(((char*)(object + 1) + sizeof(uint32_t)), atom.get_blob(), - std::min(atom.data_size(), (size_t)object->size));*/ - default: - error << "Unsupported value type for toggle control" << endl; - return false; - } - return true; -} - -} // namespace LV2Atom -} // namespace Shared -} // namespace Ingen diff --git a/src/shared/LV2URIMap.cpp b/src/shared/LV2URIMap.cpp index 14b6ca0a..8a414c9f 100644 --- a/src/shared/LV2URIMap.cpp +++ b/src/shared/LV2URIMap.cpp @@ -26,7 +26,6 @@ #include "ingen/shared/LV2URIMap.hpp" #include "lv2/lv2plug.in/ns/ext/atom/atom.h" -#include "lv2/lv2plug.in/ns/ext/event/event.h" #include "raul/log.hpp" using namespace std; @@ -36,19 +35,11 @@ namespace Ingen { namespace Shared { LV2URIMap::LV2URIMap(LV2_URID_Map* map, LV2_URID_Unmap* unmap) - : _uri_map_feature(new URIMapFeature(this)) - , _urid_map_feature(new URIDMapFeature(this, map)) + : _urid_map_feature(new URIDMapFeature(this, map)) , _urid_unmap_feature(new URIDUnmapFeature(this, unmap)) { } -LV2URIMap::URIMapFeature::URIMapFeature(LV2URIMap* map) - : Feature(LV2_URI_MAP_URI, &uri_map) -{ - uri_map.uri_to_id = &LV2URIMap::uri_map_uri_to_id; - uri_map.callback_data = map; -} - LV2URIMap::URIDMapFeature::URIDMapFeature(LV2URIMap* map, LV2_URID_Map* impl) : Feature(LV2_URID__map, &urid_map) @@ -100,83 +91,6 @@ LV2URIMap::URIDUnmapFeature::unmap(LV2_URID urid) return urid_unmap.unmap(urid_unmap.handle, urid); } -uint32_t -LV2URIMap::uri_to_id(const char* map, - const char* uri) -{ - const uint32_t id = map_uri(uri); - if (map && !strcmp(map, LV2_EVENT_URI)) { - GlobalToEvent::iterator i = _global_to_event.find(id); - if (i != _global_to_event.end()) { - return i->second; - } else { - if (_global_to_event.size() + 1 > UINT16_MAX) { - error << "Event URI " << uri << " ID out of range." << endl; - return 0; - } - const uint16_t ev_id = _global_to_event.size() + 1; - assert(_event_to_global.find(ev_id) == _event_to_global.end()); - _global_to_event.insert(make_pair(id, ev_id)); - _event_to_global.insert(make_pair(ev_id, id)); - return ev_id; - } - } else { - return id; - } -} - -const char* -LV2URIMap::id_to_uri(const char* map, - const uint32_t id) -{ - if (map && !strcmp(map, LV2_EVENT_URI)) { - EventToGlobal::iterator i = _event_to_global.find(id); - if (i == _event_to_global.end()) { - error << "Failed to unmap event URI " << id << endl; - return NULL; - } - return unmap_uri(i->second); - } else { - return unmap_uri(id); - } -} - -std::pair -LV2URIMap::event_to_global(uint16_t event_id) const -{ - EventToGlobal::const_iterator i = _event_to_global.find(event_id); - if (i == _event_to_global.end()) { - return std::make_pair(false, uint32_t(0)); - } - return std::make_pair(true, i->second); -} - -std::pair -LV2URIMap::global_to_event(uint32_t global_id) const -{ - GlobalToEvent::const_iterator i = _global_to_event.find(global_id); - if (i == _global_to_event.end()) { - return std::make_pair(false, uint16_t(0)); - } - return std::make_pair(true, i->second); -} - -uint32_t -LV2URIMap::uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data, - const char* map, - const char* uri) -{ - LV2URIMap* me = (LV2URIMap*)callback_data; - return me->uri_to_id(map, uri); -} - -LV2_URID -LV2URIMap::urid_map(LV2_URID_Map_Handle handle, const char* uri) -{ - LV2URIMap* me = (LV2URIMap*)handle; - return me->uri_to_id(NULL, uri); -} - uint32_t LV2URIMap::map_uri(const char* uri) { diff --git a/src/shared/ResourceImpl.cpp b/src/shared/ResourceImpl.cpp index de3eae17..6858fab9 100644 --- a/src/shared/ResourceImpl.cpp +++ b/src/shared/ResourceImpl.cpp @@ -121,8 +121,8 @@ ResourceImpl::type(const URIs& uris, patch = node = port = is_output = false; for (iterator i = types_range.first; i != types_range.second; ++i) { const Atom& atom = i->second; - if (atom.type() != Atom::URI) { - warn << "[ResourceImpl] Non-URI type " << atom << endl; + if (atom.type() != uris.forge.URI) { + warn << "[ResourceImpl] Non-URI type " << uris.forge.str(atom) << endl; continue; } @@ -195,17 +195,6 @@ ResourceImpl::remove_properties(const Properties& p) } } -void -ResourceImpl::dump(std::ostream& os) const -{ - typedef Resource::Properties::const_iterator iterator; - os << _uri << " [" << endl; - for (iterator i = _properties.begin(); i != _properties.end(); ++i) { - os << "\t" << i->first << " " << i->second << " ;" << endl; - } - os << "]" << endl; -} - Resource::Properties ResourceImpl::properties(Resource::Graph ctx) const { diff --git a/src/shared/URIs.cpp b/src/shared/URIs.cpp index 73718fab..07cd8ab1 100644 --- a/src/shared/URIs.cpp +++ b/src/shared/URIs.cpp @@ -37,9 +37,10 @@ using namespace Raul; namespace Ingen { namespace Shared { -URIs::Quark::Quark(LV2URIMap* map, const char* c_str) +URIs::Quark::Quark(Ingen::Forge& forge, LV2URIMap* map, const char* c_str) : Raul::URI(c_str) , id(map->map_uri(c_str)) + , atom(forge.alloc_uri(c_str)) { } @@ -48,79 +49,82 @@ URIs::Quark::Quark(LV2URIMap* map, const char* c_str) #define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" #define NS_RDFS "http://www.w3.org/2000/01/rdf-schema#" -URIs::URIs(Raul::Forge& f, LV2URIMap* map) +URIs::URIs(Ingen::Forge& f, LV2URIMap* map) : forge(f) - , atom_Bool (map, LV2_ATOM__Bool) - , atom_Float (map, LV2_ATOM__Float) - , atom_Int (map, LV2_ATOM__Int) - , atom_MessagePort (map, LV2_ATOM__MessagePort) - , atom_String (map, LV2_ATOM__String) - , atom_ValuePort (map, LV2_ATOM__ValuePort) - , atom_Vector (map, LV2_ATOM__Vector) - , atom_eventTransfer (map, LV2_ATOM__eventTransfer) - , atom_supports (map, LV2_ATOM__supports) - , ctx_audioContext (map, NS_CTX "audioContext") - , ctx_context (map, NS_CTX "context") - , ctx_messageContext (map, NS_CTX "messageContext") - , cv_CVPort (map, "http://lv2plug.in/ns/ext/cv-port#CVPort") - , doap_name (map, "http://usefulinc.com/ns/doap#name") - , ev_EventPort (map, "http://lv2plug.in/ns/ext/event#EventPort") - , ingen_Connection (map, NS_INGEN "Connection") - , ingen_Internal (map, NS_INGEN "Internal") - , ingen_Node (map, NS_INGEN "Node") - , ingen_Patch (map, NS_INGEN "Patch") - , ingen_Port (map, NS_INGEN "Port") - , ingen_activity (map, NS_INGEN "activity") - , ingen_broadcast (map, NS_INGEN "broadcast") - , ingen_canvasX (map, NS_INGEN "canvasX") - , ingen_canvasY (map, NS_INGEN "canvasY") - , ingen_controlBinding (map, NS_INGEN "controlBinding") - , ingen_destination (map, NS_INGEN "destination") - , ingen_document (map, NS_INGEN "document") - , ingen_enabled (map, NS_INGEN "enabled") - , ingen_engine (map, NS_INGEN "engine") - , ingen_nil (map, NS_INGEN "nil") - , ingen_node (map, NS_INGEN "node") - , ingen_polyphonic (map, NS_INGEN "polyphonic") - , ingen_polyphony (map, NS_INGEN "polyphony") - , ingen_sampleRate (map, NS_INGEN "sampleRate") - , ingen_selected (map, NS_INGEN "selected") - , ingen_source (map, NS_INGEN "source") - , ingen_value (map, NS_INGEN "value") - , lv2_AudioPort (map, LV2_CORE__AudioPort) - , lv2_ControlPort (map, LV2_CORE__ControlPort) - , lv2_InputPort (map, LV2_CORE__InputPort) - , lv2_OutputPort (map, LV2_CORE__OutputPort) - , lv2_Plugin (map, LV2_CORE__Plugin) - , lv2_connectionOptional(map, LV2_CORE__connectionOptional) - , lv2_default (map, LV2_CORE__default) - , lv2_index (map, LV2_CORE__index) - , lv2_integer (map, LV2_CORE__integer) - , lv2_maximum (map, LV2_CORE__maximum) - , lv2_minimum (map, LV2_CORE__minimum) - , lv2_name (map, LV2_CORE__name) - , lv2_portProperty (map, LV2_CORE__portProperty) - , lv2_sampleRate (map, LV2_CORE__sampleRate) - , lv2_symbol (map, LV2_CORE__symbol) - , lv2_toggled (map, LV2_CORE__toggled) - , midi_Bender (map, LV2_MIDI__Bender) - , midi_ChannelPressure (map, LV2_MIDI__ChannelPressure) - , midi_Controller (map, LV2_MIDI__Controller) - , midi_MidiEvent (map, LV2_MIDI__MidiEvent) - , midi_NoteOn (map, LV2_MIDI__NoteOn) - , midi_controllerNumber (map, LV2_MIDI__controllerNumber) - , midi_noteNumber (map, LV2_MIDI__noteNumber) - , patch_Get (map, LV2_PATCH__Get) - , patch_Put (map, LV2_PATCH__Put) - , patch_Response (map, LV2_PATCH__Response) - , patch_body (map, LV2_PATCH__body) - , patch_request (map, LV2_PATCH__request) - , patch_subject (map, LV2_PATCH__subject) - , rdf_instanceOf (map, NS_RDF "instanceOf") - , rdf_type (map, NS_RDF "type") - , rdfs_seeAlso (map, NS_RDFS "seeAlso") - , ui_Events (map, "http://lv2plug.in/ns/extensions/ui#Events") - , wildcard (map, NS_INGEN "wildcard") + , atom_Blank (forge, map, LV2_ATOM__Blank) + , atom_Bool (forge, map, LV2_ATOM__Bool) + , atom_Float (forge, map, LV2_ATOM__Float) + , atom_Int (forge, map, LV2_ATOM__Int) + , atom_MessagePort (forge, map, LV2_ATOM__MessagePort) + , atom_Sequence (forge, map, LV2_ATOM__Sequence) + , atom_Sound (forge, map, LV2_ATOM__Sound) + , atom_String (forge, map, LV2_ATOM__String) + , atom_ValuePort (forge, map, LV2_ATOM__ValuePort) + , atom_Vector (forge, map, LV2_ATOM__Vector) + , atom_bufferType (forge, map, LV2_ATOM__bufferType) + , atom_eventTransfer (forge, map, LV2_ATOM__eventTransfer) + , atom_supports (forge, map, LV2_ATOM__supports) + , ctx_audioContext (forge, map, NS_CTX "audioContext") + , ctx_context (forge, map, NS_CTX "context") + , ctx_messageContext (forge, map, NS_CTX "messageContext") + , cv_CVPort (forge, map, "http://lv2plug.in/ns/ext/cv-port#CVPort") + , doap_name (forge, map, "http://usefulinc.com/ns/doap#name") + , ingen_Connection (forge, map, NS_INGEN "Connection") + , ingen_Internal (forge, map, NS_INGEN "Internal") + , ingen_Node (forge, map, NS_INGEN "Node") + , ingen_Patch (forge, map, NS_INGEN "Patch") + , ingen_Port (forge, map, NS_INGEN "Port") + , ingen_activity (forge, map, NS_INGEN "activity") + , ingen_broadcast (forge, map, NS_INGEN "broadcast") + , ingen_canvasX (forge, map, NS_INGEN "canvasX") + , ingen_canvasY (forge, map, NS_INGEN "canvasY") + , ingen_controlBinding (forge, map, NS_INGEN "controlBinding") + , ingen_destination (forge, map, NS_INGEN "destination") + , ingen_document (forge, map, NS_INGEN "document") + , ingen_enabled (forge, map, NS_INGEN "enabled") + , ingen_engine (forge, map, NS_INGEN "engine") + , ingen_nil (forge, map, NS_INGEN "nil") + , ingen_node (forge, map, NS_INGEN "node") + , ingen_polyphonic (forge, map, NS_INGEN "polyphonic") + , ingen_polyphony (forge, map, NS_INGEN "polyphony") + , ingen_sampleRate (forge, map, NS_INGEN "sampleRate") + , ingen_selected (forge, map, NS_INGEN "selected") + , ingen_source (forge, map, NS_INGEN "source") + , ingen_value (forge, map, NS_INGEN "value") + , lv2_AudioPort (forge, map, LV2_CORE__AudioPort) + , lv2_ControlPort (forge, map, LV2_CORE__ControlPort) + , lv2_InputPort (forge, map, LV2_CORE__InputPort) + , lv2_OutputPort (forge, map, LV2_CORE__OutputPort) + , lv2_Plugin (forge, map, LV2_CORE__Plugin) + , lv2_connectionOptional(forge, map, LV2_CORE__connectionOptional) + , lv2_default (forge, map, LV2_CORE__default) + , lv2_index (forge, map, LV2_CORE__index) + , lv2_integer (forge, map, LV2_CORE__integer) + , lv2_maximum (forge, map, LV2_CORE__maximum) + , lv2_minimum (forge, map, LV2_CORE__minimum) + , lv2_name (forge, map, LV2_CORE__name) + , lv2_portProperty (forge, map, LV2_CORE__portProperty) + , lv2_sampleRate (forge, map, LV2_CORE__sampleRate) + , lv2_symbol (forge, map, LV2_CORE__symbol) + , lv2_toggled (forge, map, LV2_CORE__toggled) + , midi_Bender (forge, map, LV2_MIDI__Bender) + , midi_ChannelPressure (forge, map, LV2_MIDI__ChannelPressure) + , midi_Controller (forge, map, LV2_MIDI__Controller) + , midi_MidiEvent (forge, map, LV2_MIDI__MidiEvent) + , midi_NoteOn (forge, map, LV2_MIDI__NoteOn) + , midi_controllerNumber (forge, map, LV2_MIDI__controllerNumber) + , midi_noteNumber (forge, map, LV2_MIDI__noteNumber) + , patch_Get (forge, map, LV2_PATCH__Get) + , patch_Put (forge, map, LV2_PATCH__Put) + , patch_Response (forge, map, LV2_PATCH__Response) + , patch_body (forge, map, LV2_PATCH__body) + , patch_request (forge, map, LV2_PATCH__request) + , patch_subject (forge, map, LV2_PATCH__subject) + , rdf_instanceOf (forge, map, NS_RDF "instanceOf") + , rdf_type (forge, map, NS_RDF "type") + , rdfs_seeAlso (forge, map, NS_RDFS "seeAlso") + , ui_Events (forge, map, "http://lv2plug.in/ns/extensions/ui#Events") + , wildcard (forge, map, NS_INGEN "wildcard") { } diff --git a/src/shared/World.cpp b/src/shared/World.cpp index e3551302..963d53f3 100644 --- a/src/shared/World.cpp +++ b/src/shared/World.cpp @@ -109,14 +109,13 @@ public: , argv(a_argv) , conf(conf) , lv2_features(NULL) - , forge(new Raul::Forge()) , rdf_world(new Sord::World()) , lv2_uri_map(new Ingen::Shared::LV2URIMap(map, unmap)) + , forge(new Ingen::Forge(*lv2_uri_map)) , uris(new Shared::URIs(*forge, lv2_uri_map.get())) , lilv_world(lilv_world_new()) { lv2_features = new Ingen::Shared::LV2Features(); - lv2_features->add_feature(lv2_uri_map->uri_map_feature()); lv2_features->add_feature(lv2_uri_map->urid_map_feature()); lv2_features->add_feature(lv2_uri_map->urid_unmap_feature()); lilv_world_load_all(lilv_world); @@ -173,9 +172,9 @@ public: char**& argv; Raul::Configuration* conf; LV2Features* lv2_features; - Raul::Forge* forge; Sord::World* rdf_world; SharedPtr lv2_uri_map; + Ingen::Forge* forge; SharedPtr uris; SharedPtr engine; SharedPtr local_engine; @@ -216,7 +215,7 @@ SharedPtr World::serialiser() { return _impl->seria SharedPtr World::parser() { return _impl->parser; } SharedPtr World::store() { return _impl->store; } Raul::Configuration* World::conf() { return _impl->conf; } -Raul::Forge& World::forge() { return *_impl->forge; } +Ingen::Forge& World::forge() { return *_impl->forge; } LV2Features* World::lv2_features() { return _impl->lv2_features; } LilvWorld* World::lilv_world() { return _impl->lilv_world; } diff --git a/src/shared/wscript b/src/shared/wscript index 11b61f17..70806a59 100644 --- a/src/shared/wscript +++ b/src/shared/wscript @@ -13,11 +13,12 @@ def build(bld): autowaf.use_lib(bld, obj, 'GLIBMM LV2CORE LILV RAUL SORD LV2_MIDI') obj.source = ''' + AtomReader.cpp AtomWriter.cpp Builder.cpp ClashAvoider.cpp Configuration.cpp - LV2Atom.cpp + Forge.cpp LV2Features.cpp LV2URIMap.cpp Module.cpp diff --git a/wscript b/wscript index 5030e0b7..9be586b8 100644 --- a/wscript +++ b/wscript @@ -98,12 +98,8 @@ def configure(conf): uselib_store='LV2_STATE') autowaf.check_pkg(conf, 'lv2-lv2plug.in-ns-ext-contexts', uselib_store='LV2_CONTEXTS') - autowaf.check_pkg(conf, 'lv2-lv2plug.in-ns-ext-event', - uselib_store='LV2_EVENT') autowaf.check_pkg(conf, 'lv2-lv2plug.in-ns-ext-resize-port', uselib_store='LV2_RESIZE') - autowaf.check_pkg(conf, 'lv2-lv2plug.in-ns-ext-uri-map', - uselib_store='LV2_URI_MAP') autowaf.define(conf, 'INGEN_VERSION', INGEN_VERSION) -- cgit v1.2.1