21 #include <QStringList>
23 #include <QVarLengthArray>
27 #include "winmidioutput.h"
33 WinMIDIPacket() : dwPacket(0) {}
35 quint8 data[
sizeof(DWORD)];
38 static QLatin1Literal DEFAULT_PUBLIC_NAME = QLatin1Literal(
"MIDI Out");
40 void CALLBACK midiCallback( HMIDIOUT hmo,
46 class WinMIDIOutput::WinMIDIOutputPrivate {
51 QString m_currentOutput;
52 QMap<int,QString> m_outputDevices;
53 MIDIHDR m_midiSysexHdr;
54 QByteArray m_sysexBuffer;
55 QStringList m_excludedNames;
57 WinMIDIOutputPrivate():
60 m_publicName(DEFAULT_PUBLIC_NAME)
62 reloadDeviceList(
true);
65 void reloadDeviceList(
bool advanced)
68 MIDIOUTCAPS deviceCaps;
70 unsigned int dev, max = midiOutGetNumDevs();
71 m_outputDevices.clear();
72 m_clientFilter = !advanced;
74 for ( dev = 0; dev < max; ++dev) {
75 res = midiOutGetDevCaps( dev, &deviceCaps,
sizeof(MIDIOUTCAPS));
76 if (res != MMSYSERR_NOERROR)
78 if (m_clientFilter && (deviceCaps.wTechnology == MOD_MAPPER))
81 devName = QString::fromWCharArray(deviceCaps.szPname);
83 devName = QString::fromLocal8Bit(deviceCaps.szPname);
85 m_outputDevices[dev] = devName;
87 if (!m_clientFilter) {
89 res = midiOutGetDevCaps( dev, &deviceCaps,
sizeof(MIDIOUTCAPS));
90 if (res == MMSYSERR_NOERROR) {
92 devName = QString::fromWCharArray(deviceCaps.szPname);
94 devName = QString::fromLocal8Bit(deviceCaps.szPname);
96 m_outputDevices[dev] = devName;
101 void setPublicName(QString name)
103 if (m_publicName != name) {
108 int deviceIndex(
const QString& newOutputDevice )
111 QMap<int,QString>::ConstIterator it;
112 for( it = m_outputDevices.constBegin();
113 it != m_outputDevices.constEnd(); ++it ) {
114 if (it.value() == newOutputDevice) {
122 void open(QString name)
129 reloadDeviceList(!m_clientFilter);
130 dev = deviceIndex(name);
132 res = midiOutOpen( &m_handle, dev, (DWORD_PTR) midiCallback, (DWORD_PTR)
this, CALLBACK_FUNCTION);
133 if (res != MMSYSERR_NOERROR)
134 qDebug() <<
"midiStreamOpen() err:" << mmErrorString(res);
142 res = midiOutReset( m_handle );
143 if (res != MMSYSERR_NOERROR)
144 qDebug() <<
"midiOutReset() err:" << mmErrorString(res);
145 res = midiOutClose( m_handle );
146 if (res != MMSYSERR_NOERROR)
147 qDebug() <<
"midiStreamClose() err:" << mmErrorString(res);
152 void doneHeader( LPMIDIHDR lpMidiHdr )
155 res = midiOutUnprepareHeader( m_handle, lpMidiHdr,
sizeof(MIDIHDR) );
156 if (res != MMSYSERR_NOERROR)
157 qDebug() <<
"midiOutUnprepareHeader() err:" << mmErrorString(res);
158 if ((lpMidiHdr->dwFlags & MHDR_ISSTRM) == 0)
162 void sendShortMessage(WinMIDIPacket &packet)
165 res = midiOutShortMsg( m_handle, packet.dwPacket );
166 if ( res != MMSYSERR_NOERROR )
167 qDebug() <<
"midiOutShortMsg() err:" << mmErrorString(res);
170 void sendSysexEvent(
const QByteArray& data)
173 m_sysexBuffer = data;
174 m_midiSysexHdr.lpData = (LPSTR) m_sysexBuffer.data();
175 m_midiSysexHdr.dwBufferLength = m_sysexBuffer.size();
176 m_midiSysexHdr.dwBytesRecorded = m_sysexBuffer.size();
177 m_midiSysexHdr.dwFlags = 0;
178 m_midiSysexHdr.dwUser = 0;
179 res = midiOutPrepareHeader( m_handle, &m_midiSysexHdr,
sizeof(MIDIHDR) );
180 if (res != MMSYSERR_NOERROR)
181 qDebug() <<
"midiOutPrepareHeader() err:" << mmErrorString(res);
183 res = midiOutLongMsg( m_handle, &m_midiSysexHdr,
sizeof(MIDIHDR) );
184 if (res != MMSYSERR_NOERROR)
185 qDebug() <<
"midiOutLongMsg() err:" << mmErrorString(res);
189 QString mmErrorString(MMRESULT err)
194 midiOutGetErrorText(err, &buffer[0],
sizeof(buffer));
195 errstr = QString::fromUtf16((
const ushort*)buffer);
198 midiOutGetErrorText(err, &buffer[0],
sizeof(buffer));
199 errstr = QString::fromLocal8Bit(buffer);
206 void CALLBACK midiCallback( HMIDIOUT hmo,
208 DWORD_PTR dwInstance,
215 WinMIDIOutput::WinMIDIOutputPrivate* obj = (WinMIDIOutput::WinMIDIOutputPrivate*) dwInstance;
218 obj->doneHeader( (LPMIDIHDR) dwParam1 );
227 qDebug() <<
"unknown:" << hex << wMsg;
232 WinMIDIOutput::WinMIDIOutput(
QObject *parent) :
233 MIDIOutput(parent), d(new WinMIDIOutputPrivate)
236 WinMIDIOutput::~WinMIDIOutput()
241 void WinMIDIOutput::initialize(QSettings *settings)
246 QString WinMIDIOutput::backendName()
251 QString WinMIDIOutput::publicName()
253 return d->m_publicName;
256 void WinMIDIOutput::setPublicName(QString name)
258 d->setPublicName(name);
261 QStringList WinMIDIOutput::connections(
bool advanced)
263 d->reloadDeviceList(advanced);
264 return d->m_outputDevices.values();
267 void WinMIDIOutput::setExcludedConnections(QStringList conns)
269 d->m_excludedNames = conns;
272 void WinMIDIOutput::open(QString name)
277 void WinMIDIOutput::close()
282 QString WinMIDIOutput::currentConnection()
284 return d->m_currentOutput;
287 void WinMIDIOutput::sendNoteOn(
int chan,
int note,
int vel)
289 WinMIDIPacket packet;
290 packet.data[0] = MIDI_STATUS_NOTEON | (chan & MIDI_CHANNEL_MASK);
291 packet.data[1] = note;
292 packet.data[2] = vel;
293 d->sendShortMessage(packet);
296 void WinMIDIOutput::sendNoteOff(
int chan,
int note,
int vel)
298 WinMIDIPacket packet;
299 packet.data[0] = MIDI_STATUS_NOTEOFF | (chan & MIDI_CHANNEL_MASK);
300 packet.data[1] = note;
301 packet.data[2] = vel;
302 d->sendShortMessage(packet);
305 void WinMIDIOutput::sendController(
int chan,
int control,
int value)
307 WinMIDIPacket packet;
308 packet.data[0] = MIDI_STATUS_CONTROLCHANGE | (chan & MIDI_CHANNEL_MASK);
309 packet.data[1] = control;
310 packet.data[2] = value;
311 d->sendShortMessage(packet);
314 void WinMIDIOutput::sendKeyPressure(
int chan,
int note,
int value)
316 WinMIDIPacket packet;
317 packet.data[0] = MIDI_STATUS_KEYPRESURE | (chan & MIDI_CHANNEL_MASK);
318 packet.data[1] = note;
319 packet.data[2] = value;
320 d->sendShortMessage(packet);
323 void WinMIDIOutput::sendProgram(
int chan,
int program)
325 WinMIDIPacket packet;
326 packet.data[0] = MIDI_STATUS_PROGRAMCHANGE | (chan & MIDI_CHANNEL_MASK);
327 packet.data[1] = program;
328 d->sendShortMessage(packet);
331 void WinMIDIOutput::sendChannelPressure(
int chan,
int value)
333 WinMIDIPacket packet;
334 packet.data[0] = MIDI_STATUS_CHANNELPRESSURE | (chan & MIDI_CHANNEL_MASK);
335 packet.data[1] = value;
336 d->sendShortMessage(packet);
339 void WinMIDIOutput::sendPitchBend(
int chan,
int value)
341 WinMIDIPacket packet;
342 packet.data[0] = MIDI_STATUS_PITCHBEND | (chan & MIDI_CHANNEL_MASK);
343 packet.data[1] = MIDI_LSB(value);
344 packet.data[2] = MIDI_MSB(value);
345 d->sendShortMessage(packet);
348 void WinMIDIOutput::sendSystemMsg(
const int status)
350 WinMIDIPacket packet;
351 packet.data[0] = status;
352 d->sendShortMessage(packet);
355 void WinMIDIOutput::sendSysex(
const QByteArray &data)
357 d->sendSysexEvent(data);
The QObject class is the base class of all Qt objects.