diff --git a/dlls/dmusic/dmusic.c b/dlls/dmusic/dmusic.c index a74a31e68bf..cc798ce4d92 100644 --- a/dlls/dmusic/dmusic.c +++ b/dlls/dmusic/dmusic.c @@ -22,9 +22,132 @@ #include #include "dmusic_private.h" +#include "wine/heap.h" WINE_DEFAULT_DEBUG_CHANNEL(dmusic); +struct master_clock { + IReferenceClock IReferenceClock_iface; + LONG ref; + double freq; + REFERENCE_TIME last_time; +}; + +static inline struct master_clock *impl_from_IReferenceClock(IReferenceClock *iface) +{ + return CONTAINING_RECORD(iface, struct master_clock, IReferenceClock_iface); +} + +static HRESULT WINAPI master_IReferenceClock_QueryInterface(IReferenceClock *iface, REFIID riid, + void **ret_iface) +{ + TRACE("(%p, %s, %p)\n", iface, debugstr_dmguid(riid), ret_iface); + + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IReferenceClock)) + *ret_iface = iface; + else { + WARN("no interface for %s\n", debugstr_dmguid(riid)); + *ret_iface = NULL; + return E_NOINTERFACE; + } + + IReferenceClock_AddRef(iface); + + return S_OK; +} + +static ULONG WINAPI master_IReferenceClock_AddRef(IReferenceClock *iface) +{ + struct master_clock *This = impl_from_IReferenceClock(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref = %u\n", iface, ref); + + return ref; +} + +static ULONG WINAPI master_IReferenceClock_Release(IReferenceClock *iface) +{ + struct master_clock *This = impl_from_IReferenceClock(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref = %u\n", iface, ref); + + if (!ref) + heap_free(This); + + return ref; +} + +static HRESULT WINAPI master_IReferenceClock_GetTime(IReferenceClock *iface, + REFERENCE_TIME *time) +{ + struct master_clock *This = impl_from_IReferenceClock(iface); + LARGE_INTEGER counter; + HRESULT hr; + + TRACE("(%p, %p)\n", iface, time); + + QueryPerformanceCounter(&counter); + *time = counter.QuadPart * This->freq; + hr = (*time == This->last_time) ? S_FALSE : S_OK; + This->last_time = *time; + + return hr; +} + +static HRESULT WINAPI master_IReferenceClock_AdviseTime(IReferenceClock *iface, + REFERENCE_TIME base, REFERENCE_TIME offset, HANDLE event, DWORD *cookie) +{ + TRACE("(%p, %s, %s, %p, %p): method not implemented\n", iface, wine_dbgstr_longlong(base), + wine_dbgstr_longlong(offset), event, cookie); + return E_NOTIMPL; +} + +static HRESULT WINAPI master_IReferenceClock_AdvisePeriodic(IReferenceClock *iface, + REFERENCE_TIME start, REFERENCE_TIME period, HANDLE semaphore, DWORD *cookie) +{ + TRACE("(%p, %s, %s, %p, %p): method not implemented\n", iface, wine_dbgstr_longlong(start), + wine_dbgstr_longlong(period), semaphore, cookie); + return E_NOTIMPL; +} + +static HRESULT WINAPI master_IReferenceClock_Unadvise(IReferenceClock *iface, DWORD cookie) +{ + TRACE("(%p, %#x): method not implemented\n", iface, cookie); + return E_NOTIMPL; +} + +static const IReferenceClockVtbl master_clock_vtbl = { + master_IReferenceClock_QueryInterface, + master_IReferenceClock_AddRef, + master_IReferenceClock_Release, + master_IReferenceClock_GetTime, + master_IReferenceClock_AdviseTime, + master_IReferenceClock_AdvisePeriodic, + master_IReferenceClock_Unadvise, +}; + +static HRESULT master_clock_create(IReferenceClock **clock) +{ + struct master_clock *obj; + LARGE_INTEGER freq; + + TRACE("(%p)\n", clock); + + if (!(obj = heap_alloc_zero(sizeof(*obj)))) + return E_OUTOFMEMORY; + + obj->IReferenceClock_iface.lpVtbl = &master_clock_vtbl; + obj->ref = 1; + QueryPerformanceFrequency(&freq); + obj->freq = 10000000.0 / freq.QuadPart; + + *clock = &obj->IReferenceClock_iface; + + return S_OK; +} + static inline IDirectMusic8Impl *impl_from_IDirectMusic8(IDirectMusic8 *iface) { return CONTAINING_RECORD(iface, IDirectMusic8Impl, IDirectMusic8_iface); @@ -483,7 +606,7 @@ HRESULT WINAPI DMUSIC_CreateDirectMusicImpl(LPCGUID riid, LPVOID* ret_iface, LPU dmusic->IDirectMusic8_iface.lpVtbl = &DirectMusic8_Vtbl; dmusic->ref = 1; - ret = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (void **)&dmusic->master_clock, NULL); + ret = master_clock_create(&dmusic->master_clock); if (FAILED(ret)) { HeapFree(GetProcessHeap(), 0, dmusic); return ret; diff --git a/dlls/dmusic/tests/dmusic.c b/dlls/dmusic/tests/dmusic.c index d071e1cdef6..f6c417af306 100644 --- a/dlls/dmusic/tests/dmusic.c +++ b/dlls/dmusic/tests/dmusic.c @@ -801,26 +801,26 @@ static void test_master_clock(void) hr = IReferenceClock_GetTime(clock, &time1); ok(hr == S_OK, "Got hr %#x.\n", hr); time2 = counter.QuadPart * 10000000.0 / freq.QuadPart; - todo_wine ok(abs(time1 - time2) < 20 * 10000, "Expected about %s, got %s.\n", + ok(abs(time1 - time2) < 20 * 10000, "Expected about %s, got %s.\n", wine_dbgstr_longlong(time2), wine_dbgstr_longlong(time1)); hr = IReferenceClock_GetTime(clock, &time2); - todo_wine ok(hr == (time2 == time1 ? S_FALSE : S_OK), "Got hr %#x.\n", hr); + ok(hr == (time2 == time1 ? S_FALSE : S_OK), "Got hr %#x.\n", hr); Sleep(100); hr = IReferenceClock_GetTime(clock, &time2); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(time2 - time1 > 80 * 10000, "Expected about %s, but got %s.\n", + ok(time2 - time1 > 80 * 10000, "Expected about %s, but got %s.\n", wine_dbgstr_longlong(time1 + 100 * 10000), wine_dbgstr_longlong(time2)); hr = IReferenceClock_AdviseTime(clock, 0, 0, NULL, &cookie); - todo_wine ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); + ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); hr = IReferenceClock_AdvisePeriodic(clock, 0, 0, NULL, &cookie); - todo_wine ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); + ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); hr = IReferenceClock_Unadvise(clock, 0); - todo_wine ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); + ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); IReferenceClock_Release(clock);