Home | History | Annotate | Download | only in sound
      1 /*
      2  * libjingle
      3  * Copyright 2004--2010, Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #ifndef TALK_SOUND_PULSEAUDIOSOUNDSYSTEM_H_
     29 #define TALK_SOUND_PULSEAUDIOSOUNDSYSTEM_H_
     30 
     31 #ifdef HAVE_LIBPULSE
     32 
     33 #include "talk/base/constructormagic.h"
     34 #include "talk/sound/pulseaudiosymboltable.h"
     35 #include "talk/sound/soundsysteminterface.h"
     36 
     37 namespace cricket {
     38 
     39 class PulseAudioInputStream;
     40 class PulseAudioOutputStream;
     41 class PulseAudioStream;
     42 
     43 // Sound system implementation for PulseAudio, a cross-platform sound server
     44 // (but commonly used only on Linux, which is the only platform we support
     45 // it on).
     46 // Init(), Terminate(), and the destructor should never be invoked concurrently,
     47 // but all other methods are thread-safe.
     48 class PulseAudioSoundSystem : public SoundSystemInterface {
     49   friend class PulseAudioInputStream;
     50   friend class PulseAudioOutputStream;
     51   friend class PulseAudioStream;
     52  public:
     53   static SoundSystemInterface *Create() {
     54     return new PulseAudioSoundSystem();
     55   }
     56 
     57   PulseAudioSoundSystem();
     58 
     59   virtual ~PulseAudioSoundSystem();
     60 
     61   virtual bool Init();
     62   virtual void Terminate();
     63 
     64   virtual bool EnumeratePlaybackDevices(SoundDeviceLocatorList *devices);
     65   virtual bool EnumerateCaptureDevices(SoundDeviceLocatorList *devices);
     66 
     67   virtual bool GetDefaultPlaybackDevice(SoundDeviceLocator **device);
     68   virtual bool GetDefaultCaptureDevice(SoundDeviceLocator **device);
     69 
     70   virtual SoundOutputStreamInterface *OpenPlaybackDevice(
     71       const SoundDeviceLocator *device,
     72       const OpenParams &params);
     73   virtual SoundInputStreamInterface *OpenCaptureDevice(
     74       const SoundDeviceLocator *device,
     75       const OpenParams &params);
     76 
     77   virtual const char *GetName() const;
     78 
     79  private:
     80   bool IsInitialized();
     81 
     82   static void ConnectToPulseCallbackThunk(pa_context *context, void *userdata);
     83 
     84   void OnConnectToPulseCallback(pa_context *context, bool *connect_done);
     85 
     86   bool ConnectToPulse(pa_context *context);
     87 
     88   pa_context *CreateNewConnection();
     89 
     90   template <typename InfoStruct>
     91   bool EnumerateDevices(SoundDeviceLocatorList *devices,
     92                         pa_operation *(*enumerate_fn)(
     93                             pa_context *c,
     94                             void (*callback_fn)(
     95                                 pa_context *c,
     96                                 const InfoStruct *i,
     97                                 int eol,
     98                                 void *userdata),
     99                             void *userdata),
    100                         void (*callback_fn)(
    101                             pa_context *c,
    102                             const InfoStruct *i,
    103                             int eol,
    104                             void *userdata));
    105 
    106   static void EnumeratePlaybackDevicesCallbackThunk(pa_context *unused,
    107                                                     const pa_sink_info *info,
    108                                                     int eol,
    109                                                     void *userdata);
    110 
    111   static void EnumerateCaptureDevicesCallbackThunk(pa_context *unused,
    112                                                    const pa_source_info *info,
    113                                                    int eol,
    114                                                    void *userdata);
    115 
    116   void OnEnumeratePlaybackDevicesCallback(
    117       SoundDeviceLocatorList *devices,
    118       const pa_sink_info *info,
    119       int eol);
    120 
    121   void OnEnumerateCaptureDevicesCallback(
    122       SoundDeviceLocatorList *devices,
    123       const pa_source_info *info,
    124       int eol);
    125 
    126   template <const char *(pa_server_info::*field)>
    127   static void GetDefaultDeviceCallbackThunk(
    128       pa_context *unused,
    129       const pa_server_info *info,
    130       void *userdata);
    131 
    132   template <const char *(pa_server_info::*field)>
    133   void OnGetDefaultDeviceCallback(
    134       const pa_server_info *info,
    135       SoundDeviceLocator **device);
    136 
    137   template <const char *(pa_server_info::*field)>
    138   bool GetDefaultDevice(SoundDeviceLocator **device);
    139 
    140   static void StreamStateChangedCallbackThunk(pa_stream *stream,
    141                                               void *userdata);
    142 
    143   void OnStreamStateChangedCallback(pa_stream *stream);
    144 
    145   template <typename StreamInterface>
    146   StreamInterface *OpenDevice(
    147       const SoundDeviceLocator *device,
    148       const OpenParams &params,
    149       const char *stream_name,
    150       StreamInterface *(PulseAudioSoundSystem::*connect_fn)(
    151           pa_stream *stream,
    152           const char *dev,
    153           int flags,
    154           pa_stream_flags_t pa_flags,
    155           int latency,
    156           const pa_sample_spec &spec));
    157 
    158   SoundOutputStreamInterface *ConnectOutputStream(
    159       pa_stream *stream,
    160       const char *dev,
    161       int flags,
    162       pa_stream_flags_t pa_flags,
    163       int latency,
    164       const pa_sample_spec &spec);
    165 
    166   SoundInputStreamInterface *ConnectInputStream(
    167       pa_stream *stream,
    168       const char *dev,
    169       int flags,
    170       pa_stream_flags_t pa_flags,
    171       int latency,
    172       const pa_sample_spec &spec);
    173 
    174   bool FinishOperation(pa_operation *op);
    175 
    176   void Lock();
    177   void Unlock();
    178   void Wait();
    179   void Signal();
    180 
    181   const char *LastError();
    182 
    183   pa_threaded_mainloop *mainloop_;
    184   pa_context *context_;
    185   PulseAudioSymbolTable symbol_table_;
    186 
    187   DISALLOW_COPY_AND_ASSIGN(PulseAudioSoundSystem);
    188 };
    189 
    190 }  // namespace cricket
    191 
    192 #endif  // HAVE_LIBPULSE
    193 
    194 #endif  // TALK_SOUND_PULSEAUDIOSOUNDSYSTEM_H_
    195