This is MovieShowViewPart.m in view mode; [Download] [Up]
/* * MovieShowView - version 1.0 * * hacked from: "SlideShowView" by brighton@phuket.nbn.com, 13 Nov 91 * hacked by: Paul Burchard <burchard@math.utah.edu> * further hacked by sam <sam_s@next.com> to add BackSpace 3.0 inspector */ #import <appkit/NXImage.h> // NXImage #import <appkit/OpenPanel.h> // NXRunAlertPanel() #import <appkit/Text.h> // NXOrderStrings() #import <appkit/Button.h> #import <dpsclient/wraps.h> // PSsetgray() #import <defaults/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/MovieShow.anim" }, { "FrameTime", "1" }, { "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 { [super initFrame:frameRect]; [self getDefaults]; [self initMovie]; return self; } - initMovie { broken = NO; running = NO; [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]; char animFrame[MAXPATHLEN]; int i, len, fd; id local_image; const char *tiffext = ".tiff"; char animName[100]; // Reasonable directory name? if(broken) return self; if(!theMovie || !(theMovie[0]=='/' || theMovie[0]=='~')) { NXRunAlertPanel(module, "Bogus movie file.", 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; 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]; } numberOfFrames = i; currentFrame = 0; // Check if empty movie. if((numberOfFrames = [imageList count]) <= 0) { NXRunAlertPanel(module, "Could not open any frames in movie folder \"%s\"\n\n", NULL, NULL, NULL, filename); 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; } - setJump:sender { jump = [jumpButton state] ? YES:NO; NXWriteDefault("MovieShow", "Jump", jump ? "YES":"NO"); return self; } - setSlideFrames:sender { slideframes = [slideFramesButton state] ? YES:NO; NXWriteDefault("MovieShow", "SlideFrames", slideframes ? "YES":"NO"); return self; } - setSlidePauses:sender { slidebegin = slideend = [slidePausesButton state] ? YES:NO; NXWriteDefault("MovieShow", "SlidePauses", slidebegin ? "YES":"NO"); return self; } - setFile:sender { const char *const types[] = {"tiff", NULL}; char *iptr; BOOL done = NO; int i; // if ([[OpenPanel new] runModalForTypes:types]) do { if ([[OpenPanel new] runModalForDirectory:theMovie file:"" types:types]) { if (movieNameBuffer) free(movieNameBuffer); theMovie = movieNameBuffer = NXCopyStringBuffer([[OpenPanel new] filename]); if (iptr = rindex(movieNameBuffer, '/')) *iptr = '\0'; i = strlen(movieNameBuffer); if (i > 5 && !strcmp(&movieNameBuffer[i-5], ".anim")) { [filesTextField setStringValue:theMovie]; NXWriteDefault("MovieShow", "Movie", theMovie); [imageList freeObjects]; [imageList free]; imageList = nil; [self initMovie]; done = YES; } else { NXRunAlertPanel(module, "Please select a tiff in a \".anim\" folder.", NULL, NULL, NULL); } } else done = YES; } while (!done); return self; } - setBeginPause:sender { char str[100]; beginpause = [beginPauseTextField intValue]; sprintf(str,"%d", (int)beginpause); NXWriteDefault("MovieShow", "BeginPause", str); return self; } - setEndPause:sender { char str[100]; endpause = [endPauseTextField intValue]; sprintf(str,"%d", (int)endpause); NXWriteDefault("MovieShow", "EndPause", str); return self; } - setDarkFor:sender { char str[100]; darktime = [darkForTextField intValue]; sprintf(str,"%d", (int)darktime); NXWriteDefault("MovieShow", "DarkTime", str); return self; } - setTimeUnit:sender { char str[100]; timeunit = [timeUnitTextField intValue]; sprintf(str,"%d", (int)timeunit); NXWriteDefault("MovieShow", "TimeUnit", str); return self; } - inspector:sender { char buf[MAXPATHLEN]; if (!inspectorPanel) { sprintf(buf,"%s/movie.nib",[sender moduleDirectory:"MovieShow"]); [NXApp loadNibFile:buf owner:self withNames:NO]; [filesTextField setStringValue:theMovie]; [beginPauseTextField setIntValue:beginpause]; [endPauseTextField setIntValue:endpause]; [darkForTextField setIntValue:darktime]; [timeUnitTextField setIntValue:timeunit]; [jumpButton setState: (jump ? 1:0)]; [slideFramesButton setState: (slideframes ? 1:0)]; [slidePausesButton setState: (slidebegin ? 1:0)]; } return inspectorPanel; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.