ardour
midi_channel_selector.cc
Go to the documentation of this file.
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 "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 
82 {
83 }
84 
85 bool
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
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 
122 {
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 {
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  }
151 }
152 
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(
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 
185 {
186  mode_changed.clear();
187 }
188 
189 void
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
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
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 {
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 {
247  }
248  }
250 }
251 
252 void
254 {
255  if (_force_channel.get_active()) {
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) {
265  button->set_active(false);
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 {
284  _select_all.set_sensitive(true);
285  _select_none.set_sensitive(true);
286  _invert_selection.set_sensitive(true);
288  }
289 }
290 
291 void
293 {
295  return;
296 
298  for (uint16_t i = 0; i < 16; i++) {
299  ToggleButton* button = &_buttons[i / 4][i % 4];
300  button->set_active(on);
301  }
304 }
305 
306 void
308 {
310  return;
311 
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  }
323 }
324 
325 /*-----------------------------------------*/
326 
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 
343 
346 
351 }
352 
354 {
355 }
356 
357 void
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
454 {
457  }
458 }
459 
460 void
462 {
465  }
466 }
467 
468 void
470 {
473  }
474 }
475 
476 void
478 {
481  }
482 }
483 
484 void
486 {
489  }
490 }
491 
492 void
494 {
497  }
498 }
499 
500 void
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
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
548 {
550 }
551 
552 void
554 {
556 }
557 
558 void
560 {
561  uint32_t first_channel = 0;
563 
564  switch (mode) {
565  case AllChannels:
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:
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:
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 
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) {
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 
654 }
655 
656 void
658 {
659  uint32_t first_channel = 0;
661 
662  switch (mode) {
663  case AllChannels:
665  /* force mode used radio buttons. not what we want,
666  * though one could argue that we want no buttons
667  * at since they are insensitive
668  */
669  capture_buttons.clear ();
670  }
671  for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
672  (*i)->set_sensitive (false);
673  }
674  capture_all_button.set_active ();
675  break;
676 
677  case FilterChannels:
679  capture_buttons.clear ();
680  } else if (last_drawn_capture_mode == AllChannels) {
681  for (vector<ToggleButton*>::iterator i = capture_buttons.begin(); i != capture_buttons.end(); ++i) {
682  (*i)->set_sensitive (true);
683  }
684  }
685  for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
686  (*i)->set_sensitive (true);
687  }
688  capture_filter_button.set_active ();
689  break;
690 
691  case ForceChannel:
693  capture_buttons.clear ();
694  first_channel = PBD::ffs (track->get_capture_channel_mask()) - 1;
695  }
696  for (vector<Widget*>::iterator i = capture_mask_controls.begin(); i != capture_mask_controls.end(); ++i) {
697  (*i)->set_sensitive (false);
698  }
699  capture_force_button.set_active ();
700  break;
701  }
702 
703  if (capture_buttons.empty()) {
704 
706 
707  ToggleButton* tb;
708  RadioButtonGroup group;
709 
710  for (uint32_t n = 0; n < 16; ++n) {
711  char buf[3];
712  snprintf (buf, sizeof (buf), "%d", n+1);
713 
714  switch (mode) {
715  case AllChannels:
716  case FilterChannels:
717  tb = manage (new ToggleButton (buf));
718  Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to toggle recording of channel %1"), n+1));
719  break;
720  case ForceChannel:
721  tb = manage (new RadioButton (group, buf));
722  tb->property_draw_indicator() = false;
723  if (n == first_channel) {
724  tb->set_active (true);
725  }
726  Gtkmm2ext::UI::instance()->set_tip (*tb, string_compose (_("Click to force all recorded channels to %1"), n+1));
727  break;
728  }
729  capture_buttons.push_back (tb);
730  tb->set_name (X_("MidiChannelSelectorButton"));
731  capture_mask_box.pack_start (*tb);
732  tb->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiChannelSelectorWindow::capture_channel_clicked), n));
733  tb->show ();
734 
735  if (mode == AllChannels) {
736  tb->set_sensitive (false);
737  }
738  }
739 
740  if (mode != ForceChannel) {
742  }
743  }
744 
745  if (mode == AllChannels) {
746  for (vector<ToggleButton*>::iterator i = capture_buttons.begin(); i != capture_buttons.end(); ++i) {
747  (*i)->set_sensitive (false);
748  }
749  }
750 
752 }
753 
754 void
756 {
757  if (playback_buttons[n]->get_active()) {
758  switch (track->get_playback_channel_mode()) {
759  case AllChannels:
760  break;
761  case FilterChannels:
763  break;
764  case ForceChannel:
766  break;
767  }
768  } else {
771  }
772  }
773 }
774 
775 void
777 {
778  if (capture_buttons[n]->get_active()) {
779  switch (track->get_capture_channel_mode()) {
780  case AllChannels:
781  break;
782  case FilterChannels:
784  break;
785  case ForceChannel:
787  break;
788  }
789  } else {
792  }
793  }
794 }
795 
796 void
798 {
799  /* this is called twice for every radio button change. the first time
800  is for the button/mode that has been turned off, and the second is for the
801  button/mode that has been turned on.
802 
803  so we take action only if the button is active (i.e it is the one
804  just clicked on)
805  */
806 
807  switch (mode) {
808  case AllChannels:
809  if (capture_all_button.get_active()) {
811  }
812  break;
813  case FilterChannels:
814  if (capture_filter_button.get_active()) {
816  }
817  break;
818  case ForceChannel:
819  if (capture_force_button.get_active()) {
821  }
822  break;
823  }
824 }
825 
826 void
828 {
829  /* this is called twice for every radio button change. the first time
830  is for the button/mode that has been turned off, and the second is for the
831  button/mode that has been turned on.
832 
833  so we take action only if the button is active (i.e it is the one
834  just clicked on)
835  */
836 
837  switch (mode) {
838  case AllChannels:
839  if (playback_all_button.get_active()) {
841  }
842  break;
843  case FilterChannels:
844  if (playback_filter_button.get_active()) {
846  }
847  break;
848  case ForceChannel:
849  if (playback_force_button.get_active()) {
851  }
852  break;
853  }
854 }
855 
856 void
857 MidiChannelSelectorWindow::set_channel_colors (const uint32_t new_channel_colors[16])
858 {
859  for (uint32_t n = 0; n < 16; ++n) {
860 
861  char color_normal[8];
862  char color_active[8];
863 
864  snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[n], 0x000000ff, 0.6));
865  snprintf(color_active, 8, "#%x", new_channel_colors[n]);
866 
867  playback_buttons[n]->modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
868  playback_buttons[n]->modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
869 
870  capture_buttons[n]->modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
871  capture_buttons[n]->modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
872  }
873 }
874 
875 void
877 {
878  for (uint32_t n = 0; n < 16; ++n) {
879  playback_buttons[n]->unset_fg (STATE_NORMAL);
880  playback_buttons[n]->unset_bg (STATE_NORMAL);
881  playback_buttons[n]->unset_fg (STATE_ACTIVE);
882  playback_buttons[n]->unset_bg (STATE_ACTIVE);
883 
884  capture_buttons[n]->unset_fg (STATE_NORMAL);
885  capture_buttons[n]->unset_bg (STATE_NORMAL);
886  capture_buttons[n]->unset_fg (STATE_ACTIVE);
887  capture_buttons[n]->unset_bg (STATE_ACTIVE);
888  }
889 }
void set_channel_mode(ARDOUR::ChannelMode mode, uint16_t mask)
std::vector< Gtk::Widget * > playback_mask_controls
Force all events to a certain channel.
Definition: types.h:212
void set_channel_colors(const uint32_t new_channel_colors[16])
PBD::Signal0< void > ChannelModeChanged
int ffs(int x)
Definition: ffs.cc:28
void set_selected_channels(uint16_t selected_channels)
std::vector< Gtk::Widget * > capture_mask_controls
void set_capture_selected_channels(uint16_t)
Definition: ardour_ui.h:130
ARDOUR::ChannelMode last_drawn_playback_mode
std::vector< Gtk::ToggleButton * > capture_buttons
ARDOUR::ChannelMode last_drawn_capture_mode
Definition: Beats.hpp:239
Gtk::RadioButton playback_filter_button
uint16_t get_playback_channel_mask() const
Definition: midi_track.h:119
ChannelMode
Definition: types.h:209
virtual void button_toggled(Gtk::ToggleButton *button, uint8_t button_nr)
void set_capture_channel_mode(ChannelMode mode, uint16_t mask)
Definition: midi_track.cc:784
sigc::signal< void > clicked
MidiChannelFilter & playback_filter()
Definition: midi_track.h:122
void set_playback_channel_mask(uint16_t mask)
Definition: midi_track.cc:792
static UI * instance()
Definition: gtk_ui.h:119
PBD::Signal0< void > ChannelMaskChanged
uint16_t get_capture_channel_mask() const
Definition: midi_track.h:120
#define _(Text)
Definition: i18n.h:11
boost::shared_ptr< ARDOUR::MidiTrack > track
void set_capture_channel_mask(uint16_t mask)
Definition: midi_track.cc:800
#define X_(Text)
Definition: i18n.h:13
sigc::signal< void, uint8_t > channel_selected
void set_channel_colors(const uint32_t new_channel_colors[16])
virtual void button_toggled(Gtk::ToggleButton *button, uint8_t button_nr)
Gtkmm2ext::StatefulToggleButton _buttons[4][4]
void set_playback_channel_mode(ChannelMode mode, uint16_t mask)
Definition: midi_track.cc:776
MidiChannelFilter & capture_filter()
Definition: midi_track.h:123
MidiMultipleChannelSelector(ARDOUR::ChannelMode mode=ARDOUR::FilterChannels, uint16_t initial_selection=0xFFFF)
void playback_mode_toggled(ARDOUR::ChannelMode)
sigc::signal< void, ARDOUR::ChannelMode, uint16_t > mode_changed
Definition: amp.h:29
#define gui_context()
Definition: gui_thread.h:36
std::vector< Gtk::ToggleButton * > playback_buttons
bool was_clicked(GdkEventButton *)
Gtk::Label _button_labels[4][4]
void set_tip(Gtk::Widget &w, const gchar *tip)
Gtk::RadioButton capture_filter_button
Gtk::ToggleButton * _last_active_button
std::string name() const
ChannelMode get_capture_channel_mode() const
Definition: midi_track.h:118
Gtk::RadioButton playback_force_button
Pass through all channel information unmodified.
Definition: types.h:210
SingleMidiChannelSelector(uint8_t active_channel=0)
MidiChannelSelector(int n_rows=4, int n_columns=4, int start_row=0, int start_column=0)
void set_widget_name(const std::string &name)
ChannelMode get_playback_channel_mode() const
Definition: midi_track.h:117
#define UINT_INTERPOLATE(c1, c2, t)
Definition: rgb_macros.h:70
#define MISSING_INVALIDATOR
Definition: event_loop.h:86
void set_playback_selected_channels(uint16_t)
MidiChannelSelectorWindow(boost::shared_ptr< ARDOUR::MidiTrack >)
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
LIBGTKMM2EXT_API void container_clear(Gtk::Container &)
Definition: utils.cc:511
virtual void button_toggled(Gtk::ToggleButton *button, uint8_t button_nr)=0
Ignore events on certain channels.
Definition: types.h:211
void capture_mode_toggled(ARDOUR::ChannelMode)