/*** IReferenceClock methods ***/ static HRESULT WINAPI ReferenceClock_GetTime(IReferenceClock *iface, REFERENCE_TIME *pTime) { DSoundRenderImpl *This = impl_from_IReferenceClock(iface); HRESULT hr = E_FAIL; TRACE("(%p/%p)->(%p)\n", This, iface, pTime); if (!pTime) return E_POINTER; if (This->dsbuffer) { DWORD writepos1, writepos2; EnterCriticalSection(&This->renderer.filter.csFilter); DSoundRender_UpdatePositions(This, &writepos1, &writepos2); if (This->renderer.pInputPin && This->renderer.pInputPin->pin.mtCurrent.pbFormat) { *pTime = This->play_time + time_from_pos(This, This->last_playpos); hr = S_OK; } else { ERR("pInputPin Disconnected\n"); hr = E_FAIL; } LeaveCriticalSection(&This->renderer.filter.csFilter); } if (FAILED(hr)) WARN("Could not get reference time (%x)!\n", hr); return hr; }
static HRESULT WINAPI SystemClockImpl_AdviseTime(IReferenceClock* iface, REFERENCE_TIME rtBaseTime, REFERENCE_TIME rtStreamTime, HEVENT hEvent, DWORD_PTR* pdwAdviseCookie) { SystemClockImpl *This = impl_from_IReferenceClock(iface); SystemClockAdviseEntry* pEntry = NULL; TRACE("(%p, 0x%s, 0x%s, %ld, %p)\n", This, wine_dbgstr_longlong(rtBaseTime), wine_dbgstr_longlong(rtStreamTime), hEvent, pdwAdviseCookie); if (!hEvent) { return E_INVALIDARG; } if (0 >= rtBaseTime + rtStreamTime) { return E_INVALIDARG; } if (NULL == pdwAdviseCookie) { return E_POINTER; } pEntry = CoTaskMemAlloc(sizeof(SystemClockAdviseEntry)); if (NULL == pEntry) { return E_OUTOFMEMORY; } ZeroMemory(pEntry, sizeof(SystemClockAdviseEntry)); pEntry->hEvent = (HANDLE) hEvent; pEntry->rtBaseTime = rtBaseTime + rtStreamTime; pEntry->rtIntervalTime = 0; EnterCriticalSection(&This->safe); QUARTZ_InsertAviseEntryFromQueue(This, pEntry, &This->pSingleShotAdvise); LeaveCriticalSection(&This->safe); SystemClockPostMessageToAdviseThread(This, ADVISE_ADD_SINGLESHOT); *pdwAdviseCookie = (DWORD_PTR) (pEntry); return S_OK; }
static HRESULT WINAPI SystemClockImpl_AdvisePeriodic(IReferenceClock* iface, REFERENCE_TIME rtStartTime, REFERENCE_TIME rtPeriodTime, HSEMAPHORE hSemaphore, DWORD_PTR* pdwAdviseCookie) { SystemClockImpl *This = impl_from_IReferenceClock(iface); SystemClockAdviseEntry* pEntry = NULL; TRACE("(%p, 0x%s, 0x%s, %ld, %p)\n", This, wine_dbgstr_longlong(rtStartTime), wine_dbgstr_longlong(rtPeriodTime), hSemaphore, pdwAdviseCookie); if (!hSemaphore) { return E_INVALIDARG; } if (0 >= rtStartTime || 0 >= rtPeriodTime) { return E_INVALIDARG; } if (NULL == pdwAdviseCookie) { return E_POINTER; } pEntry = CoTaskMemAlloc(sizeof(SystemClockAdviseEntry)); if (NULL == pEntry) { return E_OUTOFMEMORY; } ZeroMemory(pEntry, sizeof(SystemClockAdviseEntry)); pEntry->hEvent = (HANDLE) hSemaphore; pEntry->rtBaseTime = rtStartTime; pEntry->rtIntervalTime = rtPeriodTime; EnterCriticalSection(&This->safe); QUARTZ_InsertAviseEntryFromQueue(This, pEntry, &This->pPeriodicAdvise); LeaveCriticalSection(&This->safe); SystemClockPostMessageToAdviseThread(This, ADVISE_ADD_PERIODIC); *pdwAdviseCookie = (DWORD_PTR) (pEntry); return S_OK; }
static HRESULT WINAPI SystemClockImpl_Unadvise(IReferenceClock* iface, DWORD_PTR dwAdviseCookie) { SystemClockImpl *This = impl_from_IReferenceClock(iface); SystemClockAdviseEntry* pEntry = NULL; SystemClockAdviseEntry* it = NULL; HRESULT ret = S_OK; TRACE("(%p, %lu)\n", This, dwAdviseCookie); pEntry = (SystemClockAdviseEntry*) dwAdviseCookie; EnterCriticalSection(&This->safe); for (it = This->pPeriodicAdvise; NULL != it && it != pEntry; it = it->next) ; if (it != pEntry) { for (it = This->pSingleShotAdvise; NULL != it && it != pEntry; it = it->next) ; if (it != pEntry) { ret = S_FALSE; goto out; } } QUARTZ_RemoveAviseEntryFromQueue(This, pEntry); CoTaskMemFree(pEntry); SystemClockPostMessageToAdviseThread(This, ADVISE_REMOVE); out: LeaveCriticalSection(&This->safe); return ret; }
static HRESULT WINAPI IReferenceClockImpl_AdviseTime(IReferenceClock *iface, REFERENCE_TIME baseTime, REFERENCE_TIME streamTime, HANDLE hEvent, DWORD* pdwAdviseCookie) { IReferenceClockImpl *This = impl_from_IReferenceClock(iface); FIXME("(%p)->(0x%s, 0x%s, %p, %p): stub\n", This, wine_dbgstr_longlong(baseTime), wine_dbgstr_longlong(streamTime), hEvent, pdwAdviseCookie); return S_OK; }
static HRESULT WINAPI IReferenceClockImpl_AdvisePeriodic(IReferenceClock *iface, REFERENCE_TIME startTime, REFERENCE_TIME periodTime, HANDLE hSemaphore, DWORD* pdwAdviseCookie) { IReferenceClockImpl *This = impl_from_IReferenceClock(iface); FIXME("(%p)->(0x%s, 0x%s, %p, %p): stub\n", This, wine_dbgstr_longlong(startTime), wine_dbgstr_longlong(periodTime), hSemaphore, pdwAdviseCookie); return S_OK; }
static HRESULT WINAPI IReferenceClockImpl_Unadvise(IReferenceClock *iface, DWORD dwAdviseCookie) { IReferenceClockImpl *This = impl_from_IReferenceClock(iface); FIXME("(%p)->(%d): stub\n", This, dwAdviseCookie); return S_OK; }
static ULONG WINAPI ReferenceClock_Release(IReferenceClock *iface) { DSoundRenderImpl *This = impl_from_IReferenceClock(iface); TRACE("(%p/%p)->()\n", This, iface); return DSoundRender_Release(&This->renderer.filter.IBaseFilter_iface); }
static ULONG WINAPI SystemClockImpl_AddRef(IReferenceClock* iface) { SystemClockImpl *This = impl_from_IReferenceClock(iface); ULONG ref = InterlockedIncrement(&This->ref); TRACE("(%p): AddRef from %d\n", This, ref - 1); return ref; }
/*** IUnknown methods ***/ static HRESULT WINAPI ReferenceClock_QueryInterface(IReferenceClock *iface, REFIID riid, LPVOID*ppvObj) { DSoundRenderImpl *This = impl_from_IReferenceClock(iface); TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppvObj); return DSoundRender_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj); }
/* IReferenceClockImpl IReferenceClock part: */ static HRESULT WINAPI IReferenceClockImpl_GetTime(IReferenceClock *iface, REFERENCE_TIME* pTime) { IReferenceClockImpl *This = impl_from_IReferenceClock(iface); TRACE("(%p)->(%p)\n", This, pTime); *pTime = This->rtTime; return S_OK; }
static HRESULT WINAPI ReferenceClock_Unadvise(IReferenceClock *iface, DWORD_PTR dwAdviseCookie) { DSoundRenderImpl *This = impl_from_IReferenceClock(iface); TRACE("(%p/%p)->(%p)\n", This, iface, (void*)dwAdviseCookie); if (!This->advisethread || !dwAdviseCookie) return S_FALSE; PostThreadMessageW(This->threadid, WM_APP+3, dwAdviseCookie, 0); return S_OK; }
static ULONG WINAPI IReferenceClockImpl_AddRef(IReferenceClock *iface) { IReferenceClockImpl *This = impl_from_IReferenceClock(iface); ULONG refCount = InterlockedIncrement(&This->ref); TRACE("(%p)->(ref before=%u)\n", This, refCount - 1); DMUSIC_LockModule(); return refCount; }
/* IReferenceClockImpl IUnknown part: */ static HRESULT WINAPI IReferenceClockImpl_QueryInterface(IReferenceClock *iface, REFIID riid, LPVOID *ppobj) { IReferenceClockImpl *This = impl_from_IReferenceClock(iface); TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj); if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IReferenceClock)) { IUnknown_AddRef(iface); *ppobj = This; return S_OK; } WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj); return E_NOINTERFACE; }
static ULONG WINAPI IReferenceClockImpl_Release(IReferenceClock *iface) { IReferenceClockImpl *This = impl_from_IReferenceClock(iface); ULONG refCount = InterlockedDecrement(&This->ref); TRACE("(%p)->(ref before=%u)\n", This, refCount + 1); if (!refCount) { HeapFree(GetProcessHeap(), 0, This); } DMUSIC_UnlockModule(); return refCount; }
static ULONG WINAPI SystemClockImpl_Release(IReferenceClock* iface) { SystemClockImpl *This = impl_from_IReferenceClock(iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %d\n", This, ref); if (ref == 0) { if (SystemClockPostMessageToAdviseThread(This, ADVISE_EXIT)) { WaitForSingleObject(This->adviseThread, INFINITE); CloseHandle(This->adviseThread); } This->safe.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->safe); CoTaskMemFree(This); } return ref; }
static HRESULT WINAPI SystemClockImpl_QueryInterface(IReferenceClock* iface, REFIID riid, void** ppobj) { SystemClockImpl *This = impl_from_IReferenceClock(iface); TRACE("(%p, %s,%p)\n", This, debugstr_guid(riid), ppobj); if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IReferenceClock)) { SystemClockImpl_AddRef(iface); *ppobj = &This->IReferenceClock_iface; return S_OK; } *ppobj = NULL; WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppobj); return E_NOINTERFACE; }
static HRESULT WINAPI ReferenceClock_AdviseTime(IReferenceClock *iface, REFERENCE_TIME rtBaseTime, REFERENCE_TIME rtStreamTime, HEVENT hEvent, DWORD_PTR *pdwAdviseCookie) { DSoundRenderImpl *This = impl_from_IReferenceClock(iface); REFERENCE_TIME when = rtBaseTime + rtStreamTime; REFERENCE_TIME future; TRACE("(%p/%p)->(%s, %s, %p, %p)\n", This, iface, wine_dbgstr_longlong(rtBaseTime), wine_dbgstr_longlong(rtStreamTime), (void*)hEvent, pdwAdviseCookie); if (when <= 0) return E_INVALIDARG; if (!pdwAdviseCookie) return E_POINTER; EnterCriticalSection(&This->renderer.filter.csFilter); future = when - This->play_time; if (!This->threadid && This->dsbuffer) { This->thread_wait = CreateEventW(0, 0, 0, 0); This->advisethread = CreateThread(NULL, 0, DSoundAdviseThread, This, 0, &This->threadid); WaitForSingleObject(This->thread_wait, INFINITE); CloseHandle(This->thread_wait); } LeaveCriticalSection(&This->renderer.filter.csFilter); /* If it's in the past or the next millisecond, trigger immediately */ if (future <= 10000) { SetEvent((HANDLE)hEvent); *pdwAdviseCookie = 0; } else { struct dsoundrender_timer *t = HeapAlloc(GetProcessHeap(), 0, sizeof(*t)); t->next = NULL; t->start = when; t->periodicity = 0; t->handle = (HANDLE)hEvent; t->cookie = InterlockedIncrement(&cookie_counter); PostThreadMessageW(This->threadid, WM_APP+1, (WPARAM)t, 0); *pdwAdviseCookie = t->cookie; } return S_OK; }
static HRESULT WINAPI SystemClockImpl_GetTime(IReferenceClock* iface, REFERENCE_TIME* pTime) { SystemClockImpl *This = impl_from_IReferenceClock(iface); DWORD curTimeTickCount; HRESULT hr = S_OK; TRACE("(%p, %p)\n", This, pTime); if (NULL == pTime) { return E_POINTER; } curTimeTickCount = GetTickCount(); EnterCriticalSection(&This->safe); if (This->lastTimeTickCount == curTimeTickCount) hr = S_FALSE; This->lastRefTime += (REFERENCE_TIME) (DWORD) (curTimeTickCount - This->lastTimeTickCount) * (REFERENCE_TIME) 10000; This->lastTimeTickCount = curTimeTickCount; *pTime = This->lastRefTime; LeaveCriticalSection(&This->safe); return hr; }
static HRESULT WINAPI ReferenceClock_AdvisePeriodic(IReferenceClock *iface, REFERENCE_TIME rtStartTime, REFERENCE_TIME rtPeriodTime, HSEMAPHORE hSemaphore, DWORD_PTR *pdwAdviseCookie) { DSoundRenderImpl *This = impl_from_IReferenceClock(iface); struct dsoundrender_timer *t; TRACE("(%p/%p)->(%s, %s, %p, %p)\n", This, iface, wine_dbgstr_longlong(rtStartTime), wine_dbgstr_longlong(rtPeriodTime), (void*)hSemaphore, pdwAdviseCookie); if (rtStartTime <= 0 || rtPeriodTime <= 0) return E_INVALIDARG; if (!pdwAdviseCookie) return E_POINTER; EnterCriticalSection(&This->renderer.filter.csFilter); if (!This->threadid && This->dsbuffer) { This->thread_wait = CreateEventW(0, 0, 0, 0); This->advisethread = CreateThread(NULL, 0, DSoundAdviseThread, This, 0, &This->threadid); WaitForSingleObject(This->thread_wait, INFINITE); CloseHandle(This->thread_wait); } LeaveCriticalSection(&This->renderer.filter.csFilter); t = HeapAlloc(GetProcessHeap(), 0, sizeof(*t)); t->next = NULL; t->start = rtStartTime; t->periodicity = rtPeriodTime; t->handle = (HANDLE)hSemaphore; t->cookie = InterlockedIncrement(&cookie_counter); PostThreadMessageW(This->threadid, WM_APP+1, (WPARAM)t, 0); *pdwAdviseCookie = t->cookie; return S_OK; }