The simplest way to load a collection from a file is to use the IDirectMusicLoader interface. (For more information, see Loading Objects.) Once you have obtained a pointer to the IDirectMusicCollection interface, you have access to all the instruments in the collection. At this point, though, none of them have actually been downloaded to a port. In fact, no instrument data is loaded into memory until it is needed.
Here's what happens behind the scenes. The collection is a COM object that supports the IDirectMusicCollection, IDirectMusicObject, and IPersistStream interfaces. IPersistStream is a standard COM interface providing methods for saving and loading objects that use a simple serial stream for their storage needs.
IDirectMusicCollection does not load the entire collection when IPersistStream::Load is called. Typically, objects supporting IPersistStream load all of the persistent data in the stream and do not use the IStream pointer outside of the Load method. However, supporting IPersistStream::Load in this manner in IDirectMusicCollection would mean that the entire DLS collection would have to be loaded into memory even if only a single instrument in the collection was to be used. Instead, IDirectMusicCollection saves the IStream pointer and later uses it to load only the data for instruments that will be downloaded to a DirectMusic port. IDirectMusicCollection assumes that the data stream provided through the IPersistStream interface is in the DLS file format.
The following example does manually what the IDirectMusicLoader::GetObject method does automatically: it creates a collection object and loads a stream into it:
HRESULT myLoadCollectionFromStream(
IStream *pIStream, // Stream created from file.
IDirectMusicCollection **ppICollection )
{
HRESULT hr;
hr = CoCreateInstance(CLSID_DirectMusicCollection,
NULL,
CLSCTX_INPROC,
IID_IDirectMusicCollection,
(void **)ppICollection);
if (SUCCEEDED(hr))
{
IPersistStream* pIPersistStream;
hr = *ppICollection->QueryInterface(
IID_IPersistStream, (void**)&pIPersistStream);
if (SUCCEEDED(hr))
{
hr = pIPersistStream->Load(pIStream);
pIPersistStream->Release();
}
}
return hr;
}
The following example uses the DirectMusicLoader to load the collection by file name.
HRESULT myLoadCollectionByName(
IDirectMusicLoader *pILoader,
char *pszFileName,
IDirectMusicCollection **ppICollection)
{
HRESULT hr;
DMUS_OBJECTDESC Desc; // Descriptor.
// Start by initializing Desc with the file name and GUID
// for the collection object.
// The file name starts as a char string, so convert
// to Unicode.
mbstowcs(Desc.wszFileName,pszFileName,DMUS_MAX_FILENAME);
Desc.dwSize = sizeof(DMUS_OBJECTDESC);
Desc.guidClass = CLSID_DirectMusicCollection;
Desc.dwValidData = DMUS_OBJ_CLASS
| DMUS_OBJ_FILENAME
| DMUS_OBJ_FULLPATH;
hr = pILoader->GetObject(&Desc,
IID_IDirectMusicCollection,
(void **) ppICollection);
return hr;
}
To load the standard GM/GS set, pass GUID_DefaultGMCollection to the loader in the guidObject member of the DMUS_OBJECTDESC structure. If you intend to use the loader to access this object more than once, make sure that caching is enabled (as it is by default) so you don't end up creating another copy of the GM collection each time you request it.
Note The GM/GS Sound Set cannot be altered. For more information, see the Copyright Warning.
The following code illustrates how to load a collection identified by its GUID:
HRESULT myGetGMCollection(
IDirectMusicLoader *pILoader,
IDirectMusicCollection **ppICollection)
{
HRESULT hr;
DMUS_OBJECTDESC desc;
desc.dwSize = sizeof(DMUS_OBJECTDESC);
desc.guidClass = CLSID_DirectMusicCollection;
desc.guidObject = GUID_DefaultGMCollection;
desc.dwValidData = (DMUS_OBJ_CLASS | DMUS_OBJ_OBJECT);
hr = pILoader->GetObject(&desc, IID_IDirectMusicCollection,
(void **) ppICollection);
return hr;
}