[directmusic] Re: Help! Problem when loading scripts

  • From: "Scott Morgan (Volt)" <a-smorg@xxxxxxxxxxxxx>
  • To: <directmusic@xxxxxxxxxxxxx>
  • Date: Wed, 16 Feb 2005 14:35:34 -0800

I've actually done the load from a stream thing before, but I honestly
didn't get it working for scripts...I got it working for DLS.  I can't
remember what happened with the scripts, but I think it may have been
something similar.

You called SetObject on the script right?  You make it clear that you
called it for all references.

Also, I just want you to be aware if you are not that the pStream
pointer you use when using SetObject is an IStream pointer.


Address of the IStream interface of a custom stream that can be used to
load the object into memory. In most cases this value should be NULL.See

The way I got this working was to create an IStorage file containing all
my files and loading from that.  Otherwise I couldn't get an Istream
stream.  I think the alternate method would have been to implement my
own IStream interface...which was more work than I wanted to do.

I know that probably didn't help. :(  Hopefully Todor or someone will
pipe in.

-Scott Morgan
*This message is given as is with no rights conferred.*

-----Original Message-----
From: directmusic-bounce@xxxxxxxxxxxxx
[mailto:directmusic-bounce@xxxxxxxxxxxxx] On Behalf Of
Sent: Wednesday, February 16, 2005 10:16 AM
To: directmusic@xxxxxxxxxxxxx
Subject: [directmusic] Help! Problem when loading scripts

Hi everyone,

I'm Tomas, Directmusic programmer of a small game development group and
of this mailing list for quite some time now.=20
I've noticed that there's a lot of smart people around here, so I hope
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=20
specific file functions in IDirectMusicLoader8 (e.g LoadObjectFromFile,=20
SetSearchDirectory etc). The reason for this is that the Directmusic
module in=20
our system will not have access to any files, but instead will be given
pointer to the data that I probably will=20
be able to load using IDirectMusicLoader8::GetObject. I'm pretty sure
that I've=20
managed to load a segment consisting of a number of wavetracks by first
IDirectMusicLoader8::SetObject on the wave-files referred to by the
script, and=20
then loading the Segment like usual.

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

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


int main()=20

        First run SetObject on all files that the script refers to.
        The LoaderSetObject simply runs SetObject on the file passed=20
        to it.=20

        hr =3D LoaderSetObject(g_pLoader,
                L"Audiopath_AllCh", L"C:\\Documents and

        hr =3D LoaderSetObject(g_pLoader, CLSID_DirectSoundWave,
                L"C:\\Documents and Settings\\Tomas\\My=20

        ... *snip* LoaderSetObject of all other referred files is
omitted from=20
        code listing...=20

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

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


} //End main

        Lets the loader know where all referred files can be found=20
        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 set.
HRESULT LoaderSetObject(IDirectMusicLoader8* &pLoader, GUID guidClass,=20
                        WCHAR* wcharObjName, WCHAR* wcharFilepath)
        DMUS_OBJECTDESC objDesc;
        HRESULT hr;

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

        if (wcharObjName)
                wcsncpy(objDesc.wszName, wcharObjName,
sizeof(objDesc.wszName) -
                objDesc.wszName[sizeof(objDesc.wszName) - 1] =3D 0;
                objDesc.dwValidData |=3D DMUS_OBJ_NAME;
        hr =3D pLoader->SetObject(&objDesc);
        return hr;

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

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

        objDesc.dwSize =3D sizeof(DMUS_OBJECTDESC);
        objDesc.guidClass =3D CLSID_DirectMusicScript;
        wcscpy(objDesc.wszFileName, wcharFilename);
        objDesc.dwValidData =3D DMUS_OBJ_FULLPATH | DMUS_OBJ_CLASS;
        hr =3D pLoader->GetObject(&objDesc, IID_IDirectMusicScript,
(LPVOID *)=20
        if (FAILED (hr =3D pScript->Init(pPerformance, &errInfo)))=20
                return E_FAIL;
        hr =3D 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=20
would not use files. That's because I thought that it would be=20
easy to just replace the file references with memory references later
on, since=20
I use SetObject.

Now, what happens is that when reaching the row...=20

"hr =3D pLoader->GetObject(&objDesc, IID_IDirectMusicScript, (LPVOID *)=20

... in the PlayScript-method above, I get the following debug printout
direct-x in my output window in Visual Studio and the &pScript is still=20


DMLOADER: Warning: The file Riff_Bass-01.wav couldn't be opened: No such
or directory
. Try another path.
DMLOADER: Warning: The file Riff_Chords-01.wav couldn't be opened: No
such file=20
or directory
. Try another path.
DMLOADER: Warning: The file Riff_Drums-01.wav couldn't be opened: No
such file=20
or directory
. Try another path.
DMLOADER: Warning: The file Audiopath_AllCh.aud couldn't be opened: No
file or directory
. Try another path.
DMLOADER: Warning: The file Segment1.sgt couldn't be opened: No such
file or=20
. Try another path.
DMLOADER: Warning: The file Riff_Bass-01.wav couldn't be opened: No such
or directory
. Try another path.
DMLOADER: Load failure. While attempting to load the object
DMLOADER:    [file C:\Documents and Settings\Tomas\My=20
Documents\DMUSProducer\Test1\Runtimefiles\TestScript1.spt, name
type Microsoft.DirectMusicScript.1, guid {CAFFF46E-F3D6-4AA1-BE06-
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, none of files that the script refers to can be loaded. The
cannot be found it seems, since they are found if I were to point out
directory using IDirectMusicLoader8::SetSearchDirectory (but since I
won't be=20
able to rely on files later on, that's a no-no).
I don't understand why the loader cannot find the files. If I point out
using the SetObject, the loader should be able to load them when loading
script, right?

FYI, in Producer, the script is set to load all references and download
segments when it's loaded.

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

Best regards,
Tomas Elf

Other related posts: