mirror of
git://source.winehq.org/git/wine.git
synced 2024-07-21 14:54:11 +00:00
dmusic: Rewrite instrument lrgn list parsing.
This commit is contained in:
parent
7684880546
commit
9e9b5d2980
|
@ -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,78 +192,6 @@ static inline HRESULT advance_stream(IStream *stream, ULONG bytes)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static HRESULT load_region(struct instrument *This, IStream *stream, ULONG length)
|
||||
{
|
||||
struct region *region;
|
||||
HRESULT ret;
|
||||
DMUS_PRIVATE_CHUNK chunk;
|
||||
|
||||
TRACE("(%p, %p, %lu)\n", This, stream, length);
|
||||
|
||||
if (!(region = malloc(sizeof(*region)))) return E_OUTOFMEMORY;
|
||||
|
||||
while (length)
|
||||
{
|
||||
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;
|
||||
|
||||
case FOURCC_WLNK:
|
||||
TRACE("WLNK chunk (wave link): %lu bytes\n", chunk.dwSize);
|
||||
|
||||
ret = read_from_stream(stream, ®ion->wave_link, sizeof(region->wave_link));
|
||||
if (FAILED(ret)) goto failed;
|
||||
|
||||
length = subtract_bytes(length, 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);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
list_add_tail(&This->regions, ®ion->entry);
|
||||
return S_OK;
|
||||
|
||||
failed:
|
||||
free(region);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HRESULT load_articulation(struct instrument *This, IStream *stream, ULONG length)
|
||||
{
|
||||
struct articulation *articulation;
|
||||
|
@ -289,6 +217,75 @@ static HRESULT load_articulation(struct instrument *This, IStream *stream, ULONG
|
|||
return hr;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (!(region = malloc(sizeof(*region)))) return E_OUTOFMEMORY;
|
||||
|
||||
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;
|
||||
|
||||
case FOURCC_WLNK:
|
||||
hr = stream_chunk_get_data(stream, &chunk, ®ion->wave_link, sizeof(region->wave_link));
|
||||
break;
|
||||
|
||||
default:
|
||||
FIXME("Ignoring chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type));
|
||||
break;
|
||||
}
|
||||
|
||||
if (FAILED(hr)) break;
|
||||
}
|
||||
|
||||
if (FAILED(hr)) free(region);
|
||||
else list_add_tail(&This->regions, ®ion->entry);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT parse_lrgn_list(struct instrument *This, IStream *stream, struct chunk_entry *parent)
|
||||
{
|
||||
struct chunk_entry chunk = {.parent = parent};
|
||||
HRESULT hr;
|
||||
|
||||
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;
|
||||
|
||||
default:
|
||||
FIXME("Ignoring chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type));
|
||||
break;
|
||||
}
|
||||
|
||||
if (FAILED(hr)) break;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue