This is FoneTones.m in view mode; [Download] [Up]
#import "FoneTones.h" #import "FoneTonesConstants.h" #import <appkit/appkit.h> #import <strings.h> #import <soundkit/soundkit.h> #import <drivers/event_status_driver.h> const char *knownFoneTones[] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "splat", "pound", NULL }; static char *handlerList[] = { "dialnumber", // "remembernumber", // "forgetnumber", // "NUMBERSSTARTINGWITH", // "ALLPHONENUMBERS", // "PHONEBOOK", // "PHONEBOOKS", // "switchtobook", // "speeddialing", "preloadtones", // "phonebookeditor", "CURRENTVOLUME", "setcurrentvolume", "ft_version", NULL }; static struct mach_header *loadHeader = NULL; static NXEventHandle ourEventStatusHandle; @implementation FoneTones : XModule - init { [super init]; // Do your stuff here... foneTonesAreLoaded = NO; ourEventStatusHandle = NXOpenEventStatus(); return ( self ); } - free { // Do your stuff here... return ( [super free] ); } + (const char *)moduleName { return ( "FoneTones" ); } + (const char **)xCmdsAndFcns { return ( handlerList ); } - prepareToExecuteHandlers { // [self loadInterfaceData]; return ( self ); } - executeHandler:(NXAtom)handlerName { if (!strcmp(handlerName, "dialnumber")) { return ( [self dial] ); } else if (!strcmp(handlerName, "remembernumber")) { //return ( [self rememberNumber] ); return ( [[self getEmptyContainer] setString:"rememberNumber command, not implemented yet."] ); } else if (!strcmp(handlerName, "forgetnumber")) { // return ( [self forgetNumber] ); return ( [[self getEmptyContainer] setString:"forgetNumber command, not implemented yet."] ); } else if (!strcmp(handlerName, "NUMBERSSTARTINGWITH")) { // return ( [self numbersStartingWith] ); return ( [[self getEmptyContainer] setString:"forgetNumber command, not implemented yet."] ); } else if (!strcmp(handlerName, "ALLPHONENUMBERS")) { // return ( [self allPhoneNumbers] ); return ( [[self getEmptyContainer] setString:"forgetNumber command, not implemented yet."] ); } else if (!strcmp(handlerName, "PHONEBOOK")) { // return ( [self phoneBook] ); return ( [[self getEmptyContainer] setString:"phoneBook command, not implemented yet."] ); } else if (!strcmp(handlerName, "PHONEBOOKS")) { // return ( [self phoneBooks] ); return ( [[self getEmptyContainer] setString:"phoneBooks command, not implemented yet."] ); } else if (!strcmp(handlerName, "switchtobook")) { // return ( [self switchToBook] ); return ( [[self getEmptyContainer] setString:"switchToBook command, not implemented yet."] ); } else if (!strcmp(handlerName, "speeddialing")) { // return ( [self speedDialing] ); return ( [[self getEmptyContainer] setString:"speedDialing command, not implemented yet."] ); } else if (!strcmp(handlerName, "preloadtones")) { return ( [self preloadTones] ); } else if (!strcmp(handlerName, "phonebookeditor")) { // return ( [self phoneBookEditor] ); return ( [[self getEmptyContainer] setString:"phoneBookEditor command, not implemented yet."] ); } else if (!strcmp(handlerName, "ft_version")) { return ( [self ft_version] ); } else if (!strcmp(handlerName, "setcurrentvolume")) { return ( [self setCurrentVolume] ); } else if (!strcmp(handlerName, "CURRENTVOLUME")) { return ( [self currentVolume] ); } else return ( nil ); // handlerName not recognized! } + finishLoading:(struct mach_header *)header { loadHeader = header; // Save this for later use return ( self ); } - loadInterfaceData { //[NXApp loadNibSection:"MyXModule.nib" owner:self // withNames:NO fromHeader:loadHeader] ) return ( self ); } /// // FoneTones XModule Specific Methods /// - dial { int pCount = [self paramCount]; char phoneNumber[256] = ""; // Hopefully enough space. char *pnIndex; Sound *sndObj = nil; float approxTimeToPlay; if ( pCount != 1 ) { return ( [[self getEmptyContainer] setString:"Usage: dial <phoneNumber>"] ); } if ( !foneTonesAreLoaded ) [self preloadTones:self]; pnIndex = strncpy(phoneNumber, [[self getParam:1] stringVal], 255); if ( !pnIndex || !*pnIndex ) return ( self ); // If we don't have a sound to pile tones into, then create one. if ( ![Sound findSoundFor:"numberToPlay"] ) { [Sound addName:"numberToPlay" sound:[[Sound alloc] init]]; } // Go and remove all the junk!, anything but numbers, letters, and '*' or '#' while ( *pnIndex ) { if ( index("#", *pnIndex) ) sndObj = [Sound findSoundFor:"pound_tone"]; else if ( index("*", *pnIndex) ) sndObj = [Sound findSoundFor:"splat_tone"]; else if ( index("1", *pnIndex) ) sndObj = [Sound findSoundFor:"one_tone"]; else if ( index("2abcABC", *pnIndex) ) sndObj = [Sound findSoundFor:"two_tone"]; else if ( index("3defDEF", *pnIndex) ) sndObj = [Sound findSoundFor:"three_tone"]; else if ( index("4ghiGHI", *pnIndex) ) sndObj = [Sound findSoundFor:"four_tone"]; else if ( index("5jklJKL", *pnIndex) ) sndObj = [Sound findSoundFor:"five_tone"]; else if ( index("6mnoMNO", *pnIndex) ) sndObj = [Sound findSoundFor:"six_tone"]; else if ( index("7prsPRS", *pnIndex) ) sndObj = [Sound findSoundFor:"seven_tone"]; else if ( index("8tuvTUV", *pnIndex) ) sndObj = [Sound findSoundFor:"eight_tone"]; else if ( index("9wxyWXY", *pnIndex) ) sndObj = [Sound findSoundFor:"nine_tone"]; else if ( index("0qzQZ", *pnIndex) ) sndObj = [Sound findSoundFor:"zero_tone"]; else sndObj = nil; if (( sndObj != nil ) && [[Sound findSoundFor:"numberToPlay"] compatibleWith:sndObj]) { [[Sound findSoundFor:"numberToPlay"] compactSamples]; [[Sound findSoundFor:"numberToPlay"] insertSamples:sndObj at:[[Sound findSoundFor:"numberToPlay"] dataSize]]; } pnIndex++; } [[Sound findSoundFor:"numberToPlay"] compactSamples]; // Ensure no fragmentation. approxTimeToPlay = [[Sound findSoundFor:"numberToPlay"] duration]; [[Sound findSoundFor:"numberToPlay"] play]; // Jam the sound out to the speaker. [[Sound findSoundFor:"numberToPlay"] deleteSamples]; // Get ready for next use? [[Sound findSoundFor:"numberToPlay"] compactSamples]; // Why not, just to clean up. return ( [[self getEmptyContainer] setFloat:approxTimeToPlay] ); } // Add a number to the current fonebook. - rememberNumber { return ( self ); } // Given a key, this method will remove the key-value association // from the current fone book. If the key doesn't exist, then // nothing happens. - forgetNumber { return ( self ); } // This puppy returns all the numbers starting with the letters // in the parameter string passed to this function. - numbersStartingWith { return ( self ); } // Returns a line delimited list of all the keys and associated // phone numbers to go along with them. - allPhoneNumbers { return ( self ); } // Return the name of the current fone book. - phoneBook { return ( self ); } // Return the names of all the fone books located in... // // ~/Library/FoneBooks // /Library/FoneBooks // /NextLibrary/FoneBooks // // directories. - phoneBooks { return ( self ); } // Switch from one fone book to another. - switchToBook { return ( self ); } // Don't know if I am going to bother with this one. After Doug // and I talked about it, it would seem that most phones will allow // take speed dialing. So for now, this function isn't worth working // on. - speedDialing { return ( self ); } // Used to avoid any delay loading of tones may cause. - preloadTones:sender { char **kftIndex = knownFoneTones; char sndName[256]; if ( foneTonesAreLoaded ) { if ( sender == nil ) { // Caller was HS return ( [[self getEmptyContainer] setString:"Tones already loaded."] ); } else return ( self ); } while ( *kftIndex ) { // Loop until we don't have anymore to load. sprintf(sndName, "%s%s", *kftIndex, "_tone"); if ( ![Sound findSoundFor:sndName] ) { NXLogError("%s Error -- preloadTones: Could not load the" " sound file %s.\n", [[self class] name], sndName); } kftIndex++; // Point to next string. } foneTonesAreLoaded = TRUE; if ( sender == nil ) { return ( [[self getEmptyContainer] setString:"Tones successfully loaded."] ); } return ( self ); } // Front to calling the real preloadTones: function. - preloadTones { return ( [self preloadTones:nil] ); } // At some time in the future, it would be nice to have a graphical // front end to the current fone book. I figure a nice association // of keys and values in a DBTableView would work. But hey, this // is something for the future. - phoneBookEditor { return ( self ); } /// // FoneTones XModule Support Methods /// #define MAXKEYSIZE (30) #define MAXVALUESIZE (50) // This puppy will create a new book if specified book doesn't exist. // It will be created in the ~/Library/FoneBooks directory. Only place // we for sure can create directories/files. - (HashTable *)loadPhoneBook:(const char *)newBookName { // id newFoneBook; BOOL successfullyLoadedNewBook; // char bookPathBuff[MAXPATHLEN + 1]; const char *defaultPath = NULL; NXStream *fonebookStream; NXStringTable *newStringTable; char currKey[MAXKEYSIZE], currValue[MAXVALUESIZE]; // Determine if we are to load the default fone book, or one specified. if ( !newBookName && !*newBookName ) { // Go and try to load the defaults... newBookName = NXReadDefault("FoneTonesXModule", "StartupFoneBook"); if ( !defaultPath && !*defaultPath ) { NXLogError("%s Error -- loadPhoneBook:: default fone book was not specified" " in the user's defaults data.\n", [[self class] name]); return ( (HashTable *)nil ); } } // Attempt to get a stream open to the fone book. fonebookStream = NXMapFile(newBookName, NX_READONLY); if ( fonebookStream == NULL ) { NXLogError("%s Error -- loadPhoneBook:: could not get a stream open to the" " defaults file specified (%s)\n", [[self class] name], newBookName); return ( nil ); } // Well, now we have to create a table, and go and parse the file... // File format (for convenience of user so they can use a text // processor [non-rtf] to define a phone book. newStringTable = [[NXStringTable alloc] init]; NXScanf(fonebookStream, "%MAXKEYSIZEs\t%MAXVALUESIZEs\n", currKey, currValue); if ( successfullyLoadedNewBook ) { } return ( newStringTable ); } - ft_version { id version; version = [[ self getEmptyContainer ] setString:"r" ]; [ version appendString:FT_RELEASE ]; [ version appendString:" v" ]; [ version appendString:FT_VERSION ]; [ version appendString:" " ]; [ version appendString:FT_RELTIME ]; [ version appendString:"\n" ]; [ version appendString:FT_COPYRIGHT ]; return ( version ); } ///////////////////// // Volume Functions ///////////////////// - setCurrentVolume { int pCount = [ self paramCount ]; float newVolume; if (( pCount != 1 ) || ( !([[ self getParam:1 ] validAsNumber ]) )) { return ( [[ self getEmptyContainer ] setString:"Usage: setCurrentVolume <0.0 - 1.0>" ] ); } newVolume = [[ self getParam:1 ] floatVal ]; if (( newVolume < 0.0 ) || ( newVolume > 1.0 )) { return ( [[ self getEmptyContainer ] setString:"Usage: setCurrentVolume <0.0 - 1.0>" ] ); } NXSetCurrentVolume(ourEventStatusHandle, newVolume); return ( self ); } - currentVolume { return ( [[ self getEmptyContainer ] setFloat:NXCurrentVolume(ourEventStatusHandle) ] ); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.