#include #include #include #include #include #include #include "builtins.h" #include "blocktype.h" typedef struct priv PRIV; typedef struct sb SB; typedef struct sbr SBR; struct priv { double t; int s; double *ring; int rp; double o; } ; struct sb { void (*cont)(void *, void *); void *contarg; double t; } ; struct sbr { void (*cont)(void *, int); void *contarg; void *priv; double t; } ; static int my_w = -1; static int my_h; static int delay_x; static int time_x; static int time_w; static int out_x; static BLOCKDIMS size(BLOCK_SIZE_ARGS) { int w_time; int w_delay; int w_in; int w_out; if (my_w < 0) { w_time = widthof("000000",6); w_delay = widthof("Delay",5); w_in = widthof("In",2); w_out = widthof("Out",3); time_w = (w_time > w_delay) ? w_time : w_delay; my_w = w_in + time_w + w_out + (4 * font_space); out_x = my_w - w_out - font_space; delay_x = ((my_w - w_in - w_out - w_delay) / 2) + w_in; time_x = ((my_w - w_in - w_out - w_time) / 2) + w_in; my_h = 3 * font_baselineskip; } return((BLOCKDIMS){.w=my_w,.h=my_h}); } static void setup_cont(int ok, void *sbv) { SB sb; PRIV *p; sb = *(SB *)sbv; free(sbv); if (ok) { p = malloc(sizeof(PRIV)); p->t = sb.t; p->ring = 0; } else { p = 0; } (*sb.cont)(p,sb.contarg); } static void setup(BLOCK_SETUP_ARGS) { SB *sb; sb = malloc(sizeof(SB)); sb->cont = cont; sb->contarg = contarg; setup_getarg("Delay",&setup_cont,sb,&sb->t,PT(PAR_TIME)); } static void resetup_cont(int ok, void *sbrv) { SBR sbr; sbr = *(SBR *)sbrv; free(sbrv); if (ok) ((PRIV *)sbr.priv)->t = sbr.t; (*sbr.cont)(sbr.contarg,ok); } static void resetup(BLOCK_RESETUP_ARGS) { SBR *sbr; sbr = malloc(sizeof(SBR)); sbr->cont = cont; sbr->contarg = contarg; sbr->priv = priv; sbr->t = ((PRIV *)priv)->t; setup_getarg("Delay",&resetup_cont,sbr,&sbr->t,PTD(PAR_TIME)); } static void destroy(BLOCK_DESTROY_ARGS) { PRIV *p; p = priv; free(p->ring); free(p); } static void render(BLOCK_RENDER_ARGS) { PRIV *p; int y; char s[16]; int l; p = priv; 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,time_x,y,"Delay",5); y += font_baselineskip; if (p->t < 9.99994) { l = sprintf(&s[0],"%6.4f",p->t); } else if (p->t < 99.9994) { l = sprintf(&s[0],"%6.3f",p->t); } else if (p->t < 999.994) { l = sprintf(&s[0],"%6.2f",p->t); } else if (p->t < 9999.94) { l = sprintf(&s[0],"%6.1f",p->t); } else { l = sprintf(&s[0],"%d",(int)rint(p->t)); } while ((l > 0) && (s[l-1] == '0')) l --; if ((l > 0) && (s[l-1] == '.')) l --; if (l == 0) s[l++] = '0'; XDrawString(disp,d,gc_fg,time_x+((time_w-widthof(&s[0],l))/2),y,&s[0],l); y = font_baselineskip + font_baseline; XDrawString(disp,d,gc_fg,font_space,y,"In",2); XDrawString(disp,d,gc_fg,out_x,y,"Out",3); } static int iny(BLOCK_INPUT_Y_ARGS) { return((3*font_baselineskip)/2); } static int outy(BLOCK_OUTPUT_Y_ARGS) { return((3*font_baselineskip)/2); } static void rinit(BLOCK_RUN_INIT_ARGS) { PRIV *p; int i; p = priv; p->s = p->t * 44100; free(p->ring); if (p->s > 0) { p->ring = malloc(p->s*sizeof(double)); for (i=p->s-1;i>=0;i--) p->ring[i] = 0; p->rp = 0; } else { p->ring = 0; } } static void rstep(BLOCK_RUN_STEP_ARGS) { PRIV *p; p = priv; if (p->s > 0) { p->o = p->ring[p->rp]; p->ring[p->rp] = ins[0]; p->rp = (p->rp ? p->rp : p->s) - 1; } } static double out(BLOCK_RUN_OUT_ARGS) { PRIV *p; p = priv; return((p->s>0)?p->o:ins[0]); } static const char *ins[] = { "In" }; static const char *outs[] = { "Out" }; static BLOCKPARAM params[] = { { .name = "Time", .type = PAR_TIME } }; BLOCKTYPE block_delay = BLOCKTYPE_I_O_P("Delay",ins,outs,params,size,setup,resetup,destroy,render,iny,outy,rinit,rstep,out);