| OLD | NEW |
| 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/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop/message_loop_proxy.h" | 10 #include "base/single_thread_task_runner.h" |
| 11 #include "media/audio/audio_manager.h" | 11 #include "media/audio/audio_manager.h" |
| 12 #include "media/audio/audio_manager_base.h" | 12 #include "media/audio/audio_manager_base.h" |
| 13 #include "media/base/channel_layout.h" | 13 #include "media/base/channel_layout.h" |
| 14 | 14 |
| 15 namespace media { | 15 namespace media { |
| 16 | 16 |
| 17 namespace { | 17 namespace { |
| 18 | 18 |
| 19 // Volume percent. | 19 // Volume percent. |
| 20 const double kOutputVolumePercent = 0.8; | 20 const double kOutputVolumePercent = 0.8; |
| 21 | 21 |
| 22 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL; | 22 AudioStreamHandler::TestObserver* g_observer_for_testing = NULL; |
| 23 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL; | 23 AudioOutputStream::AudioSourceCallback* g_audio_source_for_testing = NULL; |
| 24 | 24 |
| 25 } // namespace | 25 } // namespace |
| 26 | 26 |
| 27 class AudioStreamHandler::AudioStreamContainer | 27 class AudioStreamHandler::AudioStreamContainer |
| 28 : public AudioOutputStream::AudioSourceCallback { | 28 : public AudioOutputStream::AudioSourceCallback { |
| 29 public: | 29 public: |
| 30 AudioStreamContainer(const WavAudioHandler& wav_audio, | 30 AudioStreamContainer(const WavAudioHandler& wav_audio, |
| 31 const AudioParameters& params) | 31 const AudioParameters& params) |
| 32 : stream_(NULL), | 32 : stream_(NULL), |
| 33 wav_audio_(wav_audio), | 33 wav_audio_(wav_audio), |
| 34 params_(params), | 34 params_(params), |
| 35 cursor_(0) { | 35 cursor_(0) { |
| 36 } | 36 } |
| 37 | 37 |
| 38 virtual ~AudioStreamContainer() { | 38 virtual ~AudioStreamContainer() { |
| 39 DCHECK(AudioManager::Get()->GetMessageLoop()->BelongsToCurrentThread()); | 39 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); |
| 40 } | 40 } |
| 41 | 41 |
| 42 void Play() { | 42 void Play() { |
| 43 DCHECK(AudioManager::Get()->GetMessageLoop()->BelongsToCurrentThread()); | 43 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); |
| 44 | 44 |
| 45 if (!stream_) { | 45 if (!stream_) { |
| 46 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(params_, | 46 stream_ = AudioManager::Get()->MakeAudioOutputStreamProxy(params_, |
| 47 std::string(), | 47 std::string(), |
| 48 std::string()); | 48 std::string()); |
| 49 if (!stream_ || !stream_->Open()) { | 49 if (!stream_ || !stream_->Open()) { |
| 50 LOG(ERROR) << "Failed to open an output stream."; | 50 LOG(ERROR) << "Failed to open an output stream."; |
| 51 return; | 51 return; |
| 52 } | 52 } |
| 53 stream_->SetVolume(kOutputVolumePercent); | 53 stream_->SetVolume(kOutputVolumePercent); |
| 54 } else { | 54 } else { |
| 55 // TODO (ygorshenin@): implement smart stream rewind. | 55 // TODO (ygorshenin@): implement smart stream rewind. |
| 56 stream_->Stop(); | 56 stream_->Stop(); |
| 57 } | 57 } |
| 58 | 58 |
| 59 cursor_ = 0; | 59 cursor_ = 0; |
| 60 if (g_audio_source_for_testing) | 60 if (g_audio_source_for_testing) |
| 61 stream_->Start(g_audio_source_for_testing); | 61 stream_->Start(g_audio_source_for_testing); |
| 62 else | 62 else |
| 63 stream_->Start(this); | 63 stream_->Start(this); |
| 64 | 64 |
| 65 if (g_observer_for_testing) | 65 if (g_observer_for_testing) |
| 66 g_observer_for_testing->OnPlay(); | 66 g_observer_for_testing->OnPlay(); |
| 67 } | 67 } |
| 68 | 68 |
| 69 void Stop() { | 69 void Stop() { |
| 70 DCHECK(AudioManager::Get()->GetMessageLoop()->BelongsToCurrentThread()); | 70 DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); |
| 71 if (!stream_) | 71 if (!stream_) |
| 72 return; | 72 return; |
| 73 stream_->Stop(); | 73 stream_->Stop(); |
| 74 stream_->Close(); | 74 stream_->Close(); |
| 75 stream_ = NULL; | 75 stream_ = NULL; |
| 76 | 76 |
| 77 if (g_observer_for_testing) | 77 if (g_observer_for_testing) |
| 78 g_observer_for_testing->OnStop(cursor_); | 78 g_observer_for_testing->OnStop(cursor_); |
| 79 } | 79 } |
| 80 | 80 |
| 81 private: | 81 private: |
| 82 // AudioOutputStream::AudioSourceCallback overrides: | 82 // AudioOutputStream::AudioSourceCallback overrides: |
| 83 // Following methods could be called from *ANY* thread. | 83 // Following methods could be called from *ANY* thread. |
| 84 virtual int OnMoreData(AudioBus* dest, | 84 virtual int OnMoreData(AudioBus* dest, |
| 85 AudioBuffersState /* state */) OVERRIDE { | 85 AudioBuffersState /* state */) OVERRIDE { |
| 86 size_t bytes_written = 0; | 86 size_t bytes_written = 0; |
| 87 if (wav_audio_.AtEnd(cursor_) || | 87 if (wav_audio_.AtEnd(cursor_) || |
| 88 !wav_audio_.CopyTo(dest, cursor_, &bytes_written)) { | 88 !wav_audio_.CopyTo(dest, cursor_, &bytes_written)) { |
| 89 AudioManager::Get()->GetMessageLoop()->PostTask( | 89 AudioManager::Get()->GetTaskRunner()->PostTask( |
| 90 FROM_HERE, | 90 FROM_HERE, |
| 91 base::Bind(&AudioStreamContainer::Stop, base::Unretained(this))); | 91 base::Bind(&AudioStreamContainer::Stop, base::Unretained(this))); |
| 92 return 0; | 92 return 0; |
| 93 } | 93 } |
| 94 cursor_ += bytes_written; | 94 cursor_ += bytes_written; |
| 95 | 95 |
| 96 return dest->frames(); | 96 return dest->frames(); |
| 97 } | 97 } |
| 98 | 98 |
| 99 virtual int OnMoreIOData(AudioBus* /* source */, | 99 virtual int OnMoreIOData(AudioBus* /* source */, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 if (!params.IsValid()) { | 133 if (!params.IsValid()) { |
| 134 LOG(ERROR) << "Audio params are invalid."; | 134 LOG(ERROR) << "Audio params are invalid."; |
| 135 return; | 135 return; |
| 136 } | 136 } |
| 137 stream_.reset(new AudioStreamContainer(wav_audio_, params)); | 137 stream_.reset(new AudioStreamContainer(wav_audio_, params)); |
| 138 initialized_ = true; | 138 initialized_ = true; |
| 139 } | 139 } |
| 140 | 140 |
| 141 AudioStreamHandler::~AudioStreamHandler() { | 141 AudioStreamHandler::~AudioStreamHandler() { |
| 142 DCHECK(CalledOnValidThread()); | 142 DCHECK(CalledOnValidThread()); |
| 143 AudioManager::Get()->GetMessageLoop()->PostTask( | 143 AudioManager::Get()->GetTaskRunner()->PostTask( |
| 144 FROM_HERE, | 144 FROM_HERE, |
| 145 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); | 145 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); |
| 146 AudioManager::Get()->GetMessageLoop()->DeleteSoon(FROM_HERE, | 146 AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE, |
| 147 stream_.release()); | 147 stream_.release()); |
| 148 } | 148 } |
| 149 | 149 |
| 150 bool AudioStreamHandler::IsInitialized() const { | 150 bool AudioStreamHandler::IsInitialized() const { |
| 151 DCHECK(CalledOnValidThread()); | 151 DCHECK(CalledOnValidThread()); |
| 152 return initialized_; | 152 return initialized_; |
| 153 } | 153 } |
| 154 | 154 |
| 155 bool AudioStreamHandler::Play() { | 155 bool AudioStreamHandler::Play() { |
| 156 DCHECK(CalledOnValidThread()); | 156 DCHECK(CalledOnValidThread()); |
| 157 | 157 |
| 158 if (!IsInitialized()) | 158 if (!IsInitialized()) |
| 159 return false; | 159 return false; |
| 160 | 160 |
| 161 AudioManager::Get()->GetMessageLoop()->PostTask( | 161 AudioManager::Get()->GetTaskRunner()->PostTask( |
| 162 FROM_HERE, | 162 FROM_HERE, |
| 163 base::Bind(base::IgnoreResult(&AudioStreamContainer::Play), | 163 base::Bind(base::IgnoreResult(&AudioStreamContainer::Play), |
| 164 base::Unretained(stream_.get()))); | 164 base::Unretained(stream_.get()))); |
| 165 return true; | 165 return true; |
| 166 } | 166 } |
| 167 | 167 |
| 168 void AudioStreamHandler::Stop() { | 168 void AudioStreamHandler::Stop() { |
| 169 DCHECK(CalledOnValidThread()); | 169 DCHECK(CalledOnValidThread()); |
| 170 AudioManager::Get()->GetMessageLoop()->PostTask( | 170 AudioManager::Get()->GetTaskRunner()->PostTask( |
| 171 FROM_HERE, | 171 FROM_HERE, |
| 172 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); | 172 base::Bind(&AudioStreamContainer::Stop, base::Unretained(stream_.get()))); |
| 173 } | 173 } |
| 174 | 174 |
| 175 // static | 175 // static |
| 176 void AudioStreamHandler::SetObserverForTesting(TestObserver* observer) { | 176 void AudioStreamHandler::SetObserverForTesting(TestObserver* observer) { |
| 177 g_observer_for_testing = observer; | 177 g_observer_for_testing = observer; |
| 178 } | 178 } |
| 179 | 179 |
| 180 // static | 180 // static |
| 181 void AudioStreamHandler::SetAudioSourceForTesting( | 181 void AudioStreamHandler::SetAudioSourceForTesting( |
| 182 AudioOutputStream::AudioSourceCallback* source) { | 182 AudioOutputStream::AudioSourceCallback* source) { |
| 183 g_audio_source_for_testing = source; | 183 g_audio_source_for_testing = source; |
| 184 } | 184 } |
| 185 | 185 |
| 186 } // namespace media | 186 } // namespace media |
| OLD | NEW |