summaryrefslogtreecommitdiff
path: root/library.c
diff options
context:
space:
mode:
Diffstat (limited to 'library.c')
-rw-r--r--library.c152
1 files changed, 150 insertions, 2 deletions
diff --git a/library.c b/library.c
index cf947cd..1ff2510 100644
--- a/library.c
+++ b/library.c
@@ -5,6 +5,7 @@
#include <stdio.h>
#include "dr_flac.h"
+#include "stb_image.h"
static unsigned hash(const char* s) {
const unsigned char* p = (const unsigned char*)s;
@@ -121,6 +122,68 @@ void flac_meta(
}
}
+void conv_art(
+ Player* p,
+ unsigned char* pixels,
+ int w,
+ int h
+) {
+ int tx, ty, i, j, k;
+ float rx, ry;
+ unsigned px;
+ rx = (float)w / (float)album_cover_w;
+ ry = (float)h / (float)album_cover_h;
+ for (j = 0; j < album_cover_h; j++) {
+ ty = (int)((float)j * ry);
+ for (i = 0; i < album_cover_w; i++) {
+ tx = (int)((float)i * rx);
+ px = 0;
+ px |= 0xff << 24;
+ k = (tx + ty * w) * 4;
+ px |= pixels[k + 0] << 16;
+ px |= pixels[k + 1] << 8;
+ px |= pixels[k + 2];
+ p->cover[i + j * album_cover_w] = px;
+ }
+ }
+ p->has_art = 1;
+}
+
+void load_cover(Player* p, const unsigned char* data, int size) {
+ unsigned char* pixels;
+ int w, h, c, rc = 4;
+ pixels = stbi_load_from_memory(
+ data,
+ size,
+ &w,
+ &h,
+ &c,
+ rc
+ );
+ conv_art(p, pixels, w, h);
+ stbi_image_free(pixels);
+}
+
+void art_meta(
+ void* uptr,
+ drflac_metadata* m
+) {
+ switch (m->type) {
+ case DRFLAC_METADATA_BLOCK_TYPE_PICTURE:
+ if (
+ m->data.picture.type ==
+ DRFLAC_PICTURE_TYPE_COVER_FRONT
+ ) {
+ load_cover(
+ uptr,
+ m->data.picture.pPictureData,
+ m->data.picture.pictureDataSize
+ );
+ }
+ break;
+ }
+}
+
int get_song_meta(const char* path, Song* s) {
drflac* f;
f = drflac_open_file_with_metadata(
@@ -147,12 +210,15 @@ int sound_mix(
int r;
(void)size;
p = uptr;
+ if (!p->play) return 0;
f = p->f;
r = drflac_read_pcm_frames_s32(
f,
size / p->channels / 4,
(int*)buf
);
+ if (!r) p->play = 0;
+ p->cs += r;
return r * p->channels * 4;
}
@@ -162,20 +228,80 @@ void init_player(Player* p) {
p->play = 0;
}
+void try_load_art(Player* p) {
+ const char* const tt[] = {
+ "cover.jpg",
+ "cover.png",
+ "Cover.jpg",
+ "Cover.png",
+ "folder.jpg",
+ "Folder.jpg",
+ "folder.png",
+ "Folder.png",
+ "../cover.jpg",
+ "../cover.png",
+ "../Cover.jpg",
+ "../Cover.png",
+ "../folder.jpg",
+ "../Folder.jpg",
+ "../folder.png",
+ "../Folder.png"
+ };
+ unsigned char* pixels;
+ int w, h, c, rc = 4, end, i, len;
+ char buf[256];
+ char* start;
+ strcpy(buf, p->song->path);
+ len = strlen(buf);
+ while (len > 0 && buf[len] != '/') {
+ buf[len] = 0;
+ len--;
+ }
+ end = sizeof tt / sizeof *tt;
+ for (i = 0; i < end; i++) {
+ start = buf + len;
+ strcat(start, tt[i]);
+ pixels = stbi_load(
+ buf,
+ &w,
+ &h,
+ &c,
+ rc
+ );
+ if (pixels) {
+ conv_art(p, pixels, w, h);
+ stbi_image_free(pixels);
+ return;
+ }
+ buf[len + 1] = 0;
+ }
+}
+
void play_song(Player* p, Song* song) {
drflac* f;
int sr, channels;
- f = drflac_open_file(
+ p->has_art = 0;
+ f = drflac_open_file_with_metadata(
song->path,
+ art_meta,
+ p,
0
);
/* todo errors and stuff */
if (!f) return;
+ if (p->f)
+ drflac_close(p->f);
+ stop_audio();
+ p->song = song;
channels = f->channels;
sr = f->sampleRate;
p->f = f;
p->channels = channels;
- stop_audio();
+ p->play = 1;
+ p->cs = 0;
+ p->ms = f->totalPCMFrameCount;
+ if (!p->has_art)
+ try_load_art(p);
init_audio(
p,
sr,
@@ -183,5 +309,27 @@ void play_song(Player* p, Song* song) {
);
}
+void play_seek(Player* p, float v) {
+ unsigned long long fi;
+ if (!p->song) return;
+ /* probably want to protect against overflow/error */
+ fi = (unsigned long long)((float)p->ms * v);
+ lock_audio();
+ p->cs = fi;
+ drflac_seek_to_pcm_frame(p->f, fi);
+ unlock_audio();
+}
+
+void deinit_player(Player* p) {
+ if (p->song) {
+ stop_audio();
+ wait_audio();
+ drflac_close(p->f);
+ }
+}
+
#define DR_FLAC_IMPLEMENTATION
#include "dr_flac.h"
+
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb_image.h"