Mercurial > hg > aim92
view model/review.c @ 0:5242703e91d3 tip
Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author | tomwalters |
---|---|
date | Fri, 20 May 2011 15:19:45 +0100 |
parents | |
children |
line wrap: on
line source
/* Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989 =========================================================================== Permission to use, copy, modify, and distribute this software without fee is hereby granted for research purposes, provided that this copyright notice appears in all copies and in all supporting documentation, and that the software is not redistributed for any fee (except for a nominal shipping charge). Anyone wanting to incorporate all or part of this software in a commercial product must obtain a license from the Medical Research Council. The MRC makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* review.c ======== formerly known as revsai.c - reviews .ctn screen dump files from disk. Copyright (c), 1989 The Medical Research Council, Applied Psychology Unit. Authors : Paul Manson and John Holdsworth. Written : 11th March, 1989 Edited : 03 April 1989 (Paul Manson) -- A new star on the horizon! The all-singing, all-dancing new revue emerges from the ashes of last week's version. 19 April 1989 (Paul Manson) -- Added the <input> option. Changed the name to revsai. 27 April 1989 (Paul Manson) -- The port to the DecStation (and by implication, the VAX) has revealed several problems and bugs. All such known bugs have been fixed. The <memory> option has been introduced (for non-PCs only) to permit rapid reviewing on X-windows servers. NOTE THAT THE SCREEN SIZE FOR NON PC MACHINES HAS BEEN HARD_CODED! THIS SHOULD CHANGE! 05 May 1989 (Paul Manson) -- The above problem has been temporarily rectified by using the default width and height options to indicate the actual screen size. Also, the options format change has been accounted for. 11 May 1989 (Paul Manson) -- Altered options to conform to the new(est) r'egime. 15 May 1989 (Paul Manson) -- Incorporated the PC-style wildcarding into the Unix version. Made display use "NULL" instead of (char *) 0. 05 June 1989 (Paul Manson) -- Altered a couple of the option comments to reflect their behaviour more accurately. I also encountered the rather suspicious "bug" whereby revsai gets a segmentation fault whenever it is run on an old "sai" file ... those generated by sai now appear to be OK... If this really is a problem, it should be tracked down! 06 July 1989 (Paul Manson) -- As well as altering revsai to accomodate all of the new options names, I note that the abovementioned bug appears to have disappeared without trace; hopefully it was just due to previous (buggy) files, etc. 3 August 1993 (M. Akeroyd) -- Added declarations of "colourstr" and "planemaskstr". They aren't used, but are in X.c (and thus libglib.a), and are therfore required to fool the linker. 25 March 1994 (M. Akeroyd) -- Added colour. mono etc, so that 'review' would actually work. (the previuos cahnge just made it compile.) */ #include <string.h> #include <stdio.h> #include <math.h> #if defined(THINK_C) || defined(NeXT) #include <stdlib.h> #else #include <malloc.h> #endif #include "windows.h" #include "options.h" char *monostr, *colourstr, *planemaskstr; /* MAA 3-8-1993 */ char *fgcolourstr, *bgcolourstr; /* MAA 19-8-1993 */ #ifndef lint static char *sccs_id = "@(#)review.c 1.13 Paul Manson, John Holdsworth (MRC-APU) 5/31/91"; #endif #define max(A,B) (((A) > (B)) ? (A) : (B)) #define LENGTH_STR "remainder" #define MAX_LENGTH (9999) #define CENTER_STR "center" #define IMAGE_SUFFIX ".ctn" #ifdef PC #define READ_BINARY "rb" #else #define READ_BINARY "r" #endif /* configurables */ static char *helpstr ; static char *speed1str, *speed2str ; static char *xstr, *ystr, *widthstr, *heightstr ; static char *start1str, *stop1str, *step1str ; static char *start2str, *stop2str, *step2str ; static char *minstr , *maxstr , *framestr ; static char *in1str, *in2str, *downstr ; #if !defined( PC ) extern void exit(); static char *memorystr; #endif static Option res[] = { { "help", "none", &helpstr, "<wave1> [<wave2>]\n\n\ Redisplays stored images from memory or directly from disk.\n\ Review responds to various simple commands, viz.\n\n\ 1\t Activate only wave1 (default when only one wave named).\n\ 2\t Activate only wave2.\n\ b or B\t Activate Both waves (default when two waves named).\n\n\ a or A\t Animate cartoon wave(s). Hitting space bar is equivalent.\n\ s or S\t Single-step activated wave(s). Hit space bar to step.\n\ +\t Animate activated wave(s) faster.\n\ -\t Animate activated wave(s) slower.\n\n\ q or Q\t Quit Revue.\n", SilentOption }, { "input1", NULL_OPTION, &in1str, "Default input file name 1", InputOption}, { "start1" , "0" , &start1str , "Start point in wave 1 (in ms)", InputOption}, { "length1", LENGTH_STR, &stop1str , "Length of wave 1 to display (in ms)", InputOption}, { "step1" , "1" , &step1str , "Display every step-th image of wave 1", InputOption}, { "speed1", "1" , &speed1str, "Image 1 display speed (1 is fastest)", InputOption}, { "input2", NULL_OPTION, &in2str, "Default input file name 2\n", InputOption}, { "start2" , "0" , &start2str , "Start point in wave 2 (in ms)", InputOption}, { "length2", LENGTH_STR, &stop2str , "Length of wave 2 to display (in ms)", InputOption}, { "step2" , "1" , &step2str , "Display every step-th image of wave 2", InputOption}, { "speed2", "1" , &speed2str, "Image 2 display speed (1 is fastest)", InputOption}, { "x0_win", CENTER_STR, &xstr, "Left edge of window (in pixels)" , SilentOption}, { "y0_win", CENTER_STR, &ystr, "Upper edge of window (in pixels)", SilentOption}, { "width_screen", "960", &widthstr, "Physical screen width in pixels", SilentOption}, { "height_screen","750", &heightstr, "Physical screen height in pixels", SilentOption}, /* MAA: 25 March 1994 * These next added because they are used from within X.c (although defined in gen.c), and thus the graphics * calls. They are of NO meaning, however; they define how the Model makes the bitmaps. * Once made, you cannot edit bitmaps ... */ { "fg_col", "black", &fgcolourstr, "Foreground Colour.\n", SilentOption}, { "bg_col", "white", &bgcolourstr, "Background Colour.\n", SilentOption}, { "mono_ctn", ON_OPTION, &monostr, "Force monochrome (single plane) cartoons.", SilentOption}, { "colour_ctn", OFF_OPTION, &colourstr, "Force colour (multi-plane) cartoons.", SilentOption}, {"planemask_ctn", "1", &planemaskstr, "Planemask for creating cartoons.\n", SilentOption}, /* MAA: End of that bit */ #if !defined( PC ) { "memory", ON_OPTION, &memorystr, "Read images into memory for reviewing\n", InputOption}, #endif ( char * ) 0 } ; static Option hiddenRes[] = { { "downsample", "20", &downstr, "Image file frame size (in ms)", InputOption}, { "frstep_aid", "20", &framestr, "Image file frame size (in ms)", InputOption}, { "mincf_afb", "220", &minstr , "Minimum Center Frequency in Hertz", InputOption}, { "maxcf_afb", "4400", &maxstr , "Maximum Center Frequency in Hertz", InputOption}, { "width_win", "900", &widthstr, "Window width (pixels)", InputOption}, { "height_win", "600", &heightstr, "Window height (pixels)", InputOption}, ( char * ) 0 } ; #define ONE (1) #define TWO (2) #define BOTH (0) #define FALSE (0) #define TRUE (1) #define OVERTHETOP (10000) #define AXES_WIDTH (15) static int msToImages(frame, ms) double frame; double ms ; { return (((int) (ms / frame)) + 1); /* Round Up */ } /* File Name Suffix Conversion Parameters */ #define BACKSLASH_CHAR '\\' #define SLASH_CHARACTER '/' #define NULL_CHARACTER '\000' #define DOT_CHARACTER '.' /******************************************************************************************/ /* */ /* AlterSuffix(). Returns its argument fileName with a newSuffix appended in place of */ /* any previous suffix it may have had. It should be noted that this */ /* suffix must include any DOT it wishes to have appended to the name. */ /* */ /******************************************************************************************/ char *AlterSuffix(fileName, newSuffix) char *fileName, *newSuffix; { char *temp, *temp2, *lastPart; int i; temp = malloc((unsigned) (strlen(fileName) + strlen(newSuffix) + 1)); temp = strcpy(temp, fileName); #if defined( PC ) /* Change all backslashes to forward slashes */ for (i = 0; temp[i] != NULL_CHARACTER; i++) if (temp[i] == BACKSLASH_CHAR) temp[i] = SLASH_CHARACTER; #endif if ((lastPart = strrchr(temp, SLASH_CHARACTER)) == NULL) lastPart = temp; else lastPart++; /* Skip over the actual "/" */ /* lastPart points to the tail name of the path */ if ((temp2 = strchr(lastPart, DOT_CHARACTER)) == NULL) temp = strcat(temp, newSuffix); else temp2 = strcpy(temp2, newSuffix); return (temp); } /* ----------------------------------------------------------------------------------- A Routine to extend revsai for in-memory animation. This copies every image from <start> to <stop> by <step> into the images buffer for the window <w>. It then expects contiguous animation of these images. The integer returned is the number of images that were saved; subsequent image Recall() calls should refer to images in the range [1 .. this returned value]. ----------------------------------------------------------------------------------- */ static int readIntoMemory(w, filePtr, start, stop, step) WindowObject w; FILE *filePtr ; int start; int stop; int step; { int fileImage, memImage; memImage = 0; fileImage = start; while (fileImage <= stop && Read(w, filePtr, fileImage)) { Store(w); fileImage += step; memImage++; } return (memImage); } main( argc, argv ) int argc ; char *argv[] ; { WindowObject w1, w2; int screenWidth, screenHeight ; int firstWidth , firstHeight ; int secondWidth, secondHeight ; int firstPixels, secondPixels ; FILE *firstWave , *secondWave ; int OneWave, TwoWaves, spareWidth, spareHeight ; int waveMode , image1 , image2; int count1 , count2; int stopFirst, stopSecond ; int start1 , stop1 , step1 ; int start2 , stop2 , step2 ; int speed1 , speed2 ; char command, *firstWaveName, *secondWaveName, *programName; double mincf1, mincf2, maxcf1, maxcf2, frame1, frame2; int inMemory, x, y; programName = argv[0]; (void) getopts( res, &argc, &argv ); /* Extract any information from the opts which is NECESSARY for the operation of revue */ screenWidth = atoi( widthstr ); screenHeight= atoi( heightstr); #if defined( PC ) inMemory = FALSE; #else inMemory = isON( memorystr ); #endif if (argc > 2 || (argc == 0 && isNULL(in1str))) { (void) helpopts(res, programName); exit(1); } else { OneWave = ((argc == 0 && !isNULL(in1str)) || (argc == 1 && isNULL(in2str))); TwoWaves = !OneWave; } if (argc == 0) firstWaveName = AlterSuffix(in1str, IMAGE_SUFFIX) ; else firstWaveName = AlterSuffix(argv[0], IMAGE_SUFFIX); if ((firstWave = fopen(firstWaveName, READ_BINARY )) == NULL) { (void) fprintf(stderr, "Could not open the image file %s.\n", firstWaveName); exit(1); } (void) readopts(res, firstWave); if (fseek(firstWave, 0l, 0)) { (void) fprintf(stderr, "revsai: Could not re-seek the %s file.\n", firstWaveName); exit(1); } (void) readopts(hiddenRes, firstWave); if( framestr == (char *) 0 ) if( downstr == (char *) 0 ) frame1 = 1 ; else frame1 = atof(downstr); else if ((frame1 = atof(framestr)) < 0.0) frame1 = 0.0; firstWidth = atoi( widthstr ); firstHeight = atoi( heightstr); start1 = msToImages(frame1, atof( start1str )); if (strcmp(stop1str, LENGTH_STR) == 0) stop1 = MAX_LENGTH; else stop1 = msToImages(frame1, atof( stop1str )) + start1; step1 = atoi( step1str ); if (step1 < 1) step1 = 1; firstPixels = 1; /* atoi( pixelstr ); */ mincf1 = atof( minstr ); maxcf1 = atof( maxstr ); if (TwoWaves) { if (argc == 1) secondWaveName = AlterSuffix(in2str, IMAGE_SUFFIX); else secondWaveName = AlterSuffix(argv[1],IMAGE_SUFFIX); if ((secondWave = fopen(secondWaveName, READ_BINARY )) == NULL) { (void) fprintf(stderr, "Could not open the image file %s.\n", secondWaveName); exit(1); } (void) readopts(res, secondWave); if (fseek(secondWave, 0l, 0)) { (void) fprintf(stderr, "revsai: Could not re-seek the %s file.\n", secondWaveName); exit(1); } (void) readopts(hiddenRes, secondWave); if( framestr == (char *) 0 ) if( downstr == (char *) 0 ) frame2 = 1. ; else frame2 = atof(downstr); else if ((frame2 = atof(framestr)) < 0.0) frame2 = atof(downstr); secondWidth = atoi( widthstr ); secondHeight = atoi( heightstr); start2 = msToImages(frame2, atof( start2str )); if (strcmp(stop2str, LENGTH_STR) == 0) stop2 = MAX_LENGTH; else stop2 = msToImages(frame2, atof( stop2str )) + start2; step2 = atoi( step2str ); if (step2 < 1) step2 = 1; secondPixels = 1; /* atoi( pixelstr ); */ mincf2 = atof( minstr ); maxcf2 = atof( maxstr ); } /* Open display window(s) */ if (TwoWaves) { /* Center them both for height, but try to fit them both on the screen at once, width-wise. Firstly, get the REAL screen size */ #if defined( PC ) w1 = newDisplayWindow(firstWaveName, -1, -1, OVERTHETOP, OVERTHETOP, 1); screenWidth = Width(w1); screenHeight = Height(w1); Close(w1); #endif if (screenHeight < firstHeight || screenHeight < secondHeight) { (void) fprintf(stderr, "revsai: One (or both) of the waves specified was too\n high for this screen.\n"); exit(1); } if (screenWidth < firstWidth + secondWidth) { (void) fprintf(stderr, "revsai: These two waves are too wide to be viewed side-by-side.\n Please revue them one at a time, or perhaps generate them smaller.\n"); exit(1); } spareWidth = screenWidth - (firstWidth + secondWidth + (2 * AXES_WIDTH)); spareHeight = screenHeight - (firstHeight + (2 * AXES_WIDTH)); w1 = newDisplayWindow(firstWaveName, spareWidth/6 + AXES_WIDTH, spareHeight/2, firstWidth, firstHeight, firstPixels); Axes(w1, firstWaveName, 0.0, frame1, "Image Frame Size (in ms)", mincf1, maxcf1, "Center Frequency (in Hz)"); spareHeight = screenHeight - (secondHeight + (2 * AXES_WIDTH)); w2 = newDisplayWindow(secondWaveName, (5 * spareWidth / 6) + firstWidth + (2 * AXES_WIDTH), spareHeight/2, secondWidth, secondHeight, secondPixels); Axes(w2, secondWaveName, 0.0, frame2, "Image Frame Size (in ms)", mincf2, maxcf2, "Center Frequency (in Hz)"); } else { /* Easy .. MetaPC Centers it for us */ if (OptionStringsEqual(xstr, CENTER_STR)) x = -1; else x = atoi(xstr); if (OptionStringsEqual(ystr, CENTER_STR)) y = -1; else y = atoi(ystr); w1 = newDisplayWindow(firstWaveName, x, y, firstWidth, firstHeight, firstPixels ); Axes(w1, firstWaveName, 0.0, frame1, "Image Frame Size (in ms)", mincf1, maxcf1, "Center Frequency (in Hz)"); #if defined( SUN ) /* Kludge to overcome the window-sizing inconsistency when you open a SunView window with a frame */ if (Height(w1) > firstHeight || Width(w1) > firstWidth) { #else if (Height(w1) != firstHeight || Width(w1) != firstWidth) { #endif (void) fprintf(stderr, "revsai: The wave you wish to view is too large (ie. either too wide\nor too tall) for the current screen.\n"); exit(1); } } /* Do the actual reviewing */ if (TwoWaves) waveMode = BOTH; else waveMode = ONE ; speed1 = atoi( speed1str ); if (speed1 < 1) speed1 = 1; speed2 = atoi( speed2str ); if (speed2 < 1) speed2 = 1; /* Initially, just open the files and display the first frame of each, */ /* UNLESS the inMemory switch is set, in which case you should read in */ /* all of the images and adjust start, stop to suit. */ if (inMemory) { stop1 = readIntoMemory(w1, firstWave, start1, stop1, step1); start1 = 1; /* Now runs from 0 to the adjusted stop */ step1 = 1; /* Now the images are contiguous */ if (TwoWaves) { stop2 = readIntoMemory(w2, secondWave, start2, stop2, step2); start2 = 1; /* Now runs from 0 to the adjusted stop */ step2 = 1; /* Now the images are contiguous */ } } else { if (!Read(w1, firstWave, start1)) { (void) fprintf(stderr, "revsai: Could not read the first image from the first wave.\n"); exit(1); } if (TwoWaves && !Read(w2, secondWave, start2)) { (void) fprintf(stderr, "revsai: Couldn't read the first image from the second wave.\n"); exit(1); } } /* Sit and take commands */ while ((command = Pause(w1)) != 'q' && command != 'Q') { switch (command) { case '1': /* Toggle to Wave number One */ waveMode = ONE; break; case '2': /* Try to toggle to Wave number Two */ if (TwoWaves) waveMode = TWO; break; case 'b': case 'B': /* Try to toggle to Both Waves */ if (TwoWaves) waveMode = BOTH; break; case '+': /* Speed up current Wave(s) */ if (waveMode == ONE || waveMode == BOTH) speed1 = ((speed1 > 1) ? (speed1 /= 2) : (1)); if (waveMode == TWO || waveMode == BOTH) speed2 = ((speed2 > 1) ? (speed2 /= 2) : (1)); break; case '-': /* Slow down current Wave(s) */ if (waveMode == ONE || waveMode == BOTH) speed1 *= 2; if (waveMode == TWO || waveMode == BOTH) speed2 *= 2; break; case 's': case 'S': stopFirst = (waveMode == TWO); stopSecond = (waveMode == ONE); image1 = start1; image2 = start2; while (!(stopFirst && stopSecond) && (Pause(w1) == ' ')) { if (!stopFirst) { if (inMemory) Recall(w1, image1); else stopFirst = !Read(w1, firstWave , image1); if (!stopFirst) { image1 += step1; stopFirst = (image1 > stop1); } } if (!stopSecond) { if (inMemory) Recall(w2, image2); else stopSecond = !Read(w2, secondWave, image2); if (!stopSecond) { image2 += step2; stopSecond = (image2 > stop2); } } } break; case 'a': case 'A': case ' ': stopFirst = (waveMode == TWO); stopSecond = (waveMode == ONE); image1 = start1; image2 = start2; count1 = count2 = 0 ; while (!(stopFirst && stopSecond)) { if (stopFirst || image1 > stop1) { if (waveMode == BOTH && !stopSecond && image2 <= stop2 && image1 > start1 && count1 == 0) { /* Redisplay the previous image for constant speed */ if (inMemory) Recall(w1, image1-1); else stopFirst = !Read(w1, firstWave, image1-1); } stopFirst = TRUE; } else { if (inMemory) Recall(w1, image1); else stopFirst = !Read(w1, firstWave, image1); if (!stopFirst) if (++count1 >= speed1) { image1 += step1; count1 = 0 ; } } if (stopSecond || image2 > stop2) { if (waveMode == BOTH && !stopFirst && image1 <= stop1 && image2 > start2 && count2 == 0) { /* Redisplay the previous image for constant speed */ if (inMemory) Recall(w2, image2-1); else stopSecond = !Read(w2, secondWave, image2-1); } stopSecond = TRUE; } else { if (inMemory) Recall(w2, image2); else stopSecond = !Read(w2, secondWave, image2); if (!stopSecond) if (++count2 >= speed2) { image2 += step2; count2 = 0 ; } } } break; default: break; } } if (fclose(firstWave)) { (void) fprintf(stderr, "revsai: Could not close file % correctly.\n", firstWaveName); exit(1); } if (TwoWaves && fclose(secondWave)) { (void) fprintf(stderr, "revsai: Could not close file % correctly.\n", secondWaveName); exit(1); } }