Index: media/audio/audio_output_controller.cc |
=================================================================== |
--- media/audio/audio_output_controller.cc (revision 106670) |
+++ media/audio/audio_output_controller.cc (working copy) |
@@ -176,9 +176,10 @@ |
// We can start from created or paused state. |
if (state_ != kCreated && state_ != kPaused) |
return; |
- state_ = kPlaying; |
if (LowLatencyMode()) { |
+ state_ = kStarting; |
+ |
// Ask for first packet. |
sync_reader_->UpdatePendingBytes(0); |
@@ -199,7 +200,7 @@ |
// Being paranoic: do nothing if we were stopped/paused |
// after DoPlay() but before DoStartStream(). |
- if (state_ != kPlaying) |
+ if (state_ != kStarting) |
return; |
if (--number_polling_attempts_left_ == 0 || sync_reader_->DataReady()) { |
@@ -214,6 +215,7 @@ |
void AudioOutputController::StartStream() { |
DCHECK_EQ(message_loop_, MessageLoop::current()); |
+ state_ = kPlaying; |
// We start the AudioOutputStream lazily. |
stream_->Start(this); |
@@ -225,22 +227,38 @@ |
void AudioOutputController::DoPause() { |
DCHECK_EQ(message_loop_, MessageLoop::current()); |
- // We can pause from started state. |
- if (state_ != kPlaying) |
- return; |
- state_ = kPaused; |
+ switch (state_) { |
+ case kStarting: |
+ // We were asked to pause while starting. There is delayed task that will |
+ // try starting playback, and there is no way to remove that task from the |
+ // queue. If we stop now that task will be executed anyway. |
+ // We can set state to "paused" and avoid problem in the simple case, |
+ // but we can be asked to start playback for 2nd time before it started |
+ // for the 1st time, and there would be new set of problems. |
+ // Simplest solution is to delay pause a little till playback starts. |
+ message_loop_->PostDelayedTask( |
acolwell GONE FROM CHROMIUM
2011/10/24 03:47:15
This doesn't smell right. Can we add a kPauseWhile
enal1
2011/10/24 16:28:29
Initially I wrote code similar to what you suggest
acolwell GONE FROM CHROMIUM
2011/10/24 16:59:58
I'm afraid I'm going to have to insist here. I REA
|
+ FROM_HERE, |
+ base::Bind( &AudioOutputController::DoPause, this), |
+ kPollPauseInMilliseconds); |
+ break; |
+ case kPlaying: |
+ state_ = kPaused; |
- // Then we stop the audio device. This is not the perfect solution because |
- // it discards all the internal buffer in the audio device. |
- // TODO(hclam): Actually pause the audio device. |
- stream_->Stop(); |
+ // Then we stop the audio device. This is not the perfect solution |
+ // because it discards all the internal buffer in the audio device. |
+ // TODO(hclam): Actually pause the audio device. |
+ stream_->Stop(); |
- if (LowLatencyMode()) { |
- // Send a special pause mark to the low-latency audio thread. |
- sync_reader_->UpdatePendingBytes(kPauseMark); |
+ if (LowLatencyMode()) { |
+ // Send a special pause mark to the low-latency audio thread. |
+ sync_reader_->UpdatePendingBytes(kPauseMark); |
+ } |
+ |
+ handler_->OnPaused(this); |
+ break; |
+ default: |
+ return; |
} |
- |
- handler_->OnPaused(this); |
} |
void AudioOutputController::DoFlush() { |
@@ -287,10 +305,16 @@ |
// right away but when the stream is created we'll set the volume. |
volume_ = volume; |
- if (state_ != kPlaying && state_ != kPaused && state_ != kCreated) |
- return; |
- |
- stream_->SetVolume(volume_); |
+ switch (state_) { |
+ case kCreated: |
+ case kStarting: |
+ case kPlaying: |
+ case kPaused: |
+ stream_->SetVolume(volume_); |
+ break; |
+ default: |
+ return; |
+ } |
} |
void AudioOutputController::DoReportError(int code) { |