summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/audio_mixer_alsa.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/chromeos/audio_mixer_alsa.cc')
-rw-r--r--chrome/browser/chromeos/audio_mixer_alsa.cc84
1 files changed, 52 insertions, 32 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 "