[PATCH] dmime: Parse Wave track stream
Michael Stefaniuc
mstefani at winehq.org
Tue May 5 16:20:53 CDT 2020
Hello Alistair,
I have two more things:
- Parsing of the common chunks is already implemented in
IDirectMusicObject_ParseDescriptor(). You can use that; an example is in
seg_IPersistStream_Load().
- Please use something like "struct wave_item" instead of "struct
DMUS_PRIVATE_WAVE_ITEM".
I'm trying slowly to get rid of those DMUS_PRIVATE_*, especially the
LPDMUS_PRIVATE_* as it is confusing.
While it has PRIVATE in the name it trips me almost every time and I
assume a public type. Especially as there are a ton of PRIVATE stuff in
the public headers...
thanks
bye
michael
On 5/5/20 2:36 PM, Alistair Leslie-Hughes wrote:
> Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
> ---
> dlls/dmime/dmime_private.h | 7 +
> dlls/dmime/wavetrack.c | 264 ++++++++++++++++++++++++++++++++++++-
> 2 files changed, 269 insertions(+), 2 deletions(-)
>
> diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h
> index 9759039a03e9..fddb66e89f60 100644
> --- a/dlls/dmime/dmime_private.h
> +++ b/dlls/dmime/dmime_private.h
> @@ -86,6 +86,13 @@ typedef struct _DMUS_PRIVATE_TEMPO_ITEM {
> DMUS_IO_TEMPO_ITEM item;
> } DMUS_PRIVATE_TEMPO_ITEM, *LPDMUS_PRIVATE_TEMPO_ITEM;
>
> +struct DMUS_PRIVATE_WAVE_ITEM {
> + struct list entry; /* for listing elements */
> + DMUS_IO_WAVE_TRACK_HEADER header;
> +
> + IDirectMusicObject *object;
> +};
> +
> typedef struct _DMUS_PRIVATE_SEGMENT_ITEM {
> struct list entry; /* for listing elements */
> DMUS_IO_SEGMENT_ITEM_HEADER header;
> diff --git a/dlls/dmime/wavetrack.c b/dlls/dmime/wavetrack.c
> index 1c6b08b52355..84d0bfa10dd5 100644
> --- a/dlls/dmime/wavetrack.c
> +++ b/dlls/dmime/wavetrack.c
> @@ -20,6 +20,8 @@
> #include "dmime_private.h"
> #include "dmobject.h"
>
> +#include "wine/heap.h"
> +
> WINE_DEFAULT_DEBUG_CHANNEL(dmime);
>
> /*****************************************************************************
> @@ -32,6 +34,8 @@ typedef struct IDirectMusicWaveTrack {
> IDirectMusicTrack8 IDirectMusicTrack8_iface;
> struct dmobject dmobj; /* IPersistStream only */
> LONG ref;
> +
> + struct list items;
> } IDirectMusicWaveTrack;
>
> /* IDirectMusicWaveTrack IDirectMusicTrack8 part: */
> @@ -40,6 +44,11 @@ static inline IDirectMusicWaveTrack *impl_from_IDirectMusicTrack8(IDirectMusicTr
> return CONTAINING_RECORD(iface, IDirectMusicWaveTrack, IDirectMusicTrack8_iface);
> }
>
> +static inline IDirectMusicWaveTrack *impl_from_IPersistStream(IPersistStream *iface)
> +{
> + return CONTAINING_RECORD(iface, IDirectMusicWaveTrack, dmobj.IPersistStream_iface);
> +}
> +
> static HRESULT WINAPI wave_track_QueryInterface(IDirectMusicTrack8 *iface, REFIID riid,
> void **ret_iface)
> {
> @@ -81,6 +90,19 @@ static ULONG WINAPI wave_track_Release(IDirectMusicTrack8 *iface)
> TRACE("(%p) ref=%d\n", This, ref);
>
> if (!ref) {
> + struct list *cursor, *cursor2;
> + struct DMUS_PRIVATE_WAVE_ITEM *item;
> +
> + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->items) {
> + item = LIST_ENTRY(cursor, struct DMUS_PRIVATE_WAVE_ITEM, entry);
> + list_remove(cursor);
> +
> + if (item->object)
> + IDirectMusicObject_Release(item->object);
> +
> + heap_free(item);
> + }
> +
> HeapFree(GetProcessHeap(), 0, This);
> DMIME_UnlockModule();
> }
> @@ -280,10 +302,247 @@ static const IDirectMusicTrack8Vtbl dmtrack8_vtbl = {
> wave_track_Join
> };
>
> +static HRESULT stream_parse_reference(IStream *stream, const struct chunk_entry *parent,
> + IDirectMusicObject **object)
> +{
> + HRESULT hr;
> + struct chunk_entry chunk = {.parent = parent};
> + DMUS_IO_REFERENCE reference;
> + DMUS_OBJECTDESC description;
> + IDirectMusicGetLoader *getloader;
> + IDirectMusicLoader *loader;
> +
> + memset(&description, 0, sizeof(description));
> +
> + *object = NULL;
> +
> + if (FAILED(hr = stream_next_chunk(stream, &chunk)))
> + return hr;
> +
> + if(chunk.id != DMUS_FOURCC_REF_CHUNK)
> + return DMUS_E_UNSUPPORTED_STREAM;
> +
> + if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &reference, chunk.size))) {
> + WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
> + return hr;
> + }
> +
> + TRACE("REFERENCE guidClassID %s, dwValidData 0x%08x\n", debugstr_dmguid(&reference.guidClassID),
> + reference.dwValidData);
> +
> + description.dwValidData = DMUS_OBJ_CLASS;
> + description.guidClass = reference.guidClassID;
> +
> + while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) {
> + switch (chunk.id) {
> + case DMUS_FOURCC_GUID_CHUNK: {
> + if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &description.guidObject,
> + chunk.size))) {
> + WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
> + return hr;
> + }
> + description.dwValidData |= DMUS_OBJ_OBJECT;
> + break;
> + }
> + case DMUS_FOURCC_DATE_CHUNK: {
> + if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &description.ftDate,
> + chunk.size))) {
> + WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
> + return hr;
> + }
> + description.dwValidData |= DMUS_OBJ_DATE;
> + break;
> + }
> + case DMUS_FOURCC_NAME_CHUNK: {
> + if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &description.wszName,
> + chunk.size))) {
> + WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
> + return hr;
> + }
> + description.dwValidData |= DMUS_OBJ_NAME;
> + break;
> + }
> + case DMUS_FOURCC_FILE_CHUNK: {
> + if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &description.wszFileName,
> + chunk.size))) {
> + WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
> + return hr;
> + }
> + description.dwValidData |= DMUS_OBJ_FILENAME;
> + break;
> + }
> + case DMUS_FOURCC_VERSION_CHUNK: {
> + if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &description.vVersion,
> + chunk.size))) {
> + WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
> + return hr;
> + }
> + description.dwValidData |= DMUS_OBJ_VERSION;
> + break;
> + }
> + case DMUS_FOURCC_CATEGORY_CHUNK: {
> + if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &description.wszCategory,
> + chunk.size))) {
> + WARN("Failed to read data of %s\n", debugstr_chunk(&chunk));
> + return hr;
> + }
> + description.dwValidData |= DMUS_OBJ_CATEGORY;
> + break;
> + }
> + }
> + }
> +
> + dump_DMUS_OBJECTDESC(&description);
> +
> + hr = IStream_QueryInterface (stream, &IID_IDirectMusicGetLoader, (void**)&getloader);
> + if (FAILED(hr))
> + return hr;
> +
> + hr = IDirectMusicGetLoader_GetLoader (getloader, &loader);
> + if (FAILED(hr))
> + return hr;
> + IDirectMusicGetLoader_Release (getloader);
> +
> + hr = IDirectMusicLoader_GetObject (loader, &description, &IID_IDirectMusicObject, (void**)&object);
> + IDirectMusicLoader_Release (loader);
> +
> + return SUCCEEDED(hr) ? S_OK : hr;
> +}
> +
> +static HRESULT parse_wave_item(IDirectMusicWaveTrack *This, IStream *stream,
> + struct chunk_entry *wave, struct DMUS_PRIVATE_WAVE_ITEM *item)
> +{
> + HRESULT hr;
> + struct chunk_entry chunk = {.parent = wave};
> +
> + if (FAILED(hr = stream_next_chunk(stream, &chunk)))
> + return hr;
> +
> + if(chunk.id == FOURCC_LIST && chunk.type == DMUS_FOURCC_WAVE_LIST)
> + {
> + struct chunk_entry child = {.parent = &chunk};
> + DMUS_IO_WAVE_ITEM_HEADER header;
> +
> + if (FAILED(hr = stream_next_chunk(stream, &child)))
> + return hr;
> +
> + if(child.id != DMUS_FOURCC_WAVEITEM_CHUNK)
> + return DMUS_E_UNSUPPORTED_STREAM;
> +
> + if (FAILED(hr = stream_chunk_get_data(stream, &child, &header, child.size))) {
> + WARN("Failed to read data of %s\n", debugstr_chunk(&child));
> + return hr;
> + }
> +
> + TRACE("Found DMUS_IO_WAVE_ITEM_HEADER\n");
> + TRACE(" - lVolume %d\n", header.lVolume);
> + TRACE(" - dwVariations %d\n", header.dwVariations);
> + TRACE(" - rtTime %d\n", header.rtTime);
> + TRACE(" - rtStartOffset %d\n", header.rtStartOffset);
> + TRACE(" - rtReserved %d\n", header.rtReserved);
> + TRACE(" - rtDuration %d\n", header.rtDuration);
> + TRACE(" - dwLoopStart %d\n", header.dwLoopStart);
> + TRACE(" - dwLoopEnd %d\n", header.dwLoopEnd);
> + TRACE(" - dwFlags 0x%08x\n", header.dwFlags);
> + TRACE(" - wVolumeRange %d\n", header.wVolumeRange);
> + TRACE(" - wPitchRange %d\n", header.wPitchRange);
> +
> + if (FAILED(hr = stream_next_chunk(stream, &child)))
> + return hr;
> +
> + if(child.id == FOURCC_LIST && child.type == DMUS_FOURCC_REF_LIST)
> + {
> + hr = stream_parse_reference(stream, &child, &item->object);
> + }
> + }
> + else
> + hr = DMUS_E_UNSUPPORTED_STREAM;
> +
> + return SUCCEEDED(hr) ? S_OK : hr;
> +}
> +
> +static HRESULT parse_wavetrack_list(IDirectMusicWaveTrack *This, IStream *stream,
> + struct chunk_entry *wave)
> +{
> + HRESULT hr;
> + struct chunk_entry chunk = {.parent = wave};
> + struct DMUS_PRIVATE_WAVE_ITEM *item = NULL;
> +
> + TRACE("Parsing segment form in %p: %s\n", stream, debugstr_chunk(wave));
> +
> + if (FAILED(hr = stream_next_chunk(stream, &chunk)))
> + return hr;
> +
> + if (chunk.id != DMUS_FOURCC_WAVETRACK_CHUNK)
> + return DMUS_E_UNSUPPORTED_STREAM;
> +
> + item = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(struct DMUS_PRIVATE_WAVE_ITEM));
> + if (!item)
> + return E_OUTOFMEMORY;
> +
> + list_add_tail (&This->items, &item->entry);
> +
> + if (FAILED(hr = stream_next_chunk(stream, &chunk)))
> + return hr;
> +
> + if (chunk.id == FOURCC_LIST && chunk.type == DMUS_FOURCC_WAVEPART_LIST)
> + {
> + struct chunk_entry child = {.parent = wave};
> + DMUS_IO_WAVE_PART_HEADER header;
> +
> + if (FAILED(hr = stream_next_chunk(stream, &child)))
> + return hr;
> +
> + if (child.id != DMUS_FOURCC_WAVEPART_CHUNK)
> + return DMUS_E_UNSUPPORTED_STREAM;
> +
> + if (FAILED(hr = stream_chunk_get_data(stream, &child, &header, child.size))) {
> + WARN("Failed to read data of %s\n", debugstr_chunk(&child));
> + return hr;
> + }
> +
> + TRACE("Found DMUS_IO_WAVE_PART_HEADER\n");
> + TRACE(" - lVolume %d\n", header.lVolume);
> + TRACE(" - dwVariations %d\n", header.dwVariations);
> + TRACE(" - dwPChannel %d\n", header.dwPChannel);
> + TRACE(" - dwLockToPart %d\n", header.dwLockToPart);
> + TRACE(" - dwFlags 0x%08x\n", header.dwFlags);
> + TRACE(" - dwIndex %d\n", header.dwIndex);
> +
> + if (FAILED(hr = stream_next_chunk(stream, &child)))
> + return hr;
> +
> + if(child.id != FOURCC_LIST || child.type != DMUS_FOURCC_WAVEITEM_LIST)
> + return DMUS_E_UNSUPPORTED_STREAM;
> +
> + hr = parse_wave_item(This, stream, &child, item);
> + }
> + else
> + hr = DMUS_E_UNSUPPORTED_STREAM;
> +
> + return SUCCEEDED(hr) ? S_OK : hr;
> +}
> +
> static HRESULT WINAPI wave_IPersistStream_Load(IPersistStream *iface, IStream *stream)
> {
> - FIXME(": Loading not implemented yet\n");
> - return S_OK;
> + IDirectMusicWaveTrack *This = impl_from_IPersistStream(iface);
> + HRESULT hr;
> + struct chunk_entry chunk = {0};
> +
> + TRACE("%p, %p\n", This, stream);
> +
> + if (!stream)
> + return E_POINTER;
> +
> + if ((hr = stream_get_chunk(stream, &chunk) != S_OK))
> + return hr;
> +
> + if (chunk.id == FOURCC_LIST && chunk.type == DMUS_FOURCC_WAVETRACK_LIST)
> + hr = parse_wavetrack_list(This, stream, &chunk);
> + else
> + hr = DMUS_E_UNSUPPORTED_STREAM;
> +
> + return hr;
> }
>
> static const IPersistStreamVtbl persiststream_vtbl = {
> @@ -313,6 +572,7 @@ HRESULT WINAPI create_dmwavetrack(REFIID lpcGUID, void **ppobj)
> dmobject_init(&track->dmobj, &CLSID_DirectMusicWaveTrack,
> (IUnknown *)&track->IDirectMusicTrack8_iface);
> track->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
> + list_init(&track->items);
>
> DMIME_LockModule();
> hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, lpcGUID, ppobj);
>
More information about the wine-devel
mailing list