[PATCH 1/2] dmime: Parse Wave track stream

Michael Stefaniuc mstefani at winehq.org
Wed Nov 3 20:14:41 CDT 2021


Hello Alistair,

what about the attached patch? It got only basic testing aka Tron 2.0 demo 
doesn't crashes straight ahead on me and I see the code being hit in the TRACEs.

I ended up re-implementing some parts of it due to multiple issues:
- While it made sense to merge in parse_wavetrack_list() I missed the part to 
split out parse_wave_part().
   The generic idea is to keep a single chunk nesting level per function, 
basically not having to keep track of nesting. Means just one "cursor" chunk per 
function with an optional extra parent chunk that gets read at the very beginning.

- According to 
https://docs.microsoft.com/en-us/previous-versions/ms811352(v=msdn.10) both the 
wave parts as well as the wave items are actual arrays. Tron seems to just have 
a single entry of each but the code should deal with arrays in both cases.

- The headers weren't stored.


thanks
bye
	michael


On 11/1/21 07:30, Alistair Leslie-Hughes wrote:
> Tron 2.0
> 
> Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
> ---
>   dlls/dmime/dmime_private.h |   6 ++
>   dlls/dmime/wavetrack.c     | 148 ++++++++++++++++++++++++++++++++++++-
>   2 files changed, 152 insertions(+), 2 deletions(-)
> 
> diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h
> index c2221a15fd2..6ab47292b39 100644
> --- a/dlls/dmime/dmime_private.h
> +++ b/dlls/dmime/dmime_private.h
> @@ -86,6 +86,12 @@ typedef struct _DMUS_PRIVATE_TEMPO_ITEM {
>     DMUS_IO_TEMPO_ITEM item;
>   } DMUS_PRIVATE_TEMPO_ITEM, *LPDMUS_PRIVATE_TEMPO_ITEM;
>   
> +struct wave_item {
> +    struct list entry;
> +    DMUS_IO_WAVE_TRACK_HEADER header;
> +    IDirectMusicObject *object;
> +};
> +
>   typedef struct _DMUS_PRIVATE_GRAPH_TOOL {
>     struct list entry; /* for listing elements */
>     DWORD dwIndex;
> diff --git a/dlls/dmime/wavetrack.c b/dlls/dmime/wavetrack.c
> index 1c6b08b5235..da7ef37d2c8 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 wave_item *item;
> +
> +        LIST_FOR_EACH_SAFE(cursor, cursor2, &This->items) {
> +            item = LIST_ENTRY(cursor, struct 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,131 @@ static const IDirectMusicTrack8Vtbl dmtrack8_vtbl = {
>       wave_track_Join
>   };
>   
> +static HRESULT parse_wave_item(IDirectMusicWaveTrack *This, IStream *stream,
> +        struct chunk_entry *wave, struct 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, sizeof(header)))) {
> +            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 %s\n", wine_dbgstr_longlong(header.rtTime));
> +        TRACE("  - rtStartOffset %s\n", wine_dbgstr_longlong(header.rtStartOffset));
> +        TRACE("  - rtReserved %s\n", wine_dbgstr_longlong(header.rtReserved));
> +        TRACE("  - rtDuration %s\n", wine_dbgstr_longlong(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 (FAILED(hr = dmobj_parsereference(stream, &chunk, &item->object)))
> +            return hr;
> +    }
> +    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)
> +    {
> +        struct chunk_entry chunklist = {.parent = &chunk};
> +        struct wave_item *item = NULL;
> +
> +        TRACE("Parsing segment form in %p: %s\n", stream, debugstr_chunk(&chunklist));
> +
> +        if (FAILED(hr = stream_next_chunk(stream, &chunklist)))
> +            return hr;
> +
> +        if (chunklist.id != DMUS_FOURCC_WAVETRACK_CHUNK)
> +            return DMUS_E_UNSUPPORTED_STREAM;
> +
> +        item = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(struct wave_item));
> +        if (!item)
> +            return  E_OUTOFMEMORY;
> +
> +        list_add_tail (&This->items, &item->entry);
> +
> +        if (FAILED(hr = stream_next_chunk(stream, &chunklist)))
> +            return hr;
> +
> +        if (chunklist.id == FOURCC_LIST && chunklist.type == DMUS_FOURCC_WAVEPART_LIST)
> +        {
> +            struct chunk_entry child = {.parent = &chunklist};
> +            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, sizeof(header)))) {
> +                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;
> +    }
> +    else
> +        hr = DMUS_E_UNSUPPORTED_STREAM;
> +
> +    return hr;
>   }
>   
>   static const IPersistStreamVtbl persiststream_vtbl = {
> @@ -313,6 +456,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);
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-dmime-Implement-the-Wave-track-parser.patch
Type: text/x-patch
Size: 8670 bytes
Desc: not available
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20211104/76ae3f28/attachment-0001.bin>


More information about the wine-devel mailing list