ref: 5cf2a66d5a71fad0128b2f9d0b088cea743c0d60
dir: /fs.c/
#include <u.h> #include <libc.h> #include <fcall.h> #include <thread.h> #include <9p.h> #include "common.h" #include "ui.h" #include "fs.h" enum { Maxobjs = 32, }; static Aux *objs[Maxobjs]; static Aux rootaux[] = { [Xctl] = {.type = Xctl}, [Xmetadata] = {.type = Xmetadata}, [Xclone] = {.type = Xclone}, }; extern File *uif; static Fs *fs; static Aux * newobj(char *name) { File *f; Aux *o; int i, mode; for (i = 0, o = nil; o == nil && i < nelem(objs); i++) { if (objs[i] == nil){ o = objs[i] = calloc(1, sizeof(*o)); break; } } if (o == nil) return nil; o->id = i; o->type = Xdsp; o->ctl = Xdspctl; o->data = Xdspdata; sprint(name, "%d", o->id); if ((f = createfile(fs->srv.tree->root, name, nil, DMDIR|0775, o)) == nil) return nil; closefile(createfile(f, "ctl", nil, 0664, &o->ctl)); mode = 0; if (fs->dsp.read != nil) mode |= 0444; if (fs->dsp.write != nil) mode |= 0222; closefile(createfile(f, "data", nil, mode, &o->data)); uif = f; o->dsp = fs->dsp.new(); closefile(f); return o; } static void freeobj(Aux *o) { if (o == nil) return; if (o->type == Xdsp) { objs[o->id] = nil; fs->dsp.free(o->dsp); } free(o); } static void * auxtype2obj(int *type) { switch (*type) { case Xdspctl: case Xuictl: return (uchar*)type - offsetof(Aux, ctl); case Xdspdata: return (uchar*)type - offsetof(Aux, data); case Xuimeta: return (uchar*)type - offsetof(Aux, metadata); default: sysfatal("trying to get aux out of type %d", *type); } return nil; } static void fsopen(Req *r) { respond(r, nil); } static void fsread(Req *r) { Aux *a, *o; char b[256]; a = r->fid->file->aux; switch (a->type) { case Xctl: respond(r, nil); break; case Xmetadata: readstr(r, fs->metadata); respond(r, nil); break; case Xclone: if (r->ifcall.offset == 0) { if (newobj(b) != nil) { readstr(r, b); } else { snprint(b, sizeof(b), "no free objects: %r"); respond(r, b); break; } } respond(r, nil); break; case Xuictl: case Xuimeta: o = auxtype2obj(&a->type); if (o->ui->readstr != nil) readstr(r, o->ui->readstr(o->ui, a->type, b, sizeof(b))); respond(r, nil); break; case Xdspdata: o = auxtype2obj(&a->type); r->ofcall.count = fs->dsp.read(o->dsp, (float*)r->ofcall.data, r->ifcall.count/sizeof(float))*sizeof(float); respond(r, nil); break; default: respond(r, "not implemented"); break; } } static void fswrite(Req *r) { Aux *a, *o; char b[256]; if (r->ifcall.count >= sizeof(b)) { respond(r, "can't fit into buffer"); return; } memmove(b, r->ifcall.data, r->ifcall.count); b[r->ifcall.count] = '\0'; r->ofcall.count = r->ifcall.count; a = r->fid->file->aux; switch (a->type) { case Xuictl: o = auxtype2obj(&a->type); if (o->ui->writestr == nil) respond(r, "not implemented"); else if (o->ui->writestr(o->ui, a->type, b) >= 0) respond(r, nil); else responderror(r); break; case Xdspctl: /* FIXME changing sampling rate */ o = auxtype2obj(&a->type); if (strncmp(b, "reset", 5) == 0) /* FIXME ui needs to be reset as well */ fs->dsp.reset(o->dsp); respond(r, nil); break; case Xmetadata: /* FIXME should be possible to add new key/value */ default: respond(r, "not implemented"); break; } } static void fsdestroyfile(File *f) { Aux *a; if ((a = f->aux) == nil) return; switch (a->type) { case Xdsp: case Xui: freeobj(a); f->aux = nil; break; } } void fsinit(void *fs_) { fs = fs_; fs->srv.open = fsopen; fs->srv.read = fsread; fs->srv.write = fswrite; fs->srv.tree = alloctree(nil, nil, DMDIR|0775, fsdestroyfile); closefile(createfile(fs->srv.tree->root, "ctl", nil, 0666, &rootaux[Xctl])); closefile(createfile(fs->srv.tree->root, "metadata", nil, 0444, &rootaux[Xmetadata])); closefile(createfile(fs->srv.tree->root, "clone", nil, 0444, &rootaux[Xclone])); }