Fix a couple of minor typos.
[ardour2.git] / gtk2_ardour / midi_channel_selector.cc
blobcdaf42e51f7c327125a787c6b51fee4eeedb7eeb
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 ARDOUR;
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)
34 assert(n_rows >= 4);
35 assert(n_rows >= start_row + 4);
36 assert(n_columns >=4);
37 assert(n_columns >= start_column + 4);
39 property_column_spacing() = 0;
40 property_row_spacing() = 0;
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 _buttons[row][column].set_widget_name (X_("MidiChannelSelectorButton"));
57 _buttons[row][column].signal_button_release_event().connect(
58 sigc::mem_fun(this, &MidiChannelSelector::was_clicked), false);
60 int table_row = start_row + row;
61 int table_column = start_column + column;
62 attach(_buttons[row][column], table_column, table_column + 1, table_row, table_row + 1);
67 MidiChannelSelector::~MidiChannelSelector()
71 bool
72 MidiChannelSelector::was_clicked (GdkEventButton*)
74 clicked ();
75 return false;
78 void
79 MidiChannelSelector::set_channel_colors(const uint32_t new_channel_colors[16])
81 for (int row = 0; row < 4; ++row) {
82 for (int column = 0; column < 4; ++column) {
83 char color_normal[8];
84 char color_active[8];
85 snprintf(color_normal, 8, "#%x", UINT_INTERPOLATE(new_channel_colors[row * 4 + column], 0x000000ff, 0.6));
86 snprintf(color_active, 8, "#%x", new_channel_colors[row * 4 + column]);
87 _buttons[row][column].modify_bg(STATE_NORMAL, Gdk::Color(color_normal));
88 _buttons[row][column].modify_bg(STATE_ACTIVE, Gdk::Color(color_active));
93 void
94 MidiChannelSelector::set_default_channel_color()
96 for (int row = 0; row < 4; ++row) {
97 for (int column = 0; column < 4; ++column) {
98 _buttons[row][column].unset_fg (STATE_NORMAL);
99 _buttons[row][column].unset_fg (STATE_ACTIVE);
100 _buttons[row][column].unset_bg (STATE_NORMAL);
101 _buttons[row][column].unset_bg (STATE_ACTIVE);
106 SingleMidiChannelSelector::SingleMidiChannelSelector(uint8_t active_channel)
107 : MidiChannelSelector()
109 _last_active_button = 0;
110 ToggleButton* button = &_buttons[active_channel / 4][active_channel % 4];
111 _active_channel = active_channel;
112 button->set_active(true);
113 _last_active_button = button;
116 void
117 SingleMidiChannelSelector::button_toggled(ToggleButton* button, uint8_t channel)
119 ++_recursion_counter;
120 if (_recursion_counter == 1) {
121 // if the current button is active it must
122 // be different from the first one
123 if (button->get_active()) {
124 if (_last_active_button) {
125 _last_active_button->set_active(false);
126 _active_channel = channel;
127 _last_active_button = button;
128 channel_selected.emit(channel);
130 } else {
131 // if not, the user pressed the already active button
132 button->set_active(true);
133 _active_channel = channel;
136 --_recursion_counter;
139 MidiMultipleChannelSelector::MidiMultipleChannelSelector(ChannelMode mode, uint16_t mask)
140 : MidiChannelSelector(4, 6, 0, 0)
141 , _channel_mode(mode)
143 _select_all.add(*manage(new Label(_("All"))));
144 _select_all.signal_clicked().connect(
145 sigc::bind(sigc::mem_fun(this, &MidiMultipleChannelSelector::select_all), true));
147 _select_none.add(*manage(new Label(_("None"))));
148 _select_none.signal_clicked().connect(
149 sigc::bind(sigc::mem_fun(this, &MidiMultipleChannelSelector::select_all), false));
151 _invert_selection.add(*manage(new Label(_("Invert"))));
152 _invert_selection.signal_clicked().connect(
153 sigc::mem_fun(this, &MidiMultipleChannelSelector::invert_selection));
155 _force_channel.add(*manage(new Label(_("Force"))));
156 _force_channel.signal_toggled().connect(
157 sigc::mem_fun(this, &MidiMultipleChannelSelector::force_channels_button_toggled));
159 set_homogeneous(false);
160 attach(*manage(new VSeparator()), 4, 5, 0, 4, SHRINK, FILL, 0, 0);
161 //set_row_spacing(4, -5);
162 attach(_select_all, 5, 6, 0, 1);
163 attach(_select_none, 5, 6, 1, 2);
164 attach(_invert_selection, 5, 6, 2, 3);
165 attach(_force_channel, 5, 6, 3, 4);
167 set_selected_channels(mask);
170 MidiMultipleChannelSelector::~MidiMultipleChannelSelector()
172 mode_changed.clear();
175 void
176 MidiMultipleChannelSelector::set_channel_mode(ChannelMode mode, uint16_t mask)
178 switch (mode) {
179 case AllChannels:
180 _force_channel.set_active(false);
181 set_selected_channels(0xFFFF);
182 break;
183 case FilterChannels:
184 _force_channel.set_active(false);
185 set_selected_channels(mask);
186 break;
187 case ForceChannel:
188 _force_channel.set_active(true);
189 for (uint16_t i = 0; i < 16; i++) {
190 ToggleButton* button = &_buttons[i / 4][i % 4];
191 button->set_active(i == mask);
196 uint16_t
197 MidiMultipleChannelSelector::get_selected_channels() const
199 uint16_t selected_channels = 0;
200 for (uint16_t i = 0; i < 16; i++) {
201 const ToggleButton* button = &_buttons[i / 4][i % 4];
202 if (button->get_active()) {
203 selected_channels |= (1L << i);
207 return selected_channels;
210 void
211 MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels)
213 for (uint16_t i = 0; i < 16; i++) {
214 ToggleButton* button = &_buttons[i / 4][i % 4];
215 if (selected_channels & (1L << i)) {
216 button->set_active(true);
217 } else {
218 button->set_active(false);
223 void
224 MidiMultipleChannelSelector::button_toggled(ToggleButton */*button*/, uint8_t channel)
226 ++_recursion_counter;
227 if (_recursion_counter == 1) {
228 if (_channel_mode == ForceChannel) {
229 mode_changed.emit(_channel_mode, channel);
230 set_selected_channels(1 << channel);
231 } else {
232 mode_changed.emit(_channel_mode, get_selected_channels());
235 --_recursion_counter;
238 void
239 MidiMultipleChannelSelector::force_channels_button_toggled()
241 if (_force_channel.get_active()) {
242 _channel_mode = ForceChannel;
243 bool found_first_active = false;
244 // leave only the first button enabled
245 uint16_t active_channel = 0;
246 for (int i = 0; i <= 15; i++) {
247 ToggleButton* button = &_buttons[i / 4][i % 4];
248 if (button->get_active()) {
249 if (found_first_active) {
250 ++_recursion_counter;
251 button->set_active(false);
252 --_recursion_counter;
253 } else {
254 found_first_active = true;
255 active_channel = i;
260 if (!found_first_active) {
261 _buttons[0][0].set_active(true);
264 _select_all.set_sensitive(false);
265 _select_none.set_sensitive(false);
266 _invert_selection.set_sensitive(false);
267 mode_changed.emit(_channel_mode, active_channel);
268 } else {
269 _channel_mode = FilterChannels;
270 _select_all.set_sensitive(true);
271 _select_none.set_sensitive(true);
272 _invert_selection.set_sensitive(true);
273 mode_changed.emit(FilterChannels, get_selected_channels());
277 void
278 MidiMultipleChannelSelector::select_all(bool on)
280 if (_channel_mode == ForceChannel)
281 return;
283 ++_recursion_counter;
284 for (uint16_t i = 0; i < 16; i++) {
285 ToggleButton* button = &_buttons[i / 4][i % 4];
286 button->set_active(on);
288 --_recursion_counter;
289 mode_changed.emit(_channel_mode, get_selected_channels());
292 void
293 MidiMultipleChannelSelector::invert_selection(void)
295 if (_channel_mode == ForceChannel)
296 return;
298 ++_recursion_counter;
299 for (uint16_t i = 0; i < 16; i++) {
300 ToggleButton* button = &_buttons[i / 4][i % 4];
301 if (button->get_active()) {
302 button->set_active(false);
303 } else {
304 button->set_active(true);
307 --_recursion_counter;
308 mode_changed.emit(_channel_mode, get_selected_channels());