Commit 120a743c authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

dmusic: Rewrite downloading instrument to port.

parent 0cb208ce
......@@ -48,7 +48,6 @@
*/
typedef struct IDirectMusic8Impl IDirectMusic8Impl;
typedef struct IDirectMusicBufferImpl IDirectMusicBufferImpl;
typedef struct IDirectMusicDownloadedInstrumentImpl IDirectMusicDownloadedInstrumentImpl;
typedef struct IReferenceClockImpl IReferenceClockImpl;
/*****************************************************************************
......@@ -73,16 +72,6 @@ typedef struct port_info {
ULONG device;
} port_info;
struct region
{
struct list entry;
RGNHEADER header;
WAVELINK wave_link;
WSMPL wave_sample;
WLOOP wave_loop;
BOOL loop_present;
};
/*****************************************************************************
* ClassFactory
*/
......@@ -99,6 +88,9 @@ extern HRESULT download_create(DWORD size, IDirectMusicDownload **ret_iface);
extern HRESULT instrument_create_from_chunk(IStream *stream, struct chunk_entry *parent,
DMUS_OBJECTDESC *desc, IDirectMusicInstrument **ret_iface);
extern HRESULT instrument_download_to_port(IDirectMusicInstrument *iface, IDirectMusicPortDownload *port,
IDirectMusicDownloadedInstrument **downloaded);
extern HRESULT instrument_unload_from_port(IDirectMusicDownloadedInstrument *iface, IDirectMusicPortDownload *port);
/*****************************************************************************
* IDirectMusic8Impl implementation structure
......@@ -130,19 +122,6 @@ struct IDirectMusicBufferImpl {
REFERENCE_TIME start_time;
};
/*****************************************************************************
* IDirectMusicDownloadedInstrumentImpl implementation structure
*/
struct IDirectMusicDownloadedInstrumentImpl {
/* IUnknown fields */
IDirectMusicDownloadedInstrument IDirectMusicDownloadedInstrument_iface;
LONG ref;
/* IDirectMusicDownloadedInstrumentImpl fields */
BOOL downloaded;
void *data;
};
/** Internal factory */
extern HRESULT synth_port_create(IDirectMusic8Impl *parent, DMUS_PORTPARAMS *port_params,
DMUS_PORTCAPS *port_caps, IDirectMusicPort **port);
......@@ -168,22 +147,6 @@ typedef struct _DMUS_PRIVATE_POOLCUE {
struct list entry; /* for listing elements */
} DMUS_PRIVATE_POOLCUE, *LPDMUS_PRIVATE_POOLCUE;
struct instrument
{
IDirectMusicInstrument IDirectMusicInstrument_iface;
LONG ref;
INSTHEADER header;
struct list articulations;
struct list regions;
};
static inline struct instrument *impl_from_IDirectMusicInstrument(IDirectMusicInstrument *iface)
{
return CONTAINING_RECORD(iface, struct instrument, IDirectMusicInstrument_iface);
}
/*****************************************************************************
* Misc.
*/
......
......@@ -33,6 +33,33 @@ struct articulation
C_ASSERT(sizeof(struct articulation) == offsetof(struct articulation, connections[0]));
struct region
{
struct list entry;
RGNHEADER header;
WAVELINK wave_link;
WSMPL wave_sample;
WLOOP wave_loop;
BOOL loop_present;
};
struct instrument
{
IDirectMusicInstrument IDirectMusicInstrument_iface;
IDirectMusicDownloadedInstrument IDirectMusicDownloadedInstrument_iface;
LONG ref;
INSTHEADER header;
IDirectMusicDownload *download;
struct list articulations;
struct list regions;
};
static inline struct instrument *impl_from_IDirectMusicInstrument(IDirectMusicInstrument *iface)
{
return CONTAINING_RECORD(iface, struct instrument, IDirectMusicInstrument_iface);
}
static HRESULT WINAPI instrument_QueryInterface(LPDIRECTMUSICINSTRUMENT iface, REFIID riid, LPVOID *ret_iface)
{
TRACE("(%p)->(%s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
......@@ -134,6 +161,46 @@ static const IDirectMusicInstrumentVtbl instrument_vtbl =
instrument_SetPatch,
};
static inline struct instrument* impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
{
return CONTAINING_RECORD(iface, struct instrument, IDirectMusicDownloadedInstrument_iface);
}
static HRESULT WINAPI downloaded_instrument_QueryInterface(IDirectMusicDownloadedInstrument *iface, REFIID riid, VOID **ret_iface)
{
TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicDownloadedInstrument))
{
IDirectMusicDownloadedInstrument_AddRef(iface);
*ret_iface = iface;
return S_OK;
}
WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
return E_NOINTERFACE;
}
static ULONG WINAPI downloaded_instrument_AddRef(IDirectMusicDownloadedInstrument *iface)
{
struct instrument *This = impl_from_IDirectMusicDownloadedInstrument(iface);
return IDirectMusicInstrument_AddRef(&This->IDirectMusicInstrument_iface);
}
static ULONG WINAPI downloaded_instrument_Release(IDirectMusicDownloadedInstrument *iface)
{
struct instrument *This = impl_from_IDirectMusicDownloadedInstrument(iface);
return IDirectMusicInstrument_Release(&This->IDirectMusicInstrument_iface);
}
static const IDirectMusicDownloadedInstrumentVtbl downloaded_instrument_vtbl =
{
downloaded_instrument_QueryInterface,
downloaded_instrument_AddRef,
downloaded_instrument_Release,
};
static HRESULT instrument_create(IDirectMusicInstrument **ret_iface)
{
struct instrument *instrument;
......@@ -141,6 +208,7 @@ static HRESULT instrument_create(IDirectMusicInstrument **ret_iface)
*ret_iface = NULL;
if (!(instrument = calloc(1, sizeof(*instrument)))) return E_OUTOFMEMORY;
instrument->IDirectMusicInstrument_iface.lpVtbl = &instrument_vtbl;
instrument->IDirectMusicDownloadedInstrument_iface.lpVtbl = &downloaded_instrument_vtbl;
instrument->ref = 1;
list_init(&instrument->articulations);
list_init(&instrument->regions);
......@@ -365,3 +433,109 @@ HRESULT instrument_create_from_chunk(IStream *stream, struct chunk_entry *parent
*ret_iface = iface;
return S_OK;
}
struct download_buffer
{
DMUS_DOWNLOADINFO info;
ULONG offsets[];
};
C_ASSERT(sizeof(struct download_buffer) == offsetof(struct download_buffer, offsets[0]));
HRESULT instrument_download_to_port(IDirectMusicInstrument *iface, IDirectMusicPortDownload *port,
IDirectMusicDownloadedInstrument **downloaded)
{
struct instrument *This = impl_from_IDirectMusicInstrument(iface);
struct download_buffer *buffer;
IDirectMusicDownload *download;
DWORD size, offset_count;
struct region *region;
HRESULT hr;
if (This->download) goto done;
size = sizeof(DMUS_DOWNLOADINFO);
size += sizeof(ULONG) + sizeof(DMUS_INSTRUMENT);
offset_count = 1;
LIST_FOR_EACH_ENTRY(region, &This->regions, struct region, entry)
{
size += sizeof(ULONG) + sizeof(DMUS_REGION);
offset_count++;
}
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)))
{
BYTE *ptr = (BYTE *)&buffer->offsets[offset_count];
DMUS_INSTRUMENT *dmus_instrument;
DMUS_REGION *dmus_region = NULL;
UINT index = 0;
buffer->info.dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2;
buffer->info.dwNumOffsetTableEntries = offset_count;
buffer->info.cbSize = size;
buffer->offsets[index++] = ptr - (BYTE *)buffer;
dmus_instrument = (DMUS_INSTRUMENT *)ptr;
ptr += sizeof(DMUS_INSTRUMENT);
dmus_instrument->ulPatch = MIDILOCALE2Patch(&This->header.Locale);
dmus_instrument->ulFirstRegionIdx = 0;
dmus_instrument->ulCopyrightIdx = 0;
dmus_instrument->ulGlobalArtIdx = 0;
LIST_FOR_EACH_ENTRY(region, &This->regions, struct region, entry)
{
if (dmus_region) dmus_region->ulNextRegionIdx = index;
else dmus_instrument->ulFirstRegionIdx = index;
buffer->offsets[index++] = ptr - (BYTE *)buffer;
dmus_region = (DMUS_REGION *)ptr;
ptr += sizeof(DMUS_REGION);
dmus_region->RangeKey = region->header.RangeKey;
dmus_region->RangeVelocity = region->header.RangeVelocity;
dmus_region->fusOptions = region->header.fusOptions;
dmus_region->usKeyGroup = region->header.usKeyGroup;
dmus_region->ulRegionArtIdx = 0;
dmus_region->ulNextRegionIdx = 0;
dmus_region->ulFirstExtCkIdx = 0;
dmus_region->WaveLink = region->wave_link;
dmus_region->WSMP = region->wave_sample;
dmus_region->WLOOP[0] = region->wave_loop;
}
if (FAILED(hr = IDirectMusicPortDownload_Download(port, download))) goto failed;
}
This->download = download;
done:
*downloaded = &This->IDirectMusicDownloadedInstrument_iface;
IDirectMusicDownloadedInstrument_AddRef(*downloaded);
return S_OK;
failed:
WARN("Failed to download instrument to port, hr %#lx\n", hr);
IDirectMusicDownload_Release(download);
return hr;
}
HRESULT instrument_unload_from_port(IDirectMusicDownloadedInstrument *iface, IDirectMusicPortDownload *port)
{
struct instrument *This = impl_from_IDirectMusicDownloadedInstrument(iface);
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);
IDirectMusicDownload_Release(This->download);
This->download = NULL;
return hr;
}
......@@ -52,11 +52,6 @@ struct synth_port {
DWORD next_dlid;
};
static inline IDirectMusicDownloadedInstrumentImpl* impl_from_IDirectMusicDownloadedInstrument(IDirectMusicDownloadedInstrument *iface)
{
return CONTAINING_RECORD(iface, IDirectMusicDownloadedInstrumentImpl, IDirectMusicDownloadedInstrument_iface);
}
static inline struct synth_port *synth_from_IDirectMusicPort(IDirectMusicPort *iface)
{
return CONTAINING_RECORD(iface, struct synth_port, IDirectMusicPort_iface);
......@@ -77,83 +72,6 @@ static inline struct synth_port *synth_from_IKsControl(IKsControl *iface)
return CONTAINING_RECORD(iface, struct synth_port, IKsControl_iface);
}
/* IDirectMusicDownloadedInstrument IUnknown part follows: */
static HRESULT WINAPI IDirectMusicDownloadedInstrumentImpl_QueryInterface(IDirectMusicDownloadedInstrument *iface, REFIID riid, VOID **ret_iface)
{
TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicDownloadedInstrument))
{
IDirectMusicDownloadedInstrument_AddRef(iface);
*ret_iface = iface;
return S_OK;
}
WARN("(%p, %s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
return E_NOINTERFACE;
}
static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_AddRef(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
{
IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p): new ref = %lu\n", iface, ref);
return ref;
}
static ULONG WINAPI IDirectMusicDownloadedInstrumentImpl_Release(LPDIRECTMUSICDOWNLOADEDINSTRUMENT iface)
{
IDirectMusicDownloadedInstrumentImpl *This = impl_from_IDirectMusicDownloadedInstrument(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p): new ref = %lu\n", iface, ref);
if (!ref)
{
free(This->data);
free(This);
}
return ref;
}
static const IDirectMusicDownloadedInstrumentVtbl DirectMusicDownloadedInstrument_Vtbl = {
IDirectMusicDownloadedInstrumentImpl_QueryInterface,
IDirectMusicDownloadedInstrumentImpl_AddRef,
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);
}
static HRESULT DMUSIC_CreateDirectMusicDownloadedInstrumentImpl(IDirectMusicDownloadedInstrument **instrument)
{
IDirectMusicDownloadedInstrumentImpl *object;
object = calloc(1, sizeof(*object));
if (!object)
{
*instrument = NULL;
return E_OUTOFMEMORY;
}
object->IDirectMusicDownloadedInstrument_iface.lpVtbl = &DirectMusicDownloadedInstrument_Vtbl;
object->ref = 1;
*instrument = &object->IDirectMusicDownloadedInstrument_iface;
return S_OK;
}
static HRESULT WINAPI synth_port_QueryInterface(IDirectMusicPort *iface, REFIID riid, void **ret_iface)
{
struct synth_port *This = synth_from_IDirectMusicPort(iface);
......@@ -265,110 +183,26 @@ static HRESULT WINAPI synth_port_DownloadInstrument(IDirectMusicPort *iface, IDi
IDirectMusicDownloadedInstrument **downloaded_instrument, DMUS_NOTERANGE *note_ranges, DWORD num_note_ranges)
{
struct synth_port *This = synth_from_IDirectMusicPort(iface);
struct instrument *instrument_object;
struct region *instrument_region;
HRESULT ret;
BOOL on_heap;
HANDLE download;
DMUS_DOWNLOADINFO *info;
DMUS_OFFSETTABLE *offset_table;
DMUS_INSTRUMENT *instrument_info;
BYTE *data;
ULONG offset;
ULONG nb_regions;
ULONG size;
ULONG i;
TRACE("(%p, %p, %p, %p, %ld)\n", iface, instrument, downloaded_instrument, note_ranges, num_note_ranges);
if (!instrument || !downloaded_instrument || (num_note_ranges && !note_ranges))
return E_POINTER;
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 = malloc(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 */
i = 0;
LIST_FOR_EACH_ENTRY(instrument_region, &instrument_object->regions, struct region, entry)
{
DMUS_REGION *region = (DMUS_REGION*)(data + offset);
offset_table->ulOffsetTable[1 + i] = offset;
offset += sizeof(DMUS_REGION);
region->RangeKey = instrument_region->header.RangeKey;
region->RangeVelocity = instrument_region->header.RangeVelocity;
region->fusOptions = instrument_region->header.fusOptions;
region->usKeyGroup = instrument_region->header.usKeyGroup;
region->ulRegionArtIdx = 0; /* FIXME */
region->ulNextRegionIdx = i != (nb_regions - 1) ? (i + 2) : 0;
region->ulFirstExtCkIdx = 0; /* FIXME */
region->WaveLink = instrument_region->wave_link;
region->WSMP = instrument_region->wave_sample;
region->WLOOP[0] = instrument_region->wave_loop;
i++;
}
ret = IDirectMusicSynth8_Download(This->synth, &download, (void*)data, &on_heap);
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;
free(data);
return E_FAIL;
return instrument_download_to_port(instrument, &This->IDirectMusicPortDownload_iface, downloaded_instrument);
}
static HRESULT WINAPI synth_port_UnloadInstrument(IDirectMusicPort *iface,
IDirectMusicDownloadedInstrument *downloaded_instrument)
{
IDirectMusicDownloadedInstrumentImpl *downloaded_object = unsafe_impl_from_IDirectMusicDownloadedInstrument(downloaded_instrument);
struct synth_port *This = synth_from_IDirectMusicPort(iface);
TRACE("(%p, %p)\n", iface, downloaded_instrument);
if (!downloaded_instrument)
return E_POINTER;
if (!downloaded_object->downloaded)
return DMUS_E_NOT_DOWNLOADED_TO_PORT;
free(downloaded_object->data);
downloaded_object->data = NULL;
downloaded_object->downloaded = FALSE;
return S_OK;
return instrument_unload_from_port(downloaded_instrument, &This->IDirectMusicPortDownload_iface);
}
static HRESULT WINAPI synth_port_GetLatencyClock(IDirectMusicPort *iface, IReferenceClock **clock)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment