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