dmsynth: Implement latency IReferenceClock interface on the sink.

This commit is contained in:
Rémi Bernon 2023-09-06 08:29:37 +02:00 committed by Alexandre Julliard
parent 23b61b0dc8
commit 2a1b03ccc3
2 changed files with 90 additions and 19 deletions

View file

@ -29,15 +29,16 @@ struct synth_sink
{
IDirectMusicSynthSink IDirectMusicSynthSink_iface;
IKsControl IKsControl_iface;
IReferenceClock IReferenceClock_iface;
LONG ref;
IReferenceClock *latency_clock;
IReferenceClock *master_clock;
IDirectMusicSynth *synth; /* No reference hold! */
IDirectSound *dsound;
BOOL active;
REFERENCE_TIME activate_time;
REFERENCE_TIME latency_time;
};
static inline struct synth_sink *impl_from_IDirectMusicSynthSink(IDirectMusicSynthSink *iface)
@ -74,6 +75,7 @@ static HRESULT synth_sink_activate(struct synth_sink *This)
if (This->active) return DMUS_E_SYNTHACTIVE;
if (FAILED(hr = IReferenceClock_GetTime(This->master_clock, &This->activate_time))) return hr;
This->latency_time = This->activate_time;
This->active = TRUE;
return S_OK;
@ -131,8 +133,6 @@ static ULONG WINAPI synth_sink_Release(IDirectMusicSynthSink *iface)
TRACE("(%p): new ref = %lu\n", This, ref);
if (!ref) {
if (This->latency_clock)
IReferenceClock_Release(This->latency_clock);
if (This->master_clock)
IReferenceClock_Release(This->master_clock);
free(This);
@ -182,8 +182,8 @@ static HRESULT WINAPI synth_sink_GetLatencyClock(IDirectMusicSynthSink *iface,
if (!clock)
return E_POINTER;
*clock = This->latency_clock;
IReferenceClock_AddRef(This->latency_clock);
*clock = &This->IReferenceClock_iface;
IReferenceClock_AddRef(*clock);
return S_OK;
}
@ -371,10 +371,87 @@ static const IKsControlVtbl synth_sink_control =
synth_sink_control_KsEvent,
};
static inline struct synth_sink *impl_from_IReferenceClock(IReferenceClock *iface)
{
return CONTAINING_RECORD(iface, struct synth_sink, IReferenceClock_iface);
}
static HRESULT WINAPI latency_clock_QueryInterface(IReferenceClock *iface, REFIID iid, void **out)
{
TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(iid), out);
if (IsEqualIID(iid, &IID_IUnknown)
|| IsEqualIID(iid, &IID_IReferenceClock))
{
IUnknown_AddRef(iface);
*out = iface;
return S_OK;
}
FIXME("no interface for %s\n", debugstr_dmguid(iid));
*out = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI latency_clock_AddRef(IReferenceClock *iface)
{
struct synth_sink *This = impl_from_IReferenceClock(iface);
return IDirectMusicSynthSink_AddRef(&This->IDirectMusicSynthSink_iface);
}
static ULONG WINAPI latency_clock_Release(IReferenceClock *iface)
{
struct synth_sink *This = impl_from_IReferenceClock(iface);
return IDirectMusicSynthSink_Release(&This->IDirectMusicSynthSink_iface);
}
static HRESULT WINAPI latency_clock_GetTime(IReferenceClock *iface, REFERENCE_TIME *time)
{
struct synth_sink *This = impl_from_IReferenceClock(iface);
TRACE("(%p, %p)\n", iface, time);
if (!time) return E_INVALIDARG;
if (!This->active) return E_FAIL;
*time = This->latency_time;
return S_OK;
}
static HRESULT WINAPI latency_clock_AdviseTime(IReferenceClock *iface, REFERENCE_TIME base,
REFERENCE_TIME offset, HEVENT event, DWORD_PTR *cookie)
{
FIXME("(%p, %I64d, %I64d, %#Ix, %p): stub\n", iface, base, offset, event, cookie);
return E_NOTIMPL;
}
static HRESULT WINAPI latency_clock_AdvisePeriodic(IReferenceClock *iface, REFERENCE_TIME start,
REFERENCE_TIME period, HSEMAPHORE semaphore, DWORD_PTR *cookie)
{
FIXME("(%p, %I64d, %I64d, %#Ix, %p): stub\n", iface, start, period, semaphore, cookie);
return E_NOTIMPL;
}
static HRESULT WINAPI latency_clock_Unadvise(IReferenceClock *iface, DWORD_PTR cookie)
{
FIXME("(%p, %#Ix): stub\n", iface, cookie);
return E_NOTIMPL;
}
static const IReferenceClockVtbl latency_clock_vtbl =
{
latency_clock_QueryInterface,
latency_clock_AddRef,
latency_clock_Release,
latency_clock_GetTime,
latency_clock_AdviseTime,
latency_clock_AdvisePeriodic,
latency_clock_Unadvise,
};
HRESULT synth_sink_create(IUnknown **ret_iface)
{
struct synth_sink *obj;
HRESULT hr;
TRACE("(%p)\n", ret_iface);
@ -382,15 +459,9 @@ HRESULT synth_sink_create(IUnknown **ret_iface)
if (!(obj = calloc(1, sizeof(*obj)))) return E_OUTOFMEMORY;
obj->IDirectMusicSynthSink_iface.lpVtbl = &synth_sink_vtbl;
obj->IKsControl_iface.lpVtbl = &synth_sink_control;
obj->IReferenceClock_iface.lpVtbl = &latency_clock_vtbl;
obj->ref = 1;
hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (void **)&obj->latency_clock);
if (FAILED(hr))
{
free(obj);
return hr;
}
TRACE("Created DirectMusicSynthSink %p\n", obj);
*ret_iface = (IUnknown *)&obj->IDirectMusicSynthSink_iface;
return S_OK;

View file

@ -1222,12 +1222,12 @@ static void test_IDirectMusicSynthSink(void)
ok(hr == S_OK, "got %#lx\n", hr);
ok(latency_clock != clock, "got same clock\n");
ref = get_refcount(sink);
todo_wine ok(ref == 2, "got %#lx\n", ref);
ok(ref == 2, "got %#lx\n", ref);
hr = IReferenceClock_GetTime(latency_clock, NULL);
todo_wine ok(hr == E_INVALIDARG, "got %#lx\n", hr);
ok(hr == E_INVALIDARG, "got %#lx\n", hr);
hr = IReferenceClock_GetTime(latency_clock, &time);
todo_wine ok(hr == E_FAIL, "got %#lx\n", hr);
ok(hr == E_FAIL, "got %#lx\n", hr);
hr = IDirectMusicSynthSink_Init(sink, NULL);
ok(hr == S_OK, "got %#lx\n", hr);
@ -1255,7 +1255,7 @@ static void test_IDirectMusicSynthSink(void)
hr = IDirectMusicSynthSink_SetMasterClock(sink, clock);
ok(hr == S_OK, "got %#lx\n", hr);
hr = IReferenceClock_GetTime(latency_clock, &time);
todo_wine ok(hr == E_FAIL, "got %#lx\n", hr);
ok(hr == E_FAIL, "got %#lx\n", hr);
hr = IDirectMusicSynthSink_Activate(sink, TRUE);
ok(hr == S_OK, "got %#lx\n", hr);
hr = IDirectMusicSynthSink_Activate(sink, TRUE);
@ -1283,8 +1283,8 @@ static void test_IDirectMusicSynthSink(void)
/* latency clock now works fine */
tmp_time = time;
hr = IReferenceClock_GetTime(latency_clock, &tmp_time);
todo_wine_if(hr == S_FALSE) ok(hr == S_OK, "got %#lx\n", hr);
todo_wine_if(tmp_time <= time) ok(tmp_time > time, "got %I64d\n", tmp_time - time);
ok(hr == S_OK, "got %#lx\n", hr);
todo_wine ok(tmp_time > time, "got %I64d\n", tmp_time - time);
ok(tmp_time - time <= 2000000, "got %I64d\n", tmp_time - time);
/* setting the clock while active is fine */