summaryrefslogtreecommitdiffstats
path: root/media/audio/audio_output_dispatcher.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/audio/audio_output_dispatcher.cc')
-rw-r--r--media/audio/audio_output_dispatcher.cc115
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();
+ }
+}