// Copyright 2014 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/midi/midi_manager_alsa.h"

#include <errno.h>
#include <poll.h>
#include <stddef.h>
#include <stdlib.h>

#include <algorithm>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/json/json_string_value_serializer.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/posix/eintr_wrapper.h"
#include "base/posix/safe_strerror.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "crypto/sha2.h"
#include "media/midi/midi_service.h"
#include "media/midi/midi_service.mojom.h"
#include "media/midi/task_service.h"

namespace midi {

namespace {

using mojom::PortState;
using mojom::Result;

enum {
  kDefaultRunnerNotUsedOnAlsa = TaskService::kDefaultRunnerId,
  kEventTaskRunner,
  kSendTaskRunner
};

// Per-output buffer. This can be smaller, but then large sysex messages
// will be (harmlessly) split across multiple seq events. This should
// not have any real practical effect, except perhaps to slightly reorder
// realtime messages with respect to sysex.
constexpr size_t kSendBufferSize = 256;

// Minimum client id for which we will have ALSA card devices for. When we
// are searching for card devices (used to get the path, id, and manufacturer),
// we don't want to get confused by kernel clients that do not have a card.
// See seq_clientmgr.c in the ALSA code for this.
// TODO(agoode): Add proper client -> card export from the kernel to avoid
//               hardcoding.
constexpr int kMinimumClientIdForCards = 16;

// ALSA constants.
const char kAlsaHw[] = "hw";

// udev constants.
const char kUdev[] = "udev";
const char kUdevSubsystemSound[] = "sound";
const char kUdevPropertySoundInitialized[] = "SOUND_INITIALIZED";
const char kUdevActionChange[] = "change";
const char kUdevActionRemove[] = "remove";

const char kUdevIdVendor[] = "ID_VENDOR";
const char kUdevIdVendorEnc[] = "ID_VENDOR_ENC";
const char kUdevIdVendorFromDatabase[] = "ID_VENDOR_FROM_DATABASE";
const char kUdevIdVendorId[] = "ID_VENDOR_ID";
const char kUdevIdModelId[] = "ID_MODEL_ID";
const char kUdevIdBus[] = "ID_BUS";
const char kUdevIdPath[] = "ID_PATH";
const char kUdevIdUsbInterfaceNum[] = "ID_USB_INTERFACE_NUM";
const char kUdevIdSerialShort[] = "ID_SERIAL_SHORT";

const char kSysattrVendorName[] = "vendor_name";
const char kSysattrVendor[] = "vendor";
const char kSysattrModel[] = "model";
const char kSysattrGuid[] = "guid";

const char kCardSyspath[] = "/card";

// Constants for the capabilities we search for in inputs and outputs.
// See http://www.alsa-project.org/alsa-doc/alsa-lib/seq.html.
constexpr unsigned int kRequiredInputPortCaps =
    SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ;
constexpr unsigned int kRequiredOutputPortCaps =
    SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE;

constexpr unsigned int kCreateOutputPortCaps =
    SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_NO_EXPORT;
constexpr unsigned int kCreateInputPortCaps =
    SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_NO_EXPORT;
constexpr unsigned int kCreatePortType =
    SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION;

int AddrToInt(int client, int port) {
  return (client << 8) | port;
}

// Returns true if this client has an ALSA card associated with it.
bool IsCardClient(snd_seq_client_type_t type, int client_id) {
  return (type == SND_SEQ_KERNEL_CLIENT) &&
         (client_id >= kMinimumClientIdForCards);
}

// TODO(agoode): Move this to device/udev_linux.
const std::string UdevDeviceGetPropertyOrSysattr(
    struct udev_device* udev_device,
    const char* property_key,
    const char* sysattr_key) {
  // First try the property.
  std::string value =
      device::UdevDeviceGetPropertyValue(udev_device, property_key);

  // If no property, look for sysattrs and walk up the parent devices too.
  while (value.empty() && udev_device) {
    value = device::UdevDeviceGetSysattrValue(udev_device, sysattr_key);
    udev_device = device::udev_device_get_parent(udev_device);
  }
  return value;
}

int GetCardNumber(udev_device* dev) {
  const char* syspath = device::udev_device_get_syspath(dev);
  if (!syspath)
    return -1;

  std::string syspath_str(syspath);
  size_t i = syspath_str.rfind(kCardSyspath);
  if (i == std::string::npos)
    return -1;

  int number;
  if (!base::StringToInt(syspath_str.substr(i + strlen(kCardSyspath)), &number))
    return -1;
  return number;
}

std::string GetVendor(udev_device* dev) {
  // Try to get the vendor string. Sometimes it is encoded.
  std::string vendor = device::UdevDecodeString(
      device::UdevDeviceGetPropertyValue(dev, kUdevIdVendorEnc));
  // Sometimes it is not encoded.
  if (vendor.empty())
    vendor =
        UdevDeviceGetPropertyOrSysattr(dev, kUdevIdVendor, kSysattrVendorName);
  return vendor;
}

void SetStringIfNonEmpty(base::DictionaryValue* value,
                         const std::string& path,
                         const std::string& in_value) {
  if (!in_value.empty())
    value->SetString(path, in_value);
}

}  // namespace

MidiManagerAlsa::MidiManagerAlsa(MidiService* service) : MidiManager(service) {}

MidiManagerAlsa::~MidiManagerAlsa() {
  {
    base::AutoLock lock(out_client_lock_);
    // Close the out client. This will trigger the event thread to stop,
    // because of SND_SEQ_EVENT_CLIENT_EXIT.
    out_client_.reset();
  }

  // Ensure that no task is running any more.
  bool result = service()->task_service()->UnbindInstance();
  CHECK(result);
}

void MidiManagerAlsa::StartInitialization() {
  if (!service()->task_service()->BindInstance()) {
    NOTREACHED();
    return CompleteInitialization(Result::INITIALIZATION_ERROR);
  }

  // Create client handles and name the clients.
  int err;
  {
    snd_seq_t* in_seq = nullptr;
    err = snd_seq_open(&in_seq, kAlsaHw, SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK);
    if (err != 0) {
      VLOG(1) << "snd_seq_open fails: " << snd_strerror(err);
      return CompleteInitialization(Result::INITIALIZATION_ERROR);
    }
    in_client_ = ScopedSndSeqPtr(in_seq);
    in_client_id_ = snd_seq_client_id(in_client_.get());
    err = snd_seq_set_client_name(in_client_.get(), "Chrome (input)");
    if (err != 0) {
      VLOG(1) << "snd_seq_set_client_name fails: " << snd_strerror(err);
      return CompleteInitialization(Result::INITIALIZATION_ERROR);
    }
  }

  {
    snd_seq_t* out_seq = nullptr;
    err = snd_seq_open(&out_seq, kAlsaHw, SND_SEQ_OPEN_OUTPUT, 0);
    if (err != 0) {
      VLOG(1) << "snd_seq_open fails: " << snd_strerror(err);
      return CompleteInitialization(Result::INITIALIZATION_ERROR);
    }
    base::AutoLock lock(out_client_lock_);
    out_client_ = ScopedSndSeqPtr(out_seq);
    out_client_id_ = snd_seq_client_id(out_client_.get());
    err = snd_seq_set_client_name(out_client_.get(), "Chrome (output)");
    if (err != 0) {
      VLOG(1) << "snd_seq_set_client_name fails: " << snd_strerror(err);
      return CompleteInitialization(Result::INITIALIZATION_ERROR);
    }
  }

  // Create input port.
  in_port_id_ = snd_seq_create_simple_port(
      in_client_.get(), NULL, kCreateInputPortCaps, kCreatePortType);
  if (in_port_id_ < 0) {
    VLOG(1) << "snd_seq_create_simple_port fails: "
            << snd_strerror(in_port_id_);
    return CompleteInitialization(Result::INITIALIZATION_ERROR);
  }

  // Subscribe to the announce port.
  snd_seq_port_subscribe_t* subs;
  snd_seq_port_subscribe_alloca(&subs);
  snd_seq_addr_t announce_sender;
  snd_seq_addr_t announce_dest;
  announce_sender.client = SND_SEQ_CLIENT_SYSTEM;
  announce_sender.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE;
  announce_dest.client = in_client_id_;
  announce_dest.port = in_port_id_;
  snd_seq_port_subscribe_set_sender(subs, &announce_sender);
  snd_seq_port_subscribe_set_dest(subs, &announce_dest);
  err = snd_seq_subscribe_port(in_client_.get(), subs);
  if (err != 0) {
    VLOG(1) << "snd_seq_subscribe_port on the announce port fails: "
            << snd_strerror(err);
    return CompleteInitialization(Result::INITIALIZATION_ERROR);
  }

  // Initialize decoder.
  decoder_ = CreateScopedSndMidiEventPtr(0);
  snd_midi_event_no_status(decoder_.get(), 1);

  // Initialize udev and monitor.
  udev_ = device::ScopedUdevPtr(device::udev_new());
  udev_monitor_ = device::ScopedUdevMonitorPtr(
      device::udev_monitor_new_from_netlink(udev_.get(), kUdev));
  if (!udev_monitor_.get()) {
    VLOG(1) << "udev_monitor_new_from_netlink fails";
    return CompleteInitialization(Result::INITIALIZATION_ERROR);
  }
  err = device::udev_monitor_filter_add_match_subsystem_devtype(
      udev_monitor_.get(), kUdevSubsystemSound, nullptr);
  if (err != 0) {
    VLOG(1) << "udev_monitor_add_match_subsystem fails: "
            << base::safe_strerror(-err);
    return CompleteInitialization(Result::INITIALIZATION_ERROR);
  }
  err = device::udev_monitor_enable_receiving(udev_monitor_.get());
  if (err != 0) {
    VLOG(1) << "udev_monitor_enable_receiving fails: "
            << base::safe_strerror(-err);
    return CompleteInitialization(Result::INITIALIZATION_ERROR);
  }

  // Generate hotplug events for existing ports.
  // TODO(agoode): Check the return value for failure.
  EnumerateAlsaPorts();

  // Generate hotplug events for existing udev devices. This must be done
  // after udev_monitor_enable_receiving() is called. See the algorithm
  // at http://www.signal11.us/oss/udev/.
  EnumerateUdevCards();

  // Start processing events. Don't do this before enumeration of both
  // ALSA and udev.
  service()->task_service()->PostBoundTask(
      kEventTaskRunner,
      base::BindOnce(&MidiManagerAlsa::EventLoop, base::Unretained(this)));

  CompleteInitialization(Result::OK);
}

void MidiManagerAlsa::DispatchSendMidiData(MidiManagerClient* client,
                                           uint32_t port_index,
                                           const std::vector<uint8_t>& data,
                                           base::TimeTicks timestamp) {
  service()->task_service()->PostBoundDelayedTask(
      kSendTaskRunner,
      base::BindOnce(&MidiManagerAlsa::SendMidiData, base::Unretained(this),
                     client, port_index, data),
      MidiService::TimestampToTimeDeltaDelay(timestamp));
}

MidiManagerAlsa::MidiPort::Id::Id() = default;

MidiManagerAlsa::MidiPort::Id::Id(const std::string& bus,
                                  const std::string& vendor_id,
                                  const std::string& model_id,
                                  const std::string& usb_interface_num,
                                  const std::string& serial)
    : bus_(bus),
      vendor_id_(vendor_id),
      model_id_(model_id),
      usb_interface_num_(usb_interface_num),
      serial_(serial) {
}

MidiManagerAlsa::MidiPort::Id::Id(const Id&) = default;

MidiManagerAlsa::MidiPort::Id::~Id() = default;

bool MidiManagerAlsa::MidiPort::Id::operator==(const Id& rhs) const {
  return (bus_ == rhs.bus_) && (vendor_id_ == rhs.vendor_id_) &&
         (model_id_ == rhs.model_id_) &&
         (usb_interface_num_ == rhs.usb_interface_num_) &&
         (serial_ == rhs.serial_);
}

bool MidiManagerAlsa::MidiPort::Id::empty() const {
  return bus_.empty() && vendor_id_.empty() && model_id_.empty() &&
         usb_interface_num_.empty() && serial_.empty();
}

MidiManagerAlsa::MidiPort::MidiPort(const std::string& path,
                                    const Id& id,
                                    int client_id,
                                    int port_id,
                                    int midi_device,
                                    const std::string& client_name,
                                    const std::string& port_name,
                                    const std::string& manufacturer,
                                    const std::string& version,
                                    Type type)
    : id_(id),
      midi_device_(midi_device),
      type_(type),
      path_(path),
      client_id_(client_id),
      port_id_(port_id),
      client_name_(client_name),
      port_name_(port_name),
      manufacturer_(manufacturer),
      version_(version) {
}

MidiManagerAlsa::MidiPort::~MidiPort() = default;

// Note: keep synchronized with the MidiPort::Match* methods.
std::unique_ptr<base::Value> MidiManagerAlsa::MidiPort::Value() const {
  std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue);

  std::string type;
  switch (type_) {
    case Type::kInput:
      type = "input";
      break;
    case Type::kOutput:
      type = "output";
      break;
  }
  value->SetString("type", type);
  SetStringIfNonEmpty(value.get(), "path", path_);
  SetStringIfNonEmpty(value.get(), "clientName", client_name_);
  SetStringIfNonEmpty(value.get(), "portName", port_name_);
  value->SetInteger("clientId", client_id_);
  value->SetInteger("portId", port_id_);
  value->SetInteger("midiDevice", midi_device_);

  // Flatten id fields.
  SetStringIfNonEmpty(value.get(), "bus", id_.bus());
  SetStringIfNonEmpty(value.get(), "vendorId", id_.vendor_id());
  SetStringIfNonEmpty(value.get(), "modelId", id_.model_id());
  SetStringIfNonEmpty(value.get(), "usbInterfaceNum", id_.usb_interface_num());
  SetStringIfNonEmpty(value.get(), "serial", id_.serial());

  return std::move(value);
}

std::string MidiManagerAlsa::MidiPort::JSONValue() const {
  std::string json;
  JSONStringValueSerializer serializer(&json);
  serializer.Serialize(*Value().get());
  return json;
}

// TODO(agoode): Do not use SHA256 here. Instead store a persistent
//               mapping and just use a UUID or other random string.
//               http://crbug.com/465320
std::string MidiManagerAlsa::MidiPort::OpaqueKey() const {
  uint8_t hash[crypto::kSHA256Length];
  crypto::SHA256HashString(JSONValue(), &hash, sizeof(hash));
  return base::HexEncode(&hash, sizeof(hash));
}

bool MidiManagerAlsa::MidiPort::MatchConnected(const MidiPort& query) const {
  // Matches on:
  // connected == true
  // type
  // path
  // id
  // client_id
  // port_id
  // midi_device
  // client_name
  // port_name
  return connected() && (type() == query.type()) && (path() == query.path()) &&
         (id() == query.id()) && (client_id() == query.client_id()) &&
         (port_id() == query.port_id()) &&
         (midi_device() == query.midi_device()) &&
         (client_name() == query.client_name()) &&
         (port_name() == query.port_name());
}

bool MidiManagerAlsa::MidiPort::MatchCardPass1(const MidiPort& query) const {
  // Matches on:
  // connected == false
  // type
  // path
  // id
  // port_id
  // midi_device
  return MatchCardPass2(query) && (path() == query.path());
}

bool MidiManagerAlsa::MidiPort::MatchCardPass2(const MidiPort& query) const {
  // Matches on:
  // connected == false
  // type
  // id
  // port_id
  // midi_device
  return !connected() && (type() == query.type()) && (id() == query.id()) &&
         (port_id() == query.port_id()) &&
         (midi_device() == query.midi_device());
}

bool MidiManagerAlsa::MidiPort::MatchNoCardPass1(const MidiPort& query) const {
  // Matches on:
  // connected == false
  // type
  // path.empty(), for both this and query
  // id.empty(), for both this and query
  // client_id
  // port_id
  // client_name
  // port_name
  // midi_device == -1, for both this and query
  return MatchNoCardPass2(query) && (client_id() == query.client_id());
}

bool MidiManagerAlsa::MidiPort::MatchNoCardPass2(const MidiPort& query) const {
  // Matches on:
  // connected == false
  // type
  // path.empty(), for both this and query
  // id.empty(), for both this and query
  // port_id
  // client_name
  // port_name
  // midi_device == -1, for both this and query
  return !connected() && (type() == query.type()) && path().empty() &&
         query.path().empty() && id().empty() && query.id().empty() &&
         (port_id() == query.port_id()) &&
         (client_name() == query.client_name()) &&
         (port_name() == query.port_name()) && (midi_device() == -1) &&
         (query.midi_device() == -1);
}

MidiManagerAlsa::MidiPortStateBase::~MidiPortStateBase() = default;

MidiManagerAlsa::MidiPortStateBase::iterator
MidiManagerAlsa::MidiPortStateBase::Find(
    const MidiManagerAlsa::MidiPort& port) {
  auto result = FindConnected(port);
  if (result == end())
    result = FindDisconnected(port);
  return result;
}

MidiManagerAlsa::MidiPortStateBase::iterator
MidiManagerAlsa::MidiPortStateBase::FindConnected(
    const MidiManagerAlsa::MidiPort& port) {
  // Exact match required for connected ports.
  auto it = std::find_if(ports_.begin(), ports_.end(),
                         [&port](std::unique_ptr<MidiPort>& p) {
                           return p->MatchConnected(port);
                         });
  return it;
}

MidiManagerAlsa::MidiPortStateBase::iterator
MidiManagerAlsa::MidiPortStateBase::FindDisconnected(
    const MidiManagerAlsa::MidiPort& port) {
  // Always match on:
  //  type
  // Possible things to match on:
  //  path
  //  id
  //  client_id
  //  port_id
  //  midi_device
  //  client_name
  //  port_name

  if (!port.path().empty()) {
    // If path is present, then we have a card-based client.

    // Pass 1. Match on path, id, midi_device, port_id.
    // This is the best possible match for hardware card-based clients.
    // This will also match the empty id correctly for devices without an id.
    auto it = std::find_if(ports_.begin(), ports_.end(),
                           [&port](std::unique_ptr<MidiPort>& p) {
                             return p->MatchCardPass1(port);
                           });
    if (it != ports_.end())
      return it;

    if (!port.id().empty()) {
      // Pass 2. Match on id, midi_device, port_id.
      // This will give us a high-confidence match when a user moves a device to
      // another USB/Firewire/Thunderbolt/etc port, but only works if the device
      // has a hardware id.
      it = std::find_if(ports_.begin(), ports_.end(),
                        [&port](std::unique_ptr<MidiPort>& p) {
                          return p->MatchCardPass2(port);
                        });
      if (it != ports_.end())
        return it;
    }
  } else {
    // Else, we have a non-card-based client.
    // Pass 1. Match on client_id, port_id, client_name, port_name.
    // This will give us a reasonably good match.
    auto it = std::find_if(ports_.begin(), ports_.end(),
                           [&port](std::unique_ptr<MidiPort>& p) {
                             return p->MatchNoCardPass1(port);
                           });
    if (it != ports_.end())
      return it;

    // Pass 2. Match on port_id, client_name, port_name.
    // This is weaker but similar to pass 2 in the hardware card-based clients
    // match.
    it = std::find_if(ports_.begin(), ports_.end(),
                      [&port](std::unique_ptr<MidiPort>& p) {
                        return p->MatchNoCardPass2(port);
                      });
    if (it != ports_.end())
      return it;
  }

  // No match.
  return ports_.end();
}

MidiManagerAlsa::MidiPortStateBase::MidiPortStateBase() = default;

MidiManagerAlsa::MidiPortState::MidiPortState() = default;

uint32_t MidiManagerAlsa::MidiPortState::push_back(
    std::unique_ptr<MidiPort> port) {
  // Add the web midi index.
  uint32_t web_port_index = 0;
  switch (port->type()) {
    case MidiPort::Type::kInput:
      web_port_index = num_input_ports_++;
      break;
    case MidiPort::Type::kOutput:
      web_port_index = num_output_ports_++;
      break;
  }
  port->set_web_port_index(web_port_index);
  MidiPortStateBase::push_back(std::move(port));
  return web_port_index;
}

MidiManagerAlsa::AlsaSeqState::AlsaSeqState() = default;

MidiManagerAlsa::AlsaSeqState::~AlsaSeqState() = default;

void MidiManagerAlsa::AlsaSeqState::ClientStart(int client_id,
                                                const std::string& client_name,
                                                snd_seq_client_type_t type) {
  ClientExit(client_id);
  clients_.insert(
      std::make_pair(client_id, std::make_unique<Client>(client_name, type)));
  if (IsCardClient(type, client_id))
    ++card_client_count_;
}

bool MidiManagerAlsa::AlsaSeqState::ClientStarted(int client_id) {
  return clients_.find(client_id) != clients_.end();
}

void MidiManagerAlsa::AlsaSeqState::ClientExit(int client_id) {
  auto it = clients_.find(client_id);
  if (it != clients_.end()) {
    if (IsCardClient(it->second->type(), client_id))
      --card_client_count_;
    clients_.erase(it);
  }
}

void MidiManagerAlsa::AlsaSeqState::PortStart(
    int client_id,
    int port_id,
    const std::string& port_name,
    MidiManagerAlsa::AlsaSeqState::PortDirection direction,
    bool midi) {
  auto it = clients_.find(client_id);
  if (it != clients_.end())
    it->second->AddPort(port_id,
                        std::make_unique<Port>(port_name, direction, midi));
}

void MidiManagerAlsa::AlsaSeqState::PortExit(int client_id, int port_id) {
  auto it = clients_.find(client_id);
  if (it != clients_.end())
    it->second->RemovePort(port_id);
}

snd_seq_client_type_t MidiManagerAlsa::AlsaSeqState::ClientType(
    int client_id) const {
  auto it = clients_.find(client_id);
  if (it == clients_.end())
    return SND_SEQ_USER_CLIENT;
  return it->second->type();
}

std::unique_ptr<MidiManagerAlsa::TemporaryMidiPortState>
MidiManagerAlsa::AlsaSeqState::ToMidiPortState(const AlsaCardMap& alsa_cards) {
  std::unique_ptr<MidiManagerAlsa::TemporaryMidiPortState> midi_ports(
      new TemporaryMidiPortState);
  auto card_it = alsa_cards.begin();

  int card_midi_device = -1;
  for (const auto& client_pair : clients_) {
    int client_id = client_pair.first;
    auto* client = client_pair.second.get();

    // Get client metadata.
    const std::string client_name = client->name();
    std::string manufacturer;
    std::string driver;
    std::string path;
    MidiPort::Id id;
    std::string card_name;
    std::string card_longname;
    int midi_device = -1;

    if (IsCardClient(client->type(), client_id)) {
      auto& card = card_it->second;
      if (card_midi_device == -1)
        card_midi_device = 0;

      manufacturer = card->manufacturer();
      path = card->path();
      id = MidiPort::Id(card->bus(), card->vendor_id(), card->model_id(),
                        card->usb_interface_num(), card->serial());
      card_name = card->name();
      card_longname = card->longname();
      midi_device = card_midi_device;

      ++card_midi_device;
      if (card_midi_device >= card->midi_device_count()) {
        card_midi_device = -1;
        ++card_it;
      }
    }

    for (const auto& port_pair : *client) {
      int port_id = port_pair.first;
      const auto& port = port_pair.second;

      if (port->midi()) {
        std::string version;
        if (!driver.empty()) {
          version = driver + " / ";
        }
        version +=
            base::StringPrintf("ALSA library version %d.%d.%d", SND_LIB_MAJOR,
                               SND_LIB_MINOR, SND_LIB_SUBMINOR);
        PortDirection direction = port->direction();
        if (direction == PortDirection::kInput ||
            direction == PortDirection::kDuplex) {
          midi_ports->push_back(std::make_unique<MidiPort>(
              path, id, client_id, port_id, midi_device, client->name(),
              port->name(), manufacturer, version, MidiPort::Type::kInput));
        }
        if (direction == PortDirection::kOutput ||
            direction == PortDirection::kDuplex) {
          midi_ports->push_back(std::make_unique<MidiPort>(
              path, id, client_id, port_id, midi_device, client->name(),
              port->name(), manufacturer, version, MidiPort::Type::kOutput));
        }
      }
    }
  }

  return midi_ports;
}

MidiManagerAlsa::AlsaSeqState::Port::Port(
    const std::string& name,
    MidiManagerAlsa::AlsaSeqState::PortDirection direction,
    bool midi)
    : name_(name), direction_(direction), midi_(midi) {
}

MidiManagerAlsa::AlsaSeqState::Port::~Port() = default;

MidiManagerAlsa::AlsaSeqState::Client::Client(const std::string& name,
                                              snd_seq_client_type_t type)
    : name_(name), type_(type) {
}

MidiManagerAlsa::AlsaSeqState::Client::~Client() = default;

void MidiManagerAlsa::AlsaSeqState::Client::AddPort(
    int addr,
    std::unique_ptr<Port> port) {
  ports_[addr] = std::move(port);
}

void MidiManagerAlsa::AlsaSeqState::Client::RemovePort(int addr) {
  ports_.erase(addr);
}

MidiManagerAlsa::AlsaSeqState::Client::PortMap::const_iterator
MidiManagerAlsa::AlsaSeqState::Client::begin() const {
  return ports_.begin();
}

MidiManagerAlsa::AlsaSeqState::Client::PortMap::const_iterator
MidiManagerAlsa::AlsaSeqState::Client::end() const {
  return ports_.end();
}

MidiManagerAlsa::AlsaCard::AlsaCard(udev_device* dev,
                                    const std::string& name,
                                    const std::string& longname,
                                    const std::string& driver,
                                    int midi_device_count)
    : name_(name),
      longname_(longname),
      driver_(driver),
      path_(device::UdevDeviceGetPropertyValue(dev, kUdevIdPath)),
      bus_(device::UdevDeviceGetPropertyValue(dev, kUdevIdBus)),
      vendor_id_(
          UdevDeviceGetPropertyOrSysattr(dev, kUdevIdVendorId, kSysattrVendor)),
      model_id_(
          UdevDeviceGetPropertyOrSysattr(dev, kUdevIdModelId, kSysattrModel)),
      usb_interface_num_(
          device::UdevDeviceGetPropertyValue(dev, kUdevIdUsbInterfaceNum)),
      serial_(UdevDeviceGetPropertyOrSysattr(dev,
                                             kUdevIdSerialShort,
                                             kSysattrGuid)),
      midi_device_count_(midi_device_count),
      manufacturer_(ExtractManufacturerString(
          GetVendor(dev),
          vendor_id_,
          device::UdevDeviceGetPropertyValue(dev, kUdevIdVendorFromDatabase),
          name,
          longname)) {
}

MidiManagerAlsa::AlsaCard::~AlsaCard() = default;

// static
std::string MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
    const std::string& udev_id_vendor,
    const std::string& udev_id_vendor_id,
    const std::string& udev_id_vendor_from_database,
    const std::string& alsa_name,
    const std::string& alsa_longname) {
  // Let's try to determine the manufacturer. Here is the ordered preference
  // in extraction:
  //  1. Vendor name from the hardware device string, from udev properties
  //     or sysattrs.
  //  2. Vendor name from the udev database (property ID_VENDOR_FROM_DATABASE).
  //  3. Heuristic from ALSA.

  // Is the vendor string present and not just the vendor hex id?
  if (!udev_id_vendor.empty() && (udev_id_vendor != udev_id_vendor_id)) {
    return udev_id_vendor;
  }

  // Is there a vendor string in the hardware database?
  if (!udev_id_vendor_from_database.empty()) {
    return udev_id_vendor_from_database;
  }

  // Ok, udev gave us nothing useful, or was unavailable. So try a heuristic.
  // We assume that card longname is in the format of
  // "<manufacturer> <name> at <bus>". Otherwise, we give up to detect
  // a manufacturer name here.
  size_t at_index = alsa_longname.rfind(" at ");
  if (at_index && at_index != std::string::npos) {
    size_t name_index = alsa_longname.rfind(alsa_name, at_index - 1);
    if (name_index && name_index != std::string::npos)
      return alsa_longname.substr(0, name_index - 1);
  }

  // Failure.
  return "";
}

void MidiManagerAlsa::SendMidiData(MidiManagerClient* client,
                                   uint32_t port_index,
                                   const std::vector<uint8_t>& data) {
  ScopedSndMidiEventPtr encoder = CreateScopedSndMidiEventPtr(kSendBufferSize);
  for (const auto datum : data) {
    snd_seq_event_t event;
    int result = snd_midi_event_encode_byte(encoder.get(), datum, &event);
    if (result == 1) {
      // Full event, send it.
      base::AutoLock lock(out_ports_lock_);
      auto it = out_ports_.find(port_index);
      if (it != out_ports_.end()) {
        base::AutoLock lock(out_client_lock_);
        if (!out_client_)
          return;
        snd_seq_ev_set_source(&event, it->second);
        snd_seq_ev_set_subs(&event);
        snd_seq_ev_set_direct(&event);
        snd_seq_event_output_direct(out_client_.get(), &event);
      }
    }
  }

  // Acknowledge send.
  AccumulateMidiBytesSent(client, data.size());
}

void MidiManagerAlsa::EventLoop() {
  bool loop_again = true;

  struct pollfd pfd[2];
  snd_seq_poll_descriptors(in_client_.get(), &pfd[0], 1, POLLIN);
  pfd[1].fd = device::udev_monitor_get_fd(udev_monitor_.get());
  pfd[1].events = POLLIN;

  int err = HANDLE_EINTR(poll(pfd, arraysize(pfd), -1));
  if (err < 0) {
    VLOG(1) << "poll fails: " << base::safe_strerror(errno);
    loop_again = false;
  } else {
    if (pfd[0].revents & POLLIN) {
      // Read available incoming MIDI data.
      int remaining;
      base::TimeTicks timestamp = base::TimeTicks::Now();
      do {
        snd_seq_event_t* event;
        err = snd_seq_event_input(in_client_.get(), &event);
        remaining = snd_seq_event_input_pending(in_client_.get(), 0);

        if (err == -ENOSPC) {
          // Handle out of space error.
          VLOG(1) << "snd_seq_event_input detected buffer overrun";
          // We've lost events: check another way to see if we need to shut
          // down.
        } else if (err == -EAGAIN) {
          // We've read all the data.
        } else if (err < 0) {
          // Handle other errors.
          VLOG(1) << "snd_seq_event_input fails: " << snd_strerror(err);
          // TODO(agoode): Use RecordAction() or similar to log this.
          loop_again = false;
        } else if (event->source.client == SND_SEQ_CLIENT_SYSTEM &&
                   event->source.port == SND_SEQ_PORT_SYSTEM_ANNOUNCE) {
          // Handle announce events.
          switch (event->type) {
            case SND_SEQ_EVENT_PORT_START:
              // Don't use SND_SEQ_EVENT_CLIENT_START because the
              // client name may not be set by the time we query
              // it. It should be set by the time ports are made.
              ProcessClientStartEvent(event->data.addr.client);
              ProcessPortStartEvent(event->data.addr);
              break;
            case SND_SEQ_EVENT_CLIENT_EXIT:
              // Check for disconnection of our "out" client. This means "shut
              // down".
              if (event->data.addr.client == out_client_id_) {
                loop_again = false;
                remaining = 0;
              } else
                ProcessClientExitEvent(event->data.addr);
              break;
            case SND_SEQ_EVENT_PORT_EXIT:
              ProcessPortExitEvent(event->data.addr);
              break;
          }
        } else {
          // Normal operation.
          ProcessSingleEvent(event, timestamp);
        }
      } while (remaining > 0);
    }
    if (pfd[1].revents & POLLIN) {
      device::ScopedUdevDevicePtr dev(
          device::udev_monitor_receive_device(udev_monitor_.get()));
      if (dev.get())
        ProcessUdevEvent(dev.get());
      else
        VLOG(1) << "udev_monitor_receive_device fails";
    }
  }

  // Do again.
  if (loop_again) {
    service()->task_service()->PostBoundTask(
        kEventTaskRunner,
        base::BindOnce(&MidiManagerAlsa::EventLoop, base::Unretained(this)));
  }
}

void MidiManagerAlsa::ProcessSingleEvent(snd_seq_event_t* event,
                                         base::TimeTicks timestamp) {
  auto source_it =
      source_map_.find(AddrToInt(event->source.client, event->source.port));
  if (source_it != source_map_.end()) {
    uint32_t source = source_it->second;
    if (event->type == SND_SEQ_EVENT_SYSEX) {
      // Special! Variable-length sysex.
      ReceiveMidiData(source, static_cast<const uint8_t*>(event->data.ext.ptr),
                      event->data.ext.len, timestamp);
    } else {
      // Otherwise, decode this and send that on.
      unsigned char buf[12];
      long count =
          snd_midi_event_decode(decoder_.get(), buf, sizeof(buf), event);
      if (count <= 0) {
        if (count != -ENOENT) {
          // ENOENT means that it's not a MIDI message, which is not an
          // error, but other negative values are errors for us.
          VLOG(1) << "snd_midi_event_decoder fails " << snd_strerror(count);
          // TODO(agoode): Record this failure.
        }
      } else {
        ReceiveMidiData(source, buf, count, timestamp);
      }
    }
  }
}

void MidiManagerAlsa::ProcessClientStartEvent(int client_id) {
  // Ignore if client is already started.
  if (alsa_seq_state_.ClientStarted(client_id))
    return;

  snd_seq_client_info_t* client_info;
  snd_seq_client_info_alloca(&client_info);
  int err =
      snd_seq_get_any_client_info(in_client_.get(), client_id, client_info);
  if (err != 0)
    return;

  // Skip our own clients.
  if ((client_id == in_client_id_) || (client_id == out_client_id_))
    return;

  // Update our view of ALSA seq state.
  alsa_seq_state_.ClientStart(client_id,
                              snd_seq_client_info_get_name(client_info),
                              snd_seq_client_info_get_type(client_info));

  // Generate Web MIDI events.
  UpdatePortStateAndGenerateEvents();
}

void MidiManagerAlsa::ProcessPortStartEvent(const snd_seq_addr_t& addr) {
  snd_seq_port_info_t* port_info;
  snd_seq_port_info_alloca(&port_info);
  int err = snd_seq_get_any_port_info(in_client_.get(), addr.client, addr.port,
                                      port_info);
  if (err != 0)
    return;

  unsigned int caps = snd_seq_port_info_get_capability(port_info);
  bool input = (caps & kRequiredInputPortCaps) == kRequiredInputPortCaps;
  bool output = (caps & kRequiredOutputPortCaps) == kRequiredOutputPortCaps;
  AlsaSeqState::PortDirection direction;
  if (input && output)
    direction = AlsaSeqState::PortDirection::kDuplex;
  else if (input)
    direction = AlsaSeqState::PortDirection::kInput;
  else if (output)
    direction = AlsaSeqState::PortDirection::kOutput;
  else
    return;

  // Update our view of ALSA seq state.
  alsa_seq_state_.PortStart(
      addr.client, addr.port, snd_seq_port_info_get_name(port_info), direction,
      snd_seq_port_info_get_type(port_info) & SND_SEQ_PORT_TYPE_MIDI_GENERIC);
  // Generate Web MIDI events.
  UpdatePortStateAndGenerateEvents();
}

void MidiManagerAlsa::ProcessClientExitEvent(const snd_seq_addr_t& addr) {
  // Update our view of ALSA seq state.
  alsa_seq_state_.ClientExit(addr.client);
  // Generate Web MIDI events.
  UpdatePortStateAndGenerateEvents();
}

void MidiManagerAlsa::ProcessPortExitEvent(const snd_seq_addr_t& addr) {
  // Update our view of ALSA seq state.
  alsa_seq_state_.PortExit(addr.client, addr.port);
  // Generate Web MIDI events.
  UpdatePortStateAndGenerateEvents();
}

void MidiManagerAlsa::ProcessUdevEvent(udev_device* dev) {
  // Only card devices have this property set, and only when they are
  // fully initialized.
  if (!device::udev_device_get_property_value(dev,
                                              kUdevPropertySoundInitialized))
    return;

  // Get the action. If no action, then we are doing first time enumeration
  // and the device is treated as new.
  const char* action = device::udev_device_get_action(dev);
  if (!action)
    action = kUdevActionChange;

  if (strcmp(action, kUdevActionChange) == 0) {
    AddCard(dev);
    // Generate Web MIDI events.
    UpdatePortStateAndGenerateEvents();
  } else if (strcmp(action, kUdevActionRemove) == 0) {
    RemoveCard(GetCardNumber(dev));
    // Generate Web MIDI events.
    UpdatePortStateAndGenerateEvents();
  }
}

void MidiManagerAlsa::AddCard(udev_device* dev) {
  int number = GetCardNumber(dev);
  if (number == -1)
    return;

  RemoveCard(number);

  snd_ctl_card_info_t* card;
  snd_hwdep_info_t* hwdep;
  snd_ctl_card_info_alloca(&card);
  snd_hwdep_info_alloca(&hwdep);
  const std::string id = base::StringPrintf("hw:CARD=%i", number);
  snd_ctl_t* handle;
  int err = snd_ctl_open(&handle, id.c_str(), 0);
  if (err != 0) {
    VLOG(1) << "snd_ctl_open fails: " << snd_strerror(err);
    return;
  }
  err = snd_ctl_card_info(handle, card);
  if (err != 0) {
    VLOG(1) << "snd_ctl_card_info fails: " << snd_strerror(err);
    snd_ctl_close(handle);
    return;
  }
  std::string name = snd_ctl_card_info_get_name(card);
  std::string longname = snd_ctl_card_info_get_longname(card);
  std::string driver = snd_ctl_card_info_get_driver(card);

  // Count rawmidi devices (not subdevices).
  int midi_count = 0;
  for (int device = -1;
       !snd_ctl_rawmidi_next_device(handle, &device) && device >= 0;)
    ++midi_count;

  // Count any hwdep synths that become MIDI devices outside of rawmidi.
  //
  // Explanation:
  // Any kernel driver can create an ALSA client (visible to us).
  // With modern hardware, only rawmidi devices do this. Kernel
  // drivers create rawmidi devices and the rawmidi subsystem makes
  // the seq clients. But the OPL3 driver is special, it does not
  // make a rawmidi device but a seq client directly. (This is the
  // only one to worry about in the kernel code, as of 2015-03-23.)
  //
  // OPL3 is very old (but still possible to get in new
  // hardware). It is unlikely that new drivers would not use
  // rawmidi and defeat our heuristic.
  //
  // Longer term, support should be added in the kernel to expose a
  // direct link from card->client (or client->card) so that all
  // these heuristics will be obsolete.  Once that is there, we can
  // assume our old heuristics will work on old kernels and the new
  // robust code will be used on new. Then we will not need to worry
  // about changes to kernel internals breaking our code.
  // See the TODO above at kMinimumClientIdForCards.
  for (int device = -1;
       !snd_ctl_hwdep_next_device(handle, &device) && device >= 0;) {
    err = snd_ctl_hwdep_info(handle, hwdep);
    if (err != 0) {
      VLOG(1) << "snd_ctl_hwdep_info fails: " << snd_strerror(err);
      continue;
    }
    snd_hwdep_iface_t iface = snd_hwdep_info_get_iface(hwdep);
    if (iface == SND_HWDEP_IFACE_OPL2 || iface == SND_HWDEP_IFACE_OPL3 ||
        iface == SND_HWDEP_IFACE_OPL4)
      ++midi_count;
  }
  snd_ctl_close(handle);

  if (midi_count > 0) {
    std::unique_ptr<AlsaCard> card(
        new AlsaCard(dev, name, longname, driver, midi_count));
    alsa_cards_.insert(std::make_pair(number, std::move(card)));
    alsa_card_midi_count_ += midi_count;
  }
}

void MidiManagerAlsa::RemoveCard(int number) {
  auto it = alsa_cards_.find(number);
  if (it == alsa_cards_.end())
    return;

  alsa_card_midi_count_ -= it->second->midi_device_count();
  alsa_cards_.erase(it);
}

void MidiManagerAlsa::UpdatePortStateAndGenerateEvents() {
  // Verify that our information from ALSA and udev are in sync. If
  // not, we cannot generate events right now.
  if (alsa_card_midi_count_ != alsa_seq_state_.card_client_count())
    return;

  // Generate new port state.
  auto new_port_state = alsa_seq_state_.ToMidiPortState(alsa_cards_);

  // Disconnect any connected old ports that are now missing.
  for (auto& old_port : port_state_) {
    if (old_port->connected() &&
        (new_port_state->FindConnected(*old_port) == new_port_state->end())) {
      old_port->set_connected(false);
      uint32_t web_port_index = old_port->web_port_index();
      switch (old_port->type()) {
        case MidiPort::Type::kInput:
          source_map_.erase(
              AddrToInt(old_port->client_id(), old_port->port_id()));
          SetInputPortState(web_port_index, PortState::DISCONNECTED);
          break;
        case MidiPort::Type::kOutput:
          DeleteAlsaOutputPort(web_port_index);
          SetOutputPortState(web_port_index, PortState::DISCONNECTED);
          break;
      }
    }
  }

  // Reconnect or add new ports.
  auto it = new_port_state->begin();
  while (it != new_port_state->end()) {
    auto& new_port = *it;
    auto old_port = port_state_.Find(*new_port);
    if (old_port == port_state_.end()) {
      // Add new port.
      const auto& opaque_key = new_port->OpaqueKey();
      const auto& manufacturer = new_port->manufacturer();
      const auto& port_name = new_port->port_name();
      const auto& version = new_port->version();
      const auto& type = new_port->type();
      const auto& client_id = new_port->client_id();
      const auto& port_id = new_port->port_id();

      uint32_t web_port_index = port_state_.push_back(std::move(new_port));
      it = new_port_state->erase(it);

      mojom::PortInfo info(opaque_key, manufacturer, port_name, version,
                           PortState::OPENED);
      switch (type) {
        case MidiPort::Type::kInput:
          if (Subscribe(web_port_index, client_id, port_id))
            AddInputPort(info);
          break;
        case MidiPort::Type::kOutput:
          if (CreateAlsaOutputPort(web_port_index, client_id, port_id))
            AddOutputPort(info);
          break;
      }
    } else if (!(*old_port)->connected()) {
      // Reconnect.
      uint32_t web_port_index = (*old_port)->web_port_index();
      (*old_port)->Update(new_port->path(), new_port->client_id(),
                          new_port->port_id(), new_port->client_name(),
                          new_port->port_name(), new_port->manufacturer(),
                          new_port->version());
      switch ((*old_port)->type()) {
        case MidiPort::Type::kInput:
          if (Subscribe(web_port_index, (*old_port)->client_id(),
                        (*old_port)->port_id()))
            SetInputPortState(web_port_index, PortState::OPENED);
          break;
        case MidiPort::Type::kOutput:
          if (CreateAlsaOutputPort(web_port_index, (*old_port)->client_id(),
                                   (*old_port)->port_id()))
            SetOutputPortState(web_port_index, PortState::OPENED);
          break;
      }
      (*old_port)->set_connected(true);
      ++it;
    } else {
      ++it;
    }
  }
}

// TODO(agoode): return false on failure.
void MidiManagerAlsa::EnumerateAlsaPorts() {
  snd_seq_client_info_t* client_info;
  snd_seq_client_info_alloca(&client_info);
  snd_seq_port_info_t* port_info;
  snd_seq_port_info_alloca(&port_info);

  // Enumerate clients.
  snd_seq_client_info_set_client(client_info, -1);
  while (!snd_seq_query_next_client(in_client_.get(), client_info)) {
    int client_id = snd_seq_client_info_get_client(client_info);
    ProcessClientStartEvent(client_id);

    // Enumerate ports.
    snd_seq_port_info_set_client(port_info, client_id);
    snd_seq_port_info_set_port(port_info, -1);
    while (!snd_seq_query_next_port(in_client_.get(), port_info)) {
      const snd_seq_addr_t* addr = snd_seq_port_info_get_addr(port_info);
      ProcessPortStartEvent(*addr);
    }
  }
}

bool MidiManagerAlsa::EnumerateUdevCards() {
  int err;

  device::ScopedUdevEnumeratePtr enumerate(
      device::udev_enumerate_new(udev_.get()));
  if (!enumerate.get()) {
    VLOG(1) << "udev_enumerate_new fails";
    return false;
  }

  err = device::udev_enumerate_add_match_subsystem(enumerate.get(),
                                                   kUdevSubsystemSound);
  if (err) {
    VLOG(1) << "udev_enumerate_add_match_subsystem fails: "
            << base::safe_strerror(-err);
    return false;
  }

  err = device::udev_enumerate_scan_devices(enumerate.get());
  if (err) {
    VLOG(1) << "udev_enumerate_scan_devices fails: "
            << base::safe_strerror(-err);
    return false;
  }

  udev_list_entry* list_entry;
  auto* devices = device::udev_enumerate_get_list_entry(enumerate.get());
  udev_list_entry_foreach(list_entry, devices) {
    const char* path = device::udev_list_entry_get_name(list_entry);
    device::ScopedUdevDevicePtr dev(
        device::udev_device_new_from_syspath(udev_.get(), path));
    if (dev.get())
      ProcessUdevEvent(dev.get());
  }

  return true;
}

bool MidiManagerAlsa::CreateAlsaOutputPort(uint32_t port_index,
                                           int client_id,
                                           int port_id) {
  // Create the port.
  int out_port;
  {
    base::AutoLock lock(out_client_lock_);
    out_port = snd_seq_create_simple_port(
        out_client_.get(), NULL, kCreateOutputPortCaps, kCreatePortType);

    if (out_port < 0) {
      VLOG(1) << "snd_seq_create_simple_port fails: " << snd_strerror(out_port);
      return false;
    }

    // Activate port subscription.
    snd_seq_port_subscribe_t* subs;
    snd_seq_port_subscribe_alloca(&subs);
    snd_seq_addr_t sender;
    sender.client = out_client_id_;
    sender.port = out_port;
    snd_seq_port_subscribe_set_sender(subs, &sender);
    snd_seq_addr_t dest;
    dest.client = client_id;
    dest.port = port_id;
    snd_seq_port_subscribe_set_dest(subs, &dest);
    int err = snd_seq_subscribe_port(out_client_.get(), subs);
    if (err != 0) {
      VLOG(1) << "snd_seq_subscribe_port fails: " << snd_strerror(err);
      snd_seq_delete_simple_port(out_client_.get(), out_port);
      return false;
    }
  }

  // Update our map.
  base::AutoLock lock(out_ports_lock_);
  out_ports_[port_index] = out_port;
  return true;
}

void MidiManagerAlsa::DeleteAlsaOutputPort(uint32_t port_index) {
  int alsa_port;
  {
    base::AutoLock lock(out_ports_lock_);
    auto it = out_ports_.find(port_index);
    if (it == out_ports_.end())
      return;
    alsa_port = it->second;
    out_ports_.erase(it);
  }
  {
    base::AutoLock lock(out_client_lock_);
    snd_seq_delete_simple_port(out_client_.get(), alsa_port);
  }
}

bool MidiManagerAlsa::Subscribe(uint32_t port_index,
                                int client_id,
                                int port_id) {
  // Activate port subscription.
  snd_seq_port_subscribe_t* subs;
  snd_seq_port_subscribe_alloca(&subs);
  snd_seq_addr_t sender;
  sender.client = client_id;
  sender.port = port_id;
  snd_seq_port_subscribe_set_sender(subs, &sender);
  snd_seq_addr_t dest;
  dest.client = in_client_id_;
  dest.port = in_port_id_;
  snd_seq_port_subscribe_set_dest(subs, &dest);
  int err = snd_seq_subscribe_port(in_client_.get(), subs);
  if (err != 0) {
    VLOG(1) << "snd_seq_subscribe_port fails: " << snd_strerror(err);
    return false;
  }

  // Update our map.
  source_map_[AddrToInt(client_id, port_id)] = port_index;
  return true;
}

MidiManagerAlsa::ScopedSndMidiEventPtr
MidiManagerAlsa::CreateScopedSndMidiEventPtr(size_t size) {
  snd_midi_event_t* coder;
  snd_midi_event_new(size, &coder);
  return ScopedSndMidiEventPtr(coder);
}

MidiManager* MidiManager::Create(MidiService* service) {
  return new MidiManagerAlsa(service);
}

}  // namespace midi
