summaryrefslogtreecommitdiffstats
path: root/src/gui/GraphCanvas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/GraphCanvas.cpp')
-rw-r--r--src/gui/GraphCanvas.cpp185
1 files changed, 161 insertions, 24 deletions
diff --git a/src/gui/GraphCanvas.cpp b/src/gui/GraphCanvas.cpp
index 6d22f407..1a07f0c6 100644
--- a/src/gui/GraphCanvas.cpp
+++ b/src/gui/GraphCanvas.cpp
@@ -16,6 +16,7 @@
#include <algorithm>
#include <cassert>
+#include <iterator>
#include <map>
#include <set>
#include <string>
@@ -34,6 +35,7 @@
#include "ingen/client/BlockModel.hpp"
#include "ingen/client/ClientStore.hpp"
#include "ingen/client/GraphModel.hpp"
+#include "ingen/client/GroupModel.hpp"
#include "ingen/client/PluginModel.hpp"
#include "ingen/ingen.h"
#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
@@ -93,6 +95,7 @@ GraphCanvas::GraphCanvas(App& app,
Glib::RefPtr<Gtk::Builder> xml = WidgetFactory::create("canvas_menu");
xml->get_widget("canvas_menu", _menu);
+ xml->get_widget("canvas_menu_add_group_input", _add_input_group_menu);
xml->get_widget("canvas_menu_add_audio_input", _menu_add_audio_input);
xml->get_widget("canvas_menu_add_audio_output", _menu_add_audio_output);
xml->get_widget("canvas_menu_add_cv_input", _menu_add_cv_input);
@@ -109,7 +112,22 @@ GraphCanvas::GraphCanvas(App& app,
const URIs& uris = _app.uris();
+ LilvNodes* group_types = lilv_world_find_nodes(
+ app.world()->lilv_world(), NULL, uris.rdfs_subClassOf, uris.pg_DiscreteGroup);
+ LILV_FOREACH(nodes, t, group_types) {
+ const LilvNode* gtype = lilv_nodes_get(group_types, t);
+ _add_input_group_menu->items().push_back(
+ Gtk::Menu_Helpers::MenuElem(lilv_node_as_string(gtype)));
+ Gtk::MenuItem* menu_item = &(_add_input_group_menu->items().back());
+ menu_item->signal_activate().connect(
+ sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_group),
+ "group", "Group", Raul::URI(lilv_node_as_string(gtype)), false));
+ }
+
// Add port menu items
+ // _menu_add_audio_input->signal_activate().connect(
+ // sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_group),
+ // "stereo_in", "Stereo In", uris.pg_StereoGroup, false));
_menu_add_audio_input->signal_activate().connect(
sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port),
"audio_in", "Audio In", uris.lv2_AudioPort, false));
@@ -147,6 +165,10 @@ GraphCanvas::GraphCanvas(App& app,
sigc::mem_fun(this, &GraphCanvas::add_block));
_graph->signal_removed_block().connect(
sigc::mem_fun(this, &GraphCanvas::remove_block));
+ _graph->signal_new_group().connect(
+ sigc::mem_fun(this, &GraphCanvas::add_group));
+ _graph->signal_removed_group().connect(
+ sigc::mem_fun(this, &GraphCanvas::remove_group));
_graph->signal_new_port().connect(
sigc::mem_fun(this, &GraphCanvas::add_port));
_graph->signal_removed_port().connect(
@@ -357,7 +379,21 @@ GraphCanvas::remove_block(SPtr<const BlockModel> bm)
void
GraphCanvas::add_port(SPtr<const PortModel> pm)
{
- GraphPortModule* view = GraphPortModule::create(*this, pm);
+ const Atom& group = pm->get_property(_app.uris().pg_group);
+ if (group.is_valid()) {
+ // Port is on a group, add to group module
+ const Raul::URI group_uri(_app.forge().str(group, false));
+ auto gm = _app.store()->object(uri_to_path(group_uri));
+ auto g = _views.find(gm);
+ if (g != _views.end()) {
+ Port::create(_app, *g->second, pm, true);
+ return;
+ }
+ }
+
+ // Port has no group, add it to anonymous module
+ GraphPortModule* view = GraphPortModule::create(
+ *this, SPtr<const GroupModel>(), pm);
_views.insert(std::make_pair(pm, view));
view->show();
}
@@ -380,6 +416,20 @@ GraphCanvas::remove_port(SPtr<const PortModel> pm)
assert(_views.find(pm) == _views.end());
}
+void
+GraphCanvas::add_group(SPtr<const GroupModel> gm)
+{
+ GraphPortModule* view = GraphPortModule::create(
+ *this, gm, SPtr<const PortModel>());
+ _views.insert(std::make_pair(gm, view));
+ view->show();
+}
+
+void
+GraphCanvas::remove_group(SPtr<const GroupModel> gm)
+{
+}
+
Ganv::Port*
GraphCanvas::get_port_view(SPtr<PortModel> port)
{
@@ -569,12 +619,13 @@ destroy_node(GanvNode* node, void* data)
if (node_module) {
app->interface()->del(node_module->block()->uri());
} else {
- GraphPortModule* port_module = dynamic_cast<GraphPortModule*>(module);
- if (port_module &&
- strcmp(port_module->port()->path().symbol(), "control") &&
- strcmp(port_module->port()->path().symbol(), "notify")) {
- app->interface()->del(port_module->port()->uri());
- }
+ fprintf(stderr, "FIXME\n");
+ // GraphPortModule* port_module = dynamic_cast<GraphPortModule*>(module);
+ // if (port_module &&
+ // strcmp(port_module->port()->path().symbol(), "control") &&
+ // strcmp(port_module->port()->path().symbol(), "notify")) {
+ // app->interface()->del(port_module->port()->uri());
+ // }
}
}
@@ -614,7 +665,13 @@ serialise_node(GanvNode* node, void* data)
} else {
GraphPortModule* port_module = dynamic_cast<GraphPortModule*>(module);
if (port_module) {
- serialiser->serialise(port_module->port());
+ for (const auto& p : *port_module) {
+ if (Port* port = dynamic_cast<Port*>(p)) {
+ serialiser->serialise(port->model());
+ } else {
+ fprintf(stderr, "ERR\n");
+ }
+ }
}
}
}
@@ -786,33 +843,113 @@ GraphCanvas::generate_port_name(
}
void
-GraphCanvas::menu_add_port(const string& sym_base, const string& name_base,
- const Raul::URI& type, bool is_output)
+GraphCanvas::menu_add_port(const string& sym_base,
+ const string& name_base,
+ const Raul::URI& type,
+ bool is_output)
{
string sym, name;
generate_port_name(sym_base, sym, name_base, name);
- const Raul::Path& path = _graph->path().child(Raul::Symbol(sym));
- const URIs& uris = _app.uris();
+ const Raul::Path& path = _graph->path().child(Raul::Symbol(sym));
+ const URIs& uris = _app.uris();
+ Forge& forge = _app.forge();
+
+ // Basic port description
+ Properties props = {
+ {uris.rdf_type, forge.make_urid(type)},
+ {uris.rdf_type, Property(is_output
+ ? uris.lv2_OutputPort
+ : uris.lv2_InputPort)},
+ {uris.lv2_index, forge.make(int32_t(_graph->num_ports()))},
+ {uris.lv2_name, forge.alloc(name.c_str())}};
- Properties props = get_initial_data(Resource::Graph::INTERNAL);
- props.insert(make_pair(uris.rdf_type, _app.forge().make_urid(type)));
+ // Add atom:bufferType for sequence ports
if (type == uris.atom_AtomPort) {
- props.insert(make_pair(uris.atom_bufferType,
- Property(uris.atom_Sequence)));
+ props.emplace(uris.atom_bufferType,
+ Property(uris.atom_Sequence));
}
- props.insert(make_pair(uris.rdf_type,
- Property(is_output
- ? uris.lv2_OutputPort
- : uris.lv2_InputPort)));
- props.insert(make_pair(uris.lv2_index,
- _app.forge().make(int32_t(_graph->num_ports()))));
- props.insert(make_pair(uris.lv2_name,
- _app.forge().alloc(name.c_str())));
+
+ // Add initial data for canvas position etc
+ Properties init = get_initial_data(Resource::Graph::INTERNAL);
+ props.insert(std::make_move_iterator(init.begin()),
+ std::make_move_iterator(init.end()));
+
_app.interface()->put(path_to_uri(path), props);
}
void
+GraphCanvas::menu_add_group(const string& sym_base,
+ const string& name_base,
+ const Raul::URI& type,
+ bool is_output)
+{
+ string sym, name;
+ generate_port_name(sym_base, sym, name_base, name);
+
+ const Raul::Path& path = _graph->path().child(Raul::Symbol(sym));
+ const URIs& uris = _app.uris();
+ Forge& forge = _app.forge();
+ World* world = _app.world();
+ LilvWorld* lworld = world->lilv_world();
+
+ // Group description
+ Properties group_props = {
+ {uris.rdf_type, forge.make_urid(type)},
+ {uris.rdf_type, Property(is_output
+ ? uris.pg_OutputGroup
+ : uris.pg_InputGroup)},
+ {uris.lv2_name, forge.alloc(name.c_str())}};
+
+ // Add initial data for canvas position etc
+ Properties init = get_initial_data(Resource::Graph::INTERNAL);
+ group_props.insert(std::make_move_iterator(init.begin()),
+ std::make_move_iterator(init.end()));
+
+ // Create a port for each element of this group type
+ std::map<uint32_t, std::pair<Raul::Path, Properties>> ports;
+ LilvNode* group = lilv_new_uri(lworld, type.c_str());
+ LilvNodes* elements = lilv_world_find_nodes(
+ lworld, group, uris.pg_element, NULL);
+ LILV_FOREACH(nodes, e, elements) {
+ const LilvNode* element = lilv_nodes_get(elements, e);
+ const LilvNode* index_node = lilv_world_get(lworld, element, uris.lv2_index, NULL);
+ const LilvNode* designation = lilv_world_get(lworld, element, uris.lv2_designation, NULL);
+ const LilvNode* label = lilv_world_get(lworld, designation, uris.rdfs_label, NULL);
+ const char* label_str = lilv_node_as_string(label);
+ const uint32_t index = _graph->num_ports() + lilv_node_as_int(index_node);
+
+ Properties port_props = {
+ {uris.rdf_type, forge.make_urid(uris.lv2_AudioPort)},
+ {uris.rdf_type, Property(is_output
+ ? uris.lv2_OutputPort
+ : uris.lv2_InputPort)},
+ {uris.pg_group, forge.make_urid(path_to_uri(path))},
+ {uris.lv2_index, forge.make(int32_t(index))},
+ {uris.lv2_name, forge.alloc(label_str)}};
+
+ const Raul::Symbol sym = Raul::Symbol::symbolify(label_str);
+ ports.insert(
+ std::make_pair(
+ index,
+ std::make_pair(_graph->path().child(sym), port_props)));
+
+ // fprintf(stderr, "Element: %s %s %s %s\n",
+ // lilv_node_as_string(index),
+ // lilv_node_as_string(designation),
+ // lilv_node_as_string(label),
+ // Raul::Symbol::symbolify(lilv_node_as_string(label)).c_str());
+ }
+
+ _app.interface()->bundle_begin();
+ _app.interface()->put(path_to_uri(path), group_props);
+ for (const auto& p : ports) {
+ _app.interface()->put(path_to_uri(p.second.first), p.second.second);
+ }
+ _app.interface()->bundle_end();
+}
+
+void
GraphCanvas::load_plugin(WPtr<PluginModel> weak_plugin)
{
SPtr<PluginModel> plugin = weak_plugin.lock();