Module: wine Branch: master Commit: 4a7a8a7ecc8bc259da58470a7e4be64b9ba2cd8e URL: https://gitlab.winehq.org/wine/wine/-/commit/4a7a8a7ecc8bc259da58470a7e4be64...
Author: Rémi Bernon rbernon@codeweavers.com Date: Mon Sep 25 11:21:38 2023 +0200
dmime: Implement GUID_(Download|Unload)FromAudioPath for wave track.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=9027 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=34751 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45135 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48220
---
dlls/dmime/dmime_private.h | 2 ++ dlls/dmime/performance.c | 14 ++++++++++ dlls/dmime/wavetrack.c | 70 ++++++++++++++++++++++++++++++++++++++++------ dlls/dmusic/dmusic_wave.h | 1 + dlls/dmusic/wave.c | 39 ++++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 8 deletions(-)
diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h index 636004aed84..c1f777f3949 100644 --- a/dlls/dmime/dmime_private.h +++ b/dlls/dmime/dmime_private.h @@ -80,6 +80,8 @@ extern HRESULT segment_state_end_play(IDirectMusicSegmentState *iface); extern HRESULT wave_track_create_from_chunk(IStream *stream, struct chunk_entry *parent, IDirectMusicTrack8 **ret_iface);
+extern HRESULT performance_get_dsound(IDirectMusicPerformance8 *iface, IDirectSound **dsound); + /***************************************************************************** * Auxiliary definitions */ diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 327f7d88c3b..84b4b4b8575 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -1731,3 +1731,17 @@ HRESULT create_dmperformance(REFIID iid, void **ret_iface) IDirectMusicPerformance_Release(&obj->IDirectMusicPerformance8_iface); return hr; } + +static inline struct performance *unsafe_impl_from_IDirectMusicPerformance8(IDirectMusicPerformance8 *iface) +{ + if (iface->lpVtbl != &performance_vtbl) return NULL; + return CONTAINING_RECORD(iface, struct performance, IDirectMusicPerformance8_iface); +} + +HRESULT performance_get_dsound(IDirectMusicPerformance8 *iface, IDirectSound **dsound) +{ + struct performance *This = unsafe_impl_from_IDirectMusicPerformance8(iface); + if (!This || !(*dsound = This->dsound)) return E_FAIL; + IDirectSound_AddRef(*dsound); + return S_OK; +} diff --git a/dlls/dmime/wavetrack.c b/dlls/dmime/wavetrack.c index d9d6334adad..7c72065520a 100644 --- a/dlls/dmime/wavetrack.c +++ b/dlls/dmime/wavetrack.c @@ -25,6 +25,7 @@ struct wave_item { struct list entry; DMUS_IO_WAVE_ITEM_HEADER header; IUnknown *object; + IDirectSoundBuffer *buffer; };
struct wave_part { @@ -97,13 +98,18 @@ static ULONG WINAPI wave_track_Release(IDirectMusicTrack8 *iface) struct wave_item *item, *item2; struct wave_part *part, *part2;
- LIST_FOR_EACH_ENTRY_SAFE(part, part2, &This->parts, struct wave_part, entry) { + LIST_FOR_EACH_ENTRY_SAFE(part, part2, &This->parts, struct wave_part, entry) + { list_remove(&part->entry); - LIST_FOR_EACH_ENTRY_SAFE(item, item2, &part->items, struct wave_item, entry) { + + LIST_FOR_EACH_ENTRY_SAFE(item, item2, &part->items, struct wave_item, entry) + { list_remove(&item->entry); + if (item->buffer) IDirectSoundBuffer_Release(item->buffer); if (item->object) IUnknown_Release(item->object); free(item); } + free(part); }
@@ -171,9 +177,46 @@ static HRESULT WINAPI wave_track_SetParam(IDirectMusicTrack8 *iface, REFGUID typ FIXME("GUID_Download not handled yet\n"); return S_OK; } - if (IsEqualGUID(type, &GUID_DownloadToAudioPath)) { - FIXME("GUID_DownloadToAudioPath not handled yet\n"); - return S_OK; + if (IsEqualGUID(type, &GUID_DownloadToAudioPath)) + { + IDirectMusicPerformance8 *performance; + IDirectMusicAudioPath *audio_path; + IUnknown *object = param; + struct wave_part *part; + struct wave_item *item; + IDirectSound *dsound; + HRESULT hr; + + if (FAILED(hr = IDirectMusicAudioPath_QueryInterface(object, &IID_IDirectMusicPerformance8, (void **)&performance)) + && SUCCEEDED(hr = IDirectMusicAudioPath_QueryInterface(object, &IID_IDirectMusicAudioPath, (void **)&audio_path))) + { + hr = IDirectMusicAudioPath_GetObjectInPath(audio_path, DMUS_PCHANNEL_ALL, DMUS_PATH_PERFORMANCE, 0, + &GUID_All_Objects, 0, &IID_IDirectMusicPerformance8, (void **)&performance); + IDirectMusicAudioPath_Release(audio_path); + } + + if (SUCCEEDED(hr)) + hr = performance_get_dsound(performance, &dsound); + IDirectMusicPerformance_Release(performance); + + if (FAILED(hr)) + { + WARN("Failed to get direct sound from param %p, hr %#lx\n", param, hr); + return hr; + } + + LIST_FOR_EACH_ENTRY(part, &This->parts, struct wave_part, entry) + { + LIST_FOR_EACH_ENTRY(item, &part->items, struct wave_item, entry) + { + if (item->buffer) continue; + if (FAILED(hr = wave_download_to_dsound(item->object, dsound, &item->buffer))) + { + WARN("Failed to download wave %p to direct sound, hr %#lx\n", item->object, hr); + return hr; + } + } + } } if (IsEqualGUID(type, &GUID_Enable_Auto_Download)) { FIXME("GUID_Enable_Auto_Download not handled yet\n"); @@ -183,9 +226,20 @@ static HRESULT WINAPI wave_track_SetParam(IDirectMusicTrack8 *iface, REFGUID typ FIXME("GUID_Unload not handled yet\n"); return S_OK; } - if (IsEqualGUID(type, &GUID_UnloadFromAudioPath)) { - FIXME("GUID_UnloadFromAudioPath not handled yet\n"); - return S_OK; + if (IsEqualGUID(type, &GUID_UnloadFromAudioPath)) + { + struct wave_part *part; + struct wave_item *item; + + LIST_FOR_EACH_ENTRY(part, &This->parts, struct wave_part, entry) + { + LIST_FOR_EACH_ENTRY(item, &part->items, struct wave_item, entry) + { + if (!item->buffer) continue; + IDirectSoundBuffer_Release(item->buffer); + item->buffer = NULL; + } + } }
return DMUS_E_TYPE_UNSUPPORTED; diff --git a/dlls/dmusic/dmusic_wave.h b/dlls/dmusic/dmusic_wave.h index 3f7209e250e..43396250261 100644 --- a/dlls/dmusic/dmusic_wave.h +++ b/dlls/dmusic/dmusic_wave.h @@ -32,4 +32,5 @@ struct chunk_entry; extern HRESULT wave_create_from_soundfont(struct soundfont *soundfont, UINT index, IUnknown **out); extern HRESULT wave_create_from_chunk(IStream *stream, struct chunk_entry *parent, IUnknown **out); extern HRESULT wave_download_to_port(IUnknown *iface, IDirectMusicPortDownload *port, DWORD *id); +extern HRESULT wave_download_to_dsound(IUnknown *iface, IDirectSound *dsound, IDirectSoundBuffer **ret_iface); extern HRESULT wave_get_duration(IUnknown *iface, REFERENCE_TIME *duration); diff --git a/dlls/dmusic/wave.c b/dlls/dmusic/wave.c index 2f5e1409106..ef1cd2990ff 100644 --- a/dlls/dmusic/wave.c +++ b/dlls/dmusic/wave.c @@ -339,6 +339,45 @@ HRESULT wave_download_to_port(IUnknown *iface, IDirectMusicPortDownload *port, D return hr; }
+HRESULT wave_download_to_dsound(IUnknown *iface, IDirectSound *dsound, IDirectSoundBuffer **ret_iface) +{ + struct wave *This = impl_from_IUnknown(iface); + DSBUFFERDESC desc = + { + .dwSize = sizeof(desc), + .dwBufferBytes = This->data_size, + .lpwfxFormat = This->format, + }; + IDirectSoundBuffer *buffer; + HRESULT hr; + void *data; + DWORD size; + + TRACE("%p, %p, %p\n", This, dsound, ret_iface); + + if (FAILED(hr = IDirectSound_CreateSoundBuffer(dsound, &desc, &buffer, NULL))) + { + WARN("Failed to create direct sound buffer, hr %#lx\n", hr); + return hr; + } + + if (SUCCEEDED(hr = IDirectSoundBuffer_Lock(buffer, 0, This->data_size, &data, &size, NULL, 0, 0))) + { + memcpy(data, This->data, This->data_size); + hr = IDirectSoundBuffer_Unlock(buffer, data, This->data_size, NULL, 0); + } + + if (FAILED(hr)) + { + WARN("Failed to download wave to dsound, hr %#lx\n", hr); + IDirectSoundBuffer_Release(buffer); + return hr; + } + + *ret_iface = buffer; + return S_OK; +} + HRESULT wave_get_duration(IUnknown *iface, REFERENCE_TIME *duration) { struct wave *This = impl_from_IUnknown(iface);