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