Commit a4149d53 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

winepulse: Use a critical section for PE-side locking.

parent b4c7823b
...@@ -68,6 +68,15 @@ static GUID pulse_render_guid = ...@@ -68,6 +68,15 @@ static GUID pulse_render_guid =
static GUID pulse_capture_guid = static GUID pulse_capture_guid =
{ 0x25da76d0, 0x033c, 0x4235, { 0x90, 0x02, 0x19, 0xf4, 0x88, 0x94, 0xac, 0x6f } }; { 0x25da76d0, 0x033c, 0x4235, { 0x90, 0x02, 0x19, 0xf4, 0x88, 0x94, 0xac, 0x6f } };
static CRITICAL_SECTION session_cs;
static CRITICAL_SECTION_DEBUG session_cs_debug = {
0, 0, &session_cs,
{ &session_cs_debug.ProcessLocksList,
&session_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": session_cs") }
};
static CRITICAL_SECTION session_cs = { &session_cs_debug, -1, 0, 0, 0, 0 };
BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved) BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
{ {
if (reason == DLL_PROCESS_ATTACH) { if (reason == DLL_PROCESS_ATTACH) {
...@@ -367,9 +376,9 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface) ...@@ -367,9 +376,9 @@ static ULONG WINAPI AudioClient_Release(IAudioClient3 *iface)
if (This->pulse_stream) { if (This->pulse_stream) {
pulse->release_stream(This->pulse_stream, This->timer); pulse->release_stream(This->pulse_stream, This->timer);
This->pulse_stream = NULL; This->pulse_stream = NULL;
pulse->lock(); EnterCriticalSection(&session_cs);
list_remove(&This->entry); list_remove(&This->entry);
pulse->unlock(); LeaveCriticalSection(&session_cs);
} }
IUnknown_Release(This->marshal); IUnknown_Release(This->marshal);
IMMDevice_Release(This->parent); IMMDevice_Release(This->parent);
...@@ -549,10 +558,10 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, ...@@ -549,10 +558,10 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
return E_INVALIDARG; return E_INVALIDARG;
} }
pulse->lock(); EnterCriticalSection(&session_cs);
if (This->pulse_stream) { if (This->pulse_stream) {
pulse->unlock(); LeaveCriticalSection(&session_cs);
return AUDCLNT_E_ALREADY_INITIALIZED; return AUDCLNT_E_ALREADY_INITIALIZED;
} }
...@@ -562,7 +571,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, ...@@ -562,7 +571,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
if (!(pulse_thread = CreateThread(NULL, 0, pulse_mainloop_thread, event, 0, NULL))) if (!(pulse_thread = CreateThread(NULL, 0, pulse_mainloop_thread, event, 0, NULL)))
{ {
ERR("Failed to create mainloop thread.\n"); ERR("Failed to create mainloop thread.\n");
pulse->unlock(); LeaveCriticalSection(&session_cs);
CloseHandle(event); CloseHandle(event);
return E_FAIL; return E_FAIL;
} }
...@@ -577,14 +586,14 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, ...@@ -577,14 +586,14 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
free(name); free(name);
if (FAILED(hr)) if (FAILED(hr))
{ {
pulse->unlock(); LeaveCriticalSection(&session_cs);
return hr; return hr;
} }
if (!(This->vol = malloc(channel_count * sizeof(*This->vol)))) if (!(This->vol = malloc(channel_count * sizeof(*This->vol))))
{ {
pulse->release_stream(stream, NULL); pulse->release_stream(stream, NULL);
pulse->unlock(); LeaveCriticalSection(&session_cs);
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
for (i = 0; i < channel_count; i++) for (i = 0; i < channel_count; i++)
...@@ -595,7 +604,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, ...@@ -595,7 +604,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
{ {
free(This->vol); free(This->vol);
This->vol = NULL; This->vol = NULL;
pulse->unlock(); LeaveCriticalSection(&session_cs);
pulse->release_stream(stream, NULL); pulse->release_stream(stream, NULL);
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
...@@ -605,7 +614,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, ...@@ -605,7 +614,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
list_add_tail(&This->session->clients, &This->entry); list_add_tail(&This->session->clients, &This->entry);
set_stream_volumes(This); set_stream_volumes(This);
pulse->unlock(); LeaveCriticalSection(&session_cs);
return S_OK; return S_OK;
} }
...@@ -1445,12 +1454,12 @@ static HRESULT WINAPI AudioStreamVolume_SetAllVolumes( ...@@ -1445,12 +1454,12 @@ static HRESULT WINAPI AudioStreamVolume_SetAllVolumes(
if (count != This->channel_count) if (count != This->channel_count)
return E_INVALIDARG; return E_INVALIDARG;
pulse->lock(); EnterCriticalSection(&session_cs);
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
This->vol[i] = levels[i]; This->vol[i] = levels[i];
set_stream_volumes(This); set_stream_volumes(This);
pulse->unlock(); LeaveCriticalSection(&session_cs);
return S_OK; return S_OK;
} }
...@@ -1470,10 +1479,10 @@ static HRESULT WINAPI AudioStreamVolume_GetAllVolumes( ...@@ -1470,10 +1479,10 @@ static HRESULT WINAPI AudioStreamVolume_GetAllVolumes(
if (count != This->channel_count) if (count != This->channel_count)
return E_INVALIDARG; return E_INVALIDARG;
pulse->lock(); EnterCriticalSection(&session_cs);
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
levels[i] = This->vol[i]; levels[i] = This->vol[i];
pulse->unlock(); LeaveCriticalSection(&session_cs);
return S_OK; return S_OK;
} }
...@@ -1492,10 +1501,10 @@ static HRESULT WINAPI AudioStreamVolume_SetChannelVolume( ...@@ -1492,10 +1501,10 @@ static HRESULT WINAPI AudioStreamVolume_SetChannelVolume(
if (index >= This->channel_count) if (index >= This->channel_count)
return E_INVALIDARG; return E_INVALIDARG;
pulse->lock(); EnterCriticalSection(&session_cs);
This->vol[index] = level; This->vol[index] = level;
set_stream_volumes(This); set_stream_volumes(This);
pulse->unlock(); LeaveCriticalSection(&session_cs);
return S_OK; return S_OK;
} }
...@@ -1514,9 +1523,9 @@ static HRESULT WINAPI AudioStreamVolume_GetChannelVolume( ...@@ -1514,9 +1523,9 @@ static HRESULT WINAPI AudioStreamVolume_GetChannelVolume(
if (index >= This->channel_count) if (index >= This->channel_count)
return E_INVALIDARG; return E_INVALIDARG;
pulse->lock(); EnterCriticalSection(&session_cs);
*level = This->vol[index]; *level = This->vol[index];
pulse->unlock(); LeaveCriticalSection(&session_cs);
return S_OK; return S_OK;
} }
...@@ -1614,7 +1623,7 @@ static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface, ...@@ -1614,7 +1623,7 @@ static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
if (!state) if (!state)
return NULL_PTR_ERR; return NULL_PTR_ERR;
pulse->lock(); EnterCriticalSection(&session_cs);
if (list_empty(&This->session->clients)) { if (list_empty(&This->session->clients)) {
*state = AudioSessionStateExpired; *state = AudioSessionStateExpired;
goto out; goto out;
...@@ -1628,7 +1637,7 @@ static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface, ...@@ -1628,7 +1637,7 @@ static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface,
*state = AudioSessionStateInactive; *state = AudioSessionStateInactive;
out: out:
pulse->unlock(); LeaveCriticalSection(&session_cs);
return S_OK; return S_OK;
} }
...@@ -2004,11 +2013,11 @@ static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume( ...@@ -2004,11 +2013,11 @@ static HRESULT WINAPI SimpleAudioVolume_SetMasterVolume(
TRACE("PulseAudio does not support session volume control\n"); TRACE("PulseAudio does not support session volume control\n");
pulse->lock(); EnterCriticalSection(&session_cs);
session->master_vol = level; session->master_vol = level;
LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry) LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry)
set_stream_volumes(client); set_stream_volumes(client);
pulse->unlock(); LeaveCriticalSection(&session_cs);
return S_OK; return S_OK;
} }
...@@ -2041,11 +2050,11 @@ static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface, ...@@ -2041,11 +2050,11 @@ static HRESULT WINAPI SimpleAudioVolume_SetMute(ISimpleAudioVolume *iface,
if (context) if (context)
FIXME("Notifications not supported yet\n"); FIXME("Notifications not supported yet\n");
pulse->lock(); EnterCriticalSection(&session_cs);
session->mute = mute; session->mute = mute;
LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry) LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry)
set_stream_volumes(client); set_stream_volumes(client);
pulse->unlock(); LeaveCriticalSection(&session_cs);
return S_OK; return S_OK;
} }
...@@ -2148,11 +2157,11 @@ static HRESULT WINAPI ChannelAudioVolume_SetChannelVolume( ...@@ -2148,11 +2157,11 @@ static HRESULT WINAPI ChannelAudioVolume_SetChannelVolume(
TRACE("PulseAudio does not support session volume control\n"); TRACE("PulseAudio does not support session volume control\n");
pulse->lock(); EnterCriticalSection(&session_cs);
session->channel_vols[index] = level; session->channel_vols[index] = level;
LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry) LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry)
set_stream_volumes(client); set_stream_volumes(client);
pulse->unlock(); LeaveCriticalSection(&session_cs);
return S_OK; return S_OK;
} }
...@@ -2199,12 +2208,12 @@ static HRESULT WINAPI ChannelAudioVolume_SetAllVolumes( ...@@ -2199,12 +2208,12 @@ static HRESULT WINAPI ChannelAudioVolume_SetAllVolumes(
TRACE("PulseAudio does not support session volume control\n"); TRACE("PulseAudio does not support session volume control\n");
pulse->lock(); EnterCriticalSection(&session_cs);
for(i = 0; i < count; ++i) for(i = 0; i < count; ++i)
session->channel_vols[i] = levels[i]; session->channel_vols[i] = levels[i];
LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry) LIST_FOR_EACH_ENTRY(client, &This->session->clients, ACImpl, entry)
set_stream_volumes(client); set_stream_volumes(client);
pulse->unlock(); LeaveCriticalSection(&session_cs);
return S_OK; return S_OK;
} }
......
...@@ -99,12 +99,12 @@ static pthread_cond_t pulse_cond = PTHREAD_COND_INITIALIZER; ...@@ -99,12 +99,12 @@ static pthread_cond_t pulse_cond = PTHREAD_COND_INITIALIZER;
UINT8 mult_alaw_sample(UINT8, float); UINT8 mult_alaw_sample(UINT8, float);
UINT8 mult_ulaw_sample(UINT8, float); UINT8 mult_ulaw_sample(UINT8, float);
static void WINAPI pulse_lock(void) static void pulse_lock(void)
{ {
pthread_mutex_lock(&pulse_mutex); pthread_mutex_lock(&pulse_mutex);
} }
static void WINAPI pulse_unlock(void) static void pulse_unlock(void)
{ {
pthread_mutex_unlock(&pulse_mutex); pthread_mutex_unlock(&pulse_mutex);
} }
...@@ -178,13 +178,13 @@ static int pulse_poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, ...@@ -178,13 +178,13 @@ static int pulse_poll_func(struct pollfd *ufds, unsigned long nfds, int timeout,
static void WINAPI pulse_main_loop(HANDLE event) static void WINAPI pulse_main_loop(HANDLE event)
{ {
int ret; int ret;
pulse_lock();
pulse_ml = pa_mainloop_new(); pulse_ml = pa_mainloop_new();
pa_mainloop_set_poll_func(pulse_ml, pulse_poll_func, NULL); pa_mainloop_set_poll_func(pulse_ml, pulse_poll_func, NULL);
NtSetEvent(event, NULL); NtSetEvent(event, NULL);
pulse_lock();
pa_mainloop_run(pulse_ml, &ret); pa_mainloop_run(pulse_ml, &ret);
pulse_unlock();
pa_mainloop_free(pulse_ml); pa_mainloop_free(pulse_ml);
pulse_unlock();
} }
static void pulse_contextcallback(pa_context *c, void *userdata) static void pulse_contextcallback(pa_context *c, void *userdata)
...@@ -799,11 +799,19 @@ static HRESULT WINAPI pulse_create_stream(const char *name, EDataFlow dataflow, ...@@ -799,11 +799,19 @@ static HRESULT WINAPI pulse_create_stream(const char *name, EDataFlow dataflow,
unsigned int i, bufsize_bytes; unsigned int i, bufsize_bytes;
HRESULT hr; HRESULT hr;
pulse_lock();
if (FAILED(hr = pulse_connect(name))) if (FAILED(hr = pulse_connect(name)))
{
pulse_unlock();
return hr; return hr;
}
if (!(stream = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*stream)))) if (!(stream = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*stream))))
{
pulse_unlock();
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
}
stream->dataflow = dataflow; stream->dataflow = dataflow;
for (i = 0; i < ARRAY_SIZE(stream->vol); ++i) for (i = 0; i < ARRAY_SIZE(stream->vol); ++i)
...@@ -867,6 +875,9 @@ static HRESULT WINAPI pulse_create_stream(const char *name, EDataFlow dataflow, ...@@ -867,6 +875,9 @@ static HRESULT WINAPI pulse_create_stream(const char *name, EDataFlow dataflow,
} }
} }
*channel_count = stream->ss.channels;
*ret = stream;
exit: exit:
if (FAILED(hr)) { if (FAILED(hr)) {
free(stream->local_buffer); free(stream->local_buffer);
...@@ -875,12 +886,10 @@ exit: ...@@ -875,12 +886,10 @@ exit:
pa_stream_unref(stream->stream); pa_stream_unref(stream->stream);
RtlFreeHeap(GetProcessHeap(), 0, stream); RtlFreeHeap(GetProcessHeap(), 0, stream);
} }
return hr;
} }
*channel_count = stream->ss.channels; pulse_unlock();
*ret = stream; return hr;
return S_OK;
} }
static void WINAPI pulse_release_stream(struct pulse_stream *stream, HANDLE timer) static void WINAPI pulse_release_stream(struct pulse_stream *stream, HANDLE timer)
...@@ -1802,13 +1811,15 @@ static HRESULT WINAPI pulse_set_event_handle(struct pulse_stream *stream, HANDLE ...@@ -1802,13 +1811,15 @@ static HRESULT WINAPI pulse_set_event_handle(struct pulse_stream *stream, HANDLE
static BOOL WINAPI pulse_is_started(struct pulse_stream *stream) static BOOL WINAPI pulse_is_started(struct pulse_stream *stream)
{ {
return pulse_stream_valid(stream) && stream->started; BOOL ret;
pulse_lock();
ret = pulse_stream_valid(stream) && stream->started;
pulse_unlock();
return ret;
} }
static const struct unix_funcs unix_funcs = static const struct unix_funcs unix_funcs =
{ {
pulse_lock,
pulse_unlock,
pulse_main_loop, pulse_main_loop,
pulse_create_stream, pulse_create_stream,
pulse_release_stream, pulse_release_stream,
......
...@@ -33,8 +33,6 @@ struct pulse_config ...@@ -33,8 +33,6 @@ struct pulse_config
struct unix_funcs struct unix_funcs
{ {
void (WINAPI *lock)(void);
void (WINAPI *unlock)(void);
void (WINAPI *main_loop)(HANDLE event); void (WINAPI *main_loop)(HANDLE event);
HRESULT (WINAPI *create_stream)(const char *name, EDataFlow dataflow, AUDCLNT_SHAREMODE mode, HRESULT (WINAPI *create_stream)(const char *name, EDataFlow dataflow, AUDCLNT_SHAREMODE mode,
DWORD flags, REFERENCE_TIME duration, REFERENCE_TIME period, DWORD flags, REFERENCE_TIME duration, REFERENCE_TIME period,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment