//		SimpleSR.cpp//		http://www.strout.net/macdev/simplsr///		last updated: 11/10/96#include "SimpleSR.h"// constantsconst long		kWeaponLMRefCon = 'weap';// class variablesSRRecognitionSystem	LanguageModel::cRecSystem = 0;SRRecognizer		LanguageModel::cRecognizer = 0;LanguageModel		*LanguageModel::cCurModel = 0;int					LanguageModel::cCount = 0;// prototypespascal OSErr HandleSpeechDoneAppleEvent (AppleEvent *theAEevt, AppleEvent* reply, long refcon);Boolean HasSpeechRecognitionMgr (void){	OSErr		myErr;	long		mySRVersion;	Boolean		myHasSRMgr = false;		myErr = Gestalt (gestaltSpeechRecognitionVersion, &mySRVersion);	if (!myErr)		if (mySRVersion >= 0x0150)			myHasSRMgr = true;		return myHasSRMgr;}LanguageModel::LanguageModel(const long refcon){	OSErr myErr = noErr;		if (!cCount) myErr = InitClass();	cCount++;		if (!myErr)		myErr = SRNewLanguageModel (LanguageModel::cRecSystem, &mSRLanguageModel, "<LM>", 4);	if (!myErr) 		myErr = SRSetProperty (mSRLanguageModel, kSRRefCon, &refcon, sizeof(refcon));		if (!cCurModel) BecomeCurrent();}LanguageModel::LanguageModel(const OSType resType, const short resNum){	OSErr myErr = noErr;		if (!cCount) myErr = InitClass();	if (myErr) return;	cCount++;		Handle lmData = GetResource(resType, resNum);		if (lmData) {		myErr = SRNewLanguageObjectFromHandle 					(LanguageModel::cRecSystem, &mSRLanguageModel, lmData);		ReleaseResource( lmData );	}	else {		myErr = SRNewLanguageModel (LanguageModel::cRecSystem, &mSRLanguageModel, "<LM>", 4);	}		if (!cCurModel) BecomeCurrent();}LanguageModel::~LanguageModel(){	if (mSRLanguageModel)		SRReleaseObject( mSRLanguageModel );	if (cCurModel == this) cCurModel = 0;		cCount--;	if (!cCount) CleanUpClass();}OSErr LanguageModel::AddText( const Str255 text, const long refcon ){	OSErr err = SRAddText (mSRLanguageModel, &text[1], text[0], refcon);	return err;}OSErr LanguageModel::InitClass(){	OSErr myErr = 0;	// make sure speech recognition is available	if (!HasSpeechRecognitionMgr())		myErr = true;		// Install AppleEvent handler so recognizer can send us speech-done AppleEvents.	if (!myErr)		myErr = AEInstallEventHandler(kAESpeechSuite, kAESpeechDone,				NewAEEventHandlerProc(HandleSpeechDoneAppleEvent), 0, false);	// open a recognition system	if (!myErr)		myErr = SROpenRecognitionSystem (&cRecSystem, kSRDefaultRecognitionSystemID);	// set feedback and listening modes	if (!myErr)		{		short myModes = kSRHasFeedbackHasListenModes;		myErr = SRSetProperty (cRecSystem, kSRFeedbackAndListeningModes, 													&myModes, sizeof (myModes));		}	// create a recognizer			if (!myErr)		myErr = SRNewRecognizer (cRecSystem, &cRecognizer, kSRDefaultSpeechSource);		return myErr;}void LanguageModel::CleanUpClass(){	if (cRecSystem)		SRCloseRecognitionSystem (cRecSystem);	/* balance SROpenRecognitionSystem call */	if (cRecognizer)	{		SRStopListening (cRecognizer);			/* stop processing incoming sound */		SRReleaseObject (cRecognizer);			/* balance SRNewRecognizer call */	}	cRecSystem = 0;	cRecognizer = 0;	cCurModel = 0;}OSErr LanguageModel::BecomeCurrent(){	OSErr err = 0;	if (cCurModel != this) {		cCurModel = this;		err = SRSetLanguageModel (cRecognizer, mSRLanguageModel );		if (!err)			SRStartListening (cRecognizer);	}	return err;}pascal OSErr HandleSpeechDoneAppleEvent (AppleEvent *theAEevt, AppleEvent* reply, long refcon){	long				actualSize;	DescType			actualType;	OSErr				status = 0, recStatus = 0;	SRRecognitionResult	recResult = 0;			/* Get status */	status = AEGetParamPtr (theAEevt, keySRSpeechStatus, typeShortInteger,					&actualType, (Ptr)&recStatus, sizeof(recStatus), &actualSize);		/* Get result and handle it */	if (!status)	{		// find the "result" and handle it		status = AEGetParamPtr(theAEevt,keySRSpeechResult,					typeSRSpeechResult, &actualType, (Ptr)&recResult,					sizeof(SRRecognitionResult), &actualSize);				if (!status && LanguageModel::cCurModel)	{			SRLanguageModel	myResultLM = 0;			Size			myLen = sizeof (myResultLM);			status = SRGetProperty (recResult, kSRLanguageModelFormat, &myResultLM, &myLen);			if (!status) {				StartHearing();				LanguageModel::cCurModel->HandleElement (myResultLM);				EndHearing();			}			if (myResultLM) SRReleaseObject (myResultLM);		}		SRReleaseObject (recResult);	}	return status;}void LanguageModel::HandleElement( const SRLanguageObject& obj ){	// recursively handle all the subobjects, calling HearPhrase for phrases	// start by getting the type of this object	long objType;	long myLen = sizeof(objType);	OSErr myErr = SRGetProperty( obj, kSRLMObjType, &objType, &myLen);	// now, handle this item based on its type	switch (objType)	{		case kSRLanguageModelType:		case kSRPathType:			// obj is a container, so handle each subitem			SRLanguageObject	mySubElement;			long qtySubItems=0;			myErr = SRCountItems( obj, &qtySubItems );			for (int i=0; i<qtySubItems; i++) {				myErr = SRGetIndexedItem ( obj, &mySubElement, i);				HandleElement( mySubElement );							SRReleaseObject ( mySubElement );			}			break;					case kSRPhraseType:		case kSRWordType:			// we're a word or phrase, so get the refcon and spelling			long myRefCon;			myLen = sizeof (myRefCon);			myErr = SRGetProperty (obj, kSRRefCon, &myRefCon, &myLen);			Str255 mySpelling;			myLen = 255;			myErr = SRGetProperty (obj, kSRSpelling, &mySpelling[1], &myLen);			mySpelling[0] = myLen;			/* handle the phrase we heard */			HearPhrase (myRefCon, mySpelling);			break;	}	}