enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[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=\"larger\" weight=\"bold\">%1: %2</span>"), _("MIDI Channel Control"), track->name())));
371         l->set_use_markup (true);
372         l->set_alignment (0.5, 0.0);
373
374         vpacker->pack_start (*l, true, true);
375
376         l = manage (new Label (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Inbound"))));
377         l->set_use_markup (true);
378         vpacker->pack_start (*l);
379
380
381         vpacker->pack_start (capture_all_button);
382         capture_all_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), AllChannels));
383
384         vpacker->pack_start (capture_filter_button);
385         capture_filter_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), FilterChannels));
386
387         vpacker->pack_start (capture_force_button);
388         capture_force_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), ForceChannel));
389
390         vpacker->pack_start (capture_mask_box);
391
392         capture_controls = manage (new HBox);
393         capture_controls->set_spacing (6);
394
395         b = manage (new Button (_("All")));
396         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to enable recording all channels"));
397         capture_controls->pack_start (*b);
398         capture_mask_controls.push_back (b);
399         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::fill_capture_mask));
400         b = manage (new Button (_("None")));
401         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to disable recording all channels"));
402         capture_controls->pack_start (*b);
403         capture_mask_controls.push_back (b);
404         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::zero_capture_mask));
405         b = manage (new Button (_("Invert")));
406         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to invert currently selected recording channels"));
407         capture_controls->pack_start (*b);
408         capture_mask_controls.push_back (b);
409         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::invert_capture_mask));
410
411         vpacker->pack_start (*capture_controls);
412
413         l = manage (new Label (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Playback"))));
414         l->set_use_markup (true);
415         vpacker->pack_start (*l);
416
417         vpacker->pack_start (playback_all_button);
418         playback_all_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), AllChannels));
419
420         vpacker->pack_start (playback_filter_button);
421         playback_filter_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), FilterChannels));
422
423         vpacker->pack_start (playback_force_button);
424         playback_force_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_mode_toggled), ForceChannel));
425
426         vpacker->pack_start (playback_mask_box);
427
428         playback_controls = manage (new HBox);
429         playback_controls->set_spacing (6);
430
431         b = manage (new Button (_("All")));
432         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to enable playback of all channels"));
433         playback_controls->pack_start (*b);
434         playback_mask_controls.push_back (b);
435         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::fill_playback_mask));
436         b = manage (new Button (_("None")));
437         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to disable playback of all channels"));
438         playback_controls->pack_start (*b);
439         playback_mask_controls.push_back (b);
440         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::zero_playback_mask));
441         b = manage (new Button (_("Invert")));
442         Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to invert current selected playback channels"));
443         playback_controls->pack_start (*b);
444         playback_mask_controls.push_back (b);
445         b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::invert_playback_mask));
446
447         vpacker->pack_start (*playback_controls);
448
449         add (*vpacker);
450 }
451
452 void
453 MidiChannelSelectorWindow::fill_playback_mask ()
454 {
455         if (track->get_playback_channel_mode() == FilterChannels) {
456                 track->set_playback_channel_mask (0xffff);
457         }
458 }
459
460 void
461 MidiChannelSelectorWindow::zero_playback_mask ()
462 {
463         if (track->get_playback_channel_mode() == FilterChannels) {
464                 track->set_playback_channel_mask (0);
465         }
466 }
467
468 void
469 MidiChannelSelectorWindow::invert_playback_mask ()
470 {
471         if (track->get_playback_channel_mode() == FilterChannels) {
472                 track->set_playback_channel_mask (~track->get_playback_channel_mask());
473         }
474 }
475
476 void
477 MidiChannelSelectorWindow::fill_capture_mask ()
478 {
479         if (track->get_capture_channel_mode() == FilterChannels) {
480                 track->set_capture_channel_mask (0xffff);
481         }
482 }
483
484 void
485 MidiChannelSelectorWindow::zero_capture_mask ()
486 {
487         if (track->get_capture_channel_mode() == FilterChannels) {
488                 track->set_capture_channel_mask (0);
489         }
490 }
491
492 void
493 MidiChannelSelectorWindow::invert_capture_mask ()
494 {
495         if (track->get_capture_channel_mode() == FilterChannels) {
496                 track->set_capture_channel_mask (~track->get_capture_channel_mask());
497         }
498 }
499
500 void
501 MidiChannelSelectorWindow::set_playback_selected_channels (uint16_t mask)
502 {
503         switch (track->get_playback_channel_mode()) {
504         case AllChannels:
505                 /* they are insensitive, so we don't care */
506                 break;
507
508         case FilterChannels:
509                 for (uint16_t i = 0; i < 16; i++) {
510                         playback_buttons[i]->set_active ((1<<i) & mask);
511                 }
512                 break;
513
514         case ForceChannel:
515                 /* only set the lowest set channel in the mask as active */
516                 for (uint16_t i = 0; i < 16; i++) {
517                         playback_buttons[i]->set_active (i == (PBD::ffs (mask) - 1));
518                 }
519                 break;
520         }
521 }
522
523 void
524 MidiChannelSelectorWindow::set_capture_selected_channels (uint16_t mask)
525 {
526         switch (track->get_capture_channel_mode()) {
527         case AllChannels:
528                 /* they are insensitive, so we don't care */
529                 break;
530
531         case FilterChannels:
532                 for (uint16_t i = 0; i < 16; i++) {
533                         capture_buttons[i]->set_active ((1<<i) & mask);
534                 }
535                 break;
536
537         case ForceChannel:
538                 /* only set the lowest set channel in the mask as active */
539                 for (uint16_t i = 0; i < 16; i++) {
540                         capture_buttons[i]->set_active (i == (PBD::ffs (mask) - 1));
541                 }
542                 break;
543         }
544 }
545
546 void
547 MidiChannelSelectorWindow::playback_mask_changed ()
548 {
549         set_playback_selected_channels (track->get_playback_channel_mask());
550 }
551
552 void
553 MidiChannelSelectorWindow::capture_mask_changed ()
554 {
555         set_capture_selected_channels (track->get_capture_channel_mask());
556 }
557
558 void
559 MidiChannelSelectorWindow::playback_mode_changed ()
560 {
561         uint32_t first_channel = 0;
562         ChannelMode mode = track->get_playback_channel_mode();
563
564         switch (mode) {
565         case AllChannels:
566                 if (last_drawn_playback_mode == ForceChannel) {
567                         /* force mode used radio buttons. not what we want,
568                          * though one could argue that we want no buttons
569                          * at since they are insensitive
570                          */
571                         playback_buttons.clear ();
572                 }
573                 for (vector<Widget*>::iterator i = playback_mask_controls.begin(); i != playback_mask_controls.end(); ++i) {
574                         (*i)->set_sensitive (false);
575                 }
576                 playback_all_button.set_active ();
577                 break;
578
579         case FilterChannels:
580                 if (last_drawn_playback_mode == ForceChannel) {
581                         playback_buttons.clear ();
582                 } else if (last_drawn_playback_mode == AllChannels) {
583                         for (vector<ToggleButton*>::iterator i = playback_buttons.begin(); i != playback_buttons.end(); ++i) {
584                                 (*i)->set_sensitive (true);
585                         }
586                 }
587                 for (vector<Widget*>::iterator i = playback_mask_controls.begin(); i != playback_mask_controls.end(); ++i) {
588                         (*i)->set_sensitive (true);
589                 }
590                 playback_filter_button.set_active ();
591                 break;
592
593         case ForceChannel:
594                 if (last_drawn_playback_mode == AllChannels || last_drawn_playback_mode == FilterChannels) {
595                         playback_buttons.clear ();
596                         first_channel = PBD::ffs (track->get_playback_channel_mask()) - 1;
597                 }
598                 for (vector<Widget*>::iterator i = playback_mask_controls.begin(); i != playback_mask_controls.end(); ++i) {
599                         (*i)->set_sensitive (false);
600                 }
601                 playback_force_button.set_active ();
602                 break;
603         }
604
605         if (playback_buttons.empty()) {
606
607                 Gtkmm2ext::container_clear (playback_mask_box);
608
609                 ToggleButton* tb;
610                 RadioButtonGroup group;
611
612                 for (uint32_t n = 0; n < 16; ++n) {
613                         char buf[3];
614                         snprintf (buf, sizeof (buf), "%d", n+1);
615
616                         switch (mode) {
617                         case AllChannels:
618                         case FilterChannels:
619                                 tb = manage (new ToggleButton (buf));
620                                 Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to toggle playback of channel %1"), n+1));
621                                 break;
622                         case ForceChannel:
623                                 tb = manage (new RadioButton (group, buf));
624                                 tb->property_draw_indicator() = false;
625                                 if (n == first_channel) {
626                                         tb->set_active (true);
627                                 }
628                                 Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to force all MIDI channel messages to channel %1"), n+1));
629                                 break;
630                         }
631                         playback_buttons.push_back (tb);
632                         tb->set_name (X_("MidiChannelSelectorButton"));
633                         playback_mask_box.pack_start (*tb);
634                         tb->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::playback_channel_clicked), n));
635                         tb->show ();
636
637                         if (mode == AllChannels) {
638                                 tb->set_sensitive (false);
639                         }
640                 }
641
642                 if (mode != ForceChannel) {
643                         set_playback_selected_channels (track->get_playback_channel_mask());
644                 }
645         }
646
647         if (mode == AllChannels) {
648                 for (vector<ToggleButton*>::iterator i = playback_buttons.begin(); i != playback_buttons.end(); ++i) {
649                         (*i)->set_sensitive (false);
650                 }
651         }
652
653         playback_mask_changed(); // update buttons
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         capture_mask_changed (); // udpate buttons
754
755         last_drawn_capture_mode = mode;
756 }
757
758 void
759 MidiChannelSelectorWindow::playback_channel_clicked (uint16_t n)
760 {
761         if (playback_buttons[n]->get_active()) {
762                 switch (track->get_playback_channel_mode()) {
763                 case AllChannels:
764                         break;
765                 case FilterChannels:
766                         track->set_playback_channel_mask (track->get_playback_channel_mask() | (1<<n));
767                         break;
768                 case ForceChannel:
769                         track->set_playback_channel_mask (1<<n);
770                         break;
771                 }
772         } else {
773                 if (track->get_playback_channel_mode() == FilterChannels) {
774                         track->set_playback_channel_mask (track->get_playback_channel_mask() & ~(1<<n));
775                 }
776         }
777 }
778
779 void
780 MidiChannelSelectorWindow::capture_channel_clicked (uint16_t n)
781 {
782         if (capture_buttons[n]->get_active()) {
783                 switch (track->get_capture_channel_mode()) {
784                 case AllChannels:
785                         break;
786                 case FilterChannels:
787                         track->set_capture_channel_mask (track->get_capture_channel_mask() | (1<<n));
788                         break;
789                 case ForceChannel:
790                         track->set_capture_channel_mask (1<<n);
791                         break;
792                 }
793         } else {
794                 if (track->get_capture_channel_mode() == FilterChannels) {
795                         track->set_capture_channel_mask (track->get_capture_channel_mask() & ~(1<<n));
796                 }
797         }
798 }
799
800 void
801 MidiChannelSelectorWindow::capture_mode_toggled (ChannelMode mode)
802 {
803         /* this is called twice for every radio button change. the first time
804            is for the button/mode that has been turned off, and the second is for the
805            button/mode that has been turned on.
806
807            so we take action only if the button is active (i.e it is the one
808            just clicked on)
809         */
810
811         switch (mode) {
812         case AllChannels:
813                 if (capture_all_button.get_active()) {
814                         track->set_capture_channel_mode (AllChannels, track->get_capture_channel_mask());
815                 }
816                 break;
817         case FilterChannels:
818                 if (capture_filter_button.get_active()) {
819                         track->set_capture_channel_mode (FilterChannels, track->get_capture_channel_mask());
820                 }
821                 break;
822         case ForceChannel:
823                 if (capture_force_button.get_active()) {
824                         track->set_capture_channel_mode (ForceChannel, track->get_capture_channel_mask());
825                 }
826                 break;
827         }
828 }
829
830 void
831 MidiChannelSelectorWindow::playback_mode_toggled (ChannelMode mode)
832 {
833         /* this is called twice for every radio button change. the first time
834            is for the button/mode that has been turned off, and the second is for the
835            button/mode that has been turned on.
836
837            so we take action only if the button is active (i.e it is the one
838            just clicked on)
839         */
840
841         switch (mode) {
842         case AllChannels:
843                 if (playback_all_button.get_active()) {
844                         track->set_playback_channel_mode (AllChannels, track->get_playback_channel_mask());
845                 }
846                 break;
847         case FilterChannels:
848                 if (playback_filter_button.get_active()) {
849                         track->set_playback_channel_mode (FilterChannels, track->get_playback_channel_mask());
850                 }
851                 break;
852         case ForceChannel:
853                 if (playback_force_button.get_active()) {
854                         track->set_playback_channel_mode (ForceChannel, track->get_playback_channel_mask());
855                 }
856                 break;
857         }
858 }
859
860 void
861 MidiChannelSelectorWindow::set_channel_colors (const uint32_t new_channel_colors[16])
862 {
863         for (uint32_t n = 0; n < 16; ++n) {
864
865                 char color_normal[8];
866                 char color_active[8];
867
868                 snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[n], 0x000000ff, 0.6));
869                 snprintf(color_active, 8, "#%x", new_channel_colors[n]);
870
871                 playback_buttons[n]->modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
872                 playback_buttons[n]->modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
873
874                 capture_buttons[n]->modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
875                 capture_buttons[n]->modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
876         }
877 }
878
879 void
880 MidiChannelSelectorWindow::set_default_channel_color()
881 {
882         for (uint32_t n = 0; n < 16; ++n) {
883                 playback_buttons[n]->unset_fg (STATE_NORMAL);
884                 playback_buttons[n]->unset_bg (STATE_NORMAL);
885                 playback_buttons[n]->unset_fg (STATE_ACTIVE);
886                 playback_buttons[n]->unset_bg (STATE_ACTIVE);
887
888                 capture_buttons[n]->unset_fg (STATE_NORMAL);
889                 capture_buttons[n]->unset_bg (STATE_NORMAL);
890                 capture_buttons[n]->unset_fg (STATE_ACTIVE);
891                 capture_buttons[n]->unset_bg (STATE_ACTIVE);
892         }
893 }