aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/backends/pulseaudio.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2012-03-05 07:11:09 -0800
committerChris Robinson <[email protected]>2012-03-05 07:11:09 -0800
commitfe6e532c876bf3ec6776f76f9542038ac9c94d68 (patch)
tree31d29eb21462dbc02287030d8e3b6174dcab92cc /Alc/backends/pulseaudio.c
parent5cdeeb47f3b4dedefd1ceb2b32c2f7754abc058d (diff)
Use a separate backend callback to start playback of the device
This allows us to properly update the ALCdevice and its resources with the new parameters before starting playback, instead of expecting the mixer to block and wait after it has begun. This also lets us avoid holding the device lock while resetting and starting the device, which helps prevent lock inversion on some backends (ie, one thread locking A then B, and another thread locking B then A), ultimately allowing certain backends to asynchronously update the ALCdevice without risk of lockup. Capture still has issues here, however.
Diffstat (limited to 'Alc/backends/pulseaudio.c')
-rw-r--r--Alc/backends/pulseaudio.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c
index 8fe1118b..78854da7 100644
--- a/Alc/backends/pulseaudio.c
+++ b/Alc/backends/pulseaudio.c
@@ -873,6 +873,10 @@ static void pulse_close(ALCdevice *device)
if(data->stream)
{
+#if PA_CHECK_VERSION(0,9,15)
+ if(pa_stream_set_buffer_attr_callback)
+ pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL);
+#endif
pa_stream_disconnect(data->stream);
pa_stream_unref(data->stream);
}
@@ -968,6 +972,10 @@ static ALCboolean pulse_reset_playback(ALCdevice *device)
if(data->stream)
{
+#if PA_CHECK_VERSION(0,9,15)
+ if(pa_stream_set_buffer_attr_callback)
+ pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL);
+#endif
pa_stream_disconnect(data->stream);
pa_stream_unref(data->stream);
data->stream = NULL;
@@ -1079,28 +1087,25 @@ static ALCboolean pulse_reset_playback(ALCdevice *device)
device->NumUpdates = maxu(device->NumUpdates, 2);
device->UpdateSize = data->attr.minreq / pa_frame_size(&data->spec);
+ pa_threaded_mainloop_unlock(data->loop);
+ return ALC_TRUE;
+}
+
+static ALCboolean pulse_start_playback(ALCdevice *device)
+{
+ pulse_data *data = device->ExtraData;
+
data->thread = StartThread(PulseProc, device);
if(!data->thread)
- {
-#if PA_CHECK_VERSION(0,9,15)
- if(pa_stream_set_buffer_attr_callback)
- pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL);
-#endif
- pa_stream_disconnect(data->stream);
- pa_stream_unref(data->stream);
- data->stream = NULL;
-
- pa_threaded_mainloop_unlock(data->loop);
return ALC_FALSE;
- }
- pa_threaded_mainloop_unlock(data->loop);
return ALC_TRUE;
}
static void pulse_stop_playback(ALCdevice *device)
{
pulse_data *data = device->ExtraData;
+ pa_operation *o;
if(!data->stream)
return;
@@ -1115,13 +1120,10 @@ static void pulse_stop_playback(ALCdevice *device)
pa_threaded_mainloop_lock(data->loop);
-#if PA_CHECK_VERSION(0,9,15)
- if(pa_stream_set_buffer_attr_callback)
- pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL);
-#endif
- pa_stream_disconnect(data->stream);
- pa_stream_unref(data->stream);
- data->stream = NULL;
+ o = pa_stream_cork(data->stream, 1, stream_success_callback, device);
+ while(pa_operation_get_state(o) == PA_OPERATION_RUNNING)
+ pa_threaded_mainloop_wait(data->loop);
+ pa_operation_unref(o);
pa_threaded_mainloop_unlock(data->loop);
}
@@ -1352,6 +1354,7 @@ static const BackendFuncs pulse_funcs = {
pulse_open_playback,
pulse_close_playback,
pulse_reset_playback,
+ pulse_start_playback,
pulse_stop_playback,
pulse_open_capture,
pulse_close_capture,