Commit 5f6f9bce authored by crogers@google.com's avatar crogers@google.com

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
parent 68db1854
......@@ -5,6 +5,7 @@ include_rules = [
"+content/child/webkitplatformsupport_impl.h", # For in-process webkit
"+media/audio", # For audio input for speech input feature.
"+media/base", # For Android JNI registration.
"+media/midi", # For Web MIDI API
"+sql",
"+ui/webui",
"+win8/util",
......
......@@ -47,6 +47,7 @@
#include "crypto/nss_util.h"
#include "media/audio/audio_manager.h"
#include "media/base/media.h"
#include "media/midi/midi_manager.h"
#include "net/base/network_change_notifier.h"
#include "net/socket/client_socket_factory.h"
#include "net/ssl/ssl_config_service.h"
......@@ -400,7 +401,10 @@ void BrowserMainLoop::MainMessageLoopStart() {
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:AudioMan")
audio_manager_.reset(media::AudioManager::Create());
}
{
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:MIDIManager")
midi_manager_.reset(media::MIDIManager::Create());
}
#if !defined(OS_IOS)
{
......
......@@ -20,6 +20,7 @@ class SystemMonitor;
namespace media {
class AudioManager;
class MIDIManager;
}
namespace net {
......@@ -81,6 +82,7 @@ class BrowserMainLoop {
MediaStreamManager* media_stream_manager() const {
return media_stream_manager_.get();
}
media::MIDIManager* midi_manager() const { return midi_manager_.get(); }
private:
class MemoryObserver;
......@@ -106,6 +108,7 @@ class BrowserMainLoop {
scoped_ptr<HighResolutionTimerManager> hi_res_timer_manager_;
scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
scoped_ptr<media::AudioManager> audio_manager_;
scoped_ptr<media::MIDIManager> midi_manager_;
scoped_ptr<AudioMirroringManager> audio_mirroring_manager_;
scoped_ptr<MediaStreamManager> media_stream_manager_;
// Per-process listener for online state changes.
......
// 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 "content/browser/renderer_host/media/midi_host.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/debug/trace_event.h"
#include "base/process.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/media/media_internals.h"
#include "content/common/media/midi_messages.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/media_observer.h"
#include "media/midi/midi_manager.h"
using media::MIDIManager;
using media::MIDIPortInfoList;
namespace content {
MIDIHost::MIDIHost(media::MIDIManager* midi_manager)
: midi_manager_(midi_manager) {
}
MIDIHost::~MIDIHost() {
if (midi_manager_)
midi_manager_->ReleaseAccess(this);
}
void MIDIHost::OnChannelClosing() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserMessageFilter::OnChannelClosing();
}
void MIDIHost::OnDestruct() const {
BrowserThread::DeleteOnIOThread::Destruct(this);
}
///////////////////////////////////////////////////////////////////////////////
// IPC Messages handler
bool MIDIHost::OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP_EX(MIDIHost, message, *message_was_ok)
IPC_MESSAGE_HANDLER(MIDIHostMsg_RequestAccess, OnRequestAccess)
IPC_MESSAGE_HANDLER(MIDIHostMsg_SendData, OnSendData)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
return handled;
}
void MIDIHost::OnRequestAccess(int client_id, int access) {
MIDIPortInfoList input_ports;
MIDIPortInfoList output_ports;
// Ask permission and register to receive MIDI data.
bool approved = false;
if (midi_manager_) {
approved = midi_manager_->RequestAccess(this, access);
if (approved) {
input_ports = midi_manager_->input_ports();
output_ports = midi_manager_->output_ports();
}
}
Send(new MIDIMsg_AccessApproved(
client_id,
access,
approved,
input_ports,
output_ports));
}
void MIDIHost::OnSendData(int port,
const std::vector<uint8>& data,
double timestamp) {
// TODO(crogers): we need to post this to a dedicated thread for
// sending MIDI. For now, we will not implement the sending of MIDI data.
NOTIMPLEMENTED();
// if (midi_manager_)
// midi_manager_->SendMIDIData(port, data.data(), data.size(), timestamp);
}
void MIDIHost::ReceiveMIDIData(
int port_index,
const uint8* data,
size_t length,
double timestamp) {
TRACE_EVENT0("midi", "MIDIHost::ReceiveMIDIData");
// Send to the renderer.
std::vector<uint8> v(data, data + length);
Send(new MIDIMsg_DataReceived(port_index, v, timestamp));
}
} // namespace content
// 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 CONTENT_BROWSER_RENDERER_HOST_MEDIA_MIDI_HOST_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MIDI_HOST_H_
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
#include "media/midi/midi_manager.h"
namespace media {
class MIDIManager;
}
namespace content {
class CONTENT_EXPORT MIDIHost
: public BrowserMessageFilter,
public media::MIDIManagerClient {
public:
// Called from UI thread from the owner of this object.
MIDIHost(media::MIDIManager* midi_manager);
// BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE;
virtual void OnDestruct() const OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) OVERRIDE;
// MIDIManagerClient implementation.
virtual void ReceiveMIDIData(
int port_index,
const uint8* data,
size_t length,
double timestamp) OVERRIDE;
// Request access to MIDI hardware.
void OnRequestAccess(int client_id, int access);
// Data to be sent to a MIDI output port.
void OnSendData(int port,
const std::vector<uint8>& data,
double timestamp);
private:
friend class base::DeleteHelper<MIDIHost>;
friend class BrowserThread;
virtual ~MIDIHost();
media::MIDIManager* const midi_manager_;
DISALLOW_COPY_AND_ASSIGN(MIDIHost);
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MIDI_HOST_H_
......@@ -73,6 +73,7 @@
#include "content/browser/renderer_host/media/audio_mirroring_manager.h"
#include "content/browser/renderer_host/media/audio_renderer_host.h"
#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
#include "content/browser/renderer_host/media/midi_host.h"
#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
#include "content/browser/renderer_host/media/video_capture_host.h"
#include "content/browser/renderer_host/memory_benchmark_message_filter.h"
......@@ -604,6 +605,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
GetID(), audio_manager,
BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
media_internals, media_stream_manager));
channel_->AddFilter(
new MIDIHost(BrowserMainLoop::GetInstance()->midi_manager()));
channel_->AddFilter(new VideoCaptureHost(media_stream_manager));
channel_->AddFilter(new AppCacheDispatcherHost(
storage_partition_impl_->GetAppCacheService(),
......
......@@ -31,6 +31,7 @@
#include "content/common/input_messages.h"
#include "content/common/java_bridge_messages.h"
#include "content/common/media/audio_messages.h"
#include "content/common/media/midi_messages.h"
#if defined(OS_ANDROID)
#include "content/common/media/media_player_messages_android.h"
#endif
......
// 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.
// IPC messages for access to MIDI hardware.
// Multiply-included message file, hence no include guard.
#include "base/basictypes.h"
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
#include "media/midi/midi_port_info.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START MIDIMsgStart
IPC_STRUCT_TRAITS_BEGIN(media::MIDIPortInfo)
IPC_STRUCT_TRAITS_MEMBER(id)
IPC_STRUCT_TRAITS_MEMBER(manufacturer)
IPC_STRUCT_TRAITS_MEMBER(name)
IPC_STRUCT_TRAITS_MEMBER(version)
IPC_STRUCT_TRAITS_END()
// Renderer request to browser for access to MIDI services.
IPC_MESSAGE_CONTROL2(MIDIHostMsg_RequestAccess,
int /* client id */,
int /* access */)
IPC_MESSAGE_CONTROL3(MIDIHostMsg_SendData,
int /* port */,
std::vector<uint8> /* data */,
double /* timestamp */)
// Messages sent from the browser to the renderer.
IPC_MESSAGE_CONTROL5(MIDIMsg_AccessApproved,
int /* client id */,
int /* access */,
bool /* success */,
media::MIDIPortInfoList /* input ports */,
media::MIDIPortInfoList /* output ports */)
IPC_MESSAGE_CONTROL3(MIDIMsg_DataReceived,
int /* port */,
std::vector<uint8> /* data */,
double /* timestamp */)
......@@ -791,6 +791,8 @@
'browser/renderer_host/media/media_stream_requester.h',
'browser/renderer_host/media/media_stream_ui_proxy.cc',
'browser/renderer_host/media/media_stream_ui_proxy.h',
'browser/renderer_host/media/midi_host.cc',
'browser/renderer_host/media/midi_host.h',
'browser/renderer_host/media/video_capture_buffer_pool.cc',
'browser/renderer_host/media/video_capture_buffer_pool.h',
'browser/renderer_host/media/video_capture_controller.cc',
......
......@@ -265,6 +265,7 @@
'common/media/media_stream_messages.h',
'common/media/media_stream_options.cc',
'common/media/media_stream_options.h',
'common/media/midi_messages.h',
'common/media/video_capture.h',
'common/media/video_capture_messages.h',
'common/memory_benchmark_messages.h',
......
......@@ -156,6 +156,8 @@
'renderer/media/media_stream_dispatcher.h',
'renderer/media/media_stream_dispatcher_eventhandler.h',
'renderer/media/media_stream_impl.h',
'renderer/media/midi_message_filter.cc',
'renderer/media/midi_message_filter.h',
'renderer/media/pepper_platform_video_decoder_impl.cc',
'renderer/media/pepper_platform_video_decoder_impl.h',
'renderer/media/render_media_log.cc',
......@@ -164,6 +166,8 @@
'renderer/media/renderer_gpu_video_decoder_factories.h',
'renderer/media/renderer_webaudiodevice_impl.cc',
'renderer/media/renderer_webaudiodevice_impl.h',
'renderer/media/renderer_webmidiaccessor_impl.cc',
'renderer/media/renderer_webmidiaccessor_impl.h',
'renderer/media/rtc_video_renderer.cc',
'renderer/media/rtc_video_renderer.h',
'renderer/media/stream_texture_factory_impl_android.cc',
......
// 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 "content/renderer/media/midi_message_filter.h"
#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/media/midi_messages.h"
#include "content/renderer/render_thread_impl.h"
#include "ipc/ipc_logging.h"
using media::MIDIPortInfoList;
using base::AutoLock;
namespace content {
MIDIMessageFilter::MIDIMessageFilter(
const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
: channel_(NULL),
io_message_loop_(io_message_loop),
next_available_id_(0) {
}
MIDIMessageFilter::~MIDIMessageFilter() {}
void MIDIMessageFilter::Send(IPC::Message* message) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
if (!channel_) {
delete message;
} else {
channel_->Send(message);
}
}
bool MIDIMessageFilter::OnMessageReceived(const IPC::Message& message) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MIDIMessageFilter, message)
IPC_MESSAGE_HANDLER(MIDIMsg_AccessApproved, OnAccessApproved)
IPC_MESSAGE_HANDLER(MIDIMsg_DataReceived, OnDataReceived)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void MIDIMessageFilter::OnFilterAdded(IPC::Channel* channel) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
channel_ = channel;
}
void MIDIMessageFilter::OnFilterRemoved() {
DCHECK(io_message_loop_->BelongsToCurrentThread());
// Once removed, a filter will not be used again. At this time all
// delegates must be notified so they release their reference.
OnChannelClosing();
}
void MIDIMessageFilter::OnChannelClosing() {
DCHECK(io_message_loop_->BelongsToCurrentThread());
channel_ = NULL;
}
void MIDIMessageFilter::RequestAccess(
WebKit::WebMIDIAccessorClient* client, int access) {
// Generate and keep track of a "client id" which is sent to the browser
// to ask permission to talk to MIDI hardware.
// This id is handed back when we receive the answer in OnAccessApproved().
if (clients_.find(client) == clients_.end()) {
int client_id = next_available_id_++;
clients_[client] = client_id;
io_message_loop_->PostTask(FROM_HERE,
base::Bind(&MIDIMessageFilter::RequestAccessOnIOThread, this,
client_id, access));
}
}
void MIDIMessageFilter::RequestAccessOnIOThread(int client_id, int access) {
Send(new MIDIHostMsg_RequestAccess(client_id, access));
}
void MIDIMessageFilter::RemoveClient(WebKit::WebMIDIAccessorClient* client) {
ClientsMap::iterator i = clients_.find(client);
if (i != clients_.end())
clients_.erase(i);
}
// Received from browser.
void MIDIMessageFilter::OnAccessApproved(
int client_id,
int access,
bool success,
MIDIPortInfoList inputs,
MIDIPortInfoList outputs) {
// Handle on the main JS thread.
ChildThread::current()->message_loop()->PostTask(FROM_HERE,
base::Bind(&MIDIMessageFilter::HandleAccessApproved, this,
client_id, access, success, inputs, outputs));
}
void MIDIMessageFilter::HandleAccessApproved(
int client_id,
int access,
bool success,
MIDIPortInfoList inputs,
MIDIPortInfoList outputs) {
WebKit::WebMIDIAccessorClient* client = GetClientFromId(client_id);
if (!client)
return;
if (success) {
// Add the client's input and output ports.
for (size_t i = 0; i < inputs.size(); ++i) {
client->didAddInputPort(
UTF8ToUTF16(inputs[i].id),
UTF8ToUTF16(inputs[i].manufacturer),
UTF8ToUTF16(inputs[i].name),
UTF8ToUTF16(inputs[i].version));
}
for (size_t i = 0; i < outputs.size(); ++i) {
client->didAddOutputPort(
UTF8ToUTF16(outputs[i].id),
UTF8ToUTF16(outputs[i].manufacturer),
UTF8ToUTF16(outputs[i].name),
UTF8ToUTF16(outputs[i].version));
}
}
if (success)
client->didAllowAccess();
else
client->didBlockAccess();
}
WebKit::WebMIDIAccessorClient*
MIDIMessageFilter::GetClientFromId(int client_id) {
// Iterating like this seems inefficient, but in practice there generally
// will be very few clients (usually one). Additionally, this lookup
// usually happens one time during page load. So the performance hit is
// negligible.
for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i) {
if ((*i).second == client_id)
return (*i).first;
}
return NULL;
}
void MIDIMessageFilter::OnDataReceived(int port,
const std::vector<uint8>& data,
double timestamp) {
TRACE_EVENT0("midi", "MIDIMessageFilter::OnDataReceived");
ChildThread::current()->message_loop()->PostTask(FROM_HERE,
base::Bind(&MIDIMessageFilter::HandleDataReceived, this,
port, data, timestamp));
}
void MIDIMessageFilter::HandleDataReceived(int port,
const std::vector<uint8>& data,
double timestamp) {
TRACE_EVENT0("midi", "MIDIMessageFilter::HandleDataReceived");
#if defined(OS_ANDROID)
// TODO(crogers): figure out why data() method does not compile on Android.
NOTIMPLEMENTED();
#else
for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i)
(*i).first->didReceiveMIDIData(port, data.data(), data.size(), timestamp);
#endif
}
void MIDIMessageFilter::SendMIDIData(int port,
const uint8* data,
size_t length,
double timestamp) {
// TODO(crogers): we need more work to check the amount of data sent,
// throttle if necessary, and filter out the SYSEX messages if not
// approved. For now, we will not implement the sending of MIDI data.
NOTIMPLEMENTED();
// std::vector<uint8> v(data, data + length);
// io_message_loop_->PostTask(FROM_HERE,
// base::Bind(&MIDIMessageFilter::SendMIDIDataOnIOThread, this,
// port, v, timestamp));
}
void MIDIMessageFilter::SendMIDIDataOnIOThread(int port,
const std::vector<uint8>& data,
double timestamp) {
// Send to the browser.
Send(new MIDIHostMsg_SendData(port, data, timestamp));
}
} // namespace content
// 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 CONTENT_RENDERER_MEDIA_MIDI_MESSAGE_FILTER_H_
#define CONTENT_RENDERER_MEDIA_MIDI_MESSAGE_FILTER_H_
#include <map>
#include <vector>
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "ipc/ipc_channel_proxy.h"
#include "media/midi/midi_port_info.h"
#include "third_party/WebKit/public/platform/WebMIDIAccessor.h"
#include "third_party/WebKit/public/platform/WebMIDIAccessorClient.h"
namespace base {
class MessageLoopProxy;
}
namespace content {
// MessageFilter that handles MIDI messages.
class CONTENT_EXPORT MIDIMessageFilter
: public IPC::ChannelProxy::MessageFilter {
public:
explicit MIDIMessageFilter(
const scoped_refptr<base::MessageLoopProxy>& io_message_loop);
// Each client registers for MIDI access here.
// If permission is granted, then the client's
// addInputPort() and addOutputPort() methods will be called,
// giving the client access to receive and send data.
void RequestAccess(WebKit::WebMIDIAccessorClient* client, int access);
void RemoveClient(WebKit::WebMIDIAccessorClient* client);
// A client will only be able to call this method if it has a suitable
// output port (from addOutputPort()).
void SendMIDIData(int port,
const uint8* data,
size_t length,
double timestamp);
// IO message loop associated with this message filter.
scoped_refptr<base::MessageLoopProxy> io_message_loop() const {
return io_message_loop_;
}
protected:
virtual ~MIDIMessageFilter();
private:
// Sends an IPC message using |channel_|.
void Send(IPC::Message* message);
// IPC::ChannelProxy::MessageFilter override. Called on |io_message_loop|.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE;
virtual void OnFilterRemoved() OVERRIDE;
virtual void OnChannelClosing() OVERRIDE;
// Called when the browser process has approved (or denied) access to
// MIDI hardware.
void OnAccessApproved(int client_id,
int access,
bool success,
media::MIDIPortInfoList inputs,
media::MIDIPortInfoList outputs);
// Called when the browser process has sent MIDI data containing one or
// more messages.
void OnDataReceived(int port,
const std::vector<uint8>& data,
double timestamp);
void HandleAccessApproved(int client_id,
int access,
bool success,
media::MIDIPortInfoList inputs,
media::MIDIPortInfoList outputs);
void HandleDataReceived(int port,
const std::vector<uint8>& data,
double timestamp);
void RequestAccessOnIOThread(int client_id, int access);
void SendMIDIDataOnIOThread(int port,
const std::vector<uint8>& data,
double timestamp);
WebKit::WebMIDIAccessorClient* GetClientFromId(int client_id);
// IPC channel for Send(); must only be accessed on |io_message_loop_|.
IPC::Channel* channel_;
// Message loop on which IPC calls are driven.
const scoped_refptr<base::MessageLoopProxy> io_message_loop_;
// Keeps track of all MIDI clients.
// We map client to "client id" used to track permission.
// When access has been approved, we add the input and output ports to
// the client, allowing it to actually receive and send MIDI data.
typedef std::map<WebKit::WebMIDIAccessorClient*, int> ClientsMap;
ClientsMap clients_;
// Dishes out client ids.
int next_available_id_;
DISALLOW_COPY_AND_ASSIGN(MIDIMessageFilter);
};
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_MIDI_MESSAGE_FILTER_H_
// 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 "content/renderer/media/renderer_webmidiaccessor_impl.h"
#include "base/logging.h"
#include "content/renderer/media/midi_message_filter.h"
#include "content/renderer/render_thread_impl.h"
namespace content {
RendererWebMIDIAccessorImpl::RendererWebMIDIAccessorImpl(
WebKit::WebMIDIAccessorClient* client)
: client_(client) {
DCHECK(client_);
}
RendererWebMIDIAccessorImpl::~RendererWebMIDIAccessorImpl() {
midi_message_filter()->RemoveClient(client_);
}
void RendererWebMIDIAccessorImpl::requestAccess(bool access) {
midi_message_filter()->RequestAccess(client_, access ? 1 : 0);
}
void RendererWebMIDIAccessorImpl::sendMIDIData(
unsigned port_index,
const unsigned char* data,
size_t length,
double timestamp) {
midi_message_filter()->SendMIDIData(
port_index,
data,
length,
timestamp);
}
MIDIMessageFilter* RendererWebMIDIAccessorImpl::midi_message_filter() {
return RenderThreadImpl::current()->midi_message_filter();
}
} // namespace content
// 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 CONTENT_RENDERER_MEDIA_RENDERER_WEBMIDIACCESSOR_IMPL_H_
#define CONTENT_RENDERER_MEDIA_RENDERER_WEBMIDIACCESSOR_IMPL_H_
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "third_party/WebKit/public/platform/WebMIDIAccessor.h"
#include "third_party/WebKit/public/platform/WebMIDIAccessorClient.h"
namespace content {
class MIDIMessageFilter;
class RendererWebMIDIAccessorImpl
: public WebKit::WebMIDIAccessor {
public:
explicit RendererWebMIDIAccessorImpl(
WebKit::WebMIDIAccessorClient* client);
virtual ~RendererWebMIDIAccessorImpl();
// WebKit::WebMIDIAccessor implementation.
virtual void requestAccess(bool access) OVERRIDE;
virtual void sendMIDIData(unsigned port_index,
const unsigned char* data,
size_t length,
double timestamp) OVERRIDE;
private:
WebKit::WebMIDIAccessorClient* client_;
MIDIMessageFilter* midi_message_filter();
DISALLOW_COPY_AND_ASSIGN(RendererWebMIDIAccessorImpl);
};
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_RENDERER_WEBMIDIACCESSOR_IMPL_H_
......@@ -65,6 +65,7 @@
#include "content/renderer/media/audio_renderer_mixer_manager.h"
#include "content/renderer/media/media_stream_center.h"
#include "content/renderer/media/media_stream_dependency_factory.h"
#include "content/renderer/media/midi_message_filter.h"
#include "content/renderer/media/peer_connection_tracker.h"
#include "content/renderer/media/video_capture_impl_manager.h"
#include "content/renderer/media/video_capture_message_filter.h"
......@@ -368,6 +369,9 @@ void RenderThreadImpl::Init() {
audio_message_filter_ = new AudioMessageFilter(GetIOMessageLoopProxy());
AddFilter(audio_message_filter_.get());
midi_message_filter_ = new MIDIMessageFilter(GetIOMessageLoopProxy());
AddFilter(midi_message_filter_.get());
AddFilter(new IndexedDBMessageFilter);
GetContentClient()->renderer()->RenderThreadStarted();
......
......@@ -81,6 +81,7 @@ class InputEventFilter;
class InputHandlerManager;
class MediaStreamCenter;
class MediaStreamDependencyFactory;
class MIDIMessageFilter;
class P2PSocketDispatcher;
class PeerConnectionTracker;
class RendererWebKitPlatformSupportImpl;
......@@ -227,6 +228,9 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
return audio_message_filter_.get();
}
MIDIMessageFilter* midi_message_filter() {
return midi_message_filter_.get();
}
// Creates the embedder implementation of WebMediaStreamCenter.
// The resulting object is owned by WebKit and deleted by WebKit at tear-down.
......@@ -379,6 +383,7 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
scoped_refptr<DBMessageFilter> db_message_filter_;
scoped_refptr<AudioInputMessageFilter> audio_input_message_filter_;
scoped_refptr<AudioMessageFilter> audio_message_filter_;
scoped_refptr<MIDIMessageFilter> midi_message_filter_;
scoped_refptr<DevToolsAgentFilter> devtools_agent_message_filter_;
scoped_ptr<MediaStreamDependencyFactory> media_stream_factory_;
......
......@@ -31,6 +31,7 @@
#include "content/renderer/hyphenator/hyphenator.h"
#include "content/renderer/media/media_stream_dependency_factory.h"
#include "content/renderer/media/renderer_webaudiodevice_impl.h"
#include "content/renderer/media/renderer_webmidiaccessor_impl.h"
#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/renderer_clipboard_client.h"
......@@ -91,6 +92,7 @@ using WebKit::WebFileSystem;
using WebKit::WebFrame;
using WebKit::WebGamepads;
using WebKit::WebIDBFactory;
using WebKit::WebMIDIAccessor;
using WebKit::Platform;
using WebKit::WebMediaStreamCenter;
using WebKit::WebMediaStreamCenterClient;
......@@ -771,6 +773,14 @@ RendererWebKitPlatformSupportImpl::createContentDecryptionModule(
//------------------------------------------------------------------------------
WebKit::WebMIDIAccessor*
RendererWebKitPlatformSupportImpl::createMIDIAccessor(
WebKit::WebMIDIAccessorClient* client) {
return new RendererWebMIDIAccessorImpl(client);
}
//------------------------------------------------------------------------------
WebKit::WebString
RendererWebKitPlatformSupportImpl::signedPublicKeyAndChallengeString(
unsigned key_size_index,
......
......@@ -107,6 +107,8 @@ class CONTENT_EXPORT RendererWebKitPlatformSupportImpl
virtual WebKit::WebContentDecryptionModule* createContentDecryptionModule(
const WebKit::WebString& key_system);
virtual WebKit::WebMIDIAccessor*
createMIDIAccessor(WebKit::WebMIDIAccessorClient* client);
virtual WebKit::WebBlobRegistry* blobRegistry();
virtual void sampleGamepads(WebKit::WebGamepads&);
......
......@@ -47,6 +47,7 @@ enum IPCMessageStart {
DesktopNotificationMsgStart,
GeolocationMsgStart,
AudioMsgStart,
MIDIMsgStart,
ChromeMsgStart,
DragMsgStart,
PrintMsgStart,
......
......@@ -373,6 +373,12 @@
'filters/video_renderer_base.h',
'filters/vpx_video_decoder.cc',
'filters/vpx_video_decoder.h',
'midi/midi_manager.h',
'midi/midi_manager.cc',
'midi/midi_manager_mac.h',
'midi/midi_manager_mac.cc',
'midi/midi_port_info.h',
'midi/midi_port_info.cc',
'video/capture/android/video_capture_device_android.cc',
'video/capture/android/video_capture_device_android.h',
'video/capture/fake_video_capture_device.cc',
......@@ -535,6 +541,7 @@
'$(SDKROOT)/System/Library/Frameworks/AudioToolbox.framework',
'$(SDKROOT)/System/Library/Frameworks/AVFoundation.framework',
'$(SDKROOT)/System/Library/Frameworks/CoreAudio.framework',
'$(SDKROOT)/System/Library/Frameworks/CoreMIDI.framework',
],
},
}],
......@@ -747,6 +754,7 @@
'$(SDKROOT)/System/Library/Frameworks/AudioToolbox.framework',
'$(SDKROOT)/System/Library/Frameworks/AudioUnit.framework',
'$(SDKROOT)/System/Library/Frameworks/CoreAudio.framework',
'$(SDKROOT)/System/Library/Frameworks/CoreMIDI.framework',
'$(SDKROOT)/System/Library/Frameworks/CoreVideo.framework',
'$(SDKROOT)/System/Library/Frameworks/OpenGL.framework',
'$(SDKROOT)/System/Library/Frameworks/QTKit.framework',
......
// 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
// 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_
// 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
// 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_
// 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
// 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_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment