2014-07-12 17:07:52 -07:00
|
|
|
From 6b97d362c570ec4a813db1d58574a94ad61f9015 Mon Sep 17 00:00:00 2001
|
2013-12-06 12:09:21 -08:00
|
|
|
From: Maarten Lankhorst <m.b.lankhorst@gmail.com>
|
2014-07-12 17:07:52 -07:00
|
|
|
Date: Tue, 24 Jun 2014 08:48:46 +0200
|
|
|
|
Subject: [PATCH 13/43] winepulse: Add IAudioClock and IAudioClock2
|
2013-12-06 12:09:21 -08:00
|
|
|
|
|
|
|
---
|
|
|
|
dlls/winepulse.drv/mmdevdrv.c | 172 ++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
1 file changed, 172 insertions(+)
|
|
|
|
|
|
|
|
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
|
|
|
|
index 01cfd25..3ed2288 100644
|
|
|
|
--- a/dlls/winepulse.drv/mmdevdrv.c
|
|
|
|
+++ b/dlls/winepulse.drv/mmdevdrv.c
|
|
|
|
@@ -167,6 +167,16 @@ static inline ACImpl *impl_from_IAudioCaptureClient(IAudioCaptureClient *iface)
|
|
|
|
return CONTAINING_RECORD(iface, ACImpl, IAudioCaptureClient_iface);
|
|
|
|
}
|
|
|
|
|
|
|
|
+static inline ACImpl *impl_from_IAudioClock(IAudioClock *iface)
|
|
|
|
+{
|
|
|
|
+ return CONTAINING_RECORD(iface, ACImpl, IAudioClock_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline ACImpl *impl_from_IAudioClock2(IAudioClock2 *iface)
|
|
|
|
+{
|
|
|
|
+ return CONTAINING_RECORD(iface, ACImpl, IAudioClock2_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
/* Following pulseaudio design here, mainloop has the lock taken whenever
|
|
|
|
* it is handling something for pulse, and the lock is required whenever
|
|
|
|
* doing any pa_* call that can affect the state in any way
|
|
|
|
@@ -1449,6 +1459,8 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient *iface, REFIID riid,
|
|
|
|
if (This->dataflow != eCapture)
|
|
|
|
return AUDCLNT_E_WRONG_ENDPOINT_TYPE;
|
|
|
|
*ppv = &This->IAudioCaptureClient_iface;
|
|
|
|
+ } else if (IsEqualIID(riid, &IID_IAudioClock)) {
|
|
|
|
+ *ppv = &This->IAudioClock_iface;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*ppv) {
|
|
|
|
@@ -1750,6 +1762,166 @@ static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl =
|
|
|
|
AudioCaptureClient_GetNextPacketSize
|
|
|
|
};
|
|
|
|
|
|
|
|
+static HRESULT WINAPI AudioClock_QueryInterface(IAudioClock *iface,
|
|
|
|
+ REFIID riid, void **ppv)
|
|
|
|
+{
|
|
|
|
+ ACImpl *This = impl_from_IAudioClock(iface);
|
|
|
|
+
|
|
|
|
+ TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
|
|
|
|
+
|
|
|
|
+ if (!ppv)
|
|
|
|
+ return E_POINTER;
|
|
|
|
+ *ppv = NULL;
|
|
|
|
+
|
|
|
|
+ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IAudioClock))
|
|
|
|
+ *ppv = iface;
|
|
|
|
+ else if (IsEqualIID(riid, &IID_IAudioClock2))
|
|
|
|
+ *ppv = &This->IAudioClock2_iface;
|
|
|
|
+ if (*ppv) {
|
|
|
|
+ IUnknown_AddRef((IUnknown*)*ppv);
|
|
|
|
+ return S_OK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ WARN("Unknown interface %s\n", debugstr_guid(riid));
|
|
|
|
+ return E_NOINTERFACE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI AudioClock_AddRef(IAudioClock *iface)
|
|
|
|
+{
|
|
|
|
+ ACImpl *This = impl_from_IAudioClock(iface);
|
|
|
|
+ return IAudioClient_AddRef(&This->IAudioClient_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI AudioClock_Release(IAudioClock *iface)
|
|
|
|
+{
|
|
|
|
+ ACImpl *This = impl_from_IAudioClock(iface);
|
|
|
|
+ return IAudioClient_Release(&This->IAudioClient_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI AudioClock_GetFrequency(IAudioClock *iface, UINT64 *freq)
|
|
|
|
+{
|
|
|
|
+ ACImpl *This = impl_from_IAudioClock(iface);
|
|
|
|
+ HRESULT hr;
|
|
|
|
+
|
|
|
|
+ TRACE("(%p)->(%p)\n", This, freq);
|
|
|
|
+
|
|
|
|
+ pthread_mutex_lock(&pulse_lock);
|
|
|
|
+ hr = pulse_stream_valid(This);
|
|
|
|
+ if (SUCCEEDED(hr))
|
|
|
|
+ *freq = This->ss.rate * pa_frame_size(&This->ss);
|
|
|
|
+ pthread_mutex_unlock(&pulse_lock);
|
|
|
|
+ return hr;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI AudioClock_GetPosition(IAudioClock *iface, UINT64 *pos,
|
|
|
|
+ UINT64 *qpctime)
|
|
|
|
+{
|
|
|
|
+ ACImpl *This = impl_from_IAudioClock(iface);
|
|
|
|
+ pa_usec_t time;
|
|
|
|
+ HRESULT hr;
|
|
|
|
+
|
|
|
|
+ TRACE("(%p)->(%p, %p)\n", This, pos, qpctime);
|
|
|
|
+
|
|
|
|
+ if (!pos)
|
|
|
|
+ return E_POINTER;
|
|
|
|
+
|
|
|
|
+ pthread_mutex_lock(&pulse_lock);
|
|
|
|
+ hr = pulse_stream_valid(This);
|
|
|
|
+ if (FAILED(hr)) {
|
|
|
|
+ pthread_mutex_unlock(&pulse_lock);
|
|
|
|
+ return hr;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ *pos = This->clock_written;
|
|
|
|
+ if (This->clock_pulse != PA_USEC_INVALID && pa_stream_get_time(This->stream, &time) >= 0) {
|
|
|
|
+ UINT32 delta = pa_usec_to_bytes(time - This->clock_pulse, &This->ss);
|
|
|
|
+ if (delta < This->pad)
|
|
|
|
+ *pos += delta;
|
|
|
|
+ else
|
|
|
|
+ *pos += This->pad;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Make time never go backwards */
|
|
|
|
+ if (*pos < This->clock_lastpos)
|
|
|
|
+ *pos = This->clock_lastpos;
|
|
|
|
+ else
|
|
|
|
+ This->clock_lastpos = *pos;
|
|
|
|
+ pthread_mutex_unlock(&pulse_lock);
|
|
|
|
+
|
|
|
|
+ TRACE("%p Position: %u\n", This, (unsigned)*pos);
|
|
|
|
+
|
|
|
|
+ if (qpctime) {
|
|
|
|
+ LARGE_INTEGER stamp, freq;
|
|
|
|
+ QueryPerformanceCounter(&stamp);
|
|
|
|
+ QueryPerformanceFrequency(&freq);
|
|
|
|
+ *qpctime = (stamp.QuadPart * (INT64)10000000) / freq.QuadPart;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI AudioClock_GetCharacteristics(IAudioClock *iface,
|
|
|
|
+ DWORD *chars)
|
|
|
|
+{
|
|
|
|
+ ACImpl *This = impl_from_IAudioClock(iface);
|
|
|
|
+
|
|
|
|
+ TRACE("(%p)->(%p)\n", This, chars);
|
|
|
|
+
|
|
|
|
+ if (!chars)
|
|
|
|
+ return E_POINTER;
|
|
|
|
+
|
|
|
|
+ *chars = AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ;
|
|
|
|
+
|
|
|
|
+ return S_OK;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const IAudioClockVtbl AudioClock_Vtbl =
|
|
|
|
+{
|
|
|
|
+ AudioClock_QueryInterface,
|
|
|
|
+ AudioClock_AddRef,
|
|
|
|
+ AudioClock_Release,
|
|
|
|
+ AudioClock_GetFrequency,
|
|
|
|
+ AudioClock_GetPosition,
|
|
|
|
+ AudioClock_GetCharacteristics
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI AudioClock2_QueryInterface(IAudioClock2 *iface,
|
|
|
|
+ REFIID riid, void **ppv)
|
|
|
|
+{
|
|
|
|
+ ACImpl *This = impl_from_IAudioClock2(iface);
|
|
|
|
+ return IAudioClock_QueryInterface(&This->IAudioClock_iface, riid, ppv);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI AudioClock2_AddRef(IAudioClock2 *iface)
|
|
|
|
+{
|
|
|
|
+ ACImpl *This = impl_from_IAudioClock2(iface);
|
|
|
|
+ return IAudioClient_AddRef(&This->IAudioClient_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static ULONG WINAPI AudioClock2_Release(IAudioClock2 *iface)
|
|
|
|
+{
|
|
|
|
+ ACImpl *This = impl_from_IAudioClock2(iface);
|
|
|
|
+ return IAudioClient_Release(&This->IAudioClient_iface);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static HRESULT WINAPI AudioClock2_GetDevicePosition(IAudioClock2 *iface,
|
|
|
|
+ UINT64 *pos, UINT64 *qpctime)
|
|
|
|
+{
|
|
|
|
+ ACImpl *This = impl_from_IAudioClock2(iface);
|
|
|
|
+ HRESULT hr = AudioClock_GetPosition(&This->IAudioClock_iface, pos, qpctime);
|
|
|
|
+ if (SUCCEEDED(hr))
|
|
|
|
+ *pos /= pa_frame_size(&This->ss);
|
|
|
|
+ return hr;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const IAudioClock2Vtbl AudioClock2_Vtbl =
|
|
|
|
+{
|
|
|
|
+ AudioClock2_QueryInterface,
|
|
|
|
+ AudioClock2_AddRef,
|
|
|
|
+ AudioClock2_Release,
|
|
|
|
+ AudioClock2_GetDevicePosition
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device,
|
|
|
|
IAudioSessionManager2 **out)
|
|
|
|
{
|
|
|
|
--
|
2014-07-12 17:07:52 -07:00
|
|
|
2.0.0
|
2013-12-06 12:09:21 -08:00
|
|
|
|