summaryrefslogtreecommitdiffstats
path: root/media/midi
diff options
context:
space:
mode:
authorcrogers@google.com <crogers@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-22 02:08:15 +0000
committercrogers@google.com <crogers@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-22 02:08:15 +0000
commit5f6f9bce342075bea590cb69914d97eb3bdde29a (patch)
treea10c77431a369a15188a0e9fd3a89adc1ff0dbc8 /media/midi
parent68db1854c53776b1c97f6da4ad5d95d8803371ae (diff)
downloadchromium_src-5f6f9bce342075bea590cb69914d97eb3bdde29a.zip
chromium_src-5f6f9bce342075bea590cb69914d97eb3bdde29a.tar.gz
chromium_src-5f6f9bce342075bea590cb69914d97eb3bdde29a.tar.bz2
don't include iostream.h
use ChildThread for main loop - fix Android build whitespace fix minor style fix last minute compile fixes address Antoine's comments minor changes to reflect latest Blink API -- address palmer comments last minute include order fix address last minute style nits stub out other OSes support Takashi's MIDIAccessor fix minor build err undo param traits changes get rid of param_traits - other minor style nits address scherkus comments use int64 for ParamTraits WIP fix white-space issues more style basically working some cleanup -- support for multiple clients forgot midi_manager.cc Get MIDI port information sent to renderer formatting fixes lots of cleanup - added RequestAccess and Send style more style only bother sending received messages to renderer if approval was asked early steps to granting permission to Blink some progress to sending port info to Blink send client_id when requesting access fix minor style issues in .gyp files fix context/browser DEPS fix include paths git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207992 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/midi')
-rw-r--r--media/midi/midi_manager.cc67
-rw-r--r--media/midi/midi_manager.h109
-rw-r--r--media/midi/midi_manager_mac.cc205
-rw-r--r--media/midi/midi_manager_mac.h69
-rw-r--r--media/midi/midi_port_info.cc28
-rw-r--r--media/midi/midi_port_info.h36
6 files changed, 514 insertions, 0 deletions
diff --git a/media/midi/midi_manager.cc b/media/midi/midi_manager.cc
new file mode 100644
index 0000000..f991865
--- /dev/null
+++ b/media/midi/midi_manager.cc
@@ -0,0 +1,67 @@
+// 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.h"
+
+namespace media {
+
+#if !defined(OS_MACOSX)
+// TODO(crogers): implement MIDIManager for other platforms.
+MIDIManager* MIDIManager::Create() {
+ return NULL;
+}
+#endif
+
+MIDIManager::MIDIManager()
+ : initialized_(false) {
+}
+
+MIDIManager::~MIDIManager() {}
+
+bool MIDIManager::RequestAccess(MIDIManagerClient* client, int access) {
+ // TODO(crogers): determine if user prompt is necessary here.
+ // For now, simply don't allow sysex.
+ if (access != kNoSystemExclusive)
+ return false;
+
+ // Lazily initialize the MIDI back-end.
+ if (!initialized_)
+ initialized_ = Initialize();
+
+ if (initialized_) {
+ base::AutoLock auto_lock(clients_lock_);
+ clients_.insert(client);
+ }
+
+ return initialized_;
+}
+
+void MIDIManager::ReleaseAccess(MIDIManagerClient* client) {
+ base::AutoLock auto_lock(clients_lock_);
+ ClientList::iterator i = clients_.find(client);
+ if (i != clients_.end())
+ clients_.erase(i);
+}
+
+void MIDIManager::AddInputPort(const MIDIPortInfo& info) {
+ input_ports_.push_back(info);
+}
+
+void MIDIManager::AddOutputPort(const MIDIPortInfo& info) {
+ output_ports_.push_back(info);
+}
+
+void MIDIManager::ReceiveMIDIData(
+ int port_index,
+ const uint8* data,
+ size_t length,
+ double timestamp) {
+ base::AutoLock auto_lock(clients_lock_);
+
+ // TODO(crogers): Filter out sysex.
+ for (ClientList::iterator i = clients_.begin(); i != clients_.end(); ++i)
+ (*i)->ReceiveMIDIData(port_index, data, length, timestamp);
+};
+
+} // namespace media
diff --git a/media/midi/midi_manager.h b/media/midi/midi_manager.h
new file mode 100644
index 0000000..1df444f
--- /dev/null
+++ b/media/midi/midi_manager.h
@@ -0,0 +1,109 @@
+// 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.
+
+#ifndef MEDIA_MIDI_MIDI_MANAGER_H_
+#define MEDIA_MIDI_MIDI_MANAGER_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/synchronization/lock.h"
+#include "media/base/media_export.h"
+#include "media/midi/midi_port_info.h"
+
+namespace media {
+
+// A MIDIManagerClient registers with the MIDIManager to receive MIDI data.
+// See MIDIManager::RequestAccess() and MIDIManager::ReleaseAccess()
+// for details.
+class MEDIA_EXPORT MIDIManagerClient {
+ public:
+ virtual ~MIDIManagerClient() {}
+
+ // ReceiveMIDIData() is called when MIDI data has been received from the
+ // MIDI system.
+ // |port_index| represents the specific input port from input_ports().
+ // |data| represents a series of bytes encoding one or more MIDI messages.
+ // |length| is the number of bytes in |data|.
+ // |timestamp| is the time the data was received, in seconds.
+ virtual void ReceiveMIDIData(int port_index,
+ const uint8* data,
+ size_t length,
+ double timestamp) = 0;
+};
+
+// Manages access to all MIDI hardware.
+class MEDIA_EXPORT MIDIManager {
+ public:
+ enum AccessType {
+ kNoSystemExclusive,
+ kSystemExclusive
+ };
+
+ static MIDIManager* Create();
+
+ MIDIManager();
+ virtual ~MIDIManager();
+
+ // A client calls RequestAccess() to receive and send MIDI data.
+ // If access is approved, the MIDI system is lazily initialized
+ // and the client is registered to receive MIDI data.
+ // Returns |true| if access is approved.
+ bool RequestAccess(MIDIManagerClient* client, int access);
+
+ // A client calls ReleaseAccess() to stop receiving MIDI data.
+ void ReleaseAccess(MIDIManagerClient* client);
+
+ // SendMIDIData() sends one or more messages at the given time.
+ // |port_index| represents the specific output port from output_ports().
+ // |data| represents a series of bytes encoding one or more MIDI messages.
+ // |length| is the number of bytes in |data|.
+ // |timestamp| is the time to send the data, in seconds.
+ virtual void SendMIDIData(int port_index,
+ const uint8* data,
+ size_t length,
+ double timestamp) = 0;
+
+ // input_ports() is a list of MIDI ports for receiving MIDI data.
+ // Each individual port in this list can be identified by its
+ // integer index into this list.
+ const MIDIPortInfoList& input_ports() { return input_ports_; }
+
+ // output_ports() is a list of MIDI ports for sending MIDI data.
+ // Each individual port in this list can be identified by its
+ // integer index into this list.
+ const MIDIPortInfoList& output_ports() { return output_ports_; }
+
+ protected:
+ // Initializes the MIDI system, returning |true| on success.
+ virtual bool Initialize() = 0;
+
+ void AddInputPort(const MIDIPortInfo& info);
+ void AddOutputPort(const MIDIPortInfo& info);
+
+ // Dispatches to all clients.
+ void ReceiveMIDIData(
+ int port_index,
+ const uint8* data,
+ size_t length,
+ double timestamp);
+
+ bool initialized_;
+
+ // Keeps track of all clients who wish to receive MIDI data.
+ typedef std::set<MIDIManagerClient*> ClientList;
+ ClientList clients_;
+
+ // Protects access to our clients.
+ base::Lock clients_lock_;
+
+ MIDIPortInfoList input_ports_;
+ MIDIPortInfoList output_ports_;
+
+ DISALLOW_COPY_AND_ASSIGN(MIDIManager);
+};
+
+} // namespace media
+
+#endif // MEDIA_MIDI_MIDI_MANAGER_H_
diff --git a/media/midi/midi_manager_mac.cc b/media/midi/midi_manager_mac.cc
new file mode 100644
index 0000000..73df1fe
--- /dev/null
+++ b/media/midi/midi_manager_mac.cc
@@ -0,0 +1,205 @@
+// 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 <iostream>
+#include <string>
+
+#include "base/debug/trace_event.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/sys_string_conversions.h"
+#include <CoreAudio/HostTime.h>
+
+using base::IntToString;
+using base::SysCFStringRefToUTF8;
+using std::string;
+
+namespace media {
+
+MIDIManager* MIDIManager::Create() {
+ return new MIDIManagerMac();
+}
+
+MIDIManagerMac::MIDIManagerMac()
+ : midi_client_(NULL),
+ coremidi_input_(NULL),
+ coremidi_output_(NULL),
+ packet_list_(NULL),
+ midi_packet_(NULL) {
+}
+
+bool MIDIManagerMac::Initialize() {
+ TRACE_EVENT0("midi", "MIDIManagerMac::Initialize");
+
+ // CoreMIDI registration.
+ midi_client_ = NULL;
+ OSStatus result = MIDIClientCreate(
+ CFSTR("Google Chrome"),
+ NULL,
+ NULL,
+ &midi_client_);
+
+ if (result != noErr)
+ return false;
+
+ coremidi_input_ = NULL;
+
+ // Create input and output port.
+ result = MIDIInputPortCreate(
+ midi_client_,
+ CFSTR("MIDI Input"),
+ ReadMidiDispatch,
+ this,
+ &coremidi_input_);
+ if (result != noErr)
+ return false;
+
+ result = MIDIOutputPortCreate(
+ midi_client_,
+ CFSTR("MIDI Output"),
+ &coremidi_output_);
+ if (result != noErr)
+ return false;
+
+ int destination_count = MIDIGetNumberOfDestinations();
+ destinations_.reserve(destination_count);
+
+ for (int i = 0; i < destination_count ; i++) {
+ MIDIEndpointRef destination = MIDIGetDestination(i);
+
+ // Keep track of all destinations (known as outputs by the Web MIDI API).
+ // Cache to avoid any possible overhead in calling MIDIGetDestination().
+ destinations_[i] = destination;
+
+ MIDIPortInfo info = GetPortInfoFromEndpoint(destination);
+ AddOutputPort(info);
+ }
+
+ // Open connections from all sources.
+ int source_count = MIDIGetNumberOfSources();
+
+ for (int i = 0; i < source_count; ++i) {
+ // Receive from all sources.
+ MIDIEndpointRef src = MIDIGetSource(i);
+ MIDIPortConnectSource(coremidi_input_, src, src);
+
+ // Keep track of all sources (known as inputs in Web MIDI API terminology).
+ source_map_[src] = i;
+
+ MIDIPortInfo info = GetPortInfoFromEndpoint(src);
+ AddInputPort(info);
+ }
+
+ // TODO(crogers): Fix the memory management here!
+ packet_list_ = reinterpret_cast<MIDIPacketList*>(midi_buffer_);
+ midi_packet_ = MIDIPacketListInit(packet_list_);
+
+ return true;
+}
+
+MIDIManagerMac::~MIDIManagerMac() {
+ if (coremidi_input_)
+ MIDIPortDispose(coremidi_input_);
+ if (coremidi_output_)
+ MIDIPortDispose(coremidi_output_);
+}
+
+void MIDIManagerMac::ReadMidiDispatch(const MIDIPacketList* packet_list,
+ void* read_proc_refcon,
+ void* src_conn_refcon) {
+ MIDIManagerMac* manager = static_cast<MIDIManagerMac*>(read_proc_refcon);
+ MIDIEndpointRef source = static_cast<MIDIEndpointRef>(src_conn_refcon);
+
+ // Dispatch to class method.
+ manager->ReadMidi(source, packet_list);
+}
+
+void MIDIManagerMac::ReadMidi(MIDIEndpointRef source,
+ const MIDIPacketList* packet_list) {
+ // Lookup the port index based on the source.
+ SourceMap::iterator j = source_map_.find(source);
+ if (j == source_map_.end())
+ return;
+ int port_index = source_map_[source];
+
+ // Go through each packet and process separately.
+ for(size_t i = 0; i < packet_list->numPackets; i++) {
+ // Each packet contains MIDI data for one or more messages (like note-on).
+ const MIDIPacket &packet = packet_list->packet[i];
+ double timestamp_seconds = MIDITimeStampToSeconds(packet.timeStamp);
+
+ ReceiveMIDIData(
+ port_index,
+ packet.data,
+ packet.length,
+ timestamp_seconds);
+ }
+}
+
+void MIDIManagerMac::SendMIDIData(int port_index,
+ const uint8* data,
+ size_t length,
+ double timestamp) {
+ // TODO(crogers): Filter out sysex.
+
+ MIDITimeStamp coremidi_timestamp = SecondsToMIDITimeStamp(timestamp);
+
+ midi_packet_ = MIDIPacketListAdd(
+ packet_list_,
+ kMaxPacketListSize,
+ midi_packet_,
+ coremidi_timestamp,
+ length,
+ data);
+
+ // Lookup the destination based on the port index.
+ // TODO(crogers): re-factor |port_index| to use unsigned
+ // to avoid the need for this check.
+ if (port_index < 0 ||
+ static_cast<size_t>(port_index) >= destinations_.size())
+ return;
+
+ MIDIEndpointRef destination = destinations_[port_index];
+
+ MIDISend(coremidi_output_, destination, packet_list_);
+
+ // Re-initialize for next time.
+ midi_packet_ = MIDIPacketListInit(packet_list_);
+}
+
+MIDIPortInfo MIDIManagerMac::GetPortInfoFromEndpoint(
+ MIDIEndpointRef endpoint) {
+ SInt32 id_number = 0;
+ MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyUniqueID, &id_number);
+ string id = IntToString(id_number);
+
+ CFStringRef manufacturer_ref = NULL;
+ MIDIObjectGetStringProperty(
+ endpoint, kMIDIPropertyManufacturer, &manufacturer_ref);
+ string manufacturer = SysCFStringRefToUTF8(manufacturer_ref);
+
+ CFStringRef name_ref = NULL;
+ MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &name_ref);
+ string name = SysCFStringRefToUTF8(name_ref);
+
+ SInt32 version_number = 0;
+ MIDIObjectGetIntegerProperty(
+ endpoint, kMIDIPropertyDriverVersion, &version_number);
+ string version = IntToString(version_number);
+
+ return MIDIPortInfo(id, manufacturer, name, version);
+}
+
+double MIDIManagerMac::MIDITimeStampToSeconds(MIDITimeStamp timestamp) {
+ UInt64 nanoseconds = AudioConvertHostTimeToNanos(timestamp);
+ return static_cast<double>(nanoseconds) / 1.0e9;
+}
+
+MIDITimeStamp MIDIManagerMac::SecondsToMIDITimeStamp(double seconds) {
+ UInt64 nanos = UInt64(seconds * 1.0e9);
+ return AudioConvertNanosToHostTime(nanos);
+}
+
+} // namespace media
diff --git a/media/midi/midi_manager_mac.h b/media/midi/midi_manager_mac.h
new file mode 100644
index 0000000..f513e11
--- /dev/null
+++ b/media/midi/midi_manager_mac.h
@@ -0,0 +1,69 @@
+// 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.
+
+#ifndef MEDIA_MIDI_MIDI_MANAGER_MAC_H_
+#define MEDIA_MIDI_MIDI_MANAGER_MAC_H_
+
+#include <CoreMIDI/MIDIServices.h>
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "media/midi/midi_manager.h"
+#include "media/midi/midi_port_info.h"
+
+namespace media {
+
+class MEDIA_EXPORT MIDIManagerMac : public MIDIManager {
+ public:
+ MIDIManagerMac();
+ virtual ~MIDIManagerMac();
+
+ // MIDIManager implementation.
+ virtual bool Initialize() OVERRIDE;
+ virtual void SendMIDIData(int port_index,
+ const uint8* data,
+ size_t length,
+ double timestamp) OVERRIDE;
+
+ private:
+ // CoreMIDI callback for MIDI data.
+ // Each callback can contain multiple packets, each of which can contain
+ // multiple MIDI messages.
+ static void ReadMidiDispatch(
+ const MIDIPacketList *pktlist,
+ void *read_proc_refcon,
+ void *src_conn_refcon);
+ virtual void ReadMidi(MIDIEndpointRef source, const MIDIPacketList *pktlist);
+
+ // Helper
+ static media::MIDIPortInfo GetPortInfoFromEndpoint(MIDIEndpointRef endpoint);
+ static double MIDITimeStampToSeconds(MIDITimeStamp timestamp);
+ static MIDITimeStamp SecondsToMIDITimeStamp(double seconds);
+
+ // CoreMIDI
+ MIDIClientRef midi_client_;
+ MIDIPortRef coremidi_input_;
+ MIDIPortRef coremidi_output_;
+
+ enum{ kMaxPacketListSize = 512 };
+ char midi_buffer_[kMaxPacketListSize];
+ MIDIPacketList* packet_list_;
+ MIDIPacket* midi_packet_;
+
+ typedef std::map<MIDIEndpointRef, int> SourceMap;
+
+ // Keeps track of the index (0-based) for each of our sources.
+ SourceMap source_map_;
+
+ // Keeps track of all destinations.
+ std::vector<MIDIEndpointRef> destinations_;
+
+ DISALLOW_COPY_AND_ASSIGN(MIDIManagerMac);
+};
+
+} // namespace media
+
+#endif // MEDIA_MIDI_MIDI_MANAGER_MAC_H_
diff --git a/media/midi/midi_port_info.cc b/media/midi/midi_port_info.cc
new file mode 100644
index 0000000..3be7007
--- /dev/null
+++ b/media/midi/midi_port_info.cc
@@ -0,0 +1,28 @@
+// 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_port_info.h"
+
+namespace media {
+
+MIDIPortInfo::MIDIPortInfo() {}
+
+MIDIPortInfo::MIDIPortInfo(const std::string& in_id,
+ const std::string& in_manufacturer,
+ const std::string& in_name,
+ const std::string& in_version)
+ : id(in_id),
+ manufacturer(in_manufacturer),
+ name(in_name),
+ version(in_version) {}
+
+MIDIPortInfo::~MIDIPortInfo() {}
+
+MIDIPortInfo::MIDIPortInfo(const MIDIPortInfo& info)
+ : id(info.id),
+ manufacturer(info.manufacturer),
+ name(info.name),
+ version(info.version) {}
+
+} // namespace media
diff --git a/media/midi/midi_port_info.h b/media/midi/midi_port_info.h
new file mode 100644
index 0000000..f4afb49
--- /dev/null
+++ b/media/midi/midi_port_info.h
@@ -0,0 +1,36 @@
+// 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.
+
+#ifndef MEDIA_MIDI_MIDI_PORT_INFO_H_
+#define MEDIA_MIDI_MIDI_PORT_INFO_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "media/base/media_export.h"
+
+namespace media {
+
+struct MEDIA_EXPORT MIDIPortInfo {
+ MIDIPortInfo();
+ MIDIPortInfo(const std::string& in_id,
+ const std::string& in_manufacturer,
+ const std::string& in_name,
+ const std::string& in_version);
+
+ MIDIPortInfo(const MIDIPortInfo& info);
+ ~MIDIPortInfo();
+
+ std::string id;
+ std::string manufacturer;
+ std::string name;
+ std::string version;
+};
+
+typedef std::vector<MIDIPortInfo> MIDIPortInfoList;
+
+} // namespace media
+
+#endif // MEDIA_MIDI_MIDI_PORT_INFO_H_