From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmusic/dmobject.c | 2 +- dlls/dmusic/dmobject.h | 2 + dlls/dmusic/instrument.c | 176 ++++++++++++++++----------------------- 3 files changed, 77 insertions(+), 103 deletions(-)
diff --git a/dlls/dmusic/dmobject.c b/dlls/dmusic/dmobject.c index a08db8cba58..2bef5511851 100644 --- a/dlls/dmusic/dmobject.c +++ b/dlls/dmusic/dmobject.c @@ -287,7 +287,7 @@ const char *debugstr_chunk(const struct chunk_entry *chunk) return wine_dbg_sprintf("%s chunk, %ssize %lu", debugstr_fourcc(chunk->id), type, chunk->size); }
-static HRESULT stream_read(IStream *stream, void *data, ULONG size) +HRESULT stream_read(IStream *stream, void *data, ULONG size) { ULONG read; HRESULT hr; diff --git a/dlls/dmusic/dmobject.h b/dlls/dmusic/dmobject.h index 772be015c80..98069de8cc4 100644 --- a/dlls/dmusic/dmobject.h +++ b/dlls/dmusic/dmobject.h @@ -30,7 +30,9 @@ struct chunk_entry { ULARGE_INTEGER offset; /* chunk offset from start of stream */ const struct chunk_entry *parent; /* enclosing RIFF or LIST chunk */ }; +#define MAKE_IDTYPE(id, type) (((UINT64)type << 32) | (UINT64)id)
+HRESULT stream_read(IStream *stream, void *data, ULONG size); HRESULT stream_get_chunk(IStream *stream, struct chunk_entry *chunk); HRESULT stream_next_chunk(IStream *stream, struct chunk_entry *chunk); HRESULT stream_skip_chunk(IStream *stream, const struct chunk_entry *chunk); diff --git a/dlls/dmusic/instrument.c b/dlls/dmusic/instrument.c index bcd2ef58265..5941042caa1 100644 --- a/dlls/dmusic/instrument.c +++ b/dlls/dmusic/instrument.c @@ -192,98 +192,95 @@ static inline HRESULT advance_stream(IStream *stream, ULONG bytes) return ret; }
-static HRESULT load_region(struct instrument *This, IStream *stream, ULONG length) +static HRESULT load_articulation(struct instrument *This, IStream *stream, ULONG length) { - struct region *region; - HRESULT ret; - DMUS_PRIVATE_CHUNK chunk; + struct articulation *articulation; + CONNECTIONLIST list; + HRESULT hr; + UINT size;
- TRACE("(%p, %p, %lu)\n", This, stream, length); + if (FAILED(hr = read_from_stream(stream, &list, sizeof(list)))) return hr; + if (list.cbSize != sizeof(list)) return E_INVALIDARG;
- if (!(region = malloc(sizeof(*region)))) return E_OUTOFMEMORY; + size = offsetof(struct articulation, connections[list.cConnections]); + if (!(articulation = malloc(size))) return E_OUTOFMEMORY; + articulation->list = list;
- while (length) + size = sizeof(CONNECTION) * list.cConnections; + if (FAILED(hr = read_from_stream(stream, articulation->connections, size))) free(articulation); + else { - ret = read_from_stream(stream, &chunk, sizeof(chunk)); - if (FAILED(ret)) goto failed; - - length = subtract_bytes(length, sizeof(chunk)); - - switch (chunk.fccID) - { - case FOURCC_RGNH: - TRACE("RGNH chunk (region header): %lu bytes\n", chunk.dwSize); - - ret = read_from_stream(stream, ®ion->header, sizeof(region->header)); - if (FAILED(ret)) goto failed; - - length = subtract_bytes(length, sizeof(region->header)); - break; - - case FOURCC_WSMP: - TRACE("WSMP chunk (wave sample): %lu bytes\n", chunk.dwSize); - - ret = read_from_stream(stream, ®ion->wave_sample, sizeof(region->wave_sample)); - if (FAILED(ret)) goto failed; - 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)) goto failed; - - length = subtract_bytes(length, sizeof(region->wave_loop)); - break; + subtract_bytes(length, sizeof(list) + sizeof(CONNECTION) * list.cConnections); + list_add_tail(&This->articulations, &articulation->entry); + }
- case FOURCC_WLNK: - TRACE("WLNK chunk (wave link): %lu bytes\n", chunk.dwSize); + return hr; +}
- ret = read_from_stream(stream, ®ion->wave_link, sizeof(region->wave_link)); - if (FAILED(ret)) goto failed; +static HRESULT parse_rgn_chunk(struct instrument *This, IStream *stream, struct chunk_entry *parent) +{ + struct chunk_entry chunk = {.parent = parent}; + struct region *region; + HRESULT hr;
- length = subtract_bytes(length, sizeof(region->wave_link)); - break; + if (!(region = malloc(sizeof(*region)))) return E_OUTOFMEMORY;
- default: - TRACE("Unknown chunk %s (skipping): %lu bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize); + while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) + { + switch (MAKE_IDTYPE(chunk.id, chunk.type)) + { + case FOURCC_RGNH: + hr = stream_chunk_get_data(stream, &chunk, ®ion->header, sizeof(region->header)); + break; + + case FOURCC_WSMP: + if (chunk.size < sizeof(region->wave_sample)) hr = E_INVALIDARG; + else hr = stream_read(stream, ®ion->wave_sample, sizeof(region->wave_sample)); + if (SUCCEEDED(hr) && region->wave_sample.cSampleLoops) + { + if (region->wave_sample.cSampleLoops > 1) FIXME("More than one wave loop is not implemented\n"); + if (chunk.size != sizeof(WSMPL) + region->wave_sample.cSampleLoops * sizeof(WLOOP)) hr = E_INVALIDARG; + else hr = stream_read(stream, ®ion->wave_loop, sizeof(region->wave_loop)); + } + break;
- ret = advance_stream(stream, chunk.dwSize); - if (FAILED(ret)) goto failed; + case FOURCC_WLNK: + hr = stream_chunk_get_data(stream, &chunk, ®ion->wave_link, sizeof(region->wave_link)); + break;
- length = subtract_bytes(length, chunk.dwSize); - break; + default: + FIXME("Ignoring chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type)); + break; } + + if (FAILED(hr)) break; }
- list_add_tail(&This->regions, ®ion->entry); - return S_OK; + if (FAILED(hr)) free(region); + else list_add_tail(&This->regions, ®ion->entry);
-failed: - free(region); - return ret; + return hr; }
-static HRESULT load_articulation(struct instrument *This, IStream *stream, ULONG length) +static HRESULT parse_lrgn_list(struct instrument *This, IStream *stream, struct chunk_entry *parent) { - struct articulation *articulation; - CONNECTIONLIST list; + struct chunk_entry chunk = {.parent = parent}; HRESULT hr; - UINT size;
- if (FAILED(hr = read_from_stream(stream, &list, sizeof(list)))) return hr; - if (list.cbSize != sizeof(list)) return E_INVALIDARG; + while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) + { + switch (MAKE_IDTYPE(chunk.id, chunk.type)) + { + case MAKE_IDTYPE(FOURCC_LIST, FOURCC_RGN): + hr = parse_rgn_chunk(This, stream, &chunk); + break;
- size = offsetof(struct articulation, connections[list.cConnections]); - if (!(articulation = malloc(size))) return E_OUTOFMEMORY; - articulation->list = list; + default: + FIXME("Ignoring chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type)); + break; + }
- size = sizeof(CONNECTION) * list.cConnections; - if (FAILED(hr = read_from_stream(stream, articulation->connections, size))) free(articulation); - else - { - subtract_bytes(length, sizeof(list) + sizeof(CONNECTION) * list.cConnections); - list_add_tail(&This->articulations, &articulation->entry); + if (FAILED(hr)) break; }
return hr; @@ -344,40 +341,15 @@ HRESULT instrument_load(IDirectMusicInstrument *iface, IStream *stream) switch (chunk.fccID) { case FOURCC_LRGN: + { + static const LARGE_INTEGER zero = {0}; + struct chunk_entry list_chunk = {.id = FOURCC_LIST, .size = chunk.dwSize, .type = chunk.fccID}; TRACE("LRGN chunk (regions list): %lu 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: %lu 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): %lu bytes\n", chunk.dwSize); - hr = load_region(This, stream, chunk.dwSize - sizeof(chunk.fccID)); - } - else - { - TRACE("Unknown chunk %s: %lu 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)); - } + IStream_Seek(stream, zero, STREAM_SEEK_CUR, &list_chunk.offset); + list_chunk.offset.QuadPart -= 12; + hr = parse_lrgn_list(This, stream, &list_chunk); break; + }
case FOURCC_LART: TRACE("LART chunk (articulations list): %lu bytes\n", size);