blob: 850cd1a0fa57c49bf06deb2a41c32a654df4f773 [file] [log] [blame]
// Copyright (c) 2012 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/audio_input_message_filter.h"
#include "base/bind.h"
#include "base/message_loop.h"
#include "base/time.h"
#include "content/common/child_process.h"
#include "content/common/media/audio_messages.h"
#include "ipc/ipc_logging.h"
AudioInputMessageFilter* AudioInputMessageFilter::filter_ = NULL;
AudioInputMessageFilter::AudioInputMessageFilter()
: channel_(NULL) {
DVLOG(1) << "AudioInputMessageFilter()";
DCHECK(!filter_);
filter_ = this;
}
AudioInputMessageFilter::~AudioInputMessageFilter() {
DVLOG(1) << "AudioInputMessageFilter::~AudioInputMessageFilter()";
// Just in case the message filter is deleted before the channel
// is closed and there are still living audio devices.
OnChannelClosing();
DCHECK_EQ(filter_, this);
filter_ = NULL;
}
// static.
AudioInputMessageFilter* AudioInputMessageFilter::Get() {
return filter_;
}
bool AudioInputMessageFilter::Send(IPC::Message* message) {
if (!channel_) {
delete message;
return false;
}
if (MessageLoop::current() != ChildProcess::current()->io_message_loop()) {
// Can only access the IPC::Channel on the IPC thread since it's not thread
// safe.
ChildProcess::current()->io_message_loop()->PostTask(
FROM_HERE,
base::Bind(base::IgnoreResult(&AudioInputMessageFilter::Send), this,
message));
return true;
}
return channel_->Send(message);
}
bool AudioInputMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(AudioInputMessageFilter, message)
IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamCreated,
OnStreamCreated)
IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamVolume, OnStreamVolume)
IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyStreamStateChanged,
OnStreamStateChanged)
IPC_MESSAGE_HANDLER(AudioInputMsg_NotifyDeviceStarted,
OnDeviceStarted)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void AudioInputMessageFilter::OnFilterAdded(IPC::Channel* channel) {
DVLOG(1) << "AudioInputMessageFilter::OnFilterAdded()";
// Captures the channel for IPC.
channel_ = channel;
}
void AudioInputMessageFilter::OnFilterRemoved() {
channel_ = NULL;
}
void AudioInputMessageFilter::OnChannelClosing() {
channel_ = NULL;
LOG_IF(WARNING, !delegates_.IsEmpty())
<< "Not all audio devices have been closed.";
IDMap<media::AudioInputIPCDelegate>::iterator it(&delegates_);
while (!it.IsAtEnd()) {
it.GetCurrentValue()->OnIPCClosed();
delegates_.Remove(it.GetCurrentKey());
it.Advance();
}
}
void AudioInputMessageFilter::OnStreamCreated(
int stream_id,
base::SharedMemoryHandle handle,
#if defined(OS_WIN)
base::SyncSocket::Handle socket_handle,
#else
base::FileDescriptor socket_descriptor,
#endif
uint32 length) {
#if !defined(OS_WIN)
base::SyncSocket::Handle socket_handle = socket_descriptor.fd;
#endif
media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
if (!delegate) {
DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
" audio capturer (stream_id=" << stream_id << ").";
base::SharedMemory::CloseHandle(handle);
base::SyncSocket socket(socket_handle);
return;
}
// Forward message to the stream delegate.
delegate->OnStreamCreated(handle, socket_handle, length);
}
void AudioInputMessageFilter::OnStreamVolume(int stream_id, double volume) {
media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
if (!delegate) {
DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
" audio capturer.";
return;
}
delegate->OnVolume(volume);
}
void AudioInputMessageFilter::OnStreamStateChanged(
int stream_id, media::AudioInputIPCDelegate::State state) {
media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
if (!delegate) {
DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
" audio renderer.";
return;
}
delegate->OnStateChanged(state);
}
void AudioInputMessageFilter::OnDeviceStarted(int stream_id,
const std::string& device_id) {
media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
if (!delegate) {
NOTREACHED();
return;
}
delegate->OnDeviceReady(device_id);
}
int AudioInputMessageFilter::AddDelegate(
media::AudioInputIPCDelegate* delegate) {
return delegates_.Add(delegate);
}
void AudioInputMessageFilter::RemoveDelegate(int id) {
DVLOG(1) << "AudioInputMessageFilter::RemoveDelegate(id=" << id << ")";
delegates_.Remove(id);
}
void AudioInputMessageFilter::CreateStream(int stream_id,
const media::AudioParameters& params, const std::string& device_id,
bool automatic_gain_control) {
Send(new AudioInputHostMsg_CreateStream(
stream_id, params, device_id, automatic_gain_control));
}
void AudioInputMessageFilter::StartDevice(int stream_id, int session_id) {
Send(new AudioInputHostMsg_StartDevice(stream_id, session_id));
}
void AudioInputMessageFilter::RecordStream(int stream_id) {
Send(new AudioInputHostMsg_RecordStream(stream_id));
}
void AudioInputMessageFilter::CloseStream(int stream_id) {
Send(new AudioInputHostMsg_CloseStream(stream_id));
}
void AudioInputMessageFilter::SetVolume(int stream_id, double volume) {
Send(new AudioInputHostMsg_SetVolume(stream_id, volume));
}