[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.

pStream

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
Remarks.

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
tomas.elf@xxxxxxxxxxxx
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
reader=20
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
someone=20
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
a=20
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
using=20
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
(or=20
containers in general, I suspect). The only way I've managed to load a
script=20
is by either embedding all references in the script or by placing all
referred=20
files in the same directory and then pointing IDirectMusicLoader8::
SetSearchDirectory to that directory. But, as I said before, the latter
one=20
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
some=20
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
the=20
script, just as with segments. Is this not possible? Here's an excerpt
from the=20
current, flawed solution:


<CODE>


int main()=20
{


        //*snip*
       =20
        /*=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,
CLSID_DirectMusicAudioPathConfig,=20
                L"Audiopath_AllCh", L"C:\\Documents and
Settings\\Tomas\\My=20
Documents\\DMUSProducer\\Test1\\RuntimeFiles\\Audiopath_AllCh.aud");


        hr =3D LoaderSetObject(g_pLoader, CLSID_DirectSoundWave,
L"Riff_Bass-01",=20
                L"C:\\Documents and Settings\\Tomas\\My=20
Documents\\DMUSProducer\\Test1\\RuntimeFiles\\Riff_Bass-01.wav");


        /*=20
        ... *snip* LoaderSetObject of all other referred files is
omitted from=20
this=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,
wcharFilename,=20
                wcharRoutine);


        //*snip*


} //End main



/*
        LoaderSetObject:
        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;


        ZeroMemory(&objDesc,sizeof(objDesc));
        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) -
 1);
                objDesc.wszName[sizeof(objDesc.wszName) - 1] =3D 0;
                objDesc.dwValidData |=3D DMUS_OBJ_NAME;
        }
       =20
        hr =3D pLoader->SetObject(&objDesc);
       =20
        return hr;
}



/*
        PlayScript:
        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. =20
*/
HRESULT PlayScript(IDirectMusicLoader8* &pLoader,=20
                        IDirectMusicPerformance8* &pPerformance,=20
                        IDirectMusicScript8* &pScript,=20
                        WCHAR* wcharFilename,=20
                        WCHAR* wcharRoutine)
{
        HRESULT hr;
        DMUS_SCRIPT_ERRORINFO errInfo;
        DMUS_OBJECTDESC objDesc;


        try
        {
       =20
        if (!pLoader || !pPerformance)
                return E_INVALIDARG;


        ZeroMemory(&objDesc,sizeof(objDesc));
        objDesc.dwSize =3D sizeof(DMUS_OBJECTDESC);
        objDesc.guidClass =3D CLSID_DirectMusicScript;
        wcscpy(objDesc.wszFileName, wcharFilename);
        objDesc.dwValidData =3D DMUS_OBJ_FULLPATH | DMUS_OBJ_CLASS;
       =20
        //!!! ERROR PRINTOUT FROM DIRECTX DEBUG WHEN DOING THIS
GETOBJECT !!!
        hr =3D pLoader->GetObject(&objDesc, IID_IDirectMusicScript,
(LPVOID *)=20
&pScript);
       =20
        if (FAILED (hr =3D pScript->Init(pPerformance, &errInfo)))=20
        {
                pScript->Release();
                return E_FAIL;
        }
       =20
        hr =3D pScript->CallRoutine(wcharRoutine, &errInfo);


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


        pScript->Release();
        return S_OK;


        } //End try


        catch(...)
        {
                DEBUG ("PlayScript Exception!\n");
                return S_FALSE;
        }


} //End PlayScript


</CODE>


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
&pScript);"=20

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


<ERROR MESSAGE>


DMLOADER: Warning: The file Riff_Bass-01.wav couldn't be opened: No such
file=20
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
such=20
file or directory
. Try another path.
DMLOADER: Warning: The file Segment1.sgt couldn't be opened: No such
file or=20
directory
. Try another path.
DMLOADER: Warning: The file Riff_Bass-01.wav couldn't be opened: No such
file=20
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
TestScript1,=20
type Microsoft.DirectMusicScript.1, guid {CAFFF46E-F3D6-4AA1-BE06-
FACAA7A17F0E}]
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}]


</ERROR MESSAGE>


Basically, none of files that the script refers to can be loaded. The
files=20
cannot be found it seems, since they are found if I were to point out
their=20
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
them=20
using the SetObject, the loader should be able to load them when loading
the=20
script, right?

FYI, in Producer, the script is set to load all references and download
all=20
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: