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