e69dcca392471756d639b7019d87de83bb214a72
[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                 ControllerButton(ButtonID id, uint8_t cn,
229                                 void (LaunchControlXL::*press)(),
230                                 void (LaunchControlXL::*release)(),
231                                 void (LaunchControlXL::*release_long)())
232                         : Button(id, press, release, release_long), _controller_number(cn) {}
233
234
235                 uint8_t controller_number() const { return _controller_number; }
236
237                 private:
238                 uint8_t _controller_number;
239         };
240
241         struct NoteButton : public Button {
242
243                 NoteButton(ButtonID id, uint8_t cn, void (LaunchControlXL::*press)())
244                         : Button(id, press), _note_number(cn) {}
245
246                 NoteButton(ButtonID id, uint8_t cn,
247                                 void (LaunchControlXL::*press)(),
248                                 void (LaunchControlXL::*release)())
249                         : Button(id, press, release), _note_number(cn) {}
250                 NoteButton(ButtonID id, uint8_t cn,
251                                 void (LaunchControlXL::*press)(),
252                                 void (LaunchControlXL::*release)(),
253                                 void (LaunchControlXL::*release_long)())
254                         : Button(id, press, release, release_long), _note_number(cn) {}
255
256                 uint8_t note_number() const { return _note_number; }
257
258                 private:
259                 uint8_t _note_number;
260         };
261
262         struct TrackButton : public NoteButton, public MultiColorLED {
263                 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor color,
264                                 void (LaunchControlXL::*press)(), LaunchControlXL& l)
265                         : NoteButton(id, nn, press), MultiColorLED(index, color, l) {}
266
267                 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor color,
268                                 void (LaunchControlXL::*press)(),
269                                 void (LaunchControlXL::*release)(),
270                                 LaunchControlXL& l)
271                         : NoteButton(id, nn, press, release), MultiColorLED(index, color, l) {}
272
273                 MidiByteArray state_msg(bool light = true) const;
274         };
275
276         struct SelectButton : public ControllerButton, public LED {
277                 SelectButton(ButtonID id, uint8_t cn, uint8_t index, void (LaunchControlXL::*press)(), LaunchControlXL& l)
278                         : ControllerButton(id, cn, press), LED(index, RedFull, l) {}
279
280                 SelectButton(ButtonID id, uint8_t cn, uint8_t index,
281                         void (LaunchControlXL::*press)(),
282                         void (LaunchControlXL::*release)(),
283                         void (LaunchControlXL::*release_long)(),
284                         LaunchControlXL& l)
285                         : ControllerButton(id, cn, press, release, release_long), LED(index, RedFull, l) {}
286
287                 MidiByteArray state_msg(bool light) const;
288         };
289
290         struct TrackStateButton : public NoteButton, public LED {
291                 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(), LaunchControlXL& l)
292                         : NoteButton(id, nn, press)
293                         , LED(index, YellowLow, l) {}
294
295                 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(),
296                                 void (LaunchControlXL::*release)(),
297                                 LaunchControlXL& l)
298                         : NoteButton(id, nn, press, release)
299                         , LED(index, YellowLow, l) {}
300
301                 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(),
302                                 void (LaunchControlXL::*release)(),
303                                 void (LaunchControlXL::*release_long)(),
304                                 LaunchControlXL& l)
305                         : NoteButton(id, nn, press, release, release_long)
306                         , LED(index, YellowLow, l) {}
307
308                 MidiByteArray state_msg(bool light) const;
309         };
310
311         struct Fader : public Controller {
312                 Fader(FaderID id, uint8_t cn)
313                         : Controller(cn, 0), _id(id) {} // minimal value
314
315                 FaderID id() const { return _id; }
316
317                 void controller_changed(Controller* controller);
318
319                 private:
320                 FaderID _id;
321         };
322
323         struct Knob : public Controller, public MultiColorLED {
324                 Knob(KnobID id, uint8_t cn, uint8_t index, LaunchControlXL& l)
325                         : Controller(cn, 64)
326                         , MultiColorLED(index, Off, l)
327                         , _id(id) {} // knob 50/50 value
328
329                 KnobID id() const { return _id; }
330
331                 MidiByteArray state_msg(bool light = true) const;
332
333                 private:
334                 KnobID _id;
335         };
336
337 public:
338         LaunchControlXL(ARDOUR::Session &);
339         ~LaunchControlXL();
340
341
342         static bool probe();
343         static void *request_factory(uint32_t);
344
345         std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles();
346
347         bool has_editor() const { return true; }
348         void *get_gui() const;
349         void tear_down_gui();
350
351         bool use_fader8master = false;
352
353         int set_active(bool yn);
354         XMLNode &get_state();
355         int set_state(const XMLNode &node, int version);
356
357         PBD::Signal0<void> ConnectionChange;
358
359         boost::shared_ptr<ARDOUR::Port> input_port();
360         boost::shared_ptr<ARDOUR::Port> output_port();
361
362         Button *button_by_id(ButtonID);
363
364         static std::string button_name_by_id(ButtonID);
365         static std::string knob_name_by_id(KnobID);
366         static std::string fader_name_by_id(FaderID);
367
368         void write(const MidiByteArray &);
369         void reset(uint8_t chan);
370         void set_fader8master (bool yn);
371
372         TrackMode track_mode() const { return _track_mode; }
373         void set_track_mode(TrackMode mode);
374
375         uint8_t template_number() const { return _template_number; }
376
377 private:
378         bool in_use;
379         TrackMode _track_mode;
380         uint8_t _template_number;
381
382         void do_request(LaunchControlRequest *);
383
384         int begin_using_device();
385         int stop_using_device();
386         int ports_acquire();
387         void ports_release();
388         void run_event_loop();
389         void stop_event_loop();
390
391         void relax() {}
392
393         /* map of NoteButtons by NoteNumber */
394         typedef std::map<int, NoteButton *> NNNoteButtonMap;
395         NNNoteButtonMap nn_note_button_map;
396         /* map of NoteButtons by ButtonID */
397         typedef std::map<ButtonID, NoteButton *> IDNoteButtonMap;
398         IDNoteButtonMap id_note_button_map;
399         /* map of ControllerNoteButtons by CC */
400         typedef std::map<int, ControllerButton *> CCControllerButtonMap;
401         CCControllerButtonMap cc_controller_button_map;
402         /* map of ControllerButtons by ButtonID */
403         typedef std::map<ButtonID, ControllerButton *> IDControllerButtonMap;
404         IDControllerButtonMap id_controller_button_map;
405
406
407         /* map of Fader by CC */
408         typedef std::map<int, Fader *> CCFaderMap;
409         CCFaderMap cc_fader_map;
410         /* map of Fader by FaderID */
411         typedef std::map<FaderID, Fader *> IDFaderMap;
412         IDFaderMap id_fader_map;
413
414         /* map of Knob by CC */
415         typedef std::map<int, Knob *> CCKnobMap;
416         CCKnobMap cc_knob_map;
417         /* map of Knob by KnobID */
418         typedef std::map<KnobID, Knob *> IDKnobMap;
419         IDKnobMap id_knob_map;
420
421         std::set<ButtonID> buttons_down;
422         std::set<ButtonID> consumed;
423
424         bool button_long_press_timeout(ButtonID id, Button *button);
425         void start_press_timeout(Button *, ButtonID);
426
427         void init_buttons(bool startup);
428
429         void switch_template(uint8_t t);
430
431         void build_maps();
432
433         // Bundle to represent our input ports
434         boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
435         // Bundle to represent our output ports
436         boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
437
438         MIDI::Port *_input_port;
439         MIDI::Port *_output_port;
440         boost::shared_ptr<ARDOUR::Port> _async_in;
441         boost::shared_ptr<ARDOUR::Port> _async_out;
442
443         void connect_to_parser();
444         void handle_button_message(Button* button, MIDI::EventTwoBytes *);
445         void handle_fader_message(Fader* fader);
446         void handle_knob_message(Knob* knob);
447
448         bool check_pick_up(Controller* controller, boost::shared_ptr<ARDOUR::AutomationControl> ac);
449
450         void handle_midi_controller_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
451         void handle_midi_note_on_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
452         void handle_midi_note_off_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
453         void handle_midi_sysex(MIDI::Parser &, MIDI::byte *, size_t count);
454
455         bool midi_input_handler(Glib::IOCondition ioc, MIDI::Port *port);
456
457         void thread_init();
458
459         PBD::ScopedConnectionList session_connections;
460         void connect_session_signals();
461         void notify_transport_state_changed();
462         void notify_loop_state_changed();
463         void notify_parameter_changed(std::string);
464
465         /* Knob methods */
466
467         Knob** knobs_by_column(uint8_t col, Knob** knob_col);
468         void update_knob_led(uint8_t n);
469
470         /* Button methods */
471
472         TrackButton* track_button_by_range(uint8_t n, uint8_t first, uint8_t middle);
473         TrackButton* focus_button_by_column(uint8_t col) { return track_button_by_range(col, 41, 57) ; }
474         TrackButton* control_button_by_column(uint8_t col) { return track_button_by_range(col, 73, 89) ; }
475
476
477         void button_device();
478         void button_device_long_press();
479         void button_track_mode(TrackMode state);
480         void button_mute();
481         void button_solo();
482         void button_record();
483         void button_select_up();
484         void button_select_down();
485         void button_select_left();
486         void button_select_right();
487         void button_select_left_long_press();
488         void button_select_right_long_press();
489
490         void button_track_focus(uint8_t n);
491         void button_track_control(uint8_t n);
492
493         boost::shared_ptr<ARDOUR::AutomationControl> get_ac_by_state(uint8_t n);
494         void update_track_focus_led(uint8_t n);
495         void update_track_control_led(uint8_t n);
496
497         void button_track_focus_1() { button_track_focus(0); }
498         void button_track_focus_2() { button_track_focus(1); }
499         void button_track_focus_3() { button_track_focus(2); }
500         void button_track_focus_4() { button_track_focus(3); }
501         void button_track_focus_5() { button_track_focus(4); }
502         void button_track_focus_6() { button_track_focus(5); }
503         void button_track_focus_7() { button_track_focus(6); }
504         void button_track_focus_8() { button_track_focus(7); }
505
506         void button_track_control_1() { button_track_control(0); }
507         void button_track_control_2() { button_track_control(1); }
508         void button_track_control_3() { button_track_control(2); }
509         void button_track_control_4() { button_track_control(3); }
510         void button_track_control_5() { button_track_control(4); }
511         void button_track_control_6() { button_track_control(5); }
512         void button_track_control_7() { button_track_control(6); }
513         void button_track_control_8() { button_track_control(7); }
514
515         /* stripables */
516
517         int32_t bank_start;
518         PBD::ScopedConnectionList stripable_connections;
519         boost::shared_ptr<ARDOUR::Stripable> stripable[8];
520
521         void stripables_added ();
522
523         void stripable_property_change (PBD::PropertyChange const& what_changed, uint32_t which);
524
525         void switch_bank (uint32_t base);
526
527         void solo_changed (uint32_t n) { solo_mute_rec_changed(n); }
528         void mute_changed (uint32_t n) { solo_mute_rec_changed(n); }
529         void rec_changed (uint32_t n) { solo_mute_rec_changed(n); }
530         void solo_mute_rec_changed (uint32_t n);
531
532         /* special Stripable */
533
534         boost::shared_ptr<ARDOUR::Stripable> master;
535
536         PBD::ScopedConnection port_reg_connection;
537         void port_registration_handler();
538
539         enum ConnectionState { InputConnected = 0x1, OutputConnected = 0x2 };
540
541         int connection_state;
542         bool connection_handler(boost::weak_ptr<ARDOUR::Port>, std::string name1,
543                         boost::weak_ptr<ARDOUR::Port>, std::string name2,
544                         bool yn);
545         PBD::ScopedConnection port_connection;
546         void connected();
547
548         /* GUI */
549
550         mutable LCXLGUI *gui;
551         void build_gui();
552
553         void stripable_selection_changed();
554
555         bool in_range_select;
556                                                                                                 };
557
558
559 } // namespace ArdourSurface
560
561 #endif /* __ardour_launch_control_h__ */