GUI support for plugin port bypass connections

This commit is contained in:
Robin Gareus
2016-04-07 18:36:04 +02:00
parent 18713b7d1f
commit 3868c5b4a4
4 changed files with 181 additions and 45 deletions

View File

@@ -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<Pango::Layout> 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;
}

View File

@@ -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<ARDOUR::Port>, uint32_t, bool);
void remove_port (boost::weak_ptr<ARDOUR::Port>);
void disconnect_port (boost::weak_ptr<ARDOUR::Port>);

View File

@@ -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);
}
}

View File

@@ -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;