turn on all buttons that be envisaged as useful in ardour (for now); add support...
[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 }
57
58 namespace ArdourSurface {
59
60 struct Push2Request : public BaseUI::BaseRequestObject {
61 public:
62         Push2Request () {}
63         ~Push2Request () {}
64 };
65
66 class Push2 : public ARDOUR::ControlProtocol
67             , public AbstractUI<Push2Request>
68 {
69    public:
70         Push2 (ARDOUR::Session&);
71         ~Push2 ();
72
73         static bool probe ();
74         static void* request_factory (uint32_t);
75
76         int set_active (bool yn);
77         XMLNode& get_state();
78         int set_state (const XMLNode & node, int version);
79
80    private:
81         libusb_device_handle *handle;
82         uint8_t   frame_header[16];
83         uint16_t* device_frame_buffer;
84         int  device_buffer;
85         Cairo::RefPtr<Cairo::ImageSurface> frame_buffer;
86         sigc::connection vblank_connection;
87         sigc::connection periodic_connection;
88
89         static const int cols;
90         static const int rows;
91         static const int pixels_per_row;
92
93         void do_request (Push2Request*);
94         int stop ();
95         int open ();
96         int close ();
97         bool redraw ();
98         int bitblt_to_device_frame_buffer ();
99         bool vblank ();
100
101         enum ButtonID {
102                 TapTempo,
103                 Metronome,
104                 Upper1, Upper2, Upper3, Upper4, Upper5, Upper6, Upper7, Upper8,
105                 Setup,
106                 User,
107                 Delete,
108                 AddDevice,
109                 Device,
110                 Mix,
111                 Undo,
112                 AddTrack,
113                 Browse,
114                 Clip,
115                 Mute,
116                 Solo,
117                 Stop,
118                 Lower1, Lower2, Lower3, Lower4, Lower5, Lower6, Lower7, Lower8,
119                 Master,
120                 Convert,
121                 DoubleLoop,
122                 Quantize,
123                 Duplicate,
124                 New,
125                 FixedLength,
126                 Automate,
127                 RecordEnable,
128                 Play,
129                 Fwd32ndT,
130                 Fwd32nd,
131                 Fwd16thT,
132                 Fwd16th,
133                 Fwd8thT,
134                 Fwd8th,
135                 Fwd4trT,
136                 Fwd4tr,
137                 Up,
138                 Right,
139                 Down,
140                 Left,
141                 Repeat,
142                 Accent,
143                 Scale,
144                 Layout,
145                 Note,
146                 Session,
147                 OctaveUp,
148                 PageRight,
149                 OctaveDown,
150                 PageLeft,
151                 Shift,
152                 Select
153         };
154
155         struct LED
156         {
157                 enum State {
158                         NoTransition,
159                         OneShot24th,
160                         OneShot16th,
161                         OneShot8th,
162                         OneShot4th,
163                         OneShot2th,
164                         Pulsing24th,
165                         Pulsing16th,
166                         Pulsing8th,
167                         Pulsing4th,
168                         Pulsing2th,
169                         Blinking24th,
170                         Blinking16th,
171                         Blinking8th,
172                         Blinking4th,
173                         Blinking2th
174                 };
175
176                 enum Colors {
177                         Black = 0,
178                         Red = 127,
179                         Green = 126,
180                         Blue = 125,
181                         DarkGray = 124,
182                         LightGray = 123,
183                         White = 122
184                 };
185
186                 LED (uint8_t e) : _extra (e), _color_index (0), _state (NoTransition) {}
187                 virtual ~LED() {}
188
189                 uint8_t extra () const { return _extra; }
190                 uint8_t color_index () const { return _color_index; }
191                 State   state () const { return _state; }
192
193                 void set_color (uint8_t color_index);
194                 void set_state (State state);
195
196                 virtual MidiByteArray state_msg() const = 0;
197
198              protected:
199                 uint8_t _extra;
200                 uint8_t _color_index;
201                 State   _state;
202         };
203
204         struct Pad : public LED {
205                 Pad (int xx, int yy, uint8_t ex)
206                         : LED (ex)
207                         , x (xx)
208                         , y (yy) {}
209
210                 MidiByteArray state_msg () const { return MidiByteArray (3, 0x90|_state, _extra, _color_index); }
211
212                 int coord () const { return (y * 8) + x; }
213                 int note_number() const { return extra(); }
214
215                 int x;
216                 int y;
217         };
218
219         struct Button : public LED {
220                 Button (ButtonID bb, uint8_t ex)
221                         : LED (ex)
222                         , id (bb)
223                         , press_method (&Push2::relax)
224                         , release_method (&Push2::relax)
225                 {}
226
227                 Button (ButtonID bb, uint8_t ex, void (Push2::*press)())
228                         : LED (ex)
229                         , id (bb)
230                         , press_method (press)
231                         , release_method (&Push2::relax)
232                 {}
233
234                 Button (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)())
235                         : LED (ex)
236                         , id (bb)
237                         , press_method (press)
238                         , release_method (release)
239                 {}
240
241                 MidiByteArray state_msg () const { return MidiByteArray (3, 0xb0|_state, _extra, _color_index); }
242                 int controller_number() const { return extra(); }
243
244                 ButtonID id;
245                 void (Push2::*press_method)();
246                 void (Push2::*release_method)();
247         };
248
249         struct ColorButton : public Button {
250                 ColorButton (ButtonID bb, uint8_t ex)
251                         : Button (bb, ex) {}
252
253
254                 ColorButton (ButtonID bb, uint8_t ex, void (Push2::*press)())
255                         : Button (bb, ex, press) {}
256
257                 ColorButton (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)())
258                         : Button (bb, ex, press, release) {}
259         };
260
261         struct WhiteButton : public Button {
262                 WhiteButton (ButtonID bb, uint8_t ex)
263                         : Button (bb, ex) {}
264
265                 WhiteButton (ButtonID bb, uint8_t ex, void (Push2::*press)())
266                         : Button (bb, ex, press) {}
267
268                 WhiteButton (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)())
269                         : Button (bb, ex, press, release) {}
270         };
271
272         void relax () {}
273
274         /* map of Buttons by CC */
275         typedef std::map<int,Button*> CCButtonMap;
276         CCButtonMap cc_button_map;
277         /* map of Buttons by ButtonID */
278         typedef std::map<ButtonID,Button*> IDButtonMap;
279         IDButtonMap id_button_map;
280
281         void init_buttons ();
282
283         /* map of Pads by note number */
284         typedef std::map<int,Pad*> NNPadMap;
285         NNPadMap nn_pad_map;
286         /* map of Pads by coordinate
287          *
288          * coord = row * 64 + column;
289          *
290          * rows start at top left
291          */
292         typedef std::map<int,Pad*> CoordPadMap;
293         CoordPadMap coord_pad_map;
294
295         void set_button_color (ButtonID, uint8_t color_index);
296         void set_button_state (ButtonID, LED::State);
297         void set_led_color (ButtonID, uint8_t color_index);
298         void set_led_state (ButtonID, LED::State);
299
300         void build_maps ();
301
302         MIDI::Port* _input_port;
303         MIDI::Port* _output_port;
304         boost::shared_ptr<ARDOUR::Port> _async_in;
305         boost::shared_ptr<ARDOUR::Port> _async_out;
306
307         void connect_to_parser ();
308         void handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t);
309         void handle_midi_controller_message (MIDI::Parser&, MIDI::EventTwoBytes*);
310         void handle_midi_note_on_message (MIDI::Parser&, MIDI::EventTwoBytes*);
311         void handle_midi_note_off_message (MIDI::Parser&, MIDI::EventTwoBytes*);
312         void handle_midi_sysex (MIDI::Parser&, MIDI::byte *, size_t count);
313
314         void write (const MidiByteArray&);
315         bool midi_input_handler (Glib::IOCondition ioc, MIDI::Port* port);
316         bool periodic ();
317
318         void thread_init ();
319
320         PBD::ScopedConnectionList session_connections;
321         void connect_session_signals ();
322         void notify_record_state_changed ();
323         void notify_transport_state_changed ();
324         void notify_loop_state_changed ();
325         void notify_parameter_changed (std::string);
326         void notify_solo_active_changed (bool);
327
328         /* Button methods */
329         void button_play ();
330         void button_recenable ();
331         void button_up ();
332         void button_down ();
333         void button_right ();
334         void button_left ();
335         void button_metronome ();
336         void button_repeat ();
337         void button_solo ();
338         void button_fixed_length ();
339         void button_new ();
340
341         /* widgets */
342
343         Cairo::RefPtr<Cairo::Context> context;
344         Glib::RefPtr<Pango::Layout> tc_clock_layout;
345         Glib::RefPtr<Pango::Layout> bbt_clock_layout;
346         Glib::RefPtr<Pango::Layout> upper_layout[8];
347         Glib::RefPtr<Pango::Layout> mid_layout[8];
348         Glib::RefPtr<Pango::Layout> lower_layout[8];
349 };
350
351
352 } /* namespace */
353
354 #endif /* __ardour_push2_h__ */