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

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

Issue 6562001: chromeos: Check ALSA return values in mixer code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/chrome/browser/chromeos
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/message_loop.h" 12 #include "base/message_loop.h"
11 #include "base/task.h" 13 #include "base/task.h"
12 #include "base/threading/thread_restrictions.h" 14 #include "base/threading/thread_restrictions.h"
13 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/browser_thread.h" 16 #include "chrome/browser/browser_thread.h"
15 #include "chrome/browser/prefs/pref_service.h" 17 #include "chrome/browser/prefs/pref_service.h"
16 #include "chrome/common/pref_names.h" 18 #include "chrome/common/pref_names.h"
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 *vol_min = min_volume_; 120 *vol_min = min_volume_;
119 if (vol_max) 121 if (vol_max)
120 *vol_max = max_volume_; 122 *vol_max = max_volume_;
121 return true; 123 return true;
122 } 124 }
123 125
124 void AudioMixerAlsa::SetVolumeDb(double vol_db) { 126 void AudioMixerAlsa::SetVolumeDb(double vol_db) {
125 base::AutoLock lock(mixer_state_lock_); 127 base::AutoLock lock(mixer_state_lock_);
126 if (mixer_state_ != READY) 128 if (mixer_state_ != READY)
127 return; 129 return;
128 if (vol_db < kSilenceDb) 130
131 if (vol_db < kSilenceDb || isnan(vol_db)) {
132 if (isnan(vol_db))
133 LOG(WARNING) << "Got request to set volume to NaN";
129 vol_db = kSilenceDb; 134 vol_db = kSilenceDb;
135 }
136
130 DoSetVolumeDb_Locked(vol_db); 137 DoSetVolumeDb_Locked(vol_db);
131 prefs_->SetDouble(prefs::kAudioVolume, vol_db); 138 prefs_->SetDouble(prefs::kAudioVolume, vol_db);
132 } 139 }
133 140
134 bool AudioMixerAlsa::IsMute() const { 141 bool AudioMixerAlsa::IsMute() const {
135 base::AutoLock lock(mixer_state_lock_); 142 base::AutoLock lock(mixer_state_lock_);
136 if (mixer_state_ != READY) 143 if (mixer_state_ != READY)
137 return false; 144 return false;
138 return GetElementMuted_Locked(elem_master_); 145 return GetElementMuted_Locked(elem_master_);
139 } 146 }
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 snd_mixer_close(handle); 270 snd_mixer_close(handle);
264 return false; 271 return false;
265 } 272 }
266 273
267 VLOG(1) << "Opened ALSA mixer " << card << " OK"; 274 VLOG(1) << "Opened ALSA mixer " << card << " OK";
268 275
269 elem_master_ = FindElementWithName_Locked(handle, kMasterVolume); 276 elem_master_ = FindElementWithName_Locked(handle, kMasterVolume);
270 if (elem_master_) { 277 if (elem_master_) {
271 alsa_long_t long_lo = static_cast<alsa_long_t>(kDefaultMinVolume * 100); 278 alsa_long_t long_lo = static_cast<alsa_long_t>(kDefaultMinVolume * 100);
272 alsa_long_t long_hi = static_cast<alsa_long_t>(kDefaultMaxVolume * 100); 279 alsa_long_t long_hi = static_cast<alsa_long_t>(kDefaultMaxVolume * 100);
273 snd_mixer_selem_get_playback_dB_range(elem_master_, &long_lo, &long_hi); 280 err = snd_mixer_selem_get_playback_dB_range(
281 elem_master_, &long_lo, &long_hi);
282 if (err != 0) {
283 LOG(WARNING) << "snd_mixer_selem_get_playback_dB_range() failed "
284 << "for master: " << snd_strerror(err);
285 snd_mixer_close(handle);
286 return false;
287 }
274 min_volume_ = static_cast<double>(long_lo) / 100.0; 288 min_volume_ = static_cast<double>(long_lo) / 100.0;
275 max_volume_ = static_cast<double>(long_hi) / 100.0; 289 max_volume_ = static_cast<double>(long_hi) / 100.0;
276 } else { 290 } else {
277 LOG(ERROR) << "Cannot find 'Master' ALSA mixer element on " << card; 291 LOG(ERROR) << "Cannot find 'Master' ALSA mixer element on " << card;
278 snd_mixer_close(handle); 292 snd_mixer_close(handle);
279 return false; 293 return false;
280 } 294 }
281 295
282 elem_pcm_ = FindElementWithName_Locked(handle, kPCMVolume); 296 elem_pcm_ = FindElementWithName_Locked(handle, kPCMVolume);
283 if (elem_pcm_) { 297 if (elem_pcm_) {
284 alsa_long_t long_lo = static_cast<alsa_long_t>(kDefaultMinVolume * 100); 298 alsa_long_t long_lo = static_cast<alsa_long_t>(kDefaultMinVolume * 100);
285 alsa_long_t long_hi = static_cast<alsa_long_t>(kDefaultMaxVolume * 100); 299 alsa_long_t long_hi = static_cast<alsa_long_t>(kDefaultMaxVolume * 100);
286 snd_mixer_selem_get_playback_dB_range(elem_pcm_, &long_lo, &long_hi); 300 err = snd_mixer_selem_get_playback_dB_range(elem_pcm_, &long_lo, &long_hi);
301 if (err != 0) {
302 LOG(WARNING) << "snd_mixer_selem_get_playback_dB_range() failed for PCM: "
303 << snd_strerror(err);
304 snd_mixer_close(handle);
305 return false;
306 }
287 min_volume_ += static_cast<double>(long_lo) / 100.0; 307 min_volume_ += static_cast<double>(long_lo) / 100.0;
288 max_volume_ += static_cast<double>(long_hi) / 100.0; 308 max_volume_ += static_cast<double>(long_hi) / 100.0;
289 } 309 }
290 310
291 VLOG(1) << "ALSA volume range is " << min_volume_ << " dB to " 311 VLOG(1) << "ALSA volume range is " << min_volume_ << " dB to "
292 << max_volume_ << " dB"; 312 << max_volume_ << " dB";
293 313
294 alsa_mixer_ = handle; 314 alsa_mixer_ = handle;
295 mixer_state_ = READY; 315 mixer_state_ = READY;
296 return true; 316 return true;
297 } 317 }
298 318
299 void AudioMixerAlsa::FreeAlsaMixer() { 319 void AudioMixerAlsa::FreeAlsaMixer() {
300 if (alsa_mixer_) { 320 if (alsa_mixer_) {
301 snd_mixer_close(alsa_mixer_); 321 snd_mixer_close(alsa_mixer_);
302 alsa_mixer_ = NULL; 322 alsa_mixer_ = NULL;
303 } 323 }
304 done_event_.Signal(); 324 done_event_.Signal();
305 } 325 }
306 326
307 void AudioMixerAlsa::DoSetVolumeMute(double pref_volume, int pref_mute) { 327 void AudioMixerAlsa::DoSetVolumeMute(double pref_volume, int pref_mute) {
308 base::AutoLock lock(mixer_state_lock_); 328 base::AutoLock lock(mixer_state_lock_);
309 if (mixer_state_ != READY) 329 if (mixer_state_ != READY)
310 return; 330 return;
311 331
312 // If volume or mute are invalid, set them now to the current actual values. 332 // If volume or mute are invalid, set them now to the current actual values.
313 if (!PrefVolumeValid(pref_volume)) 333 if (!PrefVolumeValid(pref_volume))
314 pref_volume = DoGetVolumeDb_Locked(); 334 pref_volume = DoGetVolumeDb_Locked();
315 bool mute; 335 bool mute = false;
316 if (pref_mute == kPrefMuteInvalid) 336 if (pref_mute == kPrefMuteInvalid)
317 mute = GetElementMuted_Locked(elem_master_); 337 mute = GetElementMuted_Locked(elem_master_);
318 else 338 else
319 mute = (pref_mute == kPrefMuteOn) ? true : false; 339 mute = (pref_mute == kPrefMuteOn) ? true : false;
320 340
321 VLOG(1) << "Setting volume to " << pref_volume << " and mute to " << mute; 341 VLOG(1) << "Setting volume to " << pref_volume << " and mute to " << mute;
322 342
323 if (mute) { 343 if (mute) {
324 save_volume_ = pref_volume; 344 save_volume_ = pref_volume;
325 DoSetVolumeDb_Locked(min_volume_); 345 DoSetVolumeDb_Locked(min_volume_);
(...skipping 15 matching lines...) Expand all
341 base::AutoLock lock(mixer_state_lock_); 361 base::AutoLock lock(mixer_state_lock_);
342 if (mixer_state_ == SHUTTING_DOWN) 362 if (mixer_state_ == SHUTTING_DOWN)
343 return; 363 return;
344 thread_->message_loop()->PostTask(FROM_HERE, 364 thread_->message_loop()->PostTask(FROM_HERE,
345 NewRunnableMethod(this, &AudioMixerAlsa::DoSetVolumeMute, vol, mute)); 365 NewRunnableMethod(this, &AudioMixerAlsa::DoSetVolumeMute, vol, mute));
346 } 366 }
347 } 367 }
348 368
349 double AudioMixerAlsa::DoGetVolumeDb_Locked() const { 369 double AudioMixerAlsa::DoGetVolumeDb_Locked() const {
350 double vol_total = 0.0; 370 double vol_total = 0.0;
351 GetElementVolume_Locked(elem_master_, &vol_total); 371 if (!GetElementVolume_Locked(elem_master_, &vol_total))
372 return 0.0;
352 373
353 double vol_pcm = 0.0; 374 double vol_pcm = 0.0;
354 if (elem_pcm_ && (GetElementVolume_Locked(elem_pcm_, &vol_pcm))) 375 if (elem_pcm_ && GetElementVolume_Locked(elem_pcm_, &vol_pcm))
355 vol_total += vol_pcm; 376 vol_total += vol_pcm;
356 377
357 return vol_total; 378 return vol_total;
358 } 379 }
359 380
360 void AudioMixerAlsa::DoSetVolumeDb_Locked(double vol_db) { 381 void AudioMixerAlsa::DoSetVolumeDb_Locked(double vol_db) {
361 double actual_vol = 0.0; 382 double actual_vol = 0.0;
362 383
363 // If a PCM volume slider exists, then first set the Master volume to the 384 // If a PCM volume slider exists, then first set the Master volume to the
364 // nearest volume >= requested volume, then adjust PCM volume down to get 385 // nearest volume >= requested volume, then adjust PCM volume down to get
(...skipping 24 matching lines...) Expand all
389 << snd_mixer_selem_id_get_name(sid); 410 << snd_mixer_selem_id_get_name(sid);
390 } 411 }
391 412
392 snd_mixer_selem_id_free(sid); 413 snd_mixer_selem_id_free(sid);
393 return elem; 414 return elem;
394 } 415 }
395 416
396 bool AudioMixerAlsa::GetElementVolume_Locked(snd_mixer_elem_t* elem, 417 bool AudioMixerAlsa::GetElementVolume_Locked(snd_mixer_elem_t* elem,
397 double* current_vol) const { 418 double* current_vol) const {
398 alsa_long_t long_vol = 0; 419 alsa_long_t long_vol = 0;
399 snd_mixer_selem_get_playback_dB(elem, 420 int alsa_result = snd_mixer_selem_get_playback_dB(
400 static_cast<snd_mixer_selem_channel_id_t>(0), 421 elem, static_cast<snd_mixer_selem_channel_id_t>(0), &long_vol);
401 &long_vol); 422 if (alsa_result != 0) {
423 LOG(WARNING) << "snd_mixer_selem_get_playback_dB() failed: "
424 << snd_strerror(alsa_result);
425 return false;
426 }
427
402 *current_vol = static_cast<double>(long_vol) / 100.0; 428 *current_vol = static_cast<double>(long_vol) / 100.0;
403
404 return true; 429 return true;
405 } 430 }
406 431
407 bool AudioMixerAlsa::SetElementVolume_Locked(snd_mixer_elem_t* elem, 432 bool AudioMixerAlsa::SetElementVolume_Locked(snd_mixer_elem_t* elem,
408 double new_vol, 433 double new_vol,
409 double* actual_vol, 434 double* actual_vol,
410 double rounding_bias) { 435 double rounding_bias) {
411 alsa_long_t vol_lo = 0; 436 alsa_long_t vol_lo = 0;
412 alsa_long_t vol_hi = 0; 437 alsa_long_t vol_hi = 0;
413 snd_mixer_selem_get_playback_volume_range(elem, &vol_lo, &vol_hi); 438 int alsa_result =
439 snd_mixer_selem_get_playback_volume_range(elem, &vol_lo, &vol_hi);
440 if (alsa_result != 0) {
441 LOG(WARNING) << "snd_mixer_selem_get_playback_volume_range() failed: "
442 << snd_strerror(alsa_result);
443 return false;
444 }
414 alsa_long_t vol_range = vol_hi - vol_lo; 445 alsa_long_t vol_range = vol_hi - vol_lo;
415 if (vol_range <= 0) 446 if (vol_range <= 0)
416 return false; 447 return false;
417 448
418 alsa_long_t db_lo_int = 0; 449 alsa_long_t db_lo_int = 0;
419 alsa_long_t db_hi_int = 0; 450 alsa_long_t db_hi_int = 0;
420 snd_mixer_selem_get_playback_dB_range(elem, &db_lo_int, &db_hi_int); 451 alsa_result =
452 snd_mixer_selem_get_playback_dB_range(elem, &db_lo_int, &db_hi_int);
453 if (alsa_result != 0) {
454 LOG(WARNING) << "snd_mixer_selem_get_playback_dB_range() failed: "
455 << snd_strerror(alsa_result);
456 return false;
457 }
458
421 double db_lo = static_cast<double>(db_lo_int) / 100.0; 459 double db_lo = static_cast<double>(db_lo_int) / 100.0;
422 double db_hi = static_cast<double>(db_hi_int) / 100.0; 460 double db_hi = static_cast<double>(db_hi_int) / 100.0;
423 double db_step = static_cast<double>(db_hi - db_lo) / vol_range; 461 double db_step = static_cast<double>(db_hi - db_lo) / vol_range;
424 if (db_step <= 0.0) 462 if (db_step <= 0.0)
425 return false; 463 return false;
426 464
427 if (new_vol < db_lo) 465 if (new_vol < db_lo)
428 new_vol = db_lo; 466 new_vol = db_lo;
429 467
430 alsa_long_t value = static_cast<alsa_long_t>(rounding_bias + 468 alsa_long_t value = static_cast<alsa_long_t>(rounding_bias +
431 (new_vol - db_lo) / db_step) + vol_lo; 469 (new_vol - db_lo) / db_step) + vol_lo;
432 snd_mixer_selem_set_playback_volume_all(elem, value); 470 alsa_result = snd_mixer_selem_set_playback_volume_all(elem, value);
471 if (alsa_result != 0) {
472 LOG(WARNING) << "snd_mixer_selem_set_playback_volume_all() failed: "
473 << snd_strerror(alsa_result);
474 return false;
475 }
433 476
434 VLOG(1) << "Set volume " << snd_mixer_selem_get_name(elem) 477 VLOG(1) << "Set volume " << snd_mixer_selem_get_name(elem)
435 << " to " << new_vol << " ==> " << (value - vol_lo) * db_step + db_lo 478 << " to " << new_vol << " ==> " << (value - vol_lo) * db_step + db_lo
436 << " dB"; 479 << " dB";
437 480
438 if (actual_vol) { 481 if (actual_vol) {
439 alsa_long_t volume = vol_lo; 482 alsa_long_t volume = vol_lo;
440 snd_mixer_selem_get_playback_volume( 483 alsa_result = snd_mixer_selem_get_playback_volume(
441 elem, 484 elem, static_cast<snd_mixer_selem_channel_id_t>(0), &volume);
442 static_cast<snd_mixer_selem_channel_id_t>(0), 485 if (alsa_result != 0) {
443 &volume); 486 LOG(WARNING) << "snd_mixer_selem_get_playback_volume() failed: "
487 << snd_strerror(alsa_result);
488 return false;
489 }
444 *actual_vol = db_lo + (volume - vol_lo) * db_step; 490 *actual_vol = db_lo + (volume - vol_lo) * db_step;
445 491
446 VLOG(1) << "Actual volume " << snd_mixer_selem_get_name(elem) 492 VLOG(1) << "Actual volume " << snd_mixer_selem_get_name(elem)
447 << " now " << *actual_vol << " dB"; 493 << " now " << *actual_vol << " dB";
448 } 494 }
449 return true; 495 return true;
450 } 496 }
451 497
452 bool AudioMixerAlsa::GetElementMuted_Locked(snd_mixer_elem_t* elem) const { 498 bool AudioMixerAlsa::GetElementMuted_Locked(snd_mixer_elem_t* elem) const {
453 int enabled = 0; 499 int enabled = 0;
454 snd_mixer_selem_get_playback_switch( 500 int alsa_result = snd_mixer_selem_get_playback_switch(
455 elem, 501 elem, static_cast<snd_mixer_selem_channel_id_t>(0), &enabled);
456 static_cast<snd_mixer_selem_channel_id_t>(0), 502 if (alsa_result != 0) {
457 &enabled); 503 LOG(WARNING) << "snd_mixer_selem_get_playback_switch() failed: "
504 << snd_strerror(alsa_result);
505 return false;
506 }
458 return (enabled) ? false : true; 507 return (enabled) ? false : true;
459 } 508 }
460 509
461 void AudioMixerAlsa::SetElementMuted_Locked(snd_mixer_elem_t* elem, bool mute) { 510 void AudioMixerAlsa::SetElementMuted_Locked(snd_mixer_elem_t* elem, bool mute) {
462 int enabled = mute ? 0 : 1; 511 int enabled = mute ? 0 : 1;
463 snd_mixer_selem_set_playback_switch_all(elem, enabled); 512 int alsa_result = snd_mixer_selem_set_playback_switch_all(elem, enabled);
464 513 if (alsa_result != 0) {
465 VLOG(1) << "Set playback switch " << snd_mixer_selem_get_name(elem) 514 LOG(WARNING) << "snd_mixer_selem_set_playback_switch_all() failed: "
466 << " to " << enabled; 515 << snd_strerror(alsa_result);
516 } else {
517 VLOG(1) << "Set playback switch " << snd_mixer_selem_get_name(elem)
518 << " to " << enabled;
519 }
467 } 520 }
468 521
469 } // namespace chromeos 522 } // namespace chromeos
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