Boolean AddCommands( SRRecognizer inSpeechRecognizer, SRLanguageModel inCommandsLangaugeModel, CFArrayRef inCommandNamesArray ) { // Dictionary keys for Commands Data property list #define kCommandsDataPlacementHintKey "PlacementHint" // value type is: CFNumberRef #define kPlacementHintWhereverNumValue 0 #define kPlacementHintProcessNumValue 1 // you must also provide the PSN using kCommandsDataProcessPSNHighKey & kCommandsDataProcessPSNLowKey #define kPlacementHintFirstNumValue 2 #define kPlacementHintMiddleNumValue 3 #define kPlacementHintLastNumValue 4 #define kCommandsDataProcessPSNHighKey "ProcessPSNHigh" // value type is: CFNumberRef #define kCommandsDataProcessPSNLowKey "ProcessPSNLow" // value type is: CFNumberRef #define kCommandsDataDisplayOrderKey "DisplayOrder" // value type is: CFNumberRef - the order in which recognizers from the same client process should be displayed. #define kCommandsDataCmdInfoArrayKey "CommandInfoArray" // value type is: CFArrayRef of CFDictionaryRef values #define kCommandInfoNameKey "Text" #define kCommandInfoChildrenKey "Children" Boolean successfullyAddCommands = false; if (inCommandNamesArray) { CFIndex numOfCommands = CFArrayGetCount( inCommandNamesArray ); CFMutableArrayRef theSectionArray = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks ); // Erase any existing commands in the language model before we begin adding the given list of commands if (SREmptyLanguageObject( inCommandsLangaugeModel ) == noErr && theSectionArray) { CFIndex i; char theCSringBuffer[100]; successfullyAddCommands = true; for (i = 0; i < numOfCommands; i++) { CFStringRef theCommandName = CFArrayGetValueAtIndex(inCommandNamesArray, i); if (theCommandName && CFStringGetCString( theCommandName, theCSringBuffer, 100, kCFStringEncodingMacRoman )) { if (SRAddText( inCommandsLangaugeModel, theCSringBuffer, strlen(theCSringBuffer), i) == noErr) { CFStringRef keys[1]; CFTypeRef values[1]; CFDictionaryRef theItemDict; keys[0] = CFSTR( kCommandInfoNameKey ); values[0] = theCommandName; // Make CDDictionary our keys and values. theItemDict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); // Add to command array if (theItemDict) { CFArrayAppendValue( theSectionArray, theItemDict ); CFRelease( theItemDict ); // We release our hold on the dictionary object and let the array own it now. } else successfullyAddCommands = false; } else successfullyAddCommands = false; if (! successfullyAddCommands) break; } } // // Create the XML data that contains the commands to display and give this data to the // recognizer object to display in the Speech Commands window. // { CFIndex numOfParams = 4; CFStringRef keys[numOfParams]; CFTypeRef values[numOfParams]; CFDictionaryRef theItemDict; SInt32 placementHint = 1; // 1 = show only when this app is front process ProcessSerialNumber thisAppsPSN; thisAppsPSN.highLongOfPSN = 0; thisAppsPSN.lowLongOfPSN = 0; GetCurrentProcess( &thisAppsPSN ); keys[0] = CFSTR( kCommandsDataPlacementHintKey ); keys[1] = CFSTR( kCommandsDataCmdInfoArrayKey ); keys[2] = CFSTR( kCommandsDataProcessPSNHighKey ); keys[3] = CFSTR( kCommandsDataProcessPSNLowKey ); values[0] = CFNumberCreate(NULL, kCFNumberSInt32Type, &placementHint); values[1] = theSectionArray; values[2] = CFNumberCreate(NULL, kCFNumberSInt32Type, &(thisAppsPSN.highLongOfPSN)); values[3] = CFNumberCreate(NULL, kCFNumberSInt32Type, &(thisAppsPSN.lowLongOfPSN)); // Make CDDictionary of our keys and values. theItemDict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, numOfParams, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (theItemDict) { // Convert CFDictionary object to XML representation CFDataRef dictData = CFPropertyListCreateXMLData(NULL, theItemDict); if (dictData) { // Set command list in our SRRecognizer object, causing the Speech Commands window to update. (void)SRSetProperty (inSpeechRecognizer, 'cdpl', CFDataGetBytePtr(dictData), CFDataGetLength(dictData)); CFRelease( dictData ); } } // Release our hold on the dictionary object and let the array own it now. if (theItemDict) CFRelease( theItemDict ); // Release our values if (values[0]) CFRelease( values[0] ); if (values[2]) CFRelease( values[2] ); if (values[3]) CFRelease( values[3] ); CFRelease( theSectionArray ); } } } return successfullyAddCommands; }
Boolean AddCommands( SRRecognizer inSpeechRecognizer, SRLanguageModel inCommandsLangaugeModel, CFArrayRef inCommandNamesArray ) { // Dictionary keys for Commands Data property list #define kCommandsDataPlacementHintKey "PlacementHint" // value type is: CFNumberRef #define kPlacementHintWhereverNumValue 0 #define kPlacementHintProcessNumValue 1 // you must also provide the PSN using kCommandsDataProcessPSNHighKey & kCommandsDataProcessPSNLowKey #define kPlacementHintFirstNumValue 2 #define kPlacementHintMiddleNumValue 3 #define kPlacementHintLastNumValue 4 #define kCommandsDataProcessPSNHighKey "ProcessPSNHigh" // value type is: CFNumberRef #define kCommandsDataProcessPSNLowKey "ProcessPSNLow" // value type is: CFNumberRef #define kCommandsDataDisplayOrderKey "DisplayOrder" // value type is: CFNumberRef - the order in which recognizers from the same client process should be displayed. #define kCommandsDataCmdInfoArrayKey "CommandInfoArray" // value type is: CFArrayRef of CFDictionaryRef values #define kCommandInfoNameKey "Text" #define kCommandInfoChildrenKey "Children" Boolean successfullyAddCommands = false; if (inCommandNamesArray) { CFIndex numOfCommands = CFArrayGetCount( inCommandNamesArray ); CFMutableArrayRef theSectionArray = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks ); // Erase any existing commands in the language model before we begin adding the given list of commands if (SREmptyLanguageObject( inCommandsLangaugeModel ) == noErr && theSectionArray) { CFIndex i; char theCSringBuffer[100]; successfullyAddCommands = true; for (i = 0; i < numOfCommands; i++) { CFStringRef theCommandName = CFArrayGetValueAtIndex(inCommandNamesArray, i); if (theCommandName && CFStringGetCString( theCommandName, theCSringBuffer, 100, kCFStringEncodingMacRoman )) { // Conditionalized just to remove compiler warnings. #if __LP64__ if (SRAddText( inCommandsLangaugeModel, theCSringBuffer, strlen(theCSringBuffer), (void *)i) == noErr) { #else if (SRAddText( inCommandsLangaugeModel, theCSringBuffer, strlen(theCSringBuffer), i) == noErr) { #endif CFStringRef keys[1]; CFTypeRef values[1]; CFDictionaryRef theItemDict; keys[0] = CFSTR( kCommandInfoNameKey ); values[0] = theCommandName; // Make CDDictionary our keys and values. theItemDict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); // Add to command array if (theItemDict) { CFArrayAppendValue( theSectionArray, theItemDict ); CFRelease( theItemDict ); // We release our hold on the dictionary object and let the array own it now. } else successfullyAddCommands = false; } else successfullyAddCommands = false; if (! successfullyAddCommands) break; } } // // Create the XML data that contains the commands to display and give this data to the // recognizer object to display in the Speech Commands window. // { CFIndex numOfParams = 4; CFStringRef keys[numOfParams]; CFTypeRef values[numOfParams]; CFDictionaryRef theItemDict; SInt32 placementHint = 1; // 1 = show only when this app is front process ProcessSerialNumber thisAppsPSN; thisAppsPSN.highLongOfPSN = 0; thisAppsPSN.lowLongOfPSN = 0; GetCurrentProcess( &thisAppsPSN ); keys[0] = CFSTR( kCommandsDataPlacementHintKey ); keys[1] = CFSTR( kCommandsDataCmdInfoArrayKey ); keys[2] = CFSTR( kCommandsDataProcessPSNHighKey ); keys[3] = CFSTR( kCommandsDataProcessPSNLowKey ); values[0] = CFNumberCreate(NULL, kCFNumberSInt32Type, &placementHint); values[1] = theSectionArray; values[2] = CFNumberCreate(NULL, kCFNumberSInt32Type, &(thisAppsPSN.highLongOfPSN)); values[3] = CFNumberCreate(NULL, kCFNumberSInt32Type, &(thisAppsPSN.lowLongOfPSN)); // Make CDDictionary of our keys and values. theItemDict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, numOfParams, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (theItemDict) { // Convert CFDictionary object to XML representation CFDataRef dictData = CFPropertyListCreateXMLData(NULL, theItemDict); if (dictData) { // Set command list in our SRRecognizer object, causing the Speech Commands window to update. (void)SRSetProperty (inSpeechRecognizer, 'cdpl', CFDataGetBytePtr(dictData), CFDataGetLength(dictData)); CFRelease( dictData ); } } // Release our hold on the dictionary object and let the array own it now. if (theItemDict) CFRelease( theItemDict ); // Release our values if (values[0]) CFRelease( values[0] ); if (values[2]) CFRelease( values[2] ); if (values[3]) CFRelease( values[3] ); CFRelease( theSectionArray ); } } } return successfullyAddCommands; } /* ConvertAppleEventResultIntoCommandID This routine converts the Apple event data received from a speech done (kAESpeechSuite, kAESpeechDone) Apple event into a command ID when using the AddCommands routine to add your commands to the top-level language model. This routine returns true if the spoken utterance was recognized as a valid command. */ Boolean ConvertAppleEventResultIntoCommandID( const AppleEvent *inAppleEvent, long * outCommandID ) { Boolean successfullyFound = false; Size actualSize; DescType actualType; OSErr recStatus = noErr; // Get recognition status from AE, and check that it is equal to 0. if (AEGetParamPtr( inAppleEvent, keySRSpeechStatus, typeSInt16, &actualType, (Ptr)&recStatus, sizeof(recStatus), &actualSize) == noErr && recStatus == noErr) { // Get recognition result from AE, and continue if not NULL. SRRecognitionResult recResult = NULL; if (AEGetParamPtr( inAppleEvent, keySRSpeechResult, typeSRSpeechResult, &actualType, (Ptr)&recResult, sizeof(recResult), &actualSize) == noErr && recResult) { // Get language model result from recognition result Size theLen = sizeof(SRLanguageModel); SRLanguageModel resultLanguageModel = 0; if (SRGetProperty( recResult, kSRLanguageModelFormat, &resultLanguageModel, &theLen ) == noErr) { // Get the recognized command object from the language model // Since there will only be one object in the langauge model, we just grab the first one. SRLanguageObject resultingCommandObj = 0; if (SRGetIndexedItem( resultLanguageModel, &resultingCommandObj, 0 ) == noErr) { // Get the command ID from the refCon property of the recognized command object. theLen = sizeof(long); if (SRGetProperty( resultingCommandObj, kSRRefCon, outCommandID, &theLen ) == noErr) successfullyFound = true; } } } } return successfullyFound; }