New patch ports interface
git-svn-id: http://svn.drobilla.net/lad@48 a436a847-0d15-0410-975c-d299462d15a1
This commit is contained in:
parent
07364d95ae
commit
fcde25e41f
|
@ -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);
|
||||
|
|
|
@ -209,13 +209,16 @@ Store::new_patch_event(const string& path, uint32_t poly)
|
|||
CountedPtr<PatchModel> p(new PatchModel(path, poly));
|
||||
add_object(p);
|
||||
|
||||
CountedPtr<PatchModel> 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<PatchModel> 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<PortModel> p(new PortModel(path, ptype, pdir));
|
||||
add_object(p);
|
||||
|
||||
std::map<string, CountedPtr<ObjectModel> >::iterator pi = m_objects.find(p->path().parent());
|
||||
if (pi != m_objects.end()) {
|
||||
CountedPtr<NodeModel> parent = (*pi).second;
|
||||
CountedPtr<NodeModel> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,16 +50,17 @@ ObjectSender::send_patch(ClientInterface* client, const Patch* patch)
|
|||
|
||||
for (List<Node*>::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<sample>*)port)->buffer(0)->value_at(0));
|
||||
//if (port && port->port_info()->is_control())
|
||||
// client->control_change(port->path(),
|
||||
// ((PortBase<sample>*)port)->buffer(0)->value_at(0));
|
||||
}
|
||||
|
||||
for (List<Connection*>::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<string, string>& data = port->metadata();
|
||||
for (map<string, string>::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<sample>*)port)->buffer(0)->value_at(0));
|
||||
}*/
|
||||
client->control_change(port->path(), ((PortBase<sample>*)port)->buffer(0)->value_at(0));
|
||||
}
|
||||
|
||||
// Send metadata
|
||||
const map<string, string>& data = patch->metadata();
|
||||
for (map<string, string>::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*>(node)->as_port()) { // bridge node if as_port() returns non-NULL
|
||||
send_port(client, const_cast<Node*>(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<Port*>& 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();
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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<PatchModel> 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<PortController*>((*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<CountedPtr<ConnectionModel> >::const_iterator i = patch_model()->connections().begin();
|
||||
i != patch_model()->connections().end(); ++i) {
|
||||
|
@ -404,6 +423,30 @@ PatchController::create_connection(CountedPtr<ConnectionModel> cm)
|
|||
}
|
||||
|
||||
|
||||
NodeController*
|
||||
PatchController::create_controller_for_node(CountedPtr<NodeModel> node)
|
||||
{
|
||||
assert(!node->controller());
|
||||
NodeController* nc = NULL;
|
||||
|
||||
CountedPtr<PatchModel> 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<NodeModel> 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<NodeModel> object)
|
|||
if (node) {
|
||||
assert(node->parent() == m_patch_model);
|
||||
|
||||
NodeController* nc = NULL;
|
||||
|
||||
CountedPtr<PatchModel> 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<PortModel> 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<PortModel> 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);
|
||||
|
|
|
@ -113,6 +113,8 @@ private:
|
|||
|
||||
void create_connection(CountedPtr<ConnectionModel> cm);
|
||||
|
||||
NodeController* create_controller_for_node(CountedPtr<NodeModel> node);
|
||||
|
||||
PatchPropertiesWindow* m_properties_window;
|
||||
|
||||
PatchWindow* m_window; ///< Patch Window currently showing m_patch_view
|
||||
|
|
|
@ -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<PortModel> 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)
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <string>
|
||||
#include <gtkmm.h>
|
||||
#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<PortModel> port_model() const { return CountedPtr<PortModel>((PortModel*)m_model.get()); }
|
||||
CountedPtr<PortModel> 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
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue