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:
Makoto Kato 2016-05-06 17:33:20 +09:00
Родитель e4fd874441
Коммит 283296d609
2 изменённых файлов: 35 добавлений и 21 удалений

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

@ -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;