2 * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
3 * Copyright (C) 2011 Paul Davis
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include <gtkmm/table.h>
21 #include <gtkmm/box.h>
22 #include <gtkmm/label.h>
24 #include "gtkmm2ext/utils.h"
25 #include "gtkmm2ext/rgb_macros.h"
27 #include "ardour/plugin.h"
29 #include "io_selector.h"
30 #include "plugin_pin_dialog.h"
31 #include "gui_thread.h"
32 #include "ui_config.h"
36 using namespace ARDOUR;
40 using namespace Gtkmm2ext;
42 PluginPinDialog::PluginPinDialog (boost::shared_ptr<ARDOUR::PluginInsert> pi)
43 : ArdourWindow (string_compose (_("Pin Configuration: %1"), pi->name ()))
44 , _ind_strict_io (_("Strict I/O"))
45 , _ind_customized (_("Customized"))
46 , _rst_config (_("Configuration"))
47 , _rst_mapping (_("Connections"))
48 , _tgl_sidechain (_("Enable"))
49 , _edt_sidechain (_("Connect"))
50 , _add_plugin (_("+"))
51 , _del_plugin (_("-"))
52 , _add_output_audio (_("+"))
53 , _del_output_audio (_("-"))
54 , _add_output_midi (_("+"))
55 , _del_output_midi (_("-"))
59 , _position_valid (false)
60 , _ignore_updates (false)
62 assert (pi->owner ()); // Route
64 _pi->PluginIoReConfigure.connect (
65 _plugin_connections, invalidator (*this), boost::bind (&PluginPinDialog::plugin_reconfigured, this), gui_context ()
68 _pi->PluginMapChanged.connect (
69 _plugin_connections, invalidator (*this), boost::bind (&PluginPinDialog::plugin_reconfigured, this), gui_context ()
72 _pi->PluginConfigChanged.connect (
73 _plugin_connections, invalidator (*this), boost::bind (&PluginPinDialog::plugin_reconfigured, this), gui_context ()
76 // needs a better way: insensitive indicators
77 _ind_strict_io.set_sensitive (false); // track status
78 _ind_strict_io.set_name ("rude solo");
79 _ind_customized.set_sensitive (false); // plugin status
80 _ind_customized.set_name ("rude solo");
84 Table* t = manage (new Table (4, 3));
85 t->set_border_width (0);
88 l = manage (new Label (_("Track/Bus:"), ALIGN_END));
89 t->attach (*l, 0, 1, r, r + 1);
90 l = manage (new Label ());
91 l->set_alignment (ALIGN_START);
92 l->set_padding (2, 1);
93 l->set_ellipsize (Pango::ELLIPSIZE_MIDDLE);
94 l->set_width_chars (24);
95 l->set_max_width_chars (24);
96 l->set_text (_route ()->name ());
97 t->attach (*l, 1, 3, r, r + 1);
100 l = manage (new Label (_("Plugin:"), ALIGN_END));
101 t->attach (*l, 0, 1, r, r + 1);
102 l = manage (new Label ());
103 l->set_alignment (ALIGN_START);
104 l->set_padding (2, 1);
105 l->set_ellipsize (Pango::ELLIPSIZE_MIDDLE);
106 l->set_width_chars (24);
107 l->set_max_width_chars (24);
108 l->set_text (pi->name ());
109 t->attach (*l, 1, 3, r, r + 1);
112 l = manage (new Label (_("Status:"), ALIGN_END));
113 t->attach (*l, 0, 1, r, r + 1);
114 t->attach (_ind_strict_io, 1, 2, r, r + 1, FILL, SHRINK);
115 t->attach (_ind_customized, 2, 3, r, r + 1, FILL, SHRINK);
118 l = manage (new Label (_("Reset:"), ALIGN_END));
119 t->attach (*l, 0, 1, r, r + 1);
120 t->attach (_rst_mapping, 1, 2, r, r + 1, FILL, SHRINK);
121 t->attach (_rst_config, 2, 3, r, r + 1, FILL, SHRINK);
124 l = manage (new Label (_("Sidechain:"), ALIGN_END));
125 t->attach (*l, 0, 1, r, r + 1);
126 t->attach (_tgl_sidechain, 1, 2, r, r + 1, FILL, SHRINK);
127 t->attach (_edt_sidechain, 2, 3, r, r + 1, FILL, SHRINK);
130 l = manage (new Label (_("Instances:"), ALIGN_END));
131 t->attach (*l, 0, 1, r, r + 1);
132 t->attach (_add_plugin, 1, 2, r, r + 1, SHRINK, SHRINK);
133 t->attach (_del_plugin, 2, 3, r, r + 1, SHRINK, SHRINK);
136 l = manage (new Label (_("Audio Out:"), ALIGN_END));
137 t->attach (*l, 0, 1, r, r + 1);
138 t->attach (_add_output_audio, 1, 2, r, r + 1, SHRINK, SHRINK);
139 t->attach (_del_output_audio, 2, 3, r, r + 1, SHRINK, SHRINK);
142 l = manage (new Label (_("Midi Out:"), ALIGN_END));
143 t->attach (*l, 0, 1, r, r + 1);
144 t->attach (_add_output_midi, 1, 2, r, r + 1, SHRINK, SHRINK);
145 t->attach (_del_output_midi, 2, 3, r, r + 1, SHRINK, SHRINK);
148 HBox* hbox = manage (new HBox);
149 hbox->pack_start (darea, true, true);
150 hbox->pack_start (*t, false, true);
152 VBox* vbox = manage (new VBox);
153 vbox->pack_start (*hbox, true, true);
157 plugin_reconfigured ();
159 darea.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
160 darea.signal_size_request ().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_size_request));
161 darea.signal_size_allocate ().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_size_allocate));
162 darea.signal_expose_event ().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_expose_event));
163 darea.signal_button_press_event ().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_button_press_event));
164 darea.signal_button_release_event ().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_button_release_event));
165 darea.signal_motion_notify_event ().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_motion_notify_event));
167 _tgl_sidechain.signal_clicked.connect (sigc::mem_fun (*this, &PluginPinDialog::toggle_sidechain));
168 _edt_sidechain.signal_clicked.connect (sigc::mem_fun (*this, &PluginPinDialog::connect_sidechain));
170 _rst_mapping.signal_clicked.connect (sigc::mem_fun (*this, &PluginPinDialog::reset_mapping));
171 _rst_config.signal_clicked.connect (sigc::mem_fun (*this, &PluginPinDialog::reset_configuration));
172 _add_plugin.signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &PluginPinDialog::add_remove_plugin_clicked), true));
173 _del_plugin.signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &PluginPinDialog::add_remove_plugin_clicked), false));
175 _add_output_audio.signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &PluginPinDialog::add_remove_port_clicked), true, DataType::AUDIO));
176 _del_output_audio.signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &PluginPinDialog::add_remove_port_clicked), false, DataType::AUDIO));
177 _add_output_midi.signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &PluginPinDialog::add_remove_port_clicked), true, DataType::MIDI));
178 _del_output_midi.signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &PluginPinDialog::add_remove_port_clicked), false, DataType::MIDI));
181 PluginPinDialog::~PluginPinDialog ()
186 PluginPinDialog::plugin_reconfigured ()
188 if (_ignore_updates) {
191 _n_plugins = _pi->get_count ();
192 _pi->configured_io (_in, _out);
193 _ins = _pi->internal_streams (); // with sidechain
194 _sinks = _pi->natural_input_streams ();
195 _sources = _pi->natural_output_streams ();
197 _del_plugin.set_sensitive (_n_plugins > 1);
198 _del_output_audio.set_sensitive (_out.n_audio () > 0 && _out.n_total () > 1);
199 _del_output_midi.set_sensitive (_out.n_midi () > 0 && _out.n_total () > 1);
200 _ind_strict_io.set_active (_pi->strict_io ());
201 _ind_customized.set_active (_pi->custom_cfg ());
202 _tgl_sidechain.set_active (_pi->has_sidechain ());
203 _edt_sidechain.set_sensitive (_pi->has_sidechain ()); // && _session
205 // calc minimum width
206 const uint32_t max_ports = std::max (_ins.n_total (), _out.n_total ());
207 const uint32_t max_pins = std::max ((_sinks * _n_plugins).n_total (), (_sources * _n_plugins).n_total ());
208 uint32_t min_width = std::max (25 * max_ports, (uint32_t)(20 + _pin_box_size) * max_pins);
209 min_width = std::max (min_width, 64 * _n_plugins); // bxh2 = 18 ; aspect 16:9 (incl. 10% space)
210 min_width = std::max ((uint32_t)300, min_width);
211 min_width = 10 * ceilf (min_width / 10.f);
212 if (min_width != _min_width) {
213 _min_width = min_width;
214 darea.queue_resize ();
221 PluginPinDialog::update_elements ()
228 for (uint32_t i = 0; i < _ins.n_total (); ++i) {
229 int id = (i < _ins.n_midi ()) ? i : i - _ins.n_midi ();
230 bool sidechain = i >= _in.n_total () ? true : false;
232 CtrlWidget cw (CtrlWidget (Input, (i < _ins.n_midi () ? DataType::MIDI : DataType::AUDIO), id, 0, sidechain));
233 _elements.push_back (cw);
236 for (uint32_t i = 0; i < _out.n_total (); ++i) {
237 int id = (i < _out.n_midi ()) ? i : i - _out.n_midi ();
238 _elements.push_back (CtrlWidget (Output, (i < _out.n_midi () ? DataType::MIDI : DataType::AUDIO), id));
241 for (uint32_t n = 0; n < _n_plugins; ++n) {
242 boost::shared_ptr<Plugin> plugin = _pi->plugin (n);
243 for (uint32_t i = 0; i < _sinks.n_total (); ++i) {
244 DataType dt (_sinks.n_midi () ? DataType::MIDI : DataType::AUDIO);
245 int idx = (i < _sinks.n_midi ()) ? i : i - _sinks.n_midi ();
246 const Plugin::IOPortDescription& iod (plugin->describe_io_port (dt, true, idx));
247 CtrlWidget cw (CtrlWidget (Sink, dt, i, n, iod.is_sidechain));
248 _elements.push_back (cw);
250 for (uint32_t i = 0; i < _sources.n_total (); ++i) {
251 _elements.push_back (CtrlWidget (Source, (i < _sources.n_midi () ? DataType::MIDI : DataType::AUDIO), i, n));
254 _position_valid = false;
259 PluginPinDialog::update_element_pos ()
262 const double yc = rint (_height * .5);
263 const double bxh2 = 18;
264 const double bxw = rint ((_width * .9) / ((_n_plugins) + .2 * (_n_plugins - 1)));
265 const double bxw2 = rint (bxw * .5);
266 const double y_in = 40;
267 const double y_out = _height - 40;
269 _pin_box_size = rint (max (6., 8. * UIConfiguration::instance ().get_ui_scale ()));
270 const double dx = ceil (_pin_box_size * .5);
272 for (CtrlElemList::iterator i = _elements.begin (); i != _elements.end (); ++i) {
276 uint32_t idx = i->e->id;
277 if (i->e->dt == DataType::AUDIO) { idx += _ins.n_midi (); }
278 i->x = rint ((idx + 1) * _width / (1. + _ins.n_total ())) - 0.5 - dx;
286 uint32_t idx = i->e->id;
287 if (i->e->dt == DataType::AUDIO) { idx += _out.n_midi (); }
288 i->x = rint ((idx + 1) * _width / (1. + _out.n_total ())) - 0.5 - dx;
296 const double x0 = rint ((i->e->ip + .5) * _width / (double)(_n_plugins)) - .5 - bxw2;
297 i->x = rint (x0 + (i->e->id + 1) * bxw / (1. + _sinks.n_total ())) - .5 - _pin_box_size * .5;
298 i->y = yc - bxh2 - _pin_box_size;
299 i->w = _pin_box_size + 1;
300 i->h = _pin_box_size;
305 const double x0 = rint ((i->e->ip + .5) * _width / (double)(_n_plugins)) - .5 - bxw2;
306 i->x = rint (x0 + (i->e->id + 1) * bxw / (1. + _sources.n_total ())) - .5 - _pin_box_size * .5;
308 i->w = _pin_box_size + 1;
309 i->h = _pin_box_size;
318 PluginPinDialog::set_color (cairo_t* cr, bool midi)
320 // see also gtk2_ardour/processor_box.cc
321 static const uint32_t audio_port_color = 0x4A8A0EFF; // Green
322 static const uint32_t midi_port_color = 0x960909FF; //Red
325 cairo_set_source_rgb (cr,
326 UINT_RGBA_R_FLT (midi_port_color),
327 UINT_RGBA_G_FLT (midi_port_color),
328 UINT_RGBA_B_FLT (midi_port_color));
330 cairo_set_source_rgb (cr,
331 UINT_RGBA_R_FLT (audio_port_color),
332 UINT_RGBA_G_FLT (audio_port_color),
333 UINT_RGBA_B_FLT (audio_port_color));
338 PluginPinDialog::draw_io_pin (cairo_t* cr, const CtrlWidget& w)
340 const double dir = (w.e->ct == Input) ? 1 : -1;
341 const double dx = ceil (_pin_box_size * .5);
342 const double dy = min (36.0, 6. * dx);
344 cairo_move_to (cr, w.x + dx, w.y + ((w.e->ct == Input) ? 25 : 0));
345 cairo_rel_line_to (cr, -dx, -dx * dir);
346 cairo_rel_line_to (cr, 0., -dy * dir);
347 cairo_rel_line_to (cr, 2. * dx, 0.);
348 cairo_rel_line_to (cr, 0., dy * dir);
349 cairo_close_path (cr);
353 assert (w.e->ct == Input);
355 cairo_set_source_rgb (cr, .1, .6, .7);
357 set_color (cr, w.e->dt == DataType::MIDI);
359 if (w.e == _selection || w.e == _actor) {
360 cairo_fill_preserve (cr);
361 cairo_set_source_rgba (cr, 0.9, 0.9, 1.0, 0.6);
362 } else if (w.prelight) {
363 cairo_fill_preserve (cr);
364 cairo_set_source_rgba (cr, 0.9, 0.9, 0.9, 0.3);
366 cairo_fill_preserve (cr);
368 cairo_set_line_width (cr, 1.0);
369 cairo_set_source_rgb (cr, 0, 0, 0);
374 PluginPinDialog::draw_plugin_pin (cairo_t* cr, const CtrlWidget& w)
376 cairo_rectangle (cr, w.x, w.y, w.w, w.h);
379 assert (w.e->ct == Sink);
381 cairo_set_source_rgb (cr, .1, .6, .7);
383 set_color (cr, w.e->dt == DataType::MIDI);
386 if (w.e == _selection || w.e == _actor) {
387 cairo_fill_preserve (cr);
388 cairo_set_source_rgba (cr, 0.9, 0.9, 1.0, 0.6);
389 } else if (w.prelight) {
390 cairo_fill_preserve (cr);
391 cairo_set_source_rgba (cr, 0.9, 0.9, 0.9, 0.3);
397 PluginPinDialog::pin_x_pos (uint32_t i, double x0, double width, uint32_t n_total, uint32_t n_midi, bool midi)
399 if (!midi) { i += n_midi; }
400 return rint (x0 + (i + 1) * width / (1. + n_total)) - .5;
404 PluginPinDialog::draw_connection (cairo_t* cr, double x0, double x1, double y0, double y1, bool midi, bool dashed)
406 const double bz = 2 * _pin_box_size;
407 const double bc = (dashed && x0 == x1) ? 1.25 * _pin_box_size : 0;
409 cairo_move_to (cr, x0, y0);
410 cairo_curve_to (cr, x0 - bc, y0 + bz, x1 - bc, y1 - bz, x1, y1);
411 cairo_set_line_width (cr, 3.0);
412 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
413 cairo_set_source_rgb (cr, 1, 0, 0);
415 const double dashes[] = { 5, 7 };
416 cairo_set_dash (cr, dashes, 2, 0);
418 set_color (cr, midi);
421 cairo_set_dash (cr, 0, 0, 0);
426 PluginPinDialog::darea_expose_event (GdkEventExpose* ev)
428 Gtk::Allocation a = darea.get_allocation ();
429 double const width = a.get_width ();
430 double const height = a.get_height ();
432 if (!_position_valid) {
435 update_element_pos ();
436 _position_valid = true;
439 cairo_t* cr = gdk_cairo_create (darea.get_window ()->gobj ());
440 cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
443 Gdk::Color const bg = get_style ()->get_bg (STATE_NORMAL);
444 cairo_set_source_rgb (cr, bg.get_red_p (), bg.get_green_p (), bg.get_blue_p ());
445 cairo_rectangle (cr, 0, 0, width, height);
448 /* layout sizes -- TODO consolidate w/ update_element_pos() */
450 const double y_in = 40;
451 const double y_out = height - 40;
454 const double yc = rint (height * .5);
455 const double bxh2 = 18;
456 const double bxw = rint ((width * .9) / ((_n_plugins) + .2 * (_n_plugins - 1)));
457 const double bxw2 = rint (bxw * .5);
459 const uint32_t pc_in = _ins.n_total ();
460 const uint32_t pc_in_midi = _ins.n_midi ();
461 const uint32_t pc_out = _out.n_total ();
462 const uint32_t pc_out_midi = _out.n_midi ();
464 /* draw midi-bypass (behind) */
465 if (_pi->has_midi_bypass ()) {
466 double x0 = rint (width / (1. + pc_in)) - .5;
467 double x1 = rint (width / (1. + pc_out)) - .5;
468 draw_connection (cr, x0, x1, y_in, y_out, true, true);
471 /* plugins & connection wires */
472 for (uint32_t i = 0; i < _n_plugins; ++i) {
473 double x0 = rint ((i + .5) * width / (double)(_n_plugins)) - .5;
476 cairo_set_source_rgb (cr, .3, .3, .3);
477 rounded_rectangle (cr, x0 - bxw2, yc - bxh2, bxw, 2 * bxh2, 7);
480 const ChanMapping::Mappings in_map = _pi->input_map (i).mappings ();
481 const ChanMapping::Mappings out_map = _pi->output_map (i).mappings ();
483 for (ChanMapping::Mappings::const_iterator t = in_map.begin (); t != in_map.end (); ++t) {
484 bool is_midi = t->first == DataType::MIDI;
485 for (ChanMapping::TypeMapping::const_iterator c = (*t).second.begin (); c != (*t).second.end () ; ++c) {
486 uint32_t pn = (*c).first; // pin
487 uint32_t pb = (*c).second;
488 double c_x0 = pin_x_pos (pb, 0, width, pc_in, pc_in_midi, is_midi);
489 double c_x1 = pin_x_pos (pn, x0 - bxw2, bxw, _sinks.n_total (), _sinks.n_midi (), is_midi);
490 draw_connection (cr, c_x0, c_x1, y_in, yc - bxh2 - _pin_box_size, is_midi);
494 for (ChanMapping::Mappings::const_iterator t = out_map.begin (); t != out_map.end (); ++t) {
495 bool is_midi = t->first == DataType::MIDI;
496 for (ChanMapping::TypeMapping::const_iterator c = (*t).second.begin (); c != (*t).second.end () ; ++c) {
497 uint32_t pn = (*c).first; // pin
498 uint32_t pb = (*c).second;
499 double c_x0 = pin_x_pos (pn, x0 - bxw2, bxw, _sources.n_total (), _sources.n_midi (), is_midi);
500 double c_x1 = pin_x_pos (pb, 0, width, pc_out, pc_out_midi, is_midi);
501 draw_connection (cr, c_x0, c_x1, yc + bxh2 + _pin_box_size, y_out, is_midi);
507 for (CtrlElemList::const_iterator i = _elements.begin (); i != _elements.end (); ++i) {
511 draw_io_pin (cr, *i);
515 draw_plugin_pin (cr, *i);
525 PluginPinDialog::darea_size_request (Gtk::Requisition* req)
527 req->width = _min_width;
532 PluginPinDialog::darea_size_allocate (Gtk::Allocation&)
534 _position_valid = false;
538 PluginPinDialog::darea_motion_notify_event (GdkEventMotion* ev)
540 bool changed = false;
542 for (CtrlElemList::iterator i = _elements.begin (); i != _elements.end (); ++i) {
543 if (ev->x >= i->x && ev->x <= i->x + i->w
544 && ev->y >= i->y && ev->y <= i->y + i->h)
546 if (!i->prelight) changed = true;
550 if (i->prelight) changed = true;
561 PluginPinDialog::darea_button_press_event (GdkEventButton* ev)
563 if (ev->type != GDK_BUTTON_PRESS) {
567 switch (ev->button) {
569 if (!_selection || (_selection && !_hover)) {
573 } else if (_selection && _hover && _selection != _hover) {
574 if (_selection->dt != _hover->dt) { _actor.reset (); }
575 else if (_selection->ct == Input && _hover->ct == Sink) { _actor = _hover; }
576 else if (_selection->ct == Sink && _hover->ct == Input) { _actor = _hover; }
577 else if (_selection->ct == Output && _hover->ct == Source) { _actor = _hover; }
578 else if (_selection->ct == Source && _hover->ct == Output) { _actor = _hover; }
596 PluginPinDialog::darea_button_release_event (GdkEventButton* ev)
598 if (_hover == _actor && _actor) {
600 assert (_selection->dt == _actor->dt);
601 if (_selection->ct == Input && _actor->ct == Sink) {
602 handle_input_action (_actor, _selection);
604 else if (_selection->ct == Sink && _actor->ct == Input) {
605 handle_input_action (_selection, _actor);
607 else if (_selection->ct == Output && _actor->ct == Source) {
608 handle_output_action (_actor, _selection);
610 else if (_selection->ct == Source && _actor->ct == Output) {
611 handle_output_action (_selection, _actor);
621 PluginPinDialog::handle_input_action (const CtrlElem &s, const CtrlElem &i)
623 const int pc = s->ip;
625 ChanMapping in_map (_pi->input_map (pc));
626 uint32_t idx = in_map.get (s->dt, s->id, &valid);
628 if (valid && idx == i->id) {
630 in_map.unset (s->dt, s->id);
631 _pi->set_input_map (pc, in_map);
635 in_map.set (s->dt, s->id, i->id);
636 _pi->set_input_map (pc, in_map);
640 in_map.unset (s->dt, s->id);
641 in_map.set (s->dt, s->id, i->id);
642 _pi->set_input_map (pc, in_map);
647 PluginPinDialog::handle_output_action (const CtrlElem &s, const CtrlElem &o)
649 const uint32_t pc = s->ip;
651 ChanMapping out_map (_pi->output_map (pc));
652 uint32_t idx = out_map.get (s->dt, s->id, &valid);
654 if (valid && idx == o->id) {
656 out_map.unset (s->dt, s->id);
657 _pi->set_output_map (pc, out_map);
662 out_map.unset (s->dt, s->id);
664 // disconnect other outputs
665 _ignore_updates = true;
666 for (uint32_t n = 0; n < _n_plugins; ++n) {
670 ChanMapping n_out_map (_pi->output_map (n));
671 idx = n_out_map.get_src (s->dt, o->id, &valid);
673 n_out_map.unset (s->dt, idx);
674 _pi->set_output_map (n, n_out_map);
677 _ignore_updates = false;
678 idx = out_map.get_src (s->dt, o->id, &valid);
680 out_map.unset (s->dt, idx);
683 out_map.set (s->dt, s->id, o->id);
684 _pi->set_output_map (pc, out_map);
689 PluginPinDialog::toggle_sidechain ()
691 _route ()->add_remove_sidechain (_pi, !_pi->has_sidechain ());
695 PluginPinDialog::connect_sidechain ()
697 if (!_session) { return; }
698 // TODO non-modal would be cooler ... :)
699 SideChainUI sc (*this, _session, _pi->sidechain_input ());
704 PluginPinDialog::reset_configuration ()
706 _route ()->reset_plugin_insert (_pi);
710 PluginPinDialog::reset_mapping ()
716 PluginPinDialog::add_remove_plugin_clicked (bool add)
718 ChanCount out = _out;
719 assert (add || _n_plugins > 0);
720 _route ()->customize_plugin_insert (_pi, _n_plugins + (add ? 1 : -1), out);
724 PluginPinDialog::add_remove_port_clicked (bool add, ARDOUR::DataType dt)
726 ChanCount out = _out;
727 assert (add || out.get (dt) > 0);
728 out.set (dt, out.get (dt) + (add ? 1 : -1));
729 _route ()->customize_plugin_insert (_pi, _n_plugins, out);
732 SideChainUI::SideChainUI (Gtk::Window& p, Session* session, boost::shared_ptr<IO> sc)
733 : ArdourDialog (p, string (_("Sidechain ")) + sc->name (), true)
735 HBox* hbox = manage (new HBox);
736 IOSelector * io = Gtk::manage (new IOSelector (this, session, sc));
737 hbox->pack_start (*io, true, true);
738 get_vbox ()->pack_start (*hbox, true, true);