Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(313)

Side by Side Diff: media/audio/sounds/audio_stream_handler.cc

Issue 115693004: Added volume adjust sound behind the flag. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix, rebase. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/audio/sounds/audio_stream_handler.h" 5 #include "media/audio/sounds/audio_stream_handler.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/cancelable_callback.h"
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "base/single_thread_task_runner.h" 11 #include "base/single_thread_task_runner.h"
12 #include "base/synchronization/lock.h"
13 #include "base/time/time.h"
11 #include "media/audio/audio_manager.h" 14 #include "media/audio/audio_manager.h"
12 #include "media/audio/audio_manager_base.h" 15 #include "media/audio/audio_manager_base.h"
13 #include "media/base/channel_layout.h" 16 #include "media/base/channel_layout.h"
14 17
15 namespace media { 18 namespace media {
16 19
17 namespace { 20 namespace {
18 21
19 // Volume percent. 22 // Volume percent.
20 const double kOutputVolumePercent = 0.8; 23 const double kOutputVolumePercent = 0.8;
21 24
22 // The number of frames each OnMoreData() call will request. 25 // The number of frames each OnMoreData() call will request.
23 const int kDefaultFrameCount = 1024; 26 const int kDefaultFrameCount = 1024;
24 27
28 // Keep alive timeout for audio stream.
29 const int kKeepAliveMs = 1500;
30
25 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL; 31 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL;
26 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL; 32 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL;
27 33
28 } // namespace 34 } // namespace
29 35
30 class AudioStreamHandler::AudioStreamContainer 36 class AudioStreamHandler::AudioStreamContainer
31 : public AudioOutputStream::AudioSourceCallback { 37 : public AudioOutputStream::AudioSourceCallback {
32 public: 38 public:
33 AudioStreamContainer(const WavAudioHandler& wav_audio, 39 AudioStreamContainer(const WavAudioHandler& wav_audio)
34 const AudioParameters& params)
35 : stream_(NULL), 40 : stream_(NULL),
36 wav_audio_(wav_audio), 41 wav_audio_(wav_audio),
37 params_(params), 42 cursor_(0),
38 cursor_(0) { 43 started_(false),
44 delayed_stop_posted_(false) {
39 } 45 }
40 46
41 virtual ~AudioStreamContainer() { 47 virtual ~AudioStreamContainer() {
42 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 48 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
43 } 49 }
44 50
45 void Play() { 51 void Play() {
46 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 52 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
47 53
48 if (!stream_) { 54 if (!stream_) {
49 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(params_, 55 const AudioParameters& p = wav_audio_.params();
50 std::string(), 56 const AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
51 std::string()); 57 p.channel_layout(),
58 p.sample_rate(),
59 p.bits_per_sample(),
60 kDefaultFrameCount);
61 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(
62 params, std::string(), std::string());
52 if (!stream_ || !stream_->Open()) { 63 if (!stream_ || !stream_->Open()) {
53 LOG(ERROR) << "Failed to open an output stream."; 64 LOG(ERROR) << "Failed to open an output stream.";
54 return; 65 return;
55 } 66 }
56 stream_->SetVolume(kOutputVolumePercent); 67 stream_->SetVolume(kOutputVolumePercent);
57 } else {
58 // TODO (ygorshenin@): implement smart stream rewind.
59 stream_->Stop();
60 } 68 }
61 69
62 cursor_ = 0; 70 {
71 base::AutoLock al(state_lock_);
72
73 delayed_stop_posted_ = false;
74 stop_closure_.Reset(base::Bind(
75 &AudioStreamContainer::StopStream, base::Unretained(this)));
76
77 if (started_) {
78 if (wav_audio_.AtEnd(cursor_))
79 cursor_ = 0;
80 return;
81 }
82
83 cursor_ = 0;
84 started_ = true;
85 }
86
63 if (g_audio_source_for_testing) 87 if (g_audio_source_for_testing)
64 stream_->Start(g_audio_source_for_testing); 88 stream_->Start(g_audio_source_for_testing);
65 else 89 else
66 stream_->Start(this); 90 stream_->Start(this);
67 91
68 if (g_observer_for_testing) 92 if (g_observer_for_testing)
69 g_observer_for_testing->OnPlay(); 93 g_observer_for_testing->OnPlay();
70 } 94 }
71 95
72 void Stop() { 96 void Stop() {
73 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); 97 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
74 if (!stream_) 98 StopStream();
75 return; 99 if (stream_)
76 stream_->Stop(); 100 stream_->Close();
77 stream_->Close();
78 stream_ = NULL; 101 stream_ = NULL;
79
80 if (g_observer_for_testing)
81 g_observer_for_testing->OnStop(cursor_);
82 } 102 }
83 103
84 private: 104 private:
85 // AudioOutputStream::AudioSourceCallback overrides: 105 // AudioOutputStream::AudioSourceCallback overrides:
86 // Following methods could be called from *ANY* thread. 106 // Following methods could be called from *ANY* thread.
87 virtual int OnMoreData(AudioBus* dest, 107 virtual int OnMoreData(AudioBus* dest,
88 AudioBuffersState /* state */) OVERRIDE { 108 AudioBuffersState /* state */) OVERRIDE {
109 base::AutoLock al(state_lock_);
89 size_t bytes_written = 0; 110 size_t bytes_written = 0;
111
90 if (wav_audio_.AtEnd(cursor_) || 112 if (wav_audio_.AtEnd(cursor_) ||
91 !wav_audio_.CopyTo(dest, cursor_, &bytes_written)) { 113 !wav_audio_.CopyTo(dest, cursor_, &bytes_written)) {
92 AudioManager::Get()->GetTaskRunner()->PostTask( 114 if (delayed_stop_posted_)
115 return 0;
116 delayed_stop_posted_ = true;
117 AudioManager::Get()->GetTaskRunner()->PostDelayedTask(
93 FROM_HERE, 118 FROM_HERE,
94 base::Bind(&AudioStreamContainer::Stop, base::Unretained(this))); 119 stop_closure_.callback(),
120 base::TimeDelta::FromMilliseconds(kKeepAliveMs));
95 return 0; 121 return 0;
96 } 122 }
97 cursor_ += bytes_written; 123 cursor_ += bytes_written;
98
99 return dest->frames(); 124 return dest->frames();
100 } 125 }
101 126
102 virtual int OnMoreIOData(AudioBus* /* source */, 127 virtual int OnMoreIOData(AudioBus* /* source */,
103 AudioBus* dest, 128 AudioBus* dest,
104 AudioBuffersState state) OVERRIDE { 129 AudioBuffersState state) OVERRIDE {
105 return OnMoreData(dest, state); 130 return OnMoreData(dest, state);
106 } 131 }
107 132
108 virtual void OnError(AudioOutputStream* /* stream */) OVERRIDE { 133 virtual void OnError(AudioOutputStream* /* stream */) OVERRIDE {
109 LOG(ERROR) << "Error during system sound reproduction."; 134 LOG(ERROR) << "Error during system sound reproduction.";
110 } 135 }
111 136
137 void StopStream() {
138 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
139
140 base::AutoLock al(state_lock_);
141
142 if (stream_ && started_) {
143 stream_->Stop();
144 if (g_observer_for_testing)
145 g_observer_for_testing->OnStop(cursor_);
146 }
147 started_ = false;
148 }
149
112 AudioOutputStream* stream_; 150 AudioOutputStream* stream_;
113 151
114 const WavAudioHandler wav_audio_; 152 const WavAudioHandler wav_audio_;
115 const AudioParameters params_;
116 153
154 base::Lock state_lock_;
117 size_t cursor_; 155 size_t cursor_;
156 bool started_;
157 bool delayed_stop_posted_;
158 base::CancelableClosure stop_closure_;
118 159
119 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer); 160 DISALLOW_COPY_AND_ASSIGN(AudioStreamContainer);
120 }; 161 };
121 162
122 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data) 163 AudioStreamHandler::AudioStreamHandler(const base::StringPiece& wav_data)
123 : wav_audio_(wav_data), 164 : wav_audio_(wav_data),
124 initialized_(false) { 165 initialized_(false) {
125 AudioManager* manager = AudioManager::Get(); 166 AudioManager* manager = AudioManager::Get();
126 if (!manager) { 167 if (!manager) {
127 LOG(ERROR) << "Can't get access to audio manager."; 168 LOG(ERROR) << "Can't get access to audio manager.";
128 return; 169 return;
129 } 170 }
130 AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, 171 if (!wav_audio_.params().IsValid()) {
131 GuessChannelLayout(wav_audio_.num_channels()),
132 wav_audio_.sample_rate(),
133 wav_audio_.bits_per_sample(),
134 kDefaultFrameCount);
135 if (!params.IsValid()) {
136 LOG(ERROR) << "Audio params are invalid."; 172 LOG(ERROR) << "Audio params are invalid.";
137 return; 173 return;
138 } 174 }
139 stream_.reset(new AudioStreamContainer(wav_audio_, params)); 175 stream_.reset(new AudioStreamContainer(wav_audio_));
140 initialized_ = true; 176 initialized_ = true;
141 } 177 }
142 178
143 AudioStreamHandler::~AudioStreamHandler() { 179 AudioStreamHandler::~AudioStreamHandler() {
144 DCHECK(CalledOnValidThread()); 180 DCHECK(CalledOnValidThread());
145 AudioManager::Get()->GetTaskRunner()->PostTask( 181 AudioManager::Get()->GetTaskRunner()->PostTask(
146 FROM_HERE, 182 FROM_HERE,
147 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); 183 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get())));
148 AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE, 184 AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE,
149 stream_.release()); 185 stream_.release());
150 } 186 }
151 187
152 bool AudioStreamHandler::IsInitialized() const { 188 bool AudioStreamHandler::IsInitialized() const {
153 DCHECK(CalledOnValidThread()); 189 DCHECK(CalledOnValidThread());
154 return initialized_; 190 return initialized_;
155 } 191 }
156 192
157 bool AudioStreamHandler::Play() { 193 bool AudioStreamHandler::Play() {
158 DCHECK(CalledOnValidThread()); 194 DCHECK(CalledOnValidThread());
159 195
(...skipping 19 matching lines...) Expand all
179 g_observer_for_testing = observer; 215 g_observer_for_testing = observer;
180 } 216 }
181 217
182 // static 218 // static
183 void AudioStreamHandler::SetAudioSourceForTesting( 219 void AudioStreamHandler::SetAudioSourceForTesting(
184 AudioOutputStream::AudioSourceCallback* source) { 220 AudioOutputStream::AudioSourceCallback* source) {
185 g_audio_source_for_testing = source; 221 g_audio_source_for_testing = source;
186 } 222 }
187 223
188 } // namespace media 224 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/sounds/audio_stream_handler.h ('k') | media/audio/sounds/audio_stream_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698