Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: media/audio/pulse/pulse_output.cc

Issue 1711823004: Let default device in PulseAudio be the system default device (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/audio/pulse/pulse_output.h" 5 #include "media/audio/pulse/pulse_output.h"
6 6
7 #include <pulse/pulseaudio.h> 7 #include <pulse/pulseaudio.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include "base/single_thread_task_runner.h" 10 #include "base/single_thread_task_runner.h"
11 #include "media/audio/audio_manager_base.h" 11 #include "media/audio/audio_manager_base.h"
12 #include "media/audio/pulse/pulse_util.h" 12 #include "media/audio/pulse/pulse_util.h"
13 13
14 namespace media { 14 namespace media {
15 15
16 using pulse::AutoPulseLock; 16 using pulse::AutoPulseLock;
17 using pulse::WaitForOperationCompletion; 17 using pulse::WaitForOperationCompletion;
18 18
19 // Helper macro to avoid code spam and string bloat.
20 #define RETURN_ON_FAILURE(expression, message) \
tommi (sloooow) - chröme 2016/03/16 15:21:47 we try to avoid macros as much as we can. Even wh
rchtara 2016/03/19 12:07:29 Done.
Henrik Grunell 2016/03/21 09:44:18 As background, the macro came along with the code
rchtara 2016/03/22 16:45:48 Done.
21 do { \
22 if (!(expression)) { \
23 DLOG(ERROR) << message; \
24 return false; \
25 } \
26 } while (0)
27
19 // static, pa_stream_notify_cb 28 // static, pa_stream_notify_cb
20 void PulseAudioOutputStream::StreamNotifyCallback(pa_stream* s, void* p_this) { 29 void PulseAudioOutputStream::StreamNotifyCallback(pa_stream* s, void* p_this) {
21 PulseAudioOutputStream* stream = static_cast<PulseAudioOutputStream*>(p_this); 30 PulseAudioOutputStream* stream = static_cast<PulseAudioOutputStream*>(p_this);
22 31
23 // Forward unexpected failures to the AudioSourceCallback if available. All 32 // Forward unexpected failures to the AudioSourceCallback if available. All
24 // these variables are only modified under pa_threaded_mainloop_lock() so this 33 // these variables are only modified under pa_threaded_mainloop_lock() so this
25 // should be thread safe. 34 // should be thread safe.
26 if (s && stream->source_callback_ && 35 if (s && stream->source_callback_ &&
27 pa_stream_get_state(s) == PA_STREAM_FAILED) { 36 pa_stream_get_state(s) == PA_STREAM_FAILED) {
28 stream->source_callback_->OnError(stream); 37 stream->source_callback_->OnError(stream);
(...skipping 25 matching lines...) Expand all
54 } 63 }
55 64
56 PulseAudioOutputStream::~PulseAudioOutputStream() { 65 PulseAudioOutputStream::~PulseAudioOutputStream() {
57 // All internal structures should already have been freed in Close(), which 66 // All internal structures should already have been freed in Close(), which
58 // calls AudioManagerBase::ReleaseOutputStream() which deletes this object. 67 // calls AudioManagerBase::ReleaseOutputStream() which deletes this object.
59 DCHECK(!pa_stream_); 68 DCHECK(!pa_stream_);
60 DCHECK(!pa_context_); 69 DCHECK(!pa_context_);
61 DCHECK(!pa_mainloop_); 70 DCHECK(!pa_mainloop_);
62 } 71 }
63 72
73 // static, used by pa_context_get_server_info.
74 void PulseAudioOutputStream::UseSystemDefaultOutputDeviceCallback(
75 pa_context* context,
76 const pa_server_info* info,
77 void* user_data) {
78 PulseAudioOutputStream* stream =
79 reinterpret_cast<PulseAudioOutputStream*>(user_data);
80 stream->device_id_ = info->default_sink_name;
tommi (sloooow) - chröme 2016/03/16 15:21:47 if device_id_ was set to "default" will this perha
rchtara 2016/03/19 12:07:30 A new attribute of PulseAudioOutputStream called |
81 pa_threaded_mainloop* pa_mainloop =
82 static_cast<pa_threaded_mainloop*>(stream->pa_mainloop_);
83 pa_threaded_mainloop_signal(pa_mainloop, 0);
84 }
85
86 void PulseAudioOutputStream::UseSystemDefaultOutputDevice() {
87 DCHECK(pa_mainloop_);
88 DCHECK(pa_context_);
89 pa_operation* operation = pa_context_get_server_info(
90 pa_context_, PulseAudioOutputStream::UseSystemDefaultOutputDeviceCallback,
91 this);
92 WaitForOperationCompletion(pa_mainloop_, operation);
tommi (sloooow) - chröme 2016/03/16 15:21:47 are we on the audiomanager thread? If we can avoi
rchtara 2016/03/19 12:07:29 I'm not sure about that. I don't know how we could
tommi (sloooow) - chröme 2016/03/19 13:44:17 You can see it from where this function is called.
Henrik Grunell 2016/03/21 09:44:18 Add DCHECK here is good. We'd have to wait though
rchtara 2016/03/22 16:45:48 Done.
rchtara 2016/03/22 16:56:25 So, I created a timer to get the duration needed:
93 }
94
64 bool PulseAudioOutputStream::Open() { 95 bool PulseAudioOutputStream::Open() {
96 DCHECK(!pa_mainloop_);
Henrik Grunell 2016/03/07 11:37:17 Put the moved code in a new function, InitializeMa
rchtara 2016/03/08 17:28:16 Done.
97 DCHECK(!pa_context_);
98 std::string app_name = AudioManager::GetGlobalAppName();
99 pa_mainloop_ = pa_threaded_mainloop_new();
100 RETURN_ON_FAILURE(pa_mainloop_, "Failed to create PulseAudio main loop.");
101
102 pa_mainloop_api* pa_mainloop_api = pa_threaded_mainloop_get_api(pa_mainloop_);
103 pa_context_ = pa_context_new(
104 pa_mainloop_api, app_name.empty() ? "Chromium" : app_name.c_str());
105 RETURN_ON_FAILURE(pa_context_, "Failed to create PulseAudio context.");
106
107 // A state callback must be set before calling pa_threaded_mainloop_lock() or
108 // pa_threaded_mainloop_wait() calls may lead to dead lock.
109 pa_context_set_state_callback(pa_context_, &pulse::ContextStateCallback,
110 pa_mainloop_);
111
112 // Lock the main loop while setting up the context. Failure to do so may lead
113 // to crashes as the PulseAudio thread tries to run before things are ready.
114 AutoPulseLock auto_lock(pa_mainloop_);
Henrik Grunell 2016/03/07 11:37:17 Scope the code that should execute under this lock
rchtara 2016/03/08 17:28:16 Done.
115
116 RETURN_ON_FAILURE(pa_threaded_mainloop_start(pa_mainloop_) == 0,
117 "Failed to start PulseAudio main loop.");
118 RETURN_ON_FAILURE(
119 pa_context_connect(pa_context_, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) == 0,
120 "Failed to connect PulseAudio context.");
121
122 // Wait until |pa_context_| is ready. pa_threaded_mainloop_wait() must be
123 // called after pa_context_get_state() in case the context is already ready,
124 // otherwise pa_threaded_mainloop_wait() will hang indefinitely.
125 while (true) {
tommi (sloooow) - chröme 2016/03/16 15:21:47 same here
rchtara 2016/03/19 12:07:30 Not sure here too.
tommi (sloooow) - chröme 2016/03/19 13:44:17 See thread check below (which should be at the top
Henrik Grunell 2016/03/21 09:44:18 Tommi, did you perhaps not review the latest patch
rchtara 2016/03/22 16:45:48 Done.
126 pa_context_state_t context_state = pa_context_get_state(pa_context_);
127 RETURN_ON_FAILURE(PA_CONTEXT_IS_GOOD(context_state),
128 "Invalid PulseAudio context state.");
129 if (context_state == PA_CONTEXT_READY)
130 break;
131 pa_threaded_mainloop_wait(pa_mainloop_);
132 }
133
134 if (device_id_ == AudioManagerBase::kDefaultDeviceId) {
135 UseSystemDefaultOutputDevice();
136 }
65 DCHECK(thread_checker_.CalledOnValidThread()); 137 DCHECK(thread_checker_.CalledOnValidThread());
Henrik Grunell 2016/03/07 11:37:17 Put thread checker first in function.
rchtara 2016/03/08 17:28:16 Done.
66 return pulse::CreateOutputStream( 138 return pulse::CreateOutputStream(
67 &pa_mainloop_, &pa_context_, &pa_stream_, params_, device_id_, 139 &pa_mainloop_, &pa_context_, &pa_stream_, params_, device_id_, app_name,
68 AudioManager::GetGlobalAppName(), &StreamNotifyCallback, 140 &StreamNotifyCallback, &StreamRequestCallback, this);
69 &StreamRequestCallback, this);
70 } 141 }
71 142
72 void PulseAudioOutputStream::Reset() { 143 void PulseAudioOutputStream::Reset() {
73 if (!pa_mainloop_) { 144 if (!pa_mainloop_) {
74 DCHECK(!pa_stream_); 145 DCHECK(!pa_stream_);
75 DCHECK(!pa_context_); 146 DCHECK(!pa_context_);
76 return; 147 return;
77 } 148 }
78 149
79 { 150 {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 299
229 volume_ = static_cast<float>(volume); 300 volume_ = static_cast<float>(volume);
230 } 301 }
231 302
232 void PulseAudioOutputStream::GetVolume(double* volume) { 303 void PulseAudioOutputStream::GetVolume(double* volume) {
233 DCHECK(thread_checker_.CalledOnValidThread()); 304 DCHECK(thread_checker_.CalledOnValidThread());
234 305
235 *volume = volume_; 306 *volume = volume_;
236 } 307 }
237 308
309 #undef RETURN_ON_FAILURE
310
238 } // namespace media 311 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698