Print Preview: Refactoring print/cancel button and print summary.
[chromium-blink-merge.git] / media / audio / audio_output_dispatcher.cc
blobc70706932cccfb6653fc63e5a116fd229b4224bc
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/audio/audio_output_dispatcher.h"
7 #include "base/compiler_specific.h"
8 #include "base/message_loop.h"
9 #include "base/time.h"
10 #include "media/audio/audio_io.h"
12 AudioOutputDispatcher::AudioOutputDispatcher(
13 AudioManager* audio_manager, const AudioParameters& params,
14 int close_delay_ms)
15 : audio_manager_(audio_manager),
16 message_loop_(audio_manager->GetMessageLoop()),
17 params_(params),
18 pause_delay_milliseconds_(2 * params.samples_per_packet *
19 base::Time::kMillisecondsPerSecond / params.sample_rate),
20 paused_proxies_(0),
21 ALLOW_THIS_IN_INITIALIZER_LIST(close_timer_(
22 base::TimeDelta::FromMilliseconds(close_delay_ms),
23 this, &AudioOutputDispatcher::ClosePendingStreams)) {
26 AudioOutputDispatcher::~AudioOutputDispatcher() {
29 bool AudioOutputDispatcher::StreamOpened() {
30 DCHECK_EQ(MessageLoop::current(), message_loop_);
31 paused_proxies_++;
33 // Ensure that there is at least one open stream.
34 if (idle_streams_.empty() && !CreateAndOpenStream()) {
35 return false;
38 close_timer_.Reset();
40 return true;
43 AudioOutputStream* AudioOutputDispatcher::StreamStarted() {
44 DCHECK_EQ(MessageLoop::current(), message_loop_);
46 if (idle_streams_.empty() && !CreateAndOpenStream()) {
47 return NULL;
50 AudioOutputStream* stream = idle_streams_.back();
51 idle_streams_.pop_back();
53 DCHECK_GT(paused_proxies_, 0u);
54 paused_proxies_--;
56 close_timer_.Reset();
58 // Schedule task to allocate streams for other proxies if we need to.
59 message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
60 this, &AudioOutputDispatcher::OpenTask));
62 return stream;
65 void AudioOutputDispatcher::StreamStopped(AudioOutputStream* stream) {
66 DCHECK_EQ(MessageLoop::current(), message_loop_);
68 paused_proxies_++;
70 pausing_streams_.push_front(stream);
71 close_timer_.Reset();
73 // Don't recycle stream until two buffers worth of time has elapsed.
74 message_loop_->PostDelayedTask(
75 FROM_HERE,
76 NewRunnableMethod(this, &AudioOutputDispatcher::StopStreamTask),
77 pause_delay_milliseconds_);
80 void AudioOutputDispatcher::StopStreamTask() {
81 if (pausing_streams_.empty())
82 return;
83 AudioOutputStream* stream = pausing_streams_.back();
84 pausing_streams_.pop_back();
85 idle_streams_.push_back(stream);
88 void AudioOutputDispatcher::StreamClosed() {
89 DCHECK_EQ(MessageLoop::current(), message_loop_);
91 while (!pausing_streams_.empty()) {
92 idle_streams_.push_back(pausing_streams_.back());
93 pausing_streams_.pop_back();
96 DCHECK_GT(paused_proxies_, 0u);
97 paused_proxies_--;
99 while (idle_streams_.size() > paused_proxies_) {
100 idle_streams_.back()->Close();
101 idle_streams_.pop_back();
105 MessageLoop* AudioOutputDispatcher::message_loop() {
106 return message_loop_;
109 bool AudioOutputDispatcher::CreateAndOpenStream() {
110 AudioOutputStream* stream =
111 audio_manager_->MakeAudioOutputStream(params_);
112 if (!stream) {
113 return false;
115 if (!stream->Open()) {
116 stream->Close();
117 return false;
119 idle_streams_.push_back(stream);
120 return true;
123 void AudioOutputDispatcher::OpenTask() {
124 // Make sure that we have at least one stream allocated if there
125 // are paused streams.
126 if (paused_proxies_ > 0 && idle_streams_.empty() &&
127 pausing_streams_.empty()) {
128 CreateAndOpenStream();
131 close_timer_.Reset();
134 // This method is called by |close_timer_|.
135 void AudioOutputDispatcher::ClosePendingStreams() {
136 while (!idle_streams_.empty()) {
137 idle_streams_.back()->Close();
138 idle_streams_.pop_back();