home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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
-