I found this on google while searching on some information on SAPI identifying phrases. This example shows if there is only one property in the rule. So what if there are 2 or m
Alright, so sorry for the wait. I whipped up a simple program that may help you figure out what you're trying to do.
So here's my grammar file:
<GRAMMAR LANGID="409">
<DEFINE>
<ID NAME="LIKE_VAL" VAL="1"/>
<ID NAME="SUBJECT_VAL" VAL="2"/>
<ID NAME="COMBINED_VAL" VAL="3"/>
<ID NAME="EXIT_VAL" VAL="4"/>
</DEFINE>
<RULE NAME="LIKE_VAL" TOPLEVEL="ACTIVE">
<L>
<P>I <O>really</O> like</P>
<P>I <O>really</O> do not like</P>
</L>
</RULE>
<RULE NAME="SUBJECT_VAL" TOPLEVEL="ACTIVE">
<P>ponies.</P>
</RULE>
<RULE NAME="COMBINED_VAL" TOPLEVEL="ACTIVE">
<RULEREF NAME="LIKE_VAL"/>
<RULEREF NAME="SUBJECT_VAL"/>
</RULE>
<RULE NAME="EXIT_VAL" TOPLEVEL="ACTIVE">
<L>
<P>Exit</P>
<P>Quit</P>
<P>Terminate</P>
<P>Deluminate</P>
</L>
</RULE>
</GRAMMAR>
And here's a full program that uses it:
#include "sphelper.h"
#include <Windows.h>
#include <string>
int main(int argc, char* argv[])
{
CComPtr<ISpRecognizer> cpReco;
CComPtr<ISpRecoContext> cpRecoCtx;
CComPtr<ISpRecoGrammar> cpRecoGram;
ULONGLONG ullEvents = SPFEI(SPEI_RECOGNITION)|
SPFEI(SPEI_FALSE_RECOGNITION);
ISpObjectToken* pInputToken;
ISpRecoResult* cpRecoRslt;
HRESULT hr = S_OK;
hr = ::CoInitialize(NULL);
hr = cpReco.CoCreateInstance(CLSID_SpInprocRecognizer);
hr = cpReco->CreateRecoContext(&cpRecoCtx);
hr = cpRecoCtx->CreateGrammar(0, &cpRecoGram);
hr = cpRecoCtx->SetNotifyWin32Event();
hr = cpRecoCtx->SetInterest(ullEvents, ullEvents);
hr = SpGetDefaultTokenFromCategoryId(SPCAT_AUDIOIN, &pInputToken);
hr = cpReco->SetInput(pInputToken, FALSE);
hr = cpRecoGram->LoadCmdFromFile(L"Your_Test_File.cfg",SPLO_STATIC);
hr = cpReco->SetRecoState(SPRST_ACTIVE);
hr = cpRecoCtx->SetContextState(SPCS_ENABLED);
hr = cpRecoGram->SetGrammarState(SPGS_ENABLED);
hr = cpRecoGram->SetRuleState(NULL, NULL, SPRS_ACTIVE);
std::wstring strExit = L"Exit";
std::wstring strExitRuleName = L"EXIT_VAL";
CSpEvent spEvent;
bool isListening = true;
do{
hr = cpRecoCtx->WaitForNotifyEvent(INFINITE);
if(spEvent.GetFrom(cpRecoCtx) == S_OK)
{
switch(spEvent.eEventId){
case SPEI_RECOGNITION:{
WCHAR* strReco = 0;
cpRecoRslt = spEvent.RecoResult();
cpRecoRslt->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &strReco, NULL);
printf("%ls\n",strReco);
SPPHRASE *phrase = NULL;
cpRecoRslt->GetPhrase(&phrase);
if(phrase){
std::wstring ruleName = phrase->Rule.pszName;
if(strExitRuleName.compare(strExit)==0){
isListening = false;
}
}
break;
}
case SPEI_FALSE_RECOGNITION:{
printf("False Recognition\n");
break;
}
}
}
}while(isListening);
cpRecoGram.Release();
cpRecoCtx.Release();
cpReco.Release();
::CoUninitialize();
printf("Press any key to continue...");
getchar();
return 0;
}
You'll have to change the path of where the load grammar call is loading from. From what I understand what you're attempting to do is create grammar in a context free grammar file AND try to do this programmatically as well. Typically you start with a grammar file and modify when you need to.
If, however, you REALLY REALLY need to add new grammars programmatically, such as when someone's typing in new grammar to be recognized, THEN you'd chance SPLO_STATIC to SPLO_DYNAMIC and start implementing the code you see in the later half of the MSDN post you saw.
I completely left out any error checking. If you need to access other properties of the rule you're looking at, use the pPhrase->GetPhrase(&phrase) area. Other than just the rule's name you can also get it's ID.