[net.sources] movie - SUN rasterfile animation playback

majka@ubc-vision.UUCP (03/03/87)

- - - CUT - - - CUT - - - CUT - - - CUT - - - CUT - - - CUT - - - CUT - - -
#!/bin/sh
#
# shell archive - extract with /bin/sh
#
echo extracting file README
sed 's/^X//' > README <<'!FUNKY!STUFF!'
XThis package contains a program called movie, which is a realtime
Xplayback program for a set of SUN rasterfiles.  The code works on
Xboth SUN-2 and SUN-3 bitmap displays.  It is something like framedemo,
Xbut it uses rasterfile(5) files.  IT DOES NOT RUN UNDER SUN WINDOWS.
XSUNwindows does not provide enough control of the screen or enough
Xspeed to do this kind of stuff.  It provides single frame, forward
Xand backward loops with variable speed, mouse-stepped playback, and
Xother miscellaneous features.
X
XI think the code is reasonable,  It tries to avoid magic as much as
Xpossible.  I must warn you, however, that the whole thing was written
Xin a week, and there may be a few ugly and/or mysterious sections.
XI'm sending it out because I probably won't be adding much more to it,
Xor spending much time cleaning it up.
X
XIncluded are a makefile and a manual.
X
XHappy Graphics!
X
X---
XMarc Majka  -  UBC Laboratory for Computational Vision
!FUNKY!STUFF!
echo extracting file Makefile
sed 's/^X//' > Makefile <<'!FUNKY!STUFF!'
X# Makefile for movie
X
XBIN=movie
XPIX=-lpixrect
X
Xmovie: movie.c
X	cc -o ${BIN}/movie movie.c ${PIX}
!FUNKY!STUFF!
echo extracting file movie.c
sed 's/^X//' > movie.c <<'!FUNKY!STUFF!'
X#include <pixrect/pixrect_hs.h>
X#include <stdio.h>
X#include <sgtty.h>
X#include <fcntl.h>
X#include <sys/time.h>
X
X#define NULLPR (struct pixrect *)NULL
X
Xstruct pixrect *screen;
Xstruct pixfont *pf_default(), *pfont;
X
Xint oldr, oldc, row, col, oldx, oldy, sx, sy, ix, iy, go;
Xint oldm, mrow, oldmy, my, imy, page, px, oldpx, pc, oldpc;
Xint bl, bc, br;
Xint MouseFD;
Xstruct pr_prpos	xywh;
Xint (*Button[4])();
Xint (*MenuFunction[16][32])();
X
XFILE *mouse;
X
X#define LEFT 1
X#define CENTRE 2
X#define RIGHT 4
X#define L 1
X#define C 2
X#define R 3
X#define MenuX1 910
X#define MenuY1 60
X#define MenuY2 764
X#define MenuWidth 240
X#define MenuHeight 22
X#define MenuPages 16
X#define MenuRows 32
X#define LastMenuY MenuY2 - MenuHeight
X
X#define PageP1 MenuX1
X#define PageWidth 30
X#define PageP2 PageP1 + PageWidth
X#define PageEnd PageP2 + PageWidth
X
X#define MLineX 910
X#define MLineY 30
X#define MLWidth 80
X 
X#define PIX_XOR (PIX_SRC|PIX_DST)&PIX_NOT(PIX_SRC&PIX_DST)
X#define MAXFRAMES 100
Xstruct pixrect *movie[MAXFRAMES];
Xint nframe, lastframe, frame, rolling, screenframe, framerate;
Xstruct timeval delay;
Xint delaytab_s[201], delaytab_us[201];
Xint framex, framey, frameop;
X
Xchar menu[MenuPages][MenuRows+1][128], MouseString[4][11];
Xint MainX1, MainY1, MainX2, MainY2;
X
Xchar scriptfile[256];
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{	
X	int argn;
X	
X	scriptfile[0] == '\0';
X
X	for (argn = 1; argn < argc; argn++) {
X		if (argv[argn][0] == '-') {
X			switch (argv[argn][1]) {
X				case 'p': /* frame position */
X					framey = atoi(argv[++argn]);
X					framex = atoi(argv[++argn]);
X					break;
X				case 's': /* script */
X					strcpy(scriptfile,argv[++argn]);
X					break;
X				default:
X					Usage();
X					exit(0);
X			}
X		}
X		else {
X			Usage();
X			exit(0);
X		}
X	}
X	
X	Init();
X	Menu();
X	Fini();
X}
X
XUsage()
X{
X	fprintf(stderr,"movie [-p %%d %%d] [-s %%s]\n");
X	fprintf(stderr,"    -p   Frame row col position\n");
X	fprintf(stderr,"    -s   Script file name\n");
X}
X
XMenu()
X{
X	int dx, dy, but;
X
X	DrawMenuCursor(px,my);
X	
X	while (go) {
X		ReadMouse(&dx,&dy,&but);
X		MoveMenuCursor(dx,dy);
X		if (but) MenuHandle(my,but);
X	}
X
X	DrawMenuCursor(px,my);
X}
X
XMoveMenuCursor(dx,dy)
Xint dx,dy;
X{
X	oldm = mrow;
X	oldmy = my;
X	oldpc = pc;
X	oldpx = px;
X	imy -= dy;
X	px += dx;
X	if (imy < MenuY1) imy = MenuY1;
X	if (imy > MenuY2) imy = MenuY2;
X	if (px < PageP1) px = PageP1;
X	if (px > PageEnd) px = PageEnd;
X	
X	mrow = 1 + (imy - MenuY1) / MenuHeight;
X	my = MenuY1 + (mrow - 1) * MenuHeight;
X	pc = (px > PageP2);
X	
X	if (oldm != mrow || oldpc != pc) {
X		DrawMenuCursor(oldpx,oldmy);
X		DrawMenuCursor(px,my);
X	}
X}
X
XDrawMenuCursor(x,y)
Xint x,y;
X{
X	int r;
X	
X	r = (y - MenuY1) / MenuHeight;
X	
X	if (y > LastMenuY) {
X		if (x > PageP2) pr_rop(screen,PageP2,y,PageWidth,MenuHeight,
X				PIX_NOT(PIX_DST),NULLPR,0,0);
X		else pr_rop(screen,PageP1,y,PageWidth,MenuHeight,
X				PIX_NOT(PIX_DST),NULLPR,0,0);
X	}
X	else {
X		pr_rop(screen,MenuX1,y,MenuWidth-1,MenuHeight,
X			PIX_NOT(PIX_DST),NULLPR,0,0);
X
X		if (menu[page][r][0] == '\0')
X			pr_rop(screen,MenuX1+3,y+3,MenuWidth-7,MenuHeight-6,
X				PIX_NOT(PIX_DST),NULLPR,0,0);
X	}
X}
X
XBindButton(b,str,f)
Xint b;
Xchar *str;
Xint (*f)();
X{
X	Button[b] = f;
X	MouseLine(b,str);
X}
X
XBOGUS()
X{
X}
X
XMouseLine(b,str)
Xint b;
Xchar *str;
X{
X	MouseString[b][0] = ' ';
X	strncpy(MouseString[b]+1,str,8);
X	MouseString[b][9] = ' ';
X	MouseString[b][10] = '\0';
X	DrawMouseItem(b);
X}
X
XRefreshMouseLine()
X{
X	struct pr_prpos wh;
X
X	wh.pr = screen;
X	wh.pos.x = MLineX;
X	wh.pos.y = MLineY + MenuHeight - 3;
X	pr_rop(screen,wh.pos.x,wh.pos.y-14,MenuWidth+1,19,PIX_CLR,NULLPR,0,0);
X	wh.pos.x += 8;
X	wh.pos.y -= 3;
X	pf_text(wh,PIX_NOT(PIX_SRC),pfont," left   ");
X	wh.pos.x += MLWidth;
X	pf_text(wh,PIX_NOT(PIX_SRC),pfont," centre ");
X	wh.pos.x += MLWidth;
X	pf_text(wh,PIX_NOT(PIX_SRC),pfont," right  ");
X		
X	DrawMouseItem(L);
X	DrawMouseItem(C);
X	DrawMouseItem(R);
X}
X
XDrawMouseItem(b)
Xint b;
X{
X	struct pr_prpos wh;
X	
X	wh.pr = screen;
X	wh.pos.x = MLineX + (b - 1) * MLWidth;
X	wh.pos.y = MLineY;
X	pr_rop(screen,wh.pos.x,wh.pos.y-14,MLWidth+1,19,PIX_CLR,NULLPR,0,0);
X	pf_text(wh,PIX_SRC,pfont,MouseString[b]);
X}
X
XInit()
X{
X	FILE *fopen();
X	int one = 1;
X	int BOGUS(), Menu();
X	int i, s, us;
X	double d, dd, ds, dus;
X		
X	LoadFrames();
X	screen = pr_open("/dev/fb");
X	mouse = fopen("/dev/mouse","r");
X	if (mouse == NULL) {
X		(void)printf("can't open /dev/mouse\n");
X		exit(1);
X	}
X	MouseFD = fileno(mouse);
X	
X	go = 1;
X	framerate = 90;
X	screenframe = -1;
X	frame = 0;
X	framex = 0;
X	framey = 0;
X	frameop = PIX_SRC;
X
X	delaytab_s [  0] = delaytab_s [200] = 0;
X	delaytab_us[  0] = delaytab_us[200] = 0;
X	d = 0.75;
X	dd = d  / 99.0;
X
X	for (i = 1; i < 100; i++) {
X		s = (int)d;
X		dus = (d - (double)s) * 100000.0;
X		us = (int)dus;
X		delaytab_s[i + 100] = delaytab_s[100 - i] = s;
X		delaytab_us[i + 100] = delaytab_us[100 - i] = us;
X		d -= dd;
X	}
X	
X	MainX1 = 0;
X	MainY1 = 0;
X	MainX2 = 899;
X	MainY2 = 899;
X	imy = MenuY1;
X	my = MenuY1;
X	mrow = 1;
X	px = PageP1;
X	pc = 0;
X	
X	xywh.pr = screen;
X	xywh.pos.x = 910;
X	xywh.pos.y = 10;
X	
X	page = 1;
X 
X	pfont = pf_default();
X	EraseScreen();
X	InitMenu();
X	page = 0;
X	RefreshMenu();
X	DisplayFrame();
X	Button[0] = BOGUS;
X	BindButton(L,"Select",BOGUS);
X	BindButton(C," ",BOGUS);
X	BindButton(R," ",BOGUS);
X	RefreshMouseLine();
X}
X
XLoadFrames()
X{
X	int ifile;
X	char str[256];
X	FILE *fp, *fopen(), *script;
X	struct pixrect *pr_load();
X	struct colormap_t *cmap;
X	
X	fprintf(stderr,"Loading frames\n");
X
X	if (scriptfile[0] == '\0') {
X		ifile = 1;
X	
X		for (frame = 0; frame < MAXFRAMES && ifile; frame++) {
X			sprintf(str,"frame.%d",frame);
X			fp = fopen(str,"r");
X			if (fp == NULL) ifile = 0;
X			else {
X				movie[frame] = pr_load(fp,cmap);
X				fclose(fp);
X				fprintf(stderr,"%2d ",frame);
X				if (9 == (frame % 10)) fprintf(stderr,"\n");
X				fflush(stderr);
X			}
X		}
X	}
X	else {
X		script = fopen(scriptfile,"r");
X		if (script == NULL) {
X			fprintf(stderr,"movie: can't read script file \"%s\"\n",scriptfile);
X			exit(1);
X		}
X
X		frame = 0;
X		while (EOF != fscanf(script,"%s",str)) {
X			fp = fopen(str,"r");
X			if (fp == NULL) {
X				fprintf(stderr,"movie: can't read frame file \"%s\"\n",str);
X				exit(1);
X			}
X			movie[frame] = pr_load(fp,cmap);
X			fclose(fp);
X			fprintf(stderr,"frame %d: %s\n",frame,str);
X			frame++;
X		}
X		frame++; /* overshoot like above */
X	}
X	
X	fprintf(stderr,"\n");
X	nframe = frame - 1;
X	lastframe = frame - 2;
X	frame = 0;
X	if (nframe == 0) Fini();
X}
X
XFini()
X{
X	EraseScreen();
X	(void)fclose(mouse);
X	exit(0);
X}
X
XRefreshMenu()
X{
X	struct pr_prpos wh;
X	int r;
X	char pn[64];
X			
X	wh.pr = screen;
X	wh.pos.x = MenuX1 + 3;
X	EraseMenu();
X/*
X	pr_vector(screen,900,0,900,900,PIX_CLR,0);
X	pr_vector(screen,901,0,901,900,PIX_CLR,0);
X	pr_vector(screen,902,0,902,900,PIX_CLR,0);
X*/	
X	wh.pos.y = MenuY1 + 14;
X	for (r = 0; r < MenuRows; r++) {
X		pf_text(wh,PIX_SRC,pfont,menu[page][r]);
X		wh.pos.y += MenuHeight;
X	}
X	pf_text(wh,PIX_SRC,pfont," + ");
X	wh.pos.x += PageWidth;
X	pf_text(wh,PIX_SRC,pfont," - ");
X	wh.pos.x += PageWidth;
X	sprintf(pn,"%2d %s",page,menu[page][MenuRows]);
X	pf_text(wh,PIX_NOT(PIX_SRC),pfont,pn);
X}
X
XEraseMenu()
X{
X	pr_rop(screen,MenuX1,MenuY1,MenuWidth,MenuY2,PIX_SET,NULLPR,0,0);
X}
X	
X
XReadMouse(x,y,b)
Xint *x,*y,*b;
X{
X	char mbuf[4];
X	int ms, dx, dy, ol, oc, or, gotany, bits;
X
X	*x = 0;
X	*y = 0;
X	*b = 0;
X
X	bits = (1 << MouseFD);
X	gotany = select(16,&bits,(int *)0,(int *)0,&delay);
X
X	if (bits & (1 << MouseFD)) {
X		read(MouseFD,mbuf,3);
X
X		ms = mbuf[0];
X		dx = mbuf[1];
X		dy = mbuf[2];
X		*x = dx;
X		*y = dy;
X		ol = bl;
X		oc = bc;
X		or = br;
X		bl = 4 & ~ms;
X		bc = 2 & ~ms;
X		br = 1 & ~ms;
X		*b = 0;
X		if (bl && !ol) *b = 1;
X		if (bc && !oc) *b = 2;
X		if (br && !or) *b = 3;
X	}
X}
X
XMenuHandle(y,b)
Xint y,b;
X{
X	int r,oldp;
X	
X	r = (y - MenuY1) / MenuHeight;
X
X	if (r == MenuRows) {
X		oldp = page;
X		if (px > PageP2 && page > 0) page--;
X		else if (px < PageP2 && page < (MenuPages - 1)) page++;
X		if (page != oldp) {
X			DrawMenuCursor(px,my);
X			RefreshMenu();
X			DrawMenuCursor(px,my);
X		}
X	}
X	else if (b == L) ExecMenu(page,r);
X}
X
XExecMenu(page,row)
Xint page,row;
X{	
X	(*MenuFunction[page][row])();
X}
X
XEraseScreen()
X{
X	pr_rop(screen,0,0,1152,900,PIX_SET,NULLPR,0,0);
X}
X
XRedrawEverything()
X{
X	EraseScreen();
X	RefreshMenu();
X	RefreshMouseLine();
X	DrawMenuCursor(px,my);
X}
X
XMenuItem(str)
Xchar *str;
X{
X	int mr, mp;
X	char ms[64];
X	
X	sscanf(str+5,"%d %d %[^\n]",&mp,&mr,ms);
X	SetMenuItem(mp,mr,ms);
X}
X
XSetMenuItem(p,r,str,ptr)
Xint p,r;
Xchar *str;
Xint (*ptr)();
X{
X	char tstr[128];
X	int i, l, mc;
X	
X	mc = (MenuWidth / 8) - 1;
X	
X	strcpy(tstr," ");
X	strcat(tstr,str);
X	l = strlen(tstr);
X	if (l < mc) for (i = l; i < mc; i++) strcat(tstr," ");
X	if (l > mc) tstr[mc-1] = ' ';
X	strncpy(menu[p][r],tstr,mc);
X	MenuFunction[p][r] = ptr;
X	
X	if (p == page) {
X		DrawMenuCursor(px,my);
X		RefreshMenu();
X		DrawMenuCursor(px,my);
X	}
X}
X
XInitMenu()
X{
X	int p, r, m;
X	int BOGUS(), M_quit();
X	int DisplayFirstFrame(), DisplayNextFrame();
X	int DisplayPrevFrame(), DisplayLastFrame(), SingleFrame();
X	int ForwardLoop(), BackwardLoop(), VariableLoop();
X	int BackAndForth(), PositionFrame(), ReverseVideo();
X	int ForwardPlay(), BackwardPlay(), ScrollFrames(); 
X	
X	for (p = 0; p < MenuPages; p++)
X		for (r = 0; r <= MenuRows; r++) {
X			strcpy(menu[p][r],"");
X			MenuFunction[p][r] = BOGUS;
X		}
X	
X	m = 0;
X
X	SetMenuItem(0,m++,"First Frame",DisplayFirstFrame);
X	SetMenuItem(0,m++,"Forward Frame",DisplayNextFrame);
X	SetMenuItem(0,m++,"Backward Frame",DisplayPrevFrame);
X	SetMenuItem(0,m++,"Last Frame",DisplayLastFrame);
X	SetMenuItem(0,m++,"Single Frame",SingleFrame);
X	SetMenuItem(0,m++,"Forward Play Once",ForwardPlay);
X	SetMenuItem(0,m++,"Backward Play Once",BackwardPlay);
X	SetMenuItem(0,m++,"Forward Loop",ForwardLoop);
X	SetMenuItem(0,m++,"Backward Loop",BackwardLoop);
X	SetMenuItem(0,m++,"Back and Forth Loop",BackAndForth);
X	SetMenuItem(0,m++,"Variable Speed Loop",VariableLoop);
X	SetMenuItem(0,m++,"Scroll With Mouse",ScrollFrames);
X	SetMenuItem(0,m++,"Position Frame",PositionFrame);
X	SetMenuItem(0,m++,"Reverse Frame Video",ReverseVideo);
X	SetMenuItem(0,m++,"Quit",M_quit);
X}
X
XM_quit()
X{
X	go = 0;
X}
X
XDisplayFirstFrame()
X{
X	frame = 0;
X	DisplayFrame();
X}
X
XDisplayNextFrame()
X{
X	if (frame < lastframe) {
X		frame++;
X		DisplayFrame();
X	}
X}
X
XDisplayPrevFrame()
X{
X	if (frame > 0) {
X		frame--;
X		DisplayFrame();
X	}
X}
X
XDisplayLastFrame()
X{
X	frame = lastframe;
X	DisplayFrame();
X}
X
XSingleFrame()
X{
X	int dx, dy, but, Cut(), DisplayPrevFrame(), DisplayNextFrame();
X	
X	BindButton(L,"Backward",DisplayPrevFrame);
X	BindButton(C,"Stop",Cut);
X	BindButton(R,"Forward",DisplayNextFrame);
X	
X	rolling = 1;
X	while (rolling) {
X		ReadMouse(&dx,&dy,&but);
X		(*Button[but])();
X	}
X
X	BindButton(L,"Select",BOGUS);
X	BindButton(C," ",BOGUS);
X	BindButton(R," ",BOGUS);
X}
X
XForwardPlay()
X{
X	if (framerate < 0) framerate *= -1;
X
X	for (frame = 0; frame < nframe; frame++) {
X		if (framerate < 0) framerate = 0;
X		DisplayFrame();
X		DelayFrame();
X	}
X	frame = lastframe;
X}
X
XBackwardPlay()
X{
X	if (framerate > 0) framerate *= -1;
X
X	for (frame = lastframe; frame >= 0; frame--) {
X		if (framerate > 0) framerate = 0;
X		DisplayFrame();
X		DelayFrame();
X	}
X	frame = 0;
X}
X
XForwardLoop()
X{
X	int IncreaseRate(), DecreaseRate(), Cut(), dx, dy, but;
X	
X	BindButton(L,"Slower",DecreaseRate);
X	BindButton(C,"Stop",Cut);
X	BindButton(R,"Faster",IncreaseRate);
X
X	if (framerate < 0) framerate *= -1;
X
X	rolling = 1;
X	frame = 0;
X	
X	while (rolling) {
X		DisplayFrame();
X		ReadMouse(&dx,&dy,&but);
X		(*Button[but])();
X		DelayFrame();
X		if (framerate < 0) framerate = 0;
X		if (framerate != 0) frame = (frame + 1) % nframe;
X	}
X	frame = lastframe;
X	BindButton(L,"Select",BOGUS);
X	BindButton(C," ",BOGUS);
X	BindButton(R," ",BOGUS);
X}
X
XBackwardLoop()
X{
X	int IncreaseRate(), DecreaseRate(), Cut(), dx, dy, but;
X	
X	BindButton(L,"Slower",DecreaseRate);
X	BindButton(C,"Stop",Cut);
X	BindButton(R,"Faster",IncreaseRate);
X
X	if (framerate > 0) framerate *= -1;
X
X	rolling = 1;
X	frame = 0;
X	
X	while (rolling) {
X		DisplayFrame();
X		ReadMouse(&dx,&dy,&but);
X		(*Button[but])();
X		DelayFrame();
X		if (framerate > 0) framerate = 0;
X		if (framerate != 0) frame = (frame + lastframe) % nframe;
X	}
X	frame = lastframe;
X	BindButton(L,"Select",BOGUS);
X	BindButton(C," ",BOGUS);
X	BindButton(R," ",BOGUS);
X}
X
XVariableLoop()
X{
X	int IncreaseRate(), DecreaseRate(), Cut(), dx, dy, but;
X	
X	BindButton(L,"Slower",DecreaseRate);
X	BindButton(C,"Stop",Cut);
X	BindButton(R,"Faster",IncreaseRate);
X
X	rolling = 1;
X	frame = 0;
X	
X	while (rolling) {
X		DisplayFrame();
X		ReadMouse(&dx,&dy,&but);
X		framerate += dy;
X		if (framerate >  100) framerate =  100;
X		if (framerate < -100) framerate = -100;
X		(*Button[but])();
X		DelayFrame();
X		if (framerate > 0) frame = (frame + 1) % nframe;
X		else if (framerate < 0) frame = (frame + lastframe) % nframe;
X	}
X
X
X	BindButton(L,"Select",BOGUS);
X	BindButton(C," ",BOGUS);
X	BindButton(R," ",BOGUS);
X}
X
XBackAndForth()
X{
X	int IncreaseRate(), DecreaseRate(), Cut(), dx, dy, but, dir;
X	
X	BindButton(L,"Slower",DecreaseRate);
X	BindButton(C,"Stop",Cut);
X	BindButton(R,"Faster",IncreaseRate);
X
X	if (framerate < 0) framerate *= -1;
X
X	rolling = 1;
X	frame = 0;
X	dir = 0;
X		
X	while (rolling) {
X		DisplayFrame();
X		ReadMouse(&dx,&dy,&but);
X		(*Button[but])();
X		DelayFrame();
X		if (framerate < 0) framerate = 0;
X		if (framerate != 0) {
X			if (dir) {
X				if (frame == lastframe) {
X					dir = !dir;
X					frame--;
X				}
X				else frame++;
X			}
X			else {
X				if (frame == 0) {
X					dir = !dir;
X					frame++;
X				}
X				else frame--;
X			}
X		}
X	}
X
X	BindButton(L,"Select",BOGUS);
X	BindButton(C," ",BOGUS);
X	BindButton(R," ",BOGUS);
X}
X
XScrollFrames()
X{
X	int dx, dy, but, x, Cut();
X	
X	BindButton(L,"Stop",Cut);
X
X	x = frame * 8;
X	rolling = 1;
X	
X	while (rolling) {
X		DisplayFrame();
X		ReadMouse(&dx,&dy,&but);
X		(*Button[but])();
X		
X		x += dx;
X		frame = x / 8;
X		if (frame > lastframe) {
X			frame = lastframe;
X			x = frame * 8;
X		}
X		if (frame < 0) {
X			frame = 0;
X			x = 0;
X		}
X	}
X	BindButton(L,"Select",BOGUS);
X}
X
XIncreaseRate()
X{
X	if (framerate < 100) framerate += 1;
X}
X
XDecreaseRate()
X{
X	if (framerate > -100) framerate -= 1;
X}
X
XCut()
X{
X	rolling = 0;
X}
X
XDisplayFrame()
X{
X	Annotation();
X
X	if (frame == screenframe) return(0);
X	
X	screenframe = frame;
X	
X	pr_rop(screen,framex,framey,
X		movie[frame]->pr_size.x,movie[frame]->pr_size.y,
X		frameop,movie[frame],0,0);
X}
X
XAnnotation()
X{
X	char str[256];
X
X	sprintf(str,"Frame %2d of %d   %4d",frame,lastframe,framerate);
X	pf_text(xywh,PIX_NOT(PIX_SRC),pfont,str);
X}
X
XDelayFrame()
X{
X	int f, bits, gotsome;
X	char mbuf[3];
X	
X	bits = 1 << MouseFD;
X	
X	f = framerate + 100;
X	delay.tv_sec  = delaytab_s[f];
X	delay.tv_usec = delaytab_us[f];
X	gotsome = select(32,&bits,(int *)0,(int *)0,&delay);
X	if (gotsome < 0) {
X		perror("select");
X		fprintf(stderr,"returned value was %d\n",gotsome);
X		DieHorribly();
X	}
X	if (bits & (1 << MouseFD)) {
X		read(MouseFD,mbuf,3);
X		framerate += mbuf[2];
X		if (framerate > 100) framerate = 100;
X		if (framerate < -100) framerate = -100;
X		delay.tv_sec = 0;
X		delay.tv_usec /= 2;
X		select(32,(int *)0,(int *)0,(int *)0,&delay);
X	}
X}
X
XDieHorribly()
X{
X	char str[128];
X	
X	sprintf(str,"     Goodbye Cruel World!     ");
X	pf_text(xywh,PIX_SRC,pfont,str);
X	
X	exit(1);
X}
X
XPositionFrame()
X{
X	int dx, dy, but, Cut(), maxx, maxy, oldx, oldy, xs, ys;
X
X	BindButton(L,"Stop",Cut);
X	rolling = 1;
X
X	xs = movie[frame]->pr_size.x;
X	ys = movie[frame]->pr_size.y;
X
X	maxx = 899 - xs;
X	maxy = 899 - ys;
X
X	DrawBox(framex,framey,xs,ys);
X	
X	while (rolling) {
X		ReadMouse(&dx,&dy,&but);
X		(*Button[but])();
X		oldx = framex;
X		oldy = framey;
X		framex += dx;
X		framey -= dy;
X		if (framex < 0) framex = 0;
X		if (framey < 0) framey = 0;
X		if (framex > maxx) framex = maxx;
X		if (framey > maxy) framey = maxy;
X		if (oldx != framex || oldy != framey) {
X			DrawBox(oldx,oldy,xs,ys);
X			DrawBox(framex,framey,xs,ys);
X		}
X	}
X	EraseFrame();
X	DisplayFrame();
X	BindButton(L,"Select",BOGUS);
X}
X
XReverseVideo()
X{
X	if (frameop == PIX_SRC) frameop = PIX_NOT(PIX_SRC);
X	else frameop = PIX_SRC;
X	EraseFrame();
X	DisplayFrame();
X}
X
XEraseFrame()
X{
X	screenframe = -1;
X	pr_rop(screen,0,0,900,900,PIX_SET,NULLPR,0,0);
X}
X
XDrawBox(x,y,w,h)
Xint x,y,w,h;
X{
X	int x2, y2;
X	
X	x2 = x + w - 1;
X	y2 = y + h - 1;
X	
X	pr_vector(screen,x,y,x2-1,y,PIX_NOT(PIX_DST),0);
X	pr_vector(screen,x2,y,x2,y2-1,PIX_NOT(PIX_DST),0);
X	pr_vector(screen,x2,y2,x+1,y2,PIX_NOT(PIX_DST),0);
X	pr_vector(screen,x,y2,x,y+1,PIX_NOT(PIX_DST),0);
X}
X
XTouch(f,i)
Xint f,i;
X{
X	int pix;
X
X	if (i > 0) {
X		if (f < lastframe) pix = pr_get(movie[f+i],0,0);
X		else pix = pr_get(movie[0],0,0);
X	}
X	else {
X		if (f > 0) pix = pr_get(movie[f+i],0,0);
X		else pix = pr_get(movie[lastframe],0,0);
X	}
X}
!FUNKY!STUFF!
echo extracting file movie.1
sed 's/^X//' > movie.1 <<'!FUNKY!STUFF!'
X.TH MOVIE 1
X.SH NAME
Xmovie - realtime playback of SUN rasterfiles
X.SH SYNOPSIS
X.B movie
X[-p r c] [-s file]
X.SH DESCRIPTION
X.B movie
Xreads a set of rasterfiles (see
X.I rasterfile(5)\fR)
Xand stores them in memory.  It provides a number of functions for
Xanimating the sequence of rasters on the SUN bitmap display.  These
Xfunctions are described in the
X.B Playback Functions
Xsection below.
X.sp
X.B movie
X.I does not
Xrun under SUN-Windows.  It uses the mouse for frame and speed control,
Xas well as menu selection of playback functions.
X.sp
XThe screen is divided into 5 areas.  The left square part of the screen
X(900 * 900 pixels) is the frame area. All rasters are displayed here.
XThe right part of the screen comprises a single information line at the
Xtop of the screen, a mouse button line, a menu area, and a menu page 
Xselection area.
X.sp
XThe information line displays the currently displayed frame number,
Xthe number of the last frame, and a speed indicator.  The speed
Xcontrols the frame presentation rate during playback.  The speed is
Xshown as a number between 0 and 100.  A speed of 0 indicates no motion.
XA speed of 100 indicates the maximum possible redisplay rate.  When
Xframes are being presented in reverse sequence, as in a
X.B Backward Loop,
Xthe speed is shown as a negative number.
X.sp
XThe mouse button line shows the status of the three mouse buttons.
XThe line is divided into 3 areas, corresponding to the left,
Xcentre, and right mouse buttons.  The effect of pressing one of
Xthe buttons is indicated in the appropriate area.
X.sp
XThe menu is displayed below the mouse button line.  Each menu 
Xitem is shown in a reverse video line.  The menu cursor moves
Xup and down through the menu, and reverses the bits in the line
Xunder the cursor. 
X.sp
XThe menu page selection area is at the bottom of the menu.  It has
Xtwo areas, labeled \*(lq+\*(rq and \*(lq-\*(rq, which will switch to the next 
Xor previous menu page.  This feature unnecessary for
X.B movie,
Xas only the first menu page has any \*(lqlive\*(rq entries, but is
Xthere for future expansion.  The menu contains 16 pages, each
Xof 32 menu items.  The current page number is displayed to
Xthe right of the \*(lq-\*(rq selector.
X.sp
XMouse motion is up/down to select menu items.  Playback functions
Xgenerally take up/down motions to cause increase/decrease in playback
Xspeed, and left/right motions to indicate previous/next frame selection.
X.sp
XThe position of the upper left corner of displayed frames may be
Xset by the command line
X.B -p
Xoption.  The following two integers are taken as row and column offsets.
X.sp
XBy default
X.B movie
Xwill read rasterfiles from the current directory. Files with names of the
Xform 
X.I frame.#
X(where # is a number) are read into memory.  The files must be numbered
Xsequentially, beginning with frame.0.  This is similar to the convention
Xused by the SUN demo program
X.B framedemo,
Xbut note that in this case the files are in 
X.I rasterfile
Xformat.
XThe
X.B -s
Xoption overrides the reading of the \*(lqframe.#\*(rq files.  The argument
Xfollowing the 
X.B -s
Xoption indicates a file to be read, which contains a list of
Xrasterfiles to read in sequence.
X.SH "PLAYBACK FUNCTIONS"
X.B First Frame
X.br
XDisplays the first frame
X.sp
X.B Next Frame
X.br
XDisplays the next frame in the sequence, without wrap-around.
X.sp
X.B Previous Frame
X.br
XDisplays the previous frame in the sequence, without wrap-around.
X.sp
X.B Last Frame
X.br
XDisplays the last frame in the sequence.
X.sp
X.B Single Frame
X.br
XSingle frame playback. The left and right mouse
Xbuttons select the previous and next frames.
X.sp
X.B Forward Play Once
X.br
XPlays the sequence from first to last frame once, at the current 
Xframe speed.
X.sp
X.B Backward Play Once
X.br
XPlays the sequence from last to first frame once, at the current 
Xframe speed.
X.sp
X.B Forward Loop
X.br
XPlay the sequence continually, from first to last frame.  The 
Xplayback speed may be adjusted with up/down mouse motion, or
Xwith the left and right mouse buttons.
X.sp
X.B Backward Loop
X.br
XPlay the sequence continually, from last to first frame.  The 
Xplayback speed may be adjusted with up/down mouse motion, or
Xwith the left and right mouse buttons.
X.sp
X.B Back and Forth Loop
X.br
XPlay the sequence continually, from first to last, then last to first
Xframe.  The playback speed may be adjusted with up/down mouse motion, or
Xwith the left and right mouse buttons.
X.sp
X.B Variable Speed Loop
X.br
XPlay the sequence continually, The 
Xplayback speed may be adjusted with up/down mouse motion, or
Xwith the left and right mouse buttons. The playback direction
Xmay be changed by moving the speed through 0.  Negative
Xspeed indicates reverse playback.
X.sp
X.B Scroll With Mouse
X.br
XFrames are displayed one at a time.  Left/right mouse motion displays 
Xprevious/next frames.
X.sp
X.B Position Frame
X.br
XAllows the upper left starting position of displayed frames
Xto be adjusted interactively.  A box is drawn around the frame,
Xand moved within the frame area with mouse motion.  Pressing
Xthe left mouse button causes frame display to take place at the
Xnew position.
X.sp
X.B Reverse Frame Video
X.br
XReverses the black/white sense of displayed frames.
X.sp
X.B Quit
X.br
XExits the
X.B movie
Xprogram.
X.SH ACKNOWLEDGEMENT
XThe playback functions in 
X.B movie
Xare similar to the 
X.B S-Dynamics
Xanimation playback program on our
X.B Symbolics 3650.
XI thank the authors of that software for giving me the idea
Xto write this one.   This program is, however, in no way
Xcopied or translated from that code.
X.SH AUTHOR
XMarc Majka
!FUNKY!STUFF!
echo Done\!
exit 0