ref: 3f6f039bf673f3ecaba6aa26abd3b89d363facfb
dir: /cue.c/
#include <u.h>
#include <libc.h>
#include "cuefs.h"
#include "y.tab.h"
Timestamp
parsetime(int min, int sec, int frames)
{
sec += min*60;
frames += sec*75;
return (Timestamp){frames};
}
double
t2sec(Timestamp t)
{
return (double)t.frames/75.0;
}
Cuesheet*
newsheet(void)
{
return emallocz(sizeof(Cuesheet), 1);
}
void
maybefree(void *s, void *p)
{
if(p != nil && p != s)
free(p);
}
void
recfreeentries(Cuesheet *s, Entry *cur)
{
if(cur == nil)
return;
recfreeentries(s, cur->next);
maybefree(nil, cur->starts);
/* file should get freed by the cuesheet */
maybefree(nil, cur->title);
maybefree(s->performer, cur->performer);
}
void
recfreefiles(Cuesheet *s, AFile *cur)
{
if(cur == nil)
return;
recfreefiles(s, cur->next);
maybefree(nil, cur->name);
if(cur->fd >= 0)
close(cur->fd);
}
void
freesheet(Cuesheet *s)
{
recfreeentries(s, s->entries);
recfreefiles(s, s->files);
maybefree(nil, s->title);
maybefree(nil, s->performer);
}
AFile*
lastfile(Cuesheet *c)
{
if(c->files == nil)
return nil;
if(c->curfile == nil)
c->curfile = c->files;
while(c->curfile->next != nil)
c->curfile = c->curfile->next;
return c->curfile;
}
Entry*
lastentry(Cuesheet *c)
{
if(c->entries == nil)
return nil;
if(c->curentry == nil)
c->curentry = c->entries;
while(c->curentry->next != nil)
c->curentry = c->curentry->next;
return c->curentry;
}
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);
if(c->curentry == nil)
setstr(nil, &c->performer, artist);
else
setstr(c->performer, &c->curentry->performer, artist);
}
void
settitle(Cuesheet *c, char *title)
{
title = strdup(title);
if(c->curentry == nil)
setstr(nil, &c->title, title);
else
setstr(nil, &c->curentry->title, title);
}
void
addfile(Cuesheet *c, char *name, int format)
{
AFile *new;
lastfile(c);
new = emalloc(sizeof(*new));
new->name = strdup(name);
new->type = format;
new->actual = actualformat(new);
new->next = nil;
new->fd = -1;
if(c->files == nil)
c->files = new;
else
c->curfile->next = new;
c->curfile = new;
}
void
addnewtrack(Cuesheet *c, int i)
{
Entry *new;
lastentry(c);
new = emallocz(sizeof(*new), 1);
new->file = c->curfile;
new->performer = c->performer;
new->index = i;
if(c->entries == nil)
c->entries = new;
else
c->curentry->next = new;
c->curentry = new;
}
void
settimestamp(Cuesheet *c, int i, Timestamp t)
{
if(c->curentry == nil)
parserfatal("timestamp outside of track");
atleast(c->curentry, i);
c->curentry->starts[i] = t;
}
char*
extension(char *f)
{
char *ext = "";
for(char *c = f; *c != 0; c++)
if(*c == '.')
ext = c+1;
return ext;
}
int
actualformat(AFile *f)
{
char *ext;
if(f->type != WAVE)
return f->type;
ext = extension(f->name);
if(strcmp(ext, "wav") == 0)
return WAVE;
if(strcmp(ext, "flac") == 0 || strcmp(ext, "fla") == 0)
return FLAC;
return UNKNOWN;
}
char*
formatext(AFile *f)
{
char *tab[] =
{
[MP3] = "mp3",
[AIFF] = "aiff",
[BINARY] = "bin",
[MOTOROLA] = "" /* not sure */
};
if(f->type != WAVE)
return tab[f->type];
return extension(f->name);
}