From 259a7235672718409bfbeab32acab1777765d3d7 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 21 Aug 2015 11:58:06 +0100 Subject: [PATCH] Bug 1191814 - WebSpeech synthesis API and AudioChannelService, r=eeejay --- .../synth/ipc/PSpeechSynthesisRequest.ipdl | 2 + .../synth/ipc/SpeechSynthesisChild.cpp | 8 +++ .../synth/ipc/SpeechSynthesisChild.h | 2 + .../synth/ipc/SpeechSynthesisParent.cpp | 8 +++ .../synth/ipc/SpeechSynthesisParent.h | 2 + dom/media/webspeech/synth/nsSpeechTask.cpp | 57 ++++++++++++++++++- dom/media/webspeech/synth/nsSpeechTask.h | 11 ++++ 7 files changed, 89 insertions(+), 1 deletion(-) diff --git a/dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl b/dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl index 9a146145bbd..d244b1708ca 100644 --- a/dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl +++ b/dom/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl @@ -23,6 +23,8 @@ async protocol PSpeechSynthesisRequest ForceEnd(); + SetAudioOutputVolume(uint32_t aVolume); + child: __delete__(bool aIsError, float aElapsedTime, uint32_t aCharIndex); diff --git a/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp index c6f4e60258a..04acb3e9e5d 100644 --- a/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp +++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp @@ -191,5 +191,13 @@ SpeechTaskChild::ForceEnd() mActor->SendForceEnd(); } +void +SpeechTaskChild::SetAudioOutputVolume(uint32_t aVolume) +{ + if (mActor) { + mActor->SendSetAudioOutputVolume(aVolume); + } +} + } // namespace dom } // namespace mozilla diff --git a/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h index a89cbaa4381..cb0d7d78f84 100644 --- a/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h +++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h @@ -92,6 +92,8 @@ public: virtual void ForceEnd() override; + virtual void SetAudioOutputVolume(uint32_t aVolume) override; + private: SpeechSynthesisRequestChild* mActor; }; diff --git a/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp b/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp index e6ef6d65461..6729f3bbf62 100644 --- a/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp +++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.cpp @@ -127,6 +127,14 @@ SpeechSynthesisRequestParent::RecvForceEnd() return true; } +bool +SpeechSynthesisRequestParent::RecvSetAudioOutputVolume(const uint32_t& aVolume) +{ + MOZ_ASSERT(mTask); + mTask->SetAudioOutputVolume(aVolume); + return true; +} + // SpeechTaskParent nsresult diff --git a/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h b/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h index 67272583c5d..95417666f21 100644 --- a/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h +++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h @@ -69,6 +69,8 @@ protected: virtual bool RecvCancel() override; virtual bool RecvForceEnd() override; + + virtual bool RecvSetAudioOutputVolume(const uint32_t& aVolume) override; }; class SpeechTaskParent : public nsSpeechTask diff --git a/dom/media/webspeech/synth/nsSpeechTask.cpp b/dom/media/webspeech/synth/nsSpeechTask.cpp index efe7c66c0ec..00bef46f424 100644 --- a/dom/media/webspeech/synth/nsSpeechTask.cpp +++ b/dom/media/webspeech/synth/nsSpeechTask.cpp @@ -4,10 +4,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "AudioChannelAgent.h" +#include "AudioChannelService.h" #include "AudioSegment.h" #include "nsSpeechTask.h" -#include "SpeechSynthesis.h" #include "nsSynthVoiceRegistry.h" +#include "SpeechSynthesis.h" // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to // GetTickCount() and conflicts with nsSpeechTask::GetCurrentTime(). @@ -89,6 +91,7 @@ NS_IMPL_CYCLE_COLLECTION(nsSpeechTask, mSpeechSynthesis, mUtterance, mCallback); NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSpeechTask) NS_INTERFACE_MAP_ENTRY(nsISpeechTask) + NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgentCallback) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISpeechTask) NS_INTERFACE_MAP_END @@ -314,6 +317,8 @@ nsSpeechTask::DispatchStart() nsresult nsSpeechTask::DispatchStartInner() { + CreateAudioChannelAgent(); + nsSynthVoiceRegistry::GetInstance()->SetIsSpeaking(true); return DispatchStartImpl(); } @@ -356,6 +361,8 @@ nsSpeechTask::DispatchEnd(float aElapsedTime, uint32_t aCharIndex) nsresult nsSpeechTask::DispatchEndInner(float aElapsedTime, uint32_t aCharIndex) { + DestroyAudioChannelAgent(); + if (!mPreCanceled) { nsSynthVoiceRegistry::GetInstance()->SpeakNext(); } @@ -645,5 +652,53 @@ nsSpeechTask::SetSpeechSynthesis(SpeechSynthesis* aSpeechSynthesis) mSpeechSynthesis = aSpeechSynthesis; } +void +nsSpeechTask::CreateAudioChannelAgent() +{ + if (!mUtterance) { + return; + } + + if (mAudioChannelAgent) { + mAudioChannelAgent->NotifyStoppedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY); + } + + mAudioChannelAgent = new AudioChannelAgent(); + mAudioChannelAgent->InitWithWeakCallback(mUtterance->GetOwner(), + static_cast(AudioChannelService::GetDefaultAudioChannel()), + this); +} + +void +nsSpeechTask::DestroyAudioChannelAgent() +{ + if (mAudioChannelAgent) { + mAudioChannelAgent->NotifyStoppedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY); + mAudioChannelAgent = nullptr; + } +} + +NS_IMETHODIMP +nsSpeechTask::WindowVolumeChanged(float aVolume, bool aMuted) +{ + SetAudioOutputVolume(mVolume * aVolume * aMuted); + return NS_OK; +} + +NS_IMETHODIMP +nsSpeechTask::WindowAudioCaptureChanged() +{ + // This is not supported yet. + return NS_OK; +} + +void +nsSpeechTask::SetAudioOutputVolume(uint32_t aVolume) +{ + if (mStream) { + mStream->SetAudioOutputVolume(this, aVolume); + } +} + } // namespace dom } // namespace mozilla diff --git a/dom/media/webspeech/synth/nsSpeechTask.h b/dom/media/webspeech/synth/nsSpeechTask.h index 70e7929ef6a..327f2a93032 100644 --- a/dom/media/webspeech/synth/nsSpeechTask.h +++ b/dom/media/webspeech/synth/nsSpeechTask.h @@ -9,6 +9,7 @@ #include "MediaStreamGraph.h" #include "SpeechSynthesisUtterance.h" +#include "nsIAudioChannelAgent.h" #include "nsISpeechService.h" namespace mozilla { @@ -19,6 +20,7 @@ class SpeechSynthesis; class SynthStreamListener; class nsSpeechTask : public nsISpeechTask + , public nsIAudioChannelAgentCallback { friend class SynthStreamListener; @@ -27,6 +29,7 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsSpeechTask, nsISpeechTask) NS_DECL_NSISPEECHTASK + NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK explicit nsSpeechTask(SpeechSynthesisUtterance* aUtterance); nsSpeechTask(float aVolume, const nsAString& aText); @@ -49,6 +52,8 @@ public: void SetChosenVoiceURI(const nsAString& aUri); + virtual void SetAudioOutputVolume(uint32_t aVolume); + bool IsPreCanceled() { return mPreCanceled; @@ -102,12 +107,18 @@ private: nsresult DispatchEndInner(float aElapsedTime, uint32_t aCharIndex); + void CreateAudioChannelAgent(); + + void DestroyAudioChannelAgent(); + nsRefPtr mStream; nsRefPtr mPort; nsCOMPtr mCallback; + nsCOMPtr mAudioChannelAgent; + uint32_t mChannels; nsRefPtr mSpeechSynthesis;