#include #include #include Error(s) { MidiError("%s: ", av0); perror(s); exit(1); } use(n) { MidiError("use: %s [flags] > file\n", av0); MidiError("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s", "flags:\n", "-7 send DX7 reset sequence at end\n", "-B N set # beats/measure to N\n", "-c file use 'file' to initialize MPU\n", "-f stop recording on 0xfc byte (RT_TCIS)\n", "-m metronome on, no accent\n", "-M metronome on, with accent\n", "-S src sync clock to src = i (int), f (fsk), or m (MIDI in)\n", "-t N set tempo to N (beats/minute, default=100)\n", "-u unbuffered output\n", "-x enable recording system exclusive data\n", 0); exit(n); } int DX7 = 0; /* if true, send DX7 reset sequence */ int Fcstop = 0; /* stop on 0xFC */ char Sync = 'i'; int Unbuffered = 0; main(ac, av) char **av; { char *init_file = NULL; unsigned char buf[BUFSIZ]; Int i, midi; int otty = isatty(1); MpuSet(MPU_RESET); for_each_argument { Case '7': DX7++; Case 'B': MpuSet(MPU_METRO_MEAS), MpuSet(atoi(argument)); Case 'c': init_file = argument; Case 'f': Fcstop++; Case 'M': MpuSet(MPU_METRO_ACC); Case 'm': MpuSet(MPU_METRO_NO_ACC); Case 'S': Sync = *argument; Case 't': MpuSet(MPU_TEMPO), MpuSet(atoi(argument)); Case 'u': Unbuffered = 1; Case 'x': MpuSet(MPU_EXCLUSIVE_TO_HOST_ON); MpuSet(MPU_SEND_MEASURE_END_OFF); Default : use(1); } if ((midi = open(MidiDevice, 2)) == -1) Error(MidiDevice); if (Unbuffered) setbuf(stdout,NULL); if (init_file) { int d; FILE *sopen(), *f = sopen(init_file,"r"); if (!f) Error(init_file); while (fscanf(f,"%x",&d) == 1) MpuSet(d); sclose(f); } else { if (Sync == 'f') MpuSet(MPU_FSK_CLOCK); else if (Sync == 'm') MpuSet(MPU_MIDI_CLOCK); else MpuSet(MPU_INT_CLOCK); MpuSet(MPU_BENDER_ON); MpuSet(MPU_MIDI_THRU_OFF); MpuSet(MPU_START_RECORD); } if (MpuFlush(midi)) Error(MidiDevice); for (;;) { i = eitherwait(0, midi, 1000); if (i == 0) { /* stop on receipt of stdin */ getchar(); break; } else if (i == midi) { if (read(midi, buf, 1) <= 0) Error(MidiDevice); if (otty) printf("0x%x\n", buf[0]); else if (write(fileno(stdout), buf, 1) != 1) Error(MidiDevice); if (Fcstop && *buf == RT_TCIS) break; } } close(midi); if (DX7) dx7_reset(-1); exit(0); } /* * Wait until either 'f1' or 'f2' is ready for reading, or 'timeout'. * Return -1 for timeout (or error), f1 for f1, or f2 for f2. * Example: 'eitherwait(a,b,0)' polls file descriptors a & b * without blocking and returns a or b if they're readable, else -1; * a has priority over b. */ eitherwait(a, b, msec) unsigned long msec; /* millisecs */ { struct timeval t; int readfd; readfd = (1 << a) | (1 << b); t.tv_sec = msec / 1000; t.tv_usec = (msec % 1000) * 1000; select(sizeof(int)*8, &readfd, (int *)0, (int *)0, &t); if (readfd & (1 << a)) return(a); if (readfd & (1 << b)) return(b); return(-1); }