tweaks and so forth to get first canvas-based rendering to Push2 display
[ardour.git] / libs / surfaces / push2 / push2.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_push2_h__
20 #define __ardour_push2_h__
21
22 #include <vector>
23 #include <map>
24 #include <stack>
25 #include <list>
26 #include <set>
27
28 #include <libusb.h>
29
30 #define ABSTRACT_UI_EXPORTS
31 #include "pbd/abstract_ui.h"
32
33 #include "midi++/types.h"
34
35 #include "ardour/types.h"
36
37 #include "control_protocol/control_protocol.h"
38 #include "control_protocol/types.h"
39
40 #include "midi_byte_array.h"
41 #include "mode.h"
42
43 namespace Pango {
44         class Layout;
45 }
46
47 namespace MIDI {
48         class Parser;
49         class Port;
50 }
51
52 namespace ARDOUR {
53         class AsyncMIDIPort;
54         class Port;
55         class MidiBuffer;
56         class MidiTrack;
57 }
58
59 namespace ArdourSurface {
60
61 struct Push2Request : public BaseUI::BaseRequestObject {
62 public:
63         Push2Request () {}
64         ~Push2Request () {}
65 };
66
67 class P2GUI;
68 class Push2Menu;
69 class Push2Layout;
70 class Push2Canvas;
71
72 class Push2 : public ARDOUR::ControlProtocol
73             , public AbstractUI<Push2Request>
74 {
75   public:
76         enum ButtonID {
77                 TapTempo,
78                 Metronome,
79                 Upper1, Upper2, Upper3, Upper4, Upper5, Upper6, Upper7, Upper8,
80                 Setup,
81                 User,
82                 Delete,
83                 AddDevice,
84                 Device,
85                 Mix,
86                 Undo,
87                 AddTrack,
88                 Browse,
89                 Clip,
90                 Mute,
91                 Solo,
92                 Stop,
93                 Lower1, Lower2, Lower3, Lower4, Lower5, Lower6, Lower7, Lower8,
94                 Master,
95                 Convert,
96                 DoubleLoop,
97                 Quantize,
98                 Duplicate,
99                 New,
100                 FixedLength,
101                 Automate,
102                 RecordEnable,
103                 Play,
104                 Fwd32ndT,
105                 Fwd32nd,
106                 Fwd16thT,
107                 Fwd16th,
108                 Fwd8thT,
109                 Fwd8th,
110                 Fwd4trT,
111                 Fwd4tr,
112                 Up,
113                 Right,
114                 Down,
115                 Left,
116                 Repeat,
117                 Accent,
118                 Scale,
119                 Layout,
120                 Note,
121                 Session,
122                 OctaveUp,
123                 PageRight,
124                 OctaveDown,
125                 PageLeft,
126                 Shift,
127                 Select
128         };
129
130         struct LED
131         {
132                 enum State {
133                         NoTransition,
134                         OneShot24th,
135                         OneShot16th,
136                         OneShot8th,
137                         OneShot4th,
138                         OneShot2th,
139                         Pulsing24th,
140                         Pulsing16th,
141                         Pulsing8th,
142                         Pulsing4th,
143                         Pulsing2th,
144                         Blinking24th,
145                         Blinking16th,
146                         Blinking8th,
147                         Blinking4th,
148                         Blinking2th
149                 };
150
151                 enum Colors {
152                         Black = 0,
153                         Red = 127,
154                         Green = 126,
155                         Blue = 125,
156                         DarkGray = 124,
157                         LightGray = 123,
158                         White = 122
159                 };
160
161                 LED (uint8_t e) : _extra (e), _color_index (Black), _state (NoTransition) {}
162                 virtual ~LED() {}
163
164                 uint8_t extra () const { return _extra; }
165                 uint8_t color_index () const { return _color_index; }
166                 State   state () const { return _state; }
167
168                 void set_color (uint8_t color_index);
169                 void set_state (State state);
170
171                 virtual MidiByteArray state_msg() const = 0;
172
173              protected:
174                 uint8_t _extra;
175                 uint8_t _color_index;
176                 State   _state;
177         };
178
179         struct Pad : public LED {
180                 enum WhenPressed {
181                         Nothing,
182                         FlashOn,
183                         FlashOff,
184                 };
185
186                 Pad (int xx, int yy, uint8_t ex)
187                         : LED (ex)
188                         , x (xx)
189                         , y (yy)
190                         , do_when_pressed (FlashOn)
191                         , filtered (ex)
192                         , perma_color (LED::Black)
193                 {}
194
195                 MidiByteArray state_msg () const { return MidiByteArray (3, 0x90|_state, _extra, _color_index); }
196
197                 int coord () const { return (y * 8) + x; }
198                 int note_number() const { return extra(); }
199
200                 int x;
201                 int y;
202                 int do_when_pressed;
203                 int filtered;
204                 int perma_color;
205         };
206
207         struct Button : public LED {
208                 Button (ButtonID bb, uint8_t ex)
209                         : LED (ex)
210                         , id (bb)
211                         , press_method (&Push2::relax)
212                         , release_method (&Push2::relax)
213                         , long_press_method (&Push2::relax)
214                 {}
215
216                 Button (ButtonID bb, uint8_t ex, void (Push2::*press)())
217                         : LED (ex)
218                         , id (bb)
219                         , press_method (press)
220                         , release_method (&Push2::relax)
221                         , long_press_method (&Push2::relax)
222                 {}
223
224                 Button (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)())
225                         : LED (ex)
226                         , id (bb)
227                         , press_method (press)
228                         , release_method (release)
229                         , long_press_method (&Push2::relax)
230                 {}
231
232                 Button (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)(), void (Push2::*long_press)())
233                         : LED (ex)
234                         , id (bb)
235                         , press_method (press)
236                         , release_method (release)
237                         , long_press_method (long_press)
238                 {}
239
240                 MidiByteArray state_msg () const { return MidiByteArray (3, 0xb0|_state, _extra, _color_index); }
241                 int controller_number() const { return extra(); }
242
243                 ButtonID id;
244                 void (Push2::*press_method)();
245                 void (Push2::*release_method)();
246                 void (Push2::*long_press_method)();
247                 sigc::connection timeout_connection;
248         };
249
250         struct ColorButton : public Button {
251                 ColorButton (ButtonID bb, uint8_t ex)
252                         : Button (bb, ex) {}
253
254
255                 ColorButton (ButtonID bb, uint8_t ex, void (Push2::*press)())
256                         : Button (bb, ex, press) {}
257
258                 ColorButton (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)())
259                         : Button (bb, ex, press, release) {}
260
261                 ColorButton (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)(), void (Push2::*long_press)())
262                         : Button (bb, ex, press, release, long_press) {}
263         };
264
265         struct WhiteButton : public Button {
266                 WhiteButton (ButtonID bb, uint8_t ex)
267                         : Button (bb, ex) {}
268
269                 WhiteButton (ButtonID bb, uint8_t ex, void (Push2::*press)())
270                         : Button (bb, ex, press) {}
271
272                 WhiteButton (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)())
273                         : Button (bb, ex, press, release) {}
274
275                 WhiteButton (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)(), void (Push2::*long_press)())
276                         : Button (bb, ex, press, release, long_press) {}
277         };
278
279         enum ColorName {
280                 DarkBackground,
281                 LightBackground,
282
283                 ParameterName,
284                 StripableName,
285                 ClockText,
286
287                 KnobArcBackground,
288                 KnobArcStart,
289                 KnobArcEnd,
290
291                 KnobLine,
292                 KnobLineShadow,
293
294                 KnobForeground,
295                 KnobBackground,
296                 KnobShadow,
297                 KnobBorder,
298         };
299
300         enum PressureMode {
301                 AfterTouch,
302                 PolyPressure,
303         };
304
305   public:
306         Push2 (ARDOUR::Session&);
307         ~Push2 ();
308
309         static bool probe ();
310         static void* request_factory (uint32_t);
311
312         std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles ();
313
314         bool has_editor () const { return true; }
315         void* get_gui () const;
316         void  tear_down_gui ();
317
318         int set_active (bool yn);
319         XMLNode& get_state();
320         int set_state (const XMLNode & node, int version);
321
322         PBD::Signal0<void> ConnectionChange;
323
324         boost::shared_ptr<ARDOUR::Port> input_port();
325         boost::shared_ptr<ARDOUR::Port> output_port();
326
327         int pad_note (int row, int col) const;
328         PBD::Signal0<void> PadChange;
329
330         void set_pad_scale (int root, int octave, MusicalMode::Type mode, bool inkey);
331
332         MusicalMode::Type mode() const { return  _mode; }
333         int scale_root() const { return _scale_root; }
334         int root_octave() const { return _root_octave; }
335         bool in_key() const { return _in_key; }
336
337         Push2Layout* current_layout() const;
338         Push2Canvas* canvas() const { return _canvas; }
339
340         enum ModifierState {
341                 None = 0,
342                 ModShift = 0x1,
343                 ModSelect = 0x2,
344         };
345
346         ModifierState modifier_state() const { return _modifier_state; }
347
348         Button* button_by_id (ButtonID);
349
350         void write (const MidiByteArray&);
351
352         uint8_t get_color_index (uint32_t rgb);
353         uint32_t get_color (ColorName);
354
355         PressureMode pressure_mode () const { return _pressure_mode; }
356         void set_pressure_mode (PressureMode);
357         PBD::Signal1<void,PressureMode> PressureModeChange;
358
359         libusb_device_handle* usb_handle() const { return handle; }
360
361   private:
362         libusb_device_handle *handle;
363         ModifierState _modifier_state;
364
365         void do_request (Push2Request*);
366         int stop ();
367         int open ();
368         int close ();
369
370         void relax () {}
371
372         /* map of Buttons by CC */
373         typedef std::map<int,Button*> CCButtonMap;
374         CCButtonMap cc_button_map;
375         /* map of Buttons by ButtonID */
376         typedef std::map<ButtonID,Button*> IDButtonMap;
377         IDButtonMap id_button_map;
378         std::set<ButtonID> buttons_down;
379         std::set<ButtonID> consumed;
380
381         bool button_long_press_timeout (ButtonID id);
382         void start_press_timeout (Button&, ButtonID);
383
384         void init_buttons (bool startup);
385         void init_touch_strip ();
386
387         /* map of Pads by note number */
388         typedef std::map<int,Pad*> NNPadMap;
389         NNPadMap nn_pad_map;
390
391         void set_button_color (ButtonID, uint8_t color_index);
392         void set_button_state (ButtonID, LED::State);
393         void set_led_color (ButtonID, uint8_t color_index);
394         void set_led_state (ButtonID, LED::State);
395
396         void build_maps ();
397
398         // Bundle to represent our input ports
399         boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
400         // Bundle to represent our output ports
401         boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
402
403         MIDI::Port* _input_port;
404         MIDI::Port* _output_port;
405         boost::shared_ptr<ARDOUR::Port> _async_in;
406         boost::shared_ptr<ARDOUR::Port> _async_out;
407
408         void connect_to_parser ();
409         void handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t);
410         void handle_midi_controller_message (MIDI::Parser&, MIDI::EventTwoBytes*);
411         void handle_midi_note_on_message (MIDI::Parser&, MIDI::EventTwoBytes*);
412         void handle_midi_note_off_message (MIDI::Parser&, MIDI::EventTwoBytes*);
413         void handle_midi_sysex (MIDI::Parser&, MIDI::byte *, size_t count);
414
415         bool midi_input_handler (Glib::IOCondition ioc, MIDI::Port* port);
416
417         sigc::connection periodic_connection;
418         bool periodic ();
419
420         void thread_init ();
421
422         PBD::ScopedConnectionList session_connections;
423         void connect_session_signals ();
424         void notify_record_state_changed ();
425         void notify_transport_state_changed ();
426         void notify_loop_state_changed ();
427         void notify_parameter_changed (std::string);
428         void notify_solo_active_changed (bool);
429
430         /* Button methods */
431         void button_play ();
432         void button_recenable ();
433         void button_up ();
434         void button_down ();
435         void button_right ();
436         void button_left ();
437         void button_metronome ();
438         void button_repeat ();
439         void button_mute ();
440         void button_solo ();
441         void button_solo_long_press ();
442         void button_fixed_length ();
443         void button_new ();
444         void button_browse ();
445         void button_clip ();
446         void button_undo ();
447         void button_fwd32t ();
448         void button_fwd32 ();
449         void button_fwd16t ();
450         void button_fwd16 ();
451         void button_fwd8t ();
452         void button_fwd8 ();
453         void button_fwd4t ();
454         void button_fwd4 ();
455         void button_add_track ();
456         void button_stop ();
457         void button_shift_press ();
458         void button_shift_release ();
459         void button_shift_long_press ();
460         void button_select_press ();
461         void button_select_release ();
462         void button_select_long_press ();
463         void button_page_left ();
464         void button_page_right ();
465         void button_octave_up ();
466         void button_octave_down ();
467         void button_layout_press ();
468         void button_scale_press ();
469         void button_mix_press ();
470
471         void button_upper (uint32_t n);
472         void button_lower (uint32_t n);
473
474         void button_upper_1 () { button_upper (0); }
475         void button_upper_2 () { button_upper (1); }
476         void button_upper_3 () { button_upper (2); }
477         void button_upper_4 () { button_upper (3); }
478         void button_upper_5 () { button_upper (4); }
479         void button_upper_6 () { button_upper (5); }
480         void button_upper_7 () { button_upper (6); }
481         void button_upper_8 () { button_upper (7); }
482         void button_lower_1 () { button_lower (0); }
483         void button_lower_2 () { button_lower (1); }
484         void button_lower_3 () { button_lower (2); }
485         void button_lower_4 () { button_lower (3); }
486         void button_lower_5 () { button_lower (4); }
487         void button_lower_6 () { button_lower (5); }
488         void button_lower_7 () { button_lower (6); }
489         void button_lower_8 () { button_lower (7); }
490
491         void start_shift ();
492         void end_shift ();
493
494         /* non-strip encoders */
495
496         void other_vpot (int, int);
497         void other_vpot_touch (int, bool);
498
499         /* special Stripables */
500
501         boost::shared_ptr<ARDOUR::Stripable> master;
502         boost::shared_ptr<ARDOUR::Stripable> monitor;
503
504         sigc::connection vblank_connection;
505         bool vblank ();
506
507         void splash ();
508         ARDOUR::microseconds_t splash_start;
509
510         /* the canvas */
511
512         Push2Canvas* _canvas;
513
514         /* Layouts */
515
516         mutable Glib::Threads::Mutex layout_lock;
517         Push2Layout* _current_layout;
518         Push2Layout* mix_layout;
519         Push2Layout* scale_layout;
520         Push2Layout* track_mix_layout;
521         Push2Layout* splash_layout;
522         void set_current_layout (Push2Layout*);
523
524         bool pad_filter (ARDOUR::MidiBuffer& in, ARDOUR::MidiBuffer& out) const;
525
526         boost::weak_ptr<ARDOUR::MidiTrack> current_pad_target;
527
528         PBD::ScopedConnection port_reg_connection;
529         void port_registration_handler ();
530
531         enum ConnectionState {
532                 InputConnected = 0x1,
533                 OutputConnected = 0x2
534         };
535
536         int connection_state;
537         bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn);
538         PBD::ScopedConnection port_connection;
539         void connected ();
540
541         /* GUI */
542
543         mutable P2GUI* gui;
544         void build_gui ();
545
546         /* pad mapping */
547
548         PBD::ScopedConnection selection_connection;
549         void stripable_selection_change (ARDOUR::StripableNotificationListPtr);
550
551         MusicalMode::Type _mode;
552         int _scale_root;
553         int _root_octave;
554         bool _in_key;
555
556         int octave_shift;
557
558         bool percussion;
559         void set_percussive_mode (bool);
560
561         /* color map (device side) */
562
563         typedef std::map<uint32_t,uint8_t> ColorMap;
564         typedef std::stack<uint8_t> ColorMapFreeList;
565         ColorMap color_map;
566         ColorMapFreeList color_map_free_list;
567         void build_color_map ();
568
569         /* our own colors */
570
571         typedef std::map<ColorName,uint32_t> Colors;
572         Colors colors;
573         void fill_color_table ();
574
575         PressureMode _pressure_mode;
576         void request_pressure_mode ();
577 };
578
579 } /* namespace */
580
581 #endif /* __ardour_push2_h__ */