shithub: neindaw

ref: 72f6206d3fbe5c94479d5b0eaa6f79bcab8a8911
dir: /uiglue.c/

View raw version
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include "uiglue.h"
#include "aux.h"

static FAUSTFLOAT *declzone;
static const char *declkey;
static const char *declvalue;

static char *
ui_readstr(Aux *a, UI *ui, int type, char *s, int sz)
{
	if (type != Xuictl)
		sysfatal("unknown ui file");

	switch (a->type) {
	case UITBox: snprint(s, sz, "tbox\n"); return s;
	case UIHBox: snprint(s, sz, "hbox\n"); return s;
	case UIVBox: snprint(s, sz, "vbox\n"); return s;
	case UIButton: snprint(s, sz, "button\t%s\t%d\n", ui->key, !!*ui->zone); return s;
	case UICheck: snprint(s, sz, "check\t%s\t%d\n", ui->key, !!*ui->zone); return s;
	case UIVSlider: snprint(s, sz, "vslider\t%s\t%f\t%f\t%f\t%f\t%f\n", ui->key, *ui->zone, ui->init, ui->min, ui->max, ui->step); return s;
	case UIHSlider: snprint(s, sz, "hslider\t%s\t%f\t%f\t%f\t%f\t%f\n", ui->key, *ui->zone, ui->init, ui->min, ui->max, ui->step); return s;
	case UINum: snprint(s, sz, "num\t%s\t%f\t%f\t%f\t%f\t%f\n", ui->key, *ui->zone, ui->init, ui->min, ui->max, ui->step); return s;
	case UIHBarGraph: snprint(s, sz, "hbargraph\t%s\t%f\t%f\t%f\n", ui->key, *ui->zone, ui->min, ui->max); return s;
	case UIVBarGraph: snprint(s, sz, "vbargraph\t%s\t%f\t%f\t%f\n", ui->key, *ui->zone, ui->min, ui->max); return s;
	}
	sysfatal("unknown ui type %d", a->type);
	return nil;
}

static int
ui_write(Aux *a, UI *ui, int type, char *s)
{
	float v;

	if (type != Xuictl)
		sysfatal("unknown ui file");

	/* FIXME optional argument should specify at which frame to apply the change */

	v = 0.0f;
	if (strncmp(s, "reset", 5) == 0) { /* FIXME reset for a box should reset ALL controls inside it */
		v = ui->init;
	} else if (strncmp(s, "add", 3) == 0) {
		if (ui->zone != nil)
			v = *ui->zone + atof(s+3);
	} else if (strncmp(s, "sub", 3) == 0) {
		if (ui->zone != nil)
			v = *ui->zone - atof(s+3);
	} else {
		v = atof(s);
	}

	if (ui->zone != nil) {
		if (a->type == UIButton || a->type == UICheck)
			v = !!v;
		else if (*ui->zone < ui->min)
			v = ui->min;
		else if (*ui->zone > ui->max)
			v = ui->max;
		*ui->zone = v;
	}

	return 0;
}

static UI *
newui(File *f, const char *label, int type)
{
	Aux *a;

	a = calloc(1, sizeof(*a)+sizeof(UI));
	a->ui = (UI*)(a+1);
	a->ctl = Xuictl;
	a->type = type;
	a->ui->label = label;
	a->ui->readstr = ui_readstr;
	a->ui->write = ui_write;
	if ((uiglue.uiInterface = createfile(f, label, nil, DMDIR|0775, a)) == nil)
		sysfatal("failed to create ui: %r");
	if (createfile(uiglue.uiInterface, "ctl", nil, 0664, &a->ctl) == nil)
		sysfatal("failed to create ui ctl: %r");

	return a->ui;
}

static void
ui_tbox(void *f, const char *label)
{
	newui(f, label, UITBox);
}

static void
ui_hbox(void *f, const char *label)
{
	newui(f, label, UIHBox);
}

static void
ui_vbox(void *f, const char *label)
{
	newui(f, label, UIVBox);
}

static void
ui_close(void *file)
{
	File *f;

	f = file;
	uiglue.uiInterface = f->parent;
}

static UI *
ui_define(File *f, int type, const char *label, FAUSTFLOAT *zone)
{
	UI *ui;

	if (zone != declzone)
		sysfatal("zone mismatch");
	ui = newui(f, label, type);
	ui->zone = declzone;
	ui->key = declkey;
	ui->value = declvalue;
	uiglue.uiInterface = f;

	return ui;
}

static void
ui_button(void *f, const char *label, FAUSTFLOAT *zone)
{
	ui_define(f, UIButton, label, zone);
}

static void
ui_check(void *f, const char *label, FAUSTFLOAT *zone)
{
	ui_define(f, UICheck, label, zone);
}

static void
ui_vslider(void *f, const char *label, FAUSTFLOAT *zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
{
	UI *ui;

	ui = ui_define(f, UIVSlider, label, zone);
	ui->init = init;
	ui->min = min;
	ui->max = max;
	ui->step = step;
}

static void
ui_hslider(void *f, const char *label, FAUSTFLOAT *zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
{
	UI *ui;

	ui = ui_define(f, UIHSlider, label, zone);
	ui->init = init;
	ui->min = min;
	ui->max = max;
	ui->step = step;
}

static void
ui_num(void *f, const char *label, FAUSTFLOAT *zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
{
	UI *ui;

	ui = ui_define(f, UINum, label, zone);
	ui->init = init;
	ui->min = min;
	ui->max = max;
	ui->step = step;
}

static void
ui_hbargraph(void *f, const char *label, FAUSTFLOAT *zone, FAUSTFLOAT min, FAUSTFLOAT max)
{
	UI *ui;

	ui = ui_define(f, UIHBarGraph, label, zone);
	ui->min = min;
	ui->max = max;
}

static void
ui_vbargraph(void *f, const char *label, FAUSTFLOAT *zone, FAUSTFLOAT min, FAUSTFLOAT max)
{
	UI *ui;

	ui = ui_define(f, UIVBarGraph, label, zone);
	ui->min = min;
	ui->max = max;
}

static void
ui_declare(void *f, FAUSTFLOAT *zone, const char *key, const char *value)
{
	USED(f);

	declzone = zone;
	declkey = key;
	declvalue = value;
}

UIGlue uiglue = {
	.openTabBox = ui_tbox,
	.openHorizontalBox = ui_hbox,
	.openVerticalBox = ui_vbox,
	.closeBox = ui_close,
	.addButton = ui_button,
	.addCheckButton = ui_check,
	.addVerticalSlider = ui_vslider,
	.addHorizontalSlider = ui_hslider,
	.addNumEntry = ui_num,
	.addHorizontalBargraph = ui_hbargraph,
	.addVerticalBargraph = ui_vbargraph,
	.declare = ui_declare,
};