| 1 | greg | 2.1 | /* Copyright (c) 1995 Regents of the University of California */ | 
| 2 |  |  |  | 
| 3 |  |  | #ifndef lint | 
| 4 |  |  | static char SCCSid[] = "$SunId$ LBL"; | 
| 5 |  |  | #endif | 
| 6 |  |  |  | 
| 7 |  |  | /* | 
| 8 |  |  | * Radiance animation control program | 
| 9 |  |  | */ | 
| 10 |  |  |  | 
| 11 |  |  | #include "standard.h" | 
| 12 |  |  | #include <sys/types.h> | 
| 13 |  |  | #include <sys/stat.h> | 
| 14 |  |  | #include "view.h" | 
| 15 |  |  | #include "vars.h" | 
| 16 |  |  | /* input variables */ | 
| 17 |  |  | #define HOST            0               /* rendering host machine */ | 
| 18 |  |  | #define RENDER          1               /* rendering options */ | 
| 19 |  |  | #define PFILT           2               /* pfilt options */ | 
| 20 |  |  | #define PINTERP         3               /* pinterp options */ | 
| 21 |  |  | #define OCTREE          4               /* octree file name */ | 
| 22 |  |  | #define DIRECTORY       5               /* working (sub)directory */ | 
| 23 |  |  | #define BASENAME        6               /* output image base name */ | 
| 24 |  |  | #define VIEWFILE        7               /* animation frame views */ | 
| 25 |  |  | #define START           8               /* starting frame number */ | 
| 26 |  |  | #define END             9               /* ending frame number */ | 
| 27 |  |  | #define RIF             10              /* rad input file */ | 
| 28 |  |  | #define NEXTANIM        11              /* next animation file */ | 
| 29 |  |  | #define ANIMATE         12              /* animation command */ | 
| 30 |  |  | #define TRANSFER        13              /* frame transfer command */ | 
| 31 |  |  | #define ARCHIVE         14              /* archiving command */ | 
| 32 |  |  | #define INTERP          15              /* # frames to interpolate */ | 
| 33 |  |  | #define OVERSAMP        16              /* # times to oversample image */ | 
| 34 |  |  | #define MBLUR           17              /* samples for motion blur */ | 
| 35 |  |  | #define RTRACE          18              /* use rtrace with pinterp? */ | 
| 36 |  |  | #define DISKSPACE       19              /* how much disk space to use */ | 
| 37 |  |  | #define RESOLUTION      20              /* desired final resolution */ | 
| 38 |  |  | #define EXPOSURE        21              /* how to compute exposure */ | 
| 39 |  |  |  | 
| 40 |  |  | int     NVARS = 22;             /* total number of variables */ | 
| 41 |  |  |  | 
| 42 |  |  | VARIABLE        vv[] = {                /* variable-value pairs */ | 
| 43 |  |  | {"host",        4,      0,      NULL,   NULL}, | 
| 44 |  |  | {"render",      3,      0,      NULL,   catvalues}, | 
| 45 |  |  | {"pfilt",       2,      0,      NULL,   catvalues}, | 
| 46 |  |  | {"pinterp",     2,      0,      NULL,   catvalues}, | 
| 47 |  |  | {"OCTREE",      3,      0,      NULL,   onevalue}, | 
| 48 |  |  | {"DIRECTORY",   3,      0,      NULL,   onevalue}, | 
| 49 |  |  | {"BASENAME",    3,      0,      NULL,   onevalue}, | 
| 50 |  |  | {"VIEWFILE",    2,      0,      NULL,   onevalue}, | 
| 51 |  |  | {"START",       2,      0,      NULL,   intvalue}, | 
| 52 |  |  | {"END",         2,      0,      NULL,   intvalue}, | 
| 53 |  |  | {"RIF",         3,      0,      NULL,   onevalue}, | 
| 54 |  |  | {"NEXTANIM",    3,      0,      NULL,   onevalue}, | 
| 55 |  |  | {"ANIMATE",     2,      0,      NULL,   onevalue}, | 
| 56 |  |  | {"TRANSFER",    2,      0,      NULL,   onevalue}, | 
| 57 |  |  | {"ARCHIVE",     2,      0,      NULL,   onevalue}, | 
| 58 |  |  | {"INTERP",      3,      0,      NULL,   intvalue}, | 
| 59 |  |  | {"OVERSAMP",    2,      0,      NULL,   fltvalue}, | 
| 60 |  |  | {"MBLUR",       2,      0,      NULL,   onevalue}, | 
| 61 |  |  | {"RTRACE",      2,      0,      NULL,   boolvalue}, | 
| 62 |  |  | {"DISKSPACE",   3,      0,      NULL,   fltvalue}, | 
| 63 |  |  | {"RESOLUTION",  3,      0,      NULL,   onevalue}, | 
| 64 |  |  | {"EXPOSURE",    3,      0,      NULL,   onevalue}, | 
| 65 |  |  | }; | 
| 66 |  |  |  | 
| 67 |  |  | #define SFNAME  "STATUS"                /* status file name */ | 
| 68 |  |  |  | 
| 69 |  |  | struct { | 
| 70 |  |  | char    host[64];               /* control host name */ | 
| 71 |  |  | int     pid;                    /* control process id */ | 
| 72 |  |  | char    cfname[128];            /* control file name */ | 
| 73 |  |  | int     rnext;                  /* next frame to render */ | 
| 74 |  |  | int     fnext;                  /* next frame to filter */ | 
| 75 |  |  | int     tnext;                  /* next frame to transfer */ | 
| 76 |  |  | }       astat;                  /* animation status */ | 
| 77 |  |  |  | 
| 78 |  |  | char    *progname;              /* our program name */ | 
| 79 |  |  | char    *cfname;                /* our control file name */ | 
| 80 |  |  |  | 
| 81 |  |  | int     nowarn = 0;             /* turn warnings off? */ | 
| 82 |  |  | int     silent = 0;             /* silent mode? */ | 
| 83 |  |  | int     noaction = 0;           /* take no action? */ | 
| 84 |  |  |  | 
| 85 |  |  | char    rendopt[2048] = "";     /* rendering options */ | 
| 86 |  |  | char    rresopt[32];            /* rendering resolution options */ | 
| 87 |  |  | char    fresopt[32];            /* filter resolution options */ | 
| 88 |  |  | int     pfiltalways;            /* always use pfilt? */ | 
| 89 |  |  |  | 
| 90 |  |  | VIEW    *getview(); | 
| 91 |  |  | char    *getexp(); | 
| 92 |  |  |  | 
| 93 |  |  |  | 
| 94 |  |  | main(argc, argv) | 
| 95 |  |  | int     argc; | 
| 96 |  |  | char    *argv[]; | 
| 97 |  |  | { | 
| 98 |  |  | int     explicate = 0; | 
| 99 |  |  | int     i; | 
| 100 |  |  |  | 
| 101 |  |  | progname = argv[0];                     /* get arguments */ | 
| 102 |  |  | for (i = 1; i < argc && argv[i][0] == '-'; i++) | 
| 103 |  |  | switch (argv[i][1]) { | 
| 104 |  |  | case 'e':                       /* print variables */ | 
| 105 |  |  | explicate++; | 
| 106 |  |  | break; | 
| 107 |  |  | case 'w':                       /* turn off warnings */ | 
| 108 |  |  | nowarn++; | 
| 109 |  |  | break; | 
| 110 |  |  | case 's':                       /* silent mode */ | 
| 111 |  |  | silent++; | 
| 112 |  |  | break; | 
| 113 |  |  | case 'n':                       /* take no action */ | 
| 114 |  |  | noaction++; | 
| 115 |  |  | break; | 
| 116 |  |  | default: | 
| 117 |  |  | goto userr; | 
| 118 |  |  | } | 
| 119 |  |  | if (i != argc-1) | 
| 120 |  |  | goto userr; | 
| 121 |  |  | cfname = argv[i]; | 
| 122 |  |  | /* load variables */ | 
| 123 |  |  | loadvars(cfname); | 
| 124 |  |  | /* did we get DIRECTORY? */ | 
| 125 |  |  | checkdir(); | 
| 126 |  |  | /* check status */ | 
| 127 |  |  | if (getastat() < 0) { | 
| 128 |  |  | fprintf(stderr, "%s: exiting\n", progname); | 
| 129 |  |  | quit(1); | 
| 130 |  |  | } | 
| 131 |  |  | /* pfilt always if options given */ | 
| 132 |  |  | pfiltalways = vdef(PFILT); | 
| 133 |  |  | /* load RIF if any */ | 
| 134 |  |  | if (vdef(RIF)) | 
| 135 |  |  | getradfile(vval(RIF)); | 
| 136 |  |  | /* set defaults */ | 
| 137 |  |  | setdefaults(); | 
| 138 |  |  | /* print variables */ | 
| 139 |  |  | if (explicate) | 
| 140 |  |  | printvars(stdout); | 
| 141 |  |  | /* run animation */ | 
| 142 |  |  | animate(); | 
| 143 |  |  | /* all done */ | 
| 144 |  |  | if (vdef(NEXTANIM)) { | 
| 145 |  |  | argv[i] = vval(NEXTANIM);       /* just change input file */ | 
| 146 |  |  | if (!silent) | 
| 147 |  |  | printargs(argc, argv, stdout); | 
| 148 |  |  | if (!noaction) { | 
| 149 |  |  | execvp(progname, argv);         /* pass to next */ | 
| 150 |  |  | quit(1);                        /* shouldn't return */ | 
| 151 |  |  | } | 
| 152 |  |  | } | 
| 153 |  |  | quit(0); | 
| 154 |  |  | userr: | 
| 155 |  |  | fprintf(stderr, "Usage: %s [-s][-n][-w][-e] anim_file\n", progname); | 
| 156 |  |  | quit(1); | 
| 157 |  |  | } | 
| 158 |  |  |  | 
| 159 |  |  |  | 
| 160 |  |  | getastat()                      /* check/set animation status */ | 
| 161 |  |  | { | 
| 162 |  |  | char    buf[256]; | 
| 163 |  |  | FILE    *fp; | 
| 164 |  |  |  | 
| 165 |  |  | sprintf(buf, "%s/%s", vval(DIRECTORY), SFNAME); | 
| 166 |  |  | if ((fp = fopen(buf, "r")) == NULL) { | 
| 167 |  |  | if (errno != ENOENT) { | 
| 168 |  |  | perror(buf); | 
| 169 |  |  | return(-1); | 
| 170 |  |  | } | 
| 171 |  |  | astat.rnext = astat.fnext = astat.tnext = 0; | 
| 172 |  |  | goto setours; | 
| 173 |  |  | } | 
| 174 |  |  | if (fscanf(fp, "Control host: %s\n", astat.host) != 1) | 
| 175 |  |  | goto fmterr; | 
| 176 |  |  | if (fscanf(fp, "Control PID: %d\n", &astat.pid) != 1) | 
| 177 |  |  | goto fmterr; | 
| 178 |  |  | if (fscanf(fp, "Control file: %s\n", astat.cfname) != 1) | 
| 179 |  |  | goto fmterr; | 
| 180 |  |  | if (fscanf(fp, "Next render: %d\n", &astat.rnext) != 1) | 
| 181 |  |  | goto fmterr; | 
| 182 |  |  | if (fscanf(fp, "Next filter: %d\n", &astat.fnext) != 1) | 
| 183 |  |  | goto fmterr; | 
| 184 |  |  | if (fscanf(fp, "Next transfer: %d\n", &astat.tnext) != 1) | 
| 185 |  |  | goto fmterr; | 
| 186 |  |  | fclose(fp); | 
| 187 |  |  | if (astat.pid != 0) {                   /* thinks it's still running */ | 
| 188 |  |  | gethostname(buf, sizeof(buf)); | 
| 189 |  |  | if (strcmp(buf, astat.host)) { | 
| 190 |  |  | fprintf(stderr, | 
| 191 |  |  | "%s: process %d may still be running on host %s\n", | 
| 192 |  |  | progname, astat.pid, astat.host); | 
| 193 |  |  | return(-1); | 
| 194 |  |  | } | 
| 195 |  |  | if (kill(astat.pid, 0) != -1 || errno != ESRCH) { | 
| 196 |  |  | fprintf(stderr, "%s: process %d is still running\n", | 
| 197 |  |  | progname, astat.pid); | 
| 198 |  |  | return(-1); | 
| 199 |  |  | } | 
| 200 |  |  | /* assume it is dead */ | 
| 201 |  |  | } | 
| 202 |  |  | if (strcmp(cfname, astat.cfname) && astat.tnext != 0) { /* other's */ | 
| 203 |  |  | fprintf(stderr, "%s: unfinished job \"%s\"\n", | 
| 204 |  |  | progname, astat.cfname); | 
| 205 |  |  | return(-1); | 
| 206 |  |  | } | 
| 207 |  |  | setours:                                        /* set our values */ | 
| 208 |  |  | gethostname(astat.host, sizeof(astat.host)); | 
| 209 |  |  | astat.pid = getpid(); | 
| 210 |  |  | strcpy(astat.cfname, cfname); | 
| 211 |  |  | return(0); | 
| 212 |  |  | fmterr: | 
| 213 |  |  | fprintf(stderr, "%s: format error in status file \"%s\"\n", | 
| 214 |  |  | progname, buf); | 
| 215 |  |  | fclose(fp); | 
| 216 |  |  | return(-1); | 
| 217 |  |  | } | 
| 218 |  |  |  | 
| 219 |  |  |  | 
| 220 |  |  | putastat()                      /* put out current status */ | 
| 221 |  |  | { | 
| 222 |  |  | char    buf[256]; | 
| 223 |  |  | FILE    *fp; | 
| 224 |  |  |  | 
| 225 |  |  | sprintf(buf, "%s/%s", vval(DIRECTORY), SFNAME); | 
| 226 |  |  | if ((fp = fopen(buf, "w")) == NULL) { | 
| 227 |  |  | perror(buf); | 
| 228 |  |  | quit(1); | 
| 229 |  |  | } | 
| 230 |  |  | fprintf(fp, "Control host: %s\n", astat.host); | 
| 231 |  |  | fprintf(fp, "Control PID: %d\n", astat.pid); | 
| 232 |  |  | fprintf(fp, "Control file: %s\n", astat.cfname); | 
| 233 |  |  | fprintf(fp, "Next render: %d\n", astat.rnext); | 
| 234 |  |  | fprintf(fp, "Next filter: %d\n", astat.fnext); | 
| 235 |  |  | fprintf(fp, "Next transfer: %d\n", astat.tnext); | 
| 236 |  |  | fclose(fp); | 
| 237 |  |  | } | 
| 238 |  |  |  | 
| 239 |  |  |  | 
| 240 |  |  | checkdir()                      /* make sure we have our directory */ | 
| 241 |  |  | { | 
| 242 |  |  | struct stat     stb; | 
| 243 |  |  |  | 
| 244 |  |  | if (!vdef(DIRECTORY)) { | 
| 245 |  |  | fprintf(stderr, "%s: %s undefined\n", | 
| 246 |  |  | progname, vnam(DIRECTORY)); | 
| 247 |  |  | quit(1); | 
| 248 |  |  | } | 
| 249 |  |  | if (stat(vval(DIRECTORY), &stb) == -1) { | 
| 250 |  |  | if (errno == ENOENT && mkdir(vval(DIRECTORY), 0777) == 0) | 
| 251 |  |  | return; | 
| 252 |  |  | perror(vval(DIRECTORY)); | 
| 253 |  |  | quit(1); | 
| 254 |  |  | } | 
| 255 |  |  | if (!(stb.st_mode & S_IFDIR)) { | 
| 256 |  |  | fprintf(stderr, "%s: not a directory\n", vval(DIRECTORY)); | 
| 257 |  |  | quit(1); | 
| 258 |  |  | } | 
| 259 |  |  | } | 
| 260 |  |  |  | 
| 261 |  |  |  | 
| 262 |  |  | setdefaults()                   /* set default values */ | 
| 263 |  |  | { | 
| 264 |  |  | char    buf[256]; | 
| 265 |  |  |  | 
| 266 |  |  | if (vdef(OCTREE) == vdef(ANIMATE)) { | 
| 267 |  |  | fprintf(stderr, "%s: either %s or %s must be defined\n", | 
| 268 |  |  | progname, vnam(OCTREE), vnam(ANIMATE)); | 
| 269 |  |  | quit(1); | 
| 270 |  |  | } | 
| 271 |  |  | if (!vdef(VIEWFILE)) { | 
| 272 |  |  | fprintf(stderr, "%s: %s undefined\n", progname, vnam(VIEWFILE)); | 
| 273 |  |  | quit(1); | 
| 274 |  |  | } | 
| 275 |  |  | if (!vdef(START)) { | 
| 276 |  |  | vval(START) = "1"; | 
| 277 |  |  | vdef(START)++; | 
| 278 |  |  | } | 
| 279 |  |  | if (!vdef(END)) { | 
| 280 |  |  | sprintf(buf, "%d", countviews()); | 
| 281 |  |  | vval(END) = savqstr(buf); | 
| 282 |  |  | vdef(END)++; | 
| 283 |  |  | } | 
| 284 |  |  | if (!vdef(BASENAME)) { | 
| 285 |  |  | sprintf(buf, "%s/frame%%03d", vval(DIRECTORY)); | 
| 286 |  |  | vval(BASENAME) = savqstr(buf); | 
| 287 |  |  | vdef(BASENAME)++; | 
| 288 |  |  | } | 
| 289 |  |  | if (!vdef(RESOLUTION)) { | 
| 290 |  |  | vval(RESOLUTION) = "640"; | 
| 291 |  |  | vdef(RESOLUTION)++; | 
| 292 |  |  | } | 
| 293 |  |  | if (!vdef(OVERSAMP)) { | 
| 294 |  |  | vval(OVERSAMP) = "2"; | 
| 295 |  |  | vdef(OVERSAMP)++; | 
| 296 |  |  | } | 
| 297 |  |  | if (!vdef(INTERP)) { | 
| 298 |  |  | vval(INTERP) = "0"; | 
| 299 |  |  | vdef(INTERP)++; | 
| 300 |  |  | } | 
| 301 |  |  | if (!vdef(MBLUR)) { | 
| 302 |  |  | vval(MBLUR) = "0"; | 
| 303 |  |  | vdef(MBLUR)++; | 
| 304 |  |  | } | 
| 305 |  |  | if (!vdef(RTRACE)) { | 
| 306 |  |  | vval(RTRACE) = "F"; | 
| 307 |  |  | vdef(RTRACE)++; | 
| 308 |  |  | } | 
| 309 |  |  | if (!vdef(DISKSPACE)) { | 
| 310 |  |  | if (!nowarn) | 
| 311 |  |  | fprintf(stderr, | 
| 312 |  |  | "%s: warning - no %s setting, assuming 100 Mbytes available\n", | 
| 313 |  |  | progname, vnam(DISKSPACE)); | 
| 314 |  |  | vval(DISKSPACE) = "100"; | 
| 315 |  |  | vdef(DISKSPACE)++; | 
| 316 |  |  | } | 
| 317 |  |  | /* append rendering options */ | 
| 318 |  |  | if (vdef(RENDER)) | 
| 319 |  |  | sprintf(rendopt+strlen(rendopt), " %s", vval(RENDER)); | 
| 320 |  |  | } | 
| 321 |  |  |  | 
| 322 |  |  |  | 
| 323 |  |  | getradfile(rfname)              /* run rad and get needed variables */ | 
| 324 |  |  | char    *rfname; | 
| 325 |  |  | { | 
| 326 |  |  | static short    mvar[] = {OCTREE,PFILT,RESOLUTION,EXPOSURE,-1}; | 
| 327 |  |  | char    combuf[256]; | 
| 328 |  |  | register int    i; | 
| 329 |  |  | register char   *cp; | 
| 330 |  |  | /* create rad command */ | 
| 331 |  |  | sprintf(rendopt, " @%s/render.opt", vval(DIRECTORY)); | 
| 332 |  |  | sprintf(combuf, | 
| 333 |  |  | "rad -v 0 -s -e -w %s OPTFILE=%s | egrep '^[ \t]*(NOMATCH", | 
| 334 |  |  | rfname, rendopt+2); | 
| 335 |  |  | cp = combuf; | 
| 336 |  |  | while (*cp) cp++;               /* match unset variables */ | 
| 337 |  |  | for (i = 0; mvar[i] >= 0; i++) | 
| 338 |  |  | if (!vdef(mvar[i])) { | 
| 339 |  |  | *cp++ = '|'; | 
| 340 |  |  | strcpy(cp, vnam(mvar[i])); | 
| 341 |  |  | while (*cp) cp++; | 
| 342 |  |  | } | 
| 343 |  |  | sprintf(cp, ")[ \t]*=' > %s/radset.var", vval(DIRECTORY)); | 
| 344 |  |  | cp += 11;                       /* point to file name */ | 
| 345 |  |  | if (system(combuf)) { | 
| 346 |  |  | fprintf(stderr, "%s: bad rad input file \"%s\"\n", | 
| 347 |  |  | progname, rfname); | 
| 348 |  |  | quit(1); | 
| 349 |  |  | } | 
| 350 |  |  | loadvars(cp);                   /* load variables and remove file */ | 
| 351 |  |  | unlink(cp); | 
| 352 |  |  | } | 
| 353 |  |  |  | 
| 354 |  |  |  | 
| 355 |  |  | animate()                       /* run animation */ | 
| 356 |  |  | { | 
| 357 |  |  | int     xres, yres; | 
| 358 |  |  | float   pa, mult; | 
| 359 |  |  | int     frames_batch; | 
| 360 |  |  | register int    i; | 
| 361 |  |  | double  d1, d2; | 
| 362 |  |  | /* compute rpict resolution */ | 
| 363 |  |  | i = sscanf(vval(RESOLUTION), "%d %d %f", &xres, &yres, &pa); | 
| 364 |  |  | mult = vflt(OVERSAMP); | 
| 365 |  |  | if (i == 3) { | 
| 366 |  |  | sprintf(rresopt, "-x %d -y %d -pa %f", (int)(mult*xres), | 
| 367 |  |  | (int)(mult*yres), pa); | 
| 368 |  |  | sprintf(fresopt, "-x %d -y %d -pa %f", xres, yres, pa); | 
| 369 |  |  | } else if (i) { | 
| 370 |  |  | if (i == 1) yres = xres; | 
| 371 |  |  | sprintf(rresopt, "-x %d -y %d", (int)(mult*xres), | 
| 372 |  |  | (int)(mult*yres)); | 
| 373 |  |  | sprintf(fresopt, "-x %d -y %d -pa 1", xres, yres); | 
| 374 |  |  | } else | 
| 375 |  |  | badvalue(RESOLUTION); | 
| 376 |  |  | /* consistency checks */ | 
| 377 |  |  | if (vdef(ANIMATE)) { | 
| 378 |  |  | if (vint(INTERP)) { | 
| 379 |  |  | if (!nowarn) | 
| 380 |  |  | fprintf(stderr, | 
| 381 |  |  | "%s: resetting %s=0 for animation\n", | 
| 382 |  |  | progname, vnam(INTERP)); | 
| 383 |  |  | vval(INTERP) = "0"; | 
| 384 |  |  | } | 
| 385 |  |  | if (atoi(vval(MBLUR))) {        /* can't handle this yet */ | 
| 386 |  |  | if (!nowarn) | 
| 387 |  |  | fprintf(stderr, | 
| 388 |  |  | "%s: resetting %s=0 for animation\n", | 
| 389 |  |  | progname, vnam(MBLUR)); | 
| 390 |  |  | vval(MBLUR) = "0"; | 
| 391 |  |  | } | 
| 392 |  |  | } | 
| 393 |  |  | /* figure # frames per batch */ | 
| 394 |  |  | d1 = mult*xres*mult*yres*4;             /* space for orig. picture */ | 
| 395 |  |  | if ((i=vint(INTERP)) || atoi(vval(MBLUR))) | 
| 396 |  |  | d1 += mult*xres*mult*yres*4;    /* space for z-buffer */ | 
| 397 |  |  | d2 = xres*yres*4;                       /* space for final picture */ | 
| 398 |  |  | frames_batch = (i+1)*(vflt(DISKSPACE)*1048576.-d1)/(d1+i*d2); | 
| 399 |  |  | if (frames_batch < i+2) { | 
| 400 |  |  | fprintf(stderr, "%s: insufficient disk space allocated\n", | 
| 401 |  |  | progname); | 
| 402 |  |  | quit(1); | 
| 403 |  |  | } | 
| 404 |  |  | /* initialize status file */ | 
| 405 |  |  | if (astat.rnext == 0) | 
| 406 |  |  | astat.rnext = astat.fnext = astat.tnext = vint(START); | 
| 407 |  |  | putastat(); | 
| 408 |  |  | /* render in batches */ | 
| 409 |  |  | while (astat.rnext <= vint(END)) { | 
| 410 |  |  | renderframes(frames_batch); | 
| 411 |  |  | filterframes(); | 
| 412 |  |  | transferframes(); | 
| 413 |  |  | } | 
| 414 |  |  | /* mark status as finished */ | 
| 415 |  |  | astat.pid = 0; | 
| 416 |  |  | putastat(); | 
| 417 |  |  | /* close open files */ | 
| 418 |  |  | getview(0); | 
| 419 |  |  | getexp(0); | 
| 420 |  |  | } | 
| 421 |  |  |  | 
| 422 |  |  |  | 
| 423 |  |  | renderframes(nframes)           /* render next nframes frames */ | 
| 424 |  |  | int     nframes; | 
| 425 |  |  | { | 
| 426 |  |  | static char     vendbuf[16]; | 
| 427 |  |  | VIEW    *vp; | 
| 428 |  |  | FILE    *fp = NULL; | 
| 429 |  |  | char    vfname[128]; | 
| 430 |  |  | int     lastframe; | 
| 431 |  |  | register int    i; | 
| 432 |  |  |  | 
| 433 |  |  | if (astat.tnext < astat.rnext)  /* other work to do first */ | 
| 434 |  |  | return; | 
| 435 |  |  | /* create batch view file */ | 
| 436 |  |  | if (!vdef(ANIMATE)) { | 
| 437 |  |  | sprintf(vfname, "%s/anim.vf", vval(DIRECTORY)); | 
| 438 |  |  | if ((fp = fopen(vfname, "w")) == NULL) { | 
| 439 |  |  | perror(vfname); | 
| 440 |  |  | quit(1); | 
| 441 |  |  | } | 
| 442 |  |  | } | 
| 443 |  |  | /* bound batch properly */ | 
| 444 |  |  | lastframe = astat.rnext + nframes - 1; | 
| 445 |  |  | if ((lastframe-1) % (vint(INTERP)+1))   /* need even interval */ | 
| 446 |  |  | lastframe += vint(INTERP)+1 - ((lastframe-1)%(vint(INTERP)+1)); | 
| 447 |  |  | if (lastframe > vint(END))              /* check for end */ | 
| 448 |  |  | lastframe = vint(END); | 
| 449 |  |  | /* render each view */ | 
| 450 |  |  | for (i = astat.rnext; i <= lastframe; i++) { | 
| 451 |  |  | if ((vp = getview(i)) == NULL) { | 
| 452 |  |  | if (!nowarn) | 
| 453 |  |  | fprintf(stderr, | 
| 454 |  |  | "%s: ran out of views before last frame\n", | 
| 455 |  |  | progname); | 
| 456 |  |  | sprintf(vval(END)=vendbuf, "%d", i-1); | 
| 457 |  |  | lastframe = i - 1; | 
| 458 |  |  | break; | 
| 459 |  |  | } | 
| 460 |  |  | if (vdef(ANIMATE))              /* animate frame */ | 
| 461 |  |  | animrend(i, vp); | 
| 462 |  |  | else {                          /* else record it */ | 
| 463 |  |  | fputs(VIEWSTR, fp); | 
| 464 |  |  | fprintview(vp, fp); | 
| 465 |  |  | putc('\n', fp); | 
| 466 |  |  | } | 
| 467 |  |  | } | 
| 468 |  |  | if (vdef(ANIMATE))              /* wait for renderings to finish */ | 
| 469 |  |  | animwait(0); | 
| 470 |  |  | else {                          /* else if walk-through */ | 
| 471 |  |  | fclose(fp);             /* close view file */ | 
| 472 |  |  | walkwait(astat.rnext, lastframe, vfname);       /* walk it */ | 
| 473 |  |  | unlink(vfname);         /* remove view file */ | 
| 474 |  |  | } | 
| 475 |  |  | if (vdef(ARCHIVE))              /* archive results */ | 
| 476 |  |  | archive(astat.rnext, lastframe); | 
| 477 |  |  | astat.rnext = i;                /* update status */ | 
| 478 |  |  | putastat(); | 
| 479 |  |  | } | 
| 480 |  |  |  | 
| 481 |  |  |  | 
| 482 |  |  | filterframes()                          /* catch up with filtering */ | 
| 483 |  |  | { | 
| 484 |  |  | VIEW    *vp; | 
| 485 |  |  | register int    i; | 
| 486 |  |  |  | 
| 487 |  |  | if (astat.tnext < astat.fnext)  /* other work to do first */ | 
| 488 |  |  | return; | 
| 489 |  |  | /* filter each view */ | 
| 490 |  |  | for (i = astat.fnext; i < astat.rnext; i++) { | 
| 491 |  |  | if ((vp = getview(i)) == NULL) {        /* get view i */ | 
| 492 |  |  | fprintf(stderr, | 
| 493 |  |  | "%s: unexpected error reading view for frame %d\n", | 
| 494 |  |  | progname, i); | 
| 495 |  |  | quit(1); | 
| 496 |  |  | } | 
| 497 |  |  | dofilt(i, vp, getexp(i));               /* filter frame */ | 
| 498 |  |  | } | 
| 499 |  |  | filtwait(0);                    /* wait for filter processes */ | 
| 500 |  |  | astat.fnext = i;                /* update status */ | 
| 501 |  |  | putastat(); | 
| 502 |  |  | } | 
| 503 |  |  |  | 
| 504 |  |  |  | 
| 505 |  |  | transferframes()                        /* catch up with picture transfers */ | 
| 506 |  |  | { | 
| 507 |  |  | char    combuf[10240]; | 
| 508 |  |  | register char   *cp; | 
| 509 |  |  | register int    i; | 
| 510 |  |  |  | 
| 511 |  |  | if (astat.tnext >= astat.fnext) /* nothing to do, yet */ | 
| 512 |  |  | return; | 
| 513 |  |  | if (!vdef(TRANSFER)) {          /* no transfer function -- leave 'em */ | 
| 514 |  |  | astat.tnext = astat.fnext; | 
| 515 |  |  | putastat();             /* update status */ | 
| 516 |  |  | return; | 
| 517 |  |  | } | 
| 518 |  |  | strcpy(combuf, vval(TRANSFER)); /* start transfer command */ | 
| 519 |  |  | cp = combuf + strlen(combuf); | 
| 520 |  |  | /* make argument list */ | 
| 521 |  |  | for (i = astat.tnext; i < astat.fnext; i++) { | 
| 522 |  |  | *cp++ = ' '; | 
| 523 |  |  | sprintf(cp, vval(BASENAME), i); | 
| 524 |  |  | while (*cp) cp++; | 
| 525 |  |  | strcpy(cp, ".pic"); | 
| 526 |  |  | cp += 4; | 
| 527 |  |  | } | 
| 528 |  |  | if (runcom(combuf)) {           /* transfer frames */ | 
| 529 |  |  | fprintf(stderr, "%s: error running transfer command\n", | 
| 530 |  |  | progname); | 
| 531 |  |  | quit(1); | 
| 532 |  |  | } | 
| 533 |  |  | astat.tnext = i;                /* update status */ | 
| 534 |  |  | putastat(); | 
| 535 |  |  | } | 
| 536 |  |  |  | 
| 537 |  |  |  | 
| 538 |  |  | animrend(frame, vp)                     /* start animation frame */ | 
| 539 |  |  | int     frame; | 
| 540 |  |  | VIEW    *vp; | 
| 541 |  |  | { | 
| 542 |  |  | char    combuf[2048]; | 
| 543 |  |  | char    fname[128]; | 
| 544 |  |  |  | 
| 545 |  |  | sprintf(fname, vval(BASENAME), frame); | 
| 546 |  |  | strcat(fname, ".unf"); | 
| 547 |  |  | if (access(fname, F_OK) == 0) | 
| 548 |  |  | return; | 
| 549 |  |  | sprintf(combuf, "%s %d | rpict%s%s %s > %s", vval(ANIMATE), frame, | 
| 550 |  |  | rendopt, viewopt(vp), rresopt, fname); | 
| 551 |  |  | if (runcom(combuf)) { | 
| 552 |  |  | fprintf(stderr, "%s: error rendering frame %d\n", | 
| 553 |  |  | progname, frame); | 
| 554 |  |  | quit(1); | 
| 555 |  |  | } | 
| 556 |  |  | } | 
| 557 |  |  |  | 
| 558 |  |  |  | 
| 559 |  |  | animwait(nwait)                         /* wait for renderings to finish */ | 
| 560 |  |  | int     nwait; | 
| 561 |  |  | { | 
| 562 |  |  | /* currently does nothing since parallel rendering not working */ | 
| 563 |  |  | } | 
| 564 |  |  |  | 
| 565 |  |  |  | 
| 566 |  |  | walkwait(first, last, vfn)              /* walk-through frames */ | 
| 567 |  |  | int     first, last; | 
| 568 |  |  | char    *vfn; | 
| 569 |  |  | { | 
| 570 |  |  | char    combuf[2048]; | 
| 571 |  |  | register int    i; | 
| 572 |  |  |  | 
| 573 |  |  | if (!noaction && vint(INTERP))          /* create dummy frames */ | 
| 574 |  |  | for (i = first; i <= last; i++) | 
| 575 |  |  | if (i < vint(END) && (i-1) % (vint(INTERP)+1)) { | 
| 576 |  |  | sprintf(combuf, vval(BASENAME), i); | 
| 577 |  |  | strcat(combuf, ".unf"); | 
| 578 |  |  | close(open(combuf, O_RDONLY|O_CREAT, 0666)); | 
| 579 |  |  | } | 
| 580 |  |  | /* create command */ | 
| 581 |  |  | sprintf(combuf, "rpict%s ", rendopt); | 
| 582 |  |  | if (vint(INTERP) || atoi(vval(MBLUR))) | 
| 583 |  |  | sprintf(combuf+strlen(combuf), "-z %s.zbf ", vval(BASENAME)); | 
| 584 |  |  | sprintf(combuf+strlen(combuf), "-o %s.unf %s -S %d %s < %s", | 
| 585 |  |  | vval(BASENAME), rresopt, first, vval(OCTREE), vfn); | 
| 586 |  |  | if (runcom(combuf)) { | 
| 587 |  |  | fprintf(stderr, | 
| 588 |  |  | "%s: error rendering walk-through frames %d through %d\n", | 
| 589 |  |  | progname, first, last); | 
| 590 |  |  | quit(1); | 
| 591 |  |  | } | 
| 592 |  |  | if (!noaction && vint(INTERP))          /* remove dummy frames */ | 
| 593 |  |  | for (i = first; i <= last; i++) | 
| 594 |  |  | if (i < vint(END) && (i-1) % (vint(INTERP)+1)) { | 
| 595 |  |  | sprintf(combuf, vval(BASENAME), i); | 
| 596 |  |  | strcat(combuf, ".unf"); | 
| 597 |  |  | unlink(combuf); | 
| 598 |  |  | } | 
| 599 |  |  | } | 
| 600 |  |  |  | 
| 601 |  |  |  | 
| 602 |  |  | recover(frame)                          /* recover the specified frame */ | 
| 603 |  |  | int     frame; | 
| 604 |  |  | { | 
| 605 |  |  | char    combuf[2048]; | 
| 606 |  |  | char    fname[128]; | 
| 607 |  |  | register char   *cp; | 
| 608 |  |  |  | 
| 609 |  |  | sprintf(fname, vval(BASENAME), frame); | 
| 610 |  |  | if (vdef(ANIMATE)) | 
| 611 |  |  | sprintf(combuf, "%s %d | rpict%s", | 
| 612 |  |  | vval(ANIMATE), frame, rendopt); | 
| 613 |  |  | else | 
| 614 |  |  | sprintf(combuf, "rpict%s", rendopt); | 
| 615 |  |  | cp = combuf + strlen(combuf); | 
| 616 |  |  | if (vint(INTERP) || atoi(vval(MBLUR))) { | 
| 617 |  |  | sprintf(cp, " -z %s.zbf", fname); | 
| 618 |  |  | while (*cp) cp++; | 
| 619 |  |  | } | 
| 620 |  |  | sprintf(cp, " -ro %s.unf", fname); | 
| 621 |  |  | while (*cp) cp++; | 
| 622 |  |  | if (!vdef(ANIMATE)) { | 
| 623 |  |  | *cp++ = ' '; | 
| 624 |  |  | strcpy(cp, vval(OCTREE)); | 
| 625 |  |  | } | 
| 626 |  |  | if (runcom(combuf)) { | 
| 627 |  |  | fprintf(stderr, "%s: error recovering frame %d\n", | 
| 628 |  |  | progname, frame); | 
| 629 |  |  | quit(1); | 
| 630 |  |  | } | 
| 631 |  |  | } | 
| 632 |  |  |  | 
| 633 |  |  |  | 
| 634 |  |  | archive(first, last)                    /* archive finished renderings */ | 
| 635 |  |  | int     first, last; | 
| 636 |  |  | { | 
| 637 |  |  | char    combuf[10240]; | 
| 638 |  |  | int     offset; | 
| 639 |  |  | struct stat     stb; | 
| 640 |  |  | register char   *cp; | 
| 641 |  |  | register int    i; | 
| 642 |  |  |  | 
| 643 |  |  | strcpy(cp=combuf, vval(ARCHIVE)); | 
| 644 |  |  | while (*cp) cp++; | 
| 645 |  |  | offset = cp - combuf; | 
| 646 |  |  | *cp++ = ' ';                            /* make argument list */ | 
| 647 |  |  | for (i = first; i <= last; i++) { | 
| 648 |  |  | sprintf(cp, vval(BASENAME), i); | 
| 649 |  |  | strcat(cp, ".unf"); | 
| 650 |  |  | if (stat(cp, &stb) == 0 && stb.st_size > 0) {   /* non-zero? */ | 
| 651 |  |  | while (*cp) cp++; | 
| 652 |  |  | *cp++ = ' '; | 
| 653 |  |  | sprintf(cp, vval(BASENAME), i); | 
| 654 |  |  | strcat(cp, ".zbf"); | 
| 655 |  |  | if (access(cp, F_OK) == 0) {            /* exists? */ | 
| 656 |  |  | while (*cp) cp++; | 
| 657 |  |  | *cp++ = ' '; | 
| 658 |  |  | } | 
| 659 |  |  | } | 
| 660 |  |  | } | 
| 661 |  |  | *--cp = '\0'; | 
| 662 |  |  | if (cp <= combuf + offset)              /* no files? */ | 
| 663 |  |  | return; | 
| 664 |  |  | if (runcom(combuf)) {                   /* run archive command */ | 
| 665 |  |  | fprintf(stderr, | 
| 666 |  |  | "%s: error running archive command on frames %d through %d\n", | 
| 667 |  |  | progname, first, last); | 
| 668 |  |  | quit(1); | 
| 669 |  |  | } | 
| 670 |  |  | } | 
| 671 |  |  |  | 
| 672 |  |  |  | 
| 673 |  |  | dofilt(frame, vp, ep)                           /* filter frame */ | 
| 674 |  |  | int     frame; | 
| 675 |  |  | VIEW    *vp; | 
| 676 |  |  | char    *ep; | 
| 677 |  |  | { | 
| 678 |  |  | char    fnbefore[128], fnafter[128]; | 
| 679 |  |  | char    combuf[1024], fname[128]; | 
| 680 |  |  | int     usepinterp, usepfilt; | 
| 681 |  |  | int     frbefore, frafter, triesleft; | 
| 682 |  |  | /* check what is needed */ | 
| 683 |  |  | usepinterp = atoi(vval(MBLUR)); | 
| 684 |  |  | usepfilt = pfiltalways | ep==NULL; | 
| 685 |  |  | /* compute rendered views */ | 
| 686 |  |  | frbefore = frame - ((frame-1) % (vint(INTERP)+1)); | 
| 687 |  |  | frafter = frbefore + vint(INTERP) + 1; | 
| 688 |  |  | if (frafter > vint(END)) | 
| 689 |  |  | frafter = vint(END); | 
| 690 |  |  | if (frafter == frame) {                 /* pfilt only */ | 
| 691 |  |  | frbefore = frafter; | 
| 692 |  |  | usepinterp = 0;                 /* update what's needed */ | 
| 693 |  |  | usepfilt |= vflt(OVERSAMP)>1.01 || strcmp(ep,"1"); | 
| 694 |  |  | triesleft = 2; | 
| 695 |  |  | } else if (frbefore == frame) {         /* no interpolation */ | 
| 696 |  |  | /* remove unneeded files */ | 
| 697 |  |  | if (frbefore-vint(INTERP)-1 >= 1) { | 
| 698 |  |  | sprintf(fname, vval(BASENAME), frbefore-vint(INTERP)-1); | 
| 699 |  |  | sprintf(combuf, "rm -f %s.unf %s.zbf", fname, fname); | 
| 700 |  |  | runcom(combuf); | 
| 701 |  |  | } | 
| 702 |  |  | /* update what's needed */ | 
| 703 |  |  | if (usepinterp) | 
| 704 |  |  | triesleft = 3; | 
| 705 |  |  | else { | 
| 706 |  |  | usepfilt |= vflt(OVERSAMP)>1.01 || strcmp(ep,"1"); | 
| 707 |  |  | triesleft = 2; | 
| 708 |  |  | } | 
| 709 |  |  | } else {                                /* interpolation needed */ | 
| 710 |  |  | usepinterp++; | 
| 711 |  |  | triesleft = 3; | 
| 712 |  |  | } | 
| 713 |  |  | if (frafter >= astat.rnext) {           /* next batch unavailable */ | 
| 714 |  |  | frafter = frbefore; | 
| 715 |  |  | if (triesleft > 2) | 
| 716 |  |  | triesleft = 2; | 
| 717 |  |  | } | 
| 718 |  |  | sprintf(fnbefore, vval(BASENAME), frbefore); | 
| 719 |  |  | sprintf(fnafter, vval(BASENAME), frafter); | 
| 720 |  |  | tryit:                                          /* generate command */ | 
| 721 |  |  | if (usepinterp) {                       /* using pinterp */ | 
| 722 |  |  | if (atoi(vval(MBLUR))) { | 
| 723 |  |  | FILE    *fp;            /* motion blurring */ | 
| 724 |  |  | sprintf(fname, "%s/vw0", vval(DIRECTORY)); | 
| 725 |  |  | if ((fp = fopen(fname, "w")) == NULL) { | 
| 726 |  |  | perror(fname); quit(1); | 
| 727 |  |  | } | 
| 728 |  |  | fputs(VIEWSTR, fp); | 
| 729 |  |  | fprintview(vp, fp); | 
| 730 |  |  | putc('\n', fp); fclose(fp); | 
| 731 |  |  | if ((vp = getview(frame+1)) == NULL) { | 
| 732 |  |  | fprintf(stderr, | 
| 733 |  |  | "%s: unexpected error reading view for frame %d\n", | 
| 734 |  |  | progname, frame+1); | 
| 735 |  |  | quit(1); | 
| 736 |  |  | } | 
| 737 |  |  | sprintf(fname, "%s/vw1", vval(DIRECTORY)); | 
| 738 |  |  | if ((fp = fopen(fname, "w")) == NULL) { | 
| 739 |  |  | perror(fname); quit(1); | 
| 740 |  |  | } | 
| 741 |  |  | fputs(VIEWSTR, fp); | 
| 742 |  |  | fprintview(vp, fp); | 
| 743 |  |  | putc('\n', fp); fclose(fp); | 
| 744 |  |  | sprintf(combuf, | 
| 745 |  |  | "(pmblur %s %d %s/vw0 %s/vw1; rm -f %s/vw0 %s/vw1) | pinterp -B", | 
| 746 |  |  | *sskip(vval(MBLUR)) ? sskip(vval(MBLUR)) : "1", | 
| 747 |  |  | atoi(vval(MBLUR)), vval(DIRECTORY), | 
| 748 |  |  | vval(DIRECTORY), vval(DIRECTORY), | 
| 749 |  |  | vval(DIRECTORY), vval(DIRECTORY)); | 
| 750 |  |  | } else                          /* no blurring */ | 
| 751 |  |  | strcpy(combuf, "pinterp"); | 
| 752 |  |  | strcat(combuf, viewopt(vp)); | 
| 753 |  |  | if (vbool(RTRACE)) | 
| 754 |  |  | sprintf(combuf+strlen(combuf), " -ff -fr '%s %s'", | 
| 755 |  |  | rendopt, vval(OCTREE)); | 
| 756 |  |  | if (vdef(PINTERP)) | 
| 757 |  |  | sprintf(combuf+strlen(combuf), " %s", vval(PINTERP)); | 
| 758 |  |  | if (usepfilt) | 
| 759 |  |  | sprintf(combuf+strlen(combuf), " %s", rresopt); | 
| 760 |  |  | else | 
| 761 |  |  | sprintf(combuf+strlen(combuf), " %s -e %s", | 
| 762 |  |  | fresopt, ep); | 
| 763 |  |  | sprintf(combuf+strlen(combuf), " %s.unf %s.zbf", | 
| 764 |  |  | fnbefore, fnbefore); | 
| 765 |  |  | if (frafter != frbefore) | 
| 766 |  |  | sprintf(combuf+strlen(combuf), " %s.unf %s.zbf", | 
| 767 |  |  | fnafter, fnafter); | 
| 768 |  |  | if (usepfilt) {                 /* also pfilt */ | 
| 769 |  |  | if (vdef(PFILT)) | 
| 770 |  |  | sprintf(combuf+strlen(combuf), " | pfilt %s", | 
| 771 |  |  | vval(PFILT)); | 
| 772 |  |  | else | 
| 773 |  |  | strcat(combuf, " | pfilt"); | 
| 774 |  |  | if (ep != NULL) | 
| 775 |  |  | sprintf(combuf+strlen(combuf), " -1 -e %s %s", | 
| 776 |  |  | ep, fresopt); | 
| 777 |  |  | else | 
| 778 |  |  | sprintf(combuf+strlen(combuf), " %s", fresopt); | 
| 779 |  |  | } | 
| 780 |  |  | } else if (usepfilt) {                  /* pfilt only */ | 
| 781 |  |  | if (vdef(PFILT)) | 
| 782 |  |  | sprintf(combuf, "pfilt %s", vval(PFILT)); | 
| 783 |  |  | else | 
| 784 |  |  | strcpy(combuf, "pfilt"); | 
| 785 |  |  | if (ep != NULL) | 
| 786 |  |  | sprintf(combuf+strlen(combuf), " -1 -e %s %s %s.unf", | 
| 787 |  |  | ep, fresopt, fnbefore); | 
| 788 |  |  | else | 
| 789 |  |  | sprintf(combuf+strlen(combuf), " %s %s.unf", | 
| 790 |  |  | fresopt, fnbefore); | 
| 791 |  |  | } else {                                /* else just check it */ | 
| 792 |  |  | sprintf(combuf, "ra_rgbe -r %s.unf", fnbefore); | 
| 793 |  |  | } | 
| 794 |  |  | /* output file name */ | 
| 795 |  |  | sprintf(fname, vval(BASENAME), frame); | 
| 796 |  |  | sprintf(combuf+strlen(combuf), " > %s.pic", fname); | 
| 797 |  |  | if (runcom(combuf))                     /* run filter command */ | 
| 798 |  |  | switch (--triesleft) { | 
| 799 |  |  | case 2:                         /* try to recover frafter */ | 
| 800 |  |  | recover(frafter); | 
| 801 |  |  | goto tryit; | 
| 802 |  |  | case 1:                         /* try to recover frbefore */ | 
| 803 |  |  | recover(frbefore); | 
| 804 |  |  | goto tryit; | 
| 805 |  |  | default:                        /* we've really failed */ | 
| 806 |  |  | fprintf(stderr, | 
| 807 |  |  | "%s: unrecoverable filtering error on frame %d\n", | 
| 808 |  |  | progname, frame); | 
| 809 |  |  | quit(1); | 
| 810 |  |  | } | 
| 811 |  |  | } | 
| 812 |  |  |  | 
| 813 |  |  |  | 
| 814 |  |  | filtwait(nwait)                 /* wait for filtering processes to finish */ | 
| 815 |  |  | int     nwait; | 
| 816 |  |  | { | 
| 817 |  |  | /* currently does nothing since parallel filtering not working */ | 
| 818 |  |  | } | 
| 819 |  |  |  | 
| 820 |  |  |  | 
| 821 |  |  | VIEW * | 
| 822 |  |  | getview(n)                      /* get view number n */ | 
| 823 |  |  | int     n; | 
| 824 |  |  | { | 
| 825 |  |  | static FILE     *viewfp = NULL;         /* view file pointer */ | 
| 826 |  |  | static int      viewnum = 0;            /* current view number */ | 
| 827 |  |  | static VIEW     curview = STDVIEW;      /* current view */ | 
| 828 |  |  | char    linebuf[256]; | 
| 829 |  |  |  | 
| 830 |  |  | if (n == 0) {                   /* signal to close file and clean up */ | 
| 831 |  |  | if (viewfp != NULL) { | 
| 832 |  |  | fclose(viewfp); | 
| 833 |  |  | viewfp = NULL; | 
| 834 |  |  | viewnum = 0; | 
| 835 |  |  | copystruct(&curview, &stdview); | 
| 836 |  |  | } | 
| 837 |  |  | return(NULL); | 
| 838 |  |  | } | 
| 839 |  |  | if (viewfp == NULL) {           /* open file */ | 
| 840 |  |  | if ((viewfp = fopen(vval(VIEWFILE), "r")) == NULL) { | 
| 841 |  |  | perror(vval(VIEWFILE)); | 
| 842 |  |  | quit(1); | 
| 843 |  |  | } | 
| 844 |  |  | } else if (n < viewnum) {       /* rewind file */ | 
| 845 |  |  | if (fseek(viewfp, 0L, 0) == EOF) { | 
| 846 |  |  | perror(vval(VIEWFILE)); | 
| 847 |  |  | quit(1); | 
| 848 |  |  | } | 
| 849 |  |  | copystruct(&curview, &stdview); | 
| 850 |  |  | viewnum = 0; | 
| 851 |  |  | } | 
| 852 |  |  | while (n > viewnum) {           /* scan to desired view */ | 
| 853 |  |  | if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL) | 
| 854 |  |  | return(NULL); | 
| 855 |  |  | if (isview(linebuf) && sscanview(&curview, linebuf) > 0) | 
| 856 |  |  | viewnum++; | 
| 857 |  |  | } | 
| 858 |  |  | return(&curview);               /* return it */ | 
| 859 |  |  | } | 
| 860 |  |  |  | 
| 861 |  |  |  | 
| 862 |  |  | int | 
| 863 |  |  | countviews()                    /* count views in view file */ | 
| 864 |  |  | { | 
| 865 |  |  | register int    n = 0; | 
| 866 |  |  |  | 
| 867 |  |  | while (getview(n+1) != NULL) | 
| 868 |  |  | n++; | 
| 869 |  |  | return(n); | 
| 870 |  |  | } | 
| 871 |  |  |  | 
| 872 |  |  |  | 
| 873 |  |  | char * | 
| 874 |  |  | getexp(n)                       /* get exposure for nth frame */ | 
| 875 |  |  | int     n; | 
| 876 |  |  | { | 
| 877 |  |  | extern char     *fskip(); | 
| 878 |  |  | static char     expval[32]; | 
| 879 |  |  | static FILE     *expfp = NULL; | 
| 880 |  |  | static long     *exppos; | 
| 881 |  |  | static int      curfrm; | 
| 882 |  |  | register char   *cp; | 
| 883 |  |  |  | 
| 884 |  |  | if (n == 0) {                           /* signal to close file */ | 
| 885 |  |  | if (expfp != NULL) { | 
| 886 |  |  | fclose(expfp); | 
| 887 |  |  | expfp = NULL; | 
| 888 |  |  | } | 
| 889 |  |  | return(NULL); | 
| 890 |  |  | } | 
| 891 |  |  | if (!vdef(EXPOSURE))                    /* no setting (auto) */ | 
| 892 |  |  | return(NULL); | 
| 893 |  |  | if (isflt(vval(EXPOSURE)))              /* always the same */ | 
| 894 |  |  | return(vval(EXPOSURE)); | 
| 895 |  |  | if (expfp == NULL) {                    /* open exposure file */ | 
| 896 |  |  | if ((expfp = fopen(vval(EXPOSURE), "r")) == NULL) { | 
| 897 |  |  | fprintf(stderr, | 
| 898 |  |  | "%s: cannot open exposure file \"%s\"\n", | 
| 899 |  |  | progname, vval(EXPOSURE)); | 
| 900 |  |  | quit(1); | 
| 901 |  |  | } | 
| 902 |  |  | curfrm = vint(END) + 1;         /* init lookup tab. */ | 
| 903 |  |  | exppos = (long *)malloc(curfrm*sizeof(long *)); | 
| 904 |  |  | if (exppos == NULL) { | 
| 905 |  |  | perror(progname); | 
| 906 |  |  | quit(1); | 
| 907 |  |  | } | 
| 908 |  |  | while (curfrm--) | 
| 909 |  |  | exppos[curfrm] = -1L; | 
| 910 |  |  | curfrm = 0; | 
| 911 |  |  | } | 
| 912 |  |  | /* find position in file */ | 
| 913 |  |  | if (n-1 != curfrm && n != curfrm && exppos[n-1] >= 0 && | 
| 914 |  |  | fseek(expfp, exppos[curfrm=n-1], 0) == EOF) { | 
| 915 |  |  | fprintf(stderr, "%s: seek error on exposure file\n", progname); | 
| 916 |  |  | quit(1); | 
| 917 |  |  | } | 
| 918 |  |  | while (n > curfrm) {                    /* read exposure */ | 
| 919 |  |  | if (exppos[curfrm] < 0) | 
| 920 |  |  | exppos[curfrm] = ftell(expfp); | 
| 921 |  |  | if (fgets(expval, sizeof(expval), expfp) == NULL) { | 
| 922 |  |  | fprintf(stderr, "%s: too few exposures\n", | 
| 923 |  |  | vval(EXPOSURE)); | 
| 924 |  |  | quit(1); | 
| 925 |  |  | } | 
| 926 |  |  | curfrm++; | 
| 927 |  |  | cp = fskip(expval);                     /* check format */ | 
| 928 |  |  | if (cp == NULL || *cp != '\n') { | 
| 929 |  |  | fprintf(stderr, | 
| 930 |  |  | "%s: exposure format error on line %d\n", | 
| 931 |  |  | vval(EXPOSURE), curfrm); | 
| 932 |  |  | quit(1); | 
| 933 |  |  | } | 
| 934 |  |  | *cp = '\0'; | 
| 935 |  |  | } | 
| 936 |  |  | return(expval);                         /* return value */ | 
| 937 |  |  | } | 
| 938 |  |  |  | 
| 939 |  |  |  | 
| 940 |  |  | runcom(cs)                      /* run command */ | 
| 941 |  |  | char    *cs; | 
| 942 |  |  | { | 
| 943 |  |  | if (!silent)            /* echo it */ | 
| 944 |  |  | printf("\t%s\n", cs); | 
| 945 |  |  | if (noaction) | 
| 946 |  |  | return(0); | 
| 947 |  |  | fflush(stdout);         /* flush output and pass to shell */ | 
| 948 |  |  | return(system(cs)); | 
| 949 |  |  | } | 
| 950 |  |  |  | 
| 951 |  |  |  | 
| 952 |  |  | rmfile(fn)                      /* remove a file */ | 
| 953 |  |  | char    *fn; | 
| 954 |  |  | { | 
| 955 |  |  | if (!silent) | 
| 956 |  |  | #ifdef MSDOS | 
| 957 |  |  | printf("\tdel %s\n", fn); | 
| 958 |  |  | #else | 
| 959 |  |  | printf("\trm -f %s\n", fn); | 
| 960 |  |  | #endif | 
| 961 |  |  | if (noaction) | 
| 962 |  |  | return(0); | 
| 963 |  |  | return(unlink(fn)); | 
| 964 |  |  | } | 
| 965 |  |  |  | 
| 966 |  |  |  | 
| 967 |  |  | badvalue(vc)                    /* report bad variable value and exit */ | 
| 968 |  |  | int     vc; | 
| 969 |  |  | { | 
| 970 |  |  | fprintf(stderr, "%s: bad value for variable '%s'\n", | 
| 971 |  |  | progname, vnam(vc)); | 
| 972 |  |  | quit(1); | 
| 973 |  |  | } |