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