// Copyright (c) 2013 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_mac.h"

#include <stddef.h>

#include <algorithm>
#include <iterator>
#include <string>

#include <CoreAudio/HostTime.h>

#include "base/bind.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/sys_string_conversions.h"
#include "media/midi/midi_service.h"
#include "media/midi/task_service.h"

using base::NumberToString;
using base::SysCFStringRefToUTF8;
using midi::mojom::PortState;
using midi::mojom::Result;

// NB: System MIDI types are pointer types in 32-bit and integer types in
// 64-bit. Therefore, the initialization is the simplest one that satisfies both
// (if possible).

namespace midi {

namespace {

// Maximum buffer size that CoreMIDI can handle for MIDIPacketList.
const size_t kCoreMIDIMaxPacketListSize = 65536;
// Pessimistic estimation on available data size of MIDIPacketList.
const size_t kEstimatedMaxPacketDataSize = kCoreMIDIMaxPacketListSize / 2;

enum {
  kSessionTaskRunner = TaskService::kDefaultRunnerId,
  kClientTaskRunner,
};

mojom::PortInfo GetPortInfoFromEndpoint(MIDIEndpointRef endpoint) {
  std::string manufacturer;
  CFStringRef manufacturer_ref = NULL;
  OSStatus result = MIDIObjectGetStringProperty(
      endpoint, kMIDIPropertyManufacturer, &manufacturer_ref);
  if (result == noErr) {
    manufacturer = SysCFStringRefToUTF8(manufacturer_ref);
  } else {
    // kMIDIPropertyManufacturer is not supported in IAC driver providing
    // endpoints, and the result will be kMIDIUnknownProperty (-10835).
    DLOG(WARNING) << "Failed to get kMIDIPropertyManufacturer with status "
                  << result;
  }

  std::string name;
  CFStringRef name_ref = NULL;
  result = MIDIObjectGetStringProperty(endpoint, kMIDIPropertyDisplayName,
                                       &name_ref);
  if (result == noErr) {
    name = SysCFStringRefToUTF8(name_ref);
  } else {
    DLOG(WARNING) << "Failed to get kMIDIPropertyDisplayName with status "
                  << result;
  }

  std::string version;
  SInt32 version_number = 0;
  result = MIDIObjectGetIntegerProperty(
      endpoint, kMIDIPropertyDriverVersion, &version_number);
  if (result == noErr) {
    version = NumberToString(version_number);
  } else {
    // kMIDIPropertyDriverVersion is not supported in IAC driver providing
    // endpoints, and the result will be kMIDIUnknownProperty (-10835).
    DLOG(WARNING) << "Failed to get kMIDIPropertyDriverVersion with status "
                  << result;
  }

  std::string id;
  SInt32 id_number = 0;
  result = MIDIObjectGetIntegerProperty(
      endpoint, kMIDIPropertyUniqueID, &id_number);
  if (result == noErr) {
    id = NumberToString(id_number);
  } else {
    // On connecting some devices, e.g., nano KONTROL2, unknown endpoints
    // appear and disappear quickly and they fail on queries.
    // Let's ignore such ghost devices.
    // Same problems will happen if the device is disconnected before finishing
    // all queries.
    DLOG(WARNING) << "Failed to get kMIDIPropertyUniqueID with status "
                  << result;
  }

  const PortState state = PortState::OPENED;
  return mojom::PortInfo(id, manufacturer, name, version, state);
}

base::TimeTicks MIDITimeStampToTimeTicks(MIDITimeStamp timestamp) {
  UInt64 nanoseconds = AudioConvertHostTimeToNanos(timestamp);
  return base::TimeTicks() + base::Nanoseconds(nanoseconds);
}

MIDITimeStamp TimeTicksToMIDITimeStamp(base::TimeTicks ticks) {
  return AudioConvertNanosToHostTime(ticks.since_origin().InNanoseconds());
}

}  // namespace

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

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

MidiManagerMac::~MidiManagerMac() {
  if (!service()->task_service()->UnbindInstance())
    return;

  // Finalization steps should be implemented after the UnbindInstance() call.
  // Do not need to dispose |coremidi_input_| and |coremidi_output_| explicitly.
  // CoreMIDI automatically disposes them on the client disposal.
  base::AutoLock lock(midi_client_lock_);
  if (midi_client_)
    MIDIClientDispose(midi_client_);
}

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

  service()->task_service()->PostBoundTask(
      kClientTaskRunner, base::BindOnce(&MidiManagerMac::InitializeCoreMIDI,
                                        base::Unretained(this)));
}

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

void MidiManagerMac::InitializeCoreMIDI() {
  DCHECK(service()->task_service()->IsOnTaskRunner(kClientTaskRunner));

  // CoreMIDI registration.
  MIDIClientRef client = 0u;
  OSStatus result = MIDIClientCreate(CFSTR("Chrome"), ReceiveMidiNotifyDispatch,
                                     this, &client);
  if (result != noErr || client == 0u)
    return CompleteCoreMIDIInitialization(Result::INITIALIZATION_ERROR);

  {
    base::AutoLock lock(midi_client_lock_);
    midi_client_ = client;
  }

  // Create input and output port. These MIDIPortRef references are not needed
  // to be disposed explicitly. CoreMIDI automatically disposes them on the
  // client disposal.
  result = MIDIInputPortCreate(client, CFSTR("MIDI Input"), ReadMidiDispatch,
                               this, &midi_input_);
  if (result != noErr || midi_input_ == 0u)
    return CompleteCoreMIDIInitialization(Result::INITIALIZATION_ERROR);

  result = MIDIOutputPortCreate(client, CFSTR("MIDI Output"), &midi_output_);
  if (result != noErr || midi_output_ == 0u)
    return CompleteCoreMIDIInitialization(Result::INITIALIZATION_ERROR);

  // Following loop may miss some newly attached devices, but such device will
  // be captured by ReceiveMidiNotifyDispatch callback.
  destinations_.resize(MIDIGetNumberOfDestinations());
  for (size_t i = 0u; i < destinations_.size(); ++i) {
    MIDIEndpointRef destination = MIDIGetDestination(i);
    DCHECK_NE(0u, destination);

    // Keep track of all destinations (known as outputs by the Web MIDI API).
    destinations_[i] = destination;
    AddOutputPort(GetPortInfoFromEndpoint(destination));
  }
  // Allocate maximum size of buffer that CoreMIDI can handle.
  midi_buffer_.resize(kCoreMIDIMaxPacketListSize);

  // Open connections from all sources. This loop also may miss new devices.
  sources_.resize(MIDIGetNumberOfSources());
  for (size_t i = 0u; i < sources_.size(); ++i) {
    MIDIEndpointRef source = MIDIGetSource(i);
    DCHECK_NE(0u, source);

    // Keep track of all sources (known as inputs by the Web MIDI API).
    sources_[i] = source;
    AddInputPort(GetPortInfoFromEndpoint(source));
  }
  // Start listening.
  for (size_t i = 0u; i < sources_.size(); ++i)
    MIDIPortConnectSource(midi_input_, sources_[i], reinterpret_cast<void*>(i));

  CompleteCoreMIDIInitialization(Result::OK);
}

void MidiManagerMac::CompleteCoreMIDIInitialization(mojom::Result result) {
  service()->task_service()->PostBoundTask(
      kSessionTaskRunner,
      base::BindOnce(&MidiManagerMac::CompleteInitialization,
                     base::Unretained(this), result));
}

// static
void MidiManagerMac::ReceiveMidiNotifyDispatch(const MIDINotification* message,
                                               void* refcon) {
  // This callback function is invoked on |kClientTaskRunner|.
  // |manager| should be valid because we can ensure |midi_client_| is still
  // alive here.
  MidiManagerMac* manager = static_cast<MidiManagerMac*>(refcon);
  manager->ReceiveMidiNotify(message);
}

void MidiManagerMac::ReceiveMidiNotify(const MIDINotification* message) {
  DCHECK(service()->task_service()->IsOnTaskRunner(kClientTaskRunner));

  if (kMIDIMsgObjectAdded == message->messageID) {
    // New device is going to be attached.
    const MIDIObjectAddRemoveNotification* notification =
        reinterpret_cast<const MIDIObjectAddRemoveNotification*>(message);
    MIDIEndpointRef endpoint =
        static_cast<MIDIEndpointRef>(notification->child);
    if (notification->childType == kMIDIObjectType_Source) {
      // Attaching device is an input device.
      auto it = std::find(sources_.begin(), sources_.end(), endpoint);
      if (it == sources_.end()) {
        mojom::PortInfo info = GetPortInfoFromEndpoint(endpoint);
        // If the device disappears before finishing queries, mojom::PortInfo
        // becomes incomplete. Skip and do not cache such information here.
        // On kMIDIMsgObjectRemoved, the entry will be ignored because it
        // will not be found in the pool.
        if (!info.id.empty()) {
          sources_.push_back(endpoint);
          AddInputPort(info);
          MIDIPortConnectSource(midi_input_, endpoint,
                                reinterpret_cast<void*>(sources_.size() - 1));
        }
      } else {
        SetInputPortState(it - sources_.begin(), PortState::OPENED);
      }
    } else if (notification->childType == kMIDIObjectType_Destination) {
      // Attaching device is an output device.
      auto it = std::find(destinations_.begin(), destinations_.end(), endpoint);
      if (it == destinations_.end()) {
        mojom::PortInfo info = GetPortInfoFromEndpoint(endpoint);
        // Skip cases that queries are not finished correctly.
        if (!info.id.empty()) {
          destinations_.push_back(endpoint);
          AddOutputPort(info);
        }
      } else {
        SetOutputPortState(it - destinations_.begin(), PortState::OPENED);
      }
    }
  } else if (kMIDIMsgObjectRemoved == message->messageID) {
    // Existing device is going to be detached.
    const MIDIObjectAddRemoveNotification* notification =
        reinterpret_cast<const MIDIObjectAddRemoveNotification*>(message);
    MIDIEndpointRef endpoint =
        static_cast<MIDIEndpointRef>(notification->child);
    if (notification->childType == kMIDIObjectType_Source) {
      // Detaching device is an input device.
      auto it = std::find(sources_.begin(), sources_.end(), endpoint);
      if (it != sources_.end())
        SetInputPortState(it - sources_.begin(), PortState::DISCONNECTED);
    } else if (notification->childType == kMIDIObjectType_Destination) {
      // Detaching device is an output device.
      auto it = std::find(destinations_.begin(), destinations_.end(), endpoint);
      if (it != destinations_.end())
        SetOutputPortState(it - destinations_.begin(), PortState::DISCONNECTED);
    }
  }
}

// static
void MidiManagerMac::ReadMidiDispatch(const MIDIPacketList* packet_list,
                                      void* read_proc_refcon,
                                      void* src_conn_refcon) {
  // This method is called on a separate high-priority thread owned by CoreMIDI.
  // |manager| should be valid because we can ensure |midi_client_| is still
  // alive here.
  MidiManagerMac* manager = static_cast<MidiManagerMac*>(read_proc_refcon);
  DCHECK(manager);
  uint32_t port_index = reinterpret_cast<uintptr_t>(src_conn_refcon);

  // Go through each packet and process separately.
  const MIDIPacket* packet = &packet_list->packet[0];
  for (size_t i = 0u; i < packet_list->numPackets; i++) {
    // Each packet contains MIDI data for one or more messages (like note-on).
    base::TimeTicks timestamp = MIDITimeStampToTimeTicks(packet->timeStamp);

    manager->ReceiveMidiData(port_index, packet->data, packet->length,
                             timestamp);

    packet = MIDIPacketNext(packet);
  }
}

void MidiManagerMac::SendMidiData(MidiManagerClient* client,
                                  uint32_t port_index,
                                  const std::vector<uint8_t>& data,
                                  base::TimeTicks timestamp) {
  DCHECK(service()->task_service()->IsOnTaskRunner(kClientTaskRunner));

  // Lookup the destination based on the port index.
  if (static_cast<size_t>(port_index) >= destinations_.size())
    return;
  MIDITimeStamp coremidi_timestamp = TimeTicksToMIDITimeStamp(timestamp);
  MIDIEndpointRef destination = destinations_[port_index];

  size_t send_size;
  for (size_t sent_size = 0u; sent_size < data.size(); sent_size += send_size) {
    MIDIPacketList* packet_list =
        reinterpret_cast<MIDIPacketList*>(midi_buffer_.data());
    MIDIPacket* midi_packet = MIDIPacketListInit(packet_list);
    // Limit the maximum payload size to kEstimatedMaxPacketDataSize that is
    // half of midi_buffer data size. MIDIPacketList and MIDIPacket consume
    // extra buffer areas for meta information, and available size is smaller
    // than buffer size. Here, we simply assume that at least half size is
    // available for data payload.
    send_size = std::min(data.size() - sent_size, kEstimatedMaxPacketDataSize);
    midi_packet = MIDIPacketListAdd(
        packet_list,
        kCoreMIDIMaxPacketListSize,
        midi_packet,
        coremidi_timestamp,
        send_size,
        &data[sent_size]);
    DCHECK(midi_packet);

    MIDISend(midi_output_, destination, packet_list);
  }

  AccumulateMidiBytesSent(client, data.size());
}

}  // namespace midi
