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