Commit 9e9b5d29 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

dmusic: Rewrite instrument lrgn list parsing.

parent 76848805
......@@ -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;
......
......@@ -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);
......
......@@ -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;
subtract_bytes(length, sizeof(list) + sizeof(CONNECTION) * list.cConnections);
list_add_tail(&This->articulations, &articulation->entry);
}
length = subtract_bytes(length, sizeof(chunk));
return hr;
}
switch (chunk.fccID)
{
case FOURCC_RGNH:
TRACE("RGNH chunk (region header): %lu bytes\n", chunk.dwSize);
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;
ret = read_from_stream(stream, &region->header, sizeof(region->header));
if (FAILED(ret)) goto failed;
if (!(region = malloc(sizeof(*region)))) return E_OUTOFMEMORY;
length = subtract_bytes(length, sizeof(region->header));
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, &region->header, sizeof(region->header));
break;
case FOURCC_WSMP:
TRACE("WSMP chunk (wave sample): %lu bytes\n", chunk.dwSize);
ret = read_from_stream(stream, &region->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, &region->wave_loop, sizeof(region->wave_loop));
if (FAILED(ret)) goto failed;
length = subtract_bytes(length, sizeof(region->wave_loop));
if (chunk.size < sizeof(region->wave_sample)) hr = E_INVALIDARG;
else hr = stream_read(stream, &region->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, &region->wave_loop, sizeof(region->wave_loop));
}
break;
case FOURCC_WLNK:
TRACE("WLNK chunk (wave link): %lu bytes\n", chunk.dwSize);
ret = read_from_stream(stream, &region->wave_link, sizeof(region->wave_link));
if (FAILED(ret)) goto failed;
length = subtract_bytes(length, sizeof(region->wave_link));
hr = stream_chunk_get_data(stream, &chunk, &region->wave_link, sizeof(region->wave_link));
break;
default:
TRACE("Unknown chunk %s (skipping): %lu bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
ret = advance_stream(stream, chunk.dwSize);
if (FAILED(ret)) goto failed;
length = subtract_bytes(length, chunk.dwSize);
FIXME("Ignoring chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type));
break;
}
if (FAILED(hr)) break;
}
list_add_tail(&This->regions, &region->entry);
return S_OK;
if (FAILED(hr)) free(region);
else list_add_tail(&This->regions, &region->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:
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));
}
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);
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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment