diff options
Diffstat (limited to 'media/audio/audio_output_dispatcher.cc')
-rw-r--r-- | media/audio/audio_output_dispatcher.cc | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/media/audio/audio_output_dispatcher.cc b/media/audio/audio_output_dispatcher.cc new file mode 100644 index 0000000..3f9d848 --- /dev/null +++ b/media/audio/audio_output_dispatcher.cc @@ -0,0 +1,115 @@ +// Copyright (c) 2010 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/audio/audio_output_dispatcher.h" + +#include "base/compiler_specific.h" +#include "base/message_loop.h" +#include "media/audio/audio_io.h" + +AudioOutputDispatcher::AudioOutputDispatcher( + AudioManager* audio_manager, const AudioParameters& params, + int close_delay_ms) + : audio_manager_(audio_manager), + message_loop_(audio_manager->GetMessageLoop()), + params_(params), + paused_proxies_(0), + ALLOW_THIS_IN_INITIALIZER_LIST(close_timer_( + base::TimeDelta::FromMilliseconds(close_delay_ms), + this, &AudioOutputDispatcher::ClosePendingStreams)) { +} + +AudioOutputDispatcher::~AudioOutputDispatcher() { +} + +bool AudioOutputDispatcher::StreamOpened() { + DCHECK_EQ(MessageLoop::current(), message_loop_); + paused_proxies_++; + + // Ensure that there is at least one open stream. + if (streams_.empty() && !CreateAndOpenStream()) { + return false; + } + + close_timer_.Reset(); + + return true; +} + +AudioOutputStream* AudioOutputDispatcher::StreamStarted() { + DCHECK_EQ(MessageLoop::current(), message_loop_); + + if (streams_.empty() && !CreateAndOpenStream()) { + return NULL; + } + + AudioOutputStream* stream = streams_.back(); + streams_.pop_back(); + + DCHECK_GT(paused_proxies_, 0u); + paused_proxies_--; + + close_timer_.Reset(); + + // Schedule task to allocate streams for other proxies if we need to. + message_loop_->PostTask(FROM_HERE, NewRunnableMethod( + this, &AudioOutputDispatcher::OpenTask)); + + return stream; +} + +void AudioOutputDispatcher::StreamStopped(AudioOutputStream* stream) { + DCHECK_EQ(MessageLoop::current(), message_loop_); + paused_proxies_++; + streams_.push_back(stream); + close_timer_.Reset(); +} + +void AudioOutputDispatcher::StreamClosed() { + DCHECK_EQ(MessageLoop::current(), message_loop_); + + DCHECK_GT(paused_proxies_, 0u); + paused_proxies_--; + + while (streams_.size() > paused_proxies_) { + streams_.back()->Close(); + streams_.pop_back(); + } +} + +MessageLoop* AudioOutputDispatcher::message_loop() { + return message_loop_; +} + +bool AudioOutputDispatcher::CreateAndOpenStream() { + AudioOutputStream* stream = + audio_manager_->MakeAudioOutputStream(params_); + if (!stream) { + return false; + } + if (!stream->Open()) { + stream->Close(); + return false; + } + streams_.push_back(stream); + return true; +} + +void AudioOutputDispatcher::OpenTask() { + // Make sure that we have at least one stream allocated if there + // are paused streams. + if (paused_proxies_ > 0 && streams_.empty()) { + CreateAndOpenStream(); + } + + close_timer_.Reset(); +} + +// This method is called by |close_timer_|. +void AudioOutputDispatcher::ClosePendingStreams() { + while (!streams_.empty()) { + streams_.back()->Close(); + streams_.pop_back(); + } +} |