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 "io_selector.h"
28 #include "plugin_pin_dialog.h"
29 #include "gui_thread.h"
30 #include "ui_config.h"
34 using namespace ARDOUR;
38 using namespace Gtkmm2ext;
40 PluginPinDialog::PluginPinDialog (boost::shared_ptr<ARDOUR::PluginInsert> pi)
41 : ArdourWindow (string_compose (_("Pin Configuration: %1"), pi->name ()))
42 , _ind_strict_io (_("Strict I/O"))
43 , _ind_customized (_("Customized"))
44 , _rst_config (_("Configuration"))
45 , _rst_mapping (_("Connections"))
46 , _tgl_sidechain (_("Enable"))
47 , _edt_sidechain (_("Connect"))
48 , _add_plugin (_("+"))
49 , _del_plugin (_("-"))
50 , _add_output_audio (_("+"))
51 , _del_output_audio (_("-"))
52 , _add_output_midi (_("+"))
53 , _del_output_midi (_("-"))
57 , _position_valid (false)
58 , _ignore_updates (false)
60 assert (pi->owner ()); // Route
62 _pi->PluginIoReConfigure.connect (
63 _plugin_connections, invalidator (*this), boost::bind (&PluginPinDialog::plugin_reconfigured, this), gui_context ()
66 _pi->PluginMapChanged.connect (
67 _plugin_connections, invalidator (*this), boost::bind (&PluginPinDialog::plugin_reconfigured, this), gui_context ()
70 _pi->PluginConfigChanged.connect (
71 _plugin_connections, invalidator (*this), boost::bind (&PluginPinDialog::plugin_reconfigured, this), gui_context ()
74 // needs a better way: insensitive indicators
75 _ind_strict_io.set_sensitive (false); // track status
76 _ind_strict_io.set_name ("rude solo");
77 _ind_customized.set_sensitive (false); // plugin status
78 _ind_customized.set_name ("rude solo");
82 Table* t = manage (new Table (4, 3));
83 t->set_border_width (0);
86 l = manage (new Label (_("Track/Bus:"), ALIGN_END));
87 t->attach (*l, 0, 1, r, r + 1);
88 l = manage (new Label ());
89 l->set_alignment (ALIGN_START);
90 l->set_padding (2, 1);
91 l->set_ellipsize (Pango::ELLIPSIZE_MIDDLE);
92 l->set_width_chars (24);
93 l->set_max_width_chars (24);
94 l->set_text (_route ()->name ());
95 t->attach (*l, 1, 3, r, r + 1);
98 l = manage (new Label (_("Plugin:"), ALIGN_END));
99 t->attach (*l, 0, 1, r, r + 1);
100 l = manage (new Label ());
101 l->set_alignment (ALIGN_START);
102 l->set_padding (2, 1);
103 l->set_ellipsize (Pango::ELLIPSIZE_MIDDLE);
104 l->set_width_chars (24);
105 l->set_max_width_chars (24);
106 l->set_text (pi->name ());
107 t->attach (*l, 1, 3, r, r + 1);
110 l = manage (new Label (_("Status:"), ALIGN_END));
111 t->attach (*l, 0, 1, r, r + 1);
112 t->attach (_ind_strict_io, 1, 2, r, r + 1, FILL, SHRINK);
113 t->attach (_ind_customized, 2, 3, r, r + 1, FILL, SHRINK);
116 l = manage (new Label (_("Reset:"), ALIGN_END));
117 t->attach (*l, 0, 1, r, r + 1);
118 t->attach (_rst_mapping, 1, 2, r, r + 1, FILL, SHRINK);
119 t->attach (_rst_config, 2, 3, r, r + 1, FILL, SHRINK);
122 l = manage (new Label (_("Sidechain:"), ALIGN_END));
123 t->attach (*l, 0, 1, r, r + 1);
124 t->attach (_tgl_sidechain, 1, 2, r, r + 1, FILL, SHRINK);
125 t->attach (_edt_sidechain, 2, 3, r, r + 1, FILL, SHRINK);
128 l = manage (new Label (_("Instances:"), ALIGN_END));
129 t->attach (*l, 0, 1, r, r + 1);
130 t->attach (_add_plugin, 1, 2, r, r + 1, SHRINK, SHRINK);
131 t->attach (_del_plugin, 2, 3, r, r + 1, SHRINK, SHRINK);
134 l = manage (new Label (_("Audio Out:"), ALIGN_END));
135 t->attach (*l, 0, 1, r, r + 1);
136 t->attach (_add_output_audio, 1, 2, r, r + 1, SHRINK, SHRINK);
137 t->attach (_del_output_audio, 2, 3, r, r + 1, SHRINK, SHRINK);
140 l = manage (new Label (_("Midi Out:"), ALIGN_END));
141 t->attach (*l, 0, 1, r, r + 1);
142 t->attach (_add_output_midi, 1, 2, r, r + 1, SHRINK, SHRINK);
143 t->attach (_del_output_midi, 2, 3, r, r + 1, SHRINK, SHRINK);
146 HBox* hbox = manage (new HBox);
147 hbox->pack_start (darea, true, true);
148 hbox->pack_start (*t, false, true);
150 VBox* vbox = manage (new VBox);
151 vbox->pack_start (*hbox, true, true);
155 plugin_reconfigured ();
157 darea.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
158 darea.signal_size_request ().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_size_request));
159 darea.signal_size_allocate ().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_size_allocate));
160 darea.signal_expose_event ().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_expose_event));
161 darea.signal_button_press_event ().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_button_press_event));
162 darea.signal_button_release_event ().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_button_release_event));
163 darea.signal_motion_notify_event ().connect (sigc::mem_fun (*this, &PluginPinDialog::darea_motion_notify_event));
165 _tgl_sidechain.signal_clicked.connect (sigc::mem_fun (*this, &PluginPinDialog::toggle_sidechain));
166 _edt_sidechain.signal_clicked.connect (sigc::mem_fun (*this, &PluginPinDialog::connect_sidechain));
168 _rst_mapping.signal_clicked.connect (sigc::mem_fun (*this, &PluginPinDialog::reset_mapping));
169 _rst_config.signal_clicked.connect (sigc::mem_fun (*this, &PluginPinDialog::reset_configuration));
170 _add_plugin.signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &PluginPinDialog::add_remove_plugin_clicked), true));
171 _del_plugin.signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &PluginPinDialog::add_remove_plugin_clicked), false));
173 _add_output_audio.signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &PluginPinDialog::add_remove_port_clicked), true, DataType::AUDIO));
174 _del_output_audio.signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &PluginPinDialog::add_remove_port_clicked), false, DataType::AUDIO));
175 _add_output_midi.signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &PluginPinDialog::add_remove_port_clicked), true, DataType::MIDI));
176 _del_output_midi.signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &PluginPinDialog::add_remove_port_clicked), false, DataType::MIDI));
179 PluginPinDialog::~PluginPinDialog ()
184 PluginPinDialog::plugin_reconfigured ()
186 if (_ignore_updates) {
189 _n_plugins = _pi->get_count ();
190 _pi->configured_io (_in, _out);
191 _ins = _pi->internal_streams (); // with sidechain
192 _sinks = _pi->natural_input_streams ();
193 _sources = _pi->natural_output_streams ();
195 _del_plugin.set_sensitive (_n_plugins > 1);
196 _del_output_audio.set_sensitive (_out.n_audio () > 0 && _out.n_total () > 1);
197 _del_output_midi.set_sensitive (_out.n_midi () > 0 && _out.n_total () > 1);
198 _ind_strict_io.set_active (_pi->strict_io ());
199 _ind_customized.set_active (_pi->custom_cfg ());
200 _tgl_sidechain.set_active (_pi->has_sidechain ());
201 _edt_sidechain.set_sensitive (_pi->has_sidechain ()); // && _session
203 // calc minimum width
204 const uint32_t max_ports = std::max (_ins.n_total (), _out.n_total ());
205 const uint32_t max_pins = std::max ((_sinks * _n_plugins).n_total (), (_sources * _n_plugins).n_total ());
206 uint32_t min_width = std::max (25 * max_ports, (uint32_t)(20 + _pin_box_size) * max_pins);
207 min_width = std::max (min_width, 64 * _n_plugins); // bxh2 = 18 ; aspect 16:9 (incl. 10% space)
208 min_width = std::max ((uint32_t)300, min_width);
209 min_width = 10 * ceilf (min_width / 10.f);
210 if (min_width != _min_width) {
211 _min_width = min_width;
212 darea.queue_resize ();
219 PluginPinDialog::update_elements ()
226 for (uint32_t i = 0; i < _ins.n_total (); ++i) {
227 int id = (i < _ins.n_midi ()) ? i : i - _ins.n_midi ();
228 uint32_t sidechain = i >= _in.n_total () ? -1 : 0;
229 _elements.push_back (CtrlWidget (Input, (i < _ins.n_midi () ? DataType::MIDI : DataType::AUDIO), id, sidechain));
232 for (uint32_t i = 0; i < _out.n_total (); ++i) {
233 int id = (i < _out.n_midi ()) ? i : i - _out.n_midi ();
234 _elements.push_back (CtrlWidget (Output, (i < _out.n_midi () ? DataType::MIDI : DataType::AUDIO), id));
237 for (uint32_t n = 0; n < _n_plugins; ++n) {
238 for (uint32_t i = 0; i < _sinks.n_total (); ++i) {
239 _elements.push_back (CtrlWidget (Sink, (i < _sinks.n_midi () ? DataType::MIDI : DataType::AUDIO), i, n));
241 for (uint32_t i = 0; i < _sources.n_total (); ++i) {
242 _elements.push_back (CtrlWidget (Source, (i < _sources.n_midi () ? DataType::MIDI : DataType::AUDIO), i, n));
245 _position_valid = false;
250 PluginPinDialog::update_element_pos ()
253 const double yc = rint (_height * .5);
254 const double bxh2 = 18;
255 const double bxw = rint ((_width * .9) / ((_n_plugins) + .2 * (_n_plugins - 1)));
256 const double bxw2 = rint (bxw * .5);
257 const double y_in = 40;
258 const double y_out = _height - 40;
260 _pin_box_size = rint (max (6., 8. * UIConfiguration::instance ().get_ui_scale ()));
261 const double dx = ceil (_pin_box_size * .5);
263 for (CtrlElemList::iterator i = _elements.begin (); i != _elements.end (); ++i) {
267 uint32_t idx = i->e->id;
268 if (i->e->dt == DataType::AUDIO) { idx += _ins.n_midi (); }
269 i->x = rint ((idx + 1) * _width / (1. + _ins.n_total ())) - 0.5 - dx;
277 uint32_t idx = i->e->id;
278 if (i->e->dt == DataType::AUDIO) { idx += _out.n_midi (); }
279 i->x = rint ((idx + 1) * _width / (1. + _out.n_total ())) - 0.5 - dx;
287 const double x0 = rint ((i->e->ip + .5) * _width / (double)(_n_plugins)) - .5 - bxw2;
288 i->x = rint (x0 + (i->e->id + 1) * bxw / (1. + _sinks.n_total ())) - .5 - _pin_box_size * .5;
289 i->y = yc - bxh2 - _pin_box_size;
290 i->w = _pin_box_size + 1;
291 i->h = _pin_box_size;
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. + _sources.n_total ())) - .5 - _pin_box_size * .5;
299 i->w = _pin_box_size + 1;
300 i->h = _pin_box_size;
309 PluginPinDialog::set_color (cairo_t* cr, bool midi)
311 // see also gtk2_ardour/processor_box.cc
312 static const uint32_t audio_port_color = 0x4A8A0EFF; // Green
313 static const uint32_t midi_port_color = 0x960909FF; //Red
316 cairo_set_source_rgb (cr,
317 UINT_RGBA_R_FLT (midi_port_color),
318 UINT_RGBA_G_FLT (midi_port_color),
319 UINT_RGBA_B_FLT (midi_port_color));
321 cairo_set_source_rgb (cr,
322 UINT_RGBA_R_FLT (audio_port_color),
323 UINT_RGBA_G_FLT (audio_port_color),
324 UINT_RGBA_B_FLT (audio_port_color));
329 PluginPinDialog::draw_io_pin (cairo_t* cr, const CtrlWidget& w)
331 const double dir = (w.e->ct == Input) ? 1 : -1;
332 const double dx = ceil (_pin_box_size * .5);
333 const double dy = min (36.0, 6. * dx);
335 cairo_move_to (cr, w.x + dx, w.y + ((w.e->ct == Input) ? 25 : 0));
336 cairo_rel_line_to (cr, -dx, -dx * dir);
337 cairo_rel_line_to (cr, 0., -dy * dir);
338 cairo_rel_line_to (cr, 2. * dx, 0.);
339 cairo_rel_line_to (cr, 0., dy * dir);
340 cairo_close_path (cr);
344 assert (w.e->ct == Input);
346 cairo_set_source_rgb (cr, .1, .6, .7);
348 set_color (cr, w.e->dt == DataType::MIDI);
350 if (w.e == _selection || w.e == _actor) {
351 cairo_fill_preserve (cr);
352 cairo_set_source_rgba (cr, 0.9, 0.9, 1.0, 0.6);
353 } else if (w.prelight) {
354 cairo_fill_preserve (cr);
355 cairo_set_source_rgba (cr, 0.9, 0.9, 0.9, 0.3);
357 cairo_fill_preserve (cr);
359 cairo_set_line_width (cr, 1.0);
360 cairo_set_source_rgb (cr, 0, 0, 0);
365 PluginPinDialog::draw_plugin_pin (cairo_t* cr, const CtrlWidget& w)
367 cairo_rectangle (cr, w.x, w.y, w.w, w.h);
368 set_color (cr, w.e->dt == DataType::MIDI);
369 if (w.e == _selection || w.e == _actor) {
370 cairo_fill_preserve (cr);
371 cairo_set_source_rgba (cr, 0.9, 0.9, 1.0, 0.6);
372 } else if (w.prelight) {
373 cairo_fill_preserve (cr);
374 cairo_set_source_rgba (cr, 0.9, 0.9, 0.9, 0.3);
380 PluginPinDialog::pin_x_pos (uint32_t i, double x0, double width, uint32_t n_total, uint32_t n_midi, bool midi)
382 if (!midi) { i += n_midi; }
383 return rint (x0 + (i + 1) * width / (1. + n_total)) - .5;
387 PluginPinDialog::draw_connection (cairo_t* cr, double x0, double x1, double y0, double y1, bool midi, bool dashed)
389 const double bz = 2 * _pin_box_size;
390 const double bc = dashed ? 1.25 * _pin_box_size : 0;
392 cairo_move_to (cr, x0, y0);
393 cairo_curve_to (cr, x0 - bc, y0 + bz, x1 - bc, y1 - bz, x1, y1);
394 cairo_set_line_width (cr, 3.0);
395 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
396 cairo_set_source_rgb (cr, 1, 0, 0);
398 const double dashes[] = { 5, 7 };
399 cairo_set_dash (cr, dashes, 2, 0);
401 set_color (cr, midi);
404 cairo_set_dash (cr, 0, 0, 0);
409 PluginPinDialog::darea_expose_event (GdkEventExpose* ev)
411 Gtk::Allocation a = darea.get_allocation ();
412 double const width = a.get_width ();
413 double const height = a.get_height ();
415 if (!_position_valid) {
418 update_element_pos ();
419 _position_valid = true;
422 cairo_t* cr = gdk_cairo_create (darea.get_window ()->gobj ());
423 cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
426 Gdk::Color const bg = get_style ()->get_bg (STATE_NORMAL);
427 cairo_set_source_rgb (cr, bg.get_red_p (), bg.get_green_p (), bg.get_blue_p ());
428 cairo_rectangle (cr, 0, 0, width, height);
431 /* layout sizes -- TODO consolidate w/ update_element_pos() */
433 const double y_in = 40;
434 const double y_out = height - 40;
437 const double yc = rint (height * .5);
438 const double bxh2 = 18;
439 const double bxw = rint ((width * .9) / ((_n_plugins) + .2 * (_n_plugins - 1)));
440 const double bxw2 = rint (bxw * .5);
442 const uint32_t pc_in = _ins.n_total ();
443 const uint32_t pc_in_midi = _ins.n_midi ();
444 const uint32_t pc_out = _out.n_total ();
445 const uint32_t pc_out_midi = _out.n_midi ();
447 /* draw midi-bypass (behind) */
448 if (_pi->has_midi_bypass ()) {
449 double x0 = rint (width / (1. + pc_in)) - .5;
450 double x1 = rint (width / (1. + pc_out)) - .5;
451 draw_connection (cr, x0, x1, y_in, y_out, true, true);
454 /* plugins & connection wires */
455 for (uint32_t i = 0; i < _n_plugins; ++i) {
456 double x0 = rint ((i + .5) * width / (double)(_n_plugins)) - .5;
459 cairo_set_source_rgb (cr, .3, .3, .3);
460 rounded_rectangle (cr, x0 - bxw2, yc - bxh2, bxw, 2 * bxh2, 7);
463 const ChanMapping::Mappings in_map = _pi->input_map (i).mappings ();
464 const ChanMapping::Mappings out_map = _pi->output_map (i).mappings ();
466 for (ChanMapping::Mappings::const_iterator t = in_map.begin (); t != in_map.end (); ++t) {
467 bool is_midi = t->first == DataType::MIDI;
468 for (ChanMapping::TypeMapping::const_iterator c = (*t).second.begin (); c != (*t).second.end () ; ++c) {
469 uint32_t pn = (*c).first; // pin
470 uint32_t pb = (*c).second;
471 double c_x0 = pin_x_pos (pb, 0, width, pc_in, pc_in_midi, is_midi);
472 double c_x1 = pin_x_pos (pn, x0 - bxw2, bxw, _sinks.n_total (), _sinks.n_midi (), is_midi);
473 draw_connection (cr, c_x0, c_x1, y_in, yc - bxh2 - _pin_box_size, is_midi);
477 for (ChanMapping::Mappings::const_iterator t = out_map.begin (); t != out_map.end (); ++t) {
478 bool is_midi = t->first == DataType::MIDI;
479 for (ChanMapping::TypeMapping::const_iterator c = (*t).second.begin (); c != (*t).second.end () ; ++c) {
480 uint32_t pn = (*c).first; // pin
481 uint32_t pb = (*c).second;
482 double c_x0 = pin_x_pos (pn, x0 - bxw2, bxw, _sources.n_total (), _sources.n_midi (), is_midi);
483 double c_x1 = pin_x_pos (pb, 0, width, pc_out, pc_out_midi, is_midi);
484 draw_connection (cr, c_x0, c_x1, yc + bxh2 + _pin_box_size, y_out, is_midi);
490 for (CtrlElemList::const_iterator i = _elements.begin (); i != _elements.end (); ++i) {
494 draw_io_pin (cr, *i);
498 draw_plugin_pin (cr, *i);
508 PluginPinDialog::darea_size_request (Gtk::Requisition* req)
510 req->width = _min_width;
515 PluginPinDialog::darea_size_allocate (Gtk::Allocation&)
517 _position_valid = false;
521 PluginPinDialog::darea_motion_notify_event (GdkEventMotion* ev)
523 bool changed = false;
525 for (CtrlElemList::iterator i = _elements.begin (); i != _elements.end (); ++i) {
526 if (ev->x >= i->x && ev->x <= i->x + i->w
527 && ev->y >= i->y && ev->y <= i->y + i->h)
529 if (!i->prelight) changed = true;
533 if (i->prelight) changed = true;
544 PluginPinDialog::darea_button_press_event (GdkEventButton* ev)
546 if (ev->type != GDK_BUTTON_PRESS) {
550 switch (ev->button) {
552 if (!_selection || (_selection && !_hover)) {
556 } else if (_selection && _hover && _selection != _hover) {
557 if (_selection->dt != _hover->dt) { _actor.reset (); }
558 else if (_selection->ct == Input && _hover->ct == Sink) { _actor = _hover; }
559 else if (_selection->ct == Sink && _hover->ct == Input) { _actor = _hover; }
560 else if (_selection->ct == Output && _hover->ct == Source) { _actor = _hover; }
561 else if (_selection->ct == Source && _hover->ct == Output) { _actor = _hover; }
579 PluginPinDialog::darea_button_release_event (GdkEventButton* ev)
581 if (_hover == _actor && _actor) {
583 assert (_selection->dt == _actor->dt);
584 if (_selection->ct == Input && _actor->ct == Sink) {
585 handle_input_action (_actor, _selection);
587 else if (_selection->ct == Sink && _actor->ct == Input) {
588 handle_input_action (_selection, _actor);
590 else if (_selection->ct == Output && _actor->ct == Source) {
591 handle_output_action (_actor, _selection);
593 else if (_selection->ct == Source && _actor->ct == Output) {
594 handle_output_action (_selection, _actor);
604 PluginPinDialog::handle_input_action (const CtrlElem &s, const CtrlElem &i)
606 const int pc = s->ip;
608 ChanMapping in_map (_pi->input_map (pc));
609 uint32_t idx = in_map.get (s->dt, s->id, &valid);
611 if (valid && idx == i->id) {
613 in_map.unset (s->dt, s->id);
614 _pi->set_input_map (pc, in_map);
618 in_map.set (s->dt, s->id, i->id);
619 _pi->set_input_map (pc, in_map);
623 in_map.unset (s->dt, s->id);
624 in_map.set (s->dt, s->id, i->id);
625 _pi->set_input_map (pc, in_map);
630 PluginPinDialog::handle_output_action (const CtrlElem &s, const CtrlElem &o)
632 const uint32_t pc = s->ip;
634 ChanMapping out_map (_pi->output_map (pc));
635 uint32_t idx = out_map.get (s->dt, s->id, &valid);
637 if (valid && idx == o->id) {
639 out_map.unset (s->dt, s->id);
640 _pi->set_output_map (pc, out_map);
645 out_map.unset (s->dt, s->id);
647 // disconnect other outputs
648 _ignore_updates = true;
649 for (uint32_t n = 0; n < _n_plugins; ++n) {
653 ChanMapping n_out_map (_pi->output_map (n));
654 idx = n_out_map.get_src (s->dt, o->id, &valid);
656 n_out_map.unset (s->dt, idx);
657 _pi->set_output_map (n, n_out_map);
660 _ignore_updates = false;
661 idx = out_map.get_src (s->dt, o->id, &valid);
663 out_map.unset (s->dt, idx);
666 out_map.set (s->dt, s->id, o->id);
667 _pi->set_output_map (pc, out_map);
672 PluginPinDialog::toggle_sidechain ()
674 _route ()->add_remove_sidechain (_pi, !_pi->has_sidechain ());
678 PluginPinDialog::connect_sidechain ()
680 if (!_session) { return; }
681 // TODO non-modal would be cooler ... :)
682 SideChainUI sc (*this, _session, _pi->sidechain_input ());
687 PluginPinDialog::reset_configuration ()
689 _route ()->reset_plugin_insert (_pi);
693 PluginPinDialog::reset_mapping ()
699 PluginPinDialog::add_remove_plugin_clicked (bool add)
701 ChanCount out = _out;
702 assert (add || _n_plugins > 0);
703 _route ()->customize_plugin_insert (_pi, _n_plugins + (add ? 1 : -1), out);
707 PluginPinDialog::add_remove_port_clicked (bool add, ARDOUR::DataType dt)
709 ChanCount out = _out;
710 assert (add || out.get (dt) > 0);
711 out.set (dt, out.get (dt) + (add ? 1 : -1));
712 _route ()->customize_plugin_insert (_pi, _n_plugins, out);
715 SideChainUI::SideChainUI (Gtk::Window& p, Session* session, boost::shared_ptr<IO> sc)
716 : ArdourDialog (p, string (_("Sidechain ")) + sc->name (), true)
718 HBox* hbox = manage (new HBox);
719 IOSelector * io = Gtk::manage (new IOSelector (this, session, sc));
720 hbox->pack_start (*io, true, true);
721 get_vbox ()->pack_start (*hbox, true, true);