#include #include #include #include "noise.h" #include "builtins.h" #include "blocktype.h" typedef struct priv PRIV; typedef struct sb SB; struct priv { int bits; int kind; } ; struct sb { void (*cont)(void *, void *); void *contarg; PRIV p; } ; static int x_noise = -1; static int x_type; static int w_type; static int x_bits; static int w_bits; static int x_out; static int my_w; static int my_h; static BLOCKDIMS size(void) { int noise; int white; int pink; int brown; int nbits; int bits; int bit_total; int out; int col; int total; if (x_noise < 0) { noise = widthof("Noise",5); white = widthof("White",5); pink = widthof("Pink",4); brown = widthof("Brown",5); nbits = widthof("00",2); bits = widthof(" bits",5); out = widthof("Out",3); bit_total = nbits + bits; col = noise; if (white > col) col = white; if (pink > col) col = pink; if (brown > col) col = brown; if (bit_total > col) col = bit_total; total = col + out + (3 * font_space); x_noise = font_space + ((col - noise) / 2); x_type = font_space; w_type = col; x_bits = font_space + ((col - bit_total) / 2); w_bits = col; x_out = total - out - font_space; my_w = total; my_h = 4 * font_baselineskip; } return((BLOCKDIMS){.w=my_w,.h=my_h}); } static void setup_done(int ok, void *sbv) { SB sb; PRIV *p; sb = *(SB *)sbv; free(sbv); if (ok) { p = malloc(sizeof(PRIV)); *p = sb.p; } else { p = 0; } (*sb.cont)(p,sb.contarg); } static void setup_bits(int ok, void *sbv) { SB sb; if (ok) { setup_getarg("Bits",&setup_done,sbv,&((SB *)sbv)->p.bits,PAR_IRANGE,1,16); } else { sb = *(SB *)sbv; free(sbv); (*sb.cont)(0,sb.contarg); } } static void setup(void (*cont)(void *, void *), void *arg) { SB *sb; sb = malloc(sizeof(SB)); sb->cont = cont; sb->contarg = arg; setup_getarg("Type",&setup_bits,sb,&sb->p.kind,PAR_CHOICE,3,"White",NOISE_WHITE,"Pink",NOISE_PINK,"Brown",NOISE_BROWN); } static void destroy(void *pv) { free(pv); } static void render(void *pv, Drawable d, GC gc_bg, GC gc_fg) { PRIV *p; int y; const char *s; int l; int w; char bs[16]; int bsl; p = pv; XFillRectangle(disp,d,gc_bg,0,0,my_w,my_h); XDrawLine(disp,d,gc_fg,0,0,my_w-2,0); XDrawLine(disp,d,gc_fg,my_w-1,0,my_w-1,my_h-2); XDrawLine(disp,d,gc_fg,my_w-1,my_h-1,1,my_h-1); XDrawLine(disp,d,gc_fg,0,my_h-1,0,1); y = font_baseline + (font_baselineskip / 2); XDrawString(disp,d,gc_fg,x_noise,y,"Noise",5); y += font_baselineskip; switch (p->kind) { case NOISE_WHITE: s = "White"; l = 5; break; case NOISE_PINK: s = "Pink"; l = 4; break; case NOISE_BROWN: s = "Brown"; l = 5; break; default: panic(); break; } w = widthof(s,l); XDrawString(disp,d,gc_fg,x_type+((w_type-w)/2),y,s,l); XDrawString(disp,d,gc_fg,x_out,y,"Out",3); bsl = sprintf(&bs[0],"%d %s",p->bits,(p->bits==1)?"bit":"bits"); w = widthof(&bs[0],bsl); y += font_baselineskip; XDrawString(disp,d,gc_fg,x_bits+((w_bits-w)/2),y,&bs[0],bsl); } static const char *outs[] = { "Out" }; static const char *typenames[] = { "White", "Pink", "Brown" }; static const int typevals[] = { NOISE_WHITE, NOISE_PINK, NOISE_BROWN }; static BLOCKPARAM params[] = { { .name = "Bits", .type = PAR_IRANGE, .u = { .irange = { .min = 1, .max = 16 } } }, { .name = "Type", .type = PAR_CHOICE, .u = { .choice = { .n = 3, .names = &typenames[0], .values = &typevals[0] } } } }; BLOCKTYPE block_noise = { .name = "Noise", .n_in = 0, .ins = 0, .n_out = 1, .outs = &outs[0], .n_param = 2, .params = ¶ms[0], .compute_size = &size, .setup = &setup, .destroy = &destroy, .render = &render };