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.
18 #include "mackie_port.h"
20 #include "mackie_control_exception.h"
21 #include "mackie_control_protocol.h"
22 #include "mackie_midi_builder.h"
26 #include <midi++/types.h>
27 #include <midi++/port.h>
28 #include <sigc++/sigc++.h>
29 #include <boost/shared_array.hpp>
30 #include <ardour/configuration.h>
37 using namespace Mackie;
39 // The MCU sysex header
40 MidiByteArray mackie_sysex_hdr ( 5, MIDI::sysex, 0x0, 0x0, 0x66, 0x10 );
42 // The MCU extender sysex header
43 MidiByteArray mackie_sysex_hdr_xt ( 5, MIDI::sysex, 0x0, 0x0, 0x66, 0x11 );
45 MackiePort::MackiePort( MackieControlProtocol & mcp, MIDI::Port & port, int number, port_type_t port_type )
46 : SurfacePort( port, number )
48 , _port_type( port_type )
50 , _initialising( true )
52 //cout << "MackiePort::MackiePort" <<endl;
55 MackiePort::~MackiePort()
57 //cout << "~MackiePort" << endl;
59 //cout << "~MackiePort finished" << endl;
62 int MackiePort::strips() const
64 if ( _port_type == mcu )
68 // BCF2000 only has 8 faders, so reserve one for master
69 case bcf2000: return 7;
70 case mackie: return 8;
73 throw MackieControlException( "MackiePort::strips: don't know what emulation we're using" );
78 // must be an extender, ie no master fader
83 // should really be in MackiePort
84 void MackiePort::open()
86 //cout << "MackiePort::open " << *this << endl;
87 _sysex = port().input()->sysex.connect( ( mem_fun (*this, &MackiePort::handle_midi_sysex) ) );
89 // make sure the device is connected
93 void MackiePort::close()
95 //cout << "MackiePort::close" << endl;
101 // TODO emit a "closing" signal?
102 //cout << "MackiePort::close finished" << endl;
105 const MidiByteArray & MackiePort::sysex_hdr() const
107 switch ( _port_type )
109 case mcu: return mackie_sysex_hdr;
110 case ext: return mackie_sysex_hdr_xt;
112 cout << "MackiePort::sysex_hdr _port_type not known" << endl;
113 return mackie_sysex_hdr;
116 Control & MackiePort::lookup_control( const MidiByteArray & bytes )
118 Control * control = 0;
120 MIDI::byte midi_type = bytes[0] & 0xf0; //0b11110000
124 case MackieMidiBuilder::midi_fader_id:
125 midi_id = bytes[0] & 0x0f;
126 control = _mcp.surface().faders[midi_id];
130 os << "control for fader" << midi_id << " is null";
131 throw MackieControlException( os.str() );
136 case MackieMidiBuilder::midi_button_id:
138 control = _mcp.surface().buttons[midi_id];
142 os << "control for button" << midi_id << " is null";
143 throw MackieControlException( os.str() );
147 // pot (jog wheel, external control)
148 case MackieMidiBuilder::midi_pot_id:
149 midi_id = bytes[1] & 0x1f;
150 control = _mcp.surface().pots[midi_id];
154 os << "control for button" << midi_id << " is null";
155 throw MackieControlException( os.str() );
161 os << "Cannot find control for " << bytes;
162 throw MackieControlException( os.str() );
167 MidiByteArray calculate_challenge_response( MidiByteArray::iterator begin, MidiByteArray::iterator end )
170 back_insert_iterator<MidiByteArray> back ( l );
171 copy( begin, end, back );
173 MidiByteArray retval;
175 // this is how to calculate the response to the challenge.
176 // from the Logic docs.
177 retval << ( 0x7f & ( l[0] + ( l[1] ^ 0xa ) - l[3] ) );
178 retval << ( 0x7f & ( ( l[2] >> l[3] ) ^ ( l[0] + l[3] ) ) );
179 retval << ( 0x7f & ( l[3] - ( l[2] << 2 ) ^ ( l[0] | l[1] ) ) );
180 retval << ( 0x7f & ( l[1] - l[2] + ( 0xf0 ^ ( l[3] << 4 ) ) ) );
185 // not used right now
186 MidiByteArray MackiePort::host_connection_query( MidiByteArray & bytes )
188 // handle host connection query
189 //cout << "host connection query: " << bytes << endl;
191 if ( bytes.size() != 18 )
193 finalise_init( false );
195 os << "expecting 18 bytes, read " << bytes << " from " << port().name();
196 throw MackieControlException( os.str() );
199 // build and send host connection reply
200 MidiByteArray response;
202 copy( bytes.begin() + 6, bytes.begin() + 6 + 7, back_inserter( response ) );
203 response << calculate_challenge_response( bytes.begin() + 6 + 7, bytes.begin() + 6 + 7 + 4 );
207 // not used right now
208 MidiByteArray MackiePort::host_connection_confirmation( const MidiByteArray & bytes )
210 //cout << "host_connection_confirmation: " << bytes << endl;
212 // decode host connection confirmation
213 if ( bytes.size() != 14 )
215 finalise_init( false );
217 os << "expecting 14 bytes, read " << bytes << " from " << port().name();
218 throw MackieControlException( os.str() );
221 // send version request
222 return MidiByteArray( 2, 0x13, 0x00 );
225 void MackiePort::probe_emulation( const MidiByteArray & bytes )
227 //cout << "MackiePort::probe_emulation: " << bytes.size() << ", " << bytes << endl;
228 string version_string;
229 for ( int i = 6; i < 11; ++i ) version_string.append( 1, (char)bytes[i] );
230 //cout << "version_string: " << version_string << endl;
232 // TODO investigate using serial number. Also, possibly size of bytes might
233 // give an indication. Also, apparently MCU sends non-documented messages
237 cout << "MackiePort::probe_emulation out of sequence." << endl;
241 finalise_init( true );
244 void MackiePort::init()
246 //cout << "MackiePort::init" << endl;
248 _initialising = true;
250 //cout << "MackiePort::lock acquired" << endl;
251 // emit pre-init signal
254 // kick off initialisation. See docs in header file for init()
256 // bypass the init sequence because sometimes the first
257 // message doesn't get to the unit, and there's no way
258 // to do a timed lock in Glib.
259 //write_sysex ( MidiByteArray ( 2, 0x13, 0x00 ) );
261 finalise_init( true );
264 void MackiePort::finalise_init( bool yn )
266 //cout << "MackiePort::finalise_init" << endl;
267 bool emulation_ok = false;
269 // probing doesn't work very well, so just use a config variable
270 // to set the emulation mode
271 if ( _emulation == none )
273 if ( ARDOUR::Config->get_mackie_emulation() == "bcf" )
275 _emulation = bcf2000;
278 else if ( ARDOUR::Config->get_mackie_emulation() == "mcu" )
285 cout << "unknown mackie emulation: " << ARDOUR::Config->get_mackie_emulation() << endl;
286 emulation_ok = false;
290 yn = yn && emulation_ok;
292 SurfacePort::active( yn );
298 // start handling messages from controls
299 _any = port().input()->any.connect( ( mem_fun (*this, &MackiePort::handle_midi_any) ) );
301 _initialising = false;
306 bool MackiePort::wait_for_init()
308 Glib::Mutex::Lock lock( init_mutex );
309 while ( _initialising )
311 //cout << "MackiePort::wait_for_active waiting" << endl;
312 init_cond.wait( init_mutex );
313 //cout << "MackiePort::wait_for_active released" << endl;
315 //cout << "MackiePort::wait_for_active returning" << endl;
316 return SurfacePort::active();
319 void MackiePort::handle_midi_sysex (MIDI::Parser & parser, MIDI::byte * raw_bytes, size_t count )
321 MidiByteArray bytes( count, raw_bytes );
322 //cout << "handle_midi_sysex: " << bytes << endl;
326 // not used right now
327 write_sysex( host_connection_query( bytes ) );
330 // not used right now
331 write_sysex( host_connection_confirmation( bytes ) );
335 cout << "host connection error" << bytes << endl;
338 probe_emulation( bytes );
341 cout << "unknown sysex: " << bytes << endl;
345 // converts midi messages into control_event signals
346 void MackiePort::handle_midi_any (MIDI::Parser & parser, MIDI::byte * raw_bytes, size_t count )
348 MidiByteArray bytes( count, raw_bytes );
351 // ignore sysex messages
352 if ( bytes[0] == MIDI::sysex ) return;
354 Control & control = lookup_control( bytes );
356 // This handles incoming bytes. Outgoing bytes
357 // are sent by the signal handlers.
358 switch ( control.type() )
361 case Control::type_fader:
363 // for a BCF2000, max is 7f for high-order byte and 0x70 for low-order byte
364 // According to the Logic docs, these should both be 0x7f.
365 // Although it does mention something about only the top-order
366 // 10 bits out of 14 being used
367 int midi_pos = ( bytes[2] << 7 ) + bytes[1];
368 control_event( *this, control, float(midi_pos) / float(0x3fff) );
373 case Control::type_button:
374 control_event( *this, control, bytes[2] == 0x7f ? press : release );
377 // pot (jog wheel, external control)
378 case Control::type_pot:
382 // bytes[2] & 0b01000000 (0x40) give sign
383 int sign = ( bytes[2] & 0x40 ) == 0 ? 1 : -1;
384 // bytes[2] & 0b00111111 (0x3f) gives delta
385 state.ticks = ( bytes[2] & 0x3f) * sign;
386 state.delta = float( state.ticks ) / float( 0x3f );
388 control_event( *this, control, state );
392 cerr << "Do not understand control type " << control;
395 catch( MackieControlException & e )
397 //cout << bytes << ' ' << e.what() << endl;