| Index: media/audio/audio_output_controller.cc
|
| diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc
|
| index d780687d1b8415aee8f6223be8497905a80b8800..4262f69f46971aa114aff009d463838c9f8325e5 100644
|
| --- a/media/audio/audio_output_controller.cc
|
| +++ b/media/audio/audio_output_controller.cc
|
| @@ -119,7 +119,8 @@ void AudioOutputController::DoCreate(bool is_for_device_change) {
|
| if (state_ == kClosed)
|
| return;
|
|
|
| - DoStopCloseAndClearStream(); // Calls RemoveOutputDeviceChangeListener().
|
| + DoStopCloseAndClearStream(
|
| + is_for_device_change); // Calls RemoveOutputDeviceChangeListener().
|
| DCHECK_EQ(kEmpty, state_);
|
|
|
| stream_ = diverting_to_stream_ ?
|
| @@ -132,7 +133,7 @@ void AudioOutputController::DoCreate(bool is_for_device_change) {
|
| }
|
|
|
| if (!stream_->Open()) {
|
| - DoStopCloseAndClearStream();
|
| + DoStopCloseAndClearStream(false);
|
| state_ = kError;
|
| handler_->OnError();
|
| return;
|
| @@ -169,6 +170,9 @@ void AudioOutputController::DoPlay() {
|
| state_ = kPlaying;
|
|
|
| stream_->Start(this);
|
| + for (auto& item : duplicator_) {
|
| + item->Start();
|
| + }
|
|
|
| // For UMA tracking purposes, start the wedge detection timer. This allows us
|
| // to record statistics about the number of wedged playbacks in the field.
|
| @@ -196,6 +200,9 @@ void AudioOutputController::StopStream() {
|
| wedge_timer_.reset();
|
| stream_->Stop();
|
|
|
| + for (auto& item : duplicator_) {
|
| + item->Stop();
|
| + }
|
| // A stopped stream is silent, and power_montior_.Scan() is no longer being
|
| // called; so we must reset the power monitor.
|
| power_monitor_.Reset();
|
| @@ -228,7 +235,7 @@ void AudioOutputController::DoClose() {
|
| TRACE_EVENT0("audio", "AudioOutputController::DoClose");
|
|
|
| if (state_ != kClosed) {
|
| - DoStopCloseAndClearStream();
|
| + DoStopCloseAndClearStream(false);
|
| sync_reader_->Close();
|
| state_ = kClosed;
|
| }
|
| @@ -304,6 +311,9 @@ int AudioOutputController::OnMoreData(AudioBus* dest,
|
| if (will_monitor_audio_levels())
|
| power_monitor_.Scan(*dest, frames);
|
|
|
| + for (auto sink : duplicator_)
|
| + sink->OnData(nullptr, dest, total_bytes_delay, 1);
|
| +
|
| return frames;
|
| }
|
|
|
| @@ -319,7 +329,7 @@ void AudioOutputController::OnError(AudioOutputStream* stream) {
|
| &AudioOutputController::DoReportError, this));
|
| }
|
|
|
| -void AudioOutputController::DoStopCloseAndClearStream() {
|
| +void AudioOutputController::DoStopCloseAndClearStream(bool isForDeviceChange) {
|
| DCHECK(message_loop_->BelongsToCurrentThread());
|
|
|
| // Allow calling unconditionally and bail if we don't have a stream_ to close.
|
| @@ -336,6 +346,11 @@ void AudioOutputController::DoStopCloseAndClearStream() {
|
|
|
| StopStream();
|
| stream_->Close();
|
| + if (!isForDeviceChange) {
|
| + for (auto& item : duplicator_) {
|
| + item->Close();
|
| + }
|
| + }
|
| if (stream_ == diverting_to_stream_)
|
| diverting_to_stream_ = NULL;
|
| stream_ = NULL;
|
| @@ -392,6 +407,18 @@ void AudioOutputController::StopDiverting() {
|
| FROM_HERE, base::Bind(&AudioOutputController::DoStopDiverting, this));
|
| }
|
|
|
| +void AudioOutputController::StartDuplicating(AudioPushSink* to_stream) {
|
| + message_loop_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&AudioOutputController::DoStartDuplicating, this, to_stream));
|
| +}
|
| +
|
| +void AudioOutputController::StopDuplicating(AudioPushSink* to_stream) {
|
| + message_loop_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&AudioOutputController::DoStopDuplicating, this, to_stream));
|
| +}
|
| +
|
| void AudioOutputController::DoStartDiverting(AudioOutputStream* to_stream) {
|
| DCHECK(message_loop_->BelongsToCurrentThread());
|
|
|
| @@ -419,6 +446,36 @@ void AudioOutputController::DoStopDiverting() {
|
| DCHECK(!diverting_to_stream_);
|
| }
|
|
|
| +void AudioOutputController::DoStartDuplicating(AudioPushSink* to_stream) {
|
| + DCHECK(message_loop_->BelongsToCurrentThread());
|
| + printf("StartDup\n");
|
| + if (state_ == kClosed)
|
| + return;
|
| +
|
| + // Already serving the stream.
|
| + if (duplicator_.find(to_stream) != duplicator_.end())
|
| + return;
|
| +
|
| + duplicator_.insert(to_stream);
|
| + if (state_ == kPlaying)
|
| + to_stream->Start();
|
| +}
|
| +
|
| +void AudioOutputController::DoStopDuplicating(AudioPushSink* to_stream) {
|
| + DCHECK(message_loop_->BelongsToCurrentThread());
|
| +
|
| + if (state_ == kClosed)
|
| + return;
|
| +
|
| + // No such stream.
|
| + if (duplicator_.find(to_stream) == duplicator_.end())
|
| + return;
|
| +
|
| + to_stream->Stop();
|
| + to_stream->Close();
|
| + duplicator_.erase(to_stream);
|
| +}
|
| +
|
| std::pair<float, bool> AudioOutputController::ReadCurrentPowerAndClip() {
|
| DCHECK(will_monitor_audio_levels());
|
| return power_monitor_.ReadCurrentPowerAndClip();
|
|
|