• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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