substantial overhaul of MCU code - no more separate thread, just connect to signals...
[ardour.git] / libs / surfaces / mackie / controls.h
1 /*
2         Copyright (C) 2006,2007 John Anderson
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 #ifndef mackie_controls_h
19 #define mackie_controls_h
20
21 #include <map>
22 #include <vector>
23 #include <string>
24
25 #include "pbd/signals.h"
26
27 #include "mackie_control_exception.h"
28
29 namespace Mackie
30 {
31
32 class Control;
33
34 /**
35         This is a loose group of controls, eg cursor buttons,
36         transport buttons, functions buttons etc.
37 */
38 class Group
39 {
40 public:
41         Group( const std::string & name )
42         : _name( name )
43         {
44         }
45         
46         virtual ~Group() {}
47         
48         virtual bool is_strip() const
49         {
50                 return false;
51         }
52         
53         virtual bool is_master() const
54         {
55                 return false;
56         }
57         
58         virtual void add( Control & control );
59         
60         const std::string & name() const
61         {
62                 return _name;
63         }
64         
65         // This is for Surface only
66         void name( const std::string & rhs ) { _name = rhs; }
67         
68         typedef std::vector<Control*> Controls;
69         const Controls & controls() const { return _controls; }
70         
71 protected:
72         Controls _controls;
73         
74 private:
75         std::string _name;
76 };
77
78 class Button;
79 class Pot;
80 class Fader;
81
82 /**
83         This is the set of controls that make up a strip.
84 */
85 class Strip : public Group
86 {
87 public:
88         /**
89                 \param is the index of the strip. 0-based.
90         */
91         Strip( const std::string & name, int index );
92         
93         virtual bool is_strip() const
94         {
95                 return true;
96         }
97         
98         virtual void add( Control & control );
99         
100         /// This is the index of the strip. zero-based.
101         int index() const { return _index; }
102         
103         /// This is for Surface only
104         /// index is zero-based
105         void index( int rhs ) { _index = rhs; }
106         
107         Button & solo();
108         Button & recenable();
109         Button & mute();
110         Button & select();
111         Button & vselect();
112         Button & fader_touch();
113         Pot & vpot();
114         Fader & gain();
115         
116         bool has_solo() const { return _solo != 0; }
117         bool has_recenable() const { return _recenable != 0; }
118         bool has_mute() const { return _mute != 0; }
119         bool has_select() const { return _select != 0; }
120         bool has_vselect() const { return _vselect != 0; }
121         bool has_fader_touch() const { return _fader_touch != 0; }
122         bool has_vpot() const { return _vpot != 0; }
123         bool has_gain() const { return _gain != 0; }
124         
125 private:
126         Button * _solo;
127         Button * _recenable;
128         Button * _mute;
129         Button * _select;
130         Button * _vselect;
131         Button * _fader_touch;
132         Pot * _vpot;
133         Fader * _gain;
134         int _index;
135 };
136
137 std::ostream & operator << ( std::ostream &, const Strip & );
138
139 class MasterStrip : public Strip
140 {
141 public:
142         MasterStrip( const std::string & name, int index )
143         : Strip( name, index )
144         {
145         }
146         
147         virtual bool is_master() const
148         {
149                 return true;
150         }
151 };
152
153 class Led;
154
155 /**
156         The base class for controls on the surface. They deliberately
157         don't know the midi protocol for updating them.
158 */
159 class Control
160 {
161 public:
162         enum type_t { type_led, type_led_ring, type_fader = 0xe0, type_button = 0x90, type_pot = 0xb0 };
163         
164         Control( int id, int ordinal, std::string name, Group & group );
165         virtual ~Control() {}
166         
167         virtual const Led & led() const
168         {
169                 throw MackieControlException( "no led available" );
170         }
171
172         /// type() << 8 + midi id of the control. This
173         /// provides a unique id for any control on the surface.
174         int id() const
175         {
176                 return ( type() << 8 ) + _id;
177         }
178         
179         /// the value of the second bytes of the message. It's
180         /// the id of the control, but only guaranteed to be
181         /// unique within the control type.
182         int raw_id() const { return _id; }
183         
184         /// The 1-based number of the control
185         int ordinal() const { return _ordinal; }
186         
187         const std::string & name() const
188         {
189                 return _name;
190         }
191         
192         const Group & group() const
193         {
194                 return _group;
195         }
196         
197         const Strip & strip() const
198         {
199                 return dynamic_cast<const Strip&>( _group );
200         }
201         
202         Strip & strip()
203         {
204                 return dynamic_cast<Strip&>( _group );
205         }
206         
207         virtual bool accepts_feedback() const
208         {
209                 return true;
210         }
211         
212         virtual type_t type() const = 0;
213         
214         /// Return true if this control is the one and only Jog Wheel
215         virtual bool is_jog() const { return false; }
216
217         /**
218                 Return true if the controlis in use, or false otherwise. For buttons
219                 this returns true if the button is currently being held down. For
220                 faders, the touch button has not been released. For pots, this returns
221                 true from the first move event until a timeout after the last move event.
222         */
223         virtual bool in_use() const;
224         virtual Control & in_use( bool );
225         
226         /// The timeout value for this control. Normally defaulted to 250ms, but
227         /// certain controls (ie jog wheel) may want to override it.
228         virtual unsigned int in_use_timeout() { return _in_use_timeout; }
229
230         /// Keep track of the timeout so it can be updated with more incoming events
231         sigc::connection in_use_connection;
232         
233 private:
234         int _id;
235         int _ordinal;
236         std::string _name;
237         Group & _group;
238         bool _in_use;
239         unsigned int _in_use_timeout;
240 };
241
242 std::ostream & operator << ( std::ostream & os, const Control & control );
243
244 class Fader : public Control
245 {
246 public:
247         Fader( int id, int ordinal, std::string name, Group & group )
248         : Control( id, ordinal, name, group )
249         {
250         }
251         
252         virtual type_t type() const { return type_fader; }
253 };
254
255 class Led : public Control
256 {
257 public:
258         Led( int id, int ordinal, std::string name, Group & group )
259         : Control( id, ordinal, name, group )
260         {
261         }
262         
263         virtual const Led & led() const { return *this; }
264
265         virtual type_t type() const { return type_led; }
266 };
267
268 class Button : public Control
269 {
270 public:
271         Button( int id, int ordinal, std::string name, Group & group )
272         : Control( id, ordinal, name, group )
273         , _led( id, ordinal, name + "_led", group )
274         {
275         }
276         
277         virtual const Led & led() const
278         {
279                 return _led;
280         }
281         
282         virtual type_t type() const { return type_button; };
283         
284 private:
285         Led _led;
286 };
287
288 class LedRing : public Led
289 {
290 public:
291         LedRing( int id, int ordinal, std::string name, Group & group )
292         : Led( id, ordinal, name, group )
293         {
294         }
295
296         virtual type_t type() const { return type_led_ring; }
297 };
298
299 class Pot : public Control
300 {
301 public:
302         Pot( int id, int ordinal, std::string name, Group & group )
303         : Control( id, ordinal, name, group )
304         , _led_ring( id, ordinal, name + "_ring", group )
305         {
306         }
307
308         virtual type_t type() const { return type_pot; }
309
310         virtual const LedRing & led_ring() const
311         {
312                 return _led_ring;
313         }
314
315 private:
316         LedRing _led_ring;
317 };
318
319 class Jog : public Pot
320 {
321 public:
322         Jog( int id, int ordinal, std::string name, Group & group )
323         : Pot( id, ordinal, name, group )
324         {
325         }
326
327         virtual bool is_jog() const { return true; }
328 };
329
330 }
331
332 #endif