1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef WEBRTC_SOUND_PULSEAUDIOSOUNDSYSTEM_H_
12 #define WEBRTC_SOUND_PULSEAUDIOSOUNDSYSTEM_H_
13 
14 #ifdef HAVE_LIBPULSE
15 
16 #include "webrtc/sound/pulseaudiosymboltable.h"
17 #include "webrtc/sound/soundsysteminterface.h"
18 #include "webrtc/base/constructormagic.h"
19 
20 namespace rtc {
21 
22 class PulseAudioInputStream;
23 class PulseAudioOutputStream;
24 class PulseAudioStream;
25 
26 // Sound system implementation for PulseAudio, a cross-platform sound server
27 // (but commonly used only on Linux, which is the only platform we support
28 // it on).
29 // Init(), Terminate(), and the destructor should never be invoked concurrently,
30 // but all other methods are thread-safe.
31 class PulseAudioSoundSystem : public SoundSystemInterface {
32   friend class PulseAudioInputStream;
33   friend class PulseAudioOutputStream;
34   friend class PulseAudioStream;
35  public:
Create()36   static SoundSystemInterface *Create() {
37     return new PulseAudioSoundSystem();
38   }
39 
40   PulseAudioSoundSystem();
41 
42   virtual ~PulseAudioSoundSystem();
43 
44   virtual bool Init();
45   virtual void Terminate();
46 
47   virtual bool EnumeratePlaybackDevices(SoundDeviceLocatorList *devices);
48   virtual bool EnumerateCaptureDevices(SoundDeviceLocatorList *devices);
49 
50   virtual bool GetDefaultPlaybackDevice(SoundDeviceLocator **device);
51   virtual bool GetDefaultCaptureDevice(SoundDeviceLocator **device);
52 
53   virtual SoundOutputStreamInterface *OpenPlaybackDevice(
54       const SoundDeviceLocator *device,
55       const OpenParams &params);
56   virtual SoundInputStreamInterface *OpenCaptureDevice(
57       const SoundDeviceLocator *device,
58       const OpenParams &params);
59 
60   virtual const char *GetName() const;
61 
62  private:
63   bool IsInitialized();
64 
65   static void ConnectToPulseCallbackThunk(pa_context *context, void *userdata);
66 
67   void OnConnectToPulseCallback(pa_context *context, bool *connect_done);
68 
69   bool ConnectToPulse(pa_context *context);
70 
71   pa_context *CreateNewConnection();
72 
73   template <typename InfoStruct>
74   bool EnumerateDevices(SoundDeviceLocatorList *devices,
75                         pa_operation *(*enumerate_fn)(
76                             pa_context *c,
77                             void (*callback_fn)(
78                                 pa_context *c,
79                                 const InfoStruct *i,
80                                 int eol,
81                                 void *userdata),
82                             void *userdata),
83                         void (*callback_fn)(
84                             pa_context *c,
85                             const InfoStruct *i,
86                             int eol,
87                             void *userdata));
88 
89   static void EnumeratePlaybackDevicesCallbackThunk(pa_context *unused,
90                                                     const pa_sink_info *info,
91                                                     int eol,
92                                                     void *userdata);
93 
94   static void EnumerateCaptureDevicesCallbackThunk(pa_context *unused,
95                                                    const pa_source_info *info,
96                                                    int eol,
97                                                    void *userdata);
98 
99   void OnEnumeratePlaybackDevicesCallback(
100       SoundDeviceLocatorList *devices,
101       const pa_sink_info *info,
102       int eol);
103 
104   void OnEnumerateCaptureDevicesCallback(
105       SoundDeviceLocatorList *devices,
106       const pa_source_info *info,
107       int eol);
108 
109   template <const char *(pa_server_info::*field)>
110   static void GetDefaultDeviceCallbackThunk(
111       pa_context *unused,
112       const pa_server_info *info,
113       void *userdata);
114 
115   template <const char *(pa_server_info::*field)>
116   void OnGetDefaultDeviceCallback(
117       const pa_server_info *info,
118       SoundDeviceLocator **device);
119 
120   template <const char *(pa_server_info::*field)>
121   bool GetDefaultDevice(SoundDeviceLocator **device);
122 
123   static void StreamStateChangedCallbackThunk(pa_stream *stream,
124                                               void *userdata);
125 
126   void OnStreamStateChangedCallback(pa_stream *stream);
127 
128   template <typename StreamInterface>
129   StreamInterface *OpenDevice(
130       const SoundDeviceLocator *device,
131       const OpenParams &params,
132       const char *stream_name,
133       StreamInterface *(PulseAudioSoundSystem::*connect_fn)(
134           pa_stream *stream,
135           const char *dev,
136           int flags,
137           pa_stream_flags_t pa_flags,
138           int latency,
139           const pa_sample_spec &spec));
140 
141   SoundOutputStreamInterface *ConnectOutputStream(
142       pa_stream *stream,
143       const char *dev,
144       int flags,
145       pa_stream_flags_t pa_flags,
146       int latency,
147       const pa_sample_spec &spec);
148 
149   SoundInputStreamInterface *ConnectInputStream(
150       pa_stream *stream,
151       const char *dev,
152       int flags,
153       pa_stream_flags_t pa_flags,
154       int latency,
155       const pa_sample_spec &spec);
156 
157   bool FinishOperation(pa_operation *op);
158 
159   void Lock();
160   void Unlock();
161   void Wait();
162   void Signal();
163 
164   const char *LastError();
165 
166   pa_threaded_mainloop *mainloop_;
167   pa_context *context_;
168   PulseAudioSymbolTable symbol_table_;
169 
170   RTC_DISALLOW_COPY_AND_ASSIGN(PulseAudioSoundSystem);
171 };
172 
173 }  // namespace rtc
174 
175 #endif  // HAVE_LIBPULSE
176 
177 #endif  // WEBRTC_SOUND_PULSEAUDIOSOUNDSYSTEM_H_
178