diff options
Diffstat (limited to 'src/gui/GraphCanvas.cpp')
-rw-r--r-- | src/gui/GraphCanvas.cpp | 185 |
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(); |