summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Forge.cpp3
-rw-r--r--src/URIs.cpp1
-rw-r--r--src/client/PortModel.cpp14
-rw-r--r--src/gui/Port.cpp64
-rw-r--r--src/gui/Port.hpp2
-rw-r--r--src/gui/PropertiesWindow.cpp199
-rw-r--r--src/gui/RDFS.cpp177
-rw-r--r--src/gui/RDFS.hpp67
-rw-r--r--src/gui/wscript1
-rw-r--r--src/server/Buffer.hpp2
-rw-r--r--src/server/BufferFactory.cpp6
-rw-r--r--src/server/BufferFactory.hpp3
-rw-r--r--src/server/LV2Block.cpp25
-rw-r--r--src/server/LV2Info.cpp2
-rw-r--r--src/server/LV2Info.hpp1
-rw-r--r--src/server/events/SetPortValue.cpp2
16 files changed, 402 insertions, 167 deletions
diff --git a/src/Forge.cpp b/src/Forge.cpp
index 077bec73..d74f42ee 100644
--- a/src/Forge.cpp
+++ b/src/Forge.cpp
@@ -23,6 +23,7 @@
namespace Ingen {
Forge::Forge(URIMap& map)
+ : _map(map)
{
Int = map.map_uri(LV2_ATOM__Int);
Float = map.map_uri(LV2_ATOM__Float);
@@ -44,6 +45,8 @@ Forge::str(const Raul::Atom& atom)
ss << (atom.get_bool() ? "true" : "false");
} else if (atom.type() == URI) {
ss << "<" << atom.get_uri() << ">";
+ } else if (atom.type() == URID) {
+ ss << "<" << _map.unmap_uri(atom.get_int32()) << ">";
} else if (atom.type() == String) {
ss << "\"" << atom.get_string() << "\"";
}
diff --git a/src/URIs.cpp b/src/URIs.cpp
index 8dbf87a6..a3ee8874 100644
--- a/src/URIs.cpp
+++ b/src/URIs.cpp
@@ -98,6 +98,7 @@ URIs::URIs(Forge& f, URIMap* map)
, lv2_binary (forge, map, LV2_CORE__binary)
, lv2_connectionOptional(forge, map, LV2_CORE__connectionOptional)
, lv2_default (forge, map, LV2_CORE__default)
+ , lv2_designation (forge, map, LV2_CORE__designation)
, lv2_extensionData (forge, map, LV2_CORE__extensionData)
, lv2_index (forge, map, LV2_CORE__index)
, lv2_integer (forge, map, LV2_CORE__integer)
diff --git a/src/client/PortModel.cpp b/src/client/PortModel.cpp
index fdef852d..e936a1e2 100644
--- a/src/client/PortModel.cpp
+++ b/src/client/PortModel.cpp
@@ -50,6 +50,20 @@ PortModel::port_property(const Raul::URI& uri) const
_uris.forge.alloc_uri(uri));
}
+bool
+PortModel::is_uri() const
+{
+ // FIXME: Resource::has_property doesn't work, URI != URID
+ for (Resource::Properties::const_iterator i = properties().begin();
+ i != properties().end(); ++i) {
+ if (i->second.type() == _uris.atom_URID &&
+ static_cast<LV2_URID>(i->second.get_int32()) == _uris.atom_URID) {
+ return true;
+ }
+ }
+ return false;
+}
+
void
PortModel::set(SharedPtr<ObjectModel> model)
{
diff --git a/src/gui/Port.cpp b/src/gui/Port.cpp
index 0027e480..f6e1e46b 100644
--- a/src/gui/Port.cpp
+++ b/src/gui/Port.cpp
@@ -28,6 +28,7 @@
#include "GraphWindow.hpp"
#include "Port.hpp"
#include "PortMenu.hpp"
+#include "RDFS.hpp"
#include "Style.hpp"
#include "WidgetFactory.hpp"
#include "WindowFactory.hpp"
@@ -206,6 +207,63 @@ Port::build_enum_menu()
return menu;
}
+void
+Port::on_uri_activated(const Raul::URI& uri)
+{
+ _app.interface()->set_property(
+ model()->uri(),
+ _app.world()->uris().ingen_value,
+ _app.world()->forge().make_urid(
+ _app.world()->uri_map().map_uri(uri.c_str())));
+}
+
+Gtk::Menu*
+Port::build_uri_menu()
+{
+ World* world = _app.world();
+ SharedPtr<const BlockModel> block = PtrCast<BlockModel>(model()->parent());
+ Gtk::Menu* menu = Gtk::manage(new Gtk::Menu());
+
+ // Get the port designation, which should be a rdf:Property
+ const Raul::Atom& designation_atom = model()->get_property(
+ _app.uris().lv2_designation);
+ if (!designation_atom.is_valid()) {
+ return NULL;
+ }
+
+ LilvNode* designation = lilv_new_uri(
+ world->lilv_world(), designation_atom.get_uri());
+ LilvNode* rdfs_range = lilv_new_uri(
+ world->lilv_world(), LILV_NS_RDFS "range");
+
+ // Get every class in the range of the port's property
+ RDFS::URISet ranges;
+ LilvNodes* range = lilv_world_find_nodes(
+ world->lilv_world(), designation, rdfs_range, NULL);
+ LILV_FOREACH(nodes, r, range) {
+ ranges.insert(Raul::URI(lilv_node_as_string(lilv_nodes_get(range, r))));
+ }
+ RDFS::classes(world, ranges, false);
+
+ // Get all objects in range
+ RDFS::Objects values = RDFS::instances(world, ranges);
+
+ // Add a menu item for each such class
+ for (RDFS::Objects::const_iterator i = values.begin(); i != values.end(); ++i) {
+ if (!i->second.empty()) {
+ Glib::ustring label = world->rdf_world()->prefixes().qualify(i->first)
+ + " - " + i->second;
+ menu->items().push_back(Gtk::Menu_Helpers::MenuElem(label));
+ Gtk::MenuItem* menu_item = &(menu->items().back());
+ menu_item->signal_activate().connect(
+ sigc::bind(sigc::mem_fun(this, &Port::on_uri_activated),
+ i->first));
+ }
+ }
+
+ return menu;
+}
+
bool
Port::on_event(GdkEvent* ev)
{
@@ -229,6 +287,12 @@ Port::on_event(GdkEvent* ev)
Gtk::Menu* menu = build_enum_menu();
menu->popup(ev->button.button, ev->button.time);
return true;
+ } else if (model()->is_uri()) {
+ Gtk::Menu* menu = build_uri_menu();
+ if (menu) {
+ menu->popup(ev->button.button, ev->button.time);
+ return true;
+ }
}
_pressed = true;
} else if (ev->button.button == 3) {
diff --git a/src/gui/Port.hpp b/src/gui/Port.hpp
index 2aab66eb..94f66ecd 100644
--- a/src/gui/Port.hpp
+++ b/src/gui/Port.hpp
@@ -75,6 +75,7 @@ private:
bool flip = false);
Gtk::Menu* build_enum_menu();
+ Gtk::Menu* build_uri_menu();
GraphBox* get_graph_box() const;
void property_changed(const Raul::URI& key, const Raul::Atom& value);
@@ -82,6 +83,7 @@ private:
void on_value_changed(GVariant* value);
void on_scale_point_activated(float f);
+ void on_uri_activated(const Raul::URI& uri);
bool on_event(GdkEvent* ev);
App& _app;
diff --git a/src/gui/PropertiesWindow.cpp b/src/gui/PropertiesWindow.cpp
index f2e2b9cf..b357514d 100644
--- a/src/gui/PropertiesWindow.cpp
+++ b/src/gui/PropertiesWindow.cpp
@@ -23,12 +23,14 @@
#include "ingen/Interface.hpp"
#include "ingen/Log.hpp"
+#include "ingen/URIMap.hpp"
#include "ingen/World.hpp"
#include "ingen/client/BlockModel.hpp"
#include "ingen/client/PluginModel.hpp"
#include "App.hpp"
#include "PropertiesWindow.hpp"
+#include "RDFS.hpp"
using namespace std;
@@ -81,16 +83,17 @@ PropertiesWindow::PropertiesWindow(BaseObjectType* cobject,
void
PropertiesWindow::reset()
{
- _table->children().clear();
- _table->resize(1, 3);
- _table->property_n_rows() = 1;
+ _property_connection.disconnect();
- _records.clear();
_key_store->clear();
_value_store->clear();
+ _records.clear();
- _property_connection.disconnect();
_model.reset();
+
+ _table->children().clear();
+ _table->resize(1, 3);
+ _table->property_n_rows() = 1;
}
void
@@ -100,132 +103,6 @@ PropertiesWindow::present(SharedPtr<const ObjectModel> model)
Gtk::Window::present();
}
-/** Set @p types to its super/sub class closure.
- * @param super If true, find all superclasses, otherwise all subclasses
- */
-static void
-get_classes(World* world, URISet& types, bool super)
-{
- LilvNode* rdfs_subClassOf = lilv_new_uri(
- world->lilv_world(), LILV_NS_RDFS "subClassOf");
-
- unsigned added = 0;
- do {
- added = 0;
- URISet klasses;
- for (URISet::iterator t = types.begin(); t != types.end(); ++t) {
- LilvNode* type = lilv_new_uri(world->lilv_world(), t->c_str());
- LilvNodes* matches = (super)
- ? lilv_world_find_nodes(
- world->lilv_world(), type, rdfs_subClassOf, NULL)
- : lilv_world_find_nodes(
- world->lilv_world(), NULL, rdfs_subClassOf, type);
- LILV_FOREACH(nodes, m, matches) {
- const LilvNode* klass_node = lilv_nodes_get(matches, m);
- if (lilv_node_is_uri(klass_node)) {
- Raul::URI klass(lilv_node_as_uri(klass_node));
- if (!types.count(klass)) {
- ++added;
- klasses.insert(klass);
- }
- }
- }
- lilv_nodes_free(matches);
- lilv_node_free(type);
- }
- types.insert(klasses.begin(), klasses.end());
- } while (added > 0);
-
- lilv_node_free(rdfs_subClassOf);
-}
-
-/** Get all the types which this model is an instance of */
-static URISet
-get_types(World* world, SharedPtr<const ObjectModel> model)
-{
- typedef Resource::Properties::const_iterator PropIter;
- typedef std::pair<PropIter, PropIter> PropRange;
-
- // Start with every rdf:type
- URISet types;
- PropRange range = model->properties().equal_range(world->uris().rdf_type);
- for (PropIter t = range.first; t != range.second; ++t) {
- types.insert(Raul::URI(t->second.get_uri()));
- if (world->uris().ingen_Graph == t->second.get_uri()) {
- // Add lv2:Plugin as a type for graphs so plugin properties show up
- types.insert(world->uris().lv2_Plugin);
- }
- }
-
- // Add every superclass of every type, recursively
- get_classes(world, types, true);
-
- return types;
-}
-
-/** Get all the properties with domains appropriate to this model */
-static URISet
-get_properties(World* world, SharedPtr<const ObjectModel> model)
-{
- URISet properties;
- URISet types = get_types(world, model);
-
- LilvNode* rdf_type = lilv_new_uri(world->lilv_world(),
- LILV_NS_RDF "type");
- LilvNode* rdf_Property = lilv_new_uri(world->lilv_world(),
- LILV_NS_RDF "Property");
- LilvNode* rdfs_domain = lilv_new_uri(world->lilv_world(),
- LILV_NS_RDFS "domain");
-
- LilvNodes* props = lilv_world_find_nodes(
- world->lilv_world(), NULL, rdf_type, rdf_Property);
- LILV_FOREACH(nodes, p, props) {
- const LilvNode* prop = lilv_nodes_get(props, p);
- if (lilv_node_is_uri(prop)) {
- LilvNodes* domains = lilv_world_find_nodes(
- world->lilv_world(), prop, rdfs_domain, NULL);
- unsigned n_matching_domains = 0;
- LILV_FOREACH(nodes, d, domains) {
- const LilvNode* domain_node = lilv_nodes_get(domains, d);
- const Raul::URI domain(lilv_node_as_uri(domain_node));
- if (types.count(domain)) {
- ++n_matching_domains;
- }
- }
-
- if (lilv_nodes_size(domains) == 0 || (
- n_matching_domains > 0 &&
- n_matching_domains == lilv_nodes_size(domains))) {
- properties.insert(Raul::URI(lilv_node_as_uri(prop)));
- }
-
- lilv_nodes_free(domains);
- }
- }
-
- lilv_node_free(rdfs_domain);
- lilv_node_free(rdf_Property);
- lilv_node_free(rdf_type);
-
- return properties;
-}
-
-static Glib::ustring
-get_label(World* world, const LilvNode* node)
-{
- LilvNode* rdfs_label = lilv_new_uri(
- world->lilv_world(), LILV_NS_RDFS "label");
- LilvNodes* labels = lilv_world_find_nodes(
- world->lilv_world(), node, rdfs_label, NULL);
-
- const LilvNode* first = lilv_nodes_get_first(labels);
- Glib::ustring label = first ? lilv_node_as_string(first) : "";
-
- lilv_nodes_free(labels);
- lilv_node_free(rdfs_label);
- return label;
-}
-
void
PropertiesWindow::add_property(const Raul::URI& uri, const Raul::Atom& value)
{
@@ -236,7 +113,7 @@ PropertiesWindow::add_property(const Raul::URI& uri, const Raul::Atom& value)
// Column 0: Property
LilvNode* prop = lilv_new_uri(world->lilv_world(), uri.c_str());
- Glib::ustring lab_text = get_label(world, prop);
+ Glib::ustring lab_text = RDFS::label(world, prop);
if (lab_text.empty()) {
lab_text = world->rdf_world()->prefixes().qualify(uri);
}
@@ -278,10 +155,10 @@ PropertiesWindow::set_object(SharedPtr<const ObjectModel> model)
world->lilv_world(), LILV_NS_RDF "type");
// Populate key combo
- const URISet props = get_properties(world, model);
+ const URISet props = RDFS::properties(world, model);
for (URISet::const_iterator p = props.begin(); p != props.end(); ++p) {
LilvNode* prop = lilv_new_uri(world->lilv_world(), p->c_str());
- const Glib::ustring label = get_label(world, prop);
+ const Glib::ustring label = RDFS::label(world, prop);
if (label.empty()) {
continue;
}
@@ -293,7 +170,7 @@ PropertiesWindow::set_object(SharedPtr<const ObjectModel> model)
LILV_FOREACH(nodes, r, range) {
ranges.insert(Raul::URI(lilv_node_as_string(lilv_nodes_get(range, r))));
}
- get_classes(world, ranges, false);
+ RDFS::classes(world, ranges, false);
bool show = false;
for (URISet::const_iterator i = ranges.begin(); i != ranges.end(); ++i) {
@@ -373,6 +250,16 @@ 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() == forge.URID) {
+ const char* val_uri = _app->world()->uri_map().unmap_uri(value.get_int32());
+ Gtk::Entry* widget = manage(new Gtk::Entry());
+ if (val_uri) {
+ widget->set_text(val_uri);
+ }
+ widget->signal_changed().connect(sigc::bind(
+ sigc::mem_fun(this, &PropertiesWindow::value_edited),
+ uri));
+ return widget;
} else if (value.type() == forge.String) {
Gtk::Entry* widget = manage(new Gtk::Entry());
widget->set_text(value.get_string());
@@ -382,8 +269,8 @@ PropertiesWindow::create_value_widget(const Raul::URI& uri, const Raul::Atom& va
return widget;
}
- _app->log().error(Raul::fmt("Unable to create widget for value %1%\n")
- % forge.str(value));
+ _app->log().error(Raul::fmt("Unable to create widget for value %1% type %2%\n")
+ % forge.str(value) % value.type());
return NULL;
}
@@ -483,19 +370,21 @@ PropertiesWindow::key_changed()
{
World* world = _app->world();
- const Gtk::ListStore::Row row = *(_key_combo->get_active());
- Glib::ustring prop_uri = row[_combo_columns.uri_col];
+ _value_store->clear();
+ const Gtk::ListStore::iterator iter = _key_combo->get_active();
+ if (!iter) {
+ return;
+ }
+
+ const Gtk::ListStore::Row row = *iter;
+ Glib::ustring prop_uri = row[_combo_columns.uri_col];
if (prop_uri.empty()) {
return;
}
- _value_store->clear();
-
LilvNode* rdfs_range = lilv_new_uri(
world->lilv_world(), LILV_NS_RDFS "range");
- LilvNode* rdf_type = lilv_new_uri(
- world->lilv_world(), LILV_NS_RDF "type");
LilvNode* prop = lilv_new_uri(
world->lilv_world(), prop_uri.c_str());
@@ -507,28 +396,13 @@ PropertiesWindow::key_changed()
LILV_FOREACH(nodes, r, range) {
ranges.insert(Raul::URI(lilv_node_as_string(lilv_nodes_get(range, r))));
}
- get_classes(world, ranges, false);
+ RDFS::classes(world, ranges, false);
// Get all objects in range
- typedef std::map<Raul::URI, Glib::ustring> Values;
- Values values;
- for (URISet::const_iterator i = ranges.begin(); i != ranges.end(); ++i) {
- LilvNode* range = lilv_new_uri(world->lilv_world(), i->c_str());
- LilvNodes* objects = lilv_world_find_nodes(
- world->lilv_world(), NULL, rdf_type, range);
- LILV_FOREACH(nodes, o, objects) {
- const LilvNode* object = lilv_nodes_get(objects, o);
- const Glib::ustring label = get_label(world, object);
- values.insert(
- std::make_pair(
- Raul::URI(lilv_node_as_string(object)),
- label));
- }
- lilv_node_free(range);
- }
+ RDFS::Objects values = RDFS::instances(world, ranges);
// Fill value selector with suitable objects
- for (Values::const_iterator i = values.begin(); i != values.end(); ++i) {
+ for (RDFS::Objects::const_iterator i = values.begin(); i != values.end(); ++i) {
if (!i->second.empty()) {
Gtk::ListStore::iterator vi = _value_store->append();
Gtk::ListStore::Row vrow = *vi;
@@ -538,7 +412,6 @@ PropertiesWindow::key_changed()
}
lilv_node_free(prop);
- lilv_node_free(rdf_type);
lilv_node_free(rdfs_range);
}
@@ -587,7 +460,7 @@ void
PropertiesWindow::ok_clicked()
{
apply_clicked();
- cancel_clicked();
+ Gtk::Window::hide();
}
} // namespace GUI
diff --git a/src/gui/RDFS.cpp b/src/gui/RDFS.cpp
new file mode 100644
index 00000000..0420d4dd
--- /dev/null
+++ b/src/gui/RDFS.cpp
@@ -0,0 +1,177 @@
+/*
+ This file is part of Ingen.
+ Copyright 2007-2012 David Robillard <http://drobilla.net/>
+
+ Ingen is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or any later version.
+
+ Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with Ingen. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "ingen/Resource.hpp"
+#include "ingen/World.hpp"
+#include "ingen/client/ObjectModel.hpp"
+#include "lilv/lilv.h"
+
+#include "RDFS.hpp"
+
+namespace Ingen {
+namespace GUI {
+namespace RDFS {
+
+Glib::ustring
+label(World* world, const LilvNode* node)
+{
+ LilvNode* rdfs_label = lilv_new_uri(
+ world->lilv_world(), LILV_NS_RDFS "label");
+ LilvNodes* labels = lilv_world_find_nodes(
+ world->lilv_world(), node, rdfs_label, NULL);
+
+ const LilvNode* first = lilv_nodes_get_first(labels);
+ Glib::ustring label = first ? lilv_node_as_string(first) : "";
+
+ lilv_nodes_free(labels);
+ lilv_node_free(rdfs_label);
+ return label;
+}
+
+void
+classes(World* world, URISet& types, bool super)
+{
+ LilvNode* rdfs_subClassOf = lilv_new_uri(
+ world->lilv_world(), LILV_NS_RDFS "subClassOf");
+
+ unsigned added = 0;
+ do {
+ added = 0;
+ URISet klasses;
+ for (URISet::iterator t = types.begin(); t != types.end(); ++t) {
+ LilvNode* type = lilv_new_uri(world->lilv_world(), t->c_str());
+ LilvNodes* matches = (super)
+ ? lilv_world_find_nodes(
+ world->lilv_world(), type, rdfs_subClassOf, NULL)
+ : lilv_world_find_nodes(
+ world->lilv_world(), NULL, rdfs_subClassOf, type);
+ LILV_FOREACH(nodes, m, matches) {
+ const LilvNode* klass_node = lilv_nodes_get(matches, m);
+ if (lilv_node_is_uri(klass_node)) {
+ Raul::URI klass(lilv_node_as_uri(klass_node));
+ if (!types.count(klass)) {
+ ++added;
+ klasses.insert(klass);
+ }
+ }
+ }
+ lilv_nodes_free(matches);
+ lilv_node_free(type);
+ }
+ types.insert(klasses.begin(), klasses.end());
+ } while (added > 0);
+
+ lilv_node_free(rdfs_subClassOf);
+}
+
+URISet
+types(World* world, SharedPtr<const Client::ObjectModel> model)
+{
+ typedef Resource::Properties::const_iterator PropIter;
+ typedef std::pair<PropIter, PropIter> PropRange;
+
+ // Start with every rdf:type
+ URISet types;
+ PropRange range = model->properties().equal_range(world->uris().rdf_type);
+ for (PropIter t = range.first; t != range.second; ++t) {
+ types.insert(Raul::URI(t->second.get_uri()));
+ if (world->uris().ingen_Graph == t->second.get_uri()) {
+ // Add lv2:Plugin as a type for graphs so plugin properties show up
+ types.insert(world->uris().lv2_Plugin);
+ }
+ }
+
+ // Add every superclass of every type, recursively
+ RDFS::classes(world, types, true);
+
+ return types;
+}
+
+URISet
+properties(World* world, SharedPtr<const Client::ObjectModel> model)
+{
+ URISet properties;
+ URISet types = RDFS::types(world, model);
+
+ LilvNode* rdf_type = lilv_new_uri(world->lilv_world(),
+ LILV_NS_RDF "type");
+ LilvNode* rdf_Property = lilv_new_uri(world->lilv_world(),
+ LILV_NS_RDF "Property");
+ LilvNode* rdfs_domain = lilv_new_uri(world->lilv_world(),
+ LILV_NS_RDFS "domain");
+
+ LilvNodes* props = lilv_world_find_nodes(
+ world->lilv_world(), NULL, rdf_type, rdf_Property);
+ LILV_FOREACH(nodes, p, props) {
+ const LilvNode* prop = lilv_nodes_get(props, p);
+ if (lilv_node_is_uri(prop)) {
+ LilvNodes* domains = lilv_world_find_nodes(
+ world->lilv_world(), prop, rdfs_domain, NULL);
+ unsigned n_matching_domains = 0;
+ LILV_FOREACH(nodes, d, domains) {
+ const LilvNode* domain_node = lilv_nodes_get(domains, d);
+ const Raul::URI domain(lilv_node_as_uri(domain_node));
+ if (types.count(domain)) {
+ ++n_matching_domains;
+ }
+ }
+
+ if (lilv_nodes_size(domains) == 0 || (
+ n_matching_domains > 0 &&
+ n_matching_domains == lilv_nodes_size(domains))) {
+ properties.insert(Raul::URI(lilv_node_as_uri(prop)));
+ }
+
+ lilv_nodes_free(domains);
+ }
+ }
+
+ lilv_node_free(rdfs_domain);
+ lilv_node_free(rdf_Property);
+ lilv_node_free(rdf_type);
+
+ return properties;
+}
+
+Objects
+instances(World* world, const URISet& types)
+{
+ LilvNode* rdf_type = lilv_new_uri(
+ world->lilv_world(), LILV_NS_RDF "type");
+
+ Objects result;
+ for (URISet::const_iterator i = types.begin(); i != types.end(); ++i) {
+ LilvNode* type = lilv_new_uri(world->lilv_world(), i->c_str());
+ LilvNodes* objects = lilv_world_find_nodes(
+ world->lilv_world(), NULL, rdf_type, type);
+ LILV_FOREACH(nodes, o, objects) {
+ const LilvNode* object = lilv_nodes_get(objects, o);
+ const Glib::ustring label = RDFS::label(world, object);
+ result.insert(
+ std::make_pair(
+ Raul::URI(lilv_node_as_string(object)),
+ label));
+ }
+ lilv_node_free(type);
+ }
+
+ lilv_node_free(rdf_type);
+ return result;
+}
+
+} // namespace RDFS
+} // namespace GUI
+} // namespace Ingen
diff --git a/src/gui/RDFS.hpp b/src/gui/RDFS.hpp
new file mode 100644
index 00000000..bdc0a7a1
--- /dev/null
+++ b/src/gui/RDFS.hpp
@@ -0,0 +1,67 @@
+/*
+ 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 Affero General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or any later version.
+
+ Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with Ingen. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef INGEN_GUI_RDF_HPP
+#define INGEN_GUI_RDF_HPP
+
+#include <map>
+#include <set>
+
+#include <glibmm/ustring.h>
+
+#include "raul/URI.hpp"
+#include "raul/SharedPtr.hpp"
+
+namespace Ingen {
+
+class World;
+
+namespace Client { class ObjectModel; }
+
+namespace GUI {
+
+namespace RDFS {
+
+/** Set of URIs. */
+typedef std::set<Raul::URI> URISet;
+
+/** Map of object labels, keyed by object URI. */
+typedef std::map<Raul::URI, Glib::ustring> Objects;
+
+/** Return the label of @p node. */
+Glib::ustring
+label(World* world, const LilvNode* node);
+
+/** Set @p types to its super/sub class closure.
+ * @param super If true, find all superclasses, otherwise all subclasses
+ */
+void classes(World* world, URISet& types, bool super);
+
+/** Get all instances of any class in @p types. */
+Objects
+instances(World* world, const URISet& types);
+
+/** Get all the types which @p model is an instance of. */
+URISet types(World* world, SharedPtr<const Client::ObjectModel> model);
+
+/** Get all the properties with domains appropriate for @p model. */
+URISet properties(World* world, SharedPtr<const Client::ObjectModel> model);
+
+} // namespace RDFS
+} // namespace GUI
+} // namespace Ingen
+
+#endif // INGEN_GUI_RDF_HPP
diff --git a/src/gui/wscript b/src/gui/wscript
index 1f0a567f..982c93d8 100644
--- a/src/gui/wscript
+++ b/src/gui/wscript
@@ -48,6 +48,7 @@ def build(bld):
PortMenu.cpp
PortPropertiesWindow.cpp
PropertiesWindow.cpp
+ RDFS.cpp
RenameWindow.cpp
Style.cpp
SubgraphModule.cpp
diff --git a/src/server/Buffer.hpp b/src/server/Buffer.hpp
index 0f237e67..c710f4df 100644
--- a/src/server/Buffer.hpp
+++ b/src/server/Buffer.hpp
@@ -54,6 +54,8 @@ public:
inline LV2_URID type() const { return _type; }
inline uint32_t capacity() const { return _capacity; }
+ inline void set_type(LV2_URID t) { _type = t; }
+
inline bool is_audio() const {
return _type == _factory.uris().atom_Sound;
}
diff --git a/src/server/BufferFactory.cpp b/src/server/BufferFactory.cpp
index da459705..064b5080 100644
--- a/src/server/BufferFactory.cpp
+++ b/src/server/BufferFactory.cpp
@@ -38,6 +38,7 @@ BufferFactory::~BufferFactory()
_silent_buffer.reset();
free_list(_free_audio.get());
free_list(_free_control.get());
+ free_list(_free_sequence.get());
free_list(_free_object.get());
}
@@ -77,6 +78,8 @@ BufferFactory::default_size(LV2_URID type) const
return sizeof(LV2_Atom_Float);
} else if (type == _uris.atom_Sound) {
return audio_buffer_size(_engine.driver()->block_length());
+ } else if (type == _uris.atom_URID) {
+ return sizeof(LV2_Atom_URID);
} else if (type == _uris.atom_Sequence) {
if (_seq_size == 0) {
return _engine.driver()->block_length() * SEQ_BYTES_PER_FRAME;
@@ -95,7 +98,7 @@ BufferFactory::get(LV2_URID type,
bool force_create)
{
Raul::AtomicPtr<Buffer>& head_ptr = free_list(type);
- Buffer* try_head = NULL;
+ Buffer* try_head = NULL;
if (!force_create) {
Buffer* next;
@@ -117,6 +120,7 @@ BufferFactory::get(LV2_URID type,
}
try_head->_next = NULL;
+ try_head->set_type(type);
return BufferRef(try_head);
}
diff --git a/src/server/BufferFactory.hpp b/src/server/BufferFactory.hpp
index e466e969..1fe3a91e 100644
--- a/src/server/BufferFactory.hpp
+++ b/src/server/BufferFactory.hpp
@@ -74,6 +74,8 @@ private:
return _free_control;
} else if (type == _uris.atom_Sound) {
return _free_audio;
+ } else if (type == _uris.atom_Sequence) {
+ return _free_sequence;
} else {
return _free_object;
}
@@ -83,6 +85,7 @@ private:
Raul::AtomicPtr<Buffer> _free_audio;
Raul::AtomicPtr<Buffer> _free_control;
+ Raul::AtomicPtr<Buffer> _free_sequence;
Raul::AtomicPtr<Buffer> _free_object;
Glib::Mutex _mutex;
diff --git a/src/server/LV2Block.cpp b/src/server/LV2Block.cpp
index 47a0af4f..e334c1f9 100644
--- a/src/server/LV2Block.cpp
+++ b/src/server/LV2Block.cpp
@@ -282,6 +282,13 @@ LV2Block::instantiate(BufferFactory& bufs)
}
uint32_t port_buffer_size = bufs.default_size(buffer_type);
+ if (port_buffer_size == 0) {
+ parent_graph()->engine().log().error(
+ Raul::fmt("<%1%> port `%2%' has unknown buffer type\n")
+ % _lv2_plugin->uri().c_str() % port_sym.c_str());
+ ret = false;
+ break;
+ }
if (port_type == PortType::ATOM) {
// Get default value, and its length
@@ -293,10 +300,18 @@ LV2Block::instantiate(BufferFactory& bufs)
const uint32_t str_val_len = strlen(str_val);
val = forge.alloc(str_val);
port_buffer_size = std::max(port_buffer_size, str_val_len);
+ } else if (lilv_node_is_uri(d)) {
+ const char* uri_val = lilv_node_as_uri(d);
+ val = forge.make_urid(
+ bufs.engine().world()->uri_map().map_uri(uri_val));
}
}
lilv_nodes_free(defaults);
+ if (!val.type() && buffer_type == _uris.atom_URID) {
+ val = forge.make_urid(0);
+ }
+
// Get minimum size, if set in data
LilvNodes* sizes = lilv_port_get_value(plug, id, info->rsz_minimumSize);
LILV_FOREACH(nodes, i, sizes) {
@@ -318,14 +333,15 @@ LV2Block::instantiate(BufferFactory& bufs)
if (port_type == PortType::UNKNOWN || direction == UNKNOWN) {
parent_graph()->engine().log().error(
- Raul::fmt("<%1%> port %2% has unknown type or direction\n")
+ Raul::fmt("<%1%> port `%2%' has unknown type or direction\n")
% _lv2_plugin->uri().c_str() % port_sym.c_str());
ret = false;
break;
}
- if (!val.type())
+ if (!val.type() && port_type != PortType::ATOM) {
val = forge.make(isnan(def_values[j]) ? 0.0f : def_values[j]);
+ }
PortImpl* port = (direction == INPUT)
? static_cast<PortImpl*>(
@@ -350,7 +366,10 @@ LV2Block::instantiate(BufferFactory& bufs)
}
// Inherit certain properties from plugin port
- LilvNode* preds[] = { info->lv2_portProperty, info->atom_supports, 0 };
+ const LilvNode* preds[] = { info->lv2_designation,
+ info->lv2_portProperty,
+ info->atom_supports,
+ 0 };
for (int p = 0; preds[p]; ++p) {
LilvNodes* values = lilv_port_get_value(plug, id, preds[p]);
LILV_FOREACH(nodes, v, values) {
diff --git a/src/server/LV2Info.cpp b/src/server/LV2Info.cpp
index 744a30b2..841ee0fd 100644
--- a/src/server/LV2Info.cpp
+++ b/src/server/LV2Info.cpp
@@ -40,6 +40,7 @@ LV2Info::LV2Info(Ingen::World* world)
, lv2_InputPort(lilv_new_uri(world->lilv_world(), LV2_CORE__InputPort))
, lv2_OutputPort(lilv_new_uri(world->lilv_world(), LV2_CORE__OutputPort))
, lv2_default(lilv_new_uri(world->lilv_world(), LV2_CORE__default))
+ , lv2_designation(lilv_new_uri(world->lilv_world(), LV2_CORE__designation))
, lv2_portProperty(lilv_new_uri(world->lilv_world(), LV2_CORE__portProperty))
, lv2_sampleRate(lilv_new_uri(world->lilv_world(), LV2_CORE__sampleRate))
, morph_AutoMorphPort(lilv_new_uri(world->lilv_world(), LV2_MORPH__AutoMorphPort))
@@ -64,6 +65,7 @@ LV2Info::~LV2Info()
lilv_node_free(lv2_InputPort);
lilv_node_free(lv2_OutputPort);
lilv_node_free(lv2_default);
+ lilv_node_free(lv2_designation);
lilv_node_free(lv2_portProperty);
lilv_node_free(lv2_sampleRate);
lilv_node_free(morph_AutoMorphPort);
diff --git a/src/server/LV2Info.hpp b/src/server/LV2Info.hpp
index fd70ea83..1d38b4e1 100644
--- a/src/server/LV2Info.hpp
+++ b/src/server/LV2Info.hpp
@@ -40,6 +40,7 @@ public:
LilvNode* const lv2_InputPort;
LilvNode* const lv2_OutputPort;
LilvNode* const lv2_default;
+ LilvNode* const lv2_designation;
LilvNode* const lv2_portProperty;
LilvNode* const lv2_sampleRate;
LilvNode* const morph_AutoMorphPort;
diff --git a/src/server/events/SetPortValue.cpp b/src/server/events/SetPortValue.cpp
index 14919cee..b3481861 100644
--- a/src/server/events/SetPortValue.cpp
+++ b/src/server/events/SetPortValue.cpp
@@ -104,6 +104,8 @@ SetPortValue::apply(Context& context)
} else {
_status = NO_SPACE;
}
+ } else if (buf->type() == uris.atom_URID) {
+ ((LV2_Atom_URID*)buf->atom())->body = _value.get_int32();
} else {
_status = BAD_VALUE_TYPE;
}