Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/dmime/dmime_private.h | 6 ++
dlls/dmime/wavetrack.c | 196 ++++++++++++++++++++++++++++++++++++-
2 files changed, 200 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..92419729fce 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,179 @@ 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, 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 %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(child.id == FOURCC_LIST && child.type == DMUS_FOURCC_REF_LIST)
+ {
+ struct chunk_entry dmrf = {.parent = &child};
+ IDirectMusicGetLoader *getloader;
+ IDirectMusicLoader *loader;
+ DMUS_IO_REFERENCE reference;
+
+ if (FAILED(hr = stream_next_chunk(stream, &dmrf)))
+ return hr;
+
+ if(dmrf.id != DMUS_FOURCC_REF_CHUNK)
+ return DMUS_E_UNSUPPORTED_STREAM;
+
+ if (FAILED(hr = stream_chunk_get_data(stream, &dmrf, &reference, dmrf.size))) {
+ WARN("Failed to read data of %s\n", debugstr_chunk(&dmrf));
+ return hr;
+ }
+
+ TRACE("REFERENCE guidClassID %s, dwValidData 0x%08x\n", debugstr_dmguid(&reference.guidClassID),
+ reference.dwValidData);
+
+ This->dmobj.desc.guidClass = reference.guidClassID;
+ This->dmobj.desc.dwValidData = DMUS_OBJ_CLASS;
+
+ hr = dmobj_parsedescriptor(stream, &child, &This->dmobj.desc, reference.dwValidData);
+ if (FAILED(hr))
+ return hr;
+
+ dump_DMUS_OBJECTDESC(&This->dmobj.desc);
+
+ 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, &This->dmobj.desc, &IID_IDirectMusicObject,
+ (void**)&item->object);
+ IDirectMusicLoader_Release (loader);
+ }
+ }
+ 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 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 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 +504,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);
--
2.33.0