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

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

Issue 6562002: Merge 75698 - chromeos: Check ALSA return values in mixer code.... (Closed) Base URL: svn://svn.chromium.org/chrome/branches/648/src/
Patch Set: Created 9 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/chromeos/audio_mixer_alsa.h ('k') | no next file » | 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) 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/audio_mixer_alsa.h" 5 #include "chrome/browser/chromeos/audio_mixer_alsa.h"
6 6
7 #include <cmath>
8
7 #include <alsa/asoundlib.h> 9 #include <alsa/asoundlib.h>
8 10
9 #include "base/logging.h" 11 #include "base/logging.h"
10 #include "base/task.h" 12 #include "base/task.h"
11 #include "base/threading/thread_restrictions.h" 13 #include "base/threading/thread_restrictions.h"
12 #include "chrome/browser/browser_process.h" 14 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/browser_thread.h" 15 #include "chrome/browser/browser_thread.h"
14 #include "chrome/browser/prefs/pref_service.h" 16 #include "chrome/browser/prefs/pref_service.h"
15 #include "chrome/common/pref_names.h" 17 #include "chrome/common/pref_names.h"
16 18
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 *vol_min = min_volume_; 103 *vol_min = min_volume_;
102 if (vol_max) 104 if (vol_max)
103 *vol_max = max_volume_; 105 *vol_max = max_volume_;
104 return true; 106 return true;
105 } 107 }
106 108
107 void AudioMixerAlsa::SetVolumeDb(double vol_db) { 109 void AudioMixerAlsa::SetVolumeDb(double vol_db) {
108 base::AutoLock lock(mixer_state_lock_); 110 base::AutoLock lock(mixer_state_lock_);
109 if (mixer_state_ != READY) 111 if (mixer_state_ != READY)
110 return; 112 return;
111 if (vol_db < kSilenceDb) 113
114 if (vol_db < kSilenceDb || isnan(vol_db)) {
115 if (isnan(vol_db))
116 LOG(WARNING) << "Got request to set volume to NaN";
112 vol_db = kSilenceDb; 117 vol_db = kSilenceDb;
118 }
119
113 DoSetVolumeDb_Locked(vol_db); 120 DoSetVolumeDb_Locked(vol_db);
114 volume_pref_.SetValue(vol_db); 121 volume_pref_.SetValue(vol_db);
115 } 122 }
116 123
117 bool AudioMixerAlsa::IsMute() const { 124 bool AudioMixerAlsa::IsMute() const {
118 base::AutoLock lock(mixer_state_lock_); 125 base::AutoLock lock(mixer_state_lock_);
119 if (mixer_state_ != READY) 126 if (mixer_state_ != READY)
120 return false; 127 return false;
121 return GetElementMuted_Locked(elem_master_); 128 return GetElementMuted_Locked(elem_master_);
122 } 129 }
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 << snd_strerror(err); 255 << snd_strerror(err);
249 snd_mixer_close(handle); 256 snd_mixer_close(handle);
250 return false; 257 return false;
251 } 258 }
252 259
253 VLOG(1) << "Opened ALSA mixer " << card << " OK"; 260 VLOG(1) << "Opened ALSA mixer " << card << " OK";
254 261
255 elem_master_ = FindElementWithName_Locked(handle, kMasterVolume); 262 elem_master_ = FindElementWithName_Locked(handle, kMasterVolume);
256 if (elem_master_) { 263 if (elem_master_) {
257 alsa_long_t long_lo, long_hi; 264 alsa_long_t long_lo, long_hi;
258 snd_mixer_selem_get_playback_dB_range(elem_master_, &long_lo, &long_hi); 265 err = snd_mixer_selem_get_playback_dB_range(
266 elem_master_, &long_lo, &long_hi);
267 if (err != 0) {
268 LOG(WARNING) << "snd_mixer_selem_get_playback_dB_range() failed "
269 << "for master: " << snd_strerror(err);
270 snd_mixer_close(handle);
271 return false;
272 }
259 min_volume_ = static_cast<double>(long_lo) / 100.0; 273 min_volume_ = static_cast<double>(long_lo) / 100.0;
260 max_volume_ = static_cast<double>(long_hi) / 100.0; 274 max_volume_ = static_cast<double>(long_hi) / 100.0;
261 } else { 275 } else {
262 LOG(ERROR) << "Cannot find 'Master' ALSA mixer element on " << card; 276 LOG(ERROR) << "Cannot find 'Master' ALSA mixer element on " << card;
263 snd_mixer_close(handle); 277 snd_mixer_close(handle);
264 return false; 278 return false;
265 } 279 }
266 280
267 elem_pcm_ = FindElementWithName_Locked(handle, kPCMVolume); 281 elem_pcm_ = FindElementWithName_Locked(handle, kPCMVolume);
268 if (elem_pcm_) { 282 if (elem_pcm_) {
269 alsa_long_t long_lo, long_hi; 283 alsa_long_t long_lo, long_hi;
270 snd_mixer_selem_get_playback_dB_range(elem_pcm_, &long_lo, &long_hi); 284 err = snd_mixer_selem_get_playback_dB_range(elem_pcm_, &long_lo, &long_hi);
285 if (err != 0) {
286 LOG(WARNING) << "snd_mixer_selem_get_playback_dB_range() failed for PCM: "
287 << snd_strerror(err);
288 snd_mixer_close(handle);
289 return false;
290 }
271 min_volume_ += static_cast<double>(long_lo) / 100.0; 291 min_volume_ += static_cast<double>(long_lo) / 100.0;
272 max_volume_ += static_cast<double>(long_hi) / 100.0; 292 max_volume_ += static_cast<double>(long_hi) / 100.0;
273 } 293 }
274 294
275 VLOG(1) << "ALSA volume range is " << min_volume_ << " dB to " 295 VLOG(1) << "ALSA volume range is " << min_volume_ << " dB to "
276 << max_volume_ << " dB"; 296 << max_volume_ << " dB";
277 297
278 alsa_mixer_ = handle; 298 alsa_mixer_ = handle;
279 mixer_state_ = READY; 299 mixer_state_ = READY;
280 return true; 300 return true;
281 } 301 }
282 302
283 void AudioMixerAlsa::FreeAlsaMixer() { 303 void AudioMixerAlsa::FreeAlsaMixer() {
284 base::AutoLock lock(mixer_state_lock_); 304 base::AutoLock lock(mixer_state_lock_);
285 mixer_state_ = SHUTTING_DOWN; 305 mixer_state_ = SHUTTING_DOWN;
286 if (alsa_mixer_) { 306 if (alsa_mixer_) {
287 snd_mixer_close(alsa_mixer_); 307 snd_mixer_close(alsa_mixer_);
288 alsa_mixer_ = NULL; 308 alsa_mixer_ = NULL;
289 } 309 }
290 } 310 }
291 311
292 void AudioMixerAlsa::DoSetVolumeMute(double pref_volume, int pref_mute) { 312 void AudioMixerAlsa::DoSetVolumeMute(double pref_volume, int pref_mute) {
293 base::AutoLock lock(mixer_state_lock_); 313 base::AutoLock lock(mixer_state_lock_);
294 if (mixer_state_ != READY) 314 if (mixer_state_ != READY)
295 return; 315 return;
296 316
297 // If volume or mute are invalid, set them now to the current actual values. 317 // If volume or mute are invalid, set them now to the current actual values.
298 if (!PrefVolumeValid(pref_volume)) 318 if (!PrefVolumeValid(pref_volume))
299 pref_volume = DoGetVolumeDb_Locked(); 319 pref_volume = DoGetVolumeDb_Locked();
300 bool mute; 320 bool mute = false;
301 if (pref_mute == kPrefMuteInvalid) 321 if (pref_mute == kPrefMuteInvalid)
302 mute = GetElementMuted_Locked(elem_master_); 322 mute = GetElementMuted_Locked(elem_master_);
303 else 323 else
304 mute = (pref_mute == kPrefMuteOn) ? true : false; 324 mute = (pref_mute == kPrefMuteOn) ? true : false;
305 325
306 VLOG(1) << "Setting volume to " << pref_volume << " and mute to " << mute; 326 VLOG(1) << "Setting volume to " << pref_volume << " and mute to " << mute;
307 327
308 if (mute) { 328 if (mute) {
309 save_volume_ = pref_volume; 329 save_volume_ = pref_volume;
310 DoSetVolumeDb_Locked(min_volume_); 330 DoSetVolumeDb_Locked(min_volume_);
311 } else { 331 } else {
312 DoSetVolumeDb_Locked(pref_volume); 332 DoSetVolumeDb_Locked(pref_volume);
313 } 333 }
314 334
315 SetElementMuted_Locked(elem_master_, mute); 335 SetElementMuted_Locked(elem_master_, mute);
316 if (elem_pcm_) 336 if (elem_pcm_)
317 SetElementMuted_Locked(elem_pcm_, mute); 337 SetElementMuted_Locked(elem_pcm_, mute);
318 } 338 }
319 339
320 void AudioMixerAlsa::RestoreVolumeMuteOnUIThread() { 340 void AudioMixerAlsa::RestoreVolumeMuteOnUIThread() {
321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
322 // This happens during init, so set the volume off the UI thread. 342 // This happens during init, so set the volume off the UI thread.
323 thread_->message_loop()->PostTask(FROM_HERE, 343 thread_->message_loop()->PostTask(FROM_HERE,
324 NewRunnableMethod(this, &AudioMixerAlsa::DoSetVolumeMute, 344 NewRunnableMethod(this, &AudioMixerAlsa::DoSetVolumeMute,
325 volume_pref_.GetValue(), mute_pref_.GetValue())); 345 volume_pref_.GetValue(), mute_pref_.GetValue()));
326 } 346 }
327 347
328 double AudioMixerAlsa::DoGetVolumeDb_Locked() const { 348 double AudioMixerAlsa::DoGetVolumeDb_Locked() const {
329 double vol_total = 0.0; 349 double vol_total = 0.0;
330 GetElementVolume_Locked(elem_master_, &vol_total); 350 if (!GetElementVolume_Locked(elem_master_, &vol_total))
351 return 0.0;
331 352
332 double vol_pcm = 0.0; 353 double vol_pcm = 0.0;
333 if (elem_pcm_ && (GetElementVolume_Locked(elem_pcm_, &vol_pcm))) 354 if (elem_pcm_ && GetElementVolume_Locked(elem_pcm_, &vol_pcm))
334 vol_total += vol_pcm; 355 vol_total += vol_pcm;
335 356
336 return vol_total; 357 return vol_total;
337 } 358 }
338 359
339 void AudioMixerAlsa::DoSetVolumeDb_Locked(double vol_db) { 360 void AudioMixerAlsa::DoSetVolumeDb_Locked(double vol_db) {
340 double actual_vol = 0.0; 361 double actual_vol = 0.0;
341 362
342 // If a PCM volume slider exists, then first set the Master volume to the 363 // If a PCM volume slider exists, then first set the Master volume to the
343 // nearest volume >= requested volume, then adjust PCM volume down to get 364 // nearest volume >= requested volume, then adjust PCM volume down to get
(...skipping 24 matching lines...) Expand all
368 << snd_mixer_selem_id_get_name(sid); 389 << snd_mixer_selem_id_get_name(sid);
369 } 390 }
370 391
371 snd_mixer_selem_id_free(sid); 392 snd_mixer_selem_id_free(sid);
372 return elem; 393 return elem;
373 } 394 }
374 395
375 bool AudioMixerAlsa::GetElementVolume_Locked(snd_mixer_elem_t* elem, 396 bool AudioMixerAlsa::GetElementVolume_Locked(snd_mixer_elem_t* elem,
376 double* current_vol) const { 397 double* current_vol) const {
377 alsa_long_t long_vol = 0; 398 alsa_long_t long_vol = 0;
378 snd_mixer_selem_get_playback_dB(elem, 399 int alsa_result = snd_mixer_selem_get_playback_dB(
379 static_cast<snd_mixer_selem_channel_id_t>(0), 400 elem, static_cast<snd_mixer_selem_channel_id_t>(0), &long_vol);
380 &long_vol); 401 if (alsa_result != 0) {
402 LOG(WARNING) << "snd_mixer_selem_get_playback_dB() failed: "
403 << snd_strerror(alsa_result);
404 return false;
405 }
406
381 *current_vol = static_cast<double>(long_vol) / 100.0; 407 *current_vol = static_cast<double>(long_vol) / 100.0;
382
383 return true; 408 return true;
384 } 409 }
385 410
386 bool AudioMixerAlsa::SetElementVolume_Locked(snd_mixer_elem_t* elem, 411 bool AudioMixerAlsa::SetElementVolume_Locked(snd_mixer_elem_t* elem,
387 double new_vol, 412 double new_vol,
388 double* actual_vol, 413 double* actual_vol,
389 double rounding_bias) { 414 double rounding_bias) {
390 alsa_long_t vol_lo = 0; 415 alsa_long_t vol_lo = 0;
391 alsa_long_t vol_hi = 0; 416 alsa_long_t vol_hi = 0;
392 snd_mixer_selem_get_playback_volume_range(elem, &vol_lo, &vol_hi); 417 int alsa_result =
418 snd_mixer_selem_get_playback_volume_range(elem, &vol_lo, &vol_hi);
419 if (alsa_result != 0) {
420 LOG(WARNING) << "snd_mixer_selem_get_playback_volume_range() failed: "
421 << snd_strerror(alsa_result);
422 return false;
423 }
393 alsa_long_t vol_range = vol_hi - vol_lo; 424 alsa_long_t vol_range = vol_hi - vol_lo;
394 if (vol_range <= 0) 425 if (vol_range <= 0)
395 return false; 426 return false;
396 427
397 alsa_long_t db_lo_int = 0; 428 alsa_long_t db_lo_int = 0;
398 alsa_long_t db_hi_int = 0; 429 alsa_long_t db_hi_int = 0;
399 snd_mixer_selem_get_playback_dB_range(elem, &db_lo_int, &db_hi_int); 430 alsa_result =
431 snd_mixer_selem_get_playback_dB_range(elem, &db_lo_int, &db_hi_int);
432 if (alsa_result != 0) {
433 LOG(WARNING) << "snd_mixer_selem_get_playback_dB_range() failed: "
434 << snd_strerror(alsa_result);
435 return false;
436 }
437
400 double db_lo = static_cast<double>(db_lo_int) / 100.0; 438 double db_lo = static_cast<double>(db_lo_int) / 100.0;
401 double db_hi = static_cast<double>(db_hi_int) / 100.0; 439 double db_hi = static_cast<double>(db_hi_int) / 100.0;
402 double db_step = static_cast<double>(db_hi - db_lo) / vol_range; 440 double db_step = static_cast<double>(db_hi - db_lo) / vol_range;
403 if (db_step <= 0.0) 441 if (db_step <= 0.0)
404 return false; 442 return false;
405 443
406 if (new_vol < db_lo) 444 if (new_vol < db_lo)
407 new_vol = db_lo; 445 new_vol = db_lo;
408 446
409 alsa_long_t value = static_cast<alsa_long_t>(rounding_bias + 447 alsa_long_t value = static_cast<alsa_long_t>(rounding_bias +
410 (new_vol - db_lo) / db_step) + vol_lo; 448 (new_vol - db_lo) / db_step) + vol_lo;
411 snd_mixer_selem_set_playback_volume_all(elem, value); 449 alsa_result = snd_mixer_selem_set_playback_volume_all(elem, value);
450 if (alsa_result != 0) {
451 LOG(WARNING) << "snd_mixer_selem_set_playback_volume_all() failed: "
452 << snd_strerror(alsa_result);
453 return false;
454 }
412 455
413 VLOG(1) << "Set volume " << snd_mixer_selem_get_name(elem) 456 VLOG(1) << "Set volume " << snd_mixer_selem_get_name(elem)
414 << " to " << new_vol << " ==> " << (value - vol_lo) * db_step + db_lo 457 << " to " << new_vol << " ==> " << (value - vol_lo) * db_step + db_lo
415 << " dB"; 458 << " dB";
416 459
417 if (actual_vol) { 460 if (actual_vol) {
418 alsa_long_t volume; 461 alsa_long_t volume;
419 snd_mixer_selem_get_playback_volume( 462 alsa_result = snd_mixer_selem_get_playback_volume(
420 elem, 463 elem, static_cast<snd_mixer_selem_channel_id_t>(0), &volume);
421 static_cast<snd_mixer_selem_channel_id_t>(0), 464 if (alsa_result != 0) {
422 &volume); 465 LOG(WARNING) << "snd_mixer_selem_get_playback_volume() failed: "
466 << snd_strerror(alsa_result);
467 return false;
468 }
423 *actual_vol = db_lo + (volume - vol_lo) * db_step; 469 *actual_vol = db_lo + (volume - vol_lo) * db_step;
424 470
425 VLOG(1) << "Actual volume " << snd_mixer_selem_get_name(elem) 471 VLOG(1) << "Actual volume " << snd_mixer_selem_get_name(elem)
426 << " now " << *actual_vol << " dB"; 472 << " now " << *actual_vol << " dB";
427 } 473 }
428 return true; 474 return true;
429 } 475 }
430 476
431 bool AudioMixerAlsa::GetElementMuted_Locked(snd_mixer_elem_t* elem) const { 477 bool AudioMixerAlsa::GetElementMuted_Locked(snd_mixer_elem_t* elem) const {
432 int enabled; 478 int enabled;
433 snd_mixer_selem_get_playback_switch( 479 int alsa_result = snd_mixer_selem_get_playback_switch(
434 elem, 480 elem, static_cast<snd_mixer_selem_channel_id_t>(0), &enabled);
435 static_cast<snd_mixer_selem_channel_id_t>(0), 481 if (alsa_result != 0) {
436 &enabled); 482 LOG(WARNING) << "snd_mixer_selem_get_playback_switch() failed: "
483 << snd_strerror(alsa_result);
484 return false;
485 }
437 return (enabled) ? false : true; 486 return (enabled) ? false : true;
438 } 487 }
439 488
440 void AudioMixerAlsa::SetElementMuted_Locked(snd_mixer_elem_t* elem, bool mute) { 489 void AudioMixerAlsa::SetElementMuted_Locked(snd_mixer_elem_t* elem, bool mute) {
441 int enabled = mute ? 0 : 1; 490 int enabled = mute ? 0 : 1;
442 snd_mixer_selem_set_playback_switch_all(elem, enabled); 491 int alsa_result = snd_mixer_selem_set_playback_switch_all(elem, enabled);
443 492 if (alsa_result != 0) {
444 VLOG(1) << "Set playback switch " << snd_mixer_selem_get_name(elem) 493 LOG(WARNING) << "snd_mixer_selem_set_playback_switch_all() failed: "
445 << " to " << enabled; 494 << snd_strerror(alsa_result);
495 } else {
496 VLOG(1) << "Set playback switch " << snd_mixer_selem_get_name(elem)
497 << " to " << enabled;
498 }
446 } 499 }
447 500
448 } // namespace chromeos 501 } // namespace chromeos
449 502
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/audio_mixer_alsa.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698