merge r1449 from surfaces branch to include mackie surface and tranzport updates...
[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 <midi++/types.h>
27 #include <midi++/port.h>
28 #include <midi++/alsa_sequencer.h>
29 #include <sigc++/sigc++.h>
30 #include <boost/shared_array.hpp>
31 #include <ardour/configuration.h>
32
33 #include "i18n.h"
34
35 #include <sstream>
36
37 using namespace std;
38 using namespace Mackie;
39
40 // The MCU sysex header
41 MidiByteArray mackie_sysex_hdr ( 5, MIDI::sysex, 0x0, 0x0, 0x66, 0x10 );
42
43 // The MCU extender sysex header
44 MidiByteArray mackie_sysex_hdr_xt ( 5, MIDI::sysex, 0x0, 0x0, 0x66, 0x11 );
45
46 MackiePort::MackiePort( MackieControlProtocol & mcp, MIDI::Port & port, int number, port_type_t port_type )
47 : SurfacePort( port, number )
48 , _mcp( mcp )
49 , _port_type( port_type )
50 , _emulation( none )
51 , _initialising( true )
52 {
53         cout << "MackiePort::MackiePort" <<endl;
54 }
55
56 MackiePort::~MackiePort()
57 {
58         close();
59 }
60
61 int MackiePort::strips() const
62 {
63         if ( _port_type == mcu )
64         {
65                 switch ( _emulation )
66                 {
67                         // BCF2000 only has 8 faders, so reserve one for master
68                         case bcf2000: return 7;
69                         case mackie: return 8;
70                         case none:
71                         default:
72                                 throw MackieControlException( "MackiePort::strips: don't know what emulation we're using" );
73                 }
74         }
75         else
76         {
77                 // must be an extender, ie no master fader
78                 return 8;
79         }
80 }
81
82 // should really be in MackiePort
83 void MackiePort::open()
84 {
85         cout << "MackiePort::open " << *this << endl;
86         _sysex = port().input()->sysex.connect( ( mem_fun (*this, &MackiePort::handle_midi_sysex) ) );
87         
88         // make sure the device is connected
89         init();
90 }
91
92 void MackiePort::close()
93 {
94         // disconnect signals
95         _any.disconnect();
96         _sysex.disconnect();
97         
98         // or emit a "closing" signal
99 }
100
101 const MidiByteArray & MackiePort::sysex_hdr() const
102 {
103         switch ( _port_type )
104         {
105                 case mcu: return mackie_sysex_hdr;
106                 case ext: return mackie_sysex_hdr_xt;
107         }
108         cout << "MackiePort::sysex_hdr _port_type not known" << endl;
109         return mackie_sysex_hdr;
110 }
111
112 Control & MackiePort::lookup_control( const MidiByteArray & bytes )
113 {
114         Control * control = 0;
115         int midi_id = -1;
116         MIDI::byte midi_type = bytes[0] & 0xf0; //0b11110000
117         switch( midi_type )
118         {
119                 // fader
120                 case MackieMidiBuilder::midi_fader_id:
121                         midi_id = bytes[0] & 0x0f;
122                         control = _mcp.surface().faders[midi_id];
123                         if ( control == 0 )
124                         {
125                                 ostringstream os;
126                                 os << "control for fader" << midi_id << " is null";
127                                 throw MackieControlException( os.str() );
128                         }
129                         break;
130                         
131                 // button
132                 case MackieMidiBuilder::midi_button_id:
133                         midi_id = bytes[1];
134                         control = _mcp.surface().buttons[midi_id];
135                         if ( control == 0 )
136                         {
137                                 ostringstream os;
138                                 os << "control for button" << midi_id << " is null";
139                                 throw MackieControlException( os.str() );
140                         }
141                         break;
142                         
143                 // pot (jog wheel, external control)
144                 case MackieMidiBuilder::midi_pot_id:
145                         midi_id = bytes[1] & 0x1f;
146                         control = _mcp.surface().pots[midi_id];
147                         if ( control == 0 )
148                         {
149                                 ostringstream os;
150                                 os << "control for button" << midi_id << " is null";
151                                 throw MackieControlException( os.str() );
152                         }
153                         break;
154                 
155                 default:
156                         ostringstream os;
157                         os << "Cannot find control for " << bytes;
158                         throw MackieControlException( os.str() );
159         }
160         return *control;
161 }
162
163 MidiByteArray calculate_challenge_response( MidiByteArray::iterator begin, MidiByteArray::iterator end )
164 {
165         MidiByteArray l;
166         back_insert_iterator<MidiByteArray> back ( l );
167         copy( begin, end, back );
168         
169         MidiByteArray retval;
170         
171         // this is how to calculate the response to the challenge.
172         // from the Logic docs.
173         retval << ( 0x7f & ( l[0] + ( l[1] ^ 0xa ) - l[3] ) );
174         retval << ( 0x7f & ( ( l[2] >> l[3] ) ^ ( l[0] + l[3] ) ) );
175         retval << ( 0x7f & ( l[3] - ( l[2] << 2 ) ^ ( l[0] | l[1] ) ) );
176         retval << ( 0x7f & ( l[1] - l[2] + ( 0xf0 ^ ( l[3] << 4 ) ) ) );
177         
178         return retval;
179 }
180
181 // not used right now
182 MidiByteArray MackiePort::host_connection_query( MidiByteArray & bytes )
183 {
184         // handle host connection query
185         cout << "host connection query: " << bytes << endl;
186         
187         if ( bytes.size() != 18 )
188         {
189                 finalise_init( false );
190                 ostringstream os;
191                 os << "expecting 18 bytes, read " << bytes << " from " << port().name();
192                 throw MackieControlException( os.str() );
193         }
194
195         // build and send host connection reply
196         MidiByteArray response;
197         response << 0x02;
198         copy( bytes.begin() + 6, bytes.begin() + 6 + 7, back_inserter( response ) );
199         response << calculate_challenge_response( bytes.begin() + 6 + 7, bytes.begin() + 6 + 7 + 4 );
200         return response;
201 }
202
203 // not used right now
204 MidiByteArray MackiePort::host_connection_confirmation( const MidiByteArray & bytes )
205 {
206         cout << "host_connection_confirmation: " << bytes << endl;
207         
208         // decode host connection confirmation
209         if ( bytes.size() != 14 )
210         {
211                 finalise_init( false );
212                 ostringstream os;
213                 os << "expecting 14 bytes, read " << bytes << " from " << port().name();
214                 throw MackieControlException( os.str() );
215         }
216         
217         // send version request
218         return MidiByteArray( 2, 0x13, 0x00 );
219 }
220
221 void MackiePort::probe_emulation( const MidiByteArray & bytes )
222 {
223         cout << "MackiePort::probe_emulation: " << bytes.size() << ", " << bytes << endl;
224         string version_string;
225         for ( int i = 6; i < 11; ++i ) version_string.append( 1, (char)bytes[i] );
226         cout << "version_string: " << version_string << endl;
227         
228         // TODO investigate using serial number. Also, possibly size of bytes might
229         // give an indication. Also, apparently MCU sends non-documented messages
230         // sometimes.
231         if (!_initialising)
232         {
233                 cout << "MackiePort::probe_emulation out of sequence." << endl;
234                 return;
235         }
236
237         // probing doesn't work very well, so just use a config variable
238         // to set the emulation mode
239         bool emulation_ok = false;
240         if ( ARDOUR::Config->get_mackie_emulation() == "bcf" )
241         {
242                 _emulation = bcf2000;
243                 emulation_ok = true;
244         }
245         else if ( ARDOUR::Config->get_mackie_emulation() == "mcu" )
246         {
247                 _emulation = mackie;
248                 emulation_ok = true;
249         }
250         else
251         {
252                 cout << "unknown mackie emulation: " << ARDOUR::Config->get_mackie_emulation() << endl;
253                 emulation_ok = false;
254         }
255         
256         finalise_init( emulation_ok );
257 }
258
259 void MackiePort::init()
260 {
261         cout << "MackiePort::init" << endl;
262         init_mutex.lock();
263         _initialising = true;
264         
265         cout << "MackiePort::lock acquired" << endl;
266         // emit pre-init signal
267         init_event();
268         
269         // kick off initialisation. See docs in header file for init()
270         write_sysex ( MidiByteArray (2, 0x13, 0x00 ));
271 }
272
273 void MackiePort::finalise_init( bool yn )
274 {
275         cout << "MackiePort::finalise_init" << endl;
276         
277         SurfacePort::active( yn );
278
279         if ( yn )
280         {
281                 active_event();
282                 
283                 // start handling messages from controls
284                 _any = port().input()->any.connect( ( mem_fun (*this, &MackiePort::handle_midi_any) ) );
285         }
286         _initialising = false;
287         init_cond.signal();
288         init_mutex.unlock();
289 }
290
291 bool MackiePort::wait_for_init()
292 {
293         Glib::Mutex::Lock lock( init_mutex );
294         while ( _initialising )
295         {
296                 cout << "MackiePort::wait_for_active waiting" << endl;
297                 init_cond.wait( init_mutex );
298                 cout << "MackiePort::wait_for_active released" << endl;
299         }
300         cout << "MackiePort::wait_for_active returning" << endl;
301         return SurfacePort::active();
302 }
303
304 void MackiePort::handle_midi_sysex (MIDI::Parser & parser, MIDI::byte * raw_bytes, size_t count )
305 {
306         MidiByteArray bytes( count, raw_bytes );
307         cout << "handle_midi_sysex: " << bytes << endl;
308         switch( bytes[5] )
309         {
310                 case 0x01:
311                         // not used right now
312                         write_sysex( host_connection_query( bytes ) );
313                         break;
314                 case 0x03:
315                         // not used right now
316                         write_sysex( host_connection_confirmation( bytes ) );
317                         break;
318                 case 0x04:
319                         inactive_event();
320                         cout << "host connection error" << bytes << endl;
321                         break;
322                 case 0x14:
323                         probe_emulation( bytes );
324                         break;
325                 default:
326                         cout << "unknown sysex: " << bytes << endl;
327         }
328 }
329
330 // converts midi messages into control_event signals
331 void MackiePort::handle_midi_any (MIDI::Parser & parser, MIDI::byte * raw_bytes, size_t count )
332 {
333         MidiByteArray bytes( count, raw_bytes );
334         try
335         {
336                 // ignore sysex messages
337                 if ( bytes[0] == MIDI::sysex ) return;
338
339                 Control & control = lookup_control( bytes );
340                 
341                 // This handles incoming bytes. Outgoing bytes
342                 // are sent by the signal handlers.
343                 switch ( control.type() )
344                 {
345                         // fader
346                         case Control::type_fader:
347                                 {
348                                         // for a BCF2000, max is 7f for high-order byte and 0x70 for low-order byte
349                                         // According to the Logic docs, these should both be 0x7f.
350                                         // Although it does mention something about only the top-order
351                                         // 10 bits out of 14 being used
352                                         int midi_pos = ( bytes[2] << 7 ) + bytes[1];
353                                         control_event( *this, control, float(midi_pos) / float(0x3fff) );
354                                 }
355                                 break;
356                                 
357                         // button
358                         case Control::type_button:
359                                 control_event( *this, control, bytes[2] == 0x7f ? press : release );
360                                 break;
361                                 
362                         // pot (jog wheel, external control)
363                         case Control::type_pot:
364                                 {
365                                         ControlState state;
366                                         
367                                         // bytes[2] & 0b01000000 (0x40) give sign
368                                         int sign = ( bytes[2] & 0x40 ) == 0 ? 1 : -1; 
369                                         // bytes[2] & 0b00111111 (0x3f) gives delta
370                                         state.ticks = ( bytes[2] & 0x3f) * sign;
371                                         state.delta = float( state.ticks ) / float( 0x3f );
372                                         
373                                         control_event( *this, control, state );
374                                 }
375                                 break;
376                         default:
377                                 cerr << "Do not understand control type " << control;
378                 }
379         }
380         catch( MackieControlException & e )
381         {
382                 cout << bytes << ' ' << e.what() << endl;
383         }
384 }