Index: media/audio/audio_output_controller.cc |
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc |
index a9dd2c855c340ade8a95443a54418013f88cc6fd..ffeb639b7007039fe57c4f497fac142480180a7d 100644 |
--- a/media/audio/audio_output_controller.cc |
+++ b/media/audio/audio_output_controller.cc |
@@ -29,14 +29,15 @@ AudioOutputController::AudioOutputController(AudioManager* audio_manager, |
const AudioParameters& params, |
SyncReader* sync_reader) |
: audio_manager_(audio_manager), |
+ params_(params), |
handler_(handler), |
stream_(NULL), |
+ diverting_to_stream_(NULL), |
volume_(1.0), |
state_(kEmpty), |
sync_reader_(sync_reader), |
message_loop_(audio_manager->GetMessageLoop()), |
number_polling_attempts_left_(0), |
- params_(params), |
ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)) { |
} |
@@ -70,13 +71,10 @@ scoped_refptr<AudioOutputController> AudioOutputController::Create( |
if (!params.IsValid() || !audio_manager) |
return NULL; |
- // Starts the audio controller thread. |
scoped_refptr<AudioOutputController> controller(new AudioOutputController( |
audio_manager, event_handler, params, sync_reader)); |
- |
controller->message_loop_->PostTask(FROM_HERE, base::Bind( |
&AudioOutputController::DoCreate, controller)); |
- |
return controller; |
} |
@@ -121,7 +119,8 @@ void AudioOutputController::DoCreate() { |
DoStopCloseAndClearStream(NULL); // Calls RemoveOutputDeviceChangeListener(). |
- stream_ = audio_manager_->MakeAudioOutputStreamProxy(params_); |
+ stream_ = diverting_to_stream_ ? diverting_to_stream_ : |
+ audio_manager_->MakeAudioOutputStreamProxy(params_); |
if (!stream_) { |
state_ = kError; |
@@ -139,9 +138,10 @@ void AudioOutputController::DoCreate() { |
return; |
} |
- // Everything started okay, so register for state change callbacks if we have |
- // not already done so. |
- audio_manager_->AddOutputDeviceChangeListener(this); |
+ // Everything started okay, so re-register for state change callbacks if |
+ // stream_ was created via AudioManager. |
+ if (stream_ != diverting_to_stream_) |
+ audio_manager_->AddOutputDeviceChangeListener(this); |
// We have successfully opened the stream. Set the initial volume. |
stream_->SetVolume(volume_); |
@@ -349,10 +349,15 @@ void AudioOutputController::DoStopCloseAndClearStream(WaitableEvent* done) { |
// Allow calling unconditionally and bail if we don't have a stream_ to close. |
if (stream_) { |
- audio_manager_->RemoveOutputDeviceChangeListener(this); |
+ // De-register from state change callbacks if stream_ was created via |
+ // AudioManager. |
+ if (stream_ != diverting_to_stream_) |
+ audio_manager_->RemoveOutputDeviceChangeListener(this); |
stream_->Stop(); |
stream_->Close(); |
+ if (stream_ == diverting_to_stream_) |
+ diverting_to_stream_ = NULL; |
stream_ = NULL; |
weak_this_.InvalidateWeakPtrs(); |
@@ -366,9 +371,6 @@ void AudioOutputController::DoStopCloseAndClearStream(WaitableEvent* done) { |
void AudioOutputController::OnDeviceChange() { |
DCHECK(message_loop_->BelongsToCurrentThread()); |
- // We should always have a stream by this point. |
- CHECK(stream_); |
- |
// Recreate the stream (DoCreate() will first shut down an existing stream). |
// Exit if we ran into an error. |
const State original_state = state_; |
@@ -393,4 +395,46 @@ void AudioOutputController::OnDeviceChange() { |
} |
} |
+const AudioParameters& AudioOutputController::GetAudioParameters() { |
+ return params_; |
+} |
+ |
+void AudioOutputController::StartDiverting(AudioOutputStream* to_stream) { |
+ message_loop_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&AudioOutputController::DoStartDiverting, this, to_stream)); |
+} |
+ |
+void AudioOutputController::StopDiverting() { |
+ message_loop_->PostTask( |
+ FROM_HERE, base::Bind(&AudioOutputController::DoStopDiverting, this)); |
+} |
+ |
+void AudioOutputController::DoStartDiverting(AudioOutputStream* to_stream) { |
+ DCHECK(message_loop_->BelongsToCurrentThread()); |
+ |
+ if (state_ == kClosed) |
+ return; |
+ |
+ DCHECK(!diverting_to_stream_); |
+ diverting_to_stream_ = to_stream; |
+ // Note: OnDeviceChange() will engage the "re-create" process, which will |
+ // detect and use the alternate AudioOutputStream rather than create a new one |
+ // via AudioManager. |
+ OnDeviceChange(); |
+} |
+ |
+void AudioOutputController::DoStopDiverting() { |
+ DCHECK(message_loop_->BelongsToCurrentThread()); |
+ |
+ if (state_ == kClosed) |
+ return; |
+ |
+ // Note: OnDeviceChange() will cause the existing stream (the consumer of the |
+ // diverted audio data) to be closed, and diverting_to_stream_ will be set |
+ // back to NULL. |
+ OnDeviceChange(); |
+ DCHECK(!diverting_to_stream_); |
+} |
+ |
} // namespace media |