Home | History | Annotate | Download | only in chromeos
      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