static HRESULT load_articulation(IDirectMusicInstrumentImpl *This, IStream *stream, ULONG length) { HRESULT ret; instrument_articulation *articulation; if (!This->articulations) This->articulations = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->articulations)); else This->articulations = HeapReAlloc(GetProcessHeap(), 0, This->articulations, sizeof(*This->articulations) * (This->nb_articulations + 1)); if (!This->articulations) return E_OUTOFMEMORY; articulation = &This->articulations[This->nb_articulations]; ret = read_from_stream(stream, &articulation->connections_list, sizeof(CONNECTIONLIST)); if (FAILED(ret)) return ret; articulation->connections = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTION) * articulation->connections_list.cConnections); if (!articulation->connections) return E_OUTOFMEMORY; ret = read_from_stream(stream, articulation->connections, sizeof(CONNECTION) * articulation->connections_list.cConnections); if (FAILED(ret)) { HeapFree(GetProcessHeap(), 0, articulation->connections); return ret; } subtract_bytes(length, sizeof(CONNECTIONLIST) + sizeof(CONNECTION) * articulation->connections_list.cConnections); This->nb_articulations++; return S_OK; }
static HRESULT load_instrument(IDirectMusicInstrumentImpl *This, IStream *stream, DWORD length) { HRESULT hr; FOURCC fourcc; DWORD bytes; LARGE_INTEGER move; while(length){ hr = read_from_stream(stream, &fourcc, sizeof(fourcc)); if(FAILED(hr)) return hr; hr = read_from_stream(stream, &bytes, sizeof(bytes)); if(FAILED(hr)) return hr; length = subtract_bytes(length, sizeof(fourcc) + sizeof(bytes)); switch(fourcc){ case FOURCC_INSH: TRACE("INSH chunk: %u bytes\n", bytes); hr = read_from_stream(stream, This->pHeader, sizeof(*This->pHeader)); if(FAILED(hr)) return hr; move.QuadPart = bytes - sizeof(*This->pHeader); hr = IStream_Seek(stream, move, STREAM_SEEK_CUR, NULL); if(FAILED(hr)){ WARN("IStream_Seek failed: %08x\n", hr); return hr; } length = subtract_bytes(length, bytes); break; case FOURCC_DLID: TRACE("DLID chunk: %u bytes\n", bytes); hr = read_from_stream(stream, This->pInstrumentID, sizeof(*This->pInstrumentID)); if(FAILED(hr)) return hr; move.QuadPart = bytes - sizeof(*This->pInstrumentID); hr = IStream_Seek(stream, move, STREAM_SEEK_CUR, NULL); if(FAILED(hr)){ WARN("IStream_Seek failed: %08x\n", hr); return hr; } length = subtract_bytes(length, bytes); break; default: TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(fourcc), bytes); move.QuadPart = bytes; hr = IStream_Seek(stream, move, STREAM_SEEK_CUR, NULL); if(FAILED(hr)){ WARN("IStream_Seek failed: %08x\n", hr); return hr; } length = subtract_bytes(length, bytes); break; } } return S_OK; }
/* Function that loads all instrument data and which is called from IDirectMusicCollection_GetInstrument as in native */ HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, IStream *stream) { IDirectMusicInstrumentImpl *This = impl_from_IDirectMusicInstrument(iface); HRESULT hr; DMUS_PRIVATE_CHUNK chunk; ULONG i = 0; ULONG length = 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); if (FAILED(hr)) { WARN("IStream_Seek failed: %08x\n", hr); return DMUS_E_UNSUPPORTED_STREAM; } This->regions = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->regions) * This->header.cRegions); if (!This->regions) return E_OUTOFMEMORY; while (length) { hr = read_from_stream(stream, &chunk, sizeof(chunk)); if (FAILED(hr)) goto error; length = subtract_bytes(length, sizeof(chunk) + chunk.dwSize); switch (chunk.fccID) { case FOURCC_INSH: case FOURCC_DLID: TRACE("Chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize); /* Instrument header and id are already set so just skip */ hr = advance_stream(stream, chunk.dwSize); if (FAILED(hr)) goto error; 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): %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; case FOURCC_LART: TRACE("LART chunk (articulations list): %u bytes\n", size); while (size) { hr = read_from_stream(stream, &chunk, sizeof(chunk)); if (FAILED(hr)) goto error; if (chunk.fccID == FOURCC_ART1) { TRACE("ART1 chunk (level 1 articulation): %u bytes\n", chunk.dwSize); hr = load_articulation(This, stream, chunk.dwSize); } else { TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize); hr = advance_stream(stream, chunk.dwSize); } 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: TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize); hr = advance_stream(stream, chunk.dwSize); if (FAILED(hr)) goto error; break; } } This->loaded = TRUE; return S_OK; error: HeapFree(GetProcessHeap(), 0, This->regions); This->regions = NULL; return DMUS_E_UNSUPPORTED_STREAM; }
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; }