Prevent various things from stopping the transport by requesting a transport speed...
[ardour.git] / libs / surfaces / mackie / mackie_port.cc
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 #include "mackie_port.h"
19
20 #include "mackie_control_exception.h"
21 #include "mackie_control_protocol.h"
22 #include "mackie_midi_builder.h"
23 #include "controls.h"
24 #include "surface.h"
25
26 #include <glibmm/main.h>
27
28 #include <boost/shared_array.hpp>
29
30 #include "midi++/types.h"
31 #include "midi++/port.h"
32
33 #include "ardour/debug.h"
34 #include "ardour/rc_configuration.h"
35
36 #include "i18n.h"
37
38 #include <sstream>
39
40 using namespace std;
41 using namespace Mackie;
42 using namespace ARDOUR;
43 using namespace PBD;
44
45 // The MCU sysex header
46 MidiByteArray mackie_sysex_hdr ( 5, MIDI::sysex, 0x0, 0x0, 0x66, 0x10 );
47
48 // The MCU extender sysex header
49 MidiByteArray mackie_sysex_hdr_xt ( 5, MIDI::sysex, 0x0, 0x0, 0x66, 0x11 );
50
51 MackiePort::MackiePort (MackieControlProtocol & mcp, MIDI::Port & input_port, MIDI::Port & output_port, int number, port_type_t port_type)
52         : SurfacePort (input_port, output_port, number)
53         , _mcp( mcp )
54         , _port_type( port_type )
55         , _emulation( none )
56         , _initialising( true )
57 {
58         DEBUG_TRACE (DEBUG::MackieControl, "MackiePort::MackiePort\n");
59 }
60
61 MackiePort::~MackiePort()
62 {
63         DEBUG_TRACE (DEBUG::MackieControl, "MackiePort::~MackiePort\n");
64         close();
65         DEBUG_TRACE (DEBUG::MackieControl, "~MackiePort finished\n");
66 }
67
68 int MackiePort::strips() const
69 {
70         if ( _port_type == mcu )
71         {
72                 switch ( _emulation )
73                 {
74                         // BCF2000 only has 8 faders, so reserve one for master
75                         case bcf2000: return 7;
76                         case mackie: return 8;
77                         case none:
78                         default:
79                                 throw MackieControlException( "MackiePort::strips: don't know what emulation we're using" );
80                 }
81         }
82         else
83         {
84                 // must be an extender, ie no master fader
85                 return 8;
86         }
87 }
88
89 // should really be in MackiePort
90 void MackiePort::open()
91 {
92         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackiePort::open %1\n", *this));
93         
94         input_port().parser()->sysex.connect_same_thread (sysex_connection, boost::bind (&MackiePort::handle_midi_sysex, this, _1, _2, _3));
95                      
96         // make sure the device is connected
97         init();
98 }
99
100 void MackiePort::close()
101 {
102         DEBUG_TRACE (DEBUG::MackieControl, "MackiePort::close\n");
103         
104         // disconnect signals
105         any_connection.disconnect();
106         sysex_connection.disconnect();
107         
108         // TODO emit a "closing" signal?
109 }
110
111 const MidiByteArray & MackiePort::sysex_hdr() const
112 {
113         switch ( _port_type )
114         {
115                 case mcu: return mackie_sysex_hdr;
116                 case ext: return mackie_sysex_hdr_xt;
117         }
118         cout << "MackiePort::sysex_hdr _port_type not known" << endl;
119         return mackie_sysex_hdr;
120 }
121
122 MidiByteArray calculate_challenge_response( MidiByteArray::iterator begin, MidiByteArray::iterator end )
123 {
124         MidiByteArray l;
125         back_insert_iterator<MidiByteArray> back ( l );
126         copy( begin, end, back );
127         
128         MidiByteArray retval;
129         
130         // this is how to calculate the response to the challenge.
131         // from the Logic docs.
132         retval << ( 0x7f & ( l[0] + ( l[1] ^ 0xa ) - l[3] ) );
133         retval << ( 0x7f & ( ( l[2] >> l[3] ) ^ ( l[0] + l[3] ) ) );
134         retval << ( 0x7f & ( (l[3] - ( l[2] << 2 )) ^ ( l[0] | l[1] ) ) );
135         retval << ( 0x7f & ( l[1] - l[2] + ( 0xf0 ^ ( l[3] << 4 ) ) ) );
136         
137         return retval;
138 }
139
140 // not used right now
141 MidiByteArray MackiePort::host_connection_query( MidiByteArray & bytes )
142 {
143         // handle host connection query
144         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("host connection query: %1\n", bytes));
145         
146         if ( bytes.size() != 18 )
147         {
148                 finalise_init( false );
149                 ostringstream os;
150                 os << "expecting 18 bytes, read " << bytes << " from " << input_port().name();
151                 throw MackieControlException( os.str() );
152         }
153
154         // build and send host connection reply
155         MidiByteArray response;
156         response << 0x02;
157         copy( bytes.begin() + 6, bytes.begin() + 6 + 7, back_inserter( response ) );
158         response << calculate_challenge_response( bytes.begin() + 6 + 7, bytes.begin() + 6 + 7 + 4 );
159         return response;
160 }
161
162 // not used right now
163 MidiByteArray MackiePort::host_connection_confirmation( const MidiByteArray & bytes )
164 {
165         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("host_connection_confirmation: %1\n", bytes));
166         
167         // decode host connection confirmation
168         if ( bytes.size() != 14 )
169         {
170                 finalise_init( false );
171                 ostringstream os;
172                 os << "expecting 14 bytes, read " << bytes << " from " << input_port().name();
173                 throw MackieControlException( os.str() );
174         }
175         
176         // send version request
177         return MidiByteArray( 2, 0x13, 0x00 );
178 }
179
180 void MackiePort::probe_emulation (const MidiByteArray &)
181 {
182 #if 0
183         cout << "MackiePort::probe_emulation: " << bytes.size() << ", " << bytes << endl;
184
185         MidiByteArray version_string;
186         for ( int i = 6; i < 11; ++i ) version_string << bytes[i];
187         cout << "version_string: " << version_string << endl;
188 #endif
189         
190         // TODO investigate using serial number. Also, possibly size of bytes might
191         // give an indication. Also, apparently MCU sends non-documented messages
192         // sometimes.
193         if (!_initialising)
194         {
195                 //cout << "MackiePort::probe_emulation out of sequence." << endl;
196                 return;
197         }
198
199         finalise_init( true );
200 }
201
202 void MackiePort::init()
203 {
204         DEBUG_TRACE (DEBUG::MackieControl,  "MackiePort::init\n");
205
206         init_mutex.lock();
207         _initialising = true;
208
209         DEBUG_TRACE (DEBUG::MackieControl, "MackiePort::init lock acquired\n");
210
211         // emit pre-init signal
212         init_event();
213         
214         // kick off initialisation. See docs in header file for init()
215         
216         // bypass the init sequence because sometimes the first
217         // message doesn't get to the unit, and there's no way
218         // to do a timed lock in Glib.
219         //write_sysex ( MidiByteArray ( 2, 0x13, 0x00 ) );
220         
221         finalise_init( true );
222 }
223
224 void MackiePort::finalise_init( bool yn )
225 {
226         DEBUG_TRACE (DEBUG::MackieControl, "MackiePort::finalise_init\n");
227
228         bool emulation_ok = false;
229         
230         // probing doesn't work very well, so just use a config variable
231         // to set the emulation mode
232         // TODO This might have to be specified on a per-port basis
233         // in the config file
234         // if an mcu and a bcf are needed to work as one surface
235         if ( _emulation == none )
236         {
237                 // TODO same as code in mackie_control_protocol.cc
238                 if ( ARDOUR::Config->get_mackie_emulation() == "bcf" )
239                 {
240                         _emulation = bcf2000;
241                         emulation_ok = true;
242                 }
243                 else if ( ARDOUR::Config->get_mackie_emulation() == "mcu" )
244                 {
245                         _emulation = mackie;
246                         emulation_ok = true;
247                 }
248                 else
249                 {
250                         cout << "unknown mackie emulation: " << ARDOUR::Config->get_mackie_emulation() << endl;
251                         emulation_ok = false;
252                 }
253         }
254         
255         yn = yn && emulation_ok;
256         
257         SurfacePort::active( yn );
258
259         if (yn) {
260                 active_event();
261                 
262                 // start handling messages from controls
263                 connect_any();
264         }
265
266         _initialising = false;
267         init_cond.signal();
268         init_mutex.unlock();
269
270         DEBUG_TRACE (DEBUG::MackieControl, "MackiePort::finalise_init lock released\n");
271 }
272
273 void MackiePort::connect_any()
274 {
275         if (!any_connection.connected()) {
276                 input_port().parser()->any.connect_same_thread (any_connection, boost::bind (&MackiePort::handle_midi_any, this, _1, _2, _3));
277         }
278 }
279
280 bool MackiePort::wait_for_init()
281 {
282         Glib::Mutex::Lock lock( init_mutex );
283         while (_initialising) {
284                 DEBUG_TRACE (DEBUG::MackieControl, "MackiePort::wait_for_active waiting\n");
285                 init_cond.wait( init_mutex );
286                 DEBUG_TRACE (DEBUG::MackieControl, "MackiePort::wait_for_active released\n");
287         }
288         DEBUG_TRACE (DEBUG::MackieControl, "MackiePort::wait_for_active returning\n");
289         return SurfacePort::active();
290 }
291
292 void MackiePort::handle_midi_sysex (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count )
293 {
294         MidiByteArray bytes( count, raw_bytes );
295         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("handle_midi_sysex: %1\n", bytes));
296
297         switch( bytes[5] )
298         {
299                 case 0x01:
300                         // not used right now
301                         write_sysex (host_connection_query (bytes));
302                         break;
303                 case 0x03:
304                         // not used right now
305                         write_sysex (host_connection_confirmation (bytes));
306                         break;
307                 case 0x04:
308                         inactive_event ();
309                         cout << "host connection error" << bytes << endl;
310                         break;
311                 case 0x14:
312                         probe_emulation (bytes);
313                         break;
314                 default:
315                         cout << "unknown sysex: " << bytes << endl;
316         }
317 }
318
319 Control & MackiePort::lookup_control( MIDI::byte * bytes, size_t count )
320 {
321         // Don't instantiate a MidiByteArray here unless it's needed for exceptions.
322         // Reason being that this method is called for every single incoming
323         // midi event, and it needs to be as efficient as possible.
324
325         Control * control = 0;
326         MIDI::byte midi_type = bytes[0] & 0xf0; //0b11110000
327
328         switch (midi_type) {
329                 // fader
330                 case MackieMidiBuilder::midi_fader_id:
331                 {
332                         int midi_id = bytes[0] & 0x0f;
333                         control = _mcp.surface().faders[midi_id];
334                         if ( control == 0 )
335                         {
336                                 MidiByteArray mba( count, bytes );
337                                 ostringstream os;
338                                 os << "Control for fader" << bytes << " id " << midi_id << " is null";
339                                 throw MackieControlException( os.str() );
340                         }
341                         break;
342                 }
343                         
344                 // button
345                 case MackieMidiBuilder::midi_button_id:
346                         control = _mcp.surface().buttons[bytes[1]];
347                         if ( control == 0 )
348                         {
349                                 MidiByteArray mba( count, bytes );
350                                 ostringstream os;
351                                 os << "Control for button " << mba << " is null";
352                                 throw MackieControlException( os.str() );
353                         }
354                         break;
355                         
356                 // pot (jog wheel, external control)
357                 case MackieMidiBuilder::midi_pot_id:
358                         control = _mcp.surface().pots[bytes[1]];
359                         if ( control == 0 )
360                         {
361                                 MidiByteArray mba( count, bytes );
362                                 ostringstream os;
363                                 os << "Control for rotary " << mba << " is null";
364                                 throw MackieControlException( os.str() );
365                         }
366                         break;
367                 
368                 default:
369                         MidiByteArray mba( count, bytes );
370                         ostringstream os;
371                         os << "Cannot find control for " << mba;
372                         throw MackieControlException( os.str() );
373         }
374         return *control;
375 }
376
377 bool MackiePort::handle_control_timeout_event ( Control * control )
378 {
379         // empty control_state
380         ControlState control_state;
381         control->in_use( false );
382         control_event( *this, *control, control_state );
383         
384         // only call this method once from the timer
385         return false;
386 }
387
388 // converts midi messages into control_event signals
389 // it might be worth combining this with lookup_control
390 // because they have similar logic flows.
391 void MackiePort::handle_midi_any (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count )
392 {
393         MidiByteArray bytes( count, raw_bytes );
394         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackiePort::handle_midi_any %1\n", bytes));
395
396         try
397         {
398                 // ignore sysex messages
399                 if ( raw_bytes[0] == MIDI::sysex ) return;
400
401                 // sanity checking
402                 if (count != 3) {
403                         ostringstream os;
404                         MidiByteArray mba( count, raw_bytes );
405                         os << "MackiePort::handle_midi_any needs 3 bytes, but received " << mba;
406                         throw MackieControlException( os.str() );
407                 }
408                 
409                 Control & control = lookup_control( raw_bytes, count );
410                 control.in_use( true );
411                 
412                 // This handles incoming bytes. Outgoing bytes
413                 // are sent by the signal handlers.
414                 switch (control.type()) {
415                         // fader
416                         case Control::type_fader:
417                         {
418                                 // only the top-order 10 bits out of 14 are used
419                                 int midi_pos = ( ( raw_bytes[2] << 7 ) + raw_bytes[1] ) >> 4;
420                                 
421                                 // in_use is set by the MackieControlProtocol::handle_strip_button
422                                 
423                                 // relies on implicit ControlState constructor
424                                 control_event( *this, control, float(midi_pos) / float(0x3ff) );
425                         }
426                         break;
427                                 
428                         // button
429                         case Control::type_button:
430                         {
431                                 ControlState control_state( raw_bytes[2] == 0x7f ? press : release );
432                                 control.in_use( control_state.button_state == press );
433                                 control_event( *this, control, control_state );
434                                 
435                                 break;
436                         }
437                                 
438                         // pot (jog wheel, external control)
439                         case Control::type_pot:
440                         {
441                                 ControlState state;
442                                 
443                                 // bytes[2] & 0b01000000 (0x40) give sign
444                                 state.sign = ( raw_bytes[2] & 0x40 ) == 0 ? 1 : -1; 
445                                 // bytes[2] & 0b00111111 (0x3f) gives delta
446                                 state.ticks = ( raw_bytes[2] & 0x3f);
447                                 if (state.ticks == 0) {
448                                         /* euphonix and perhaps other devices send zero
449                                            when they mean 1, we think.
450                                         */
451                                         state.ticks = 1;
452                                 }
453                                 state.delta = float( state.ticks ) / float( 0x3f );
454                                 
455                                 /*
456                                         Pots only emit events when they move, not when they
457                                         stop moving. So to get a stop event, we need to use a timeout.
458                                 */
459                                 // this is set to false ...
460                                 control.in_use( true );
461                                 
462                                 // ... by this timeout
463                                 
464                                 // first disconnect any previous timeouts
465                                 control.in_use_connection.disconnect();
466                                 
467                                 // now connect a new timeout to call handle_control_timeout_event
468                                 // XXX should this use the GUI event loop (default) or the
469                                 // MIDI UI event loop ?
470
471                                 sigc::slot<bool> timeout_slot = sigc::bind 
472                                         (sigc::mem_fun( *this, &MackiePort::handle_control_timeout_event), &control);
473
474                                 control.in_use_connection = Glib::signal_timeout().connect (timeout_slot , control.in_use_timeout());
475
476                                 // emit the control event
477                                 control_event( *this, control, state );
478                                 break;
479                         }
480                         default:
481                                 cerr << "Do not understand control type " << control;
482                 }
483         }
484
485         catch( MackieControlException & e ) {
486                 MidiByteArray bytes( count, raw_bytes );
487                 cout << bytes << ' ' << e.what() << endl;
488         }
489
490         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("finished MackiePort::handle_midi_any %1\n", bytes));
491 }