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