scripts

misc scripts and tools
git clone git://git.2f30.org/scripts.git
Log | Files | Refs

commit b89c0ccf95f120c45271c83f3159dfe37e82ed15
parent 518266ee6eb78ce8b616414cd7ee8f24cc3a6f8b
Author: lostd <lostd@2f30.org>
Date:   Sun Mar  8 13:10:27 +0200

Album art mpd client and merge with mpdlen

Diffstat:
mpdlen/Makefile | 7-------
mpdlen/mpdlen.c | 32--------------------------------
mpdutil/Makefile | 10++++++++++
mpdutil/mpdart.c | 261+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
mpdutil/mpdlen.c | 35+++++++++++++++++++++++++++++++++++
5 files changed, 306 insertions(+), 39 deletions(-)
diff --git a/mpdlen/Makefile b/mpdlen/Makefile @@ -1,7 +0,0 @@ -LDLIBS = -lmpdclient - -BIN = mpdlen -all: $(BIN) - -clean: - rm -f $(BIN) diff --git a/mpdlen/mpdlen.c b/mpdlen/mpdlen.c @@ -1,32 +0,0 @@ -#include <stdio.h> - -#include <mpd/client.h> - -/* usage: mpdlen [list] */ - -int -main(int argc, char *argv[]) -{ - struct mpd_connection *conn; - struct mpd_song *song; - unsigned secs = 0; - char *list = argv[1]; - - conn = mpd_connection_new(NULL, 0, 0); - - if (list != NULL) - mpd_send_list_playlist_meta(conn, list); - else - mpd_send_list_queue_meta(conn); - - while ((song = mpd_recv_song(conn)) != NULL) { - secs += mpd_song_get_duration(song); - mpd_song_free(song); - } - - mpd_connection_free(conn); - - printf("%02u:%02u:%02u\n", secs / 3600, secs % 3600 / 60, secs % 60); - - return 0; -} diff --git a/mpdutil/Makefile b/mpdutil/Makefile @@ -0,0 +1,10 @@ +#CPPFLAGS = -g -DDEBUG +CFLAGS = -I/usr/local/include +LDFLAGS = -L/usr/local/lib +LDLIBS = -lmpdclient + +BIN = mpdlen mpdart +all: $(BIN) + +clean: + rm -f $(BIN) diff --git a/mpdutil/mpdart.c b/mpdutil/mpdart.c @@ -0,0 +1,261 @@ +#include <sys/types.h> +#include <sys/time.h> + +#include <dirent.h> +#include <libgen.h> +#include <poll.h> +#include <regex.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <mpd/client.h> + +#ifdef DEBUG +#define DPRINTF printf +#define DPRINTF_D(t) printf(#t"=%d\n", t) +#define DPRINTF_U(t) printf(#t"=%u\n", t) +#define DPRINTF_S(t) printf(#t"=%s\n", t) +#else +#define DPRINTF +#define DPRINTF_D(t) +#define DPRINTF_U(t) +#define DPRINTF_S(t) +#endif + +char *musicdir = "/home/lostd/.mpd/music"; +char **imgs; +unsigned int cur; +char *defimg = "/home/lostd/.mpdart.png"; +unsigned int cyclms = 3000; +unsigned int pollms = 3000; +int change; + +char * +xdirname(const char *path) +{ + char *p, *tmp; + + tmp = strdup(path); + p = dirname(tmp); + p = strdup(p); + free(tmp); + + return p; +} + +int +imgcmp(const void *va, const void *vb) +{ + const char *a, *b; + static regex_t regex; + + a = *(const char **)va; + b = *(const char **)vb; + DPRINTF_S(a); + DPRINTF_S(b); + + /* Front covers first */ + regcomp(&regex, "cover|front", REG_NOSUB | REG_EXTENDED); + if (regexec(&regex, a, 0, NULL, 0) == 0) + return -1; + if (regexec(&regex, b, 0, NULL, 0) == 0) + return 1; + + return strcmp(a, b); +} + +void +init_imgs_default(void) +{ + DPRINTF("default\n"); + + imgs = malloc(2 * sizeof(*imgs)); + imgs[0] = strdup(defimg); + imgs[1] = NULL; + cur = 0; +} + +void +init_imgs_from_path(char *path) +{ + DIR *dirp; + struct dirent *dp; + unsigned int n = 0; + static regex_t regex; + + DPRINTF("images\n"); + + regcomp(&regex, "\\.(jpg|png|gif)$", REG_NOSUB | REG_EXTENDED); + + dirp = opendir(path); + if (dirp == NULL) + err(1, "opendir %s", path); + + while ((dp = readdir(dirp)) != NULL) { + /* Skip self and parent */ + if (strcmp(dp->d_name, ".") == 0 + || strcmp(dp->d_name, "..") == 0) + continue; + if (regexec(&regex, dp->d_name, 0, NULL, 0) != 0) + continue; + imgs = realloc(imgs, (n + 1) * sizeof(*imgs)); + asprintf(&imgs[n], "%s/%s", path, dp->d_name); + n++; + } + + qsort(imgs, n, sizeof(*imgs), imgcmp); + + /* Terminate list or set default image if empty */ + if (n > 0) { + imgs = realloc(imgs, (n + 1) * sizeof(*imgs)); + imgs[n] = NULL; + cur = 0; + } else { + init_imgs_default(); + } + + closedir(dirp); +} + +void +free_imgs(void) +{ + unsigned int i; + + for (i = 0; imgs[i] != NULL; i++) + free(imgs[i]); + free(imgs); + imgs = NULL; +} + +void +print_imgs(void) +{ + unsigned int i; + static char *oldimg = NULL; + static struct timespec tp, oldtp = { 0, 0 }; + unsigned int delta; + + clock_gettime(CLOCK_MONOTONIC, &tp); + delta = (tp.tv_sec * 1000 + tp.tv_nsec / 1000000) + - (oldtp.tv_sec * 1000 + oldtp.tv_nsec / 1000000); + + DPRINTF("delta=%u\n", delta); + + if (delta < cyclms && !change) { + pollms = cyclms - delta; + return; + } + + if (change) { + cur = 0; + change = 0; + } + + oldtp = tp; + + for (i = 0; imgs[i] != NULL; i++) + DPRINTF("%s\n", imgs[i]); + DPRINTF("i=%u cur=%u\n", i, cur); + + if (oldimg == NULL || strcmp(imgs[cur], oldimg) != 0) { + printf("%s\n", imgs[cur]); + fflush(stdout); + } + free(oldimg); + oldimg = strdup(imgs[cur]); + + cur++; + if (cur == i) + cur = 0; +} + +void +update_imgs(struct mpd_connection *conn) +{ + struct mpd_status *status; + struct mpd_song *song; + const char *name; + enum mpd_state state; + static char *path, *oldpath = NULL; + char *abspath; + + DPRINTF("update\n"); + + /* State */ + mpd_send_status(conn); + status = mpd_recv_status(conn); + state = mpd_status_get_state(status); + /* Not playing */ + if (state != MPD_STATE_PLAY && + state != MPD_STATE_PAUSE) { + DPRINTF("state\n"); + free_imgs(); + init_imgs_default(); + mpd_status_free(status); + free(oldpath); + oldpath = NULL; + change = 1; + return; + } + mpd_response_finish(conn); + + /* Song */ + mpd_send_current_song(conn); + song = mpd_recv_song(conn); + name = mpd_song_get_uri(song); + path = xdirname(name); + /* Album change */ + if (oldpath == NULL || strcmp(path, oldpath) != 0) { + DPRINTF("song\n"); + DPRINTF("path=%s oldpath=%s\n", path, oldpath); + asprintf(&abspath, "%s/%s", musicdir, path); + free_imgs(); + init_imgs_from_path(abspath); + free(abspath); + change = 1; + } + free(oldpath); + oldpath = strdup(path); + mpd_song_free(song); + mpd_response_finish(conn); +} + +int +main(int argc, char *argv[]) +{ + struct mpd_connection *conn; + struct pollfd fds[1]; + + conn = mpd_connection_new(NULL, 0, 0); + if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) + err(1, "mpd_connection_new"); + + fds[0].fd = mpd_connection_get_fd(conn); + fds[0].events = POLLIN; + + init_imgs_default(); + + for (;;) { + /* Update images if needed */ + update_imgs(conn); + + /* Print next image on change or timeout */ + print_imgs(); + + /* Wait for a player change */ + mpd_send_idle_mask(conn, MPD_IDLE_PLAYER); + poll(fds, 1, pollms); + mpd_send_noidle(conn); + mpd_response_finish(conn); + + DPRINTF("poll\n"); + } + + mpd_connection_free(conn); + + return 0; +} diff --git a/mpdutil/mpdlen.c b/mpdutil/mpdlen.c @@ -0,0 +1,35 @@ +#include <stdio.h> + +#include <mpd/client.h> + +/* usage: mpdlen [list] */ + +int +main(int argc, char *argv[]) +{ + struct mpd_connection *conn; + struct mpd_song *song; + unsigned secs = 0; + char *list = argv[1]; + + conn = mpd_connection_new(NULL, 0, 0); + + if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) + err(1, "mpd_connection_new"); + + if (list != NULL) + mpd_send_list_playlist_meta(conn, list); + else + mpd_send_list_queue_meta(conn); + + while ((song = mpd_recv_song(conn)) != NULL) { + secs += mpd_song_get_duration(song); + mpd_song_free(song); + } + + mpd_connection_free(conn); + + printf("%02u:%02u:%02u\n", secs / 3600, secs % 3600 / 60, secs % 60); + + return 0; +}