Logo Search packages:      
Sourcecode: csound version File versions

mkgraph.c

/*  
    mkgraph.c

    Copyright (C) 1991 John ffitch

    This file is part of Csound.

    Csound is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Csound is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Csound; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/* MKGRAPH */
/* John Fitch */
/* 8 December 1994 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <limits.h>
#include <signal.h>
#include <sound.h>
#include <fg.h>

#define XINIT    fg_displaybox[FG_X1]
#define YINIT    fg_displaybox[FG_Y1]
#define WIDTH    (fg_displaybox[FG_X2]-XINIT)
#define HEIGHT   (fg_displaybox[FG_Y2]-YINIT)
#define XLIMIT   (fg_displaybox[FG_X2])
#define YLIMIT   (fg_displaybox[FG_Y2])

#define FALSE    (0)
#define TRUE     (1)
#define BASEOFF  (30)

float smallest_y = 0.0;
float largest_y = 1.0;
float minview = 0.0;
float maxview = 20.0;
float scale_x = 1.0;
float scale_y = 1.0;

char grid = TRUE;
int grid_size = 2;
char debugging = FALSE;
char *outfile = "newgraph";
fg_box_t wbox;

void clearscreen(void);
char mkgraph(void);
void read_file(char *);
void write_file(void);
void write_table(void);
void do_help(void);

typedef struct graph_node {
    float x, y;
    struct graph_node* next;
} graph_node;

graph_node *env = NULL;

void my_term(int xxx)
{
    sound_beep(1331);
    fg_term();
    sound_beep(665);
    exit(1);
}

int main(int argc, char **argv)
{
    graph_node *tt;
    char change;

    if (fg_init_all () == FG_NULL) {
      fputs ("Cannot open screen\n", stderr);
      exit (1);
    }
    if (signal(SIGABRT,my_term) == SIG_ERR ||
      signal(SIGTERM,my_term) == SIG_ERR ||
      signal(SIGFPE, my_term) == SIG_ERR ||
      signal(SIGILL, my_term) == SIG_ERR ||
      signal(SIGSEGV,my_term) == SIG_ERR ||
        signal(SIGINT, my_term) == SIG_ERR) {
            perror("Failed to set signal");
            fg_term();
            abort();
        }
    if (!fg.msm) {
      fg_term();
      fprintf(stderr, "This program needs a mouse as yet\n");
      exit(1);
    }

    argv++;
    while (argc>1) {
      char *s = *argv;
      if (*s == '-') {
          switch (*++s) {
          case 'o':
            if (*++s == '\0') {
                if (!(--argc) || (s = *++argv) && *s == '-') {
                  fprintf(stderr, "no outfilename in -o option\n");
                  exit(1);
                }
            }
            outfile = s;
            break;
          case 'h':
            fprintf(stderr, "Options\n\t-o outfile\tdefine output file\n");
            fprintf(stderr, "\t-v\t\tSet trace mode (generates trace file)\n");
            exit(0);
          case 'v':
            debugging = TRUE;
            break;
          default:
            fprintf(stderr, "Unknown option -%s\n", s);
            break;
          }
      }
      else 
          read_file(*argv);
      argc--;
    }
    if (env == NULL) {
      tt = (graph_node*) malloc(sizeof(graph_node));
      tt->x = 10000.0; tt->y = 0.0; tt->next = NULL;
      env = (graph_node*) malloc(sizeof(graph_node));
      env->x = 0.0; env->y = 0.0; env->next = tt;
    }

    wbox[FG_X1] = XINIT;
    wbox[FG_Y1] = YINIT;
    wbox[FG_X2] = XLIMIT;
    wbox[FG_Y2] = YLIMIT;
    fg_init();
/*  fg_drawbox(FG_WHITE, FG_MODE_SET, ~0, FG_LINE_SOLID, wbox, fg.displaybox);*/
  
    change = mkgraph();
    fg_term();
    if (change==TRUE) {
      int c;
      fprintf(stderr, "Graph not saved.  Save now? ");
      while (change==TRUE) {
          c = getchar();
          switch (c) {
          case 'Y': case 'y':
            write_file();
            change = FALSE;
            break;
          case 'N': case 'n':
            change = FALSE;
            break;
          default:
            fprintf(stderr, "Answer Y or N. Save now? ");
            while (c != '\n') c = getchar();
          }
      }
    }
    return 0;
}

void draw_env(float minx, float maxx, float miny, float maxy)
{
    graph_node *tt = env;
    fg_line_t line;

    clearscreen();
    line[FG_X1] = 0; line[FG_Y1] = 0; line[FG_X2] = WIDTH; line[FG_Y2] = 0;
    fg_drawlineclip(FG_WHITE,FG_MODE_SET,~0, FG_LINE_DENSE_DOTTED,
                  line, fg_displaybox);
    if (grid==TRUE) {
      int i = (int)minx;
      if (i<0) i=0;
      for ( ; (float)i<maxx; i += grid_size) {
          line[FG_X1] = (int)(((float)i-minview) * scale_x);
          line[FG_X2] = line[FG_X1];
          line[FG_Y1] = 0; line[FG_Y2] = HEIGHT-30;
          fg_drawlineclip(FG_WHITE,FG_MODE_SET,~0, FG_LINE_SPARSE_DOTTED,
                  line, fg_displaybox);
      }
    }
    line[FG_X2] = 0; line[FG_Y2] = 0;
    while (tt != NULL) {
      line[FG_X1] = line[FG_X2]; line[FG_Y1] = line[FG_Y2];
      line[FG_X2] = (int)((tt->x-minview) * scale_x);
      line[FG_Y2] = (int)(tt->y * scale_y);
      fg_drawlineclip(FG_WHITE,FG_MODE_SET,~0, FG_LINE_SOLID,
                  line, fg_displaybox);
      tt = tt->next;
    }
}

char arrow_matrix[15] =
{
  0x06,  /*      XX  */
  0x06,  /*      XX  */
  0x8c,  /* X   XX   */
  0xcc,  /* XX  XX   */
  0xf8,  /* XXXXX    */
  0xf8,  /* XXXXX    */
  0xfc,  /* XXXXXX   */
  0xff,  /* XXXXXXXX */
  0xfe,  /* XXXXXXX  */
  0xfc,  /* XXXXXX   */
  0xf8,  /* XXXXX    */
  0xf0,  /* XXXX     */
  0xe0,  /* XXX      */
  0xc0,  /* XX       */
  0x80,  /* X        */
};

fg_msm_cursor_t arrow = {arrow_matrix,{0,0,7,14}, 0, 0};

char mkgraph(void)
{
    unsigned int status;
    unsigned int last_status = 0xffff;
    fg_coord_t x, y, oldx = 0xffff, oldy = 0xffff;
    fg_box_t string_box;
    char done = FALSE;
    int in_char;
    float xx, yy;
    FILE *debug;
    char changed = FALSE;

    if (debugging) debug = fopen("trace", "w");
    fg_box_cpy(string_box, fg_charbox);
    string_box[FG_Y1] += HEIGHT-BASEOFF;
    string_box[FG_Y2] += HEIGHT-BASEOFF;
    if (debugging) fprintf(debug, "HEIGHT=%d, WIDTH=%d\n", HEIGHT, WIDTH);
    scale_x = (float)WIDTH/(maxview-minview);
    scale_y = (float)HEIGHT/(largest_y - smallest_y);
    if (debugging)
      fprintf(debug, "Scale_x = %f scale_y = %f\n", scale_x, scale_y);
    draw_env(minview, maxview, smallest_y, largest_y);

    fg_msm_setcurpos(0, 0);   /* Unnecessary */
    fg_msm_motion(0);         /* Linear */
    fg_msm_showcursor();
    fg_flush();
    fg_msm_setcursor(arrow);

    do {
      char str[100];
      do {
          fg_flush();
          status = fg_msm_getstatus(&x, &y);
/*        fg_msm_setcurpos(x,y); */
          if (x != oldx || y != oldy) {
            yy = (float)y/scale_y;
            xx = (float)x/scale_x + minview;
            sprintf(str, "MKGRAPH CsTool   time:%.4f ampl:%.4f (%3d,%3d)", xx, yy, x, y);
            string_box [FG_X1] = 20;
            string_box [FG_X2] = 60 * fg_box_width (fg.charbox);
            fg_fillbox(FG_BLACK, FG_MODE_SET, ~0, string_box);
            fg_puts(FG_WHITE, FG_MODE_SET, ~0, FG_ROT0,
                  20, HEIGHT-BASEOFF, str, fg.displaybox);
            oldx = x; oldy = y;
          }
          
          if (status != last_status) {
            if (debugging) fprintf(debug, "%s\n", str);
            fg_flush();
            if (status & FG_MSM_RIGHT) {
                graph_node *ss = env;
                if (debugging) fprintf(debug, "Right mouse %d %d\n", x, y);
                while (ss->next != NULL && ss->next->x < xx) 
                  ss = ss->next;
                if (debugging)
                  fprintf(debug, "  (%.3f %.3f) -> (%.3f %.3f)\n",
                        ss->x, ss->y, xx, yy);
                ss->x = xx;
                ss->y = yy;
                changed = TRUE;
            }
            else if (status & FG_MSM_LEFT) {
                graph_node *tt = (graph_node*) malloc(sizeof(graph_node));
                graph_node *ss = env;
                while (ss->next != NULL) {
                  if (ss->next->x == xx) {
                      graph_node *uu = ss->next->next;
                      free(ss->next);
                      tt->next = uu;
                      ss->next = tt;
                      tt->x = xx;
                      tt->y = yy;
                      if (debugging)
                        fprintf(debug, "Replacing node at x=%d\n", x);
                      break;
                  }
                  if (ss->next->x > xx) {
                      tt->next = ss->next;
                      ss->next = tt;
                      tt->x = xx;
                      tt->y = yy;
                      break;
                  }
                  ss = ss->next;
                }
                changed = TRUE;
            }
            draw_env(minview, maxview, smallest_y, largest_y);
            fg_puts(FG_WHITE, FG_MODE_SET, ~0, FG_ROT0,
                  20, HEIGHT-BASEOFF, str, fg.displaybox);
            fg_flush();
            last_status = status;
            fg_flush();
          }
      } while(!kbhit());
      
      in_char = getch();
      if (in_char == 0) /* Extended key, function key, whatever. */
          in_char = getch() << 8;
      if (debugging) fprintf(debug, "Character %x\n", in_char);

#define ESC    0x1b
#define F1     (0x3b << 8)
#define HOME   (0x47 << 8)
#define UP     (0x48 << 8)
#define PGUP   (0x49 << 8)
#define LEFT   (0x4b << 8)
#define RIGHT  (0x4d << 8)
#define DOWN   (0x50 << 8)
#define PGDN   (0x51 << 8)
#define F1ALT  (0x68 << 8)

      switch (in_char) {
      case ESC:
          done = 1;
          write_file();
          changed = FALSE;
          break;
      case HOME:
          break;
      case UP:
          largest_y *= 0.5;
          scale_y = (float)HEIGHT/(largest_y - smallest_y);
          break;
      case DOWN:    /* Lower numbers mean faster mouse. */
          largest_y *= 2.0;
          scale_y = (float)HEIGHT/(largest_y - smallest_y);
          break;
      case RIGHT:
          maxview += (maxview-minview)*0.05;
          minview += (maxview-minview)*0.05;
          break;
      case LEFT:
          if (minview > -0.1) {
            maxview -= (maxview-minview)*0.05;
            minview -= (maxview-minview)*0.05;
          }
          else sound_beep(500);
          break;
      case PGUP:
          scale_x *= 0.5;
          maxview += (maxview - minview);
          break;
      case PGDN:
          scale_x *= 2.0;
          maxview -= (maxview - minview)*0.5;
          break;
      case F1:
          grid_size++;
          break;
      case F1ALT:
          if (grid_size>1) grid_size--;
          break;
      case 'E': case 'e':
      case 'W': case 'w':
          write_file();
          changed = FALSE;
          break;
      case 'F': case 'f':
          write_table();
          changed = FALSE;
          break;
      case 'G': case 'g':
          grid = !grid;
          break;
      case 'H': case 'h': case '?':
          fg_term();
          do_help();
          fg_init();
          fg_msm_setcurpos(x,y);
          fg_msm_motion(0);         /* Linear */
          fg_msm_showcursor();
          fg_flush();
          fg_msm_setcursor(arrow);
          break;
      case 'Q': case 'q':
          done = 1;
          break;
        default:
          sound_beep(440);
          break;
      }
      draw_env(minview, maxview, smallest_y, largest_y);
      yy = (float)y/scale_y;
      xx = (float)x/scale_x + minview;
      sprintf(str, "MKGRAPH CsTool   time:%.4f ampl:%.4f (%3d,%3d)",
            xx, yy, x, y);
      string_box [FG_X1] = 20;
      string_box [FG_X2] = 60 * fg_box_width (fg.charbox);
      fg_fillbox(FG_BLACK, FG_MODE_SET, ~0, string_box);
      fg_puts(FG_WHITE, FG_MODE_SET, ~0, FG_ROT0,
            20, HEIGHT-BASEOFF, str, fg.displaybox);
    } while(done==FALSE);

    fg_msm_hidecursor();
    return changed;
}

void 
clearscreen(void)
{
    fg_fillbox (FG_BLACK, FG_MODE_SET, ~0, fg.displaybox);
}

void 
read_file(char *name)
{
    FILE *in = fopen(name, "r");
    float xx, yy;
    graph_node *tt, *ss = NULL;
    if (in==NULL) {
      fprintf(stderr, "Cannot open file %s\n", name);
      fg_term();
      exit(1);
    }
    while (fscanf(in, "%f %f\n", &xx, &yy) == 2) {
      tt = (graph_node *) malloc(sizeof(graph_node));
      tt->x = xx; tt->y = yy;
      tt->next = NULL;
      if (ss == NULL) env = tt;
      else ss->next = tt;
      ss = tt;
    }
    fclose(in);
}

void 
write_file()
{
    graph_node *tt = env;
    FILE* out = fopen(outfile, "w");
    if (out==NULL) {
      fprintf(stderr, "Cannot open %s file\n", outfile);
      fg_term();
      exit(1);
    }
    while (tt != NULL) {
      fprintf(out, "%.3f\t%.3f\n", tt->x, tt->y);
      tt = tt->next;
    }
    fclose(out);
}

void
write_table()
{
    FILE* out = fopen(outfile, "w");
    int size = 0;
    int i = 0;
    int twos[] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384};
    graph_node *tt = env;
    if (out==NULL) {
      fprintf(stderr, "Cannot open %s file\n", outfile);
      fg_term();
      exit(1);
    }
    while (tt!= NULL) size+=2, tt = tt->next;
    while (size>twos[i]) i++;
    size = twos[i];
    fprintf(out, "f 1 0 %d 7", size);
    tt = env;
    while (tt!=NULL) {
      fprintf(out, " %.0f %.0f", tt->x*100, tt->y*100);
      tt = tt->next;
      size -=2;
    }
    while (size>0) {
      fprintf(out, " 0 0");
      size -=2;
    }
    fprintf(out, "\n");
    fclose(out);
}

void do_help(void)
{
    fprintf(stderr, "MKGRAPH Controls:\n\n");
    fprintf(stderr, "Left button\tSet new point\n");
    fprintf(stderr, "Right button\tModify node to left of cursor\n\n");
    fprintf(stderr, "Keyboard controls:\n\n");
    fprintf(stderr, "Escape\t\tWrite graph file and exit\n");
    fprintf(stderr, "Home\t\tRedraw screen\n");
    fprintf(stderr, "Uparrow\t\tDecrease amplitude range displayed\n");
    fprintf(stderr, "Downarrow\tIncrease amplitude range displayed\n");
    fprintf(stderr, "Rightarrow\tMove time window right 5%% of screen\n");
    fprintf(stderr, "PageUp\t\tDisplay twice the time\n");
    fprintf(stderr, "PageDown\tDisplay half the time\n");
    fprintf(stderr, "F1\t\tCoarser grid\n");
    fprintf(stderr, "ALT+F1\t\tFiner grid\n");
    fprintf(stderr, "E,e\t\tWrite envelope file\n");
    fprintf(stderr, "F,f\t\tWrite table file\n");
    fprintf(stderr, "G,g\t\tToggle display of grid\n");
    fprintf(stderr, "H,h\t\tHelp page\n");
    fprintf(stderr, "Q,q\t\tQuit program\n");
    fprintf(stderr, "W,w\t\tWrite envelope file\n");
    fprintf(stderr, "?\t\tDisplay help page\n");
    fprintf(stderr, "\n\t\t\t\t\t....ENTER to continue");
    while (getchar()!='\n');
}

/****************************
Terminate gracefully.
****************************/
void 
terminate (void)
{
    write_file();
    fg_term ();
    exit (0);
}


Generated by  Doxygen 1.6.0   Back to index