20 #include "macmidiinput.h"
21 #include "rtmidioutput.h"
22 #include "maccommon.h"
25 #include <QStringList>
30 #include <CoreFoundation/CoreFoundation.h>
31 #include <CoreMIDI/CoreMIDI.h>
36 static CFStringRef DEFAULT_PUBLIC_NAME CFSTR(
"MIDI In");
38 void MacMIDIReadProc(
const MIDIPacketList *pktlist,
39 void *refCon,
void *connRefCon );
41 class MacMIDIInputPrivate {
45 MIDIClientRef m_client;
47 MIDIEndpointRef m_endpoint;
48 MIDIEndpointRef m_source;
52 QString m_currentInput;
53 QStringList m_excludedNames;
54 QStringList m_inputDevices;
56 MacMIDIInputPrivate(MacMIDIInput *inp) :
65 m_publicName(QString::fromCFString(DEFAULT_PUBLIC_NAME))
67 internalCreate( DEFAULT_PUBLIC_NAME );
70 void internalCreate(CFStringRef name)
72 OSStatus result = noErr;
73 result = MIDIClientCreate( name , NULL, NULL, &m_client );
74 if (result != noErr) {
75 qDebug() <<
"MIDIClientCreate() err:" << result;
78 result = MIDIDestinationCreate ( m_client, name, MacMIDIReadProc, (
void*)
this, &m_endpoint );
79 if (result != noErr) {
80 qDebug() <<
"MIDIDestinationCreate() err:" << result;
83 result = MIDIInputPortCreate( m_client, name, MacMIDIReadProc, (
void *)
this, &m_port );
84 if (result != noErr) {
85 qDebug() <<
"MIDIInputPortCreate() error:" << result;
88 reloadDeviceList(
true);
91 virtual ~MacMIDIInputPrivate()
96 void internalDispose()
98 OSStatus result = noErr;
100 result = MIDIPortDispose(m_port);
101 if (result != noErr) {
102 qDebug() <<
"MIDIPortDispose() error:" << result;
106 if (m_endpoint != 0) {
107 result = MIDIEndpointDispose(m_endpoint);
108 if (result != noErr) {
109 qDebug() <<
"MIDIEndpointDispose() err:" << result;
114 result = MIDIClientDispose(m_client);
115 if (result != noErr) {
116 qDebug() <<
"MIDIClientDispose() err:" << result;
122 void reloadDeviceList(
bool advanced)
124 int num = MIDIGetNumberOfSources();
125 m_clientFilter = !advanced;
126 m_inputDevices.clear();
127 for (
int i = 0; i < num; ++i) {
128 bool excluded =
false;
129 MIDIEndpointRef dest = MIDIGetSource( i );
131 QString name = getEndpointName(dest);
132 if ( m_clientFilter &&
133 name.contains(QLatin1String(
"IAC"), Qt::CaseSensitive) )
135 if ( name.contains(m_publicName))
137 foreach(
const QString& n, m_excludedNames) {
138 if (name.contains(n)) {
144 m_inputDevices << name;
147 if (!m_currentInput.isEmpty() && m_source != 0 &&
148 !m_inputDevices.contains(m_currentInput)) {
149 m_currentInput.clear();
154 void setPublicName(QString name)
156 if (m_publicName != name) {
158 internalCreate(name.toCFString());
163 void open(QString name)
166 OSStatus result = noErr;
167 QStringList allInputDevices;
168 int num = MIDIGetNumberOfSources();
169 for (
int i = 0; i < num; ++i) {
170 MIDIEndpointRef dest = MIDIGetDestination( i );
172 allInputDevices << getEndpointName( dest );
174 index = allInputDevices.indexOf(name);
177 m_source = MIDIGetSource( index );
178 result = MIDIPortConnectSource( m_port, m_source, NULL );
179 if (result != noErr) {
180 qDebug() <<
"MIDIPortConnectSource() error:" << result;
183 m_currentInput = name;
189 OSStatus result = noErr;
191 result = MIDIPortDisconnectSource(m_port, m_source);
193 qDebug() <<
"MIDIPortDisconnectSource() error:" << result;
195 m_currentInput.clear();
199 void emitSignals(MIDIPacket* packet)
202 int status = packet->data[0] & 0xf0;
203 int channel = packet->data[0] & 0x0f;
206 case MIDI_STATUS_NOTEOFF:
207 if(m_out != 0 && m_thruEnabled)
208 m_out->sendNoteOff(channel, packet->data[1], packet->data[2]);
209 emit m_inp->midiNoteOff(channel, packet->data[1], packet->data[2]);
211 case MIDI_STATUS_NOTEON:
212 if(m_out != 0 && m_thruEnabled)
213 m_out->sendNoteOn(channel, packet->data[1], packet->data[2]);
214 emit m_inp->midiNoteOn(channel, packet->data[1], packet->data[2]);
216 case MIDI_STATUS_KEYPRESURE:
217 if(m_out != 0 && m_thruEnabled)
218 m_out->sendKeyPressure(channel, packet->data[1], packet->data[2]);
219 emit m_inp->midiKeyPressure(channel, packet->data[1], packet->data[2]);
221 case MIDI_STATUS_CONTROLCHANGE:
222 if(m_out != 0 && m_thruEnabled)
223 m_out->sendController(channel, packet->data[1], packet->data[2]);
224 emit m_inp->midiController(channel, packet->data[1], packet->data[2]);
226 case MIDI_STATUS_PROGRAMCHANGE:
227 if(m_out != 0 && m_thruEnabled)
228 m_out->sendProgram(channel, packet->data[1]);
229 emit m_inp->midiProgram(channel, packet->data[1]);
231 case MIDI_STATUS_CHANNELPRESSURE:
232 if(m_out != 0 && m_thruEnabled)
233 m_out->sendChannelPressure(channel, packet->data[1]);
234 emit m_inp->midiChannelPressure(channel, packet->data[1]);
236 case MIDI_STATUS_PITCHBEND:
237 value = (packet->data[1] + packet->data[2] * 0x80) - 8192;
238 if(m_out != 0 && m_thruEnabled)
239 m_out->sendPitchBend(channel, value);
240 emit m_inp->midiPitchBend(channel, value);
242 case MIDI_STATUS_SYSEX:
243 data = QByteArray((
const char *)packet->data, packet->length);
244 if(m_out != 0 && m_thruEnabled)
245 m_out->sendSysex(data);
246 emit m_inp->midiSysex(data);
249 qDebug() <<
"status?" << status;
255 void MacMIDIReadProc(
const MIDIPacketList *pktlist,
256 void *refCon,
void *connRefCon )
259 MacMIDIInputPrivate *obj = NULL;
261 obj = static_cast<MacMIDIInputPrivate*>(refCon);
263 MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
264 for (
unsigned int i = 0; i < pktlist->numPackets; ++i) {
266 obj->emitSignals(packet);
267 packet = MIDIPacketNext(packet);
271 MacMIDIInput::MacMIDIInput(
QObject *parent) :
272 MIDIInput(parent), d(new MacMIDIInputPrivate(this))
276 MacMIDIInput::~MacMIDIInput()
281 void MacMIDIInput::initialize(QSettings *settings)
286 QString MacMIDIInput::backendName()
288 return QLatin1Literal(
"CoreMIDI");
291 QString MacMIDIInput::publicName()
293 return d->m_publicName;
296 void MacMIDIInput::setPublicName(QString name)
298 d->setPublicName(name);
301 QStringList MacMIDIInput::connections(
bool advanced)
303 d->reloadDeviceList(advanced);
304 return d->m_inputDevices;
307 void MacMIDIInput::setExcludedConnections(QStringList conns)
309 d->m_excludedNames = conns;
312 void MacMIDIInput::open(QString name)
317 void MacMIDIInput::close()
322 QString MacMIDIInput::currentConnection()
324 return d->m_currentInput;
327 void MacMIDIInput::setMIDIThruDevice(MIDIOutput *device)
332 void MacMIDIInput::enableMIDIThru(
bool enable)
334 d->m_thruEnabled = enable;
337 bool MacMIDIInput::isEnabledMIDIThru()
339 return d->m_thruEnabled && d->m_out != 0;
The QObject class is the base class of all Qt objects.