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

Side by Side Diff: chrome/browser/chromeos/audio_mixer_pulse.cc

Issue 5859003: Add ALSA support to volume keys (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/chrome/browser/chromeos
Patch Set: cleanups Created 10 years 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "chrome/browser/chromeos/pulse_audio_mixer.h" 5 #include "chrome/browser/chromeos/audio_mixer_pulse.h"
6 6
7 #include <pulse/pulseaudio.h> 7 #include <pulse/pulseaudio.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/task.h" 10 #include "base/task.h"
11 11
12 namespace chromeos { 12 namespace chromeos {
13 13
14 // Using asynchronous versions of the threaded PulseAudio API, as well 14 // Using asynchronous versions of the threaded PulseAudio API, as well
15 // as a worker thread so gets, sets, and the init sequence do not block the 15 // as a worker thread so gets, sets, and the init sequence do not block the
16 // calling thread. GetVolume() and IsMute() can still be called synchronously 16 // calling thread. GetVolume() and IsMute() can still be called synchronously
17 // if needed, but take a bit longer (~2ms vs ~0.3ms). 17 // if needed, but take a bit longer (~2ms vs ~0.3ms).
18 // 18 //
19 // Set calls just return without waiting. If you must guarantee the value has 19 // Set calls just return without waiting. If you must guarantee the value has
20 // been set before continuing, immediately call the blocking Get version to 20 // been set before continuing, immediately call the blocking Get version to
21 // synchronously get the value back. 21 // synchronously get the value back.
22 // 22 //
23 // TODO(davej): Serialize volume/mute to preserve settings when restarting? 23 // TODO(davej): Serialize volume/mute to preserve settings when restarting?
24 24
25 namespace { 25 namespace {
26 26
27 const int kInvalidDeviceId = -1; 27 const int kInvalidDeviceId = -1;
28 28
29 const double kMinVolumeDb = -90.0;
30 // Choosing 6.0dB here instead of 0dB to give user chance to amplify audio some
31 // in case sounds or their setup is too quiet for them.
32 const double kMaxVolumeDb = 6.0;
33
29 // Used for passing custom data to the PulseAudio callbacks. 34 // Used for passing custom data to the PulseAudio callbacks.
30 struct CallbackWrapper { 35 struct CallbackWrapper {
31 PulseAudioMixer* instance; 36 AudioMixerPulse* instance;
32 bool done; 37 bool done;
33 void* userdata; 38 void* userdata;
34 }; 39 };
35 40
36 } // namespace 41 } // namespace
37 42
38 // AudioInfo contains all the values we care about when getting info for a 43 // AudioInfo contains all the values we care about when getting info for a
39 // Sink (output device) used by GetAudioInfo(). 44 // Sink (output device) used by GetAudioInfo().
40 struct PulseAudioMixer::AudioInfo { 45 struct AudioMixerPulse::AudioInfo {
41 pa_cvolume cvolume; 46 pa_cvolume cvolume;
42 bool muted; 47 bool muted;
43 }; 48 };
44 49
45 PulseAudioMixer::PulseAudioMixer() 50 AudioMixerPulse::AudioMixerPulse()
46 : device_id_(kInvalidDeviceId), 51 : device_id_(kInvalidDeviceId),
47 last_channels_(0), 52 last_channels_(0),
48 mainloop_lock_count_(0), 53 mainloop_lock_count_(0),
49 mixer_state_lock_(), 54 mixer_state_lock_(),
50 mixer_state_(UNINITIALIZED), 55 mixer_state_(UNINITIALIZED),
51 pa_context_(NULL), 56 pa_context_(NULL),
52 pa_mainloop_(NULL), 57 pa_mainloop_(NULL),
53 thread_(NULL) { 58 thread_(NULL) {
54 } 59 }
55 60
56 PulseAudioMixer::~PulseAudioMixer() { 61 AudioMixerPulse::~AudioMixerPulse() {
57 PulseAudioFree(); 62 PulseAudioFree();
58 thread_->Stop(); 63 if (thread_ != NULL) {
59 thread_.reset(); 64 thread_->Stop();
65 thread_.reset();
66 }
60 } 67 }
61 68
62 bool PulseAudioMixer::Init(InitDoneCallback* callback) { 69 bool AudioMixerPulse::Init(InitDoneCallback* callback) {
63 if (!InitThread()) 70 if (!InitThread())
64 return false; 71 return false;
65 72
66 // Post the task of starting up, which can block for 200-500ms, 73 // Post the task of starting up, which can block for 200-500ms,
67 // so best not to do it on the caller's thread. 74 // so best not to do it on the caller's thread.
68 thread_->message_loop()->PostTask(FROM_HERE, 75 thread_->message_loop()->PostTask(FROM_HERE,
69 NewRunnableMethod(this, &PulseAudioMixer::DoInit, callback)); 76 NewRunnableMethod(this, &AudioMixerPulse::DoInit, callback));
scherkus (not reviewing) 2010/12/22 22:31:58 nit: indent by two extra spaces
70 return true; 77 return true;
71 } 78 }
72 79
73 bool PulseAudioMixer::InitSync() { 80 bool AudioMixerPulse::InitSync() {
74 if (!InitThread()) 81 if (!InitThread())
75 return false; 82 return false;
76 return PulseAudioInit(); 83 return PulseAudioInit();
77 } 84 }
78 85
79 double PulseAudioMixer::GetVolumeDb() const { 86 double AudioMixerPulse::GetVolumeDb() const {
80 if (!MainloopLockIfReady()) 87 if (!MainloopLockIfReady())
81 return pa_sw_volume_to_dB(0); // this returns -inf. 88 return kSilenceDb;
82 AudioInfo data; 89 AudioInfo data;
83 GetAudioInfo(&data); 90 GetAudioInfo(&data);
84 MainloopUnlock(); 91 MainloopUnlock();
85 return pa_sw_volume_to_dB(data.cvolume.values[0]); 92 return pa_sw_volume_to_dB(data.cvolume.values[0]);
86 } 93 }
87 94
88 bool PulseAudioMixer::GetVolumeDbAsync(GetVolumeCallback* callback, 95 void AudioMixerPulse::GetVolumeLimits(double* vol_min, double* vol_max) {
89 void* user) { 96 if (vol_min)
90 if (CheckState() != READY) 97 *vol_min = kMinVolumeDb;
91 return false; 98 if (vol_max)
92 thread_->message_loop()->PostTask(FROM_HERE, 99 *vol_max = kMaxVolumeDb;
93 NewRunnableMethod(this,
94 &PulseAudioMixer::DoGetVolume,
95 callback, user));
96 return true;
97 } 100 }
98 101
99 void PulseAudioMixer::SetVolumeDb(double vol_db) { 102 void AudioMixerPulse::SetVolumeDb(double vol_db) {
100 if (!MainloopLockIfReady()) 103 if (!MainloopLockIfReady())
101 return; 104 return;
102 105
103 // last_channels_ determines the number of channels on the main output device, 106 // last_channels_ determines the number of channels on the main output device,
104 // and is used later to set the volume on all channels at once. 107 // and is used later to set the volume on all channels at once.
105 if (!last_channels_) { 108 if (!last_channels_) {
106 AudioInfo data; 109 AudioInfo data;
107 GetAudioInfo(&data); 110 GetAudioInfo(&data);
108 last_channels_ = data.cvolume.channels; 111 last_channels_ = data.cvolume.channels;
109 } 112 }
110 113
111 pa_operation* pa_op; 114 pa_operation* pa_op;
112 pa_cvolume cvolume; 115 pa_cvolume cvolume;
113 pa_cvolume_set(&cvolume, last_channels_, pa_sw_volume_from_dB(vol_db)); 116 pa_cvolume_set(&cvolume, last_channels_, pa_sw_volume_from_dB(vol_db));
114 pa_op = pa_context_set_sink_volume_by_index(pa_context_, device_id_, 117 pa_op = pa_context_set_sink_volume_by_index(pa_context_, device_id_,
115 &cvolume, NULL, NULL); 118 &cvolume, NULL, NULL);
116 pa_operation_unref(pa_op); 119 pa_operation_unref(pa_op);
117 MainloopUnlock(); 120 MainloopUnlock();
121 VLOG(1) << "Set volume to " << vol_db << " dB";
118 } 122 }
119 123
120 bool PulseAudioMixer::IsMute() const { 124 bool AudioMixerPulse::IsMute() const {
121 if (!MainloopLockIfReady()) 125 if (!MainloopLockIfReady())
122 return false; 126 return false;
123 AudioInfo data; 127 AudioInfo data;
124 GetAudioInfo(&data); 128 GetAudioInfo(&data);
125 MainloopUnlock(); 129 MainloopUnlock();
126 return data.muted; 130 return data.muted;
127 } 131 }
128 132
129 void PulseAudioMixer::SetMute(bool mute) { 133 void AudioMixerPulse::SetMute(bool mute) {
130 if (!MainloopLockIfReady()) 134 if (!MainloopLockIfReady())
131 return; 135 return;
132 pa_operation* pa_op; 136 pa_operation* pa_op;
133 pa_op = pa_context_set_sink_mute_by_index(pa_context_, device_id_, 137 pa_op = pa_context_set_sink_mute_by_index(pa_context_, device_id_,
134 mute ? 1 : 0, NULL, NULL); 138 mute ? 1 : 0, NULL, NULL);
135 pa_operation_unref(pa_op); 139 pa_operation_unref(pa_op);
136 MainloopUnlock(); 140 MainloopUnlock();
141 VLOG(1) << "Set mute to " << mute;
137 } 142 }
138 143
139 PulseAudioMixer::State PulseAudioMixer::CheckState() const { 144 AudioMixerBase::State AudioMixerPulse::CheckState() const {
140 AutoLock lock(mixer_state_lock_); 145 AutoLock lock(mixer_state_lock_);
141 // If we think it's ready, verify it is actually so. 146 // If we think it's ready, verify it is actually so.
142 if ((mixer_state_ == READY) && 147 if ((mixer_state_ == READY) &&
143 (pa_context_get_state(pa_context_) != PA_CONTEXT_READY)) 148 (pa_context_get_state(pa_context_) != PA_CONTEXT_READY))
144 mixer_state_ = IN_ERROR; 149 mixer_state_ = IN_ERROR;
145 return mixer_state_; 150 return mixer_state_;
146 } 151 }
147 152
148 //////////////////////////////////////////////////////////////////////////////// 153 ////////////////////////////////////////////////////////////////////////////////
149 // Private functions follow 154 // Private functions follow
150 155
151 void PulseAudioMixer::DoInit(InitDoneCallback* callback) { 156 void AudioMixerPulse::DoInit(InitDoneCallback* callback) {
152 bool success = PulseAudioInit(); 157 bool success = PulseAudioInit();
153 callback->Run(success); 158 callback->Run(success);
154 delete callback; 159 delete callback;
155 } 160 }
156 161
157 void PulseAudioMixer::DoGetVolume(GetVolumeCallback* callback, 162 bool AudioMixerPulse::InitThread() {
158 void* user) {
159 callback->Run(GetVolumeDb(), user);
160 delete callback;
161 }
162
163 bool PulseAudioMixer::InitThread() {
164 AutoLock lock(mixer_state_lock_); 163 AutoLock lock(mixer_state_lock_);
165 164
166 if (mixer_state_ != UNINITIALIZED) 165 if (mixer_state_ != UNINITIALIZED)
167 return false; 166 return false;
167
168 if (thread_ == NULL) { 168 if (thread_ == NULL) {
169 thread_.reset(new base::Thread("PulseAudioMixer")); 169 thread_.reset(new base::Thread("AudioMixerPulse"));
170 if (!thread_->Start()) { 170 if (!thread_->Start()) {
171 thread_.reset(); 171 thread_.reset();
172 return false; 172 return false;
173 } 173 }
174 } 174 }
175 mixer_state_ = INITIALIZING; 175 mixer_state_ = INITIALIZING;
176 return true; 176 return true;
177 } 177 }
178 178
179 // static 179 // static
180 void PulseAudioMixer::ConnectToPulseCallbackThunk( 180 void AudioMixerPulse::ConnectToPulseCallbackThunk(
181 pa_context* context, void* userdata) { 181 pa_context* context, void* userdata) {
182 CallbackWrapper* data = 182 CallbackWrapper* data =
183 static_cast<CallbackWrapper*>(userdata); 183 static_cast<CallbackWrapper*>(userdata);
184 data->instance->OnConnectToPulseCallback(context, &data->done); 184 data->instance->OnConnectToPulseCallback(context, &data->done);
185 } 185 }
186 186
187 void PulseAudioMixer::OnConnectToPulseCallback( 187 void AudioMixerPulse::OnConnectToPulseCallback(
188 pa_context* context, bool* connect_done) { 188 pa_context* context, bool* connect_done) {
189 pa_context_state_t state = pa_context_get_state(context); 189 pa_context_state_t state = pa_context_get_state(context);
190 if (state == PA_CONTEXT_READY || 190 if (state == PA_CONTEXT_READY ||
191 state == PA_CONTEXT_FAILED || 191 state == PA_CONTEXT_FAILED ||
192 state == PA_CONTEXT_TERMINATED) { 192 state == PA_CONTEXT_TERMINATED) {
193 // Connection process has reached a terminal state. Wake PulseAudioInit(). 193 // Connection process has reached a terminal state. Wake PulseAudioInit().
194 *connect_done = true; 194 *connect_done = true;
195 MainloopSignal(); 195 MainloopSignal();
196 } 196 }
197 } 197 }
198 198
199 bool PulseAudioMixer::PulseAudioInit() { 199 bool AudioMixerPulse::PulseAudioInit() {
200 pa_context_state_t state = PA_CONTEXT_FAILED; 200 pa_context_state_t state = PA_CONTEXT_FAILED;
201 201
202 { 202 {
203 AutoLock lock(mixer_state_lock_); 203 AutoLock lock(mixer_state_lock_);
204 if (mixer_state_ != INITIALIZING) 204 if (mixer_state_ != INITIALIZING)
205 return false; 205 return false;
206 206
207 pa_mainloop_ = pa_threaded_mainloop_new(); 207 pa_mainloop_ = pa_threaded_mainloop_new();
208 if (!pa_mainloop_) { 208 if (!pa_mainloop_) {
209 LOG(ERROR) << "Can't create PulseAudio mainloop"; 209 LOG(ERROR) << "Can't create PulseAudio mainloop";
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 } 291 }
292 292
293 return true; 293 return true;
294 } 294 }
295 295
296 // Failed startup sequence, clean up now. 296 // Failed startup sequence, clean up now.
297 PulseAudioFree(); 297 PulseAudioFree();
298 return false; 298 return false;
299 } 299 }
300 300
301 void PulseAudioMixer::PulseAudioFree() { 301 void AudioMixerPulse::PulseAudioFree() {
302 { 302 {
303 AutoLock lock(mixer_state_lock_); 303 AutoLock lock(mixer_state_lock_);
304 if (!pa_mainloop_) 304 if (!pa_mainloop_)
305 mixer_state_ = UNINITIALIZED; 305 mixer_state_ = UNINITIALIZED;
306 if ((mixer_state_ == UNINITIALIZED) || (mixer_state_ == SHUTTING_DOWN)) 306 if ((mixer_state_ == UNINITIALIZED) || (mixer_state_ == SHUTTING_DOWN))
307 return; 307 return;
308
308 // If still initializing on another thread, this will cause it to exit. 309 // If still initializing on another thread, this will cause it to exit.
309 mixer_state_ = SHUTTING_DOWN; 310 mixer_state_ = SHUTTING_DOWN;
310 } 311 }
311 312
312 DCHECK(pa_mainloop_); 313 DCHECK(pa_mainloop_);
313 314
314 MainloopLock(); 315 MainloopLock();
315 if (pa_context_) { 316 if (pa_context_) {
316 pa_context_disconnect(pa_context_); 317 pa_context_disconnect(pa_context_);
317 pa_context_unref(pa_context_); 318 pa_context_unref(pa_context_);
318 pa_context_ = NULL; 319 pa_context_ = NULL;
319 } 320 }
320 MainloopUnlock(); 321 MainloopUnlock();
321 322
322 pa_threaded_mainloop_stop(pa_mainloop_); 323 pa_threaded_mainloop_stop(pa_mainloop_);
323 pa_threaded_mainloop_free(pa_mainloop_); 324 pa_threaded_mainloop_free(pa_mainloop_);
324 pa_mainloop_ = NULL; 325 pa_mainloop_ = NULL;
325 326
326 { 327 {
327 AutoLock lock(mixer_state_lock_); 328 AutoLock lock(mixer_state_lock_);
328 mixer_state_ = UNINITIALIZED; 329 mixer_state_ = UNINITIALIZED;
329 } 330 }
330 } 331 }
331 332
332 void PulseAudioMixer::CompleteOperation(pa_operation* pa_op, 333 void AudioMixerPulse::CompleteOperation(pa_operation* pa_op,
333 bool* done) const { 334 bool* done) const {
334 // After starting any operation, this helper checks if it started OK, then 335 // After starting any operation, this helper checks if it started OK, then
335 // waits for it to complete by iterating through the mainloop until the 336 // waits for it to complete by iterating through the mainloop until the
336 // operation is not running anymore. 337 // operation is not running anymore.
337 CHECK(pa_op); 338 CHECK(pa_op);
338 339
339 while (pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING) { 340 while (pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING) {
340 // If operation still running, but we got what we needed, cancel it now. 341 // If operation still running, but we got what we needed, cancel it now.
341 if (*done) { 342 if (*done) {
342 pa_operation_cancel(pa_op); 343 pa_operation_cancel(pa_op);
343 break; 344 break;
344 } 345 }
345 MainloopWait(); 346 MainloopWait();
346 } 347 }
347 pa_operation_unref(pa_op); 348 pa_operation_unref(pa_op);
348 } 349 }
349 350
350 // Must be called with mainloop lock held 351 // Must be called with mainloop lock held
351 void PulseAudioMixer::GetDefaultPlaybackDevice() { 352 void AudioMixerPulse::GetDefaultPlaybackDevice() {
352 DCHECK_GT(mainloop_lock_count_, 0); 353 DCHECK_GT(mainloop_lock_count_, 0);
353 DCHECK(pa_context_); 354 DCHECK(pa_context_);
354 DCHECK(pa_context_get_state(pa_context_) == PA_CONTEXT_READY); 355 DCHECK(pa_context_get_state(pa_context_) == PA_CONTEXT_READY);
355 356
356 CallbackWrapper data = {this, false, NULL}; 357 CallbackWrapper data = {this, false, NULL};
357 358
358 pa_operation* pa_op = pa_context_get_sink_info_list(pa_context_, 359 pa_operation* pa_op = pa_context_get_sink_info_list(pa_context_,
359 EnumerateDevicesCallback, 360 EnumerateDevicesCallback,
360 &data); 361 &data);
361 CompleteOperation(pa_op, &data.done); 362 CompleteOperation(pa_op, &data.done);
362 return; 363 return;
363 } 364 }
364 365
365 void PulseAudioMixer::OnEnumerateDevices(const pa_sink_info* sink_info, 366 void AudioMixerPulse::OnEnumerateDevices(const pa_sink_info* sink_info,
366 int eol, bool* done) { 367 int eol, bool* done) {
367 if (device_id_ != kInvalidDeviceId) 368 if (device_id_ != kInvalidDeviceId)
368 return; 369 return;
369 370
370 // TODO(davej): Should we handle cases of more than one output sink device? 371 // TODO(davej): Should we handle cases of more than one output sink device?
371 372
372 // eol is < 0 for error, > 0 for end of list, ==0 while listing. 373 // eol is < 0 for error, > 0 for end of list, ==0 while listing.
373 if (eol == 0) { 374 if (eol == 0) {
374 device_id_ = sink_info->index; 375 device_id_ = sink_info->index;
375 } 376 }
376 *done = true; 377 *done = true;
377 MainloopSignal(); 378 MainloopSignal();
378 } 379 }
379 380
380 // static 381 // static
381 void PulseAudioMixer::EnumerateDevicesCallback(pa_context* unused, 382 void AudioMixerPulse::EnumerateDevicesCallback(pa_context* unused,
382 const pa_sink_info* sink_info, 383 const pa_sink_info* sink_info,
383 int eol, 384 int eol,
384 void* userdata) { 385 void* userdata) {
385 CallbackWrapper* data = 386 CallbackWrapper* data =
386 static_cast<CallbackWrapper*>(userdata); 387 static_cast<CallbackWrapper*>(userdata);
387 data->instance->OnEnumerateDevices(sink_info, eol, &data->done); 388 data->instance->OnEnumerateDevices(sink_info, eol, &data->done);
388 } 389 }
389 390
390 // Must be called with lock held 391 // Must be called with lock held
391 void PulseAudioMixer::GetAudioInfo(AudioInfo* info) const { 392 void AudioMixerPulse::GetAudioInfo(AudioInfo* info) const {
392 DCHECK_GT(mainloop_lock_count_, 0); 393 DCHECK_GT(mainloop_lock_count_, 0);
393 CallbackWrapper data = {const_cast<PulseAudioMixer*>(this), false, info}; 394 CallbackWrapper data = {const_cast<AudioMixerPulse*>(this), false, info};
394 pa_operation* pa_op = pa_context_get_sink_info_by_index(pa_context_, 395 pa_operation* pa_op = pa_context_get_sink_info_by_index(pa_context_,
395 device_id_, 396 device_id_,
396 GetAudioInfoCallback, 397 GetAudioInfoCallback,
397 &data); 398 &data);
398 CompleteOperation(pa_op, &data.done); 399 CompleteOperation(pa_op, &data.done);
399 } 400 }
400 401
401 // static 402 // static
402 void PulseAudioMixer::GetAudioInfoCallback(pa_context* unused, 403 void AudioMixerPulse::GetAudioInfoCallback(pa_context* unused,
403 const pa_sink_info* sink_info, 404 const pa_sink_info* sink_info,
404 int eol, 405 int eol,
405 void* userdata) { 406 void* userdata) {
406 CallbackWrapper* data = static_cast<CallbackWrapper*>(userdata); 407 CallbackWrapper* data = static_cast<CallbackWrapper*>(userdata);
407 AudioInfo* info = static_cast<AudioInfo*>(data->userdata); 408 AudioInfo* info = static_cast<AudioInfo*>(data->userdata);
408 409
409 // Copy just the information we care about. 410 // Copy just the information we care about.
410 if (eol == 0) { 411 if (eol == 0) {
411 info->cvolume = sink_info->volume; 412 info->cvolume = sink_info->volume;
412 info->muted = sink_info->mute ? true : false; 413 info->muted = sink_info->mute ? true : false;
413 data->done = true; 414 data->done = true;
414 } 415 }
415 data->instance->MainloopSignal(); 416 data->instance->MainloopSignal();
416 } 417 }
417 418
418 inline void PulseAudioMixer::MainloopLock() const { 419 inline void AudioMixerPulse::MainloopLock() const {
419 pa_threaded_mainloop_lock(pa_mainloop_); 420 pa_threaded_mainloop_lock(pa_mainloop_);
420 ++mainloop_lock_count_; 421 ++mainloop_lock_count_;
421 } 422 }
422 423
423 inline void PulseAudioMixer::MainloopUnlock() const { 424 inline void AudioMixerPulse::MainloopUnlock() const {
424 --mainloop_lock_count_; 425 --mainloop_lock_count_;
425 pa_threaded_mainloop_unlock(pa_mainloop_); 426 pa_threaded_mainloop_unlock(pa_mainloop_);
426 } 427 }
427 428
428 // Must be called with the lock held. 429 // Must be called with the lock held.
429 inline void PulseAudioMixer::MainloopWait() const { 430 inline void AudioMixerPulse::MainloopWait() const {
430 DCHECK_GT(mainloop_lock_count_, 0); 431 DCHECK_GT(mainloop_lock_count_, 0);
431 pa_threaded_mainloop_wait(pa_mainloop_); 432 pa_threaded_mainloop_wait(pa_mainloop_);
432 } 433 }
433 434
434 // Must be called with the lock held. 435 // Must be called with the lock held.
435 inline void PulseAudioMixer::MainloopSignal() const { 436 inline void AudioMixerPulse::MainloopSignal() const {
436 DCHECK_GT(mainloop_lock_count_, 0); 437 DCHECK_GT(mainloop_lock_count_, 0);
437 pa_threaded_mainloop_signal(pa_mainloop_, 0); 438 pa_threaded_mainloop_signal(pa_mainloop_, 0);
438 } 439 }
439 440
440 inline bool PulseAudioMixer::MainloopSafeLock() const { 441 inline bool AudioMixerPulse::MainloopSafeLock() const {
441 AutoLock lock(mixer_state_lock_); 442 AutoLock lock(mixer_state_lock_);
442 if ((mixer_state_ == SHUTTING_DOWN) || (!pa_mainloop_)) 443 if ((mixer_state_ == SHUTTING_DOWN) || (!pa_mainloop_))
443 return false; 444 return false;
445
444 pa_threaded_mainloop_lock(pa_mainloop_); 446 pa_threaded_mainloop_lock(pa_mainloop_);
445 ++mainloop_lock_count_; 447 ++mainloop_lock_count_;
446 return true; 448 return true;
447 } 449 }
448 450
449 inline bool PulseAudioMixer::MainloopLockIfReady() const { 451 inline bool AudioMixerPulse::MainloopLockIfReady() const {
450 AutoLock lock(mixer_state_lock_); 452 AutoLock lock(mixer_state_lock_);
451 if (mixer_state_ != READY) 453 if (mixer_state_ != READY)
452 return false; 454 return false;
453 if (!pa_mainloop_) 455 if (!pa_mainloop_)
454 return false; 456 return false;
455 pa_threaded_mainloop_lock(pa_mainloop_); 457 pa_threaded_mainloop_lock(pa_mainloop_);
456 ++mainloop_lock_count_; 458 ++mainloop_lock_count_;
457 return true; 459 return true;
458 } 460 }
459 461
460 } // namespace chromeos 462 } // namespace chromeos
461 463
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698