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

Unified Diff: media/audio/audio_output_controller.cc

Issue 11413078: Tab Audio Capture: Browser-side connect/disconnect functionality. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed tommi's comments (dependency injection for testing AudioMirroringManager). Created 8 years 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 side-by-side diff with in-line comments
Download patch
Index: media/audio/audio_output_controller.cc
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc
index 50850c9265cdd2b0f503e97994a122b70167047d..1375c5d0d303b1028f833586ac6dff84b9b83c34 100644
--- a/media/audio/audio_output_controller.cc
+++ b/media/audio/audio_output_controller.cc
@@ -29,15 +29,19 @@ 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)) {
+ // This thread-checker is only used to ensure calls to StartDiverting() and
+ // StopDiverting() are made by the same single outside thread.
+ divert_thread_checker_.DetachFromThread();
}
AudioOutputController::~AudioOutputController() {
@@ -70,13 +74,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;
}
@@ -120,7 +121,8 @@ void AudioOutputController::DoCreate() {
DCHECK(state_ == kEmpty || state_ == kRecreating) << state_;
DoStopCloseAndClearStream(NULL);
- stream_ = audio_manager_->MakeAudioOutputStreamProxy(params_);
+ stream_ = diverting_to_stream_ ? diverting_to_stream_ :
+ audio_manager_->MakeAudioOutputStreamProxy(params_);
if (!stream_) {
state_ = kError;
@@ -138,9 +140,11 @@ void AudioOutputController::DoCreate() {
return;
}
- // Everything started okay, so register for state change callbacks if we have
- // not already done so.
- if (state_ != kRecreating)
+ // Everything started okay, so re-register for state change callbacks if
+ // stream_ was created via AudioManager. Note: The call to
+ // DoStopCloseAndClearStream() above called
+ // RemoveOutputDeviceChangeListener().
+ if (stream_ != diverting_to_stream_)
audio_manager_->AddOutputDeviceChangeListener(this);
// We have successfully opened the stream. Set the initial volume.
@@ -348,13 +352,17 @@ void AudioOutputController::DoStopCloseAndClearStream(WaitableEvent* done) {
// Allow calling unconditionally and bail if we don't have a stream_ to close.
if (stream_) {
+ // 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;
- audio_manager_->RemoveOutputDeviceChangeListener(this);
- audio_manager_ = NULL;
-
weak_this_.InvalidateWeakPtrs();
}
@@ -366,16 +374,9 @@ void AudioOutputController::DoStopCloseAndClearStream(WaitableEvent* done) {
void AudioOutputController::OnDeviceChange() {
DCHECK(message_loop_->BelongsToCurrentThread());
- // We should always have a stream by this point.
- CHECK(stream_);
-
- // Preserve the original state and shutdown the stream.
- State original_state = state_;
- stream_->Stop();
- stream_->Close();
- stream_ = NULL;
-
- // Recreate the stream, exit if we ran into an error.
+ // Recreate the stream (DoCreate() will first shut down an existing stream).
+ // Exit if we ran into an error.
+ const State original_state = state_;
state_ = kRecreating;
DoCreate();
if (!stream_ || state_ == kError)
@@ -397,4 +398,33 @@ void AudioOutputController::OnDeviceChange() {
}
}
+void AudioOutputController::StartDiverting(AudioOutputStream* to_stream) {
+ if (!message_loop_->BelongsToCurrentThread()) {
DaleCurtis 2013/01/02 21:56:44 This is still odd and inconsistent with the rest o
miu 2013/01/03 22:30:42 Done.
+ DCHECK(divert_thread_checker_.CalledOnValidThread());
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioOutputController::StartDiverting, this, to_stream));
+ return;
+ }
+
+ DCHECK(!diverting_to_stream_);
+ diverting_to_stream_ = to_stream;
+ DCHECK_NE(kClosed, state_);
DaleCurtis 2013/01/02 21:56:44 Instead of a DHCECK_NE, shouldn't this be an if (s
miu 2013/01/03 22:30:42 Done.
+ OnDeviceChange();
+}
+
+void AudioOutputController::StopDiverting() {
DaleCurtis 2013/01/02 21:56:44 Ditto.
miu 2013/01/03 22:30:42 Done.
+ if (!message_loop_->BelongsToCurrentThread()) {
+ DCHECK(divert_thread_checker_.CalledOnValidThread());
+ message_loop_->PostTask(
+ FROM_HERE, base::Bind(&AudioOutputController::StopDiverting, this));
+ return;
+ }
+
+ if (state_ != kClosed) {
+ OnDeviceChange();
DaleCurtis 2013/01/02 21:56:44 This needs a comment since it's subtle that OnDevi
miu 2013/01/03 22:30:42 Done.
+ DCHECK(!diverting_to_stream_);
+ }
+}
+
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698