1 // Copyright (c) 2012 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.
4 
5 #include "media/audio/audio_output_proxy.h"
6 
7 #include "base/check_op.h"
8 #include "media/audio/audio_manager.h"
9 #include "media/audio/audio_output_dispatcher.h"
10 
11 namespace media {
12 
AudioOutputProxy(base::WeakPtr<AudioOutputDispatcher> dispatcher)13 AudioOutputProxy::AudioOutputProxy(
14     base::WeakPtr<AudioOutputDispatcher> dispatcher)
15     : dispatcher_(std::move(dispatcher)), state_(kCreated), volume_(1.0) {
16   DCHECK(dispatcher_);
17 }
18 
~AudioOutputProxy()19 AudioOutputProxy::~AudioOutputProxy() {
20   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
21   DCHECK(state_ == kCreated || state_ == kClosed) << "State is: " << state_;
22 }
23 
Open()24 bool AudioOutputProxy::Open() {
25   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
26   DCHECK_EQ(state_, kCreated);
27 
28   if (!dispatcher_ || !dispatcher_->OpenStream()) {
29     state_ = kOpenError;
30     return false;
31   }
32 
33   state_ = kOpened;
34   return true;
35 }
36 
Start(AudioSourceCallback * callback)37 void AudioOutputProxy::Start(AudioSourceCallback* callback) {
38   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
39 
40   // We need to support both states since the callback may not handle OnError()
41   // immediately (or at all).  It's also possible for subsequent StartStream()
42   // calls to succeed after failing, so we allow it to be called again.
43   DCHECK(state_ == kOpened || state_ == kStartError);
44 
45   if (!dispatcher_ || !dispatcher_->StartStream(callback, this)) {
46     state_ = kStartError;
47     callback->OnError(AudioSourceCallback::ErrorType::kUnknown);
48     return;
49   }
50   state_ = kPlaying;
51 }
52 
Stop()53 void AudioOutputProxy::Stop() {
54   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
55   if (state_ != kPlaying)
56     return;
57 
58   if (dispatcher_)
59     dispatcher_->StopStream(this);
60   state_ = kOpened;
61 }
62 
SetVolume(double volume)63 void AudioOutputProxy::SetVolume(double volume) {
64   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
65   volume_ = volume;
66 
67   if (dispatcher_)
68     dispatcher_->StreamVolumeSet(this, volume);
69 }
70 
GetVolume(double * volume)71 void AudioOutputProxy::GetVolume(double* volume) {
72   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
73   *volume = volume_;
74 }
75 
Close()76 void AudioOutputProxy::Close() {
77   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
78   DCHECK(state_ == kCreated || state_ == kOpenError || state_ == kOpened ||
79          state_ == kStartError);
80 
81   // kStartError means OpenStream() succeeded and the stream must be closed
82   // before destruction.
83   if (state_ != kCreated && state_ != kOpenError && dispatcher_)
84     dispatcher_->CloseStream(this);
85 
86   state_ = kClosed;
87 
88   // Delete the object now like is done in the Close() implementation of
89   // physical stream objects.  If we delete the object via DeleteSoon, we
90   // unnecessarily complicate the Shutdown procedure of the
91   // dispatcher+audio manager.
92   delete this;
93 }
94 
Flush()95 void AudioOutputProxy::Flush() {
96   DCHECK(state_ != kPlaying);
97 
98   if (dispatcher_)
99     dispatcher_->FlushStream(this);
100 }
101 
102 }  // namespace media
103