/*	MIRP -- Mirage parameter display  psl 4/88 */

#include	<suntool/sunview.h>
#include	<suntool/canvas.h>
#include	<suntool/panel.h>
#include	<suntool/scrollbar.h>
#include	<midi.h>
#include	<stdio.h>
#include	<sys/types.h>
#include	<sys/stat.h>

#define	MAXP		128
#define	BARHEIGHT	16

#define	TMPFILE	"/tmp/mirpar.0"
#define	SEQFILE	"/tmp/mirp.seq"

#define	PIX_INV	PIX_NOT(PIX_DST)
#define	PIX_XOR	(PIX_DST^PIX_SRC)
#define	ROP(OX,OY,CX,CY,OP)	pw_rop(Dpw,OX,OY,CX-(OX),CY-(OY),OP,0,0,0);
#define	RECTOP(R,OP)		ROP((R).o.x,(R).o.y,(R).c.x,(R).c.y,OP)
#define	RINV(OX,OY,CX,CY)	pw_rop(Dpw,OX,OY,CX-(OX),CY-(OY),PIX_INV,0,0,0);
#define	RECTINV(R)		RINV((R).o.x,(R).o.y,(R).c.x,(R).c.y)

typedef	unsigned char	uchar;

char	Flbuf[128];		/* frame label buffer */
int	Trace	= 0;
int	Npar	= 0;		/* How many parameters we're controlling */
int	Par[MAXP];		/* numbers for parameters we're controlling */
int	Pval[MAXP];		/* values for parameters we're controlling */
int	Chan	= 2;		/* Where the Mirage listens */
Frame	Dframe;			/* whole display's frame */
Panel	Controls;		/* control panel */
Panel_item Slide[MAXP];		/* id for parameter sliders */

/* Button 3 menu */
Menu	b3mp;
#define	PLAY		1
#define	QUIT		2
#define	B3MINIT() b3mp = menu_create( \
MENU_INITIAL_SELECTION, MENU_SELECTED, \
MENU_INITIAL_SELECTION_SELECTED, FALSE, \
MENU_STRINGS, \
	"PLAY SEQ", \
	"QUIT", \
0, 0)

main(argc, argv)
char	*argv[];
{
	int i;

/****/setbuf(stderr, 0);	/* THOSE ASSHOLES AT SUN! */
	for (i = 1; i < argc; i++) {
	    if (argv[i][0] == '-') {
		switch (argv[i][1]) {
		default:
		    goto syntax;
		}
	    } else if (Npar < MAXP) {
		Par[Npar] = atoi(argv[i]);
		Pval[Npar] = getval(Par[Npar]);
		Npar++;
	    } else {
		fprintf(stderr, "Too many parameters; limit is %d\n", MAXP);
		goto syntax;
	    }
	}
	if (Npar == 0) {
syntax:
	    fprintf(stderr, "Usage: %s # [# ...]\n", argv[0]);
	    exit(2);
	}
	miscinits();
	window_main_loop(Dframe);
	exit(0);
}

miscinits()		/* do one-time inits */
{
	char buf[64];
	int swidth, i;
	Rect tmp;
	void cntlchng(), pinput();

	swidth = 258;
	tmp.r_left = 8;
	tmp.r_top = 8;
	tmp.r_width = swidth + 25 * 16;
	tmp.r_height = Npar * (BARHEIGHT + 2) + 20;
	Dframe = window_create(NULL, FRAME,
	    FRAME_OPEN_RECT,	&tmp,
	    0);
	Controls = window_create(Dframe, PANEL,
	    WIN_X,			0,
	    WIN_Y,			0,
	    WIN_WIDTH,			WIN_EXTEND_TO_EDGE,
	    WIN_HEIGHT,			WIN_EXTEND_TO_EDGE,
	    PANEL_SHOW_MENU,		FALSE,
	    PANEL_LABEL_BOLD,		TRUE,
	    PANEL_ITEM_Y_GAP,		2,
	    PANEL_EVENT_PROC,		pinput,
	    0);
	for (i = 0; i < Npar; i++) {
	    if (Masos_par[i]].pfmt == MP_BOOL)
		continue;
	    sprintf(buf, "[%02d] %-20.20s", Par[i], Masos_par[Par[i]].pname);
	    Slide[i] = panel_create_item(Controls, PANEL_SLIDER,
		PANEL_LABEL_STRING,	buf,
		PANEL_SLIDER_WIDTH,	swidth,
		PANEL_VALUE,		Pval[i],
		PANEL_MIN_VALUE,	Masos_par[Par[i]].lolim,
		PANEL_MAX_VALUE,	Masos_par[Par[i]].hilim,
		PANEL_NOTIFY_PROC,	cntlchng,
		0);
	}
	for (i = 0; i < Npar; i++) {
	    if (Masos_par[i]].pfmt != MP_BOOL)
		continue;
	    sprintf(buf, "[%02d] %20.20s", Par[i], Masos_par[Par[i]].pname);
	    Slide[i] = panel_create_item(Controls, PANEL_SLIDER,
		PANEL_LABEL_STRING,	buf,
		PANEL_SLIDER_WIDTH,	swidth,
		PANEL_VALUE,		Pval[i],
		PANEL_MIN_VALUE,	Masos_par[Par[i]].lolim,
		PANEL_MAX_VALUE,	Masos_par[Par[i]].hilim,
		PANEL_NOTIFY_PROC,	cntlchng,
		0);
	}

	window_fit_height(Controls);
	window_fit_width(Controls);
	B3MINIT();
}

void
cntlchng(item, value, event)
Panel_item item;
Event	*event;
{
	register int i, p, ov;
	char buf[32];

	for (i = Npar; --i >= 0 && item != Slide[i]; );
	if (i < 0)
	    return;
	sprintf(buf, "mirset %d=%d", Par[i], value);
	system(buf);
}

void
pinput(item, event)
Panel_item	item;
Event	*event;
{
	register int i;

	i = event_id(event);
	if (i == MS_RIGHT)
	    mouseright(event);
	else
	    panel_default_handle_event(item, event);
}

mouseright(event)
Event	*event;
{
	register int i, fh;
	uchar buf[64];

	i = (int) menu_show(b3mp, Controls, event, 0);
	switch(i) {
	case PLAY:
	    if (close(open(SEQFILE, 0)) < 0) {
		if ((fh = creat(SEQFILE, 0644)) < 0) {
		    perror(SEQFILE);
		    break;
		} else {
		    buf[0] = 0;
		    buf[1] = 0x90 | Chan;
		    buf[2] = i;
		    buf[3] = 0x40;
		    buf[4] = 24;
		    buf[5] = i;
		    buf[6] = 0;
		    for (i = 36; i < 97; i++) {
			buf[2] = buf[5] = i;
			write(fh, buf, 7);
		    }
		    close(fh);
		}
	    }
	    sprintf(buf, "play %s", SEQFILE);
	    system(buf);
	    break;
	case QUIT:
	    quit();
	    break;
	}
}

quit()
{
	exit(0);
	/*NOTREACHED*/
}

getval(p)
{
	char buf[32], rbuf[128], *cp;
	int i;
	FILE *fp;

	sprintf(buf, "mirset %d='?' >%s", p, TMPFILE);
	for (i = 10; --i > 0; ) {
	    system(buf);
	    if (!(fp = fopen(TMPFILE, "r"))) {
		perror(TMPFILE);
		return(0);
	    }
	    while (fgets(rbuf, sizeof rbuf, fp)) {
		if (atoi(rbuf) == p) {
		    for (cp = rbuf; *cp && *cp != '='; cp++);
		    if (*cp++ == '=')
			return(atoi(cp));
		}
	    }
	}
	return(0);
}
