Bug 469275 - Seeks requested while Wave state machine is in ended state are lost. r+sr=roc

--HG--
extra : rebase_source : 03ead0a2032ac705b2156bb1b02aef33a414c67b
This commit is contained in:
Matthew Gregan 2009-02-24 15:34:36 +13:00
parent 3a177d3880
commit b6b81dc5ee

View File

@ -354,6 +354,9 @@ private:
// run. This allows coalescing of these events as they can be produced
// many times per second.
PRPackedBool mPositionChangeQueued;
// True if paused. Tracks only the play/paused state.
PRPackedBool mPaused;
};
nsWaveStateMachine::nsWaveStateMachine(nsWaveDecoder* aDecoder, nsMediaStream* aStream,
@ -379,7 +382,8 @@ nsWaveStateMachine::nsWaveStateMachine(nsWaveDecoder* aDecoder, nsMediaStream* a
mTimeOffset(0),
mSeekTime(0.0),
mMetadataValid(PR_FALSE),
mPositionChangeQueued(PR_FALSE)
mPositionChangeQueued(PR_FALSE),
mPaused(mNextState == STATE_PAUSED)
{
mMonitor = nsAutoMonitor::NewMonitor("nsWaveStateMachine");
mDownloadStatistics.Start(PR_IntervalNow());
@ -400,6 +404,7 @@ void
nsWaveStateMachine::Play()
{
nsAutoMonitor monitor(mMonitor);
mPaused = PR_FALSE;
if (mState == STATE_LOADING_METADATA || mState == STATE_SEEKING) {
mNextState = STATE_PLAYING;
} else {
@ -431,6 +436,7 @@ void
nsWaveStateMachine::Pause()
{
nsAutoMonitor monitor(mMonitor);
mPaused = PR_TRUE;
if (mState == STATE_LOADING_METADATA || mState == STATE_SEEKING) {
mNextState = STATE_PAUSED;
} else {
@ -722,14 +728,21 @@ nsWaveStateMachine::Run()
}
if (mState == STATE_SEEKING && mSeekTime == seekTime) {
// Special case: if a seek was requested during metadata load,
// Special case #1: if a seek was requested during metadata load,
// mNextState will have been clobbered. This can only happen when
// we're instantiating a decoder to service a seek request after
// playback has ended, so we know that the clobbered mNextState
// was PAUSED.
// Special case #2: if a seek is requested after the state machine
// entered STATE_ENDED but before the user has seen the ended
// event, playback has not ended as far as the user's
// concerned--the state machine needs to return to the last
// playback state.
State nextState = mNextState;
if (nextState == STATE_SEEKING) {
nextState = STATE_PAUSED;
} else if (nextState == STATE_ENDED) {
nextState = mPaused ? STATE_PAUSED : STATE_PLAYING;
}
ChangeState(nextState);
}
@ -757,14 +770,14 @@ nsWaveStateMachine::Run()
monitor.Enter();
}
if (mState != STATE_SHUTDOWN) {
if (mState == STATE_ENDED) {
nsCOMPtr<nsIRunnable> event =
NS_NEW_RUNNABLE_METHOD(nsWaveDecoder, mDecoder, PlaybackEnded);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
}
while (mState != STATE_SHUTDOWN) {
monitor.Wait();
do {
monitor.Wait();
} while (mState == STATE_ENDED);
}
break;
@ -823,6 +836,9 @@ IsValidStateTransition(State aStartState, State aEndState)
return PR_TRUE;
break;
case STATE_ENDED:
if (aEndState == STATE_SEEKING)
return PR_TRUE;
/* fallthrough */
case STATE_ERROR:
case STATE_SHUTDOWN:
break;
@ -1428,6 +1444,10 @@ nsWaveDecoder::PlaybackEnded()
return;
}
if (!mPlaybackStateMachine->IsEnded()) {
return;
}
Stop();
if (mElement) {
mElement->PlaybackEnded();