dmusic: Implement instrument regions loading.
This commit is contained in:
parent
fd269e4dca
commit
bf0605c08a
|
@ -77,6 +77,13 @@ typedef struct port_info {
|
||||||
ULONG device;
|
ULONG device;
|
||||||
} port_info;
|
} port_info;
|
||||||
|
|
||||||
|
typedef struct instrument_region {
|
||||||
|
RGNHEADER header;
|
||||||
|
WAVELINK wave_link;
|
||||||
|
WSMPL wave_sample;
|
||||||
|
WLOOP wave_loop;
|
||||||
|
BOOL loop_present;
|
||||||
|
} instrument_region;
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* ClassFactory
|
* ClassFactory
|
||||||
|
@ -224,17 +231,19 @@ struct IDirectMusicCollectionImpl {
|
||||||
* IDirectMusicInstrumentImpl implementation structure
|
* IDirectMusicInstrumentImpl implementation structure
|
||||||
*/
|
*/
|
||||||
struct IDirectMusicInstrumentImpl {
|
struct IDirectMusicInstrumentImpl {
|
||||||
/* IUnknown fields */
|
/* IUnknown fields */
|
||||||
IDirectMusicInstrument IDirectMusicInstrument_iface;
|
IDirectMusicInstrument IDirectMusicInstrument_iface;
|
||||||
LONG ref;
|
LONG ref;
|
||||||
|
|
||||||
/* IDirectMusicInstrumentImpl fields */
|
/* IDirectMusicInstrumentImpl fields */
|
||||||
LARGE_INTEGER liInstrumentPosition; /* offset in a stream where instrument chunk can be found */
|
LARGE_INTEGER liInstrumentPosition; /* offset in a stream where instrument chunk can be found */
|
||||||
ULONG length; /* Length of the instrument in the stream */
|
ULONG length; /* Length of the instrument in the stream */
|
||||||
LPGUID pInstrumentID;
|
LPGUID pInstrumentID;
|
||||||
LPINSTHEADER pHeader;
|
LPINSTHEADER pHeader;
|
||||||
WCHAR wszName[DMUS_MAX_NAME];
|
WCHAR wszName[DMUS_MAX_NAME];
|
||||||
/* instrument data */
|
/* instrument data */
|
||||||
|
BOOL loaded;
|
||||||
|
instrument_region *regions;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline IDirectMusicInstrumentImpl *impl_from_IDirectMusicInstrument(IDirectMusicInstrument *iface)
|
static inline IDirectMusicInstrumentImpl *impl_from_IDirectMusicInstrument(IDirectMusicInstrument *iface)
|
||||||
|
|
|
@ -75,7 +75,10 @@ static ULONG WINAPI IDirectMusicInstrumentImpl_Release(LPDIRECTMUSICINSTRUMENT i
|
||||||
TRACE("(%p)->(): new ref = %u\n", iface, ref);
|
TRACE("(%p)->(): new ref = %u\n", iface, ref);
|
||||||
|
|
||||||
if (!ref)
|
if (!ref)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, This->regions);
|
||||||
HeapFree(GetProcessHeap(), 0, This);
|
HeapFree(GetProcessHeap(), 0, This);
|
||||||
|
}
|
||||||
|
|
||||||
DMUSIC_UnlockModule();
|
DMUSIC_UnlockModule();
|
||||||
|
|
||||||
|
@ -170,16 +173,90 @@ static inline HRESULT advance_stream(IStream *stream, ULONG bytes)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT load_region(IDirectMusicInstrumentImpl *This, IStream *stream, instrument_region *region, ULONG length)
|
||||||
|
{
|
||||||
|
HRESULT ret;
|
||||||
|
DMUS_PRIVATE_CHUNK chunk;
|
||||||
|
|
||||||
|
TRACE("(%p, %p, %p, %u)\n", This, stream, region, length);
|
||||||
|
|
||||||
|
while (length)
|
||||||
|
{
|
||||||
|
ret = read_from_stream(stream, &chunk, sizeof(chunk));
|
||||||
|
if (FAILED(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
length = subtract_bytes(length, sizeof(chunk));
|
||||||
|
|
||||||
|
switch (chunk.fccID)
|
||||||
|
{
|
||||||
|
case FOURCC_RGNH:
|
||||||
|
TRACE("RGNH chunk (region header): %u bytes\n", chunk.dwSize);
|
||||||
|
|
||||||
|
ret = read_from_stream(stream, ®ion->header, sizeof(region->header));
|
||||||
|
if (FAILED(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
length = subtract_bytes(length, sizeof(region->header));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FOURCC_WSMP:
|
||||||
|
TRACE("WSMP chunk (wave sample): %u bytes\n", chunk.dwSize);
|
||||||
|
|
||||||
|
ret = read_from_stream(stream, ®ion->wave_sample, sizeof(region->wave_sample));
|
||||||
|
if (FAILED(ret))
|
||||||
|
return ret;
|
||||||
|
length = subtract_bytes(length, sizeof(region->wave_sample));
|
||||||
|
|
||||||
|
if (!(region->loop_present = (chunk.dwSize != sizeof(region->wave_sample))))
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = read_from_stream(stream, ®ion->wave_loop, sizeof(region->wave_loop));
|
||||||
|
if (FAILED(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
length = subtract_bytes(length, sizeof(region->wave_loop));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FOURCC_WLNK:
|
||||||
|
TRACE("WLNK chunk (wave link): %u bytes\n", chunk.dwSize);
|
||||||
|
|
||||||
|
ret = read_from_stream(stream, ®ion->wave_link, sizeof(region->wave_link));
|
||||||
|
if (FAILED(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
length = subtract_bytes(length, sizeof(region->wave_link));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
TRACE("Unknown chunk %s (skipping): %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
|
||||||
|
|
||||||
|
ret = advance_stream(stream, chunk.dwSize);
|
||||||
|
if (FAILED(ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
length = subtract_bytes(length, chunk.dwSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Function that loads all instrument data and which is called from IDirectMusicCollection_GetInstrument as in native */
|
/* Function that loads all instrument data and which is called from IDirectMusicCollection_GetInstrument as in native */
|
||||||
HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, IStream *stream)
|
HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, IStream *stream)
|
||||||
{
|
{
|
||||||
IDirectMusicInstrumentImpl *This = impl_from_IDirectMusicInstrument(iface);
|
IDirectMusicInstrumentImpl *This = impl_from_IDirectMusicInstrument(iface);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
DMUS_PRIVATE_CHUNK chunk;
|
DMUS_PRIVATE_CHUNK chunk;
|
||||||
|
ULONG i = 0;
|
||||||
ULONG length = This->length;
|
ULONG length = This->length;
|
||||||
|
|
||||||
TRACE("(%p, %p): offset = 0x%s, length = %u)\n", This, stream, wine_dbgstr_longlong(This->liInstrumentPosition.QuadPart), This->length);
|
TRACE("(%p, %p): offset = 0x%s, length = %u)\n", This, stream, wine_dbgstr_longlong(This->liInstrumentPosition.QuadPart), This->length);
|
||||||
|
|
||||||
|
if (This->loaded)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
hr = IStream_Seek(stream, This->liInstrumentPosition, STREAM_SEEK_SET, NULL);
|
hr = IStream_Seek(stream, This->liInstrumentPosition, STREAM_SEEK_SET, NULL);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
|
@ -187,11 +264,15 @@ HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, ISt
|
||||||
return DMUS_E_UNSUPPORTED_STREAM;
|
return DMUS_E_UNSUPPORTED_STREAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
This->regions = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->regions) * This->pHeader->cRegions);
|
||||||
|
if (!This->regions)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
while (length)
|
while (length)
|
||||||
{
|
{
|
||||||
hr = read_from_stream(stream, &chunk, sizeof(chunk));
|
hr = read_from_stream(stream, &chunk, sizeof(chunk));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return DMUS_E_UNSUPPORTED_STREAM;
|
goto error;
|
||||||
|
|
||||||
length = subtract_bytes(length, sizeof(chunk) + chunk.dwSize);
|
length = subtract_bytes(length, sizeof(chunk) + chunk.dwSize);
|
||||||
|
|
||||||
|
@ -204,20 +285,90 @@ HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, ISt
|
||||||
/* Instrument header and id are already set so just skip */
|
/* Instrument header and id are already set so just skip */
|
||||||
hr = advance_stream(stream, chunk.dwSize);
|
hr = advance_stream(stream, chunk.dwSize);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return DMUS_E_UNSUPPORTED_STREAM;
|
goto error;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FOURCC_LIST: {
|
||||||
|
DWORD size = chunk.dwSize;
|
||||||
|
|
||||||
|
TRACE("LIST chunk: %u bytes\n", chunk.dwSize);
|
||||||
|
|
||||||
|
hr = read_from_stream(stream, &chunk.fccID, sizeof(chunk.fccID));
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
size = subtract_bytes(size, sizeof(chunk.fccID));
|
||||||
|
|
||||||
|
switch (chunk.fccID)
|
||||||
|
{
|
||||||
|
case FOURCC_LRGN:
|
||||||
|
TRACE("LRGN chunk (regions list): %u bytes\n", size);
|
||||||
|
|
||||||
|
while (size)
|
||||||
|
{
|
||||||
|
hr = read_from_stream(stream, &chunk, sizeof(chunk));
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (chunk.fccID != FOURCC_LIST)
|
||||||
|
{
|
||||||
|
TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = read_from_stream(stream, &chunk.fccID, sizeof(chunk.fccID));
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (chunk.fccID == FOURCC_RGN)
|
||||||
|
{
|
||||||
|
TRACE("RGN chunk (region list): %u bytes\n", chunk.dwSize);
|
||||||
|
hr = load_region(This, stream, &This->regions[i++], chunk.dwSize - sizeof(chunk.fccID));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
|
||||||
|
hr = advance_stream(stream, chunk.dwSize - sizeof(chunk.fccID));
|
||||||
|
}
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
size = subtract_bytes(size, chunk.dwSize + sizeof(chunk));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
|
||||||
|
|
||||||
|
hr = advance_stream(stream, chunk.dwSize - sizeof(chunk.fccID));
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
size = subtract_bytes(size, chunk.dwSize - sizeof(chunk.fccID));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
|
TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
|
||||||
|
|
||||||
hr = advance_stream(stream, chunk.dwSize);
|
hr = advance_stream(stream, chunk.dwSize);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return DMUS_E_UNSUPPORTED_STREAM;
|
goto error;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
This->loaded = TRUE;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
HeapFree(GetProcessHeap(), 0, This->regions);
|
||||||
|
This->regions = NULL;
|
||||||
|
|
||||||
|
return DMUS_E_UNSUPPORTED_STREAM;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue