[PATCH 1/2] dmusic: Implement instrument regions loading.
Christian Costa
titan.costa at gmail.com
Fri Dec 21 03:27:38 CST 2012
---
dlls/dmusic/dmusic_private.h | 29 +++++---
dlls/dmusic/instrument.c | 157 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 173 insertions(+), 13 deletions(-)
diff --git a/dlls/dmusic/dmusic_private.h b/dlls/dmusic/dmusic_private.h
index 3c05ceb..a37a1c3 100644
--- a/dlls/dmusic/dmusic_private.h
+++ b/dlls/dmusic/dmusic_private.h
@@ -77,6 +77,13 @@ typedef struct port_info {
ULONG device;
} port_info;
+typedef struct instrument_region {
+ RGNHEADER header;
+ WAVELINK wave_link;
+ WSMPL wave_sample;
+ WLOOP wave_loop;
+ BOOL loop_present;
+} instrument_region;
/*****************************************************************************
* ClassFactory
@@ -224,17 +231,19 @@ struct IDirectMusicCollectionImpl {
* IDirectMusicInstrumentImpl implementation structure
*/
struct IDirectMusicInstrumentImpl {
- /* IUnknown fields */
- IDirectMusicInstrument IDirectMusicInstrument_iface;
- LONG ref;
+ /* IUnknown fields */
+ IDirectMusicInstrument IDirectMusicInstrument_iface;
+ LONG ref;
- /* IDirectMusicInstrumentImpl fields */
- LARGE_INTEGER liInstrumentPosition; /* offset in a stream where instrument chunk can be found */
- ULONG length; /* Length of the instrument in the stream */
- LPGUID pInstrumentID;
- LPINSTHEADER pHeader;
- WCHAR wszName[DMUS_MAX_NAME];
- /* instrument data */
+ /* IDirectMusicInstrumentImpl fields */
+ LARGE_INTEGER liInstrumentPosition; /* offset in a stream where instrument chunk can be found */
+ ULONG length; /* Length of the instrument in the stream */
+ LPGUID pInstrumentID;
+ LPINSTHEADER pHeader;
+ WCHAR wszName[DMUS_MAX_NAME];
+ /* instrument data */
+ BOOL loaded;
+ instrument_region *regions;
};
static inline IDirectMusicInstrumentImpl *impl_from_IDirectMusicInstrument(IDirectMusicInstrument *iface)
diff --git a/dlls/dmusic/instrument.c b/dlls/dmusic/instrument.c
index cc57313..c96c389 100644
--- a/dlls/dmusic/instrument.c
+++ b/dlls/dmusic/instrument.c
@@ -75,7 +75,10 @@ static ULONG WINAPI IDirectMusicInstrumentImpl_Release(LPDIRECTMUSICINSTRUMENT i
TRACE("(%p)->(): new ref = %u\n", iface, ref);
if (!ref)
+ {
+ HeapFree(GetProcessHeap(), 0, This->regions);
HeapFree(GetProcessHeap(), 0, This);
+ }
DMUSIC_UnlockModule();
@@ -170,16 +173,90 @@ static inline HRESULT advance_stream(IStream *stream, ULONG bytes)
return ret;
}
+static HRESULT load_region(IDirectMusicInstrumentImpl *This, IStream *stream, instrument_region *region, ULONG length)
+{
+ HRESULT ret;
+ DMUS_PRIVATE_CHUNK chunk;
+
+ TRACE("(%p, %p, %p, %u)\n", This, stream, region, length);
+
+ while (length)
+ {
+ ret = read_from_stream(stream, &chunk, sizeof(chunk));
+ if (FAILED(ret))
+ return ret;
+
+ length = subtract_bytes(length, sizeof(chunk));
+
+ switch (chunk.fccID)
+ {
+ case FOURCC_RGNH:
+ TRACE("RGNH chunk (region header): %u bytes\n", chunk.dwSize);
+
+ ret = read_from_stream(stream, ®ion->header, sizeof(region->header));
+ if (FAILED(ret))
+ return ret;
+
+ length = subtract_bytes(length, sizeof(region->header));
+ break;
+
+ case FOURCC_WSMP:
+ TRACE("WSMP chunk (wave sample): %u bytes\n", chunk.dwSize);
+
+ ret = read_from_stream(stream, ®ion->wave_sample, sizeof(region->wave_sample));
+ if (FAILED(ret))
+ return ret;
+ length = subtract_bytes(length, sizeof(region->wave_sample));
+
+ if (!(region->loop_present = (chunk.dwSize != sizeof(region->wave_sample))))
+ break;
+
+ ret = read_from_stream(stream, ®ion->wave_loop, sizeof(region->wave_loop));
+ if (FAILED(ret))
+ return ret;
+
+ length = subtract_bytes(length, sizeof(region->wave_loop));
+ break;
+
+ case FOURCC_WLNK:
+ TRACE("WLNK chunk (wave link): %u bytes\n", chunk.dwSize);
+
+ ret = read_from_stream(stream, ®ion->wave_link, sizeof(region->wave_link));
+ if (FAILED(ret))
+ return ret;
+
+ length = subtract_bytes(length, sizeof(region->wave_link));
+ break;
+
+ default:
+ TRACE("Unknown chunk %s (skipping): %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
+
+ ret = advance_stream(stream, chunk.dwSize);
+ if (FAILED(ret))
+ return ret;
+
+ length = subtract_bytes(length, chunk.dwSize);
+ break;
+ }
+ }
+
+ return S_OK;
+}
+
/* Function that loads all instrument data and which is called from IDirectMusicCollection_GetInstrument as in native */
HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, IStream *stream)
{
IDirectMusicInstrumentImpl *This = impl_from_IDirectMusicInstrument(iface);
HRESULT hr;
DMUS_PRIVATE_CHUNK chunk;
+ ULONG i = 0;
ULONG length = This->length;
TRACE("(%p, %p): offset = 0x%s, length = %u)\n", This, stream, wine_dbgstr_longlong(This->liInstrumentPosition.QuadPart), This->length);
+ if (This->loaded)
+ return S_OK;
+
hr = IStream_Seek(stream, This->liInstrumentPosition, STREAM_SEEK_SET, NULL);
if (FAILED(hr))
{
@@ -187,11 +264,15 @@ HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, ISt
return DMUS_E_UNSUPPORTED_STREAM;
}
+ This->regions = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->regions) * This->pHeader->cRegions);
+ if (!This->regions)
+ return E_OUTOFMEMORY;
+
while (length)
{
hr = read_from_stream(stream, &chunk, sizeof(chunk));
if (FAILED(hr))
- return DMUS_E_UNSUPPORTED_STREAM;
+ goto error;
length = subtract_bytes(length, sizeof(chunk) + chunk.dwSize);
@@ -204,20 +285,90 @@ HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, ISt
/* Instrument header and id are already set so just skip */
hr = advance_stream(stream, chunk.dwSize);
if (FAILED(hr))
- return DMUS_E_UNSUPPORTED_STREAM;
+ goto error;
+
+ break;
+ case FOURCC_LIST: {
+ DWORD size = chunk.dwSize;
+
+ TRACE("LIST chunk: %u bytes\n", chunk.dwSize);
+
+ hr = read_from_stream(stream, &chunk.fccID, sizeof(chunk.fccID));
+ if (FAILED(hr))
+ goto error;
+
+ size = subtract_bytes(size, sizeof(chunk.fccID));
+
+ switch (chunk.fccID)
+ {
+ case FOURCC_LRGN:
+ TRACE("LRGN chunk (regions list): %u bytes\n", chunk.dwSize - sizeof(chunk.fccID));
+
+ while (size)
+ {
+ hr = read_from_stream(stream, &chunk, sizeof(chunk));
+ if (FAILED(hr))
+ goto error;
+
+ if (chunk.fccID != FOURCC_LIST)
+ {
+ TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
+ goto error;
+ }
+
+ hr = read_from_stream(stream, &chunk.fccID, sizeof(chunk.fccID));
+ if (FAILED(hr))
+ goto error;
+
+ if (chunk.fccID == FOURCC_RGN)
+ {
+ TRACE("RGN chunk (region list): %u bytes\n", chunk.dwSize);
+ hr = load_region(This, stream, &This->regions[i++], chunk.dwSize - sizeof(chunk.fccID));
+ }
+ else
+ {
+ TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
+ hr = advance_stream(stream, chunk.dwSize - sizeof(chunk.fccID));
+ }
+ if (FAILED(hr))
+ goto error;
+
+ size = subtract_bytes(size, chunk.dwSize + sizeof(chunk));
+ }
+ break;
+
+ default:
+ TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
+
+ hr = advance_stream(stream, chunk.dwSize - sizeof(chunk.fccID));
+ if (FAILED(hr))
+ goto error;
+
+ size = subtract_bytes(size, chunk.dwSize - sizeof(chunk.fccID));
+ break;
+ }
break;
+ }
default:
TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
hr = advance_stream(stream, chunk.dwSize);
if (FAILED(hr))
- return DMUS_E_UNSUPPORTED_STREAM;
+ goto error;
break;
}
}
+ This->loaded = TRUE;
+
return S_OK;
+
+error:
+ HeapFree(GetProcessHeap(), 0, This->regions);
+ This->regions = NULL;
+
+ return DMUS_E_UNSUPPORTED_STREAM;
}
More information about the wine-patches
mailing list