// 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 <alsa/asoundlib.h>
#include <stdlib.h>
#include <algorithm>
#include <string>

#include "base/bind.h"
#include "base/json/json_string_value_serializer.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/message_loop/message_loop.h"
#include "base/posix/eintr_wrapper.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "base/values.h"
#include "crypto/sha2.h"
#include "media/midi/midi_port_info.h"

namespace media {

namespace {

// 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.
const 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.
const int kMinimumClientIdForCards = 16;

// udev key constants.
#if defined(USE_UDEV)
const char kSoundClass[] = "sound";
const char kIdVendor[] = "ID_VENDOR";
const char kIdVendorEnc[] = "ID_VENDOR_ENC";
const char kIdVendorFromDatabase[] = "ID_VENDOR_FROM_DATABASE";
const char kSysattrVendorName[] = "vendor_name";
const char kIdVendorId[] = "ID_VENDOR_ID";
const char kSysattrVendor[] = "vendor";
const char kIdModelId[] = "ID_MODEL_ID";
const char kSysattrModel[] = "model";
const char kIdBus[] = "ID_BUS";
const char kIdPath[] = "ID_PATH";
const char kUsbInterfaceNum[] = "ID_USB_INTERFACE_NUM";
#endif  // defined(USE_UDEV)

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

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

int AddrToInt(const snd_seq_addr_t* addr) {
  return (addr->client << 8) | addr->port;
}

// TODO(agoode): Move this to device/udev_linux.
#if defined(USE_UDEV)
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;
}
#endif  // defined(USE_UDEV)

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()
    : in_client_(NULL),
      out_client_(NULL),
      out_client_id_(-1),
      in_port_(-1),
      decoder_(NULL),
#if defined(USE_UDEV)
      udev_(device::udev_new()),
#endif  // defined(USE_UDEV)
      send_thread_("MidiSendThread"),
      event_thread_("MidiEventThread"),
      event_thread_shutdown_(false) {
  // Initialize decoder.
  snd_midi_event_new(0, &decoder_);
  snd_midi_event_no_status(decoder_, 1);
}

MidiManagerAlsa::~MidiManagerAlsa() {
  // Tell the event thread it will soon be time to shut down. This gives
  // us assurance the thread will stop in case the SND_SEQ_EVENT_CLIENT_EXIT
  // message is lost.
  {
    base::AutoLock lock(shutdown_lock_);
    event_thread_shutdown_ = true;
  }

  // Stop the send thread.
  send_thread_.Stop();

  // Close the out client. This will trigger the event thread to stop,
  // because of SND_SEQ_EVENT_CLIENT_EXIT.
  if (out_client_)
    snd_seq_close(out_client_);

  // Wait for the event thread to stop.
  event_thread_.Stop();

  // Close the in client.
  if (in_client_)
    snd_seq_close(in_client_);

  // Free the decoder.
  snd_midi_event_free(decoder_);
}

void MidiManagerAlsa::StartInitialization() {
  // TODO(agoode): Move off I/O thread. See http://crbug.com/374341.

  // Create client handles.
  int err = snd_seq_open(&in_client_, kAlsaHw, SND_SEQ_OPEN_INPUT, 0);
  if (err != 0) {
    VLOG(1) << "snd_seq_open fails: " << snd_strerror(err);
    return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
  }
  int in_client_id = snd_seq_client_id(in_client_);
  err = snd_seq_open(&out_client_, kAlsaHw, SND_SEQ_OPEN_OUTPUT, 0);
  if (err != 0) {
    VLOG(1) << "snd_seq_open fails: " << snd_strerror(err);
    return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
  }
  out_client_id_ = snd_seq_client_id(out_client_);

  // Name the clients.
  err = snd_seq_set_client_name(in_client_, "Chrome (input)");
  if (err != 0) {
    VLOG(1) << "snd_seq_set_client_name fails: " << snd_strerror(err);
    return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
  }
  err = snd_seq_set_client_name(out_client_, "Chrome (output)");
  if (err != 0) {
    VLOG(1) << "snd_seq_set_client_name fails: " << snd_strerror(err);
    return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
  }

  // Create input port.
  in_port_ = snd_seq_create_simple_port(in_client_, NULL,
                                        SND_SEQ_PORT_CAP_WRITE |
                                        SND_SEQ_PORT_CAP_NO_EXPORT,
                                        SND_SEQ_PORT_TYPE_MIDI_GENERIC |
                                        SND_SEQ_PORT_TYPE_APPLICATION);
  if (in_port_ < 0) {
    VLOG(1) << "snd_seq_create_simple_port fails: " << snd_strerror(in_port_);
    return CompleteInitialization(MIDI_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_;
  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_, subs);
  if (err != 0) {
    VLOG(1) << "snd_seq_subscribe_port on the announce port fails: "
            << snd_strerror(err);
    return CompleteInitialization(MIDI_INITIALIZATION_ERROR);
  }

  EnumeratePorts();

  event_thread_.Start();
  event_thread_.message_loop()->PostTask(
      FROM_HERE,
      base::Bind(&MidiManagerAlsa::ScheduleEventLoop, base::Unretained(this)));

  CompleteInitialization(MIDI_OK);
}

void MidiManagerAlsa::DispatchSendMidiData(MidiManagerClient* client,
                                           uint32 port_index,
                                           const std::vector<uint8>& data,
                                           double timestamp) {
  if (out_ports_.size() <= port_index)
    return;

  // Not correct right now. http://crbug.com/374341.
  if (!send_thread_.IsRunning())
    send_thread_.Start();

  base::TimeDelta delay;
  if (timestamp != 0.0) {
    base::TimeTicks time_to_send =
        base::TimeTicks() + base::TimeDelta::FromMicroseconds(
                                timestamp * base::Time::kMicrosecondsPerSecond);
    delay = std::max(time_to_send - base::TimeTicks::Now(), base::TimeDelta());
  }

  send_thread_.message_loop()->PostDelayedTask(
      FROM_HERE, base::Bind(&MidiManagerAlsa::SendMidiData,
                            base::Unretained(this), port_index, data),
      delay);

  // Acknowledge send.
  send_thread_.message_loop()->PostTask(
      FROM_HERE, base::Bind(&MidiManagerClient::AccumulateMidiBytesSent,
                            base::Unretained(client), data.size()));
}

MidiManagerAlsa::AlsaCard::AlsaCard(const MidiManagerAlsa* outer,
                                    const std::string& alsa_name,
                                    const std::string& alsa_longname,
                                    const std::string& alsa_driver,
                                    int card_index,
                                    int midi_count)
    : alsa_name_(alsa_name),
      alsa_longname_(alsa_longname),
      alsa_driver_(alsa_driver),
      midi_count_(midi_count) {
  // Get udev properties if available.
  std::string vendor;
  std::string vendor_from_database;

#if defined(USE_UDEV)
  const std::string sysname = base::StringPrintf("card%i", card_index);
  device::ScopedUdevDevicePtr udev_device(
      device::udev_device_new_from_subsystem_sysname(
          outer->udev_.get(), kSoundClass, sysname.c_str()));

  // TODO(agoode): Move this to a new utility class in device/udev_linux?

  // Try to get the vendor string. Sometimes it is encoded.
  vendor = device::UdevDecodeString(
      device::UdevDeviceGetPropertyValue(udev_device.get(), kIdVendorEnc));
  // Sometimes it is not encoded.
  if (vendor.empty())
    vendor = UdevDeviceGetPropertyOrSysattr(udev_device.get(), kIdVendor,
                                            kSysattrVendorName);
  // Also get the vendor string from the hardware database.
  vendor_from_database = device::UdevDeviceGetPropertyValue(
      udev_device.get(), kIdVendorFromDatabase);

  // Get the device path.
  path_ = device::UdevDeviceGetPropertyValue(udev_device.get(), kIdPath);

  // Get the bus.
  bus_ = device::UdevDeviceGetPropertyValue(udev_device.get(), kIdBus);

  // Get the vendor id, by either property or sysattr.
  vendor_id_ = UdevDeviceGetPropertyOrSysattr(udev_device.get(), kIdVendorId,
                                              kSysattrVendor);

  // Get the model id, by either property or sysattr.
  model_id_ = UdevDeviceGetPropertyOrSysattr(udev_device.get(), kIdModelId,
                                             kSysattrModel);

  // Get the usb interface number.
  usb_interface_num_ =
      device::UdevDeviceGetPropertyValue(udev_device.get(), kUsbInterfaceNum);
#endif  // defined(USE_UDEV)

  manufacturer_ = ExtractManufacturerString(
      vendor, vendor_id_, vendor_from_database, alsa_name, alsa_longname);
}

MidiManagerAlsa::AlsaCard::~AlsaCard() {
}

const std::string MidiManagerAlsa::AlsaCard::alsa_name() const {
  return alsa_name_;
}

const std::string MidiManagerAlsa::AlsaCard::alsa_longname() const {
  return alsa_longname_;
}

const std::string MidiManagerAlsa::AlsaCard::manufacturer() const {
  return manufacturer_;
}

const std::string MidiManagerAlsa::AlsaCard::alsa_driver() const {
  return alsa_driver_;
}

const std::string MidiManagerAlsa::AlsaCard::path() const {
  return path_;
}

const std::string MidiManagerAlsa::AlsaCard::bus() const {
  return bus_;
}

const std::string MidiManagerAlsa::AlsaCard::vendor_id() const {
  return vendor_id_;
}

const std::string MidiManagerAlsa::AlsaCard::id() const {
  std::string id = vendor_id_;
  if (!model_id_.empty())
    id += ":" + model_id_;
  if (!usb_interface_num_.empty())
    id += ":" + usb_interface_num_;
  return id;
}

const int MidiManagerAlsa::AlsaCard::midi_count() const {
  return midi_count_;
}

// 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 "";
}

MidiManagerAlsa::AlsaPortMetadata::AlsaPortMetadata(
    const std::string& path,
    const std::string& bus,
    const std::string& id,
    const snd_seq_addr_t* address,
    const std::string& client_name,
    const std::string& port_name,
    const std::string& card_name,
    const std::string& card_longname,
    Type type)
    : path_(path),
      bus_(bus),
      id_(id),
      client_addr_(address->client),
      port_addr_(address->port),
      client_name_(client_name),
      port_name_(port_name),
      card_name_(card_name),
      card_longname_(card_longname),
      type_(type) {
}

MidiManagerAlsa::AlsaPortMetadata::~AlsaPortMetadata() {
}

scoped_ptr<base::Value> MidiManagerAlsa::AlsaPortMetadata::Value() const {
  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue);
  SetStringIfNonEmpty(value.get(), "path", path_);
  SetStringIfNonEmpty(value.get(), "bus", bus_);
  SetStringIfNonEmpty(value.get(), "id", id_);
  value->SetInteger("clientAddr", client_addr_);
  value->SetInteger("portAddr", port_addr_);
  SetStringIfNonEmpty(value.get(), "clientName", client_name_);
  SetStringIfNonEmpty(value.get(), "portName", port_name_);
  SetStringIfNonEmpty(value.get(), "cardName", card_name_);
  SetStringIfNonEmpty(value.get(), "cardLongname", card_longname_);
  std::string type;
  switch (type_) {
    case Type::kInput:
      type = "input";
      break;

    case Type::kOutput:
      type = "output";
      break;
  }
  SetStringIfNonEmpty(value.get(), "type", type);

  return value.Pass();
}

std::string MidiManagerAlsa::AlsaPortMetadata::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::AlsaPortMetadata::OpaqueKey() const {
  uint8 hash[crypto::kSHA256Length];
  crypto::SHA256HashString(JSONValue(), &hash, sizeof(hash));
  return base::HexEncode(&hash, sizeof(hash));
}

// TODO(agoode): Add a client->card/rawmidi mapping to the kernel to avoid
//               needing to probe in this way.
ScopedVector<MidiManagerAlsa::AlsaCard> MidiManagerAlsa::AllMidiCards() {
  ScopedVector<AlsaCard> devices;
  snd_ctl_card_info_t* card;
  snd_hwdep_info_t* hwdep;
  snd_ctl_card_info_alloca(&card);
  snd_hwdep_info_alloca(&hwdep);
  for (int card_index = -1; !snd_card_next(&card_index) && card_index >= 0;) {
    int midi_count = 0;
    const std::string id = base::StringPrintf("hw:CARD=%i", card_index);
    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);
      continue;
    }
    err = snd_ctl_card_info(handle, card);
    if (err != 0) {
      VLOG(1) << "snd_ctl_card_info fails: " << snd_strerror(err);
      snd_ctl_close(handle);
      continue;
    }
    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).
    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;) {
      snd_ctl_hwdep_info(handle, hwdep);
      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;
    }

    if (midi_count > 0)
      devices.push_back(
          new AlsaCard(this, name, longname, driver, card_index, midi_count));
    snd_ctl_close(handle);
  }

  return devices.Pass();
}

void MidiManagerAlsa::EnumeratePorts() {
  ScopedVector<AlsaCard> cards = AllMidiCards();
  std::vector<const AlsaCard*> devices;
  for (const auto* card : cards) {
    // Insert 1 AlsaCard per number of MIDI devices.
    for (int n = 0; n < card->midi_count(); ++n)
      devices.push_back(card);
  }

  snd_seq_port_subscribe_t* subs;
  snd_seq_port_subscribe_alloca(&subs);

  int in_client_id = snd_seq_client_id(in_client_);

  // Enumerate all clients.
  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);
  uint32 current_input = 0;
  unsigned int current_device = 0;
  while (!snd_seq_query_next_client(in_client_, client_info)) {
    int client_id = snd_seq_client_info_get_client(client_info);
    if ((client_id == in_client_id) || (client_id == out_client_id_)) {
      // Skip our own clients.
      continue;
    }

    // Get client metadata.
    const std::string client_name = snd_seq_client_info_get_name(client_info);
    snd_seq_port_info_set_client(port_info, client_id);
    snd_seq_port_info_set_port(port_info, -1);

    std::string manufacturer;
    std::string driver;
    std::string path;
    std::string bus;
    std::string vendor_id;
    std::string id;
    std::string card_name;
    std::string card_longname;

    // Join kernel clients against the list of AlsaCards.
    // In the current ALSA kernel implementation, kernel clients match the
    // kernel devices in the same order, for clients with client_id over
    // kMinimumClientIdForCards.
    if ((snd_seq_client_info_get_type(client_info) == SND_SEQ_KERNEL_CLIENT) &&
        (current_device < devices.size()) &&
        (client_id >= kMinimumClientIdForCards)) {
      const AlsaCard* device = devices[current_device];
      manufacturer = device->manufacturer();
      driver = device->alsa_driver();
      path = device->path();
      bus = device->bus();
      vendor_id = device->vendor_id();
      id = device->id();
      card_name = device->alsa_name();
      card_longname = device->alsa_longname();
      current_device++;
    }
    // Enumerate ports.
    while (!snd_seq_query_next_port(in_client_, port_info)) {
      unsigned int port_type = snd_seq_port_info_get_type(port_info);
      if (port_type & SND_SEQ_PORT_TYPE_MIDI_GENERIC) {
        const snd_seq_addr_t* addr = snd_seq_port_info_get_addr(port_info);
        const std::string name = snd_seq_port_info_get_name(port_info);
        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);
        unsigned int caps = snd_seq_port_info_get_capability(port_info);
        if ((caps & kRequiredInputPortCaps) == kRequiredInputPortCaps) {
          // Subscribe to this port.
          const snd_seq_addr_t* sender = snd_seq_port_info_get_addr(port_info);
          snd_seq_addr_t dest;
          dest.client = snd_seq_client_id(in_client_);
          dest.port = in_port_;
          snd_seq_port_subscribe_set_sender(subs, sender);
          snd_seq_port_subscribe_set_dest(subs, &dest);
          int err = snd_seq_subscribe_port(in_client_, subs);
          if (err != 0) {
            VLOG(1) << "snd_seq_subscribe_port fails: " << snd_strerror(err);
          } else {
            source_map_[AddrToInt(sender)] = current_input++;
            const AlsaPortMetadata metadata(path, bus, id, addr, client_name,
                                            name, card_name, card_longname,
                                            AlsaPortMetadata::Type::kInput);
            const std::string id = metadata.OpaqueKey();
            AddInputPort(MidiPortInfo(id.c_str(), manufacturer, name, version,
                                      MIDI_PORT_OPENED));
          }
        }
        if ((caps & kRequiredOutputPortCaps) == kRequiredOutputPortCaps) {
          // Create a port for us to send on.
          int out_port =
              snd_seq_create_simple_port(out_client_, NULL,
                                         SND_SEQ_PORT_CAP_READ |
                                         SND_SEQ_PORT_CAP_NO_EXPORT,
                                         SND_SEQ_PORT_TYPE_MIDI_GENERIC |
                                         SND_SEQ_PORT_TYPE_APPLICATION);
          if (out_port < 0) {
            VLOG(1) << "snd_seq_create_simple_port fails: "
                    << snd_strerror(out_port);
            // Skip this output port for now.
            continue;
          }

          // Activate port subscription.
          snd_seq_addr_t sender;
          const snd_seq_addr_t* dest = snd_seq_port_info_get_addr(port_info);
          sender.client = snd_seq_client_id(out_client_);
          sender.port = out_port;
          snd_seq_port_subscribe_set_sender(subs, &sender);
          snd_seq_port_subscribe_set_dest(subs, dest);
          int err = snd_seq_subscribe_port(out_client_, subs);
          if (err != 0) {
            VLOG(1) << "snd_seq_subscribe_port fails: " << snd_strerror(err);
            snd_seq_delete_simple_port(out_client_, out_port);
          } else {
            out_ports_.push_back(out_port);
            const AlsaPortMetadata metadata(path, bus, id, addr, client_name,
                                            name, card_name, card_longname,
                                            AlsaPortMetadata::Type::kOutput);
            const std::string id = metadata.OpaqueKey();
            AddOutputPort(MidiPortInfo(id.c_str(), manufacturer, name, version,
                                       MIDI_PORT_OPENED));
          }
        }
      }
    }
  }
}

void MidiManagerAlsa::SendMidiData(uint32 port_index,
                                   const std::vector<uint8>& data) {
  DCHECK(send_thread_.message_loop_proxy()->BelongsToCurrentThread());

  snd_midi_event_t* encoder;
  snd_midi_event_new(kSendBufferSize, &encoder);
  for (unsigned int i = 0; i < data.size(); i++) {
    snd_seq_event_t event;
    int result = snd_midi_event_encode_byte(encoder, data[i], &event);
    if (result == 1) {
      // Full event, send it.
      snd_seq_ev_set_source(&event, out_ports_[port_index]);
      snd_seq_ev_set_subs(&event);
      snd_seq_ev_set_direct(&event);
      snd_seq_event_output_direct(out_client_, &event);
    }
  }
  snd_midi_event_free(encoder);
}

void MidiManagerAlsa::ScheduleEventLoop() {
  event_thread_.message_loop()->PostTask(
      FROM_HERE,
      base::Bind(&MidiManagerAlsa::EventLoop, base::Unretained(this)));
}

void MidiManagerAlsa::EventLoop() {
  // Read available incoming MIDI data.
  snd_seq_event_t* event;
  int err = snd_seq_event_input(in_client_, &event);
  double timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();

  // Handle errors.
  if (err == -ENOSPC) {
    VLOG(1) << "snd_seq_event_input detected buffer overrun";
    // We've lost events: check another way to see if we need to shut down.
    base::AutoLock lock(shutdown_lock_);
    if (!event_thread_shutdown_)
      ScheduleEventLoop();
    return;
  } else if (err < 0) {
    VLOG(1) << "snd_seq_event_input fails: " << snd_strerror(err);
    // TODO(agoode): Use RecordAction() or similar to log this.
    return;
  }

  // Handle announce events.
  if (event->source.client == SND_SEQ_CLIENT_SYSTEM &&
      event->source.port == SND_SEQ_PORT_SYSTEM_ANNOUNCE) {
    switch (event->type) {
      case SND_SEQ_EVENT_CLIENT_START:
        // TODO(agoode): rescan hardware devices.
        break;

      case SND_SEQ_EVENT_PORT_START:
        // TODO(agoode): add port.
        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_)
          return;

        // TODO(agoode): remove all ports for a client.
        break;

      case SND_SEQ_EVENT_PORT_EXIT:
        // TODO(agoode): remove port.
        break;
    }
  } else {
    ProcessSingleEvent(event, timestamp);
  }

  // Do again.
  ScheduleEventLoop();
}

void MidiManagerAlsa::ProcessSingleEvent(snd_seq_event_t* event,
                                         double timestamp) {
  auto source_it = source_map_.find(AddrToInt(&event->source));
  if (source_it != source_map_.end()) {
    uint32 source = source_it->second;
    if (event->type == SND_SEQ_EVENT_SYSEX) {
      // Special! Variable-length sysex.
      ReceiveMidiData(source, static_cast<const uint8*>(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_, 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);
      }
    }
  }
}

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

}  // namespace media
