/*
 * libjingle
 * Copyright 2010, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/sound/pulseaudiosoundsystem.h"

#ifdef HAVE_LIBPULSE

#include <pulse/context.h>
#include <pulse/error.h>
#include <pulse/introspect.h>
#include <pulse/stream.h>
#include <pulse/thread-mainloop.h>

#include "talk/base/common.h"
#include "talk/base/fileutils.h"  // for GetApplicationName()
#include "talk/base/logging.h"
#include "talk/base/worker.h"
#include "talk/sound/sounddevicelocator.h"
#include "talk/sound/soundinputstreaminterface.h"
#include "talk/sound/soundoutputstreaminterface.h"

namespace cricket {

// First PulseAudio protocol version that supports PA_STREAM_ADJUST_LATENCY.
static const uint32_t kAdjustLatencyProtocolVersion = 13;

// We define this flag if it's missing from our headers, because we want to be
// able to compile against old headers but still use PA_STREAM_ADJUST_LATENCY
// if run against a recent version of the library.
#ifndef PA_STREAM_ADJUST_LATENCY
#define PA_STREAM_ADJUST_LATENCY 0x2000U
#endif

// Lookup table from the cricket format enum in soundsysteminterface.h to
// Pulse's enums.
static const pa_sample_format_t kCricketFormatToPulseFormatTable[] = {
  // The order here must match the order in soundsysteminterface.h
  PA_SAMPLE_S16LE,
};

// Some timing constants for optimal operation. See
// https://tango.0pointer.de/pipermail/pulseaudio-discuss/2008-January/001170.html
// for a good explanation of some of the factors that go into this.

// Playback.

// For playback, there is a round-trip delay to fill the server-side playback
// buffer, so setting too low of a latency is a buffer underflow risk. We will
// automatically increase the latency if a buffer underflow does occur, but we
// also enforce a sane minimum at start-up time. Anything lower would be
// virtually guaranteed to underflow at least once, so there's no point in
// allowing lower latencies.
static const int kPlaybackLatencyMinimumMsecs = 20;
// Every time a playback stream underflows, we will reconfigure it with target
// latency that is greater by this amount.
static const int kPlaybackLatencyIncrementMsecs = 20;
// We also need to configure a suitable request size. Too small and we'd burn
// CPU from the overhead of transfering small amounts of data at once. Too large
// and the amount of data remaining in the buffer right before refilling it
// would be a buffer underflow risk. We set it to half of the buffer size.
static const int kPlaybackRequestFactor = 2;

// Capture.

// For capture, low latency is not a buffer overflow risk, but it makes us burn
// CPU from the overhead of transfering small amounts of data at once, so we set
// a recommended value that we use for the kLowLatency constant (but if the user
// explicitly requests something lower then we will honour it).
// 1ms takes about 6-7% CPU. 5ms takes about 5%. 10ms takes about 4.x%.
static const int kLowCaptureLatencyMsecs = 10;
// There is a round-trip delay to ack the data to the server, so the
// server-side buffer needs extra space to prevent buffer overflow. 20ms is
// sufficient, but there is no penalty to making it bigger, so we make it huge.
// (750ms is libpulse's default value for the _total_ buffer size in the
// kNoLatencyRequirements case.)
static const int kCaptureBufferExtraMsecs = 750;

static const int kMsecsPerSec = 1000;

static void FillPlaybackBufferAttr(int latency,
                                   pa_buffer_attr *attr) {
  attr->maxlength = latency;
  attr->tlength = latency;
  attr->minreq = latency / kPlaybackRequestFactor;
  attr->prebuf = attr->tlength - attr->minreq;
  LOG(LS_VERBOSE) << "Configuring latency = " << attr->tlength << ", minreq = "
                  << attr->minreq << ", minfill = " << attr->prebuf;
}

static pa_volume_t CricketVolumeToPulseVolume(int volume) {
  // PA's volume space goes from 0% at PA_VOLUME_MUTED (value 0) to 100% at
  // PA_VOLUME_NORM (value 0x10000). It can also go beyond 100% up to
  // PA_VOLUME_MAX (value UINT32_MAX-1), but using that is probably unwise.
  // We just linearly map the 0-255 scale of SoundSystemInterface onto
  // PA_VOLUME_MUTED-PA_VOLUME_NORM. If the programmer exceeds kMaxVolume then
  // they can access the over-100% features of PA.
  return PA_VOLUME_MUTED + (PA_VOLUME_NORM - PA_VOLUME_MUTED) *
      volume / SoundSystemInterface::kMaxVolume;
}

static int PulseVolumeToCricketVolume(pa_volume_t pa_volume) {
  return SoundSystemInterface::kMinVolume +
      (SoundSystemInterface::kMaxVolume - SoundSystemInterface::kMinVolume) *
      pa_volume / PA_VOLUME_NORM;
}

static pa_volume_t MaxChannelVolume(pa_cvolume *channel_volumes) {
  pa_volume_t pa_volume = PA_VOLUME_MUTED;  // Minimum possible value.
  for (int i = 0; i < channel_volumes->channels; ++i) {
    if (pa_volume < channel_volumes->values[i]) {
      pa_volume = channel_volumes->values[i];
    }
  }
  return pa_volume;
}

class PulseAudioDeviceLocator : public SoundDeviceLocator {
 public:
  PulseAudioDeviceLocator(const std::string &name,
                          const std::string &device_name)
      : SoundDeviceLocator(name, device_name) {
  }

  virtual SoundDeviceLocator *Copy() const {
    return new PulseAudioDeviceLocator(*this);
  }
};

// Accesses Pulse functions through our late-binding symbol table instead of
// directly. This way we don't have to link to libpulse, which means our binary
// will work on systems that don't have it.
#define LATE(sym) \
  LATESYM_GET(PulseAudioSymbolTable, &pulse_->symbol_table_, sym)

// Functionality that is common to both PulseAudioInputStream and
// PulseAudioOutputStream.
class PulseAudioStream {
 public:
  PulseAudioStream(PulseAudioSoundSystem *pulse, pa_stream *stream, int flags)
      : pulse_(pulse), stream_(stream), flags_(flags) {
  }

  ~PulseAudioStream() {
    // Close() should have been called during the containing class's destructor.
    ASSERT(stream_ == NULL);
  }

  // Must be called with the lock held.
  bool Close() {
    if (!IsClosed()) {
      // Unset this here so that we don't get a TERMINATED callback.
      LATE(pa_stream_set_state_callback)(stream_, NULL, NULL);
      if (LATE(pa_stream_disconnect)(stream_) != 0) {
        LOG(LS_ERROR) << "Can't disconnect stream";
        // Continue and return true anyways.
      }
      LATE(pa_stream_unref)(stream_);
      stream_ = NULL;
    }
    return true;
  }

  // Must be called with the lock held.
  int LatencyUsecs() {
    if (!(flags_ & SoundSystemInterface::FLAG_REPORT_LATENCY)) {
      return 0;
    }

    pa_usec_t latency;
    int negative;
    Lock();
    int re = LATE(pa_stream_get_latency)(stream_, &latency, &negative);
    Unlock();
    if (re != 0) {
      LOG(LS_ERROR) << "Can't query latency";
      // We'd rather continue playout/capture with an incorrect delay than stop
      // it altogether, so return a valid value.
      return 0;
    }
    if (negative) {
      // The delay can be negative for monitoring streams if the captured
      // samples haven't been played yet. In such a case, "latency" contains the
      // magnitude, so we must negate it to get the real value.
      return -latency;
    } else {
      return latency;
    }
  }

  PulseAudioSoundSystem *pulse() {
    return pulse_;
  }

  pa_stream *stream() {
    ASSERT(stream_ != NULL);
    return stream_;
  }

  bool IsClosed() {
    return stream_ == NULL;
  }

  void Lock() {
    pulse()->Lock();
  }

  void Unlock() {
    pulse()->Unlock();
  }

 private:
  PulseAudioSoundSystem *pulse_;
  pa_stream *stream_;
  int flags_;

  DISALLOW_COPY_AND_ASSIGN(PulseAudioStream);
};

// Redefine for the next two classes.
#undef LATE
#define LATE(sym) \
  LATESYM_GET(PulseAudioSymbolTable, &stream_.pulse()->symbol_table_, sym)

// Implementation of an input stream. See soundinputstreaminterface.h regarding
// thread-safety.
class PulseAudioInputStream :
    public SoundInputStreamInterface,
    private talk_base::Worker {

  struct GetVolumeCallbackData {
    PulseAudioInputStream *instance;
    pa_cvolume *channel_volumes;
  };

  struct GetSourceChannelCountCallbackData {
    PulseAudioInputStream *instance;
    uint8_t *channels;
  };

 public:
  PulseAudioInputStream(PulseAudioSoundSystem *pulse,
                        pa_stream *stream,
                        int flags)
      : stream_(pulse, stream, flags),
        temp_sample_data_(NULL),
        temp_sample_data_size_(0) {
    // This callback seems to never be issued, but let's set it anyways.
    LATE(pa_stream_set_overflow_callback)(stream, &OverflowCallback, NULL);
  }

  virtual ~PulseAudioInputStream() {
    bool success = Close();
    // We need that to live.
    VERIFY(success);
  }

  virtual bool StartReading() {
    return StartWork();
  }

  virtual bool StopReading() {
    return StopWork();
  }

  virtual bool GetVolume(int *volume) {
    bool ret = false;

    Lock();

    // Unlike output streams, input streams have no concept of a stream volume,
    // only a device volume. So we have to retrieve the volume of the device
    // itself.

    pa_cvolume channel_volumes;

    GetVolumeCallbackData data;
    data.instance = this;
    data.channel_volumes = &channel_volumes;

    pa_operation *op = LATE(pa_context_get_source_info_by_index)(
        stream_.pulse()->context_,
        LATE(pa_stream_get_device_index)(stream_.stream()),
        &GetVolumeCallbackThunk,
        &data);
    if (!stream_.pulse()->FinishOperation(op)) {
      goto done;
    }

    if (data.channel_volumes) {
      // This pointer was never unset by the callback, so we must have received
      // an empty list of infos. This probably never happens, but we code for it
      // anyway.
      LOG(LS_ERROR) << "Did not receive GetVolumeCallback";
      goto done;
    }

    // We now have the volume for each channel. Each channel could have a
    // different volume if, e.g., the user went and changed the volumes in the
    // PA UI. To get a single volume for SoundSystemInterface we just take the
    // maximum. Ideally we'd do so with pa_cvolume_max, but it doesn't exist in
    // Hardy, so we do it manually.
    pa_volume_t pa_volume;
    pa_volume = MaxChannelVolume(&channel_volumes);
    // Now map onto the SoundSystemInterface range.
    *volume = PulseVolumeToCricketVolume(pa_volume);

    ret = true;
   done:
    Unlock();
    return ret;
  }

  virtual bool SetVolume(int volume) {
    bool ret = false;
    pa_volume_t pa_volume = CricketVolumeToPulseVolume(volume);

    Lock();

    // Unlike output streams, input streams have no concept of a stream volume,
    // only a device volume. So we have to change the volume of the device
    // itself.

    // The device may have a different number of channels than the stream and
    // their mapping may be different, so we don't want to use the channel count
    // from our sample spec. We could use PA_CHANNELS_MAX to cover our bases,
    // and the server allows that even if the device's channel count is lower,
    // but some buggy PA clients don't like that (the pavucontrol on Hardy dies
    // in an assert if the channel count is different). So instead we look up
    // the actual number of channels that the device has.

    uint8_t channels;

    GetSourceChannelCountCallbackData data;
    data.instance = this;
    data.channels = &channels;

    uint32_t device_index = LATE(pa_stream_get_device_index)(stream_.stream());

    pa_operation *op = LATE(pa_context_get_source_info_by_index)(
        stream_.pulse()->context_,
        device_index,
        &GetSourceChannelCountCallbackThunk,
        &data);
    if (!stream_.pulse()->FinishOperation(op)) {
      goto done;
    }

    if (data.channels) {
      // This pointer was never unset by the callback, so we must have received
      // an empty list of infos. This probably never happens, but we code for it
      // anyway.
      LOG(LS_ERROR) << "Did not receive GetSourceChannelCountCallback";
      goto done;
    }

    pa_cvolume channel_volumes;
    LATE(pa_cvolume_set)(&channel_volumes, channels, pa_volume);

    op = LATE(pa_context_set_source_volume_by_index)(
        stream_.pulse()->context_,
        device_index,
        &channel_volumes,
        // This callback merely logs errors.
        &SetVolumeCallback,
        NULL);
    if (!op) {
      LOG(LS_ERROR) << "pa_context_set_source_volume_by_index()";
      goto done;
    }
    // Don't need to wait for this to complete.
    LATE(pa_operation_unref)(op);

    ret = true;
   done:
    Unlock();
    return ret;
  }

  virtual bool Close() {
    if (!StopReading()) {
      return false;
    }
    bool ret = true;
    if (!stream_.IsClosed()) {
      Lock();
      ret = stream_.Close();
      Unlock();
    }
    return ret;
  }

  virtual int LatencyUsecs() {
    return stream_.LatencyUsecs();
  }

 private:
  void Lock() {
    stream_.Lock();
  }

  void Unlock() {
    stream_.Unlock();
  }

  void EnableReadCallback() {
    LATE(pa_stream_set_read_callback)(
         stream_.stream(),
         &ReadCallbackThunk,
         this);
  }

  void DisableReadCallback() {
    LATE(pa_stream_set_read_callback)(
         stream_.stream(),
         NULL,
         NULL);
  }

  static void ReadCallbackThunk(pa_stream *unused1,
                                size_t unused2,
                                void *userdata) {
    PulseAudioInputStream *instance =
        static_cast<PulseAudioInputStream *>(userdata);
    instance->OnReadCallback();
  }

  void OnReadCallback() {
    // We get the data pointer and size now in order to save one Lock/Unlock
    // on OnMessage.
    if (LATE(pa_stream_peek)(stream_.stream(),
                             &temp_sample_data_,
                             &temp_sample_data_size_) != 0) {
      LOG(LS_ERROR) << "Can't read data!";
      return;
    }
    // Since we consume the data asynchronously on a different thread, we have
    // to temporarily disable the read callback or else Pulse will call it
    // continuously until we consume the data. We re-enable it below.
    DisableReadCallback();
    HaveWork();
  }

  // Inherited from Worker.
  virtual void OnStart() {
    Lock();
    EnableReadCallback();
    Unlock();
  }

  // Inherited from Worker.
  virtual void OnHaveWork() {
    ASSERT(temp_sample_data_ && temp_sample_data_size_);
    SignalSamplesRead(temp_sample_data_,
                      temp_sample_data_size_,
                      this);
    temp_sample_data_ = NULL;
    temp_sample_data_size_ = 0;

    Lock();
    for (;;) {
      // Ack the last thing we read.
      if (LATE(pa_stream_drop)(stream_.stream()) != 0) {
        LOG(LS_ERROR) << "Can't ack read data";
      }

      if (LATE(pa_stream_readable_size)(stream_.stream()) <= 0) {
        // Then that was all the data.
        break;
      }

      // Else more data.
      const void *sample_data;
      size_t sample_data_size;
      if (LATE(pa_stream_peek)(stream_.stream(),
                               &sample_data,
                               &sample_data_size) != 0) {
        LOG(LS_ERROR) << "Can't read data!";
        break;
      }

      // Drop lock for sigslot dispatch, which could take a while.
      Unlock();
      SignalSamplesRead(sample_data, sample_data_size, this);
      Lock();

      // Return to top of loop for the ack and the check for more data.
    }
    EnableReadCallback();
    Unlock();
  }

  // Inherited from Worker.
  virtual void OnStop() {
    Lock();
    DisableReadCallback();
    Unlock();
  }

  static void OverflowCallback(pa_stream *stream,
                               void *userdata) {
    LOG(LS_WARNING) << "Buffer overflow on capture stream " << stream;
  }

  static void GetVolumeCallbackThunk(pa_context *unused,
                                     const pa_source_info *info,
                                     int eol,
                                     void *userdata) {
    GetVolumeCallbackData *data =
        static_cast<GetVolumeCallbackData *>(userdata);
    data->instance->OnGetVolumeCallback(info, eol, &data->channel_volumes);
  }

  void OnGetVolumeCallback(const pa_source_info *info,
                           int eol,
                           pa_cvolume **channel_volumes) {
    if (eol) {
      // List is over. Wake GetVolume().
      stream_.pulse()->Signal();
      return;
    }

    if (*channel_volumes) {
      **channel_volumes = info->volume;
      // Unset the pointer so that we know that we have have already copied the
      // volume.
      *channel_volumes = NULL;
    } else {
      // We have received an additional callback after the first one, which
      // doesn't make sense for a single source. This probably never happens,
      // but we code for it anyway.
      LOG(LS_WARNING) << "Ignoring extra GetVolumeCallback";
    }
  }

  static void GetSourceChannelCountCallbackThunk(pa_context *unused,
                                                 const pa_source_info *info,
                                                 int eol,
                                                 void *userdata) {
    GetSourceChannelCountCallbackData *data =
        static_cast<GetSourceChannelCountCallbackData *>(userdata);
    data->instance->OnGetSourceChannelCountCallback(info, eol, &data->channels);
  }

  void OnGetSourceChannelCountCallback(const pa_source_info *info,
                                       int eol,
                                       uint8_t **channels) {
    if (eol) {
      // List is over. Wake SetVolume().
      stream_.pulse()->Signal();
      return;
    }

    if (*channels) {
      **channels = info->channel_map.channels;
      // Unset the pointer so that we know that we have have already copied the
      // channel count.
      *channels = NULL;
    } else {
      // We have received an additional callback after the first one, which
      // doesn't make sense for a single source. This probably never happens,
      // but we code for it anyway.
      LOG(LS_WARNING) << "Ignoring extra GetSourceChannelCountCallback";
    }
  }

  static void SetVolumeCallback(pa_context *unused1,
                                int success,
                                void *unused2) {
    if (!success) {
      LOG(LS_ERROR) << "Failed to change capture volume";
    }
  }

  PulseAudioStream stream_;
  // Temporary storage for passing data between threads.
  const void *temp_sample_data_;
  size_t temp_sample_data_size_;

  DISALLOW_COPY_AND_ASSIGN(PulseAudioInputStream);
};

// Implementation of an output stream. See soundoutputstreaminterface.h
// regarding thread-safety.
class PulseAudioOutputStream :
    public SoundOutputStreamInterface,
    private talk_base::Worker {

  struct GetVolumeCallbackData {
    PulseAudioOutputStream *instance;
    pa_cvolume *channel_volumes;
  };

 public:
  PulseAudioOutputStream(PulseAudioSoundSystem *pulse,
                         pa_stream *stream,
                         int flags,
                         int latency)
      : stream_(pulse, stream, flags),
        configured_latency_(latency),
        temp_buffer_space_(0) {
    LATE(pa_stream_set_underflow_callback)(stream,
                                           &UnderflowCallbackThunk,
                                           this);
  }

  virtual ~PulseAudioOutputStream() {
    bool success = Close();
    // We need that to live.
    VERIFY(success);
  }

  virtual bool EnableBufferMonitoring() {
    return StartWork();
  }

  virtual bool DisableBufferMonitoring() {
    return StopWork();
  }

  virtual bool WriteSamples(const void *sample_data,
                            size_t size) {
    bool ret = true;
    Lock();
    if (LATE(pa_stream_write)(stream_.stream(),
                              sample_data,
                              size,
                              NULL,
                              0,
                              PA_SEEK_RELATIVE) != 0) {
      LOG(LS_ERROR) << "Unable to write";
      ret = false;
    }
    Unlock();
    return ret;
  }

  virtual bool GetVolume(int *volume) {
    bool ret = false;

    Lock();

    pa_cvolume channel_volumes;

    GetVolumeCallbackData data;
    data.instance = this;
    data.channel_volumes = &channel_volumes;

    pa_operation *op = LATE(pa_context_get_sink_input_info)(
        stream_.pulse()->context_,
        LATE(pa_stream_get_index)(stream_.stream()),
        &GetVolumeCallbackThunk,
        &data);
    if (!stream_.pulse()->FinishOperation(op)) {
      goto done;
    }

    if (data.channel_volumes) {
      // This pointer was never unset by the callback, so we must have received
      // an empty list of infos. This probably never happens, but we code for it
      // anyway.
      LOG(LS_ERROR) << "Did not receive GetVolumeCallback";
      goto done;
    }

    // We now have the volume for each channel. Each channel could have a
    // different volume if, e.g., the user went and changed the volumes in the
    // PA UI. To get a single volume for SoundSystemInterface we just take the
    // maximum. Ideally we'd do so with pa_cvolume_max, but it doesn't exist in
    // Hardy, so we do it manually.
    pa_volume_t pa_volume;
    pa_volume = MaxChannelVolume(&channel_volumes);
    // Now map onto the SoundSystemInterface range.
    *volume = PulseVolumeToCricketVolume(pa_volume);

    ret = true;
   done:
    Unlock();
    return ret;
  }

  virtual bool SetVolume(int volume) {
    bool ret = false;
    pa_volume_t pa_volume = CricketVolumeToPulseVolume(volume);

    Lock();

    const pa_sample_spec *spec = LATE(pa_stream_get_sample_spec)(
        stream_.stream());
    if (!spec) {
      LOG(LS_ERROR) << "pa_stream_get_sample_spec()";
      goto done;
    }

    pa_cvolume channel_volumes;
    LATE(pa_cvolume_set)(&channel_volumes, spec->channels, pa_volume);

    pa_operation *op;
    op = LATE(pa_context_set_sink_input_volume)(
        stream_.pulse()->context_,
        LATE(pa_stream_get_index)(stream_.stream()),
        &channel_volumes,
        // This callback merely logs errors.
        &SetVolumeCallback,
        NULL);
    if (!op) {
      LOG(LS_ERROR) << "pa_context_set_sink_input_volume()";
      goto done;
    }
    // Don't need to wait for this to complete.
    LATE(pa_operation_unref)(op);

    ret = true;
   done:
    Unlock();
    return ret;
  }

  virtual bool Close() {
    if (!DisableBufferMonitoring()) {
      return false;
    }
    bool ret = true;
    if (!stream_.IsClosed()) {
      Lock();
      LATE(pa_stream_set_underflow_callback)(stream_.stream(),
                                             NULL,
                                             NULL);
      ret = stream_.Close();
      Unlock();
    }
    return ret;
  }

  virtual int LatencyUsecs() {
    return stream_.LatencyUsecs();
  }

#if 0
  // TODO: Versions 0.9.16 and later of Pulse have a new API for
  // zero-copy writes, but Hardy is not new enough to have that so we can't
  // rely on it. Perhaps auto-detect if it's present or not and use it if we
  // can?

  virtual bool GetWriteBuffer(void **buffer, size_t *size) {
    bool ret = true;
    Lock();
    if (LATE(pa_stream_begin_write)(stream_.stream(), buffer, size) != 0) {
      LOG(LS_ERROR) << "Can't get write buffer";
      ret = false;
    }
    Unlock();
    return ret;
  }

  // Releases the caller's hold on the write buffer. "written" must be the
  // amount of data that was written.
  virtual bool ReleaseWriteBuffer(void *buffer, size_t written) {
    bool ret = true;
    Lock();
    if (written == 0) {
      if (LATE(pa_stream_cancel_write)(stream_.stream()) != 0) {
        LOG(LS_ERROR) << "Can't cancel write";
        ret = false;
      }
    } else {
      if (LATE(pa_stream_write)(stream_.stream(),
                                buffer,
                                written,
                                NULL,
                                0,
                                PA_SEEK_RELATIVE) != 0) {
        LOG(LS_ERROR) << "Unable to write";
        ret = false;
      }
    }
    Unlock();
    return ret;
  }
#endif

 private:
  void Lock() {
    stream_.Lock();
  }

  void Unlock() {
    stream_.Unlock();
  }

  void EnableWriteCallback() {
    pa_stream_state_t state = LATE(pa_stream_get_state)(stream_.stream());
    if (state == PA_STREAM_READY) {
      // May already have available space. Must check.
      temp_buffer_space_ = LATE(pa_stream_writable_size)(stream_.stream());
      if (temp_buffer_space_ > 0) {
        // Yup, there is already space available, so if we register a write
        // callback then it will not receive any event. So dispatch one ourself
        // instead.
        HaveWork();
        return;
      }
    }
    LATE(pa_stream_set_write_callback)(
         stream_.stream(),
         &WriteCallbackThunk,
         this);
  }

  void DisableWriteCallback() {
    LATE(pa_stream_set_write_callback)(
         stream_.stream(),
         NULL,
         NULL);
  }

  static void WriteCallbackThunk(pa_stream *unused,
                                 size_t buffer_space,
                                 void *userdata) {
    PulseAudioOutputStream *instance =
        static_cast<PulseAudioOutputStream *>(userdata);
    instance->OnWriteCallback(buffer_space);
  }

  void OnWriteCallback(size_t buffer_space) {
    temp_buffer_space_ = buffer_space;
    // Since we write the data asynchronously on a different thread, we have
    // to temporarily disable the write callback or else Pulse will call it
    // continuously until we write the data. We re-enable it below.
    DisableWriteCallback();
    HaveWork();
  }

  // Inherited from Worker.
  virtual void OnStart() {
    Lock();
    EnableWriteCallback();
    Unlock();
  }

  // Inherited from Worker.
  virtual void OnHaveWork() {
    ASSERT(temp_buffer_space_ > 0);

    SignalBufferSpace(temp_buffer_space_, this);

    temp_buffer_space_ = 0;
    Lock();
    EnableWriteCallback();
    Unlock();
  }

  // Inherited from Worker.
  virtual void OnStop() {
    Lock();
    DisableWriteCallback();
    Unlock();
  }

  static void UnderflowCallbackThunk(pa_stream *unused,
                                     void *userdata) {
    PulseAudioOutputStream *instance =
        static_cast<PulseAudioOutputStream *>(userdata);
    instance->OnUnderflowCallback();
  }

  void OnUnderflowCallback() {
    LOG(LS_WARNING) << "Buffer underflow on playback stream "
                    << stream_.stream();

    if (configured_latency_ == SoundSystemInterface::kNoLatencyRequirements) {
      // We didn't configure a pa_buffer_attr before, so switching to one now
      // would be questionable.
      return;
    }

    // Otherwise reconfigure the stream with a higher target latency.

    const pa_sample_spec *spec = LATE(pa_stream_get_sample_spec)(
        stream_.stream());
    if (!spec) {
      LOG(LS_ERROR) << "pa_stream_get_sample_spec()";
      return;
    }

    size_t bytes_per_sec = LATE(pa_bytes_per_second)(spec);

    int new_latency = configured_latency_ +
        bytes_per_sec * kPlaybackLatencyIncrementMsecs / kMsecsPerSec;

    pa_buffer_attr new_attr = {0};
    FillPlaybackBufferAttr(new_latency, &new_attr);

    pa_operation *op = LATE(pa_stream_set_buffer_attr)(stream_.stream(),
                                                       &new_attr,
                                                       // No callback.
                                                       NULL,
                                                       NULL);
    if (!op) {
      LOG(LS_ERROR) << "pa_stream_set_buffer_attr()";
      return;
    }
    // Don't need to wait for this to complete.
    LATE(pa_operation_unref)(op);

    // Save the new latency in case we underflow again.
    configured_latency_ = new_latency;
  }

  static void GetVolumeCallbackThunk(pa_context *unused,
                                     const pa_sink_input_info *info,
                                     int eol,
                                     void *userdata) {
    GetVolumeCallbackData *data =
        static_cast<GetVolumeCallbackData *>(userdata);
    data->instance->OnGetVolumeCallback(info, eol, &data->channel_volumes);
  }

  void OnGetVolumeCallback(const pa_sink_input_info *info,
                           int eol,
                           pa_cvolume **channel_volumes) {
    if (eol) {
      // List is over. Wake GetVolume().
      stream_.pulse()->Signal();
      return;
    }

    if (*channel_volumes) {
      **channel_volumes = info->volume;
      // Unset the pointer so that we know that we have have already copied the
      // volume.
      *channel_volumes = NULL;
    } else {
      // We have received an additional callback after the first one, which
      // doesn't make sense for a single sink input. This probably never
      // happens, but we code for it anyway.
      LOG(LS_WARNING) << "Ignoring extra GetVolumeCallback";
    }
  }

  static void SetVolumeCallback(pa_context *unused1,
                                int success,
                                void *unused2) {
    if (!success) {
      LOG(LS_ERROR) << "Failed to change playback volume";
    }
  }

  PulseAudioStream stream_;
  int configured_latency_;
  // Temporary storage for passing data between threads.
  size_t temp_buffer_space_;

  DISALLOW_COPY_AND_ASSIGN(PulseAudioOutputStream);
};

// Redefine for the main class.
#undef LATE
#define LATE(sym) \
  LATESYM_GET(PulseAudioSymbolTable, &symbol_table_, sym)

PulseAudioSoundSystem::PulseAudioSoundSystem()
    : mainloop_(NULL), context_(NULL) {
}

PulseAudioSoundSystem::~PulseAudioSoundSystem() {
  Terminate();
}

bool PulseAudioSoundSystem::Init() {
  if (IsInitialized()) {
    return true;
  }

  // Load libpulse.
  if (!symbol_table_.Load()) {
    // Most likely the Pulse library and sound server are not installed on
    // this system.
    LOG(LS_WARNING) << "Failed to load symbol table";
    return false;
  }

  // Now create and start the Pulse event thread.
  mainloop_ = LATE(pa_threaded_mainloop_new)();
  if (!mainloop_) {
    LOG(LS_ERROR) << "Can't create mainloop";
    goto fail0;
  }

  if (LATE(pa_threaded_mainloop_start)(mainloop_) != 0) {
    LOG(LS_ERROR) << "Can't start mainloop";
    goto fail1;
  }

  Lock();
  context_ = CreateNewConnection();
  Unlock();

  if (!context_) {
    goto fail2;
  }

  // Otherwise we're now ready!
  return true;

 fail2:
  LATE(pa_threaded_mainloop_stop)(mainloop_);
 fail1:
  LATE(pa_threaded_mainloop_free)(mainloop_);
  mainloop_ = NULL;
 fail0:
  return false;
}

void PulseAudioSoundSystem::Terminate() {
  if (!IsInitialized()) {
    return;
  }

  Lock();
  LATE(pa_context_disconnect)(context_);
  LATE(pa_context_unref)(context_);
  Unlock();
  context_ = NULL;
  LATE(pa_threaded_mainloop_stop)(mainloop_);
  LATE(pa_threaded_mainloop_free)(mainloop_);
  mainloop_ = NULL;

  // We do not unload the symbol table because we may need it again soon if
  // Init() is called again.
}

bool PulseAudioSoundSystem::EnumeratePlaybackDevices(
    SoundDeviceLocatorList *devices) {
  return EnumerateDevices<pa_sink_info>(
      devices,
      &LATE(pa_context_get_sink_info_list),
      &EnumeratePlaybackDevicesCallbackThunk);
}

bool PulseAudioSoundSystem::EnumerateCaptureDevices(
    SoundDeviceLocatorList *devices) {
  return EnumerateDevices<pa_source_info>(
      devices,
      &LATE(pa_context_get_source_info_list),
      &EnumerateCaptureDevicesCallbackThunk);
}

bool PulseAudioSoundSystem::GetDefaultPlaybackDevice(
    SoundDeviceLocator **device) {
  return GetDefaultDevice<&pa_server_info::default_sink_name>(device);
}

bool PulseAudioSoundSystem::GetDefaultCaptureDevice(
    SoundDeviceLocator **device) {
  return GetDefaultDevice<&pa_server_info::default_source_name>(device);
}

SoundOutputStreamInterface *PulseAudioSoundSystem::OpenPlaybackDevice(
    const SoundDeviceLocator *device,
    const OpenParams &params) {
  return OpenDevice<SoundOutputStreamInterface>(
      device,
      params,
      "Playback",
      &PulseAudioSoundSystem::ConnectOutputStream);
}

SoundInputStreamInterface *PulseAudioSoundSystem::OpenCaptureDevice(
    const SoundDeviceLocator *device,
    const OpenParams &params) {
  return OpenDevice<SoundInputStreamInterface>(
      device,
      params,
      "Capture",
      &PulseAudioSoundSystem::ConnectInputStream);
}

const char *PulseAudioSoundSystem::GetName() const {
  return "PulseAudio";
}

inline bool PulseAudioSoundSystem::IsInitialized() {
  return mainloop_ != NULL;
}

struct ConnectToPulseCallbackData {
  PulseAudioSoundSystem *instance;
  bool connect_done;
};

void PulseAudioSoundSystem::ConnectToPulseCallbackThunk(
    pa_context *context, void *userdata) {
  ConnectToPulseCallbackData *data =
      static_cast<ConnectToPulseCallbackData *>(userdata);
  data->instance->OnConnectToPulseCallback(context, &data->connect_done);
}

void PulseAudioSoundSystem::OnConnectToPulseCallback(
    pa_context *context, bool *connect_done) {
  pa_context_state_t state = LATE(pa_context_get_state)(context);
  if (state == PA_CONTEXT_READY ||
      state == PA_CONTEXT_FAILED ||
      state == PA_CONTEXT_TERMINATED) {
    // Connection process has reached a terminal state. Wake ConnectToPulse().
    *connect_done = true;
    Signal();
  }
}

// Must be called with the lock held.
bool PulseAudioSoundSystem::ConnectToPulse(pa_context *context) {
  bool ret = true;
  ConnectToPulseCallbackData data;
  // Have to put this up here to satisfy the compiler.
  pa_context_state_t state;

  data.instance = this;
  data.connect_done = false;

  LATE(pa_context_set_state_callback)(context,
                                      &ConnectToPulseCallbackThunk,
                                      &data);

  // Connect to PulseAudio sound server.
  if (LATE(pa_context_connect)(context,
                               NULL,          // Default server
                               PA_CONTEXT_NOAUTOSPAWN,
                               NULL) != 0) {  // No special fork handling needed
    LOG(LS_ERROR) << "Can't start connection to PulseAudio sound server";
    ret = false;
    goto done;
  }

  // Wait for the connection state machine to reach a terminal state.
  do {
    Wait();
  } while (!data.connect_done);

  // Now check to see what final state we reached.
  state = LATE(pa_context_get_state)(context);

  if (state != PA_CONTEXT_READY) {
    if (state == PA_CONTEXT_FAILED) {
      LOG(LS_ERROR) << "Failed to connect to PulseAudio sound server";
    } else if (state == PA_CONTEXT_TERMINATED) {
      LOG(LS_ERROR) << "PulseAudio connection terminated early";
    } else {
      // Shouldn't happen, because we only signal on one of those three states.
      LOG(LS_ERROR) << "Unknown problem connecting to PulseAudio";
    }
    ret = false;
  }

 done:
  // We unset our callback for safety just in case the state might somehow
  // change later, because the pointer to "data" will be invalid after return
  // from this function.
  LATE(pa_context_set_state_callback)(context, NULL, NULL);
  return ret;
}

// Must be called with the lock held.
pa_context *PulseAudioSoundSystem::CreateNewConnection() {
  // Create connection context.
  std::string app_name;
  // TODO: Pulse etiquette says this name should be localized. Do
  // we care?
  talk_base::Filesystem::GetApplicationName(&app_name);
  pa_context *context = LATE(pa_context_new)(
      LATE(pa_threaded_mainloop_get_api)(mainloop_),
      app_name.c_str());
  if (!context) {
    LOG(LS_ERROR) << "Can't create context";
    goto fail0;
  }

  // Now connect.
  if (!ConnectToPulse(context)) {
    goto fail1;
  }

  // Otherwise the connection succeeded and is ready.
  return context;

 fail1:
  LATE(pa_context_unref)(context);
 fail0:
  return NULL;
}

struct EnumerateDevicesCallbackData {
  PulseAudioSoundSystem *instance;
  SoundSystemInterface::SoundDeviceLocatorList *devices;
};

void PulseAudioSoundSystem::EnumeratePlaybackDevicesCallbackThunk(
    pa_context *unused,
    const pa_sink_info *info,
    int eol,
    void *userdata) {
  EnumerateDevicesCallbackData *data =
      static_cast<EnumerateDevicesCallbackData *>(userdata);
  data->instance->OnEnumeratePlaybackDevicesCallback(data->devices, info, eol);
}

void PulseAudioSoundSystem::EnumerateCaptureDevicesCallbackThunk(
    pa_context *unused,
    const pa_source_info *info,
    int eol,
    void *userdata) {
  EnumerateDevicesCallbackData *data =
      static_cast<EnumerateDevicesCallbackData *>(userdata);
  data->instance->OnEnumerateCaptureDevicesCallback(data->devices, info, eol);
}

void PulseAudioSoundSystem::OnEnumeratePlaybackDevicesCallback(
    SoundDeviceLocatorList *devices,
    const pa_sink_info *info,
    int eol) {
  if (eol) {
    // List is over. Wake EnumerateDevices().
    Signal();
    return;
  }

  // Else this is the next device.
  devices->push_back(
      new PulseAudioDeviceLocator(info->description, info->name));
}

void PulseAudioSoundSystem::OnEnumerateCaptureDevicesCallback(
    SoundDeviceLocatorList *devices,
    const pa_source_info *info,
    int eol) {
  if (eol) {
    // List is over. Wake EnumerateDevices().
    Signal();
    return;
  }

  if (info->monitor_of_sink != PA_INVALID_INDEX) {
    // We don't want to list monitor sources, since they are almost certainly
    // not what the user wants for voice conferencing.
    return;
  }

  // Else this is the next device.
  devices->push_back(
      new PulseAudioDeviceLocator(info->description, info->name));
}

template <typename InfoStruct>
bool PulseAudioSoundSystem::EnumerateDevices(
    SoundDeviceLocatorList *devices,
    pa_operation *(*enumerate_fn)(
        pa_context *c,
        void (*callback_fn)(
            pa_context *c,
            const InfoStruct *i,
            int eol,
            void *userdata),
        void *userdata),
    void (*callback_fn)(
        pa_context *c,
        const InfoStruct *i,
        int eol,
        void *userdata)) {
  ClearSoundDeviceLocatorList(devices);
  if (!IsInitialized()) {
    return false;
  }

  EnumerateDevicesCallbackData data;
  data.instance = this;
  data.devices = devices;

  Lock();
  pa_operation *op = (*enumerate_fn)(
      context_,
      callback_fn,
      &data);
  bool ret = FinishOperation(op);
  Unlock();
  return ret;
}

struct GetDefaultDeviceCallbackData {
  PulseAudioSoundSystem *instance;
  SoundDeviceLocator **device;
};

template <const char *(pa_server_info::*field)>
void PulseAudioSoundSystem::GetDefaultDeviceCallbackThunk(
    pa_context *unused,
    const pa_server_info *info,
    void *userdata) {
  GetDefaultDeviceCallbackData *data =
      static_cast<GetDefaultDeviceCallbackData *>(userdata);
  data->instance->OnGetDefaultDeviceCallback<field>(info, data->device);
}

template <const char *(pa_server_info::*field)>
void PulseAudioSoundSystem::OnGetDefaultDeviceCallback(
    const pa_server_info *info,
    SoundDeviceLocator **device) {
  if (info) {
    const char *dev = info->*field;
    if (dev) {
      *device = new PulseAudioDeviceLocator("Default device", dev);
    }
  }
  Signal();
}

template <const char *(pa_server_info::*field)>
bool PulseAudioSoundSystem::GetDefaultDevice(SoundDeviceLocator **device) {
  if (!IsInitialized()) {
    return false;
  }
  bool ret;
  *device = NULL;
  GetDefaultDeviceCallbackData data;
  data.instance = this;
  data.device = device;
  Lock();
  pa_operation *op = LATE(pa_context_get_server_info)(
      context_,
      &GetDefaultDeviceCallbackThunk<field>,
      &data);
  ret = FinishOperation(op);
  Unlock();
  return ret && (*device != NULL);
}

void PulseAudioSoundSystem::StreamStateChangedCallbackThunk(
    pa_stream *stream,
    void *userdata) {
  PulseAudioSoundSystem *instance =
      static_cast<PulseAudioSoundSystem *>(userdata);
  instance->OnStreamStateChangedCallback(stream);
}

void PulseAudioSoundSystem::OnStreamStateChangedCallback(pa_stream *stream) {
  pa_stream_state_t state = LATE(pa_stream_get_state)(stream);
  if (state == PA_STREAM_READY) {
    LOG(LS_INFO) << "Pulse stream " << stream << " ready";
  } else if (state == PA_STREAM_FAILED ||
             state == PA_STREAM_TERMINATED ||
             state == PA_STREAM_UNCONNECTED) {
    LOG(LS_ERROR) << "Pulse stream " << stream << " failed to connect: "
                  << LastError();
  }
}

template <typename StreamInterface>
StreamInterface *PulseAudioSoundSystem::OpenDevice(
    const SoundDeviceLocator *device,
    const OpenParams &params,
    const char *stream_name,
    StreamInterface *(PulseAudioSoundSystem::*connect_fn)(
        pa_stream *stream,
        const char *dev,
        int flags,
        pa_stream_flags_t pa_flags,
        int latency,
        const pa_sample_spec &spec)) {
  if (!IsInitialized()) {
    return NULL;
  }

  const char *dev = static_cast<const PulseAudioDeviceLocator *>(device)->
      device_name().c_str();

  StreamInterface *stream_interface = NULL;

  ASSERT(params.format < ARRAY_SIZE(kCricketFormatToPulseFormatTable));

  pa_sample_spec spec;
  spec.format = kCricketFormatToPulseFormatTable[params.format];
  spec.rate = params.freq;
  spec.channels = params.channels;

  int pa_flags = 0;
  if (params.flags & FLAG_REPORT_LATENCY) {
    pa_flags |= PA_STREAM_INTERPOLATE_TIMING |
                PA_STREAM_AUTO_TIMING_UPDATE;
  }

  if (params.latency != kNoLatencyRequirements) {
    // If configuring a specific latency then we want to specify
    // PA_STREAM_ADJUST_LATENCY to make the server adjust parameters
    // automatically to reach that target latency. However, that flag doesn't
    // exist in Ubuntu 8.04 and many people still use that, so we have to check
    // the protocol version of libpulse.
    if (LATE(pa_context_get_protocol_version)(context_) >=
        kAdjustLatencyProtocolVersion) {
      pa_flags |= PA_STREAM_ADJUST_LATENCY;
    }
  }

  Lock();

  pa_stream *stream = LATE(pa_stream_new)(context_, stream_name, &spec, NULL);
  if (!stream) {
    LOG(LS_ERROR) << "Can't create pa_stream";
    goto done;
  }

  // Set a state callback to log errors.
  LATE(pa_stream_set_state_callback)(stream,
                                     &StreamStateChangedCallbackThunk,
                                     this);

  stream_interface = (this->*connect_fn)(
      stream,
      dev,
      params.flags,
      static_cast<pa_stream_flags_t>(pa_flags),
      params.latency,
      spec);
  if (!stream_interface) {
    LOG(LS_ERROR) << "Can't connect stream to " << dev;
    LATE(pa_stream_unref)(stream);
  }

 done:
  Unlock();
  return stream_interface;
}

// Must be called with the lock held.
SoundOutputStreamInterface *PulseAudioSoundSystem::ConnectOutputStream(
    pa_stream *stream,
    const char *dev,
    int flags,
    pa_stream_flags_t pa_flags,
    int latency,
    const pa_sample_spec &spec) {
  pa_buffer_attr attr = {0};
  pa_buffer_attr *pattr = NULL;
  if (latency != kNoLatencyRequirements) {
    // kLowLatency is 0, so we treat it the same as a request for zero latency.
    ssize_t bytes_per_sec = LATE(pa_bytes_per_second)(&spec);
    latency = talk_base::_max(
        latency,
        static_cast<int>(
            bytes_per_sec * kPlaybackLatencyMinimumMsecs / kMsecsPerSec));
    FillPlaybackBufferAttr(latency, &attr);
    pattr = &attr;
  }
  if (LATE(pa_stream_connect_playback)(stream,
                                       dev,
                                       pattr,
                                       pa_flags,
                                       // Let server choose volume
                                       NULL,
                                       // Not synchronized to any other playout
                                       NULL) != 0) {
    return NULL;
  }
  return new PulseAudioOutputStream(this, stream, flags, latency);
}

// Must be called with the lock held.
SoundInputStreamInterface *PulseAudioSoundSystem::ConnectInputStream(
    pa_stream *stream,
    const char *dev,
    int flags,
    pa_stream_flags_t pa_flags,
    int latency,
    const pa_sample_spec &spec) {
  pa_buffer_attr attr = {0};
  pa_buffer_attr *pattr = NULL;
  if (latency != kNoLatencyRequirements) {
    size_t bytes_per_sec = LATE(pa_bytes_per_second)(&spec);
    if (latency == kLowLatency) {
      latency = bytes_per_sec * kLowCaptureLatencyMsecs / kMsecsPerSec;
    }
    // Note: fragsize specifies a maximum transfer size, not a minimum, so it is
    // not possible to force a high latency setting, only a low one.
    attr.fragsize = latency;
    attr.maxlength = latency +
        bytes_per_sec * kCaptureBufferExtraMsecs / kMsecsPerSec;
    LOG(LS_VERBOSE) << "Configuring latency = " << attr.fragsize
                    << ", maxlength = " << attr.maxlength;
    pattr = &attr;
  }
  if (LATE(pa_stream_connect_record)(stream,
                                     dev,
                                     pattr,
                                     pa_flags) != 0) {
    return NULL;
  }
  return new PulseAudioInputStream(this, stream, flags);
}

// Must be called with the lock held.
bool PulseAudioSoundSystem::FinishOperation(pa_operation *op) {
  if (!op) {
    LOG(LS_ERROR) << "Failed to start operation";
    return false;
  }

  do {
    Wait();
  } while (LATE(pa_operation_get_state)(op) == PA_OPERATION_RUNNING);

  LATE(pa_operation_unref)(op);

  return true;
}

inline void PulseAudioSoundSystem::Lock() {
  LATE(pa_threaded_mainloop_lock)(mainloop_);
}

inline void PulseAudioSoundSystem::Unlock() {
  LATE(pa_threaded_mainloop_unlock)(mainloop_);
}

// Must be called with the lock held.
inline void PulseAudioSoundSystem::Wait() {
  LATE(pa_threaded_mainloop_wait)(mainloop_);
}

// Must be called with the lock held.
inline void PulseAudioSoundSystem::Signal() {
  LATE(pa_threaded_mainloop_signal)(mainloop_, 0);
}

// Must be called with the lock held.
const char *PulseAudioSoundSystem::LastError() {
  return LATE(pa_strerror)(LATE(pa_context_errno)(context_));
}

}  // namespace cricket

#endif  // HAVE_LIBPULSE
