shithub: cuefs

ref: 3f6f039bf673f3ecaba6aa26abd3b89d363facfb
dir: cuefs/cue.c

View raw version
#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);
}