[directmusic] DM-test

  • From: tomas <tomas.elf@xxxxxxxxxxxx>
  • To: d99elf@xxxxxxxxxxxxxxxx, directmusic@xxxxxxxxxxxxx
  • Date: Wed, 16 Feb 2005 17:35:31 +0100

Hi everyone,

I'm Tomas, Directmusic programmer of a small game development group and 
reader of this mailing list for quite some time now.
I've noticed that there's a lot of smart people around here, so I hope 
someone can help me with a Directmusic problem that I'm having :-).

The background: I must find a way to load Directmusic-objects without using 
the specific file functions in
IDirectMusicLoader8 (e.g LoadObjectFromFile, SetSearchDirectory etc). The 
reason for this is that the Directmusic
module in our system will not have access to any files, but instead will be 
given a pointer to the data that I probably will
be able to load using IDirectMusicLoader8::GetObject. I'm pretty sure that 
I've managed to load a segment consisting of a number of wavetracks by 
first using IDirectMusicLoader8::SetObject on the wave-files referred to by 
the script, and then loading the Segment like usual.

Now, the problem is: This does not seem to work too well with scripts (or 
containers in general, I suspect). The only way I've
managed to load a script is by either embedding all references in the 
script or by placing all referred files in the same directory
and then pointing IDirectMusicLoader8::SetSearchDirectory to that 
directory. But, as I said before, the latter one does not meet
our requirements (and obviously, the first one is very inefficient if I 
want to use the same file in a lot of scripts). So, I need to be able
to load scripts by using IDirectMusicLoader8::SetObject or by some other 
solution that lets me give the loader a pointer to the data.

What I thought was that you could simply use IDirectMusicLoader8::SetObject 
on all the objects that are referred to by the script,
and then simply load the script, just as with segments. Is this not 
possible? Here's an excerpt of how the current, flawed solution looks like:


int main()


         //First run SetObject on all files that the script refers to. The 
LoaderSetObject simply runs SetObject on the file passed to it.
         hr = LoaderSetObject(g_pLoader, CLSID_DirectMusicAudioPathConfig, 
L"Audiopath_AllCh", L"C:\\Runtimefiles\\Audiopath_AllCh.aud");
         hr = LoaderSetObject(g_pLoader, CLSID_DirectSoundWave, 
L"Riff_Bass-01", L"C:\\Runtimefiles\\Riff_Bass-01.wav");

         //... *snip* LoaderSetObject of all other referred files is 
omitted from this code listing...

         WCHAR wcharFilename[] = L"C:\\Runtimefiles\\TestScript1.spt";
         WCHAR wcharRoutine[] = L"PlaySegment";

         //... Then load & play the script.
         hr = PlayScript(g_pLoader, g_pPerformance, pScript, wcharFilename, 


} //End main

         Lets the loader know where all referred files can be found when 
loading a script.
         pLoader: The Directmusic loader
         guidClass: The class id of the object to give to SetObject.
         wcharObjName: The internal name of the object to set [optional]
         wcharFilepath: The path+filename to the object that is going to be 
HRESULT LoaderSetObject(IDirectMusicLoader8* &pLoader, GUID guidClass, 
WCHAR* wcharObjName, WCHAR* wcharFilepath)
         DMUS_OBJECTDESC objDesc;
         HRESULT hr;

         objDesc.dwSize = sizeof(objDesc);
         objDesc.guidClass = guidClass;
         wcscpy(objDesc.wszFileName, wcharFilepath);
         objDesc.dwValidData = DMUS_OBJ_FULLPATH | DMUS_OBJ_CLASS;

         if (wcharObjName)
                 wcsncpy(objDesc.wszName, wcharObjName, 
sizeof(objDesc.wszName) - 1);
                 objDesc.wszName[sizeof(objDesc.wszName) - 1] = 0;
                 objDesc.dwValidData |= DMUS_OBJ_NAME;

         hr = pLoader->SetObject(&objDesc);

         return hr;

         Loads and plays the script.
         pLoader & pPerformance: Obvious ;-)
         pScript: Return variable of the script object loaded by PlayScript
         wcharFilename: The path+filename of the script to load & play.
         wcharRoutinge: The name of the script routine to play.
HRESULT PlayScript(IDirectMusicLoader8* &pLoader, IDirectMusicPerformance8* 
&pPerformance, IDirectMusicScript8* &pScript, WCHAR* wcharFilename, WCHAR* 
         HRESULT hr;
         DMUS_OBJECTDESC objDesc;


         if (!pLoader || !pPerformance)
                 return E_INVALIDARG;

         objDesc.dwSize = sizeof(DMUS_OBJECTDESC);
         objDesc.guidClass = CLSID_DirectMusicScript;
         wcscpy(objDesc.wszFileName, wcharFilename);
         objDesc.dwValidData = DMUS_OBJ_FULLPATH | DMUS_OBJ_CLASS;

         hr = pLoader->GetObject(&objDesc, IID_IDirectMusicScript, (LPVOID 
*) &pScript);

         if (FAILED (hr = pScript->Init(pPerformance, &errInfo)))
                 return E_FAIL;

         hr = pScript->CallRoutine(wcharRoutine, &errInfo);

         MessageBox(NULL, "Script", "Playing", MB_OK);
         pPerformance->Stop(NULL, NULL, 0, 0);

         return S_OK;

         } //End try

                 DEBUG ("PlayScript Exception!\n");
                 return S_FALSE;

} //End PlayScript


You may wonder why I load files in this code example when I told you that I 
would not use files. That's because I thought that it would be
easy to just replace the file references with memory references later on, 
since I use SetObject.

Now, what happens is that when reaching the row: "hr = 
pLoader->GetObject(&objDesc, IID_IDirectMusicScript, (LPVOID *) &pScript);" in
the PlayScript-method above, I get the following debug printout from 
direct-x in my output window in Visual Studio and the &pScript is still

DMLOADER: Warning: The file Riff_Bass-01.wav couldn't be opened: No such 
file or directory
. Try another path.
DMLOADER: Warning: The file Riff_Chords-01.wav couldn't be opened: No such 
file or directory
. Try another path.
DMLOADER: Warning: The file Riff_Drums-01.wav couldn't be opened: No such 
file or directory
. Try another path.
DMLOADER: Warning: The file Audiopath_AllCh.aud couldn't be opened: No such 
file or directory
. Try another path.
DMLOADER: Warning: The file Segment1.sgt couldn't be opened: No such file 
or directory
. Try another path.
DMLOADER: Warning: The file Riff_Bass-01.wav couldn't be opened: No such 
file or directory
. Try another path.
DMLOADER: Load failure. While attempting to load the object
DMLOADER:    [file C:\Documents and Settings\Tomas\My 
Documents\DMUSProducer\Test1\Runtimefiles\TestScript1.spt, name 
TestScript1, type Microsoft.DirectMusicScript.1, guid 
DMLOADER: the following referenced objects could not be loaded:
DMLOADER:    [file Riff_Bass-01.wav, name Riff_Bass-01, type 
Microsoft.DirectMusicSegment.1, guid {F7B4BDBE-4695-4320-9A9E-C4CF4785B8C0}]

Basically, all files that the script refers to cannot be loaded. They 
cannot be found it seems, since they are found if I were to point out their
the directory using IDirectMusicLoader8::SetSearchDirectory (but since I 
won't be able to rely on files, this is a no-no).
I don't understand why the loader cannot find the files. If I point out 
them using the SetObject, the loader should be able to load them when 
loading the script, right?
FYI, in Producer, the script is set to load all references and download all 
segments when it's loaded.

I would be very grateful if somebody with more experience out there could 
help me with this problem. It makes no sense to me :-(.

Best regards,
Tomas Elf

Other related posts:

  • » [directmusic] DM-test