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

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

Issue 5859003: Add ALSA support to volume keys (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/chrome/browser/chromeos
Patch Set: cleanups Created 10 years 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
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_handler.h" 5 #include "chrome/browser/chromeos/audio_handler.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/singleton.h" 10 #include "base/singleton.h"
11 #include "chrome/browser/chromeos/pulse_audio_mixer.h" 11 #include "chrome/browser/chromeos/audio_mixer_pulse.h"
12 #include "chrome/browser/chromeos/audio_mixer_alsa.h"
scherkus (not reviewing) 2010/12/22 22:31:58 nit: alphabetize include order
13 #include "chrome/browser/browser_thread.h"
12 14
13 namespace chromeos { 15 namespace chromeos {
14 16
15 namespace { 17 namespace {
16 18
17 const double kSilenceDb = -200.0;
18 const double kMinVolumeDb = -90.0; 19 const double kMinVolumeDb = -90.0;
19 // Choosing 6.0dB here instead of 0dB to give user chance to amplify audio some 20 // Choosing 6.0dB here instead of 0dB to give user chance to amplify audio some
20 // in case sounds or their setup is too quiet for them. 21 // in case sounds or their setup is too quiet for them.
21 const double kMaxVolumeDb = 6.0; 22 const double kMaxVolumeDb = 6.0;
22 // A value of less than one adjusts quieter volumes in larger steps (giving 23 // A value of less than one adjusts quieter volumes in larger steps (giving
23 // finer resolution in the higher volumes). 24 // finer resolution in the higher volumes).
24 const double kVolumeBias = 0.5; 25 const double kVolumeBias = 0.5;
25 // If a connection is lost, we try again this many times 26 // If a connection is lost, we try again this many times
26 const int kMaxReconnectTries = 4; 27 const int kMaxReconnectTries = 4;
27 28
28 } // namespace 29 } // namespace
29 30
30 // This class will set volume using PulseAudio to adjust volume and mute, and 31 // This class will set volume using PulseAudio or ALSA to adjust volume and
31 // handles the volume level logic. 32 // mute, and handles the volume level logic.
32
33 // TODO(davej): Serialize volume/mute for next startup?
34 33
35 double AudioHandler::GetVolumePercent() { 34 double AudioHandler::GetVolumePercent() {
36 if (!VerifyMixerConnection()) 35 if (!VerifyMixerConnection())
37 return 0; 36 return 0;
38 37
39 return VolumeDbToPercent(mixer_->GetVolumeDb()); 38 return VolumeDbToPercent(mixer_->GetVolumeDb());
40 } 39 }
41 40
42 // Set volume using our internal 0-100% range. Notice 0% is a special case of 41 // Set volume using our internal 0-100% range. Notice 0% is a special case of
43 // silence, so we set the mixer volume to kSilenceDb instead of kMinVolumeDb. 42 // silence, so we set the mixer volume to kSilenceDb instead of min_volume_db_.
44 void AudioHandler::SetVolumePercent(double volume_percent) { 43 void AudioHandler::SetVolumePercent(double volume_percent) {
45 if (!VerifyMixerConnection()) 44 if (!VerifyMixerConnection())
46 return; 45 return;
47 DCHECK(volume_percent >= 0.0); 46 DCHECK(volume_percent >= 0.0);
48 47
49 double vol_db; 48 double vol_db;
50 if (volume_percent <= 0) 49 if (volume_percent <= 0)
51 vol_db = kSilenceDb; 50 vol_db = kSilenceDb;
52 else 51 else
53 vol_db = PercentToVolumeDb(volume_percent); 52 vol_db = PercentToVolumeDb(volume_percent);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 88
90 void AudioHandler::SetMute(bool do_mute) { 89 void AudioHandler::SetMute(bool do_mute) {
91 if (!VerifyMixerConnection()) 90 if (!VerifyMixerConnection())
92 return; 91 return;
93 92
94 DVLOG(1) << "Setting Mute to " << do_mute; 93 DVLOG(1) << "Setting Mute to " << do_mute;
95 94
96 mixer_->SetMute(do_mute); 95 mixer_->SetMute(do_mute);
97 } 96 }
98 97
98 bool AudioHandler::TryToConnect(bool async) {
99 if (using_mixer_ == MIXER_TYPE_PULSEAUDIO) {
100 VLOG(1) << "Trying to connect to PulseAudio";
101 mixer_.reset(new AudioMixerPulse());
102 } else if (using_mixer_ == MIXER_TYPE_ALSA) {
103 VLOG(1) << "Trying to connect to ALSA";
104 mixer_.reset(new AudioMixerAlsa());
105 } else {
106 VLOG(1) << "Cannot find valid volume mixer";
107 mixer_.reset();
108 return false;
109 }
110
111 if (async) {
112 if (mixer_->Init(NewCallback(this, &AudioHandler::OnMixerInitialized)))
113 return true;
114 } else {
115 if (mixer_->InitSync())
116 return true;
zhurunz 2010/12/22 22:21:26 Prefer early-return only on error cases, and retur
davejcool 2010/12/23 03:09:02 Fixed.
117 VLOG(1) << "Unable to reconnect to Mixer";
118 }
119 return false;
120 }
121
122 void AudioHandler::UseNextMixer() {
123 if (using_mixer_ == MIXER_TYPE_PULSEAUDIO)
124 using_mixer_ = MIXER_TYPE_ALSA;
125 else
126 using_mixer_ = MIXER_TYPE_NONE;
127 }
128
99 void AudioHandler::OnMixerInitialized(bool success) { 129 void AudioHandler::OnMixerInitialized(bool success) {
100 connected_ = success; 130 connected_ = success;
101 DVLOG(1) << "OnMixerInitialized, success = " << success; 131 DVLOG(1) << "OnMixerInitialized, success = " << success;
132
133 if (connected_) {
134 mixer_->GetVolumeLimits(&min_volume_db_, &max_volume_db_);
zhurunz 2010/12/22 22:21:26 undefined mXX_volume_db_ on error?
davejcool 2010/12/23 03:09:02 Values are unchanged on error, but now GetVolumeLi
135 if (min_volume_db_ < kMinVolumeDb)
136 min_volume_db_ = kMinVolumeDb;
137 if (max_volume_db_ > kMaxVolumeDb)
138 max_volume_db_ = kMaxVolumeDb;
zhurunz 2010/12/22 22:21:26 Suggest moving this into a utility function. Somet
139 } else {
140 UseNextMixer();
141 VLOG(1) << "Unable to connect to mixer, trying next";
142
143 BrowserThread::PostTask(
144 BrowserThread::UI, FROM_HERE,
145 NewRunnableMethod(this, &AudioHandler::TryToConnect, true));
146 }
102 } 147 }
103 148
104 AudioHandler::AudioHandler() 149 AudioHandler::AudioHandler()
105 : connected_(false), 150 : connected_(false),
106 reconnect_tries_(0) { 151 reconnect_tries_(0),
107 mixer_.reset(new PulseAudioMixer()); 152 max_volume_db_(0),
108 if (!mixer_->Init(NewCallback(this, &AudioHandler::OnMixerInitialized))) { 153 min_volume_db_(-90),
109 LOG(ERROR) << "Unable to connect to PulseAudio"; 154 using_mixer_(MIXER_TYPE_PULSEAUDIO) {
155 while (using_mixer_ != MIXER_TYPE_NONE) {
156 if (TryToConnect(true)) {
157 break;
158 }
159 UseNextMixer();
110 } 160 }
111 } 161 }
112 162
113 AudioHandler::~AudioHandler() { 163 AudioHandler::~AudioHandler() {
114 mixer_.reset(); 164 mixer_.reset();
115 }; 165 };
116 166
117 bool AudioHandler::VerifyMixerConnection() { 167 bool AudioHandler::VerifyMixerConnection() {
118 PulseAudioMixer::State mixer_state = mixer_->CheckState(); 168 if (mixer_ == NULL)
119 if (mixer_state == PulseAudioMixer::READY) 169 return false;
170
171 AudioMixerBase::State mixer_state = mixer_->CheckState();
172 if (mixer_state == AudioMixerBase::READY)
120 return true; 173 return true;
121 if (connected_) { 174 if (connected_) {
122 // Something happened and the mixer is no longer valid after having been 175 // Something happened and the mixer is no longer valid after having been
123 // initialized earlier. 176 // initialized earlier.
124 connected_ = false; 177 connected_ = false;
125 LOG(ERROR) << "Lost connection to PulseAudio"; 178 LOG(ERROR) << "Lost connection to mixer";
126 } else { 179 } else {
127 LOG(ERROR) << "Mixer not valid"; 180 LOG(ERROR) << "Mixer not valid";
128 } 181 }
129 182
130 if ((mixer_state == PulseAudioMixer::INITIALIZING) || 183 if ((mixer_state == AudioMixerBase::INITIALIZING) ||
131 (mixer_state == PulseAudioMixer::SHUTTING_DOWN)) 184 (mixer_state == AudioMixerBase::SHUTTING_DOWN))
132 return false; 185 return false;
133 186
134 if (reconnect_tries_ < kMaxReconnectTries) { 187 if (reconnect_tries_ < kMaxReconnectTries) {
135 reconnect_tries_++; 188 reconnect_tries_++;
136 VLOG(1) << "Re-connecting to PulseAudio attempt " << reconnect_tries_ << "/" 189 VLOG(1) << "Re-connecting to mixer attempt " << reconnect_tries_ << "/"
137 << kMaxReconnectTries; 190 << kMaxReconnectTries;
138 mixer_.reset(new PulseAudioMixer()); 191
139 connected_ = mixer_->InitSync(); 192 connected_ = TryToConnect(false);
193
140 if (connected_) { 194 if (connected_) {
141 reconnect_tries_ = 0; 195 reconnect_tries_ = 0;
142 return true; 196 return true;
143 } 197 }
144 LOG(ERROR) << "Unable to re-connect to PulseAudio"; 198 LOG(ERROR) << "Unable to re-connect to mixer";
145 } 199 }
146 return false; 200 return false;
147 } 201 }
148 202
149 // VolumeDbToPercent() and PercentToVolumeDb() conversion functions allow us 203 // VolumeDbToPercent() and PercentToVolumeDb() conversion functions allow us
150 // complete control over how the 0 to 100% range is mapped to actual loudness. 204 // complete control over how the 0 to 100% range is mapped to actual loudness.
151 // Volume range is from kMinVolumeDb at just above 0% to kMaxVolumeDb at 100% 205 // Volume range is from min_volume_db_ at just above 0% to max_volume_db_
152 // with a special case at 0% which maps to kSilenceDb. 206 // at 100% with a special case at 0% which maps to kSilenceDb.
153 // 207 //
154 // The mapping is confined to these two functions to make it easy to adjust and 208 // The mapping is confined to these two functions to make it easy to adjust and
155 // have everything else just work. The range is biased to give finer resolution 209 // have everything else just work. The range is biased to give finer resolution
156 // in the higher volumes if kVolumeBias is less than 1.0. 210 // in the higher volumes if kVolumeBias is less than 1.0.
157 211
158 // static 212 // static
159 double AudioHandler::VolumeDbToPercent(double volume_db) { 213 double AudioHandler::VolumeDbToPercent(double volume_db) const {
160 if (volume_db < kMinVolumeDb) 214 if (volume_db < min_volume_db_)
161 return 0; 215 return 0;
162 return 100.0 * pow((volume_db - kMinVolumeDb) / 216 return 100.0 * pow((volume_db - min_volume_db_) /
163 (kMaxVolumeDb - kMinVolumeDb), 1/kVolumeBias); 217 (max_volume_db_ - min_volume_db_), 1/kVolumeBias);
164 } 218 }
165 219
166 // static 220 // static
167 double AudioHandler::PercentToVolumeDb(double volume_percent) { 221 double AudioHandler::PercentToVolumeDb(double volume_percent) const {
168 return pow(volume_percent / 100.0, kVolumeBias) * 222 return pow(volume_percent / 100.0, kVolumeBias) *
169 (kMaxVolumeDb - kMinVolumeDb) + kMinVolumeDb; 223 (max_volume_db_ - min_volume_db_) + min_volume_db_;
170 } 224 }
171 225
172 // static 226 // static
173 AudioHandler* AudioHandler::instance() { 227 AudioHandler* AudioHandler::instance() {
174 return Singleton<AudioHandler>::get(); 228 return Singleton<AudioHandler>::get();
175 } 229 }
176 230
177 } // namespace chromeos 231 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698