diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-04 19:28:53 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-04 19:28:53 +0000 |
commit | 8a7499e2fb2c6a80aa6a8509fa00b9cf7b6e5031 (patch) | |
tree | 9b335e29f25acfbeae49533a5a7ce0f132dfef22 /chrome/browser/renderer_host/audio_renderer_host.cc | |
parent | 0e19849067bead96a0c0ca48b2b82a9682e78013 (diff) | |
download | chromium_src-8a7499e2fb2c6a80aa6a8509fa00b9cf7b6e5031.zip chromium_src-8a7499e2fb2c6a80aa6a8509fa00b9cf7b6e5031.tar.gz chromium_src-8a7499e2fb2c6a80aa6a8509fa00b9cf7b6e5031.tar.bz2 |
AudioRendererHost and unit test files
AudioRendererHost provide service in browser process for AudioRenderer to access hardware in render process.
There will be one AudioRendererHost for every RenderProcessHost, each one of AudioRendererHost will service multiple AudioRenderer in the related render process.
The main functionality of AudioRendererHost is to group audio related services and provide access to AudioRenderer through IPC. It maps an internal stream id to the actual AudioOutputStream which most calls are delegated to.
AudioRendererHost::IPCAudioSource is to implement audio data source using IPC.
Review URL: http://codereview.chromium.org/21008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9159 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/renderer_host/audio_renderer_host.cc')
-rw-r--r-- | chrome/browser/renderer_host/audio_renderer_host.cc | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/chrome/browser/renderer_host/audio_renderer_host.cc b/chrome/browser/renderer_host/audio_renderer_host.cc new file mode 100644 index 0000000..66ee9ff --- /dev/null +++ b/chrome/browser/renderer_host/audio_renderer_host.cc @@ -0,0 +1,174 @@ +// Copyright (c) 2006-2009 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 "base/message_loop.h" +#include "base/process.h" +#include "chrome/browser/renderer_host/audio_renderer_host.h" + +AudioRendererHost::IPCAudioSource::IPCAudioSource( + AudioRendererHost* host, + int32 id, + AudioOutputStream* stream, + IPC::Message::Sender* sender, + base::ProcessHandle process, + size_t packet_size) + : host_(host), + id_(id), + stream_(stream), + sender_(sender) { + // Make sure we can create and map the shared memory. + DCHECK(shared_memory_.Create(L"", false, false, packet_size) && + shared_memory_.Map(packet_size)); + // Also make sure we can create the buffer and share to render process. + DCHECK(shared_memory_.ShareToProcess(process, &foreign_memory_handle_)); +} + +AudioRendererHost::IPCAudioSource::~IPCAudioSource() { +} + +size_t AudioRendererHost::IPCAudioSource::OnMoreData(AudioOutputStream* stream, + void* dest, + size_t max_size) { + // TODO(hclam): send an IPC message to renderer provided with a + // SharedMemoryHandle for audio renderer inside render process to fill in. + // We should sleep until we receive a notification from render process that + // the buffer is ready or this source is closed or an error is encountered. + // Stuff do there here: + // 1. Prepare the SharedMemory. + // 2. Send an IPC. + // 3. Wait until we receive notification. + return 0; +} + +void AudioRendererHost::IPCAudioSource::OnClose(AudioOutputStream* stream) { + // TODO(hclam): should set a flag here and wakes up the thread waiting for + // audio buffer. Should also make sure this call come from the thread as this + // object is created. + // Stuff to do here: + // 1. Send an IPC to renderer about close complete. + // 2. Remove this object from host. + host_->DestroySource(id_); +} + +void AudioRendererHost::IPCAudioSource::OnError(AudioOutputStream* stream, + int code) { + // TODO(hclam): make sure this method is received in the same thread as this + // object is created and remove this object and from the map gracefully. + // Stuff to do here: + // 1. Send an IPC to renderer about the error. + // 2. Close the stream so it would get closed. + // TODO(cpu): make sure it is safe to close() in this method. + stream_->Close(); +} + +void AudioRendererHost::IPCAudioSource::NotifyPacketReady() { + // TODO(hclam): wake the thread waiting for buffer. +} + +AudioRendererHost::AudioRendererHost(MessageLoop* message_loop) + : next_id_(INVALID_ID+1), + message_loop_(message_loop) { +} + +AudioRendererHost::~AudioRendererHost() { + DestroyAllStreams(); +} + +int AudioRendererHost::CreateStream( + IPC::Message::Sender* sender, base::ProcessHandle handle, + AudioManager::Format format, int channels, int sample_rate, + int bits_per_sample, size_t packet_size) { + DCHECK(MessageLoop::current() == message_loop_); + + // Create the stream in the first place. + AudioOutputStream* stream = AudioManager::GetAudioManager()->MakeAudioStream( + format, channels, sample_rate, bits_per_sample); + if (!stream) + return INVALID_ID; + + // Try to open the stream if we can create it. + if (stream->Open(packet_size)) { + // Create the containing IPCAudioSource and save it to the map. + IPCAudioSource* source = + new IPCAudioSource(this, next_id_++, stream, sender, handle, + packet_size); + sources_.AddWithID(source, source->id()); + return source->id(); + } + return INVALID_ID; +} + +bool AudioRendererHost::Start(int stream_id) { + DCHECK(MessageLoop::current() == message_loop_); + IPCAudioSource* source = sources_.Lookup(stream_id); + if (source) { + source->stream()->Start(source); + return true; + } + return false; +} + +bool AudioRendererHost::Stop(int stream_id) { + DCHECK(MessageLoop::current() == message_loop_); + IPCAudioSource* source = sources_.Lookup(stream_id); + if (source) { + source->stream()->Stop(); + return true; + } + return false; +} + +bool AudioRendererHost::Close(int stream_id) { + DCHECK(MessageLoop::current() == message_loop_); + IPCAudioSource* source = sources_.Lookup(stream_id); + if (source) { + source->stream()->Close(); + return true; + } + return false; +} + +bool AudioRendererHost::SetVolume( + int stream_id, double left_channel, double right_channel) { + DCHECK(MessageLoop::current() == message_loop_); + IPCAudioSource* source = sources_.Lookup(stream_id); + if (source) { + source->stream()->SetVolume(left_channel, right_channel); + } + return false; +} + +bool AudioRendererHost::GetVolume( + int stream_id, double* left_channel, double* right_channel) { + DCHECK(MessageLoop::current() == message_loop_); + IPCAudioSource* source = sources_.Lookup(stream_id); + if (source) { + source->stream()->GetVolume(left_channel, right_channel); + return true; + } + return false; +} + +void AudioRendererHost::NotifyPacketReady(int stream_id) { + DCHECK(MessageLoop::current() == message_loop_); + IPCAudioSource* source = sources_.Lookup(stream_id); + if (source) { + source->NotifyPacketReady(); + } +} + +void AudioRendererHost::DestroyAllStreams() { + DCHECK(MessageLoop::current() == message_loop_); + // TODO(hclam): iterate on the map, close and delete every stream, and clear + // the map. +} + +void AudioRendererHost::DestroySource(int stream_id) { + DCHECK(MessageLoop::current() == message_loop_); + IPCAudioSource* source = sources_.Lookup(stream_id); + if (source) { + sources_.Remove(stream_id); + delete source; + } +} |