Module: wine Branch: master Commit: d32fb707ad30fad9e13d4609e4347dab55ec8a8b URL: https://gitlab.winehq.org/wine/wine/-/commit/d32fb707ad30fad9e13d4609e4347da...
Author: Rémi Bernon rbernon@codeweavers.com Date: Sat Sep 9 14:06:32 2023 +0200
dmusic: Implement downloading wave to port.
---
dlls/dmusic/collection.c | 21 +++++++++++++++++++++ dlls/dmusic/dmusic_private.h | 2 ++ dlls/dmusic/instrument.c | 33 +++++++++++++++++++++++++++++++++ dlls/dmusic/tests/dmusic.c | 4 +--- dlls/dmusic/wave.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 3 deletions(-)
diff --git a/dlls/dmusic/collection.c b/dlls/dmusic/collection.c index cfe7589485d..b7c11dacb77 100644 --- a/dlls/dmusic/collection.c +++ b/dlls/dmusic/collection.c @@ -72,6 +72,27 @@ extern void collection_internal_release(struct collection *collection) free(collection); }
+extern HRESULT collection_get_wave(struct collection *collection, DWORD index, IUnknown **out) +{ + struct wave_entry *wave_entry; + DWORD offset; + + if (index >= collection->pool->table.cCues) return E_INVALIDARG; + offset = collection->pool->cues[index].ulOffset; + + LIST_FOR_EACH_ENTRY(wave_entry, &collection->waves, struct wave_entry, entry) + { + if (offset == wave_entry->offset) + { + *out = wave_entry->wave; + IUnknown_AddRef(wave_entry->wave); + return S_OK; + } + } + + return E_FAIL; +} + static inline struct collection *impl_from_IDirectMusicCollection(IDirectMusicCollection *iface) { return CONTAINING_RECORD(iface, struct collection, IDirectMusicCollection_iface); diff --git a/dlls/dmusic/dmusic_private.h b/dlls/dmusic/dmusic_private.h index 1f6b33ec34d..0b000fb6f1c 100644 --- a/dlls/dmusic/dmusic_private.h +++ b/dlls/dmusic/dmusic_private.h @@ -79,6 +79,7 @@ typedef struct port_info { struct collection; extern void collection_internal_addref(struct collection *collection); extern void collection_internal_release(struct collection *collection); +extern HRESULT collection_get_wave(struct collection *collection, DWORD index, IUnknown **out);
/* CLSID */ extern HRESULT music_create(IUnknown **ret_iface); @@ -97,6 +98,7 @@ extern HRESULT instrument_download_to_port(IDirectMusicInstrument *iface, IDirec extern HRESULT instrument_unload_from_port(IDirectMusicDownloadedInstrument *iface, IDirectMusicPortDownload *port);
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);
/***************************************************************************** * IDirectMusic8Impl implementation structure diff --git a/dlls/dmusic/instrument.c b/dlls/dmusic/instrument.c index b79e7671c5b..663e2112a06 100644 --- a/dlls/dmusic/instrument.c +++ b/dlls/dmusic/instrument.c @@ -453,6 +453,7 @@ HRESULT instrument_download_to_port(IDirectMusicInstrument *iface, IDirectMusicP IDirectMusicDownload *download; DWORD size, offset_count; struct region *region; + IUnknown *wave; HRESULT hr;
if (This->download) goto done; @@ -509,6 +510,13 @@ HRESULT instrument_download_to_port(IDirectMusicInstrument *iface, IDirectMusicP dmus_region->WaveLink = region->wave_link; dmus_region->WSMP = region->wave_sample; dmus_region->WLOOP[0] = region->wave_loop; + + if (SUCCEEDED(hr = collection_get_wave(This->collection, region->wave_link.ulTableIndex, &wave))) + { + hr = wave_download_to_port(wave, port, &dmus_region->WaveLink.ulTableIndex); + IUnknown_Release(wave); + } + if (FAILED(hr)) goto failed; }
if (FAILED(hr = IDirectMusicPortDownload_Download(port, download))) goto failed; @@ -530,12 +538,37 @@ failed: HRESULT instrument_unload_from_port(IDirectMusicDownloadedInstrument *iface, IDirectMusicPortDownload *port) { struct instrument *This = impl_from_IDirectMusicDownloadedInstrument(iface); + struct download_buffer *buffer; + DWORD size; HRESULT hr;
if (!This->download) return DMUS_E_NOT_DOWNLOADED_TO_PORT;
if (FAILED(hr = IDirectMusicPortDownload_Unload(port, This->download))) WARN("Failed to unload instrument download buffer, hr %#lx\n", hr); + else if (SUCCEEDED(hr = IDirectMusicDownload_GetBuffer(This->download, (void **)&buffer, &size))) + { + IDirectMusicDownload *wave_download; + DMUS_INSTRUMENT *instrument; + BYTE *ptr = (BYTE *)buffer; + DMUS_REGION *region; + UINT index; + + instrument = (DMUS_INSTRUMENT *)(ptr + buffer->offsets[0]); + for (index = instrument->ulFirstRegionIdx; index; index = region->ulNextRegionIdx) + { + region = (DMUS_REGION *)(ptr + buffer->offsets[index]); + + if (FAILED(hr = IDirectMusicPortDownload_GetBuffer(port, region->WaveLink.ulTableIndex, &wave_download))) + WARN("Failed to get wave download with id %#lx, hr %#lx\n", region->WaveLink.ulTableIndex, hr); + else + { + if (FAILED(hr = IDirectMusicPortDownload_Unload(port, wave_download))) + WARN("Failed to unload wave download buffer, hr %#lx\n", hr); + IDirectMusicDownload_Release(wave_download); + } + } + }
IDirectMusicDownload_Release(This->download); This->download = NULL; diff --git a/dlls/dmusic/tests/dmusic.c b/dlls/dmusic/tests/dmusic.c index 1561c51df76..879a6f800cd 100644 --- a/dlls/dmusic/tests/dmusic.c +++ b/dlls/dmusic/tests/dmusic.c @@ -1300,8 +1300,7 @@ static void test_download_instrument(void) check_interface(instrument, &IID_IDirectMusicDownloadedInstrument, FALSE);
hr = IDirectMusicPort_DownloadInstrument(port, instrument, &downloaded, NULL, 0); - todo_wine ok(hr == S_OK, "got %#lx\n", hr); - if (hr != S_OK) goto skip_tests; + ok(hr == S_OK, "got %#lx\n", hr);
check_interface(downloaded, &IID_IDirectMusicObject, FALSE); check_interface(downloaded, &IID_IDirectMusicDownload, FALSE); @@ -1313,7 +1312,6 @@ static void test_download_instrument(void)
IDirectMusicInstrument_Release(instrument);
-skip_tests: IDirectMusicCollection_Release(collection); IDirectMusicPort_Release(port); IDirectMusic_Release(dmusic); diff --git a/dlls/dmusic/wave.c b/dlls/dmusic/wave.c index cda895484cb..08146db0d1c 100644 --- a/dlls/dmusic/wave.c +++ b/dlls/dmusic/wave.c @@ -212,3 +212,46 @@ HRESULT wave_create_from_chunk(IStream *stream, struct chunk_entry *parent, IUnk *ret_iface = iface; return S_OK; } + +HRESULT wave_download_to_port(IUnknown *iface, IDirectMusicPortDownload *port, DWORD *id) +{ + struct download_buffer + { + DMUS_DOWNLOADINFO info; + ULONG offsets[2]; + DMUS_WAVE wave; + DMUS_WAVEDATA data; + } *buffer; + + struct wave *This = impl_from_IUnknown(iface); + DWORD size = offsetof(struct download_buffer, data.byData[This->data_size]); + IDirectMusicDownload *download; + HRESULT hr; + + if (FAILED(hr = IDirectMusicPortDownload_AllocateBuffer(port, size, &download))) return hr; + + if (SUCCEEDED(hr = IDirectMusicDownload_GetBuffer(download, (void **)&buffer, &size)) + && SUCCEEDED(hr = IDirectMusicPortDownload_GetDLId(port, &buffer->info.dwDLId, 1))) + { + buffer->info.dwDLType = DMUS_DOWNLOADINFO_WAVE; + buffer->info.dwNumOffsetTableEntries = 2; + buffer->info.cbSize = size; + + buffer->offsets[0] = offsetof(struct download_buffer, wave); + buffer->offsets[1] = offsetof(struct download_buffer, data); + + buffer->wave.WaveformatEx = *This->format; + buffer->wave.ulWaveDataIdx = 1; + buffer->wave.ulCopyrightIdx = 0; + buffer->wave.ulFirstExtCkIdx = 0; + + buffer->data.cbSize = This->data_size; + memcpy(buffer->data.byData, This->data, This->data_size); + + if (SUCCEEDED(hr = IDirectMusicPortDownload_Download(port, download))) *id = buffer->info.dwDLId; + else WARN("Failed to download wave to port, hr %#lx\n", hr); + } + + IDirectMusicDownload_Release(download); + return hr; +}