From 4a95e7b0c93167ce808db629f5d0a786cc7f228e Mon Sep 17 00:00:00 2001 From: Andrew Eikum Date: Mon, 2 May 2011 08:21:49 -0500 Subject: [PATCH] wineoss.drv: Implement IAudioSessionControl::GetState. --- dlls/wineoss.drv/audio.c | 5 +- dlls/wineoss.drv/mmdevdrv.c | 234 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 202 insertions(+), 37 deletions(-) diff --git a/dlls/wineoss.drv/audio.c b/dlls/wineoss.drv/audio.c index 174eca56933..eb3dc1e717a 100644 --- a/dlls/wineoss.drv/audio.c +++ b/dlls/wineoss.drv/audio.c @@ -76,10 +76,11 @@ #include "mmreg.h" #include "dsound.h" #include "ks.h" -#include "ksmedia.h" +#include "wine/debug.h" + #include "initguid.h" +#include "ksmedia.h" #include "dsdriver.h" -#include "wine/debug.h" #include "audio.h" diff --git a/dlls/wineoss.drv/mmdevdrv.c b/dlls/wineoss.drv/mmdevdrv.c index 278b1b3bf13..c6baee98eb6 100644 --- a/dlls/wineoss.drv/mmdevdrv.c +++ b/dlls/wineoss.drv/mmdevdrv.c @@ -18,7 +18,6 @@ #define NONAMELESSUNION #define COBJMACROS -#define INITGUID #include "config.h" #include @@ -36,9 +35,11 @@ #include "devpkey.h" #include "dshow.h" #include "dsound.h" -#include "audioclient.h" #include "endpointvolume.h" + +#include "initguid.h" #include "audiopolicy.h" +#include "audioclient.h" #include #include @@ -62,14 +63,36 @@ WINE_DEFAULT_DEBUG_CHANNEL(oss); +#define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER) + static const REFERENCE_TIME DefaultPeriod = 200000; static const REFERENCE_TIME MinimumPeriod = 100000; -typedef struct ACImpl { +struct ACImpl; +typedef struct ACImpl ACImpl; + +typedef struct _AudioSession { + GUID guid; + struct list clients; + + EDataFlow dataflow; + + struct list entry; +} AudioSession; + +typedef struct _AudioSessionWrapper { + IAudioSessionControl2 IAudioSessionControl2_iface; + + LONG ref; + + ACImpl *client; + AudioSession *session; +} AudioSessionWrapper; + +struct ACImpl { IAudioClient IAudioClient_iface; IAudioRenderClient IAudioRenderClient_iface; IAudioCaptureClient IAudioCaptureClient_iface; - IAudioSessionControl2 IAudioSessionControl2_iface; ISimpleAudioVolume ISimpleAudioVolume_iface; IAudioClock IAudioClock_iface; IAudioClock2 IAudioClock2_iface; @@ -98,7 +121,12 @@ typedef struct ACImpl { HANDLE timer; CRITICAL_SECTION lock; -} ACImpl; + + AudioSession *session; + AudioSessionWrapper *session_wrapper; + + struct list entry; +}; enum BufferStates { NOT_LOCKED = 0, @@ -108,6 +136,11 @@ enum BufferStates { static HANDLE g_timer_q; +static CRITICAL_SECTION g_sessions_lock; +static struct list g_sessions = LIST_INIT(g_sessions); + +static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client); + static const IAudioClientVtbl AudioClient_Vtbl; static const IAudioRenderClientVtbl AudioRenderClient_Vtbl; static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl; @@ -131,9 +164,9 @@ static inline ACImpl *impl_from_IAudioCaptureClient(IAudioCaptureClient *iface) return CONTAINING_RECORD(iface, ACImpl, IAudioCaptureClient_iface); } -static inline ACImpl *impl_from_IAudioSessionControl2(IAudioSessionControl2 *iface) +static inline AudioSessionWrapper *impl_from_IAudioSessionControl2(IAudioSessionControl2 *iface) { - return CONTAINING_RECORD(iface, ACImpl, IAudioSessionControl2_iface); + return CONTAINING_RECORD(iface, AudioSessionWrapper, IAudioSessionControl2_iface); } static inline ACImpl *impl_from_ISimpleAudioVolume(ISimpleAudioVolume *iface) @@ -157,6 +190,8 @@ BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved) g_timer_q = CreateTimerQueue(); if(!g_timer_q) return FALSE; + + InitializeCriticalSection(&g_sessions_lock); } return TRUE; @@ -325,7 +360,6 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(char *devnode, IMMDevice *dev, This->IAudioClient_iface.lpVtbl = &AudioClient_Vtbl; This->IAudioRenderClient_iface.lpVtbl = &AudioRenderClient_Vtbl; This->IAudioCaptureClient_iface.lpVtbl = &AudioCaptureClient_Vtbl; - This->IAudioSessionControl2_iface.lpVtbl = &AudioSessionControl2_Vtbl; This->ISimpleAudioVolume_iface.lpVtbl = &SimpleAudioVolume_Vtbl; This->IAudioClock_iface.lpVtbl = &AudioClock_Vtbl; This->IAudioClock2_iface.lpVtbl = &AudioClock2_Vtbl; @@ -380,6 +414,15 @@ static ULONG WINAPI AudioClient_Release(IAudioClient *iface) IMMDevice_Release(This->parent); DeleteCriticalSection(&This->lock); close(This->fd); + if(This->initted){ + EnterCriticalSection(&g_sessions_lock); + list_remove(&This->entry); + if(list_empty(&This->session->clients)){ + list_remove(&This->session->entry); + HeapFree(GetProcessHeap(), 0, This->session); + } + LeaveCriticalSection(&g_sessions_lock); + } HeapFree(GetProcessHeap(), 0, This->local_buffer); HeapFree(GetProcessHeap(), 0, This->tmp_buffer); CoTaskMemFree(This->fmt); @@ -577,6 +620,25 @@ static HRESULT setup_oss_device(ACImpl *This, const WAVEFORMATEX *fmt, return ret; } +static AudioSession *create_session(const GUID *guid, EDataFlow flow) +{ + AudioSession *ret; + + ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AudioSession)); + if(!ret) + return NULL; + + memcpy(&ret->guid, guid, sizeof(GUID)); + + ret->dataflow = flow; + + list_init(&ret->clients); + + list_add_head(&g_sessions, &ret->entry); + + return ret; +} + static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, AUDCLNT_SHAREMODE mode, DWORD flags, REFERENCE_TIME duration, REFERENCE_TIME period, const WAVEFORMATEX *fmt, @@ -658,10 +720,44 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, return E_OUTOFMEMORY; } - This->initted = TRUE; This->share = mode; This->flags = flags; + EnterCriticalSection(&g_sessions_lock); + + if(!sessionguid || IsEqualGUID(sessionguid, &GUID_NULL)){ + This->session = create_session(&GUID_NULL, This->dataflow); + if(!This->session){ + CoTaskMemFree(This->fmt); + This->fmt = NULL; + LeaveCriticalSection(&g_sessions_lock); + return E_OUTOFMEMORY; + } + }else{ + AudioSession *session; + + LIST_FOR_EACH_ENTRY(session, &g_sessions, AudioSession, entry) + if(IsEqualGUID(sessionguid, &session->guid) && + This->dataflow == session->dataflow) + This->session = session; + + if(!This->session){ + This->session = create_session(sessionguid, This->dataflow); + if(!This->session){ + CoTaskMemFree(This->fmt); + This->fmt = NULL; + LeaveCriticalSection(&g_sessions_lock); + return E_OUTOFMEMORY; + } + } + } + + list_add_tail(&This->session->clients, &This->entry); + + LeaveCriticalSection(&g_sessions_lock); + + This->initted = TRUE; + LeaveCriticalSection(&This->lock); return S_OK; @@ -1183,18 +1279,28 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient *iface, REFIID riid, return AUDCLNT_E_NOT_INITIALIZED; } - LeaveCriticalSection(&This->lock); - if(IsEqualIID(riid, &IID_IAudioRenderClient)){ - if(This->dataflow != eRender) + if(This->dataflow != eRender){ + LeaveCriticalSection(&This->lock); return AUDCLNT_E_WRONG_ENDPOINT_TYPE; + } *ppv = &This->IAudioRenderClient_iface; }else if(IsEqualIID(riid, &IID_IAudioCaptureClient)){ - if(This->dataflow != eCapture) + if(This->dataflow != eCapture){ + LeaveCriticalSection(&This->lock); return AUDCLNT_E_WRONG_ENDPOINT_TYPE; + } *ppv = &This->IAudioCaptureClient_iface; }else if(IsEqualIID(riid, &IID_IAudioSessionControl)){ - *ppv = &This->IAudioSessionControl2_iface; + if(!This->session_wrapper){ + This->session_wrapper = AudioSessionWrapper_Create(This); + if(!This->session_wrapper){ + LeaveCriticalSection(&This->lock); + return E_OUTOFMEMORY; + } + } + + *ppv = &This->session_wrapper->IAudioSessionControl2_iface; }else if(IsEqualIID(riid, &IID_ISimpleAudioVolume)){ *ppv = &This->ISimpleAudioVolume_iface; }else if(IsEqualIID(riid, &IID_IAudioClock)){ @@ -1203,9 +1309,12 @@ static HRESULT WINAPI AudioClient_GetService(IAudioClient *iface, REFIID riid, if(*ppv){ IUnknown_AddRef((IUnknown*)*ppv); + LeaveCriticalSection(&This->lock); return S_OK; } + LeaveCriticalSection(&This->lock); + FIXME("stub %s\n", debugstr_guid(riid)); return E_NOINTERFACE; } @@ -1566,6 +1675,24 @@ static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl = AudioCaptureClient_GetNextPacketSize }; +static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client) +{ + AudioSessionWrapper *ret; + + ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(AudioSessionWrapper)); + if(!ret) + return NULL; + + ret->IAudioSessionControl2_iface.lpVtbl = &AudioSessionControl2_Vtbl; + + ret->client = client; + ret->session = client->session; + AudioClient_AddRef(&client->IAudioClient_iface); + + return ret; +} + static HRESULT WINAPI AudioSessionControl_QueryInterface( IAudioSessionControl2 *iface, REFIID riid, void **ppv) { @@ -1590,33 +1717,70 @@ static HRESULT WINAPI AudioSessionControl_QueryInterface( static ULONG WINAPI AudioSessionControl_AddRef(IAudioSessionControl2 *iface) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); - return IAudioClient_AddRef(&This->IAudioClient_iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); + ULONG ref; + ref = InterlockedIncrement(&This->ref); + TRACE("(%p) Refcount now %u\n", This, ref); + return ref; } static ULONG WINAPI AudioSessionControl_Release(IAudioSessionControl2 *iface) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); - return IAudioClient_Release(&This->IAudioClient_iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); + ULONG ref; + ref = InterlockedDecrement(&This->ref); + TRACE("(%p) Refcount now %u\n", This, ref); + if(!ref){ + EnterCriticalSection(&This->client->lock); + This->client->session_wrapper = NULL; + LeaveCriticalSection(&This->client->lock); + AudioClient_Release(&This->client->IAudioClient_iface); + HeapFree(GetProcessHeap(), 0, This); + } + return ref; } static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface, AudioSessionState *state) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); + ACImpl *client; - FIXME("(%p)->(%p) - stub\n", This, state); + TRACE("(%p)->(%p)\n", This, state); if(!state) - return E_POINTER; + return NULL_PTR_ERR; - return E_NOTIMPL; + EnterCriticalSection(&g_sessions_lock); + + if(list_empty(&This->session->clients)){ + *state = AudioSessionStateExpired; + LeaveCriticalSection(&g_sessions_lock); + return S_OK; + } + + LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry){ + EnterCriticalSection(&client->lock); + if(client->playing){ + *state = AudioSessionStateActive; + LeaveCriticalSection(&client->lock); + LeaveCriticalSection(&g_sessions_lock); + return S_OK; + } + LeaveCriticalSection(&client->lock); + } + + LeaveCriticalSection(&g_sessions_lock); + + *state = AudioSessionStateInactive; + + return S_OK; } static HRESULT WINAPI AudioSessionControl_GetDisplayName( IAudioSessionControl2 *iface, WCHAR **name) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); FIXME("(%p)->(%p) - stub\n", This, name); @@ -1626,7 +1790,7 @@ static HRESULT WINAPI AudioSessionControl_GetDisplayName( static HRESULT WINAPI AudioSessionControl_SetDisplayName( IAudioSessionControl2 *iface, const WCHAR *name, const GUID *session) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); FIXME("(%p)->(%p, %s) - stub\n", This, name, debugstr_guid(session)); @@ -1636,7 +1800,7 @@ static HRESULT WINAPI AudioSessionControl_SetDisplayName( static HRESULT WINAPI AudioSessionControl_GetIconPath( IAudioSessionControl2 *iface, WCHAR **path) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); FIXME("(%p)->(%p) - stub\n", This, path); @@ -1646,7 +1810,7 @@ static HRESULT WINAPI AudioSessionControl_GetIconPath( static HRESULT WINAPI AudioSessionControl_SetIconPath( IAudioSessionControl2 *iface, const WCHAR *path, const GUID *session) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); FIXME("(%p)->(%p, %s) - stub\n", This, path, debugstr_guid(session)); @@ -1656,7 +1820,7 @@ static HRESULT WINAPI AudioSessionControl_SetIconPath( static HRESULT WINAPI AudioSessionControl_GetGroupingParam( IAudioSessionControl2 *iface, GUID *group) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); FIXME("(%p)->(%p) - stub\n", This, group); @@ -1666,7 +1830,7 @@ static HRESULT WINAPI AudioSessionControl_GetGroupingParam( static HRESULT WINAPI AudioSessionControl_SetGroupingParam( IAudioSessionControl2 *iface, GUID *group, const GUID *session) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); FIXME("(%p)->(%s, %s) - stub\n", This, debugstr_guid(group), debugstr_guid(session)); @@ -1677,7 +1841,7 @@ static HRESULT WINAPI AudioSessionControl_SetGroupingParam( static HRESULT WINAPI AudioSessionControl_RegisterAudioSessionNotification( IAudioSessionControl2 *iface, IAudioSessionEvents *events) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); FIXME("(%p)->(%p) - stub\n", This, events); @@ -1687,7 +1851,7 @@ static HRESULT WINAPI AudioSessionControl_RegisterAudioSessionNotification( static HRESULT WINAPI AudioSessionControl_UnregisterAudioSessionNotification( IAudioSessionControl2 *iface, IAudioSessionEvents *events) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); FIXME("(%p)->(%p) - stub\n", This, events); @@ -1697,7 +1861,7 @@ static HRESULT WINAPI AudioSessionControl_UnregisterAudioSessionNotification( static HRESULT WINAPI AudioSessionControl_GetSessionIdentifier( IAudioSessionControl2 *iface, WCHAR **id) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); FIXME("(%p)->(%p) - stub\n", This, id); @@ -1707,7 +1871,7 @@ static HRESULT WINAPI AudioSessionControl_GetSessionIdentifier( static HRESULT WINAPI AudioSessionControl_GetSessionInstanceIdentifier( IAudioSessionControl2 *iface, WCHAR **id) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); FIXME("(%p)->(%p) - stub\n", This, id); @@ -1717,7 +1881,7 @@ static HRESULT WINAPI AudioSessionControl_GetSessionInstanceIdentifier( static HRESULT WINAPI AudioSessionControl_GetProcessId( IAudioSessionControl2 *iface, DWORD *pid) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); TRACE("(%p)->(%p)\n", This, pid); @@ -1732,7 +1896,7 @@ static HRESULT WINAPI AudioSessionControl_GetProcessId( static HRESULT WINAPI AudioSessionControl_IsSystemSoundsSession( IAudioSessionControl2 *iface) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); TRACE("(%p)\n", This); @@ -1742,7 +1906,7 @@ static HRESULT WINAPI AudioSessionControl_IsSystemSoundsSession( static HRESULT WINAPI AudioSessionControl_SetDuckingPreference( IAudioSessionControl2 *iface, BOOL optout) { - ACImpl *This = impl_from_IAudioSessionControl2(iface); + AudioSessionWrapper *This = impl_from_IAudioSessionControl2(iface); TRACE("(%p)->(%d)\n", This, optout); -- 2.11.4.GIT