#include MidiData::MidiData(const String &midiPathFileName) : mTimerCallback(this,&MidiData::timerEvent), mMidiFile(midiPathFileName,FileIO::BigEndian), MidiTrack(mMidiFile) { insertHandler(&mTimerCallback); if(!readHeader(mMidiFile))return; ::OutputDebugString(String(MidiHeader::toString()+String("\n")).str()); setMethod(timingMethod()); } MidiData::~MidiData() { stopTimer(); mMIDIOutDevice.closeDevice(); mMIDIEventVector.size(0); } WORD MidiData::play(WORD blocking) { mPlayIndex=0; mTempoChange.remove(); if(!tracks())return FALSE; while(readTrack()); if(!makeRealTime())return FALSE; startTimer(TimerDelay); if(blocking)waitEvent(); return TRUE; } WORD MidiData::makeRealTime(void) { TimeBlock timeBlock; if(!mTempoChange.size())return FALSE; timeBlock.setTempo(mTempoChange[0].microsecsPerQtrNote()); timeBlock.setDivision(method()); timeBlock.setStartTime(getSystemTime()+TwoSecs); timeBlock.fixTimeBlock(mMIDIEvents,mMIDIEventVector); return TRUE; } CallbackData::ReturnType MidiData::timerEvent(CallbackData &/*someCallbackData*/) { DWORD currTime(getSystemTime()); if(!mMIDIOutDevice.hasDevice()||!mMIDIEventVector.size())return closeDevice(); while(mMIDIEventVector[mPlayIndex].playTime()<=currTime) { if(!mMIDIOutDevice.midiEvent(mMIDIEventVector[mPlayIndex]))return closeDevice(); if(++mPlayIndex>=mMIDIEventVector.size())return closeDevice(); } return (CallbackData::ReturnType)TRUE; } CallbackData::ReturnType MidiData::closeDevice(void) { mMIDIOutDevice.closeDevice(); return (CallbackData::ReturnType)FALSE; } // virtual overloads void MidiData::midiChannelMessage(PureEvent &midiEvent) { mMIDIEvents[midiEvent.channel()].insert(&midiEvent); return; } void MidiData::setTempo(DWORD microsecsPerQtrNote) { mTempoChange.insert(&TempoChange(microsecsPerQtrNote,0L)); return; } void MidiData::smpteFormat(const SMPTEFormat &someSMPTEFormat) { mSMPTEFormat=someSMPTEFormat; return; } void MidiData::timeSignature(const TimeInfo &/*someTimeInfo*/) { return; }