summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authortoyoshim@chromium.org <toyoshim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-18 08:17:16 +0000
committertoyoshim@chromium.org <toyoshim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-18 08:17:16 +0000
commitb90727df54af9be1037095be8f046d93e6d922dc (patch)
treec8dc4088390042365a28b470a21b613292cfd352 /media
parenta572edfcbc9fe4a3d857de0aa87ce9230fdf3c49 (diff)
downloadchromium_src-b90727df54af9be1037095be8f046d93e6d922dc.zip
chromium_src-b90727df54af9be1037095be8f046d93e6d922dc.tar.gz
chromium_src-b90727df54af9be1037095be8f046d93e6d922dc.tar.bz2
Web MIDI: minimum support for Linux and Chrome OS
This change enables Web MIDI API on Linux and Chrome OS. Only Sending functionality works with this first experimental change. BUG=303601 Review URL: https://codereview.chromium.org/111443005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@241524 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/media.gyp2
-rw-r--r--media/midi/midi_manager.cc4
-rw-r--r--media/midi/midi_manager_linux.cc139
-rw-r--r--media/midi/midi_manager_linux.h39
4 files changed, 182 insertions, 2 deletions
diff --git a/media/media.gyp b/media/media.gyp
index fb844de..d70938d 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -407,6 +407,8 @@
'filters/wsola_internals.h',
'midi/midi_manager.cc',
'midi/midi_manager.h',
+ 'midi/midi_manager_linux.cc',
+ 'midi/midi_manager_linux.h',
'midi/midi_manager_mac.cc',
'midi/midi_manager_mac.h',
'midi/midi_message_queue.cc',
diff --git a/media/midi/midi_manager.cc b/media/midi/midi_manager.cc
index 6d3f1d3..5ef103f 100644
--- a/media/midi/midi_manager.cc
+++ b/media/midi/midi_manager.cc
@@ -9,8 +9,8 @@
namespace media {
-#if !defined(OS_MACOSX) && !defined(OS_WIN)
-// TODO(crogers): implement MIDIManager for other platforms.
+#if defined(OS_ANDROID) || defined(OS_IOS)
+// TODO(toyoshim): implement MIDIManager for other platforms.
MIDIManager* MIDIManager::Create() {
return NULL;
}
diff --git a/media/midi/midi_manager_linux.cc b/media/midi/midi_manager_linux.cc
new file mode 100644
index 0000000..712d53d
--- /dev/null
+++ b/media/midi/midi_manager_linux.cc
@@ -0,0 +1,139 @@
+// Copyright 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_linux.h"
+
+#include <fcntl.h>
+#include <sound/asound.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "base/bind.h"
+#include "base/debug/trace_event.h"
+#include "base/files/file.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string_util.h"
+#include "base/threading/thread.h"
+#include "media/midi/midi_port_info.h"
+
+namespace media {
+namespace {
+
+const char kDevSnd[] = "/dev/snd";
+const char kMIDIPattern[] = "midi*";
+const char kUnknown[] = "[unknown]";
+
+} // namespace
+
+class MIDIManagerLinux::MIDIDeviceInfo
+ : public base::RefCounted<MIDIDeviceInfo> {
+ public:
+ MIDIDeviceInfo(MIDIManagerLinux* manager, base::FilePath path)
+ : flags_(0) {
+ file_ = base::File(path,
+ base::File::FLAG_OPEN |
+ base::File::FLAG_READ |
+ base::File::FLAG_WRITE);
+ if (file_.error() != base::File::FILE_OK)
+ return;
+
+ struct snd_rawmidi_info info = {};
+ if (ioctl(file_.GetPlatformFile(), SNDRV_RAWMIDI_IOCTL_INFO, &info))
+ return;
+
+ flags_ = info.flags;
+ const char* name = reinterpret_cast<const char*>(&info.name[0]);
+ port_info_ = MIDIPortInfo(path.value(), kUnknown, name, kUnknown);
+ }
+
+ void Send(MIDIManagerClient* client, const std::vector<uint8>& data) {
+ if (!file_.IsValid())
+ return;
+ file_.WriteAtCurrentPos(reinterpret_cast<const char*>(&data[0]),
+ data.size());
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&MIDIManagerClient::AccumulateMIDIBytesSent,
+ base::Unretained(client), data.size()));
+ }
+
+ bool HasInputPort() const { return flags_ & SNDRV_RAWMIDI_INFO_INPUT; }
+ bool HasOutputPort() const { return flags_ & SNDRV_RAWMIDI_INFO_OUTPUT; }
+ const MIDIPortInfo& GetMIDIPortInfo() const { return port_info_; }
+
+ private:
+ friend class base::RefCounted<MIDIDeviceInfo>;
+ virtual ~MIDIDeviceInfo() {}
+
+ base::File file_;
+ int flags_;
+ MIDIPortInfo port_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(MIDIDeviceInfo);
+};
+
+MIDIManagerLinux::MIDIManagerLinux()
+ : send_thread_("MIDISendThread") {
+}
+
+bool MIDIManagerLinux::Initialize() {
+ TRACE_EVENT0("midi", "MIDIManagerMac::Initialize");
+
+ base::FilePath path(kDevSnd);
+ base::FileEnumerator enumerator(path, false, base::FileEnumerator::FILES,
+ FILE_PATH_LITERAL(kMIDIPattern));
+ for (base::FilePath name = enumerator.Next();
+ !name.empty();
+ name = enumerator.Next()) {
+ scoped_refptr<MIDIDeviceInfo> device = new MIDIDeviceInfo(this, name);
+ if (device->HasInputPort()) {
+ in_devices_.push_back(device);
+ AddInputPort(device->GetMIDIPortInfo());
+ }
+ if (device->HasOutputPort()) {
+ out_devices_.push_back(device);
+ AddOutputPort(device->GetMIDIPortInfo());
+ }
+ }
+ return true;
+}
+
+MIDIManagerLinux::~MIDIManagerLinux() {
+ send_thread_.Stop();
+}
+
+void MIDIManagerLinux::DispatchSendMIDIData(MIDIManagerClient* client,
+ uint32 port_index,
+ const std::vector<uint8>& data,
+ double timestamp) {
+ if (out_devices_.size() <= port_index)
+ return;
+
+ 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());
+ }
+
+ if (!send_thread_.IsRunning())
+ send_thread_.Start();
+
+ scoped_refptr<MIDIDeviceInfo> device = out_devices_[port_index];
+ send_thread_.message_loop()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&MIDIDeviceInfo::Send, device, client, data),
+ delay);
+}
+
+MIDIManager* MIDIManager::Create() {
+ return new MIDIManagerLinux();
+}
+
+} // namespace media
diff --git a/media/midi/midi_manager_linux.h b/media/midi/midi_manager_linux.h
new file mode 100644
index 0000000..f033f14
--- /dev/null
+++ b/media/midi/midi_manager_linux.h
@@ -0,0 +1,39 @@
+// Copyright 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_LINUX_H_
+#define MEDIA_MIDI_MIDI_MANAGER_LINUX_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread.h"
+#include "media/midi/midi_manager.h"
+
+namespace media {
+
+class MIDIManagerLinux : public MIDIManager {
+ public:
+ MIDIManagerLinux();
+ virtual ~MIDIManagerLinux();
+
+ // MIDIManager implementation.
+ virtual bool Initialize() OVERRIDE;
+ virtual void DispatchSendMIDIData(MIDIManagerClient* client,
+ uint32 port_index,
+ const std::vector<uint8>& data,
+ double timestamp) OVERRIDE;
+
+ private:
+ class MIDIDeviceInfo;
+ std::vector<scoped_refptr<MIDIDeviceInfo> > in_devices_;
+ std::vector<scoped_refptr<MIDIDeviceInfo> > out_devices_;
+ base::Thread send_thread_;
+ DISALLOW_COPY_AND_ASSIGN(MIDIManagerLinux);
+};
+
+} // namespace media
+
+#endif // MEDIA_MIDI_MIDI_MANAGER_LINUX_H_