Language.c

/*
    File:       Language.c
 
    Contains:   
 
    Written by:     
 
    Copyright:  Copyright © 1996-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                8/2/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
#ifndef __LANGUAGE__
#include "Language.h"
#endif
#include <Errors.h>
 
OSErr       MakeNewLanguage     (SpeechInfoPtr theSpeechInfo)
{
    OSErr       theErr      = noErr;
 
    /* Make language models */
    theErr = ReadInLanguages (theSpeechInfo);
 
    /* Use this LM in recognition */
    if (theErr == noErr) {
        theErr = SRSetLanguageModel (theSpeechInfo->theRecognizer, theSpeechInfo->languages->theLanguage);
    }
 
    return theErr;
}
 
OSErr   ReadInLanguages         (SpeechInfoPtr theSpeechInfo)
{
    LanguageModelListPtr    currentLang         = nil;
    TREEResourcePtr         TREEResPtr          = nil;
    short                   numLanguages        = 0,
                            onlySubPath         = false,
                            i;
    OSErr                   theErr              = noErr;
 
    numLanguages = Count1Resources (kTREEType);
    theErr = ResError ();
 
    theSpeechInfo->languages = (LanguageModelListPtr)NewPtr (sizeof (LanguageModelList));
    theSpeechInfo->languages->nextLanguage = nil;
    currentLang = theSpeechInfo->languages;
 
    for (i = 0; i < numLanguages; i++) {
        theErr = GetTREERes (&TREEResPtr, kBaseResID + i, 1, &onlySubPath);
        DisposePtr ((Ptr)TREEResPtr);
        if (onlySubPath == false) {
            theErr = AddStringsToLanguage (theSpeechInfo, currentLang, kBaseResID + i);
            if (i+1 < numLanguages) {
                currentLang->nextLanguage = (LanguageModelListPtr)NewPtr (sizeof (LanguageModelList));
                currentLang = currentLang->nextLanguage;
            }
            else {
                currentLang->nextLanguage = nil;
            }
            currentLang->resID = kBaseResID + i;
        }
    }
 
    return theErr;
}
 
OSErr   AddStringsToLanguage        (SpeechInfoPtr theSpeechInfo, LanguageModelListPtr currentLang, short resID)
{
    SRLanguageModel         newModel;
    SRPath                  beginningOfPath,
                            restOfPath;
    Str63                   phraseString;
    OSType                  type                = 0;
    TREEResourcePtr         TREEResPtr          = nil;
    CommandPtr              theCommand          = nil;
    long                    refCon              = 0,
                            flags               = 0,
                            ID                  = 0;
    short                   j                   = 1,
                            onlySubPath         = false;
    OSErr                   theErr              = noErr;
    Boolean                 done                = false;
 
    theErr = SRNewLanguageModel (theSpeechInfo->recogSystem, &newModel, nil, 0);
    refCon = resID;
    theErr = SRSetProperty (newModel, kSRRefCon, &refCon, sizeof (refCon));
    /* add each phrase to LM */
    refCon = refCon << 16;
    do {
        theErr = GetTREERes (&TREEResPtr, resID, j, &onlySubPath);
        if (theErr == noErr) {
            theErr = GetFlagsFromTREE (&flags, TREEResPtr);
        }
        if (theErr == noErr && flags == 0) {
            /* Read resource to get top level names to be recognized */
            theErr = GetStringFromTREE (phraseString, TREEResPtr);
            if (phraseString[0] == 0) {
                theErr = noErr;
                done = true;    /* Found the last name */
            }
            if (done == false) {
                theErr = RegisterCommand (TREEResPtr, &theCommand);
                theErr = SRAddText (newModel, phraseString+1, phraseString[0], (long)theCommand);
            }
        }
        else if (theErr == noErr && flags == 1) {
        /*  This word is the beginning of a path, i.e. "lights X" where X can
            be on, off, dim, etc. */
            theErr = GetTypeFromTREE (&type, TREEResPtr);
            if (theErr == noErr && type == kTREEType) {
                theErr = GetIDFromTREE (&ID, TREEResPtr);
            }
            if (theErr == noErr) {
                theErr = SRNewPath (theSpeechInfo->recogSystem, &beginningOfPath);
                if (theErr == noErr) {
                    theErr = GetStringFromTREE (phraseString, TREEResPtr);
                    if (phraseString[0] == 0) {
                        theErr = noErr;
                        done = true;    /* Found the last name */
                    }
                    if (done == false) {
                        theErr = SRAddText (beginningOfPath, phraseString+1, phraseString[0], 0);
                        if (theErr == noErr) {
                            theErr = GetTREERes (&TREEResPtr, ID, 1, &onlySubPath);
                        }
                        if (theErr == noErr) {
                            theErr = AddStringsToLanguage (theSpeechInfo, currentLang, ID);
                        }
                        if (theErr == noErr) {
                            theErr = SRNewPath (theSpeechInfo->recogSystem, &restOfPath);
                            if (theErr == noErr) {
                                theErr = SRAddLanguageObject (restOfPath, currentLang->theLanguage);
                            }
                            if (theErr == noErr) {
                                theErr = SRAddLanguageObject (beginningOfPath, restOfPath);
                            }
                            if (theErr == noErr) {
                                theErr = SRAddLanguageObject (newModel, beginningOfPath);
                            }
                        }
                    }
                }
            }
        }
        j++;
    } while (theErr == noErr && done == false);
    if (theErr == resNotFound) {
        theErr = noErr;
    }
    if (theErr != noErr) {  /*  release newly created LM if an error occured while adding phrases */
        SRReleaseObject (newModel);
    }
    else {                  /*  return new LM */
    //We don't release the language models because we will be switching between them later
        currentLang->theLanguage = newModel;
    }
 
    return theErr;
}
 
OSErr   GetTREERes              (TREEResourcePtr *theTREEResPtr, short resID, short index, short *onlySubPath)
{
    TREEResourcePtr     TREEResPtr      = nil;
    Handle              TREEHandle      = nil;
    long                offset          = 0;
    OSErr               theErr          = noErr;
    short               itemCount       = 0,
                        i;
 
    TREEHandle = Get1Resource (kTREEType, resID);
    theErr = ResError ();
    if (TREEHandle != nil && theErr == noErr) {
        *onlySubPath = ((short *)*TREEHandle)[0];
        itemCount = ((short *)*TREEHandle)[1];
        if (index > itemCount || index < 1) {
            theErr = resNotFound;
        }
        else {
            offset = 4;     /* account for one time bytes at start of resource */
            for (i = 0; i < index; i++) {
                TREEResPtr = (TREEResourcePtr)&(*TREEHandle)[offset];
                offset += 12;   /* account for flags, type, and ID */
                /* length of string (plus size byte), rounded to a quad byte length */
                offset += (((TREEResPtr->name[0] + 1) + 3) & ~3);
            }
            *theTREEResPtr = (TREEResourcePtr)NewPtr (sizeof (TREEResource) + TREEResPtr->name[0]);
            if (*theTREEResPtr != nil && MemError () == noErr) {
                (*theTREEResPtr)->flags = TREEResPtr->flags;
                (*theTREEResPtr)->type  = TREEResPtr->type;
                (*theTREEResPtr)->ID    = TREEResPtr->ID;
                for (i = 0; i < TREEResPtr->name[0] + 1; i++) {
                    (*theTREEResPtr)->name[i] = TREEResPtr->name[i];
                }
            }
            ReleaseResource (TREEHandle);
            theErr = ResError ();
        }
    }
 
    return theErr;
}
 
OSErr   RegisterCommand         (TREEResourcePtr theTREEResPtr, CommandPtr *theCommand)
{
    OSErr               theErr          = noErr;
 
    *theCommand = (CommandPtr)NewPtr (sizeof(Command));
 
    theErr = GetFlagsFromTREE (&(*theCommand)->flags, theTREEResPtr);
    theErr = GetTypeFromTREE (&(*theCommand)->type, theTREEResPtr);
    theErr = GetIDFromTREE (&(*theCommand)->ID, theTREEResPtr);
 
    return theErr;
}
 
OSErr   GetFlagsFromTREE        (long *theFlags, TREEResourcePtr theTREEResPtr)
{
    OSErr               theErr          = noErr;
 
    if (theTREEResPtr != nil) {
        *theFlags = theTREEResPtr->flags;
    }
    else {
        theErr = kNilPtrErr;
    }
 
    return theErr;
}
 
OSErr   GetTypeFromTREE         (OSType *theType, TREEResourcePtr theTREEResPtr)
{
    OSErr               theErr          = noErr;
 
    if (theTREEResPtr != nil) {
        *theType = theTREEResPtr->type;
    }
    else {
        theErr = kNilPtrErr;
    }
 
    return theErr;
}
 
OSErr   GetIDFromTREE           (long *theID, TREEResourcePtr theTREEResPtr)
{
    OSErr               theErr          = noErr;
 
    if (theTREEResPtr != nil) {
        *theID = theTREEResPtr->ID;
    }
    else {
        theErr = kNilPtrErr;
    }
 
    return theErr;
}
 
OSErr   GetStringFromTREE       (Str255 theString, TREEResourcePtr theTREEResPtr)
{
    OSErr               theErr          = noErr;
    short               i;
 
    if (theTREEResPtr != nil) {
        for (i = 0; i < theTREEResPtr->name[0] + 1; i++) {
            theString[i] = theTREEResPtr->name[i];
        }
    }
    else {
        theString[0] = 0;
        theErr = kNilPtrErr;
    }
 
    return theErr;
}