dmusic: Allocate and parse instruments in a single pass.

This commit is contained in:
Rémi Bernon 2023-09-07 10:12:29 +02:00 committed by Alexandre Julliard
parent 01127ce474
commit ff4cb785cb
3 changed files with 35 additions and 86 deletions

View file

@ -115,7 +115,6 @@ static HRESULT WINAPI collection_GetInstrument(IDirectMusicCollection *iface,
if (patch == inst_patch) {
*instrument = inst_entry->pInstrument;
IDirectMusicInstrument_AddRef(inst_entry->pInstrument);
instrument_load(inst_entry->pInstrument, This->pStm);
TRACE(": returning instrument %p\n", *instrument);
return S_OK;
}
@ -212,7 +211,6 @@ static HRESULT WINAPI collection_stream_Load(IPersistStream *iface,
DMUS_PRIVATE_CHUNK chunk;
DWORD StreamSize, StreamCount, ListSize[2], ListCount[2];
LARGE_INTEGER liMove; /* used when skipping chunks */
ULARGE_INTEGER dlibInstrumentPosition;
IStream_AddRef(stream); /* add count for later references */
This->pStm = stream;
@ -374,68 +372,12 @@ static HRESULT WINAPI collection_stream_Load(IPersistStream *iface,
ListCount[1] = 0;
switch (chunk.fccID) {
case FOURCC_INS: {
DMUS_PRIVATE_INSTRUMENTENTRY *new_instrument = calloc(1, sizeof(DMUS_PRIVATE_INSTRUMENTENTRY));
DMUS_PRIVATE_INSTRUMENTENTRY *entry = calloc(1, sizeof(DMUS_PRIVATE_INSTRUMENTENTRY));
TRACE_(dmfile)(": instrument list\n");
/* Only way to create this one... even M$ does it discretely */
instrument_create(&new_instrument->pInstrument);
{
struct instrument *instrument = impl_from_IDirectMusicInstrument(new_instrument->pInstrument);
/* Store offset and length, they will be needed when loading the instrument */
liMove.QuadPart = 0;
IStream_Seek(stream, liMove, STREAM_SEEK_CUR, &dlibInstrumentPosition);
instrument->liInstrumentPosition.QuadPart = dlibInstrumentPosition.QuadPart;
instrument->length = ListSize[1];
do {
IStream_Read(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD), NULL);
ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize;
TRACE_(dmfile)(": %s chunk (size = %#04lx)", debugstr_fourcc(chunk.fccID), chunk.dwSize);
switch (chunk.fccID) {
case FOURCC_INSH: {
TRACE_(dmfile)(": instrument header chunk\n");
IStream_Read(stream, &instrument->header, chunk.dwSize, NULL);
break;
}
case FOURCC_DLID: {
TRACE_(dmfile)(": DLID (GUID) chunk\n");
IStream_Read(stream, &instrument->id, chunk.dwSize, NULL);
break;
}
case FOURCC_LIST: {
IStream_Read(stream, &chunk.fccID, sizeof(FOURCC), NULL);
TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunk.fccID));
switch (chunk.fccID) {
default: {
TRACE_(dmfile)(": unknown (skipping)\n");
liMove.QuadPart = chunk.dwSize - sizeof(FOURCC);
IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
break;
}
}
break;
}
default: {
TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
liMove.QuadPart = chunk.dwSize;
IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
break;
}
}
TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
} while (ListCount[1] < ListSize[1]);
/* DEBUG: dumps whole instrument object tree: */
if (TRACE_ON(dmusic)) {
TRACE("*** IDirectMusicInstrument (%p) ***\n", instrument);
if (!IsEqualGUID(&instrument->id, &GUID_NULL))
TRACE(" - GUID = %s\n", debugstr_dmguid(&instrument->id));
TRACE(" - Instrument header:\n");
TRACE(" - cRegions: %ld\n", instrument->header.cRegions);
TRACE(" - Locale:\n");
TRACE(" - ulBank: %ld\n", instrument->header.Locale.ulBank);
TRACE(" - ulInstrument: %ld\n", instrument->header.Locale.ulInstrument);
TRACE(" => dwPatch: %ld\n", MIDILOCALE2Patch(&instrument->header.Locale));
}
list_add_tail(&This->Instruments, &new_instrument->entry);
}
liMove.QuadPart = -12;
IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
if (FAILED(instrument_create_from_stream(stream, &entry->pInstrument))) free(entry);
else list_add_tail(&This->Instruments, &entry->entry);
break;
}
}

View file

@ -95,7 +95,7 @@ extern HRESULT DMUSIC_CreateReferenceClockImpl (LPCGUID lpcGUID, LPVOID* ppobj,
extern HRESULT download_create(DWORD size, IDirectMusicDownload **ret_iface);
extern HRESULT instrument_create(IDirectMusicInstrument **ret_iface);
extern HRESULT instrument_create_from_stream(IStream *stream, IDirectMusicInstrument **ret_iface);
/*****************************************************************************
* IDirectMusic8Impl implementation structure
@ -175,13 +175,10 @@ struct instrument
IDirectMusicInstrument IDirectMusicInstrument_iface;
LONG ref;
LARGE_INTEGER liInstrumentPosition; /* offset in a stream where instrument chunk can be found */
ULONG length; /* Length of the instrument in the stream */
GUID id;
INSTHEADER header;
WCHAR wszName[DMUS_MAX_NAME];
/* instrument data */
BOOL loaded;
struct list articulations;
struct list regions;
@ -192,8 +189,6 @@ static inline struct instrument *impl_from_IDirectMusicInstrument(IDirectMusicIn
return CONTAINING_RECORD(iface, struct instrument, IDirectMusicInstrument_iface);
}
extern HRESULT instrument_load(IDirectMusicInstrument *iface, IStream *stream);
/*****************************************************************************
* Misc.
*/

View file

@ -135,7 +135,7 @@ static const IDirectMusicInstrumentVtbl instrument_vtbl =
instrument_SetPatch,
};
HRESULT instrument_create(IDirectMusicInstrument **ret_iface)
static HRESULT instrument_create(IDirectMusicInstrument **ret_iface)
{
struct instrument *instrument;
@ -277,8 +277,11 @@ static HRESULT parse_ins_chunk(struct instrument *This, IStream *stream, struct
switch (MAKE_IDTYPE(chunk.id, chunk.type))
{
case FOURCC_INSH:
hr = stream_chunk_get_data(stream, &chunk, &This->header, sizeof(This->header));
break;
case FOURCC_DLID:
/* Instrument header and id are already set so just skip */
hr = stream_chunk_get_data(stream, &chunk, &This->id, sizeof(This->id));
break;
case MAKE_IDTYPE(FOURCC_LIST, FOURCC_LRGN):
@ -300,24 +303,17 @@ static HRESULT parse_ins_chunk(struct instrument *This, IStream *stream, struct
return hr;
}
/* Function that loads all instrument data and which is called from IDirectMusicCollection_GetInstrument as in native */
HRESULT instrument_load(IDirectMusicInstrument *iface, IStream *stream)
HRESULT instrument_create_from_stream(IStream *stream, IDirectMusicInstrument **ret_iface)
{
struct instrument *This = impl_from_IDirectMusicInstrument(iface);
struct chunk_entry chunk = {0};
IDirectMusicInstrument *iface;
struct instrument *This;
HRESULT hr;
TRACE("(%p, %p): offset = 0x%s, length = %lu)\n", This, stream, wine_dbgstr_longlong(This->liInstrumentPosition.QuadPart), This->length);
TRACE("(%p, %p)\n", stream, ret_iface);
if (This->loaded)
return S_OK;
hr = IStream_Seek(stream, This->liInstrumentPosition, STREAM_SEEK_SET, NULL);
if (FAILED(hr))
{
WARN("IStream_Seek failed: %08lx\n", hr);
return DMUS_E_UNSUPPORTED_STREAM;
}
if (FAILED(hr = instrument_create(&iface))) return hr;
This = impl_from_IDirectMusicInstrument(iface);
if ((hr = stream_next_chunk(stream, &chunk)) == S_OK)
{
@ -329,16 +325,32 @@ HRESULT instrument_load(IDirectMusicInstrument *iface, IStream *stream)
default:
WARN("Invalid instrument chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type));
goto error;
hr = E_INVALIDARG;
break;
}
}
if (FAILED(hr)) goto error;
This->loaded = TRUE;
if (TRACE_ON(dmusic))
{
TRACE("Created DirectMusicInstrument (%p) ***\n", This);
if (!IsEqualGUID(&This->id, &GUID_NULL))
TRACE(" - GUID = %s\n", debugstr_dmguid(&This->id));
TRACE(" - Instrument header:\n");
TRACE(" - cRegions: %ld\n", This->header.cRegions);
TRACE(" - Locale:\n");
TRACE(" - ulBank: %ld\n", This->header.Locale.ulBank);
TRACE(" - ulInstrument: %ld\n", This->header.Locale.ulInstrument);
TRACE(" => dwPatch: %ld\n", MIDILOCALE2Patch(&This->header.Locale));
}
*ret_iface = iface;
return S_OK;
error:
IDirectMusicInstrument_Release(iface);
stream_skip_chunk(stream, &chunk);
return DMUS_E_UNSUPPORTED_STREAM;
}