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

Side by Side Diff: chrome/browser/chromeos/audio/audio_mixer_alsa.cc

Issue 10873085: Implement two new policies to control muting the audio I/O. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 months 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/audio_mixer_alsa.h" 5 #include "chrome/browser/chromeos/audio/audio_mixer_alsa.h"
6 6
7 #include <unistd.h> 7 #include <unistd.h>
8 8
9 #include <alsa/asoundlib.h> 9 #include <alsa/asoundlib.h>
10 10
(...skipping 23 matching lines...) Expand all
34 const char kCardName[] = "default"; 34 const char kCardName[] = "default";
35 35
36 // Mixer element names. We'll use the first master element from the list that 36 // Mixer element names. We'll use the first master element from the list that
37 // exists. 37 // exists.
38 const char* const kMasterElementNames[] = { 38 const char* const kMasterElementNames[] = {
39 "Master", // x86 39 "Master", // x86
40 "Digital", // ARM 40 "Digital", // ARM
41 }; 41 };
42 const char kPCMElementName[] = "PCM"; 42 const char kPCMElementName[] = "PCM";
43 43
44 const char kMicElementName[] = "Mic";
45 const char kFrontMicElementName[] = "Front Mic";
46
44 // Default minimum and maximum volume (before we've loaded the actual range from 47 // Default minimum and maximum volume (before we've loaded the actual range from
45 // ALSA), in decibels. 48 // ALSA), in decibels.
46 const double kDefaultMinVolumeDb = -90.0; 49 const double kDefaultMinVolumeDb = -90.0;
47 const double kDefaultMaxVolumeDb = 0.0; 50 const double kDefaultMaxVolumeDb = 0.0;
48 51
49 // Default volume as a percentage in the range [0.0, 100.0]. 52 // Default volume as a percentage in the range [0.0, 100.0].
50 const double kDefaultVolumePercent = 75.0; 53 const double kDefaultVolumePercent = 75.0;
51 54
52 // A value of less than 1.0 adjusts quieter volumes in larger steps (giving 55 // A value of less than 1.0 adjusts quieter volumes in larger steps (giving
53 // finer resolution in the higher volumes). 56 // finer resolution in the higher volumes).
(...skipping 15 matching lines...) Expand all
69 72
70 AudioMixerAlsa::AudioMixerAlsa() 73 AudioMixerAlsa::AudioMixerAlsa()
71 : min_volume_db_(kDefaultMinVolumeDb), 74 : min_volume_db_(kDefaultMinVolumeDb),
72 max_volume_db_(kDefaultMaxVolumeDb), 75 max_volume_db_(kDefaultMaxVolumeDb),
73 volume_db_(kDefaultMinVolumeDb), 76 volume_db_(kDefaultMinVolumeDb),
74 is_muted_(false), 77 is_muted_(false),
75 apply_is_pending_(true), 78 apply_is_pending_(true),
76 initial_volume_percent_(kDefaultVolumePercent), 79 initial_volume_percent_(kDefaultVolumePercent),
77 alsa_mixer_(NULL), 80 alsa_mixer_(NULL),
78 pcm_element_(NULL), 81 pcm_element_(NULL),
82 mic_element_(NULL),
83 front_mic_element_(NULL),
79 disconnected_event_(true, false), 84 disconnected_event_(true, false),
80 num_connection_attempts_(0) { 85 num_connection_attempts_(0) {
81 } 86 }
82 87
83 AudioMixerAlsa::~AudioMixerAlsa() { 88 AudioMixerAlsa::~AudioMixerAlsa() {
84 if (!thread_.get()) 89 if (!thread_.get())
85 return; 90 return;
86 DCHECK(MessageLoop::current() != thread_->message_loop()); 91 DCHECK(MessageLoop::current() != thread_->message_loop());
87 92
88 thread_->message_loop()->PostTask( 93 thread_->message_loop()->PostTask(
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 } 139 }
135 140
136 bool AudioMixerAlsa::IsMuted() { 141 bool AudioMixerAlsa::IsMuted() {
137 base::AutoLock lock(lock_); 142 base::AutoLock lock(lock_);
138 return is_muted_; 143 return is_muted_;
139 } 144 }
140 145
141 void AudioMixerAlsa::SetMuted(bool muted) { 146 void AudioMixerAlsa::SetMuted(bool muted) {
142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
143 base::AutoLock lock(lock_); 148 base::AutoLock lock(lock_);
149 if (is_mute_locked_)
150 return;
144 is_muted_ = muted; 151 is_muted_ = muted;
145 if (!apply_is_pending_) 152 if (!apply_is_pending_)
Daniel Erat 2012/08/27 17:38:35 nit: add curly braces since the statement doesn't
pastarmovj 2012/08/28 15:11:50 Done.
146 thread_->message_loop()->PostTask(FROM_HERE, 153 thread_->message_loop()->PostTask(FROM_HERE,
147 base::Bind(&AudioMixerAlsa::ApplyState, base::Unretained(this))); 154 base::Bind(&AudioMixerAlsa::ApplyState, base::Unretained(this)));
148 } 155 }
149 156
157 bool AudioMixerAlsa::IsMuteLocked() {
158 base::AutoLock lock(lock_);
159 return is_mute_locked_;
160 }
161
162 void AudioMixerAlsa::SetMuteLocked(bool locked) {
163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
164 base::AutoLock lock(lock_);
165 is_mute_locked_ = locked;
166 if (!apply_is_pending_)
Daniel Erat 2012/08/27 17:38:35 ditto
pastarmovj 2012/08/28 15:11:50 Done.
167 thread_->message_loop()->PostTask(FROM_HERE,
168 base::Bind(&AudioMixerAlsa::ApplyState, base::Unretained(this)));
169 }
170
171 bool AudioMixerAlsa::IsCaptureMuted() {
172 base::AutoLock lock(lock_);
173 return is_capture_muted_;
174 }
175
176 void AudioMixerAlsa::SetCaptureMuted(bool muted) {
177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
178 base::AutoLock lock(lock_);
179 if (is_capture_mute_locked_)
180 return;
181 is_capture_muted_ = muted;
182 if (!apply_is_pending_)
Daniel Erat 2012/08/27 17:38:35 ditto
pastarmovj 2012/08/28 15:11:50 Done.
183 thread_->message_loop()->PostTask(FROM_HERE,
184 base::Bind(&AudioMixerAlsa::ApplyState, base::Unretained(this)));
185 }
186
187 bool AudioMixerAlsa::IsCaptureMuteLocked() {
188 base::AutoLock lock(lock_);
189 return is_capture_mute_locked_;
190 }
191
192 void AudioMixerAlsa::SetCaptureMuteLocked(bool locked) {
193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
194 base::AutoLock lock(lock_);
195 is_capture_mute_locked_ = locked;
196 if (!apply_is_pending_)
Daniel Erat 2012/08/27 17:38:35 mind fixing this one too?
pastarmovj 2012/08/28 15:11:50 Done.
197 thread_->message_loop()->PostTask(FROM_HERE,
198 base::Bind(&AudioMixerAlsa::ApplyState, base::Unretained(this)));
Mattias Nissler (ping if slow) 2012/08/28 12:24:24 Lots of code duplication here. Any chance to fix?
pastarmovj 2012/08/28 15:11:50 Done.
199 }
200
150 void AudioMixerAlsa::Connect() { 201 void AudioMixerAlsa::Connect() {
151 DCHECK(MessageLoop::current() == thread_->message_loop()); 202 DCHECK(MessageLoop::current() == thread_->message_loop());
152 DCHECK(!alsa_mixer_); 203 DCHECK(!alsa_mixer_);
153 204
154 if (disconnected_event_.IsSignaled()) 205 if (disconnected_event_.IsSignaled())
155 return; 206 return;
156 207
157 // Do not attempt to connect if we're not on the device. 208 // Do not attempt to connect if we're not on the device.
158 if (!base::chromeos::IsRunningOnChromeOS()) 209 if (!base::chromeos::IsRunningOnChromeOS())
159 return; 210 return;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 << kPCMElementName << ": " << snd_strerror(err); 310 << kPCMElementName << ": " << snd_strerror(err);
260 snd_mixer_close(handle); 311 snd_mixer_close(handle);
261 return false; 312 return false;
262 } 313 }
263 min_volume_db += static_cast<double>(long_low) / 100.0; 314 min_volume_db += static_cast<double>(long_low) / 100.0;
264 max_volume_db += static_cast<double>(long_high) / 100.0; 315 max_volume_db += static_cast<double>(long_high) / 100.0;
265 } 316 }
266 317
267 VLOG(1) << "Volume range is " << min_volume_db << " dB to " 318 VLOG(1) << "Volume range is " << min_volume_db << " dB to "
268 << max_volume_db << " dB"; 319 << max_volume_db << " dB";
320
321 snd_mixer_elem_t* mic_element = FindElementWithName(handle, kMicElementName);
322 snd_mixer_elem_t* front_mic_element =
323 FindElementWithName(handle, kFrontMicElementName);
269 { 324 {
270 base::AutoLock lock(lock_); 325 base::AutoLock lock(lock_);
271 alsa_mixer_ = handle; 326 alsa_mixer_ = handle;
272 master_element_ = master_element; 327 master_element_ = master_element;
273 pcm_element_ = pcm_element; 328 pcm_element_ = pcm_element;
329 mic_element_ = mic_element;
330 front_mic_element_ = front_mic_element;
274 min_volume_db_ = min_volume_db; 331 min_volume_db_ = min_volume_db;
275 max_volume_db_ = max_volume_db; 332 max_volume_db_ = max_volume_db;
276 volume_db_ = PercentToDb(initial_volume_percent_); 333 volume_db_ = PercentToDb(initial_volume_percent_);
277 } 334 }
278 335
279 // The speech synthesis service shouldn't be initialized until after 336 // The speech synthesis service shouldn't be initialized until after
280 // we get to this point, so we call this function to tell it that it's 337 // we get to this point, so we call this function to tell it that it's
281 // safe to do TTS now. NotificationService would be cleaner, 338 // safe to do TTS now. NotificationService would be cleaner,
282 // but it's not available at this point. 339 // but it's not available at this point.
283 EnableChromeOsTts(); 340 EnableChromeOsTts();
(...skipping 10 matching lines...) Expand all
294 } 351 }
295 disconnected_event_.Signal(); 352 disconnected_event_.Signal();
296 } 353 }
297 354
298 void AudioMixerAlsa::ApplyState() { 355 void AudioMixerAlsa::ApplyState() {
299 DCHECK(MessageLoop::current() == thread_->message_loop()); 356 DCHECK(MessageLoop::current() == thread_->message_loop());
300 if (!alsa_mixer_) 357 if (!alsa_mixer_)
301 return; 358 return;
302 359
303 bool should_mute = false; 360 bool should_mute = false;
361 bool should_mute_capture = false;
304 double new_volume_db = 0; 362 double new_volume_db = 0;
305 { 363 {
306 base::AutoLock lock(lock_); 364 base::AutoLock lock(lock_);
307 should_mute = is_muted_; 365 should_mute = is_muted_;
366 should_mute_capture = is_capture_muted_;
308 new_volume_db = should_mute ? min_volume_db_ : volume_db_; 367 new_volume_db = should_mute ? min_volume_db_ : volume_db_;
309 apply_is_pending_ = false; 368 apply_is_pending_ = false;
310 } 369 }
311 370
312 if (pcm_element_) { 371 if (pcm_element_) {
313 // If a PCM volume slider exists, then first set the Master volume to the 372 // If a PCM volume slider exists, then first set the Master volume to the
314 // nearest volume >= requested volume, then adjust PCM volume down to get 373 // nearest volume >= requested volume, then adjust PCM volume down to get
315 // closer to the requested volume. 374 // closer to the requested volume.
316 SetElementVolume(master_element_, new_volume_db, 0.9999f); 375 SetElementVolume(master_element_, new_volume_db, 0.9999f);
317 376
318 double pcm_volume_db = 0.0; 377 double pcm_volume_db = 0.0;
319 double master_volume_db = 0.0; 378 double master_volume_db = 0.0;
320 if (GetElementVolume(master_element_, &master_volume_db)) 379 if (GetElementVolume(master_element_, &master_volume_db))
321 pcm_volume_db = new_volume_db - master_volume_db; 380 pcm_volume_db = new_volume_db - master_volume_db;
322 SetElementVolume(pcm_element_, pcm_volume_db, 0.5f); 381 SetElementVolume(pcm_element_, pcm_volume_db, 0.5f);
323 } else { 382 } else {
324 SetElementVolume(master_element_, new_volume_db, 0.5f); 383 SetElementVolume(master_element_, new_volume_db, 0.5f);
325 } 384 }
326 385
327 SetElementMuted(master_element_, should_mute); 386 SetElementMuted(master_element_, should_mute);
387 if (mic_element_)
388 SetElementMuted(mic_element_, should_mute_capture);
389 if (front_mic_element_)
390 SetElementMuted(front_mic_element_, should_mute_capture);
328 } 391 }
329 392
330 snd_mixer_elem_t* AudioMixerAlsa::FindElementWithName( 393 snd_mixer_elem_t* AudioMixerAlsa::FindElementWithName(
331 snd_mixer_t* handle, const string& element_name) const { 394 snd_mixer_t* handle, const string& element_name) const {
332 DCHECK(MessageLoop::current() == thread_->message_loop()); 395 DCHECK(MessageLoop::current() == thread_->message_loop());
333 snd_mixer_selem_id_t* sid = NULL; 396 snd_mixer_selem_id_t* sid = NULL;
334 397
335 // Using id_malloc/id_free API instead of id_alloca since the latter gives the 398 // Using id_malloc/id_free API instead of id_alloca since the latter gives the
336 // warning: the address of 'sid' will always evaluate as 'true'. 399 // warning: the address of 'sid' will always evaluate as 'true'.
337 if (snd_mixer_selem_id_malloc(&sid)) 400 if (snd_mixer_selem_id_malloc(&sid))
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 (max_volume_db_ - min_volume_db_), 1/kVolumeBias); 497 (max_volume_db_ - min_volume_db_), 1/kVolumeBias);
435 } 498 }
436 499
437 double AudioMixerAlsa::PercentToDb(double percent) const { 500 double AudioMixerAlsa::PercentToDb(double percent) const {
438 lock_.AssertAcquired(); 501 lock_.AssertAcquired();
439 return pow(percent / 100.0, kVolumeBias) * 502 return pow(percent / 100.0, kVolumeBias) *
440 (max_volume_db_ - min_volume_db_) + min_volume_db_; 503 (max_volume_db_ - min_volume_db_) + min_volume_db_;
441 } 504 }
442 505
443 } // namespace chromeos 506 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698