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
20namespace rtc {
21
22class PulseAudioInputStream;
23class PulseAudioOutputStream;
24class 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.
31class PulseAudioSoundSystem : public SoundSystemInterface {
32  friend class PulseAudioInputStream;
33  friend class PulseAudioOutputStream;
34  friend class PulseAudioStream;
35 public:
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