scope

signal visualizer for plan9
git clone git://nsmpr.xyz/scope.git
Log | Files | Refs

scope.c (4943B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <thread.h>
      4 #include <draw.h>
      5 #include <mouse.h>
      6 #include <cursor.h>
      7 #include <keyboard.h>
      8 
      9 #define LMAX 1024
     10 #define RBUF 1024
     11 #define DFPS 60
     12 
     13 enum {
     14 	C_BG = 0x3f3f3fff,
     15 	C_GG = 0x000000ff,
     16 	C_FG = 0xffff00ff,
     17 };
     18 
     19 Point P[LMAX];
     20 
     21 typedef struct Readctl Readctl;
     22 
     23 struct Readctl {
     24 	Channel *c;
     25 };
     26 
     27 Image *Im, *Ibg, *Igg, *Ifg, *Igrid;
     28 Rectangle R;
     29 int rh;
     30 
     31 void (*dlines)(void);
     32 
     33 
     34 
     35 
     36 void
     37 usage(void)
     38 {
     39 	fprint(2, "usage: %s [-lrs2]\n", argv0);
     40 	threadexitsall("usage");
     41 }
     42 
     43 void
     44 dclear(void)
     45 {
     46 	draw(screen, screen->r, Ibg, 0, ZP);
     47 	//draw(screen, R, Ibg, 0, ZP);
     48 }
     49 
     50 void
     51 dgrid(void)
     52 {
     53 	const int div = 8;
     54 	int i;
     55 	Rectangle r;
     56 	Point p;
     57 	/* horizontal */
     58 	r =Rect(0,0,rh,1);
     59 	for (i = 0; i <= div; i++){
     60 		p = Pt(0, i * (rh-1)/div);
     61 		draw(Igrid, rectaddpt(r, p), Igg, 0, ZP);
     62 	}
     63 	/* vertical */
     64 	r = Rect(0,0,1,rh);
     65 	for (i = 0; i <= div; i++){
     66 		p = Pt(i * (rh-1)/div, 0);
     67 		draw(Igrid, rectaddpt(r, p), Igg, 0, ZP);
     68 	}
     69 }
     70 
     71 void
     72 dfade(void)
     73 {
     74 	draw(screen, R, Ibg, Im, ZP);
     75 }
     76 
     77 void
     78 dXY(void)
     79 {
     80 	int i;
     81 	Point p;
     82 	for (i = 0; i < LMAX; i++){
     83 		p = Pt(P[i].x, -P[i].y);
     84 		p = addpt(p, addpt(R.min, Pt(rh/2, rh/2)));
     85 		draw(screen, Rpt(p, addpt(p, Pt(1,1))), Ifg, 0, ZP);
     86 	}
     87 }
     88 
     89 void
     90 dboth(void)
     91 {
     92 	int i;
     93 	Point p0, p1;
     94 	for (i = 0; i < LMAX; i++){
     95 		p0.x = R.min.x + i * rh / LMAX;
     96 		p0.y = R.min.y + rh/4 - P[i].x/2;
     97 		p1.x = p0.x;
     98 		p1.y = R.min.y + (3 * rh)/4 - P[i].y/2;
     99 		draw(screen, Rpt(p0, addpt(p0, Pt(1,1))), Ifg, 0, ZP);
    100 		draw(screen, Rpt(p1, addpt(p1, Pt(1,1))), Ifg, 0, ZP);
    101 	}
    102 }
    103 
    104 void
    105 dmono(int c)
    106 {
    107 	int i;
    108 	Point p;
    109 	for (i = 0; i < LMAX; i++){
    110 		p.x = R.min.x + i * rh / LMAX;
    111 		p.y = R.min.y + rh/2;
    112 		p.y += c ? -P[i].x : -P[i].y;
    113 		draw(screen, Rpt(p, addpt(p, Pt(1,1))), Ifg, 0, ZP);
    114 	}
    115 }
    116 
    117 void
    118 dleft(void)
    119 {
    120 	dmono(0);
    121 }
    122 
    123 void
    124 dright(void)
    125 {
    126 	dmono(1);
    127 }
    128 
    129 void (*dfunc[])(void) = {dleft, dright, dboth, dXY};
    130 
    131 
    132 void
    133 threadupdate(void *v)
    134 {
    135 	vlong ot, ct;
    136 	Channel *c;
    137 	c = v;
    138 	threadsetname("threadupdate");
    139 	ot = 0;
    140 	for (;;) {
    141 		ct = nsec();
    142 		if ((ct - ot) > (1000000000/DFPS)) {
    143 			send(c, 0);
    144 			ot = nsec();
    145 		}
    146 		yield();
    147 	};
    148 }
    149 
    150 void
    151 procread(void *v)
    152 {
    153 	s16int buf[RBUF];
    154 	s16int *bp;
    155 	long n;
    156 	Readctl *rctl;
    157 	rctl = v;
    158 	threadsetname("procread");
    159 	while((n = read(0, buf, sizeof(s16int) * RBUF)) > 0) {
    160 		for (bp = buf; bp < buf + (n / sizeof(s16int)); bp+=2) {
    161 			send(rctl->c, bp);
    162 		}
    163 	}
    164 	chanclose(rctl->c);
    165 }
    166 
    167 Rectangle
    168 getdrawrect(void)
    169 {
    170 	Rectangle R;
    171 	R.max = Pt(Dx(screen->r), Dy(screen->r));
    172 	R.min = Pt(0, 0);
    173 	R.max.x = (R.max.x < R.max.y) ? R.max.x : R.max.y;
    174 	rh = R.max.y = R.max.x;
    175 	R = rectaddpt(R, addpt(screen->r.min,
    176 		Pt((Dx(screen->r)-rh)/2,(Dy(screen->r)-rh)/2)));
    177 	return R;
    178 }
    179 
    180 void
    181 threadmain(int argc, char **argv)
    182 {
    183 	long pp;
    184 	Mousectl *mctl;
    185 	Keyboardctl *kctl;
    186 	Rune kv;
    187 	Mouse mv;
    188 	int rv[2];
    189 	Channel *supc;
    190 	int sv;
    191 	Readctl *rctl;
    192 	s16int prv[2];
    193 	
    194 	dlines = dXY;
    195 	pp = 0;
    196 
    197 	ARGBEGIN {
    198 	case 'l':
    199 		dlines = dleft;
    200 		break;
    201 	case 'r':
    202 		dlines = dright;
    203 		break;
    204 	case 's':
    205 		dlines = dboth;
    206 		break;
    207 	case '2':
    208 		dlines = dXY;
    209 		break;
    210 	default:
    211 		usage();
    212 	} ARGEND
    213 	if (argc > 0) usage();
    214 	if (initdraw(nil, nil, "scope") < 0) sysfatal("initdraw failed: %r");
    215 	if ((mctl = initmouse(0, screen)) == nil) sysfatal("initmouse failed: %r");
    216 	if ((kctl = initkeyboard(0)) == nil) sysfatal("initkeyboard failed: %r");
    217 	supc = chancreate(sizeof(int), 0);
    218 	
    219 	Ibg = allocimage(display, Rect(0,0,1,1), RGB24, 1, C_BG);
    220 	Igg = allocimage(display, Rect(0,0,1,1), RGB24, 1, C_GG);
    221 	Ifg = allocimage(display, Rect(0,0,1,1), RGB24, 1, C_FG);
    222 	Im  = allocimage(display, Rect(0,0,1,1), RGBA32, 1, 0xffffff1f);
    223 	rctl = malloc(sizeof(Readctl));
    224 	rctl->c = chancreate(sizeof(s16int) * 2, LMAX);
    225 	
    226 	threadcreate(threadupdate, supc, 8 * 1024);
    227 	proccreate(procread, rctl, 64*1024);
    228 	
    229 	char *menustr[5] = {
    230 		"left",
    231 		"right",
    232 		"both",
    233 		"XY",
    234 		nil,
    235 	};
    236 
    237 	Menu menu = {menustr, nil, 0};
    238 	
    239 	R = getdrawrect();
    240 	Igrid = allocimage(display, Rect(0,0,rh,rh), RGB24, 0, C_BG);
    241 	dgrid();
    242 	dclear();
    243 	flushimage(display, 1);
    244 	Alt alts[6] = {
    245 		{kctl->c, &kv, CHANRCV},
    246 		{mctl->c, &mv, CHANRCV},
    247 		{mctl->resizec, rv, CHANRCV},
    248 		{supc, &sv, CHANRCV},
    249 		{rctl->c, prv, CHANRCV},
    250 		{0, 0, CHANEND},
    251 	}; 
    252 	for(;;){
    253 		switch(alt(alts)){
    254 		case 0: /* keyboard */
    255 			if (kv == 'q') threadexitsall(0);
    256 			if (kv == 0x7f) threadexitsall(0);
    257 			break;
    258 		case 1: /* mouse */
    259 			if (mv.buttons == 1) {
    260 				int m;
    261 				m = menuhit(1, mctl, &menu, 0);
    262 				if (m >=0) dlines = dfunc[m];
    263 			}
    264 			break;
    265 		case 2: /* resize */
    266 			if(getwindow(display, Refnone) < 0)
    267 				sysfatal("resize failed: %r");
    268 			R = getdrawrect();
    269 			freeimage(Igrid);
    270 			Igrid = allocimage(display, Rect(0,0,rh,rh), RGB24, 0, C_BG);
    271 			dgrid();
    272 			dclear();
    273 		case 3: /* update screen */
    274 			draw(screen, R, Igrid, 0, ZP);
    275 			dlines();
    276 			flushimage(display, 1);
    277 			break;
    278 		case 4: /* read input */
    279 			P[pp] = (Pt(prv[0] * rh / 0xffff, prv[1] * rh / 0xffff));
    280 			pp = (pp+1)%LMAX;
    281 			break;
    282 		}
    283 	}
    284 }