From: Yuxuan Shui yshui@codeweavers.com
So that instrument loading can work. --- dlls/dmime/segment.c | 158 +++++++++++++++++++++++++++++++++++++++ dlls/dmime/tests/dmime.c | 2 +- 2 files changed, 159 insertions(+), 1 deletion(-)
diff --git a/dlls/dmime/segment.c b/dlls/dmime/segment.c index beba1bbd34d..aa39dc1c02f 100644 --- a/dlls/dmime/segment.c +++ b/dlls/dmime/segment.c @@ -60,6 +60,117 @@ struct segment
static struct segment *segment_create(void);
+/* Create a trivial DirectMusicBand. + * + * There is no obvious way to create a DirectMusicBand from outside dmband, + * either we add a wine private interface, or generate a RIFF stream and load + * it. + */ +static HRESULT gen_trivial_band_stream(IStream **out_stream) +{ + const LARGE_INTEGER zero = {.QuadPart = 0}; + const DWORD lbil_size = (sizeof(DMUS_IO_INSTRUMENT) + 8 + 8 + 4) * 128 + 4; + const DWORD dmbd_size = 4 + sizeof(GUID) + 8 + lbil_size + 8; + HRESULT hr; + char buffer[128]; + char *p = buffer; + DWORD data; + IStream *stream; + int i; + + TRACE("(%p)\n", out_stream); + + if (!out_stream) + return E_POINTER; + *out_stream = NULL; + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + if (FAILED(hr)) + return hr; + + /* is the endianness going to be ok? */ + /* Top-level RIFF chunk */ + data = FOURCC_RIFF; + memcpy(p, &data, 4); + p += 4; + memcpy(p, &dmbd_size, 4); + p += 4; + data = DMUS_FOURCC_BAND_FORM; + memcpy(p, &data, 4); + p += 4; + + /* GUID chunk */ + data = DMUS_FOURCC_GUID_CHUNK; + memcpy(p, &data, 4); + p += 4; + data = sizeof(GUID); + memcpy(p, &data, 4); + p += 4; + memcpy(p, &CLSID_DirectMusicSegment, sizeof(GUID)); + p += sizeof(GUID); + + /* Band instruments list */ + data = FOURCC_LIST; + memcpy(p, &data, 4); + p += 4; + memcpy(p, &lbil_size, 4); + p += 4; + data = DMUS_FOURCC_INSTRUMENTS_LIST; + memcpy(p, &data, 4); + p += 4; + + hr = IStream_Write(stream, buffer, p - buffer, NULL); + if (FAILED(hr)) + goto out; + + for (i = 0; i < 128; i++) + { + DMUS_IO_INSTRUMENT instrument = { + .dwPatch = i, + .dwPChannel = 0, + .dwFlags = DMUS_IO_INST_PATCH, + }; + + p = buffer; + + data = FOURCC_LIST; + memcpy(p, &data, 4); + p += 4; + data = sizeof(DMUS_IO_INSTRUMENT) + 8 + 4; + memcpy(p, &data, 4); + p += 4; + data = DMUS_FOURCC_INSTRUMENT_LIST; + memcpy(p, &data, 4); + p += 4; + + data = DMUS_FOURCC_INSTRUMENT_CHUNK; + memcpy(p, &data, 4); + p += 4; + data = sizeof(DMUS_IO_INSTRUMENT); + memcpy(p, &data, 4); + p += 4; + memcpy(p, &instrument, sizeof(DMUS_IO_INSTRUMENT)); + p += sizeof(DMUS_IO_INSTRUMENT); + + hr = IStream_Write(stream, buffer, p - buffer, NULL); + if (FAILED(hr)) + goto out; + } + + hr = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); + if (FAILED(hr)) + goto out; + *out_stream = stream; + IStream_AddRef(stream); + +out: + if (FAILED(hr)) + WARN("Failed to create trivial band stream, hr %#lx.\n", hr); + IStream_Release(stream); + return hr; +} + + static inline struct segment *impl_from_IDirectMusicSegment8(IDirectMusicSegment8 *iface) { return CONTAINING_RECORD(iface, struct segment, IDirectMusicSegment8_iface); @@ -839,7 +950,54 @@ static HRESULT parse_midi(struct segment *This, IStream *stream) DWORD length; ULONG i; HRESULT hr; + IStream *band_stream; + IDirectMusicBand *band; + IDirectMusicTrack *bandtrack; + IPersistStream *persist_stream; WORD format, number_of_tracks, division; + DMUS_BAND_PARAM bandparam; + + hr = gen_trivial_band_stream(&band_stream); + if (FAILED(hr)) + return hr; + hr = CoCreateInstance(&CLSID_DirectMusicBand, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicBand, (void **)&band); + if (FAILED(hr)) + { + IStream_Release(band_stream); + return hr; + } + + IDirectMusicBand_QueryInterface(band, &IID_IPersistStream, (void **)&persist_stream); + hr = IPersistStream_Load(persist_stream, band_stream); + IPersistStream_Release(persist_stream); + IStream_Release(band_stream); + if (FAILED(hr)) + { + IDirectMusicBand_Release(band); + return hr; + } + + hr = CoCreateInstance(&CLSID_DirectMusicBandTrack, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack, (void **)&bandtrack); + if (FAILED(hr)) + { + IDirectMusicBand_Release(band); + return hr; + } + + bandparam.mtTimePhysical = 0; + bandparam.pBand = band; + hr = IDirectMusicTrack_SetParam(bandtrack, &GUID_BandParam, 0, &bandparam); + IDirectMusicBand_Release(band); + if (FAILED(hr)) + { + IDirectMusicTrack_Release(bandtrack); + return hr; + } + + segment_append_track(This, bandtrack, 0, 0); + IDirectMusicTrack_Release(bandtrack); + if (FAILED(hr)) + return hr;
/* Skip over the 'MThd' magic number. */ offset.QuadPart = 4; diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index 145c6824154..ad7dc05ba2c 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -1572,7 +1572,7 @@ static void test_midi(void) ok(hr == S_OK, "got %#lx\n", hr);
hr = IDirectMusicSegment8_GetTrack(segment, &CLSID_DirectMusicBandTrack, 0xffffffff, 0, &track); - todo_wine ok(hr == S_OK, "unable to get band track from midi file: %#lx\n", hr); + ok(hr == S_OK, "unable to get band track from midi file: %#lx\n", hr); if (track) IDirectMusicTrack_Release(track);