ref: b7a4f1e6e70cb97de31ec684d243825e395fe001
dir: /dir.c/
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <draw.h>
#include "dat.h"
#include "fncs.h"
Song*
file2song(char *path, int needpic)
{
char *dot;
Song *s;
int fd;
dot = strrchr(path, '.');
if(dot == nil)
return nil;
dot+=1;
s = emalloc(sizeof(Song));
if(strcmp(dot, "flac") == 0){
s->type = FLAC;
goto done;
}
if(strcmp(dot, "mp3") == 0){
s->type = MP3;
goto done;
}
if(strcmp(dot, "ogg") == 0){
s->type = VORBIS;
goto done;
}
/* Unsupported file suffix */
goto error;
done:
fd = open(path, OREAD);
if(fd < 0)
goto error;
switch(s->type){
case FLAC:
s->fmeta = readflacmeta(fd, needpic);
break;
case MP3:
s->idmeta = readid3(fd);
break;
case VORBIS:
/* TODO parse raw ogg file */
break;
}
close(fd);
/* We can check the pointer without having to worry about which one it is */
if(s->fmeta == nil)
goto error;
return s;
error:
free(s);
return nil;
}
void
dir2album(Album *a, char *path)
{
Dir *files;
int fd;
long n;
long i;
char *dot;
Rune *albumtitle;
char buf[512];
int songcount = 0;
int needpic = 1;
fd = open(path, OREAD);
if(fd < 0)
return;
n = dirreadall(fd, &files);
close(fd);
if(n <= 0)
return;
/* Do a single pass to find cover.^(jp^(eg g) png) */
for(i=0;i<n;i++){
dot = cistrstr(files[i].name, "cover.");
if(dot == nil){
dot = cistrstr(files[i].name, "folder.");
if(dot == nil)
continue;
}
dot = strrchr(dot, '.');
dot++;
snprint(buf, 512, "%s/%s", path, files[i].name);
fd = open(buf, OREAD);
if(fd<0)
continue;
a->cover = convpic(fd, dot);
if(a->cover != nil){
needpic = 0;
close(fd);
break;
}
close(fd);
}
/* Greedy alloc to start, we will trim down later */
a->nsong = n;
a->songs = emalloc(sizeof(Song*) * n);
for(i=0;i<n;i++){
snprint(buf, 512, "%s/%s", path, files[i].name);
a->songs[songcount] = file2song(buf, needpic);
if(a->songs[songcount] == nil)
continue;
if(a->name == nil){
switch(a->songs[songcount]->type){
case FLAC:
albumtitle = a->songs[songcount]->fmeta->com->album;
break;
case MP3:
albumtitle = a->songs[songcount]->idmeta->album;
break;
case VORBIS:
albumtitle = a->songs[songcount]->vmeta->album;
break;
default:
albumtitle = nil;
}
if(albumtitle != nil)
a->name = runesmprint("%S", albumtitle);
}
a->songs[songcount]->path = strdup(buf);
if(needpic == 1 && a->songs[songcount]->type == FLAC && a->songs[songcount]->fmeta->pic != nil){
FlacPic *p = a->songs[songcount]->fmeta->pic;
a->cover = convpicbuf(p->data, p->size, p->mime);
if(a->cover == nil)
quit("dir2album: Could not convert image");
needpic--;
}
songcount++;
}
a->nsong = songcount;
a->songs = realloc(a->songs, sizeof(Song*) * songcount);
free(files);
return;
}
int
parselibrary(Album **als, char *path)
{
Dir *files;
int fd;
uint n, i;
uint numdirs = 0;
uint alcount = 0;
char buf[512];
fd = open(path, OREAD);
if(fd < 0)
return 0;
n = dirreadall(fd, &files);
close(fd);
if(n <= 0)
return 0;
for(i=0;i<n;i++)
if(files[i].qid.type&QTDIR)
numdirs++;
*als = emalloc(sizeof(Album)*numdirs);
for(i=0;i<n;i++)
if(files[i].qid.type&QTDIR){
snprint(buf, 512, "%s/%s", path, files[i].name);
dir2album(*als+alcount, buf);
if(*als+alcount != nil)
alcount++;
}
*als = realloc(*als, sizeof(Album)*alcount);
return alcount;
}