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