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