ref: adb84ba1604eca9fbacc16b1eede182a107562ca
parent: 448e84898530e6f597db845c72ea66e372374558
author: Tevo <estevan.cps@gmail.com>
date: Wed Dec 23 19:04:34 EST 2020
Fix timestamps, don't allow reads after the end of the song
--- /dev/null
+++ b/BUGS
@@ -1,0 +1,4 @@
+• unsure if seeking on a file works correctly
+• crashes on unmount (buffer overflow caught by free())
+• current treatment of lossy sources is less than ideal
+• can only serve .wav and raw pcm files (no flac encoder)
--- a/cue.c
+++ b/cue.c
@@ -48,7 +48,11 @@
if(cur == nil)
return;
recfreeentries(s, cur->next);
- maybefree(nil, cur->starts);
+ for(Start *s = cur->starts; s != nil; s = cur->starts)
+ {
+ cur->starts = s->next;
+ free(s);
+ }
/* file should get freed by the cuesheet */
maybefree(nil, cur->title);
maybefree(s->performer, cur->performer);
@@ -103,15 +107,6 @@
}
void
-atleast(Timestamps *ts, int val)
-{
- if(ts->maxindex > val)
- return;
- ts->starts = erealloc(ts->starts, (val+1) * sizeof(*ts->starts));
- ts->maxindex = val;
-}
-
-void
setperformer(Cuesheet *c, char *artist)
{
artist = strdup(artist);
@@ -175,12 +170,28 @@
void
settimestamp(Cuesheet *c, int i, Timestamp t)
{
+ Start *entry, *before;
+
if(c->curentry == nil)
parserfatal("timestamp outside of track");
- atleast(c->curentry, i);
debug("setting timestamp[%d] for %d as %ud frames\n", i, c->curentry->index, t.frames);
- c->curentry->starts[i] = t;
+
+ entry = emallocz(sizeof(*entry), 1);
+ entry->Timestamp = t;
+ entry->index = i;
+
+ before = nil;
+
+ if(c->curentry->starts == nil)
+ c->curentry->starts = entry;
+ else
+ {
+ for(Start *s = c->curentry->starts; s != nil && s->index < i; s++)
+ before = s;
+ entry->next = before->next;
+ before->next = entry;
+ }
}
char*
--- a/cuefs.h
+++ b/cuefs.h
@@ -47,15 +47,16 @@
char *name;
} AFile;
-typedef struct
+typedef struct Start
{
- Timestamp *starts;
- u8int maxindex;
-} Timestamps;
+ Timestamp;
+ u8int index;
+ struct Start *next;
+} Start;
typedef struct Entry
{
- Timestamps;
+ Start *starts;
AFile *file;
int index;
char *title, *performer;
--- a/fs.c
+++ b/fs.c
@@ -15,7 +15,7 @@
typedef struct
{
int fd, pid;
- vlong curoff;
+ vlong curoff, end;
} Decoder;
void pcmserve(Entry*, Req*);
@@ -35,8 +35,12 @@
[WAVE] = "audio/wavdec"
};
+/*
+ * FIXME find a better way to signal decoder failure,
+ * one that we can answer the Tread with
+ */
Decoder*
-pipedec(AFile *f, double sec, vlong off)
+pipedec(AFile *f, double sec, vlong off, vlong end)
{
Decoder *ret;
int fd[2], afd;
@@ -52,6 +56,7 @@
ret = emalloc(sizeof(*ret));
ret->fd = fd[0];
ret->curoff = off;
+ ret->end = end;
switch(ret->pid = rfork(RFPROC|RFFDG|RFREND|RFNOTEG))
{
@@ -110,8 +115,17 @@
long
readdec(Decoder *dec, void *buf, long count)
{
- long ret;
+ long ret, n;
+ debug("readdec: decoder offset = %lld, decoder end = %lld, count = %ld\n",
+ dec->curoff, dec->end, count);
+
+ n = dec->end - dec->curoff + count;
+ if(n < 0)
+ count += n;
+
+ debug("reading %ld bytes from pid %d\n", count, dec->pid);
+
ret = read(dec->fd, buf, count);
dec->curoff += ret;
@@ -123,13 +137,22 @@
{
Decoder *dec;
double sec;
+ long end;
sec = t2sec(e->starts[0]) + of2sec(44100, 16, 2, r->ifcall.offset);
+ /*
+ * wouldn't be that bad to just read and throw away a little of the
+ * decoded pcm if r->ifcall.offset isn't that far from dec->curoff
+ */
if((dec = r->fid->aux) == nil || dec->curoff != r->ifcall.offset)
{
+ /* amount of samples between songs... */
+ end = (e->next->starts->frames - e->starts->frames) * (44100/75);
+ /* ...*2 channels, 2 bytes per sample */
+ end *= 2*2;
closedec(dec);
- dec = r->fid->aux = pipedec(e->file, sec, r->ifcall.offset);
+ dec = r->fid->aux = pipedec(e->file, sec, r->ifcall.offset, end);
}
r->ofcall.count = readdec(dec, r->ofcall.data, r->ifcall.count);