diff --git a/dlls/dmusic/wave.c b/dlls/dmusic/wave.c index ef1cd2990ff..e5e7c4dc2a0 100644 --- a/dlls/dmusic/wave.c +++ b/dlls/dmusic/wave.c @@ -32,6 +32,7 @@ C_ASSERT(sizeof(struct sample) == offsetof(struct sample, loops[0])); struct wave { IUnknown IUnknown_iface; + struct dmobject dmobj; LONG ref; struct sample *sample; @@ -58,6 +59,20 @@ static HRESULT WINAPI wave_QueryInterface(IUnknown *iface, REFIID riid, void **r return S_OK; } + if (IsEqualIID(riid, &IID_IDirectMusicObject)) + { + *ret_iface = &This->dmobj.IDirectMusicObject_iface; + IDirectMusicObject_AddRef(&This->dmobj.IDirectMusicObject_iface); + return S_OK; + } + + if (IsEqualIID(riid, &IID_IPersistStream)) + { + *ret_iface = &This->dmobj.IPersistStream_iface; + IDirectMusicObject_AddRef(&This->dmobj.IPersistStream_iface); + return S_OK; + } + WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface); *ret_iface = NULL; return E_NOINTERFACE; @@ -96,18 +111,6 @@ static const IUnknownVtbl unknown_vtbl = wave_Release, }; -static HRESULT wave_create(IUnknown **ret_iface) -{ - struct wave *obj; - - if (!(obj = calloc(1, sizeof(*obj)))) return E_OUTOFMEMORY; - obj->IUnknown_iface.lpVtbl = &unknown_vtbl; - obj->ref = 1; - - *ret_iface = &obj->IUnknown_iface; - return S_OK; -} - static HRESULT parse_wsmp_chunk(struct wave *This, IStream *stream, struct chunk_entry *chunk) { struct sample *sample; @@ -167,6 +170,110 @@ static HRESULT parse_wave_chunk(struct wave *This, IStream *stream, struct chunk return hr; } +static HRESULT WINAPI wave_object_ParseDescriptor(IDirectMusicObject *iface, + IStream *stream, DMUS_OBJECTDESC *desc) +{ + struct chunk_entry chunk = {0}; + HRESULT hr; + + TRACE("(%p, %p, %p)\n", iface, stream, desc); + + if (!stream || !desc) return E_POINTER; + + if ((hr = stream_next_chunk(stream, &chunk)) == S_OK) + { + switch (MAKE_IDTYPE(chunk.id, chunk.type)) + { + case MAKE_IDTYPE(FOURCC_RIFF, mmioFOURCC('W','A','V','E')): + hr = dmobj_parsedescriptor(stream, &chunk, desc, + DMUS_OBJ_NAME_INFO | DMUS_OBJ_OBJECT | DMUS_OBJ_VERSION); + break; + + default: + WARN("Invalid wave chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type)); + hr = DMUS_E_CHUNKNOTFOUND; + break; + } + } + + if (FAILED(hr)) return hr; + + TRACE("returning descriptor:\n"); + dump_DMUS_OBJECTDESC(desc); + return S_OK; +} + +static const IDirectMusicObjectVtbl wave_object_vtbl = +{ + dmobj_IDirectMusicObject_QueryInterface, + dmobj_IDirectMusicObject_AddRef, + dmobj_IDirectMusicObject_Release, + dmobj_IDirectMusicObject_GetDescriptor, + dmobj_IDirectMusicObject_SetDescriptor, + wave_object_ParseDescriptor, +}; + +static inline struct wave *impl_from_IPersistStream(IPersistStream *iface) +{ + return CONTAINING_RECORD(iface, struct wave, dmobj.IPersistStream_iface); +} + +static HRESULT WINAPI wave_persist_stream_Load(IPersistStream *iface, IStream *stream) +{ + struct wave *This = impl_from_IPersistStream(iface); + struct chunk_entry chunk = {0}; + HRESULT hr; + + TRACE("(%p, %p)\n", This, stream); + + if (!stream) return E_POINTER; + + if ((hr = stream_next_chunk(stream, &chunk)) == S_OK) + { + switch (MAKE_IDTYPE(chunk.id, chunk.type)) + { + case MAKE_IDTYPE(FOURCC_RIFF, mmioFOURCC('W','A','V','E')): + hr = parse_wave_chunk(This, stream, &chunk); + break; + + default: + WARN("Invalid wave chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type)); + hr = DMUS_E_UNSUPPORTED_STREAM; + break; + } + } + + stream_skip_chunk(stream, &chunk); + return hr; +} + +static const IPersistStreamVtbl wave_persist_stream_vtbl = +{ + dmobj_IPersistStream_QueryInterface, + dmobj_IPersistStream_AddRef, + dmobj_IPersistStream_Release, + dmobj_IPersistStream_GetClassID, + unimpl_IPersistStream_IsDirty, + wave_persist_stream_Load, + unimpl_IPersistStream_Save, + unimpl_IPersistStream_GetSizeMax, +}; + +static HRESULT wave_create(IUnknown **ret_iface) +{ + struct wave *obj; + + if (!(obj = calloc(1, sizeof(*obj)))) return E_OUTOFMEMORY; + obj->IUnknown_iface.lpVtbl = &unknown_vtbl; + obj->ref = 1; + dmobject_init(&obj->dmobj, &CLSID_DirectSoundWave, &obj->IUnknown_iface); + obj->dmobj.IDirectMusicObject_iface.lpVtbl = &wave_object_vtbl; + obj->dmobj.IPersistStream_iface.lpVtbl = &wave_persist_stream_vtbl; + + *ret_iface = &obj->IUnknown_iface; + return S_OK; +} + HRESULT wave_create_from_chunk(IStream *stream, struct chunk_entry *parent, IUnknown **ret_iface) { struct wave *This;