mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 10:09:05 +02:00
Recast Windows speech recognizer code to not use ATL
Visual Studio Express generates lots of linker warnings otherwise.
This commit is contained in:
parent
07630755d4
commit
a0a6a5019b
2 changed files with 36 additions and 30 deletions
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) && defined(HAVE_ATL)
|
#if defined(Q_OS_WIN) && defined(HAVE_ATL)
|
||||||
|
|
||||||
|
#include <sapi.h>
|
||||||
|
|
||||||
SpeechRecognizer::SpeechRecognizer() :
|
SpeechRecognizer::SpeechRecognizer() :
|
||||||
QObject(),
|
QObject(),
|
||||||
_enabled(false),
|
_enabled(false),
|
||||||
|
@ -36,17 +38,17 @@ SpeechRecognizer::SpeechRecognizer() :
|
||||||
}
|
}
|
||||||
|
|
||||||
_commandRecognizedNotifier = new QWinEventNotifier();
|
_commandRecognizedNotifier = new QWinEventNotifier();
|
||||||
connect(_commandRecognizedNotifier, SIGNAL(activated(HANDLE)), SLOT(notifyCommandRecognized(HANDLE)));
|
connect(_commandRecognizedNotifier, &QWinEventNotifier::activated, this, &SpeechRecognizer::notifyCommandRecognized);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpeechRecognizer::~SpeechRecognizer() {
|
SpeechRecognizer::~SpeechRecognizer() {
|
||||||
if (_speechRecognizerGrammar) {
|
if (_speechRecognizerGrammar) {
|
||||||
_speechRecognizerGrammar.Release();
|
static_cast<ISpRecoGrammar*>(_speechRecognizerGrammar)->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_enabled) {
|
if (_enabled) {
|
||||||
_speechRecognizerContext.Release();
|
static_cast<ISpRecoContext*>(_speechRecognizerContext)->Release();
|
||||||
_speechRecognizer.Release();
|
static_cast<ISpRecognizer*>(_speechRecognizer)->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_comInitialized) {
|
if (_comInitialized) {
|
||||||
|
@ -74,28 +76,29 @@ void SpeechRecognizer::setEnabled(bool enabled) {
|
||||||
// - Unless do SetGrammarState(SPGS_EXCLUSIVE) on shared recognizer but then non-Interface commands don't work at all.
|
// - Unless do SetGrammarState(SPGS_EXCLUSIVE) on shared recognizer but then non-Interface commands don't work at all.
|
||||||
// - With dedicated recognizer, user can choose whether to have Windows recognizer running in addition to Interface's.
|
// - With dedicated recognizer, user can choose whether to have Windows recognizer running in addition to Interface's.
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
hr = _speechRecognizer.CoCreateInstance(CLSID_SpInprocRecognizer);
|
hr = CoCreateInstance(CLSID_SpInprocRecognizer, NULL, CLSCTX_ALL, IID_ISpRecognizer, (void**)&_speechRecognizer);
|
||||||
}
|
}
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
CComPtr<ISpObjectToken> cpAudioToken;
|
CComPtr<ISpObjectToken> cpAudioToken;
|
||||||
hr = SpGetDefaultTokenFromCategoryId(SPCAT_AUDIOIN, &cpAudioToken);
|
hr = SpGetDefaultTokenFromCategoryId(SPCAT_AUDIOIN, &cpAudioToken);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
hr = _speechRecognizer->SetInput(cpAudioToken, TRUE);
|
hr = static_cast<ISpRecognizer*>(_speechRecognizer)->SetInput(cpAudioToken, TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
hr = _speechRecognizer->CreateRecoContext(&_speechRecognizerContext);
|
hr = static_cast<ISpRecognizer*>(_speechRecognizer)
|
||||||
|
->CreateRecoContext(reinterpret_cast<ISpRecoContext**>(&_speechRecognizerContext));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
_speechRecognizer.Release();
|
static_cast<ISpRecognizer*>(_speechRecognizer)->Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up event notification mechanism.
|
// Set up event notification mechanism.
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
hr = _speechRecognizerContext->SetNotifyWin32Event();
|
hr = static_cast<ISpRecoContext*>(_speechRecognizerContext)->SetNotifyWin32Event();
|
||||||
}
|
}
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
_commandRecognizedEvent = _speechRecognizerContext->GetNotifyEventHandle();
|
_commandRecognizedEvent = static_cast<ISpRecoContext*>(_speechRecognizerContext)->GetNotifyEventHandle();
|
||||||
if (_commandRecognizedEvent) {
|
if (_commandRecognizedEvent) {
|
||||||
_commandRecognizedNotifier->setHandle(_commandRecognizedEvent);
|
_commandRecognizedNotifier->setHandle(_commandRecognizedEvent);
|
||||||
_commandRecognizedNotifier->setEnabled(true);
|
_commandRecognizedNotifier->setEnabled(true);
|
||||||
|
@ -106,12 +109,14 @@ void SpeechRecognizer::setEnabled(bool enabled) {
|
||||||
|
|
||||||
// Set which events to be notified of.
|
// Set which events to be notified of.
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
hr = _speechRecognizerContext->SetInterest(SPFEI(SPEI_RECOGNITION), SPFEI(SPEI_RECOGNITION));
|
hr = static_cast<ISpRecoContext*>(_speechRecognizerContext)
|
||||||
|
->SetInterest(SPFEI(SPEI_RECOGNITION), SPFEI(SPEI_RECOGNITION));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create grammar and load commands.
|
// Create grammar and load commands.
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
hr = _speechRecognizerContext->CreateGrammar(NULL, &_speechRecognizerGrammar);
|
hr = static_cast<ISpRecoContext*>(_speechRecognizerContext)
|
||||||
|
->CreateGrammar(NULL, reinterpret_cast<ISpRecoGrammar**>(&_speechRecognizerGrammar));
|
||||||
}
|
}
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
reloadCommands();
|
reloadCommands();
|
||||||
|
@ -123,8 +128,8 @@ void SpeechRecognizer::setEnabled(bool enabled) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_commandRecognizedNotifier->setEnabled(false);
|
_commandRecognizedNotifier->setEnabled(false);
|
||||||
_speechRecognizerContext.Release();
|
static_cast<ISpRecoContext*>(_speechRecognizerContext)->Release();
|
||||||
_speechRecognizer.Release();
|
static_cast<ISpRecognizer*>(_speechRecognizer)->Release();
|
||||||
qDebug() << "Speech recognition disabled";
|
qDebug() << "Speech recognition disabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,12 +154,12 @@ void SpeechRecognizer::reloadCommands() {
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
hr = _speechRecognizerContext->Pause(NULL);
|
hr = static_cast<ISpRecoContext*>(_speechRecognizerContext)->Pause(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
WORD langId = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
|
WORD langId = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
|
||||||
hr = _speechRecognizerGrammar->ResetGrammar(langId);
|
hr = static_cast<ISpRecoGrammar*>(_speechRecognizerGrammar)->ResetGrammar(langId);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD ruleID = 0;
|
DWORD ruleID = 0;
|
||||||
|
@ -163,27 +168,27 @@ void SpeechRecognizer::reloadCommands() {
|
||||||
ruleID += 1;
|
ruleID += 1;
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
hr = _speechRecognizerGrammar->
|
hr = static_cast<ISpRecoGrammar*>(_speechRecognizerGrammar)->
|
||||||
GetRule(NULL, ruleID, SPRAF_TopLevel | SPRAF_Active | SPRAF_Dynamic, TRUE, &initialState);
|
GetRule(NULL, ruleID, SPRAF_TopLevel | SPRAF_Active | SPRAF_Dynamic, TRUE, &initialState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
const std::wstring command = (*iter).toStdWString();
|
const std::wstring command = (*iter).toStdWString();
|
||||||
hr = _speechRecognizerGrammar->
|
hr = static_cast<ISpRecoGrammar*>(_speechRecognizerGrammar)->
|
||||||
AddWordTransition(initialState, NULL, command.c_str(), L" ", SPWT_LEXICAL, 1.0, NULL);
|
AddWordTransition(initialState, NULL, command.c_str(), L" ", SPWT_LEXICAL, 1.0, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
hr = _speechRecognizerGrammar->Commit(NULL);
|
hr = static_cast<ISpRecoGrammar*>(_speechRecognizerGrammar)->Commit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
hr = _speechRecognizerContext->Resume(NULL);
|
hr = static_cast<ISpRecoContext*>(_speechRecognizerContext)->Resume(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
hr = _speechRecognizerGrammar->SetRuleState(NULL, NULL, SPRS_ACTIVE);
|
hr = static_cast<ISpRecoGrammar*>(_speechRecognizerGrammar)->SetRuleState(NULL, NULL, SPRS_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -191,10 +196,10 @@ void SpeechRecognizer::reloadCommands() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpeechRecognizer::notifyCommandRecognized(HANDLE handle) {
|
void SpeechRecognizer::notifyCommandRecognized(void* handle) {
|
||||||
SPEVENT eventItem;
|
SPEVENT eventItem;
|
||||||
memset(&eventItem, 0, sizeof(SPEVENT));
|
memset(&eventItem, 0, sizeof(SPEVENT));
|
||||||
HRESULT hr = _speechRecognizerContext->GetEvents(1, &eventItem, NULL);
|
HRESULT hr = static_cast<ISpRecoContext*>(_speechRecognizerContext)->GetEvents(1, &eventItem, NULL);
|
||||||
|
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
if (eventItem.eEventId == SPEI_RECOGNITION && eventItem.elParamType == SPET_LPARAM_IS_OBJECT) {
|
if (eventItem.eEventId == SPEI_RECOGNITION && eventItem.elParamType == SPET_LPARAM_IS_OBJECT) {
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
#if defined(Q_OS_WIN) && defined(HAVE_ATL)
|
#if defined(Q_OS_WIN) && defined(HAVE_ATL)
|
||||||
#include <QWinEventNotifier>
|
#include <QWinEventNotifier>
|
||||||
|
|
||||||
#include <atlbase.h>
|
//#include <atlbase.h>
|
||||||
#include <sapi.h>
|
//#include <sapi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class SpeechRecognizer : public QObject {
|
class SpeechRecognizer : public QObject {
|
||||||
|
@ -52,16 +52,17 @@ private:
|
||||||
void* _speechRecognizer;
|
void* _speechRecognizer;
|
||||||
#elif defined(Q_OS_WIN) && defined(HAVE_ATL)
|
#elif defined(Q_OS_WIN) && defined(HAVE_ATL)
|
||||||
bool _comInitialized;
|
bool _comInitialized;
|
||||||
CComPtr<ISpRecognizer> _speechRecognizer;
|
// Use void* instead of ATL CComPtr<> for speech recognizer in order to avoid linker errors with Visual Studio Express.
|
||||||
CComPtr<ISpRecoContext> _speechRecognizerContext;
|
void* _speechRecognizer;
|
||||||
CComPtr<ISpRecoGrammar> _speechRecognizerGrammar;
|
void* _speechRecognizerContext;
|
||||||
HANDLE _commandRecognizedEvent;
|
void* _speechRecognizerGrammar;
|
||||||
|
void* _commandRecognizedEvent;
|
||||||
QWinEventNotifier* _commandRecognizedNotifier;
|
QWinEventNotifier* _commandRecognizedNotifier;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) && defined(HAVE_ATL)
|
#if defined(Q_OS_WIN) && defined(HAVE_ATL)
|
||||||
private slots:
|
private slots:
|
||||||
void notifyCommandRecognized(HANDLE handle);
|
void notifyCommandRecognized(void* handle);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue