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