OLD | NEW |
---|---|
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 Loading... | |
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 |
OLD | NEW |