From: Yuxuan Shui yshui@codeweavers.com
--- dlls/dmime/midi.c | 263 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 262 insertions(+), 1 deletion(-)
diff --git a/dlls/dmime/midi.c b/dlls/dmime/midi.c index a7e57947c6f..877c3cfbb91 100644 --- a/dlls/dmime/midi.c +++ b/dlls/dmime/midi.c @@ -29,15 +29,275 @@ WINE_DEFAULT_DEBUG_CHANNEL(dmime); #define GET_BE_DWORD(x) RtlUlongByteSwap(x) #endif
+struct midi_sequence_track +{ + IDirectMusicTrack8 IDirectMusicTrack8_iface; + struct dmobject dmobj; /* IPersistStream only */ + LONG ref; +}; + +static inline struct midi_sequence_track *impl_from_IDirectMusicTrack8(IDirectMusicTrack8 *iface) +{ + return CONTAINING_RECORD(iface, struct midi_sequence_track, IDirectMusicTrack8_iface); +} + +static HRESULT WINAPI midi_sequence_track_QueryInterface(IDirectMusicTrack8 *iface, REFIID riid, void **ret_iface) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + + TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface); + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IDirectMusicTrack) || + IsEqualIID(riid, &IID_IDirectMusicTrack8)) + *ret_iface = &This->IDirectMusicTrack8_iface; + else if (IsEqualIID(riid, &IID_IPersistStream)) + *ret_iface = &This->dmobj.IPersistStream_iface; + else + { + *ret_iface = NULL; + WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface); + return E_NOINTERFACE; + } + + IDirectMusicTrack8_AddRef(iface); + return S_OK; +} + +static ULONG WINAPI midi_sequence_track_AddRef(IDirectMusicTrack8 *iface) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): %lu\n", This, ref); + + return ref; +} + +static ULONG WINAPI midi_sequence_track_Release(IDirectMusicTrack8 *iface) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): %lu\n", This, ref); + + if (!ref) free(This); + + return ref; +} + +static HRESULT WINAPI midi_sequence_track_Init(IDirectMusicTrack8 *iface, IDirectMusicSegment *segment) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + FIXME("(%p, %p): stub\n", This, segment); + return S_OK; +} + +static HRESULT WINAPI midi_sequence_track_InitPlay(IDirectMusicTrack8 *iface, IDirectMusicSegmentState *segment_state, + IDirectMusicPerformance *performance, void **state_data, DWORD virtual_track_id, DWORD flags) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + FIXME("(%p, %p, %p, %p, %ld, %ld): stub\n", This, segment_state, performance, state_data, + virtual_track_id, flags); + return S_OK; +} + +static HRESULT WINAPI midi_sequence_track_EndPlay(IDirectMusicTrack8 *iface, void *state_data) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + FIXME("(%p, %p): stub\n", This, state_data); + return S_OK; +} + +static HRESULT WINAPI midi_sequence_track_Play(IDirectMusicTrack8 *iface, void *state_data, + MUSIC_TIME start_time, MUSIC_TIME end_time, MUSIC_TIME time_offset, DWORD segment_flags, + IDirectMusicPerformance *performance, IDirectMusicSegmentState *segment_state, DWORD track_id) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + + FIXME("(%p, %p, %ld, %ld, %ld, %#lx, %p, %p, %ld): stub\n", This, state_data, start_time, + end_time, time_offset, segment_flags, performance, segment_state, track_id); + + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_sequence_track_GetParam(IDirectMusicTrack8 *iface, REFGUID type, + MUSIC_TIME time, MUSIC_TIME *next, void *param) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + + TRACE("(%p, %s, %ld, %p, %p): method not implemented\n", This, debugstr_dmguid(type), time, next, param); + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_sequence_track_SetParam(IDirectMusicTrack8 *iface, REFGUID type, + MUSIC_TIME time, void *param) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + + FIXME("(%p, %s, %ld, %p): method not implemented\n", This, debugstr_dmguid(type), time, param); + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_sequence_track_IsParamSupported(IDirectMusicTrack8 *iface, REFGUID type) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + + FIXME("(%p, %s): method not implemented\n", This, debugstr_dmguid(type)); + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_sequence_track_AddNotificationType(IDirectMusicTrack8 *iface, REFGUID notiftype) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + + FIXME("(%p, %s): method not implemented\n", This, debugstr_dmguid(notiftype)); + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_sequence_track_RemoveNotificationType(IDirectMusicTrack8 *iface, REFGUID notiftype) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + + FIXME("(%p, %s): method not implemented\n", This, debugstr_dmguid(notiftype)); + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_sequence_track_Clone(IDirectMusicTrack8 *iface, MUSIC_TIME start, + MUSIC_TIME end, IDirectMusicTrack **track) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + FIXME("(%p, %ld, %ld, %p): stub\n", This, start, end, track); + return S_OK; +} + +static HRESULT WINAPI midi_sequence_track_PlayEx(IDirectMusicTrack8 *iface, void *state_data, + REFERENCE_TIME start, REFERENCE_TIME end, REFERENCE_TIME offset, DWORD flags, + IDirectMusicPerformance *performance, IDirectMusicSegmentState *segment_state, DWORD virtual_id) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + FIXME("(%p, %p, 0x%s, 0x%s, 0x%s, %ld, %p, %p, %ld): stub\n", This, state_data, + wine_dbgstr_longlong(start), wine_dbgstr_longlong(end), wine_dbgstr_longlong(offset), + flags, performance, segment_state, virtual_id); + return S_OK; +} + +static HRESULT WINAPI midi_sequence_track_GetParamEx(IDirectMusicTrack8 *iface, REFGUID type, + REFERENCE_TIME time, REFERENCE_TIME *next, void *param, void *state, DWORD flags) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + + FIXME("(%p, %s, %s, %p, %p, %p, %lx): method not implemented\n", This, debugstr_dmguid(type), + wine_dbgstr_longlong(time), next, param, state, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_sequence_track_SetParamEx(IDirectMusicTrack8 *iface, REFGUID type, + REFERENCE_TIME time, void *param, void *state, DWORD flags) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + + FIXME("(%p, %s, %s, %p, %p, %lx): method not implemented\n", This, debugstr_dmguid(type), + wine_dbgstr_longlong(time), param, state, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_sequence_track_Compose(IDirectMusicTrack8 *iface, IUnknown *context, + DWORD trackgroup, IDirectMusicTrack **track) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + + FIXME("(%p, %p, %ld, %p): method not implemented\n", This, context, trackgroup, track); + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_sequence_track_Join(IDirectMusicTrack8 *iface, IDirectMusicTrack *newtrack, + MUSIC_TIME join, IUnknown *context, DWORD trackgroup, IDirectMusicTrack **resulttrack) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + FIXME("(%p, %p, %ld, %p, %ld, %p): method not implemented\n", This, newtrack, join, context, + trackgroup, resulttrack); + return E_NOTIMPL; +} + +struct IDirectMusicTrack8Vtbl midi_sequence_track_vtbl = +{ + midi_sequence_track_QueryInterface, + midi_sequence_track_AddRef, + midi_sequence_track_Release, + midi_sequence_track_Init, + midi_sequence_track_InitPlay, + midi_sequence_track_EndPlay, + midi_sequence_track_Play, + midi_sequence_track_GetParam, + midi_sequence_track_SetParam, + midi_sequence_track_IsParamSupported, + midi_sequence_track_AddNotificationType, + midi_sequence_track_RemoveNotificationType, + midi_sequence_track_Clone, + midi_sequence_track_PlayEx, + midi_sequence_track_GetParamEx, + midi_sequence_track_SetParamEx, + midi_sequence_track_Compose, + midi_sequence_track_Join, +}; + +static inline struct midi_sequence_track *impl_from_IPersistStream(IPersistStream *iface) +{ + return CONTAINING_RECORD(iface, struct midi_sequence_track, dmobj.IPersistStream_iface); +} + +static HRESULT WINAPI track_IPersistStream_Load(IPersistStream *iface, IStream *stream) +{ + struct midi_sequence_track *This = impl_from_IPersistStream(iface); + + TRACE("(%p, %p): stub\n", This, stream); + return S_OK; +} + +static const IPersistStreamVtbl midi_sequence_track_persiststream_vtbl = +{ + dmobj_IPersistStream_QueryInterface, + dmobj_IPersistStream_AddRef, + dmobj_IPersistStream_Release, + dmobj_IPersistStream_GetClassID, + unimpl_IPersistStream_IsDirty, + track_IPersistStream_Load, + unimpl_IPersistStream_Save, + unimpl_IPersistStream_GetSizeMax, +}; + +HRESULT create_midiseqtrack(REFIID riid, void **ppobj) +{ + struct midi_sequence_track *track; + HRESULT hr; + + *ppobj = NULL; + if (!(track = calloc(1, sizeof(*track)))) return E_OUTOFMEMORY; + track->IDirectMusicTrack8_iface.lpVtbl = &midi_sequence_track_vtbl; + track->ref = 1; + dmobject_init(&track->dmobj, &CLSID_DirectMusicSeqTrack, (IUnknown *)&track->IDirectMusicTrack8_iface); + track->dmobj.IPersistStream_iface.lpVtbl = &midi_sequence_track_persiststream_vtbl; + + hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, riid, ppobj); + IDirectMusicTrack8_Release(&track->IDirectMusicTrack8_iface); + + return hr; +} + struct midi_parser { IStream *stream; + WORD number_of_tracks, current_track; };
HRESULT midi_parser_next_track(struct midi_parser *parser, IDirectMusicTrack **out_track, MUSIC_TIME *out_length) { TRACE("(%p, %p, %p): stub\n", parser, out_track, out_length); - return S_FALSE; + if (parser->current_track >= parser->number_of_tracks) return S_FALSE; + *out_length = 0; + parser->current_track++; + return create_midiseqtrack(&IID_IDirectMusicTrack, (void **)out_track); }
HRESULT midi_parser_new(IStream *stream, struct midi_parser **out_parser) @@ -92,6 +352,7 @@ HRESULT midi_parser_new(IStream *stream, struct midi_parser **out_parser) parser = calloc(1, sizeof(struct midi_parser)); if (!parser) return E_OUTOFMEMORY; parser->stream = stream; + parser->number_of_tracks = number_of_tracks; IStream_AddRef(stream); *out_parser = parser;