Merged with trunk R1612.
[ardour.git] / libs / surfaces / mackie / mackie_port.h
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 #ifndef mackie_port_h
19 #define mackie_port_h
20
21 #include "surface_port.h"
22
23 #include <midi++/types.h>
24 #include <sigc++/signal.h>
25 #include <sigc++/connection.h>
26
27 #include <glibmm/thread.h>
28
29 #include "midi_byte_array.h"
30 #include "types.h"
31
32 namespace MIDI {
33         class Port;
34         class Parser;
35 }
36
37 class MackieControlProtocol;
38
39 namespace Mackie
40 {
41
42 class MackiePort : public SurfacePort
43 {
44 public:
45         enum port_type_t { mcu, ext };
46         enum emulation_t { none, mackie, bcf2000 };
47         
48         MackiePort( MackieControlProtocol & mcp, MIDI::Port & port, int number, port_type_t = mcu );
49         ~MackiePort();
50
51         virtual void open();
52         virtual void close();
53
54         /// MCU and extenders have different sysex headers
55         virtual const MidiByteArray & sysex_hdr() const;
56
57         /// Handle device initialisation
58         void handle_midi_sysex( MIDI::Parser &, MIDI::byte *, size_t );
59
60         /// Handle all control messags
61         void handle_midi_any( MIDI::Parser &, MIDI::byte *, size_t );
62         
63         Control & lookup_control( const MidiByteArray & bytes );
64         
65         /// return the number of strips associated with this port
66         virtual int strips() const;
67
68         /// Block until the port has finished initialising, and then return
69         /// whether the intialisation succeeded
70         bool wait_for_init();
71         
72         emulation_t emulation() const { return _emulation; }
73         
74 protected:
75         /**
76                 The initialisation sequence is fairly complex. First a lock is acquired
77                 so that a condition can be used to signal the end of the init process.
78                 Then a sysex is sent to the device. The response to the sysex
79                 is handled by a switch in handle_midi_sysex which calls one of the
80                 other methods.
81                 
82                 However, windows DAWs ignore the documented init sequence and so we
83                 do too. Thanks to Essox for helping with this.
84                 
85                 So we use the version firmware to figure out what device is on
86                 the other end of the cable.
87         */
88         void init();
89
90         /**
91                 Once the device is initialised, finalise_init(true) is called, which
92                 releases the lock and signals the condition, and starts handling incoming
93                 messages. finalise_init(false) will also release the lock but doesn't
94                 start handling messages.
95         */
96         void finalise_init( bool yn );
97
98         MidiByteArray host_connection_query( MidiByteArray & bytes );
99         MidiByteArray host_connection_confirmation( const MidiByteArray & bytes );
100
101         /**
102                 Will set _emulation to what it thinks is correct, based
103                 on responses from the device. Or get/set parameters. Or
104                 environment variables. Or existence of a file.
105         */
106         void probe_emulation( const MidiByteArray & bytes );
107
108 private:
109         MackieControlProtocol & _mcp;
110         port_type_t _port_type;
111         sigc::connection _any;
112         sigc::connection _sysex;
113         emulation_t _emulation;
114
115         bool _initialising;
116         Glib::Cond init_cond;
117         Glib::Mutex init_mutex;
118 };
119
120 }
121
122 #endif