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

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

Issue 1998173002: Use "application default" audio device as default PulseAudio device. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2704
Patch Set: Created 4 years, 7 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
« no previous file with comments | « media/audio/pulse/pulse_output.h ('k') | media/audio/pulse/pulse_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 } 54 }
55 55
56 PulseAudioOutputStream::~PulseAudioOutputStream() { 56 PulseAudioOutputStream::~PulseAudioOutputStream() {
57 // All internal structures should already have been freed in Close(), which 57 // All internal structures should already have been freed in Close(), which
58 // calls AudioManagerBase::ReleaseOutputStream() which deletes this object. 58 // calls AudioManagerBase::ReleaseOutputStream() which deletes this object.
59 DCHECK(!pa_stream_); 59 DCHECK(!pa_stream_);
60 DCHECK(!pa_context_); 60 DCHECK(!pa_context_);
61 DCHECK(!pa_mainloop_); 61 DCHECK(!pa_mainloop_);
62 } 62 }
63 63
64 bool PulseAudioOutputStream::InitializeMainloopAndContext() {
65 DCHECK(!pa_mainloop_);
66 DCHECK(!pa_context_);
67 DCHECK(thread_checker_.CalledOnValidThread());
68 pa_mainloop_ = pa_threaded_mainloop_new();
69 if (!pa_mainloop_) {
70 DLOG(ERROR) << "Failed to create PulseAudio main loop.";
71 return false;
72 }
73
74 pa_mainloop_api* pa_mainloop_api = pa_threaded_mainloop_get_api(pa_mainloop_);
75 std::string app_name = AudioManager::GetGlobalAppName();
76 pa_context_ = pa_context_new(
77 pa_mainloop_api, app_name.empty() ? "Chromium" : app_name.c_str());
78 if (!pa_context_) {
79 DLOG(ERROR) << "Failed to create PulseAudio context.";
80 return false;
81 }
82
83 // A state callback must be set before calling pa_threaded_mainloop_lock() or
84 // pa_threaded_mainloop_wait() calls may lead to dead lock.
85 pa_context_set_state_callback(pa_context_, &pulse::ContextStateCallback,
86 pa_mainloop_);
87 {
88 // Lock the main loop while setting up the context. Failure to do so may
89 // lead to crashes as the PulseAudio thread tries to run before things are
90 // ready.
91 AutoPulseLock auto_lock(pa_mainloop_);
92
93 if (pa_threaded_mainloop_start(pa_mainloop_) != 0) {
94 DLOG(ERROR) << "Failed to start PulseAudio main loop.";
95 return false;
96 }
97
98 if (pa_context_connect(pa_context_, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) !=
99 0) {
100 DLOG(ERROR) << "Failed to connect PulseAudio context.";
101 return false;
102 }
103
104 // Wait until |pa_context_| is ready. pa_threaded_mainloop_wait() must be
105 // called after pa_context_get_state() in case the context is already ready,
106 // otherwise pa_threaded_mainloop_wait() will hang indefinitely.
107 while (true) {
108 pa_context_state_t context_state = pa_context_get_state(pa_context_);
109 if (!PA_CONTEXT_IS_GOOD(context_state)) {
110 DLOG(ERROR) << "Invalid PulseAudio context state.";
111 return false;
112 }
113
114 if (context_state == PA_CONTEXT_READY)
115 break;
116 pa_threaded_mainloop_wait(pa_mainloop_);
117 }
118 }
119
120 return true;
121 }
122
123 // static, used by pa_context_get_server_info.
124 void PulseAudioOutputStream::GetSystemDefaultOutputDeviceCallback(
125 pa_context* context,
126 const pa_server_info* info,
127 void* user_data) {
128 media::PulseAudioOutputStream* stream =
129 static_cast<media::PulseAudioOutputStream*>(user_data);
130 stream->default_system_device_name_ = info->default_sink_name;
131 pa_threaded_mainloop_signal(stream->pa_mainloop_, 0);
132 }
133
134 void PulseAudioOutputStream::GetSystemDefaultOutputDevice() {
135 DCHECK(thread_checker_.CalledOnValidThread());
136 DCHECK(pa_mainloop_);
137 DCHECK(pa_context_);
138 pa_operation* operation = pa_context_get_server_info(
139 pa_context_, PulseAudioOutputStream::GetSystemDefaultOutputDeviceCallback,
140 this);
141 WaitForOperationCompletion(pa_mainloop_, operation);
142 }
143
144 bool PulseAudioOutputStream::Open() { 64 bool PulseAudioOutputStream::Open() {
145 DCHECK(thread_checker_.CalledOnValidThread()); 65 DCHECK(thread_checker_.CalledOnValidThread());
146 if (!InitializeMainloopAndContext()) {
147 return false;
148 }
149
150 AutoPulseLock auto_lock(pa_mainloop_);
151
152 std::string device_name_to_use = device_id_;
153 if (device_id_ == AudioManagerBase::kDefaultDeviceId) {
154 GetSystemDefaultOutputDevice();
155 device_name_to_use = default_system_device_name_;
156 }
157
158 return pulse::CreateOutputStream( 66 return pulse::CreateOutputStream(
159 pa_mainloop_, pa_context_, &pa_stream_, params_, device_name_to_use, 67 &pa_mainloop_, &pa_context_, &pa_stream_, params_, device_id_,
160 AudioManager::GetGlobalAppName(), &StreamNotifyCallback, 68 AudioManager::GetGlobalAppName(), &StreamNotifyCallback,
161 &StreamRequestCallback, this); 69 &StreamRequestCallback, this);
162 } 70 }
163 71
164 void PulseAudioOutputStream::Reset() { 72 void PulseAudioOutputStream::Reset() {
165 if (!pa_mainloop_) { 73 if (!pa_mainloop_) {
166 DCHECK(!pa_stream_); 74 DCHECK(!pa_stream_);
167 DCHECK(!pa_context_); 75 DCHECK(!pa_context_);
168 return; 76 return;
169 } 77 }
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 volume_ = static_cast<float>(volume); 229 volume_ = static_cast<float>(volume);
322 } 230 }
323 231
324 void PulseAudioOutputStream::GetVolume(double* volume) { 232 void PulseAudioOutputStream::GetVolume(double* volume) {
325 DCHECK(thread_checker_.CalledOnValidThread()); 233 DCHECK(thread_checker_.CalledOnValidThread());
326 234
327 *volume = volume_; 235 *volume = volume_;
328 } 236 }
329 237
330 } // namespace media 238 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/pulse/pulse_output.h ('k') | media/audio/pulse/pulse_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698