d30f89fabeedfea21a05434a6d3ea9acb72d3d03
[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_mute ();
447         void button_solo ();
448         void button_solo_long_press ();
449         void button_fixed_length ();
450         void button_new ();
451         void button_browse ();
452         void button_clip ();
453         void button_undo ();
454         void button_fwd32t ();
455         void button_fwd32 ();
456         void button_fwd16t ();
457         void button_fwd16 ();
458         void button_fwd8t ();
459         void button_fwd8 ();
460         void button_fwd4t ();
461         void button_fwd4 ();
462         void button_add_track ();
463         void button_stop ();
464         void button_shift_press ();
465         void button_shift_release ();
466         void button_shift_long_press ();
467         void button_select_press ();
468         void button_select_release ();
469         void button_select_long_press ();
470         void button_page_left ();
471         void button_page_right ();
472         void button_octave_up ();
473         void button_octave_down ();
474         void button_layout_press ();
475         void button_scale_press ();
476         void button_mix_press ();
477
478         void button_upper (uint32_t n);
479         void button_lower (uint32_t n);
480
481         void button_upper_1 () { button_upper (0); }
482         void button_upper_2 () { button_upper (1); }
483         void button_upper_3 () { button_upper (2); }
484         void button_upper_4 () { button_upper (3); }
485         void button_upper_5 () { button_upper (4); }
486         void button_upper_6 () { button_upper (5); }
487         void button_upper_7 () { button_upper (6); }
488         void button_upper_8 () { button_upper (7); }
489         void button_lower_1 () { button_lower (0); }
490         void button_lower_2 () { button_lower (1); }
491         void button_lower_3 () { button_lower (2); }
492         void button_lower_4 () { button_lower (3); }
493         void button_lower_5 () { button_lower (4); }
494         void button_lower_6 () { button_lower (5); }
495         void button_lower_7 () { button_lower (6); }
496         void button_lower_8 () { button_lower (7); }
497
498         void start_shift ();
499         void end_shift ();
500
501         /* non-strip encoders */
502
503         void other_vpot (int, int);
504         void other_vpot_touch (int, bool);
505
506         /* special Stripables */
507
508         boost::shared_ptr<ARDOUR::Stripable> master;
509         boost::shared_ptr<ARDOUR::Stripable> monitor;
510
511         /* Cairo graphics context */
512
513         Cairo::RefPtr<Cairo::Context> context;
514
515         void splash ();
516         ARDOUR::microseconds_t splash_start;
517
518         /* Layouts */
519
520         mutable Glib::Threads::Mutex layout_lock;
521         Push2Layout* _current_layout;
522         Push2Layout* drawn_layout;
523         Push2Layout* mix_layout;
524         Push2Layout* scale_layout;
525         Push2Layout* track_mix_layout;
526         void set_current_layout (Push2Layout*);
527
528         bool pad_filter (ARDOUR::MidiBuffer& in, ARDOUR::MidiBuffer& out) const;
529
530         boost::weak_ptr<ARDOUR::MidiTrack> current_pad_target;
531
532         PBD::ScopedConnection port_reg_connection;
533         void port_registration_handler ();
534
535         enum ConnectionState {
536                 InputConnected = 0x1,
537                 OutputConnected = 0x2
538         };
539
540         int connection_state;
541         bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn);
542         PBD::ScopedConnection port_connection;
543
544         /* GUI */
545
546         mutable P2GUI* gui;
547         void build_gui ();
548
549         /* pad mapping */
550
551         PBD::ScopedConnection selection_connection;
552         void stripable_selection_change (ARDOUR::StripableNotificationListPtr);
553
554         MusicalMode::Type _mode;
555         int _scale_root;
556         int _root_octave;
557         bool _in_key;
558
559         int octave_shift;
560
561         bool percussion;
562         void set_percussive_mode (bool);
563
564         /* color map (device side) */
565
566         typedef std::map<uint32_t,uint8_t> ColorMap;
567         typedef std::stack<uint8_t> ColorMapFreeList;
568         ColorMap color_map;
569         ColorMapFreeList color_map_free_list;
570         void build_color_map ();
571
572         /* our own colors */
573
574         typedef std::map<ColorName,uint32_t> Colors;
575         Colors colors;
576         void fill_color_table ();
577 };
578
579 } /* namespace */
580
581 #endif /* __ardour_push2_h__ */