mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 14:55:47 +00:00
Bug 1184142 - Support WebSpeech in GeckoView. r=snorp r=smaug
--HG-- extra : rebase_source : 81eb1ce2f67f70ee08908d69db54f8625df341cb
This commit is contained in:
parent
0ee918977a
commit
f765d0d585
49
dom/media/webspeech/synth/android/AndroidSpeechModule.cpp
Normal file
49
dom/media/webspeech/synth/android/AndroidSpeechModule.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 "mozilla/ModuleUtils.h"
|
||||
#include "SpeechSynthesisService.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
#define ANDROIDSPEECHSERVICE_CID \
|
||||
{0x311b2dab, 0xf4d3, 0x4be4, {0x81, 0x23, 0x67, 0x32, 0x31, 0x3d, 0x95, 0xc2}}
|
||||
|
||||
#define ANDROIDSPEECHSERVICE_CONTRACTID "@mozilla.org/androidspeechsynth;1"
|
||||
|
||||
// Defines AndroidSpeechServiceConstructor
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(SpeechSynthesisService,
|
||||
SpeechSynthesisService::GetInstanceForService)
|
||||
|
||||
// Defines kANDROIDSPEECHSERVICE_CID
|
||||
NS_DEFINE_NAMED_CID(ANDROIDSPEECHSERVICE_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry kCIDs[] = {
|
||||
{ &kANDROIDSPEECHSERVICE_CID, true, nullptr, SpeechSynthesisServiceConstructor },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module::ContractIDEntry kContracts[] = {
|
||||
{ ANDROIDSPEECHSERVICE_CONTRACTID, &kANDROIDSPEECHSERVICE_CID },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module::CategoryEntry kCategories[] = {
|
||||
{ "speech-synth-started", "Android Speech Synth", ANDROIDSPEECHSERVICE_CONTRACTID },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module kModule = {
|
||||
mozilla::Module::kVersion,
|
||||
kCIDs,
|
||||
kContracts,
|
||||
kCategories,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
};
|
||||
|
||||
NSMODULE_DEFN(androidspeechsynth) = &kModule;
|
245
dom/media/webspeech/synth/android/SpeechSynthesisService.cpp
Normal file
245
dom/media/webspeech/synth/android/SpeechSynthesisService.cpp
Normal file
@ -0,0 +1,245 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 "SpeechSynthesisService.h"
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/dom/nsSynthVoiceRegistry.h"
|
||||
#include "mozilla/jni/Utils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#define ALOG(args...) \
|
||||
__android_log_print(ANDROID_LOG_INFO, "GeckoSpeechSynthesis", ##args)
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
StaticRefPtr<SpeechSynthesisService> SpeechSynthesisService::sSingleton;
|
||||
|
||||
class AndroidSpeechCallback final : public nsISpeechTaskCallback
|
||||
{
|
||||
public:
|
||||
AndroidSpeechCallback()
|
||||
{
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD OnResume() override { return NS_OK; }
|
||||
|
||||
NS_IMETHOD OnPause() override { return NS_OK; }
|
||||
|
||||
NS_IMETHOD OnCancel() override
|
||||
{
|
||||
java::SpeechSynthesisService::Stop();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHOD OnVolumeChanged(float aVolume) override { return NS_OK; }
|
||||
|
||||
private:
|
||||
~AndroidSpeechCallback() {}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(AndroidSpeechCallback, nsISpeechTaskCallback)
|
||||
|
||||
NS_IMPL_ISUPPORTS(SpeechSynthesisService, nsISpeechService)
|
||||
|
||||
void
|
||||
SpeechSynthesisService::Setup()
|
||||
{
|
||||
ALOG("SpeechSynthesisService::Setup");
|
||||
|
||||
if (!Preferences::GetBool("media.webspeech.synth.enabled") ||
|
||||
Preferences::GetBool("media.webspeech.synth.test")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!jni::IsAvailable()) {
|
||||
NS_WARNING("Failed to initialize speech synthesis");
|
||||
return;
|
||||
}
|
||||
|
||||
Init();
|
||||
java::SpeechSynthesisService::InitSynth();
|
||||
}
|
||||
|
||||
// nsISpeechService
|
||||
|
||||
NS_IMETHODIMP
|
||||
SpeechSynthesisService::Speak(const nsAString& aText,
|
||||
const nsAString& aUri,
|
||||
float aVolume,
|
||||
float aRate,
|
||||
float aPitch,
|
||||
nsISpeechTask* aTask)
|
||||
{
|
||||
if (mTask) {
|
||||
NS_WARNING("Service only supports one speech task at a time.");
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
RefPtr<AndroidSpeechCallback> callback = new AndroidSpeechCallback();
|
||||
nsresult rv = aTask->Setup(callback);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
jni::String::LocalRef utteranceId =
|
||||
java::SpeechSynthesisService::Speak(aUri, aText, aRate, aPitch, aVolume);
|
||||
if (!utteranceId) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
mTaskUtteranceId = utteranceId->ToCString();
|
||||
mTask = aTask;
|
||||
mTaskTextLength = aText.Length();
|
||||
mTaskTextOffset = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
SpeechSynthesisService*
|
||||
SpeechSynthesisService::GetInstance(bool aCreate)
|
||||
{
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
MOZ_ASSERT(
|
||||
false,
|
||||
"SpeechSynthesisService can only be started on main gecko process");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!sSingleton && aCreate) {
|
||||
sSingleton = new SpeechSynthesisService();
|
||||
sSingleton->Setup();
|
||||
ClearOnShutdown(&sSingleton);
|
||||
}
|
||||
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
already_AddRefed<SpeechSynthesisService>
|
||||
SpeechSynthesisService::GetInstanceForService()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
RefPtr<SpeechSynthesisService> sapiService = GetInstance();
|
||||
return sapiService.forget();
|
||||
}
|
||||
|
||||
// JNI
|
||||
|
||||
void
|
||||
SpeechSynthesisService::RegisterVoice(jni::String::Param aUri,
|
||||
jni::String::Param aName,
|
||||
jni::String::Param aLocale,
|
||||
bool aIsNetwork,
|
||||
bool aIsDefault)
|
||||
{
|
||||
nsSynthVoiceRegistry* registry = nsSynthVoiceRegistry::GetInstance();
|
||||
SpeechSynthesisService* service = SpeechSynthesisService::GetInstance(false);
|
||||
// This service can only speak one utterance at a time, so we set
|
||||
// aQueuesUtterances to true in order to track global state and schedule
|
||||
// access to this service.
|
||||
DebugOnly<nsresult> rv = registry->AddVoice(service,
|
||||
aUri->ToString(),
|
||||
aName->ToString(),
|
||||
aLocale->ToString(),
|
||||
!aIsNetwork,
|
||||
true);
|
||||
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to add voice");
|
||||
|
||||
if (aIsDefault) {
|
||||
DebugOnly<nsresult> rv = registry->SetDefaultVoice(aUri->ToString(), true);
|
||||
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to set voice as default");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisService::DoneRegisteringVoices()
|
||||
{
|
||||
nsSynthVoiceRegistry* registry = nsSynthVoiceRegistry::GetInstance();
|
||||
registry->NotifyVoicesChanged();
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisService::DispatchStart(jni::String::Param aUtteranceId)
|
||||
{
|
||||
if (sSingleton) {
|
||||
MOZ_ASSERT(sSingleton->mTaskUtteranceId.Equals(aUtteranceId->ToCString()));
|
||||
nsCOMPtr<nsISpeechTask> task = sSingleton->mTask;
|
||||
if (task) {
|
||||
sSingleton->mTaskStartTime = TimeStamp::Now();
|
||||
DebugOnly<nsresult> rv = task->DispatchStart();
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Unable to dispatch start");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisService::DispatchEnd(jni::String::Param aUtteranceId)
|
||||
{
|
||||
if (sSingleton) {
|
||||
// In API older than 23, we will sometimes call this function
|
||||
// without providing an utterance ID.
|
||||
MOZ_ASSERT(!aUtteranceId ||
|
||||
sSingleton->mTaskUtteranceId.Equals(aUtteranceId->ToCString()));
|
||||
nsCOMPtr<nsISpeechTask> task = sSingleton->mTask;
|
||||
sSingleton->mTask = nullptr;
|
||||
if (task) {
|
||||
TimeStamp startTime = sSingleton->mTaskStartTime;
|
||||
DebugOnly<nsresult> rv = task->DispatchEnd(
|
||||
(TimeStamp::Now() - startTime).ToSeconds(), sSingleton->mTaskTextLength);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Unable to dispatch start");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisService::DispatchError(jni::String::Param aUtteranceId)
|
||||
{
|
||||
if (sSingleton) {
|
||||
MOZ_ASSERT(sSingleton->mTaskUtteranceId.Equals(aUtteranceId->ToCString()));
|
||||
nsCOMPtr<nsISpeechTask> task = sSingleton->mTask;
|
||||
sSingleton->mTask = nullptr;
|
||||
if (task) {
|
||||
TimeStamp startTime = sSingleton->mTaskStartTime;
|
||||
DebugOnly<nsresult> rv = task->DispatchError(
|
||||
(TimeStamp::Now() - startTime).ToSeconds(), sSingleton->mTaskTextOffset);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Unable to dispatch start");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SpeechSynthesisService::DispatchBoundary(jni::String::Param aUtteranceId,
|
||||
int32_t aStart,
|
||||
int32_t aEnd)
|
||||
{
|
||||
if (sSingleton) {
|
||||
MOZ_ASSERT(sSingleton->mTaskUtteranceId.Equals(aUtteranceId->ToCString()));
|
||||
nsCOMPtr<nsISpeechTask> task = sSingleton->mTask;
|
||||
if (task) {
|
||||
TimeStamp startTime = sSingleton->mTaskStartTime;
|
||||
sSingleton->mTaskTextOffset = aStart;
|
||||
DebugOnly<nsresult> rv =
|
||||
task->DispatchBoundary(NS_LITERAL_STRING("word"),
|
||||
(TimeStamp::Now() - startTime).ToSeconds(),
|
||||
aStart,
|
||||
aEnd - aStart,
|
||||
1);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Unable to dispatch boundary");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
72
dom/media/webspeech/synth/android/SpeechSynthesisService.h
Normal file
72
dom/media/webspeech/synth/android/SpeechSynthesisService.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_SpeechSynthesisService_h
|
||||
#define mozilla_dom_SpeechSynthesisService_h
|
||||
|
||||
#include "GeneratedJNINatives.h"
|
||||
#include "nsISpeechService.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class SpeechSynthesisService final
|
||||
: public nsISpeechService
|
||||
, public java::SpeechSynthesisService::Natives<SpeechSynthesisService>
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISPEECHSERVICE
|
||||
|
||||
SpeechSynthesisService(){};
|
||||
|
||||
void Setup();
|
||||
|
||||
static void DoneRegisteringVoices();
|
||||
|
||||
static void RegisterVoice(jni::String::Param aUri,
|
||||
jni::String::Param aName,
|
||||
jni::String::Param aLocale,
|
||||
bool aIsNetwork,
|
||||
bool aIsDefault);
|
||||
|
||||
static void DispatchStart(jni::String::Param aUtteranceId);
|
||||
|
||||
static void DispatchEnd(jni::String::Param aUtteranceId);
|
||||
|
||||
static void DispatchError(jni::String::Param aUtteranceId);
|
||||
|
||||
static void DispatchBoundary(jni::String::Param aUtteranceId,
|
||||
int32_t aStart,
|
||||
int32_t aEnd);
|
||||
|
||||
static SpeechSynthesisService* GetInstance(bool aCreate = true);
|
||||
static already_AddRefed<SpeechSynthesisService> GetInstanceForService();
|
||||
|
||||
static StaticRefPtr<SpeechSynthesisService> sSingleton;
|
||||
|
||||
private:
|
||||
virtual ~SpeechSynthesisService(){};
|
||||
|
||||
nsCOMPtr<nsISpeechTask> mTask;
|
||||
|
||||
// Unique ID assigned to utterance when it is sent to system service.
|
||||
nsCString mTaskUtteranceId;
|
||||
|
||||
// Time stamp from the moment the utterance is started.
|
||||
TimeStamp mTaskStartTime;
|
||||
|
||||
// Length of text of the utterance.
|
||||
uint32_t mTaskTextLength;
|
||||
|
||||
// Current offset in characters of what has been spoken.
|
||||
uint32_t mTaskTextOffset;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
#endif
|
15
dom/media/webspeech/synth/android/moz.build
Normal file
15
dom/media/webspeech/synth/android/moz.build
Normal file
@ -0,0 +1,15 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# 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/.
|
||||
|
||||
EXPORTS.mozilla.dom += ['SpeechSynthesisService.h']
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'AndroidSpeechModule.cpp',
|
||||
'SpeechSynthesisService.cpp'
|
||||
]
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
@ -48,6 +48,9 @@ if CONFIG['MOZ_WEBSPEECH']:
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
DIRS += ['cocoa']
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
||||
DIRS += ['android']
|
||||
|
||||
if CONFIG['MOZ_SYNTH_SPEECHD']:
|
||||
DIRS += ['speechd']
|
||||
|
||||
|
@ -0,0 +1,159 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil -*- */
|
||||
/* vim: set ts=20 sts=4 et sw=4: */
|
||||
/* 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/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import android.speech.tts.UtteranceProgressListener;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.System;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SpeechSynthesisService {
|
||||
private static final String LOGTAG = "GeckoSpeechSynthesis";
|
||||
private static TextToSpeech sTTS;
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
public static void initSynth() {
|
||||
if (sTTS != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Context ctx = GeckoAppShell.getApplicationContext();
|
||||
|
||||
sTTS = new TextToSpeech(ctx, new TextToSpeech.OnInitListener() {
|
||||
@Override
|
||||
public void onInit(int status) {
|
||||
if (status != TextToSpeech.SUCCESS) {
|
||||
Log.w(LOGTAG, "Failed to initialize TextToSpeech");
|
||||
return;
|
||||
}
|
||||
|
||||
setUtteranceListener();
|
||||
registerVoicesByLocale();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void registerVoicesByLocale() {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Locale defaultLocale = sTTS.getDefaultLanguage();
|
||||
for (Locale locale : getAvailableLanguages()) {
|
||||
final Set<String> features = sTTS.getFeatures(locale);
|
||||
boolean isLocal = features.contains(TextToSpeech.Engine.KEY_FEATURE_EMBEDDED_SYNTHESIS);
|
||||
String localeStr = locale.toString();
|
||||
registerVoice("moz-tts:android:" + localeStr, locale.getDisplayName(), localeStr.replace("_", "-"), !isLocal, defaultLocale == locale);
|
||||
}
|
||||
doneRegisteringVoices();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static Set<Locale> getAvailableLanguages() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
return sTTS.getAvailableLanguages();
|
||||
}
|
||||
Set<Locale> locales = new HashSet<Locale>();
|
||||
for (Locale locale : Locale.getAvailableLocales()) {
|
||||
if (locale.getVariant().isEmpty() && sTTS.isLanguageAvailable(locale) > 0) {
|
||||
locales.add(locale);
|
||||
}
|
||||
}
|
||||
|
||||
return locales;
|
||||
}
|
||||
|
||||
@WrapForJNI(dispatchTo = "gecko")
|
||||
private static native void registerVoice(String uri, String name, String locale, boolean isNetwork, boolean isDefault);
|
||||
|
||||
@WrapForJNI(dispatchTo = "gecko")
|
||||
private static native void doneRegisteringVoices();
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
public static String speak(final String uri, final String text, float rate, float pitch, float volume) {
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
final String utteranceId = UUID.randomUUID().toString();
|
||||
params.put(TextToSpeech.Engine.KEY_PARAM_VOLUME, Float.toString(volume));
|
||||
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utteranceId);
|
||||
sTTS.setLanguage(new Locale(uri.substring("moz-tts:android:".length())));
|
||||
sTTS.setSpeechRate(rate);
|
||||
sTTS.setPitch(pitch);
|
||||
int result = sTTS.speak(text, TextToSpeech.QUEUE_FLUSH, params);
|
||||
if (result != TextToSpeech.SUCCESS) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return utteranceId;
|
||||
}
|
||||
|
||||
private static void setUtteranceListener() {
|
||||
sTTS.setOnUtteranceProgressListener(new UtteranceProgressListener() {
|
||||
@Override
|
||||
public void onDone(String utteranceId) {
|
||||
dispatchEnd(utteranceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String utteranceId) {
|
||||
dispatchError(utteranceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(String utteranceId) {
|
||||
dispatchStart(utteranceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop(String utteranceId, boolean interrupted) {
|
||||
if (interrupted) {
|
||||
dispatchEnd(utteranceId);
|
||||
} else {
|
||||
// utterance isn't started yet.
|
||||
dispatchError(utteranceId);
|
||||
}
|
||||
}
|
||||
|
||||
public void onRangeStart (String utteranceId, int start, int end, int frame) {
|
||||
dispatchBoundary(utteranceId, start, end);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@WrapForJNI(dispatchTo = "gecko")
|
||||
private static native void dispatchStart(String utteranceId);
|
||||
|
||||
@WrapForJNI(dispatchTo = "gecko")
|
||||
private static native void dispatchEnd(String utteranceId);
|
||||
|
||||
@WrapForJNI(dispatchTo = "gecko")
|
||||
private static native void dispatchError(String utteranceId);
|
||||
|
||||
@WrapForJNI(dispatchTo = "gecko")
|
||||
private static native void dispatchBoundary(String utteranceId, int start, int end);
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
public static void stop() {
|
||||
sTTS.stop();
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
// Android M has onStop method. If Android L or above, dispatch
|
||||
// event
|
||||
dispatchEnd(null);
|
||||
}
|
||||
}
|
||||
}
|
@ -326,6 +326,41 @@ const JNINativeMethod ScreenManagerHelper::Natives<Impl>::methods[] = {
|
||||
::template Wrap<&Impl::RemoveDisplay>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class SpeechSynthesisService::Natives : public mozilla::jni::NativeImpl<SpeechSynthesisService, Impl>
|
||||
{
|
||||
public:
|
||||
static const JNINativeMethod methods[6];
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
const JNINativeMethod SpeechSynthesisService::Natives<Impl>::methods[] = {
|
||||
|
||||
mozilla::jni::MakeNativeMethod<SpeechSynthesisService::DispatchBoundary_t>(
|
||||
mozilla::jni::NativeStub<SpeechSynthesisService::DispatchBoundary_t, Impl>
|
||||
::template Wrap<&Impl::DispatchBoundary>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<SpeechSynthesisService::DispatchEnd_t>(
|
||||
mozilla::jni::NativeStub<SpeechSynthesisService::DispatchEnd_t, Impl>
|
||||
::template Wrap<&Impl::DispatchEnd>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<SpeechSynthesisService::DispatchError_t>(
|
||||
mozilla::jni::NativeStub<SpeechSynthesisService::DispatchError_t, Impl>
|
||||
::template Wrap<&Impl::DispatchError>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<SpeechSynthesisService::DispatchStart_t>(
|
||||
mozilla::jni::NativeStub<SpeechSynthesisService::DispatchStart_t, Impl>
|
||||
::template Wrap<&Impl::DispatchStart>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<SpeechSynthesisService::DoneRegisteringVoices_t>(
|
||||
mozilla::jni::NativeStub<SpeechSynthesisService::DoneRegisteringVoices_t, Impl>
|
||||
::template Wrap<&Impl::DoneRegisteringVoices>),
|
||||
|
||||
mozilla::jni::MakeNativeMethod<SpeechSynthesisService::RegisterVoice_t>(
|
||||
mozilla::jni::NativeStub<SpeechSynthesisService::RegisterVoice_t, Impl>
|
||||
::template Wrap<&Impl::RegisterVoice>)
|
||||
};
|
||||
|
||||
template<class Impl>
|
||||
class SurfaceTextureListener::Natives : public mozilla::jni::NativeImpl<SurfaceTextureListener, Impl>
|
||||
{
|
||||
|
@ -1017,6 +1017,51 @@ constexpr char ScreenManagerHelper::AddDisplay_t::signature[];
|
||||
constexpr char ScreenManagerHelper::RemoveDisplay_t::name[];
|
||||
constexpr char ScreenManagerHelper::RemoveDisplay_t::signature[];
|
||||
|
||||
const char SpeechSynthesisService::name[] =
|
||||
"org/mozilla/gecko/SpeechSynthesisService";
|
||||
|
||||
constexpr char SpeechSynthesisService::DispatchBoundary_t::name[];
|
||||
constexpr char SpeechSynthesisService::DispatchBoundary_t::signature[];
|
||||
|
||||
constexpr char SpeechSynthesisService::DispatchEnd_t::name[];
|
||||
constexpr char SpeechSynthesisService::DispatchEnd_t::signature[];
|
||||
|
||||
constexpr char SpeechSynthesisService::DispatchError_t::name[];
|
||||
constexpr char SpeechSynthesisService::DispatchError_t::signature[];
|
||||
|
||||
constexpr char SpeechSynthesisService::DispatchStart_t::name[];
|
||||
constexpr char SpeechSynthesisService::DispatchStart_t::signature[];
|
||||
|
||||
constexpr char SpeechSynthesisService::DoneRegisteringVoices_t::name[];
|
||||
constexpr char SpeechSynthesisService::DoneRegisteringVoices_t::signature[];
|
||||
|
||||
constexpr char SpeechSynthesisService::InitSynth_t::name[];
|
||||
constexpr char SpeechSynthesisService::InitSynth_t::signature[];
|
||||
|
||||
auto SpeechSynthesisService::InitSynth() -> void
|
||||
{
|
||||
return mozilla::jni::Method<InitSynth_t>::Call(SpeechSynthesisService::Context(), nullptr);
|
||||
}
|
||||
|
||||
constexpr char SpeechSynthesisService::RegisterVoice_t::name[];
|
||||
constexpr char SpeechSynthesisService::RegisterVoice_t::signature[];
|
||||
|
||||
constexpr char SpeechSynthesisService::Speak_t::name[];
|
||||
constexpr char SpeechSynthesisService::Speak_t::signature[];
|
||||
|
||||
auto SpeechSynthesisService::Speak(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1, float a2, float a3, float a4) -> mozilla::jni::String::LocalRef
|
||||
{
|
||||
return mozilla::jni::Method<Speak_t>::Call(SpeechSynthesisService::Context(), nullptr, a0, a1, a2, a3, a4);
|
||||
}
|
||||
|
||||
constexpr char SpeechSynthesisService::Stop_t::name[];
|
||||
constexpr char SpeechSynthesisService::Stop_t::signature[];
|
||||
|
||||
auto SpeechSynthesisService::Stop() -> void
|
||||
{
|
||||
return mozilla::jni::Method<Stop_t>::Call(SpeechSynthesisService::Context(), nullptr);
|
||||
}
|
||||
|
||||
const char SurfaceTextureListener::name[] =
|
||||
"org/mozilla/gecko/SurfaceTextureListener";
|
||||
|
||||
|
@ -3095,6 +3095,194 @@ public:
|
||||
template<class Impl> class Natives;
|
||||
};
|
||||
|
||||
class SpeechSynthesisService : public mozilla::jni::ObjectBase<SpeechSynthesisService>
|
||||
{
|
||||
public:
|
||||
static const char name[];
|
||||
|
||||
explicit SpeechSynthesisService(const Context& ctx) : ObjectBase<SpeechSynthesisService>(ctx) {}
|
||||
|
||||
struct DispatchBoundary_t {
|
||||
typedef SpeechSynthesisService Owner;
|
||||
typedef void ReturnType;
|
||||
typedef void SetterType;
|
||||
typedef mozilla::jni::Args<
|
||||
mozilla::jni::String::Param,
|
||||
int32_t,
|
||||
int32_t> Args;
|
||||
static constexpr char name[] = "dispatchBoundary";
|
||||
static constexpr char signature[] =
|
||||
"(Ljava/lang/String;II)V";
|
||||
static const bool isStatic = true;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::ANY;
|
||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||
mozilla::jni::DispatchTarget::GECKO;
|
||||
};
|
||||
|
||||
struct DispatchEnd_t {
|
||||
typedef SpeechSynthesisService Owner;
|
||||
typedef void ReturnType;
|
||||
typedef void SetterType;
|
||||
typedef mozilla::jni::Args<
|
||||
mozilla::jni::String::Param> Args;
|
||||
static constexpr char name[] = "dispatchEnd";
|
||||
static constexpr char signature[] =
|
||||
"(Ljava/lang/String;)V";
|
||||
static const bool isStatic = true;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::ANY;
|
||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||
mozilla::jni::DispatchTarget::GECKO;
|
||||
};
|
||||
|
||||
struct DispatchError_t {
|
||||
typedef SpeechSynthesisService Owner;
|
||||
typedef void ReturnType;
|
||||
typedef void SetterType;
|
||||
typedef mozilla::jni::Args<
|
||||
mozilla::jni::String::Param> Args;
|
||||
static constexpr char name[] = "dispatchError";
|
||||
static constexpr char signature[] =
|
||||
"(Ljava/lang/String;)V";
|
||||
static const bool isStatic = true;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::ANY;
|
||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||
mozilla::jni::DispatchTarget::GECKO;
|
||||
};
|
||||
|
||||
struct DispatchStart_t {
|
||||
typedef SpeechSynthesisService Owner;
|
||||
typedef void ReturnType;
|
||||
typedef void SetterType;
|
||||
typedef mozilla::jni::Args<
|
||||
mozilla::jni::String::Param> Args;
|
||||
static constexpr char name[] = "dispatchStart";
|
||||
static constexpr char signature[] =
|
||||
"(Ljava/lang/String;)V";
|
||||
static const bool isStatic = true;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::ANY;
|
||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||
mozilla::jni::DispatchTarget::GECKO;
|
||||
};
|
||||
|
||||
struct DoneRegisteringVoices_t {
|
||||
typedef SpeechSynthesisService Owner;
|
||||
typedef void ReturnType;
|
||||
typedef void SetterType;
|
||||
typedef mozilla::jni::Args<> Args;
|
||||
static constexpr char name[] = "doneRegisteringVoices";
|
||||
static constexpr char signature[] =
|
||||
"()V";
|
||||
static const bool isStatic = true;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::ANY;
|
||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||
mozilla::jni::DispatchTarget::GECKO;
|
||||
};
|
||||
|
||||
struct InitSynth_t {
|
||||
typedef SpeechSynthesisService Owner;
|
||||
typedef void ReturnType;
|
||||
typedef void SetterType;
|
||||
typedef mozilla::jni::Args<> Args;
|
||||
static constexpr char name[] = "initSynth";
|
||||
static constexpr char signature[] =
|
||||
"()V";
|
||||
static const bool isStatic = true;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::GECKO;
|
||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||
mozilla::jni::DispatchTarget::CURRENT;
|
||||
};
|
||||
|
||||
static auto InitSynth() -> void;
|
||||
|
||||
struct RegisterVoice_t {
|
||||
typedef SpeechSynthesisService Owner;
|
||||
typedef void ReturnType;
|
||||
typedef void SetterType;
|
||||
typedef mozilla::jni::Args<
|
||||
mozilla::jni::String::Param,
|
||||
mozilla::jni::String::Param,
|
||||
mozilla::jni::String::Param,
|
||||
bool,
|
||||
bool> Args;
|
||||
static constexpr char name[] = "registerVoice";
|
||||
static constexpr char signature[] =
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZ)V";
|
||||
static const bool isStatic = true;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::ANY;
|
||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||
mozilla::jni::DispatchTarget::GECKO;
|
||||
};
|
||||
|
||||
struct Speak_t {
|
||||
typedef SpeechSynthesisService Owner;
|
||||
typedef mozilla::jni::String::LocalRef ReturnType;
|
||||
typedef mozilla::jni::String::Param SetterType;
|
||||
typedef mozilla::jni::Args<
|
||||
mozilla::jni::String::Param,
|
||||
mozilla::jni::String::Param,
|
||||
float,
|
||||
float,
|
||||
float> Args;
|
||||
static constexpr char name[] = "speak";
|
||||
static constexpr char signature[] =
|
||||
"(Ljava/lang/String;Ljava/lang/String;FFF)Ljava/lang/String;";
|
||||
static const bool isStatic = true;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::GECKO;
|
||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||
mozilla::jni::DispatchTarget::CURRENT;
|
||||
};
|
||||
|
||||
static auto Speak(mozilla::jni::String::Param, mozilla::jni::String::Param, float, float, float) -> mozilla::jni::String::LocalRef;
|
||||
|
||||
struct Stop_t {
|
||||
typedef SpeechSynthesisService Owner;
|
||||
typedef void ReturnType;
|
||||
typedef void SetterType;
|
||||
typedef mozilla::jni::Args<> Args;
|
||||
static constexpr char name[] = "stop";
|
||||
static constexpr char signature[] =
|
||||
"()V";
|
||||
static const bool isStatic = true;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::GECKO;
|
||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||
mozilla::jni::DispatchTarget::CURRENT;
|
||||
};
|
||||
|
||||
static auto Stop() -> void;
|
||||
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::ANY;
|
||||
|
||||
template<class Impl> class Natives;
|
||||
};
|
||||
|
||||
class SurfaceTextureListener : public mozilla::jni::ObjectBase<SurfaceTextureListener>
|
||||
{
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user