void CALLBACK Win32MidiIn::midiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { Q_UNUSED(dwParam2); SynthRoute *synthRoute = (SynthRoute *)dwInstance; LPMIDIHDR pMIDIhdr = (LPMIDIHDR)dwParam1; if (wMsg == MIM_LONGDATA) { if (pMIDIhdr->dwBytesRecorded == 0) { // 0 length means returning the buffer to the application when closing return; } synthRoute->pushMIDISysex((BYTE *)pMIDIhdr->lpData, pMIDIhdr->dwBytesRecorded, MasterClock::getClockNanos()); // Add SysEx Buffer for reuse if (midiInAddBuffer(hMidiIn, pMIDIhdr, sizeof(MIDIHDR)) != MMSYSERR_NOERROR) { QMessageBox::critical(NULL, "Win32MidiIn Error", "Failed to add SysEx Buffer for reuse"); return; } return; } if (wMsg == MIM_DATA) synthRoute->pushMIDIShortMessage(dwParam1, MasterClock::getClockNanos()); }
void SMFProcessor::run() { MidiSession *session = driver->createMidiSession(QFileInfo(fileName).fileName()); SynthRoute *synthRoute = session->getSynthRoute(); const MidiEventList &midiEvents = parser.getMIDIEvents(); midiTick = parser.getMidiTick(); quint32 totalSeconds = estimateRemainingTime(midiEvents, 0); MasterClockNanos startNanos = MasterClock::getClockNanos(); MasterClockNanos currentNanos = startNanos; for (int i = 0; i < midiEvents.count(); i++) { const MidiEvent &e = midiEvents.at(i); currentNanos += e.getTimestamp() * midiTick; while (!stopProcessing && synthRoute->getState() == SynthRouteState_OPEN) { if (bpmUpdated) { bpmUpdated = false; totalSeconds = (currentNanos - startNanos) / MasterClock::NANOS_PER_SECOND + estimateRemainingTime(midiEvents, i + 1); } if (driver->seekPosition > -1) { SMFProcessor::sendAllNotesOff(synthRoute); MasterClockNanos seekNanos = totalSeconds * driver->seekPosition * MasterClock::NANOS_PER_MILLISECOND; MasterClockNanos eventNanos = currentNanos - e.getTimestamp() * midiTick - startNanos; if (seekNanos < eventNanos) { i = 0; eventNanos = 0; midiTick = parser.getMidiTick(); emit driver->tempoUpdated(0); } i = seek(synthRoute, midiEvents, i, seekNanos, eventNanos) - 1; currentNanos = MasterClock::getClockNanos(); startNanos = currentNanos - seekNanos; break; } emit driver->playbackTimeChanged(MasterClock::getClockNanos() - startNanos, totalSeconds); MasterClockNanos delay = currentNanos - MasterClock::getClockNanos(); if (driver->fastForwardingFactor > 1) { MasterClockNanos timeShift = delay - (delay / driver->fastForwardingFactor); delay -= timeShift; currentNanos -= timeShift; startNanos -= timeShift; } if (delay < MasterClock::NANOS_PER_MILLISECOND) break; usleep(((delay < MAX_SLEEP_TIME ? delay : MAX_SLEEP_TIME) - MasterClock::NANOS_PER_MILLISECOND) / MasterClock::NANOS_PER_MICROSECOND); } if (stopProcessing || synthRoute->getState() != SynthRouteState_OPEN) break; if (driver->seekPosition > -1) { driver->seekPosition = -1; continue; } switch (e.getType()) { case SHORT_MESSAGE: synthRoute->pushMIDIShortMessage(e.getShortMessage(), currentNanos); break; case SYSEX: synthRoute->pushMIDISysex(e.getSysexData(), e.getSysexLen(), currentNanos); break; case SET_TEMPO: { uint tempo = e.getShortMessage(); midiTick = parser.getMidiTick(tempo); emit driver->tempoUpdated(MidiParser::MICROSECONDS_PER_MINUTE / tempo); break; } default: break; } } SMFProcessor::sendAllNotesOff(synthRoute); emit driver->playbackTimeChanged(0, 0); qDebug() << "SMFDriver: processor thread stopped"; driver->deleteMidiSession(session); if (!stopProcessing) emit driver->playbackFinished(); }