зеркало из https://github.com/mozilla/gecko-dev.git
Bug 525444 - (Part 1/3) Basic SpeechSynthesis setup and voice registration. r=smaug
--HG-- rename : content/media/webspeech/moz.build => content/media/webspeech/synth/moz.build rename : content/media/webspeech/moz.build => content/media/webspeech/synth/test/moz.build
This commit is contained in:
Родитель
542d52e905
Коммит
998738aff3
|
@ -751,6 +751,10 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
|
|||
@BINPATH@/components/B2GAboutRedirector.js
|
||||
@BINPATH@/components/FilePicker.js
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
@BINPATH@/components/dom_webspeechsynth.xpt
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
@BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
|
||||
#endif
|
||||
|
|
|
@ -540,6 +540,10 @@
|
|||
@BINPATH@/components/marionettecomponent.js
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
@BINPATH@/components/dom_webspeechsynth.xpt
|
||||
#endif
|
||||
|
||||
; Modules
|
||||
@BINPATH@/browser/modules/*
|
||||
@BINPATH@/modules/*
|
||||
|
|
|
@ -2164,4 +2164,7 @@ GK_ATOM(onspeechend, "onspeechend")
|
|||
GK_ATOM(onresult, "onresult")
|
||||
GK_ATOM(onnomatch, "onnomatch")
|
||||
GK_ATOM(onstart, "onstart")
|
||||
GK_ATOM(onresume, "onresume")
|
||||
GK_ATOM(onmark, "onmark")
|
||||
GK_ATOM(onboundary, "onboundary")
|
||||
#endif
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
# 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/.
|
||||
|
||||
PARALLEL_DIRS = ['recognition']
|
||||
PARALLEL_DIRS = ['recognition', 'synth']
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 "EnableSpeechSynthesisCheck.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
namespace {
|
||||
|
||||
bool gPrefInitialized = false;
|
||||
bool gWebSpeechEnabled = false;
|
||||
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/* static */ bool
|
||||
EnableSpeechSynthesisCheck::PrefEnabled()
|
||||
{
|
||||
if (!gPrefInitialized) {
|
||||
Preferences::AddBoolVarCache(&gWebSpeechEnabled, "media.webspeech.synth.enabled");
|
||||
gPrefInitialized = true;
|
||||
}
|
||||
|
||||
return gWebSpeechEnabled;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// This is a helper class which enables Web Speech to be enabled or disabled
|
||||
// as whole. Individual Web Speech object classes should inherit from this.
|
||||
class EnableSpeechSynthesisCheck
|
||||
{
|
||||
public:
|
||||
static bool PrefEnabled();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# 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/.
|
||||
|
||||
DEPTH := @DEPTH@
|
||||
topsrcdir := @top_srcdir@
|
||||
srcdir := @srcdir@
|
||||
VPATH := @srcdir@
|
||||
FAIL_ON_WARNINGS := 1
|
||||
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/dom/dom-config.mk
|
||||
|
||||
VPATH += \
|
||||
$(NULL)
|
||||
|
||||
LIBRARY_NAME := gkconwebspeechsynth_s
|
||||
EXPORT_LIBRARY = 1
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
LOCAL_INCLUDES += $(VPATH:%=-I%)
|
||||
|
||||
CPPSRCS := \
|
||||
EnableSpeechSynthesisCheck.cpp \
|
||||
SpeechSynthesisUtterance.cpp \
|
||||
SpeechSynthesisVoice.cpp \
|
||||
SpeechSynthesis.cpp \
|
||||
SpeechSynthesisChild.cpp \
|
||||
SpeechSynthesisParent.cpp \
|
||||
nsSynthVoiceRegistry.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_NAMESPACES := mozilla/dom
|
||||
EXPORTS_mozilla/dom := \
|
||||
EnableSpeechSynthesisCheck.h \
|
||||
SpeechSynthesisUtterance.h \
|
||||
SpeechSynthesisVoice.h \
|
||||
SpeechSynthesis.h \
|
||||
SpeechSynthesisChild.h \
|
||||
SpeechSynthesisParent.h \
|
||||
nsSynthVoiceRegistry.h \
|
||||
$(NULL)
|
||||
|
||||
FORCE_STATIC_LIB := 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,231 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 "prlog.h"
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
#include "mozilla/dom/SpeechSynthesisBinding.h"
|
||||
#include "SpeechSynthesis.h"
|
||||
#include "nsSynthVoiceRegistry.h"
|
||||
|
||||
#undef LOG
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo*
|
||||
GetSpeechSynthLog()
|
||||
{
|
||||
static PRLogModuleInfo* sLog = nullptr;
|
||||
|
||||
if (!sLog) {
|
||||
sLog = PR_NewLogModule("SpeechSynthesis");
|
||||
}
|
||||
|
||||
return sLog;
|
||||
}
|
||||
#define LOG(type, msg) PR_LOG(GetSpeechSynthLog(), type, msg)
|
||||
#else
|
||||
#define LOG(type, msg)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
static PLDHashOperator
|
||||
TraverseCachedVoices(const nsAString& aKey, SpeechSynthesisVoice* aEntry, void* aData)
|
||||
{
|
||||
nsCycleCollectionTraversalCallback* cb = static_cast<nsCycleCollectionTraversalCallback*>(aData);
|
||||
cb->NoteXPCOMChild(aEntry);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SpeechSynthesis)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
tmp->mVoiceCache.Clear();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(SpeechSynthesis)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
tmp->mVoiceCache.EnumerateRead(TraverseCachedVoices, &cb);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(SpeechSynthesis)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SpeechSynthesis)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(SpeechSynthesis)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(SpeechSynthesis)
|
||||
|
||||
SpeechSynthesis::SpeechSynthesis(nsPIDOMWindow* aParent)
|
||||
: mParent(aParent)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
mVoiceCache.Init();
|
||||
}
|
||||
|
||||
SpeechSynthesis::~SpeechSynthesis()
|
||||
{
|
||||
mVoiceCache.Clear();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
SpeechSynthesis::WrapObject(JSContext* aCx, JSObject* aScope)
|
||||
{
|
||||
return SpeechSynthesisBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
nsIDOMWindow*
|
||||
SpeechSynthesis::GetParentObject() const
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
bool
|
||||
SpeechSynthesis::Pending() const
|
||||
{
|
||||
switch (mSpeechQueue.Length()) {
|
||||
case 0:
|
||||
return false;
|
||||
|
||||
case 1:
|
||||
return mSpeechQueue.ElementAt(0)->GetState() == SpeechSynthesisUtterance::STATE_PENDING;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SpeechSynthesis::Speaking() const
|
||||
{
|
||||
if (mSpeechQueue.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mSpeechQueue.ElementAt(0)->GetState() == SpeechSynthesisUtterance::STATE_SPEAKING;
|
||||
}
|
||||
|
||||
bool
|
||||
SpeechSynthesis::Paused() const
|
||||
{
|
||||
if (mSpeechQueue.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mSpeechQueue.ElementAt(0)->IsPaused();
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesis::Speak(SpeechSynthesisUtterance& aUtterance)
|
||||
{
|
||||
if (aUtterance.mState != SpeechSynthesisUtterance::STATE_NONE) {
|
||||
// XXX: Should probably raise an error
|
||||
return;
|
||||
}
|
||||
|
||||
mSpeechQueue.AppendElement(&aUtterance);
|
||||
aUtterance.mState = SpeechSynthesisUtterance::STATE_PENDING;
|
||||
|
||||
if (mSpeechQueue.Length() == 1) {
|
||||
AdvanceQueue();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesis::AdvanceQueue()
|
||||
{
|
||||
LOG(PR_LOG_DEBUG,
|
||||
("SpeechSynthesis::AdvanceQueue length=%d", mSpeechQueue.Length()));
|
||||
|
||||
if (mSpeechQueue.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<SpeechSynthesisUtterance> utterance = mSpeechQueue.ElementAt(0);
|
||||
|
||||
nsAutoString docLang;
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mParent);
|
||||
nsIDocument* doc = win->GetExtantDoc();
|
||||
|
||||
if (doc) {
|
||||
Element* elm = doc->GetHtmlElement();
|
||||
|
||||
if (elm) {
|
||||
elm->GetLang(docLang);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesis::Cancel()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesis::Pause()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesis::Resume()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesis::OnEnd()
|
||||
{
|
||||
if (!mSpeechQueue.IsEmpty()) {
|
||||
mSpeechQueue.RemoveElementAt(0);
|
||||
}
|
||||
|
||||
AdvanceQueue();
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesis::GetVoices(nsTArray< nsRefPtr<SpeechSynthesisVoice> >& aResult)
|
||||
{
|
||||
aResult.Clear();
|
||||
uint32_t voiceCount = 0;
|
||||
|
||||
nsresult rv = nsSynthVoiceRegistry::GetInstance()->GetVoiceCount(&voiceCount);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
for (uint32_t i = 0; i < voiceCount; i++) {
|
||||
nsAutoString uri;
|
||||
rv = nsSynthVoiceRegistry::GetInstance()->GetVoice(i, uri);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to retrieve voice from registry");
|
||||
continue;
|
||||
}
|
||||
|
||||
SpeechSynthesisVoice* voice = mVoiceCache.GetWeak(uri);
|
||||
|
||||
if (!voice) {
|
||||
voice = new SpeechSynthesisVoice(this, uri);
|
||||
}
|
||||
|
||||
aResult.AppendElement(voice);
|
||||
}
|
||||
|
||||
mVoiceCache.Clear();
|
||||
|
||||
for (uint32_t i = 0; i < aResult.Length(); i++) {
|
||||
SpeechSynthesisVoice* voice = aResult[i];
|
||||
mVoiceCache.Put(voice->mUri, voice);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,71 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
#include "EnableSpeechSynthesisCheck.h"
|
||||
#include "SpeechSynthesisUtterance.h"
|
||||
#include "SpeechSynthesisVoice.h"
|
||||
|
||||
struct JSContext;
|
||||
class nsIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class nsSpeechTask;
|
||||
|
||||
class SpeechSynthesis MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache,
|
||||
public EnableSpeechSynthesisCheck
|
||||
{
|
||||
public:
|
||||
SpeechSynthesis(nsPIDOMWindow* aParent);
|
||||
virtual ~SpeechSynthesis();
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(SpeechSynthesis)
|
||||
|
||||
nsIDOMWindow* GetParentObject() const;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope);
|
||||
|
||||
bool Pending() const;
|
||||
|
||||
bool Speaking() const;
|
||||
|
||||
bool Paused() const;
|
||||
|
||||
void Speak(SpeechSynthesisUtterance& aUtterance);
|
||||
|
||||
void Cancel();
|
||||
|
||||
void Pause();
|
||||
|
||||
void Resume();
|
||||
|
||||
void OnEnd();
|
||||
|
||||
void GetVoices(nsTArray< nsRefPtr<SpeechSynthesisVoice> >& aResult);
|
||||
|
||||
private:
|
||||
|
||||
void AdvanceQueue();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mParent;
|
||||
|
||||
nsTArray<nsRefPtr<SpeechSynthesisUtterance>> mSpeechQueue;
|
||||
|
||||
nsRefPtrHashtable<nsStringHashKey, SpeechSynthesisVoice> mVoiceCache;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,168 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 "nsCOMPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
||||
#include "GeneratedEvents.h"
|
||||
#include "nsIDOMSpeechSynthesisEvent.h"
|
||||
|
||||
#include "mozilla/dom/SpeechSynthesisUtteranceBinding.h"
|
||||
#include "SpeechSynthesisUtterance.h"
|
||||
#include "SpeechSynthesisVoice.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(SpeechSynthesisUtterance)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(SpeechSynthesisUtterance, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(SpeechSynthesisUtterance, nsDOMEventTargetHelper)
|
||||
|
||||
SpeechSynthesisUtterance::SpeechSynthesisUtterance(const nsAString& text)
|
||||
: mText(text)
|
||||
, mVolume(1)
|
||||
, mRate(1)
|
||||
, mPitch(1)
|
||||
, mState(STATE_NONE)
|
||||
, mPaused(false)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
SpeechSynthesisUtterance::~SpeechSynthesisUtterance() {}
|
||||
|
||||
JSObject*
|
||||
SpeechSynthesisUtterance::WrapObject(JSContext* aCx, JSObject* aScope)
|
||||
{
|
||||
return SpeechSynthesisUtteranceBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
SpeechSynthesisUtterance::GetParentObject() const
|
||||
{
|
||||
return GetOwner();
|
||||
}
|
||||
|
||||
already_AddRefed<SpeechSynthesisUtterance>
|
||||
SpeechSynthesisUtterance::Constructor(GlobalObject& aGlobal,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
return Constructor(aGlobal, NS_LITERAL_STRING(""), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<SpeechSynthesisUtterance>
|
||||
SpeechSynthesisUtterance::Constructor(GlobalObject& aGlobal,
|
||||
const nsAString& aText,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aGlobal.Get());
|
||||
|
||||
if (!win) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(win->IsInnerWindow());
|
||||
SpeechSynthesisUtterance* object = new SpeechSynthesisUtterance(aText);
|
||||
NS_ADDREF(object);
|
||||
object->BindToOwner(win);
|
||||
return object;
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisUtterance::GetText(nsString& aResult) const
|
||||
{
|
||||
aResult = mText;
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisUtterance::SetText(const nsAString& aText)
|
||||
{
|
||||
mText = aText;
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisUtterance::GetLang(nsString& aResult) const
|
||||
{
|
||||
aResult = mLang;
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisUtterance::SetLang(const nsAString& aLang)
|
||||
{
|
||||
mLang = aLang;
|
||||
}
|
||||
|
||||
SpeechSynthesisVoice*
|
||||
SpeechSynthesisUtterance::GetVoice() const
|
||||
{
|
||||
return mVoice;
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisUtterance::SetVoice(SpeechSynthesisVoice* aVoice)
|
||||
{
|
||||
mVoice = aVoice;
|
||||
}
|
||||
|
||||
float
|
||||
SpeechSynthesisUtterance::Volume() const
|
||||
{
|
||||
return mVolume;
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisUtterance::SetVolume(float aVolume)
|
||||
{
|
||||
mVolume = aVolume;
|
||||
}
|
||||
|
||||
float
|
||||
SpeechSynthesisUtterance::Rate() const
|
||||
{
|
||||
return mRate;
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisUtterance::SetRate(float aRate)
|
||||
{
|
||||
mRate = aRate;
|
||||
}
|
||||
|
||||
float
|
||||
SpeechSynthesisUtterance::Pitch() const
|
||||
{
|
||||
return mPitch;
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisUtterance::SetPitch(float aPitch)
|
||||
{
|
||||
mPitch = aPitch;
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisUtterance::DispatchSpeechSynthesisEvent(const nsAString& aEventType,
|
||||
uint32_t aCharIndex,
|
||||
float aElapsedTime,
|
||||
const nsAString& aName)
|
||||
{
|
||||
nsCOMPtr<nsIDOMEvent> domEvent;
|
||||
NS_NewDOMSpeechSynthesisEvent(getter_AddRefs(domEvent), nullptr, nullptr, nullptr);
|
||||
|
||||
nsCOMPtr<nsIDOMSpeechSynthesisEvent> ssEvent = do_QueryInterface(domEvent);
|
||||
ssEvent->InitSpeechSynthesisEvent(aEventType, false, false,
|
||||
aCharIndex, aElapsedTime, aName);
|
||||
|
||||
DispatchTrustedEvent(domEvent);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,114 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "EnableSpeechSynthesisCheck.h"
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class SpeechSynthesisVoice;
|
||||
|
||||
class SpeechSynthesisUtterance MOZ_FINAL : public nsDOMEventTargetHelper,
|
||||
public EnableSpeechSynthesisCheck
|
||||
{
|
||||
friend class SpeechSynthesis;
|
||||
|
||||
public:
|
||||
SpeechSynthesisUtterance(const nsAString& aText);
|
||||
virtual ~SpeechSynthesisUtterance();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
|
||||
|
||||
nsISupports* GetParentObject() const;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope);
|
||||
|
||||
static
|
||||
already_AddRefed<SpeechSynthesisUtterance> Constructor(GlobalObject& aGlobal,
|
||||
ErrorResult& aRv);
|
||||
static
|
||||
already_AddRefed<SpeechSynthesisUtterance> Constructor(GlobalObject& aGlobal,
|
||||
const nsAString& aText,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void GetText(nsString& aResult) const;
|
||||
|
||||
void SetText(const nsAString& aText);
|
||||
|
||||
void GetLang(nsString& aResult) const;
|
||||
|
||||
void SetLang(const nsAString& aLang);
|
||||
|
||||
SpeechSynthesisVoice* GetVoice() const;
|
||||
|
||||
void SetVoice(SpeechSynthesisVoice* aVoice);
|
||||
|
||||
float Volume() const;
|
||||
|
||||
void SetVolume(float aVolume);
|
||||
|
||||
float Rate() const;
|
||||
|
||||
void SetRate(float aRate);
|
||||
|
||||
float Pitch() const;
|
||||
|
||||
void SetPitch(float aPitch);
|
||||
|
||||
enum {
|
||||
STATE_NONE,
|
||||
STATE_PENDING,
|
||||
STATE_SPEAKING,
|
||||
STATE_ENDED
|
||||
};
|
||||
|
||||
uint32_t GetState() { return mState; }
|
||||
|
||||
bool IsPaused() { return mPaused; }
|
||||
|
||||
IMPL_EVENT_HANDLER(start)
|
||||
IMPL_EVENT_HANDLER(end)
|
||||
IMPL_EVENT_HANDLER(error)
|
||||
IMPL_EVENT_HANDLER(pause)
|
||||
IMPL_EVENT_HANDLER(resume)
|
||||
IMPL_EVENT_HANDLER(mark)
|
||||
IMPL_EVENT_HANDLER(boundary)
|
||||
|
||||
private:
|
||||
|
||||
void DispatchSpeechSynthesisEvent(const nsAString& aEventType,
|
||||
uint32_t aCharIndex,
|
||||
float aElapsedTime, const nsAString& aName);
|
||||
|
||||
nsString mText;
|
||||
|
||||
nsString mLang;
|
||||
|
||||
float mVolume;
|
||||
|
||||
float mRate;
|
||||
|
||||
float mPitch;
|
||||
|
||||
uint32_t mState;
|
||||
|
||||
bool mPaused;
|
||||
|
||||
nsRefPtr<SpeechSynthesisVoice> mVoice;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,93 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 "SpeechSynthesis.h"
|
||||
#include "nsSynthVoiceRegistry.h"
|
||||
#include "mozilla/dom/SpeechSynthesisVoiceBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(SpeechSynthesisVoice, mParent)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(SpeechSynthesisVoice)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(SpeechSynthesisVoice)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SpeechSynthesisVoice)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
SpeechSynthesisVoice::SpeechSynthesisVoice(nsISupports* aParent,
|
||||
const nsAString& aUri)
|
||||
: mParent(aParent)
|
||||
, mUri(aUri)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
SpeechSynthesisVoice::~SpeechSynthesisVoice()
|
||||
{
|
||||
}
|
||||
|
||||
JSObject*
|
||||
SpeechSynthesisVoice::WrapObject(JSContext* aCx, JSObject* aScope)
|
||||
{
|
||||
return SpeechSynthesisVoiceBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
nsISupports*
|
||||
SpeechSynthesisVoice::GetParentObject() const
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisVoice::GetVoiceURI(nsString& aRetval) const
|
||||
{
|
||||
aRetval = mUri;
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisVoice::GetName(nsString& aRetval) const
|
||||
{
|
||||
DebugOnly<nsresult> rv =
|
||||
nsSynthVoiceRegistry::GetInstance()->GetVoiceName(mUri, aRetval);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to get SpeechSynthesisVoice.name");
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisVoice::GetLang(nsString& aRetval) const
|
||||
{
|
||||
DebugOnly<nsresult> rv =
|
||||
nsSynthVoiceRegistry::GetInstance()->GetVoiceLang(mUri, aRetval);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to get SpeechSynthesisVoice.lang");
|
||||
}
|
||||
|
||||
bool
|
||||
SpeechSynthesisVoice::LocalService() const
|
||||
{
|
||||
bool isLocal;
|
||||
DebugOnly<nsresult> rv =
|
||||
nsSynthVoiceRegistry::GetInstance()->IsLocalVoice(mUri, &isLocal);
|
||||
NS_WARN_IF_FALSE(
|
||||
NS_SUCCEEDED(rv), "Failed to get SpeechSynthesisVoice.localService");
|
||||
|
||||
return isLocal;
|
||||
}
|
||||
|
||||
bool
|
||||
SpeechSynthesisVoice::Default() const
|
||||
{
|
||||
bool isDefault;
|
||||
DebugOnly<nsresult> rv =
|
||||
nsSynthVoiceRegistry::GetInstance()->IsDefaultVoice(mUri, &isDefault);
|
||||
NS_WARN_IF_FALSE(
|
||||
NS_SUCCEEDED(rv), "Failed to get SpeechSynthesisVoice.default");
|
||||
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,58 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
#include "EnableSpeechSynthesisCheck.h"
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class SpeechSynthesis;
|
||||
|
||||
class SpeechSynthesisVoice MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache,
|
||||
public EnableSpeechSynthesisCheck
|
||||
{
|
||||
friend class SpeechSynthesis;
|
||||
|
||||
public:
|
||||
SpeechSynthesisVoice(nsISupports* aParent, const nsAString& aUri);
|
||||
|
||||
virtual ~SpeechSynthesisVoice();
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(SpeechSynthesisVoice)
|
||||
|
||||
nsISupports* GetParentObject() const;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope);
|
||||
|
||||
void GetVoiceURI(nsString& aRetval) const;
|
||||
|
||||
void GetName(nsString& aRetval) const;
|
||||
|
||||
void GetLang(nsString& aRetval) const;
|
||||
|
||||
bool LocalService() const;
|
||||
|
||||
bool Default() const;
|
||||
|
||||
private:
|
||||
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
|
||||
nsString mUri;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,15 @@
|
|||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# 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/.
|
||||
|
||||
MODULE = 'content'
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
XPIDL_MODULE = 'dom_webspeechsynth'
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMSpeechSynthesisEvent.idl',
|
||||
'nsISynthVoiceRegistry.idl'
|
||||
]
|
|
@ -0,0 +1,33 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(b5240841-dc69-43dd-bcf1-9306b8ddaa09)]
|
||||
interface nsIDOMSpeechSynthesisEvent : nsIDOMEvent {
|
||||
[noscript] void initSpeechSynthesisEvent(in DOMString aEventTypeArg,
|
||||
in boolean aCanBubbleArg,
|
||||
in boolean aCancelableArg,
|
||||
in unsigned long aCharIndex,
|
||||
in float aElapsedTime,
|
||||
in DOMString aName);
|
||||
|
||||
readonly attribute unsigned long charIndex;
|
||||
readonly attribute float elapsedTime;
|
||||
readonly attribute DOMString name;
|
||||
};
|
||||
|
||||
dictionary SpeechSynthesisEventInit : EventInit {
|
||||
unsigned long charIndex;
|
||||
float elapsedTime;
|
||||
DOMString name;
|
||||
};
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 "nsISupports.idl"
|
||||
|
||||
[scriptable, builtinclass, uuid(53dcc868-4193-4c3c-a1d9-fe5a0a6af2fb)]
|
||||
interface nsISynthVoiceRegistry : nsISupports
|
||||
{
|
||||
/**
|
||||
* Register a speech synthesis voice.
|
||||
*
|
||||
* @param aService the service that provides this voice.
|
||||
* @param aUri a unique identifier for this voice.
|
||||
* @param aName human-readable name for this voice.
|
||||
* @param aLang a BCP 47 language tag.
|
||||
* @param aLocalService true if service does not require network.
|
||||
*/
|
||||
void addVoice(in nsISupports aService, in DOMString aUri,
|
||||
in DOMString aName, in DOMString aLang,
|
||||
in boolean aLocalService);
|
||||
|
||||
/**
|
||||
* Remove a speech synthesis voice.
|
||||
*
|
||||
* @param aService the service that was used to add the voice.
|
||||
* @param aUri a unique identifier of an existing voice.
|
||||
*/
|
||||
void removeVoice(in nsISupports aService, in DOMString aUri);
|
||||
|
||||
/**
|
||||
* Set a voice as default.
|
||||
*
|
||||
* @param aUri a unique identifier of an existing voice.
|
||||
* @param aIsDefault true if this voice should be toggled as default.
|
||||
*/
|
||||
void setDefaultVoice(in DOMString aUri, in boolean aIsDefault);
|
||||
|
||||
readonly attribute uint32_t voiceCount;
|
||||
|
||||
AString getVoice(in uint32_t aIndex);
|
||||
|
||||
bool isDefaultVoice(in DOMString aUri);
|
||||
|
||||
bool isLocalVoice(in DOMString aUri);
|
||||
|
||||
AString getVoiceLang(in DOMString aUri);
|
||||
|
||||
AString getVoiceName(in DOMString aUri);
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define NS_SYNTHVOICEREGISTRY_CID \
|
||||
{ /* {7090524d-5574-4492-a77f-d8d558ced59d} */ \
|
||||
0x7090524d, \
|
||||
0x5574, \
|
||||
0x4492, \
|
||||
{ 0xa7, 0x7f, 0xd8, 0xd5, 0x58, 0xce, 0xd5, 0x9d } \
|
||||
}
|
||||
|
||||
#define NS_SYNTHVOICEREGISTRY_CONTRACTID \
|
||||
"@mozilla.org/synth-voice-registry;1"
|
||||
|
||||
#define NS_SYNTHVOICEREGISTRY_CLASSNAME \
|
||||
"Speech Synthesis Voice Registry"
|
||||
|
||||
%}
|
|
@ -0,0 +1,255 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 "nsILocaleService.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include "SpeechSynthesisUtterance.h"
|
||||
#include "SpeechSynthesisVoice.h"
|
||||
#include "nsSynthVoiceRegistry.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
#undef LOG
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo* GetSpeechSynthLog();
|
||||
#define LOG(type, msg) PR_LOG(GetSpeechSynthLog(), type, msg)
|
||||
#else
|
||||
#define LOG(type, msg)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// VoiceData
|
||||
|
||||
class VoiceData
|
||||
{
|
||||
public:
|
||||
VoiceData(nsISupports* aService, const nsAString& aUri,
|
||||
const nsAString& aName, const nsAString& aLang, bool aIsLocal)
|
||||
: mService(aService)
|
||||
, mUri(aUri)
|
||||
, mName(aName)
|
||||
, mLang(aLang)
|
||||
, mIsLocal(aIsLocal) {}
|
||||
|
||||
~VoiceData() {}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(VoiceData)
|
||||
|
||||
nsCOMPtr<nsISupports> mService;
|
||||
|
||||
nsString mUri;
|
||||
|
||||
nsString mName;
|
||||
|
||||
nsString mLang;
|
||||
|
||||
bool mIsLocal;
|
||||
};
|
||||
|
||||
// nsSynthVoiceRegistry
|
||||
|
||||
static StaticRefPtr<nsSynthVoiceRegistry> gSynthVoiceRegistry;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsSynthVoiceRegistry, nsISynthVoiceRegistry)
|
||||
|
||||
nsSynthVoiceRegistry::nsSynthVoiceRegistry()
|
||||
{
|
||||
mUriVoiceMap.Init();
|
||||
}
|
||||
|
||||
nsSynthVoiceRegistry::~nsSynthVoiceRegistry()
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("~nsSynthVoiceRegistry"));
|
||||
|
||||
mUriVoiceMap.Clear();
|
||||
}
|
||||
|
||||
nsSynthVoiceRegistry*
|
||||
nsSynthVoiceRegistry::GetInstance()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!gSynthVoiceRegistry) {
|
||||
gSynthVoiceRegistry = new nsSynthVoiceRegistry();
|
||||
}
|
||||
|
||||
return gSynthVoiceRegistry;
|
||||
}
|
||||
|
||||
already_AddRefed<nsSynthVoiceRegistry>
|
||||
nsSynthVoiceRegistry::GetInstanceForService()
|
||||
{
|
||||
nsRefPtr<nsSynthVoiceRegistry> registry = GetInstance();
|
||||
|
||||
return registry.forget();
|
||||
}
|
||||
|
||||
void
|
||||
nsSynthVoiceRegistry::Shutdown()
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("nsSynthVoiceRegistry::Shutdown()"));
|
||||
gSynthVoiceRegistry = nullptr;
|
||||
}
|
||||
|
||||
// nsISynthVoiceRegistry
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSynthVoiceRegistry::AddVoice(nsISupports* aService,
|
||||
const nsAString& aUri,
|
||||
const nsAString& aName,
|
||||
const nsAString& aLang,
|
||||
bool aLocalService)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG,
|
||||
("nsSynthVoiceRegistry::AddVoice uri='%s' name='%s' lang='%s' local=%s",
|
||||
NS_ConvertUTF16toUTF8(aUri).get(), NS_ConvertUTF16toUTF8(aName).get(),
|
||||
NS_ConvertUTF16toUTF8(aLang).get(),
|
||||
aLocalService ? "true" : "false"));
|
||||
|
||||
return AddVoiceImpl(aService, aUri, aName, aLang,
|
||||
aLocalService);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSynthVoiceRegistry::RemoveVoice(nsISupports* aService,
|
||||
const nsAString& aUri)
|
||||
{
|
||||
LOG(PR_LOG_DEBUG,
|
||||
("nsSynthVoiceRegistry::RemoveVoice uri='%s'",
|
||||
NS_ConvertUTF16toUTF8(aUri).get()));
|
||||
|
||||
bool found = false;
|
||||
VoiceData* retval = mUriVoiceMap.GetWeak(aUri, &found);
|
||||
|
||||
NS_ENSURE_TRUE(found, NS_ERROR_NOT_AVAILABLE);
|
||||
NS_ENSURE_TRUE(aService == retval->mService, NS_ERROR_INVALID_ARG);
|
||||
|
||||
mVoices.RemoveElement(retval);
|
||||
mDefaultVoices.RemoveElement(retval);
|
||||
mUriVoiceMap.Remove(aUri);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSynthVoiceRegistry::SetDefaultVoice(const nsAString& aUri,
|
||||
bool aIsDefault)
|
||||
{
|
||||
bool found = false;
|
||||
VoiceData* retval = mUriVoiceMap.GetWeak(aUri, &found);
|
||||
NS_ENSURE_TRUE(found, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
mDefaultVoices.RemoveElement(retval);
|
||||
|
||||
LOG(PR_LOG_DEBUG, ("nsSynthVoiceRegistry::SetDefaultVoice %s %s",
|
||||
NS_ConvertUTF16toUTF8(aUri).get(),
|
||||
aIsDefault ? "true" : "false"));
|
||||
|
||||
if (aIsDefault) {
|
||||
mDefaultVoices.AppendElement(retval);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSynthVoiceRegistry::GetVoiceCount(uint32_t* aRetval)
|
||||
{
|
||||
*aRetval = mVoices.Length();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSynthVoiceRegistry::GetVoice(uint32_t aIndex, nsAString& aRetval)
|
||||
{
|
||||
NS_ENSURE_TRUE(aIndex < mVoices.Length(), NS_ERROR_INVALID_ARG);
|
||||
|
||||
aRetval = mVoices[aIndex]->mUri;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSynthVoiceRegistry::IsDefaultVoice(const nsAString& aUri, bool* aRetval)
|
||||
{
|
||||
bool found;
|
||||
VoiceData* voice = mUriVoiceMap.GetWeak(aUri, &found);
|
||||
NS_ENSURE_TRUE(found, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
for (int32_t i = mDefaultVoices.Length(); i > 0; ) {
|
||||
VoiceData* defaultVoice = mDefaultVoices[--i];
|
||||
|
||||
if (voice->mLang.Equals(defaultVoice->mLang)) {
|
||||
*aRetval = voice == defaultVoice;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
*aRetval = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSynthVoiceRegistry::IsLocalVoice(const nsAString& aUri, bool* aRetval)
|
||||
{
|
||||
bool found;
|
||||
VoiceData* voice = mUriVoiceMap.GetWeak(aUri, &found);
|
||||
NS_ENSURE_TRUE(found, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
*aRetval = voice->mIsLocal;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSynthVoiceRegistry::GetVoiceLang(const nsAString& aUri, nsAString& aRetval)
|
||||
{
|
||||
bool found;
|
||||
VoiceData* voice = mUriVoiceMap.GetWeak(aUri, &found);
|
||||
NS_ENSURE_TRUE(found, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
aRetval = voice->mLang;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSynthVoiceRegistry::GetVoiceName(const nsAString& aUri, nsAString& aRetval)
|
||||
{
|
||||
bool found;
|
||||
VoiceData* voice = mUriVoiceMap.GetWeak(aUri, &found);
|
||||
NS_ENSURE_TRUE(found, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
aRetval = voice->mName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSynthVoiceRegistry::AddVoiceImpl(nsISupports* aService,
|
||||
const nsAString& aUri,
|
||||
const nsAString& aName,
|
||||
const nsAString& aLang,
|
||||
bool aLocalService)
|
||||
{
|
||||
bool found = false;
|
||||
mUriVoiceMap.GetWeak(aUri, &found);
|
||||
NS_ENSURE_FALSE(found, NS_ERROR_INVALID_ARG);
|
||||
|
||||
nsRefPtr<VoiceData> voice = new VoiceData(aService, aUri, aName, aLang,
|
||||
aLocalService);
|
||||
|
||||
mVoices.AppendElement(voice);
|
||||
mUriVoiceMap.Put(aUri, voice);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,52 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsISynthVoiceRegistry.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class RemoteVoice;
|
||||
class SpeechSynthesisUtterance;
|
||||
class nsSpeechTask;
|
||||
class VoiceData;
|
||||
|
||||
class nsSynthVoiceRegistry : public nsISynthVoiceRegistry
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISYNTHVOICEREGISTRY
|
||||
|
||||
nsSynthVoiceRegistry();
|
||||
virtual ~nsSynthVoiceRegistry();
|
||||
|
||||
static nsSynthVoiceRegistry* GetInstance();
|
||||
|
||||
static already_AddRefed<nsSynthVoiceRegistry> GetInstanceForService();
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
private:
|
||||
nsresult AddVoiceImpl(nsISupports* aService,
|
||||
const nsAString& aUri,
|
||||
const nsAString& aName,
|
||||
const nsAString& aLang,
|
||||
bool aLocalService);
|
||||
|
||||
nsTArray<nsRefPtr<VoiceData> > mVoices;
|
||||
|
||||
nsTArray<nsRefPtr<VoiceData> > mDefaultVoices;
|
||||
|
||||
nsRefPtrHashtable<nsStringHashKey, VoiceData> mUriVoiceMap;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,18 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# 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/.
|
||||
|
||||
DEPTH := @DEPTH@
|
||||
topsrcdir := @top_srcdir@
|
||||
srcdir := @srcdir@
|
||||
VPATH := @srcdir@
|
||||
relativesrcdir := @relativesrcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MOCHITEST_FILES := \
|
||||
common.js \
|
||||
test_setup.html \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,54 @@
|
|||
SpecialPowers.setBoolPref("media.webspeech.synth.enabled", true);
|
||||
|
||||
var gSpeechRegistry = SpecialPowers.Cc["@mozilla.org/synth-voice-registry;1"]
|
||||
.getService(SpecialPowers.Ci.nsISynthVoiceRegistry);
|
||||
|
||||
var gAddedVoices = [];
|
||||
|
||||
var TestSpeechServiceNoAudio = {
|
||||
QueryInterface: function(iid) {
|
||||
return this;
|
||||
},
|
||||
|
||||
getInterfaces: function(c) {},
|
||||
|
||||
getHelperForLanguage: function() {}
|
||||
};
|
||||
|
||||
function synthAddVoice(aServiceName, aName, aLang, aIsLocal) {
|
||||
var voicesBefore = speechSynthesis.getVoices().length;
|
||||
var uri = "urn:moz-tts:mylittleservice:" + encodeURI(aName + '?' + aLang);
|
||||
gSpeechRegistry.addVoice(window[aServiceName], uri, aName, aLang, aIsLocal);
|
||||
|
||||
gAddedVoices.push([window[aServiceName], uri]);
|
||||
var voicesAfter = speechSynthesis.getVoices().length;
|
||||
|
||||
is(voicesBefore + 1, voicesAfter, "Voice added");
|
||||
var voice = speechSynthesis.getVoices()[voicesAfter - 1];
|
||||
is(voice.voiceURI, uri, "voice URI matches");
|
||||
is(voice.name, aName, "voice name matches");
|
||||
is(voice.lang, aLang, "voice lang matches");
|
||||
is(voice.localService, aIsLocal, "voice localService matches");
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
function synthSetDefault(aUri, aIsDefault) {
|
||||
gSpeechRegistry.setDefaultVoice(aUri, aIsDefault);
|
||||
var voices = speechSynthesis.getVoices();
|
||||
for (var i in voices) {
|
||||
if (voices[i].voiceURI == aUri)
|
||||
ok(voices[i]['default'], "Voice set to default");
|
||||
}
|
||||
}
|
||||
|
||||
function synthCleanup() {
|
||||
var voicesBefore = speechSynthesis.getVoices().length;
|
||||
var toRemove = gAddedVoices.length;
|
||||
var removeArgs;
|
||||
while ((removeArgs = gAddedVoices.shift()))
|
||||
gSpeechRegistry.removeVoice.apply(gSpeechRegistry.removeVoice, removeArgs);
|
||||
|
||||
var voicesAfter = speechSynthesis.getVoices().length;
|
||||
is(voicesAfter, voicesBefore - toRemove, "Successfully removed test voices");
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# 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/.
|
|
@ -0,0 +1,78 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=525444
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 525444: Web Speech API check all classes are present</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body onunload="synthCleanup();">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650295">Mozilla Bug 650295</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 525444 **/
|
||||
|
||||
synthAddVoice('TestSpeechServiceNoAudio', 'Bob Marley', 'en-JM', true);
|
||||
synthAddVoice('TestSpeechServiceNoAudio', 'Amy Winehouse', 'en-GB', true);
|
||||
synthAddVoice('TestSpeechServiceNoAudio', 'Leonard Cohen', 'en-CA', true);
|
||||
synthAddVoice('TestSpeechServiceNoAudio', 'Celine Dion', 'fr-CA', true);
|
||||
synthAddVoice('TestSpeechServiceNoAudio', 'Julieta Venegas', 'es-MX', true);
|
||||
|
||||
ok(SpeechSynthesis, "SpeechSynthesis exists in global scope");
|
||||
ok(SpeechSynthesisVoice, "SpeechSynthesisVoice exists in global scope");
|
||||
ok(SpeechSynthesisEvent, "SpeechSynthesisEvent exists in global scope");
|
||||
|
||||
// SpeechSynthesisUtterance is the only type that has a constructor
|
||||
// and writable properties
|
||||
ok(SpeechSynthesisUtterance, "SpeechSynthesisUtterance exists in global scope");
|
||||
var ssu = new SpeechSynthesisUtterance("hello world");
|
||||
is(typeof ssu, "object", "SpeechSynthesisUtterance instance is an object");
|
||||
is(ssu.text, "hello world", "SpeechSynthesisUtterance.text is correct");
|
||||
is(ssu.volume, 1, "SpeechSynthesisUtterance.volume default is correct");
|
||||
is(ssu.rate, 1, "SpeechSynthesisUtterance.rate default is correct");
|
||||
is(ssu.pitch, 1, "SpeechSynthesisUtterance.pitch default is correct");
|
||||
ssu.lang = "he-IL";
|
||||
ssu.volume = 0.5;
|
||||
ssu.rate = 2.0;
|
||||
ssu.pitch = 1.5;
|
||||
is(ssu.lang, "he-IL", "SpeechSynthesisUtterance.lang is correct");
|
||||
is(ssu.volume, 0.5, "SpeechSynthesisUtterance.volume is correct");
|
||||
is(ssu.rate, 2.0, "SpeechSynthesisUtterance.rate is correct");
|
||||
is(ssu.pitch, 1.5, "SpeechSynthesisUtterance.pitch is correct");
|
||||
|
||||
// Test for singleton instance hanging off of window.
|
||||
ok(speechSynthesis, "speechSynthesis exists in global scope");
|
||||
is(typeof speechSynthesis, "object", "speechSynthesis instance is an object");
|
||||
is(typeof speechSynthesis.speak, "function", "speechSynthesis.speak is a function");
|
||||
is(typeof speechSynthesis.cancel, "function", "speechSynthesis.cancel is a function");
|
||||
is(typeof speechSynthesis.pause, "function", "speechSynthesis.pause is a function");
|
||||
is(typeof speechSynthesis.resume, "function", "speechSynthesis.resume is a function");
|
||||
is(typeof speechSynthesis.getVoices, "function", "speechSynthesis.getVoices is a function");
|
||||
|
||||
is(typeof speechSynthesis.pending, "boolean", "speechSynthesis.pending is a boolean");
|
||||
is(typeof speechSynthesis.speaking, "boolean", "speechSynthesis.speaking is a boolean");
|
||||
is(typeof speechSynthesis.paused, "boolean", "speechSynthesis.paused is a boolean");
|
||||
|
||||
var voices1 = speechSynthesis.getVoices();
|
||||
var voices2 = speechSynthesis.getVoices();
|
||||
|
||||
ok(voices1.length == voices2.length, "Voice count matches");
|
||||
|
||||
for (var i in voices1) {
|
||||
ok(voices1[i] == voices2[i], "Voice instance matches");
|
||||
}
|
||||
|
||||
synthCleanup();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1775,6 +1775,9 @@ nsDOMClassInfo::Init()
|
|||
|
||||
DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow)
|
||||
DOM_CLASSINFO_WINDOW_MAP_ENTRIES(nsGlobalWindow::HasIndexedDBSupport())
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSpeechSynthesisGetter)
|
||||
#endif
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(WindowUtils, nsIDOMWindowUtils)
|
||||
|
@ -2116,6 +2119,9 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeWindow, nsIDOMWindow)
|
||||
DOM_CLASSINFO_WINDOW_MAP_ENTRIES(true)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMChromeWindow)
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSpeechSynthesisGetter)
|
||||
#endif
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(ImageDocument, nsIImageDocument)
|
||||
|
@ -2304,6 +2310,9 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
|
||||
DOM_CLASSINFO_WINDOW_MAP_ENTRIES(nsGlobalWindow::HasIndexedDBSupport())
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMModalContentWindow)
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSpeechSynthesisGetter)
|
||||
#endif
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(DataContainerEvent, nsIDOMDataContainerEvent)
|
||||
|
|
|
@ -229,6 +229,10 @@
|
|||
#include "nsPISocketTransportService.h"
|
||||
#include "mozilla/dom/AudioContext.h"
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
#include "mozilla/dom/SpeechSynthesis.h"
|
||||
#endif
|
||||
|
||||
// Apple system headers seem to have a check() macro. <sigh>
|
||||
#ifdef check
|
||||
#undef check
|
||||
|
@ -1319,6 +1323,10 @@ nsGlobalWindow::CleanUp(bool aIgnoreModalDialog)
|
|||
|
||||
mPerformance = nullptr;
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
mSpeechSynthesis = nullptr;
|
||||
#endif
|
||||
|
||||
ClearControllers();
|
||||
|
||||
mOpener = nullptr; // Forces Release
|
||||
|
@ -1483,6 +1491,9 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)
|
||||
#ifdef MOZ_B2G
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMWindowB2G)
|
||||
#endif // MOZ_B2G
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMSpeechSynthesisGetter)
|
||||
#endif // MOZ_B2G
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMJSWindow)
|
||||
if (aIID.Equals(NS_GET_IID(nsIDOMWindowInternal))) {
|
||||
|
@ -1575,6 +1586,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechSynthesis)
|
||||
#endif
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInnerWindowHolder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOuterWindow)
|
||||
|
||||
|
@ -1615,6 +1630,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSpeechSynthesis)
|
||||
#endif
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mInnerWindowHolder)
|
||||
if (tmp->mOuterWindow) {
|
||||
static_cast<nsGlobalWindow*>(tmp->mOuterWindow.get())->MaybeClearInnerWindow(tmp);
|
||||
|
@ -3287,6 +3306,35 @@ nsPIDOMWindow::CreatePerformanceObjectIfNeeded()
|
|||
}
|
||||
}
|
||||
|
||||
// nsIDOMSpeechSynthesisGetter
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::GetSpeechSynthesis(nsISupports** aSpeechSynthesis)
|
||||
{
|
||||
FORWARD_TO_INNER(GetSpeechSynthesis, (aSpeechSynthesis), NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
NS_IF_ADDREF(*aSpeechSynthesis = nsPIDOMWindow::GetSpeechSynthesisInternal());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
SpeechSynthesis*
|
||||
nsPIDOMWindow::GetSpeechSynthesisInternal()
|
||||
{
|
||||
MOZ_ASSERT(IsInnerWindow());
|
||||
|
||||
if (!SpeechSynthesis::PrefEnabled()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mSpeechSynthesis) {
|
||||
mSpeechSynthesis = new SpeechSynthesis(this);
|
||||
}
|
||||
|
||||
return mSpeechSynthesis;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* GetScriptableParent is called when script reads window.parent.
|
||||
*
|
||||
|
|
|
@ -72,6 +72,10 @@
|
|||
#include "nsIDOMWindowB2G.h"
|
||||
#endif // MOZ_B2G
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
#include "nsIDOMSpeechSynthesisGetter.h"
|
||||
#endif // MOZ_WEBSPEECH
|
||||
|
||||
#define DEFAULT_HOME_PAGE "www.mozilla.org"
|
||||
#define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
|
||||
|
||||
|
@ -267,6 +271,9 @@ class nsGlobalWindow : public mozilla::dom::EventTarget,
|
|||
#ifdef MOZ_B2G
|
||||
, public nsIDOMWindowB2G
|
||||
#endif // MOZ_B2G
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
, public nsIDOMSpeechSynthesisGetter
|
||||
#endif // MOZ_WEBSPEECH
|
||||
{
|
||||
public:
|
||||
typedef mozilla::TimeStamp TimeStamp;
|
||||
|
@ -319,6 +326,11 @@ public:
|
|||
NS_DECL_NSIDOMWINDOWB2G
|
||||
#endif // MOZ_B2G
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
// nsIDOMSpeechSynthesisGetter
|
||||
NS_DECL_NSIDOMSPEECHSYNTHESISGETTER
|
||||
#endif // MOZ_WEBSPEECH
|
||||
|
||||
// nsIDOMWindowPerformance
|
||||
NS_DECL_NSIDOMWINDOWPERFORMANCE
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ class nsPIWindowRoot;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
class AudioContext;
|
||||
class SpeechSynthesis;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -651,6 +652,10 @@ public:
|
|||
static bool HasPerformanceSupport();
|
||||
nsPerformance* GetPerformance();
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
mozilla::dom::SpeechSynthesis* GetSpeechSynthesisInternal();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// The nsPIDOMWindow constructor. The aOuterWindow argument should
|
||||
// be null if and only if the created window itself is an outer
|
||||
|
@ -690,6 +695,11 @@ protected:
|
|||
// mPerformance is only used on inner windows.
|
||||
nsRefPtr<nsPerformance> mPerformance;
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
// mSpeechSynthesis is only used on inner windows.
|
||||
nsRefPtr<mozilla::dom::SpeechSynthesis> mSpeechSynthesis;
|
||||
#endif
|
||||
|
||||
uint32_t mModalStateDepth;
|
||||
|
||||
// These variables are only used on inner windows.
|
||||
|
|
|
@ -58,6 +58,11 @@ if CONFIG['MOZ_B2G']:
|
|||
'nsIDOMWindowB2G.idl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WEBSPEECH']:
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMSpeechSynthesisGetter.idl'
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_base'
|
||||
|
||||
XPIDL_FLAGS += [
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* SpeechSynthesisGetter
|
||||
* http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#tts-section
|
||||
*/
|
||||
|
||||
[scriptable, uuid(9fe60496-8356-430e-bf38-2debec45711e)]
|
||||
interface nsIDOMSpeechSynthesisGetter : nsISupports
|
||||
{
|
||||
readonly attribute nsISupports speechSynthesis;
|
||||
};
|
|
@ -547,6 +547,8 @@ var interfaceNamesInGlobalScope =
|
|||
"GamepadAxisMoveEvent",
|
||||
"SpeechRecognitionEvent",
|
||||
"SpeechRecognitionError",
|
||||
"SpeechSynthesisEvent",
|
||||
"SpeechSynthesisGetter",
|
||||
"PushManager",
|
||||
"StyleSheetAddedEvent",
|
||||
"StyleSheetRemovedEvent"
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[PrefControlled]
|
||||
interface SpeechSynthesis {
|
||||
readonly attribute boolean pending;
|
||||
readonly attribute boolean speaking;
|
||||
readonly attribute boolean paused;
|
||||
|
||||
void speak(SpeechSynthesisUtterance utterance);
|
||||
void cancel();
|
||||
void pause();
|
||||
void resume();
|
||||
sequence<SpeechSynthesisVoice> getVoices();
|
||||
};
|
|
@ -0,0 +1,18 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
interface Event;
|
||||
|
||||
interface SpeechSynthesisEvent : Event {
|
||||
readonly attribute unsigned long charIndex;
|
||||
readonly attribute float elapsedTime;
|
||||
readonly attribute DOMString name;
|
||||
};
|
|
@ -0,0 +1,38 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[PrefControlled,
|
||||
Constructor,
|
||||
Constructor(DOMString text)]
|
||||
interface SpeechSynthesisUtterance : EventTarget {
|
||||
attribute DOMString text;
|
||||
attribute DOMString lang;
|
||||
attribute SpeechSynthesisVoice? voice;
|
||||
attribute float volume;
|
||||
attribute float rate;
|
||||
attribute float pitch;
|
||||
|
||||
[SetterThrows]
|
||||
attribute EventHandler onstart;
|
||||
[SetterThrows]
|
||||
attribute EventHandler onend;
|
||||
[SetterThrows]
|
||||
attribute EventHandler onerror;
|
||||
[SetterThrows]
|
||||
attribute EventHandler onpause;
|
||||
[SetterThrows]
|
||||
attribute EventHandler onresume;
|
||||
[SetterThrows]
|
||||
attribute EventHandler onmark;
|
||||
[SetterThrows]
|
||||
attribute EventHandler onboundary;
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
[PrefControlled]
|
||||
interface SpeechSynthesisVoice {
|
||||
readonly attribute DOMString voiceURI;
|
||||
readonly attribute DOMString name;
|
||||
readonly attribute DOMString lang;
|
||||
readonly attribute boolean localService;
|
||||
readonly attribute boolean default;
|
||||
};
|
|
@ -321,13 +321,16 @@ endif
|
|||
|
||||
ifdef MOZ_WEBSPEECH
|
||||
webidl_files += \
|
||||
SpeechGrammar.webidl \
|
||||
SpeechGrammarList.webidl \
|
||||
SpeechRecognitionAlternative.webidl \
|
||||
SpeechRecognitionResultList.webidl \
|
||||
SpeechRecognitionResult.webidl \
|
||||
SpeechRecognition.webidl \
|
||||
$(NULL)
|
||||
SpeechGrammar.webidl \
|
||||
SpeechGrammarList.webidl \
|
||||
SpeechRecognitionAlternative.webidl \
|
||||
SpeechRecognitionResultList.webidl \
|
||||
SpeechRecognitionResult.webidl \
|
||||
SpeechRecognition.webidl \
|
||||
SpeechSynthesisUtterance.webidl \
|
||||
SpeechSynthesisVoice.webidl \
|
||||
SpeechSynthesis.webidl \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
|
|
|
@ -46,6 +46,7 @@ members = [
|
|||
'nsIDOMWindow.onmouseleave',
|
||||
'nsIDOMWindowPerformance.performance',
|
||||
'nsIDOMJSWindow.dump',
|
||||
'nsIDOMSpeechSynthesisGetter.speechSynthesis',
|
||||
# nsLocationSH has ~ALLOW_PROP_MODS_TO_PROTOTYPE, so don't try.
|
||||
#'nsIDOMLocation.hostname',
|
||||
#'nsIDOMLocation.href',
|
||||
|
|
|
@ -43,6 +43,9 @@ simple_events = [
|
|||
'ElementReplaceEvent',
|
||||
'MozSmsEvent',
|
||||
'MozMmsEvent',
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
'SpeechSynthesisEvent',
|
||||
#endif
|
||||
'DeviceStorageChangeEvent',
|
||||
'PopupBlockedEvent',
|
||||
'BlobEvent',
|
||||
|
|
|
@ -211,6 +211,7 @@ endif
|
|||
ifdef MOZ_WEBSPEECH
|
||||
SHARED_LIBRARY_LIBS += \
|
||||
$(DEPTH)/content/media/webspeech/recognition/$(LIB_PREFIX)gkconwebspeechrecognition_s.$(LIB_SUFFIX) \
|
||||
$(DEPTH)/content/media/webspeech/synth/$(LIB_PREFIX)gkconwebspeechsynth_s.$(LIB_SUFFIX) \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -342,6 +343,10 @@ ifdef MOZ_B2G_BT #{
|
|||
LOCAL_INCLUDES += -I$(topsrcdir)/dom/bluetooth
|
||||
endif #}
|
||||
|
||||
ifdef MOZ_WEBSPEECH #{
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/content/media/webspeech/synth
|
||||
endif #}
|
||||
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/dom/camera
|
||||
|
||||
DEFINES += -D_IMPL_NS_LAYOUT
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
#include "mozilla/dom/FakeSpeechRecognitionService.h"
|
||||
#include "mozilla/dom/nsSynthVoiceRegistry.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
|
@ -297,6 +298,11 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(BluetoothService,
|
|||
BluetoothService::FactoryCreate)
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsSynthVoiceRegistry,
|
||||
nsSynthVoiceRegistry::GetInstanceForService)
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(AudioManager)
|
||||
#endif
|
||||
|
@ -865,6 +871,7 @@ NS_DEFINE_NAMED_CID(NS_GAMEPAD_TEST_CID);
|
|||
#endif
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
NS_DEFINE_NAMED_CID(NS_FAKE_SPEECH_RECOGNITION_SERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SYNTHVOICEREGISTRY_CID);
|
||||
#endif
|
||||
|
||||
static nsresult
|
||||
|
@ -1116,6 +1123,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
|
|||
{ &kNS_FOCUSMANAGER_CID, false, NULL, CreateFocusManager },
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
{ &kNS_FAKE_SPEECH_RECOGNITION_SERVICE_CID, false, NULL, FakeSpeechRecognitionServiceConstructor },
|
||||
{ &kNS_SYNTHVOICEREGISTRY_CID, true, NULL, nsSynthVoiceRegistryConstructor },
|
||||
#endif
|
||||
{ &kCSPSERVICE_CID, false, NULL, CSPServiceConstructor },
|
||||
{ &kNS_MIXEDCONTENTBLOCKER_CID, false, NULL, nsMixedContentBlockerConstructor },
|
||||
|
@ -1265,6 +1273,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
|
|||
{ "@mozilla.org/focus-manager;1", &kNS_FOCUSMANAGER_CID },
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
{ NS_SPEECH_RECOGNITION_SERVICE_CONTRACTID_PREFIX "fake", &kNS_FAKE_SPEECH_RECOGNITION_SERVICE_CID },
|
||||
{ NS_SYNTHVOICEREGISTRY_CONTRACTID, &kNS_SYNTHVOICEREGISTRY_CID },
|
||||
#endif
|
||||
{ CSPSERVICE_CONTRACTID, &kCSPSERVICE_CID },
|
||||
{ NS_MIXEDCONTENTBLOCKER_CONTRACTID, &kNS_MIXEDCONTENTBLOCKER_CID },
|
||||
|
|
|
@ -75,6 +75,10 @@
|
|||
#include "nsHTMLEditor.h"
|
||||
#include "nsTextServicesDocument.h"
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
#include "nsSynthVoiceRegistry.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_MEDIA_PLUGINS
|
||||
#include "MediaPluginHost.h"
|
||||
#endif
|
||||
|
@ -358,6 +362,10 @@ nsLayoutStatics::Shutdown()
|
|||
nsVolumeService::Shutdown();
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
nsSynthVoiceRegistry::Shutdown();
|
||||
#endif
|
||||
|
||||
nsCORSListenerProxy::Shutdown();
|
||||
|
||||
nsIPresShell::ReleaseStatics();
|
||||
|
|
|
@ -392,6 +392,10 @@
|
|||
@BINPATH@/components/captivedetect.js
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
@BINPATH@/components/dom_webspeechsynth.xpt
|
||||
#endif
|
||||
|
||||
; Modules
|
||||
@BINPATH@/modules/*
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче