Fix some unused parameter warnings.
[ardour.git] / gtk2_ardour / midi_channel_selector.cc
1 /*
2     Copyright (C) 2008 Paul Davis 
3     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 <sstream>
21 #include "midi_channel_selector.h"
22 #include "gtkmm/separator.h"
23 #include "i18n.h"
24 #include "rgb_macros.h"
25
26 using namespace std;
27 using namespace Gtk;
28 using namespace sigc;
29 using namespace ARDOUR;
30
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)
34 {       
35         assert(n_rows >= 4);
36         assert(n_rows >= start_row + 4);
37         assert(n_columns >=4);
38         assert(n_columns >= start_column + 4);
39         
40         property_column_spacing() = 0;
41         property_row_spacing() = 0;
42         
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));
56
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);
60                 }
61         }
62 }
63
64 MidiChannelSelector::~MidiChannelSelector()
65 {
66 }
67
68 void
69 MidiChannelSelector::set_channel_colors(const uint32_t new_channel_colors[16])
70 {
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));
79                 }
80         }
81 }
82
83 void
84 MidiChannelSelector::set_default_channel_color()
85 {
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);
90                 }
91         }
92 }
93
94 SingleMidiChannelSelector::SingleMidiChannelSelector(uint8_t active_channel)
95         : MidiChannelSelector()
96 {
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;
102 }
103
104 void
105 SingleMidiChannelSelector::button_toggled(ToggleButton* button, uint8_t channel)
106 {       
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);
117                         }
118                 } else {
119                         // if not, the user pressed the already active button
120                         button->set_active(true);
121                         _active_channel = channel;
122                 }
123         }
124         --_recursion_counter;
125 }
126
127 MidiMultipleChannelSelector::MidiMultipleChannelSelector(ChannelMode mode, uint16_t mask)
128         : MidiChannelSelector(4, 6, 0, 0)
129         , _channel_mode(mode)
130 {
131         _select_all.add(*manage(new Label(_("All"))));
132         _select_all.signal_clicked().connect(
133                         bind(mem_fun(this, &MidiMultipleChannelSelector::select_all), true));
134         
135         _select_none.add(*manage(new Label(_("None"))));
136         _select_none.signal_clicked().connect(
137                         bind(mem_fun(this, &MidiMultipleChannelSelector::select_all), false));
138         
139         _invert_selection.add(*manage(new Label(_("Invert"))));
140         _invert_selection.signal_clicked().connect(
141                         mem_fun(this, &MidiMultipleChannelSelector::invert_selection));
142         
143         _force_channel.add(*manage(new Label(_("Force"))));
144         _force_channel.signal_toggled().connect(
145                         mem_fun(this, &MidiMultipleChannelSelector::force_channels_button_toggled));
146
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);
154         
155         set_selected_channels(mask);
156 }
157
158 MidiMultipleChannelSelector::~MidiMultipleChannelSelector()
159 {
160         mode_changed.clear();
161 }
162
163 void
164 MidiMultipleChannelSelector::set_channel_mode(ChannelMode mode, uint16_t mask)
165 {
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);
180                 }
181         }
182 }
183
184 uint16_t 
185 MidiMultipleChannelSelector::get_selected_channels() const 
186
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);
192                 } 
193         }
194         
195         return selected_channels; 
196 }
197
198 void 
199 MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels)
200 {
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);
207                 }
208         }
209 }
210
211 void
212 MidiMultipleChannelSelector::button_toggled(ToggleButton */*button*/, uint8_t channel)
213 {
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());
221                 }
222         }
223         --_recursion_counter;
224 }
225
226 void 
227 MidiMultipleChannelSelector::force_channels_button_toggled()
228 {
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;
244                                 }
245                         } 
246                 }
247                 
248                 if (!found_first_active) {
249                         _buttons[0][0].set_active(true);
250                 }
251                 
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());
262         }
263 }
264
265 void 
266 MidiMultipleChannelSelector::select_all(bool on)
267 {
268         if (_channel_mode == ForceChannel)
269                 return;
270
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);
275         }
276         --_recursion_counter;
277         mode_changed.emit(_channel_mode, get_selected_channels());
278 }
279
280 void 
281 MidiMultipleChannelSelector::invert_selection(void)
282 {
283         if (_channel_mode == ForceChannel)
284                 return;
285
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);
293                 }
294         }
295         --_recursion_counter;
296         mode_changed.emit(_channel_mode, get_selected_channels());
297 }
298