MCP: change refresh interval for meters + automation + timecode to 100msec
[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         Glib::Mutex route_signals_lock; 
268
269         // return which of the ports a particular route_table
270         // index belongs to
271         Mackie::MackiePort & port_for_id(uint32_t index);
272
273         /**
274            Handle a button press for the control and return whether
275            the corresponding light should be on or off.
276         */
277         bool handle_strip_button (Mackie::SurfacePort &, Mackie::Control &, Mackie::ButtonState, boost::shared_ptr<ARDOUR::Route>);
278
279         void add_port (MIDI::Port &, MIDI::Port &, int number, Mackie::MackiePort::port_type_t);
280
281         /**
282            Read session data and send to surface. Includes
283            automation from the currently active routes and
284            timecode displays.
285         */
286         void poll_session_data();
287         
288         // called from poll_automation to figure out which automations need to be sent
289         void update_automation(Mackie::RouteSignal &);
290         
291         // also called from poll_automation to update timecode display
292         void update_timecode_display();
293
294         std::string format_bbt_timecode (ARDOUR::framepos_t now_frame);
295         std::string format_timecode_timecode (ARDOUR::framepos_t now_frame);
296         
297         /**
298            notification that the port is about to start it's init sequence.
299            We must make sure that before this exits, the port is being polled
300            for new data.
301         */
302         void handle_port_init(Mackie::SurfacePort *);
303
304         /// notification from a MackiePort that it's now active
305         void handle_port_active(Mackie::SurfacePort *);
306         
307         /// notification from a MackiePort that it's now inactive
308         void handle_port_inactive(Mackie::SurfacePort *);
309         
310         boost::shared_ptr<ARDOUR::Route> master_route();
311         Mackie::Strip & master_strip();
312
313         void do_request (MackieControlUIRequest*);
314         int stop ();
315
316   private:
317
318         void port_connected_or_disconnected (std::string, std::string, bool);
319         bool control_in_use_timeout (Mackie::SurfacePort*, Mackie::Control *, Mackie::Control *);
320         bool meter_update();
321         sigc::connection meter_connection;
322
323         boost::shared_ptr<Mackie::RouteSignal> master_route_signal;
324         
325         static const char * default_port_name;
326         
327         /// The Midi port(s) connected to the units
328         typedef std::vector<Mackie::MackiePort*> MackiePorts;
329         MackiePorts _ports;
330   
331         /// Sometimes the real port goes away, and we want to contain the breakage
332         Mackie::DummyPort _dummy_port;
333   
334         /// The initial remote_id of the currently switched in bank.
335         uint32_t _current_initial_bank;
336         
337         /// protects the port list
338         Glib::Mutex update_mutex;
339
340         PBD::ScopedConnectionList audio_engine_connections;
341         PBD::ScopedConnectionList session_connections;
342         PBD::ScopedConnectionList port_connections;
343         PBD::ScopedConnectionList route_connections;
344         
345         /// The representation of the physical controls on the surface.
346         Mackie::Surface * _surface;
347         
348         bool _transport_previously_rolling;
349         
350         // timer for two quick marker left presses
351         Mackie::Timer _frm_left_last;
352         
353         Mackie::JogWheel _jog_wheel;
354         
355         // last written timecode string
356         std::string _timecode_last;
357         
358         // Which timecode are we displaying? BBT or Timecode
359         ARDOUR::AnyTime::Type _timecode_type;
360
361         // Bundle to represent our input ports
362         boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
363         // Bundle to represent our output ports
364         boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
365
366         void build_gui ();
367         void* _gui;
368 };
369
370 #endif // ardour_mackie_control_protocol_h