amp

pcm player/editor for plan9
git clone git://nsmpr.xyz/amp.git
Log | Files | Refs | README

commit a8e7ed87318a9b388a7866741175b89d00776f48
parent 890d073d9da414458d62f5aaca7509b299f5b9c1
Author: Pavel Renev <an2qzavok@gmail.org>
Date:   Sun, 11 Feb 2024 17:53:30 +0000

start implementing separate fs backend

Diffstat:
Afs.c | 133+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmkfile | 9+++++----
Apages.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apages.h | 29+++++++++++++++++++++++++++++
4 files changed, 255 insertions(+), 4 deletions(-)

diff --git a/fs.c b/fs.c @@ -0,0 +1,133 @@ +#include <u.h> +#include <libc.h> +#include <fcall.h> +#include <thread.h> +#include <9p.h> + +#include "pages.h" + +enum { + FrameSize = sizeof(s16int) * 2, +}; + +PBuf pg; + +struct { + int min; + int max; + char str[32]; +} sel; + +void fs_read(Req *r); +void fs_write(Req *r); + +void normalize_sel(void); +void update_selstr(void); + +Srv ampsrv = { + .read = fs_read, + .write = fs_write, + // .open/.create (???) for handling truncating +}; + +File *fdata, *fcut, *fctl; + +void +usage(void) +{ + fprint(2,"usage: %s\n", argv0); + threadexitsall("usage"); +} + +void +threadmain(int argc, char **argv) +{ + ARGBEGIN { + case 'D': + chatty9p++; + break; + default: usage(); + } ARGEND + if (argc != 0) usage(); + + update_selstr(); + + ampsrv.tree = alloctree("amp", "amp", DMDIR|0555, nil); + fdata = createfile(ampsrv.tree->root, "data", "amp", 0666, nil); + fcut = createfile(ampsrv.tree->root, "cut", "amp", 0666, nil); + fctl = createfile(ampsrv.tree->root, "ctl", "amp", 0666, nil); + threadpostmountsrv(&ampsrv, "amp", "/mnt/amp", MREPL); +} + +void +fs_read(Req *r) +{ + if (r->fid->file == fdata) { + r->ofcall.count = pbread(&pg, r->ofcall.data, + r->ifcall.count, r->ifcall.offset); + respond(r, nil); + } else if (r->fid->file == fcut) { + respond(r, "fcut nope"); + } else if (r->fid->file == fctl) { + readstr(r, sel.str); + respond(r, nil); + } else { + respond(r, "nope"); + } +} + +void +fs_write(Req *r) +{ + if (r->fid->file == fdata) { + r->ofcall.count = pbwrite(&pg, r->ifcall.data, + r->ifcall.count, r->ifcall.offset); + if (pg.count > fdata->length) fdata->length = pg.count; + respond(r, nil); + } else if (r->fid->file == fcut) { + respond(r, "fcut nope"); + } else if (r->fid->file == fctl) { + int newmin, newmax; + char *np, *rp; + np = r->ifcall.data; + newmin = strtol(np, &rp, 10); + if (rp <= np) { + respond(r, "bad first value"); + return; + } + newmax = strtol(rp, &rp, 10); + if (rp <= np) { + respond(r, "bad second value"); + return; + } + if (rp - np > r->ifcall.count) { + respond(r, "somehow buffer overrun"); + return; + } + sel.min = newmin; + sel.max = newmax; + normalize_sel(); + update_selstr(); + r->ofcall.count = r->ifcall.count; + respond(r, nil); + } else { + respond(r, "nope"); + } +} + +void +normalize_sel(void) +{ + if (sel.min > sel.max) { + int x = sel.max; + sel.max = sel.min; + sel.min = x; + }; + // TODO: should check max is not bigger than total buffer size +} + +void +update_selstr(void) +{ + snprint(sel.str, sizeof(sel.str), "%11d %11d ", sel.min, sel.max); +} diff --git a/mkfile b/mkfile @@ -1,9 +1,10 @@ </$objtype/mkfile -TARG=amp +TARG=fs -OFILES=\ - amp.$O\ +OFILES=pages.$O +HFILES=pages.h BIN=/$objtype/bin -</sys/src/cmd/mkone + +</sys/src/cmd/mkmany diff --git a/pages.c b/pages.c @@ -0,0 +1,88 @@ +#include <u.h> +#include <libc.h> + +#include "pages.h" + +Page * +allocpage(void) +{ + Page *new = mallocz(sizeof(Page), 1); + new->count = PageSize; + new->buf = mallocz(PageSize, 1); + return new; +} + +long +pbwrite(PBuf *pb, void *buf, long nbytes, vlong offset) +{ + Page *pgpt; + vlong page_offset = 0; + long n, nwritten = 0; + while (offset + nbytes > pb->size) { + addpage(pb); + } + pgpt = pb->start; + if (pb->count < offset + nbytes) pb->count = offset + nbytes; + while (nbytes > 0) { + assert(page_offset <= offset); + if (page_offset + pgpt->count > offset) { + n = page_offset + pgpt->count - offset; + if (n > nbytes) n = nbytes; + memcpy(pgpt->buf, buf, n); + nwritten += n; + buf = (char *)buf + n; + offset +=n; + nbytes -= n; + } + page_offset += pgpt->count; + pgpt = pgpt->next; + } + if (offset > pb->size) { + pb->size = offset; + } + return nwritten; +} + +long +pbread(PBuf *pb, void *buf, long nbytes, vlong offset) +{ + Page *pgpt = pb->start; + long n, nread = 0; + if (offset >= pb->count) nbytes = 0; + if (offset + nbytes >= pb->count) { + nbytes = (pb->count - offset); + } + while (nbytes > 0) { + if (pgpt == nil) { + break; + } + if (offset >= pgpt->count) { + offset -= pgpt->count; + pgpt = pgpt->next; + continue; + } + n = nbytes; + if (pgpt->count - offset < n) n = pgpt->count - offset; + memcpy(buf, pgpt->buf + offset, n); + nread += n; + buf = (char *)buf + n; + offset += n; + nbytes -= n; + } + return nread; +} + +Page * +addpage(PBuf *pb) +{ + Page *new = allocpage(); + if (pb->start == nil) pb->start = new; + if (pb->end == nil) pb->end = new; + else { + new->prev = pb->end; + pb->end->next = new; + pb->end = new; + } + pb->size += new->count; + return new; +} diff --git a/pages.h b/pages.h @@ -0,0 +1,29 @@ +// managing paginated memory buffers + +enum { + PageSize = 2048, +}; + +typedef struct Page Page; +struct Page { + Page *prev; + Page *next; + vlong count; + char *buf; +}; + +Page *allocpage(void); + +typedef struct PBuf PBuf; +struct PBuf { + Page *start; + Page *end; + vlong size; // how many bytes were allocated in total + vlong count; // how many bytes are used for storage + // count <= size +}; + +long pbwrite(PBuf *pb, void *buf, long nbytes, vlong offset); +long pbread(PBuf *pb, void *buf, long nbytes, vlong offset); + +Page * addpage(PBuf *pb);