2 * Copyright (C) 2008-2015 David Robillard <d@drobilla.net>
3 * Copyright (C) 2008 Hans Baier <hansfbaier@googlemail.com>
4 * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
5 * Copyright (C) 2009-2016 Paul Davis <paul@linuxaudiosystems.com>
6 * Copyright (C) 2015 Robin Gareus <robin@gareus.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include <gtkmm/separator.h>
26 #include <gtkmm/box.h>
27 #include <gtkmm/label.h>
28 #include <gtkmm/togglebutton.h>
29 #include <gtkmm/radiobutton.h>
30 #include <gtkmm/table.h>
32 #include "pbd/compose.h"
35 #include "gtkmm2ext/gtk_ui.h"
36 #include "gtkmm2ext/gui_thread.h"
37 #include "gtkmm2ext/utils.h"
39 #include "ardour/midi_track.h"
41 #include "midi_channel_selector.h"
42 #include "rgb_macros.h"
48 using namespace ARDOUR;
50 MidiChannelSelector::MidiChannelSelector(int n_rows, int n_columns, int start_row, int start_column)
51 : Table(std::max(4, std::max(n_rows, start_row + 4)),
52 std::max(4, std::max(n_columns, start_column + 4)),
54 , _recursion_counter(0)
56 property_column_spacing() = 0;
57 property_row_spacing() = 0;
59 uint8_t channel_nr = 0;
60 for (int row = 0; row < 4; ++row) {
61 for (int column = 0; column < 4; ++column) {
62 ostringstream channel;
63 channel << int(++channel_nr);
64 _button_labels[row][column].set_text(channel.str());
65 _button_labels[row][column].set_justify(JUSTIFY_RIGHT);
66 _buttons[row][column].add(_button_labels[row][column]);
67 _buttons[row][column].signal_toggled().connect(
69 sigc::mem_fun(this, &MidiChannelSelector::button_toggled),
70 &_buttons[row][column],
72 _buttons[row][column].set_widget_name (X_("MidiChannelSelectorButton"));
74 _buttons[row][column].signal_button_release_event().connect(
75 sigc::mem_fun(this, &MidiChannelSelector::was_clicked), false);
77 int table_row = start_row + row;
78 int table_column = start_column + column;
79 attach(_buttons[row][column], table_column, table_column + 1, table_row, table_row + 1);
84 MidiChannelSelector::~MidiChannelSelector()
89 MidiChannelSelector::was_clicked (GdkEventButton*)
96 MidiChannelSelector::set_channel_colors(const uint32_t new_channel_colors[16])
98 for (int row = 0; row < 4; ++row) {
99 for (int column = 0; column < 4; ++column) {
100 char color_normal[8];
101 char color_active[8];
102 snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[row * 4 + column], 0x000000ff, 0.6));
103 snprintf(color_active, 8, "#%x", new_channel_colors[row * 4 + column]);
104 _buttons[row][column].modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
105 _buttons[row][column].modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
111 MidiChannelSelector::set_default_channel_color()
113 for (int row = 0; row < 4; ++row) {
114 for (int column = 0; column < 4; ++column) {
115 _buttons[row][column].unset_fg (STATE_NORMAL);
116 _buttons[row][column].unset_fg (STATE_ACTIVE);
117 _buttons[row][column].unset_bg (STATE_NORMAL);
118 _buttons[row][column].unset_bg (STATE_ACTIVE);
123 SingleMidiChannelSelector::SingleMidiChannelSelector(uint8_t active_channel)
124 : MidiChannelSelector()
126 _last_active_button = 0;
127 ToggleButton* button = &_buttons[active_channel / 4][active_channel % 4];
128 _active_channel = active_channel;
129 button->set_active(true);
130 _last_active_button = button;
134 SingleMidiChannelSelector::button_toggled(ToggleButton* button, uint8_t channel)
136 ++_recursion_counter;
137 if (_recursion_counter == 1) {
138 // if the current button is active it must
139 // be different from the first one
140 if (button->get_active()) {
141 if (_last_active_button) {
142 _last_active_button->set_active(false);
143 _active_channel = channel;
144 _last_active_button = button;
145 channel_selected.emit(channel);
148 // if not, the user pressed the already active button
149 button->set_active(true);
150 _active_channel = channel;
153 --_recursion_counter;
156 MidiMultipleChannelSelector::MidiMultipleChannelSelector(ChannelMode mode, uint16_t mask)
157 : MidiChannelSelector(4, 6, 0, 0)
158 , _channel_mode(mode)
160 _select_all.add(*manage(new Label(_("All"))));
161 _select_all.signal_clicked().connect(
162 sigc::bind(sigc::mem_fun(this, &MidiMultipleChannelSelector::select_all), true));
164 _select_none.add(*manage(new Label(_("None"))));
165 _select_none.signal_clicked().connect(
166 sigc::bind(sigc::mem_fun(this, &MidiMultipleChannelSelector::select_all), false));
168 _invert_selection.add(*manage(new Label(_("Invert"))));
169 _invert_selection.signal_clicked().connect(
170 sigc::mem_fun(this, &MidiMultipleChannelSelector::invert_selection));
172 _force_channel.add(*manage(new Label(_("Force"))));
173 _force_channel.signal_toggled().connect(
174 sigc::mem_fun(this, &MidiMultipleChannelSelector::force_channels_button_toggled));
176 set_homogeneous(false);
177 attach(*manage(new VSeparator()), 4, 5, 0, 4, SHRINK, FILL, 0, 0);
178 //set_row_spacing(4, -5);
179 attach(_select_all, 5, 6, 0, 1);
180 attach(_select_none, 5, 6, 1, 2);
181 attach(_invert_selection, 5, 6, 2, 3);
182 attach(_force_channel, 5, 6, 3, 4);
184 set_selected_channels(mask);
187 MidiMultipleChannelSelector::~MidiMultipleChannelSelector()
189 mode_changed.clear();
193 MidiMultipleChannelSelector::set_channel_mode(ChannelMode mode, uint16_t mask)
197 _force_channel.set_active(false);
198 set_selected_channels(0xFFFF);
201 _force_channel.set_active(false);
202 set_selected_channels(mask);
205 _force_channel.set_active(true);
206 for (uint16_t i = 0; i < 16; i++) {
207 ToggleButton* button = &_buttons[i / 4][i % 4];
208 button->set_active(i == mask);
214 MidiMultipleChannelSelector::get_selected_channels() const
216 uint16_t selected_channels = 0;
217 for (uint16_t i = 0; i < 16; i++) {
218 const ToggleButton* button = &_buttons[i / 4][i % 4];
219 if (button->get_active()) {
220 selected_channels |= (1L << i);
224 return selected_channels;
228 MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels)
230 for (uint16_t i = 0; i < 16; i++) {
231 ToggleButton* button = &_buttons[i / 4][i % 4];
232 if (selected_channels & (1L << i)) {
233 button->set_active(true);
235 button->set_active(false);
241 MidiMultipleChannelSelector::button_toggled(ToggleButton */*button*/, uint8_t channel)
243 ++_recursion_counter;
244 if (_recursion_counter == 1) {
245 if (_channel_mode == ForceChannel) {
246 mode_changed.emit(_channel_mode, channel);
247 set_selected_channels(1 << channel);
249 mode_changed.emit(_channel_mode, get_selected_channels());
252 --_recursion_counter;
256 MidiMultipleChannelSelector::force_channels_button_toggled()
258 if (_force_channel.get_active()) {
259 _channel_mode = ForceChannel;
260 bool found_first_active = false;
261 // leave only the first button enabled
262 uint16_t active_channel = 0;
263 for (int i = 0; i <= 15; i++) {
264 ToggleButton* button = &_buttons[i / 4][i % 4];
265 if (button->get_active()) {
266 if (found_first_active) {
267 ++_recursion_counter;
268 button->set_active(false);
269 --_recursion_counter;
271 found_first_active = true;
277 if (!found_first_active) {
278 _buttons[0][0].set_active(true);
281 _select_all.set_sensitive(false);
282 _select_none.set_sensitive(false);
283 _invert_selection.set_sensitive(false);
284 mode_changed.emit(_channel_mode, active_channel);
286 _channel_mode = FilterChannels;
287 _select_all.set_sensitive(true);
288 _select_none.set_sensitive(true);
289 _invert_selection.set_sensitive(true);
290 mode_changed.emit(FilterChannels, get_selected_channels());
295 MidiMultipleChannelSelector::select_all(bool on)
297 if (_channel_mode == ForceChannel)
300 ++_recursion_counter;
301 for (uint16_t i = 0; i < 16; i++) {
302 ToggleButton* button = &_buttons[i / 4][i % 4];
303 button->set_active(on);
305 --_recursion_counter;
306 mode_changed.emit(_channel_mode, get_selected_channels());
310 MidiMultipleChannelSelector::invert_selection(void)
312 if (_channel_mode == ForceChannel)
315 ++_recursion_counter;
316 for (uint16_t i = 0; i < 16; i++) {
317 ToggleButton* button = &_buttons[i / 4][i % 4];
318 if (button->get_active()) {
319 button->set_active(false);
321 button->set_active(true);
324 --_recursion_counter;
325 mode_changed.emit(_channel_mode, get_selected_channels());
328 /*-----------------------------------------*/
330 MidiChannelSelectorWindow::MidiChannelSelectorWindow (boost::shared_ptr<MidiTrack> mt)
331 : ArdourWindow (_("MIDI Channel Control"))
333 , playback_all_button (playback_button_group, _("Playback all channels"))
334 , playback_filter_button (playback_button_group, _("Play only selected channels"))
335 , playback_force_button (playback_button_group, _("Use a single fixed channel for all playback"))
336 , capture_all_button (capture_button_group, _("Record all channels"))
337 , capture_filter_button (capture_button_group, _("Record only selected channels"))
338 , capture_force_button (capture_button_group, _("Force all channels to 1 channel"))
339 , last_drawn_capture_mode (AllChannels)
340 , last_drawn_playback_mode (AllChannels)
344 playback_mode_changed ();
345 capture_mode_changed ();
347 playback_mask_changed ();
348 capture_mask_changed ();
350 track->playback_filter().ChannelMaskChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::playback_mask_changed, this), gui_context());
351 track->playback_filter().ChannelModeChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::playback_mode_changed, this), gui_context());
352 track->capture_filter().ChannelMaskChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::capture_mask_changed, this), gui_context());
353 track->capture_filter().ChannelModeChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&MidiChannelSelectorWindow::capture_mode_changed, this), gui_context());
356 MidiChannelSelectorWindow::~MidiChannelSelectorWindow()
361 MidiChannelSelectorWindow::build ()
364 HBox* capture_controls;
365 HBox* playback_controls;
369 vpacker = manage (new VBox);
370 vpacker->set_spacing (6);
371 vpacker->set_border_width (12);
373 l = manage (new Label (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Inbound"))));
374 l->set_use_markup (true);
375 vpacker->pack_start (*l, true, true);
377 vpacker->pack_start (capture_all_button);
378 capture_all_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), AllChannels));
380 vpacker->pack_start (capture_filter_button);
381 capture_filter_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), FilterChannels));
383 vpacker->pack_start (capture_force_button);
384 capture_force_button.signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_mode_toggled), ForceChannel));
386 vpacker->pack_start (capture_mask_box);
388 capture_controls = manage (new HBox);
389 capture_controls->set_spacing (6);
391 b = manage (new Button (_("All")));
392 Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to enable recording all channels"));
393 capture_controls->pack_start (*b);
394 capture_mask_controls.push_back (b);
395 b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::fill_capture_mask));
396 b = manage (new Button (_("None")));
397 Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to disable recording all channels"));
398 capture_controls->pack_start (*b);
399 capture_mask_controls.push_back (b);
400 b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::zero_capture_mask));
401 b = manage (new Button (_("Invert")));
402 Gtkmm2ext::UI::instance()->set_tip (*b, _("Click to invert currently selected recording channels"));
403 capture_controls->pack_start (*b);
404 capture_mask_controls.push_back (b);
405 b->signal_clicked().connect (sigc::mem_fun (*this, &MidiChannelSelectorWindow::invert_capture_mask));
407 vpacker->pack_start (*capture_controls);
409 Gtk::HSeparator *hseparator2 = manage(new Gtk::HSeparator);
410 vpacker->pack_start (*hseparator2, false, false, 6);
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);
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));
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));
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));
425 vpacker->pack_start (playback_mask_box);
427 playback_controls = manage (new HBox);
428 playback_controls->set_spacing (6);
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));
446 vpacker->pack_start (*playback_controls);
452 MidiChannelSelectorWindow::fill_playback_mask ()
454 if (track->get_playback_channel_mode() == FilterChannels) {
455 track->set_playback_channel_mask (0xffff);
460 MidiChannelSelectorWindow::zero_playback_mask ()
462 if (track->get_playback_channel_mode() == FilterChannels) {
463 track->set_playback_channel_mask (0);
468 MidiChannelSelectorWindow::invert_playback_mask ()
470 if (track->get_playback_channel_mode() == FilterChannels) {
471 track->set_playback_channel_mask (~track->get_playback_channel_mask());
476 MidiChannelSelectorWindow::fill_capture_mask ()
478 if (track->get_capture_channel_mode() == FilterChannels) {
479 track->set_capture_channel_mask (0xffff);
484 MidiChannelSelectorWindow::zero_capture_mask ()
486 if (track->get_capture_channel_mode() == FilterChannels) {
487 track->set_capture_channel_mask (0);
492 MidiChannelSelectorWindow::invert_capture_mask ()
494 if (track->get_capture_channel_mode() == FilterChannels) {
495 track->set_capture_channel_mask (~track->get_capture_channel_mask());
500 MidiChannelSelectorWindow::set_playback_selected_channels (uint16_t mask)
502 switch (track->get_playback_channel_mode()) {
504 /* they are insensitive, so we don't care */
508 for (uint16_t i = 0; i < 16; i++) {
509 playback_buttons[i]->set_active ((1<<i) & mask);
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));
523 MidiChannelSelectorWindow::set_capture_selected_channels (uint16_t mask)
525 switch (track->get_capture_channel_mode()) {
527 /* they are insensitive, so we don't care */
531 for (uint16_t i = 0; i < 16; i++) {
532 capture_buttons[i]->set_active ((1<<i) & mask);
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));
546 MidiChannelSelectorWindow::playback_mask_changed ()
548 set_playback_selected_channels (track->get_playback_channel_mask());
552 MidiChannelSelectorWindow::capture_mask_changed ()
554 set_capture_selected_channels (track->get_capture_channel_mask());
558 MidiChannelSelectorWindow::playback_mode_changed ()
560 uint32_t first_channel = 0;
561 ChannelMode mode = track->get_playback_channel_mode();
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
570 playback_buttons.clear ();
572 for (vector<Widget*>::iterator i = playback_mask_controls.begin(); i != playback_mask_controls.end(); ++i) {
573 (*i)->set_sensitive (false);
575 playback_all_button.set_active ();
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);
586 for (vector<Widget*>::iterator i = playback_mask_controls.begin(); i != playback_mask_controls.end(); ++i) {
587 (*i)->set_sensitive (true);
589 playback_filter_button.set_active ();
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;
597 for (vector<Widget*>::iterator i = playback_mask_controls.begin(); i != playback_mask_controls.end(); ++i) {
598 (*i)->set_sensitive (false);
600 playback_force_button.set_active ();
604 if (playback_buttons.empty()) {
606 Gtkmm2ext::container_clear (playback_mask_box);
609 RadioButtonGroup group;
611 for (uint32_t n = 0; n < 16; ++n) {
613 snprintf (buf, sizeof (buf), "%d", n+1);
618 tb = manage (new ToggleButton (buf));
619 Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to toggle playback of channel %1"), n+1));
622 tb = manage (new RadioButton (group, buf));
623 tb->property_draw_indicator() = false;
624 if (n == first_channel) {
625 tb->set_active (true);
627 Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to force all MIDI channel messages to channel %1"), n+1));
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));
636 if (mode == AllChannels) {
637 tb->set_sensitive (false);
641 if (mode != ForceChannel) {
642 set_playback_selected_channels (track->get_playback_channel_mask());
646 if (mode == AllChannels) {
647 for (vector<ToggleButton*>::iterator i = playback_buttons.begin(); i != playback_buttons.end(); ++i) {
648 (*i)->set_sensitive (false);
652 playback_mask_changed(); // update buttons
654 last_drawn_playback_mode = mode;
658 MidiChannelSelectorWindow::capture_mode_changed ()
660 uint32_t first_channel = 0;
661 ChannelMode mode = track->get_capture_channel_mode();
665 if (last_drawn_capture_mode == ForceChannel) {
666 /* force mode used radio buttons. not what we want,
667 * though one could argue that we want no buttons
668 * at since they are insensitive
670 capture_buttons.clear ();
672 for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
673 (*i)->set_sensitive (false);
675 capture_all_button.set_active ();
679 if (last_drawn_capture_mode == ForceChannel) {
680 capture_buttons.clear ();
681 } else if (last_drawn_capture_mode == AllChannels) {
682 for (vector<ToggleButton*>::iterator i = capture_buttons.begin(); i != capture_buttons.end(); ++i) {
683 (*i)->set_sensitive (true);
686 for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
687 (*i)->set_sensitive (true);
689 capture_filter_button.set_active ();
693 if (last_drawn_capture_mode == AllChannels || last_drawn_capture_mode == FilterChannels) {
694 capture_buttons.clear ();
695 first_channel = PBD::ffs (track->get_capture_channel_mask()) - 1;
697 for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
698 (*i)->set_sensitive (false);
700 capture_force_button.set_active ();
704 if (capture_buttons.empty()) {
706 Gtkmm2ext::container_clear (capture_mask_box);
709 RadioButtonGroup group;
711 for (uint32_t n = 0; n < 16; ++n) {
713 snprintf (buf, sizeof (buf), "%d", n+1);
718 tb = manage (new ToggleButton (buf));
719 Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to toggle recording of channel %1"), n+1));
722 tb = manage (new RadioButton (group, buf));
723 tb->property_draw_indicator() = false;
724 if (n == first_channel) {
725 tb->set_active (true);
727 Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to force all recorded channels to %1"), n+1));
730 capture_buttons.push_back (tb);
731 tb->set_name (X_("MidiChannelSelectorButton"));
732 capture_mask_box.pack_start (*tb);
733 tb->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_channel_clicked), n));
736 if (mode == AllChannels) {
737 tb->set_sensitive (false);
741 if (mode != ForceChannel) {
742 set_capture_selected_channels (track->get_capture_channel_mask());
746 if (mode == AllChannels) {
747 for (vector<ToggleButton*>::iterator i = capture_buttons.begin(); i != capture_buttons.end(); ++i) {
748 (*i)->set_sensitive (false);
752 capture_mask_changed (); // udpate buttons
754 last_drawn_capture_mode = mode;
758 MidiChannelSelectorWindow::playback_channel_clicked (uint16_t n)
760 if (playback_buttons[n]->get_active()) {
761 switch (track->get_playback_channel_mode()) {
765 track->set_playback_channel_mask (track->get_playback_channel_mask() | (1<<n));
768 track->set_playback_channel_mask (1<<n);
772 if (track->get_playback_channel_mode() == FilterChannels) {
773 track->set_playback_channel_mask (track->get_playback_channel_mask() & ~(1<<n));
779 MidiChannelSelectorWindow::capture_channel_clicked (uint16_t n)
781 if (capture_buttons[n]->get_active()) {
782 switch (track->get_capture_channel_mode()) {
786 track->set_capture_channel_mask (track->get_capture_channel_mask() | (1<<n));
789 track->set_capture_channel_mask (1<<n);
793 if (track->get_capture_channel_mode() == FilterChannels) {
794 track->set_capture_channel_mask (track->get_capture_channel_mask() & ~(1<<n));
800 MidiChannelSelectorWindow::capture_mode_toggled (ChannelMode mode)
802 /* this is called twice for every radio button change. the first time
803 is for the button/mode that has been turned off, and the second is for the
804 button/mode that has been turned on.
806 so we take action only if the button is active (i.e it is the one
812 if (capture_all_button.get_active()) {
813 track->set_capture_channel_mode (AllChannels, track->get_capture_channel_mask());
817 if (capture_filter_button.get_active()) {
818 track->set_capture_channel_mode (FilterChannels, track->get_capture_channel_mask());
822 if (capture_force_button.get_active()) {
823 track->set_capture_channel_mode (ForceChannel, track->get_capture_channel_mask());
830 MidiChannelSelectorWindow::playback_mode_toggled (ChannelMode mode)
832 /* this is called twice for every radio button change. the first time
833 is for the button/mode that has been turned off, and the second is for the
834 button/mode that has been turned on.
836 so we take action only if the button is active (i.e it is the one
842 if (playback_all_button.get_active()) {
843 track->set_playback_channel_mode (AllChannels, track->get_playback_channel_mask());
847 if (playback_filter_button.get_active()) {
848 track->set_playback_channel_mode (FilterChannels, track->get_playback_channel_mask());
852 if (playback_force_button.get_active()) {
853 track->set_playback_channel_mode (ForceChannel, track->get_playback_channel_mask());
860 MidiChannelSelectorWindow::set_channel_colors (const uint32_t new_channel_colors[16])
862 for (uint32_t n = 0; n < 16; ++n) {
864 char color_normal[8];
865 char color_active[8];
867 snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[n], 0x000000ff, 0.6));
868 snprintf(color_active, 8, "#%x", new_channel_colors[n]);
870 playback_buttons[n]->modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
871 playback_buttons[n]->modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
873 capture_buttons[n]->modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
874 capture_buttons[n]->modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
879 MidiChannelSelectorWindow::set_default_channel_color()
881 for (uint32_t n = 0; n < 16; ++n) {
882 playback_buttons[n]->unset_fg (STATE_NORMAL);
883 playback_buttons[n]->unset_bg (STATE_NORMAL);
884 playback_buttons[n]->unset_fg (STATE_ACTIVE);
885 playback_buttons[n]->unset_bg (STATE_ACTIVE);
887 capture_buttons[n]->unset_fg (STATE_NORMAL);
888 capture_buttons[n]->unset_bg (STATE_NORMAL);
889 capture_buttons[n]->unset_fg (STATE_ACTIVE);
890 capture_buttons[n]->unset_bg (STATE_ACTIVE);