summaryrefslogtreecommitdiffstats
path: root/src/progs/ingenuity/PatchCanvas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/progs/ingenuity/PatchCanvas.cpp')
-rw-r--r--src/progs/ingenuity/PatchCanvas.cpp523
1 files changed, 0 insertions, 523 deletions
diff --git a/src/progs/ingenuity/PatchCanvas.cpp b/src/progs/ingenuity/PatchCanvas.cpp
deleted file mode 100644
index e6397a3d..00000000
--- a/src/progs/ingenuity/PatchCanvas.cpp
+++ /dev/null
@@ -1,523 +0,0 @@
-/* This file is part of Ingen.
- * Copyright (C) 2007 Dave 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 <cassert>
-#include <flowcanvas/FlowCanvas.h>
-#include "interface/EngineInterface.h"
-#include "client/PluginModel.h"
-#include "client/PatchModel.h"
-#include "client/NodeModel.h"
-#include "client/Store.h"
-#include "client/Serializer.h"
-#include "App.h"
-#include "PatchCanvas.h"
-#include "PatchWindow.h"
-#include "PatchPortModule.h"
-#include "LoadPluginWindow.h"
-#include "LoadSubpatchWindow.h"
-#include "NewSubpatchWindow.h"
-#include "Port.h"
-#include "Connection.h"
-#include "NodeModule.h"
-#include "SubpatchModule.h"
-#include "GladeFactory.h"
-#include "WindowFactory.h"
-#include "config.h"
-using Ingen::Client::Store;
-using Ingen::Client::Serializer;
-using Ingen::Client::PluginModel;
-
-namespace Ingenuity {
-
-
-PatchCanvas::PatchCanvas(SharedPtr<PatchModel> patch, int width, int height)
-: FlowCanvas(width, height),
- _patch(patch),
- _last_click_x(0),
- _last_click_y(0)
-{
- Glib::RefPtr<Gnome::Glade::Xml> xml = GladeFactory::new_glade_reference();
- 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_control_input", _menu_add_control_input);
- xml->get_widget("canvas_menu_add_control_output", _menu_add_control_output);
- xml->get_widget("canvas_menu_add_midi_input", _menu_add_midi_input);
- xml->get_widget("canvas_menu_add_midi_output", _menu_add_midi_output);
- xml->get_widget("canvas_menu_load_plugin", _menu_load_plugin);
- xml->get_widget("canvas_menu_load_patch", _menu_load_patch);
- xml->get_widget("canvas_menu_new_patch", _menu_new_patch);
-
- // Add port menu items
- _menu_add_audio_input->signal_activate().connect(
- sigc::bind(sigc::mem_fun(this, &PatchCanvas::menu_add_port),
- "audio_input", "ingen:audio", false));
- _menu_add_audio_output->signal_activate().connect(
- sigc::bind(sigc::mem_fun(this, &PatchCanvas::menu_add_port),
- "audio_output", "ingen:audio", true));
- _menu_add_control_input->signal_activate().connect(
- sigc::bind(sigc::mem_fun(this, &PatchCanvas::menu_add_port),
- "control_input", "ingen:control", false));
- _menu_add_control_output->signal_activate().connect(
- sigc::bind(sigc::mem_fun(this, &PatchCanvas::menu_add_port),
- "control_output", "ingen:control", true));
- _menu_add_midi_input->signal_activate().connect(
- sigc::bind(sigc::mem_fun(this, &PatchCanvas::menu_add_port),
- "midi_input", "ingen:midi", false));
- _menu_add_midi_output->signal_activate().connect(
- sigc::bind(sigc::mem_fun(this, &PatchCanvas::menu_add_port),
- "midi_output", "ingen:midi", true));
-
- build_plugin_menu();
-
- // Connect to model signals to track state
- _patch->new_node_sig.connect(sigc::mem_fun(this, &PatchCanvas::add_node));
- _patch->removed_node_sig.connect(sigc::mem_fun(this, &PatchCanvas::remove_node));
- _patch->new_port_sig.connect(sigc::mem_fun(this, &PatchCanvas::add_port));
- _patch->removed_port_sig.connect(sigc::mem_fun(this, &PatchCanvas::remove_port));
- _patch->new_connection_sig.connect(sigc::mem_fun(this, &PatchCanvas::connection));
- _patch->removed_connection_sig.connect(sigc::mem_fun(this, &PatchCanvas::disconnection));
-
- // Connect widget signals to do things
- _menu_load_plugin->signal_activate().connect(sigc::mem_fun(this, &PatchCanvas::menu_load_plugin));
- _menu_load_patch->signal_activate().connect(sigc::mem_fun(this, &PatchCanvas::menu_load_patch));
- _menu_new_patch->signal_activate().connect(sigc::mem_fun(this, &PatchCanvas::menu_new_patch));
-}
-
-
-void
-PatchCanvas::build_plugin_class_menu(Gtk::Menu* menu,
- SLV2PluginClass plugin_class, SLV2PluginClasses classes)
-{
-#ifdef HAVE_SLV2
- // Add submenus
- for (unsigned i=0; i < slv2_plugin_classes_size(classes); ++i) {
- SLV2PluginClass c = slv2_plugin_classes_get_at(classes, i);
- const char* parent = slv2_plugin_class_get_parent_uri(c);
-
- if (parent && !strcmp(parent, slv2_plugin_class_get_uri(plugin_class))) {
- menu->items().push_back(Gtk::Menu_Helpers::MenuElem(
- slv2_plugin_class_get_label(c)));
- Gtk::MenuItem* menu_item = &(menu->items().back());
- Gtk::Menu* submenu = Gtk::manage(new Gtk::Menu());
- menu_item->set_submenu(*submenu);
- build_plugin_class_menu(submenu, c, classes);
- }
- }
-
-
- const Store::Plugins& plugins = App::instance().store()->plugins();
-
- // Add plugins
- for (Store::Plugins::const_iterator i = plugins.begin(); i != plugins.end(); ++i) {
- SLV2Plugin p = i->second->slv2_plugin();
- if (p && slv2_plugin_get_class(p) == plugin_class)
- menu->items().push_back(Gtk::Menu_Helpers::MenuElem(i->second->name(),
- sigc::bind(sigc::mem_fun(this, &PatchCanvas::load_plugin),
- i->second)));
- }
-
-
-#endif
-}
-
-
-void
-PatchCanvas::build_plugin_menu()
-{
-#ifdef HAVE_SLV2
- _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());
- Gtk::Menu* plugin_menu = Gtk::manage(new Gtk::Menu());
- plugin_menu_item->set_submenu(*plugin_menu);
- _menu->reorder_child(*plugin_menu_item, 2);
-
- SLV2PluginClass lv2_plugin = slv2_world_get_plugin_class(PluginModel::slv2_world());
- SLV2PluginClasses classes = slv2_world_get_plugin_classes(PluginModel::slv2_world());
-
- build_plugin_class_menu(plugin_menu, lv2_plugin, classes);
-#endif
-}
-
-
-void
-PatchCanvas::build()
-{
- boost::shared_ptr<PatchCanvas> shared_this =
- boost::dynamic_pointer_cast<PatchCanvas>(shared_from_this());
-
- // Create modules for nodes
- for (NodeModelMap::const_iterator i = _patch->nodes().begin();
- i != _patch->nodes().end(); ++i) {
- add_node((*i).second);
- }
-
- // Create pseudo modules for ports (ports on this canvas, not on our module)
- for (PortModelList::const_iterator i = _patch->ports().begin();
- i != _patch->ports().end(); ++i) {
- add_port(*i);
- }
-
- // Create connections
- for (list<SharedPtr<ConnectionModel> >::const_iterator i = _patch->connections().begin();
- i != _patch->connections().end(); ++i) {
- connection(*i);
- }
-}
-
-
-void
-PatchCanvas::arrange()
-{
- LibFlowCanvas::FlowCanvas::arrange();
-
- for (list<boost::shared_ptr<Item> >::iterator i = _items.begin(); i != _items.end(); ++i)
- (*i)->store_location();
-}
-
-
-void
-PatchCanvas::add_node(SharedPtr<NodeModel> nm)
-{
- boost::shared_ptr<PatchCanvas> shared_this =
- boost::dynamic_pointer_cast<PatchCanvas>(shared_from_this());
-
- SharedPtr<PatchModel> pm = PtrCast<PatchModel>(nm);
- SharedPtr<NodeModule> module;
- if (pm)
- module = SubpatchModule::create(shared_this, pm);
- else
- module = NodeModule::create(shared_this, nm);
-
- add_item(module);
- module->show();
- _views.insert(std::make_pair(nm, module));
-}
-
-
-void
-PatchCanvas::remove_node(SharedPtr<NodeModel> nm)
-{
- Views::iterator i = _views.find(nm);
-
- if (i != _views.end()) {
- remove_item(i->second);
- _views.erase(i);
- }
-}
-
-
-void
-PatchCanvas::add_port(SharedPtr<PortModel> pm)
-{
- boost::shared_ptr<PatchCanvas> shared_this =
- boost::dynamic_pointer_cast<PatchCanvas>(shared_from_this());
-
- SharedPtr<PatchPortModule> view = PatchPortModule::create(shared_this, pm);
- _views.insert(std::make_pair(pm, view));
- add_item(view);
- view->show();
-}
-
-
-void
-PatchCanvas::remove_port(SharedPtr<PortModel> pm)
-{
- Views::iterator i = _views.find(pm);
-
- if (i != _views.end()) {
- remove_item(i->second);
- _views.erase(i);
- }
-}
-
-
-SharedPtr<LibFlowCanvas::Port>
-PatchCanvas::get_port_view(SharedPtr<PortModel> port)
-{
- SharedPtr<LibFlowCanvas::Port> ret;
- SharedPtr<LibFlowCanvas::Module> module = _views[port];
-
- // Port on this patch
- if (module) {
- ret = (PtrCast<PatchPortModule>(module))
- ? *(PtrCast<PatchPortModule>(module)->ports().begin())
- : PtrCast<LibFlowCanvas::Port>(module);
- } else {
- module = PtrCast<NodeModule>(_views[port->parent()]);
- if (module)
- ret = module->get_port(port->path().name());
- }
-
- return ret;
-}
-
-
-void
-PatchCanvas::connection(SharedPtr<ConnectionModel> cm)
-{
- const SharedPtr<LibFlowCanvas::Port> src = get_port_view(cm->src_port());
- const SharedPtr<LibFlowCanvas::Port> dst = get_port_view(cm->dst_port());
-
- if (src && dst)
- add_connection(boost::shared_ptr<Connection>(new Connection(shared_from_this(),
- cm, src, dst, src->color() + 0x22222200)));
- else
- cerr << "[PatchCanvas] ERROR: Unable to find ports to connect "
- << cm->src_port_path() << " -> " << cm->dst_port_path() << endl;
-}
-
-
-void
-PatchCanvas::disconnection(SharedPtr<ConnectionModel> cm)
-{
- const SharedPtr<LibFlowCanvas::Port> src = get_port_view(cm->src_port());
- const SharedPtr<LibFlowCanvas::Port> dst = get_port_view(cm->dst_port());
-
- if (src && dst)
- remove_connection(src, dst);
- else
- cerr << "[PatchCanvas] ERROR: Unable to find ports to disconnect "
- << cm->src_port_path() << " -> " << cm->dst_port_path() << endl;
-}
-
-
-void
-PatchCanvas::connect(boost::shared_ptr<LibFlowCanvas::Connectable> src_port,
- boost::shared_ptr<LibFlowCanvas::Connectable> dst_port)
-{
- const boost::shared_ptr<Ingenuity::Port> src
- = boost::dynamic_pointer_cast<Ingenuity::Port>(src_port);
-
- const boost::shared_ptr<Ingenuity::Port> dst
- = boost::dynamic_pointer_cast<Ingenuity::Port>(dst_port);
-
- if (!src || !dst)
- return;
-
- // Midi binding/learn shortcut
- if (src->model()->is_midi() && dst->model()->is_control())
- {
- cerr << "FIXME: MIDI binding" << endl;
-#if 0
- SharedPtr<PluginModel> pm(new PluginModel(PluginModel::Internal, "", "midi_control_in", ""));
- SharedPtr<NodeModel> nm(new NodeModel(pm, _patch->path().base()
- + src->name() + "-" + dst->name(), false));
- nm->set_metadata("canvas-x", Atom((float)
- (dst->module()->property_x() - dst->module()->width() - 20)));
- nm->set_metadata("canvas-y", Atom((float)
- (dst->module()->property_y())));
- App::instance().engine()->create_node_from_model(nm.get());
- App::instance().engine()->connect(src->model()->path(), nm->path() + "/MIDI_In");
- App::instance().engine()->connect(nm->path() + "/Out_(CR)", dst->model()->path());
- App::instance().engine()->midi_learn(nm->path());
-
- // Set control node range to port's user range
-
- App::instance().engine()->set_port_value_queued(nm->path().base() + "Min",
- dst->model()->get_metadata("user-min").get_float());
- App::instance().engine()->set_port_value_queued(nm->path().base() + "Max",
- dst->model()->get_metadata("user-max").get_float());
-#endif
- } else {
- App::instance().engine()->connect(src->model()->path(), dst->model()->path());
- }
-}
-
-
-void
-PatchCanvas::disconnect(boost::shared_ptr<LibFlowCanvas::Connectable> src_port,
- boost::shared_ptr<LibFlowCanvas::Connectable> dst_port)
-{
- const boost::shared_ptr<Ingenuity::Port> src
- = boost::dynamic_pointer_cast<Ingenuity::Port>(src_port);
-
- const boost::shared_ptr<Ingenuity::Port> dst
- = boost::dynamic_pointer_cast<Ingenuity::Port>(dst_port);
-
- App::instance().engine()->disconnect(src->model()->path(),
- dst->model()->path());
-}
-
-
-bool
-PatchCanvas::canvas_event(GdkEvent* event)
-{
- assert(event);
-
- switch (event->type) {
-
- case GDK_BUTTON_PRESS:
- if (event->button.button == 3) {
- _last_click_x = (int)event->button.x;
- _last_click_y = (int)event->button.y;
- show_menu(event);
- }
- break;
-
- /*case GDK_KEY_PRESS:
- if (event->key.keyval == GDK_Delete)
- destroy_selected();
- break;
- */
-
- default:
- break;
- }
-
- return FlowCanvas::canvas_event(event);
-}
-
-
-void
-PatchCanvas::destroy_selection()
-{
- for (list<boost::shared_ptr<Item> >::iterator m = _selected_items.begin(); m != _selected_items.end(); ++m) {
- boost::shared_ptr<NodeModule> module = boost::dynamic_pointer_cast<NodeModule>(*m);
- if (module) {
- App::instance().engine()->destroy(module->node()->path());
- } else {
- boost::shared_ptr<PatchPortModule> port_module = boost::dynamic_pointer_cast<PatchPortModule>(*m);
- if (port_module)
- App::instance().engine()->destroy(port_module->port()->path());
- }
- }
-
-}
-
-
-void
-PatchCanvas::copy_selection()
-{
- Serializer serializer(*App::instance().rdf_world());
- serializer.start_to_string();
-
- for (list<boost::shared_ptr<Item> >::iterator m = _selected_items.begin(); m != _selected_items.end(); ++m) {
- boost::shared_ptr<NodeModule> module = boost::dynamic_pointer_cast<NodeModule>(*m);
- if (module) {
- serializer.serialize(module->node());
- } else {
- boost::shared_ptr<PatchPortModule> port_module = boost::dynamic_pointer_cast<PatchPortModule>(*m);
- if (port_module)
- serializer.serialize(port_module->port());
- }
- }
-
- for (list<boost::shared_ptr<LibFlowCanvas::Connection> >::iterator c = _selected_connections.begin();
- c != _selected_connections.end(); ++c) {
- boost::shared_ptr<Connection> connection = boost::dynamic_pointer_cast<Connection>(*c);
- if (connection)
- serializer.serialize_connection(connection->model());
- }
-
- string result = serializer.finish();
-
- Glib::RefPtr<Gtk::Clipboard> clipboard = Gtk::Clipboard::get();
- clipboard->set_text(result);
-}
-
-
-string
-PatchCanvas::generate_port_name(const string& base) {
- string name = base;
-
- char num_buf[5];
- for (uint i=1; i < 9999; ++i) {
- snprintf(num_buf, 5, "%u", i);
- name = base + "_";
- name += num_buf;
- if (!_patch->get_port(name))
- break;
- }
-
- assert(Path::is_valid(string("/") + name));
-
- return name;
-}
-
-
-void
-PatchCanvas::menu_add_port(const string& name, const string& type, bool is_output)
-{
- const Path& path = _patch->path().base() + generate_port_name(name);
- App::instance().engine()->create_port(path, type, is_output);
- MetadataMap data = get_initial_data();
- for (MetadataMap::const_iterator i = data.begin(); i != data.end(); ++i)
- App::instance().engine()->set_metadata(path, i->first, i->second);
-}
-
-
-void
-PatchCanvas::load_plugin(SharedPtr<PluginModel> plugin)
-{
- const Path& path = _patch->path().base() + plugin->default_node_name(_patch);
- // FIXME: polyphony?
- App::instance().engine()->create_node(plugin->uri(), path, false);
- MetadataMap data = get_initial_data();
- for (MetadataMap::const_iterator i = data.begin(); i != data.end(); ++i)
- App::instance().engine()->set_metadata(path, i->first, i->second);
-}
-
-
-/** Try to guess a suitable location for a new module.
- */
-void
-PatchCanvas::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;
-}
-
-
-MetadataMap
-PatchCanvas::get_initial_data()
-{
- MetadataMap result;
-
- result["ingenuity:canvas-x"] = Atom((float)_last_click_x);
- result["ingenuity:canvas-y"] = Atom((float)_last_click_y);
-
- return result;
-}
-
-void
-PatchCanvas::menu_load_plugin()
-{
- App::instance().window_factory()->present_load_plugin(_patch, get_initial_data());
-}
-
-
-void
-PatchCanvas::menu_load_patch()
-{
- App::instance().window_factory()->present_load_subpatch(_patch, get_initial_data());
-}
-
-
-void
-PatchCanvas::menu_new_patch()
-{
- App::instance().window_factory()->present_new_subpatch(_patch, get_initial_data());
-}
-
-
-} // namespace Ingenuity