This is MovieShowViewPart.m in view mode; [Download] [Up]
/* * MovieShowView - version 1.1 * * hacked from: "SlideShowView" by brighton@phuket.nbn.com, 13 Nov 91 * hacked by: Paul Burchard <burchard@math.utah.edu>, 2 Jun 92 * thanks to sam streeper for corrections! */ #import <appkit/NXImage.h> // NXImage #import <appkit/Panel.h> // NXRunAlertPanel() #import <appkit/Text.h> // NXOrderStrings() #import <dpsclient/wraps.h> // PSsetgray() #import <defaults.h> // NXDefaults stuff #import <libc.h> // lots of sys stuff #import <math.h> // floor() #import <string.h> // strcmp(), index() #import <c.h> // TRUE, FALSE, etc #import <sys/dir.h> // opendir(), etc #import "MovieShowViewPart.h" #import "Thinker.h" // States. #define msh_DARK 0 #define msh_BEGIN 1 #define msh_FRAME 2 #define msh_END 3 static const char *module = "MovieShow"; static int stringToBool(const char *answer) { if (strcasecmp(answer, "yes") == 0) return 1; if (strcasecmp(answer, "on") == 0) return 1; return atoi(answer); // returns zero if no digits encountered } @implementation MovieShowView + initialize { static NXDefaultsVector MovieShowDefaults = { { "Movie", "~/Library/Images/Weather-920515.anim" }, { "FrameTime", "5" }, { "BeginPause", "12" }, { "EndPause", "30" }, { "DarkTime", "0" }, { "Jump", "YES" }, { "SlideFrames", "NO" }, { "SlidePauses", "NO" }, { "TimeUnit", "25" }, { NULL } }; NXRegisterDefaults(module, MovieShowDefaults); return self; } - getDefaults { const char *app = module; // Read from defaults database. NXUpdateDefaults(); theMovie = NXGetDefaultValue(app, "Movie"); timeunit = (unsigned)atoi(NXGetDefaultValue(app, "TimeUnit")); frametime = (unsigned)atoi(NXGetDefaultValue(app, "FrameTime")); beginpause = (unsigned)atoi(NXGetDefaultValue(app, "BeginPause")); endpause = (unsigned)atoi(NXGetDefaultValue(app, "EndPause")); darktime = (unsigned)atoi(NXGetDefaultValue(app, "DarkTime")); if(stringToBool(NXGetDefaultValue(app, "SlideFrames"))) slideframes = YES; else slideframes = NO; if(stringToBool(NXGetDefaultValue(app, "SlidePauses"))) slidebegin = slideend = YES; else slidebegin = slideend = NO; if(stringToBool(NXGetDefaultValue(app, "Jump"))) jump = YES; else jump = NO; // Clean up. if(timeunit == 0) timeunit = 1; if(frametime == 0) frametime = 1; if(beginpause == 0) slidebegin = NO; if(endpause == 0) slideend = NO; return self; } - initFrame:(NXRect *)frameRect { broken = NO; running = NO; [super initFrame:frameRect]; [self getDefaults]; [self loadMovie]; if(!broken) { image = [imageList objectAt:0]; [image getSize:&imageRect.size]; [self setImageConstraints]; } state = msh_DARK; currentFrame = 0; wait = 1; countdown = 1; slideDelta.x = randBetween(0.5, 4.0); slideDelta.y = randBetween(0.5, 4.0); return self; } - drawSelf:(const NXRect *)rects :(int)rectCount { NXPoint p; if (!rects || !rectCount) return self; [super drawSelf:rects :rectCount]; p.x = floor(imageRect.origin.x); p.y = floor(imageRect.origin.y); // Draw current image. if(broken) return self; if(!running) [self cacheMovie]; [image composite:NX_SOVER toPoint:&p]; return self; } - oneStep { int prevFrame; // Wait for designated time period. if(![self timePassed:(wait*timeunit)]) return self; if(!running) [self cacheMovie]; if(broken) return self; // Erase previous image. prevFrame = currentFrame; PSsetgray(0.0); NXRectFill(&imageRect); // State machine. if(--countdown == 0) { // Determine new state and movie frame. switch(state) { case msh_DARK: if(beginpause != 0) { state = msh_BEGIN; currentFrame = 0; } else { state = msh_FRAME; currentFrame = 0; } break; case msh_BEGIN: state = msh_FRAME; currentFrame = 0; break; case msh_FRAME: if(currentFrame < (numberOfFrames-1)) { state = msh_FRAME; currentFrame++; } else if(endpause != 0) { state = msh_END; currentFrame = (numberOfFrames-1); } else if(darktime != 0) { state = msh_DARK; currentFrame = 0; } else if(beginpause != 0) { state = msh_BEGIN; currentFrame = 0; } else { state = msh_FRAME; currentFrame = 0; } break; case msh_END: if(darktime != 0) { state = msh_DARK; currentFrame = 0; } else if(beginpause != 0) { state = msh_BEGIN; currentFrame = 0; } else { state = msh_FRAME; currentFrame = 0; } break; default: state = msh_DARK; currentFrame = 0; break; } // Set waiting period and countdown repeater for new state. switch(state) { case msh_DARK: wait = darktime; countdown = 1; break; case msh_BEGIN: wait = (slidebegin ? 1 : beginpause); countdown = (slidebegin ? beginpause : 1); break; case msh_FRAME: wait = (slideframes ? 1 : frametime); countdown = (slideframes ? frametime : 1); break; case msh_END: wait = (slideend ? 1 : endpause); countdown = (slideend ? endpause : 1); break; default: wait = 1; countdown = 1; break; } } // Perform graphics action. image = [imageList objectAt:currentFrame]; [image getSize:&imageRect.size]; [self setImageConstraints]; if(jump && currentFrame<prevFrame) { imageRect.origin.x = floor(randBetween(0, maxCoord.x)); imageRect.origin.y = floor(randBetween(0, maxCoord.y)); } switch(state) { case msh_BEGIN: if(slidebegin) [self slideImageRectOrigin]; [image composite:NX_SOVER toPoint:&imageRect.origin]; break; case msh_FRAME: if(slideframes) [self slideImageRectOrigin]; [image composite:NX_SOVER toPoint:&imageRect.origin]; break; case msh_END: if(slideend) [self slideImageRectOrigin]; [image composite:NX_SOVER toPoint:&imageRect.origin]; break; } return self; } - slideImageRectOrigin { float rand; NXPoint p; p.x = imageRect.origin.x + slideDelta.x; p.y = imageRect.origin.y + slideDelta.y; rand = randBetween(0.5, 4.0); if (p.x < 0) { p.x = 0; slideDelta.x = rand; } else if (p.x > maxCoord.x) { p.x = maxCoord.x; slideDelta.x = -rand; } rand = randBetween(0.5, 4.0); if (p.y < 0) { p.y = 0; slideDelta.y = rand; } else if (p.y > maxCoord.y) { p.y = maxCoord.y; slideDelta.y = -rand; } imageRect.origin.x = p.x; imageRect.origin.y = p.y; return self; } - loadMovie { char filename[MAXPATHLEN], animname[MAXPATHLEN], animframe[MAXPATHLEN]; int i, len, fd; id local_image; // Reasonable directory name? if(broken) return self; if(!theMovie || !(theMovie[0]=='/' || theMovie[0]=='~')) { NXRunAlertPanel(module, "Please use \"dwrite %s Movie mymovie.anim\" to choose a movie, then restart the screensaver.", NULL, NULL, NULL, theMovie, module); broken = TRUE; return self; } // Clean up directory name, replacing initial '~' with HOME. if(theMovie[0] == '~') { strcpy(filename, NXHomeDirectory()); if(theMovie[1] != '/') strcat(filename, "/"); strcat(filename, theMovie+1); } else strcpy(filename, theMovie); len = strlen(filename); if(len>1 && filename[len-1]=='/') filename[--len] = 0; // Loop through TIFF files in directory, inserting numerically in list. imageList = [[List alloc] init]; strcpy(animname, rindex(filename,'/')+1); *rindex(animname,'.') = 0; for (i=0; ; i++) { sprintf(animframe, "%s/%s.%d.tiff", filename, animname, i+1); if (!(local_image = [NXImage findImageNamed:animframe])) { if ((fd=open(animframe, O_RDONLY)) < 0) break; close(fd); local_image = [[NXImage alloc] initFromFile:animframe]; if (local_image == NULL) break; // never null, even if no file [local_image setName:animframe]; } [imageList addObject:local_image]; } currentFrame = 0; // Check if empty movie. if((numberOfFrames = [imageList count]) <= 0) { NXRunAlertPanel(module, "Could not open any frames in movie folder \"%s\"\n\nPlease use \"dwrite %s Movie mymovie.anim\" to choose another movie, then restart the screensaver.", NULL, NULL, NULL, filename, module); broken = TRUE; return self; } return self; } - cacheMovie { id this_image; int i; // Force lazy images to load now so that first movie run is correct speed. if(running) return self; running = YES; numberOfFrames = [imageList count]; for(i=0; i<numberOfFrames; i++) { this_image = [imageList objectAt:i]; if([this_image lockFocus]) [this_image unlockFocus]; else fprintf(stderr, "%s: bad image: %s\n", module, [this_image name]); } return self; } // override this method so that Thinker can't set the default image. - setImage:newImage { return self; } // override - (BOOL) useBufferedWindow { return YES; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.