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