Fix DSP load sorting with inactive plugins
[ardour.git] / gtk2_ardour / midi_channel_selector.cc
1 /*
2  * Copyright (C) 2008-2015 David Robillard <d@drobilla.net>
3  * Copyright (C) 2008 Hans Baier <hansfbaier@googlemail.com>
4  * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
5  * Copyright (C) 2009-2016 Paul Davis <paul@linuxaudiosystems.com>
6  * Copyright (C) 2015 Robin Gareus <robin@gareus.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include <algorithm>
24 #include <sstream>
25 #include <gtkmm/separator.h>
26 #include <gtkmm/box.h>
27 #include <gtkmm/label.h>
28 #include <gtkmm/togglebutton.h>
29 #include <gtkmm/radiobutton.h>
30 #include <gtkmm/table.h>
31
32 #include "pbd/compose.h"
33 #include "pbd/ffs.h"
34
35 #include "gtkmm2ext/gtk_ui.h"
36 #include "gtkmm2ext/gui_thread.h"
37 #include "gtkmm2ext/utils.h"
38
39 #include "ardour/midi_track.h"
40
41 #include "midi_channel_selector.h"
42 #include "rgb_macros.h"
43
44 #include "pbd/i18n.h"
45
46 using namespace std;
47 using namespace Gtk;
48 using namespace ARDOUR;
49
50 MidiChannelSelector::MidiChannelSelector(int n_rows, int n_columns, int start_row, int start_column)
51         : Table(std::max(4, std::max(n_rows,    start_row    + 4)),
52                 std::max(4, std::max(n_columns, start_column + 4)),
53                 true)
54         , _recursion_counter(0)
55 {
56         property_column_spacing() = 0;
57         property_row_spacing() = 0;
58
59         uint8_t channel_nr = 0;
60         for (int row = 0; row < 4; ++row) {
61                 for (int column = 0; column < 4; ++column) {
62                         ostringstream channel;
63                         channel << int(++channel_nr);
64                         _button_labels[row][column].set_text(channel.str());
65                         _button_labels[row][column].set_justify(JUSTIFY_RIGHT);
66                         _buttons[row][column].add(_button_labels[row][column]);
67                         _buttons[row][column].signal_toggled().connect(
68                                 sigc::bind(
69                                         sigc::mem_fun(this, &MidiChannelSelector::button_toggled),
70                                         &_buttons[row][column],
71                                         channel_nr - 1));
72                         _buttons[row][column].set_widget_name (X_("MidiChannelSelectorButton"));
73
74                         _buttons[row][column].signal_button_release_event().connect(
75                                 sigc::mem_fun(this, &MidiChannelSelector::was_clicked), false);
76
77                         int table_row    = start_row + row;
78                         int table_column = start_column + column;
79                         attach(_buttons[row][column], table_column, table_column + 1, table_row, table_row + 1);
80                 }
81         }
82 }
83
84 MidiChannelSelector::~MidiChannelSelector()
85 {
86 }
87
88 bool
89 MidiChannelSelector::was_clicked (GdkEventButton*)
90 {
91         clicked ();
92         return false;
93 }
94
95 void
96 MidiChannelSelector::set_channel_colors(const uint32_t new_channel_colors[16])
97 {
98         for (int row = 0; row < 4; ++row) {
99                 for (int column = 0; column < 4; ++column) {
100                         char color_normal[8];
101                         char color_active[8];
102                         snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[row * 4 + column], 0x000000ff, 0.6));
103                         snprintf(color_active, 8, "#%x", new_channel_colors[row * 4 + column]);
104                         _buttons[row][column].modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
105                         _buttons[row][column].modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
106                 }
107         }
108 }
109
110 void
111 MidiChannelSelector::set_default_channel_color()
112 {
113         for (int row = 0; row < 4; ++row) {
114                 for (int column = 0; column < 4; ++column) {
115                         _buttons[row][column].unset_fg (STATE_NORMAL);
116                         _buttons[row][column].unset_fg (STATE_ACTIVE);
117                         _buttons[row][column].unset_bg (STATE_NORMAL);
118                         _buttons[row][column].unset_bg (STATE_ACTIVE);
119                 }
120         }
121 }
122
123 SingleMidiChannelSelector::SingleMidiChannelSelector(uint8_t active_channel)
124         : MidiChannelSelector()
125 {
126         _last_active_button = 0;
127         ToggleButton* button = &_buttons[active_channel / 4][active_channel % 4];
128         _active_channel = active_channel;
129         button->set_active(true);
130         _last_active_button = button;
131 }
132
133 void
134 SingleMidiChannelSelector::button_toggled(ToggleButton* button, uint8_t channel)
135 {
136         ++_recursion_counter;
137         if (_recursion_counter == 1) {
138                 // if the current button is active it must
139                 // be different from the first one
140                 if (button->get_active()) {
141                         if (_last_active_button) {
142                                 _last_active_button->set_active(false);
143                                 _active_channel = channel;
144                                 _last_active_button = button;
145                                 channel_selected.emit(channel);
146                         }
147                 } else {
148                         // if not, the user pressed the already active button
149                         button->set_active(true);
150                         _active_channel = channel;
151                 }
152         }
153         --_recursion_counter;
154 }
155
156 MidiMultipleChannelSelector::MidiMultipleChannelSelector(ChannelMode mode, uint16_t mask)
157         : MidiChannelSelector(4, 6, 0, 0)
158         , _channel_mode(mode)
159 {
160         _select_all.add(*manage(new Label(_("All"))));
161         _select_all.signal_clicked().connect(
162                         sigc::bind(sigc::mem_fun(this, &MidiMultipleChannelSelector::select_all), true));
163
164         _select_none.add(*manage(new Label(_("None"))));
165         _select_none.signal_clicked().connect(
166                         sigc::bind(sigc::mem_fun(this, &MidiMultipleChannelSelector::select_all), false));
167
168         _invert_selection.add(*manage(new Label(_("Invert"))));
169         _invert_selection.signal_clicked().connect(
170                         sigc::mem_fun(this, &MidiMultipleChannelSelector::invert_selection));
171
172         _force_channel.add(*manage(new Label(_("Force"))));
173         _force_channel.signal_toggled().connect(
174                         sigc::mem_fun(this, &MidiMultipleChannelSelector::force_channels_button_toggled));
175
176         set_homogeneous(false);
177         attach(*manage(new VSeparator()), 4, 5, 0, 4, SHRINK, FILL, 0, 0);
178         //set_row_spacing(4, -5);
179         attach(_select_all,       5, 6, 0, 1);
180         attach(_select_none,      5, 6, 1, 2);
181         attach(_invert_selection, 5, 6, 2, 3);
182         attach(_force_channel,    5, 6, 3, 4);
183
184         set_selected_channels(mask);
185 }
186
187 MidiMultipleChannelSelector::~MidiMultipleChannelSelector()
188 {
189         mode_changed.clear();
190 }
191
192 void
193 MidiMultipleChannelSelector::set_channel_mode(ChannelMode mode, uint16_t mask)
194 {
195         switch (mode) {
196         case AllChannels:
197                 _force_channel.set_active(false);
198                 set_selected_channels(0xFFFF);
199                 break;
200         case FilterChannels:
201                 _force_channel.set_active(false);
202                 set_selected_channels(mask);
203                 break;
204         case ForceChannel:
205                 _force_channel.set_active(true);
206                 for (uint16_t i = 0; i < 16; i++) {
207                         ToggleButton* button = &_buttons[i / 4][i % 4];
208                         button->set_active(i == mask);
209                 }
210         }
211 }
212
213 uint16_t
214 MidiMultipleChannelSelector::get_selected_channels() const
215 {
216         uint16_t selected_channels = 0;
217         for (uint16_t i = 0; i < 16; i++) {
218                 const ToggleButton* button = &_buttons[i / 4][i % 4];
219                 if (button->get_active()) {
220                         selected_channels |= (1L << i);
221                 }
222         }
223
224         return selected_channels;
225 }
226
227 void
228 MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels)
229 {
230         for (uint16_t i = 0; i < 16; i++) {
231                 ToggleButton* button = &_buttons[i / 4][i % 4];
232                 if (selected_channels & (1L << i)) {
233                         button->set_active(true);
234                 } else {
235                         button->set_active(false);
236                 }
237         }
238 }
239
240 void
241 MidiMultipleChannelSelector::button_toggled(ToggleButton */*button*/, uint8_t channel)
242 {
243         ++_recursion_counter;
244         if (_recursion_counter == 1) {
245                 if (_channel_mode == ForceChannel) {
246                         mode_changed.emit(_channel_mode, channel);
247                         set_selected_channels(1 << channel);
248                 } else {
249                         mode_changed.emit(_channel_mode, get_selected_channels());
250                 }
251         }
252         --_recursion_counter;
253 }
254
255 void
256 MidiMultipleChannelSelector::force_channels_button_toggled()
257 {
258         if (_force_channel.get_active()) {
259                 _channel_mode = ForceChannel;
260                 bool found_first_active = false;
261                 // leave only the first button enabled
262                 uint16_t active_channel = 0;
263                 for (int i = 0; i <= 15; i++) {
264                         ToggleButton* button = &_buttons[i / 4][i % 4];
265                         if (button->get_active()) {
266                                 if (found_first_active) {
267                                         ++_recursion_counter;
268                                         button->set_active(false);
269                                         --_recursion_counter;
270                                 } else {
271                                         found_first_active = true;
272                                         active_channel = i;
273                                 }
274                         }
275                 }
276
277                 if (!found_first_active) {
278                         _buttons[0][0].set_active(true);
279                 }
280
281                 _select_all.set_sensitive(false);
282                 _select_none.set_sensitive(false);
283                 _invert_selection.set_sensitive(false);
284                 mode_changed.emit(_channel_mode, active_channel);
285         } else {
286                 _channel_mode = FilterChannels;
287                 _select_all.set_sensitive(true);
288                 _select_none.set_sensitive(true);
289                 _invert_selection.set_sensitive(true);
290                 mode_changed.emit(FilterChannels, get_selected_channels());
291         }
292 }
293
294 void
295 MidiMultipleChannelSelector::select_all(bool on)
296 {
297         if (_channel_mode == ForceChannel)
298                 return;
299
300         ++_recursion_counter;
301         for (uint16_t i = 0; i < 16; i++) {
302                 ToggleButton* button = &_buttons[i / 4][i % 4];
303                 button->set_active(on);
304         }
305         --_recursion_counter;
306         mode_changed.emit(_channel_mode, get_selected_channels());
307 }
308
309 void
310 MidiMultipleChannelSelector::invert_selection(void)
311 {
312         if (_channel_mode == ForceChannel)
313                 return;
314
315         ++_recursion_counter;
316         for (uint16_t i = 0; i < 16; i++) {
317                 ToggleButton* button = &_buttons[i / 4][i % 4];
318                 if (button->get_active()) {
319                         button->set_active(false);
320                 } else {
321                         button->set_active(true);
322                 }
323         }
324         --_recursion_counter;
325         mode_changed.emit(_channel_mode, get_selected_channels());
326 }
327
328 /*-----------------------------------------*/
329
330 MidiChannelSelectorWindow::MidiChannelSelectorWindow (boost::shared_ptr<MidiTrack> mt)
331         : ArdourWindow (_("MIDI Channel Control"))
332         , track (mt)
333         , playback_all_button (playback_button_group, _("Playback all channels"))
334         , playback_filter_button (playback_button_group, _("Play only selected channels"))
335         , playback_force_button (playback_button_group, _("Use a single fixed channel for all playback"))
336         , capture_all_button (capture_button_group, _("Record all channels"))
337         , capture_filter_button (capture_button_group, _("Record only selected channels"))
338         , capture_force_button (capture_button_group, _("Force all channels to 1 channel"))
339         , last_drawn_capture_mode (AllChannels)
340         , last_drawn_playback_mode (AllChannels)
341 {
342         build ();
343
344         playback_mode_changed ();
345         capture_mode_changed ();
346
347         playback_mask_changed ();
348         capture_mask_changed ();
349
350         track->playback_filter().ChannelMaskChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::playback_mask_changed, this), gui_context());
351         track->playback_filter().ChannelModeChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::playback_mode_changed, this), gui_context());
352         track->capture_filter().ChannelMaskChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::capture_mask_changed, this), gui_context());
353         track->capture_filter().ChannelModeChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::capture_mode_changed, this), gui_context());
354 }
355
356 MidiChannelSelectorWindow::~MidiChannelSelectorWindow()
357 {
358 }
359
360 void
361 MidiChannelSelectorWindow::build ()
362 {
363         VBox* vpacker;
364         HBox* capture_controls;
365         HBox* playback_controls;
366         Button* b;
367         Label* l;
368
369         vpacker = manage (new VBox);
370         vpacker->set_spacing (6);
371         vpacker->set_border_width (12);
372
373         l = manage (new Label (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Inbound"))));
374         l->set_use_markup (true);
375         vpacker->pack_start (*l, true, true);
376
377         vpacker->pack_start (capture_all_button);
378         capture_all_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), AllChannels));
379
380         vpacker->pack_start (capture_filter_button);
381         capture_filter_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), FilterChannels));
382
383         vpacker->pack_start (capture_force_button);
384         capture_force_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), ForceChannel));
385
386         vpacker->pack_start (capture_mask_box);
387
388         capture_controls = manage (new HBox);
389         capture_controls->set_spacing (6);
390
391         b = manage (new Button (_("All")));
392         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to enable recording all channels"));
393         capture_controls->pack_start (*b);
394         capture_mask_controls.push_back (b);
395         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::fill_capture_mask));
396         b = manage (new Button (_("None")));
397         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to disable recording all channels"));
398         capture_controls->pack_start (*b);
399         capture_mask_controls.push_back (b);
400         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::zero_capture_mask));
401         b = manage (new Button (_("Invert")));
402         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to invert currently selected recording channels"));
403         capture_controls->pack_start (*b);
404         capture_mask_controls.push_back (b);
405         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::invert_capture_mask));
406
407         vpacker->pack_start (*capture_controls);
408
409         Gtk::HSeparator *hseparator2 = manage(new Gtk::HSeparator);
410         vpacker->pack_start (*hseparator2, false, false, 6);
411
412         l = manage (new Label (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Playback"))));
413         l->set_use_markup (true);
414         vpacker->pack_start (*l);
415
416         vpacker->pack_start (playback_all_button);
417         playback_all_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), AllChannels));
418
419         vpacker->pack_start (playback_filter_button);
420         playback_filter_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), FilterChannels));
421
422         vpacker->pack_start (playback_force_button);
423         playback_force_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), ForceChannel));
424
425         vpacker->pack_start (playback_mask_box);
426
427         playback_controls = manage (new HBox);
428         playback_controls->set_spacing (6);
429
430         b = manage (new Button (_("All")));
431         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to enable playback of all channels"));
432         playback_controls->pack_start (*b);
433         playback_mask_controls.push_back (b);
434         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::fill_playback_mask));
435         b = manage (new Button (_("None")));
436         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to disable playback of all channels"));
437         playback_controls->pack_start (*b);
438         playback_mask_controls.push_back (b);
439         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::zero_playback_mask));
440         b = manage (new Button (_("Invert")));
441         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to invert current selected playback channels"));
442         playback_controls->pack_start (*b);
443         playback_mask_controls.push_back (b);
444         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::invert_playback_mask));
445
446         vpacker->pack_start (*playback_controls);
447
448         add (*vpacker);
449 }
450
451 void
452 MidiChannelSelectorWindow::fill_playback_mask ()
453 {
454         if (track->get_playback_channel_mode() == FilterChannels) {
455                 track->set_playback_channel_mask (0xffff);
456         }
457 }
458
459 void
460 MidiChannelSelectorWindow::zero_playback_mask ()
461 {
462         if (track->get_playback_channel_mode() == FilterChannels) {
463                 track->set_playback_channel_mask (0);
464         }
465 }
466
467 void
468 MidiChannelSelectorWindow::invert_playback_mask ()
469 {
470         if (track->get_playback_channel_mode() == FilterChannels) {
471                 track->set_playback_channel_mask (~track->get_playback_channel_mask());
472         }
473 }
474
475 void
476 MidiChannelSelectorWindow::fill_capture_mask ()
477 {
478         if (track->get_capture_channel_mode() == FilterChannels) {
479                 track->set_capture_channel_mask (0xffff);
480         }
481 }
482
483 void
484 MidiChannelSelectorWindow::zero_capture_mask ()
485 {
486         if (track->get_capture_channel_mode() == FilterChannels) {
487                 track->set_capture_channel_mask (0);
488         }
489 }
490
491 void
492 MidiChannelSelectorWindow::invert_capture_mask ()
493 {
494         if (track->get_capture_channel_mode() == FilterChannels) {
495                 track->set_capture_channel_mask (~track->get_capture_channel_mask());
496         }
497 }
498
499 void
500 MidiChannelSelectorWindow::set_playback_selected_channels (uint16_t mask)
501 {
502         switch (track->get_playback_channel_mode()) {
503         case AllChannels:
504                 /* they are insensitive, so we don't care */
505                 break;
506
507         case FilterChannels:
508                 for (uint16_t i = 0; i < 16; i++) {
509                         playback_buttons[i]->set_active ((1<<i) & mask);
510                 }
511                 break;
512
513         case ForceChannel:
514                 /* only set the lowest set channel in the mask as active */
515                 for (uint16_t i = 0; i < 16; i++) {
516                         playback_buttons[i]->set_active (i == (PBD::ffs (mask) - 1));
517                 }
518                 break;
519         }
520 }
521
522 void
523 MidiChannelSelectorWindow::set_capture_selected_channels (uint16_t mask)
524 {
525         switch (track->get_capture_channel_mode()) {
526         case AllChannels:
527                 /* they are insensitive, so we don't care */
528                 break;
529
530         case FilterChannels:
531                 for (uint16_t i = 0; i < 16; i++) {
532                         capture_buttons[i]->set_active ((1<<i) & mask);
533                 }
534                 break;
535
536         case ForceChannel:
537                 /* only set the lowest set channel in the mask as active */
538                 for (uint16_t i = 0; i < 16; i++) {
539                         capture_buttons[i]->set_active (i == (PBD::ffs (mask) - 1));
540                 }
541                 break;
542         }
543 }
544
545 void
546 MidiChannelSelectorWindow::playback_mask_changed ()
547 {
548         set_playback_selected_channels (track->get_playback_channel_mask());
549 }
550
551 void
552 MidiChannelSelectorWindow::capture_mask_changed ()
553 {
554         set_capture_selected_channels (track->get_capture_channel_mask());
555 }
556
557 void
558 MidiChannelSelectorWindow::playback_mode_changed ()
559 {
560         uint32_t first_channel = 0;
561         ChannelMode mode = track->get_playback_channel_mode();
562
563         switch (mode) {
564         case AllChannels:
565                 if (last_drawn_playback_mode == ForceChannel) {
566                         /* force mode used radio buttons. not what we want,
567                          * though one could argue that we want no buttons
568                          * at since they are insensitive
569                          */
570                         playback_buttons.clear ();
571                 }
572                 for (vector<Widget*>::iterator i = playback_mask_controls.begin(); i != playback_mask_controls.end(); ++i) {
573                         (*i)->set_sensitive (false);
574                 }
575                 playback_all_button.set_active ();
576                 break;
577
578         case FilterChannels:
579                 if (last_drawn_playback_mode == ForceChannel) {
580                         playback_buttons.clear ();
581                 } else if (last_drawn_playback_mode == AllChannels) {
582                         for (vector<ToggleButton*>::iterator i = playback_buttons.begin(); i != playback_buttons.end(); ++i) {
583                                 (*i)->set_sensitive (true);
584                         }
585                 }
586                 for (vector<Widget*>::iterator i = playback_mask_controls.begin(); i != playback_mask_controls.end(); ++i) {
587                         (*i)->set_sensitive (true);
588                 }
589                 playback_filter_button.set_active ();
590                 break;
591
592         case ForceChannel:
593                 if (last_drawn_playback_mode == AllChannels || last_drawn_playback_mode == FilterChannels) {
594                         playback_buttons.clear ();
595                         first_channel = PBD::ffs (track->get_playback_channel_mask()) - 1;
596                 }
597                 for (vector<Widget*>::iterator i = playback_mask_controls.begin(); i != playback_mask_controls.end(); ++i) {
598                         (*i)->set_sensitive (false);
599                 }
600                 playback_force_button.set_active ();
601                 break;
602         }
603
604         if (playback_buttons.empty()) {
605
606                 Gtkmm2ext::container_clear (playback_mask_box);
607
608                 ToggleButton* tb;
609                 RadioButtonGroup group;
610
611                 for (uint32_t n = 0; n < 16; ++n) {
612                         char buf[3];
613                         snprintf (buf, sizeof (buf), "%d", n+1);
614
615                         switch (mode) {
616                         case AllChannels:
617                         case FilterChannels:
618                                 tb = manage (new ToggleButton (buf));
619                                 Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to toggle playback of channel %1"), n+1));
620                                 break;
621                         case ForceChannel:
622                                 tb = manage (new RadioButton (group, buf));
623                                 tb->property_draw_indicator() = false;
624                                 if (n == first_channel) {
625                                         tb->set_active (true);
626                                 }
627                                 Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to force all MIDI channel messages to channel %1"), n+1));
628                                 break;
629                         }
630                         playback_buttons.push_back (tb);
631                         tb->set_name (X_("MidiChannelSelectorButton"));
632                         playback_mask_box.pack_start (*tb);
633                         tb->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_channel_clicked), n));
634                         tb->show ();
635
636                         if (mode == AllChannels) {
637                                 tb->set_sensitive (false);
638                         }
639                 }
640
641                 if (mode != ForceChannel) {
642                         set_playback_selected_channels (track->get_playback_channel_mask());
643                 }
644         }
645
646         if (mode == AllChannels) {
647                 for (vector<ToggleButton*>::iterator i = playback_buttons.begin(); i != playback_buttons.end(); ++i) {
648                         (*i)->set_sensitive (false);
649                 }
650         }
651
652         playback_mask_changed(); // update buttons
653
654         last_drawn_playback_mode = mode;
655 }
656
657 void
658 MidiChannelSelectorWindow::capture_mode_changed ()
659 {
660         uint32_t first_channel = 0;
661         ChannelMode mode = track->get_capture_channel_mode();
662
663         switch (mode) {
664         case AllChannels:
665                 if (last_drawn_capture_mode == ForceChannel) {
666                         /* force mode used radio buttons. not what we want,
667                          * though one could argue that we want no buttons
668                          * at since they are insensitive
669                          */
670                         capture_buttons.clear ();
671                 }
672                 for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
673                         (*i)->set_sensitive (false);
674                 }
675                 capture_all_button.set_active ();
676                 break;
677
678         case FilterChannels:
679                 if (last_drawn_capture_mode == ForceChannel) {
680                         capture_buttons.clear ();
681                 } else if (last_drawn_capture_mode == AllChannels) {
682                         for (vector<ToggleButton*>::iterator i = capture_buttons.begin(); i != capture_buttons.end(); ++i) {
683                                 (*i)->set_sensitive (true);
684                         }
685                 }
686                 for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
687                         (*i)->set_sensitive (true);
688                 }
689                 capture_filter_button.set_active ();
690                 break;
691
692         case ForceChannel:
693                 if (last_drawn_capture_mode == AllChannels || last_drawn_capture_mode == FilterChannels) {
694                         capture_buttons.clear ();
695                         first_channel = PBD::ffs (track->get_capture_channel_mask()) - 1;
696                 }
697                 for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
698                         (*i)->set_sensitive (false);
699                 }
700                 capture_force_button.set_active ();
701                 break;
702         }
703
704         if (capture_buttons.empty()) {
705
706                 Gtkmm2ext::container_clear (capture_mask_box);
707
708                 ToggleButton* tb;
709                 RadioButtonGroup group;
710
711                 for (uint32_t n = 0; n < 16; ++n) {
712                         char buf[3];
713                         snprintf (buf, sizeof (buf), "%d", n+1);
714
715                         switch (mode) {
716                         case AllChannels:
717                         case FilterChannels:
718                                 tb = manage (new ToggleButton (buf));
719                                 Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to toggle recording of channel %1"), n+1));
720                                 break;
721                         case ForceChannel:
722                                 tb = manage (new RadioButton (group, buf));
723                                 tb->property_draw_indicator() = false;
724                                 if (n == first_channel) {
725                                         tb->set_active (true);
726                                 }
727                                 Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to force all recorded channels to %1"), n+1));
728                                 break;
729                         }
730                         capture_buttons.push_back (tb);
731                         tb->set_name (X_("MidiChannelSelectorButton"));
732                         capture_mask_box.pack_start (*tb);
733                         tb->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_channel_clicked), n));
734                         tb->show ();
735
736                         if (mode == AllChannels) {
737                                 tb->set_sensitive (false);
738                         }
739                 }
740
741                 if (mode != ForceChannel) {
742                         set_capture_selected_channels (track->get_capture_channel_mask());
743                 }
744         }
745
746         if (mode == AllChannels) {
747                 for (vector<ToggleButton*>::iterator i = capture_buttons.begin(); i != capture_buttons.end(); ++i) {
748                         (*i)->set_sensitive (false);
749                 }
750         }
751
752         capture_mask_changed (); // udpate buttons
753
754         last_drawn_capture_mode = mode;
755 }
756
757 void
758 MidiChannelSelectorWindow::playback_channel_clicked (uint16_t n)
759 {
760         if (playback_buttons[n]->get_active()) {
761                 switch (track->get_playback_channel_mode()) {
762                 case AllChannels:
763                         break;
764                 case FilterChannels:
765                         track->set_playback_channel_mask (track->get_playback_channel_mask() | (1<<n));
766                         break;
767                 case ForceChannel:
768                         track->set_playback_channel_mask (1<<n);
769                         break;
770                 }
771         } else {
772                 if (track->get_playback_channel_mode() == FilterChannels) {
773                         track->set_playback_channel_mask (track->get_playback_channel_mask() & ~(1<<n));
774                 }
775         }
776 }
777
778 void
779 MidiChannelSelectorWindow::capture_channel_clicked (uint16_t n)
780 {
781         if (capture_buttons[n]->get_active()) {
782                 switch (track->get_capture_channel_mode()) {
783                 case AllChannels:
784                         break;
785                 case FilterChannels:
786                         track->set_capture_channel_mask (track->get_capture_channel_mask() | (1<<n));
787                         break;
788                 case ForceChannel:
789                         track->set_capture_channel_mask (1<<n);
790                         break;
791                 }
792         } else {
793                 if (track->get_capture_channel_mode() == FilterChannels) {
794                         track->set_capture_channel_mask (track->get_capture_channel_mask() & ~(1<<n));
795                 }
796         }
797 }
798
799 void
800 MidiChannelSelectorWindow::capture_mode_toggled (ChannelMode mode)
801 {
802         /* this is called twice for every radio button change. the first time
803            is for the button/mode that has been turned off, and the second is for the
804            button/mode that has been turned on.
805
806            so we take action only if the button is active (i.e it is the one
807            just clicked on)
808         */
809
810         switch (mode) {
811         case AllChannels:
812                 if (capture_all_button.get_active()) {
813                         track->set_capture_channel_mode (AllChannels, track->get_capture_channel_mask());
814                 }
815                 break;
816         case FilterChannels:
817                 if (capture_filter_button.get_active()) {
818                         track->set_capture_channel_mode (FilterChannels, track->get_capture_channel_mask());
819                 }
820                 break;
821         case ForceChannel:
822                 if (capture_force_button.get_active()) {
823                         track->set_capture_channel_mode (ForceChannel, track->get_capture_channel_mask());
824                 }
825                 break;
826         }
827 }
828
829 void
830 MidiChannelSelectorWindow::playback_mode_toggled (ChannelMode mode)
831 {
832         /* this is called twice for every radio button change. the first time
833            is for the button/mode that has been turned off, and the second is for the
834            button/mode that has been turned on.
835
836            so we take action only if the button is active (i.e it is the one
837            just clicked on)
838         */
839
840         switch (mode) {
841         case AllChannels:
842                 if (playback_all_button.get_active()) {
843                         track->set_playback_channel_mode (AllChannels, track->get_playback_channel_mask());
844                 }
845                 break;
846         case FilterChannels:
847                 if (playback_filter_button.get_active()) {
848                         track->set_playback_channel_mode (FilterChannels, track->get_playback_channel_mask());
849                 }
850                 break;
851         case ForceChannel:
852                 if (playback_force_button.get_active()) {
853                         track->set_playback_channel_mode (ForceChannel, track->get_playback_channel_mask());
854                 }
855                 break;
856         }
857 }
858
859 void
860 MidiChannelSelectorWindow::set_channel_colors (const uint32_t new_channel_colors[16])
861 {
862         for (uint32_t n = 0; n < 16; ++n) {
863
864                 char color_normal[8];
865                 char color_active[8];
866
867                 snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[n], 0x000000ff, 0.6));
868                 snprintf(color_active, 8, "#%x", new_channel_colors[n]);
869
870                 playback_buttons[n]->modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
871                 playback_buttons[n]->modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
872
873                 capture_buttons[n]->modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
874                 capture_buttons[n]->modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
875         }
876 }
877
878 void
879 MidiChannelSelectorWindow::set_default_channel_color()
880 {
881         for (uint32_t n = 0; n < 16; ++n) {
882                 playback_buttons[n]->unset_fg (STATE_NORMAL);
883                 playback_buttons[n]->unset_bg (STATE_NORMAL);
884                 playback_buttons[n]->unset_fg (STATE_ACTIVE);
885                 playback_buttons[n]->unset_bg (STATE_ACTIVE);
886
887                 capture_buttons[n]->unset_fg (STATE_NORMAL);
888                 capture_buttons[n]->unset_bg (STATE_NORMAL);
889                 capture_buttons[n]->unset_fg (STATE_ACTIVE);
890                 capture_buttons[n]->unset_bg (STATE_ACTIVE);
891         }
892 }