* persisting/restoring track channel settings works now
[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, int8_t force_channel)
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 void 
133 MidiMultipleChannelSelector::set_force_channel(int8_t channel)
134 {
135         if(channel < 0) {
136                 // if forcing is already activated, deactivate
137                 if(_mode == FORCING_SINGLE_CHANNEL) {
138                         _force_channel.toggled();
139                 } 
140                 // if not, nothing to do
141         } else {
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();
146         }
147 }
148
149
150 const uint16_t 
151 MidiMultipleChannelSelector::get_selected_channels() const 
152
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);
158                 } 
159         }
160         
161         return selected_channels; 
162 }
163
164 void 
165 MidiMultipleChannelSelector::set_selected_channels(uint16_t selected_channels)
166 {
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);
171                 } else {
172                         button->set_active(false);
173                 }
174         }
175 }
176
177 void
178 MidiMultipleChannelSelector::button_toggled(ToggleButton *button, uint8_t channel)
179 {
180         ++_recursion_counter;
181         if(_recursion_counter == 1) {
182                 if(_mode == FORCING_SINGLE_CHANNEL) {
183                         set_selected_channels(1 << channel);
184                 }
185         
186                 force_channel_changed.emit(get_force_channel());
187                 selection_changed.emit(get_selected_channels());
188         }
189         --_recursion_counter;
190 }
191
192 void 
193 MidiMultipleChannelSelector::force_channels_button_toggled()
194 {
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;
206                                 } else {
207                                         found_first_active = true;
208                                 }
209                         } 
210                 }
211                 
212                 if(!found_first_active) {
213                         _buttons[0][0].set_active(true);
214                 }
215                 
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());
221         } else {
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());
228         }
229 }
230
231 void 
232 MidiMultipleChannelSelector::select_all(bool on)
233 {
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);
238         }
239         --_recursion_counter;
240         selection_changed.emit(get_selected_channels());
241 }
242
243 void 
244 MidiMultipleChannelSelector::invert_selection(void)
245 {
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);
251                 } else {
252                         button->set_active(true);
253                 }
254         }
255         --_recursion_counter;
256         selection_changed.emit(get_selected_channels());
257 }
258