From a7d83f19b08eb4c6f79a82fe60c2b86db13f4420 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 24 Nov 2018 13:44:03 +0100 Subject: Squashed 'waflib/' changes from 6e726eb1..5ea8f99f 5ea8f99f Improve test output spacing 0e23b29f Raise exception when test suite fails to ensure non-zero exit status d6de073b Show run time of unit tests 5b655541 Add short configure option for ultra-strict flags 4687ba6d Use gtest-like test output 258903d9 Fix failure count in test group summaries da07e738 Fix verbose tests with Python 3 git-subtree-dir: waflib git-subtree-split: 5ea8f99f6e1246079c1fe6bb590c38a53aadd40d --- src/gui/GraphCanvas.cpp | 899 ------------------------------------------------ 1 file changed, 899 deletions(-) delete mode 100644 src/gui/GraphCanvas.cpp (limited to 'src/gui/GraphCanvas.cpp') diff --git a/src/gui/GraphCanvas.cpp b/src/gui/GraphCanvas.cpp deleted file mode 100644 index 0ae4d709..00000000 --- a/src/gui/GraphCanvas.cpp +++ /dev/null @@ -1,899 +0,0 @@ -/* - This file is part of Ingen. - Copyright 2007-2016 David Robillard - - 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 . -*/ - -#include -#include -#include -#include -#include - -#include -#include - -#include "ganv/Canvas.hpp" -#include "ganv/Circle.hpp" -#include "ingen/ClashAvoider.hpp" -#include "ingen/Configuration.hpp" -#include "ingen/Interface.hpp" -#include "ingen/Log.hpp" -#include "ingen/Serialiser.hpp" -#include "ingen/World.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/ClientStore.hpp" -#include "ingen/client/GraphModel.hpp" -#include "ingen/client/PluginModel.hpp" -#include "ingen/ingen.h" -#include "lv2/lv2plug.in/ns/ext/atom/atom.h" - -#include "App.hpp" -#include "Arc.hpp" -#include "GraphCanvas.hpp" -#include "GraphPortModule.hpp" -#include "GraphWindow.hpp" -#include "LoadPluginWindow.hpp" -#include "NewSubgraphWindow.hpp" -#include "NodeModule.hpp" -#include "PluginMenu.hpp" -#include "Port.hpp" -#include "SubgraphModule.hpp" -#include "ThreadedLoader.hpp" -#include "WidgetFactory.hpp" -#include "WindowFactory.hpp" - -using std::string; - -namespace Ingen { - -using namespace Client; - -namespace GUI { - -static int -port_order(const GanvPort* a, const GanvPort* b, void* data) -{ - const Port* pa = dynamic_cast(Glib::wrap(a)); - const Port* pb = dynamic_cast(Glib::wrap(b)); - if (pa && pb) { - return ((int)pa->model()->index() - (int)pb->model()->index()); - } - return 0; -} - -GraphCanvas::GraphCanvas(App& app, - SPtr graph, - int width, - int height) - : Canvas(width, height) - , _app(app) - , _graph(std::move(graph)) - , _auto_position_count(0) - , _menu_x(0) - , _menu_y(0) - , _paste_count(0) - , _menu(nullptr) - , _internal_menu(nullptr) - , _plugin_menu(nullptr) - , _human_names(true) - , _show_port_names(true) - , _menu_dirty(false) -{ - Glib::RefPtr xml = WidgetFactory::create("canvas_menu"); - xml->get_widget("canvas_menu", _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); - xml->get_widget("canvas_menu_add_cv_output", _menu_add_cv_output); - xml->get_widget("canvas_menu_add_control_input", _menu_add_control_input); - xml->get_widget("canvas_menu_add_control_output", _menu_add_control_output); - xml->get_widget("canvas_menu_add_event_input", _menu_add_event_input); - xml->get_widget("canvas_menu_add_event_output", _menu_add_event_output); - xml->get_widget("canvas_menu_load_plugin", _menu_load_plugin); - xml->get_widget("canvas_menu_load_graph", _menu_load_graph); - xml->get_widget("canvas_menu_new_graph", _menu_new_graph); - xml->get_widget("canvas_menu_edit", _menu_edit); - xml->get_widget("canvas_menu_properties", _menu_properties); - - const URIs& uris = _app.uris(); - - // Add port menu items - _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)); - _menu_add_audio_output->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "audio_out", "Audio Out", uris.lv2_AudioPort, true)); - _menu_add_cv_input->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "cv_in", "CV In", uris.lv2_CVPort, false)); - _menu_add_cv_output->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "cv_out", "CV Out", uris.lv2_CVPort, true)); - _menu_add_control_input->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "control_in", "Control In", uris.lv2_ControlPort, false)); - _menu_add_control_output->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "control_out", "Control Out", uris.lv2_ControlPort, true)); - _menu_add_event_input->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "event_in", "Event In", uris.atom_AtomPort, false)); - _menu_add_event_output->signal_activate().connect( - sigc::bind(sigc::mem_fun(this, &GraphCanvas::menu_add_port), - "event_out", "Event Out", uris.atom_AtomPort, true)); - - signal_event.connect( - sigc::mem_fun(this, &GraphCanvas::on_event)); - signal_connect.connect( - sigc::mem_fun(this, &GraphCanvas::connect)); - signal_disconnect.connect( - sigc::mem_fun(this, &GraphCanvas::disconnect)); - - // Connect to model signals to track state - _graph->signal_new_block().connect( - sigc::mem_fun(this, &GraphCanvas::add_block)); - _graph->signal_removed_block().connect( - sigc::mem_fun(this, &GraphCanvas::remove_block)); - _graph->signal_new_port().connect( - sigc::mem_fun(this, &GraphCanvas::add_port)); - _graph->signal_removed_port().connect( - sigc::mem_fun(this, &GraphCanvas::remove_port)); - _graph->signal_new_arc().connect( - sigc::mem_fun(this, &GraphCanvas::connection)); - _graph->signal_removed_arc().connect( - sigc::mem_fun(this, &GraphCanvas::disconnection)); - - _app.store()->signal_new_plugin().connect( - sigc::mem_fun(this, &GraphCanvas::add_plugin)); - _app.store()->signal_plugin_deleted().connect( - sigc::mem_fun(this, &GraphCanvas::remove_plugin)); - - // Connect widget signals to do things - _menu_load_plugin->signal_activate().connect( - sigc::mem_fun(this, &GraphCanvas::menu_load_plugin)); - _menu_load_graph->signal_activate().connect( - sigc::mem_fun(this, &GraphCanvas::menu_load_graph)); - _menu_new_graph->signal_activate().connect( - sigc::mem_fun(this, &GraphCanvas::menu_new_graph)); - _menu_properties->signal_activate().connect( - sigc::mem_fun(this, &GraphCanvas::menu_properties)); - - show_human_names(app.world()->conf().option("human-names").get()); - show_port_names(app.world()->conf().option("port-labels").get()); - set_port_order(port_order, nullptr); -} - -void -GraphCanvas::show_menu(bool position, unsigned button, uint32_t time) -{ - _app.request_plugins_if_necessary(); - - if (!_internal_menu || _menu_dirty) { - build_menus(); - } - - if (position) { - _menu->popup(sigc::mem_fun(this, &GraphCanvas::auto_menu_position), button, time); - } else { - _menu->popup(button, time); - } -} - -void -GraphCanvas::build_menus() -{ - // Build (or clear existing) internal plugin menu - if (_internal_menu) { - _internal_menu->items().clear(); - } else { - _menu->items().push_back( - Gtk::Menu_Helpers::ImageMenuElem( - "In_ternal", - *(manage(new Gtk::Image(Gtk::Stock::EXECUTE, Gtk::ICON_SIZE_MENU))))); - Gtk::MenuItem* internal_menu_item = &(_menu->items().back()); - _internal_menu = Gtk::manage(new Gtk::Menu()); - internal_menu_item->set_submenu(*_internal_menu); - _menu->reorder_child(*internal_menu_item, 4); - } - - // Build skeleton LV2 plugin class heirarchy for 'Plugin' menu - if (_plugin_menu) { - _plugin_menu->clear(); - } else { - _plugin_menu = Gtk::manage(new PluginMenu(*_app.world())); - _menu->items().push_back( - Gtk::Menu_Helpers::ImageMenuElem( - "_Plugin", - *(manage(new Gtk::Image(Gtk::Stock::EXECUTE, Gtk::ICON_SIZE_MENU))))); - Gtk::MenuItem* plugin_menu_item = &(_menu->items().back()); - plugin_menu_item->set_submenu(*_plugin_menu); - _menu->reorder_child(*plugin_menu_item, 5); - _plugin_menu->signal_load_plugin.connect( - sigc::mem_fun(this, &GraphCanvas::load_plugin)); - } - - // Add known plugins to menu heirarchy - SPtr plugins = _app.store()->plugins(); - for (const auto& p : *plugins.get()) { - add_plugin(p.second); - } - - _menu_dirty = false; -} - -void -GraphCanvas::build() -{ - const Store::const_range kids = _app.store()->children_range(_graph); - - // Create modules for blocks - for (Store::const_iterator i = kids.first; i != kids.second; ++i) { - SPtr block = dynamic_ptr_cast(i->second); - if (block && block->parent() == _graph) { - add_block(block); - } - } - - // Create pseudo modules for ports (ports on this canvas, not on our module) - for (const auto& p : _graph->ports()) { - add_port(p); - } - - // Create arcs - for (const auto& a : _graph->arcs()) { - connection(dynamic_ptr_cast(a.second)); - } -} - -static void -show_module_human_names(GanvNode* node, void* data) -{ - bool b = *(bool*)data; - if (GANV_IS_MODULE(node)) { - Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - NodeModule* nmod = dynamic_cast(module); - if (nmod) { - nmod->show_human_names(b); - } - - GraphPortModule* pmod = dynamic_cast(module); - if (pmod) { - pmod->show_human_names(b); - } - } -} - -void -GraphCanvas::show_human_names(bool b) -{ - _human_names = b; - _app.world()->conf().set("human-names", _app.forge().make(b)); - - for_each_node(show_module_human_names, &b); -} - -static void -ensure_port_labels(GanvNode* node, void* data) -{ - if (GANV_IS_MODULE(node)) { - Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - for (Ganv::Port* p : *module) { - Ingen::GUI::Port* port = dynamic_cast(p); - if (port) { - port->ensure_label(); - } - } - } -} - -void -GraphCanvas::show_port_names(bool b) -{ - ganv_canvas_set_direction(gobj(), b ? GANV_DIRECTION_RIGHT : GANV_DIRECTION_DOWN); - for_each_node(ensure_port_labels, &b); -} - -void -GraphCanvas::add_plugin(SPtr p) -{ - if (_internal_menu && _app.uris().ingen_Internal == p->type()) { - _internal_menu->items().push_back( - Gtk::Menu_Helpers::MenuElem( - std::string("_") + p->human_name(), - sigc::bind(sigc::mem_fun(this, &GraphCanvas::load_plugin), p))); - } else if (_plugin_menu) { - _plugin_menu->add_plugin(p); - } -} - -void -GraphCanvas::remove_plugin(const URI& uri) -{ - // Flag menus as dirty so they will be rebuilt when needed next - _menu_dirty = true; -} - -void -GraphCanvas::add_block(SPtr bm) -{ - SPtr pm = dynamic_ptr_cast(bm); - NodeModule* module; - if (pm) { - module = SubgraphModule::create(*this, pm, _human_names); - } else { - module = NodeModule::create(*this, bm, _human_names); - } - - module->show(); - _views.emplace(bm, module); - if (_pastees.find(bm->path()) != _pastees.end()) { - module->set_selected(true); - } -} - -void -GraphCanvas::remove_block(SPtr bm) -{ - auto i = _views.find(bm); - - if (i != _views.end()) { - const guint n_ports = i->second->num_ports(); - for (gint p = n_ports - 1; p >= 0; --p) { - delete i->second->get_port(p); - } - delete i->second; - _views.erase(i); - } -} - -void -GraphCanvas::add_port(SPtr pm) -{ - GraphPortModule* view = GraphPortModule::create(*this, pm); - _views.emplace(pm, view); - view->show(); -} - -void -GraphCanvas::remove_port(SPtr pm) -{ - auto i = _views.find(pm); - - // Port on this graph - if (i != _views.end()) { - delete i->second; - _views.erase(i); - - } else { - NodeModule* module = dynamic_cast(_views[pm->parent()]); - module->delete_port_view(pm); - } - - assert(_views.find(pm) == _views.end()); -} - -Ganv::Port* -GraphCanvas::get_port_view(SPtr port) -{ - Ganv::Module* module = _views[port]; - - // Port on this graph - if (module) { - GraphPortModule* ppm = dynamic_cast(module); - return ppm - ? *ppm->begin() - : dynamic_cast(module); - } else { - module = dynamic_cast(_views[port->parent()]); - if (module) { - for (const auto& p : *module) { - GUI::Port* pv = dynamic_cast(p); - if (pv && pv->model() == port) { - return pv; - } - } - } - } - - return nullptr; -} - -/** Called when a connection is added to the model. */ -void -GraphCanvas::connection(SPtr arc) -{ - Ganv::Port* const tail = get_port_view(arc->tail()); - Ganv::Port* const head = get_port_view(arc->head()); - - if (tail && head) { - new GUI::Arc(*this, arc, tail, head); - } else { - _app.log().error(fmt("Unable to find ports to connect %1% => %2%\n") - % arc->tail_path() % arc->head_path()); - } -} - -/** Called when a connection is removed from the model. */ -void -GraphCanvas::disconnection(SPtr arc) -{ - Ganv::Port* const tail = get_port_view(arc->tail()); - Ganv::Port* const head = get_port_view(arc->head()); - - if (tail && head) { - remove_edge_between(tail, head); - if (arc->head()->is_a(_app.uris().lv2_AudioPort)) { - GUI::Port* const h = dynamic_cast(head); - if (h) { - h->activity(_app.forge().make(0.0f)); // Reset peaks - } - } - } else { - _app.log().error(fmt("Unable to find ports to disconnect %1% => %2%\n") - % arc->tail_path() % arc->head_path()); - } -} - -/** Called when the user connects ports on the canvas. */ -void -GraphCanvas::connect(Ganv::Node* tail, Ganv::Node* head) -{ - const GUI::Port* const t = dynamic_cast(tail); - const GUI::Port* const h = dynamic_cast(head); - - if (t && h) { - _app.interface()->connect(t->model()->path(), h->model()->path()); - } -} - -/** Called when the user disconnects ports on the canvas. */ -void -GraphCanvas::disconnect(Ganv::Node* tail, Ganv::Node* head) -{ - const GUI::Port* const t = dynamic_cast(tail); - const GUI::Port* const h = dynamic_cast(head); - - if (t && h) { - _app.interface()->disconnect(t->model()->path(), h->model()->path()); - } -} - -void -GraphCanvas::auto_menu_position(int& x, int& y, bool& push_in) -{ - std::pair scroll_offsets; - get_scroll_offsets(scroll_offsets.first, scroll_offsets.second); - - if (_auto_position_count > 1 && scroll_offsets != _auto_position_scroll_offsets) { - // Scroll changed since last auto position, reset - _menu_x = 0; - _menu_y = 0; - _auto_position_count = 0; - } - - if (_menu_x == 0 && _menu_y == 0) { - // No menu position set, start near top left of canvas - widget().translate_coordinates( - *_app.window_factory()->graph_window(_graph), - 64, 64, _menu_x, _menu_y); - - int origin_x; - int origin_y; - widget().get_window()->get_origin(origin_x, origin_y); - _menu_x += origin_x; - _menu_y += origin_y; - } - - const int cascade = _auto_position_count * 32; - - x = _menu_x + cascade; - y = _menu_y + cascade; - push_in = true; - - ++_auto_position_count; - _auto_position_scroll_offsets = scroll_offsets; -} - -bool -GraphCanvas::on_event(GdkEvent* event) -{ - assert(event); - - bool ret = false; - - switch (event->type) { - case GDK_BUTTON_PRESS: - if (event->button.button == 3) { - _auto_position_count = 1; - _menu_x = (int)event->button.x_root; - _menu_y = (int)event->button.y_root; - show_menu(false, event->button.button, event->button.time); - ret = true; - } - break; - - case GDK_KEY_PRESS: - switch (event->key.keyval) { - case GDK_Delete: - destroy_selection(); - ret = true; - break; - case GDK_Home: - scroll_to(0, 0); - break; - case GDK_space: - case GDK_Menu: - show_menu(true, 3, event->key.time); - default: break; - } - break; - - case GDK_MOTION_NOTIFY: - _paste_count = 0; - break; - - default: break; - } - - return ret; -} - -void -GraphCanvas::clear_selection() -{ - GraphWindow* win = _app.window_factory()->graph_window(_graph); - if (win) { - win->set_documentation("", false); - } - - Ganv::Canvas::clear_selection(); -} - -static void -destroy_node(GanvNode* node, void* data) -{ - if (!GANV_IS_MODULE(node)) { - return; - } - - App* app = (App*)data; - Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - NodeModule* node_module = dynamic_cast(module); - - if (node_module) { - app->interface()->del(node_module->block()->uri()); - } else { - GraphPortModule* port_module = dynamic_cast(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()); - } - } -} - -static void -destroy_arc(GanvEdge* arc, void* data) -{ - App* app = (App*)data; - Ganv::Edge* arcmm = Glib::wrap(arc); - - Port* tail = dynamic_cast(arcmm->get_tail()); - Port* head = dynamic_cast(arcmm->get_head()); - app->interface()->disconnect(tail->model()->path(), head->model()->path()); -} - -void -GraphCanvas::destroy_selection() -{ - _app.interface()->bundle_begin(); - for_each_selected_edge(destroy_arc, &_app); - for_each_selected_node(destroy_node, &_app); - _app.interface()->bundle_end(); -} - -static void -serialise_node(GanvNode* node, void* data) -{ - Serialiser* serialiser = (Serialiser*)data; - if (!GANV_IS_MODULE(node)) { - return; - } - - Ganv::Module* module = Glib::wrap(GANV_MODULE(node)); - NodeModule* node_module = dynamic_cast(module); - - if (node_module) { - serialiser->serialise(node_module->block()); - } else { - GraphPortModule* port_module = dynamic_cast(module); - if (port_module) { - serialiser->serialise(port_module->port()); - } - } -} - -static void -serialise_arc(GanvEdge* arc, void* data) -{ - Serialiser* serialiser = (Serialiser*)data; - if (!GANV_IS_EDGE(arc)) { - return; - } - - GUI::Arc* garc = dynamic_cast(Glib::wrap(GANV_EDGE(arc))); - if (garc) { - serialiser->serialise_arc(Sord::Node(), garc->model()); - } -} - -void -GraphCanvas::copy_selection() -{ - std::lock_guard lock(_app.world()->rdf_mutex()); - - Serialiser serialiser(*_app.world()); - serialiser.start_to_string(_graph->path(), _graph->base_uri()); - - for_each_selected_node(serialise_node, &serialiser); - for_each_selected_edge(serialise_arc, &serialiser); - - Glib::RefPtr clipboard = Gtk::Clipboard::get(); - clipboard->set_text(serialiser.finish()); - _paste_count = 0; -} - -void -GraphCanvas::paste() -{ - typedef Properties::const_iterator PropIter; - - std::lock_guard lock(_app.world()->rdf_mutex()); - - const Glib::ustring str = Gtk::Clipboard::get()->wait_for_text(); - SPtr parser = _app.loader()->parser(); - const URIs& uris = _app.uris(); - const Raul::Path& parent = _graph->path(); - if (!parser) { - _app.log().error("Unable to load parser, paste unavailable\n"); - return; - } - - // Prepare for paste - clear_selection(); - _pastees.clear(); - ++_paste_count; - - // Make a client store to serve as clipboard - ClientStore clipboard(_app.world()->uris(), _app.log()); - clipboard.set_plugins(_app.store()->plugins()); - clipboard.put(main_uri(), - {{uris.rdf_type, Property(uris.ingen_Graph)}}); - - // Parse clipboard text into clipboard store - boost::optional base_uri = parser->parse_string( - _app.world(), &clipboard, str, main_uri()); - - // Figure out the copy graph base path - Raul::Path copy_root("/"); - if (base_uri) { - std::string base = *base_uri; - if (base[base.size() - 1] == '/') { - base = base.substr(0, base.size() - 1); - } - copy_root = uri_to_path(URI(base)); - } - - // Find the minimum x and y coordinate of objects to be pasted - float min_x = std::numeric_limits::max(); - float min_y = std::numeric_limits::max(); - for (const auto& c : clipboard) { - if (c.first.parent() == Raul::Path("/")) { - const Atom& x = c.second->get_property(uris.ingen_canvasX); - const Atom& y = c.second->get_property(uris.ingen_canvasY); - if (x.type() == uris.atom_Float) { - min_x = std::min(min_x, x.get()); - } - if (y.type() == uris.atom_Float) { - min_y = std::min(min_y, y.get()); - } - } - } - - // Find canvas paste origin based on pointer position - int widget_point_x, widget_point_y, scroll_x, scroll_y; - widget().get_pointer(widget_point_x, widget_point_y); - get_scroll_offsets(scroll_x, scroll_y); - const int paste_x = widget_point_x + scroll_x + (20.0f * _paste_count); - const int paste_y = widget_point_y + scroll_y + (20.0f * _paste_count); - - _app.interface()->bundle_begin(); - - // Put each top level object in the clipboard store - ClashAvoider avoider(*_app.store().get()); - for (const auto& c : clipboard) { - if (c.first.is_root() || c.first.parent() != Raul::Path("/")) { - continue; - } - - const SPtr node = c.second; - const Raul::Path& old_path = copy_root.child(node->path()); - const URI& old_uri = path_to_uri(old_path); - const Raul::Path& new_path = avoider.map_path(parent.child(node->path())); - - Properties props{{uris.lv2_prototype, - _app.forge().make_urid(old_uri)}}; - - // Set the same types - const auto t = node->properties().equal_range(uris.rdf_type); - props.insert(t.first, t.second); - - // Set coordinates so paste origin is at the mouse pointer - PropIter xi = node->properties().find(uris.ingen_canvasX); - PropIter yi = node->properties().find(uris.ingen_canvasY); - if (xi != node->properties().end()) { - const float x = xi->second.get() - min_x + paste_x; - props.insert({xi->first, Property(_app.forge().make(x), - xi->second.context())}); - } - if (yi != node->properties().end()) { - const float y = yi->second.get() - min_y + paste_y; - props.insert({yi->first, Property(_app.forge().make(y), - yi->second.context())}); - } - - _app.interface()->put(path_to_uri(new_path), props); - _pastees.insert(new_path); - } - - // Connect objects - for (auto a : clipboard.object(Raul::Path("/"))->arcs()) { - _app.interface()->connect( - avoider.map_path(parent.child(a.second->tail_path())), - avoider.map_path(parent.child(a.second->head_path()))); - } - - _app.interface()->bundle_end(); -} - -void -GraphCanvas::generate_port_name( - const string& sym_base, string& symbol, - const string& name_base, string& name) -{ - symbol = sym_base; - name = name_base; - - char num_buf[5]; - uint32_t i = 1; - for ( ; i < 9999; ++i) { - snprintf(num_buf, sizeof(num_buf), "%u", i); - symbol = sym_base + "_"; - symbol += num_buf; - if (!_graph->get_port(Raul::Symbol::symbolify(symbol))) { - break; - } - } - - assert(Raul::Path::is_valid(string("/") + symbol)); - - name.append(" ").append(num_buf); -} - -void -GraphCanvas::menu_add_port(const string& sym_base, - const string& name_base, - const 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(); - - Properties props = get_initial_data(Resource::Graph::INTERNAL); - props.emplace(uris.rdf_type, _app.forge().make_urid(type)); - if (type == uris.atom_AtomPort) { - props.emplace(uris.atom_bufferType, Property(uris.atom_Sequence)); - } - props.emplace( - uris.rdf_type, - Property(is_output ? uris.lv2_OutputPort : uris.lv2_InputPort)); - props.emplace(uris.lv2_index, - _app.forge().make(int32_t(_graph->num_ports()))); - props.emplace(uris.lv2_name, _app.forge().alloc(name.c_str())); - _app.interface()->put(path_to_uri(path), props); -} - -void -GraphCanvas::load_plugin(WPtr weak_plugin) -{ - SPtr plugin = weak_plugin.lock(); - if (!plugin) { - return; - } - - Raul::Symbol symbol = plugin->default_block_symbol(); - unsigned offset = _app.store()->child_name_offset(_graph->path(), symbol); - if (offset != 0) { - std::stringstream ss; - ss << symbol << "_" << offset; - symbol = Raul::Symbol(ss.str()); - } - - const URIs& uris = _app.uris(); - const Raul::Path path = _graph->path().child(symbol); - - // FIXME: polyphony? - Properties props = get_initial_data(); - props.emplace(uris.rdf_type, Property(uris.ingen_Block)); - props.emplace(uris.lv2_prototype, uris.forge.make_urid(plugin->uri())); - _app.interface()->put(path_to_uri(path), props); -} - -/** Try to guess a suitable location for a new module. - */ -void -GraphCanvas::get_new_module_location(double& x, double& y) -{ - int scroll_x; - int scroll_y; - get_scroll_offsets(scroll_x, scroll_y); - x = scroll_x + 20; - y = scroll_y + 20; -} - -Properties -GraphCanvas::get_initial_data(Resource::Graph ctx) -{ - Properties result; - const URIs& uris = _app.uris(); - result.emplace(uris.ingen_canvasX, - Property(_app.forge().make((float)_menu_x), ctx)); - result.emplace(uris.ingen_canvasY, - Property(_app.forge().make((float)_menu_y), ctx)); - return result; -} - -void -GraphCanvas::menu_load_plugin() -{ - _app.window_factory()->present_load_plugin(_graph, get_initial_data()); -} - -void -GraphCanvas::menu_load_graph() -{ - _app.window_factory()->present_load_subgraph( - _graph, get_initial_data(Resource::Graph::EXTERNAL)); -} - -void -GraphCanvas::menu_new_graph() -{ - _app.window_factory()->present_new_subgraph( - _graph, get_initial_data(Resource::Graph::EXTERNAL)); -} - -void -GraphCanvas::menu_properties() -{ - _app.window_factory()->present_properties(_graph); -} - -} // namespace GUI -} // namespace Ingen -- cgit v1.2.1