ref: b1e84a59c5c100e9aa5c31eb39d58e174289249d
dir: /uiglue.c/
#include <u.h> #include <libc.h> #include <fcall.h> #include <thread.h> #include <9p.h> #include "uiglue.h" #include "aux.h" static struct { FAUSTFLOAT *zone; Meta *meta; int nummeta; }decl; static char * ui_readstr(Aux *a, UI *ui, int type, char *s, int sz) { char *x; int i; if (type == Xuictl) { switch (a->type) { case UITGroup: snprint(s, sz, "tgroup\n"); return s; case UIHGroup: snprint(s, sz, "hgroup\n"); return s; case UIVGroup: snprint(s, sz, "vgroup\n"); return s; case UIButton: snprint(s, sz, "button\t%d\n", !!*ui->zone); return s; case UICheckBox: snprint(s, sz, "checkbox\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 UINEntry: snprint(s, sz, "nentry\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"); } 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 == UICheckBox) 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) + 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->zone = decl.zone; 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"); 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; } static void ui_tgroup(void *f, const char *label) { newui(f, label, UITGroup); } static void ui_hgroup(void *f, const char *label) { newui(f, label, UIHGroup); } static void ui_vgroup(void *f, const char *label) { newui(f, label, UIVGroup); } static void ui_close_group(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 != decl.zone) sysfatal("zone mismatch during definition"); ui = newui(f, label, type); 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_checkbox(void *f, const char *label, FAUSTFLOAT *zone) { ui_define(f, UICheckBox, 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_nentry(void *f, const char *label, FAUSTFLOAT *zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) { UI *ui; ui = ui_define(f, UINEntry, 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); 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 = { .openTabBox = ui_tgroup, .openHorizontalBox = ui_hgroup, .openVerticalBox = ui_vgroup, .closeBox = ui_close_group, .addButton = ui_button, .addCheckButton = ui_checkbox, .addVerticalSlider = ui_vslider, .addHorizontalSlider = ui_hslider, .addNumEntry = ui_nentry, .addHorizontalBargraph = ui_hbargraph, .addVerticalBargraph = ui_vbargraph, .declare = ui_declare, };