26 #include "winmidiinput.h"
31 static QLatin1Literal DEFAULT_PUBLIC_NAME = QLatin1Literal(
"MIDI In");
33 void CALLBACK midiCallback( HMIDIIN hMidiIn,
40 class WinMIDIInput::WinMIDIInputPrivate {
48 QString m_currentInput;
49 QStringList m_excludedNames;
50 QMap<int,QString> m_inputDevices;
52 WinMIDIInputPrivate(WinMIDIInput *inp):
58 m_publicName(DEFAULT_PUBLIC_NAME)
60 reloadDeviceList(
true);
63 int deviceIndex(
const QString& newDevice )
66 QMap<int,QString>::ConstIterator it;
67 for( it = m_inputDevices.constBegin();
68 it != m_inputDevices.constEnd(); ++it ) {
69 if (it.value() == newDevice) {
77 void open(QString name) {
79 if (name != m_currentInput) {
82 reloadDeviceList(!m_clientFilter);
83 int dev = deviceIndex(name);
85 res = midiInOpen(&m_handle, dev, (DWORD_PTR) midiCallback, (DWORD_PTR)
this, CALLBACK_FUNCTION | MIDI_IO_STATUS );
86 if (res != MMSYSERR_NOERROR)
87 qDebug() <<
"midiInOpen() err:" << mmErrorString(res);
88 m_currentInput = name;
96 res = midiInReset( m_handle );
97 if (res != MMSYSERR_NOERROR)
98 qDebug() <<
"midiInReset() err:" << mmErrorString(res);
99 res = midiInClose( m_handle );
100 if (res != MMSYSERR_NOERROR)
101 qDebug() <<
"midiInClose() err:" << mmErrorString(res);
104 m_currentInput.clear();
107 void reloadDeviceList(
bool advanced)
110 MIDIINCAPS deviceCaps;
112 unsigned int dev, max = midiInGetNumDevs();
113 m_inputDevices.clear();
114 m_clientFilter = !advanced;
116 for ( dev = 0; dev < max; ++dev) {
117 bool excluded =
false;
118 res = midiInGetDevCaps( dev, &deviceCaps,
sizeof(MIDIINCAPS));
119 if (res != MMSYSERR_NOERROR)
122 devName = QString::fromWCharArray(deviceCaps.szPname);
124 devName = QString::fromLocal8Bit(deviceCaps.szPname);
126 foreach(
const QString& n, m_excludedNames) {
127 if (devName.startsWith(n)) {
133 m_inputDevices[dev] = devName;
137 void setPublicName(QString name)
139 if (m_publicName != name) {
144 void emitSignals(
int status,
int channel,
int data1,
int data2)
147 case MIDI_STATUS_NOTEOFF:
148 if(m_out != 0 && m_thruEnabled)
149 m_out->sendNoteOff(channel, data1, data2);
150 emit m_inp->midiNoteOff(channel, data1, data2);
152 case MIDI_STATUS_NOTEON:
153 if(m_out != 0 && m_thruEnabled)
154 m_out->sendNoteOn(channel, data1, data2);
155 emit m_inp->midiNoteOn(channel, data1, data2);
157 case MIDI_STATUS_KEYPRESURE:
158 if(m_out != 0 && m_thruEnabled)
159 m_out->sendKeyPressure(channel, data1, data2);
160 emit m_inp->midiKeyPressure(channel, data1, data2);
162 case MIDI_STATUS_CONTROLCHANGE:
163 if(m_out != 0 && m_thruEnabled)
164 m_out->sendController(channel, data1, data2);
165 emit m_inp->midiController(channel, data1, data2);
167 case MIDI_STATUS_PROGRAMCHANGE:
168 if(m_out != 0 && m_thruEnabled)
169 m_out->sendProgram(channel, data1);
170 emit m_inp->midiProgram(channel, data1);
172 case MIDI_STATUS_CHANNELPRESSURE:
173 if(m_out != 0 && m_thruEnabled)
174 m_out->sendChannelPressure(channel, data1);
175 emit m_inp->midiChannelPressure(channel, data1);
177 case MIDI_STATUS_PITCHBEND: {
178 int value = (data1 + data2 * 0x80) - 8192;
179 if(m_out != 0 && m_thruEnabled)
180 m_out->sendPitchBend(channel, value);
181 emit m_inp->midiPitchBend(channel, value);
185 qDebug() <<
"status?" << status;
189 void emitSysex(QByteArray data)
191 if(m_out != 0 && m_thruEnabled)
192 m_out->sendSysex(data);
193 emit m_inp->midiSysex(data);
196 QString mmErrorString(MMRESULT err)
201 midiInGetErrorText(err, &buffer[0],
sizeof(buffer));
202 errstr = QString::fromUtf16((
const ushort*)buffer);
205 midiOutGetErrorText(err, &buffer[0],
sizeof(buffer));
206 errstr = QString::fromLocal8Bit(buffer);
213 void CALLBACK midiCallback( HMIDIIN hMidiIn,
215 DWORD_PTR dwInstance,
221 WinMIDIInput::WinMIDIInputPrivate*
object = (WinMIDIInput::WinMIDIInputPrivate*) dwInstance;
231 qDebug() <<
"Errors";
234 qDebug() <<
"Sysex data";
238 int status = dwParam1 & 0xf0;
239 int channel = dwParam1 & 0x0f;
240 int data1 = (dwParam1 & 0x7f00) >> 8;
241 int data2 = (dwParam1 & 0x7f0000) >> 16;
242 object->emitSignals(status, channel, data1, data2);
246 qDebug() <<
"unknown:" << hex << wMsg;
251 WinMIDIInput::WinMIDIInput(
QObject *parent) :
252 MIDIInput(parent), d(new WinMIDIInputPrivate(this))
255 WinMIDIInput::~WinMIDIInput()
260 void WinMIDIInput::initialize(QSettings *settings)
265 QString WinMIDIInput::backendName()
267 return QLatin1Literal(
"Windows MM");
270 QString WinMIDIInput::publicName()
272 return d->m_publicName;
275 void WinMIDIInput::setPublicName(QString name)
277 d->setPublicName(name);
280 QStringList WinMIDIInput::connections(
bool advanced)
282 d->reloadDeviceList(advanced);
283 return d->m_inputDevices.values();
286 void WinMIDIInput::setExcludedConnections(QStringList conns)
288 d->m_excludedNames = conns;
291 void WinMIDIInput::open(QString name)
296 void WinMIDIInput::close()
301 QString WinMIDIInput::currentConnection()
303 return d->m_currentInput;
306 void WinMIDIInput::setMIDIThruDevice(MIDIOutput *device)
311 void WinMIDIInput::enableMIDIThru(
bool enable)
313 d->m_thruEnabled = enable;
316 bool WinMIDIInput::isEnabledMIDIThru()
318 return d->m_thruEnabled && d->m_out != 0;
The QObject class is the base class of all Qt objects.