From: Yuxuan Shui yshui@codeweavers.com
--- dlls/dmime/Makefile.in | 1 + dlls/dmime/miditracks.c | 275 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 276 insertions(+) create mode 100644 dlls/dmime/miditracks.c
diff --git a/dlls/dmime/Makefile.in b/dlls/dmime/Makefile.in index cf041ef2b27..fe7aa7df272 100644 --- a/dlls/dmime/Makefile.in +++ b/dlls/dmime/Makefile.in @@ -10,6 +10,7 @@ SOURCES = \ graph.c \ lyricstrack.c \ markertrack.c \ + miditracks.c \ paramcontroltrack.c \ performance.c \ segment.c \ diff --git a/dlls/dmime/miditracks.c b/dlls/dmime/miditracks.c new file mode 100644 index 00000000000..e515ab12568 --- /dev/null +++ b/dlls/dmime/miditracks.c @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2024 Yuxuan Shui for CodeWeavers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "dmime_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dmime); + +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 *pSegment) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + FIXME("(%p, %p): stub\n", This, pSegment); + return S_OK; +} + +static HRESULT WINAPI midi_sequence_track_InitPlay(IDirectMusicTrack8 *iface, + IDirectMusicSegmentState *pSegmentState, IDirectMusicPerformance *pPerformance, + void **ppStateData, DWORD dwVirtualTrack8ID, DWORD dwFlags) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + FIXME("(%p, %p, %p, %p, %ld, %ld): stub\n", This, pSegmentState, pPerformance, ppStateData, + dwVirtualTrack8ID, dwFlags); + return S_OK; +} + +static HRESULT WINAPI midi_sequence_track_EndPlay(IDirectMusicTrack8 *iface, void *pStateData) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + FIXME("(%p, %p): stub\n", This, pStateData); + 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); + + TRACE("(%p, %p, %ld, %ld, %ld, %#lx, %p, %p, %ld)\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); + + TRACE("(%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); + + TRACE("(%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); + + TRACE("(%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); + + TRACE("(%p, %s): method not implemented\n", This, debugstr_dmguid(notiftype)); + return E_NOTIMPL; +} + +static HRESULT WINAPI midi_sequence_track_Clone(IDirectMusicTrack8 *iface, MUSIC_TIME mtStart, + MUSIC_TIME mtEnd, IDirectMusicTrack **ppTrack) +{ + struct midi_sequence_track *This = impl_from_IDirectMusicTrack8(iface); + FIXME("(%p, %ld, %ld, %p): stub\n", This, mtStart, mtEnd, ppTrack); + return S_OK; +} + +static HRESULT WINAPI midi_sequence_track_PlayEx(IDirectMusicTrack8 *iface, void *pStateData, + REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, REFERENCE_TIME rtOffset, DWORD dwFlags, + IDirectMusicPerformance *pPerf, IDirectMusicSegmentState *pSegSt, DWORD dwVirtualID) +{ + 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, pStateData, + wine_dbgstr_longlong(rtStart), wine_dbgstr_longlong(rtEnd), + wine_dbgstr_longlong(rtOffset), dwFlags, pPerf, pSegSt, dwVirtualID); + 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); + + TRACE("(%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); + + TRACE("(%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); + + TRACE("(%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); + TRACE("(%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; +}