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 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_ALSA_H_ 6 #define CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_ALSA_H_ 7 #pragma once 8 9 #include "base/basictypes.h" 10 #include "base/callback.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/synchronization/lock.h" 13 #include "base/synchronization/waitable_event.h" 14 #include "base/threading/thread.h" 15 #include "chrome/browser/chromeos/audio_mixer.h" 16 17 class PrefService; 18 19 struct _snd_mixer_elem; 20 struct _snd_mixer; 21 22 namespace chromeos { 23 24 class AudioMixerAlsa : public AudioMixer { 25 public: 26 AudioMixerAlsa(); 27 virtual ~AudioMixerAlsa(); 28 29 // Implementation of AudioMixer 30 virtual void Init(InitDoneCallback* callback); 31 virtual bool InitSync(); 32 virtual double GetVolumeDb() const; 33 virtual bool GetVolumeLimits(double* vol_min, double* vol_max); 34 virtual void SetVolumeDb(double vol_db); 35 virtual bool IsMute() const; 36 virtual void SetMute(bool mute); 37 virtual State GetState() const; 38 39 // Registers volume and mute in preferences 40 static void RegisterPrefs(PrefService* local_state); 41 42 private: 43 // Called to do initialization in background from worker thread. 44 void DoInit(InitDoneCallback* callback); 45 46 // Helper functions to get our message loop thread and prefs initialized. 47 bool InitThread(); 48 void InitPrefs(); 49 50 // Try to connect to the ALSA mixer through their simple controls interface, 51 // and cache mixer handle and mixer elements we'll be using. 52 bool InitializeAlsaMixer(); 53 void FreeAlsaMixer(); 54 void DoSetVolumeMute(double pref_volume, int pref_mute); 55 56 // Access to PrefMember variables must be done on UI thread. 57 void RestoreVolumeMuteOnUIThread(); 58 59 // All these internal volume commands must be called with the lock held. 60 double DoGetVolumeDb_Locked() const; 61 void DoSetVolumeDb_Locked(double vol_db); 62 63 _snd_mixer_elem* FindElementWithName_Locked(_snd_mixer* handle, 64 const char* element_name) const; 65 66 bool GetElementVolume_Locked(_snd_mixer_elem* elem, 67 double* current_vol) const; 68 69 // Since volume is done in steps, we may not get the exact volume asked for, 70 // so actual_vol will contain the true volume that was set. This information 71 // can be used to further refine the volume by adjust a different mixer 72 // element. The rounding_bias is added in before rounding to the nearest 73 // volume step (use 0.5 to round to nearest). 74 bool SetElementVolume_Locked(_snd_mixer_elem* elem, 75 double new_vol, 76 double* actual_vol, 77 double rounding_bias); 78 79 // In ALSA, the mixer element's 'switch' is turned off to mute. 80 // GetElementMuted_Locked() returns false on failure. 81 bool GetElementMuted_Locked(_snd_mixer_elem* elem) const; 82 void SetElementMuted_Locked(_snd_mixer_elem* elem, bool mute); 83 84 // Volume range limits are computed once during InitializeAlsaMixer. 85 double min_volume_; 86 double max_volume_; 87 88 // Muting is done by setting volume to minimum, so we must save the original. 89 // This is the only state information kept in this object. In some cases, 90 // ALSA can report it has a volume switch and we can turn it off, but it has 91 // no effect. 92 double save_volume_; 93 94 mutable base::Lock mixer_state_lock_; 95 mutable State mixer_state_; 96 97 // Cached contexts for use in ALSA calls. 98 _snd_mixer* alsa_mixer_; 99 _snd_mixer_elem* elem_master_; 100 _snd_mixer_elem* elem_pcm_; 101 102 PrefService* prefs_; 103 base::WaitableEvent done_event_; 104 105 scoped_ptr<base::Thread> thread_; 106 107 DISALLOW_COPY_AND_ASSIGN(AudioMixerAlsa); 108 }; 109 110 } // namespace chromeos 111 112 DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::AudioMixerAlsa); 113 114 #endif // CHROME_BROWSER_CHROMEOS_AUDIO_MIXER_ALSA_H_ 115