/* ** MERGE -- Merge two or more streams of MIDI data ** psl 5/86 */ #include #include #define BIGTIME 0x7FFFFFFF #define MAXFILES 16 #define MAXMIDILEN 4 /* longest non-sysex MIDI command */ struct mfstr { FILE *fp; MCMD m; char *mbuf; int stat; } Mf[MAXFILES]; char Mbuf[MAXFILES * MAXMIDILEN]; int Nfiles = 0; int Sysex = 0; int Stat[MAXFILES]; int Blen; main(argc, argv) char *argv[]; { register int i, f, minf; long mintime; for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case '\0': /* stdin */ if (!openmf((char *) 0)) exit(1); break; case 'x': /* allow sysex */ if (Nfiles) { fprintf(stderr, "-x must precede file names\n"); exit(2); } Sysex = argv[i][2]? atoi(&argv[i][2]) : 1024; break; default: goto syntax; } } else { if (!openmf(argv[i])) exit(1); } } if (Nfiles < 2) { syntax: fprintf(stderr, "Usage: %s [-x[#]] file1 file2 [file3 ...] > new", argv[0]); fprintf(stderr, "-\tcan be used as a file name to mean stdin.\n"); fprintf(stderr, "-x\tallows sys excl up to ~1020 chars long\n"); fprintf(stderr, "-x#\tallows sys excl up to ~#-4 chars long\n"); fprintf(stderr, "\t(else sys excl is silently ignored.)\n"); exit(2); } Blen = Sysex? Sysex : MAXMIDILEN; for (mintime = BIGTIME; ; mintime = Mf[minf].m.when) { for (f = Nfiles; --f >= 0; ) { if (Mf[f].m.when < mintime) { mintime = Mf[f].m.when; minf = f; } } if (mintime == BIGTIME) break; writemf(&Mf[minf]); readmf(&Mf[minf]); } } openmf(file) char *file; { if (Nfiles >= MAXFILES) { fprintf(stderr, "Too many files; max is %d\n", MAXFILES); exit(2); } if (file) { if ((Mf[Nfiles].fp = fopen(file, "r")) < 0) return(0); } else Mf[Nfiles].fp = stdin; Mf[Nfiles].m.when = 0L; Mf[Nfiles].stat = 0; if (!Sysex) Mf[Nfiles].mbuf = &Mbuf[MAXMIDILEN * Nfiles]; else if ((Mf[Nfiles].mbuf = (char *) sbrk(Sysex)) <= 0) { fprintf(stderr, "sbrk(%d) failed\n", Sysex); exit(1); } readmf(&Mf[Nfiles++]); return(1); } readmf(p) /* read the next event from *p */ struct mfstr *p; { register MCMD *mp; while (!(mp = getmcmdb(p->fp, p->m.when, p->mbuf, Blen, &p->stat))) { if (feof(p->fp)) { fclose(p->fp); p->m.when = BIGTIME; return; } } p->m = *mp; } writemf(p) struct mfstr *p; { putmcmd(stdout, &p->m); }