/*
 * libjingle
 * Copyright 2004--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/alsasoundsystem.h"

#include "talk/base/common.h"
#include "talk/base/logging.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/stringutils.h"
#include "talk/base/timeutils.h"
#include "talk/base/worker.h"
#include "talk/sound/sounddevicelocator.h"
#include "talk/sound/soundinputstreaminterface.h"
#include "talk/sound/soundoutputstreaminterface.h"

namespace cricket {

// Lookup table from the cricket format enum in soundsysteminterface.h to
// ALSA's enums.
static const snd_pcm_format_t kCricketFormatToAlsaFormatTable[] = {
  // The order here must match the order in soundsysteminterface.h
  SND_PCM_FORMAT_S16_LE,
};

// Lookup table for the size of a single sample of a given format.
static const size_t kCricketFormatToSampleSizeTable[] = {
  // The order here must match the order in soundsysteminterface.h
  sizeof(int16_t),  // 2
};

// Minimum latency we allow, in microseconds. This is more or less arbitrary,
// but it has to be at least large enough to be able to buffer data during a
// missed context switch, and the typical Linux scheduling quantum is 10ms.
static const int kMinimumLatencyUsecs = 20 * 1000;

// The latency we'll use for kNoLatencyRequirements (chosen arbitrarily).
static const int kDefaultLatencyUsecs = kMinimumLatencyUsecs * 2;

// We translate newlines in ALSA device descriptions to hyphens.
static const char kAlsaDescriptionSearch[] = "\n";
static const char kAlsaDescriptionReplace[] = " - ";

class AlsaDeviceLocator : public SoundDeviceLocator {
 public:
  AlsaDeviceLocator(const std::string &name,
                    const std::string &device_name)
      : SoundDeviceLocator(name, device_name) {
    // The ALSA descriptions have newlines in them, which won't show up in
    // a drop-down box. Replace them with hyphens.
    talk_base::replace_substrs(kAlsaDescriptionSearch,
                               sizeof(kAlsaDescriptionSearch) - 1,
                               kAlsaDescriptionReplace,
                               sizeof(kAlsaDescriptionReplace) - 1,
                               &name_);
  }

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

// Accesses ALSA functions through our late-binding symbol table instead of
// directly. This way we don't have to link to libasound, which means our binary
// will load faster and we can run on strange systems that may not have
// libasound
#define LATE(sym) \
  LATESYM_GET(AlsaSymbolTable, &alsa_->symbol_table_, sym)

// Functionality that is common to both AlsaInputStream and AlsaOutputStream.
class AlsaStream {
 public:
  AlsaStream(AlsaSoundSystem *alsa,
             snd_pcm_t *handle,
             size_t frame_size,
             int wait_timeout_ms,
             int flags,
             int freq)
      : alsa_(alsa),
        handle_(handle),
        frame_size_(frame_size),
        wait_timeout_ms_(wait_timeout_ms),
        flags_(flags),
        freq_(freq) {
  }

  ~AlsaStream() {
    Close();
  }

  // Waits for the stream to be ready to accept/return more data, and returns
  // how much can be written/read, or 0 if we need to Wait() again.
  snd_pcm_uframes_t Wait() {
    snd_pcm_sframes_t frames;
    // Ideally we would not use snd_pcm_wait() and instead hook snd_pcm_poll_*
    // into PhysicalSocketServer, but PhysicalSocketServer is nasty enough
    // already and the current clients of SoundSystemInterface do not run
    // anything else on their worker threads, so snd_pcm_wait() is good enough.
    frames = LATE(snd_pcm_avail_update)(handle_);
    if (frames < 0) {
      LOG(LS_ERROR) << "snd_pcm_avail_update(): " << GetError(frames);
      Recover(frames);
      return 0;
    } else if (frames > 0) {
      // Already ready, so no need to wait.
      return frames;
    }
    // Else no space/data available, so must wait.
    int ready = LATE(snd_pcm_wait)(handle_, wait_timeout_ms_);
    if (ready < 0) {
      LOG(LS_ERROR) << "snd_pcm_wait(): " << GetError(ready);
      Recover(ready);
      return 0;
    } else if (ready == 0) {
      // Timeout, so nothing can be written/read right now.
      // We set the timeout to twice the requested latency, so continuous
      // timeouts are indicative of a problem, so log as a warning.
      LOG(LS_WARNING) << "Timeout while waiting on stream";
      return 0;
    }
    // Else ready > 0 (i.e., 1), so it's ready. Get count.
    frames = LATE(snd_pcm_avail_update)(handle_);
    if (frames < 0) {
      LOG(LS_ERROR) << "snd_pcm_avail_update(): " << GetError(frames);
      Recover(frames);
      return 0;
    } else if (frames == 0) {
      // wait() said we were ready, so this ought to have been positive. Has
      // been observed to happen in practice though.
      LOG(LS_WARNING) << "Spurious wake-up";
    }
    return frames;
  }

  int CurrentDelayUsecs() {
    if (!(flags_ & SoundSystemInterface::FLAG_REPORT_LATENCY)) {
      return 0;
    }

    snd_pcm_sframes_t delay;
    int err = LATE(snd_pcm_delay)(handle_, &delay);
    if (err != 0) {
      LOG(LS_ERROR) << "snd_pcm_delay(): " << GetError(err);
      Recover(err);
      // We'd rather continue playout/capture with an incorrect delay than stop
      // it altogether, so return a valid value.
      return 0;
    }
    // The delay is in frames. Convert to microseconds.
    return delay * talk_base::kNumMicrosecsPerSec / freq_;
  }

  // Used to recover from certain recoverable errors, principally buffer overrun
  // or underrun (identified as EPIPE). Without calling this the stream stays
  // in the error state forever.
  bool Recover(int error) {
    int err;
    err = LATE(snd_pcm_recover)(handle_,
                                error,
                                // Silent; i.e., no logging on stderr.
                                1);
    if (err != 0) {
      // Docs say snd_pcm_recover returns the original error if it is not one
      // of the recoverable ones, so this log message will probably contain the
      // same error twice.
      LOG(LS_ERROR) << "Unable to recover from \"" << GetError(error) << "\": "
                    << GetError(err);
      return false;
    }
    if (error == -EPIPE &&  // Buffer underrun/overrun.
        LATE(snd_pcm_stream)(handle_) == SND_PCM_STREAM_CAPTURE) {
      // For capture streams we also have to repeat the explicit start() to get
      // data flowing again.
      err = LATE(snd_pcm_start)(handle_);
      if (err != 0) {
        LOG(LS_ERROR) << "snd_pcm_start(): " << GetError(err);
        return false;
      }
    }
    return true;
  }

  bool Close() {
    if (handle_) {
      int err;
      err = LATE(snd_pcm_drop)(handle_);
      if (err != 0) {
        LOG(LS_ERROR) << "snd_pcm_drop(): " << GetError(err);
        // Continue anyways.
      }
      err = LATE(snd_pcm_close)(handle_);
      if (err != 0) {
        LOG(LS_ERROR) << "snd_pcm_close(): " << GetError(err);
        // Continue anyways.
      }
      handle_ = NULL;
    }
    return true;
  }

  AlsaSoundSystem *alsa() {
    return alsa_;
  }

  snd_pcm_t *handle() {
    return handle_;
  }

  const char *GetError(int err) {
    return alsa_->GetError(err);
  }

  size_t frame_size() {
    return frame_size_;
  }

 private:
  AlsaSoundSystem *alsa_;
  snd_pcm_t *handle_;
  size_t frame_size_;
  int wait_timeout_ms_;
  int flags_;
  int freq_;

  DISALLOW_COPY_AND_ASSIGN(AlsaStream);
};

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

// Implementation of an input stream. See soundinputstreaminterface.h regarding
// thread-safety.
class AlsaInputStream :
    public SoundInputStreamInterface,
    private talk_base::Worker {
 public:
  AlsaInputStream(AlsaSoundSystem *alsa,
                  snd_pcm_t *handle,
                  size_t frame_size,
                  int wait_timeout_ms,
                  int flags,
                  int freq)
      : stream_(alsa, handle, frame_size, wait_timeout_ms, flags, freq),
        buffer_size_(0) {
  }

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

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

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

  virtual bool GetVolume(int *volume) {
    // TODO: Implement this.
    return false;
  }

  virtual bool SetVolume(int volume) {
    // TODO: Implement this.
    return false;
  }

  virtual bool Close() {
    return StopReading() && stream_.Close();
  }

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

 private:
  // Inherited from Worker.
  virtual void OnStart() {
    HaveWork();
  }

  // Inherited from Worker.
  virtual void OnHaveWork() {
    // Block waiting for data.
    snd_pcm_uframes_t avail = stream_.Wait();
    if (avail > 0) {
      // Data is available.
      size_t size = avail * stream_.frame_size();
      if (size > buffer_size_) {
        // Must increase buffer size.
        buffer_.reset(new char[size]);
        buffer_size_ = size;
      }
      // Read all the data.
      snd_pcm_sframes_t read = LATE(snd_pcm_readi)(stream_.handle(),
                                                   buffer_.get(),
                                                   avail);
      if (read < 0) {
        LOG(LS_ERROR) << "snd_pcm_readi(): " << GetError(read);
        stream_.Recover(read);
      } else if (read == 0) {
        // Docs say this shouldn't happen.
        ASSERT(false);
        LOG(LS_ERROR) << "No data?";
      } else {
        // Got data. Pass it off to the app.
        SignalSamplesRead(buffer_.get(),
                          read * stream_.frame_size(),
                          this);
      }
    }
    // Check for more data with no delay, after any pending messages are
    // dispatched.
    HaveWork();
  }

  // Inherited from Worker.
  virtual void OnStop() {
    // Nothing to do.
  }

  const char *GetError(int err) {
    return stream_.GetError(err);
  }

  AlsaStream stream_;
  talk_base::scoped_array<char> buffer_;
  size_t buffer_size_;

  DISALLOW_COPY_AND_ASSIGN(AlsaInputStream);
};

// Implementation of an output stream. See soundoutputstreaminterface.h
// regarding thread-safety.
class AlsaOutputStream :
    public SoundOutputStreamInterface,
    private talk_base::Worker {
 public:
  AlsaOutputStream(AlsaSoundSystem *alsa,
                   snd_pcm_t *handle,
                   size_t frame_size,
                   int wait_timeout_ms,
                   int flags,
                   int freq)
      : stream_(alsa, handle, frame_size, wait_timeout_ms, flags, freq) {
  }

  virtual ~AlsaOutputStream() {
    bool success = DisableBufferMonitoring();
    // 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) {
    if (size % stream_.frame_size() != 0) {
      // No client of SoundSystemInterface does this, so let's not support it.
      // (If we wanted to support it, we'd basically just buffer the fractional
      // frame until we get more data.)
      ASSERT(false);
      LOG(LS_ERROR) << "Writes with fractional frames are not supported";
      return false;
    }
    snd_pcm_uframes_t frames = size / stream_.frame_size();
    snd_pcm_sframes_t written = LATE(snd_pcm_writei)(stream_.handle(),
                                                     sample_data,
                                                     frames);
    if (written < 0) {
      LOG(LS_ERROR) << "snd_pcm_writei(): " << GetError(written);
      stream_.Recover(written);
      return false;
    } else if (static_cast<snd_pcm_uframes_t>(written) < frames) {
      // Shouldn't happen. Drop the rest of the data.
      LOG(LS_ERROR) << "Stream wrote only " << written << " of " << frames
                    << " frames!";
      return false;
    }
    return true;
  }

  virtual bool GetVolume(int *volume) {
    // TODO: Implement this.
    return false;
  }

  virtual bool SetVolume(int volume) {
    // TODO: Implement this.
    return false;
  }

  virtual bool Close() {
    return DisableBufferMonitoring() && stream_.Close();
  }

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

 private:
  // Inherited from Worker.
  virtual void OnStart() {
    HaveWork();
  }

  // Inherited from Worker.
  virtual void OnHaveWork() {
    snd_pcm_uframes_t avail = stream_.Wait();
    if (avail > 0) {
      size_t space = avail * stream_.frame_size();
      SignalBufferSpace(space, this);
    }
    HaveWork();
  }

  // Inherited from Worker.
  virtual void OnStop() {
    // Nothing to do.
  }

  const char *GetError(int err) {
    return stream_.GetError(err);
  }

  AlsaStream stream_;

  DISALLOW_COPY_AND_ASSIGN(AlsaOutputStream);
};

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

AlsaSoundSystem::AlsaSoundSystem() : initialized_(false) {}

AlsaSoundSystem::~AlsaSoundSystem() {
  // Not really necessary, because Terminate() doesn't really do anything.
  Terminate();
}

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

  // Load libasound.
  if (!symbol_table_.Load()) {
    // Very odd for a Linux machine to not have a working libasound ...
    LOG(LS_ERROR) << "Failed to load symbol table";
    return false;
  }

  initialized_ = true;

  return true;
}

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

  initialized_ = false;

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

bool AlsaSoundSystem::EnumeratePlaybackDevices(
    SoundDeviceLocatorList *devices) {
  return EnumerateDevices(devices, false);
}

bool AlsaSoundSystem::EnumerateCaptureDevices(
    SoundDeviceLocatorList *devices) {
  return EnumerateDevices(devices, true);
}

bool AlsaSoundSystem::GetDefaultPlaybackDevice(SoundDeviceLocator **device) {
  return GetDefaultDevice(device);
}

bool AlsaSoundSystem::GetDefaultCaptureDevice(SoundDeviceLocator **device) {
  return GetDefaultDevice(device);
}

SoundOutputStreamInterface *AlsaSoundSystem::OpenPlaybackDevice(
    const SoundDeviceLocator *device,
    const OpenParams &params) {
  return OpenDevice<SoundOutputStreamInterface>(
      device,
      params,
      SND_PCM_STREAM_PLAYBACK,
      &AlsaSoundSystem::StartOutputStream);
}

SoundInputStreamInterface *AlsaSoundSystem::OpenCaptureDevice(
    const SoundDeviceLocator *device,
    const OpenParams &params) {
  return OpenDevice<SoundInputStreamInterface>(
      device,
      params,
      SND_PCM_STREAM_CAPTURE,
      &AlsaSoundSystem::StartInputStream);
}

const char *AlsaSoundSystem::GetName() const {
  return "ALSA";
}

bool AlsaSoundSystem::EnumerateDevices(
    SoundDeviceLocatorList *devices,
    bool capture_not_playback) {
  ClearSoundDeviceLocatorList(devices);

  if (!IsInitialized()) {
    return false;
  }

  const char *type = capture_not_playback ? "Input" : "Output";
  // dmix and dsnoop are only for playback and capture, respectively, but ALSA
  // stupidly includes them in both lists.
  const char *ignore_prefix = capture_not_playback ? "dmix:" : "dsnoop:";
  // (ALSA lists many more "devices" of questionable interest, but we show them
  // just in case the weird devices may actually be desirable for some
  // users/systems.)
  const char *ignore_default = "default";
  const char *ignore_null = "null";
  const char *ignore_pulse = "pulse";
  // The 'pulse' entry has a habit of mysteriously disappearing when you query
  // a second time. Remove it from our list. (GIPS lib did the same thing.)
  int err;

  void **hints;
  err = LATE(snd_device_name_hint)(-1,     // All cards
                                   "pcm",  // Only PCM devices
                                   &hints);
  if (err != 0) {
    LOG(LS_ERROR) << "snd_device_name_hint(): " << GetError(err);
    return false;
  }

  for (void **list = hints; *list != NULL; ++list) {
    char *actual_type = LATE(snd_device_name_get_hint)(*list, "IOID");
    if (actual_type) {  // NULL means it's both.
      bool wrong_type = (strcmp(actual_type, type) != 0);
      free(actual_type);
      if (wrong_type) {
        // Wrong type of device (i.e., input vs. output).
        continue;
      }
    }

    char *name = LATE(snd_device_name_get_hint)(*list, "NAME");
    if (!name) {
      LOG(LS_ERROR) << "Device has no name???";
      // Skip it.
      continue;
    }

    // Now check if we actually want to show this device.
    if (strcmp(name, ignore_default) != 0 &&
        strcmp(name, ignore_null) != 0 &&
        strcmp(name, ignore_pulse) != 0 &&
        !talk_base::starts_with(name, ignore_prefix)) {

      // Yes, we do.
      char *desc = LATE(snd_device_name_get_hint)(*list, "DESC");
      if (!desc) {
        // Virtual devices don't necessarily have descriptions. Use their names
        // instead (not pretty!).
        desc = name;
      }

      AlsaDeviceLocator *device = new AlsaDeviceLocator(desc, name);

      devices->push_back(device);

      if (desc != name) {
        free(desc);
      }
    }

    free(name);
  }

  err = LATE(snd_device_name_free_hint)(hints);
  if (err != 0) {
    LOG(LS_ERROR) << "snd_device_name_free_hint(): " << GetError(err);
    // Continue and return true anyways, since we did get the whole list.
  }

  return true;
}

bool AlsaSoundSystem::GetDefaultDevice(SoundDeviceLocator **device) {
  if (!IsInitialized()) {
    return false;
  }
  *device = new AlsaDeviceLocator("Default device", "default");
  return true;
}

inline size_t AlsaSoundSystem::FrameSize(const OpenParams &params) {
  ASSERT(params.format < ARRAY_SIZE(kCricketFormatToSampleSizeTable));
  return kCricketFormatToSampleSizeTable[params.format] * params.channels;
}

template <typename StreamInterface>
StreamInterface *AlsaSoundSystem::OpenDevice(
    const SoundDeviceLocator *device,
    const OpenParams &params,
    snd_pcm_stream_t type,
    StreamInterface *(AlsaSoundSystem::*start_fn)(
        snd_pcm_t *handle,
        size_t frame_size,
        int wait_timeout_ms,
        int flags,
        int freq)) {

  if (!IsInitialized()) {
    return NULL;
  }

  StreamInterface *stream;
  int err;

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

  snd_pcm_t *handle = NULL;
  err = LATE(snd_pcm_open)(
      &handle,
      dev,
      type,
      // No flags.
      0);
  if (err != 0) {
    LOG(LS_ERROR) << "snd_pcm_open(" << dev << "): " << GetError(err);
    return NULL;
  }
  LOG(LS_VERBOSE) << "Opening " << dev;
  ASSERT(handle);  // If open succeeded, handle ought to be valid

  // Compute requested latency in microseconds.
  int latency;
  if (params.latency == kNoLatencyRequirements) {
    latency = kDefaultLatencyUsecs;
  } else {
    // kLowLatency is 0, so we treat it the same as a request for zero latency.
    // Compute what the user asked for.
    latency = talk_base::kNumMicrosecsPerSec *
        params.latency /
        params.freq /
        FrameSize(params);
    // And this is what we'll actually use.
    latency = talk_base::_max(latency, kMinimumLatencyUsecs);
  }

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

  err = LATE(snd_pcm_set_params)(handle,
                                 kCricketFormatToAlsaFormatTable[params.format],
                                 // SoundSystemInterface only supports
                                 // interleaved audio.
                                 SND_PCM_ACCESS_RW_INTERLEAVED,
                                 params.channels,
                                 params.freq,
                                 1,  // Allow ALSA to resample.
                                 latency);
  if (err != 0) {
    LOG(LS_ERROR) << "snd_pcm_set_params(): " << GetError(err);
    goto fail;
  }

  err = LATE(snd_pcm_prepare)(handle);
  if (err != 0) {
    LOG(LS_ERROR) << "snd_pcm_prepare(): " << GetError(err);
    goto fail;
  }

  stream = (this->*start_fn)(
      handle,
      FrameSize(params),
      // We set the wait time to twice the requested latency, so that wait
      // timeouts should be rare.
      2 * latency / talk_base::kNumMicrosecsPerMillisec,
      params.flags,
      params.freq);
  if (stream) {
    return stream;
  }
  // Else fall through.

 fail:
  err = LATE(snd_pcm_close)(handle);
  if (err != 0) {
    LOG(LS_ERROR) << "snd_pcm_close(): " << GetError(err);
  }
  return NULL;
}

SoundOutputStreamInterface *AlsaSoundSystem::StartOutputStream(
    snd_pcm_t *handle,
    size_t frame_size,
    int wait_timeout_ms,
    int flags,
    int freq) {
  // Nothing to do here but instantiate the stream.
  return new AlsaOutputStream(
      this, handle, frame_size, wait_timeout_ms, flags, freq);
}

SoundInputStreamInterface *AlsaSoundSystem::StartInputStream(
    snd_pcm_t *handle,
    size_t frame_size,
    int wait_timeout_ms,
    int flags,
    int freq) {
  // Output streams start automatically once enough data has been written, but
  // input streams must be started manually or else snd_pcm_wait() will never
  // return true.
  int err;
  err = LATE(snd_pcm_start)(handle);
  if (err != 0) {
    LOG(LS_ERROR) << "snd_pcm_start(): " << GetError(err);
    return NULL;
  }
  return new AlsaInputStream(
      this, handle, frame_size, wait_timeout_ms, flags, freq);
}

inline const char *AlsaSoundSystem::GetError(int err) {
  return LATE(snd_strerror)(err);
}

}  // namespace cricket
