Remove idiocy.
[ardour2.git] / gtk2_ardour / midi_channel_selector.cc
blob03f0630eb97c51ed6d12f272deb3c73f7615d656
1 /*
2 Copyright (C) 2008 Paul Davis
3 Author: Hans Baier
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.
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.
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.
20 #include <sstream>
21 #include "midi_channel_selector.h"
22 #include "gtkmm/separator.h"
23 #include "i18n.h"
24 #include "rgb_macros.h"
26 using namespace std;
27 using namespace Gtk;
28 using namespace sigc;
29 using namespace ARDOUR;
31 MidiChannelSelector::MidiChannelSelector(int n_rows, int n_columns, int start_row, int start_column)
32 : Table(n_rows, n_columns, true)
33 , _recursion_counter(0)
35 assert(n_rows >= 4);
36 assert(n_rows >= start_row + 4);
37 assert(n_columns >=4);
38 assert(n_columns >= start_column + 4);
40 property_column_spacing() = 0;
41 property_row_spacing() = 0;
43 uint8_t channel_nr = 0;
44 for (int row = 0; row < 4; ++row) {
45 for (int column = 0; column < 4; ++column) {
46 ostringstream channel;
47 channel << int(++channel_nr);
48 _button_labels[row][column].set_text(channel.str());
49 _button_labels[row][column].set_justify(JUSTIFY_RIGHT);
50 _buttons[row][column].add(_button_labels[row][column]);
51 _buttons[row][column].signal_toggled().connect(
52 bind(
53 mem_fun(this, &MidiChannelSelector::button_toggled),
54 &_buttons[row][column],
55 channel_nr - 1));
57 int table_row = start_row + row;
58 int table_column = start_column + column;
59 attach(_buttons[row][column], table_column, table_column + 1, table_row, table_row + 1);
64 MidiChannelSelector::~MidiChannelSelector()
68 void
69 MidiChannelSelector::set_channel_colors(const uint32_t new_channel_colors[16])
71 for (int row = 0; row < 4; ++row) {
72 for (int column = 0; column < 4; ++column) {
73 char color_normal[8];
74 char color_active[8];
75 snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[row * 4 + column], 0x000000ff, 0.6));
76 snprintf(color_active, 8, "#%x", new_channel_colors[row * 4 + column]);
77 _buttons[row][column].modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
78 _buttons[row][column].modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
83 void
84 MidiChannelSelector::set_default_channel_color()
86 for (int row = 0; row < 4; ++row) {
87 for (int column = 0; column < 4; ++column) {
88 _buttons[row][column].unset_bg(STATE_NORMAL);
89 _buttons[row][column].unset_bg(STATE_ACTIVE);
94 SingleMidiChannelSelector::SingleMidiChannelSelector(uint8_t active_channel)
95 : MidiChannelSelector()
97 _last_active_button = 0;
98 ToggleButton* button = &_buttons[active_channel / 4][active_channel % 4];
99 _active_channel = active_channel;
100 button->set_active(true);
101 _last_active_button = button;
104 void
105 SingleMidiChannelSelector::button_toggled(ToggleButton* button, uint8_t channel)
107 ++_recursion_counter;
108 if (_recursion_counter == 1) {
109 // if the current button is active it must
110 // be different from the first one
111 if (button->get_active()) {
112 if (_last_active_button) {
113 _last_active_button->set_active(false);
114 _active_channel = channel;
115 _last_active_button = button;
116 channel_selected.emit(channel);
118 } else {
119 // if not, the user pressed the already active button
120 button->set_active(true);
121 _active_channel = channel;
124 --_recursion_counter;
127 MidiMultipleChannelSelector::MidiMultipleChannelSelector(ChannelMode mode, uint16_t mask)
128 : MidiChannelSelector(4, 6, 0, 0)
129 , _channel_mode(mode)
131 _select_all.add(*manage(new Label(_("All"))));
132 _select_all.signal_clicked().connect(
133 bind(mem_fun(this, &MidiMultipleChannelSelector::select_all), true));
135 _select_none.add(*manage(new Label(_("None"))));
136 _select_none.signal_clicked().connect(
137 bind(mem_fun(this, &MidiMultipleChannelSelector::select_all), false));
139 _invert_selection.add(*manage(new Label(_("Invert"))));
140 _invert_selection.signal_clicked().connect(
141 mem_fun(this, &MidiMultipleChannelSelector::invert_selection));
143 _force_channel.add(*manage(new Label(_("Force"))));
144 _force_channel.signal_toggled().connect(
145 mem_fun(this, &MidiMultipleChannelSelector::force_channels_button_toggled));
147 set_homogeneous(false);
148 attach(*manage(new VSeparator()), 4, 5, 0, 4, SHRINK, FILL, 0, 0);
149 //set_row_spacing(4, -5);
150 attach(_select_all, 5, 6, 0, 1);
151 attach(_select_none, 5, 6, 1, 2);
152 attach(_invert_selection, 5, 6, 2, 3);
153 attach(_force_channel, 5, 6, 3, 4);
155 set_selected_channels(mask);
158 MidiMultipleChannelSelector::~MidiMultipleChannelSelector()
160 mode_changed.clear();
163 void
164 MidiMultipleChannelSelector::set_channel_mode(ChannelMode mode, uint16_t mask)
166 switch (mode) {
167 case AllChannels:
168 _force_channel.set_active(false);
169 set_selected_channels(0xFFFF);
170 break;
171 case FilterChannels:
172 _force_channel.set_active(false);
173 set_selected_channels(mask);
174 break;
175 case ForceChannel:
176 _force_channel.set_active(true);
177 for (uint16_t i = 0; i < 16; i++) {
178 ToggleButton* button = &_buttons[i / 4][i % 4];
179 button->set_active(i == mask);
184 uint16_t
185 MidiMultipleChannelSelector::get_selected_channels() const
187 uint16_t selected_channels = 0;
188 for (uint16_t i = 0; i < 16; i++) {
189 const ToggleButton* button = &_buttons[i / 4][i % 4];
190 if (button->get_active()) {
191 selected_channels |= (1L << i);
195 return selected_channels;
198 void
199 MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels)
201 for (uint16_t i = 0; i < 16; i++) {
202 ToggleButton* button = &_buttons[i / 4][i % 4];
203 if (selected_channels & (1L << i)) {
204 button->set_active(true);
205 } else {
206 button->set_active(false);
211 void
212 MidiMultipleChannelSelector::button_toggled(ToggleButton */*button*/, uint8_t channel)
214 ++_recursion_counter;
215 if (_recursion_counter == 1) {
216 if (_channel_mode == ForceChannel) {
217 mode_changed.emit(_channel_mode, channel);
218 set_selected_channels(1 << channel);
219 } else {
220 mode_changed.emit(_channel_mode, get_selected_channels());
223 --_recursion_counter;
226 void
227 MidiMultipleChannelSelector::force_channels_button_toggled()
229 if (_force_channel.get_active()) {
230 _channel_mode = ForceChannel;
231 bool found_first_active = false;
232 // leave only the first button enabled
233 uint16_t active_channel = 0;
234 for (int i = 0; i <= 15; i++) {
235 ToggleButton* button = &_buttons[i / 4][i % 4];
236 if (button->get_active()) {
237 if (found_first_active) {
238 ++_recursion_counter;
239 button->set_active(false);
240 --_recursion_counter;
241 } else {
242 found_first_active = true;
243 active_channel = i;
248 if (!found_first_active) {
249 _buttons[0][0].set_active(true);
252 _select_all.set_sensitive(false);
253 _select_none.set_sensitive(false);
254 _invert_selection.set_sensitive(false);
255 mode_changed.emit(_channel_mode, active_channel);
256 } else {
257 _channel_mode = FilterChannels;
258 _select_all.set_sensitive(true);
259 _select_none.set_sensitive(true);
260 _invert_selection.set_sensitive(true);
261 mode_changed.emit(FilterChannels, get_selected_channels());
265 void
266 MidiMultipleChannelSelector::select_all(bool on)
268 if (_channel_mode == ForceChannel)
269 return;
271 ++_recursion_counter;
272 for (uint16_t i = 0; i < 16; i++) {
273 ToggleButton* button = &_buttons[i / 4][i % 4];
274 button->set_active(on);
276 --_recursion_counter;
277 mode_changed.emit(_channel_mode, get_selected_channels());
280 void
281 MidiMultipleChannelSelector::invert_selection(void)
283 if (_channel_mode == ForceChannel)
284 return;
286 ++_recursion_counter;
287 for (uint16_t i = 0; i < 16; i++) {
288 ToggleButton* button = &_buttons[i / 4][i % 4];
289 if (button->get_active()) {
290 button->set_active(false);
291 } else {
292 button->set_active(true);
295 --_recursion_counter;
296 mode_changed.emit(_channel_mode, get_selected_channels());