зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1258526
- Create SAPI object per speech to clear previous speech state at force. r=eeejay
When using the following script, stop method cannot clear pause state on SAPI backend. speech.pause(); speech.stop(); Since SPF_PURGEBEFORESPEAK doesn't clear previous speech state, we should create SAPI object per speech instead of recycling it. MozReview-Commit-ID: 2ajsTbauQpO --HG-- extra : rebase_source : b72d3e1215e136f204afda18497b042112002995
This commit is contained in:
Родитель
e4fd874441
Коммит
283296d609
|
@ -160,10 +160,11 @@ SapiCallback::OnSpeechEvent(const SPEVENT& speechEvent)
|
|||
void __stdcall
|
||||
SapiService::SpeechEventCallback(WPARAM aWParam, LPARAM aLParam)
|
||||
{
|
||||
RefPtr<SapiService> service = (SapiService*) aWParam;
|
||||
RefPtr<ISpVoice> spVoice = (ISpVoice*) aWParam;
|
||||
RefPtr<SapiService> service = (SapiService*) aLParam;
|
||||
|
||||
SPEVENT speechEvent;
|
||||
while (service->mSapiClient->GetEvents(1, &speechEvent, nullptr) == S_OK) {
|
||||
while (spVoice->GetEvents(1, &speechEvent, nullptr) == S_OK) {
|
||||
for (size_t i = 0; i < service->mCallbacks.Length(); i++) {
|
||||
RefPtr<SapiCallback> callback = service->mCallbacks[i];
|
||||
if (callback->GetStreamNum() == speechEvent.ulStreamNum) {
|
||||
|
@ -208,11 +209,24 @@ SapiService::Init()
|
|||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(CoCreateInstance(CLSID_SpVoice, nullptr, CLSCTX_ALL, IID_ISpVoice,
|
||||
getter_AddRefs(mSapiClient)))) {
|
||||
// Get all the voices from sapi and register in the SynthVoiceRegistry
|
||||
if (!RegisterVoices()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<ISpVoice>
|
||||
SapiService::InitSapiInstance()
|
||||
{
|
||||
RefPtr<ISpVoice> spVoice;
|
||||
if (FAILED(CoCreateInstance(CLSID_SpVoice, nullptr, CLSCTX_ALL, IID_ISpVoice,
|
||||
getter_AddRefs(spVoice)))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set interest for all the events we are interested in
|
||||
ULONGLONG eventMask =
|
||||
SPFEI(SPEI_START_INPUT_STREAM) |
|
||||
|
@ -221,21 +235,16 @@ SapiService::Init()
|
|||
SPFEI(SPEI_SENTENCE_BOUNDARY) |
|
||||
SPFEI(SPEI_END_INPUT_STREAM);
|
||||
|
||||
if (FAILED(mSapiClient->SetInterest(eventMask, eventMask))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get all the voices from sapi and register in the SynthVoiceRegistry
|
||||
if (!RegisterVoices()) {
|
||||
return false;
|
||||
if (FAILED(spVoice->SetInterest(eventMask, eventMask))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set the callback function for receiving the events
|
||||
mSapiClient->SetNotifyCallbackFunction(
|
||||
(SPNOTIFYCALLBACK*) SapiService::SpeechEventCallback, (WPARAM) this, 0);
|
||||
spVoice->SetNotifyCallbackFunction(
|
||||
(SPNOTIFYCALLBACK*) SapiService::SpeechEventCallback,
|
||||
(WPARAM) spVoice.get(), (LPARAM) this);
|
||||
|
||||
mInitialized = true;
|
||||
return true;
|
||||
return spVoice.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -331,11 +340,16 @@ SapiService::Speak(const nsAString& aText, const nsAString& aUri,
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (FAILED(mSapiClient->SetVoice(voiceToken))) {
|
||||
RefPtr<ISpVoice> spVoice = InitSapiInstance();
|
||||
if (!spVoice) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (FAILED(mSapiClient->SetVolume(static_cast<USHORT>(aVolume * 100)))) {
|
||||
if (FAILED(spVoice->SetVoice(voiceToken))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (FAILED(spVoice->SetVolume(static_cast<USHORT>(aVolume * 100)))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -348,7 +362,7 @@ SapiService::Speak(const nsAString& aText, const nsAString& aUri,
|
|||
// rate by the 10th root of 3"
|
||||
// https://msdn.microsoft.com/en-us/library/ee431826(v=vs.85).aspx
|
||||
long rate = aRate != 0 ? static_cast<long>(10 * log10(aRate) / log10(3)) : 0;
|
||||
if (FAILED(mSapiClient->SetRate(rate))) {
|
||||
if (FAILED(spVoice->SetRate(rate))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -370,7 +384,7 @@ SapiService::Speak(const nsAString& aText, const nsAString& aUri,
|
|||
xml.AppendLiteral("</pitch>");
|
||||
|
||||
RefPtr<SapiCallback> callback =
|
||||
new SapiCallback(aTask, mSapiClient, textOffset, aText.Length());
|
||||
new SapiCallback(aTask, spVoice, textOffset, aText.Length());
|
||||
|
||||
// The last three parameters doesn't matter for an indirect service
|
||||
nsresult rv = aTask->Setup(callback, 0, 0, 0);
|
||||
|
@ -379,7 +393,7 @@ SapiService::Speak(const nsAString& aText, const nsAString& aUri,
|
|||
}
|
||||
|
||||
ULONG streamNum;
|
||||
if (FAILED(mSapiClient->Speak(xml.get(), SPF_ASYNC, &streamNum))) {
|
||||
if (FAILED(spVoice->Speak(xml.get(), SPF_ASYNC, &streamNum))) {
|
||||
aTask->Setup(nullptr, 0, 0, 0);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -43,11 +43,11 @@ public:
|
|||
private:
|
||||
virtual ~SapiService();
|
||||
|
||||
already_AddRefed<ISpVoice> InitSapiInstance();
|
||||
bool RegisterVoices();
|
||||
|
||||
nsRefPtrHashtable<nsStringHashKey, ISpObjectToken> mVoices;
|
||||
nsTArray<RefPtr<SapiCallback>> mCallbacks;
|
||||
RefPtr<ISpVoice> mSapiClient;
|
||||
|
||||
bool mInitialized;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче