Module: wine Branch: master Commit: bf0605c08abd990ebb584cdc18e32bccdf9b94ee URL: http://source.winehq.org/git/wine.git/?a=commit;h=bf0605c08abd990ebb584cdc18...
Author: Christian Costa titan.costa@gmail.com Date: Fri Dec 21 10:27:38 2012 +0100
dmusic: Implement instrument regions loading.
---
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..13d0c2f 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", size); + + 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; }