/*
**	RTLOOP -- Repeat the input to the output in "real-time".
**	psl 10/87
*/
#include <midi.h>
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>

int	Period = MPU_CLOCK_PERIOD;
int	Tempo	= 100;		/* metronome marking, beats / sec */

main(argc, argv)
char	*argv[];
{
	register int i, dt, n, limit;
	int tfh, exstat, sleepsecs, deltat;
	char tmpfil[128], buf[4096];
	long now = 0;
	MCMD *mp;
	FILE *tfp;

	limit = sleepsecs = deltat = 0;
	for (i = 1; i < argc; i++) {
	    if (argv[i][0] == '-') {
		switch (argv[i][1]) {
		case 'd':			/* change in ... */
		    if (argv[i][2] == 't')
			deltat = atoi(&argv[i][3]);
		    else
			syntax(argv[0]);
		    break;
		case 't':			/* tempo */
		    Tempo = atoi(&argv[i][2]);
		    break;
		case 'w':			/* wait */
		    sleepsecs = atoi(&argv[i][2]);
		    break;
		default:
		    syntax(argv[0]);
		}
	    } else
		limit = atoi(argv[i]);
	}
	sprintf(tmpfil, "/tmp/rtloop%d", getpid());
	if ((tfh = creat(tmpfil, 0600)) < 0) {
	    perror(tmpfil);
	    exit(3);
	}
	while ((i = read(0, buf, sizeof buf)) > 0)
	    write(tfh, buf, i);
	close(tfh);
	exstat = 0;
	if (!(tfp = fopen(tmpfil, "r"))) {
	    perror(tmpfil);
	    exstat = 3;
	    goto done;
	}
	if (sleepsecs)
	    sleep(sleepsecs);
	for (n = 0; limit == 0 || n < limit; n++) {
	    now = 0L;
	    for (fseek(tfp, 0L, 0); mp = getmcmd(tfp, now); ) {
		dt = mp->when - now;
		if (dt) {
		    delay(dt);
		    now += dt;
		}
		if (*mp->cmd != RT_TCWME)
		    write(1, mp->cmd, mp->len);
	    }
	    Tempo += deltat;
	}
done:
	unlink(tmpfil);
	exit(exstat);
}

int	Ringring;	/* the alarm bell */

catch(sig)
{
	Ringring++;
}

delay(dt)		/* delay the specified number of MPU clock ticks */
{
	register int sec, usec;
        struct itimerval itv, oitv;

	if (dt <= 0)
	    return;
	itv.it_interval.tv_sec = itv.it_interval.tv_usec = 0;
	usec = (500000 * dt) / Tempo;
	sec = usec / 1000000;
	usec -= 1000000 * sec;
	itv.it_value.tv_sec = sec;
	itv.it_value.tv_usec = usec;
	signal(SIGALRM, catch);
	setitimer(ITIMER_REAL, &itv, 0);
	for (Ringring = 0; Ringring == 0; sigpause());
	setitimer(ITIMER_REAL, 0, 0);
}

syntax(argv0)
char	*argv0;
{
	fprintf(stderr, "Usage: %s [-t#] [-w#] [N] <input >output\n", argv0);
	fprintf(stderr, "-t sets tempo (beats/minute == m.m.)\n");
	fprintf(stderr, "-w sets initial wait time (secs)\n");
	fprintf(stderr, "%s will stop after N copies are output\n", argv0);
	fprintf(stderr, "Default N is infinity.\n");
	exit(2);
}
