This is BongAppController.m in view mode; [Download] [Up]
#import "BongAppController.h" #import "dpsclient/dpsNeXT.h" #import <sys/time.h> #import <misckit/misckit.h> // Get stuff for string class... @implementation BongAppController - setBongSound:sender { const char *types[] = { "snd", NULL }; OpenPanel *openPanel = [OpenPanel new]; // Convenience reference. Reduce code, and maybe calls. MiscString *pathString = [MiscString newWithString:""]; // Grab an empty instance of MiscString... ;') if ( pathString ) { if ( [[openPanel allowMultipleFiles:NO] runModalForTypes:types] ) { [pathString catStrings:[openPanel directory], "/", *[openPanel filenames], NULL]; // Construct full path. [pathString replaceHomeWithTilde]; // Attempt to substitute a tilde for home path. [soundTextField setStringValue:[pathString stringValueAndFree]]; // Get the value, and free object. [self textWillEnd:soundTextField]; // Get the sound to be updated. NXWriteDefault("BongApp", [defaultsStringTable valueForStringKey:"bongFileSoundPath"], [soundTextField stringValue]); } } else NXLogError("%s Error -- setBongSound: could not aquire a new MiscString instance.\n", [[self class] name]); return ( self ); } - setWhenToPlay:sender { MiscString *whenToPlay = [MiscString newWithString:""]; MiscString *indexString = [[MiscString alloc] init]; int index; for ( index = 1; index <= 4; index++ ) { if ( [[sender findCellWithTag:index] intValue] ) { [indexString sprintf:"%d", index]; [whenToPlay cat:[defaultsStringTable valueForStringKey:[indexString stringValue]]]; [whenToPlay cat:" "]; } } [whenToPlay squashSpaces]; NXWriteDefault("BongApp", [defaultsStringTable valueForStringKey:"whenToPlay"] ,[whenToPlay stringValueAndFree]); return ( self ); } // Timed Entry functions. void updateTimeAndCheck(DPSTimedEntry teNum, double now, id self) { [self updateTimeAndCheck]; } // Application Delegate Methods // Set up the timed entry to check for the time (hour or half hour). - appDidInit:sender { int defaultIndex; MiscString *index = [[MiscString alloc] init]; MiscString *whenToPlayDefaults = [[MiscString alloc] init]; MiscString *currPlayDefault = [[MiscString alloc] init]; [soundTextField setStringValue:NXReadDefault("BongApp", [defaultsStringTable valueForStringKey:"bongFileSoundPath"])]; [self textWillEnd:soundTextField]; // "force" retrieval of the sound if (!(DPSAddTimedEntry(1.0, (DPSTimedEntryProc)&updateTimeAndCheck, self, NX_BASETHRESHOLD))) { NXLogError("%s Error -- appDidInit: could not aquire" " timed entry for time check.\n", [[self class] name]); [NXApp terminate:self]; } // Get whenToPlay default, and set the appropriate switches to reflect the settings. // Assuming that the switch defaults are labeled 1 - 4 (or even higher if there are more switches // that you add. I kept it simple since most people don't want "bong'in" going on more than // at the quarter hour marks. [whenToPlayDefaults setString:NXReadDefault("BongApp", [defaultsStringTable valueForStringKey:"whenToPlay"])]; for ( defaultIndex = 4; defaultIndex; defaultIndex-- ) { [index sprintf:"%d", defaultIndex]; [currPlayDefault setString:[defaultsStringTable valueForStringKey:[index stringValue]]]; [[whenToPlayMatrix findCellWithTag:defaultIndex] setIntValue: ([whenToPlayDefaults spotOfRegex:[currPlayDefault stringValue]] != -1 ) ? YES : NO]; } return ( self ); } - showInfoPanel:sender; { MiscString *revisionString = [[MiscString alloc] init]; MiscString *infoNibPath = [[MiscString alloc] init]; char buffer[MAXPATHLEN + 1]; if ( !infoPanel ) { [[NXBundle mainBundle] getPath:buffer forResource:"Info" ofType:"nib"]; [infoNibPath setString:buffer]; if ( ![NXApp loadNibFile:[infoNibPath stringValue] owner:self withNames:NO fromZone:[self zone]] ) { NXLogError("%s Error -- showInfoPanel: could not load the info panel.\n", [[self class] name]); return ( self ); } else { [revisionString sprintf:"Ver %.2f Rel %.2f", B_VERSION, B_RELEASE]; [revisionTextField setStringValue:[revisionString stringValue]]; } } [infoPanel makeKeyAndOrderFront:self]; return ( self ); } - updateTimeAndCheck { struct tm *localTime; struct timeval currentTime; Sound *totalBongSound; // Get the time in seconds, and microseconds from 1970 ... gettimeofday (¤tTime, NULL); // ... and then break it down into something useful. The time that is. localTime = localtime (&(currentTime.tv_sec)); // Update the fields [[timeForm findCellWithTag:HOURS] setIntValue:localTime->tm_hour]; [[timeForm findCellWithTag:MINUTES] setIntValue:localTime->tm_min]; [[timeForm findCellWithTag:SECONDS] setIntValue:localTime->tm_sec]; // Now based on the values, do a bong for hour, or half hour... if ( localTime->tm_sec == 0 ) { // If we are on a 15 minute interval, then check if we are allowed to play... if ((localTime->tm_min == 0) && ([self _allowedToPlayAt:B_ON_THE_HOUR])) { bongCount = localTime->tm_hour; if ( bongCount == 0 ) bongCount = 12; else if ( bongCount > 12 ) bongCount -= 12; } else if ((localTime->tm_min == 15) && ([self _allowedToPlayAt:B_QUARTER_AFTER])) { bongCount = 1; } else if ((localTime->tm_min == 30) && ([self _allowedToPlayAt:B_HALF_AFTER])) { bongCount = 1; } else if ((localTime->tm_min == 45) && ([self _allowedToPlayAt:B_QUARTER_TILL])) { bongCount = 1; } else return ( self ); // ... else return. // Get a new sound, then construct many bongs and play the sound totalBongSound = [[Sound alloc] init]; while ( bongCount-- ) { [totalBongSound insertSamples:[Sound findSoundFor:"bongSound"] at:[totalBongSound dataSize]]; if ( [totalBongSound needsCompacting] ) [totalBongSound compactSamples]; // Compact if sound has fragmentation. } [totalBongSound play]; // Spawn a sound playing thread, and play the sound. } return ( self ); } // Another support method - (BOOL)_allowedToPlayAt:(int)timeRequested { MiscString *defaultTimes = [[MiscString alloc] init]; MiscString *indexString = [[MiscString alloc] init]; // Check and see if we are within our known limits of play, and then get the defaults if so. if ((timeRequested < B_ON_THE_HOUR) || (timeRequested > B_QUARTER_TILL)) return ( NO ); [defaultTimes setString:NXReadDefault("BongApp", [defaultsStringTable valueForStringKey:"whenToPlay"])]; // Now use the MiscString instance methods to find any instance of a known string in the defaults. [indexString sprintf:"%d", timeRequested]; if ( [defaultTimes rspotOfRegex:[defaultsStringTable valueForStringKey:[indexString stringValue]]] < 0 ) return ( NO ); return ( YES ); } // Text field delegate overrides... - (BOOL)textWillEnd:sender { Sound *newSound; Sound *oldSound; MiscString *pathString = [MiscString newWithString:[soundTextField stringValue]]; oldSound = [Sound removeSoundForName:"bongSound"]; [pathString replaceTildeWithHome]; if (!(newSound = [Sound addName:"bongSound" fromSoundfile:[pathString stringValue]])) { NXLogError("%s Error -- textWillEnd: could not aquire the new sound (%s).\n", [[self class] name], [pathString stringValue]); if ( oldSound ) [Sound addName:"bongSound" sound:oldSound]; return ( NO ); } NXWriteDefault("BongApp", [defaultsStringTable valueForStringKey:"bongFileSoundPath"], [soundTextField stringValue]); return ( YES ); // Allow the changes. } // Going to add some simple/smashing animation to the information panel. - smashClock:sender { return ( self ); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.