appearantly this is working
This commit is contained in:
parent
c748985f3d
commit
e417ff18a0
5 changed files with 234 additions and 38 deletions
|
|
@ -5,14 +5,16 @@
|
||||||
|
|
||||||
static void* audio;
|
static void* audio;
|
||||||
pthread_mutex_t audio_mutex;
|
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) {
|
static void handler(void* handle, void* user, void* data, int frames) {
|
||||||
memset(data, 0, frames * 2 * 2);
|
memset(data, 0, frames * 2 * 2);
|
||||||
|
|
||||||
pthread_mutex_lock(&audio_mutex);
|
pthread_mutex_lock(&audio_mutex);
|
||||||
if(arrlen(queue) > 0) {
|
if(queue_seek != -1 && !paused) {
|
||||||
int from_frames = frames * queue[0].sfi.samplerate / MDEAudioRate;
|
int from_frames = frames * queue[queue_seek].sfi.samplerate / MDEAudioRate;
|
||||||
float* from = malloc(from_frames * sizeof(*from) * 2);
|
float* from = malloc(from_frames * sizeof(*from) * 2);
|
||||||
float* to = malloc(frames * sizeof(*to) * 2);
|
float* to = malloc(frames * sizeof(*to) * 2);
|
||||||
SRC_DATA d;
|
SRC_DATA d;
|
||||||
|
|
@ -22,18 +24,21 @@ static void handler(void* handle, void* user, void* data, int frames) {
|
||||||
d.data_out = to;
|
d.data_out = to;
|
||||||
d.input_frames = from_frames;
|
d.input_frames = from_frames;
|
||||||
d.output_frames = 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_simple(&d, SRC_SINC_BEST_QUALITY, 2);
|
||||||
src_float_to_short_array(to, data, frames * 2);
|
src_float_to_short_array(to, data, frames * 2);
|
||||||
queue[0].frames += f;
|
queue[queue_seek].frames += f;
|
||||||
|
|
||||||
free(from);
|
free(from);
|
||||||
free(to);
|
free(to);
|
||||||
|
|
||||||
if(f < from_frames) {
|
if(f < from_frames) {
|
||||||
arrdel(queue, 0);
|
queue_seek++;
|
||||||
|
if(queue_seek >= arrlen(queue)) {
|
||||||
|
queue_seek = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&audio_mutex);
|
pthread_mutex_unlock(&audio_mutex);
|
||||||
|
|
@ -55,5 +60,8 @@ void audio_queue(const char* path) {
|
||||||
|
|
||||||
pthread_mutex_lock(&audio_mutex);
|
pthread_mutex_lock(&audio_mutex);
|
||||||
arrput(queue, q);
|
arrput(queue, q);
|
||||||
|
if(queue_seek == -1) queue_seek = arrlen(queue) - 1;
|
||||||
|
|
||||||
|
ui_set_play_queue(arrlen(queue));
|
||||||
pthread_mutex_unlock(&audio_mutex);
|
pthread_mutex_unlock(&audio_mutex);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
101
mauplay/id3.c
Normal file
101
mauplay/id3.c
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -256,7 +256,6 @@ int main() {
|
||||||
db_scan();
|
db_scan();
|
||||||
|
|
||||||
audio_init();
|
audio_init();
|
||||||
audio_queue("test2.mp3");
|
|
||||||
|
|
||||||
MwLoop(window);
|
MwLoop(window);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,13 @@ void ui_set_genres(int v);
|
||||||
/* audio.c */
|
/* audio.c */
|
||||||
extern pthread_mutex_t audio_mutex;
|
extern pthread_mutex_t audio_mutex;
|
||||||
extern queue_t* queue;
|
extern queue_t* queue;
|
||||||
|
extern int queue_seek;
|
||||||
|
extern int paused;
|
||||||
|
|
||||||
void audio_init(void);
|
void audio_init(void);
|
||||||
void audio_queue(const char* path);
|
void audio_queue(const char* path);
|
||||||
|
|
||||||
|
/* id3.c */
|
||||||
|
unsigned char* id3_findimage(const char* path, size_t* size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
143
mauplay/ui.c
143
mauplay/ui.c
|
|
@ -8,6 +8,7 @@ static void* albums;
|
||||||
static void* artists;
|
static void* artists;
|
||||||
static void* genres;
|
static void* genres;
|
||||||
void* ui_last;
|
void* ui_last;
|
||||||
|
static int changed = 0;
|
||||||
|
|
||||||
void ui_list_reset(const char* merge) {
|
void ui_list_reset(const char* merge) {
|
||||||
void* p;
|
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) {
|
static void window_tick(MwWidget handle, void* user, void* client) {
|
||||||
pthread_mutex_lock(&audio_mutex);
|
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) {
|
if(ui_last == play_queue) {
|
||||||
pthread_mutex_unlock(&audio_mutex);
|
pthread_mutex_unlock(&audio_mutex);
|
||||||
MwDispatchUserHandler(tree, MwNactivateHandler, ui_last);
|
MwDispatchUserHandler(tree, MwNactivateHandler, ui_last);
|
||||||
pthread_mutex_lock(&audio_mutex);
|
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) {
|
buf[0] = 0;
|
||||||
MwVaApply(info,
|
strcpy(buf, db_musics[ind].title);
|
||||||
MwNtext, "",
|
strcat(buf, "\n");
|
||||||
NULL);
|
strcat(buf, db_musics[ind].artist);
|
||||||
} 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;
|
MwVaApply(info,
|
||||||
strcpy(buf, db_musics[ind].title);
|
MwNtext, buf,
|
||||||
strcat(buf, "\n");
|
NULL);
|
||||||
strcat(buf, db_musics[ind].artist);
|
MwVaApply(seekbar,
|
||||||
|
MwNmaxValue, queue[queue_seek].sfi.frames / queue[queue_seek].sfi.samplerate,
|
||||||
|
NULL);
|
||||||
|
|
||||||
MwVaApply(info,
|
free(buf);
|
||||||
MwNtext, buf,
|
} else if(queue_seek == -1) {
|
||||||
NULL);
|
MwVaApply(info,
|
||||||
MwVaApply(seekbar,
|
MwNtext, "",
|
||||||
MwNmaxValue, queue[0].sfi.frames / queue[0].sfi.samplerate,
|
NULL);
|
||||||
NULL);
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(arrlen(queue) > 0) {
|
if(arrlen(queue) > 0 && queue_seek != -1) {
|
||||||
int elsec = queue[0].frames / queue[0].sfi.samplerate;
|
int elsec = queue[queue_seek].frames / queue[queue_seek].sfi.samplerate;
|
||||||
int rmsec = (queue[0].sfi.frames / queue[0].sfi.samplerate) - elsec;
|
int rmsec = (queue[queue_seek].sfi.frames / queue[queue_seek].sfi.samplerate) - elsec;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
|
||||||
sprintf(buf, "%d:%02d", elsec / 60, elsec % 60);
|
sprintf(buf, "%d:%02d", elsec / 60, elsec % 60);
|
||||||
|
|
@ -235,9 +247,14 @@ static void window_tick(MwWidget handle, void* user, void* client) {
|
||||||
MwNtext, buf,
|
MwNtext, buf,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
MwVaApply(seekbar,
|
if(changed) {
|
||||||
MwNvalue, elsec,
|
sf_seek(queue[queue_seek].sf, (queue[queue_seek].frames = MwGetInteger(seekbar, MwNvalue) * queue[queue_seek].sfi.samplerate), SEEK_SET);
|
||||||
NULL);
|
changed = 0;
|
||||||
|
} else {
|
||||||
|
MwVaApply(seekbar,
|
||||||
|
MwNvalue, elsec,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MwVaApply(eltime,
|
MwVaApply(eltime,
|
||||||
MwNtext, "0:00",
|
MwNtext, "0:00",
|
||||||
|
|
@ -246,7 +263,65 @@ static void window_tick(MwWidget handle, void* user, void* client) {
|
||||||
MwNtext, "0:00",
|
MwNtext, "0:00",
|
||||||
NULL);
|
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);
|
pthread_mutex_unlock(&audio_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -261,6 +336,14 @@ void ui_init(void) {
|
||||||
ui_set_genres(0);
|
ui_set_genres(0);
|
||||||
|
|
||||||
ui_last = all_music;
|
ui_last = all_music;
|
||||||
|
MwAddUserHandler(list, MwNactivateHandler, list_activate, NULL);
|
||||||
MwAddUserHandler(tree, MwNactivateHandler, tree_activate, NULL);
|
MwAddUserHandler(tree, MwNactivateHandler, tree_activate, NULL);
|
||||||
MwAddUserHandler(window, MwNtickHandler, window_tick, 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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue