diff options
author | derat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-01 21:44:33 +0000 |
---|---|---|
committer | derat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-01 21:44:33 +0000 |
commit | 3a3a6f42941903cb6af8c5df2e6ebdfd9e0b57cf (patch) | |
tree | 274e0e3f28622d1e10ec5131bf2d94ded34d512a | |
parent | a3845c429cc361407e0d436d7ddba520580ec6bb (diff) | |
download | chromium_src-3a3a6f42941903cb6af8c5df2e6ebdfd9e0b57cf.zip chromium_src-3a3a6f42941903cb6af8c5df2e6ebdfd9e0b57cf.tar.gz chromium_src-3a3a6f42941903cb6af8c5df2e6ebdfd9e0b57cf.tar.bz2 |
chromeos: Make mixer code also look for mixers on ARM.
This makes the ALSA code look for controls named Headphone
and Speaker in addition to the already-supported Master
control.
BUG=chromium-os:18284
TEST=still works on x86
Review URL: http://codereview.chromium.org/7523050
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@94985 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/chromeos/audio_mixer_alsa.cc | 84 | ||||
-rw-r--r-- | chrome/browser/chromeos/audio_mixer_alsa.h | 16 |
2 files changed, 64 insertions, 36 deletions
diff --git a/chrome/browser/chromeos/audio_mixer_alsa.cc b/chrome/browser/chromeos/audio_mixer_alsa.cc index c627093..68c3da9 100644 --- a/chrome/browser/chromeos/audio_mixer_alsa.cc +++ b/chrome/browser/chromeos/audio_mixer_alsa.cc @@ -25,6 +25,8 @@ typedef long alsa_long_t; // 'long' is required for ALSA API calls. using std::max; using std::min; +using std::string; +using std::vector; namespace chromeos { @@ -33,8 +35,13 @@ namespace { // Name of the ALSA card to which we connect. const char kCardName[] = "default"; -// Mixer element names. -const char kMasterElementName[] = "Master"; +// Mixer element names. We keep an array of possible master element names and +// will control all that exist. +const char* const kMasterElementNames[] = { + "Master", + "Headphone", + "Speaker", +}; const char kPCMElementName[] = "PCM"; // Default minimum and maximum volume (before we've loaded the actual range from @@ -61,8 +68,7 @@ AudioMixerAlsa::AudioMixerAlsa() is_muted_(false), apply_is_pending_(true), alsa_mixer_(NULL), - element_master_(NULL), - element_pcm_(NULL), + pcm_element_(NULL), prefs_(NULL), disconnected_event_(true, false) { } @@ -220,33 +226,39 @@ bool AudioMixerAlsa::ConnectInternal() { double min_volume_db = kDefaultMinVolumeDb; double max_volume_db = kDefaultMaxVolumeDb; - element_master_ = FindElementWithName(handle, kMasterElementName); - if (element_master_) { - alsa_long_t long_low = static_cast<alsa_long_t>(kDefaultMinVolumeDb * 100); - alsa_long_t long_high = static_cast<alsa_long_t>(kDefaultMaxVolumeDb * 100); - err = snd_mixer_selem_get_playback_dB_range( - element_master_, &long_low, &long_high); - if (err != 0) { - LOG(WARNING) << "snd_mixer_selem_get_playback_dB_range() failed " - << "for " << kMasterElementName << ": " << snd_strerror(err); - snd_mixer_close(handle); - return false; - } - min_volume_db = static_cast<double>(long_low) / 100.0; - max_volume_db = static_cast<double>(long_high) / 100.0; - } else { - LOG(WARNING) << "Cannot find " << kMasterElementName - << " ALSA mixer element on " << kCardName; + vector<snd_mixer_elem_t*> master_elements; + for (size_t i = 0; i < arraysize(kMasterElementNames); ++i) { + snd_mixer_elem_t* element = + FindElementWithName(handle, kMasterElementNames[i]); + if (element) + master_elements.push_back(element); + } + + if (master_elements.empty()) { + LOG(WARNING) << "Unable to find any ALSA mixer elements on " << kCardName; + snd_mixer_close(handle); + return false; + } + + alsa_long_t long_low = static_cast<alsa_long_t>(kDefaultMinVolumeDb * 100); + alsa_long_t long_high = static_cast<alsa_long_t>(kDefaultMaxVolumeDb * 100); + err = snd_mixer_selem_get_playback_dB_range( + master_elements.at(0), &long_low, &long_high); + if (err != 0) { + LOG(WARNING) << "snd_mixer_selem_get_playback_dB_range() failed:" + << snd_strerror(err); snd_mixer_close(handle); return false; } + min_volume_db = static_cast<double>(long_low) / 100.0; + max_volume_db = static_cast<double>(long_high) / 100.0; - element_pcm_ = FindElementWithName(handle, kPCMElementName); - if (element_pcm_) { + snd_mixer_elem_t* pcm_element = FindElementWithName(handle, kPCMElementName); + if (pcm_element) { alsa_long_t long_low = static_cast<alsa_long_t>(kDefaultMinVolumeDb * 100); alsa_long_t long_high = static_cast<alsa_long_t>(kDefaultMaxVolumeDb * 100); err = snd_mixer_selem_get_playback_dB_range( - element_pcm_, &long_low, &long_high); + pcm_element, &long_low, &long_high); if (err != 0) { LOG(WARNING) << "snd_mixer_selem_get_playback_dB_range() failed for " << kPCMElementName << ": " << snd_strerror(err); @@ -262,6 +274,8 @@ bool AudioMixerAlsa::ConnectInternal() { { base::AutoLock lock(lock_); alsa_mixer_ = handle; + master_elements_.swap(master_elements); + pcm_element_ = pcm_element; min_volume_db_ = min_volume_db; max_volume_db_ = max_volume_db; volume_db_ = min(max(volume_db_, min_volume_db_), max_volume_db_); @@ -294,26 +308,32 @@ void AudioMixerAlsa::ApplyState() { apply_is_pending_ = false; } - if (element_pcm_) { + if (pcm_element_) { // If a PCM volume slider exists, then first set the Master volume to the // nearest volume >= requested volume, then adjust PCM volume down to get // closer to the requested volume. - SetElementVolume(element_master_, new_volume_db, 0.9999f); + for (vector<snd_mixer_elem_t*>::iterator it = master_elements_.begin(); + it != master_elements_.end(); ++it) + SetElementVolume(*it, new_volume_db, 0.9999f); double pcm_volume_db = 0.0; double master_volume_db = 0.0; - if (GetElementVolume(element_master_, &master_volume_db)) + if (GetElementVolume(master_elements_.at(0), &master_volume_db)) pcm_volume_db = new_volume_db - master_volume_db; - SetElementVolume(element_pcm_, pcm_volume_db, 0.5f); + SetElementVolume(pcm_element_, pcm_volume_db, 0.5f); } else { - SetElementVolume(element_master_, new_volume_db, 0.5f); + for (vector<snd_mixer_elem_t*>::iterator it = master_elements_.begin(); + it != master_elements_.end(); ++it) + SetElementVolume(*it, new_volume_db, 0.5f); } - SetElementMuted(element_master_, should_mute); + for (vector<snd_mixer_elem_t*>::iterator it = master_elements_.begin(); + it != master_elements_.end(); ++it) + SetElementMuted(*it, should_mute); } snd_mixer_elem_t* AudioMixerAlsa::FindElementWithName( - snd_mixer_t* handle, const char* element_name) const { + snd_mixer_t* handle, const string& element_name) const { DCHECK(MessageLoop::current() == thread_->message_loop()); snd_mixer_selem_id_t* sid = NULL; @@ -323,7 +343,7 @@ snd_mixer_elem_t* AudioMixerAlsa::FindElementWithName( return NULL; snd_mixer_selem_id_set_index(sid, 0); - snd_mixer_selem_id_set_name(sid, element_name); + snd_mixer_selem_id_set_name(sid, element_name.c_str()); snd_mixer_elem_t* element = snd_mixer_find_selem(handle, sid); if (!element) { LOG(WARNING) << "ALSA unable to find simple control " diff --git a/chrome/browser/chromeos/audio_mixer_alsa.h b/chrome/browser/chromeos/audio_mixer_alsa.h index bd24e0d..d09d323 100644 --- a/chrome/browser/chromeos/audio_mixer_alsa.h +++ b/chrome/browser/chromeos/audio_mixer_alsa.h @@ -6,6 +6,9 @@ #define CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_ALSA_H_ #pragma once +#include <string> +#include <vector> + #include "base/basictypes.h" #include "base/callback_old.h" #include "base/memory/scoped_ptr.h" @@ -61,7 +64,7 @@ class AudioMixerAlsa : public AudioMixer { // Finds the element named |element_name|. Returns NULL on failure. _snd_mixer_elem* FindElementWithName(_snd_mixer* handle, - const char* element_name) const; + const std::string& element_name) const; // Queries |element|'s current volume, copying it to |new_volume_db|. // Returns true on success. @@ -96,10 +99,15 @@ class AudioMixerAlsa : public AudioMixer { // Is there already a pending call to ApplyState() scheduled on |thread_|? bool apply_is_pending_; - // Cached context for use in ALSA calls. NULL if not connected. + // Connection to ALSA. NULL if not connected. _snd_mixer* alsa_mixer_; - _snd_mixer_elem* element_master_; - _snd_mixer_elem* element_pcm_; + + // Master mixers (some hardware has e.g. separate headphone and speaker + // elements). + std::vector<_snd_mixer_elem*> master_elements_; + + // PCM mixer. May be NULL if the driver doesn't expose one. + _snd_mixer_elem* pcm_element_; PrefService* prefs_; |