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:
Eitan Isaacson 2013-04-03 15:13:16 -07:00
Родитель 542d52e905
Коммит 998738aff3
40 изменённых файлов: 1669 добавлений и 8 удалений

Просмотреть файл

@ -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/*