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