FaderPort8 updates
[ardour.git] / libs / surfaces / faderport8 / faderport8.h
1 /*
2  * Copyright (C) 2017 Robin Gareus <robin@gareus.org>
3  * Copyright (C) 2015 Paul Davis
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19
20 #ifndef ardour_surface_faderport8_h
21 #define ardour_surface_faderport8_h
22
23 // allow to undo "mute clear", "solo clear"
24 // eventually this should use some libardour mixer history/undo
25 #define FP8_MUTESOLO_UNDO
26
27 #include <list>
28 #include <map>
29 #include <glibmm/threads.h>
30
31 #define ABSTRACT_UI_EXPORTS
32 #include "pbd/abstract_ui.h"
33 #include "pbd/properties.h"
34
35 #include "ardour/types.h"
36 #include "ardour/async_midi_port.h"
37 #include "ardour/midi_port.h"
38
39 #include "control_protocol/control_protocol.h"
40
41 #include "fp8_base.h"
42 #include "fp8_controls.h"
43
44 namespace MIDI {
45         class Parser;
46 }
47
48 namespace ARDOUR {
49         class Bundle;
50         class Session;
51         class Processor;
52         class PluginInsert;
53 }
54
55 namespace ArdourSurface {
56
57 struct FaderPort8Request : public BaseUI::BaseRequestObject
58 {
59         public:
60                 FaderPort8Request () {}
61                 ~FaderPort8Request () {}
62 };
63
64 class FaderPort8 : public FP8Base, public ARDOUR::ControlProtocol, public AbstractUI<FaderPort8Request>
65 {
66 public:
67         FaderPort8 (ARDOUR::Session&);
68         virtual ~FaderPort8();
69
70         int set_active (bool yn);
71
72         /* we probe for a device when our ports are connected. Before that,
73          * there's no way to know if the device exists or not.
74          */
75         static bool  probe() { return true; }
76         static void* request_factory (uint32_t);
77
78         XMLNode& get_state ();
79         int set_state (const XMLNode&, int version);
80
81         /* configuration GUI */
82         bool  has_editor () const { return true; }
83         void* get_gui () const;
84         void  tear_down_gui ();
85         PBD::Signal0<void> ConnectionChange;
86
87         void set_button_action (FP8Controls::ButtonId, bool, std::string const&);
88         std::string get_button_action (FP8Controls::ButtonId, bool);
89         FP8Controls const& control () const { return  _ctrls; }
90
91         int stop ();
92         void do_request (FaderPort8Request*);
93         void thread_init ();
94
95         boost::shared_ptr<ARDOUR::Port> input_port() const { return _input_port; }
96         boost::shared_ptr<ARDOUR::Port> output_port() const { return _output_port; }
97         std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles ();
98
99         size_t tx_midi (std::vector<uint8_t> const&) const;
100
101 private:
102         void close ();
103
104         void start_midi_handling ();
105         void stop_midi_handling ();
106
107         /* I/O Ports */
108         PBD::ScopedConnectionList port_connections;
109         boost::shared_ptr<ARDOUR::AsyncMIDIPort> _input_port;
110         boost::shared_ptr<ARDOUR::AsyncMIDIPort> _output_port;
111         boost::shared_ptr<ARDOUR::Bundle>        _input_bundle;
112         boost::shared_ptr<ARDOUR::Bundle>        _output_bundle;
113
114         bool midi_input_handler (Glib::IOCondition ioc, boost::weak_ptr<ARDOUR::AsyncMIDIPort> port);
115
116         bool connection_handler (std::string name1, std::string name2);
117         void engine_reset ();
118
119         enum ConnectionState {
120                 InputConnected = 0x1,
121                 OutputConnected = 0x2
122         };
123
124         void connected ();
125         void disconnected ();
126         int  _connection_state;
127         bool _device_active;
128
129         /* MIDI input message handling */
130         void sysex_handler (MIDI::Parser &p, MIDI::byte *, size_t);
131         void polypressure_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb);
132         void pitchbend_handler (MIDI::Parser &, uint8_t chan, MIDI::pitchbend_t pb);
133         void controller_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb);
134         void note_on_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb);
135         void note_off_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb);
136         PBD::ScopedConnectionList midi_connections;
137
138         /* ***************************************************************************
139          * Control Elements
140          */
141         FP8Controls _ctrls;
142         void notify_stripable_added_or_removed ();
143         void notify_fader_mode_changed ();
144         void filter_stripables (ARDOUR::StripableList& strips) const;
145         void assign_stripables (bool select_only = false);
146         void set_periodic_display_mode (FP8Strip::DisplayMode);
147
148         void assign_strips (bool reset_bank);
149         void bank (bool down, bool page);
150         void move_selected_into_view ();
151         void select_prev_next (bool next);
152
153         void assign_sends ();
154         void spill_plugins ();
155         void assign_processor_ctrls ();
156         void build_well_known_processor_ctrls (boost::shared_ptr<ARDOUR::Stripable>, bool);
157         void select_plugin (int num);
158
159         void bank_param (bool down, bool page);
160         /* bank offsets */
161         int _channel_off;
162         int _plugin_off;
163         int _parameter_off;
164
165         /* plugin + send mode stripable
166          *
167          * This is used when parameters of one strip are assigned to
168          * individual FP8Strip controls (Edit Send, Edit Plugins).
169          *
170          * When there's one stripable per FP8Strip, FP8Strip itself keeps
171          * track of the object lifetime and these are NULL.
172          */
173         PBD::ScopedConnectionList processor_connections;
174
175         PBD::ScopedConnectionList assigned_stripable_connections;
176         typedef std::map<boost::shared_ptr<ARDOUR::Stripable>, uint8_t> StripAssignmentMap;
177         StripAssignmentMap _assigned_strips;
178
179         void drop_ctrl_connections ();
180
181         void select_strip (boost::weak_ptr<ARDOUR::Stripable>);
182
183         void notify_pi_property_changed (const PBD::PropertyChange&);
184         void notify_stripable_property_changed (boost::weak_ptr<ARDOUR::Stripable>, const PBD::PropertyChange&);
185         void stripable_selection_changed ();
186
187         PBD::ScopedConnection selection_connection;
188         PBD::ScopedConnectionList automation_state_connections;
189         PBD::ScopedConnectionList modechange_connections;
190         /* **************************************************************************/
191         struct ProcessorCtrl {
192                 ProcessorCtrl (std::string const &n, boost::shared_ptr<ARDOUR::AutomationControl> c)
193                  : name (n)
194                  , ac (c)
195                 {}
196                 std::string name;
197                 boost::shared_ptr<ARDOUR::AutomationControl> ac;
198         };
199         std::list <ProcessorCtrl> _proc_params;
200         boost::weak_ptr<ARDOUR::PluginInsert> _plugin_insert;
201         int _showing_well_known;
202         /* **************************************************************************/
203
204         /* periodic updates, parameter poll */
205         sigc::connection _periodic_connection;
206         bool periodic ();
207         std::string _timecode;
208         std::string const& timecode () const { return _timecode; }
209
210         /* sync button blink -- the FP's blink mode does not work */
211         sigc::connection _blink_connection;
212         bool _blink_onoff;
213         bool blink_it ();
214
215         /* shift key */
216         sigc::connection _shift_connection;
217         bool _shift_lock;
218         int _shift_pressed;
219         bool shift_timeout () { _shift_lock = true; return false; }
220         bool shift_mod () const { return _shift_lock || (_shift_pressed > 0); }
221
222         /* GUI */
223         void build_gui ();
224         mutable void *gui;
225
226         /* setup callbacks & actions */
227         void connect_session_signals ();
228         void setup_actions ();
229         void send_session_state ();
230
231         /* callbacks */
232         PBD::ScopedConnectionList session_connections;
233         void notify_parameter_changed (std::string);
234         void notify_record_state_changed ();
235         void notify_transport_state_changed ();
236         void notify_loop_state_changed ();
237         void notify_snap_change ();
238         void notify_session_dirty_changed ();
239         void notify_history_changed ();
240         void notify_solo_changed ();
241         void notify_mute_changed ();
242         void notify_automation_mode_changed ();
243         void notify_plugin_active_changed ();
244
245         /* actions */
246         PBD::ScopedConnectionList button_connections;
247         void button_play ();
248         void button_stop ();
249         void button_record ();
250         void button_loop ();
251         void button_metronom ();
252         void button_bypass ();
253         void button_varispeed (bool);
254 #ifdef FP8_MUTESOLO_UNDO
255         void button_solo_clear ();
256 #endif
257         void button_mute_clear ();
258         void button_arm (bool);
259         void button_arm_all ();
260         void button_automation (ARDOUR::AutoState);
261         void button_prev_next (bool);
262         void button_action (const std::string& group, const std::string& item);
263
264         void button_encoder ();
265         void button_parameter ();
266         void encoder_navigate (bool, int);
267         void encoder_parameter (bool, int);
268
269         /* mute undo history */
270 #ifdef FP8_MUTESOLO_UNDO
271         std::vector <boost::weak_ptr<ARDOUR::AutomationControl> > _mute_state;
272         std::vector <boost::weak_ptr<ARDOUR::AutomationControl> > _solo_state;
273 #endif
274
275         /* user bound actions */
276         void button_user (bool, FP8Controls::ButtonId);
277
278         enum ActionType {
279                 Unset,
280                 NamedAction,
281                 // InternalFunction, // unused
282         };
283
284         struct UserAction {
285                 UserAction () : _type (Unset) {}
286
287                 ActionType _type;
288                 std::string _action_name;
289                 //boost::function<void()> function; // unused
290
291                 void clear ()
292                 {
293                         _type = Unset;
294                         _action_name.clear();
295                 }
296
297                 void assign_action (std::string const& action_name)
298                 {
299                         if (action_name.empty ()) {
300                                 _type = Unset;
301                                 _action_name.clear();
302                         } else {
303                                 _type = NamedAction;
304                                 _action_name = action_name;
305                         }
306                 }
307
308                 bool empty () const
309                 {
310                         return _type == Unset;
311                 }
312
313                 void call (FaderPort8& _base) const
314                 {
315                         switch (_type) {
316                                 case NamedAction:
317                                         _base.access_action (_action_name);
318                                         break;
319                                 default:
320                                         break;
321                         }
322                 }
323         };
324
325         struct ButtonAction {
326                 UserAction on_press;
327                 UserAction on_release;
328
329                 UserAction& action (bool press)
330                 {
331                         return press ? on_press : on_release;
332                 }
333
334                 UserAction const& action (bool press) const
335                 {
336                         return press ? on_press : on_release;
337                 }
338
339                 void call (FaderPort8& _base, bool press) const
340                 {
341                         action (press).call (_base);
342                 }
343                 bool empty () const
344                 {
345                         return on_press.empty () && on_release.empty();
346                 }
347         };
348
349         typedef std::map<FP8Controls::ButtonId, ButtonAction> UserActionMap;
350         UserActionMap _user_action_map;
351 };
352
353 } /* namespace */
354
355 #endif /* ardour_surface_faderport8_h */