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

#include <unistd.h>
#include "talk/media/base/mediacommon.h"
#include "talk/media/devices/libudevsymboltable.h"
#include "talk/media/devices/v4llookup.h"
#include "webrtc/sound/platformsoundsystem.h"
#include "webrtc/sound/platformsoundsystemfactory.h"
#include "webrtc/sound/sounddevicelocator.h"
#include "webrtc/sound/soundsysteminterface.h"
#include "webrtc/base/fileutils.h"
#include "webrtc/base/linux.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/pathutils.h"
#include "webrtc/base/physicalsocketserver.h"
#include "webrtc/base/stream.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/base/thread.h"

namespace cricket {

DeviceManagerInterface* DeviceManagerFactory::Create() {
  return new LinuxDeviceManager();
}

class LinuxDeviceWatcher
    : public DeviceWatcher,
      private rtc::Dispatcher {
 public:
  explicit LinuxDeviceWatcher(DeviceManagerInterface* dm);
  virtual ~LinuxDeviceWatcher();
  virtual bool Start();
  virtual void Stop();

 private:
  virtual uint32 GetRequestedEvents();
  virtual void OnPreEvent(uint32 ff);
  virtual void OnEvent(uint32 ff, int err);
  virtual int GetDescriptor();
  virtual bool IsDescriptorClosed();

  DeviceManagerInterface* manager_;
  LibUDevSymbolTable libudev_;
  struct udev* udev_;
  struct udev_monitor* udev_monitor_;
  bool registered_;
};

static const char* const kFilteredAudioDevicesName[] = {
#if defined(CHROMEOS)
    "surround40:",
    "surround41:",
    "surround50:",
    "surround51:",
    "surround71:",
    "iec958:",      // S/PDIF
#endif
    NULL,
};
static const char* kFilteredVideoDevicesName[] = {
    NULL,
};

LinuxDeviceManager::LinuxDeviceManager()
    : sound_system_(new rtc::PlatformSoundSystemFactory()) {
  set_watcher(new LinuxDeviceWatcher(this));
}

LinuxDeviceManager::~LinuxDeviceManager() {
}

bool LinuxDeviceManager::GetAudioDevices(bool input,
                                         std::vector<Device>* devs) {
  devs->clear();
  if (!sound_system_.get()) {
    return false;
  }
  rtc::SoundSystemInterface::SoundDeviceLocatorList list;
  bool success;
  if (input) {
    success = sound_system_->EnumerateCaptureDevices(&list);
  } else {
    success = sound_system_->EnumeratePlaybackDevices(&list);
  }
  if (!success) {
    LOG(LS_ERROR) << "Can't enumerate devices";
    sound_system_.release();
    return false;
  }
  // We have to start the index at 1 because webrtc VoiceEngine puts the default
  // device at index 0, but Enumerate(Capture|Playback)Devices does not include
  // a locator for the default device.
  int index = 1;
  for (rtc::SoundSystemInterface::SoundDeviceLocatorList::iterator i = list.begin();
       i != list.end();
       ++i, ++index) {
    devs->push_back(Device((*i)->name(), index));
  }
  rtc::SoundSystemInterface::ClearSoundDeviceLocatorList(&list);
  sound_system_.release();
  return FilterDevices(devs, kFilteredAudioDevicesName);
}

static const std::string kVideoMetaPathK2_4("/proc/video/dev/");
static const std::string kVideoMetaPathK2_6("/sys/class/video4linux/");

enum MetaType { M2_4, M2_6, NONE };

static void ScanDeviceDirectory(const std::string& devdir,
                                std::vector<Device>* devices) {
  rtc::scoped_ptr<rtc::DirectoryIterator> directoryIterator(
      rtc::Filesystem::IterateDirectory());

  if (directoryIterator->Iterate(rtc::Pathname(devdir))) {
    do {
      std::string filename = directoryIterator->Name();
      std::string device_name = devdir + filename;
      if (!directoryIterator->IsDots()) {
        if (filename.find("video") == 0 &&
            V4LLookup::IsV4L2Device(device_name)) {
          devices->push_back(Device(device_name, device_name));
        }
      }
    } while (directoryIterator->Next());
  }
}

static std::string GetVideoDeviceNameK2_6(const std::string& device_meta_path) {
  std::string device_name;

  rtc::scoped_ptr<rtc::FileStream> device_meta_stream(
      rtc::Filesystem::OpenFile(device_meta_path, "r"));

  if (device_meta_stream) {
    if (device_meta_stream->ReadLine(&device_name) != rtc::SR_SUCCESS) {
      LOG(LS_ERROR) << "Failed to read V4L2 device meta " << device_meta_path;
    }
    device_meta_stream->Close();
  }

  return device_name;
}

static std::string Trim(const std::string& s, const std::string& drop = " \t") {
  std::string::size_type first = s.find_first_not_of(drop);
  std::string::size_type last  = s.find_last_not_of(drop);

  if (first == std::string::npos || last == std::string::npos)
    return std::string("");

  return s.substr(first, last - first + 1);
}

static std::string GetVideoDeviceNameK2_4(const std::string& device_meta_path) {
  rtc::ConfigParser::MapVector all_values;

  rtc::ConfigParser config_parser;
  rtc::FileStream* file_stream =
      rtc::Filesystem::OpenFile(device_meta_path, "r");

  if (file_stream == NULL) return "";

  config_parser.Attach(file_stream);
  config_parser.Parse(&all_values);

  for (rtc::ConfigParser::MapVector::iterator i = all_values.begin();
      i != all_values.end(); ++i) {
    rtc::ConfigParser::SimpleMap::iterator device_name_i =
        i->find("name");

    if (device_name_i != i->end()) {
      return device_name_i->second;
    }
  }

  return "";
}

static std::string GetVideoDeviceName(MetaType meta,
    const std::string& device_file_name) {
  std::string device_meta_path;
  std::string device_name;
  std::string meta_file_path;

  if (meta == M2_6) {
    meta_file_path = kVideoMetaPathK2_6 + device_file_name + "/name";

    LOG(LS_INFO) << "Trying " + meta_file_path;
    device_name = GetVideoDeviceNameK2_6(meta_file_path);

    if (device_name.empty()) {
      meta_file_path = kVideoMetaPathK2_6 + device_file_name + "/model";

      LOG(LS_INFO) << "Trying " << meta_file_path;
      device_name = GetVideoDeviceNameK2_6(meta_file_path);
    }
  } else {
    meta_file_path = kVideoMetaPathK2_4 + device_file_name;
    LOG(LS_INFO) << "Trying " << meta_file_path;
    device_name = GetVideoDeviceNameK2_4(meta_file_path);
  }

  if (device_name.empty()) {
    device_name = "/dev/" + device_file_name;
    LOG(LS_ERROR)
      << "Device name not found, defaulting to device path " << device_name;
  }

  LOG(LS_INFO) << "Name for " << device_file_name << " is " << device_name;

  return Trim(device_name);
}

static void ScanV4L2Devices(std::vector<Device>* devices) {
  LOG(LS_INFO) << ("Enumerating V4L2 devices");

  MetaType meta;
  std::string metadata_dir;

  rtc::scoped_ptr<rtc::DirectoryIterator> directoryIterator(
      rtc::Filesystem::IterateDirectory());

  // Try and guess kernel version
  if (directoryIterator->Iterate(kVideoMetaPathK2_6)) {
    meta = M2_6;
    metadata_dir = kVideoMetaPathK2_6;
  } else if (directoryIterator->Iterate(kVideoMetaPathK2_4)) {
    meta = M2_4;
    metadata_dir = kVideoMetaPathK2_4;
  } else {
    meta = NONE;
  }

  if (meta != NONE) {
    LOG(LS_INFO) << "V4L2 device metadata found at " << metadata_dir;

    do {
      std::string filename = directoryIterator->Name();

      if (filename.find("video") == 0) {
        std::string device_path = "/dev/" + filename;

        if (V4LLookup::IsV4L2Device(device_path)) {
          devices->push_back(
              Device(GetVideoDeviceName(meta, filename), device_path));
        }
      }
    } while (directoryIterator->Next());
  } else {
    LOG(LS_ERROR) << "Unable to detect v4l2 metadata directory";
  }

  if (devices->size() == 0) {
    LOG(LS_INFO) << "Plan B. Scanning all video devices in /dev directory";
    ScanDeviceDirectory("/dev/", devices);
  }

  LOG(LS_INFO) << "Total V4L2 devices found : " << devices->size();
}

bool LinuxDeviceManager::GetVideoCaptureDevices(std::vector<Device>* devices) {
  devices->clear();
  ScanV4L2Devices(devices);
  return FilterDevices(devices, kFilteredVideoDevicesName);
}

LinuxDeviceWatcher::LinuxDeviceWatcher(DeviceManagerInterface* dm)
    : DeviceWatcher(dm),
      manager_(dm),
      udev_(NULL),
      udev_monitor_(NULL),
      registered_(false) {
}

LinuxDeviceWatcher::~LinuxDeviceWatcher() {
}

static rtc::PhysicalSocketServer* CurrentSocketServer() {
  rtc::SocketServer* ss =
      rtc::ThreadManager::Instance()->WrapCurrentThread()->socketserver();
  return reinterpret_cast<rtc::PhysicalSocketServer*>(ss);
}

bool LinuxDeviceWatcher::Start() {
  // We deliberately return true in the failure paths here because libudev is
  // not a critical component of a Linux system so it may not be present/usable,
  // and we don't want to halt LinuxDeviceManager initialization in such a case.
  if (!libudev_.Load() || IsWrongLibUDevAbiVersion(libudev_.GetDllHandle())) {
    LOG(LS_WARNING)
        << "libudev not present/usable; LinuxDeviceWatcher disabled";
    return true;
  }
  udev_ = libudev_.udev_new()();
  if (!udev_) {
    LOG_ERR(LS_ERROR) << "udev_new()";
    return true;
  }
  // The second argument here is the event source. It can be either "kernel" or
  // "udev", but "udev" is the only correct choice. Apps listen on udev and the
  // udev daemon in turn listens on the kernel.
  udev_monitor_ = libudev_.udev_monitor_new_from_netlink()(udev_, "udev");
  if (!udev_monitor_) {
    LOG_ERR(LS_ERROR) << "udev_monitor_new_from_netlink()";
    return true;
  }
  // We only listen for changes in the video devices. Audio devices are more or
  // less unimportant because receiving device change notifications really only
  // matters for broadcasting updated send/recv capabilities based on whether
  // there is at least one device available, and almost all computers have at
  // least one audio device. Also, PulseAudio device notifications don't come
  // from the udev daemon, they come from the PulseAudio daemon, so we'd only
  // want to listen for audio device changes from udev if using ALSA. For
  // simplicity, we don't bother with any audio stuff at all.
  if (libudev_.udev_monitor_filter_add_match_subsystem_devtype()(
          udev_monitor_, "video4linux", NULL) < 0) {
    LOG_ERR(LS_ERROR) << "udev_monitor_filter_add_match_subsystem_devtype()";
    return true;
  }
  if (libudev_.udev_monitor_enable_receiving()(udev_monitor_) < 0) {
    LOG_ERR(LS_ERROR) << "udev_monitor_enable_receiving()";
    return true;
  }
  CurrentSocketServer()->Add(this);
  registered_ = true;
  return true;
}

void LinuxDeviceWatcher::Stop() {
  if (registered_) {
    CurrentSocketServer()->Remove(this);
    registered_ = false;
  }
  if (udev_monitor_) {
    libudev_.udev_monitor_unref()(udev_monitor_);
    udev_monitor_ = NULL;
  }
  if (udev_) {
    libudev_.udev_unref()(udev_);
    udev_ = NULL;
  }
  libudev_.Unload();
}

uint32 LinuxDeviceWatcher::GetRequestedEvents() {
  return rtc::DE_READ;
}

void LinuxDeviceWatcher::OnPreEvent(uint32 ff) {
  // Nothing to do.
}

void LinuxDeviceWatcher::OnEvent(uint32 ff, int err) {
  udev_device* device = libudev_.udev_monitor_receive_device()(udev_monitor_);
  if (!device) {
    // Probably the socket connection to the udev daemon was terminated (perhaps
    // the daemon crashed or is being restarted?).
    LOG_ERR(LS_WARNING) << "udev_monitor_receive_device()";
    // Stop listening to avoid potential livelock (an fd with EOF in it is
    // always considered readable).
    CurrentSocketServer()->Remove(this);
    registered_ = false;
    return;
  }
  // Else we read the device successfully.

  // Since we already have our own filesystem-based device enumeration code, we
  // simply re-enumerate rather than inspecting the device event.
  libudev_.udev_device_unref()(device);
  manager_->SignalDevicesChange();
}

int LinuxDeviceWatcher::GetDescriptor() {
  return libudev_.udev_monitor_get_fd()(udev_monitor_);
}

bool LinuxDeviceWatcher::IsDescriptorClosed() {
  // If it is closed then we will just get an error in
  // udev_monitor_receive_device and unregister, so we don't need to check for
  // it separately.
  return false;
}

};  // namespace cricket
