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