This source file includes following definitions.
- unacknowledged_bytes_sent_
- Send
- OnMessageReceived
- OnFilterAdded
- OnFilterRemoved
- OnChannelClosing
- StartSession
- StartSessionOnIOThread
- RemoveClient
- OnSessionStarted
- HandleSessionStarted
- GetClientFromId
- OnDataReceived
- OnAcknowledgeSentData
- HandleDataReceived
- SendMidiData
- SendMidiDataOnIOThread
#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;
static const size_t kMaxUnacknowledgedBytesSent = 10 * 1024 * 1024;
namespace content {
MidiMessageFilter::MidiMessageFilter(
const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
: channel_(NULL),
io_message_loop_(io_message_loop),
main_message_loop_(base::MessageLoopProxy::current()),
next_available_id_(0),
unacknowledged_bytes_sent_(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_SessionStarted, OnSessionStarted)
IPC_MESSAGE_HANDLER(MidiMsg_DataReceived, OnDataReceived)
IPC_MESSAGE_HANDLER(MidiMsg_AcknowledgeSentData, OnAcknowledgeSentData)
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());
OnChannelClosing();
}
void MidiMessageFilter::OnChannelClosing() {
DCHECK(io_message_loop_->BelongsToCurrentThread());
channel_ = NULL;
}
void MidiMessageFilter::StartSession(blink::WebMIDIAccessorClient* client) {
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::StartSessionOnIOThread, this,
client_id));
}
}
void MidiMessageFilter::StartSessionOnIOThread(int client_id) {
Send(new MidiHostMsg_StartSession(client_id));
}
void MidiMessageFilter::RemoveClient(blink::WebMIDIAccessorClient* client) {
ClientsMap::iterator i = clients_.find(client);
if (i != clients_.end())
clients_.erase(i);
}
void MidiMessageFilter::OnSessionStarted(
int client_id,
bool success,
MidiPortInfoList inputs,
MidiPortInfoList outputs) {
main_message_loop_->PostTask(
FROM_HERE,
base::Bind(&MidiMessageFilter::HandleSessionStarted, this,
client_id, success, inputs, outputs));
}
void MidiMessageFilter::HandleSessionStarted(
int client_id,
bool success,
MidiPortInfoList inputs,
MidiPortInfoList outputs) {
blink::WebMIDIAccessorClient* client = GetClientFromId(client_id);
if (!client)
return;
if (success) {
for (size_t i = 0; i < inputs.size(); ++i) {
client->didAddInputPort(
base::UTF8ToUTF16(inputs[i].id),
base::UTF8ToUTF16(inputs[i].manufacturer),
base::UTF8ToUTF16(inputs[i].name),
base::UTF8ToUTF16(inputs[i].version));
}
for (size_t i = 0; i < outputs.size(); ++i) {
client->didAddOutputPort(
base::UTF8ToUTF16(outputs[i].id),
base::UTF8ToUTF16(outputs[i].manufacturer),
base::UTF8ToUTF16(outputs[i].name),
base::UTF8ToUTF16(outputs[i].version));
}
}
client->didStartSession(success);
}
blink::WebMIDIAccessorClient*
MidiMessageFilter::GetClientFromId(int client_id) {
for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i) {
if ((*i).second == client_id)
return (*i).first;
}
return NULL;
}
void MidiMessageFilter::OnDataReceived(uint32 port,
const std::vector<uint8>& data,
double timestamp) {
TRACE_EVENT0("midi", "MidiMessageFilter::OnDataReceived");
main_message_loop_->PostTask(
FROM_HERE,
base::Bind(&MidiMessageFilter::HandleDataReceived, this,
port, data, timestamp));
}
void MidiMessageFilter::OnAcknowledgeSentData(size_t bytes_sent) {
DCHECK_GE(unacknowledged_bytes_sent_, bytes_sent);
if (unacknowledged_bytes_sent_ >= bytes_sent)
unacknowledged_bytes_sent_ -= bytes_sent;
}
void MidiMessageFilter::HandleDataReceived(uint32 port,
const std::vector<uint8>& data,
double timestamp) {
DCHECK(!data.empty());
TRACE_EVENT0("midi", "MidiMessageFilter::HandleDataReceived");
for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i)
(*i).first->didReceiveMIDIData(port, &data[0], data.size(), timestamp);
}
void MidiMessageFilter::SendMidiData(uint32 port,
const uint8* data,
size_t length,
double timestamp) {
if (length > kMaxUnacknowledgedBytesSent) {
return;
}
std::vector<uint8> v(data, data + length);
io_message_loop_->PostTask(FROM_HERE,
base::Bind(&MidiMessageFilter::SendMidiDataOnIOThread, this,
port, v, timestamp));
}
void MidiMessageFilter::SendMidiDataOnIOThread(uint32 port,
const std::vector<uint8>& data,
double timestamp) {
size_t n = data.size();
if (n > kMaxUnacknowledgedBytesSent ||
unacknowledged_bytes_sent_ > kMaxUnacknowledgedBytesSent ||
n + unacknowledged_bytes_sent_ > kMaxUnacknowledgedBytesSent) {
return;
}
unacknowledged_bytes_sent_ += n;
Send(new MidiHostMsg_SendData(port, data, timestamp));
}
}