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

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: Adding ALSA volume support 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"
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
29 const int kUsingPulseAudio = 0;
30 const int kUsingAlsa = 1;
31 const int kUsingNone = 2;
32
28 } // namespace 33 } // namespace
29 34
30 // This class will set volume using PulseAudio to adjust volume and mute, and 35 // This class will set volume using PulseAudio or ALSA to adjust volume and
31 // handles the volume level logic. 36 // mute, and handles the volume level logic.
32
33 // TODO(davej): Serialize volume/mute for next startup?
34 37
35 double AudioHandler::GetVolumePercent() { 38 double AudioHandler::GetVolumePercent() {
36 if (!VerifyMixerConnection()) 39 if (!VerifyMixerConnection())
37 return 0; 40 return 0;
38 41
39 return VolumeDbToPercent(mixer_->GetVolumeDb()); 42 return VolumeDbToPercent(mixer_->GetVolumeDb());
40 } 43 }
41 44
42 // Set volume using our internal 0-100% range. Notice 0% is a special case of 45 // 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. 46 // silence, so we set the mixer volume to kSilenceDb instead of min_volume_db_.
44 void AudioHandler::SetVolumePercent(double volume_percent) { 47 void AudioHandler::SetVolumePercent(double volume_percent) {
45 if (!VerifyMixerConnection()) 48 if (!VerifyMixerConnection())
46 return; 49 return;
47 DCHECK(volume_percent >= 0.0); 50 DCHECK(volume_percent >= 0.0);
48 51
49 double vol_db; 52 double vol_db;
50 if (volume_percent <= 0) 53 if (volume_percent <= 0)
51 vol_db = kSilenceDb; 54 vol_db = kSilenceDb;
52 else 55 else
53 vol_db = PercentToVolumeDb(volume_percent); 56 vol_db = PercentToVolumeDb(volume_percent);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 92
90 void AudioHandler::SetMute(bool do_mute) { 93 void AudioHandler::SetMute(bool do_mute) {
91 if (!VerifyMixerConnection()) 94 if (!VerifyMixerConnection())
92 return; 95 return;
93 96
94 DVLOG(1) << "Setting Mute to " << do_mute; 97 DVLOG(1) << "Setting Mute to " << do_mute;
95 98
96 mixer_->SetMute(do_mute); 99 mixer_->SetMute(do_mute);
97 } 100 }
98 101
102 bool AudioHandler::TryToConnect(bool async) {
103 if (using_mixer_ == kUsingPulseAudio) {
104 VLOG(1) << "Trying to connect to PulseAudio";
105 mixer_.reset(new AudioMixerPulse());
106 } else if (using_mixer_ == kUsingAlsa) {
107 VLOG(1) << "Trying to connect to ALSA";
108 mixer_.reset(new AudioMixerAlsa());
109 } else {
110 VLOG(1) << "Cannot find valid volume mixer";
111 mixer_.reset();
112 return false;
113 }
114
115 if (async) {
116 if (mixer_->Init(NewCallback(this, &AudioHandler::OnMixerInitialized)))
117 return true;
118 } else {
119 if (mixer_->InitSync())
120 return true;
121 VLOG(1) << "Unable to reconnect to Mixer";
122 }
123 return false;
124 }
125
99 void AudioHandler::OnMixerInitialized(bool success) { 126 void AudioHandler::OnMixerInitialized(bool success) {
100 connected_ = success; 127 connected_ = success;
101 DVLOG(1) << "OnMixerInitialized, success = " << success; 128 DVLOG(1) << "OnMixerInitialized, success = " << success;
129
130 if (connected_) {
131 mixer_->GetVolumeLimits(&min_volume_db_, &max_volume_db_);
132 if (min_volume_db_ < kMinVolumeDb)
133 min_volume_db_ = kMinVolumeDb;
134 if (max_volume_db_ > kMaxVolumeDb)
135 max_volume_db_ = kMaxVolumeDb;
136 } else {
137 ++using_mixer_;
Daniel Erat 2010/12/20 22:01:12 this seems fragile; please spell out the transitio
davejcool 2010/12/21 02:00:21 Now logic is in UseNextMixer()
138 VLOG(1) << "Unable to connect to Mixer, trying next";
139
140 BrowserThread::PostTask(
141 BrowserThread::UI, FROM_HERE,
142 NewRunnableMethod(this, &AudioHandler::TryToConnect, true));
143 }
102 } 144 }
103 145
104 AudioHandler::AudioHandler() 146 AudioHandler::AudioHandler()
105 : connected_(false), 147 : connected_(false),
106 reconnect_tries_(0) { 148 reconnect_tries_(0),
107 mixer_.reset(new PulseAudioMixer()); 149 max_volume_db_(0),
108 if (!mixer_->Init(NewCallback(this, &AudioHandler::OnMixerInitialized))) { 150 min_volume_db_(-90),
109 LOG(ERROR) << "Unable to connect to PulseAudio"; 151 using_mixer_(kUsingPulseAudio) {
152 while (using_mixer_ != kUsingNone) {
153 if (TryToConnect(true)) {
154 break;
155 }
156 ++using_mixer_;
110 } 157 }
111 } 158 }
112 159
113 AudioHandler::~AudioHandler() { 160 AudioHandler::~AudioHandler() {
114 mixer_.reset(); 161 mixer_.reset();
115 }; 162 };
116 163
117 bool AudioHandler::VerifyMixerConnection() { 164 bool AudioHandler::VerifyMixerConnection() {
118 PulseAudioMixer::State mixer_state = mixer_->CheckState(); 165 if (mixer_ == NULL)
119 if (mixer_state == PulseAudioMixer::READY) 166 return false;
167
168 AudioMixerBase::State mixer_state = mixer_->CheckState();
169 if (mixer_state == AudioMixerBase::READY)
120 return true; 170 return true;
121 if (connected_) { 171 if (connected_) {
122 // Something happened and the mixer is no longer valid after having been 172 // Something happened and the mixer is no longer valid after having been
123 // initialized earlier. 173 // initialized earlier.
124 connected_ = false; 174 connected_ = false;
125 LOG(ERROR) << "Lost connection to PulseAudio"; 175 LOG(ERROR) << "Lost connection to Mixer";
Daniel Erat 2010/12/20 22:01:12 nit: make all of the "mixer"s in these comments lo
126 } else { 176 } else {
127 LOG(ERROR) << "Mixer not valid"; 177 LOG(ERROR) << "Mixer not valid";
128 } 178 }
129 179
130 if ((mixer_state == PulseAudioMixer::INITIALIZING) || 180 if ((mixer_state == AudioMixerBase::INITIALIZING) ||
131 (mixer_state == PulseAudioMixer::SHUTTING_DOWN)) 181 (mixer_state == AudioMixerBase::SHUTTING_DOWN))
132 return false; 182 return false;
133 183
134 if (reconnect_tries_ < kMaxReconnectTries) { 184 if (reconnect_tries_ < kMaxReconnectTries) {
135 reconnect_tries_++; 185 reconnect_tries_++;
136 VLOG(1) << "Re-connecting to PulseAudio attempt " << reconnect_tries_ << "/" 186 VLOG(1) << "Re-connecting to Mixer attempt " << reconnect_tries_ << "/"
137 << kMaxReconnectTries; 187 << kMaxReconnectTries;
138 mixer_.reset(new PulseAudioMixer()); 188
139 connected_ = mixer_->InitSync(); 189 connected_ = TryToConnect(false);
190
140 if (connected_) { 191 if (connected_) {
141 reconnect_tries_ = 0; 192 reconnect_tries_ = 0;
142 return true; 193 return true;
143 } 194 }
144 LOG(ERROR) << "Unable to re-connect to PulseAudio"; 195 LOG(ERROR) << "Unable to re-connect to Mixer";
145 } 196 }
146 return false; 197 return false;
147 } 198 }
148 199
149 // VolumeDbToPercent() and PercentToVolumeDb() conversion functions allow us 200 // VolumeDbToPercent() and PercentToVolumeDb() conversion functions allow us
150 // complete control over how the 0 to 100% range is mapped to actual loudness. 201 // 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% 202 // 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. 203 // at 100% with a special case at 0% which maps to kSilenceDb.
153 // 204 //
154 // The mapping is confined to these two functions to make it easy to adjust and 205 // 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 206 // 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. 207 // in the higher volumes if kVolumeBias is less than 1.0.
157 208
158 // static 209 // static
159 double AudioHandler::VolumeDbToPercent(double volume_db) { 210 double AudioHandler::VolumeDbToPercent(double volume_db) const {
160 if (volume_db < kMinVolumeDb) 211 if (volume_db < min_volume_db_)
161 return 0; 212 return 0;
162 return 100.0 * pow((volume_db - kMinVolumeDb) / 213 return 100.0 * pow((volume_db - min_volume_db_) /
163 (kMaxVolumeDb - kMinVolumeDb), 1/kVolumeBias); 214 (max_volume_db_ - min_volume_db_), 1/kVolumeBias);
164 } 215 }
165 216
166 // static 217 // static
167 double AudioHandler::PercentToVolumeDb(double volume_percent) { 218 double AudioHandler::PercentToVolumeDb(double volume_percent) const {
168 return pow(volume_percent / 100.0, kVolumeBias) * 219 return pow(volume_percent / 100.0, kVolumeBias) *
169 (kMaxVolumeDb - kMinVolumeDb) + kMinVolumeDb; 220 (max_volume_db_ - min_volume_db_) + min_volume_db_;
170 } 221 }
171 222
172 // static 223 // static
173 AudioHandler* AudioHandler::instance() { 224 AudioHandler* AudioHandler::instance() {
174 return Singleton<AudioHandler>::get(); 225 return Singleton<AudioHandler>::get();
175 } 226 }
176 227
177 } // namespace chromeos 228 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698