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