NO-OP: whitespace
[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, Yellow = 50, AmberLow = 17, AmberFull = 51};
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(LEDFlag::Normal), lcxl(&l)  {}
158                 LED(uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& lcxl) : _index(i), _color(c), _flag(f) {}
159
160                 LEDColor color() const { return _color; }
161                 LEDFlag flag() const { return _flag; }
162                 uint8_t index() const { return _index; }
163                 void set_flag(LEDFlag f) { _flag = f; }
164
165                 virtual MidiByteArray state_msg(bool light) const = 0;
166
167                 protected:
168                 uint8_t _index;
169                 LEDColor _color;
170                 LEDFlag _flag;
171                 MidiByteArray _state_msg;
172                 LaunchControlXL* lcxl;
173         };
174
175         struct MultiColorLED : public LED {
176                 MultiColorLED (uint8_t i, LEDColor c, LaunchControlXL& l) : LED(i, c, l) {}
177                 MultiColorLED (uint8_t i, LEDColor c, LEDFlag f, LaunchControlXL& l)
178                         : LED(i, c, f, l) {}
179
180                 void set_color(LEDColor c) { _color = c; }
181         };
182
183         struct Button {
184                 Button(ButtonID id)
185                         : press_method(&LaunchControlXL::relax)
186                         , release_method(&LaunchControlXL::relax)
187                         , long_press_method(&LaunchControlXL::relax), _id(id) {}
188
189                 Button(ButtonID id, void (LaunchControlXL::*press)())
190                         : press_method(press)
191                         , release_method(&LaunchControlXL::relax)
192                         , long_press_method(&LaunchControlXL::relax), _id(id) {}
193
194                 Button(ButtonID id, void (LaunchControlXL::*press)(), void (LaunchControlXL::*release)())
195                         : press_method(press), release_method(release)
196                         , long_press_method(&LaunchControlXL::relax), _id(id) {}
197
198                 Button(ButtonID id, void (LaunchControlXL::*press)(), void (LaunchControlXL::*release)(), void (LaunchControlXL::*long_press)())
199                         : press_method(press), release_method(release)
200                         , long_press_method(long_press), _id(id) {}
201
202                 virtual ~Button() {}
203
204                 ButtonID id() const { return _id; }
205
206                 void (LaunchControlXL::*press_method)();
207                 void (LaunchControlXL::*release_method)();
208                 void (LaunchControlXL::*long_press_method)();
209
210                 sigc::connection timeout_connection;
211
212                 protected:
213                 ButtonID _id;
214         };
215
216         struct ControllerButton : public Button {
217
218                 ControllerButton(ButtonID id, uint8_t cn,
219                                 void (LaunchControlXL::*press)())
220                         : Button(id, press), _controller_number(cn) {}
221
222                 ControllerButton(ButtonID id, uint8_t cn,
223                                 void (LaunchControlXL::*press)(),
224                                 void (LaunchControlXL::*release)())
225                         : Button(id, press, release), _controller_number(cn) {}
226
227
228                 uint8_t controller_number() const { return _controller_number; }
229
230                 private:
231                 uint8_t _controller_number;
232         };
233
234         struct NoteButton : public Button {
235
236                 NoteButton(ButtonID id, uint8_t cn, void (LaunchControlXL::*press)())
237                         : Button(id, press), _note_number(cn) {}
238
239                 NoteButton(ButtonID id, uint8_t cn,
240                                 void (LaunchControlXL::*press)(),
241                                 void (LaunchControlXL::*release)())
242                         : Button(id, press, release), _note_number(cn) {}
243                 NoteButton(ButtonID id, uint8_t cn,
244                                 void (LaunchControlXL::*press)(),
245                                 void (LaunchControlXL::*release)(),
246                                 void (LaunchControlXL::*release_long)())
247                         : Button(id, press, release, release_long), _note_number(cn) {}
248
249                 uint8_t note_number() const { return _note_number; }
250
251                 private:
252                 uint8_t _note_number;
253         };
254
255         struct TrackButton : public NoteButton, public MultiColorLED {
256                 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor color,
257                                 void (LaunchControlXL::*press)(), LaunchControlXL& l)
258                         : NoteButton(id, nn, press), MultiColorLED(index, color, l) {}
259
260                 TrackButton(ButtonID id, uint8_t nn, uint8_t index, LEDColor color,
261                                 void (LaunchControlXL::*press)(),
262                                 void (LaunchControlXL::*release)(),
263                                 LaunchControlXL& l)
264                         : NoteButton(id, nn, press, release), MultiColorLED(index, color, l) {}
265
266                 MidiByteArray state_msg(bool light = true) const;
267         };
268
269         struct SelectButton : public ControllerButton, public LED {
270                 SelectButton(ButtonID id, uint8_t cn, uint8_t index, void (LaunchControlXL::*press)(), LaunchControlXL& l)
271                         : ControllerButton(id, cn, press), LED(index, LEDColor::RedFull, l) {}
272
273                 MidiByteArray state_msg(bool light) const;
274         };
275
276         struct TrackStateButton : public NoteButton, public LED {
277                 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(), LaunchControlXL& l)
278                         : NoteButton(id, nn, press)
279                         , LED(index, LEDColor::Yellow, l) {}
280
281                 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(),
282                                 void (LaunchControlXL::*release)(),
283                                 LaunchControlXL& l)
284                         : NoteButton(id, nn, press, release)
285                         , LED(index, LEDColor::Yellow, l) {}
286
287                 TrackStateButton(ButtonID id, uint8_t nn, uint8_t index, void (LaunchControlXL::*press)(),
288                                 void (LaunchControlXL::*release)(),
289                                 void (LaunchControlXL::*release_long)(),
290                                 LaunchControlXL& l)
291                         : NoteButton(id, nn, press, release, release_long)
292                         , LED(index, LEDColor::Yellow, l) {}
293
294                 MidiByteArray state_msg(bool light) const;
295         };
296
297         struct Fader : public Controller {
298                 Fader(FaderID id, uint8_t cn)
299                         : Controller(cn, 0), _id(id) {} // minimal value
300
301                 FaderID id() const { return _id; }
302
303                 void controller_changed(Controller* controller);
304
305                 private:
306                 FaderID _id;
307         };
308
309         struct Knob : public Controller, public MultiColorLED {
310                 Knob(KnobID id, uint8_t cn, uint8_t index, LEDColor color, LaunchControlXL& l)
311                         : Controller(cn, 64)
312                         , MultiColorLED(index, color, l)
313                         , _id(id) {} // knob 50/50 value
314
315                 KnobID id() const { return _id; }
316
317                 MidiByteArray state_msg(bool light = true) const;
318
319                 private:
320                 KnobID _id;
321         };
322
323 public:
324         LaunchControlXL(ARDOUR::Session &);
325         ~LaunchControlXL();
326
327
328         static bool probe();
329         static void *request_factory(uint32_t);
330
331         std::list<boost::shared_ptr<ARDOUR::Bundle>> bundles();
332
333         bool has_editor() const { return true; }
334         void *get_gui() const;
335         void tear_down_gui();
336
337         int set_active(bool yn);
338         XMLNode &get_state();
339         int set_state(const XMLNode &node, int version);
340
341         PBD::Signal0<void> ConnectionChange;
342
343         boost::shared_ptr<ARDOUR::Port> input_port();
344         boost::shared_ptr<ARDOUR::Port> output_port();
345
346         Button *button_by_id(ButtonID);
347
348         static std::string button_name_by_id(ButtonID);
349         static std::string knob_name_by_id(KnobID);
350         static std::string fader_name_by_id(FaderID);
351
352         void write(const MidiByteArray &);
353
354         TrackMode track_mode() const { return _track_mode; }
355         void set_track_mode(TrackMode mode);
356
357         uint8_t template_number() const { return _template_number; }
358
359 private:
360         bool in_use;
361         TrackMode _track_mode;
362         uint8_t _template_number;
363
364         void do_request(LaunchControlRequest *);
365
366         int begin_using_device();
367         int stop_using_device();
368         int ports_acquire();
369         void ports_release();
370         void run_event_loop();
371         void stop_event_loop();
372
373         void relax() {}
374
375         /* map of NoteButtons by NoteNumber */
376         typedef std::map<int, NoteButton *> NNNoteButtonMap;
377         NNNoteButtonMap nn_note_button_map;
378         /* map of NoteButtons by ButtonID */
379         typedef std::map<ButtonID, NoteButton *> IDNoteButtonMap;
380         IDNoteButtonMap id_note_button_map;
381         /* map of ControllerNoteButtons by CC */
382         typedef std::map<int, ControllerButton *> CCControllerButtonMap;
383         CCControllerButtonMap cc_controller_button_map;
384         /* map of ControllerButtons by ButtonID */
385         typedef std::map<ButtonID, ControllerButton *> IDControllerButtonMap;
386         IDControllerButtonMap id_controller_button_map;
387
388
389         /* map of Fader by CC */
390         typedef std::map<int, Fader *> CCFaderMap;
391         CCFaderMap cc_fader_map;
392         /* map of Fader by FaderID */
393         typedef std::map<FaderID, Fader *> IDFaderMap;
394         IDFaderMap id_fader_map;
395
396         /* map of Knob by CC */
397         typedef std::map<int, Knob *> CCKnobMap;
398         CCKnobMap cc_knob_map;
399         /* map of Knob by KnobID */
400         typedef std::map<KnobID, Knob *> IDKnobMap;
401         IDKnobMap id_knob_map;
402
403         std::set<ButtonID> buttons_down;
404         std::set<ButtonID> consumed;
405
406         bool button_long_press_timeout(ButtonID id, Button *button);
407         void start_press_timeout(Button *, ButtonID);
408
409         void init_buttons(bool startup);
410
411         void switch_template(uint8_t t);
412
413         void build_maps();
414
415         // Bundle to represent our input ports
416         boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
417         // Bundle to represent our output ports
418         boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
419
420         MIDI::Port *_input_port;
421         MIDI::Port *_output_port;
422         boost::shared_ptr<ARDOUR::Port> _async_in;
423         boost::shared_ptr<ARDOUR::Port> _async_out;
424
425         void connect_to_parser();
426         void handle_button_message(Button* button, MIDI::EventTwoBytes *);
427         void handle_fader_message(Fader* fader);
428         void handle_knob_message(Knob* knob);
429
430         void handle_midi_controller_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
431         void handle_midi_note_on_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
432         void handle_midi_note_off_message(MIDI::Parser &, MIDI::EventTwoBytes *, MIDI::channel_t chan);
433         void handle_midi_sysex(MIDI::Parser &, MIDI::byte *, size_t count);
434
435         bool midi_input_handler(Glib::IOCondition ioc, MIDI::Port *port);
436
437         void thread_init();
438
439         PBD::ScopedConnectionList session_connections;
440         void connect_session_signals();
441         void notify_transport_state_changed();
442         void notify_loop_state_changed();
443         void notify_parameter_changed(std::string);
444
445
446         /* Button methods */
447
448         TrackButton* track_button_by_number(uint8_t n, uint8_t first, uint8_t middle);
449         TrackButton* focus_button_by_number(uint8_t n) { return track_button_by_number(n, 41, 57) ; }
450         TrackButton* control_button_by_number(uint8_t n) { return track_button_by_number(n, 73, 89) ; }
451
452
453         void button_device();
454         void button_device_long_press();
455         void button_track_mode(TrackMode state);
456         void button_mute() { button_track_mode(TrackMode::TrackMute); }
457         void button_solo() { button_track_mode(TrackMode::TrackSolo); }
458         void button_record() { button_track_mode(TrackMode::TrackRecord); }
459         void button_select_up();
460         void button_select_down();
461         void button_select_left();
462         void button_select_right();
463
464         void button_track_focus(uint8_t n);
465         void button_track_control(uint8_t n);
466
467         boost::shared_ptr<ARDOUR::AutomationControl> get_ac_by_state(uint8_t n);
468         void update_track_control_led(uint8_t n);
469
470         void button_track_focus_1() { ControlProtocol::ToggleStripableSelection (stripable[0]); }
471         void button_track_focus_2() { ControlProtocol::ToggleStripableSelection (stripable[1]); }
472         void button_track_focus_3() { ControlProtocol::ToggleStripableSelection (stripable[2]); }
473         void button_track_focus_4() { ControlProtocol::ToggleStripableSelection (stripable[3]); }
474         void button_track_focus_5() { ControlProtocol::ToggleStripableSelection (stripable[4]); }
475         void button_track_focus_6() { ControlProtocol::ToggleStripableSelection (stripable[5]); }
476         void button_track_focus_7() { ControlProtocol::ToggleStripableSelection (stripable[6]); }
477         void button_track_focus_8() { ControlProtocol::ToggleStripableSelection (stripable[7]); }
478
479         void button_track_control_1() { button_track_control(0); }
480         void button_track_control_2() { button_track_control(1); }
481         void button_track_control_3() { button_track_control(2); }
482         void button_track_control_4() { button_track_control(3); }
483         void button_track_control_5() { button_track_control(4); }
484         void button_track_control_6() { button_track_control(5); }
485         void button_track_control_7() { button_track_control(6); }
486         void button_track_control_8() { button_track_control(7); }
487
488         /* stripables */
489
490         int32_t bank_start;
491         PBD::ScopedConnectionList stripable_connections;
492         boost::shared_ptr<ARDOUR::Stripable> stripable[8];
493
494         void stripables_added ();
495
496         void stripable_property_change (PBD::PropertyChange const& what_changed, uint32_t which);
497
498         void switch_bank (uint32_t base);
499
500         void solo_changed (uint32_t n) { solo_mute_rec_changed(n); }
501         void mute_changed (uint32_t n) { solo_mute_rec_changed(n); }
502         void rec_changed (uint32_t n) { solo_mute_rec_changed(n); }
503         void solo_mute_rec_changed (uint32_t n);
504
505         /* special Stripable */
506
507         boost::shared_ptr<ARDOUR::Stripable> master;
508
509         PBD::ScopedConnection port_reg_connection;
510         void port_registration_handler();
511
512         enum ConnectionState { InputConnected = 0x1, OutputConnected = 0x2 };
513
514         int connection_state;
515         bool connection_handler(boost::weak_ptr<ARDOUR::Port>, std::string name1,
516                         boost::weak_ptr<ARDOUR::Port>, std::string name2,
517                         bool yn);
518         PBD::ScopedConnection port_connection;
519         void connected();
520
521         /* GUI */
522
523         mutable LCXLGUI *gui;
524         void build_gui();
525
526         void stripable_selection_changed();
527
528         bool in_range_select;
529                                                                                                 };
530
531
532 } // namespace ArdourSurface
533
534 #endif /* __ardour_launch_control_h__ */