Add knob leds and refine colors
[ardour.git] / libs / surfaces / launch_control_xl / launch_control_xl.h
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 #ifndef __ardour_launch_control_h__
20 #define __ardour_launch_control_h__
21
22 #include <vector>
23 #include <map>
24 #include <stack>
25 #include <list>
26 #include <set>
27
28 #define ABSTRACT_UI_EXPORTS
29 #include "pbd/abstract_ui.h"
30
31 #include "midi++/types.h"
32
33 #include "ardour/mode.h"
34 #include "ardour/types.h"
35
36 #include "control_protocol/control_protocol.h"
37 #include "control_protocol/types.h"
38
39 #include "midi_byte_array.h"
40
41 namespace MIDI {
42 class Parser;
43 class Port;
44 } // namespace MIDI
45
46 namespace ARDOUR {
47 class AsyncMIDIPort;
48 class Port;
49 class MidiBuffer;
50 class MidiTrack;
51 } // namespace ARDOUR
52
53 namespace ArdourSurface {
54
55
56 struct LaunchControlRequest : public BaseUI::BaseRequestObject {
57         public:
58                 LaunchControlRequest() {}
59                 ~LaunchControlRequest() {}
60 };
61
62 class LCXLGUI;
63 class LaunchControlMenu;
64
65 class LaunchControlXL : public ARDOUR::ControlProtocol,
66                         public AbstractUI<LaunchControlRequest> {
67 public:
68         enum TrackMode {
69                 TrackMute,
70                 TrackSolo,
71                 TrackRecord
72         };
73
74         enum ButtonID {
75                 Focus1 = 0,
76                 Focus2,
77                 Focus3,
78                 Focus4,
79                 Focus5,
80                 Focus6,
81                 Focus7,
82                 Focus8,
83                 Control1,
84                 Control2,
85                 Control3,
86                 Control4,
87                 Control5,
88                 Control6,
89                 Control7,
90                 Control8,
91                 Device,
92                 Mute,
93                 Solo,
94                 Record,
95                 SelectUp,
96                 SelectDown,
97                 SelectLeft,
98                 SelectRight
99         };
100
101         enum FaderID {
102                 Fader1 = 0,
103                 Fader2,
104                 Fader3,
105                 Fader4,
106                 Fader5,
107                 Fader6,
108                 Fader7,
109                 Fader8
110         };
111
112         enum KnobID {
113                 SendA1 = 0,
114                 SendA2,
115                 SendA3,
116                 SendA4,
117                 SendA5,
118                 SendA6,
119                 SendA7,
120                 SendA8,
121                 SendB1,
122                 SendB2,
123                 SendB3,
124                 SendB4,
125                 SendB5,
126                 SendB6,
127                 SendB7,
128                 SendB8,
129                 Pan1,
130                 Pan2,
131                 Pan3,
132                 Pan4,
133                 Pan5,
134                 Pan6,
135                 Pan7,
136                 Pan8
137         };
138
139         enum LEDFlag { Normal = 0xC, Blink = 0x8, DoubleBuffering = 0x0 };
140
141         enum LEDColor { Off=0, RedLow = 1, RedFull = 3, GreenLow = 16, GreenFull = 48, YellowLow = 34, YellowFull = 51, AmberLow = 18, AmberFull = 35};
142
143
144         struct Controller {
145                 Controller(uint8_t cn,  uint8_t val = 0) : _controller_number(cn), _value(val)  {}
146
147                 uint8_t  controller_number() const { return _controller_number; }
148                 uint8_t value() const { return _value; }
149                 void set_value(uint8_t val) { _value = val; }
150
151                 protected:
152                 uint8_t _controller_number;
153                 uint8_t _value;
154         };
155
156         struct LED {
157                 LED(uint8_t i, LEDColor c, LaunchControlXL& l) : _index(i), _color(c), _flag(Normal), lcxl(&l)  {}
158                 LED(uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& lcxl) : _index(i), _color(c), _flag(f) {}
159                 virtual ~LED() {}
160
161                 LEDColor color() const { return _color; }
162                 LEDFlag flag() const { return _flag; }
163                 uint8_t index() const { return _index; }
164                 void set_flag(LEDFlag f) { _flag = f; }
165
166                 virtual MidiByteArray state_msg(bool light) const = 0;
167
168                 protected:
169                 uint8_t _index;
170                 LEDColor _color;
171                 LEDFlag _flag;
172                 MidiByteArray _state_msg;
173                 LaunchControlXL* lcxl;
174         };
175
176         struct MultiColorLED : public LED {
177                 MultiColorLED (uint8_t i, LEDColor c, LaunchControlXL& l) : LED(i, c, l) {}
178                 MultiColorLED (uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& l)
179                         : LED(i, c, f, l) {}
180
181                 void set_color(LEDColor c) { _color = c; }
182         };
183
184         struct Button {
185                 Button(ButtonID id)
186                         : press_method(&LaunchControlXL::relax)
187                         , release_method(&LaunchControlXL::relax)
188                         , long_press_method(&LaunchControlXL::relax), _id(id) {}
189
190                 Button(ButtonID id, void (LaunchControlXL::*press)())
191                         : press_method(press)
192                         , release_method(&LaunchControlXL::relax)
193                         , long_press_method(&LaunchControlXL::relax), _id(id) {}
194
195                 Button(ButtonID id, void (LaunchControlXL::*press)(), void (LaunchControlXL::*release)())
196                         : press_method(press), release_method(release)
197                         , long_press_method(&LaunchControlXL::relax), _id(id) {}
198
199                 Button(ButtonID id, void (LaunchControlXL::*press)(), void (LaunchControlXL::*release)(), void (LaunchControlXL::*long_press)())
200                         : press_method(press), release_method(release)
201                         , long_press_method(long_press), _id(id) {}
202
203                 virtual ~Button() {}
204
205                 ButtonID id() const { return _id; }
206
207                 void (LaunchControlXL::*press_method)();
208                 void (LaunchControlXL::*release_method)();
209                 void (LaunchControlXL::*long_press_method)();
210
211                 sigc::connection timeout_connection;
212
213                 protected:
214                 ButtonID _id;
215         };
216
217         struct ControllerButton : public Button {
218
219                 ControllerButton(ButtonID id, uint8_t cn,
220                                 void (LaunchControlXL::*press)())
221                         : Button(id, press), _controller_number(cn) {}
222
223                 ControllerButton(ButtonID id, uint8_t cn,
224                                 void (LaunchControlXL::*press)(),
225                                 void (LaunchControlXL::*release)())
226                         : Button(id, press, release), _controller_number(cn) {}
227
228
229                 uint8_t controller_number() const { return _controller_number; }
230
231                 private:
232                 uint8_t _controller_number;
233         };
234
235         struct NoteButton : public Button {
236
237                 NoteButton(ButtonID id, uint8_t cn, void (LaunchControlXL::*press)())
238                         : Button(id, press), _note_number(cn) {}
239
240                 NoteButton(ButtonID id, uint8_t cn,
241                                 void (LaunchControlXL::*press)(),
242                                 void (LaunchControlXL::*release)())
243                         : Button(id, press, release), _note_number(cn) {}
244                 NoteButton(ButtonID id, uint8_t cn,
245                                 void (LaunchControlXL::*press)(),
246                                 void (LaunchControlXL::*release)(),
247                                 void (LaunchControlXL::*release_long)())
248                         : Button(id, press, release, release_long), _note_number(cn) {}
249
250                 uint8_t note_number() const { return _note_number; }
251
252                 private:
253                 uint8_t _note_number;
254         };
255
256         struct TrackButton : public NoteButton, public MultiColorLED {
257                 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor color,
258                                 void (LaunchControlXL::*press)(), LaunchControlXL& l)
259                         : NoteButton(id, nn, press), MultiColorLED(index, color, l) {}
260
261                 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor color,
262                                 void (LaunchControlXL::*press)(),
263                                 void (LaunchControlXL::*release)(),
264                                 LaunchControlXL& l)
265                         : NoteButton(id, nn, press, release), MultiColorLED(index, color, l) {}
266
267                 MidiByteArray state_msg(bool light = true) const;
268         };
269
270         struct SelectButton : public ControllerButton, public LED {
271                 SelectButton(ButtonID id, uint8_t cn, uint8_t index, void (LaunchControlXL::*press)(), LaunchControlXL& l)
272                         : ControllerButton(id, cn, press), LED(index, RedFull, l) {}
273
274                 MidiByteArray state_msg(bool light) const;
275         };
276
277         struct TrackStateButton : public NoteButton, public LED {
278                 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(), LaunchControlXL& l)
279                         : NoteButton(id, nn, press)
280                         , LED(index, YellowLow, l) {}
281
282                 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(),
283                                 void (LaunchControlXL::*release)(),
284                                 LaunchControlXL& l)
285                         : NoteButton(id, nn, press, release)
286                         , LED(index, YellowLow, l) {}
287
288                 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(),
289                                 void (LaunchControlXL::*release)(),
290                                 void (LaunchControlXL::*release_long)(),
291                                 LaunchControlXL& l)
292                         : NoteButton(id, nn, press, release, release_long)
293                         , LED(index, YellowLow, l) {}
294
295                 MidiByteArray state_msg(bool light) const;
296         };
297
298         struct Fader : public Controller {
299                 Fader(FaderID id, uint8_t cn)
300                         : Controller(cn, 0), _id(id) {} // minimal value
301
302                 FaderID id() const { return _id; }
303
304                 void controller_changed(Controller* controller);
305
306                 private:
307                 FaderID _id;
308         };
309
310         struct Knob : public Controller, public MultiColorLED {
311                 Knob(KnobID id, uint8_t cn, uint8_t index, LaunchControlXL& l)
312                         : Controller(cn, 64)
313                         , MultiColorLED(index, Off, l)
314                         , _id(id) {} // knob 50/50 value
315
316                 KnobID id() const { return _id; }
317
318                 MidiByteArray state_msg(bool light = true) const;
319
320                 private:
321                 KnobID _id;
322         };
323
324 public:
325         LaunchControlXL(ARDOUR::Session &);
326         ~LaunchControlXL();
327
328
329         static bool probe();
330         static void *request_factory(uint32_t);
331
332         std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles();
333
334         bool has_editor() const { return true; }
335         void *get_gui() const;
336         void tear_down_gui();
337
338         int set_active(bool yn);
339         XMLNode &get_state();
340         int set_state(const XMLNode &node, int version);
341
342         PBD::Signal0<void> ConnectionChange;
343
344         boost::shared_ptr<ARDOUR::Port> input_port();
345         boost::shared_ptr<ARDOUR::Port> output_port();
346
347         Button *button_by_id(ButtonID);
348
349         static std::string button_name_by_id(ButtonID);
350         static std::string knob_name_by_id(KnobID);
351         static std::string fader_name_by_id(FaderID);
352
353         void write(const MidiByteArray &);
354         void reset(uint8_t chan);
355
356         TrackMode track_mode() const { return _track_mode; }
357         void set_track_mode(TrackMode mode);
358
359         uint8_t template_number() const { return _template_number; }
360
361 private:
362         bool in_use;
363         TrackMode _track_mode;
364         uint8_t _template_number;
365
366         void do_request(LaunchControlRequest *);
367
368         int begin_using_device();
369         int stop_using_device();
370         int ports_acquire();
371         void ports_release();
372         void run_event_loop();
373         void stop_event_loop();
374
375         void relax() {}
376
377         /* map of NoteButtons by NoteNumber */
378         typedef std::map<int, NoteButton *> NNNoteButtonMap;
379         NNNoteButtonMap nn_note_button_map;
380         /* map of NoteButtons by ButtonID */
381         typedef std::map<ButtonID, NoteButton *> IDNoteButtonMap;
382         IDNoteButtonMap id_note_button_map;
383         /* map of ControllerNoteButtons by CC */
384         typedef std::map<int, ControllerButton *> CCControllerButtonMap;
385         CCControllerButtonMap cc_controller_button_map;
386         /* map of ControllerButtons by ButtonID */
387         typedef std::map<ButtonID, ControllerButton *> IDControllerButtonMap;
388         IDControllerButtonMap id_controller_button_map;
389
390
391         /* map of Fader by CC */
392         typedef std::map<int, Fader *> CCFaderMap;
393         CCFaderMap cc_fader_map;
394         /* map of Fader by FaderID */
395         typedef std::map<FaderID, Fader *> IDFaderMap;
396         IDFaderMap id_fader_map;
397
398         /* map of Knob by CC */
399         typedef std::map<int, Knob *> CCKnobMap;
400         CCKnobMap cc_knob_map;
401         /* map of Knob by KnobID */
402         typedef std::map<KnobID, Knob *> IDKnobMap;
403         IDKnobMap id_knob_map;
404
405         std::set<ButtonID> buttons_down;
406         std::set<ButtonID> consumed;
407
408         bool button_long_press_timeout(ButtonID id, Button *button);
409         void start_press_timeout(Button *, ButtonID);
410
411         void init_buttons(bool startup);
412
413         void switch_template(uint8_t t);
414
415         void build_maps();
416
417         // Bundle to represent our input ports
418         boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
419         // Bundle to represent our output ports
420         boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
421
422         MIDI::Port *_input_port;
423         MIDI::Port *_output_port;
424         boost::shared_ptr<ARDOUR::Port> _async_in;
425         boost::shared_ptr<ARDOUR::Port> _async_out;
426
427         void connect_to_parser();
428         void handle_button_message(Button* button, MIDI::EventTwoBytes *);
429         void handle_fader_message(Fader* fader);
430         void handle_knob_message(Knob* knob);
431
432         bool check_pick_up(Controller* controller, boost::shared_ptr<ARDOUR::AutomationControl> ac);
433
434         void handle_midi_controller_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
435         void handle_midi_note_on_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
436         void handle_midi_note_off_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
437         void handle_midi_sysex(MIDI::Parser &, MIDI::byte *, size_t count);
438
439         bool midi_input_handler(Glib::IOCondition ioc, MIDI::Port *port);
440
441         void thread_init();
442
443         PBD::ScopedConnectionList session_connections;
444         void connect_session_signals();
445         void notify_transport_state_changed();
446         void notify_loop_state_changed();
447         void notify_parameter_changed(std::string);
448
449         /* Knob methods */
450
451         Knob** knobs_by_collumn(uint8_t col, Knob** knob_col);
452         void update_knob_led(uint8_t n);
453
454         /* Button methods */
455
456         TrackButton* track_button_by_range(uint8_t n, uint8_t first, uint8_t middle);
457         TrackButton* focus_button_by_column(uint8_t col) { return track_button_by_range(col, 41, 57) ; }
458         TrackButton* control_button_by_column(uint8_t col) { return track_button_by_range(col, 73, 89) ; }
459
460
461         void button_device();
462         void button_device_long_press();
463         void button_track_mode(TrackMode state);
464         void button_mute();
465         void button_solo();
466         void button_record();
467         void button_select_up();
468         void button_select_down();
469         void button_select_left();
470         void button_select_right();
471
472         void button_track_focus(uint8_t n);
473         void button_track_control(uint8_t n);
474
475         boost::shared_ptr<ARDOUR::AutomationControl> get_ac_by_state(uint8_t n);
476         void update_track_focus_led(uint8_t n);
477         void update_track_control_led(uint8_t n);
478
479         void button_track_focus_1() { button_track_focus(0); }
480         void button_track_focus_2() { button_track_focus(1); }
481         void button_track_focus_3() { button_track_focus(2); }
482         void button_track_focus_4() { button_track_focus(3); }
483         void button_track_focus_5() { button_track_focus(4); }
484         void button_track_focus_6() { button_track_focus(5); }
485         void button_track_focus_7() { button_track_focus(6); }
486         void button_track_focus_8() { button_track_focus(7); }
487
488         void button_track_control_1() { button_track_control(0); }
489         void button_track_control_2() { button_track_control(1); }
490         void button_track_control_3() { button_track_control(2); }
491         void button_track_control_4() { button_track_control(3); }
492         void button_track_control_5() { button_track_control(4); }
493         void button_track_control_6() { button_track_control(5); }
494         void button_track_control_7() { button_track_control(6); }
495         void button_track_control_8() { button_track_control(7); }
496
497         /* stripables */
498
499         int32_t bank_start;
500         PBD::ScopedConnectionList stripable_connections;
501         boost::shared_ptr<ARDOUR::Stripable> stripable[8];
502
503         void stripables_added ();
504
505         void stripable_property_change (PBD::PropertyChange const& what_changed, uint32_t which);
506
507         void switch_bank (uint32_t base);
508
509         void solo_changed (uint32_t n) { solo_mute_rec_changed(n); }
510         void mute_changed (uint32_t n) { solo_mute_rec_changed(n); }
511         void rec_changed (uint32_t n) { solo_mute_rec_changed(n); }
512         void solo_mute_rec_changed (uint32_t n);
513
514         /* special Stripable */
515
516         boost::shared_ptr<ARDOUR::Stripable> master;
517
518         PBD::ScopedConnection port_reg_connection;
519         void port_registration_handler();
520
521         enum ConnectionState { InputConnected = 0x1, OutputConnected = 0x2 };
522
523         int connection_state;
524         bool connection_handler(boost::weak_ptr<ARDOUR::Port>, std::string name1,
525                         boost::weak_ptr<ARDOUR::Port>, std::string name2,
526                         bool yn);
527         PBD::ScopedConnection port_connection;
528         void connected();
529
530         /* GUI */
531
532         mutable LCXLGUI *gui;
533         void build_gui();
534
535         void stripable_selection_changed();
536
537         bool in_range_select;
538                                                                                                 };
539
540
541 } // namespace ArdourSurface
542
543 #endif /* __ardour_launch_control_h__ */