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 res = midiInStart(m_handle);
89 if (res != MMSYSERR_NOERROR)
90 qDebug() <<
"midiInStart() err:" << mmErrorString(res);
91 m_currentInput = name;
99 res = midiInStop(m_handle);
100 if (res != MMSYSERR_NOERROR)
101 qDebug() <<
"midiInStop() err:" << mmErrorString(res);
102 res = midiInReset( m_handle );
103 if (res != MMSYSERR_NOERROR)
104 qDebug() <<
"midiInReset() err:" << mmErrorString(res);
105 res = midiInClose( m_handle );
106 if (res != MMSYSERR_NOERROR)
107 qDebug() <<
"midiInClose() err:" << mmErrorString(res);
110 m_currentInput.clear();
113 void reloadDeviceList(
bool advanced)
116 MIDIINCAPS deviceCaps;
118 unsigned int dev, max = midiInGetNumDevs();
119 m_inputDevices.clear();
120 m_clientFilter = !advanced;
122 for ( dev = 0; dev < max; ++dev) {
123 bool excluded =
false;
124 res = midiInGetDevCaps( dev, &deviceCaps,
sizeof(MIDIINCAPS));
125 if (res != MMSYSERR_NOERROR)
128 devName = QString::fromWCharArray(deviceCaps.szPname);
130 devName = QString::fromLocal8Bit(deviceCaps.szPname);
132 foreach(
const QString& n, m_excludedNames) {
133 if (devName.startsWith(n)) {
139 m_inputDevices[dev] = devName;
143 void setPublicName(QString name)
145 if (m_publicName != name) {
150 void emitSignals(
int status,
int channel,
int data1,
int data2)
153 case MIDI_STATUS_NOTEOFF:
154 if(m_out != 0 && m_thruEnabled)
155 m_out->sendNoteOff(channel, data1, data2);
156 emit m_inp->midiNoteOff(channel, data1, data2);
158 case MIDI_STATUS_NOTEON:
159 if(m_out != 0 && m_thruEnabled)
160 m_out->sendNoteOn(channel, data1, data2);
161 emit m_inp->midiNoteOn(channel, data1, data2);
163 case MIDI_STATUS_KEYPRESURE:
164 if(m_out != 0 && m_thruEnabled)
165 m_out->sendKeyPressure(channel, data1, data2);
166 emit m_inp->midiKeyPressure(channel, data1, data2);
168 case MIDI_STATUS_CONTROLCHANGE:
169 if(m_out != 0 && m_thruEnabled)
170 m_out->sendController(channel, data1, data2);
171 emit m_inp->midiController(channel, data1, data2);
173 case MIDI_STATUS_PROGRAMCHANGE:
174 if(m_out != 0 && m_thruEnabled)
175 m_out->sendProgram(channel, data1);
176 emit m_inp->midiProgram(channel, data1);
178 case MIDI_STATUS_CHANNELPRESSURE:
179 if(m_out != 0 && m_thruEnabled)
180 m_out->sendChannelPressure(channel, data1);
181 emit m_inp->midiChannelPressure(channel, data1);
183 case MIDI_STATUS_PITCHBEND: {
184 int value = (data1 + data2 * 0x80) - 8192;
185 if(m_out != 0 && m_thruEnabled)
186 m_out->sendPitchBend(channel, value);
187 emit m_inp->midiPitchBend(channel, value);
191 qDebug() <<
"MIDI in status?" << status;
195 void emitSysex(QByteArray data)
197 if(m_out != 0 && m_thruEnabled)
198 m_out->sendSysex(data);
199 emit m_inp->midiSysex(data);
202 QString mmErrorString(MMRESULT err)
207 midiInGetErrorText(err, &buffer[0],
sizeof(buffer));
208 errstr = QString::fromUtf16((
const ushort*)buffer);
211 midiOutGetErrorText(err, &buffer[0],
sizeof(buffer));
212 errstr = QString::fromLocal8Bit(buffer);
219 void CALLBACK midiCallback( HMIDIIN hMidiIn,
221 DWORD_PTR dwInstance,
227 WinMIDIInput::WinMIDIInputPrivate*
object = (WinMIDIInput::WinMIDIInputPrivate*) dwInstance;
230 qDebug() <<
"Open input" << hMidiIn;
233 qDebug() <<
"Close input" << hMidiIn;
237 qDebug() <<
"Errors input";
240 qDebug() <<
"Sysex data input";
244 int status = dwParam1 & 0xf0;
245 int channel = dwParam1 & 0x0f;
246 int data1 = (dwParam1 & 0x7f00) >> 8;
247 int data2 = (dwParam1 & 0x7f0000) >> 16;
248 object->emitSignals(status, channel, data1, data2);
252 qDebug() <<
"unknown input message:" << hex << wMsg;
257 WinMIDIInput::WinMIDIInput(
QObject *parent) :
258 MIDIInput(parent), d(new WinMIDIInputPrivate(this))
261 WinMIDIInput::~WinMIDIInput()
266 void WinMIDIInput::initialize(QSettings *settings)
271 QString WinMIDIInput::backendName()
273 return QLatin1Literal(
"Windows MM");
276 QString WinMIDIInput::publicName()
278 return d->m_publicName;
281 void WinMIDIInput::setPublicName(QString name)
283 d->setPublicName(name);
286 QStringList WinMIDIInput::connections(
bool advanced)
288 d->reloadDeviceList(advanced);
289 return d->m_inputDevices.values();
292 void WinMIDIInput::setExcludedConnections(QStringList conns)
294 d->m_excludedNames = conns;
297 void WinMIDIInput::open(QString name)
302 void WinMIDIInput::close()
307 QString WinMIDIInput::currentConnection()
309 return d->m_currentInput;
312 void WinMIDIInput::setMIDIThruDevice(MIDIOutput *device)
317 void WinMIDIInput::enableMIDIThru(
bool enable)
319 d->m_thruEnabled = enable;
322 bool WinMIDIInput::isEnabledMIDIThru()
324 return d->m_thruEnabled && d->m_out != 0;
The QObject class is the base class of all Qt objects.