I recently posted a question about DirectMusic port GUIDs, which came up when I wrote up a class that represents a MIDI file. Here is the source for that class (in an MFC app):
midifile.h:
#pragma once
#define INITGUID
#include <guiddef.h>
#include <dmusici.h>
#undef INITGUID
class MidiFile {
private:
IDirectMusicSegment *m_seg;
bool m_playing;
IDirectMusicPerformance8 *m_performance;
static IDirectMusicLoader8 *s_loader;
public:
MidiFile(const TCHAR *filePath, const TCHAR *fileName);
~MidiFile();
void play();
void stop();
};
midifile.cpp
#include "stdafx.h"
#include "midifile.h"
IDirectMusicLoader8 *MidiFile::s_loader = NULL;
MidiFile::MidiFile(const TCHAR *filePath, const TCHAR *fileName) {
m_playing = false;
CCriticalSection cs;
cs.Lock();
if(!s_loader && FAILED(CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, IID_IDirectMusicLoader8, (void **)&s_loader)))
// some error exit function
else
s_loader->AddRef();
if(FAILED(CoCreateInstance(CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC, IID_IDirectMusicPerformance8, (void **)&m_performance)))
// ...
IDirectMusic *dmus;
if(FAILED(m_performance->Init(&dmus, NULL, NULL)))
// ...
IDirectMusic8 *dmus8;
if(FAILED(dmus->QueryInterface(IID_IDirectMusic8, (void **)&dmus8)))
// ...
dmus->Release();
// This GUID represents the MS MIDI Mapper (on my machine, anyway)
GUID mapper = {0x27b76ff5, 0xd88f, 0x4e45, {0xac, 0x6e, 0xb8, 0x46, 0x70, 0xb2, 0x49, 0x7d}};
DMUS_PORTPARAMS8 portParams;
memset(&portParams, 0, sizeof(DMUS_PORTPARAMS8));
portParams.dwSize = sizeof(DMUS_PORTPARAMS8);
IDirectMusicPort *mapperPort;
if(FAILED(dmus8->CreatePort(mapper, &portParams, &mapperPort, NULL)))
// ...
dmus8->Release();
mapperPort->Activate(TRUE);
m_performance->AddPort(mapperPort);
m_performance->AssignPChannelBlock(0, mapperPort, 1);
mapperPort->Release();
wchar_t *wFilePath, *wFileName;
size_t fileNameLen = _tcslen(fileName);
wFilePath = new wchar_t[MAX_PATH * 2];
wFileName = new wchar_t[fileNameLen + 1];
if(!filePath) {
TCHAR *tFilePath = new TCHAR[MAX_PATH * 2 + fileNameLen + 1], *tFileName;
GetFullPathName(fileName, MAX_PATH * 2 + (DWORD)(fileNameLen + 1), tFilePath, &tFileName);
if(!tFileName)
// ...
#ifdef UNICODE
wcsncpy(wFilePath, tFilePath, tFileName - tFilePath - 1);
wcscpy(wFileName, tFileName);
#else
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, tFilePath, (int)(tFileName - tFilePath - 1), wFileName, MAX_PATH * 2);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, tFileName, -1, wFileName, (int)fileNameLen + 1);
#endif
delete[] tFilePath;
}
else {
#ifdef UNICODE
wcscpy(wFilePath, filePath);
wcscpy(wFileName, fileName);
#else
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, filePath, -1, wFilePath, MAX_PATH * 2);
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, fileName, -1, wFileName, (int)fileNameLen + 1);
#endif
}
if(FAILED(s_loader->SetSearchDirectory(GUID_DirectMusicAllTypes, wFilePath, FALSE)))
// ...
HRESULT loadResult = s_loader->LoadObjectFromFile(CLSID_DirectMusicSegment, IID_IDirectMusicSegment8, wFileName, (void **)&m_seg);
delete[] wFilePath;
delete[] wFileName;
if(FAILED(loadResult))
// ...
if(FAILED(m_seg->SetParam(GUID_StandardMIDIFile, (DWORD)-1, 0, 0, NULL)))
// ...
if(FAILED(m_seg->SetRepeats(DMUS_SEG_REPEAT_INFINITE)))
// ...
cs.Unlock();
}
MidiFile::~MidiFile() {
CCriticalSection cs;
cs.Lock();
stop();
m_performance->CloseDown();
s_loader->Release();
m_performance->Release();
m_seg->Release();
cs.Unlock();
}
void MidiFile::play() {
if(m_playing)
return;
if(FAILED(m_performance->PlaySegmentEx(m_seg, NULL, NULL, 0, 0, NULL, NULL, NULL)))
// ...
m_playing = true;
}
void MidiFile::stop() {
if(!m_playing)
return;
if(FAILED(m_performance->Stop(NULL, NULL, 0, 0)))
// ...
m_playing = false;
}
Here's my new problem. Say I create two MidiFile objects like this:
MidiFile *file1 = new MidiFile(NULL, _T("song1.mid"));
MidiFile *file2 = new MidiFIle(NULL, _T("song2.mid"));
I want to prematurely stop file1 and start file2, so that they sound like one continuous file:
file1->play();
// ...
file1->stop();
file2->play();
// ...
Problem is, I can get file1 to play fine, but when I stop it, and try to play file2, it won't play at all. Any suggestions?