2 Copyright (C) 2006,2007 John Anderson
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.
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.
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.
19 #ifndef ardour_mackie_control_protocol_h
20 #define ardour_mackie_control_protocol_h
27 #include <glibmm/thread.h>
29 #include "pbd/abstract_ui.h"
31 #include "ardour/types.h"
32 #include "ardour/midi_ui.h"
33 #include "midi++/types.h"
35 #include "control_protocol/control_protocol.h"
36 #include "midi_byte_array.h"
38 #include "dummy_port.h"
39 #include "route_signal.h"
40 #include "mackie_port.h"
41 #include "mackie_jog_wheel.h"
55 This handles the plugin duties, and the midi encoding and decoding,
56 and the signal callbacks, mostly from ARDOUR::Route.
58 The model of the control surface is handled by classes in controls.h
60 What happens is that each strip on the control surface has
61 a corresponding route in ControlProtocol::route_table. When
62 an incoming midi message is signaled, the correct route
63 is looked up, and the relevant changes made to it.
65 For each route currently in route_table, there's a RouteSignal object
66 which encapsulates the signals that indicate that there are changes
67 to be sent to the surface. The signals are handled by this class.
69 Calls to signal handlers pass a Route object which is used to look
70 up the relevant Strip in Surface. Then the state is retrieved from
71 the Route and encoded as the correct midi message.
74 struct MackieControlUIRequest : public BaseUI::BaseRequestObject {
76 MackieControlUIRequest () {}
77 ~MackieControlUIRequest () {}
80 class MackieControlProtocol
81 : public ARDOUR::ControlProtocol
82 , public AbstractUI<MackieControlUIRequest>
85 MackieControlProtocol(ARDOUR::Session &);
86 virtual ~MackieControlProtocol();
88 int set_active (bool yn);
90 XMLNode& get_state ();
91 int set_state (const XMLNode&, int version);
95 Mackie::Surface & surface();
97 std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles ();
99 bool has_editor () const { return true; }
100 void* get_gui () const;
101 void tear_down_gui ();
104 void handle_control_event (Mackie::SurfacePort & port, Mackie::Control & control, const Mackie::ControlState & state);
105 void handle_button_event (Mackie::Button& button, Mackie::ButtonState);
107 // strip/route related stuff
109 void notify_solo_changed (Mackie::RouteSignal *);
110 void notify_mute_changed (Mackie::RouteSignal *);
111 void notify_record_enable_changed (Mackie::RouteSignal *);
112 void notify_gain_changed (Mackie::RouteSignal *, bool force_update = true);
113 void notify_property_changed (const PBD::PropertyChange&, Mackie::RouteSignal *);
114 void notify_panner_changed (Mackie::RouteSignal *, bool force_update = true);
115 void notify_route_added (ARDOUR::RouteList &);
116 void notify_active_changed (Mackie::RouteSignal *);
118 void notify_remote_id_changed();
120 /// rebuild the current bank. Called on route added/removed and
121 /// remote id changed.
122 void refresh_current_bank();
125 // button-related signals
126 void notify_record_state_changed();
127 void notify_transport_state_changed();
128 // mainly to pick up punch-in and punch-out
129 void notify_parameter_changed(std::string const &);
130 void notify_solo_active_changed(bool);
132 /// Turn timecode on and beats off, or vice versa, depending
133 /// on state of _timecode_type
134 void update_timecode_beats_led();
136 /// this is called to generate the midi to send in response to a button press.
137 void update_led(Mackie::Button & button, Mackie::LedState);
139 void update_global_button(const std::string & name, Mackie::LedState);
140 void update_global_led(const std::string & name, Mackie::LedState);
142 /* implemented button handlers */
143 Mackie::LedState frm_left_press(Mackie::Button &);
144 Mackie::LedState frm_left_release(Mackie::Button &);
145 Mackie::LedState frm_right_press(Mackie::Button &);
146 Mackie::LedState frm_right_release(Mackie::Button &);
147 Mackie::LedState stop_press(Mackie::Button &);
148 Mackie::LedState stop_release(Mackie::Button &);
149 Mackie::LedState play_press(Mackie::Button &);
150 Mackie::LedState play_release(Mackie::Button &);
151 Mackie::LedState record_press(Mackie::Button &);
152 Mackie::LedState record_release(Mackie::Button &);
153 Mackie::LedState loop_press(Mackie::Button &);
154 Mackie::LedState loop_release(Mackie::Button &);
155 Mackie::LedState punch_in_press(Mackie::Button &);
156 Mackie::LedState punch_in_release(Mackie::Button &);
157 Mackie::LedState punch_out_press(Mackie::Button &);
158 Mackie::LedState punch_out_release(Mackie::Button &);
159 Mackie::LedState home_press(Mackie::Button &);
160 Mackie::LedState home_release(Mackie::Button &);
161 Mackie::LedState end_press(Mackie::Button &);
162 Mackie::LedState end_release(Mackie::Button &);
163 Mackie::LedState rewind_press(Mackie::Button & button);
164 Mackie::LedState rewind_release(Mackie::Button & button);
165 Mackie::LedState ffwd_press(Mackie::Button & button);
166 Mackie::LedState ffwd_release(Mackie::Button & button);
167 Mackie::LedState cursor_up_press (Mackie::Button &);
168 Mackie::LedState cursor_up_release (Mackie::Button &);
169 Mackie::LedState cursor_down_press (Mackie::Button &);
170 Mackie::LedState cursor_down_release (Mackie::Button &);
171 Mackie::LedState cursor_left_press (Mackie::Button &);
172 Mackie::LedState cursor_left_release (Mackie::Button &);
173 Mackie::LedState cursor_right_press (Mackie::Button &);
174 Mackie::LedState cursor_right_release (Mackie::Button &);
175 Mackie::LedState left_press(Mackie::Button &);
176 Mackie::LedState left_release(Mackie::Button &);
177 Mackie::LedState right_press(Mackie::Button &);
178 Mackie::LedState right_release(Mackie::Button &);
179 Mackie::LedState channel_left_press(Mackie::Button &);
180 Mackie::LedState channel_left_release(Mackie::Button &);
181 Mackie::LedState channel_right_press(Mackie::Button &);
182 Mackie::LedState channel_right_release(Mackie::Button &);
183 Mackie::LedState clicking_press(Mackie::Button &);
184 Mackie::LedState clicking_release(Mackie::Button &);
185 Mackie::LedState global_solo_press(Mackie::Button &);
186 Mackie::LedState global_solo_release(Mackie::Button &);
187 Mackie::LedState marker_press(Mackie::Button &);
188 Mackie::LedState marker_release(Mackie::Button &);
189 Mackie::LedState drop_press(Mackie::Button &);
190 Mackie::LedState drop_release(Mackie::Button &);
191 Mackie::LedState save_press(Mackie::Button &);
192 Mackie::LedState save_release(Mackie::Button &);
193 Mackie::LedState timecode_beats_press(Mackie::Button &);
194 Mackie::LedState timecode_beats_release(Mackie::Button &);
195 Mackie::LedState zoom_press(Mackie::Button &);
196 Mackie::LedState zoom_release(Mackie::Button &);
197 Mackie::LedState scrub_press(Mackie::Button &);
198 Mackie::LedState scrub_release(Mackie::Button &);
199 Mackie::LedState undo_press (Mackie::Button &);
200 Mackie::LedState undo_release (Mackie::Button &);
201 Mackie::LedState redo_press (Mackie::Button &);
202 Mackie::LedState redo_release (Mackie::Button &);
204 /* unimplemented button handlers */
206 Mackie::LedState io_press (Mackie::Button &) { return Mackie::off; }
207 Mackie::LedState io_release (Mackie::Button &) { return Mackie::off; }
208 Mackie::LedState sends_press (Mackie::Button &) { return Mackie::off; }
209 Mackie::LedState sends_release (Mackie::Button &) { return Mackie::off; }
210 Mackie::LedState pan_press (Mackie::Button &) { return Mackie::off; }
211 Mackie::LedState pan_release (Mackie::Button &) { return Mackie::off; }
212 Mackie::LedState plugin_press (Mackie::Button &) { return Mackie::off; }
213 Mackie::LedState plugin_release (Mackie::Button &) { return Mackie::off; }
214 Mackie::LedState eq_press (Mackie::Button &) { return Mackie::off; }
215 Mackie::LedState eq_release (Mackie::Button &) { return Mackie::off; }
216 Mackie::LedState dyn_press (Mackie::Button &) { return Mackie::off; }
217 Mackie::LedState dyn_release (Mackie::Button &) { return Mackie::off; }
218 Mackie::LedState flip_press (Mackie::Button &) { return Mackie::off; }
219 Mackie::LedState flip_release (Mackie::Button &) { return Mackie::off; }
220 Mackie::LedState edit_press (Mackie::Button &) { return Mackie::off; }
221 Mackie::LedState edit_release (Mackie::Button &) { return Mackie::off; }
222 Mackie::LedState name_value_press (Mackie::Button &) { return Mackie::off; }
223 Mackie::LedState name_value_release (Mackie::Button &) { return Mackie::off; }
224 Mackie::LedState F1_press (Mackie::Button &) { return Mackie::off; }
225 Mackie::LedState F1_release (Mackie::Button &) { return Mackie::off; }
226 Mackie::LedState F2_press (Mackie::Button &) { return Mackie::off; }
227 Mackie::LedState F2_release (Mackie::Button &) { return Mackie::off; }
228 Mackie::LedState F3_press (Mackie::Button &) { return Mackie::off; }
229 Mackie::LedState F3_release (Mackie::Button &) { return Mackie::off; }
230 Mackie::LedState F4_press (Mackie::Button &) { return Mackie::off; }
231 Mackie::LedState F4_release (Mackie::Button &) { return Mackie::off; }
232 Mackie::LedState F5_press (Mackie::Button &) { return Mackie::off; }
233 Mackie::LedState F5_release (Mackie::Button &) { return Mackie::off; }
234 Mackie::LedState F6_press (Mackie::Button &) { return Mackie::off; }
235 Mackie::LedState F6_release (Mackie::Button &) { return Mackie::off; }
236 Mackie::LedState F7_press (Mackie::Button &) { return Mackie::off; }
237 Mackie::LedState F7_release (Mackie::Button &) { return Mackie::off; }
238 Mackie::LedState F8_press (Mackie::Button &) { return Mackie::off; }
239 Mackie::LedState F8_release (Mackie::Button &) { return Mackie::off; }
240 Mackie::LedState F9_press (Mackie::Button &) { return Mackie::off; }
241 Mackie::LedState F9_release (Mackie::Button &) { return Mackie::off; }
242 Mackie::LedState F10_press (Mackie::Button &) { return Mackie::off; }
243 Mackie::LedState F10_release (Mackie::Button &) { return Mackie::off; }
244 Mackie::LedState F11_press (Mackie::Button &) { return Mackie::off; }
245 Mackie::LedState F11_release (Mackie::Button &) { return Mackie::off; }
246 Mackie::LedState F12_press (Mackie::Button &) { return Mackie::off; }
247 Mackie::LedState F12_release (Mackie::Button &) { return Mackie::off; }
248 Mackie::LedState F13_press (Mackie::Button &) { return Mackie::off; }
249 Mackie::LedState F13_release (Mackie::Button &) { return Mackie::off; }
250 Mackie::LedState F14_press (Mackie::Button &) { return Mackie::off; }
251 Mackie::LedState F14_release (Mackie::Button &) { return Mackie::off; }
252 Mackie::LedState F15_press (Mackie::Button &) { return Mackie::off; }
253 Mackie::LedState F15_release (Mackie::Button &) { return Mackie::off; }
254 Mackie::LedState F16_press (Mackie::Button &) { return Mackie::off; }
255 Mackie::LedState F16_release (Mackie::Button &) { return Mackie::off; }
256 Mackie::LedState shift_press (Mackie::Button &) { return Mackie::off; }
257 Mackie::LedState shift_release (Mackie::Button &) { return Mackie::off; }
258 Mackie::LedState option_press (Mackie::Button &) { return Mackie::off; }
259 Mackie::LedState option_release (Mackie::Button &) { return Mackie::off; }
260 Mackie::LedState control_press (Mackie::Button &) { return Mackie::off; }
261 Mackie::LedState control_release (Mackie::Button &) { return Mackie::off; }
262 Mackie::LedState cmd_alt_press (Mackie::Button &) { return Mackie::off; }
263 Mackie::LedState cmd_alt_release (Mackie::Button &) { return Mackie::off; }
264 Mackie::LedState on_press (Mackie::Button &) { return Mackie::off; }
265 Mackie::LedState on_release (Mackie::Button &) { return Mackie::off; }
266 Mackie::LedState rec_ready_press (Mackie::Button &) { return Mackie::off; }
267 Mackie::LedState rec_ready_release (Mackie::Button &) { return Mackie::off; }
268 Mackie::LedState snapshot_press (Mackie::Button &) { return Mackie::off; }
269 Mackie::LedState snapshot_release (Mackie::Button &) { return Mackie::off; }
270 Mackie::LedState touch_press (Mackie::Button &) { return Mackie::off; }
271 Mackie::LedState touch_release (Mackie::Button &) { return Mackie::off; }
272 Mackie::LedState enter_press (Mackie::Button &) { return Mackie::off; }
273 Mackie::LedState enter_release (Mackie::Button &) { return Mackie::off; }
274 Mackie::LedState cancel_press (Mackie::Button &) { return Mackie::off; }
275 Mackie::LedState cancel_release (Mackie::Button &) { return Mackie::off; }
276 Mackie::LedState mixer_press (Mackie::Button &) { return Mackie::off; }
277 Mackie::LedState mixer_release (Mackie::Button &) { return Mackie::off; }
278 Mackie::LedState user_a_press (Mackie::Button &) { return Mackie::off; }
279 Mackie::LedState user_a_release (Mackie::Button &) { return Mackie::off; }
280 Mackie::LedState user_b_press (Mackie::Button &) { return Mackie::off; }
281 Mackie::LedState user_b_release (Mackie::Button &) { return Mackie::off; }
282 Mackie::LedState fader_touch_press (Mackie::Button &) { return Mackie::off; }
283 Mackie::LedState fader_touch_release (Mackie::Button &) { return Mackie::off; }
286 /// This is the main MCU port, ie not an extender port
287 /// Only for use by JogWheel
288 const Mackie::SurfacePort & mcu_port() const;
289 Mackie::SurfacePort & mcu_port();
290 ARDOUR::Session & get_session() { return *session; }
292 void add_in_use_timeout (Mackie::SurfacePort& port, Mackie::Control& in_use_control, Mackie::Control* touch_control);
295 // create instances of MackiePort, depending on what's found in ardour.rc
298 // shut down the surface
301 // create the Surface object, with the correct number
302 // of strips for the currently connected ports and
303 // hook up the control event notification
304 void initialize_surface();
306 // This sets up the notifications and sets the
307 // controls to the correct values
308 void update_surface();
310 // connects global (not strip) signals from the Session to here
311 // so the surface can be notified of changes from the other UIs.
312 void connect_session_signals();
314 // set all controls to their zero position
318 Fetch the set of routes to be considered for control by the
319 surface. Excluding master, hidden and control routes, and inactive routes
321 typedef std::vector<boost::shared_ptr<ARDOUR::Route> > Sorted;
322 Sorted get_sorted_routes();
325 void switch_banks(int initial);
329 // delete all RouteSignal objects connecting Routes to Strips
330 void clear_route_signals();
332 typedef std::vector<Mackie::RouteSignal*> RouteSignals;
333 RouteSignals route_signals;
334 Glib::Mutex route_signals_lock;
336 // return which of the ports a particular route_table
338 Mackie::MackiePort & port_for_id(uint32_t index);
341 Handle a button press for the control and return whether
342 the corresponding light should be on or off.
344 bool handle_strip_button (Mackie::SurfacePort &, Mackie::Control &, Mackie::ButtonState, boost::shared_ptr<ARDOUR::Route>);
346 void add_port (MIDI::Port &, MIDI::Port &, int number, Mackie::MackiePort::port_type_t);
348 // called from poll_automation to figure out which automations need to be sent
349 void update_automation(Mackie::RouteSignal &);
351 // also called from poll_automation to update timecode display
352 void update_timecode_display();
354 std::string format_bbt_timecode (ARDOUR::framepos_t now_frame);
355 std::string format_timecode_timecode (ARDOUR::framepos_t now_frame);
358 notification that the port is about to start it's init sequence.
359 We must make sure that before this exits, the port is being polled
362 void handle_port_init(Mackie::SurfacePort *);
364 /// notification from a MackiePort that it's now active
365 void handle_port_active(Mackie::SurfacePort *);
367 /// notification from a MackiePort that it's now inactive
368 void handle_port_inactive(Mackie::SurfacePort *);
370 boost::shared_ptr<ARDOUR::Route> master_route();
371 Mackie::Strip & master_strip();
373 void do_request (MackieControlUIRequest*);
378 void port_connected_or_disconnected (std::string, std::string, bool);
379 bool control_in_use_timeout (Mackie::SurfacePort*, Mackie::Control *, Mackie::Control *);
382 sigc::connection periodic_connection;
384 boost::shared_ptr<Mackie::RouteSignal> master_route_signal;
386 static const char * default_port_name;
388 /// The Midi port(s) connected to the units
389 typedef std::vector<Mackie::MackiePort*> MackiePorts;
392 /// Sometimes the real port goes away, and we want to contain the breakage
393 Mackie::DummyPort _dummy_port;
395 /// The initial remote_id of the currently switched in bank.
396 uint32_t _current_initial_bank;
398 /// protects the port list
399 Glib::Mutex update_mutex;
401 PBD::ScopedConnectionList audio_engine_connections;
402 PBD::ScopedConnectionList session_connections;
403 PBD::ScopedConnectionList port_connections;
404 PBD::ScopedConnectionList route_connections;
406 /// The representation of the physical controls on the surface.
407 Mackie::Surface * _surface;
409 bool _transport_previously_rolling;
411 // timer for two quick marker left presses
412 Mackie::Timer _frm_left_last;
414 Mackie::JogWheel _jog_wheel;
416 // last written timecode string
417 std::string _timecode_last;
419 // Which timecode are we displaying? BBT or Timecode
420 ARDOUR::AnyTime::Type _timecode_type;
422 // Bundle to represent our input ports
423 boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
424 // Bundle to represent our output ports
425 boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
433 #endif // ardour_mackie_control_protocol_h