audio_manager_pulse.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright 2013 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#include "media/audio/pulse/audio_manager_pulse.h"
6
7#include "base/command_line.h"
8#include "base/environment.h"
9#include "base/files/file_path.h"
10#include "base/logging.h"
11#include "base/nix/xdg_util.h"
12#include "base/stl_util.h"
13#if defined(USE_ALSA)
14#include "media/audio/alsa/audio_manager_alsa.h"
15#endif
16#include "media/audio/audio_parameters.h"
17#include "media/audio/pulse/pulse_input.h"
18#include "media/audio/pulse/pulse_output.h"
19#include "media/audio/pulse/pulse_util.h"
20#include "media/base/channel_layout.h"
21
22#if defined(DLOPEN_PULSEAUDIO)
23#include "media/audio/pulse/pulse_stubs.h"
24
25using media_audio_pulse::kModulePulse;
26using media_audio_pulse::InitializeStubs;
27using media_audio_pulse::StubPathMap;
28#endif  // defined(DLOPEN_PULSEAUDIO)
29
30namespace media {
31
32using pulse::AutoPulseLock;
33using pulse::WaitForOperationCompletion;
34
35// Maximum number of output streams that can be open simultaneously.
36static const int kMaxOutputStreams = 50;
37
38// Define bounds for the output buffer size.
39static const int kMinimumOutputBufferSize = 512;
40static const int kMaximumOutputBufferSize = 8192;
41
42// Default input buffer size.
43static const int kDefaultInputBufferSize = 1024;
44
45#if defined(DLOPEN_PULSEAUDIO)
46static const base::FilePath::CharType kPulseLib[] =
47    FILE_PATH_LITERAL("libpulse.so.0");
48#endif
49
50// static
51AudioManager* AudioManagerPulse::Create(AudioLogFactory* audio_log_factory) {
52  scoped_ptr<AudioManagerPulse> ret(new AudioManagerPulse(audio_log_factory));
53  if (ret->Init())
54    return ret.release();
55
56  DVLOG(1) << "PulseAudio is not available on the OS";
57  return NULL;
58}
59
60AudioManagerPulse::AudioManagerPulse(AudioLogFactory* audio_log_factory)
61    : AudioManagerBase(audio_log_factory),
62      input_mainloop_(NULL),
63      input_context_(NULL),
64      devices_(NULL),
65      native_input_sample_rate_(0) {
66  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
67}
68
69AudioManagerPulse::~AudioManagerPulse() {
70  Shutdown();
71
72  // The Pulse objects are the last things to be destroyed since Shutdown()
73  // needs them.
74  DestroyPulse();
75}
76
77// Implementation of AudioManager.
78bool AudioManagerPulse::HasAudioOutputDevices() {
79  AudioDeviceNames devices;
80  GetAudioOutputDeviceNames(&devices);
81  return !devices.empty();
82}
83
84bool AudioManagerPulse::HasAudioInputDevices() {
85  AudioDeviceNames devices;
86  GetAudioInputDeviceNames(&devices);
87  return !devices.empty();
88}
89
90void AudioManagerPulse::ShowAudioInputSettings() {
91#if defined(USE_ALSA)
92  AudioManagerAlsa::ShowLinuxAudioInputSettings();
93#endif
94}
95
96void AudioManagerPulse::GetAudioDeviceNames(
97    bool input, media::AudioDeviceNames* device_names) {
98  DCHECK(device_names->empty());
99  DCHECK(input_mainloop_);
100  DCHECK(input_context_);
101  AutoPulseLock auto_lock(input_mainloop_);
102  devices_ = device_names;
103  pa_operation* operation = NULL;
104  if (input) {
105    operation = pa_context_get_source_info_list(
106      input_context_, InputDevicesInfoCallback, this);
107  } else {
108    operation = pa_context_get_sink_info_list(
109        input_context_, OutputDevicesInfoCallback, this);
110  }
111  WaitForOperationCompletion(input_mainloop_, operation);
112
113  // Prepend the default device if the list is not empty.
114  if (!device_names->empty()) {
115    device_names->push_front(
116        AudioDeviceName(AudioManagerBase::kDefaultDeviceName,
117                        AudioManagerBase::kDefaultDeviceId));
118  }
119}
120
121void AudioManagerPulse::GetAudioInputDeviceNames(
122    AudioDeviceNames* device_names) {
123  GetAudioDeviceNames(true, device_names);
124}
125
126void AudioManagerPulse::GetAudioOutputDeviceNames(
127    AudioDeviceNames* device_names) {
128  GetAudioDeviceNames(false, device_names);
129}
130
131AudioParameters AudioManagerPulse::GetInputStreamParameters(
132    const std::string& device_id) {
133  int user_buffer_size = GetUserBufferSize();
134  int buffer_size = user_buffer_size ?
135      user_buffer_size : kDefaultInputBufferSize;
136
137  // TODO(xians): add support for querying native channel layout for pulse.
138  return AudioParameters(
139      AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
140      GetNativeSampleRate(), 16, buffer_size);
141}
142
143AudioOutputStream* AudioManagerPulse::MakeLinearOutputStream(
144    const AudioParameters& params) {
145  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
146  return MakeOutputStream(params, AudioManagerBase::kDefaultDeviceId);
147}
148
149AudioOutputStream* AudioManagerPulse::MakeLowLatencyOutputStream(
150    const AudioParameters& params,
151    const std::string& device_id) {
152  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
153  return MakeOutputStream(
154      params,
155      device_id.empty() ? AudioManagerBase::kDefaultDeviceId : device_id);
156}
157
158AudioInputStream* AudioManagerPulse::MakeLinearInputStream(
159    const AudioParameters& params, const std::string& device_id) {
160  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
161  return MakeInputStream(params, device_id);
162}
163
164AudioInputStream* AudioManagerPulse::MakeLowLatencyInputStream(
165    const AudioParameters& params, const std::string& device_id) {
166  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
167  return MakeInputStream(params, device_id);
168}
169
170AudioParameters AudioManagerPulse::GetPreferredOutputStreamParameters(
171    const std::string& output_device_id,
172    const AudioParameters& input_params) {
173  // TODO(tommi): Support |output_device_id|.
174  VLOG_IF(0, !output_device_id.empty()) << "Not implemented!";
175
176  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
177  int buffer_size = kMinimumOutputBufferSize;
178  int bits_per_sample = 16;
179  int sample_rate = GetNativeSampleRate();
180  if (input_params.IsValid()) {
181    bits_per_sample = input_params.bits_per_sample();
182    channel_layout = input_params.channel_layout();
183    buffer_size =
184        std::min(kMaximumOutputBufferSize,
185                 std::max(buffer_size, input_params.frames_per_buffer()));
186  }
187
188  int user_buffer_size = GetUserBufferSize();
189  if (user_buffer_size)
190    buffer_size = user_buffer_size;
191
192  return AudioParameters(
193      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
194      sample_rate, bits_per_sample, buffer_size, AudioParameters::NO_EFFECTS);
195}
196
197AudioOutputStream* AudioManagerPulse::MakeOutputStream(
198    const AudioParameters& params,
199    const std::string& device_id) {
200  DCHECK(!device_id.empty());
201  return new PulseAudioOutputStream(params, device_id, this);
202}
203
204AudioInputStream* AudioManagerPulse::MakeInputStream(
205    const AudioParameters& params, const std::string& device_id) {
206  return new PulseAudioInputStream(this, device_id, params,
207                                   input_mainloop_, input_context_);
208}
209
210int AudioManagerPulse::GetNativeSampleRate() {
211  DCHECK(input_mainloop_);
212  DCHECK(input_context_);
213  AutoPulseLock auto_lock(input_mainloop_);
214  pa_operation* operation = pa_context_get_server_info(
215      input_context_, SampleRateInfoCallback, this);
216  WaitForOperationCompletion(input_mainloop_, operation);
217
218  return native_input_sample_rate_;
219}
220
221bool AudioManagerPulse::Init() {
222  DCHECK(!input_mainloop_);
223
224#if defined(DLOPEN_PULSEAUDIO)
225  StubPathMap paths;
226
227  // Check if the pulse library is avialbale.
228  paths[kModulePulse].push_back(kPulseLib);
229  if (!InitializeStubs(paths)) {
230    VLOG(1) << "Failed on loading the Pulse library and symbols";
231    return false;
232  }
233#endif  // defined(DLOPEN_PULSEAUDIO)
234
235  // Create a mainloop API and connect to the default server.
236  // The mainloop is the internal asynchronous API event loop.
237  input_mainloop_ = pa_threaded_mainloop_new();
238  if (!input_mainloop_)
239    return false;
240
241  // Start the threaded mainloop.
242  if (pa_threaded_mainloop_start(input_mainloop_))
243    return false;
244
245  // Lock the event loop object, effectively blocking the event loop thread
246  // from processing events. This is necessary.
247  AutoPulseLock auto_lock(input_mainloop_);
248
249  pa_mainloop_api* pa_mainloop_api =
250      pa_threaded_mainloop_get_api(input_mainloop_);
251  input_context_ = pa_context_new(pa_mainloop_api, "Chrome input");
252  if (!input_context_)
253    return false;
254
255  pa_context_set_state_callback(input_context_, &pulse::ContextStateCallback,
256                                input_mainloop_);
257  if (pa_context_connect(input_context_, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL)) {
258    VLOG(0) << "Failed to connect to the context.  Error: "
259            << pa_strerror(pa_context_errno(input_context_));
260    return false;
261  }
262
263  // Wait until |input_context_| is ready.  pa_threaded_mainloop_wait() must be
264  // called after pa_context_get_state() in case the context is already ready,
265  // otherwise pa_threaded_mainloop_wait() will hang indefinitely.
266  while (true) {
267    pa_context_state_t context_state = pa_context_get_state(input_context_);
268    if (!PA_CONTEXT_IS_GOOD(context_state))
269      return false;
270    if (context_state == PA_CONTEXT_READY)
271      break;
272    pa_threaded_mainloop_wait(input_mainloop_);
273  }
274
275  return true;
276}
277
278void AudioManagerPulse::DestroyPulse() {
279  if (!input_mainloop_) {
280    DCHECK(!input_context_);
281    return;
282  }
283
284  {
285    AutoPulseLock auto_lock(input_mainloop_);
286    if (input_context_) {
287      // Clear our state callback.
288      pa_context_set_state_callback(input_context_, NULL, NULL);
289      pa_context_disconnect(input_context_);
290      pa_context_unref(input_context_);
291      input_context_ = NULL;
292    }
293  }
294
295  pa_threaded_mainloop_stop(input_mainloop_);
296  pa_threaded_mainloop_free(input_mainloop_);
297  input_mainloop_ = NULL;
298}
299
300void AudioManagerPulse::InputDevicesInfoCallback(pa_context* context,
301                                                 const pa_source_info* info,
302                                                 int error, void *user_data) {
303  AudioManagerPulse* manager = reinterpret_cast<AudioManagerPulse*>(user_data);
304
305  if (error) {
306    // Signal the pulse object that it is done.
307    pa_threaded_mainloop_signal(manager->input_mainloop_, 0);
308    return;
309  }
310
311  // Exclude the output devices.
312  if (info->monitor_of_sink == PA_INVALID_INDEX) {
313    manager->devices_->push_back(AudioDeviceName(info->description,
314                                                 info->name));
315  }
316}
317
318void AudioManagerPulse::OutputDevicesInfoCallback(pa_context* context,
319                                                  const pa_sink_info* info,
320                                                  int error, void *user_data) {
321  AudioManagerPulse* manager = reinterpret_cast<AudioManagerPulse*>(user_data);
322
323  if (error) {
324    // Signal the pulse object that it is done.
325    pa_threaded_mainloop_signal(manager->input_mainloop_, 0);
326    return;
327  }
328
329  manager->devices_->push_back(AudioDeviceName(info->description,
330                                               info->name));
331}
332
333void AudioManagerPulse::SampleRateInfoCallback(pa_context* context,
334                                               const pa_server_info* info,
335                                               void* user_data) {
336  AudioManagerPulse* manager = reinterpret_cast<AudioManagerPulse*>(user_data);
337
338  manager->native_input_sample_rate_ = info->sample_spec.rate;
339  pa_threaded_mainloop_signal(manager->input_mainloop_, 0);
340}
341
342}  // namespace media
343