b810268633234e07a12f60f2b3edabff59163065
[ardour.git] / gtk2_ardour / midi_channel_selector.cc
1 #include "midi_channel_selector.h"
2 #include "gtkmm/separator.h"
3 #include "i18n.h"
4 #include <sstream>
5
6 using namespace std;
7 using namespace Gtk;
8 using namespace sigc;
9
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)
12 {       
13         assert(no_rows >= 4);
14         assert(no_rows >= start_row + 4);
15         assert(no_columns >=4);
16         assert(no_columns >= start_column + 4);
17         
18         property_column_spacing() = 0;
19         property_row_spacing() = 0;
20         
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(
30                                 bind(
31                                         mem_fun(this, &MidiChannelSelector::button_toggled),
32                                         &_buttons[row][column],
33                                         channel_nr - 1));
34
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);
38                 }
39         }
40 }
41
42 MidiChannelSelector::~MidiChannelSelector()
43 {
44 }
45
46 SingleMidiChannelSelector::SingleMidiChannelSelector(uint8_t active_channel)
47         : MidiChannelSelector()
48 {
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;
54 }
55
56 void
57 SingleMidiChannelSelector::button_toggled(ToggleButton *button, uint8_t channel)
58 {       
59         ++_recursion_counter;
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;
68                         }
69                 } else {
70                         // if not, the user pressed the already active button
71                         button->set_active(true);
72                         _active_channel = channel;
73                 }
74         }
75         --_recursion_counter;
76 }
77
78 MidiMultipleChannelSelector::MidiMultipleChannelSelector(uint16_t initial_selection)
79         : MidiChannelSelector(4, 6, 0, 0), _mode(FILTERING_MULTIPLE_CHANNELS)
80 {
81         _select_all.add(*manage(new Label(_("All"))));
82         _select_all.signal_clicked().connect(
83                         bind(mem_fun(this, &MidiMultipleChannelSelector::select_all), true));
84         
85         _select_none.add(*manage(new Label(_("None"))));
86         _select_none.signal_clicked().connect(
87                         bind(mem_fun(this, &MidiMultipleChannelSelector::select_all), false));
88         
89         _invert_selection.add(*manage(new Label(_("Invert"))));
90         _invert_selection.signal_clicked().connect(
91                         mem_fun(this, &MidiMultipleChannelSelector::invert_selection));
92         
93         _force_channel.add(*manage(new Label(_("Force"))));
94         _force_channel.signal_toggled().connect(
95                         mem_fun(this, &MidiMultipleChannelSelector::force_channels_button_toggled));
96
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);
104         
105         set_selected_channels(initial_selection);
106 }
107
108 MidiMultipleChannelSelector::~MidiMultipleChannelSelector()
109 {
110         selection_changed.clear();
111         force_channel_changed.clear();
112 }
113
114 const int8_t 
115 MidiMultipleChannelSelector::get_force_channel() const
116 {
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()) {
121                                 return i;
122                         } 
123                 }
124                 
125                 // this point should not be reached.
126                 assert(false);
127         } 
128         
129         return -1;
130 }
131
132 const uint16_t 
133 MidiMultipleChannelSelector::get_selected_channels() const 
134
135         uint16_t selected_channels = 0;
136         for(uint16_t i = 0; i < 16; i++) {
137                 const ToggleButton *button = &_buttons[i / 4][i % 4];
138                 if(button->get_active()) {
139                         selected_channels |= (1L << i);
140                 } 
141         }
142         
143         return selected_channels; 
144 }
145
146 void 
147 MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels)
148 {
149         for(uint16_t i = 0; i < 16; i++) {
150                 ToggleButton *button = &_buttons[i / 4][i % 4];
151                 if(selected_channels & (1L << i)) {
152                         button->set_active(true);
153                 } else {
154                         button->set_active(false);
155                 }
156         }
157 }
158
159 void
160 MidiMultipleChannelSelector::button_toggled(ToggleButton *button, uint8_t channel)
161 {
162         ++_recursion_counter;
163         if(_recursion_counter == 1) {
164                 if(_mode == FORCING_SINGLE_CHANNEL) {
165                         set_selected_channels(1 << channel);
166                 }
167         
168                 force_channel_changed.emit(get_force_channel());
169                 selection_changed.emit(get_selected_channels());
170         }
171         --_recursion_counter;
172 }
173
174 void 
175 MidiMultipleChannelSelector::force_channels_button_toggled()
176 {
177         if(_force_channel.get_active()) {
178                 _mode = FORCING_SINGLE_CHANNEL;
179                 bool found_first_active = false;
180                 // leave only the first button enabled
181                 for(int i = 0; i <= 15; i++) {
182                         ToggleButton *button = &_buttons[i / 4][i % 4];
183                         if(button->get_active()) {
184                                 if(found_first_active) {
185                                         ++_recursion_counter;
186                                         button->set_active(false);
187                                         --_recursion_counter;
188                                 } else {
189                                         found_first_active = true;
190                                 }
191                         } 
192                 }
193                 
194                 if(!found_first_active) {
195                         _buttons[0][0].set_active(true);
196                 }
197                 
198                 _select_all.set_sensitive(false);
199                 _select_none.set_sensitive(false);
200                 _invert_selection.set_sensitive(false);
201                 force_channel_changed.emit(get_force_channel());
202                 selection_changed.emit(get_selected_channels());
203         } else {
204                 _mode = FILTERING_MULTIPLE_CHANNELS;
205                 _select_all.set_sensitive(true);
206                 _select_none.set_sensitive(true);
207                 _invert_selection.set_sensitive(true);
208                 force_channel_changed.emit(get_force_channel());
209                 selection_changed.emit(get_selected_channels());
210         }
211 }
212
213 void 
214 MidiMultipleChannelSelector::select_all(bool on)
215 {
216         ++_recursion_counter;
217         for(uint16_t i = 0; i < 16; i++) {
218                 ToggleButton *button = &_buttons[i / 4][i % 4];
219                 button->set_active(on);
220         }
221         --_recursion_counter;
222         selection_changed.emit(get_selected_channels());
223 }
224
225 void 
226 MidiMultipleChannelSelector::invert_selection(void)
227 {
228         ++_recursion_counter;
229         for(uint16_t i = 0; i < 16; i++) {
230                 ToggleButton *button = &_buttons[i / 4][i % 4];
231                 if(button->get_active()) {
232                         button->set_active(false);
233                 } else {
234                         button->set_active(true);
235                 }
236         }
237         --_recursion_counter;
238         selection_changed.emit(get_selected_channels());
239 }
240