From f8946263f5f66f5e326d30ca8da1fe43c408db6f Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Thu, 30 Jul 2015 16:04:25 -0700 Subject: [PATCH] Bug 1187105 - Pause speechsynthesis on empty queue. r=smaug --- dom/media/webspeech/synth/SpeechSynthesis.cpp | 35 +++++++++++++------ dom/media/webspeech/synth/SpeechSynthesis.h | 3 +- .../synth/test/file_speech_cancel.html | 8 +++++ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/dom/media/webspeech/synth/SpeechSynthesis.cpp b/dom/media/webspeech/synth/SpeechSynthesis.cpp index e09537685a9c..b93c2878439a 100644 --- a/dom/media/webspeech/synth/SpeechSynthesis.cpp +++ b/dom/media/webspeech/synth/SpeechSynthesis.cpp @@ -72,6 +72,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(SpeechSynthesis) SpeechSynthesis::SpeechSynthesis(nsPIDOMWindow* aParent) : mParent(aParent) + , mHoldQueue(false) { MOZ_ASSERT(aParent->IsInnerWindow()); } @@ -120,11 +121,8 @@ SpeechSynthesis::Speaking() const bool SpeechSynthesis::Paused() const { - if (mSpeechQueue.IsEmpty()) { - return false; - } - - return mSpeechQueue.ElementAt(0)->IsPaused(); + return mHoldQueue || + (!mSpeechQueue.IsEmpty() && mSpeechQueue.ElementAt(0)->IsPaused()); } void @@ -138,7 +136,7 @@ SpeechSynthesis::Speak(SpeechSynthesisUtterance& aUtterance) mSpeechQueue.AppendElement(&aUtterance); aUtterance.mState = SpeechSynthesisUtterance::STATE_PENDING; - if (mSpeechQueue.Length() == 1 && !mCurrentTask) { + if (mSpeechQueue.Length() == 1 && !mCurrentTask && !mHoldQueue) { AdvanceQueue(); } } @@ -181,28 +179,43 @@ void SpeechSynthesis::Cancel() { if (mCurrentTask) { - if (mSpeechQueue.Length() > 1) { + if (mSpeechQueue.Length() > 1) { // Remove all queued utterances except for current one. mSpeechQueue.RemoveElementsAt(1, mSpeechQueue.Length() - 1); } - - mCurrentTask->Cancel(); + mCurrentTask->Cancel(); + } else { + mSpeechQueue.Clear(); } } void SpeechSynthesis::Pause() { - if (mCurrentTask && !Paused() && (Speaking() || Pending())) { + if (Paused()) { + return; + } + + if (mCurrentTask && + mSpeechQueue.ElementAt(0)->GetState() != SpeechSynthesisUtterance::STATE_ENDED) { mCurrentTask->Pause(); + } else { + mHoldQueue = true; } } void SpeechSynthesis::Resume() { - if (mCurrentTask && Paused()) { + if (!Paused()) { + return; + } + + if (mCurrentTask) { mCurrentTask->Resume(); + } else { + mHoldQueue = false; + AdvanceQueue(); } } diff --git a/dom/media/webspeech/synth/SpeechSynthesis.h b/dom/media/webspeech/synth/SpeechSynthesis.h index 4b779f9616eb..2efab85bf80a 100644 --- a/dom/media/webspeech/synth/SpeechSynthesis.h +++ b/dom/media/webspeech/synth/SpeechSynthesis.h @@ -66,9 +66,10 @@ private: nsRefPtr mCurrentTask; nsRefPtrHashtable mVoiceCache; + + bool mHoldQueue; }; } // namespace dom } // namespace mozilla - #endif diff --git a/dom/media/webspeech/synth/test/file_speech_cancel.html b/dom/media/webspeech/synth/test/file_speech_cancel.html index 78a473176324..293dc76fb29b 100644 --- a/dom/media/webspeech/synth/test/file_speech_cancel.html +++ b/dom/media/webspeech/synth/test/file_speech_cancel.html @@ -71,6 +71,14 @@ utterance3.addEventListener('end', function(e) { SimpleTest.finish(); }); +// Speak/cancel while paused (Bug 1187105) +speechSynthesis.pause(); +speechSynthesis.speak(new SpeechSynthesisUtterance("hello.")); +ok(speechSynthesis.pending, "paused speechSynthesis has an utterance queued."); +speechSynthesis.cancel(); +ok(!speechSynthesis.pending, "paused speechSynthesis has no utterance queued."); +speechSynthesis.resume(); + speechSynthesis.speak(utterance); ok(!speechSynthesis.speaking, "speechSynthesis is not speaking yet."); ok(speechSynthesis.pending, "speechSynthesis has an utterance queued.");