From e417ff18a02f1fce784e9d2f5620c6574e802e76 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Mon, 24 Nov 2025 16:21:56 +0900 Subject: [PATCH] appearantly this is working --- mauplay/audio.c | 22 ++++--- mauplay/id3.c | 101 ++++++++++++++++++++++++++++++++ mauplay/main.c | 1 - mauplay/mauplay.h | 5 ++ mauplay/ui.c | 143 ++++++++++++++++++++++++++++++++++++---------- 5 files changed, 234 insertions(+), 38 deletions(-) create mode 100644 mauplay/id3.c diff --git a/mauplay/audio.c b/mauplay/audio.c index b945d8a..e92f591 100644 --- a/mauplay/audio.c +++ b/mauplay/audio.c @@ -5,14 +5,16 @@ static void* audio; pthread_mutex_t audio_mutex; -queue_t* queue = NULL; +queue_t* queue = NULL; +int queue_seek = -1; +int paused = 0; static void handler(void* handle, void* user, void* data, int frames) { memset(data, 0, frames * 2 * 2); pthread_mutex_lock(&audio_mutex); - if(arrlen(queue) > 0) { - int from_frames = frames * queue[0].sfi.samplerate / MDEAudioRate; + if(queue_seek != -1 && !paused) { + int from_frames = frames * queue[queue_seek].sfi.samplerate / MDEAudioRate; float* from = malloc(from_frames * sizeof(*from) * 2); float* to = malloc(frames * sizeof(*to) * 2); SRC_DATA d; @@ -22,18 +24,21 @@ static void handler(void* handle, void* user, void* data, int frames) { d.data_out = to; d.input_frames = from_frames; d.output_frames = frames; - d.src_ratio = (double)MDEAudioRate / queue[0].sfi.samplerate; + d.src_ratio = (double)MDEAudioRate / queue[queue_seek].sfi.samplerate; - f = sf_readf_float(queue[0].sf, from, from_frames); + f = sf_readf_float(queue[queue_seek].sf, from, from_frames); src_simple(&d, SRC_SINC_BEST_QUALITY, 2); src_float_to_short_array(to, data, frames * 2); - queue[0].frames += f; + queue[queue_seek].frames += f; free(from); free(to); if(f < from_frames) { - arrdel(queue, 0); + queue_seek++; + if(queue_seek >= arrlen(queue)) { + queue_seek = -1; + } } } pthread_mutex_unlock(&audio_mutex); @@ -55,5 +60,8 @@ void audio_queue(const char* path) { pthread_mutex_lock(&audio_mutex); arrput(queue, q); + if(queue_seek == -1) queue_seek = arrlen(queue) - 1; + + ui_set_play_queue(arrlen(queue)); pthread_mutex_unlock(&audio_mutex); } diff --git a/mauplay/id3.c b/mauplay/id3.c new file mode 100644 index 0000000..e5fb523 --- /dev/null +++ b/mauplay/id3.c @@ -0,0 +1,101 @@ +#include "mauplay.h" + +static unsigned int syncsafe(FILE* f) { + unsigned char d[4]; + unsigned int r = 0; + int i; + fread(d, 4, 1, f); + + for(i = 0; i < 4; i++) { + r = r << 7; + r = r | (d[i] & 127); + } + + return r; +} + +static unsigned int big(FILE* f) { + unsigned char d[4]; + unsigned int r = 0; + int i; + fread(d, 4, 1, f); + + for(i = 0; i < 4; i++) { + r = r << 8; + r = r | d[i]; + } + + return r; +} + +unsigned char* id3_findimage(const char* path, size_t* size) { + FILE* f = fopen(path, "rb"); + unsigned char* d = NULL; + char sig[3]; + unsigned char ver[2]; + unsigned char flag; + unsigned char frame[4]; + unsigned int dsz = 0; + if(f == NULL) return NULL; + + fread(sig, 3, 1, f); + if(memcmp(sig, "ID3", 3) != 0) return NULL; + + fread(ver, 2, 1, f); + if(memcmp(ver, "\x04\x00", 2) != 0 && memcmp(ver, "\x03\x00", 2) != 0) return NULL; + + fread(&flag, 1, 1, f); + if(flag & (1 << 6)) return NULL; /* FIXME */ + if(flag & (1 << 7)) return NULL; /* what even is this??? */ + + dsz = syncsafe(f); + + while(dsz > 0) { + unsigned int fsz; + + fread(frame, 4, 1, f); + if(frame[0] == 0) break; /* XXX: Is this ok? */ + + if(memcmp(ver, "\x04\x00", 2) == 0) { + fsz = syncsafe(f); + } else { + fsz = big(f); + } + + fseek(f, 2, SEEK_CUR); + if(memcmp(frame, "APIC", 4) == 0) { + unsigned char* buffer = malloc(fsz); + int i; + fread(buffer, fsz, 1, f); + for(i = 1; i < fsz; i++) { + if(buffer[i] == 0) break; + } + i++; + /* XXX: 0 is technically Other - am not sure if this should be done... */ + if(buffer[i] == 0 || buffer[i] == 3) { + int count = (buffer[0] == 1 || buffer[0] == 2) ? 2 : 1; + + i++; + + for(; i < fsz; i++) { + if(buffer[i] == 0) count--; + if(count == 0) break; + } + i++; + d = malloc(fsz - i); + memcpy(d, buffer + i, fsz - i); + *size = fsz - i; + } + free(buffer); + if(d != NULL) break; + } else { + fseek(f, fsz, SEEK_CUR); + } + + dsz -= 4 + 4 + 2 + fsz; + } + + fclose(f); + + return d; +} diff --git a/mauplay/main.c b/mauplay/main.c index 955e88f..c0175ab 100644 --- a/mauplay/main.c +++ b/mauplay/main.c @@ -256,7 +256,6 @@ int main() { db_scan(); audio_init(); - audio_queue("test2.mp3"); MwLoop(window); } diff --git a/mauplay/mauplay.h b/mauplay/mauplay.h index 7a6ba1d..6fef90a 100644 --- a/mauplay/mauplay.h +++ b/mauplay/mauplay.h @@ -70,8 +70,13 @@ void ui_set_genres(int v); /* audio.c */ extern pthread_mutex_t audio_mutex; extern queue_t* queue; +extern int queue_seek; +extern int paused; void audio_init(void); void audio_queue(const char* path); +/* id3.c */ +unsigned char* id3_findimage(const char* path, size_t* size); + #endif diff --git a/mauplay/ui.c b/mauplay/ui.c index 32dd313..5612236 100644 --- a/mauplay/ui.c +++ b/mauplay/ui.c @@ -8,6 +8,7 @@ static void* albums; static void* artists; static void* genres; void* ui_last; +static int changed = 0; void ui_list_reset(const char* merge) { void* p; @@ -184,45 +185,56 @@ static void tree_activate(MwWidget handle, void* user, void* client) { } } -int queue_last = 0; +static void list_activate(MwWidget handle, void* user, void* client) { + if(ui_last == play_queue) { + pthread_mutex_lock(&audio_mutex); + queue_seek = (*(int*)client) - 1; + queue[queue_seek].frames = 0; + sf_seek(queue[queue_seek].sf, 0, SEEK_SET); + pthread_mutex_unlock(&audio_mutex); + } else if(ui_last == all_music) { + audio_queue(db_musics[(*(int*)client) - 1].key); + } +} + +int queue_last = -1; static void window_tick(MwWidget handle, void* user, void* client) { pthread_mutex_lock(&audio_mutex); - if(queue_last != arrlen(queue)) { + if(queue_last != queue_seek && queue_seek != -1) { + int ind; + char* buf; + if(ui_last == play_queue) { pthread_mutex_unlock(&audio_mutex); MwDispatchUserHandler(tree, MwNactivateHandler, ui_last); pthread_mutex_lock(&audio_mutex); } - ui_set_play_queue(arrlen(queue)); + ind = shgeti(db_musics, queue[queue_seek].path); + buf = malloc(strlen(db_musics[ind].title) + 1 + strlen(db_musics[ind].artist) + 1); - if(arrlen(queue) == 0) { - MwVaApply(info, - MwNtext, "", - NULL); - } else { - int ind = shgeti(db_musics, queue[0].path); - char* buf = malloc(strlen(db_musics[ind].title) + 1 + strlen(db_musics[ind].artist) + 1); + buf[0] = 0; + strcpy(buf, db_musics[ind].title); + strcat(buf, "\n"); + strcat(buf, db_musics[ind].artist); - buf[0] = 0; - strcpy(buf, db_musics[ind].title); - strcat(buf, "\n"); - strcat(buf, db_musics[ind].artist); + MwVaApply(info, + MwNtext, buf, + NULL); + MwVaApply(seekbar, + MwNmaxValue, queue[queue_seek].sfi.frames / queue[queue_seek].sfi.samplerate, + NULL); - MwVaApply(info, - MwNtext, buf, - NULL); - MwVaApply(seekbar, - MwNmaxValue, queue[0].sfi.frames / queue[0].sfi.samplerate, - NULL); - - free(buf); - } + free(buf); + } else if(queue_seek == -1) { + MwVaApply(info, + MwNtext, "", + NULL); } - if(arrlen(queue) > 0) { - int elsec = queue[0].frames / queue[0].sfi.samplerate; - int rmsec = (queue[0].sfi.frames / queue[0].sfi.samplerate) - elsec; + if(arrlen(queue) > 0 && queue_seek != -1) { + int elsec = queue[queue_seek].frames / queue[queue_seek].sfi.samplerate; + int rmsec = (queue[queue_seek].sfi.frames / queue[queue_seek].sfi.samplerate) - elsec; char buf[64]; sprintf(buf, "%d:%02d", elsec / 60, elsec % 60); @@ -235,9 +247,14 @@ static void window_tick(MwWidget handle, void* user, void* client) { MwNtext, buf, NULL); - MwVaApply(seekbar, - MwNvalue, elsec, - NULL); + if(changed) { + sf_seek(queue[queue_seek].sf, (queue[queue_seek].frames = MwGetInteger(seekbar, MwNvalue) * queue[queue_seek].sfi.samplerate), SEEK_SET); + changed = 0; + } else { + MwVaApply(seekbar, + MwNvalue, elsec, + NULL); + } } else { MwVaApply(eltime, MwNtext, "0:00", @@ -246,7 +263,65 @@ static void window_tick(MwWidget handle, void* user, void* client) { MwNtext, "0:00", NULL); } - queue_last = arrlen(queue); + queue_last = queue_seek; + pthread_mutex_unlock(&audio_mutex); +} + +static void seekbar_changed(MwWidget handle, void* user, void* client) { + changed = 1; +} + +static void bskipback_activate(MwWidget handle, void* user, void* client) { + pthread_mutex_lock(&audio_mutex); + if(queue_seek == -1) { + queue_seek = 0; + } else { + if(queue_seek > 0) queue_seek--; + } + if(arrlen(queue) > 0) { + queue[queue_seek].frames = 0; + sf_seek(queue[queue_seek].sf, 0, SEEK_SET); + } else { + queue_seek = -1; + } + pthread_mutex_unlock(&audio_mutex); +} + +static void bplay_activate(MwWidget handle, void* user, void* client) { + pthread_mutex_lock(&audio_mutex); + paused = 0; + pthread_mutex_unlock(&audio_mutex); +} + +static void bpause_activate(MwWidget handle, void* user, void* client) { + pthread_mutex_lock(&audio_mutex); + paused = 1; + pthread_mutex_unlock(&audio_mutex); +} + +static void bstop_activate(MwWidget handle, void* user, void* client) { + pthread_mutex_lock(&audio_mutex); + if(queue_seek != -1) { + queue[queue_seek].frames = 0; + sf_seek(queue[queue_seek].sf, 0, SEEK_SET); + } + queue_seek = -1; + pthread_mutex_unlock(&audio_mutex); +} + +static void bskipfwd_activate(MwWidget handle, void* user, void* client) { + pthread_mutex_lock(&audio_mutex); + if(queue_seek == -1) { + queue_seek = 0; + } else { + if(queue_seek < (arrlen(queue) - 1)) queue_seek++; + } + if(arrlen(queue) > 0) { + queue[queue_seek].frames = 0; + sf_seek(queue[queue_seek].sf, 0, SEEK_SET); + } else { + queue_seek = -1; + } pthread_mutex_unlock(&audio_mutex); } @@ -261,6 +336,14 @@ void ui_init(void) { ui_set_genres(0); ui_last = all_music; + MwAddUserHandler(list, MwNactivateHandler, list_activate, NULL); MwAddUserHandler(tree, MwNactivateHandler, tree_activate, NULL); MwAddUserHandler(window, MwNtickHandler, window_tick, NULL); + MwAddUserHandler(seekbar, MwNchangedHandler, seekbar_changed, NULL); + + MwAddUserHandler(bskipback, MwNactivateHandler, bskipback_activate, NULL); + MwAddUserHandler(bplay, MwNactivateHandler, bplay_activate, NULL); + MwAddUserHandler(bpause, MwNactivateHandler, bpause_activate, NULL); + MwAddUserHandler(bstop, MwNactivateHandler, bstop_activate, NULL); + MwAddUserHandler(bskipfwd, MwNactivateHandler, bskipfwd_activate, NULL); }