shithub: neindaw

Download patch

ref: e93003292b1c6bceed680831cffeae5329bb0104
parent: 1110500359d75192a9e224f90fe6cc679a6e0a25
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon Dec 30 07:34:59 EST 2019

proper ui metadata handling

--- a/aux.h
+++ b/aux.h
@@ -16,10 +16,12 @@
 	UIHBarGraph,
 	UIVBarGraph,
 	Xuictl,
+	Xuimeta,
 };
 
 typedef struct Aux Aux;
 typedef struct Auxdsp Auxdsp;
+typedef struct Meta Meta;
 typedef struct UI UI;
 
 struct Auxdsp {
@@ -35,12 +37,16 @@
 	Auxdsp dsp;
 	int ctl;
 	int data;
+	int metadata;
 	UI *ui;
 };
 
+struct Meta {
+	const char *k;
+	const char *v;
+};
+
 struct UI {
-	const char *key;
-	const char *value;
 	const char *label;
 	FAUSTFLOAT *zone;
 	FAUSTFLOAT init;
@@ -49,4 +55,7 @@
 	FAUSTFLOAT step;
 	char *(*readstr)(Aux *a, UI *ui, int type, char *s, int sz);
 	int (*write)(Aux *a, UI *ui, int type, char *s);
+
+	Meta *meta;
+	int nummeta;
 };
--- a/fs.c
+++ b/fs.c
@@ -36,6 +36,8 @@
 		return (uchar*)type - offsetof(Aux, ctl);
 	case Xdspdata:
 		return (uchar*)type - offsetof(Aux, data);
+	case Xuimeta:
+		return (uchar*)type - offsetof(Aux, metadata);
 	default:
 		sysfatal("trying to get aux out of type %d", *type);
 	}
@@ -160,9 +162,10 @@
 		respond(r, nil);
 		break;
 	case Xuictl:
+	case Xuimeta:
 		o = auxtype2obj(&a->type);
 		if (o->ui->readstr != nil)
-			readstr(r, o->ui->readstr(o, o->ui, Xuictl, b, sizeof(b)));
+			readstr(r, o->ui->readstr(o, o->ui, a->type, b, sizeof(b)));
 		respond(r, nil);
 		break;
 	case Xdspdata:
--- a/kick_drum.dsp
+++ b/kick_drum.dsp
@@ -3,13 +3,13 @@
 declare group "synthesis";
 import("stdfaust.lib");
 
-aFreq = vslider("h:a/[0]frequency", 100, 10, 200, 5);
-aA = vslider("h:a/[1]attack", 0.001, 0.00001, 0.2, 0.001);
-aD = vslider("h:a/[2]delay", 0.01, 0.00001, 1.0, 0.001);
-aR = vslider("h:a/[3]release", 0.001, 0.00001, 1.0, 0.001);
-bA = vslider("h:b/[0]attack", 0.001, 0.00001, 0.2, 0.001);
+aFreq = vslider("h:a/[0]frequency[unit:Hz]", 100, 10, 200, 5);
+aA = vslider("h:a/[1]attack[unit:s]", 0.001, 0.00001, 0.2, 0.001);
+aD = vslider("h:a/[2]delay[unit:s]", 0.01, 0.00001, 1.0, 0.001);
+aR = vslider("h:a/[3]release[unit:s]", 0.001, 0.00001, 1.0, 0.001);
+bA = vslider("h:b/[0]attack[unit:s]", 0.001, 0.00001, 0.2, 0.001);
 bFreq = checkbox("h:control/[1]b enable") * vslider("h:b/[1]frequency", 200, -400, 400, 5);
-bR = vslider("h:b/[2]release", 0.001, 0.00001, 0.2, 0.001);
+bR = vslider("h:b/[2]release[unit:s]", 0.001, 0.00001, 0.2, 0.001);
 gate = button("h:control/[0]gate");
 
 process = os.oscsin(aFreq + bFreq*en.ar(bA, bR, gate)) * en.adsr(aA, aD, 0.000001, aR, gate) <: _, _;
--- a/uiglue.c
+++ b/uiglue.c
@@ -6,29 +6,42 @@
 #include "uiglue.h"
 #include "aux.h"
 
-static FAUSTFLOAT *declzone;
-static const char *declkey;
-static const char *declvalue;
+static struct {
+	FAUSTFLOAT *zone;
+	Meta *meta;
+	int nummeta;
+}decl;
 
 static char *
 ui_readstr(Aux *a, UI *ui, int type, char *s, int sz)
 {
-	if (type != Xuictl)
-		sysfatal("unknown ui file");
+	char *x;
+	int i;
 
-	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;
+	if (type == Xuictl) {
+		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%d\n", !!*ui->zone); return s;
+		case UICheck: snprint(s, sz, "check\t%d\n", !!*ui->zone); return s;
+		case UIVSlider: snprint(s, sz, "vslider\t%f\t%f\t%f\t%f\t%f\n", *ui->zone, ui->init, ui->min, ui->max, ui->step); return s;
+		case UIHSlider: snprint(s, sz, "hslider\t%f\t%f\t%f\t%f\t%f\n", *ui->zone, ui->init, ui->min, ui->max, ui->step); return s;
+		case UINum: snprint(s, sz, "num\t%f\t%f\t%f\t%f\t%f\n", *ui->zone, ui->init, ui->min, ui->max, ui->step); return s;
+		case UIHBarGraph: snprint(s, sz, "hbargraph\t%f\t%f\t%f\n", *ui->zone, ui->min, ui->max); return s;
+		case UIVBarGraph: snprint(s, sz, "vbargraph\t%f\t%f\t%f\n", *ui->zone, ui->min, ui->max); return s;
+		default: sysfatal("unknown ui type %d", a->type);
+		}
+	} else if (type == Xuimeta) {
+		x = s;
+		*x = 0;
+		for (i = 0; i < ui->nummeta; i++)
+			x = seprint(x, s+sz-1, "%s\t%s\n", ui->meta[i].k, ui->meta[i].v);
+		return s;
+	} else {
+		sysfatal("unknown ui file");
 	}
-	sysfatal("unknown ui type %d", a->type);
+
 	return nil;
 }
 
@@ -73,9 +86,13 @@
 {
 	Aux *a;
 
-	a = calloc(1, sizeof(*a)+sizeof(UI));
+	a = calloc(1, sizeof(*a)+sizeof(UI) + sizeof(Meta)*decl.nummeta);
 	a->ui = (UI*)(a+1);
+	a->ui->meta = (Meta*)(a->ui+1);
+	a->ui->nummeta = decl.nummeta;
+	memmove(a->ui->meta, decl.meta, sizeof(Meta)*decl.nummeta);
 	a->ctl = Xuictl;
+	a->metadata = Xuimeta;
 	a->type = type;
 	a->ui->label = label;
 	a->ui->readstr = ui_readstr;
@@ -84,7 +101,14 @@
 		sysfatal("failed to create ui: %r");
 	if (createfile(uiglue.uiInterface, "ctl", nil, 0664, &a->ctl) == nil)
 		sysfatal("failed to create ui ctl: %r");
+	if (createfile(uiglue.uiInterface, "metadata", nil, 0664, &a->metadata) == nil)
+		sysfatal("failed to create ui metadata: %r");
 
+	free(decl.meta);
+	decl.zone = nil;
+	decl.meta = nil;
+	decl.nummeta = 0;
+
 	return a->ui;
 }
 
@@ -120,12 +144,10 @@
 {
 	UI *ui;
 
-	if (zone != declzone)
-		sysfatal("zone mismatch");
+	if (zone != decl.zone)
+		sysfatal("zone mismatch during definition");
 	ui = newui(f, label, type);
-	ui->zone = declzone;
-	ui->key = declkey;
-	ui->value = declvalue;
+	ui->zone = decl.zone;
 	uiglue.uiInterface = f;
 
 	return ui;
@@ -204,9 +226,13 @@
 {
 	USED(f);
 
-	declzone = zone;
-	declkey = key;
-	declvalue = value;
+	if (decl.zone != nil && decl.zone != zone)
+		sysfatal("zone mismatch during declaration");
+	decl.zone = zone;
+	decl.meta = realloc(decl.meta, sizeof(Meta)*(decl.nummeta+1));
+	decl.meta[decl.nummeta].k = key;
+	decl.meta[decl.nummeta].v = value;
+	decl.nummeta++;
 }
 
 UIGlue uiglue = {