dmusic: Implement the master clock object.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Michael Stefaniuc <mstefani@winehq.org>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2019-06-14 11:42:45 -05:00 committed by Alexandre Julliard
parent 89ecfe19ca
commit 6e3c9d6e49
2 changed files with 130 additions and 7 deletions

View File

@ -22,9 +22,132 @@
#include <stdio.h> #include <stdio.h>
#include "dmusic_private.h" #include "dmusic_private.h"
#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmusic); 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) static inline IDirectMusic8Impl *impl_from_IDirectMusic8(IDirectMusic8 *iface)
{ {
return CONTAINING_RECORD(iface, IDirectMusic8Impl, 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->IDirectMusic8_iface.lpVtbl = &DirectMusic8_Vtbl;
dmusic->ref = 1; dmusic->ref = 1;
ret = DMUSIC_CreateReferenceClockImpl(&IID_IReferenceClock, (void **)&dmusic->master_clock, NULL); ret = master_clock_create(&dmusic->master_clock);
if (FAILED(ret)) { if (FAILED(ret)) {
HeapFree(GetProcessHeap(), 0, dmusic); HeapFree(GetProcessHeap(), 0, dmusic);
return ret; return ret;

View File

@ -801,26 +801,26 @@ static void test_master_clock(void)
hr = IReferenceClock_GetTime(clock, &time1); hr = IReferenceClock_GetTime(clock, &time1);
ok(hr == S_OK, "Got hr %#x.\n", hr); ok(hr == S_OK, "Got hr %#x.\n", hr);
time2 = counter.QuadPart * 10000000.0 / freq.QuadPart; 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)); wine_dbgstr_longlong(time2), wine_dbgstr_longlong(time1));
hr = IReferenceClock_GetTime(clock, &time2); 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); Sleep(100);
hr = IReferenceClock_GetTime(clock, &time2); hr = IReferenceClock_GetTime(clock, &time2);
ok(hr == S_OK, "Got hr %#x.\n", hr); 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)); wine_dbgstr_longlong(time1 + 100 * 10000), wine_dbgstr_longlong(time2));
hr = IReferenceClock_AdviseTime(clock, 0, 0, NULL, &cookie); 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); 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); 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); IReferenceClock_Release(clock);