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