Make MIDI channel selector rows/col constraints actually do something.
[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
31 #include "gtkmm2ext/gtk_ui.h"
32 #include "gtkmm2ext/gui_thread.h"
33 #include "gtkmm2ext/utils.h"
34
35 #include "ardour/midi_track.h"
36
37 #include "midi_channel_selector.h"
38 #include "rgb_macros.h"
39
40 #include "i18n.h"
41
42 using namespace std;
43 using namespace Gtk;
44 using namespace ARDOUR;
45
46 MidiChannelSelector::MidiChannelSelector(int n_rows, int n_columns, int start_row, int start_column)
47         : Table(std::max(4, std::max(n_rows,    start_row    + 4)),
48                 std::max(4, std::max(n_columns, start_column + 4)),
49                 true)
50         , _recursion_counter(0)
51 {
52         property_column_spacing() = 0;
53         property_row_spacing() = 0;
54
55         uint8_t channel_nr = 0;
56         for (int row = 0; row < 4; ++row) {
57                 for (int column = 0; column < 4; ++column) {
58                         ostringstream channel;
59                         channel << int(++channel_nr);
60                         _button_labels[row][column].set_text(channel.str());
61                         _button_labels[row][column].set_justify(JUSTIFY_RIGHT);
62                         _buttons[row][column].add(_button_labels[row][column]);
63                         _buttons[row][column].signal_toggled().connect(
64                                 sigc::bind(
65                                         sigc::mem_fun(this, &MidiChannelSelector::button_toggled),
66                                         &_buttons[row][column],
67                                         channel_nr - 1));
68                         _buttons[row][column].set_widget_name (X_("MidiChannelSelectorButton"));
69
70                         _buttons[row][column].signal_button_release_event().connect(
71                                 sigc::mem_fun(this, &MidiChannelSelector::was_clicked), false);
72
73                         int table_row    = start_row + row;
74                         int table_column = start_column + column;
75                         attach(_buttons[row][column], table_column, table_column + 1, table_row, table_row + 1);
76                 }
77         }
78 }
79
80 MidiChannelSelector::~MidiChannelSelector()
81 {
82 }
83
84 bool
85 MidiChannelSelector::was_clicked (GdkEventButton*)
86 {
87         clicked ();
88         return false;
89 }
90
91 void
92 MidiChannelSelector::set_channel_colors(const uint32_t new_channel_colors[16])
93 {
94         for (int row = 0; row < 4; ++row) {
95                 for (int column = 0; column < 4; ++column) {
96                         char color_normal[8];
97                         char color_active[8];
98                         snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[row * 4 + column], 0x000000ff, 0.6));
99                         snprintf(color_active, 8, "#%x", new_channel_colors[row * 4 + column]);
100                         _buttons[row][column].modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
101                         _buttons[row][column].modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
102                 }
103         }
104 }
105
106 void
107 MidiChannelSelector::set_default_channel_color()
108 {
109         for (int row = 0; row < 4; ++row) {
110                 for (int column = 0; column < 4; ++column) {
111                         _buttons[row][column].unset_fg (STATE_NORMAL);
112                         _buttons[row][column].unset_fg (STATE_ACTIVE);
113                         _buttons[row][column].unset_bg (STATE_NORMAL);
114                         _buttons[row][column].unset_bg (STATE_ACTIVE);
115                 }
116         }
117 }
118
119 SingleMidiChannelSelector::SingleMidiChannelSelector(uint8_t active_channel)
120         : MidiChannelSelector()
121 {
122         _last_active_button = 0;
123         ToggleButton* button = &_buttons[active_channel / 4][active_channel % 4];
124         _active_channel = active_channel;
125         button->set_active(true);
126         _last_active_button = button;
127 }
128
129 void
130 SingleMidiChannelSelector::button_toggled(ToggleButton* button, uint8_t channel)
131 {
132         ++_recursion_counter;
133         if (_recursion_counter == 1) {
134                 // if the current button is active it must
135                 // be different from the first one
136                 if (button->get_active()) {
137                         if (_last_active_button) {
138                                 _last_active_button->set_active(false);
139                                 _active_channel = channel;
140                                 _last_active_button = button;
141                                 channel_selected.emit(channel);
142                         }
143                 } else {
144                         // if not, the user pressed the already active button
145                         button->set_active(true);
146                         _active_channel = channel;
147                 }
148         }
149         --_recursion_counter;
150 }
151
152 MidiMultipleChannelSelector::MidiMultipleChannelSelector(ChannelMode mode, uint16_t mask)
153         : MidiChannelSelector(4, 6, 0, 0)
154         , _channel_mode(mode)
155 {
156         _select_all.add(*manage(new Label(_("All"))));
157         _select_all.signal_clicked().connect(
158                         sigc::bind(sigc::mem_fun(this, &MidiMultipleChannelSelector::select_all), true));
159
160         _select_none.add(*manage(new Label(_("None"))));
161         _select_none.signal_clicked().connect(
162                         sigc::bind(sigc::mem_fun(this, &MidiMultipleChannelSelector::select_all), false));
163
164         _invert_selection.add(*manage(new Label(_("Invert"))));
165         _invert_selection.signal_clicked().connect(
166                         sigc::mem_fun(this, &MidiMultipleChannelSelector::invert_selection));
167
168         _force_channel.add(*manage(new Label(_("Force"))));
169         _force_channel.signal_toggled().connect(
170                         sigc::mem_fun(this, &MidiMultipleChannelSelector::force_channels_button_toggled));
171
172         set_homogeneous(false);
173         attach(*manage(new VSeparator()), 4, 5, 0, 4, SHRINK, FILL, 0, 0);
174         //set_row_spacing(4, -5);
175         attach(_select_all,       5, 6, 0, 1);
176         attach(_select_none,      5, 6, 1, 2);
177         attach(_invert_selection, 5, 6, 2, 3);
178         attach(_force_channel,    5, 6, 3, 4);
179
180         set_selected_channels(mask);
181 }
182
183 MidiMultipleChannelSelector::~MidiMultipleChannelSelector()
184 {
185         mode_changed.clear();
186 }
187
188 void
189 MidiMultipleChannelSelector::set_channel_mode(ChannelMode mode, uint16_t mask)
190 {
191         switch (mode) {
192         case AllChannels:
193                 _force_channel.set_active(false);
194                 set_selected_channels(0xFFFF);
195                 break;
196         case FilterChannels:
197                 _force_channel.set_active(false);
198                 set_selected_channels(mask);
199                 break;
200         case ForceChannel:
201                 _force_channel.set_active(true);
202                 for (uint16_t i = 0; i < 16; i++) {
203                         ToggleButton* button = &_buttons[i / 4][i % 4];
204                         button->set_active(i == mask);
205                 }
206         }
207 }
208
209 uint16_t
210 MidiMultipleChannelSelector::get_selected_channels() const
211 {
212         uint16_t selected_channels = 0;
213         for (uint16_t i = 0; i < 16; i++) {
214                 const ToggleButton* button = &_buttons[i / 4][i % 4];
215                 if (button->get_active()) {
216                         selected_channels |= (1L << i);
217                 }
218         }
219
220         return selected_channels;
221 }
222
223 void
224 MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels)
225 {
226         for (uint16_t i = 0; i < 16; i++) {
227                 ToggleButton* button = &_buttons[i / 4][i % 4];
228                 if (selected_channels & (1L << i)) {
229                         button->set_active(true);
230                 } else {
231                         button->set_active(false);
232                 }
233         }
234 }
235
236 void
237 MidiMultipleChannelSelector::button_toggled(ToggleButton */*button*/, uint8_t channel)
238 {
239         ++_recursion_counter;
240         if (_recursion_counter == 1) {
241                 if (_channel_mode == ForceChannel) {
242                         mode_changed.emit(_channel_mode, channel);
243                         set_selected_channels(1 << channel);
244                 } else {
245                         mode_changed.emit(_channel_mode, get_selected_channels());
246                 }
247         }
248         --_recursion_counter;
249 }
250
251 void
252 MidiMultipleChannelSelector::force_channels_button_toggled()
253 {
254         if (_force_channel.get_active()) {
255                 _channel_mode = ForceChannel;
256                 bool found_first_active = false;
257                 // leave only the first button enabled
258                 uint16_t active_channel = 0;
259                 for (int i = 0; i <= 15; i++) {
260                         ToggleButton* button = &_buttons[i / 4][i % 4];
261                         if (button->get_active()) {
262                                 if (found_first_active) {
263                                         ++_recursion_counter;
264                                         button->set_active(false);
265                                         --_recursion_counter;
266                                 } else {
267                                         found_first_active = true;
268                                         active_channel = i;
269                                 }
270                         }
271                 }
272
273                 if (!found_first_active) {
274                         _buttons[0][0].set_active(true);
275                 }
276
277                 _select_all.set_sensitive(false);
278                 _select_none.set_sensitive(false);
279                 _invert_selection.set_sensitive(false);
280                 mode_changed.emit(_channel_mode, active_channel);
281         } else {
282                 _channel_mode = FilterChannels;
283                 _select_all.set_sensitive(true);
284                 _select_none.set_sensitive(true);
285                 _invert_selection.set_sensitive(true);
286                 mode_changed.emit(FilterChannels, get_selected_channels());
287         }
288 }
289
290 void
291 MidiMultipleChannelSelector::select_all(bool on)
292 {
293         if (_channel_mode == ForceChannel)
294                 return;
295
296         ++_recursion_counter;
297         for (uint16_t i = 0; i < 16; i++) {
298                 ToggleButton* button = &_buttons[i / 4][i % 4];
299                 button->set_active(on);
300         }
301         --_recursion_counter;
302         mode_changed.emit(_channel_mode, get_selected_channels());
303 }
304
305 void
306 MidiMultipleChannelSelector::invert_selection(void)
307 {
308         if (_channel_mode == ForceChannel)
309                 return;
310
311         ++_recursion_counter;
312         for (uint16_t i = 0; i < 16; i++) {
313                 ToggleButton* button = &_buttons[i / 4][i % 4];
314                 if (button->get_active()) {
315                         button->set_active(false);
316                 } else {
317                         button->set_active(true);
318                 }
319         }
320         --_recursion_counter;
321         mode_changed.emit(_channel_mode, get_selected_channels());
322 }
323
324 /*-----------------------------------------*/
325
326 MidiChannelSelectorWindow::MidiChannelSelectorWindow (boost::shared_ptr<MidiTrack> mt)
327         : ArdourWindow (_("MIDI Channel Control"))
328         , track (mt)
329         , playback_all_button (playback_button_group, _("Playback all channels"))
330         , playback_filter_button (playback_button_group, _("Play only selected channels"))
331         , playback_force_button (playback_button_group, _("Use a single fixed channel for all playback"))
332         , capture_all_button (capture_button_group, _("Record all channels"))
333         , capture_filter_button (capture_button_group, _("Record only selected channels"))
334         , capture_force_button (capture_button_group, _("Force all channels to 1 channel"))
335         , last_drawn_capture_mode (AllChannels)
336         , last_drawn_playback_mode (AllChannels)
337 {
338         build ();
339
340         playback_mode_changed ();
341         capture_mode_changed ();
342
343         playback_mask_changed ();
344         capture_mask_changed ();
345
346         track->PlaybackChannelMaskChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::playback_mask_changed, this), gui_context());
347         track->PlaybackChannelModeChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::playback_mode_changed, this), gui_context());
348         track->CaptureChannelMaskChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::capture_mask_changed, this), gui_context());
349         track->CaptureChannelModeChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::capture_mode_changed, this), gui_context());
350 }
351
352 MidiChannelSelectorWindow::~MidiChannelSelectorWindow()
353 {
354 }
355
356 void
357 MidiChannelSelectorWindow::build ()
358 {
359         VBox* vpacker;
360         HBox* capture_controls;
361         HBox* playback_controls;
362         Button* b;
363         Label* l;
364
365         vpacker = manage (new VBox);
366         vpacker->set_spacing (6);
367         vpacker->set_border_width (12);
368
369         l = manage (new Label (string_compose (("<span size=\"larger\" weight=\"bold\">%1: %2</span>"), _("MIDI Channel Control"), track->name())));
370         l->set_use_markup (true);
371         l->set_alignment (0.5, 0.0);
372
373         vpacker->pack_start (*l, true, true);
374
375         l = manage (new Label (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Inbound"))));
376         l->set_use_markup (true);
377         vpacker->pack_start (*l);
378
379
380         vpacker->pack_start (capture_all_button);
381         capture_all_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), AllChannels));
382         
383         vpacker->pack_start (capture_filter_button);
384         capture_filter_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), FilterChannels));
385         
386         vpacker->pack_start (capture_force_button);
387         capture_force_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), ForceChannel));
388
389         vpacker->pack_start (capture_mask_box);
390         
391         capture_controls = manage (new HBox);
392         capture_controls->set_spacing (6);
393
394         b = manage (new Button (_("All")));
395         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to enable recording all channels"));
396         capture_controls->pack_start (*b);
397         capture_mask_controls.push_back (b);
398         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::fill_capture_mask)); 
399         b = manage (new Button (_("None")));
400         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to disable recording all channels"));
401         capture_controls->pack_start (*b);
402         capture_mask_controls.push_back (b);
403         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::zero_capture_mask)); 
404         b = manage (new Button (_("Invert")));
405         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to invert currently selected recording channels"));
406         capture_controls->pack_start (*b);
407         capture_mask_controls.push_back (b);
408         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::invert_capture_mask)); 
409
410         vpacker->pack_start (*capture_controls);
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         last_drawn_playback_mode = mode;
653 }
654
655 void
656 MidiChannelSelectorWindow::capture_mode_changed ()
657 {
658         uint32_t first_channel = 0;
659         ChannelMode mode = track->get_capture_channel_mode();
660
661         switch (mode) {
662         case AllChannels:
663                 if (last_drawn_capture_mode == ForceChannel) {
664                         /* force mode used radio buttons. not what we want,
665                          * though one could argue that we want no buttons
666                          * at since they are insensitive
667                          */
668                         capture_buttons.clear ();
669                 }
670                 for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
671                         (*i)->set_sensitive (false);
672                 }
673                 capture_all_button.set_active ();
674                 break;
675
676         case FilterChannels:
677                 if (last_drawn_capture_mode == ForceChannel) {
678                         capture_buttons.clear ();
679                 } else if (last_drawn_capture_mode == AllChannels) {
680                         for (vector<ToggleButton*>::iterator i = capture_buttons.begin(); i != capture_buttons.end(); ++i) {
681                                 (*i)->set_sensitive (true);
682                         }
683                 }
684                 for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
685                         (*i)->set_sensitive (true);
686                 }
687                 capture_filter_button.set_active ();
688                 break;
689
690         case ForceChannel:
691                 if (last_drawn_capture_mode == AllChannels || last_drawn_capture_mode == FilterChannels) {
692                         capture_buttons.clear ();
693                         first_channel = PBD::ffs (track->get_capture_channel_mask()) - 1;
694                 }
695                 for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
696                         (*i)->set_sensitive (false);
697                 }
698                 capture_force_button.set_active ();
699                 break;
700         }
701
702         if (capture_buttons.empty()) {
703
704                 Gtkmm2ext::container_clear (capture_mask_box);
705                 
706                 ToggleButton* tb;
707                 RadioButtonGroup group;
708                 
709                 for (uint32_t n = 0; n < 16; ++n) {
710                         char buf[3];
711                         snprintf (buf, sizeof (buf), "%d", n+1);
712
713                         switch (mode) {
714                         case AllChannels:
715                         case FilterChannels:
716                                 tb = manage (new ToggleButton (buf));
717                                 Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to toggle recording of channel %1"), n+1));
718                                 break;
719                         case ForceChannel:
720                                 tb = manage (new RadioButton (group, buf));
721                                 tb->property_draw_indicator() = false;
722                                 if (n == first_channel) {
723                                         tb->set_active (true);
724                                 }
725                                 Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to force all recorded channels to %1"), n+1));
726                                 break;
727                         }
728                         capture_buttons.push_back (tb);
729                         tb->set_name (X_("MidiChannelSelectorButton"));
730                         capture_mask_box.pack_start (*tb);
731                         tb->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_channel_clicked), n));
732                         tb->show ();
733
734                         if (mode == AllChannels) {
735                                 tb->set_sensitive (false);
736                         }
737                 }
738                 
739                 if (mode != ForceChannel) {
740                         set_capture_selected_channels (track->get_capture_channel_mask());
741                 } 
742         }
743
744         if (mode == AllChannels) {
745                 for (vector<ToggleButton*>::iterator i = capture_buttons.begin(); i != capture_buttons.end(); ++i) {
746                         (*i)->set_sensitive (false);
747                 }
748         }
749
750         last_drawn_capture_mode = mode;
751 }
752
753 void
754 MidiChannelSelectorWindow::playback_channel_clicked (uint16_t n)
755 {
756         if (playback_buttons[n]->get_active()) {
757                 switch (track->get_playback_channel_mode()) {
758                 case AllChannels:
759                         break;
760                 case FilterChannels:
761                         track->set_playback_channel_mask (track->get_playback_channel_mask() | (1<<n));
762                         break;
763                 case ForceChannel:
764                         track->set_playback_channel_mask (1<<n);
765                         break;
766                 }
767         } else {
768                 if (track->get_playback_channel_mode() == FilterChannels) {
769                         track->set_playback_channel_mask (track->get_playback_channel_mask() & ~(1<<n));
770                 }
771         }
772 }
773
774 void
775 MidiChannelSelectorWindow::capture_channel_clicked (uint16_t n)
776 {
777         if (capture_buttons[n]->get_active()) {
778                 switch (track->get_capture_channel_mode()) {
779                 case AllChannels:
780                         break;
781                 case FilterChannels:
782                         track->set_capture_channel_mask (track->get_capture_channel_mask() | (1<<n));
783                         break;
784                 case ForceChannel:
785                         track->set_capture_channel_mask (1<<n);
786                         break;
787                 }
788         } else {
789                 if (track->get_capture_channel_mode() == FilterChannels) {
790                         track->set_capture_channel_mask (track->get_capture_channel_mask() & ~(1<<n));
791                 }
792         }
793 }
794
795 void
796 MidiChannelSelectorWindow::capture_mode_toggled (ChannelMode mode)
797 {
798         /* this is called twice for every radio button change. the first time
799            is for the button/mode that has been turned off, and the second is for the
800            button/mode that has been turned on.
801
802            so we take action only if the button is active (i.e it is the one
803            just clicked on)
804         */
805         
806         switch (mode) {
807         case AllChannels:
808                 if (capture_all_button.get_active()) {
809                         track->set_capture_channel_mode (AllChannels, track->get_capture_channel_mask());
810                 }
811                 break;
812         case FilterChannels:
813                 if (capture_filter_button.get_active()) {
814                         track->set_capture_channel_mode (FilterChannels, track->get_capture_channel_mask());
815                 }
816                 break;
817         case ForceChannel:
818                 if (capture_force_button.get_active()) {
819                         track->set_capture_channel_mode (ForceChannel, track->get_capture_channel_mask());
820                 }
821                 break;
822         }
823 }
824
825 void
826 MidiChannelSelectorWindow::playback_mode_toggled (ChannelMode mode)
827 {
828         /* this is called twice for every radio button change. the first time
829            is for the button/mode that has been turned off, and the second is for the
830            button/mode that has been turned on.
831
832            so we take action only if the button is active (i.e it is the one
833            just clicked on)
834         */
835         
836         switch (mode) {
837         case AllChannels:
838                 if (playback_all_button.get_active()) {
839                         track->set_playback_channel_mode (AllChannels, track->get_playback_channel_mask());
840                 }
841                 break;
842         case FilterChannels:
843                 if (playback_filter_button.get_active()) {
844                         track->set_playback_channel_mode (FilterChannels, track->get_playback_channel_mask());
845                 }
846                 break;
847         case ForceChannel:
848                 if (playback_force_button.get_active()) {
849                         track->set_playback_channel_mode (ForceChannel, track->get_playback_channel_mask());
850                 }
851                 break;
852         }
853 }
854
855 void
856 MidiChannelSelectorWindow::set_channel_colors (const uint32_t new_channel_colors[16])
857 {
858         for (uint32_t n = 0; n < 16; ++n) {
859
860                 char color_normal[8];
861                 char color_active[8];
862                 
863                 snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[n], 0x000000ff, 0.6));
864                 snprintf(color_active, 8, "#%x", new_channel_colors[n]);
865
866                 playback_buttons[n]->modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
867                 playback_buttons[n]->modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
868
869                 capture_buttons[n]->modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
870                 capture_buttons[n]->modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
871         }
872 }
873
874 void
875 MidiChannelSelectorWindow::set_default_channel_color()
876 {
877         for (uint32_t n = 0; n < 16; ++n) {
878                 playback_buttons[n]->unset_fg (STATE_NORMAL);
879                 playback_buttons[n]->unset_bg (STATE_NORMAL);
880                 playback_buttons[n]->unset_fg (STATE_ACTIVE);
881                 playback_buttons[n]->unset_bg (STATE_ACTIVE);
882
883                 capture_buttons[n]->unset_fg (STATE_NORMAL);
884                 capture_buttons[n]->unset_bg (STATE_NORMAL);
885                 capture_buttons[n]->unset_fg (STATE_ACTIVE);
886                 capture_buttons[n]->unset_bg (STATE_ACTIVE);
887         }
888 }