light solo button, and do cancel_all_solo() when it is pressed
[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                         Off,
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                         Red = 127,
178                         Green = 126,
179                         Blue = 125,
180                         DarkGray = 124,
181                         LightGray = 123,
182                         White = 122
183                 };
184
185                 LED (uint8_t e) : _extra (e), _color_index (0), _state (Off) {}
186                 virtual ~LED() {}
187
188                 uint8_t extra () const { return _extra; }
189                 uint8_t color_index () const { return _color_index; }
190                 State   state () const { return _state; }
191
192                 void set_color (uint8_t color_index);
193                 void set_state (State state);
194
195                 virtual MidiByteArray state_msg() const = 0;
196
197              protected:
198                 uint8_t _extra;
199                 uint8_t _color_index;
200                 State   _state;
201         };
202
203         struct Pad : public LED {
204                 Pad (int xx, int yy, uint8_t ex)
205                         : LED (ex)
206                         , x (xx)
207                         , y (yy) {}
208
209                 MidiByteArray state_msg () const { return MidiByteArray (3, 0x90|_state, _extra, (_state == Off) ? 0 : _color_index); }
210
211                 int coord () const { return (y * 8) + x; }
212                 int note_number() const { return extra(); }
213
214                 int x;
215                 int y;
216         };
217
218         struct Button : public LED {
219                 Button (ButtonID bb, uint8_t ex)
220                         : LED (ex)
221                         , id (bb)
222                         , press_method (&Push2::relax)
223                         , release_method (&Push2::relax)
224                 {}
225
226                 Button (ButtonID bb, uint8_t ex, void (Push2::*press)())
227                         : LED (ex)
228                         , id (bb)
229                         , press_method (press)
230                         , release_method (&Push2::relax)
231                 {}
232
233                 Button (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)())
234                         : LED (ex)
235                         , id (bb)
236                         , press_method (press)
237                         , release_method (release)
238                 {}
239
240                 MidiByteArray state_msg () const { return MidiByteArray (3, 0xb0|_state, _extra, (_state == Off) ? 0 : _color_index); }
241                 int controller_number() const { return extra(); }
242
243                 ButtonID id;
244                 void (Push2::*press_method)();
245                 void (Push2::*release_method)();
246         };
247
248         struct ColorButton : public Button {
249                 ColorButton (ButtonID bb, uint8_t ex)
250                         : Button (bb, ex) {}
251
252
253                 ColorButton (ButtonID bb, uint8_t ex, void (Push2::*press)())
254                         : Button (bb, ex, press) {}
255
256                 ColorButton (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)())
257                         : Button (bb, ex, press, release) {}
258         };
259
260         struct WhiteButton : public Button {
261                 WhiteButton (ButtonID bb, uint8_t ex)
262                         : Button (bb, ex) {}
263
264                 WhiteButton (ButtonID bb, uint8_t ex, void (Push2::*press)())
265                         : Button (bb, ex, press) {}
266
267                 WhiteButton (ButtonID bb, uint8_t ex, void (Push2::*press)(), void (Push2::*release)())
268                         : Button (bb, ex, press, release) {}
269         };
270
271         void relax () {}
272
273         /* map of Buttons by CC */
274         typedef std::map<int,Button*> CCButtonMap;
275         CCButtonMap cc_button_map;
276         /* map of Buttons by ButtonID */
277         typedef std::map<ButtonID,Button*> IDButtonMap;
278         IDButtonMap id_button_map;
279
280         /* map of Pads by note number */
281         typedef std::map<int,Pad*> NNPadMap;
282         NNPadMap nn_pad_map;
283         /* map of Pads by coordinate
284          *
285          * coord = row * 64 + column;
286          *
287          * rows start at top left
288          */
289         typedef std::map<int,Pad*> CoordPadMap;
290         CoordPadMap coord_pad_map;
291
292         void set_button_color (ButtonID, uint8_t color_index);
293         void set_button_state (ButtonID, LED::State);
294         void set_led_color (ButtonID, uint8_t color_index);
295         void set_led_state (ButtonID, LED::State);
296
297         void build_maps ();
298
299         MIDI::Port* _input_port;
300         MIDI::Port* _output_port;
301         boost::shared_ptr<ARDOUR::Port> _async_in;
302         boost::shared_ptr<ARDOUR::Port> _async_out;
303
304         void connect_to_parser ();
305         void handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t);
306         void handle_midi_controller_message (MIDI::Parser&, MIDI::EventTwoBytes*);
307         void handle_midi_note_on_message (MIDI::Parser&, MIDI::EventTwoBytes*);
308         void handle_midi_note_off_message (MIDI::Parser&, MIDI::EventTwoBytes*);
309         void handle_midi_sysex (MIDI::Parser&, MIDI::byte *, size_t count);
310
311         void write (const MidiByteArray&);
312         bool midi_input_handler (Glib::IOCondition ioc, MIDI::Port* port);
313         bool periodic ();
314
315         void thread_init ();
316
317         PBD::ScopedConnectionList session_connections;
318         void connect_session_signals ();
319         void notify_record_state_changed ();
320         void notify_transport_state_changed ();
321         void notify_loop_state_changed ();
322         void notify_parameter_changed (std::string);
323         void notify_solo_active_changed (bool);
324
325         /* Button methods */
326         void button_play ();
327         void button_recenable ();
328         void button_up ();
329         void button_down ();
330         void button_right ();
331         void button_left ();
332         void button_metronome ();
333         void button_repeat ();
334         void button_solo ();
335
336         /* widgets */
337
338         Cairo::RefPtr<Cairo::Context> context;
339         Glib::RefPtr<Pango::Layout> tc_clock_layout;
340         Glib::RefPtr<Pango::Layout> bbt_clock_layout;
341         Glib::RefPtr<Pango::Layout> upper_layout[8];
342         Glib::RefPtr<Pango::Layout> mid_layout[8];
343         Glib::RefPtr<Pango::Layout> lower_layout[8];
344 };
345
346
347 } /* namespace */
348
349 #endif /* __ardour_push2_h__ */