summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-03-19 20:16:46 +0000
committerDavid Robillard <d@drobilla.net>2012-03-19 20:16:46 +0000
commit254b434f0a79fea54bd963e8ff2e845a5b0cd3a6 (patch)
treeddf849fc5b64d1096846c28c1f1a742f54c3adff /src
parentbc3afd8380d59c750c8f8e9bf1ed1b8d4a6826e9 (diff)
downloadingen-254b434f0a79fea54bd963e8ff2e845a5b0cd3a6.tar.gz
ingen-254b434f0a79fea54bd963e8ff2e845a5b0cd3a6.tar.bz2
ingen-254b434f0a79fea54bd963e8ff2e845a5b0cd3a6.zip
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
Diffstat (limited to 'src')
-rwxr-xr-xsrc/bindings/test_ingen.py2
-rw-r--r--src/client/ClientStore.cpp15
-rw-r--r--src/client/NodeModel.cpp4
-rw-r--r--src/client/ObjectModel.cpp2
-rw-r--r--src/client/PluginModel.cpp9
-rw-r--r--src/client/PluginUI.cpp40
-rw-r--r--src/client/PortModel.cpp8
-rw-r--r--src/gui/App.cpp4
-rw-r--r--src/gui/App.hpp5
-rw-r--r--src/gui/Configuration.cpp2
-rw-r--r--src/gui/Controls.cpp23
-rw-r--r--src/gui/LoadPluginWindow.cpp8
-rw-r--r--src/gui/NodeModule.cpp31
-rw-r--r--src/gui/ObjectMenu.cpp2
-rw-r--r--src/gui/PatchBox.cpp10
-rw-r--r--src/gui/PatchCanvas.cpp43
-rw-r--r--src/gui/PatchPortModule.cpp12
-rw-r--r--src/gui/PatchTreeWindow.cpp2
-rw-r--r--src/gui/PatchView.cpp11
-rw-r--r--src/gui/PatchWindow.cpp1
-rw-r--r--src/gui/Port.cpp8
-rw-r--r--src/gui/PortMenu.cpp2
-rw-r--r--src/gui/PortPropertiesWindow.cpp2
-rw-r--r--src/gui/PropertiesWindow.cpp72
-rw-r--r--src/gui/PropertiesWindow.hpp6
-rw-r--r--src/gui/RenameWindow.cpp2
-rw-r--r--src/gui/WindowFactory.cpp8
-rw-r--r--src/gui/ingen_gui_lv2.cpp18
-rw-r--r--src/ingen/main.cpp9
-rw-r--r--src/serialisation/Parser.cpp87
-rw-r--r--src/serialisation/Serialiser.cpp92
-rw-r--r--src/serialisation/sratom/sratom.c731
-rw-r--r--src/serialisation/sratom/sratom.h176
-rw-r--r--src/serialisation/wscript9
-rw-r--r--src/server/AudioBuffer.cpp37
-rw-r--r--src/server/AudioBuffer.hpp15
-rw-r--r--src/server/Buffer.cpp164
-rw-r--r--src/server/Buffer.hpp46
-rw-r--r--src/server/BufferFactory.cpp77
-rw-r--r--src/server/BufferFactory.hpp35
-rw-r--r--src/server/ConnectionImpl.cpp56
-rw-r--r--src/server/ControlBindings.cpp110
-rw-r--r--src/server/ControlBindings.hpp9
-rw-r--r--src/server/DuplexPort.cpp9
-rw-r--r--src/server/DuplexPort.hpp1
-rw-r--r--src/server/Engine.cpp17
-rw-r--r--src/server/EventBuffer.cpp217
-rw-r--r--src/server/EventBuffer.hpp86
-rw-r--r--src/server/InputPort.cpp10
-rw-r--r--src/server/InputPort.hpp1
-rw-r--r--src/server/JackDriver.cpp64
-rw-r--r--src/server/LV2Info.cpp2
-rw-r--r--src/server/LV2Info.hpp1
-rw-r--r--src/server/LV2Node.cpp64
-rw-r--r--src/server/NodeImpl.cpp4
-rw-r--r--src/server/NodeImpl.hpp4
-rw-r--r--src/server/Notification.cpp2
-rw-r--r--src/server/ObjectBuffer.cpp151
-rw-r--r--src/server/ObjectBuffer.hpp56
-rw-r--r--src/server/OutputPort.cpp3
-rw-r--r--src/server/OutputPort.hpp1
-rw-r--r--src/server/PatchImpl.cpp9
-rw-r--r--src/server/PatchImpl.hpp7
-rw-r--r--src/server/PortImpl.cpp74
-rw-r--r--src/server/PortImpl.hpp5
-rw-r--r--src/server/PortType.hpp9
-rw-r--r--src/server/ServerInterfaceImpl.cpp2
-rw-r--r--src/server/ServerInterfaceImpl.hpp2
-rw-r--r--src/server/events/CreateNode.cpp2
-rw-r--r--src/server/events/CreatePort.cpp40
-rw-r--r--src/server/events/CreatePort.hpp9
-rw-r--r--src/server/events/SetMetadata.cpp14
-rw-r--r--src/server/events/SetPortValue.cpp45
-rw-r--r--src/server/ingen_jack.cpp7
-rw-r--r--src/server/ingen_lv2.cpp129
-rw-r--r--src/server/internals/Controller.cpp52
-rw-r--r--src/server/internals/Controller.hpp3
-rw-r--r--src/server/internals/Delay.cpp13
-rw-r--r--src/server/internals/Note.cpp75
-rw-r--r--src/server/internals/Trigger.cpp60
-rw-r--r--src/server/mix.hpp40
-rw-r--r--src/server/wscript3
-rw-r--r--src/shared/AtomReader.cpp83
-rw-r--r--src/shared/AtomWriter.cpp18
-rw-r--r--src/shared/Builder.cpp6
-rw-r--r--src/shared/Configuration.cpp34
-rw-r--r--src/shared/Forge.cpp53
-rw-r--r--src/shared/LV2Atom.cpp96
-rw-r--r--src/shared/LV2URIMap.cpp88
-rw-r--r--src/shared/ResourceImpl.cpp15
-rw-r--r--src/shared/URIs.cpp150
-rw-r--r--src/shared/World.cpp7
-rw-r--r--src/shared/wscript3
93 files changed, 2192 insertions, 1659 deletions
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<PluginModel> 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<PluginModel>(
@@ -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<PortModel> 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<Resource> 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<const PortModel> 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<const PortModel> 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<bool, uint16_t> 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 <gtkmm.h>
-#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<Gdk::Pixbuf> icon_from_path(const std::string& path, int size);
- Raul::Forge& forge() const { return _world->forge(); }
+ Ingen::Forge& forge() const { return _world->forge(); }
SharedPtr<Ingen::Interface> engine() const { return _world->engine(); }
SharedPtr<Client::SigClientInterface> client() const { return _client; }
SharedPtr<Client::ClientStore> 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<const PortModel> 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 <glib/gstdio.h>
#include <glibmm/fileutils.h>
-#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<PatchModel*>(_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 <cassert>
#include <map>
#include <string>
+
#include <boost/format.hpp>
-#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<PluginModel> 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<const NodeModel> parent(PtrCast<const NodeModel>(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<const PortModel> 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<Gtk::Builder>& 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<Raul::Atom::Type>(i);
- ostringstream ss;
- ss << static_cast<Raul::Atom::Type>(i);
- row[_type_cols.choice] = ss.str();
- }
-
_cancel_button->signal_clicked().connect(
sigc::mem_fun(this, &PropertiesWindow::cancel_clicked));
@@ -63,6 +55,33 @@ PropertiesWindow::PropertiesWindow(BaseObjectType* cobject,
}
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()
{
_table->children().clear();
@@ -137,7 +156,8 @@ PropertiesWindow::set_object(SharedPtr<const ObjectModel> 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<Gtk::SpinButton*>(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<Gtk::SpinButton*>(record.value_widget->get_child());
if (!widget) goto bad_type;
record.value = _app->forge().make(static_cast<float>(widget->get_value()));
- } else if (type == Atom::BOOL) {
+ } else if (type == forge.Bool) {
Gtk::CheckButton* widget = dynamic_cast<Gtk::CheckButton*>(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<Gtk::Entry*>(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<Gtk::Entry*>(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<Raul::Atom::Type> type;
- Gtk::TreeModelColumn<Glib::ustring> choice;
+ Gtk::TreeModelColumn<Raul::Atom::TypeID> type;
+ Gtk::TreeModelColumn<Glib::ustring> 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<const ObjectModel> 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<const PatchModel> 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<Ingen::GUI::App> app;
SharedPtr<Ingen::GUI::PatchView> view;
SharedPtr<Ingen::Interface> engine;
+ SharedPtr<Ingen::Shared::AtomReader> reader;
SharedPtr<Ingen::Client::SigClientInterface> 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<Ingen::Shared::AtomReader>(
+ 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<Path> parent;
boost::optional<Symbol> 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 <locale.h>
-
#include <set>
-#include <boost/format.hpp>
-
#include <glibmm/convert.h>
#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h>
#include <glibmm/ustring.h>
+#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<GraphObject::Properties> 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 <locale.h>
-
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <cstring>
-#include <fstream>
-#include <map>
-#include <stdexcept>
#include <string>
-#include <utility>
-#include <vector>
#include <glib.h>
#include <glib/gstdio.h>
@@ -36,26 +29,23 @@
#include <glibmm/miscutils.h>
#include <glibmm/module.h>
-#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<const Patch> patch,
}
string
-Serialiser::to_string(SharedPtr<const GraphObject> object,
- const string& base_uri,
- const GraphObject::Properties& extra_rdf)
+Serialiser::to_string(SharedPtr<const GraphObject> 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<const GraphObject> 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<const GraphObject> 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<const Patch> patch = PtrCast<const Patch>(object);
if (patch) {
@@ -372,13 +348,17 @@ Serialiser::Impl::serialise_patch(SharedPtr<const Patch> 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<const Patch> 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<const Patch> 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 <http://drobilla.net>
+
+ 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 <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <http://drobilla.net>
+
+ 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 <stdint.h>
+
+#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 <boost/utility.hpp>
+#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 <http://drobilla.net>
+ *
+ * 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 <stdint.h>
+#include <string.h>
+
+#include <algorithm>
+
+#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<void*>(
+ const_cast<Buffer*>(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 <boost/intrusive_ptr.hpp>
#include <boost/utility.hpp>
+#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 <algorithm>
-#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<Buffer>& 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 <glibmm/thread.h>
+#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<Buffer> 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<Buffer>& 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<Buffer>& 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<Buffer> _free_audio;
Raul::AtomicPtr<Buffer> _free_control;
- Raul::AtomicPtr<Buffer> _free_event;
Raul::AtomicPtr<Buffer> _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 <algorithm>
#include <boost/intrusive_ptr.hpp>
-#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<EventBuffer> src_buf =
- boost::dynamic_pointer_cast<EventBuffer>(_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<Buffer> 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 <math.h>
-#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<AudioBuffer*>(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 = _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<Bindings> 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> _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<Ingen::Shared::Store>(
new EngineStore(SharedPtr<BufferFactory>(_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 <http://drobilla.net>
- *
- * 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 <stdint.h>
-#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<uint8_t*>(_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<const EventBuffer*>(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 <http://drobilla.net>
- *
- * 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<EventBuffer>(_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<EventBuffer>(_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<LV2Info> 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 <http://drobilla.net>
- *
- * 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 <string.h>
-#include <stdint.h>
-#include <algorithm>
-#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<const ObjectBuffer*>(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 <http://drobilla.net>
- *
- * 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<Patch*>(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<BufferFactory::Ref>*
@@ -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), &note);
- }
- 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), &note);
+ }
+ }
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<Iterator, Iterator> 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<int32_t>(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<PortImpl*>* _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<PortImpl*>(_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<PatchImpl*>(_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<PatchImpl*>(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<NodeImpl*>(obj);
@@ -288,7 +288,7 @@ SetMetadata::execute(ProcessContext& context)
std::vector<SpecialType>::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<AudioBuffer*>(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<EventBuffer*>(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<ObjectBuffer*>(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<Server::Driver>(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<LV2Port*> 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<Ingen::Server::Driver>(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<PortImpl*>(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<PortImpl*>(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<PortImpl*>(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 <boost/intrusive_ptr.hpp>
+#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<Buffer>* srcs, uint32_t num_srcs)
+mix(Context& context,
+ Shared::URIs& uris,
+ Buffer* dst,
+ const boost::intrusive_ptr<Buffer>* 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<Buffer>* 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 <http://drobilla.net>
+ *
+ * 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 <iostream>
+#include <utility>
+
+#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<const GraphObject> 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<const GraphObject> 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 <http://drobilla.net>
+ *
+ * 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 <sstream>
+
+#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 <http://drobilla.net>
- *
- * 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)
@@ -101,83 +92,6 @@ LV2URIMap::URIDUnmapFeature::unmap(LV2_URID 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<bool, uint32_t>
-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<bool, uint16_t>
-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)
{
return _urid_map_feature->map(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<LV2URIMap> lv2_uri_map;
+ Ingen::Forge* forge;
SharedPtr<URIs> uris;
SharedPtr<Interface> engine;
SharedPtr<EngineBase> local_engine;
@@ -216,7 +215,7 @@ SharedPtr<Serialisation::Serialiser> World::serialiser() { return _impl->seria
SharedPtr<Serialisation::Parser> World::parser() { return _impl->parser; }
SharedPtr<Store> 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