Index: media/audio/restartable_audio_output_device_impl.cc |
diff --git a/media/audio/restartable_audio_output_device_impl.cc b/media/audio/restartable_audio_output_device_impl.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a1b2d1ce09262618e287343fe7cbcc21d2faab07 |
--- /dev/null |
+++ b/media/audio/restartable_audio_output_device_impl.cc |
@@ -0,0 +1,118 @@ |
+// Copyright (c) 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "media/audio/restartable_audio_output_device_impl.h" |
+ |
+#include "media/audio/audio_output_device.h" |
+ |
+namespace media { |
+ |
+RestartableAudioOutputDeviceImpl::RestartableAudioOutputDeviceImpl( |
+ const GetSinkCB& get_sink_cb, |
+ const GetHWParamsCB& get_hw_params_cb) |
+ : state_(kStopped), |
+ volume_(1.0f), |
+ render_cb_(nullptr), |
+ get_sink_cb_(get_sink_cb), |
+ get_hw_params_cb_(get_hw_params_cb), |
+ // Creating output device now, since it may be needed to get output |
+ // parameters before the device is started. |
+ sink_(get_sink_cb_.Run()) {} |
+ |
+void RestartableAudioOutputDeviceImpl::Initialize(const AudioParameters& params, |
+ RenderCallback* callback) { |
+ DCHECK_EQ(state_, kStopped) << "Calling Initialize() on a running device."; |
+ DCHECK(callback); |
+ |
+ params_ = params; |
+ render_cb_ = callback; |
+} |
+ |
+RestartableAudioOutputDeviceImpl::~RestartableAudioOutputDeviceImpl() { |
+ DCHECK_EQ(state_, kStopped) << "Stop() has not been called."; |
+ if (sink_) |
+ sink_->Stop(); // AudioOutputDevice must be stopped. |
+} |
+ |
+void RestartableAudioOutputDeviceImpl::Start() { |
+ DCHECK_EQ(state_, kStopped) << "Already started."; |
+ DCHECK(render_cb_) << "Initialize() has not been called."; |
+ |
+ state_ = kStarted; |
+ |
+ if (!sink_) { |
+ // Restarting the device after it was stopped. |
+ sink_ = get_sink_cb_.Run(); // Restarting the device after it was stopped. |
+ } // Otherwise the sink is created in the constructor. |
+ |
+ if (sink_->GetDeviceStatus() == OUTPUT_DEVICE_STATUS_OK) |
+ sink_->Initialize(params_, render_cb_); |
+} |
+ |
+void RestartableAudioOutputDeviceImpl::Stop() { |
+ if (sink_) { |
+ sink_->Stop(); |
+ sink_ = nullptr; // AudioOutputDevice cannot be restarted. |
+ } |
+ state_ = kStopped; |
+} |
+ |
+void RestartableAudioOutputDeviceImpl::Play() { |
+ if ((state_ == kPlaying) || (state_ == kStopped)) |
+ return; |
+ |
+ if (state_ == kPaused) |
+ sink_->Play(); |
+ else { // kStarted, it's the first time Play() is called. |
+ sink_->Start(); // AudioOutputDevice plays on start. |
+ sink_->SetVolume(volume_); |
+ } |
+ state_ = kPlaying; |
+} |
+ |
+void RestartableAudioOutputDeviceImpl::Pause() { |
+ if (state_ != kPlaying) |
+ return; |
+ |
+ sink_->Pause(); |
+ state_ = kPaused; |
+} |
+ |
+bool RestartableAudioOutputDeviceImpl::SetVolume(double volume) { |
+ volume_ = volume; |
+ if (sink_ && ((state_ == kPaused) || (state_ == kPlaying))) |
+ return sink_->SetVolume(volume_); // sink_->Start() is already called. |
+ return true; |
+} |
+ |
+OutputDevice* RestartableAudioOutputDeviceImpl::GetOutputDevice() { |
+ return this; |
+} |
+ |
+void RestartableAudioOutputDeviceImpl::SwitchOutputDevice( |
+ const std::string& device_id, |
+ const url::Origin& security_origin, |
+ const SwitchOutputDeviceCB& callback) { |
+ NOTREACHED(); |
+} |
+ |
+AudioParameters RestartableAudioOutputDeviceImpl::GetOutputParameters() { |
+ if (sink_) |
+ return sink_->GetOutputParameters(); |
+ |
+ return get_hw_params_cb_.Run(); |
+} |
+ |
+OutputDeviceStatus RestartableAudioOutputDeviceImpl::GetDeviceStatus() { |
+ if (sink_) |
+ return sink_->GetDeviceStatus(); |
+ |
+ // If there is no sink because the device was stopped: |
+ if (state_ == kStopped) |
+ return OUTPUT_DEVICE_STATUS_OK; |
+ |
+ return OUTPUT_DEVICE_STATUS_ERROR_INTERNAL; |
+} |
+ |
+} // namespace media |