shithub: plumbto

Download patch

ref: b5bb94de9a129d9a063320402cc6cfe9c02f12ed
author: sirjofri <[email protected]>
date: Fri Dec 11 16:44:42 EST 2020

adds files

this adds mkfile and plumbto.c source code.
The project works already, you need the channel in your plumb rules

	echo plumb to chanselect >> /mnt/plumb/rules

the messages need destination to this channel, as well as the attribute:

	channels=chan1,chan2,chan3

Whenever a message arrives there, the window pops up and you can click the
correct destination channel (these are buttons). The message is altered (the
channels attribute is removed) and delivered.

--- /dev/null
+++ b/mkfile
@@ -1,0 +1,6 @@
+</$objtype/mkfile
+
+TARG=plumbto
+OFILES=plumbto.$O
+
+</sys/src/cmd/mkone
--- /dev/null
+++ b/plumbto.c
@@ -1,0 +1,157 @@
+#include <u.h>
+#include <libc.h>
+#include <plumb.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <control.h>
+
+Controlset *cs;
+int ctldeletequits = 1;
+
+Control *items[] = {
+	nil, /* pmhead */
+	nil,
+	nil, nil, nil, nil, nil,
+	nil, nil, nil,
+};
+int itemsize = 1;
+int maxitems = 10;
+
+void
+resizecontrolset(Controlset*)
+{
+	int i;
+	Rectangle r;
+	if (getwindow(display, Refnone) < 0)
+		sysfatal("resize failed: %r");
+	r = insetrect(screen->r, 10);
+	for (i = 0; items[i]; i++){
+		r = insetrect(screen->r, 10);
+		r.min.y = r.min.y +  i   *(1+font->height+1);
+		r.max.y = r.min.y +       (1+font->height+1);
+		chanprint(cs->ctl, "%s rect %R\n%s show", items[i]->name, r, items[i]->name);
+	}
+}
+
+int pfd, psfd;
+Plumbmsg *pm;
+char *channels;
+
+void
+plumblisten(void *arg)
+{
+	while ((pm = plumbrecv(pfd)) != nil){
+		channels = plumblookup(pm->attr, "channels");
+		if (channels != nil && strcmp(channels, "") != 0)
+			send((Channel*)arg, 0);
+	}
+}
+
+void
+cleanup(void)
+{
+	int i;
+	for (i = 1; items[i]; i++){
+		closecontrol(items[i]);
+		items[i] = nil;
+	}
+	resizecontrolset(cs);
+}
+
+void
+handleplumb(Channel *c)
+{
+	char *args[10]; // maxitems-1+1
+	int n, i;
+
+	cleanup();
+
+	n = getfields(channels, args, 10, 1, ",");
+	for (i = 0; i < n; i++){
+		items[i+1] = createtextbutton(cs, args[i]);
+		activate(items[i+1]);
+		chanprint(cs->ctl, "%q text %q", args[i], args[i]);
+		controlwire(items[i+1], "event", c);
+		itemsize++;
+	}
+	resizecontrolset(cs);
+}
+
+void
+handleevent(char *c)
+{
+	char *args[10];
+	int n;
+	
+	gettokens(c, args, 10, " \t:");
+	
+	if (atoi(args[2]) == 1){
+		pm->attr = plumbdelattr(pm->attr, "channels");
+		pm->dst = args[0];
+		n = plumbsend(psfd, pm);
+		if (!n)
+			fprint(2, "plumbsend failed: %r\n");
+	}
+	cleanup();
+}
+
+void
+threadmain(int argc, char **argv)
+{
+	USED(argc, argv);
+	int i;
+	int wctlfd;
+	char *chanval;
+	Alt a[] = {
+		{nil, &i, CHANRCV},
+		{nil, &chanval, CHANRCV},
+		{nil, nil, CHANEND},
+	};
+	
+	pfd = plumbopen("chanselect", OREAD);
+	if (!pfd)
+		sysfatal("cannot open plumb channel: %r");
+	psfd = plumbopen("send", OWRITE);
+	if (!psfd)
+		sysfatal("cannot open plumb send: %r");
+	
+	wctlfd = open("/dev/wctl", OWRITE);
+	if (wctlfd)
+		fprint(wctlfd, "hide\n");
+	
+	initdraw(0, 0, "plumbto!");
+	initcontrols();
+	
+	a[0].c = chancreate(sizeof(int), 0);
+	proccreate(plumblisten, a[0].c, 2048);
+	
+	cs = newcontrolset(screen, nil, nil, nil);
+	cs->clicktotype = 1;
+	
+	items[0] = createlabel(cs, "pmhead");
+	chanprint(cs->ctl, "pmhead value %q", "no message");
+	
+	a[1].c = chancreate(sizeof(char*), 0);
+	
+	resizecontrolset(cs);
+	for (;;){
+		switch (alt(a)){
+		case 0: /* plumb event */
+			chanprint(cs->ctl, "pmhead value %q", pm->wdir);
+			handleplumb(a[1].c);
+			if (wctlfd)
+				fprint(wctlfd, "unhide\n");
+			break;
+		case 1: /* control event */
+			handleevent(chanval);
+		//	plumbfree(pm);
+			if (wctlfd)
+				fprint(wctlfd, "hide\n");
+			break;
+		default:
+			sysfatal("can't happen");
+		}
+	}
+}