shithub: pain

ref: aea23b76b347d68d5c75d51065c1982acd23ee07
dir: /fs.c/

View raw version
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <draw.h>
#include <9p.h>
#include <stdio.h>

#include "dat.h"
#include "fns.h"

static void fsstart(Srv *);
static void fsend(Srv *);
static void fswrite(Req *);
static void fsread(Req *);

static char * canvasread(Req *);
static char * canvaswrite(Req *);
static char * colorread(Req *);
static char * colorwrite(Req *);
static int FsPID = -1;

typedef struct FileEntry {
	char * name;
	char * (*read) (Req *);
	char * (*write) (Req *);
	int mode;
} FileEntry;

FileEntry entries[] = {
	{"canvas", canvasread, canvaswrite, 0666 },
	{"color", colorread, colorwrite, 0666 }
};
static Image * CanvasReadImage = nil;
static long CanvasReadReady = 0;
static char * FsName = nil;

Srv s = {
	.start = fsstart,
	.end = fsend,
	.read = fsread,
	.write = fswrite,
};

static void
fsstart(Srv *)
{
	File * r, * t;
	char * u;
	int i;

	u = getuser();
	if ((s.tree = alloctree(u, u, 0555, nil)) == nil)
		sysfatal("alloctree: %r");

	r = s.tree->root;
	if ((t = createfile(r, FsName, u, DMDIR | 0555, nil)) == nil)
		sysfatal("createfile: %r");
	
	for (i = 0; i < ARRLEN(entries); i++)
		if (createfile(t, entries[i].name, u, entries[i].mode, &entries[i]) == nil)
			sysfatal("createfile: %r");
	FsPID = getpid();
}

static void
fsend(Srv *)
{
	exits(nil);
}

static void
fsread(Req * r)
{
	FileEntry * e;
	r->ofcall.count = 0;
	e = r->fid->file->aux;
	respond(r, e->read(r));
}

static void
fswrite(Req * r)
{
	FileEntry * e;
	e = r->fid->file->aux;
	respond(r, e->write(r));
}

static char *
canvasread(Req * r)
{
	uchar * b;
	int n;
	char hdr[11+5*12+1], cbuf[20];
	
	if ((CanvasReadImage = namedimage(display, "pain.view")) == nil) {
		return "no view image";
	}

	sprint(hdr, "%11s %11d %11d %11d %11d ",
			chantostr(cbuf, CanvasReadImage->chan), 
			CanvasReadImage->r.min.x, 
			CanvasReadImage->r.min.y, 
			CanvasReadImage->r.max.x, 
			CanvasReadImage->r.max.y
	);
	
	n = bytesperline(CanvasReadImage->r, CanvasReadImage->depth) * Dy(CanvasReadImage->r);
	b = emalloc9p(n + sizeof(hdr));
	memcpy(b, hdr, sizeof(hdr));
	b += sizeof(hdr);
	if (b != nil) {
		unloadimage(CanvasReadImage, CanvasReadImage->r, b, n);
		b -= sizeof(hdr);
		readbuf(r, b, n + sizeof(hdr));
		free(b);
	}

	freeimage(CanvasReadImage);

	return nil;
}

static char *
canvaswrite(Req *)
{
	return nil;
}

static char *
colorread(Req * r)
{
	char b[10];
	u32int p[4];
	Image * br;
	
	br = namedimage(display, "pain.brush");
	if (br == nil) {
		return "failed to get brush image";
	}

	unloadimage(br, br->r, (uchar*)p, sizeof(p));
	snprint(b, sizeof(b), "%08ux\n", p[0]);
	readbuf(r, b, sizeof(b));
	freeimage(br);
	
	return nil;
}

static char *
colorwrite(Req *r)
{
	u32int c;
	Image * i, * br;
	
	br = namedimage(display, "pain.brush");
	if (br == nil) {
		return "failed to get brush image";
	}

	if(r->ifcall.count == 0) {
		c = DNofill;
	} else {
		sscanf(r->ifcall.data, "%x", &c);
	}

	i = allocimage(display, br->r, RGBA32, 0, c);
	if (i == nil) {
		freeimage(br);
		return "failed to allocate image";
	}

	drawop(br, br->r, i, nil, ZP, S);
	
	freeimage(i);
	
	return nil;
}

int
fsinit(char * name)
{
	FsName = name;
	postmountsrv(&s, name, "/n", MBEFORE);
	return 1;
}

void
fsclose(void)
{
	if (FsPID < 0)
		return;

	postnote(PNGROUP, FsPID, "shutdown");
}