remove using namespace sigc everywhere to ensure clarity over which bind/mem_fun...
[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 ARDOUR;
29
30 MidiChannelSelector::MidiChannelSelector(int n_rows, int n_columns, int start_row, int start_column)
31         : Table(n_rows, n_columns, true)
32         , _recursion_counter(0)
33 {
34         assert(n_rows >= 4);
35         assert(n_rows >= start_row + 4);
36         assert(n_columns >=4);
37         assert(n_columns >= start_column + 4);
38
39         property_column_spacing() = 0;
40         property_row_spacing() = 0;
41
42         uint8_t channel_nr = 0;
43         for (int row = 0; row < 4; ++row) {
44                 for (int column = 0; column < 4; ++column) {
45                         ostringstream channel;
46                         channel << int(++channel_nr);
47                         _button_labels[row][column].set_text(channel.str());
48                         _button_labels[row][column].set_justify(JUSTIFY_RIGHT);
49                         _buttons[row][column].add(_button_labels[row][column]);
50                         _buttons[row][column].signal_toggled().connect(
51                                 sigc::bind(
52                                         sigc::mem_fun(this, &MidiChannelSelector::button_toggled),
53                                         &_buttons[row][column],
54                                         channel_nr - 1));
55
56                         int table_row    = start_row + row;
57                         int table_column = start_column + column;
58                         attach(_buttons[row][column], table_column, table_column + 1, table_row, table_row + 1);
59                 }
60         }
61 }
62
63 MidiChannelSelector::~MidiChannelSelector()
64 {
65 }
66
67 void
68 MidiChannelSelector::set_channel_colors(const uint32_t new_channel_colors[16])
69 {
70         for (int row = 0; row < 4; ++row) {
71                 for (int column = 0; column < 4; ++column) {
72                         char color_normal[8];
73                         char color_active[8];
74                         snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[row * 4 + column], 0x000000ff, 0.6));
75                         snprintf(color_active, 8, "#%x", new_channel_colors[row * 4 + column]);
76                         _buttons[row][column].modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
77                         _buttons[row][column].modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
78                 }
79         }
80 }
81
82 void
83 MidiChannelSelector::set_default_channel_color()
84 {
85         for (int row = 0; row < 4; ++row) {
86                 for (int column = 0; column < 4; ++column) {
87                         _buttons[row][column].unset_bg(STATE_NORMAL);
88                         _buttons[row][column].unset_bg(STATE_ACTIVE);
89                 }
90         }
91 }
92
93 SingleMidiChannelSelector::SingleMidiChannelSelector(uint8_t active_channel)
94         : MidiChannelSelector()
95 {
96         _last_active_button = 0;
97         ToggleButton* button = &_buttons[active_channel / 4][active_channel % 4];
98         _active_channel = active_channel;
99         button->set_active(true);
100         _last_active_button = button;
101 }
102
103 void
104 SingleMidiChannelSelector::button_toggled(ToggleButton* button, uint8_t channel)
105 {
106         ++_recursion_counter;
107         if (_recursion_counter == 1) {
108                 // if the current button is active it must
109                 // be different from the first one
110                 if (button->get_active()) {
111                         if (_last_active_button) {
112                                 _last_active_button->set_active(false);
113                                 _active_channel = channel;
114                                 _last_active_button = button;
115                                 channel_selected.emit(channel);
116                         }
117                 } else {
118                         // if not, the user pressed the already active button
119                         button->set_active(true);
120                         _active_channel = channel;
121                 }
122         }
123         --_recursion_counter;
124 }
125
126 MidiMultipleChannelSelector::MidiMultipleChannelSelector(ChannelMode mode, uint16_t mask)
127         : MidiChannelSelector(4, 6, 0, 0)
128         , _channel_mode(mode)
129 {
130         _select_all.add(*manage(new Label(_("All"))));
131         _select_all.signal_clicked().connect(
132                         sigc::bind(sigc::mem_fun(this, &MidiMultipleChannelSelector::select_all), true));
133
134         _select_none.add(*manage(new Label(_("None"))));
135         _select_none.signal_clicked().connect(
136                         sigc::bind(sigc::mem_fun(this, &MidiMultipleChannelSelector::select_all), false));
137
138         _invert_selection.add(*manage(new Label(_("Invert"))));
139         _invert_selection.signal_clicked().connect(
140                         sigc::mem_fun(this, &MidiMultipleChannelSelector::invert_selection));
141
142         _force_channel.add(*manage(new Label(_("Force"))));
143         _force_channel.signal_toggled().connect(
144                         sigc::mem_fun(this, &MidiMultipleChannelSelector::force_channels_button_toggled));
145
146         set_homogeneous(false);
147         attach(*manage(new VSeparator()), 4, 5, 0, 4, SHRINK, FILL, 0, 0);
148         //set_row_spacing(4, -5);
149         attach(_select_all,       5, 6, 0, 1);
150         attach(_select_none,      5, 6, 1, 2);
151         attach(_invert_selection, 5, 6, 2, 3);
152         attach(_force_channel,    5, 6, 3, 4);
153
154         set_selected_channels(mask);
155 }
156
157 MidiMultipleChannelSelector::~MidiMultipleChannelSelector()
158 {
159         mode_changed.clear();
160 }
161
162 void
163 MidiMultipleChannelSelector::set_channel_mode(ChannelMode mode, uint16_t mask)
164 {
165         switch (mode) {
166         case AllChannels:
167                 _force_channel.set_active(false);
168                 set_selected_channels(0xFFFF);
169                 break;
170         case FilterChannels:
171                 _force_channel.set_active(false);
172                 set_selected_channels(mask);
173                 break;
174         case ForceChannel:
175                 _force_channel.set_active(true);
176                 for (uint16_t i = 0; i < 16; i++) {
177                         ToggleButton* button = &_buttons[i / 4][i % 4];
178                         button->set_active(i == mask);
179                 }
180         }
181 }
182
183 uint16_t
184 MidiMultipleChannelSelector::get_selected_channels() const
185 {
186         uint16_t selected_channels = 0;
187         for (uint16_t i = 0; i < 16; i++) {
188                 const ToggleButton* button = &_buttons[i / 4][i % 4];
189                 if (button->get_active()) {
190                         selected_channels |= (1L << i);
191                 }
192         }
193
194         return selected_channels;
195 }
196
197 void
198 MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels)
199 {
200         for (uint16_t i = 0; i < 16; i++) {
201                 ToggleButton* button = &_buttons[i / 4][i % 4];
202                 if (selected_channels & (1L << i)) {
203                         button->set_active(true);
204                 } else {
205                         button->set_active(false);
206                 }
207         }
208 }
209
210 void
211 MidiMultipleChannelSelector::button_toggled(ToggleButton */*button*/, uint8_t channel)
212 {
213         ++_recursion_counter;
214         if (_recursion_counter == 1) {
215                 if (_channel_mode == ForceChannel) {
216                         mode_changed.emit(_channel_mode, channel);
217                         set_selected_channels(1 << channel);
218                 } else {
219                         mode_changed.emit(_channel_mode, get_selected_channels());
220                 }
221         }
222         --_recursion_counter;
223 }
224
225 void
226 MidiMultipleChannelSelector::force_channels_button_toggled()
227 {
228         if (_force_channel.get_active()) {
229                 _channel_mode = ForceChannel;
230                 bool found_first_active = false;
231                 // leave only the first button enabled
232                 uint16_t active_channel = 0;
233                 for (int i = 0; i <= 15; i++) {
234                         ToggleButton* button = &_buttons[i / 4][i % 4];
235                         if (button->get_active()) {
236                                 if (found_first_active) {
237                                         ++_recursion_counter;
238                                         button->set_active(false);
239                                         --_recursion_counter;
240                                 } else {
241                                         found_first_active = true;
242                                         active_channel = i;
243                                 }
244                         }
245                 }
246
247                 if (!found_first_active) {
248                         _buttons[0][0].set_active(true);
249                 }
250
251                 _select_all.set_sensitive(false);
252                 _select_none.set_sensitive(false);
253                 _invert_selection.set_sensitive(false);
254                 mode_changed.emit(_channel_mode, active_channel);
255         } else {
256                 _channel_mode = FilterChannels;
257                 _select_all.set_sensitive(true);
258                 _select_none.set_sensitive(true);
259                 _invert_selection.set_sensitive(true);
260                 mode_changed.emit(FilterChannels, get_selected_channels());
261         }
262 }
263
264 void
265 MidiMultipleChannelSelector::select_all(bool on)
266 {
267         if (_channel_mode == ForceChannel)
268                 return;
269
270         ++_recursion_counter;
271         for (uint16_t i = 0; i < 16; i++) {
272                 ToggleButton* button = &_buttons[i / 4][i % 4];
273                 button->set_active(on);
274         }
275         --_recursion_counter;
276         mode_changed.emit(_channel_mode, get_selected_channels());
277 }
278
279 void
280 MidiMultipleChannelSelector::invert_selection(void)
281 {
282         if (_channel_mode == ForceChannel)
283                 return;
284
285         ++_recursion_counter;
286         for (uint16_t i = 0; i < 16; i++) {
287                 ToggleButton* button = &_buttons[i / 4][i % 4];
288                 if (button->get_active()) {
289                         button->set_active(false);
290                 } else {
291                         button->set_active(true);
292                 }
293         }
294         --_recursion_counter;
295         mode_changed.emit(_channel_mode, get_selected_channels());
296 }
297