LCXL: fix some more typos
[ardour.git] / libs / surfaces / launch_control_xl / controllers.cc
1 /*
2   Copyright (C) 2016 Paul Davis
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 2 of the License, or
7   (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program; if not, write to the Free Software
16   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <algorithm>
20
21 #include "ardour/debug.h"
22 #include "ardour/mute_control.h"
23 #include "ardour/session.h"
24 #include "ardour/solo_control.h"
25 #include "ardour/solo_isolate_control.h"
26
27 #include "launch_control_xl.h"
28
29 using namespace ArdourSurface;
30 using namespace ARDOUR;
31 using namespace PBD;
32 using std::cerr;
33
34 void
35 LaunchControlXL::build_maps ()
36 {
37         /* Knobs */
38
39         Knob* knob;
40
41         #define MAKE_KNOB(i,cc, index) \
42                 knob = new Knob ((i), (cc), (index), (*this)); \
43                 cc_knob_map.insert (std::make_pair (knob->controller_number(), knob)); \
44                 id_knob_map.insert (std::make_pair (knob->id(), knob))
45
46                 for (uint8_t n = 0; n < 8; ++n) {
47                         MAKE_KNOB (static_cast<KnobID>(n), (n + 13), n);
48                         MAKE_KNOB (static_cast<KnobID>(n + 8), (n + 29), (n + 8));
49                         MAKE_KNOB (static_cast<KnobID>(n + 16), (n + 49), (n + 16));
50                 }
51
52         /* Faders */
53
54         Fader* fader;
55
56         #define MAKE_FADER(i,cc) \
57                 fader = new Fader ((i), (cc)); \
58                 cc_fader_map.insert (std::make_pair (fader->controller_number(), fader)); \
59                 id_fader_map.insert (std::make_pair (fader->id(), fader))
60
61                 for (uint8_t n = 0; n < 8; ++n) {
62                         MAKE_FADER (static_cast<FaderID>(n), (n + 77) );
63                 }
64
65         /* Buttons */
66
67         ControllerButton *controller_button;
68         NoteButton *note_button;
69
70
71         #define MAKE_TRACK_BUTTON_PRESS(i,nn,index,color,p) \
72                 note_button = new TrackButton ((i), (nn), (index), (color), (p), (*this)); \
73                 nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
74                 id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
75         #define MAKE_SELECT_BUTTON_PRESS(i,cc,index,p) \
76                 controller_button = new SelectButton ((i), (cc), (index), (p), (*this)); \
77                 cc_controller_button_map.insert (std::make_pair (controller_button->controller_number(), controller_button)); \
78                 id_controller_button_map.insert (std::make_pair (controller_button->id(), controller_button))
79         #define MAKE_SELECT_BUTTON_PRESS_RELEASE_LONG(i,cc,index,p,r,l) \
80                 controller_button = new SelectButton ((i), (cc), (index), (p), (r), (l), (*this)); \
81                 cc_controller_button_map.insert (std::make_pair (controller_button->controller_number(), controller_button)); \
82                 id_controller_button_map.insert (std::make_pair (controller_button->id(), controller_button))
83         #define MAKE_TRACK_STATE_BUTTON_PRESS(i,nn,index,p) \
84                 note_button = new TrackStateButton ((i), (nn), (index), (p), (*this)); \
85                 nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
86                 id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
87         #define MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(i,nn,index,p,r,l) \
88                 note_button = new TrackStateButton ((i), (nn), (index), (p), (r), (l), (*this)); \
89                 nn_note_button_map.insert (std::make_pair (note_button->note_number(), note_button)); \
90                 id_note_button_map.insert (std::make_pair (note_button->id(), note_button))
91
92
93         MAKE_TRACK_BUTTON_PRESS(Focus1, 41, 24, YellowLow, &LaunchControlXL::button_track_focus_1);
94         MAKE_TRACK_BUTTON_PRESS(Focus2, 42, 25, YellowLow, &LaunchControlXL::button_track_focus_2);
95         MAKE_TRACK_BUTTON_PRESS(Focus3, 43, 26, YellowLow, &LaunchControlXL::button_track_focus_3);
96         MAKE_TRACK_BUTTON_PRESS(Focus4, 44, 27, YellowLow, &LaunchControlXL::button_track_focus_4);
97         MAKE_TRACK_BUTTON_PRESS(Focus5, 57, 28, YellowLow, &LaunchControlXL::button_track_focus_5);
98         MAKE_TRACK_BUTTON_PRESS(Focus6, 58, 29, YellowLow, &LaunchControlXL::button_track_focus_6);
99         MAKE_TRACK_BUTTON_PRESS(Focus7, 59, 30, YellowLow, &LaunchControlXL::button_track_focus_7);
100         MAKE_TRACK_BUTTON_PRESS(Focus8, 60, 31, YellowLow, &LaunchControlXL::button_track_focus_8);
101         MAKE_TRACK_BUTTON_PRESS(Control1, 73, 32, AmberLow, &LaunchControlXL::button_track_control_1);
102         MAKE_TRACK_BUTTON_PRESS(Control2, 74, 33, AmberLow, &LaunchControlXL::button_track_control_2);
103         MAKE_TRACK_BUTTON_PRESS(Control3, 75, 34, AmberLow, &LaunchControlXL::button_track_control_3);
104         MAKE_TRACK_BUTTON_PRESS(Control4, 76, 35, AmberLow, &LaunchControlXL::button_track_control_4);
105         MAKE_TRACK_BUTTON_PRESS(Control5, 89, 36, AmberLow, &LaunchControlXL::button_track_control_5);
106         MAKE_TRACK_BUTTON_PRESS(Control6, 90, 37, AmberLow, &LaunchControlXL::button_track_control_6);
107         MAKE_TRACK_BUTTON_PRESS(Control7, 91, 38, AmberLow, &LaunchControlXL::button_track_control_7);
108         MAKE_TRACK_BUTTON_PRESS(Control8, 92, 39, AmberLow, &LaunchControlXL::button_track_control_8);
109
110         MAKE_SELECT_BUTTON_PRESS(SelectUp, 104, 44, &LaunchControlXL::button_select_up);
111         MAKE_SELECT_BUTTON_PRESS(SelectDown, 105, 45, &LaunchControlXL::button_select_down);
112         MAKE_SELECT_BUTTON_PRESS_RELEASE_LONG(SelectLeft, 106, 46, &LaunchControlXL::relax, &LaunchControlXL::button_select_left, &LaunchControlXL::button_select_left_long_press);
113         MAKE_SELECT_BUTTON_PRESS_RELEASE_LONG(SelectRight, 107, 47, &LaunchControlXL::relax, &LaunchControlXL::button_select_right, &LaunchControlXL::button_select_right_long_press);
114
115         MAKE_TRACK_STATE_BUTTON_PRESS_RELEASE_LONG(Device, 105, 40, &LaunchControlXL::relax, &LaunchControlXL::button_device, &LaunchControlXL::button_device_long_press);
116         MAKE_TRACK_STATE_BUTTON_PRESS(Mute, 106, 41, &LaunchControlXL::button_mute);
117         MAKE_TRACK_STATE_BUTTON_PRESS(Solo, 107, 42, &LaunchControlXL::button_solo);
118         MAKE_TRACK_STATE_BUTTON_PRESS(Record, 108, 43, &LaunchControlXL::button_record);
119
120 }
121
122 std::string
123 LaunchControlXL::button_name_by_id (ButtonID id)
124 {
125         switch (id) {
126                 case Device:
127                         return "Device";
128                 case Mute:
129                         return "Mute";
130                 case Solo:
131                         return "Solo";
132                 case Record:
133                         return "Record";
134                 case SelectUp:
135                         return "Select Up";
136                 case SelectDown:
137                         return "Select Down";
138                 case SelectRight:
139                         return "Select Right";
140                 case SelectLeft:
141                         return "Select Left";
142                 case Focus1:
143                         return "Focus 1";
144                 case Focus2:
145                         return "Focus 2";
146                 case Focus3:
147                         return "Focus 3";
148                 case Focus4:
149                         return "Focus 4";
150                 case Focus5:
151                         return "Focus 5";
152                 case Focus6:
153                         return "Focus 6";
154                 case Focus7:
155                         return "Focus 7";
156                 case Focus8:
157                         return "Focus 8";
158                 case Control1:
159                         return "Control 1";
160                 case Control2:
161                         return "Control 2";
162                 case Control3:
163                         return "Control 3";
164                 case Control4:
165                         return "Control 4";
166                 case Control5:
167                         return "Control 5";
168                 case Control6:
169                         return "Control 6";
170                 case Control7:
171                         return "Control 7";
172                 case Control8:
173                         return "Control 8";
174         default:
175                 break;
176         }
177
178         return "???";
179 }
180
181 std::string
182 LaunchControlXL::knob_name_by_id (KnobID id)
183 {
184         switch (id) {
185                 case SendA1:
186                         return "SendA 1";
187                 case SendA2:
188                         return "SendA 2";
189                 case SendA3:
190                         return "SendA 3";
191                 case SendA4:
192                         return "SendA 4";
193                 case SendA5:
194                         return "SendA 5";
195                 case SendA6:
196                         return "SendA 6";
197                 case SendA7:
198                         return "SendA 7";
199                 case SendA8:
200                         return "SendA 8";
201                 case SendB1:
202                         return "SendB 1";
203                 case SendB2:
204                         return "SendB 2";
205                 case SendB3:
206                         return "SendB 3";
207                 case SendB4:
208                         return "SendB 4";
209                 case SendB5:
210                         return "SendB 5";
211                 case SendB6:
212                         return "SendB 6";
213                 case SendB7:
214                         return "SendB 7";
215                 case SendB8:
216                         return "SendB 8";
217                 case Pan1:
218                         return "Pan 1";
219                 case Pan2:
220                         return "Pan 2";
221                 case Pan3:
222                         return "Pan 3";
223                 case Pan4:
224                         return "Pan 4";
225                 case Pan5:
226                         return "Pan 5";
227                 case Pan6:
228                         return "Pan 6";
229                 case Pan7:
230                         return "Pan 7";
231                 case Pan8:
232                         return "Pan 8";
233         default:
234                 break;
235         }
236
237         return "???";
238 }
239
240 std::string
241 LaunchControlXL::fader_name_by_id (FaderID id)
242 {
243         switch (id) {
244                 case Fader1:
245                         return "Fader 1";
246                 case Fader2:
247                         return "Fader 2";
248                 case Fader3:
249                         return "Fader 3";
250                 case Fader4:
251                         return "Fader 4";
252                 case Fader5:
253                         return "Fader 5";
254                 case Fader6:
255                         return "Fader 6";
256                 case Fader7:
257                         return "Fader 7";
258                 case Fader8:
259                         return "Fader 8";
260         default:
261                 break;
262         }
263
264         return "???";
265 }
266
267 LaunchControlXL::TrackButton*
268 LaunchControlXL::track_button_by_range(uint8_t n, uint8_t first, uint8_t middle)
269 {
270         NNNoteButtonMap::iterator b;
271         if ( n < 4)     {
272                 b = nn_note_button_map.find (first + n);
273         } else {
274                 b = nn_note_button_map.find (middle + n - 4);
275         }
276
277         TrackButton* button = 0;
278
279         if (b != nn_note_button_map.end()) {
280                 button = static_cast<TrackButton*>(b->second);
281         }
282
283         return button;
284
285 }
286
287 void
288 LaunchControlXL::update_track_focus_led(uint8_t n)
289 {
290         TrackButton* b = focus_button_by_column(n);
291
292         if (!b) {
293                 return;
294         }
295
296         if (stripable[n]) {
297                 if ( stripable[n]->is_selected() ) {
298                         b->set_color(YellowFull);
299                 } else {
300                         b->set_color(AmberLow);
301                 }
302         } else {
303                 b->set_color(Off);
304         }
305
306         write (b->state_msg());
307 }
308
309 void
310 LaunchControlXL::button_track_focus(uint8_t n)
311 {
312         if (buttons_down.find(Device) != buttons_down.end()) {
313                 DEBUG_TRACE (DEBUG::LaunchControlXL, "DEVICE BUTTON HOLD\n");
314                 stripable[n]->solo_isolate_control()->set_value (!stripable[n]->solo_isolate_control()->get_value(), PBD::Controllable::UseGroup);
315                 return;
316         }
317
318         if (stripable[n]) {
319                 if ( stripable[n]->is_selected() ) {
320                          ControlProtocol::RemoveStripableFromSelection (stripable[n]);
321                 } else {
322                         ControlProtocol::AddStripableToSelection (stripable[n]);
323                 }
324         } else {
325                 return;
326         }
327 }
328
329
330
331 boost::shared_ptr<AutomationControl>
332 LaunchControlXL::get_ac_by_state(uint8_t n) {
333                 boost::shared_ptr<AutomationControl> ac;
334
335                 switch(track_mode()) {
336                         case TrackMute:
337                                 ac = stripable[n]->mute_control();
338                                 break;
339
340                         case TrackSolo:
341                                 ac = stripable[n]->solo_control();
342                                 break;
343
344                         case TrackRecord:
345                                 ac = stripable[n]->rec_enable_control();
346                                 break;
347
348                         default:
349                         break;
350                 }
351                 return ac;
352 }
353
354 LaunchControlXL::Knob**
355 LaunchControlXL::knobs_by_column(uint8_t col, Knob** knob_col)
356 {
357         for (uint8_t n = 0; n < 3; ++n) {
358                 knob_col[n] = id_knob_map.find(static_cast<KnobID>(col+n*8))->second;
359         }
360
361         return knob_col;
362 }
363
364 void
365 LaunchControlXL::update_knob_led(uint8_t n)
366 {
367         LEDColor color;
368
369         uint32_t absolute_strip_num = (n + bank_start) % 8;
370
371         switch (absolute_strip_num) {
372                 case 0:
373                 case 4:
374                         if (stripable[n] && stripable[n]->is_selected()) {
375                                 color = RedFull;
376                         } else {
377                                 color = RedLow;
378                         }
379                         break;
380
381                 case 1:
382                 case 5:
383                         if (stripable[n] && stripable[n]->is_selected()) {
384                                 color = YellowFull;
385                         } else {
386                                 color = YellowLow;
387                         }
388                         break;
389
390                 case 2:
391                 case 6:
392                         if (stripable[n] && stripable[n]->is_selected()) {
393                                 color = GreenFull;
394                         } else {
395                                 color = GreenLow;
396                         }
397                         break;
398
399                 case 3:
400                 case 7:
401                         if (stripable[n] && stripable[n]->is_selected()) {
402                                 color = AmberFull;
403                         } else {
404                                 color = AmberLow;
405                         }
406         }
407
408         Knob* knobs_col[3];
409         knobs_by_column(n, knobs_col);
410
411         for  (uint8_t s = 0; s < 3; ++s)
412         {
413                 if (stripable[n]) {
414                         knobs_col[s]->set_color(color);
415                 } else {
416                         knobs_col[s]->set_color(Off);
417                 }
418                 write (knobs_col[s]->state_msg());
419         }
420 }
421
422 void
423 LaunchControlXL::update_track_control_led(uint8_t n)
424 {
425         TrackButton* b = control_button_by_column(n);
426
427         if (!b) {
428                 return;
429         }
430
431         if (stripable[n]) {
432                 boost::shared_ptr<AutomationControl> ac = get_ac_by_state(n);
433
434                 switch(track_mode()) {
435                         case TrackMute:
436                                 if (ac->get_value()) {
437                                         b->set_color(YellowFull);
438                                 } else {
439                                         b->set_color(AmberLow);
440                                 }
441                                 break;
442                         case TrackSolo:
443                                 if (ac && stripable[n] != master ) {
444                                         if (ac->get_value()) {
445                                                 b->set_color(GreenFull);
446                                         } else {
447                                                 b->set_color(GreenLow);
448                                         }
449                                 } else {
450                                         b->set_color(Off);
451                                 }
452                                 break;
453                         case TrackRecord:
454                                 if (ac) {
455                                         if (ac->get_value()) {
456                                                 b->set_color(RedFull);
457                                         } else {
458                                                 b->set_color(RedLow);
459                                         }
460                                 } else {
461                                         b->set_color(Off);
462                                 }
463                                 break;
464
465                         default:
466                         break;
467                 }
468         } else {
469                 b->set_color(Off);
470         }
471
472         write (b->state_msg());
473 }
474
475 void
476 LaunchControlXL::solo_mute_rec_changed(uint32_t n) {
477         if (!stripable[n]) {
478                 return;
479         }
480         update_track_control_led(n);
481 }
482
483 void
484 LaunchControlXL::button_track_control(uint8_t n) {
485         if (!stripable[n]) {
486                 return;
487         }
488         boost::shared_ptr<AutomationControl> ac = get_ac_by_state(n);
489
490         if (ac) {
491                 session->set_control (ac, !ac->get_value(), PBD::Controllable::UseGroup);
492         }
493 }
494
495 void
496 LaunchControlXL::button_track_mode(TrackMode state)
497 {
498                 set_track_mode(state);
499                 for (uint8_t n = 0; n < 8; ++n) {
500                         update_track_control_led(n);
501                 }
502
503                 TrackStateButton* mute = static_cast<TrackStateButton*>(id_note_button_map[Mute]);
504                 TrackStateButton* solo = static_cast<TrackStateButton*>(id_note_button_map[Solo]);
505                 TrackStateButton* record = static_cast<TrackStateButton*>(id_note_button_map[Record]);
506
507                 write(mute->state_msg((state == TrackMute)));
508                 write(solo->state_msg((state == TrackSolo)));
509                 write(record->state_msg((state == TrackRecord)));
510 }
511
512 void
513 LaunchControlXL::button_select_left()
514 {
515         switch_bank (max (0, bank_start - 1));
516 }
517
518 void
519 LaunchControlXL::button_select_right()
520 {
521         switch_bank (max (0, bank_start + 1));
522 }
523
524 void
525 LaunchControlXL::button_select_left_long_press()
526 {
527         switch_bank (0);
528 }
529
530 void
531 LaunchControlXL::button_select_right_long_press()
532 {
533         switch_bank (session->get_stripables().size() - 3);
534 }
535
536 void
537 LaunchControlXL::button_select_up()
538 {
539
540 }
541
542 void
543 LaunchControlXL::button_select_down()
544 {
545
546 }
547
548 void
549 LaunchControlXL::button_device()
550 {
551
552 }
553
554 void
555 LaunchControlXL::button_device_long_press()
556 {
557
558 }
559
560 void
561 LaunchControlXL::button_mute()
562 {
563         if (buttons_down.find(Device) != buttons_down.end()) {
564                 access_action ("Editor/track-mute-toggle");
565         } else {
566                 button_track_mode(TrackMute);
567         }
568 }
569
570 void
571 LaunchControlXL::button_solo()
572 {
573         if (buttons_down.find(Device) != buttons_down.end()) {
574                 access_action ("Editor/track-solo-toggle");
575         } else {
576                 button_track_mode(TrackSolo);
577         }
578 }
579
580 void
581 LaunchControlXL::button_record()
582 {
583         if (buttons_down.find(Device) != buttons_down.end()) {
584                 access_action ("Editor/track-record-enable-toggle");
585         } else {
586                 button_track_mode(TrackRecord);
587         }
588 }
589
590 bool
591 LaunchControlXL::button_long_press_timeout (ButtonID id, Button* button)
592 {
593         if (buttons_down.find (id) != buttons_down.end()) {
594                 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose ("long press timeout for %1, invoking method\n", id));
595                 (this->*button->long_press_method) ();
596         } else {
597                 DEBUG_TRACE (DEBUG::LaunchControlXL, string_compose ("long press timeout for %1, expired/cancelled\n", id));
598                 /* release happened and somehow we were not cancelled */
599         }
600
601         /* whichever button this was, we've used it ... don't invoke the
602            release action.
603         */
604         consumed.insert (id);
605
606         return false; /* don't get called again */
607 }
608
609
610 void
611 LaunchControlXL::start_press_timeout (Button* button, ButtonID id)
612 {
613         Glib::RefPtr<Glib::TimeoutSource> timeout = Glib::TimeoutSource::create (500); // milliseconds
614         button->timeout_connection = timeout->connect (sigc::bind (sigc::mem_fun (*this, &LaunchControlXL::button_long_press_timeout), id, button));
615         timeout->attach (main_loop()->get_context());
616 }