From fcde25e41ff5484d2c577a22b93634976d7df2f1 Mon Sep 17 00:00:00 2001 From: dave Date: Sat, 17 Jun 2006 23:47:42 +0000 Subject: [PATCH] New patch ports interface git-svn-id: http://svn.drobilla.net/lad@48 a436a847-0d15-0410-975c-d299462d15a1 --- flowcanvas/src/Module.cpp | 18 +++- grauph/src/libs/client/Store.cpp | 33 +++--- grauph/src/libs/engine/ObjectSender.cpp | 71 ++++++------ grauph/src/libs/engine/Patch.cpp | 2 +- grauph/src/progs/gtk/Makefile.am | 4 + grauph/src/progs/gtk/PatchController.cpp | 132 +++++++++++++++-------- grauph/src/progs/gtk/PatchController.h | 2 + grauph/src/progs/gtk/PortController.cpp | 19 ++++ grauph/src/progs/gtk/PortController.h | 12 ++- 9 files changed, 195 insertions(+), 98 deletions(-) diff --git a/flowcanvas/src/Module.cpp b/flowcanvas/src/Module.cpp index 9f23195b..7740b79a 100644 --- a/flowcanvas/src/Module.cpp +++ b/flowcanvas/src/Module.cpp @@ -37,6 +37,9 @@ static const int MODULE_TITLE_COLOUR = 0xFFFFFFFF; * Note you must call resize() at some point or the module will look ridiculous. * This it to avoid unecessary text measuring and resizing, which is insanely * expensive. + * + * If @a name is the empty string, the space where the title would usually be + * is not created (eg the module will be shorter). */ Module::Module(FlowCanvas* canvas, const string& name, double x, double y) : Gnome::Canvas::Group(*canvas->root(), x, y), @@ -406,6 +409,12 @@ Module::resize() double widest_in = 0.0; double widest_out = 0.0; + // The amount of space between a port edge and the module edge (on the + // side that the port isn't right on the edge). + double hor_pad = 5.0; + if (m_name.length() == 0) + hor_pad = 10.0; // leave more room for something to grab for dragging + Port* p = NULL; // Find widest in/out ports @@ -419,16 +428,19 @@ Module::resize() // Make sure module is wide enough for ports if (widest_in > widest_out) - width(widest_in + 5.0 + border_width()*2.0); + width(widest_in + hor_pad + border_width()*2.0); else - width(widest_out + 5.0 + border_width()*2.0); + width(widest_out + hor_pad + border_width()*2.0); // Make sure module is wide enough for title if (m_canvas_title.property_text_width() + 6.0 > m_width) width(m_canvas_title.property_text_width() + 6.0); // Set height to contain ports and title - double height_base = m_canvas_title.property_text_height() + 2; + double height_base = 2; + if (m_name.length() > 0) + height_base += m_canvas_title.property_text_height(); + double h = height_base; if (m_ports.size() > 0) h += m_ports.size() * ((*m_ports.begin())->height()+2.0); diff --git a/grauph/src/libs/client/Store.cpp b/grauph/src/libs/client/Store.cpp index 34b86e2e..542c1bc5 100644 --- a/grauph/src/libs/client/Store.cpp +++ b/grauph/src/libs/client/Store.cpp @@ -209,13 +209,16 @@ Store::new_patch_event(const string& path, uint32_t poly) CountedPtr p(new PatchModel(path, poly)); add_object(p); - CountedPtr parent = object(p->path().parent()); - if (parent) { - p->set_parent(parent); - parent->add_node(p); - assert(p->parent() == parent); - } else { - cerr << "ERROR: new patch with no parent" << endl; + if (path != "/") { + CountedPtr parent = object(p->path().parent()); + if (parent) { + assert(path.substr(0, parent->path().length()) == parent->path()); + p->set_parent(parent); + parent->add_node(p); + assert(p->parent() == parent); + } else { + cerr << "ERROR: new patch with no parent" << endl; + } } } } @@ -283,16 +286,14 @@ Store::new_port_event(const string& path, const string& type, bool is_output) CountedPtr p(new PortModel(path, ptype, pdir)); add_object(p); - std::map >::iterator pi = m_objects.find(p->path().parent()); - if (pi != m_objects.end()) { - CountedPtr parent = (*pi).second; + CountedPtr parent = object(p->path().parent()); + if (parent) { p->set_parent(parent); - if (parent) { - parent->add_port(p); - assert(p->parent() == parent); - } else { - cerr << "ERROR: new port with no parent" << endl; - } + assert(p->parent() == parent); + parent->add_port(p); + assert(p->parent() == parent); + } else { + cerr << "ERROR: new port with no parent" << endl; } } } diff --git a/grauph/src/libs/engine/ObjectSender.cpp b/grauph/src/libs/engine/ObjectSender.cpp index 441cb2d9..b5eb458d 100644 --- a/grauph/src/libs/engine/ObjectSender.cpp +++ b/grauph/src/libs/engine/ObjectSender.cpp @@ -50,16 +50,17 @@ ObjectSender::send_patch(ClientInterface* client, const Patch* patch) for (List::const_iterator j = patch->nodes().begin(); j != patch->nodes().end(); ++j) { - Node* const node = (*j); - Port* const port = node->as_port(); // NULL unless a bridge node + const Node* const node = (*j); + //const Port* const port = node->as_port(); // NULL unless a bridge node + send_node(client, node); usleep(100); // If this is a bridge (input/output) node, send the patch control value as well - if (port && port->port_info()->is_control()) - client->control_change(port->path(), - ((PortBase*)port)->buffer(0)->value_at(0)); + //if (port && port->port_info()->is_control()) + // client->control_change(port->path(), + // ((PortBase*)port)->buffer(0)->value_at(0)); } for (List::const_iterator j = patch->connections().begin(); @@ -67,31 +68,54 @@ ObjectSender::send_patch(ClientInterface* client, const Patch* patch) client->connection((*j)->src_port()->path(), (*j)->dst_port()->path()); // Send port information - /*for (size_t i=0; i < m_ports.size(); ++i) { - Port* const port = m_ports.at(i); + for (size_t i=0; i < patch->ports().size(); ++i) { + Port* const port = patch->ports().at(i); // Send metadata const map& data = port->metadata(); for (map::const_iterator i = data.begin(); i != data.end(); ++i) - om->client_broadcaster()->send_metadata_update_to(client, port->path(), (*i).first, (*i).second); + client->metadata_update(port->path(), (*i).first, (*i).second); if (port->port_info()->is_control()) - om->client_broadcaster()->send_control_change_to(client, port->path(), - ((PortBase*)port)->buffer(0)->value_at(0)); - }*/ + client->control_change(port->path(), ((PortBase*)port)->buffer(0)->value_at(0)); + } + + // Send metadata + const map& data = patch->metadata(); + for (map::const_iterator j = data.begin(); j != data.end(); ++j) + client->metadata_update(patch->path(), (*j).first, (*j).second); + } +/** Sends a node or a patch */ void ObjectSender::send_node(ClientInterface* client, const Node* node) { + // Don't send node notification for bridge nodes, from the client's + // perspective they don't even exist (just the ports they represent) + // FIXME: hack, these nodes probably shouldn't even exist in the + // engine anymore + if (const_cast(node)->as_port()) { // bridge node if as_port() returns non-NULL + send_port(client, const_cast(node)->as_port()); + return; + } + + const Plugin* const plugin = node->plugin(); + int polyphonic = (node->poly() > 1 && node->poly() == node->parent_patch()->internal_poly() ? 1 : 0); assert(node->path().length() > 0); - if (node->plugin()->uri().length() == 0) { + + if (plugin->type() == Plugin::Patch) { + send_patch(client, (Patch*)node); + return; + } + + if (plugin->uri().length() == 0) { cerr << "Node " << node->path() << " plugin has no URI! Not sending." << endl; return; } @@ -102,10 +126,10 @@ ObjectSender::send_node(ClientInterface* client, const Node* node) // FIXME: bundleify const Array& ports = node->ports(); - + client->new_node(node->plugin()->type_string(), node->plugin()->uri(), node->path(), polyphonic, ports.size()); - + // Send ports for (size_t j=0; j < ports.size(); ++j) { Port* const port = ports.at(j); @@ -115,25 +139,6 @@ ObjectSender::send_node(ClientInterface* client, const Node* node) assert(info); client->new_port(port->path(), info->type_string(), info->is_output()); - - /*m = lo_message_new(); - lo_message_add_string(m, port->path().c_str()); - lo_message_add_string(m, info->type_string().c_str()); - lo_message_add_string(m, info->direction_string().c_str()); - lo_message_add_string(m, info->hint_string().c_str()); - lo_message_add_float(m, info->default_val()); - lo_message_add_float(m, info->min_val()); - lo_message_add_float(m, info->max_val()); - lo_bundle_add_message(b, "/om/new_port", m); - msgs.push_back(m);*/ - - // If the bundle is getting very large, send it and start - // a new one - /*if (lo_bundle_length(b) > 1024) { - lo_send_bundle(_address, b); - lo_bundle_free(b); - b = lo_bundle_new(tt); - }*/ } client->bundle_end(); diff --git a/grauph/src/libs/engine/Patch.cpp b/grauph/src/libs/engine/Patch.cpp index be938cae..ce71214e 100644 --- a/grauph/src/libs/engine/Patch.cpp +++ b/grauph/src/libs/engine/Patch.cpp @@ -45,7 +45,7 @@ Patch::Patch(const string& path, size_t poly, Patch* parent, samplerate srate, s assert(internal_poly >= 1); m_plugin.type(Plugin::Patch); - m_plugin.lib_path(""); + m_plugin.uri("http://codeson.net/grauph/patch"); m_plugin.plug_label("om_patch"); m_plugin.name("Om patch"); diff --git a/grauph/src/progs/gtk/Makefile.am b/grauph/src/progs/gtk/Makefile.am index 3bf779a8..bb42d575 100644 --- a/grauph/src/progs/gtk/Makefile.am +++ b/grauph/src/progs/gtk/Makefile.am @@ -62,12 +62,16 @@ om_gtk_SOURCES = \ ../../common/Path.h \ OmModule.h \ OmModule.cpp \ + OmPortModule.h \ + OmPortModule.cpp \ DSSIModule.h \ DSSIModule.cpp \ SubpatchModule.h \ SubpatchModule.cpp \ OmPort.h \ OmPort.cpp \ + OmPatchPort.h \ + OmPatchPort.cpp \ NewSubpatchWindow.h \ NewSubpatchWindow.cpp \ ConfigWindow.h \ diff --git a/grauph/src/progs/gtk/PatchController.cpp b/grauph/src/progs/gtk/PatchController.cpp index 1caf1e8c..d9b22e35 100644 --- a/grauph/src/progs/gtk/PatchController.cpp +++ b/grauph/src/progs/gtk/PatchController.cpp @@ -33,6 +33,7 @@ #include "PatchWindow.h" #include "NodeModel.h" #include "OmModule.h" +#include "OmPortModule.h" #include "OmPort.h" #include "ControlModel.h" #include "NodeControlWindow.h" @@ -73,6 +74,7 @@ PatchController::PatchController(CountedPtr model) cerr << "[PatchController] " << path() << " ERROR: Parent not found." << endl; }*/ + //model->new_port_sig.connect(sigc::mem_fun(this, &PatchController::add_port)); model->new_node_sig.connect(sigc::mem_fun(this, &PatchController::add_node)); model->removed_node_sig.connect(sigc::mem_fun(this, &PatchController::remove_node)); model->new_connection_sig.connect(sigc::mem_fun(this, &PatchController::connection)); @@ -278,6 +280,7 @@ PatchController::create_module(OmFlowCanvas* canvas) assert(canvas != NULL); assert(m_module == NULL); + assert(!m_patch_view || canvas != m_patch_view->canvas()); m_module = new SubpatchModule(canvas, this); @@ -333,7 +336,10 @@ PatchController::create_view() NodeController* nc = ((NodeController*)nm->controller()); if (!nc) - nc = new NodeController(nm); // this should set nm->controller() + nc = create_controller_for_node(nm); + + assert(nc); + assert(nm->controller() == nc); if (nc->module() == NULL); nc->create_module(m_patch_view->canvas()); @@ -341,6 +347,19 @@ PatchController::create_view() m_patch_view->canvas()->add_module(nc->module()); } + // Create pseudo modules for ports (ports on this canvas, not on our module) + for (PortModelList::const_iterator i = patch_model()->ports().begin(); + i != patch_model()->ports().end(); ++i) { + PortController* const pc = dynamic_cast((*i)->controller()); + assert(pc); + if (pc->module() == NULL) + pc->create_module(m_patch_view->canvas(), 1600, 1200); + assert(pc->module() != NULL); + m_patch_view->canvas()->add_module(pc->module()); + pc->module()->resize(); + } + + // Create connections for (list >::const_iterator i = patch_model()->connections().begin(); i != patch_model()->connections().end(); ++i) { @@ -404,6 +423,30 @@ PatchController::create_connection(CountedPtr cm) } +NodeController* +PatchController::create_controller_for_node(CountedPtr node) +{ + assert(!node->controller()); + NodeController* nc = NULL; + + CountedPtr patch(node); + if (patch) { + assert(patch == node); + assert(patch->parent() == m_patch_model); + nc = new PatchController(patch); + } else { + assert(node->plugin()); + if (node->plugin()->type() == PluginModel::DSSI) + nc = new DSSIController(node); + else + nc = new NodeController(node); + } + + assert(node->controller() == nc); + return nc; +} + + /** Add a child node to this patch. * * This is for plugin nodes and patches, and is responsible for creating the @@ -413,8 +456,8 @@ void PatchController::add_node(CountedPtr object) { assert(object); - assert(object->path().parent() == m_patch_model->path()); assert(object->parent() == m_patch_model); + assert(patch_model()->get_node(object->name())); /*if (patch_model()->get_node(nm->name()) != NULL) { cerr << "Ignoring existing\n"; @@ -428,36 +471,10 @@ PatchController::add_node(CountedPtr object) if (node) { assert(node->parent() == m_patch_model); - NodeController* nc = NULL; - - CountedPtr patch(node); - if (patch) { - assert(patch == node == object); - assert(patch->parent() == m_patch_model); - nc = new PatchController(patch); - } else { - assert(node->plugin()); - if (node->plugin()->type() == PluginModel::DSSI) - nc = new DSSIController(node); - else - nc = new NodeController(node); - } - - assert(nc != NULL); + NodeController* nc = create_controller_for_node(node); + assert(nc); assert(node->controller() == nc); - // Check if this is a bridge node - FIXME: remove this - CountedPtr pm = patch_model()->get_port(node->path().name()); - if (pm) { - cerr << "Bridge node." << endl; - PortController* pc = ((PortController*)pm->controller()); - assert(pc != NULL); - nc->bridge_port(pc); - } - - //nc->add_to_store(); - //patch_model()->add_node(node); - if (m_patch_view != NULL) { int x, y; get_new_module_location(x, y); @@ -514,29 +531,58 @@ void PatchController::add_port(CountedPtr pm) { assert(pm); - assert(!pm->parent()); + assert(pm->parent() == m_patch_model); + assert(patch_model()->get_port(pm->name())); + + cerr << "ADDING PORT " << pm->name() << "TO PATCH: " << patch_model()->path() << endl; //cerr << "[PatchController] Adding port " << pm->path() << endl; - if (patch_model()->get_port(pm->name())) { - cerr << "[PatchController] Ignoring duplicate port " - << pm->path() << endl; - return; - } - - node_model()->add_port(pm); + /*if (patch_model()->get_port(pm->name())) { + cerr << "[PatchController] Ignoring duplicate port " + << pm->path() << endl; + return; + }*/ + + //node_model()->add_port(pm); + // FIXME: leak PortController* pc = new PortController(pm); // Handle bridge ports/nodes (this is uglier than it should be) - NodeController* nc = (NodeController*)Store::instance().node(pm->path())->controller(); - if (nc != NULL) - nc->bridge_port(pc); - + /*NodeController* nc = (NodeController*)Store::instance().node(pm->path())->controller(); + if (nc != NULL) + nc->bridge_port(pc); + */ + + // Create port on this patch's module (if there is one) if (m_module != NULL) { pc->create_port(m_module); m_module->resize(); + } + + // Create port's (pseudo) module on this patch's canvas (if there is one) + if (m_patch_view != NULL) { + int x, y; + get_new_module_location(x, y); + + // Set zoom to 1.0 so module isn't messed up (Death to GnomeCanvas) + float old_zoom = m_patch_view->canvas()->zoom(); + if (old_zoom != 1.0) + m_patch_view->canvas()->zoom(1.0); + + if (pc->module() == NULL) + pc->create_module(m_patch_view->canvas(), x, y); + assert(pc->module() != NULL); + m_patch_view->canvas()->add_module(pc->module()); + pc->module()->resize(); + + // Reset zoom + if (old_zoom != 1.0) { + m_patch_view->canvas()->zoom(old_zoom); + pc->module()->zoom(old_zoom); + } } - + if (m_control_window != NULL) { assert(m_control_window->control_panel() != NULL); m_control_window->control_panel()->add_port(pc); diff --git a/grauph/src/progs/gtk/PatchController.h b/grauph/src/progs/gtk/PatchController.h index eff525c8..04bc82a8 100644 --- a/grauph/src/progs/gtk/PatchController.h +++ b/grauph/src/progs/gtk/PatchController.h @@ -113,6 +113,8 @@ private: void create_connection(CountedPtr cm); + NodeController* create_controller_for_node(CountedPtr node); + PatchPropertiesWindow* m_properties_window; PatchWindow* m_window; ///< Patch Window currently showing m_patch_view diff --git a/grauph/src/progs/gtk/PortController.cpp b/grauph/src/progs/gtk/PortController.cpp index fcb93b30..cdae49f7 100644 --- a/grauph/src/progs/gtk/PortController.cpp +++ b/grauph/src/progs/gtk/PortController.cpp @@ -19,6 +19,7 @@ #include "PortModel.h" #include "ControlPanel.h" #include "OmPort.h" +#include "OmPatchPort.h" #include "Store.h" namespace OmGtk { @@ -26,6 +27,7 @@ namespace OmGtk { PortController::PortController(CountedPtr model) : GtkObjectController(model), + m_module(NULL), m_port(NULL), m_control_panel(NULL) { @@ -65,6 +67,23 @@ PortController::destroy() } +void +PortController::create_module(OmFlowCanvas* canvas, double x, double y) +{ + cerr << "Creating port module " << m_model->path() << endl; + + assert(canvas); + assert(port_model()); + m_module = new OmPortModule(canvas, this, x, y); + + // FIXME: leak + m_patch_port = new OmPatchPort(m_module, port_model()); + m_module->add_port(m_patch_port, false); + + m_module->move_to(x, y); +} + + void PortController::metadata_update(const string& key, const string& value) { diff --git a/grauph/src/progs/gtk/PortController.h b/grauph/src/progs/gtk/PortController.h index ee4dc41f..34919129 100644 --- a/grauph/src/progs/gtk/PortController.h +++ b/grauph/src/progs/gtk/PortController.h @@ -20,6 +20,7 @@ #include #include #include "GtkObjectController.h" +#include "OmPortModule.h" using std::string; using namespace LibOmClient; @@ -33,8 +34,11 @@ namespace OmGtk { class Controller; class OmPort; +class OmPatchPort; class ControlPanel; class OmModule; +class OmPortModule; +class OmFlowCanvas; /** Controller for a port on a (non-patch) node. @@ -49,6 +53,8 @@ public: virtual void destroy(); + virtual void create_module(OmFlowCanvas* canvas, double x, double y); + OmPortModule* module() { return m_module; } /* virtual void add_to_store(); virtual void remove_from_store(); @@ -63,10 +69,12 @@ public: ControlPanel* control_panel() const { return m_control_panel; } void set_control_panel(ControlPanel* cp); - CountedPtr port_model() const { return CountedPtr((PortModel*)m_model.get()); } + CountedPtr port_model() const { return m_model; } private: - OmPort* m_port; ///< Canvas module port + OmPatchPort* m_patch_port; ///< Port on m_module + OmPortModule* m_module; ///< Port pseudo-module (for patch ports only) + OmPort* m_port; ///< Port on some other canvas module ControlPanel* m_control_panel; ///< Control panel that contains this port };