From c6694e6dec9c9010d10ed7fe37526218b3a99302 Mon Sep 17 00:00:00 2001 From: Christian Costa Date: Mon, 24 Dec 2012 09:46:18 +0100 Subject: [PATCH] dmusic: Implement SynthPortImpl_IDirectMusicPort_DownloadInstrument. --- dlls/dmusic/dmusic_private.h | 2 + dlls/dmusic/port.c | 106 +++++++++++++++++++++++++++++++++-- 2 files changed, 104 insertions(+), 4 deletions(-) diff --git a/dlls/dmusic/dmusic_private.h b/dlls/dmusic/dmusic_private.h index 18721770ddc..286b48b1c80 100644 --- a/dlls/dmusic/dmusic_private.h +++ b/dlls/dmusic/dmusic_private.h @@ -140,6 +140,8 @@ struct IDirectMusicDownloadedInstrumentImpl { LONG ref; /* IDirectMusicDownloadedInstrumentImpl fields */ + BOOL downloaded; + void *data; }; /***************************************************************************** diff --git a/dlls/dmusic/port.c b/dlls/dmusic/port.c index eb139cae33c..55d0dad31a0 100644 --- a/dlls/dmusic/port.c +++ b/dlls/dmusic/port.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include #include "dmusic_private.h" WINE_DEFAULT_DEBUG_CHANNEL(dmusic); @@ -82,7 +83,10 @@ static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_Release(LPDIRECTMUSICDO TRACE("(%p)->(): new ref = %u\n", iface, ref); if (!ref) + { + HeapFree(GetProcessHeap(), 0, This->data); HeapFree(GetProcessHeap(), 0, This); + } DMUSIC_UnlockModule(); @@ -95,11 +99,20 @@ static const IDirectMusicDownloadedInstrumentVtbl DirectMusicDownloadedInstrumen IDirectMusicDownloadedInstrumentImpl_Release }; +static inline IDirectMusicDownloadedInstrumentImpl* unsafe_impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface) +{ + if (!iface) + return NULL; + assert(iface->lpVtbl == &DirectMusicDownloadedInstrument_Vtbl); + + return impl_from_IDirectMusicDownloadedInstrument(iface); +} + HRESULT DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(IDirectMusicDownloadedInstrument **instrument) { IDirectMusicDownloadedInstrumentImpl *object; - object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object)); + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); if (!object) { *instrument = NULL; @@ -227,20 +240,105 @@ static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_Read(LPDIRECTMUSICPORT ifac static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_DownloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicInstrument* instrument, IDirectMusicDownloadedInstrument** downloaded_instrument, DMUS_NOTERANGE* note_ranges, DWORD num_note_ranges) { SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); + IDirectMusicInstrumentImpl *instrument_object; + HRESULT ret; + BOOL free; + HANDLE download; + DMUS_DOWNLOADINFO *info; + DMUS_OFFSETTABLE *offset_table; + DMUS_INSTRUMENT *instrument_info; + BYTE *data; + ULONG offset; + ULONG nb_regions; + ULONG size; + int i; - FIXME("(%p/%p)->(%p, %p, %p, %d): stub\n", iface, This, instrument, downloaded_instrument, note_ranges, num_note_ranges); + TRACE("(%p/%p)->(%p, %p, %p, %d)\n", iface, This, instrument, downloaded_instrument, note_ranges, num_note_ranges); if (!instrument || !downloaded_instrument || (num_note_ranges && !note_ranges)) return E_POINTER; - return DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(downloaded_instrument); + instrument_object = impl_from_IDirectMusicInstrument(instrument); + + nb_regions = instrument_object->header.cRegions; + size = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions) + sizeof(DMUS_INSTRUMENT) + sizeof(DMUS_REGION) * nb_regions; + + data = (BYTE*)HeapAlloc(GetProcessHeap(), 0, size); + if (!data) + return E_OUTOFMEMORY; + + info = (DMUS_DOWNLOADINFO*)data; + offset_table = (DMUS_OFFSETTABLE*)(data + sizeof(DMUS_DOWNLOADINFO)); + offset = sizeof(DMUS_DOWNLOADINFO) + sizeof(ULONG) * (1 + nb_regions); + + info->dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2; + info->dwDLId = 0; + info->dwNumOffsetTableEntries = 1 + instrument_object->header.cRegions; + info->cbSize = size; + + offset_table->ulOffsetTable[0] = offset; + instrument_info = (DMUS_INSTRUMENT*)(data + offset); + offset += sizeof(DMUS_INSTRUMENT); + instrument_info->ulPatch = MIDILOCALE2Patch(&instrument_object->header.Locale); + instrument_info->ulFirstRegionIdx = 1; + instrument_info->ulGlobalArtIdx = 0; /* FIXME */ + instrument_info->ulFirstExtCkIdx = 0; /* FIXME */ + instrument_info->ulCopyrightIdx = 0; /* FIXME */ + instrument_info->ulFlags = 0; /* FIXME */ + + for (i = 0; i < nb_regions; i++) + { + DMUS_REGION *region = (DMUS_REGION*)(data + offset); + + offset_table->ulOffsetTable[1 + i] = offset; + offset += sizeof(DMUS_REGION); + region->RangeKey = instrument_object->regions[i].header.RangeKey; + region->RangeVelocity = instrument_object->regions[i].header.RangeVelocity; + region->fusOptions = instrument_object->regions[i].header.fusOptions; + region->usKeyGroup = instrument_object->regions[i].header.usKeyGroup; + region->ulRegionArtIdx = 0; /* FIXME */ + region->ulNextRegionIdx = i != (nb_regions - 1) ? (i + 2) : 0; + region->ulFirstExtCkIdx = 0; /* FIXME */ + region->WaveLink = instrument_object->regions[i].wave_link; + region->WSMP = instrument_object->regions[i].wave_sample; + region->WLOOP[0] = instrument_object->regions[i].wave_loop; + } + + ret = IDirectMusicSynth8_Download(This->synth, &download, (VOID*)data, &free); + + if (SUCCEEDED(ret)) + ret = DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(downloaded_instrument); + + if (SUCCEEDED(ret)) + { + IDirectMusicDownloadedInstrumentImpl *downloaded_object = impl_from_IDirectMusicDownloadedInstrument(*downloaded_instrument); + + downloaded_object->data = data; + downloaded_object->downloaded = TRUE; + } + + *downloaded_instrument = NULL; + HeapFree(GetProcessHeap(), 0, data); + + return E_FAIL; } static HRESULT WINAPI SynthPortImpl_IDirectMusicPort_UnloadInstrument(LPDIRECTMUSICPORT iface, IDirectMusicDownloadedInstrument *downloaded_instrument) { SynthPortImpl *This = impl_from_SynthPortImpl_IDirectMusicPort(iface); + IDirectMusicDownloadedInstrumentImpl *downloaded_object = unsafe_impl_from_IDirectMusicDownloadedInstrument(downloaded_instrument); - FIXME("(%p/%p)->(%p): stub\n", iface, This, downloaded_instrument); + TRACE("(%p/%p)->(%p)\n", iface, This, downloaded_instrument); + + if (!downloaded_instrument) + return E_POINTER; + + if (!downloaded_object->downloaded) + return DMUS_E_NOT_DOWNLOADED_TO_PORT; + + HeapFree(GetProcessHeap(), 0, downloaded_object->data); + downloaded_object->data = NULL; + downloaded_object->downloaded = FALSE; return S_OK; }