// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/audio/linux/audio_manager_linux.h"

#include "base/command_line.h"
#include "base/environment.h"
#include "base/logging.h"
#include "base/nix/xdg_util.h"
#include "base/process_util.h"
#include "base/stl_util.h"
#include "media/audio/audio_output_dispatcher.h"
#include "media/audio/audio_util.h"
#include "media/audio/linux/alsa_input.h"
#include "media/audio/linux/alsa_output.h"
#include "media/audio/linux/alsa_wrapper.h"
#if defined(USE_PULSEAUDIO)
#include "media/audio/pulse/pulse_output.h"
#endif
#if defined(USE_CRAS)
#include "media/audio/linux/cras_input.h"
#include "media/audio/linux/cras_output.h"
#endif
#include "media/base/limits.h"
#include "media/base/media_switches.h"

namespace media {

// Maximum number of output streams that can be open simultaneously.
static const int kMaxOutputStreams = 50;

// Since "default", "pulse" and "dmix" devices are virtual devices mapped to
// real devices, we remove them from the list to avoiding duplicate counting.
// In addition, note that we support no more than 2 channels for recording,
// hence surround devices are not stored in the list.
static const char* kInvalidAudioInputDevices[] = {
  "default",
  "null",
  "pulse",
  "dmix",
  "surround",
};

static const char kCrasAutomaticDeviceName[] = "Automatic";
static const char kCrasAutomaticDeviceId[] = "automatic";

// Implementation of AudioManager.
bool AudioManagerLinux::HasAudioOutputDevices() {
  if (UseCras())
    return true;

  return HasAnyAlsaAudioDevice(kStreamPlayback);
}

bool AudioManagerLinux::HasAudioInputDevices() {
  if (UseCras())
    return true;

  return HasAnyAlsaAudioDevice(kStreamCapture);
}

AudioManagerLinux::AudioManagerLinux()
    : wrapper_(new AlsaWrapper()) {
  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
}

AudioManagerLinux::~AudioManagerLinux() {
  Shutdown();
}

bool AudioManagerLinux::CanShowAudioInputSettings() {
  scoped_ptr<base::Environment> env(base::Environment::Create());

  switch (base::nix::GetDesktopEnvironment(env.get())) {
    case base::nix::DESKTOP_ENVIRONMENT_GNOME:
    case base::nix::DESKTOP_ENVIRONMENT_KDE3:
    case base::nix::DESKTOP_ENVIRONMENT_KDE4:
      return true;
    case base::nix::DESKTOP_ENVIRONMENT_OTHER:
    case base::nix::DESKTOP_ENVIRONMENT_UNITY:
    case base::nix::DESKTOP_ENVIRONMENT_XFCE:
      return false;
  }
  // Unless GetDesktopEnvironment() badly misbehaves, this should never happen.
  NOTREACHED();
  return false;
}

void AudioManagerLinux::ShowAudioInputSettings() {
  scoped_ptr<base::Environment> env(base::Environment::Create());
  base::nix::DesktopEnvironment desktop = base::nix::GetDesktopEnvironment(
      env.get());
  std::string command((desktop == base::nix::DESKTOP_ENVIRONMENT_GNOME) ?
                      "gnome-volume-control" : "kmix");
  base::LaunchProcess(CommandLine(FilePath(command)), base::LaunchOptions(),
                      NULL);
}

void AudioManagerLinux::GetAudioInputDeviceNames(
    media::AudioDeviceNames* device_names) {
  DCHECK(device_names->empty());
  if (UseCras()) {
    GetCrasAudioInputDevices(device_names);
    return;
  }

  GetAlsaAudioInputDevices(device_names);
}

bool AudioManagerLinux::UseCras() {
#if defined(USE_CRAS)
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseCras)) {
    return true;
  }
#endif
  return false;
}

void AudioManagerLinux::GetCrasAudioInputDevices(
    media::AudioDeviceNames* device_names) {
  // Cras will route audio from a proper physical device automatically.
  device_names->push_back(media::AudioDeviceName(
      kCrasAutomaticDeviceName, kCrasAutomaticDeviceId));
}

void AudioManagerLinux::GetAlsaAudioInputDevices(
    media::AudioDeviceNames* device_names) {
  // Constants specified by the ALSA API for device hints.
  static const char kPcmInterfaceName[] = "pcm";
  int card = -1;

  // Loop through the sound cards to get ALSA device hints.
  while (!wrapper_->CardNext(&card) && card >= 0) {
    void** hints = NULL;
    int error = wrapper_->DeviceNameHint(card, kPcmInterfaceName, &hints);
    if (!error) {
      GetAlsaDevicesInfo(hints, device_names);

      // Destroy the hints now that we're done with it.
      wrapper_->DeviceNameFreeHint(hints);
    } else {
      DLOG(WARNING) << "GetAudioInputDevices: unable to get device hints: "
                    << wrapper_->StrError(error);
    }
  }
}

void AudioManagerLinux::GetAlsaDevicesInfo(
    void** hints, media::AudioDeviceNames* device_names) {
  static const char kIoHintName[] = "IOID";
  static const char kNameHintName[] = "NAME";
  static const char kDescriptionHintName[] = "DESC";
  static const char kOutputDevice[] = "Output";

  for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) {
    // Only examine devices that are input capable.  Valid values are
    // "Input", "Output", and NULL which means both input and output.
    scoped_ptr_malloc<char> io(wrapper_->DeviceNameGetHint(*hint_iter,
                                                           kIoHintName));
    if (io != NULL && strcmp(kOutputDevice, io.get()) == 0)
      continue;

    // Found an input device, prepend the default device since we always want
    // it to be on the top of the list for all platforms. And there is no
    // duplicate counting here since it is only done if the list is still empty.
    // Note, pulse has exclusively opened the default device, so we must open
    // the device via the "default" moniker.
    if (device_names->empty()) {
      device_names->push_front(media::AudioDeviceName(
          AudioManagerBase::kDefaultDeviceName,
          AudioManagerBase::kDefaultDeviceId));
    }

    // Get the unique device name for the device.
    scoped_ptr_malloc<char> unique_device_name(
        wrapper_->DeviceNameGetHint(*hint_iter, kNameHintName));

    // Find out if the device is available.
    if (IsAlsaDeviceAvailable(unique_device_name.get())) {
      // Get the description for the device.
      scoped_ptr_malloc<char> desc(wrapper_->DeviceNameGetHint(
          *hint_iter, kDescriptionHintName));

      media::AudioDeviceName name;
      name.unique_id = unique_device_name.get();
      if (desc.get()) {
        // Use the more user friendly description as name.
        // Replace '\n' with '-'.
        char* pret = strchr(desc.get(), '\n');
        if (pret)
          *pret = '-';
        name.device_name = desc.get();
      } else {
        // Virtual devices don't necessarily have descriptions.
        // Use their names instead.
        name.device_name = unique_device_name.get();
      }

      // Store the device information.
      device_names->push_back(name);
    }
  }
}

bool AudioManagerLinux::IsAlsaDeviceAvailable(const char* device_name) {
  if (!device_name)
    return false;

  // Check if the device is in the list of invalid devices.
  for (size_t i = 0; i < arraysize(kInvalidAudioInputDevices); ++i) {
    if (strncmp(kInvalidAudioInputDevices[i], device_name,
                strlen(kInvalidAudioInputDevices[i])) == 0)
      return false;
  }

  return true;
}

bool AudioManagerLinux::HasAnyAlsaAudioDevice(StreamType stream) {
  static const char kPcmInterfaceName[] = "pcm";
  static const char kIoHintName[] = "IOID";
  const char* kNotWantedDevice =
      (stream == kStreamPlayback ? "Input" : "Output");
  void** hints = NULL;
  bool has_device = false;
  int card = -1;

  // Loop through the sound cards.
  // Don't use snd_device_name_hint(-1,..) since there is a access violation
  // inside this ALSA API with libasound.so.2.0.0.
  while (!wrapper_->CardNext(&card) && (card >= 0) && !has_device) {
    int error = wrapper_->DeviceNameHint(card, kPcmInterfaceName, &hints);
    if (!error) {
      for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) {
        // Only examine devices that are |stream| capable.  Valid values are
        // "Input", "Output", and NULL which means both input and output.
        scoped_ptr_malloc<char> io(wrapper_->DeviceNameGetHint(*hint_iter,
                                                               kIoHintName));
        if (io != NULL && strcmp(kNotWantedDevice, io.get()) == 0)
          continue;  // Wrong type, skip the device.

        // Found an input device.
        has_device = true;
        break;
      }

      // Destroy the hints now that we're done with it.
      wrapper_->DeviceNameFreeHint(hints);
      hints = NULL;
    } else {
      DLOG(WARNING) << "HasAnyAudioDevice: unable to get device hints: "
                    << wrapper_->StrError(error);
    }
  }

  return has_device;
}

AudioOutputStream* AudioManagerLinux::MakeLinearOutputStream(
    const AudioParameters& params) {
  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
  return MakeOutputStream(params);
}

AudioOutputStream* AudioManagerLinux::MakeLowLatencyOutputStream(
    const AudioParameters& params) {
  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
  return MakeOutputStream(params);
}

AudioInputStream* AudioManagerLinux::MakeLinearInputStream(
    const AudioParameters& params, const std::string& device_id) {
  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
  return MakeInputStream(params, device_id);
}

AudioInputStream* AudioManagerLinux::MakeLowLatencyInputStream(
    const AudioParameters& params, const std::string& device_id) {
  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
  return MakeInputStream(params, device_id);
}

AudioOutputStream* AudioManagerLinux::MakeOutputStream(
    const AudioParameters& params) {
#if defined(USE_CRAS)
  if (UseCras()) {
    return new CrasOutputStream(params, this);
  }
#endif

#if defined(USE_PULSEAUDIO)
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUsePulseAudio)) {
    return new PulseAudioOutputStream(params, this);
  }
#endif

  std::string device_name = AlsaPcmOutputStream::kAutoSelectDevice;
  if (CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kAlsaOutputDevice)) {
    device_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
        switches::kAlsaOutputDevice);
  }
  return new AlsaPcmOutputStream(device_name, params, wrapper_.get(), this);
}

AudioInputStream* AudioManagerLinux::MakeInputStream(
    const AudioParameters& params, const std::string& device_id) {
#if defined(USE_CRAS)
  if (UseCras()) {
    return new CrasInputStream(params, this);
  }
#endif

  std::string device_name = (device_id == AudioManagerBase::kDefaultDeviceId) ?
      AlsaPcmInputStream::kAutoSelectDevice : device_id;
  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAlsaInputDevice)) {
    device_name = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
        switches::kAlsaInputDevice);
  }

  return new AlsaPcmInputStream(this, device_name, params, wrapper_.get());
}

AudioManager* CreateAudioManager() {
  return new AudioManagerLinux();
}

AudioParameters AudioManagerLinux::GetPreferredLowLatencyOutputStreamParameters(
    const AudioParameters& input_params) {
  // Since Linux doesn't actually have a low latency path the hardware buffer
  // size is quite large in order to prevent glitches with general usage.  Some
  // clients, such as WebRTC, have a more limited use case and work acceptably
  // with a smaller buffer size.  The check below allows clients which want to
  // try a smaller buffer size on Linux to do so.
  int buffer_size = GetAudioHardwareBufferSize();
  if (input_params.frames_per_buffer() < buffer_size)
    buffer_size = input_params.frames_per_buffer();

  int sample_rate = GetAudioHardwareSampleRate();
  // CRAS will sample rate convert if needed, so pass through input sample rate.
  if (UseCras())
    sample_rate = input_params.sample_rate();

  // TODO(dalecurtis): This should include bits per channel and channel layout
  // eventually.
  return AudioParameters(
      AudioParameters::AUDIO_PCM_LOW_LATENCY, input_params.channel_layout(),
      sample_rate, 16, buffer_size);
}

}  // namespace media
