summaryrefslogtreecommitdiff
path: root/chromium/media/audio/pulse/pulse_util.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/audio/pulse/pulse_util.cc')
-rw-r--r--chromium/media/audio/pulse/pulse_util.cc64
1 files changed, 52 insertions, 12 deletions
diff --git a/chromium/media/audio/pulse/pulse_util.cc b/chromium/media/audio/pulse/pulse_util.cc
index a00769c220d..5044fa4d26e 100644
--- a/chromium/media/audio/pulse/pulse_util.cc
+++ b/chromium/media/audio/pulse/pulse_util.cc
@@ -170,7 +170,6 @@ bool CreateInputStream(pa_threaded_mainloop* mainloop,
void* user_data) {
DCHECK(mainloop);
DCHECK(context);
- DCHECK_NE(device_id, AudioManagerBase::kDefaultDeviceId);
// Set sample specifications.
pa_sample_spec sample_specifications;
@@ -212,8 +211,12 @@ bool CreateInputStream(pa_threaded_mainloop* mainloop,
PA_STREAM_ADJUST_LATENCY |
PA_STREAM_START_CORKED;
RETURN_ON_FAILURE(
- pa_stream_connect_record(*stream, device_id.c_str(), &buffer_attributes,
- static_cast<pa_stream_flags_t>(flags)) == 0,
+ pa_stream_connect_record(
+ *stream,
+ device_id == AudioManagerBase::kDefaultDeviceId ?
+ NULL : device_id.c_str(),
+ &buffer_attributes,
+ static_cast<pa_stream_flags_t>(flags)) == 0,
"pa_stream_connect_record FAILED ");
// Wait for the stream to be ready.
@@ -229,8 +232,8 @@ bool CreateInputStream(pa_threaded_mainloop* mainloop,
return true;
}
-bool CreateOutputStream(pa_threaded_mainloop* mainloop,
- pa_context* context,
+bool CreateOutputStream(pa_threaded_mainloop** mainloop,
+ pa_context** context,
pa_stream** stream,
const AudioParameters& params,
const std::string& device_id,
@@ -238,9 +241,42 @@ bool CreateOutputStream(pa_threaded_mainloop* mainloop,
pa_stream_notify_cb_t stream_callback,
pa_stream_request_cb_t write_callback,
void* user_data) {
- DCHECK(mainloop);
- DCHECK(context);
- DCHECK(device_id != AudioManagerBase::kDefaultDeviceId);
+ DCHECK(!*mainloop);
+ DCHECK(!*context);
+
+ *mainloop = pa_threaded_mainloop_new();
+ RETURN_ON_FAILURE(*mainloop, "Failed to create PulseAudio main loop.");
+
+ pa_mainloop_api* pa_mainloop_api = pa_threaded_mainloop_get_api(*mainloop);
+ *context = pa_context_new(pa_mainloop_api,
+ app_name.empty() ? "Chromium" : app_name.c_str());
+ RETURN_ON_FAILURE(*context, "Failed to create PulseAudio context.");
+
+ // A state callback must be set before calling pa_threaded_mainloop_lock() or
+ // pa_threaded_mainloop_wait() calls may lead to dead lock.
+ pa_context_set_state_callback(*context, &ContextStateCallback, *mainloop);
+
+ // Lock the main loop while setting up the context. Failure to do so may lead
+ // to crashes as the PulseAudio thread tries to run before things are ready.
+ AutoPulseLock auto_lock(*mainloop);
+
+ RETURN_ON_FAILURE(pa_threaded_mainloop_start(*mainloop) == 0,
+ "Failed to start PulseAudio main loop.");
+ RETURN_ON_FAILURE(
+ pa_context_connect(*context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) == 0,
+ "Failed to connect PulseAudio context.");
+
+ // Wait until |pa_context_| is ready. pa_threaded_mainloop_wait() must be
+ // called after pa_context_get_state() in case the context is already ready,
+ // otherwise pa_threaded_mainloop_wait() will hang indefinitely.
+ while (true) {
+ pa_context_state_t context_state = pa_context_get_state(*context);
+ RETURN_ON_FAILURE(
+ PA_CONTEXT_IS_GOOD(context_state), "Invalid PulseAudio context state.");
+ if (context_state == PA_CONTEXT_READY)
+ break;
+ pa_threaded_mainloop_wait(*mainloop);
+ }
// Set sample specifications.
pa_sample_spec sample_specifications;
@@ -265,7 +301,7 @@ bool CreateOutputStream(pa_threaded_mainloop* mainloop,
pa_proplist_sets(property_list.get(), PA_PROP_APPLICATION_ICON_NAME,
kBrowserDisplayName);
*stream = pa_stream_new_with_proplist(
- context, "Playback", &sample_specifications, map, property_list.get());
+ *context, "Playback", &sample_specifications, map, property_list.get());
RETURN_ON_FAILURE(*stream, "failed to create PA playback stream");
pa_stream_set_state_callback(*stream, stream_callback, user_data);
@@ -296,12 +332,16 @@ bool CreateOutputStream(pa_threaded_mainloop* mainloop,
// and error.
RETURN_ON_FAILURE(
pa_stream_connect_playback(
- *stream, device_id.c_str(), &pa_buffer_attributes,
+ *stream,
+ device_id == AudioManagerBase::kDefaultDeviceId ?
+ NULL : device_id.c_str(),
+ &pa_buffer_attributes,
static_cast<pa_stream_flags_t>(
PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY |
PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_NOT_MONOTONIC |
PA_STREAM_START_CORKED),
- NULL, NULL) == 0,
+ NULL,
+ NULL) == 0,
"pa_stream_connect_playback FAILED ");
// Wait for the stream to be ready.
@@ -311,7 +351,7 @@ bool CreateOutputStream(pa_threaded_mainloop* mainloop,
PA_STREAM_IS_GOOD(stream_state), "Invalid PulseAudio stream state");
if (stream_state == PA_STREAM_READY)
break;
- pa_threaded_mainloop_wait(mainloop);
+ pa_threaded_mainloop_wait(*mainloop);
}
return true;