GUI support for plugin port bypass connections
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user