From 53787fc71e98f49cdae4fa8ceddc7b2182649abc Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Tue, 21 Apr 2015 11:21:55 +0200 Subject: use libav/ffmpeg to get artwork from mp3 files --- Makefile | 1 + mpd-notification.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- mpd-notification.h | 6 +++++ 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 3ac2764..9bb5297 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ RM := rm CFLAGS += -std=c11 -O2 -Wall -Werror CFLAGS += $(shell pkg-config --cflags --libs libmpdclient) CFLAGS += $(shell pkg-config --cflags --libs libnotify) +CFLAGS += $(shell pkg-config --cflags --libs libavcodec libavformat) # this is just a fallback in case you do not use git but downloaded # a release tarball... VERSION := 0.5.2 diff --git a/mpd-notification.c b/mpd-notification.c index 1a7dec2..856f8b0 100644 --- a/mpd-notification.c +++ b/mpd-notification.c @@ -54,13 +54,71 @@ void received_signal(int signal) { } } +/*** retrieve_album_art ***/ +char * retrieve_album_art(const char *path) { + int i, ret = 0; + FILE * album_art; + char * album_art_file = NULL; + AVPacket pkt; + AVFormatContext * pFormatCtx = NULL; + + album_art_file = malloc(strlen(PROGNAME) + 15); + sprintf(album_art_file, "/tmp/.%s-%d", PROGNAME, getpid()); + + pFormatCtx = avformat_alloc_context(); + + if (avformat_open_input(&pFormatCtx, path, NULL, NULL) != 0) { + printf("avformat_open_input() failed"); + goto fail; + } + + /* only mp3 file contain artwork, so ignore others */ + if (strcmp(pFormatCtx->iformat->name, "mp3") != 0) + goto fail; + + if (pFormatCtx->iformat->read_header(pFormatCtx) < 0) { + printf("could not read the format header\n"); + goto fail; + } + + /* find the first attached picture, if available */ + for (i = 0; i < pFormatCtx->nb_streams; i++) { + if (pFormatCtx->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) { + pkt = pFormatCtx->streams[i]->attached_pic; + album_art = fopen(album_art_file, "wb"); + ret = fwrite(pkt.data, pkt.size, 1, album_art); + fclose(album_art); + break; + } + } + +fail: + if (pFormatCtx) + avformat_free_context(pFormatCtx); + + if (ret) { + return album_art_file; + } else { + free(album_art_file); + return NULL; + } +} + /*** get_icon ***/ char * get_icon(const char * music_dir, const char * uri) { - char * icon = NULL, * uri_dirname; + char * icon = NULL, * uri_path = NULL, * uri_dirname = NULL; DIR * dir; struct dirent * entry; regex_t regex; + /* try album artwork first */ + uri_path = malloc(strlen(music_dir) + strlen(uri) + 2); + sprintf(uri_path, "%s/%s", music_dir, uri); + icon = retrieve_album_art(uri_path); + + if (icon != NULL) + goto found; + uri_dirname = strdup(uri); /* cut the dirname or just use "." (string, not char!) for current directory */ @@ -93,7 +151,11 @@ char * get_icon(const char * music_dir, const char * uri) { regfree(®ex); closedir(dir); - free(uri_dirname); +found: + if (uri_path) + free(uri_path); + if (uri_dirname) + free(uri_dirname); return icon; } @@ -164,6 +226,9 @@ int main(int argc, char ** argv) { } } + /* libav */ + av_register_all(); + conn = mpd_connection_new(mpd_host, mpd_port, mpd_timeout); if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { diff --git a/mpd-notification.h b/mpd-notification.h index 29cf0f2..c991fd1 100644 --- a/mpd-notification.h +++ b/mpd-notification.h @@ -14,6 +14,9 @@ #include +#include +#include + #include #include #include @@ -30,6 +33,9 @@ /*** received_signal ***/ void received_signal(int signal); +/*** retrieve_album_art ***/ +char * retrieve_album_art(const char *path); + /*** get_icon ***/ char * get_icon(const char * music_dir, const char * uri); -- cgit v1.2.3-54-g00ecf