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

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

Issue 7582024: chromeos: Look for "Master" or "Digital" mixer elements. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge Created 9 years, 4 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
« no previous file with comments | « chrome/browser/chromeos/audio_mixer_alsa.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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_mixer_alsa.h" 5 #include "chrome/browser/chromeos/audio_mixer_alsa.h"
6 6
7 #include <unistd.h> 7 #include <unistd.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <cmath> 10 #include <cmath>
11 11
12 #include <alsa/asoundlib.h> 12 #include <alsa/asoundlib.h>
13 13
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/message_loop.h" 15 #include "base/message_loop.h"
16 #include "base/task.h" 16 #include "base/task.h"
17 #include "base/threading/thread.h" 17 #include "base/threading/thread.h"
18 #include "base/threading/thread_restrictions.h" 18 #include "base/threading/thread_restrictions.h"
19 #include "chrome/browser/browser_process.h" 19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/prefs/pref_service.h" 20 #include "chrome/browser/prefs/pref_service.h"
21 #include "chrome/common/pref_names.h" 21 #include "chrome/common/pref_names.h"
22 #include "content/browser/browser_thread.h" 22 #include "content/browser/browser_thread.h"
23 23
24 typedef long alsa_long_t; // 'long' is required for ALSA API calls. 24 typedef long alsa_long_t; // 'long' is required for ALSA API calls.
25 25
26 using std::max; 26 using std::max;
27 using std::min; 27 using std::min;
28 using std::string; 28 using std::string;
29 using std::vector;
30 29
31 namespace chromeos { 30 namespace chromeos {
32 31
33 namespace { 32 namespace {
34 33
35 // Name of the ALSA card to which we connect. 34 // Name of the ALSA card to which we connect.
36 const char kCardName[] = "default"; 35 const char kCardName[] = "default";
37 36
38 // Mixer element names. We try to connect to the preferred master element 37 // Mixer element names. We'll use the first master element from the list that
39 // first; if it doesn't exist, we'll control any of the alternates that exist. 38 // exists.
40 const char kPreferredMasterElementName[] = "Master"; 39 const char* const kMasterElementNames[] = {
41 const char* const kAlternateMasterElementNames[] = { 40 "Master", // x86
42 "Headphone", 41 "Digital", // ARM
43 "Speaker",
44 }; 42 };
45 const char kPCMElementName[] = "PCM"; 43 const char kPCMElementName[] = "PCM";
46 44
47 // Default minimum and maximum volume (before we've loaded the actual range from 45 // Default minimum and maximum volume (before we've loaded the actual range from
48 // ALSA), in decibels. 46 // ALSA), in decibels.
49 const double kDefaultMinVolumeDb = -90.0; 47 const double kDefaultMinVolumeDb = -90.0;
50 const double kDefaultMaxVolumeDb = 0.0; 48 const double kDefaultMaxVolumeDb = 0.0;
51 49
52 // Default value assigned to the pref when it's first created, in decibels. 50 // Default value assigned to the pref when it's first created, in decibels.
53 const double kDefaultVolumeDb = -10.0; 51 const double kDefaultVolumeDb = -10.0;
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 << snd_strerror(err); 231 << snd_strerror(err);
234 snd_mixer_close(handle); 232 snd_mixer_close(handle);
235 return false; 233 return false;
236 } 234 }
237 235
238 VLOG(1) << "Opened mixer " << kCardName << " successfully"; 236 VLOG(1) << "Opened mixer " << kCardName << " successfully";
239 237
240 double min_volume_db = kDefaultMinVolumeDb; 238 double min_volume_db = kDefaultMinVolumeDb;
241 double max_volume_db = kDefaultMaxVolumeDb; 239 double max_volume_db = kDefaultMaxVolumeDb;
242 240
243 vector<snd_mixer_elem_t*> master_elements; 241 snd_mixer_elem_t* master_element = NULL;
244 snd_mixer_elem_t* element = 242 for (size_t i = 0; i < arraysize(kMasterElementNames); ++i) {
245 FindElementWithName(handle, kPreferredMasterElementName); 243 master_element = FindElementWithName(handle, kMasterElementNames[i]);
246 if (element) { 244 if (master_element)
247 master_elements.push_back(element); 245 break;
248 } else {
249 for (size_t i = 0; i < arraysize(kAlternateMasterElementNames); ++i) {
250 element = FindElementWithName(handle, kAlternateMasterElementNames[i]);
251 if (element)
252 master_elements.push_back(element);
253 }
254 } 246 }
255 247
256 if (master_elements.empty()) { 248 if (!master_element) {
257 if (num_connection_attempts_ == kConnectionAttemptToLogFailure) 249 if (num_connection_attempts_ == kConnectionAttemptToLogFailure)
258 LOG(WARNING) << "Unable to find any mixer elements on " << kCardName; 250 LOG(WARNING) << "Unable to find a master element on " << kCardName;
259 snd_mixer_close(handle); 251 snd_mixer_close(handle);
260 return false; 252 return false;
261 } 253 }
262 254
263 alsa_long_t long_low = static_cast<alsa_long_t>(kDefaultMinVolumeDb * 100); 255 alsa_long_t long_low = static_cast<alsa_long_t>(kDefaultMinVolumeDb * 100);
264 alsa_long_t long_high = static_cast<alsa_long_t>(kDefaultMaxVolumeDb * 100); 256 alsa_long_t long_high = static_cast<alsa_long_t>(kDefaultMaxVolumeDb * 100);
265 err = snd_mixer_selem_get_playback_dB_range( 257 err = snd_mixer_selem_get_playback_dB_range(
266 master_elements.at(0), &long_low, &long_high); 258 master_element, &long_low, &long_high);
267 if (err != 0) { 259 if (err != 0) {
268 if (num_connection_attempts_ == kConnectionAttemptToLogFailure) 260 if (num_connection_attempts_ == kConnectionAttemptToLogFailure)
269 LOG(WARNING) << "snd_mixer_selem_get_playback_dB_range() failed:" 261 LOG(WARNING) << "snd_mixer_selem_get_playback_dB_range() failed:"
270 << snd_strerror(err); 262 << snd_strerror(err);
271 snd_mixer_close(handle); 263 snd_mixer_close(handle);
272 return false; 264 return false;
273 } 265 }
274 min_volume_db = static_cast<double>(long_low) / 100.0; 266 min_volume_db = static_cast<double>(long_low) / 100.0;
275 max_volume_db = static_cast<double>(long_high) / 100.0; 267 max_volume_db = static_cast<double>(long_high) / 100.0;
276 268
(...skipping 12 matching lines...) Expand all
289 } 281 }
290 min_volume_db += static_cast<double>(long_low) / 100.0; 282 min_volume_db += static_cast<double>(long_low) / 100.0;
291 max_volume_db += static_cast<double>(long_high) / 100.0; 283 max_volume_db += static_cast<double>(long_high) / 100.0;
292 } 284 }
293 285
294 VLOG(1) << "Volume range is " << min_volume_db << " dB to " 286 VLOG(1) << "Volume range is " << min_volume_db << " dB to "
295 << max_volume_db << " dB"; 287 << max_volume_db << " dB";
296 { 288 {
297 base::AutoLock lock(lock_); 289 base::AutoLock lock(lock_);
298 alsa_mixer_ = handle; 290 alsa_mixer_ = handle;
299 master_elements_.swap(master_elements); 291 master_element_ = master_element;
300 pcm_element_ = pcm_element; 292 pcm_element_ = pcm_element;
301 min_volume_db_ = min_volume_db; 293 min_volume_db_ = min_volume_db;
302 max_volume_db_ = max_volume_db; 294 max_volume_db_ = max_volume_db;
303 volume_db_ = min(max(volume_db_, min_volume_db_), max_volume_db_); 295 volume_db_ = min(max(volume_db_, min_volume_db_), max_volume_db_);
304 } 296 }
305 297
306 ApplyState(); 298 ApplyState();
307 return true; 299 return true;
308 } 300 }
309 301
(...skipping 17 matching lines...) Expand all
327 base::AutoLock lock(lock_); 319 base::AutoLock lock(lock_);
328 should_mute = is_muted_; 320 should_mute = is_muted_;
329 new_volume_db = should_mute ? min_volume_db_ : volume_db_; 321 new_volume_db = should_mute ? min_volume_db_ : volume_db_;
330 apply_is_pending_ = false; 322 apply_is_pending_ = false;
331 } 323 }
332 324
333 if (pcm_element_) { 325 if (pcm_element_) {
334 // If a PCM volume slider exists, then first set the Master volume to the 326 // If a PCM volume slider exists, then first set the Master volume to the
335 // nearest volume >= requested volume, then adjust PCM volume down to get 327 // nearest volume >= requested volume, then adjust PCM volume down to get
336 // closer to the requested volume. 328 // closer to the requested volume.
337 for (vector<snd_mixer_elem_t*>::iterator it = master_elements_.begin(); 329 SetElementVolume(master_element_, new_volume_db, 0.9999f);
338 it != master_elements_.end(); ++it)
339 SetElementVolume(*it, new_volume_db, 0.9999f);
340 330
341 double pcm_volume_db = 0.0; 331 double pcm_volume_db = 0.0;
342 double master_volume_db = 0.0; 332 double master_volume_db = 0.0;
343 if (GetElementVolume(master_elements_.at(0), &master_volume_db)) 333 if (GetElementVolume(master_element_, &master_volume_db))
344 pcm_volume_db = new_volume_db - master_volume_db; 334 pcm_volume_db = new_volume_db - master_volume_db;
345 SetElementVolume(pcm_element_, pcm_volume_db, 0.5f); 335 SetElementVolume(pcm_element_, pcm_volume_db, 0.5f);
346 } else { 336 } else {
347 for (vector<snd_mixer_elem_t*>::iterator it = master_elements_.begin(); 337 SetElementVolume(master_element_, new_volume_db, 0.5f);
348 it != master_elements_.end(); ++it)
349 SetElementVolume(*it, new_volume_db, 0.5f);
350 } 338 }
351 339
352 for (vector<snd_mixer_elem_t*>::iterator it = master_elements_.begin(); 340 SetElementMuted(master_element_, should_mute);
353 it != master_elements_.end(); ++it)
354 SetElementMuted(*it, should_mute);
355 } 341 }
356 342
357 snd_mixer_elem_t* AudioMixerAlsa::FindElementWithName( 343 snd_mixer_elem_t* AudioMixerAlsa::FindElementWithName(
358 snd_mixer_t* handle, const string& element_name) const { 344 snd_mixer_t* handle, const string& element_name) const {
359 DCHECK(MessageLoop::current() == thread_->message_loop()); 345 DCHECK(MessageLoop::current() == thread_->message_loop());
360 snd_mixer_selem_id_t* sid = NULL; 346 snd_mixer_selem_id_t* sid = NULL;
361 347
362 // Using id_malloc/id_free API instead of id_alloca since the latter gives the 348 // Using id_malloc/id_free API instead of id_alloca since the latter gives the
363 // warning: the address of 'sid' will always evaluate as 'true'. 349 // warning: the address of 'sid' will always evaluate as 'true'.
364 if (snd_mixer_selem_id_malloc(&sid)) 350 if (snd_mixer_selem_id_malloc(&sid))
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 if (alsa_result != 0) { 433 if (alsa_result != 0) {
448 LOG(WARNING) << "snd_mixer_selem_set_playback_switch_all() failed: " 434 LOG(WARNING) << "snd_mixer_selem_set_playback_switch_all() failed: "
449 << snd_strerror(alsa_result); 435 << snd_strerror(alsa_result);
450 } else { 436 } else {
451 VLOG(1) << "Set playback switch " << snd_mixer_selem_get_name(element) 437 VLOG(1) << "Set playback switch " << snd_mixer_selem_get_name(element)
452 << " to " << mute; 438 << " to " << mute;
453 } 439 }
454 } 440 }
455 441
456 } // namespace chromeos 442 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/audio_mixer_alsa.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698