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

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: using snd_mixer_selem_id_malloc Created 9 years, 11 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 | 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_(),
50 mixer_state_(UNINITIALIZED), 54 mixer_state_(UNINITIALIZED),
51 pa_context_(NULL), 55 pa_context_(NULL),
52 pa_mainloop_(NULL), 56 pa_mainloop_(NULL) {
53 thread_(NULL) {
54 } 57 }
55 58
56 PulseAudioMixer::~PulseAudioMixer() { 59 AudioMixerPulse::~AudioMixerPulse() {
57 PulseAudioFree(); 60 PulseAudioFree();
58 thread_->Stop(); 61 if (thread_ != NULL) {
59 thread_.reset(); 62 thread_->Stop();
63 thread_.reset();
64 }
60 } 65 }
61 66
62 bool PulseAudioMixer::Init(InitDoneCallback* callback) { 67 bool AudioMixerPulse::Init(InitDoneCallback* callback) {
63 if (!InitThread()) 68 if (!InitThread())
64 return false; 69 return false;
scherkus (not reviewing) 2011/01/11 00:24:12 what happens to the callback?
davejcool 2011/01/11 02:52:54 Ahhh! This callback wasn't being deleted in earlie
65 70
66 // Post the task of starting up, which can block for 200-500ms, 71 // Post the task of starting up, which can block for 200-500ms,
67 // so best not to do it on the caller's thread. 72 // so best not to do it on the caller's thread.
68 thread_->message_loop()->PostTask(FROM_HERE, 73 thread_->message_loop()->PostTask(FROM_HERE,
69 NewRunnableMethod(this, &PulseAudioMixer::DoInit, callback)); 74 NewRunnableMethod(this, &AudioMixerPulse::DoInit, callback));
70 return true; 75 return true;
71 } 76 }
72 77
73 bool PulseAudioMixer::InitSync() { 78 bool AudioMixerPulse::InitSync() {
74 if (!InitThread()) 79 if (!InitThread())
75 return false; 80 return false;
76 return PulseAudioInit(); 81 return PulseAudioInit();
77 } 82 }
78 83
79 double PulseAudioMixer::GetVolumeDb() const { 84 double AudioMixerPulse::GetVolumeDb() const {
80 if (!MainloopLockIfReady()) 85 if (!MainloopLockIfReady())
81 return pa_sw_volume_to_dB(0); // this returns -inf. 86 return AudioMixer::kSilenceDb;
82 AudioInfo data; 87 AudioInfo data;
83 GetAudioInfo(&data); 88 GetAudioInfo(&data);
84 MainloopUnlock(); 89 MainloopUnlock();
85 return pa_sw_volume_to_dB(data.cvolume.values[0]); 90 return pa_sw_volume_to_dB(data.cvolume.values[0]);
86 } 91 }
87 92
88 bool PulseAudioMixer::GetVolumeDbAsync(GetVolumeCallback* callback, 93 bool AudioMixerPulse::GetVolumeLimits(double* vol_min, double* vol_max) {
89 void* user) { 94 if (vol_min)
90 if (CheckState() != READY) 95 *vol_min = kMinVolumeDb;
91 return false; 96 if (vol_max)
92 thread_->message_loop()->PostTask(FROM_HERE, 97 *vol_max = kMaxVolumeDb;
93 NewRunnableMethod(this,
94 &PulseAudioMixer::DoGetVolume,
95 callback, user));
96 return true; 98 return true;
97 } 99 }
98 100
99 void PulseAudioMixer::SetVolumeDb(double vol_db) { 101 void AudioMixerPulse::SetVolumeDb(double vol_db) {
100 if (!MainloopLockIfReady()) 102 if (!MainloopLockIfReady())
101 return; 103 return;
102 104
103 // last_channels_ determines the number of channels on the main output device, 105 // 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. 106 // and is used later to set the volume on all channels at once.
105 if (!last_channels_) { 107 if (!last_channels_) {
106 AudioInfo data; 108 AudioInfo data;
107 GetAudioInfo(&data); 109 GetAudioInfo(&data);
108 last_channels_ = data.cvolume.channels; 110 last_channels_ = data.cvolume.channels;
109 } 111 }
110 112
111 pa_operation* pa_op; 113 pa_operation* pa_op;
112 pa_cvolume cvolume; 114 pa_cvolume cvolume;
113 pa_cvolume_set(&cvolume, last_channels_, pa_sw_volume_from_dB(vol_db)); 115 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_, 116 pa_op = pa_context_set_sink_volume_by_index(pa_context_, device_id_,
115 &cvolume, NULL, NULL); 117 &cvolume, NULL, NULL);
116 pa_operation_unref(pa_op); 118 pa_operation_unref(pa_op);
117 MainloopUnlock(); 119 MainloopUnlock();
120 VLOG(1) << "Set volume to " << vol_db << " dB";
118 } 121 }
119 122
120 bool PulseAudioMixer::IsMute() const { 123 bool AudioMixerPulse::IsMute() const {
121 if (!MainloopLockIfReady()) 124 if (!MainloopLockIfReady())
122 return false; 125 return false;
123 AudioInfo data; 126 AudioInfo data;
124 GetAudioInfo(&data); 127 GetAudioInfo(&data);
125 MainloopUnlock(); 128 MainloopUnlock();
126 return data.muted; 129 return data.muted;
127 } 130 }
128 131
129 void PulseAudioMixer::SetMute(bool mute) { 132 void AudioMixerPulse::SetMute(bool mute) {
130 if (!MainloopLockIfReady()) 133 if (!MainloopLockIfReady())
131 return; 134 return;
132 pa_operation* pa_op; 135 pa_operation* pa_op;
133 pa_op = pa_context_set_sink_mute_by_index(pa_context_, device_id_, 136 pa_op = pa_context_set_sink_mute_by_index(pa_context_, device_id_,
134 mute ? 1 : 0, NULL, NULL); 137 mute ? 1 : 0, NULL, NULL);
135 pa_operation_unref(pa_op); 138 pa_operation_unref(pa_op);
136 MainloopUnlock(); 139 MainloopUnlock();
140 VLOG(1) << "Set mute to " << mute;
137 } 141 }
138 142
139 PulseAudioMixer::State PulseAudioMixer::CheckState() const { 143 AudioMixer::State AudioMixerPulse::CheckState() const {
140 AutoLock lock(mixer_state_lock_); 144 AutoLock lock(mixer_state_lock_);
141 // If we think it's ready, verify it is actually so. 145 // If we think it's ready, verify it is actually so.
142 if ((mixer_state_ == READY) && 146 if ((mixer_state_ == READY) &&
143 (pa_context_get_state(pa_context_) != PA_CONTEXT_READY)) 147 (pa_context_get_state(pa_context_) != PA_CONTEXT_READY))
144 mixer_state_ = IN_ERROR; 148 mixer_state_ = IN_ERROR;
145 return mixer_state_; 149 return mixer_state_;
146 } 150 }
147 151
148 //////////////////////////////////////////////////////////////////////////////// 152 ////////////////////////////////////////////////////////////////////////////////
149 // Private functions follow 153 // Private functions follow
150 154
151 void PulseAudioMixer::DoInit(InitDoneCallback* callback) { 155 void AudioMixerPulse::DoInit(InitDoneCallback* callback) {
152 bool success = PulseAudioInit(); 156 bool success = PulseAudioInit();
153 callback->Run(success); 157 callback->Run(success);
154 delete callback; 158 delete callback;
155 } 159 }
156 160
157 void PulseAudioMixer::DoGetVolume(GetVolumeCallback* callback, 161 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_); 162 AutoLock lock(mixer_state_lock_);
165 163
166 if (mixer_state_ != UNINITIALIZED) 164 if (mixer_state_ != UNINITIALIZED)
167 return false; 165 return false;
166
168 if (thread_ == NULL) { 167 if (thread_ == NULL) {
169 thread_.reset(new base::Thread("PulseAudioMixer")); 168 thread_.reset(new base::Thread("AudioMixerPulse"));
170 if (!thread_->Start()) { 169 if (!thread_->Start()) {
171 thread_.reset(); 170 thread_.reset();
172 return false; 171 return false;
173 } 172 }
174 } 173 }
175 mixer_state_ = INITIALIZING; 174 mixer_state_ = INITIALIZING;
176 return true; 175 return true;
177 } 176 }
178 177
179 // static 178 // static
180 void PulseAudioMixer::ConnectToPulseCallbackThunk( 179 void AudioMixerPulse::ConnectToPulseCallbackThunk(
181 pa_context* context, void* userdata) { 180 pa_context* context, void* userdata) {
182 CallbackWrapper* data = 181 CallbackWrapper* data =
183 static_cast<CallbackWrapper*>(userdata); 182 static_cast<CallbackWrapper*>(userdata);
184 data->instance->OnConnectToPulseCallback(context, &data->done); 183 data->instance->OnConnectToPulseCallback(context, &data->done);
185 } 184 }
186 185
187 void PulseAudioMixer::OnConnectToPulseCallback( 186 void AudioMixerPulse::OnConnectToPulseCallback(
188 pa_context* context, bool* connect_done) { 187 pa_context* context, bool* connect_done) {
189 pa_context_state_t state = pa_context_get_state(context); 188 pa_context_state_t state = pa_context_get_state(context);
190 if (state == PA_CONTEXT_READY || 189 if (state == PA_CONTEXT_READY ||
191 state == PA_CONTEXT_FAILED || 190 state == PA_CONTEXT_FAILED ||
192 state == PA_CONTEXT_TERMINATED) { 191 state == PA_CONTEXT_TERMINATED) {
193 // Connection process has reached a terminal state. Wake PulseAudioInit(). 192 // Connection process has reached a terminal state. Wake PulseAudioInit().
194 *connect_done = true; 193 *connect_done = true;
195 MainloopSignal(); 194 MainloopSignal();
196 } 195 }
197 } 196 }
198 197
199 bool PulseAudioMixer::PulseAudioInit() { 198 bool AudioMixerPulse::PulseAudioInit() {
200 pa_context_state_t state = PA_CONTEXT_FAILED; 199 pa_context_state_t state = PA_CONTEXT_FAILED;
201 200
202 { 201 {
203 AutoLock lock(mixer_state_lock_); 202 AutoLock lock(mixer_state_lock_);
204 if (mixer_state_ != INITIALIZING) 203 if (mixer_state_ != INITIALIZING)
205 return false; 204 return false;
206 205
207 pa_mainloop_ = pa_threaded_mainloop_new(); 206 pa_mainloop_ = pa_threaded_mainloop_new();
208 if (!pa_mainloop_) { 207 if (!pa_mainloop_) {
209 LOG(ERROR) << "Can't create PulseAudio mainloop"; 208 LOG(ERROR) << "Can't create PulseAudio mainloop";
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 } 290 }
292 291
293 return true; 292 return true;
294 } 293 }
295 294
296 // Failed startup sequence, clean up now. 295 // Failed startup sequence, clean up now.
297 PulseAudioFree(); 296 PulseAudioFree();
298 return false; 297 return false;
299 } 298 }
300 299
301 void PulseAudioMixer::PulseAudioFree() { 300 void AudioMixerPulse::PulseAudioFree() {
302 { 301 {
303 AutoLock lock(mixer_state_lock_); 302 AutoLock lock(mixer_state_lock_);
304 if (!pa_mainloop_) 303 if (!pa_mainloop_)
305 mixer_state_ = UNINITIALIZED; 304 mixer_state_ = UNINITIALIZED;
306 if ((mixer_state_ == UNINITIALIZED) || (mixer_state_ == SHUTTING_DOWN)) 305 if ((mixer_state_ == UNINITIALIZED) || (mixer_state_ == SHUTTING_DOWN))
307 return; 306 return;
307
308 // If still initializing on another thread, this will cause it to exit. 308 // If still initializing on another thread, this will cause it to exit.
309 mixer_state_ = SHUTTING_DOWN; 309 mixer_state_ = SHUTTING_DOWN;
310 } 310 }
311 311
312 DCHECK(pa_mainloop_); 312 DCHECK(pa_mainloop_);
313 313
314 MainloopLock(); 314 MainloopLock();
315 if (pa_context_) { 315 if (pa_context_) {
316 pa_context_disconnect(pa_context_); 316 pa_context_disconnect(pa_context_);
317 pa_context_unref(pa_context_); 317 pa_context_unref(pa_context_);
318 pa_context_ = NULL; 318 pa_context_ = NULL;
319 } 319 }
320 MainloopUnlock(); 320 MainloopUnlock();
321 321
322 pa_threaded_mainloop_stop(pa_mainloop_); 322 pa_threaded_mainloop_stop(pa_mainloop_);
323 pa_threaded_mainloop_free(pa_mainloop_); 323 pa_threaded_mainloop_free(pa_mainloop_);
324 pa_mainloop_ = NULL; 324 pa_mainloop_ = NULL;
325 325
326 { 326 {
327 AutoLock lock(mixer_state_lock_); 327 AutoLock lock(mixer_state_lock_);
328 mixer_state_ = UNINITIALIZED; 328 mixer_state_ = UNINITIALIZED;
329 } 329 }
330 } 330 }
331 331
332 void PulseAudioMixer::CompleteOperation(pa_operation* pa_op, 332 void AudioMixerPulse::CompleteOperation(pa_operation* pa_op,
333 bool* done) const { 333 bool* done) const {
334 // After starting any operation, this helper checks if it started OK, then 334 // 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 335 // waits for it to complete by iterating through the mainloop until the
336 // operation is not running anymore. 336 // operation is not running anymore.
337 CHECK(pa_op); 337 CHECK(pa_op);
338 338
339 while (pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING) { 339 while (pa_operation_get_state(pa_op) == PA_OPERATION_RUNNING) {
340 // If operation still running, but we got what we needed, cancel it now. 340 // If operation still running, but we got what we needed, cancel it now.
341 if (*done) { 341 if (*done) {
342 pa_operation_cancel(pa_op); 342 pa_operation_cancel(pa_op);
343 break; 343 break;
344 } 344 }
345 MainloopWait(); 345 MainloopWait();
346 } 346 }
347 pa_operation_unref(pa_op); 347 pa_operation_unref(pa_op);
348 } 348 }
349 349
350 // Must be called with mainloop lock held 350 // Must be called with mainloop lock held
351 void PulseAudioMixer::GetDefaultPlaybackDevice() { 351 void AudioMixerPulse::GetDefaultPlaybackDevice() {
352 DCHECK_GT(mainloop_lock_count_, 0); 352 DCHECK_GT(mainloop_lock_count_, 0);
353 DCHECK(pa_context_); 353 DCHECK(pa_context_);
354 DCHECK(pa_context_get_state(pa_context_) == PA_CONTEXT_READY); 354 DCHECK(pa_context_get_state(pa_context_) == PA_CONTEXT_READY);
355 355
356 CallbackWrapper data = {this, false, NULL}; 356 CallbackWrapper data = {this, false, NULL};
357 357
358 pa_operation* pa_op = pa_context_get_sink_info_list(pa_context_, 358 pa_operation* pa_op = pa_context_get_sink_info_list(pa_context_,
359 EnumerateDevicesCallback, 359 EnumerateDevicesCallback,
360 &data); 360 &data);
361 CompleteOperation(pa_op, &data.done); 361 CompleteOperation(pa_op, &data.done);
362 return; 362 return;
363 } 363 }
364 364
365 void PulseAudioMixer::OnEnumerateDevices(const pa_sink_info* sink_info, 365 void AudioMixerPulse::OnEnumerateDevices(const pa_sink_info* sink_info,
366 int eol, bool* done) { 366 int eol, bool* done) {
367 if (device_id_ != kInvalidDeviceId) 367 if (device_id_ != kInvalidDeviceId)
368 return; 368 return;
369 369
370 // TODO(davej): Should we handle cases of more than one output sink device? 370 // TODO(davej): Should we handle cases of more than one output sink device?
371 371
372 // eol is < 0 for error, > 0 for end of list, ==0 while listing. 372 // eol is < 0 for error, > 0 for end of list, ==0 while listing.
373 if (eol == 0) { 373 if (eol == 0) {
374 device_id_ = sink_info->index; 374 device_id_ = sink_info->index;
375 } 375 }
376 *done = true; 376 *done = true;
377 MainloopSignal(); 377 MainloopSignal();
378 } 378 }
379 379
380 // static 380 // static
381 void PulseAudioMixer::EnumerateDevicesCallback(pa_context* unused, 381 void AudioMixerPulse::EnumerateDevicesCallback(pa_context* unused,
382 const pa_sink_info* sink_info, 382 const pa_sink_info* sink_info,
383 int eol, 383 int eol,
384 void* userdata) { 384 void* userdata) {
385 CallbackWrapper* data = 385 CallbackWrapper* data =
386 static_cast<CallbackWrapper*>(userdata); 386 static_cast<CallbackWrapper*>(userdata);
387 data->instance->OnEnumerateDevices(sink_info, eol, &data->done); 387 data->instance->OnEnumerateDevices(sink_info, eol, &data->done);
388 } 388 }
389 389
390 // Must be called with lock held 390 // Must be called with lock held
391 void PulseAudioMixer::GetAudioInfo(AudioInfo* info) const { 391 void AudioMixerPulse::GetAudioInfo(AudioInfo* info) const {
392 DCHECK_GT(mainloop_lock_count_, 0); 392 DCHECK_GT(mainloop_lock_count_, 0);
393 CallbackWrapper data = {const_cast<PulseAudioMixer*>(this), false, info}; 393 CallbackWrapper data = {const_cast<AudioMixerPulse*>(this), false, info};
394 pa_operation* pa_op = pa_context_get_sink_info_by_index(pa_context_, 394 pa_operation* pa_op = pa_context_get_sink_info_by_index(pa_context_,
395 device_id_, 395 device_id_,
396 GetAudioInfoCallback, 396 GetAudioInfoCallback,
397 &data); 397 &data);
398 CompleteOperation(pa_op, &data.done); 398 CompleteOperation(pa_op, &data.done);
399 } 399 }
400 400
401 // static 401 // static
402 void PulseAudioMixer::GetAudioInfoCallback(pa_context* unused, 402 void AudioMixerPulse::GetAudioInfoCallback(pa_context* unused,
403 const pa_sink_info* sink_info, 403 const pa_sink_info* sink_info,
404 int eol, 404 int eol,
405 void* userdata) { 405 void* userdata) {
406 CallbackWrapper* data = static_cast<CallbackWrapper*>(userdata); 406 CallbackWrapper* data = static_cast<CallbackWrapper*>(userdata);
407 AudioInfo* info = static_cast<AudioInfo*>(data->userdata); 407 AudioInfo* info = static_cast<AudioInfo*>(data->userdata);
408 408
409 // Copy just the information we care about. 409 // Copy just the information we care about.
410 if (eol == 0) { 410 if (eol == 0) {
411 info->cvolume = sink_info->volume; 411 info->cvolume = sink_info->volume;
412 info->muted = sink_info->mute ? true : false; 412 info->muted = sink_info->mute ? true : false;
413 data->done = true; 413 data->done = true;
414 } 414 }
415 data->instance->MainloopSignal(); 415 data->instance->MainloopSignal();
416 } 416 }
417 417
418 inline void PulseAudioMixer::MainloopLock() const { 418 inline void AudioMixerPulse::MainloopLock() const {
419 pa_threaded_mainloop_lock(pa_mainloop_); 419 pa_threaded_mainloop_lock(pa_mainloop_);
420 ++mainloop_lock_count_; 420 ++mainloop_lock_count_;
421 } 421 }
422 422
423 inline void PulseAudioMixer::MainloopUnlock() const { 423 inline void AudioMixerPulse::MainloopUnlock() const {
424 --mainloop_lock_count_; 424 --mainloop_lock_count_;
425 pa_threaded_mainloop_unlock(pa_mainloop_); 425 pa_threaded_mainloop_unlock(pa_mainloop_);
426 } 426 }
427 427
428 // Must be called with the lock held. 428 // Must be called with the lock held.
429 inline void PulseAudioMixer::MainloopWait() const { 429 inline void AudioMixerPulse::MainloopWait() const {
430 DCHECK_GT(mainloop_lock_count_, 0); 430 DCHECK_GT(mainloop_lock_count_, 0);
431 pa_threaded_mainloop_wait(pa_mainloop_); 431 pa_threaded_mainloop_wait(pa_mainloop_);
432 } 432 }
433 433
434 // Must be called with the lock held. 434 // Must be called with the lock held.
435 inline void PulseAudioMixer::MainloopSignal() const { 435 inline void AudioMixerPulse::MainloopSignal() const {
436 DCHECK_GT(mainloop_lock_count_, 0); 436 DCHECK_GT(mainloop_lock_count_, 0);
437 pa_threaded_mainloop_signal(pa_mainloop_, 0); 437 pa_threaded_mainloop_signal(pa_mainloop_, 0);
438 } 438 }
439 439
440 inline bool PulseAudioMixer::MainloopSafeLock() const { 440 inline bool AudioMixerPulse::MainloopSafeLock() const {
441 AutoLock lock(mixer_state_lock_); 441 AutoLock lock(mixer_state_lock_);
442 if ((mixer_state_ == SHUTTING_DOWN) || (!pa_mainloop_)) 442 if ((mixer_state_ == SHUTTING_DOWN) || (!pa_mainloop_))
443 return false; 443 return false;
444
444 pa_threaded_mainloop_lock(pa_mainloop_); 445 pa_threaded_mainloop_lock(pa_mainloop_);
445 ++mainloop_lock_count_; 446 ++mainloop_lock_count_;
446 return true; 447 return true;
447 } 448 }
448 449
449 inline bool PulseAudioMixer::MainloopLockIfReady() const { 450 inline bool AudioMixerPulse::MainloopLockIfReady() const {
450 AutoLock lock(mixer_state_lock_); 451 AutoLock lock(mixer_state_lock_);
451 if (mixer_state_ != READY) 452 if (mixer_state_ != READY)
452 return false; 453 return false;
453 if (!pa_mainloop_) 454 if (!pa_mainloop_)
454 return false; 455 return false;
455 pa_threaded_mainloop_lock(pa_mainloop_); 456 pa_threaded_mainloop_lock(pa_mainloop_);
456 ++mainloop_lock_count_; 457 ++mainloop_lock_count_;
457 return true; 458 return true;
458 } 459 }
459 460
460 } // namespace chromeos 461 } // namespace chromeos
461 462
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698