interactive GUI to manage plugins pins
This commit is contained in:
@@ -48,6 +48,7 @@ PluginPinDialog::PluginPinDialog (boost::shared_ptr<ARDOUR::PluginInsert> pi)
|
||||
, _del_output_midi (_("-"))
|
||||
, _pi (pi)
|
||||
, _pin_box_size (4)
|
||||
, _position_valid (false)
|
||||
{
|
||||
assert (pi->owner ()); // Route
|
||||
|
||||
@@ -63,15 +64,13 @@ PluginPinDialog::PluginPinDialog (boost::shared_ptr<ARDOUR::PluginInsert> pi)
|
||||
_plugin_connections, invalidator (*this), boost::bind (&PluginPinDialog::plugin_reconfigured, this), gui_context()
|
||||
);
|
||||
|
||||
darea.signal_expose_event().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_expose_event));
|
||||
|
||||
// TODO min. width depending on # of pins.
|
||||
darea.set_size_request(600, 200);
|
||||
_strict_io.set_sensitive (false);
|
||||
|
||||
Label *l;
|
||||
Label* l;
|
||||
int r = 0;
|
||||
Table *t = manage (new Table (4, 3));
|
||||
Table* t = manage (new Table (4, 3));
|
||||
t->set_border_width (0);
|
||||
t->set_spacings (4);
|
||||
|
||||
@@ -130,7 +129,14 @@ PluginPinDialog::PluginPinDialog (boost::shared_ptr<ARDOUR::PluginInsert> pi)
|
||||
|
||||
plugin_reconfigured ();
|
||||
|
||||
_automatic.signal_clicked.connect (sigc::mem_fun(*this, &PluginPinDialog::automatic_clicked));
|
||||
darea.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
|
||||
darea.signal_size_allocate().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_size_allocate));
|
||||
darea.signal_expose_event().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_expose_event));
|
||||
darea.signal_button_press_event().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_button_press_event));
|
||||
darea.signal_button_release_event().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_button_release_event));
|
||||
darea.signal_motion_notify_event().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_motion_notify_event));
|
||||
|
||||
_automatic.signal_clicked.connect (sigc::mem_fun(*this, &PluginPinDialog::automatic_clicked));
|
||||
_add_plugin.signal_clicked.connect (sigc::bind (sigc::mem_fun(*this, &PluginPinDialog::add_remove_plugin_clicked), true));
|
||||
_del_plugin.signal_clicked.connect (sigc::bind (sigc::mem_fun(*this, &PluginPinDialog::add_remove_plugin_clicked), false));
|
||||
|
||||
@@ -147,18 +153,97 @@ PluginPinDialog::~PluginPinDialog()
|
||||
void
|
||||
PluginPinDialog::plugin_reconfigured ()
|
||||
{
|
||||
uint32_t plugins = _pi->get_count ();
|
||||
ChanCount in, out;
|
||||
_pi->configured_io (in, out);
|
||||
_n_plugins = _pi->get_count ();
|
||||
_pi->configured_io (_in, _out);
|
||||
_sinks = _pi->natural_input_streams ();
|
||||
_sources = _pi->natural_output_streams ();
|
||||
|
||||
_del_plugin.set_sensitive (plugins > 1);
|
||||
_del_output_audio.set_sensitive (out.n_audio () > 0 && out.n_total () > 1);
|
||||
_del_output_midi.set_sensitive (out.n_midi () > 0 && out.n_total () > 1);
|
||||
_del_plugin.set_sensitive (_n_plugins > 1);
|
||||
_del_output_audio.set_sensitive (_out.n_audio () > 0 && _out.n_total () > 1);
|
||||
_del_output_midi.set_sensitive (_out.n_midi () > 0 && _out.n_total () > 1);
|
||||
_strict_io.set_active (_pi->strict_io());
|
||||
|
||||
update_elements ();
|
||||
}
|
||||
|
||||
void
|
||||
PluginPinDialog::update_elements ()
|
||||
{
|
||||
_elements.clear ();
|
||||
_hover.reset();
|
||||
_actor.reset();
|
||||
_selection.reset();
|
||||
|
||||
for (uint32_t i = 0; i < _in.n_total (); ++i) {
|
||||
_elements.push_back (CtrlWidget (Input, (i < _in.n_midi () ? DataType::MIDI : DataType::AUDIO), i));
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < _out.n_total (); ++i) {
|
||||
_elements.push_back (CtrlWidget (Output, (i < _out.n_midi () ? DataType::MIDI : DataType::AUDIO), i));
|
||||
}
|
||||
|
||||
for (uint32_t n = 0; n < _n_plugins; ++n) {
|
||||
for (uint32_t i = 0; i < _sinks.n_total(); ++i) {
|
||||
_elements.push_back (CtrlWidget (Sink, (i < _sinks.n_midi () ? DataType::MIDI : DataType::AUDIO), i, n));
|
||||
}
|
||||
for (uint32_t i = 0; i < _sources.n_total(); ++i) {
|
||||
_elements.push_back (CtrlWidget (Source, (i < _sources.n_midi () ? DataType::MIDI : DataType::AUDIO), i, n));
|
||||
}
|
||||
}
|
||||
_position_valid = false;
|
||||
darea.queue_draw ();
|
||||
}
|
||||
|
||||
void
|
||||
PluginPinDialog::update_element_pos ()
|
||||
{
|
||||
/* layout sizes */
|
||||
const double yc = rint (_height * .5);
|
||||
const double bxh2 = 18;
|
||||
const double bxw = rint ((_width * .9) / ((_n_plugins) + .2 * (_n_plugins - 1)));
|
||||
const double bxw2 = rint (bxw * .5);
|
||||
const double y_in = 40;
|
||||
const double y_out = _height - 40;
|
||||
|
||||
_pin_box_size = rint (max (6., 8. * UIConfiguration::instance().get_ui_scale()));
|
||||
|
||||
for (CtrlElemList::iterator i = _elements.begin(); i != _elements.end(); ++i) {
|
||||
switch (i->e->ct) {
|
||||
case Input:
|
||||
i->x = rint ((i->e->id + 1) * _width / (1. + _in.n_total ())) - 5.5;
|
||||
i->y = y_in - 25;
|
||||
i->w = 10;
|
||||
i->h = 25;
|
||||
break;
|
||||
case Output:
|
||||
i->x = rint ((i->e->id + 1) * _width / (1. + _out.n_total ())) - 5.5;
|
||||
i->y = y_out;
|
||||
i->w = 10;
|
||||
i->h = 25;
|
||||
break;
|
||||
case Sink:
|
||||
{
|
||||
const double x0 = rint ((i->e->ip + .5) * _width / (double)(_n_plugins)) - .5 - bxw2;
|
||||
i->x = rint (x0 + (i->e->id + 1) * bxw / (1. + _sinks.n_total ())) - .5 - _pin_box_size * .5;
|
||||
i->y = yc - bxh2 - _pin_box_size;
|
||||
i->w = _pin_box_size + 1;
|
||||
i->h = _pin_box_size;
|
||||
}
|
||||
break;
|
||||
case Source:
|
||||
{
|
||||
const double x0 = rint ((i->e->ip + .5) * _width / (double)(_n_plugins)) - .5 - bxw2;
|
||||
i->x = rint (x0 + (i->e->id + 1) * bxw / (1. + _sources.n_total ())) - .5 - _pin_box_size * .5;
|
||||
i->y = yc + bxh2;
|
||||
i->w = _pin_box_size + 1;
|
||||
i->h = _pin_box_size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
PluginPinDialog::set_color (cairo_t* cr, bool midi)
|
||||
{
|
||||
@@ -180,25 +265,43 @@ PluginPinDialog::set_color (cairo_t* cr, bool midi)
|
||||
}
|
||||
|
||||
void
|
||||
PluginPinDialog::draw_io_pins (cairo_t* cr, double y0, double width, uint32_t n_total, uint32_t n_midi, bool input)
|
||||
PluginPinDialog::draw_io_pin (cairo_t* cr, const CtrlWidget& w)
|
||||
{
|
||||
double dir = input ? 1. : -1.;
|
||||
const double dir = (w.e->ct == Input) ? 1 : -1;
|
||||
|
||||
for (uint32_t i = 0; i < n_total; ++i) {
|
||||
double x0 = rint ((i + 1) * width / (1. + n_total)) - .5;
|
||||
cairo_move_to (cr, x0, y0);
|
||||
cairo_rel_line_to (cr, -5., -5. * dir);
|
||||
cairo_rel_line_to (cr, 0., -25. * dir);
|
||||
cairo_rel_line_to (cr, 10., 0.);
|
||||
cairo_rel_line_to (cr, 0., 25. * dir);
|
||||
cairo_close_path (cr);
|
||||
cairo_move_to (cr, w.x + 5.0, w.y + ((w.e->ct == Input) ? 25 : 0));
|
||||
cairo_rel_line_to (cr, -5., -5. * dir);
|
||||
cairo_rel_line_to (cr, 0., -25. * dir);
|
||||
cairo_rel_line_to (cr, 10., 0.);
|
||||
cairo_rel_line_to (cr, 0., 25. * dir);
|
||||
cairo_close_path (cr);
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_stroke_preserve (cr);
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
set_color (cr, i < n_midi);
|
||||
cairo_fill (cr);
|
||||
set_color (cr, w.e->dt == DataType::MIDI);
|
||||
if (w.e == _selection || w.e == _actor) {
|
||||
cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
|
||||
} else if (w.prelight) {
|
||||
cairo_fill_preserve (cr);
|
||||
cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.5);
|
||||
}
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
void
|
||||
PluginPinDialog::draw_plugin_pin (cairo_t* cr, const CtrlWidget& w)
|
||||
{
|
||||
cairo_rectangle (cr, w.x, w.y, w.w, w.h);
|
||||
set_color (cr, w.e->dt == DataType::MIDI);
|
||||
if (w.e == _selection || w.e == _actor) {
|
||||
cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
|
||||
} else if (w.prelight) {
|
||||
cairo_fill_preserve (cr);
|
||||
cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.5);
|
||||
}
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -218,30 +321,15 @@ PluginPinDialog::pin_x_pos (uint32_t i, double x0, double width, uint32_t n_tota
|
||||
return rint (x0 + (i + 1) * width / (1. + n_total)) - .5;
|
||||
}
|
||||
|
||||
void
|
||||
PluginPinDialog::draw_plugin_pins (cairo_t* cr, double x0, double y0, double width, uint32_t n_total, uint32_t n_midi, bool input)
|
||||
{
|
||||
// see also ProcessorEntry::PortIcon::on_expose_event
|
||||
const double dxy = _pin_box_size;
|
||||
|
||||
for (uint32_t i = 0; i < n_total; ++i) {
|
||||
double x = rint (x0 + (i + 1) * width / (1. + n_total)) - .5;
|
||||
cairo_rectangle (cr, x - dxy * .5, input ? y0 - dxy : y0, 1 + dxy, dxy);
|
||||
|
||||
set_color (cr, i < n_midi);
|
||||
cairo_fill(cr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginPinDialog::draw_connection (cairo_t* cr, double x0, double x1, double y0, double y1, bool midi, bool dashed)
|
||||
{
|
||||
double bz = 2 * _pin_box_size;
|
||||
const double bz = 2 * _pin_box_size;
|
||||
|
||||
cairo_move_to (cr, x0, y0);
|
||||
cairo_curve_to (cr, x0, y0 + bz, x1, y1 - bz, x1, y1);
|
||||
cairo_set_line_width (cr, 3.0);
|
||||
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
|
||||
cairo_set_line_width (cr, 3.0);
|
||||
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
|
||||
cairo_set_source_rgb (cr, 1, 0, 0);
|
||||
if (dashed) {
|
||||
const double dashes[] = { 5, 7 };
|
||||
@@ -261,10 +349,14 @@ PluginPinDialog::darea_expose_event (GdkEventExpose* ev)
|
||||
double const width = a.get_width();
|
||||
double const height = a.get_height();
|
||||
|
||||
_pin_box_size = rint (max (6., 8. * UIConfiguration::instance().get_ui_scale()));
|
||||
if (!_position_valid) {
|
||||
_width = width;
|
||||
_height = height;
|
||||
update_element_pos ();
|
||||
_position_valid = true;
|
||||
}
|
||||
|
||||
cairo_t* cr = gdk_cairo_create (darea.get_window()->gobj());
|
||||
|
||||
cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
|
||||
cairo_clip (cr);
|
||||
|
||||
@@ -273,53 +365,40 @@ PluginPinDialog::darea_expose_event (GdkEventExpose* ev)
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_fill (cr);
|
||||
|
||||
ChanCount in, out; // actual configured i/o
|
||||
_pi->configured_io (in, out);
|
||||
|
||||
ChanCount sinks = _pi->natural_input_streams ();
|
||||
ChanCount sources = _pi->natural_output_streams ();
|
||||
uint32_t plugins = _pi->get_count ();
|
||||
|
||||
/* layout sizes */
|
||||
/* layout sizes -- TODO consolidate w/ update_element_pos() */
|
||||
// i/o pins
|
||||
double y_in = 40;
|
||||
double y_out = height - 40;
|
||||
const double y_in = 40;
|
||||
const double y_out = height - 40;
|
||||
|
||||
// plugin box(es)
|
||||
double yc = rint (height * .5);
|
||||
double bxh2 = 18;
|
||||
double bxw = rint ((width * .9) / ((plugins) + .2 * (plugins - 1)));
|
||||
double bxw2 = rint (bxw * .5);
|
||||
const double yc = rint (height * .5);
|
||||
const double bxh2 = 18;
|
||||
const double bxw = rint ((width * .9) / ((_n_plugins) + .2 * (_n_plugins - 1)));
|
||||
const double bxw2 = rint (bxw * .5);
|
||||
|
||||
// i/o pins
|
||||
const uint32_t pc_in = in.n_total();
|
||||
const uint32_t pc_in_midi = in.n_midi();
|
||||
const uint32_t pc_out = out.n_total();
|
||||
const uint32_t pc_out_midi = out.n_midi();
|
||||
const uint32_t pc_in = _in.n_total();
|
||||
const uint32_t pc_in_midi = _in.n_midi();
|
||||
const uint32_t pc_out = _out.n_total();
|
||||
const uint32_t pc_out_midi = _out.n_midi();
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
draw_io_pins (cr, y_in, width, pc_in, pc_in_midi, true);
|
||||
draw_io_pins (cr, y_out, width, pc_out, pc_out_midi, false);
|
||||
|
||||
// draw midi-bypass (behind)
|
||||
/* draw midi-bypass (behind) */
|
||||
if (_pi->has_midi_bypass ()) {
|
||||
double x0 = rint (width / (1. + pc_in)) - .5;
|
||||
double x1 = rint (width / (1. + pc_out)) - .5;
|
||||
draw_connection (cr, x0, x1, y_in, y_out, true, true);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < plugins; ++i) {
|
||||
double x0 = rint ((i + .5) * width / (double)(plugins)) - .5;
|
||||
|
||||
draw_plugin_pins (cr, x0 - bxw2, yc - bxh2, bxw, sinks.n_total (), sinks.n_midi (), true);
|
||||
draw_plugin_pins (cr, x0 - bxw2, yc + bxh2, bxw, sources.n_total (), sources.n_midi (), false);
|
||||
/* plugins & connection wires */
|
||||
for (uint32_t i = 0; i < _n_plugins; ++i) {
|
||||
double x0 = rint ((i + .5) * width / (double)(_n_plugins)) - .5;
|
||||
|
||||
/* plugin box */
|
||||
cairo_set_source_rgb (cr, .3, .3, .3);
|
||||
rounded_rectangle (cr, x0 - bxw2, yc - bxh2, bxw, 2 * bxh2, 7);
|
||||
cairo_fill (cr);
|
||||
|
||||
const ChanMapping::Mappings in_map = _pi->input_map (i).mappings();
|
||||
const ChanMapping::Mappings out_map = _pi->output_map (i).mappings();
|
||||
const ChanMapping::Mappings in_map = _pi->input_map (i).mappings();
|
||||
const ChanMapping::Mappings out_map = _pi->output_map (i).mappings();
|
||||
|
||||
for (ChanMapping::Mappings::const_iterator t = in_map.begin (); t != in_map.end (); ++t) {
|
||||
bool is_midi = t->first == DataType::MIDI;
|
||||
@@ -330,7 +409,7 @@ PluginPinDialog::darea_expose_event (GdkEventExpose* ev)
|
||||
continue;
|
||||
}
|
||||
double c_x0 = pin_x_pos (pb, 0, width, pc_in, pc_in_midi, is_midi);
|
||||
double c_x1 = pin_x_pos (pn, x0 - bxw2, bxw, sinks.n_total (), sinks.n_midi (), is_midi);
|
||||
double c_x1 = pin_x_pos (pn, x0 - bxw2, bxw, _sinks.n_total (), _sinks.n_midi (), is_midi);
|
||||
draw_connection (cr, c_x0, c_x1, y_in, yc - bxh2 - _pin_box_size, is_midi);
|
||||
}
|
||||
}
|
||||
@@ -338,22 +417,180 @@ PluginPinDialog::darea_expose_event (GdkEventExpose* ev)
|
||||
for (ChanMapping::Mappings::const_iterator t = out_map.begin (); t != out_map.end (); ++t) {
|
||||
bool is_midi = t->first == DataType::MIDI;
|
||||
for (ChanMapping::TypeMapping::const_iterator c = (*t).second.begin (); c != (*t).second.end () ; ++c) {
|
||||
uint32_t pn = (*c).first; // pin
|
||||
uint32_t pn = (*c).first; // pin
|
||||
uint32_t pb = (*c).second;
|
||||
if (!is_valid_port (pb, pc_out, pc_out_midi, is_midi)) {
|
||||
continue;
|
||||
}
|
||||
double c_x0 = pin_x_pos (pn, x0 - bxw2, bxw, sources.n_total (), sources.n_midi (), is_midi);
|
||||
double c_x0 = pin_x_pos (pn, x0 - bxw2, bxw, _sources.n_total (), _sources.n_midi (), is_midi);
|
||||
double c_x1 = pin_x_pos (pb, 0, width, pc_out, pc_out_midi, is_midi);
|
||||
draw_connection (cr, c_x0, c_x1, yc + bxh2 + _pin_box_size, y_out, is_midi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* pins and ports */
|
||||
for (CtrlElemList::const_iterator i = _elements.begin(); i != _elements.end(); ++i) {
|
||||
switch (i->e->ct) {
|
||||
case Input:
|
||||
case Output:
|
||||
draw_io_pin (cr, *i);
|
||||
break;
|
||||
case Sink:
|
||||
case Source:
|
||||
draw_plugin_pin (cr, *i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cairo_destroy (cr);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PluginPinDialog::darea_size_allocate (Gtk::Allocation&)
|
||||
{
|
||||
_position_valid = false;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginPinDialog::darea_motion_notify_event (GdkEventMotion* ev)
|
||||
{
|
||||
bool changed = false;
|
||||
_hover.reset ();
|
||||
for (CtrlElemList::iterator i = _elements.begin(); i != _elements.end(); ++i) {
|
||||
if (ev->x >= i->x && ev->x <= i->x + i->w
|
||||
&& ev->y >= i->y && ev->y <= i->y + i->h)
|
||||
{
|
||||
if (!i->prelight) changed = true;
|
||||
i->prelight = true;
|
||||
_hover = i->e;
|
||||
} else {
|
||||
if (i->prelight) changed = true;
|
||||
i->prelight = false;
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
darea.queue_draw ();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginPinDialog::darea_button_press_event (GdkEventButton* ev)
|
||||
{
|
||||
if (ev->type != GDK_BUTTON_PRESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ev->button) {
|
||||
case 1:
|
||||
if (!_selection || (_selection && !_hover)) {
|
||||
_selection = _hover;
|
||||
_actor.reset ();
|
||||
darea.queue_draw ();
|
||||
} else if (_selection && _hover && _selection != _hover) {
|
||||
if (_selection->dt != _hover->dt) { _actor.reset (); }
|
||||
else if (_selection->ct == Input && _hover->ct == Sink) { _actor = _hover; }
|
||||
else if (_selection->ct == Sink && _hover->ct == Input) { _actor = _hover; }
|
||||
else if (_selection->ct == Output && _hover->ct == Source) { _actor = _hover; }
|
||||
else if (_selection->ct == Source && _hover->ct == Output) { _actor = _hover; }
|
||||
if (!_actor) {
|
||||
_selection = _hover;
|
||||
}
|
||||
darea.queue_draw ();
|
||||
}
|
||||
case 3:
|
||||
if (_hover) {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginPinDialog::darea_button_release_event (GdkEventButton* ev)
|
||||
{
|
||||
if (_hover == _actor && _actor) {
|
||||
assert (_selection);
|
||||
assert (_selection->dt == _actor->dt);
|
||||
if (_selection->ct == Input && _actor->ct == Sink) {
|
||||
handle_input_action (_actor, _selection);
|
||||
}
|
||||
else if (_selection->ct == Sink && _actor->ct == Input) {
|
||||
handle_input_action (_selection, _actor);
|
||||
}
|
||||
else if (_selection->ct == Output && _actor->ct == Source) {
|
||||
handle_output_action (_actor, _selection);
|
||||
}
|
||||
else if (_selection->ct == Source && _actor->ct == Output) {
|
||||
handle_output_action (_selection, _actor);
|
||||
}
|
||||
_selection.reset ();
|
||||
}
|
||||
_actor.reset ();
|
||||
darea.queue_draw ();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PluginPinDialog::handle_input_action (const CtrlElem &s, const CtrlElem &i)
|
||||
{
|
||||
const int pc = s->ip;
|
||||
bool valid;
|
||||
ChanMapping in_map (_pi->input_map (pc));
|
||||
uint32_t idx = in_map.get (s->dt, s->id, &valid);
|
||||
|
||||
if (valid && idx == i->id) {
|
||||
// disconnect
|
||||
in_map.unset (s->dt, s->id);
|
||||
_pi->set_input_map (pc, in_map);
|
||||
}
|
||||
else if (!valid) {
|
||||
// connect
|
||||
in_map.set (s->dt, s->id, i->id);
|
||||
_pi->set_input_map (pc, in_map);
|
||||
}
|
||||
else {
|
||||
// reconnect
|
||||
in_map.unset (s->dt, s->id);
|
||||
in_map.set (s->dt, s->id, i->id);
|
||||
_pi->set_input_map (pc, in_map);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginPinDialog::handle_output_action (const CtrlElem &s, const CtrlElem &o)
|
||||
{
|
||||
const int pc = s->ip;
|
||||
bool valid;
|
||||
ChanMapping out_map (_pi->output_map (pc));
|
||||
uint32_t idx = out_map.get (s->dt, s->id, &valid);
|
||||
|
||||
if (valid && idx == o->id) {
|
||||
// disconnect
|
||||
out_map.unset (s->dt, s->id);
|
||||
_pi->set_output_map (pc, out_map);
|
||||
}
|
||||
else {
|
||||
// disconnect source
|
||||
if (valid) {
|
||||
out_map.unset (s->dt, s->id);
|
||||
}
|
||||
// disconnect other outputs
|
||||
uint32_t idx = out_map.get_src (s->dt, o->id, &valid);
|
||||
if (valid) {
|
||||
out_map.unset (s->dt, idx);
|
||||
}
|
||||
// connect
|
||||
out_map.set (s->dt, s->id, o->id);
|
||||
_pi->set_output_map (pc, out_map);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginPinDialog::automatic_clicked ()
|
||||
{
|
||||
@@ -363,20 +600,16 @@ PluginPinDialog::automatic_clicked ()
|
||||
void
|
||||
PluginPinDialog::add_remove_plugin_clicked (bool add)
|
||||
{
|
||||
uint32_t plugins = _pi->get_count ();
|
||||
ChanCount in, out;
|
||||
_pi->configured_io (in, out);
|
||||
assert (add || plugins > 0);
|
||||
_route()->customize_plugin_insert (_pi, plugins + (add ? 1 : -1), out);
|
||||
ChanCount out = _out;
|
||||
assert (add || _n_plugins > 0);
|
||||
_route()->customize_plugin_insert (_pi, _n_plugins + (add ? 1 : -1), out);
|
||||
}
|
||||
|
||||
void
|
||||
PluginPinDialog::add_remove_port_clicked (bool add, ARDOUR::DataType dt)
|
||||
{
|
||||
uint32_t plugins = _pi->get_count ();
|
||||
ChanCount in, out;
|
||||
_pi->configured_io (in, out);
|
||||
ChanCount out = _out;
|
||||
assert (add || out.get (dt) > 0);
|
||||
out.set (dt, out.get (dt) + (add ? 1 : -1));
|
||||
_route()->customize_plugin_insert (_pi, plugins, out);
|
||||
_route()->customize_plugin_insert (_pi, _n_plugins, out);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,44 @@ public:
|
||||
~PluginPinDialog ();
|
||||
|
||||
private:
|
||||
typedef enum {
|
||||
Input,
|
||||
Sink,
|
||||
Source,
|
||||
Output
|
||||
} CtrlType;
|
||||
|
||||
struct _CtrlElem {
|
||||
_CtrlElem (CtrlType c, ARDOUR::DataType d, uint32_t i, uint32_t p = -1)
|
||||
: ct (c), dt (d), id (i), ip (p) {}
|
||||
CtrlType ct;
|
||||
ARDOUR::DataType dt;
|
||||
uint32_t id; // port/pin ID
|
||||
uint32_t ip; // plugin ID (for Sink, Source only)
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<_CtrlElem> CtrlElem;
|
||||
|
||||
struct CtrlWidget {
|
||||
CtrlWidget (CtrlType ct, ARDOUR::DataType dt, uint32_t id, uint32_t ip = 0)
|
||||
: x(0), y(0), w (0), h (0), prelight (false)
|
||||
{
|
||||
e = CtrlElem (new _CtrlElem (ct, dt, id, ip));
|
||||
}
|
||||
double x,y;
|
||||
double w,h;
|
||||
bool prelight;
|
||||
CtrlElem e;
|
||||
};
|
||||
|
||||
typedef std::vector<CtrlWidget> CtrlElemList;
|
||||
|
||||
CtrlElem _selection;
|
||||
CtrlElem _actor;
|
||||
CtrlElem _hover;
|
||||
CtrlElemList _elements;
|
||||
|
||||
|
||||
Gtk::DrawingArea darea;
|
||||
ArdourButton _strict_io;
|
||||
ArdourButton _automatic;
|
||||
@@ -47,24 +85,40 @@ private:
|
||||
ArdourButton _add_output_midi;
|
||||
ArdourButton _del_output_midi;
|
||||
|
||||
bool darea_expose_event (GdkEventExpose* event);
|
||||
void plugin_reconfigured ();
|
||||
void update_elements ();
|
||||
void update_element_pos ();
|
||||
|
||||
void darea_size_allocate (Gtk::Allocation&);
|
||||
bool darea_expose_event (GdkEventExpose*);
|
||||
bool darea_motion_notify_event (GdkEventMotion*);
|
||||
bool darea_button_press_event (GdkEventButton*);
|
||||
bool darea_button_release_event (GdkEventButton*);
|
||||
|
||||
void draw_io_pin (cairo_t*, const CtrlWidget&);
|
||||
void draw_plugin_pin (cairo_t*, const CtrlWidget&);
|
||||
|
||||
double pin_x_pos (uint32_t, double, double, uint32_t, uint32_t, bool);
|
||||
void draw_io_pins (cairo_t*, double, double, uint32_t, uint32_t, bool);
|
||||
void draw_plugin_pins (cairo_t*, double, double, double, uint32_t, uint32_t, bool);
|
||||
void draw_connection (cairo_t*, double, double, double, double, bool, bool dashed = false);
|
||||
bool is_valid_port (uint32_t, uint32_t, uint32_t, bool);
|
||||
void set_color (cairo_t*, bool);
|
||||
double pin_x_pos (uint32_t, double, double, uint32_t, uint32_t, bool);
|
||||
bool is_valid_port (uint32_t, uint32_t, uint32_t, bool);
|
||||
void draw_connection (cairo_t*, double, double, double, double, bool, bool dashed = false);
|
||||
|
||||
void automatic_clicked ();
|
||||
void add_remove_plugin_clicked (bool);
|
||||
void add_remove_port_clicked (bool, ARDOUR::DataType);
|
||||
void handle_input_action (const CtrlElem &, const CtrlElem &);
|
||||
void handle_output_action (const CtrlElem &, const CtrlElem &);
|
||||
|
||||
PBD::ScopedConnectionList _plugin_connections;
|
||||
boost::shared_ptr<ARDOUR::PluginInsert> _pi;
|
||||
double _pin_box_size;
|
||||
|
||||
uint32_t _n_plugins;
|
||||
ARDOUR::ChanCount _in, _out;
|
||||
ARDOUR::ChanCount _sinks, _sources;
|
||||
|
||||
double _pin_box_size;
|
||||
double _width, _height;
|
||||
bool _position_valid;
|
||||
ARDOUR::Route* _route () { return static_cast<ARDOUR::Route*> (_pi->owner ()); }
|
||||
};
|
||||
|
||||
|
||||
@@ -939,12 +939,16 @@ PluginInsertProcessorEntry::PluginInsertProcessorEntry (ProcessorBox* b, boost::
|
||||
p->PluginMapChanged.connect (
|
||||
_iomap_connection, invalidator (*this), boost::bind (&PluginInsertProcessorEntry::iomap_changed, this), gui_context()
|
||||
);
|
||||
p->PluginConfigChanged.connect (
|
||||
_iomap_connection, invalidator (*this), boost::bind (&PluginInsertProcessorEntry::iomap_changed, this), gui_context()
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
PluginInsertProcessorEntry::iomap_changed ()
|
||||
{
|
||||
_parent->setup_routing_feeds ();
|
||||
routing_icon.queue_draw();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1020,12 +1024,23 @@ ProcessorEntry::RoutingIcon::set (
|
||||
|
||||
bool
|
||||
ProcessorEntry::RoutingIcon::identity () const {
|
||||
if (!_in_map.is_monotonic ()) {
|
||||
if (!_in_map.is_monotonic () || !_in_map.is_monotonic ()) {
|
||||
return false;
|
||||
}
|
||||
if (_feed && (!_f_out_map.is_monotonic () || _sinks != _f_sources)) {
|
||||
if (_in_map.count () != _sinks.n_total ()) {
|
||||
return false;
|
||||
}
|
||||
if (_feed) {
|
||||
if (!_f_out_map.is_monotonic () || _sinks != _f_sources) {
|
||||
return false;
|
||||
}
|
||||
if (!_f_out_map.is_identity ()) {
|
||||
return false;
|
||||
}
|
||||
if (_f_out_map.count () != _f_sources.n_total ()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1142,6 +1157,8 @@ ProcessorEntry::RoutingIcon::expose_map (cairo_t* cr, const double width, const
|
||||
bool valid_src;
|
||||
uint32_t src = _f_out_map.get_src (is_midi ? DataType::MIDI : DataType::AUDIO, idx, &valid_src);
|
||||
if (!valid_src) {
|
||||
double x = pin_x_pos (i, width, pc_in, pc_in_midi, is_midi);
|
||||
draw_gnd (cr, x, height, is_midi);
|
||||
continue;
|
||||
}
|
||||
c_x0 = pin_x_pos (src, width, _f_out.n_total(), _f_out.n_midi(), is_midi);
|
||||
@@ -2523,6 +2540,7 @@ ProcessorBox::setup_routing_feeds ()
|
||||
}
|
||||
} else {
|
||||
(*i)->routing_icon.show();
|
||||
(*i)->routing_icon.queue_draw();
|
||||
(*i)->input_icon.show();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user