diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c index e2eca5a4f4d..ccb5064345c 100644 --- a/dlls/winealsa.drv/alsa.c +++ b/dlls/winealsa.drv/alsa.c @@ -31,18 +31,22 @@ #include "winbase.h" #include "wingdi.h" #include "winuser.h" +#include "winnls.h" +#include "winerror.h" #include "mmddk.h" - +#include "mmreg.h" +#include "dsound.h" +#include "dsdriver.h" #include "ks.h" -#include "guiddef.h" -#include "ksmedia.h" - -#include "alsa.h" - #include "wine/library.h" #include "wine/unicode.h" #include "wine/debug.h" +#include "alsa.h" + +#include "initguid.h" +#include "ksmedia.h" + WINE_DEFAULT_DEBUG_CHANNEL(alsa); /* unless someone makes a wineserver kernel module, Unix pipes are faster than win32 events */ #define USE_PIPE_SYNC diff --git a/dlls/winealsa.drv/alsa.h b/dlls/winealsa.drv/alsa.h index 8c21b01ccfe..ff978617f9e 100644 --- a/dlls/winealsa.drv/alsa.h +++ b/dlls/winealsa.drv/alsa.h @@ -43,14 +43,6 @@ #include #endif -#include "mmreg.h" -#include "dsound.h" -#include "dsdriver.h" - -#include "ks.h" -#include "ksmedia.h" -#include "ksguid.h" - /* state diagram for waveOut writing: * * +---------+-------------+---------------+---------------------------------+ diff --git a/dlls/winealsa.drv/dscapture.c b/dlls/winealsa.drv/dscapture.c index edf8c136e02..70e70ede995 100644 --- a/dlls/winealsa.drv/dscapture.c +++ b/dlls/winealsa.drv/dscapture.c @@ -48,6 +48,9 @@ #include "winerror.h" #include "winuser.h" #include "mmddk.h" +#include "mmreg.h" +#include "dsound.h" +#include "dsdriver.h" #include "alsa.h" #include "wine/library.h" diff --git a/dlls/winealsa.drv/dsoutput.c b/dlls/winealsa.drv/dsoutput.c index ec219d99fc2..562853da03e 100644 --- a/dlls/winealsa.drv/dsoutput.c +++ b/dlls/winealsa.drv/dsoutput.c @@ -52,6 +52,9 @@ #include "winerror.h" #include "winuser.h" #include "mmddk.h" +#include "mmreg.h" +#include "dsound.h" +#include "dsdriver.h" #include "alsa.h" #include "wine/library.h" diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c index 7dd6c0fdaca..8bd048ee925 100644 --- a/dlls/winealsa.drv/midi.c +++ b/dlls/winealsa.drv/midi.c @@ -48,6 +48,9 @@ #include "winuser.h" #include "winnls.h" #include "mmddk.h" +#include "mmreg.h" +#include "dsound.h" +#include "dsdriver.h" #include "alsa.h" #include "wine/debug.h" diff --git a/dlls/winealsa.drv/mixer.c b/dlls/winealsa.drv/mixer.c index 833d2aef3d8..e28361ce32c 100644 --- a/dlls/winealsa.drv/mixer.c +++ b/dlls/winealsa.drv/mixer.c @@ -45,6 +45,9 @@ #include "winuser.h" #include "winnls.h" #include "mmddk.h" +#include "mmreg.h" +#include "dsound.h" +#include "dsdriver.h" #include "mmsystem.h" #include "alsa.h" #include "wine/unicode.h" diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c index 1bbb23c5451..2b16f867c69 100644 --- a/dlls/winealsa.drv/mmdevdrv.c +++ b/dlls/winealsa.drv/mmdevdrv.c @@ -19,7 +19,6 @@ #define NONAMELESSUNION #define COBJMACROS -#define INITGUID #include "config.h" #include @@ -35,26 +34,50 @@ #include "ole2.h" #include "mmdeviceapi.h" +#include "devpkey.h" #include "dshow.h" #include "dsound.h" -#include "audioclient.h" #include "endpointvolume.h" -#include "audiopolicy.h" +#include "initguid.h" +#include "audioclient.h" +#include "audiopolicy.h" #include "dsdriver.h" #include WINE_DEFAULT_DEBUG_CHANNEL(alsa); +#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; @@ -83,7 +106,12 @@ typedef struct ACImpl { int buf_state; CRITICAL_SECTION lock; -} ACImpl; + + AudioSession *session; + AudioSessionWrapper *session_wrapper; + + struct list entry; +}; enum BufferStates { NOT_LOCKED = 0, @@ -93,6 +121,9 @@ enum BufferStates { static HANDLE g_timer_q; +static CRITICAL_SECTION g_sessions_lock; +static struct list g_sessions = LIST_INIT(g_sessions); + static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0}; static const IAudioClientVtbl AudioClient_Vtbl; @@ -104,6 +135,7 @@ static const IAudioClockVtbl AudioClock_Vtbl; static const IAudioClock2Vtbl AudioClock2_Vtbl; int wine_snd_pcm_recover(snd_pcm_t *pcm, int err, int silent); +static AudioSessionWrapper *AudioSessionWrapper_Create(ACImpl *client); static inline ACImpl *impl_from_IAudioClient(IAudioClient *iface) { @@ -120,9 +152,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) @@ -147,6 +179,7 @@ BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved) if(!g_timer_q) return FALSE; + InitializeCriticalSection(&g_sessions_lock); } return TRUE; @@ -194,7 +227,6 @@ HRESULT WINAPI AUDDRV_GetAudioEndpoint(void *key, 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; @@ -275,6 +307,15 @@ static ULONG WINAPI AudioClient_Release(IAudioClient *iface) DeleteCriticalSection(&This->lock); snd_pcm_drop(This->pcm_handle); snd_pcm_close(This->pcm_handle); + 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->hw_params); CoTaskMemFree(This->fmt); @@ -338,6 +379,25 @@ static WAVEFORMATEX *clone_format(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, @@ -561,10 +621,42 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient *iface, goto exit; } - 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){ + LeaveCriticalSection(&g_sessions_lock); + hr = E_OUTOFMEMORY; + goto exit; + } + }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){ + LeaveCriticalSection(&g_sessions_lock); + hr = E_OUTOFMEMORY; + goto exit; + } + } + } + + list_add_tail(&This->session->clients, &This->entry); + + LeaveCriticalSection(&g_sessions_lock); + + This->initted = TRUE; + exit: HeapFree(GetProcessHeap(), 0, sw_params); if(FAILED(hr)){ @@ -1328,18 +1420,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)){ @@ -1348,9 +1450,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; } @@ -1720,6 +1825,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) { @@ -1744,33 +1867,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->started){ + *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); @@ -1780,7 +1940,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)); @@ -1790,7 +1950,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); @@ -1800,7 +1960,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)); @@ -1810,7 +1970,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); @@ -1820,7 +1980,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)); @@ -1831,7 +1991,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); @@ -1841,7 +2001,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); @@ -1851,7 +2011,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); @@ -1861,7 +2021,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); @@ -1871,7 +2031,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); @@ -1886,7 +2046,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); @@ -1896,7 +2056,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); diff --git a/dlls/winealsa.drv/wavein.c b/dlls/winealsa.drv/wavein.c index 67759a69d78..86e8c75c0df 100644 --- a/dlls/winealsa.drv/wavein.c +++ b/dlls/winealsa.drv/wavein.c @@ -51,6 +51,11 @@ #include "winuser.h" #include "winnls.h" #include "mmddk.h" +#include "mmreg.h" +#include "dsound.h" +#include "dsdriver.h" +#include "ks.h" +#include "ksmedia.h" #include "alsa.h" #include "wine/library.h" diff --git a/dlls/winealsa.drv/waveinit.c b/dlls/winealsa.drv/waveinit.c index e218197bd36..e4c81f22bc3 100644 --- a/dlls/winealsa.drv/waveinit.c +++ b/dlls/winealsa.drv/waveinit.c @@ -51,6 +51,9 @@ #include "winnls.h" #include "winreg.h" #include "mmddk.h" +#include "mmreg.h" +#include "dsound.h" +#include "dsdriver.h" #include "alsa.h" diff --git a/dlls/winealsa.drv/waveout.c b/dlls/winealsa.drv/waveout.c index 92907780c10..88153e76bee 100644 --- a/dlls/winealsa.drv/waveout.c +++ b/dlls/winealsa.drv/waveout.c @@ -51,6 +51,11 @@ #include "winuser.h" #include "winnls.h" #include "mmddk.h" +#include "mmreg.h" +#include "dsound.h" +#include "dsdriver.h" +#include "ks.h" +#include "ksmedia.h" #include "alsa.h"