1 #include "midi_channel_selector.h"
2 #include "gtkmm/separator.h"
10 MidiChannelSelector::MidiChannelSelector(int no_rows, int no_columns, int start_row, int start_column) :
11 Table(no_rows, no_columns, true), _recursion_counter(0)
14 assert(no_rows >= start_row + 4);
15 assert(no_columns >=4);
16 assert(no_columns >= start_column + 4);
18 property_column_spacing() = 0;
19 property_row_spacing() = 0;
21 uint8_t channel_nr = 0;
22 for(int row = 0; row < 4; ++row) {
23 for(int column = 0; column < 4; ++column) {
24 ostringstream channel;
25 channel << int(++channel_nr);
26 _button_labels[row][column].set_text(channel.str());
27 _button_labels[row][column].set_justify(JUSTIFY_RIGHT);
28 _buttons[row][column].add(_button_labels[row][column]);
29 _buttons[row][column].signal_toggled().connect(
31 mem_fun(this, &MidiChannelSelector::button_toggled),
32 &_buttons[row][column],
35 int table_row = start_row + row;
36 int table_column = start_column + column;
37 attach(_buttons[row][column], table_column, table_column + 1, table_row, table_row + 1);
42 MidiChannelSelector::~MidiChannelSelector()
46 SingleMidiChannelSelector::SingleMidiChannelSelector(uint8_t active_channel)
47 : MidiChannelSelector()
49 _last_active_button = 0;
50 ToggleButton *button = &_buttons[active_channel / 4][active_channel % 4];
51 _active_channel = active_channel;
52 button->set_active(true);
53 _last_active_button = button;
57 SingleMidiChannelSelector::button_toggled(ToggleButton *button, uint8_t channel)
60 if(_recursion_counter == 1) {
61 // if the current button is active it must
62 // be different from the first one
63 if(button->get_active()) {
64 if(_last_active_button) {
65 _last_active_button->set_active(false);
66 _active_channel = channel;
67 _last_active_button = button;
70 // if not, the user pressed the already active button
71 button->set_active(true);
72 _active_channel = channel;
78 MidiMultipleChannelSelector::MidiMultipleChannelSelector(uint16_t initial_selection, int8_t force_channel)
79 : MidiChannelSelector(4, 6, 0, 0), _mode(FILTERING_MULTIPLE_CHANNELS)
81 _select_all.add(*manage(new Label(_("All"))));
82 _select_all.signal_clicked().connect(
83 bind(mem_fun(this, &MidiMultipleChannelSelector::select_all), true));
85 _select_none.add(*manage(new Label(_("None"))));
86 _select_none.signal_clicked().connect(
87 bind(mem_fun(this, &MidiMultipleChannelSelector::select_all), false));
89 _invert_selection.add(*manage(new Label(_("Invert"))));
90 _invert_selection.signal_clicked().connect(
91 mem_fun(this, &MidiMultipleChannelSelector::invert_selection));
93 _force_channel.add(*manage(new Label(_("Force"))));
94 _force_channel.signal_toggled().connect(
95 mem_fun(this, &MidiMultipleChannelSelector::force_channels_button_toggled));
97 set_homogeneous(false);
98 attach(*manage(new VSeparator()), 4, 5, 0, 4, SHRINK, FILL, 0, 0);
99 //set_row_spacing(4, -5);
100 attach(_select_all, 5, 6, 0, 1);
101 attach(_select_none, 5, 6, 1, 2);
102 attach(_invert_selection, 5, 6, 2, 3);
103 attach(_force_channel, 5, 6, 3, 4);
105 set_selected_channels(initial_selection);
108 MidiMultipleChannelSelector::~MidiMultipleChannelSelector()
110 selection_changed.clear();
111 force_channel_changed.clear();
115 MidiMultipleChannelSelector::get_force_channel() const
117 if(_mode == FORCING_SINGLE_CHANNEL) {
118 for(int8_t i = 0; i < 16; i++) {
119 const ToggleButton *button = &_buttons[i / 4][i % 4];
120 if(button->get_active()) {
125 // this point should not be reached.
133 MidiMultipleChannelSelector::set_force_channel(int8_t channel)
136 // if forcing is already activated, deactivate
137 if(_mode == FORCING_SINGLE_CHANNEL) {
138 _force_channel.toggled();
140 // if not, nothing to do
142 // otherwise simulate activating force channels by pressing the
143 // two buttons the user would press
144 _force_channel.toggled();
145 _buttons[channel / 4][channel % 4].toggled();
151 MidiMultipleChannelSelector::get_selected_channels() const
153 uint16_t selected_channels = 0;
154 for(uint16_t i = 0; i < 16; i++) {
155 const ToggleButton *button = &_buttons[i / 4][i % 4];
156 if(button->get_active()) {
157 selected_channels |= (1L << i);
161 return selected_channels;
165 MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels)
167 for(uint16_t i = 0; i < 16; i++) {
168 ToggleButton *button = &_buttons[i / 4][i % 4];
169 if(selected_channels & (1L << i)) {
170 button->set_active(true);
172 button->set_active(false);
178 MidiMultipleChannelSelector::button_toggled(ToggleButton *button, uint8_t channel)
180 ++_recursion_counter;
181 if(_recursion_counter == 1) {
182 if(_mode == FORCING_SINGLE_CHANNEL) {
183 set_selected_channels(1 << channel);
186 force_channel_changed.emit(get_force_channel());
187 selection_changed.emit(get_selected_channels());
189 --_recursion_counter;
193 MidiMultipleChannelSelector::force_channels_button_toggled()
195 if(_force_channel.get_active()) {
196 _mode = FORCING_SINGLE_CHANNEL;
197 bool found_first_active = false;
198 // leave only the first button enabled
199 for(int i = 0; i <= 15; i++) {
200 ToggleButton *button = &_buttons[i / 4][i % 4];
201 if(button->get_active()) {
202 if(found_first_active) {
203 ++_recursion_counter;
204 button->set_active(false);
205 --_recursion_counter;
207 found_first_active = true;
212 if(!found_first_active) {
213 _buttons[0][0].set_active(true);
216 _select_all.set_sensitive(false);
217 _select_none.set_sensitive(false);
218 _invert_selection.set_sensitive(false);
219 force_channel_changed.emit(get_force_channel());
220 selection_changed.emit(get_selected_channels());
222 _mode = FILTERING_MULTIPLE_CHANNELS;
223 _select_all.set_sensitive(true);
224 _select_none.set_sensitive(true);
225 _invert_selection.set_sensitive(true);
226 force_channel_changed.emit(get_force_channel());
227 selection_changed.emit(get_selected_channels());
232 MidiMultipleChannelSelector::select_all(bool on)
234 ++_recursion_counter;
235 for(uint16_t i = 0; i < 16; i++) {
236 ToggleButton *button = &_buttons[i / 4][i % 4];
237 button->set_active(on);
239 --_recursion_counter;
240 selection_changed.emit(get_selected_channels());
244 MidiMultipleChannelSelector::invert_selection(void)
246 ++_recursion_counter;
247 for(uint16_t i = 0; i < 16; i++) {
248 ToggleButton *button = &_buttons[i / 4][i % 4];
249 if(button->get_active()) {
250 button->set_active(false);
252 button->set_active(true);
255 --_recursion_counter;
256 selection_changed.emit(get_selected_channels());