Here's an old .cpp file I wrote, which creates a window (invisible) that does MIDI playing. You can probably take excerpts from it. The purpose of the separate window was to have a separate message queue dedicated to MIDI messages only; you can easily put this in any class you like, and simply intercept the relevant messages. I think you only need to handle the MM_MCINOTIFY message.
It was written for Borland C++, so the window objects are OWL, not MFC, but you could easily port this, I'm sure.
.h file:
Code:
#ifndef _MIDIWIN_H
#define _MIDIWIN_H
#include <windows.h>
#include <owl\window.h>
#include <mmsystem.h>
class MidiWindow : public TWindow{
public:
MidiWindow(TWindow*,const char *);
~MidiWindow();
int Play(const char *,bool loop = false);
//void WaitPlay(const char *, bool loop = false);
void Stop();
bool IsPlaying();
void EvSetFocus(THandle);
LRESULT MciNotify(WPARAM, LPARAM);
DECLARE_RESPONSE_TABLE(MidiWindow);
private:
void PlayAgain(bool loop = true);
bool isOpen;
bool repeat;
MCI_OPEN_PARMS midiParams;
} *MIDI;
#endif
.cpp file:
Code:
#include "midiwin.h"
DEFINE_RESPONSE_TABLE1(MidiWindow,TWindow)
EV_MESSAGE(MM_MCINOTIFY, MciNotify),
EV_WM_SETFOCUS,
END_RESPONSE_TABLE;
MidiWindow::MidiWindow(TWindow * twp, const char * ccp) : TWindow(twp,ccp){
isOpen = false;
}
MidiWindow::~MidiWindow(){
Stop();
}
LRESULT MidiWindow::MciNotify(WPARAM, LPARAM){ // this is called whenever a MIDI stops.
if (IsPlaying()) return 0; // If we've started playing between message generation and message processing, quit.
if (repeat) PlayAgain();
return 0;
}
int MidiWindow::Play(const char * file, bool rep){
// Stop/close the device
Stop();
// Set parameters for playback
midiParams.dwCallback = (unsigned long)HWindow;
midiParams.lpstrDeviceType = (LPCSTR)MCI_DEVTYPE_SEQUENCER;
midiParams.lpstrElementName = file;
//Open the device
if ((mciSendCommand(0, MCI_OPEN, MCI_WAIT|MCI_OPEN_ELEMENT|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID, (DWORD)(LPVOID)&midiParams))){
return 1;
}
isOpen = true;
//Start the MIDI, set the notify flag to tell us when we stop.
if ((mciSendCommand(midiParams.wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)(LPVOID)&midiParams))){
Stop();
return 1;
}
//Set repeat flag
repeat = rep;
return 0;
}
void MidiWindow::Stop(){ // Stops playback + closes device
repeat = false;
if (isOpen) mciSendCommand(midiParams.wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD)(LPVOID)&midiParams);
isOpen = false;
}
void MidiWindow::PlayAgain(bool rep){
// Stop/close the device
Stop();
// Open the device
if ((mciSendCommand(0, MCI_OPEN, MCI_WAIT|MCI_OPEN_ELEMENT|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID, (DWORD)(LPVOID)&midiParams))){
return;
}
isOpen = true;
// Play the MIDI
if ((mciSendCommand(midiParams.wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)(LPVOID)&midiParams))){
Stop();
return;
}
// Set repeat flag
repeat = rep;
}
void MidiWindow::EvSetFocus(THandle){ // Make sure we DON'T receive the focus, because we don't want it.
Parent->SetFocus();
}
bool MidiWindow::IsPlaying(){
if (!isOpen) return false; // if we don't have a MIDI device open, we can't be playing
// Set up structures to query device
DWORD flags = MCI_WAIT | MCI_STATUS_ITEM;
MCI_STATUS_PARMS statusParms;
statusParms.dwItem = MCI_STATUS_MODE;
// Ask the device what it's doing
mciSendCommand(midiParams.wDeviceID, MCI_STATUS, flags, (DWORD)(LPVOID) &statusParms);
return (statusParms.dwReturn == MCI_MODE_PLAY);
}