f37bf8e92d0bd7e01cf6c80d6371fbc9d752590f
[ardour.git] / libs / surfaces / mackie / controls.cc
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
19 #include <iostream>
20 #include <iomanip>
21 #include <sstream>
22
23 #include "controls.h"
24 #include "types.h"
25 #include "mackie_midi_builder.h"
26 #include "surface.h"
27
28 using namespace Mackie;
29 using namespace std;
30
31 void Group::add (Control& control)
32 {
33         _controls.push_back (&control);
34 }
35
36 Strip::Strip (const std::string& name, int index)
37         : Group (name)
38         , _solo (0)
39         , _recenable (0)
40         , _mute (0)
41         , _select (0)
42         , _vselect (0)
43         , _fader_touch (0)
44         , _vpot (0)
45         , _gain (0)
46         , _index (index)
47 {
48         /* master strip only */
49 }
50
51 Strip::Strip (Surface& surface, const std::string& name, int index, int unit_index, StripControlDefinition* ctls)
52         : Group (name)
53         , _solo (0)
54         , _recenable (0)
55         , _mute (0)
56         , _select (0)
57         , _vselect (0)
58         , _fader_touch (0)
59         , _vpot (0)
60         , _gain (0)
61         , _index (index)
62 {
63         /* build the controls for this track, which will automatically add them
64            to the Group 
65         */
66
67         for (uint32_t i = 0; ctls[i].name[0]; ++i) {
68                 ctls[i].factory (surface, ctls[i].base_id + unit_index, unit_index+1, ctls[i].name, *this);
69         }
70 }       
71
72 /**
73         TODO could optimise this to use enum, but it's only
74         called during the protocol class instantiation.
75 */
76 void Strip::add (Control & control)
77 {
78         Group::add (control);
79
80         if  (control.name() == "gain") {
81                 _gain = reinterpret_cast<Fader*>(&control);
82         } else if  (control.name() == "vpot") {
83                 _vpot = reinterpret_cast<Pot*>(&control);
84         } else if  (control.name() == "recenable") {
85                 _recenable = reinterpret_cast<Button*>(&control);
86         } else if  (control.name() == "solo") {
87                 _solo = reinterpret_cast<Button*>(&control);
88         } else if  (control.name() == "mute") {
89                 _mute = reinterpret_cast<Button*>(&control);
90         } else if  (control.name() == "select") {
91                 _select = reinterpret_cast<Button*>(&control);
92         } else if  (control.name() == "vselect") {
93                 _vselect = reinterpret_cast<Button*>(&control);
94         } else if  (control.name() == "fader_touch") {
95                 _fader_touch = reinterpret_cast<Button*>(&control);
96         } else if  (control.type() == Control::type_led || control.type() == Control::type_led_ring) {
97                 // relax
98         } else {
99                 ostringstream os;
100                 os << "Strip::add: unknown control type " << control;
101                 throw MackieControlException (os.str());
102         }
103 }
104
105 Control::Control (int id, int ordinal, std::string name, Group & group)
106         : _id (id)
107         , _ordinal (ordinal)
108         , _name (name)
109         , _group (group)
110         , _in_use (false)
111 {
112 }
113
114 Fader& 
115 Strip::gain()
116 {
117         if  (_gain == 0) {
118                 throw MackieControlException ("gain is null");
119         }
120         return *_gain;
121 }
122
123 Pot& 
124 Strip::vpot()
125 {
126         if  (_vpot == 0) {
127                 throw MackieControlException ("vpot is null");
128         }
129         return *_vpot;
130 }
131
132 Button& 
133 Strip::recenable()
134 {
135         if  (_recenable == 0) {
136                 throw MackieControlException ("recenable is null");
137         }
138         return *_recenable;
139 }
140
141 Button& 
142 Strip::solo()
143 {
144         if  (_solo == 0) {
145                 throw MackieControlException ("solo is null");
146         }
147         return *_solo;
148 }
149 Button& 
150 Strip::mute()
151 {
152         if  (_mute == 0) {
153                 throw MackieControlException ("mute is null");
154         }
155         return *_mute;
156 }
157
158 Button& 
159 Strip::select()
160 {
161         if  (_select == 0) {
162                 throw MackieControlException ("select is null");
163         }
164         return *_select;
165 }
166
167 Button& 
168 Strip::vselect()
169 {
170         if  (_vselect == 0) {
171                 throw MackieControlException ("vselect is null");
172         }
173         return *_vselect;
174 }
175
176 Button& 
177 Strip::fader_touch()
178 {
179         if  (_fader_touch == 0) {
180                 throw MackieControlException ("fader_touch is null");
181         }
182         return *_fader_touch;
183 }
184
185 /** @return true if the control is in use, or false otherwise.
186     Buttons are `in use' when they are held down.
187     Faders with touch support are `in use' when they are being touched.
188     Pots, or faders without touch support, are `in use' from the first move
189     event until a timeout after the last move event.
190 */
191 bool
192 Control::in_use () const
193 {
194         return _in_use;
195 }
196
197 void
198 Control::set_in_use (bool in_use)
199 {
200         _in_use = in_use;
201 }
202
203 ostream & Mackie::operator <<  (ostream & os, const Mackie::Control & control)
204 {
205         os << typeid (control).name();
206         os << " { ";
207         os << "name: " << control.name();
208         os << ", ";
209         os << "id: " << "0x" << setw(4) << setfill('0') << hex << control.id() << setfill(' ');
210         os << ", ";
211         os << "type: " << "0x" << setw(2) << setfill('0') << hex << control.type() << setfill(' ');
212         os << ", ";
213         os << "raw_id: " << "0x" << setw(2) << setfill('0') << hex << control.raw_id() << setfill(' ');
214         os << ", ";
215         os << "ordinal: " << dec << control.ordinal();
216         os << ", ";
217         os << "group: " << control.group().name();
218         os << " }";
219         
220         return os;
221 }
222
223 std::ostream & Mackie::operator <<  (std::ostream & os, const Strip & strip)
224 {
225         os << typeid (strip).name();
226         os << " { ";
227         os << "has_solo: " << boolalpha << strip.has_solo();
228         os << ", ";
229         os << "has_recenable: " << boolalpha << strip.has_recenable();
230         os << ", ";
231         os << "has_mute: " << boolalpha << strip.has_mute();
232         os << ", ";
233         os << "has_select: " << boolalpha << strip.has_select();
234         os << ", ";
235         os << "has_vselect: " << boolalpha << strip.has_vselect();
236         os << ", ";
237         os << "has_fader_touch: " << boolalpha << strip.has_fader_touch();
238         os << ", ";
239         os << "has_vpot: " << boolalpha << strip.has_vpot();
240         os << ", ";
241         os << "has_gain: " << boolalpha << strip.has_gain();
242         os << " }";
243         
244         return os;
245 }
246
247 Control*
248 Button::factory (Surface& surface, int id, int ordinal, const char* name, Group& group)
249 {
250         Button* b = new Button (id, ordinal, name, group);
251         surface.buttons[id] = b;
252         surface.controls.push_back (b);
253         group.add (*b);
254         return b;
255 }
256
257 Control*
258 Fader::factory (Surface& surface, int id, int ordinal, const char* name, Group& group)
259 {
260         Fader* f = new Fader (id, ordinal, name, group);
261         surface.faders[id] = f;
262         surface.controls.push_back (f);
263         group.add (*f);
264         return f;
265 }
266
267 Control*
268 Pot::factory (Surface& surface, int id, int ordinal, const char* name, Group& group)
269 {
270         Pot* p = new Pot (id, ordinal, name, group);
271         surface.pots[id] = p;
272         surface.controls.push_back (p);
273         group.add (*p);
274         return p;
275 }
276
277 Control*
278 Led::factory (Surface& surface, int id, int ordinal, const char* name, Group& group)
279 {
280         Led* l = new Led (id, ordinal, name, group);
281         surface.leds[id] = l;
282         surface.controls.push_back (l);
283         group.add (*l);
284         return l;
285 }
286
287 Control*
288 Jog::factory (Surface& surface, int id, int ordinal, const char* name, Group& group)
289 {
290         Jog* j = new Jog (id, ordinal, name, group);
291         surface.controls.push_back (j);
292         surface.controls_by_name["jog"] = j;
293         group.add (*j);
294         return j;
295 }