From 3868c5b4a4a4a41e7568da039345472ed4da71f0 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 7 Apr 2016 18:36:04 +0200 Subject: GUI support for plugin port bypass connections --- gtk2_ardour/plugin_pin_dialog.cc | 124 +++++++++++++++++++++++++++++++++------ gtk2_ardour/plugin_pin_dialog.h | 3 + gtk2_ardour/processor_box.cc | 72 ++++++++++++++++++----- gtk2_ardour/processor_box.h | 27 +++++---- 4 files changed, 181 insertions(+), 45 deletions(-) (limited to 'gtk2_ardour') diff --git a/gtk2_ardour/plugin_pin_dialog.cc b/gtk2_ardour/plugin_pin_dialog.cc index 18c6852b0c..0096f8d913 100644 --- a/gtk2_ardour/plugin_pin_dialog.cc +++ b/gtk2_ardour/plugin_pin_dialog.cc @@ -712,6 +712,16 @@ PluginPinDialog::darea_expose_event (GdkEventExpose* ev) draw_connection (cr, cw0, cw1, true); } + /* thru connections */ + const ChanMapping::Mappings thru_map = _pi->thru_map ().mappings (); + for (ChanMapping::Mappings::const_iterator t = thru_map.begin (); t != thru_map.end (); ++t) { + for (ChanMapping::TypeMapping::const_iterator c = (*t).second.begin (); c != (*t).second.end () ; ++c) { + const CtrlWidget& cw0 = get_io_ctrl (Output, t->first, c->first); + const CtrlWidget& cw1 = get_io_ctrl (Input, t->first, c->second); + draw_connection (cr, cw1, cw0, true); + } + } + /* labels */ Glib::RefPtr layout; layout = Pango::Layout::create (get_pango_context ()); @@ -842,10 +852,12 @@ PluginPinDialog::drag_type_matches (CtrlType ct) { if (!_dragging || !_selection) { return true; } - if (_selection->ct == Input && ct == Sink) { return true; } - if (_selection->ct == Sink && ct == Input) { return true; } + if (_selection->ct == Input && ct == Sink) { return true; } + if (_selection->ct == Sink && ct == Input) { return true; } if (_selection->ct == Output && ct == Source) { return true; } if (_selection->ct == Source && ct == Output) { return true; } + if (_selection->ct == Input && ct == Output) { return true; } + if (_selection->ct == Output && ct == Input) { return true; } return false; } @@ -896,10 +908,12 @@ PluginPinDialog::darea_button_press_event (GdkEventButton* ev) 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 == 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; } + else if (_selection->ct == Input && _hover->ct == Output) { _actor = _hover; } + else if (_selection->ct == Output && _hover->ct == Input) { _actor = _hover; } if (!_actor) { _selection = _hover; _dragging = true; @@ -950,6 +964,12 @@ PluginPinDialog::darea_button_release_event (GdkEventButton* ev) else if (_selection->ct == Source && _actor->ct == Output) { handle_output_action (_selection, _actor); } + else if (_selection->ct == Input && _actor->ct == Output) { + handle_thru_action (_actor, _selection); + } + else if (_selection->ct == Output && _actor->ct == Input) { + handle_thru_action (_selection, _actor); + } _selection.reset (); } else if (_hover == _selection && _selection && ev->button == 3) { handle_disconnect (_selection); @@ -988,6 +1008,39 @@ PluginPinDialog::handle_input_action (const CtrlElem &s, const CtrlElem &i) } } +void +PluginPinDialog::disconnect_other_outputs (uint32_t skip_pc, DataType dt, uint32_t id) +{ + _ignore_updates = true; + for (uint32_t n = 0; n < _n_plugins; ++n) { + if (n == skip_pc) { + continue; + } + bool valid; + ChanMapping n_out_map (_pi->output_map (n)); + uint32_t idx = n_out_map.get_src (dt, id, &valid); + if (valid) { + n_out_map.unset (dt, idx); + _pi->set_output_map (n, n_out_map); + } + } + _ignore_updates = false; +} + +void +PluginPinDialog::disconnect_other_thru (DataType dt, uint32_t id) +{ + _ignore_updates = true; + bool valid; + ChanMapping n_thru_map (_pi->thru_map ()); + n_thru_map.get (dt, id, &valid); + if (valid) { + n_thru_map.unset (dt, id); + _pi->set_thru_map (n_thru_map); + } + _ignore_updates = false; +} + void PluginPinDialog::handle_output_action (const CtrlElem &s, const CtrlElem &o) { @@ -1006,20 +1059,9 @@ PluginPinDialog::handle_output_action (const CtrlElem &s, const CtrlElem &o) if (valid) { out_map.unset (s->dt, s->id); } - // disconnect other outputs - _ignore_updates = true; - for (uint32_t n = 0; n < _n_plugins; ++n) { - if (n == pc) { - continue; - } - ChanMapping n_out_map (_pi->output_map (n)); - idx = n_out_map.get_src (s->dt, o->id, &valid); - if (valid) { - n_out_map.unset (s->dt, idx); - _pi->set_output_map (n, n_out_map); - } - } - _ignore_updates = false; + disconnect_other_outputs (pc, s->dt, o->id); + disconnect_other_thru (s->dt, o->id); + idx = out_map.get_src (s->dt, o->id, &valid); if (valid) { out_map.unset (s->dt, idx); @@ -1030,6 +1072,26 @@ PluginPinDialog::handle_output_action (const CtrlElem &s, const CtrlElem &o) } } +void +PluginPinDialog::handle_thru_action (const CtrlElem &o, const CtrlElem &i) +{ + bool valid; + ChanMapping thru_map (_pi->thru_map ()); + uint32_t idx = thru_map.get (o->dt, o->id, &valid); + + if (valid && idx == i->id) { + // disconnect + thru_map.unset (o->dt, o->id); + } else { + // disconnect other outputs first + disconnect_other_outputs (UINT32_MAX, o->dt, o->id); + disconnect_other_thru (o->dt, o->id); + + thru_map.set (o->dt, o->id, i->id); + } + _pi->set_thru_map (thru_map); +} + void PluginPinDialog::handle_disconnect (const CtrlElem &e) { @@ -1039,6 +1101,19 @@ PluginPinDialog::handle_disconnect (const CtrlElem &e) switch (e->ct) { case Input: + { + ChanMapping n_thru_map (_pi->thru_map ()); + for (uint32_t i = 0; i < _sources.n_total (); ++i) { + uint32_t idx = n_thru_map.get (e->dt, i, &valid); + if (valid && idx == e->id) { + n_thru_map.unset (e->dt, i); + changed = true; + } + } + if (changed) { + _pi->set_thru_map (n_thru_map); + } + } for (uint32_t n = 0; n < _n_plugins; ++n) { ChanMapping map (_pi->input_map (n)); for (uint32_t i = 0; i < _sinks.n_total (); ++i) { @@ -1083,7 +1158,18 @@ PluginPinDialog::handle_disconnect (const CtrlElem &e) changed = true; } } - _pi->set_output_map (n, map); + if (changed) { + _pi->set_output_map (n, map); + } + } + { + ChanMapping n_thru_map (_pi->thru_map ()); + n_thru_map.get (e->dt, e->id, &valid); + if (valid) { + n_thru_map.unset (e->dt, e->id); + changed = true; + _pi->set_thru_map (n_thru_map); + } } break; } diff --git a/gtk2_ardour/plugin_pin_dialog.h b/gtk2_ardour/plugin_pin_dialog.h index 70e4fca3f7..ac7912f908 100644 --- a/gtk2_ardour/plugin_pin_dialog.h +++ b/gtk2_ardour/plugin_pin_dialog.h @@ -125,7 +125,10 @@ private: void add_sidechain_port (ARDOUR::DataType); void handle_input_action (const CtrlElem &, const CtrlElem &); void handle_output_action (const CtrlElem &, const CtrlElem &); + void handle_thru_action (const CtrlElem &, const CtrlElem &); void handle_disconnect (const CtrlElem &); + void disconnect_other_outputs (uint32_t skip_pc, ARDOUR::DataType dt, uint32_t id); + void disconnect_other_thru (ARDOUR::DataType dt, uint32_t id); void add_port_to_table (boost::shared_ptr, uint32_t, bool); void remove_port (boost::weak_ptr); void disconnect_port (boost::weak_ptr); diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc index a058788e7f..ff6731e6e7 100644 --- a/gtk2_ardour/processor_box.cc +++ b/gtk2_ardour/processor_box.cc @@ -1025,12 +1025,16 @@ ProcessorEntry::RoutingIcon::set ( const ARDOUR::ChanCount& sinks, const ARDOUR::ChanCount& sources, const ARDOUR::ChanMapping& in_map, - const ARDOUR::ChanMapping& out_map) + const ARDOUR::ChanMapping& out_map, + const ARDOUR::ChanMapping& thru_map) { - _in = in; _out = out; - _sources = sources; _sinks = sinks; - _in_map = in_map; _out_map = out_map; - + _in = in; + _out = out; + _sources = sources; + _sinks = sinks; + _in_map = in_map; + _out_map = out_map; + _thru_map = thru_map; } bool @@ -1060,6 +1064,9 @@ ProcessorEntry::RoutingIcon::out_identity () const { if (_out_map.count () != _sources.n_total () || _out.n_total () != _sources.n_total ()) { return false; } + if (_thru_map.count () > 0) { + return false; + } return true; } @@ -1067,12 +1074,14 @@ void ProcessorEntry::RoutingIcon::set_feed ( const ARDOUR::ChanCount& out, const ARDOUR::ChanCount& sources, - const ARDOUR::ChanMapping& out_map) + const ARDOUR::ChanMapping& out_map, + const ARDOUR::ChanMapping& thru_map) { - _f_out = out; - _f_sources = sources; - _f_out_map = out_map; - _feed = true; + _f_out = out; + _f_sources = sources; + _f_out_map = out_map; + _f_thru_map = thru_map; + _feed = true; } double @@ -1138,6 +1147,22 @@ ProcessorEntry::RoutingIcon::draw_sidechain (cairo_t* cr, double x0, double heig cairo_stroke (cr); } +void +ProcessorEntry::RoutingIcon::draw_thru (cairo_t* cr, double x0, double height, bool midi) +{ + const double dx = 1 + rint (max(2., 2. * UIConfiguration::instance().get_ui_scale())); + const double y0 = rint (height * .5) - .5; + + cairo_move_to (cr, x0 - dx, y0); + cairo_line_to (cr, x0, height); + cairo_line_to (cr, x0 + dx, y0); + cairo_close_path (cr); + + set_routing_color (cr, midi); + cairo_set_line_width (cr, 1.0); + cairo_fill (cr); +} + void ProcessorEntry::RoutingIcon::draw_connection (cairo_t* cr, double x0, double x1, double y0, double y1, bool midi, bool dashed) { @@ -1224,7 +1249,13 @@ ProcessorEntry::RoutingIcon::expose_input_map (cairo_t* cr, const double width, uint32_t src = _f_out_map.get_src (dt, idx, &valid_src); if (!valid_src) { double x = pin_x_pos (i, width, pc_in, 0, false); - draw_gnd (cr, x, height, is_midi); + bool valid_thru; + _f_thru_map.get (dt, idx, &valid_thru); + if (valid_thru) { + draw_thru (cr, x, height, is_midi); + } else { + draw_gnd (cr, x, height, is_midi); + } continue; } c_x0 = pin_x_pos (src, width, _f_sources.n_total(), _f_sources.n_midi(), is_midi); @@ -1266,10 +1297,17 @@ ProcessorEntry::RoutingIcon::expose_output_map (cairo_t* cr, const double width, double x = pin_x_pos (i, width, n_out, 0, is_midi); uint32_t pn = is_midi ? i : i - n_out_midi; DataType dt = is_midi ? DataType::MIDI : DataType::AUDIO; + // TODO check thru bool valid_src; _out_map.get_src (dt, pn, &valid_src); if (!valid_src) { - draw_gnd (cr, x, height, is_midi); + bool valid_thru; + _thru_map.get (dt, pn, &valid_thru); + if (valid_thru) { + draw_thru (cr, x, height, is_midi); + } else { + draw_gnd (cr, x, height, is_midi); + } } set_routing_color (cr, is_midi); cairo_move_to (cr, x , height); @@ -2619,10 +2657,11 @@ ProcessorBox::setup_routing_feeds () sinks * count + midi_thru, sources * count + midi_bypass, input_map, - pi->output_map ()); + pi->output_map (), + pi->thru_map ()); if (next != children.end()) { - (*next)->routing_icon.set_feed (out, sources * count + midi_bypass, pi->output_map ()); + (*next)->routing_icon.set_feed (out, sources * count + midi_bypass, pi->output_map (), pi->thru_map ()); } } else { @@ -2630,15 +2669,16 @@ ProcessorBox::setup_routing_feeds () (*i)->output_icon.set_ports (p->output_streams()); ChanMapping inmap (p->input_streams ()); ChanMapping outmap (p->input_streams ()); + ChanMapping thrumap; (*i)->routing_icon.set ( p->input_streams(), p->output_streams(), p->input_streams(), p->output_streams(), - inmap, outmap); + inmap, outmap, thrumap); if (next != children.end()) { - (*next)->routing_icon.set_feed (p->output_streams(), p->output_streams(), outmap); + (*next)->routing_icon.set_feed (p->output_streams(), p->output_streams(), outmap, thrumap); } } diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h index 8336864a6c..de3eaf03ab 100644 --- a/gtk2_ardour/processor_box.h +++ b/gtk2_ardour/processor_box.h @@ -290,23 +290,27 @@ private: const ARDOUR::ChanCount&, const ARDOUR::ChanCount&, const ARDOUR::ChanMapping&, + const ARDOUR::ChanMapping&, const ARDOUR::ChanMapping&); void set_feed ( const ARDOUR::ChanCount&, const ARDOUR::ChanCount&, + const ARDOUR::ChanMapping&, const ARDOUR::ChanMapping&); void copy_state (const RoutingIcon& other) { - _in = other._in; - _out = other._out; - _sources = other._sources; - _sinks = other._sinks; - _in_map = other._in_map; - _out_map = other._out_map; - _f_out = other._f_out; - _f_out_map = other._f_out_map; - _f_sources = other._f_sources; - _feed = other._feed; + _in = other._in; + _out = other._out; + _sources = other._sources; + _sinks = other._sinks; + _in_map = other._in_map; + _out_map = other._out_map; + _thru_map = other._thru_map; + _f_out = other._f_out; + _f_out_map = other._f_out_map; + _f_thru_map = other._f_thru_map; + _f_sources = other._f_sources; + _feed = other._feed; } void unset_feed () { _feed = false ; } @@ -318,6 +322,7 @@ private: static void draw_gnd (cairo_t*, double, double, bool); static void draw_X (cairo_t*, double, double, bool); static void draw_sidechain (cairo_t*, double, double, bool); + static void draw_thru (cairo_t*, double, double, bool); private: bool on_expose_event (GdkEventExpose *); @@ -330,8 +335,10 @@ private: ARDOUR::ChanCount _sinks; ARDOUR::ChanMapping _in_map; ARDOUR::ChanMapping _out_map; + ARDOUR::ChanMapping _thru_map; ARDOUR::ChanCount _f_out; ARDOUR::ChanMapping _f_out_map; + ARDOUR::ChanMapping _f_thru_map; ARDOUR::ChanCount _f_sources; bool _feed; bool _input; -- cgit v1.2.3