#include "library.h" #include "plat.h" #include #include #include "dr_flac.h" static unsigned hash(const char* s) { const unsigned char* p = (const unsigned char*)s; unsigned h = 2166136261; while (*p) h = (h ^ *p++) * 16777619; return h; } Song* find_song(Library* l, const char* path) { int i = hash(path) % l->cap; int c; Song* s; for (c = 0; c < l->cap; c++) { s = &l->songs[i]; if (!s->path[0] || !strcmp(path, s->path)) return s; i++; i %= l->cap; } return 0; } static void cap_iter( void* uptr, const char* path ) { Library* lib = uptr; (void)path; lib->cap++; } static void adder_iter( void* uptr, const char* path ) { Song* s; Library* lib = uptr; s = find_song(lib, path); if (get_song_meta(path, s)) { strcpy(s->path, path); lib->indices[lib->cnt++] = s - lib->songs; } } void build_library( Arena* a, Library* lib, const char* path ) { int i; lib->cnt = lib->cap = 0; iter_dir(path, cap_iter, lib); lib->cap += 16; lib->songs = arena_alloc( a, lib->cap * sizeof *lib->songs ); lib->indices = arena_alloc( a, lib->cap * sizeof *lib->indices ); for (i = 0; i < lib->cap; i++) lib->songs[i].path[0] = 0; iter_dir(path, adder_iter, lib); } void parse_vorbis_comment( Song* s, const char* com, int len ) { /* this is not safe xDDDD idrc */ if (len > 64) { len = 64; } if (!memcmp(com, "ARTIST=", 7)) { len -= 7; memcpy(s->artist, com + 7, len); s->artist[len] = 0; } else if (!memcmp(com, "TITLE=", 6)) { len -= 6; memcpy(s->name, com + 6, len); s->name[len] = 0; } else if (!memcmp(com, "ALBUM=", 6)) { len -= 6; memcpy(s->album, com + 6, len); s->album[len] = 0; } } void flac_meta( void* uptr, drflac_metadata* m ) { Song* s = uptr; drflac_vorbis_comment_iterator i; drflac_uint32 len; const char* c; int size; switch (m->type) { case DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT: drflac_init_vorbis_comment_iterator( &i, m->data.vorbis_comment.commentCount, m->data.vorbis_comment.pComments ); while ((c = drflac_next_vorbis_comment( &i, &len ))) { parse_vorbis_comment(s, c, len); } break; } } int get_song_meta(const char* path, Song* s) { drflac* f; f = drflac_open_file_with_metadata( path, flac_meta, s, 0 ); if (f) { drflac_close(f); return 1; } s->path[0] = 0; return 0; } #define DR_FLAC_IMPLEMENTATION #include "dr_flac.h"