remove unused member
[ardour.git] / libs / surfaces / faderport8 / fp8_controls.cc
1 /*
2  * Copyright (C) 2017-2018 Robin Gareus <robin@gareus.org>
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 along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 #include "fp8_controls.h"
20
21 using namespace ArdourSurface::FP_NAMESPACE;
22 using namespace ArdourSurface::FP_NAMESPACE::FP8Types;
23
24 bool FP8ButtonInterface::force_change = false;
25
26 #define NEWBUTTON(midi_id, button_id, color)            \
27   do {                                                  \
28   assert (_midimap.end() == _midimap.find (midi_id));   \
29   assert (_ctrlmap.end() == _ctrlmap.find (button_id)); \
30   FP8Button *t = new FP8Button (b, midi_id);            \
31   _midimap[midi_id] = t;                                \
32   _ctrlmap[button_id] = t;                              \
33   } while (0)
34
35
36 #define NEWTYPEBUTTON(TYPE, midi_id, button_id, color)  \
37   do {                                                  \
38   assert (_midimap.end() == _midimap.find (midi_id));   \
39   assert (_ctrlmap.end() == _ctrlmap.find (button_id)); \
40   TYPE *t = new TYPE (b, midi_id);                      \
41   _midimap[midi_id] = t;                                \
42   _ctrlmap[button_id] = t;                              \
43   } while (0)
44
45
46
47 #define NEWSHIFTBUTTON(midi_id, id1, id2, color)        \
48   do {                                                  \
49   assert (_midimap.end() == _midimap.find (midi_id));   \
50   assert (_ctrlmap.end() == _ctrlmap.find (id1));       \
51   assert (_ctrlmap.end() == _ctrlmap.find (id2));       \
52   FP8ShiftSensitiveButton *t =                          \
53     new FP8ShiftSensitiveButton (b, midi_id, color);    \
54   _midimap[midi_id] = t;                                \
55   _ctrlmap[id1] = t->button ();                         \
56   _ctrlmap[id2] = t->button_shift ();                   \
57   } while (0)
58
59
60 FP8Controls::FP8Controls (FP8Base& b)
61         : _fadermode (ModeTrack)
62 #ifdef FADERPORT2
63         , _navmode (NavScroll)
64 #else
65         , _navmode (NavMaster)
66 #endif
67         , _mixmode (MixAll)
68         , _display_timecode (false)
69 {
70         NEWBUTTON (0x56, BtnLoop, false);
71         NEWTYPEBUTTON (FP8RepeatButton, 0x5b, BtnRewind, false);
72         NEWTYPEBUTTON (FP8RepeatButton, 0x5c, BtnFastForward, false);
73         NEWBUTTON (0x5d, BtnStop, false);
74         NEWBUTTON (0x5e, BtnPlay, false);
75         NEWBUTTON (0x5f, BtnRecord, false);
76
77 #ifdef FADERPORT2
78
79         NEWSHIFTBUTTON (0x4a, BtnARead, BtnAOff, true);
80         NEWSHIFTBUTTON (0x4b, BtnAWrite, BtnATrim, true);
81         NEWSHIFTBUTTON (0x4d, BtnATouch, BtnALatch, true);
82
83         NEWSHIFTBUTTON (0x2e, BtnPrev, BtnUndo, false);
84         NEWSHIFTBUTTON (0x2f, BtnNext, BtnRedo, false);
85
86         NEWSHIFTBUTTON (0x2a, BtnPan, BtnFlip, true);  //TODO: Flip Pan knob to fader ...?
87
88         NEWSHIFTBUTTON (0x36, BtnChannel, BtnChanLock, true);
89
90         NEWSHIFTBUTTON (0x38, BtnScroll,  BtnZoom, true);
91
92         NEWSHIFTBUTTON (0x3a, BtnMaster,  BtnF1, false);
93         NEWSHIFTBUTTON (0x3b, BtnClick,   BtnF2, false);
94         NEWSHIFTBUTTON (0x3c, BtnSection, BtnF3, false);
95         NEWSHIFTBUTTON (0x3d, BtnMarker,  BtnF4, false);
96
97         //these buttons do not exist in FP2, but they need to exist in the ctrlmap:
98         NEWBUTTON (0x71, BtnBank, false);
99         NEWBUTTON (0x72, BtnF5, false);
100         NEWBUTTON (0x73, BtnF6, false);
101         NEWBUTTON (0x74, BtnF7, false);
102         NEWBUTTON (0x75, BtnF8, false);
103         NEWBUTTON (0x76, BtnUser1, false);
104         NEWBUTTON (0x77, BtnUser2, false);
105         NEWBUTTON (0x78, BtnUser3, false);
106         NEWBUTTON (0x79, BtnSave, false);
107
108 #else
109         NEWSHIFTBUTTON (0x4a, BtnARead, BtnUser3, true);
110         NEWSHIFTBUTTON (0x4b, BtnAWrite, BtnUser2, true);
111         NEWSHIFTBUTTON (0x4c, BtnATrim, BtnRedo, true);
112         NEWSHIFTBUTTON (0x4d, BtnATouch, BtnUser1, true);
113         NEWSHIFTBUTTON (0x4e, BtnALatch, BtnSave, true);
114         NEWSHIFTBUTTON (0x4f, BtnAOff, BtnUndo, true);
115
116         NEWBUTTON (0x2e, BtnPrev, false);
117         NEWBUTTON (0x2f, BtnNext, false);
118
119         NEWSHIFTBUTTON (0x36, BtnChannel, BtnF1, false);
120         NEWSHIFTBUTTON (0x37, BtnZoom,    BtnF2, false);
121         NEWSHIFTBUTTON (0x38, BtnScroll,  BtnF3, false);
122         NEWSHIFTBUTTON (0x39, BtnBank,    BtnF4, false);
123         NEWSHIFTBUTTON (0x3a, BtnMaster,  BtnF5, false);
124         NEWSHIFTBUTTON (0x3b, BtnClick,   BtnF6, false);
125         NEWSHIFTBUTTON (0x3c, BtnSection, BtnF7, false);
126         NEWSHIFTBUTTON (0x3d, BtnMarker,  BtnF8, false);
127
128         NEWBUTTON (0x2a, BtnPan, false);
129 #endif
130
131         NEWSHIFTBUTTON (0x28, BtnTrack, BtnTimecode, false);
132         NEWBUTTON (0x2b, BtnPlugins, false);
133         NEWBUTTON (0x29, BtnSend, false);
134
135         NEWSHIFTBUTTON (0x00, BtnArm, BtnArmAll, false);
136         NEWBUTTON (0x01, BtnSoloClear, false);
137         NEWBUTTON (0x02, BtnMuteClear, false);
138
139         NEWSHIFTBUTTON (0x03, BtnBypass, BtnBypassAll, true);
140         NEWSHIFTBUTTON (0x04, BtnMacro, BtnOpen, true);
141         NEWSHIFTBUTTON (0x05, BtnLink, BtnLock, true);
142
143         NEWSHIFTBUTTON (0x3e, BtnMAudio, BtnMInputs, true);
144         NEWSHIFTBUTTON (0x3f, BtnMVI, BtnMMIDI, true);
145         NEWSHIFTBUTTON (0x40, BtnMBus, BtnMOutputs, true);
146         NEWSHIFTBUTTON (0x41, BtnMVCA, BtnMFX, true);
147         NEWSHIFTBUTTON (0x42, BtnMAll, BtnMUser, true);
148
149         NEWTYPEBUTTON (FP8ReadOnlyButton, 0x53, BtnEncoder, false);
150         NEWTYPEBUTTON (FP8ReadOnlyButton, 0x20, BtnParam, false);
151         NEWTYPEBUTTON (FP8ReadOnlyButton, 0x66, BtnFootswitch, false);
152
153         /* internal bindings */
154
155 #define BindMethod(ID, CB) \
156         button (ID).released.connect_same_thread (button_connections, boost::bind (&FP8Controls:: CB, this));
157
158         BindMethod (FP8Controls::BtnTimecode, toggle_timecode);
159
160 #define BindNav(BTN, MODE)\
161         button (BTN).released.connect_same_thread (button_connections, boost::bind (&FP8Controls::set_nav_mode, this, MODE))
162
163         BindNav (BtnChannel, NavChannel);
164         BindNav (BtnZoom,    NavZoom);
165         BindNav (BtnScroll,  NavScroll);
166         BindNav (BtnBank,    NavBank);
167         BindNav (BtnMaster,  NavMaster);
168         BindNav (BtnSection, NavSection);
169         BindNav (BtnMarker,  NavMarker);
170 #ifdef FADERPORT2
171         BindNav (BtnPan,     NavPan);
172 #endif
173
174 #define BindFader(BTN, MODE)\
175         button (BTN).released.connect_same_thread (button_connections, boost::bind (&FP8Controls::set_fader_mode, this, MODE))
176
177         BindFader (BtnTrack,   ModeTrack);
178         BindFader (BtnPlugins, ModePlugins);
179         BindFader (BtnSend,    ModeSend);
180 #ifndef FADERPORT2
181         BindFader (BtnPan,     ModePan);
182 #endif
183
184
185 #define BindMix(BTN, MODE)\
186         button (BTN).released.connect_same_thread (button_connections, boost::bind (&FP8Controls::set_mix_mode, this, MODE))
187
188         BindMix (BtnMAudio,   MixAudio);
189         BindMix (BtnMVI,      MixInstrument);
190         BindMix (BtnMBus,     MixBus);
191         BindMix (BtnMVCA,     MixVCA);
192         BindMix (BtnMAll,     MixAll);
193         BindMix (BtnMInputs,  MixInputs);
194         BindMix (BtnMMIDI,    MixMIDI);
195         BindMix (BtnMOutputs, MixOutputs);
196         BindMix (BtnMFX,      MixFX);
197         BindMix (BtnMUser,    MixUser);
198
199         /* create channelstrips */
200         for (uint8_t id = 0; id < N_STRIPS; ++id) {
201                 chanstrip[id] = new FP8Strip (b, id);
202                 _midimap_strip[FP8Strip::midi_ctrl_id (FP8Strip::BtnSolo, id)] = &(chanstrip[id]->solo_button());
203                 _midimap_strip[FP8Strip::midi_ctrl_id (FP8Strip::BtnMute, id)] = &(chanstrip[id]->mute_button());
204                 _midimap_strip[FP8Strip::midi_ctrl_id (FP8Strip::BtnSelect, id)] = &(chanstrip[id]->selrec_button());
205         }
206
207         /* set User button names */
208
209 #define REGISTER_ENUM(ID, NAME) \
210         _user_str_to_enum[#ID] = ID; \
211         _user_enum_to_str[ID]  = #ID; \
212         _user_buttons[ID]      = NAME;
213
214 #ifdef FADERPORT2
215         REGISTER_ENUM (BtnF1        , "F1");
216         REGISTER_ENUM (BtnF2        , "F2");
217         REGISTER_ENUM (BtnF3        , "F3");
218         REGISTER_ENUM (BtnF4        , "F4");
219         REGISTER_ENUM (BtnFootswitch, "Footswitch");
220 #else
221         REGISTER_ENUM (BtnFootswitch, "Footswitch");
222         REGISTER_ENUM (BtnUser1     , "User 1");
223         REGISTER_ENUM (BtnUser2     , "User 2");
224         REGISTER_ENUM (BtnUser3     , "User 3");
225         REGISTER_ENUM (BtnF1        , "F1");
226         REGISTER_ENUM (BtnF2        , "F2");
227         REGISTER_ENUM (BtnF3        , "F3");
228         REGISTER_ENUM (BtnF4        , "F4");
229         REGISTER_ENUM (BtnF5        , "F5");
230         REGISTER_ENUM (BtnF6        , "F6");
231         REGISTER_ENUM (BtnF7        , "F7");
232         REGISTER_ENUM (BtnF8        , "F8");
233 #endif
234
235 #undef REGISTER_ENUM
236 }
237
238 FP8Controls::~FP8Controls ()
239 {
240         for (MidiButtonMap::const_iterator i = _midimap.begin (); i != _midimap.end (); ++i) {
241                 delete i->second;
242         }
243         for (uint8_t id = 0; id < N_STRIPS; ++id) {
244                 delete chanstrip[id];
245         }
246         _midimap_strip.clear ();
247         _ctrlmap.clear ();
248         _midimap.clear ();
249 }
250
251 bool
252 FP8Controls::button_name_to_enum (std::string const& n, ButtonId& id) const
253 {
254         std::map<std::string, ButtonId>::const_iterator i = _user_str_to_enum.find (n);
255         if (i == _user_str_to_enum.end()) {
256                 return false;
257         }
258         id = i->second;
259         return true;
260 }
261
262 bool
263 FP8Controls::button_enum_to_name (ButtonId id, std::string& n) const
264 {
265         std::map<ButtonId, std::string>::const_iterator i = _user_enum_to_str.find (id);
266         if (i == _user_enum_to_str.end()) {
267                 return false;
268         }
269         n = i->second;
270         return true;
271 }
272
273 void
274 FP8Controls::initialize ()
275 {
276         FP8ButtonInterface::force_change = true;
277         /* set RGB colors */
278         button (BtnUndo).set_color (0x00ff00ff);
279         button (BtnRedo).set_color (0x00ff00ff);
280
281         button (BtnAOff).set_color (0xffffffff);
282         button (BtnATrim).set_color (0x000030ff);
283         button (BtnARead).set_color (0x00ff00ff);
284         button (BtnAWrite).set_color (0xff0000ff);
285         button (BtnATouch).set_color (0xff8800ff);
286         button (BtnALatch).set_color (0xffff00ff);
287
288         button (BtnUser1).set_color (0x0000ffff);
289         button (BtnUser2).set_color (0x0000ffff);
290         button (BtnUser3).set_color (0x0000ffff);
291
292         button (BtnBypass).set_color (0x888888ff);
293         button (BtnBypassAll).set_color (0xffffffff);
294
295         button (BtnMacro).set_color (0x888888ff);
296         button (BtnOpen).set_color (0xffffffff);
297
298         button (BtnLink).set_color (0x888888ff);
299         button (BtnLock).set_color (0xffffffff);
300
301         button (BtnMAudio).set_color (0x0000ffff);
302         button (BtnMVI).set_color (0x0000ffff);
303         button (BtnMBus).set_color (0x0000ffff);
304         button (BtnMVCA).set_color (0x0000ffff);
305         button (BtnMAll).set_color (0x0000ffff);
306
307         button (BtnMInputs).set_color (0x0000ffff);
308         button (BtnMMIDI).set_color (0x0000ffff);
309         button (BtnMOutputs).set_color (0x0000ffff);
310         button (BtnMFX).set_color (0x0000ffff);
311         button (BtnMUser).set_color (0x0000ffff);
312
313 #ifdef FADERPORT2
314         /* encoder mode-switches are orange, to match the Master switch physical color */
315         button (BtnLink).set_color (0x000000ff);
316         button (BtnChannel).set_color (0x0000ffff);
317         button (BtnScroll).set_color (0x0000ffff);
318         button (BtnPan).set_color (0xffffffff);
319 #endif
320
321         for (uint8_t id = 0; id < N_STRIPS; ++id) {
322                 chanstrip[id]->initialize ();
323         }
324
325         /* initally turn all lights off */
326         all_lights_off ();
327
328         /* default modes */
329 #ifdef FADERPORT2
330         button (BtnScroll).set_active (true);
331 #else
332         button (BtnMaster).set_active (true);
333 #endif
334         button (BtnTrack).set_active (true);
335         button (BtnMAll).set_active (true);
336         button (BtnTimecode).set_active (_display_timecode);
337
338         FP8ButtonInterface::force_change = false;
339 }
340
341 void
342 FP8Controls::all_lights_off () const
343 {
344         for (CtrlButtonMap::const_iterator i = _ctrlmap.begin (); i != _ctrlmap.end (); ++i) {
345                 i->second->set_active (false);
346         }
347 }
348
349 FP8ButtonInterface&
350 FP8Controls::button (ButtonId id)
351 {
352         CtrlButtonMap::const_iterator i = _ctrlmap.find (id);
353         if (i == _ctrlmap.end()) {
354                 assert (0);
355                 return _dummy_button;
356         }
357         return *(i->second);
358 }
359
360 FP8Strip&
361 FP8Controls::strip (uint8_t id)
362 {
363         assert (id < N_STRIPS);
364         return *chanstrip[id];
365 }
366
367 /* *****************************************************************************
368  * Delegate MIDI events
369  */
370
371 bool
372 FP8Controls::midi_event (uint8_t id, uint8_t val)
373 {
374         MidiButtonMap::const_iterator i;
375
376         i = _midimap_strip.find (id);
377         if (i != _midimap_strip.end()) {
378                 return i->second->midi_event (val > 0x40);
379         }
380
381         i = _midimap.find (id);
382         if (i != _midimap.end()) {
383                 return i->second->midi_event (val > 0x40);
384         }
385         return false;
386 }
387
388 bool
389 FP8Controls::midi_touch (uint8_t id, uint8_t val)
390 {
391         assert (id < N_STRIPS);
392         return chanstrip[id]->midi_touch (val > 0x40);
393 }
394
395 bool
396 FP8Controls::midi_fader (uint8_t id, unsigned short val)
397 {
398         assert (id < N_STRIPS);
399         return chanstrip[id]->midi_fader ((val >> 4) / 1023.f);
400 }
401
402 /* *****************************************************************************
403  * Internal Model + View for Modes
404  */
405
406 void
407 FP8Controls::set_nav_mode (NavigationMode m)
408 {
409         if (_navmode == m) {
410                 return;
411         }
412         // TODO add special-cases:
413         // - master/monitor (blink when button is held + monitor section present)
414         // - "click" hold -> encoder sets click volume, encoder-press toggle rec-only-metro
415         button (BtnChannel).set_active (m == NavChannel);
416         button (BtnZoom).set_active (m == NavZoom);
417         button (BtnScroll).set_active (m == NavScroll);
418         button (BtnBank).set_active (m == NavBank);
419         button (BtnMaster).set_active (m == NavMaster);
420         button (BtnSection).set_active (m == NavSection);
421         button (BtnMarker).set_active (m == NavMarker);
422 #ifdef FADERPORT2
423         button (BtnPan).set_active (m == NavPan);
424 #endif
425         _navmode = m;
426 }
427
428 void
429 FP8Controls::set_fader_mode (FaderMode m)
430 {
431         if (_fadermode == m) {
432                 if (m == ModePlugins || m == ModeSend) {
433                         /* "Edit Plugins" while editing Plugin-params, returns back
434                          * to plugin selection.
435                          * "Sends" button banks through sends.
436                          */
437                         FaderModeChanged ();
438                 }
439                 return;
440         }
441         // set lights
442         button (BtnTrack).set_active (m == ModeTrack);
443         button (BtnPlugins).set_active (m == ModePlugins);
444         button (BtnSend).set_active (m == ModeSend);
445         button (BtnPan).set_active (m == ModePan);
446         _fadermode = m;
447         FaderModeChanged ();
448 }
449
450 void
451 FP8Controls::set_mix_mode (MixMode m)
452 {
453         if (_mixmode == m) {
454                 if (m == MixUser || m == MixInputs) {
455                         /* always re-assign:
456                          *  - MixUser: depends on selection
457                          *  - MixInputs: depends on rec-arm
458                          */
459                         MixModeChanged ();
460                 }
461                 return;
462         }
463         button (BtnMAudio).set_active (m == MixAudio);
464         button (BtnMVI).set_active (m == MixInstrument);
465         button (BtnMBus).set_active (m == MixBus);
466         button (BtnMVCA).set_active (m == MixVCA);
467         button (BtnMAll).set_active (m == MixAll);
468         button (BtnMInputs).set_active (m == MixInputs);
469         button (BtnMMIDI).set_active (m == MixMIDI);
470         button (BtnMOutputs).set_active (m == MixOutputs);
471         button (BtnMFX).set_active (m == MixFX);
472         button (BtnMUser).set_active (m == MixUser);
473
474         _mixmode = m;
475         MixModeChanged ();
476 }
477
478 void
479 FP8Controls::toggle_timecode ()
480 {
481         _display_timecode = !_display_timecode;
482         button (BtnTimecode).set_active (_display_timecode);
483 }