summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorderat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-01 21:44:33 +0000
committerderat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-01 21:44:33 +0000
commit3a3a6f42941903cb6af8c5df2e6ebdfd9e0b57cf (patch)
tree274e0e3f28622d1e10ec5131bf2d94ded34d512a
parenta3845c429cc361407e0d436d7ddba520580ec6bb (diff)
downloadchromium_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.cc84
-rw-r--r--chrome/browser/chromeos/audio_mixer_alsa.h16
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_;