MCP: add debug tracing for timeouts
[ardour.git] / libs / surfaces / mackie / mackie_control_protocol.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
19 #ifndef ardour_mackie_control_protocol_h
20 #define ardour_mackie_control_protocol_h
21
22 #include <vector>
23
24 #include <sys/time.h>
25 #include <pthread.h>
26
27 #include <glibmm/thread.h>
28
29 #include "pbd/abstract_ui.h"
30
31 #include "ardour/types.h"
32 #include "ardour/midi_ui.h"
33 #include "midi++/types.h"
34
35 #include "control_protocol/control_protocol.h"
36 #include "midi_byte_array.h"
37 #include "controls.h"
38 #include "dummy_port.h"
39 #include "route_signal.h"
40 #include "mackie_button_handler.h"
41 #include "mackie_port.h"
42 #include "mackie_jog_wheel.h"
43 #include "timer.h"
44
45 namespace MIDI {
46         class Port;
47 }
48
49 namespace Mackie {
50         class Surface;
51         class Control;
52         class SurfacePort;
53 }
54
55 /**
56         This handles the plugin duties, and the midi encoding and decoding,
57         and the signal callbacks, mostly from ARDOUR::Route.
58
59         The model of the control surface is handled by classes in controls.h
60
61         What happens is that each strip on the control surface has
62         a corresponding route in ControlProtocol::route_table. When
63         an incoming midi message is signaled, the correct route
64         is looked up, and the relevant changes made to it.
65
66         For each route currently in route_table, there's a RouteSignal object
67         which encapsulates the signals that indicate that there are changes
68         to be sent to the surface. The signals are handled by this class.
69
70         Calls to signal handlers pass a Route object which is used to look
71         up the relevant Strip in Surface. Then the state is retrieved from
72         the Route and encoded as the correct midi message.
73 */
74
75 struct MackieControlUIRequest : public BaseUI::BaseRequestObject {
76 public:
77         MackieControlUIRequest () {}
78         ~MackieControlUIRequest () {}
79 };
80
81 class MackieControlProtocol 
82         : public ARDOUR::ControlProtocol
83         , public AbstractUI<MackieControlUIRequest>
84         , public Mackie::MackieButtonHandler
85 {
86   public:
87         MackieControlProtocol(ARDOUR::Session &);
88         virtual ~MackieControlProtocol();
89
90         int set_active (bool yn);
91
92         XMLNode& get_state ();
93         int set_state (const XMLNode&, int version);
94   
95         static bool probe();
96         
97         Mackie::Surface & surface();
98
99         std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles ();
100
101         bool has_editor () const { return true; }
102         void* get_gui () const;
103         void tear_down_gui ();
104         
105         // control events
106         void handle_control_event (Mackie::SurfacePort & port, Mackie::Control & control, const Mackie::ControlState & state);
107
108         // strip/route related stuff
109   public:       
110         void notify_solo_changed (Mackie::RouteSignal *);
111         void notify_mute_changed (Mackie::RouteSignal *);
112         void notify_record_enable_changed (Mackie::RouteSignal *);
113         void notify_gain_changed (Mackie::RouteSignal *, bool force_update = true);
114         void notify_property_changed (const PBD::PropertyChange&, Mackie::RouteSignal *);
115         void notify_panner_changed (Mackie::RouteSignal *, bool force_update = true);
116         void notify_route_added (ARDOUR::RouteList &);
117         void notify_active_changed (Mackie::RouteSignal *);
118  
119         void notify_remote_id_changed();
120
121         /// rebuild the current bank. Called on route added/removed and
122         /// remote id changed.
123         void refresh_current_bank();
124
125   public:
126         // button-related signals
127         void notify_record_state_changed();
128         void notify_transport_state_changed();
129         // mainly to pick up punch-in and punch-out
130         void notify_parameter_changed(std::string const &);
131         void notify_solo_active_changed(bool);
132
133         /// Turn timecode on and beats off, or vice versa, depending
134         /// on state of _timecode_type
135         void update_timecode_beats_led();
136   
137         /// this is called to generate the midi to send in response to a button press.
138         void update_led(Mackie::Button & button, Mackie::LedState);
139   
140         void update_global_button(const std::string & name, Mackie::LedState);
141         void update_global_led(const std::string & name, Mackie::LedState);
142   
143         // transport button handler methods from MackieButtonHandler
144         virtual Mackie::LedState frm_left_press(Mackie::Button &);
145         virtual Mackie::LedState frm_left_release(Mackie::Button &);
146
147         virtual Mackie::LedState frm_right_press(Mackie::Button &);
148         virtual Mackie::LedState frm_right_release(Mackie::Button &);
149
150         virtual Mackie::LedState stop_press(Mackie::Button &);
151         virtual Mackie::LedState stop_release(Mackie::Button &);
152
153         virtual Mackie::LedState play_press(Mackie::Button &);
154         virtual Mackie::LedState play_release(Mackie::Button &);
155
156         virtual Mackie::LedState record_press(Mackie::Button &);
157         virtual Mackie::LedState record_release(Mackie::Button &);
158
159         virtual Mackie::LedState loop_press(Mackie::Button &);
160         virtual Mackie::LedState loop_release(Mackie::Button &);
161
162         virtual Mackie::LedState punch_in_press(Mackie::Button &);
163         virtual Mackie::LedState punch_in_release(Mackie::Button &);
164
165         virtual Mackie::LedState punch_out_press(Mackie::Button &);
166         virtual Mackie::LedState punch_out_release(Mackie::Button &);
167
168         virtual Mackie::LedState home_press(Mackie::Button &);
169         virtual Mackie::LedState home_release(Mackie::Button &);
170
171         virtual Mackie::LedState end_press(Mackie::Button &);
172         virtual Mackie::LedState end_release(Mackie::Button &);
173         
174         virtual Mackie::LedState rewind_press(Mackie::Button & button);
175         virtual Mackie::LedState rewind_release(Mackie::Button & button);
176
177         virtual Mackie::LedState ffwd_press(Mackie::Button & button);
178         virtual Mackie::LedState ffwd_release(Mackie::Button & button);
179
180         // bank switching button handler methods from MackieButtonHandler
181         virtual Mackie::LedState left_press(Mackie::Button &);
182         virtual Mackie::LedState left_release(Mackie::Button &);
183
184         virtual Mackie::LedState right_press(Mackie::Button &);
185         virtual Mackie::LedState right_release(Mackie::Button &);
186
187         virtual Mackie::LedState channel_left_press(Mackie::Button &);
188         virtual Mackie::LedState channel_left_release(Mackie::Button &);
189
190         virtual Mackie::LedState channel_right_press(Mackie::Button &);
191         virtual Mackie::LedState channel_right_release(Mackie::Button &);
192         
193         virtual Mackie::LedState clicking_press(Mackie::Button &);
194         virtual Mackie::LedState clicking_release(Mackie::Button &);
195         
196         virtual Mackie::LedState global_solo_press(Mackie::Button &);
197         virtual Mackie::LedState global_solo_release(Mackie::Button &);
198         
199         // function buttons
200         virtual Mackie::LedState marker_press(Mackie::Button &);
201         virtual Mackie::LedState marker_release(Mackie::Button &);
202
203         virtual Mackie::LedState drop_press(Mackie::Button &);
204         virtual Mackie::LedState drop_release(Mackie::Button &);
205
206         virtual Mackie::LedState save_press(Mackie::Button &);
207         virtual Mackie::LedState save_release(Mackie::Button &);
208
209         virtual Mackie::LedState timecode_beats_press(Mackie::Button &);
210         virtual Mackie::LedState timecode_beats_release(Mackie::Button &);
211
212         // jog wheel states
213         virtual Mackie::LedState zoom_press(Mackie::Button &);
214         virtual Mackie::LedState zoom_release(Mackie::Button &);
215
216         virtual Mackie::LedState scrub_press(Mackie::Button &);
217         virtual Mackie::LedState scrub_release(Mackie::Button &);
218         
219         /// This is the main MCU port, ie not an extender port
220         /// Only for use by JogWheel
221         const Mackie::SurfacePort & mcu_port() const;
222         Mackie::SurfacePort & mcu_port();
223         ARDOUR::Session & get_session() { return *session; }
224  
225         void add_in_use_timeout (Mackie::SurfacePort& port, Mackie::Control& in_use_control, Mackie::Control* touch_control);
226         
227   protected:
228         // create instances of MackiePort, depending on what's found in ardour.rc
229         void create_ports();
230   
231         // shut down the surface
232         void close();
233   
234         // create the Surface object, with the correct number
235         // of strips for the currently connected ports and 
236         // hook up the control event notification
237         void initialize_surface();
238   
239         // This sets up the notifications and sets the
240         // controls to the correct values
241         void update_surface();
242         
243         // connects global (not strip) signals from the Session to here
244         // so the surface can be notified of changes from the other UIs.
245         void connect_session_signals();
246         
247         // set all controls to their zero position
248         void zero_all();
249         
250         /**
251            Fetch the set of routes to be considered for control by the
252            surface. Excluding master, hidden and control routes, and inactive routes
253         */
254         typedef std::vector<boost::shared_ptr<ARDOUR::Route> > Sorted;
255         Sorted get_sorted_routes();
256   
257         // bank switching
258         void switch_banks(int initial);
259         void prev_track();
260         void next_track();
261   
262         // delete all RouteSignal objects connecting Routes to Strips
263         void clear_route_signals();
264         
265         typedef std::vector<Mackie::RouteSignal*> RouteSignals;
266         RouteSignals route_signals;
267         
268         // return which of the ports a particular route_table
269         // index belongs to
270         Mackie::MackiePort & port_for_id(uint32_t index);
271
272         /**
273            Handle a button press for the control and return whether
274            the corresponding light should be on or off.
275         */
276         bool handle_strip_button (Mackie::SurfacePort &, Mackie::Control &, Mackie::ButtonState, boost::shared_ptr<ARDOUR::Route>);
277
278         void add_port (MIDI::Port &, MIDI::Port &, int number, Mackie::MackiePort::port_type_t);
279
280         /**
281            Read session data and send to surface. Includes
282            automation from the currently active routes and
283            timecode displays.
284         */
285         void poll_session_data();
286         
287         // called from poll_automation to figure out which automations need to be sent
288         void update_automation(Mackie::RouteSignal &);
289         
290         // also called from poll_automation to update timecode display
291         void update_timecode_display();
292
293         std::string format_bbt_timecode (ARDOUR::framepos_t now_frame);
294         std::string format_timecode_timecode (ARDOUR::framepos_t now_frame);
295         
296         /**
297            notification that the port is about to start it's init sequence.
298            We must make sure that before this exits, the port is being polled
299            for new data.
300         */
301         void handle_port_init(Mackie::SurfacePort *);
302
303         /// notification from a MackiePort that it's now active
304         void handle_port_active(Mackie::SurfacePort *);
305         
306         /// notification from a MackiePort that it's now inactive
307         void handle_port_inactive(Mackie::SurfacePort *);
308         
309         boost::shared_ptr<ARDOUR::Route> master_route();
310         Mackie::Strip & master_strip();
311
312         void do_request (MackieControlUIRequest*);
313         int stop ();
314
315   private:
316
317         void port_connected_or_disconnected (std::string, std::string, bool);
318         bool control_in_use_timeout (Mackie::SurfacePort*, Mackie::Control *, Mackie::Control *);
319         
320         boost::shared_ptr<Mackie::RouteSignal> master_route_signal;
321         
322         static const char * default_port_name;
323         
324         /// The Midi port(s) connected to the units
325         typedef std::vector<Mackie::MackiePort*> MackiePorts;
326         MackiePorts _ports;
327   
328         /// Sometimes the real port goes away, and we want to contain the breakage
329         Mackie::DummyPort _dummy_port;
330   
331         /// The initial remote_id of the currently switched in bank.
332         uint32_t _current_initial_bank;
333         
334         /// protects the port list
335         Glib::Mutex update_mutex;
336
337         PBD::ScopedConnectionList audio_engine_connections;
338         PBD::ScopedConnectionList session_connections;
339         PBD::ScopedConnectionList port_connections;
340         PBD::ScopedConnectionList route_connections;
341         
342         /// The representation of the physical controls on the surface.
343         Mackie::Surface * _surface;
344         
345         bool _transport_previously_rolling;
346         
347         // timer for two quick marker left presses
348         Mackie::Timer _frm_left_last;
349         
350         Mackie::JogWheel _jog_wheel;
351         
352         // last written timecode string
353         std::string _timecode_last;
354         
355         // Which timecode are we displaying? BBT or Timecode
356         ARDOUR::AnyTime::Type _timecode_type;
357
358         // Bundle to represent our input ports
359         boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
360         // Bundle to represent our output ports
361         boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
362
363         void build_gui ();
364         void* _gui;
365 };
366
367 #endif // ardour_mackie_control_protocol_h