From da1bcb7a33d75a9f56012cbd7890e7af7c0dec6a Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Wed, 5 Oct 2016 13:54:37 +0200 Subject: do not handle image path, but always give pixbuf --- mpd-notification.c | 34 ++++++++++++++-------------------- mpd-notification.h | 8 ++++---- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/mpd-notification.c b/mpd-notification.c index 0917270..ad2f7b1 100644 --- a/mpd-notification.c +++ b/mpd-notification.c @@ -59,8 +59,8 @@ void received_signal(int signal) { } #ifdef HAVE_LIBAV -/*** retrieve_album_art ***/ -GdkPixbuf * retrieve_album_art(const char * music_dir, const char * uri) { +/*** retrieve_artwork_media ***/ +GdkPixbuf * retrieve_artwork_media(const char * music_dir, const char * uri) { int i; AVPacket pkt; AVFormatContext * pFormatCtx; @@ -113,12 +113,13 @@ fail: } #endif -/*** get_icon ***/ -char * get_icon(const char * music_dir, const char * uri) { +/*** retrieve_artwork_image ***/ +GdkPixbuf * retrieve_artwork_image(const char * music_dir, const char * uri) { char * icon = NULL, * uri_dirname = NULL; DIR * dir; struct dirent * entry; regex_t regex; + GdkPixbuf * pixbuf = NULL; uri_dirname = strdup(uri); @@ -145,6 +146,8 @@ char * get_icon(const char * music_dir, const char * uri) { if (regexec(®ex, entry->d_name, 0, NULL, 0) == 0) { icon = malloc(strlen(music_dir) + strlen(uri_dirname) + strlen(entry->d_name) + 3); sprintf(icon, "%s/%s/%s", music_dir, uri_dirname, entry->d_name); + pixbuf = gdk_pixbuf_new_from_file (icon, NULL); + free(icon); break; } } @@ -155,7 +158,7 @@ char * get_icon(const char * music_dir, const char * uri) { if (uri_dirname) free(uri_dirname); - return icon; + return pixbuf; } /*** append_string ***/ @@ -183,7 +186,7 @@ char * append_string(char * string, const char * format, const char delim, const /*** main ***/ int main(int argc, char ** argv) { const char * title = NULL, * artist = NULL, * album = NULL; - char * icon = NULL, * notifystr = NULL; + char * notifystr = NULL; GdkPixbuf * pixbuf = NULL; GError * error = NULL; unsigned short int errcount = 0, state = MPD_STATE_UNKNOWN; @@ -343,17 +346,17 @@ int main(int argc, char ** argv) { if (music_dir != NULL && uri != NULL) { #ifdef HAVE_LIBAV - pixbuf = retrieve_album_art(music_dir, uri); + pixbuf = retrieve_artwork_media(music_dir, uri); if (verbose > 0 && pixbuf != NULL) printf("%s: found artwork in media file: %s/%s\n", program, music_dir, uri); if (pixbuf == NULL) #endif - icon = get_icon(music_dir, uri); + pixbuf = retrieve_artwork_image(music_dir, uri); - if (verbose > 0 && icon != NULL) - printf("%s: found icon: %s\n", program, icon); + if (verbose > 0 && pixbuf != NULL) + printf("%s: found artwork in image file near %s/%s\n", program, music_dir, uri); } mpd_song_free(song); @@ -367,13 +370,8 @@ int main(int argc, char ** argv) { if (verbose > 0) printf("%s: %s\n", program, notifystr); - /* What combinations do we have? - * icon pixbuf (impossible, icon is set only when !pixbuf) - * !icon pixbuf -> icon -> NULL (use pixbuf) - * !icon !pixbuf -> ICON_AUDIO_X_GENERIC - * icon !pixbuf -> icon */ notify_notification_update(notification, TEXT_TOPIC, notifystr, - icon == NULL && pixbuf == NULL ? ICON_AUDIO_X_GENERIC : icon); + ICON_AUDIO_X_GENERIC); /* Call this unconditionally! When pixbuf is NULL this clears old image. */ notify_notification_set_image_from_pixbuf(notification, pixbuf); @@ -408,10 +406,6 @@ nonotification: free(notifystr); notifystr = NULL; } - if (icon != NULL) { - free(icon); - icon = NULL; - } if (pixbuf != NULL) { g_object_unref(pixbuf); pixbuf = NULL; diff --git a/mpd-notification.h b/mpd-notification.h index 429f3ed..9fdd941 100644 --- a/mpd-notification.h +++ b/mpd-notification.h @@ -34,13 +34,13 @@ /*** received_signal ***/ void received_signal(int signal); -/*** retrieve_album_art ***/ +/*** retrieve_artwork_media ***/ #ifdef HAVE_LIBAV -GdkPixbuf * retrieve_album_art(const char * music_dir, const char * uri); +GdkPixbuf * retrieve_artwork_media(const char * music_dir, const char * uri); #endif -/*** get_icon ***/ -char * get_icon(const char * music_dir, const char * uri); +/*** retrieve_artwork_image ***/ +GdkPixbuf * retrieve_artwork_image(const char * music_dir, const char * uri); /*** append_string ***/ char * append_string(char * string, const char * format, const char delim, const char * s); -- cgit v1.2.3-54-g00ecf From ff1595ed259b2acb2839d98c62db54113bf32976 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Wed, 5 Oct 2016 14:25:10 +0200 Subject: merge the artwork functions --- mpd-notification.c | 84 +++++++++++++++++++++--------------------------------- mpd-notification.h | 9 ++---- 2 files changed, 34 insertions(+), 59 deletions(-) diff --git a/mpd-notification.c b/mpd-notification.c index ad2f7b1..9e7f1f7 100644 --- a/mpd-notification.c +++ b/mpd-notification.c @@ -58,15 +58,19 @@ void received_signal(int signal) { } } +/*** retrieve_artwork ***/ +GdkPixbuf * retrieve_artwork(const char * music_dir, const char * uri) { + GdkPixbuf * pixbuf = NULL; + char * uri_path = NULL, * imagefile = NULL; + DIR * dir; + struct dirent * entry; + regex_t regex; + #ifdef HAVE_LIBAV -/*** retrieve_artwork_media ***/ -GdkPixbuf * retrieve_artwork_media(const char * music_dir, const char * uri) { int i; AVPacket pkt; AVFormatContext * pFormatCtx; GdkPixbufLoader * loader; - GdkPixbuf * pixbuf = NULL; - char * uri_path = NULL; /* try album artwork first */ uri_path = malloc(strlen(music_dir) + strlen(uri) + 2); @@ -76,16 +80,16 @@ GdkPixbuf * retrieve_artwork_media(const char * music_dir, const char * uri) { if (avformat_open_input(&pFormatCtx, uri_path, NULL, NULL) != 0) { printf("avformat_open_input() failed"); - goto fail; + goto image; } /* only mp3 file contain artwork, so ignore others */ if (strcmp(pFormatCtx->iformat->name, "mp3") != 0) - goto fail; + goto image; if (pFormatCtx->iformat->read_header(pFormatCtx) < 0) { printf("could not read the format header\n"); - goto fail; + goto image; } /* find the first attached picture, if available */ @@ -98,45 +102,24 @@ GdkPixbuf * retrieve_artwork_media(const char * music_dir, const char * uri) { pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); gdk_pixbuf_loader_close(loader, NULL); - break; + goto done; } } -fail: - avformat_close_input(&pFormatCtx); - avformat_free_context(pFormatCtx); - - if (uri_path) - free(uri_path); - - return pixbuf; -} +image: #endif -/*** retrieve_artwork_image ***/ -GdkPixbuf * retrieve_artwork_image(const char * music_dir, const char * uri) { - char * icon = NULL, * uri_dirname = NULL; - DIR * dir; - struct dirent * entry; - regex_t regex; - GdkPixbuf * pixbuf = NULL; - - uri_dirname = strdup(uri); - - /* cut the dirname or just use "." (string, not char!) for current directory */ - if (strrchr(uri_dirname, '/') != NULL) - *strrchr(uri_dirname, '/') = 0; - else - strcpy(uri_dirname, "."); + /* cut the file name from path for current directory */ + *strrchr(uri_path, '/') = 0; - if ((dir = opendir(uri_dirname)) == NULL) { - fprintf(stderr, "%s: Can not read directory '%s': ", program, uri_dirname); - return NULL; + if ((dir = opendir(uri_path)) == NULL) { + fprintf(stderr, "%s: Can not read directory '%s': ", program, uri_path); + goto fail; } if (regcomp(®ex, REGEX_ARTWORK, REG_NOSUB + REG_ICASE) != 0) { fprintf(stderr, "%s: Could not compile regex\n", program); - return NULL; + goto fail; } while ((entry = readdir(dir))) { @@ -144,10 +127,10 @@ GdkPixbuf * retrieve_artwork_image(const char * music_dir, const char * uri) { continue; if (regexec(®ex, entry->d_name, 0, NULL, 0) == 0) { - icon = malloc(strlen(music_dir) + strlen(uri_dirname) + strlen(entry->d_name) + 3); - sprintf(icon, "%s/%s/%s", music_dir, uri_dirname, entry->d_name); - pixbuf = gdk_pixbuf_new_from_file (icon, NULL); - free(icon); + imagefile = malloc(strlen(uri_path) + strlen(entry->d_name) + 2); + sprintf(imagefile, "%s/%s", uri_path, entry->d_name); + pixbuf = gdk_pixbuf_new_from_file(imagefile, NULL); + free(imagefile); break; } } @@ -155,8 +138,13 @@ GdkPixbuf * retrieve_artwork_image(const char * music_dir, const char * uri) { regfree(®ex); closedir(dir); - if (uri_dirname) - free(uri_dirname); +done: +fail: + avformat_close_input(&pFormatCtx); + avformat_free_context(pFormatCtx); + + if (uri_path) + free(uri_path); return pixbuf; } @@ -345,18 +333,10 @@ int main(int argc, char ** argv) { uri = mpd_song_get_uri(song); if (music_dir != NULL && uri != NULL) { -#ifdef HAVE_LIBAV - pixbuf = retrieve_artwork_media(music_dir, uri); - - if (verbose > 0 && pixbuf != NULL) - printf("%s: found artwork in media file: %s/%s\n", program, music_dir, uri); - - if (pixbuf == NULL) -#endif - pixbuf = retrieve_artwork_image(music_dir, uri); + pixbuf = retrieve_artwork(music_dir, uri); if (verbose > 0 && pixbuf != NULL) - printf("%s: found artwork in image file near %s/%s\n", program, music_dir, uri); + printf("%s: found artwork in or near media file: %s/%s\n", program, music_dir, uri); } mpd_song_free(song); diff --git a/mpd-notification.h b/mpd-notification.h index 9fdd941..e11c359 100644 --- a/mpd-notification.h +++ b/mpd-notification.h @@ -34,13 +34,8 @@ /*** received_signal ***/ void received_signal(int signal); -/*** retrieve_artwork_media ***/ -#ifdef HAVE_LIBAV -GdkPixbuf * retrieve_artwork_media(const char * music_dir, const char * uri); -#endif - -/*** retrieve_artwork_image ***/ -GdkPixbuf * retrieve_artwork_image(const char * music_dir, const char * uri); +/*** retrieve_artwork ***/ +GdkPixbuf * retrieve_artwork(const char * music_dir, const char * uri); /*** append_string ***/ char * append_string(char * string, const char * format, const char delim, const char * s); -- cgit v1.2.3-54-g00ecf From 9fea2b316110f47a0e561bb1ba498e9d5c9e43a3 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Wed, 5 Oct 2016 14:36:12 +0200 Subject: allow to scale artwork images --- README.md | 1 + mpd-notification.c | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4f2bd8e..dd876ec 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ or `systemctl --user enable mpd-notification`. * *-o*: Notification text is one line (no line breaks) * *-p PORT*: connect to *PORT* * *-t TIMEOUT*: notification timeout, *TIMEOUT* in seconds +* *-s PIXELS*: scale image to *PIXELS* x *PIXELS* pixels * *-v*: verbose output * *-V*: print version information diff --git a/mpd-notification.c b/mpd-notification.c index 9e7f1f7..c271131 100644 --- a/mpd-notification.c +++ b/mpd-notification.c @@ -7,7 +7,7 @@ #include "mpd-notification.h" -const static char optstring[] = "hH:m:op:t:vV"; +const static char optstring[] = "hH:m:op:s:t:vV"; const static struct option options_long[] = { /* name has_arg flag val */ { "help", no_argument, NULL, 'h' }, @@ -15,6 +15,7 @@ const static struct option options_long[] = { { "music-dir", required_argument, NULL, 'm' }, { "oneline", no_argument, NULL, 'o' }, { "port", required_argument, NULL, 'p' }, + { "scale", required_argument, NULL, 's' }, { "timeout", required_argument, NULL, 't' }, { "verbose", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'V' }, @@ -181,7 +182,7 @@ int main(int argc, char ** argv) { const char * mpd_host, * mpd_port_str, * music_dir, * uri = NULL; unsigned mpd_port = MPD_PORT, mpd_timeout = MPD_TIMEOUT, notification_timeout = NOTIFICATION_TIMEOUT; struct mpd_song * song = NULL; - unsigned int i, version = 0, help = 0; + unsigned int i, version = 0, help = 0, scale = 0; program = argv[0]; @@ -245,6 +246,9 @@ int main(int argc, char ** argv) { if (verbose > 0) printf("%s: using host %s\n", program, mpd_host); break; + case 's': + scale = atof(optarg); + break; case 't': notification_timeout = atof(optarg) * 1000; if (verbose > 0) @@ -333,10 +337,21 @@ int main(int argc, char ** argv) { uri = mpd_song_get_uri(song); if (music_dir != NULL && uri != NULL) { + GdkPixbuf * copy; + pixbuf = retrieve_artwork(music_dir, uri); if (verbose > 0 && pixbuf != NULL) printf("%s: found artwork in or near media file: %s/%s\n", program, music_dir, uri); + + if (scale > 0) { + if ((copy = gdk_pixbuf_scale_simple (pixbuf, scale, scale, GDK_INTERP_BILINEAR)) != NULL) { + g_object_unref(pixbuf); + pixbuf = copy; + } + } + + } mpd_song_free(song); -- cgit v1.2.3-54-g00ecf From 81300293395926cf1b7633db4679f3e5ab6beca0 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Wed, 5 Oct 2016 15:56:28 +0200 Subject: keep aspect ratio when scaling --- README.md | 3 ++- mpd-notification.c | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dd876ec..f834801 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,9 @@ or `systemctl --user enable mpd-notification`. * *-m MUSIC-DIR*: use *MUSIC-DIR* for artwork lookup * *-o*: Notification text is one line (no line breaks) * *-p PORT*: connect to *PORT* +* *-s PIXELS*: scale image to a maximum size *PIXELS* x *PIXELS* pixels, keeping + ratio * *-t TIMEOUT*: notification timeout, *TIMEOUT* in seconds -* *-s PIXELS*: scale image to *PIXELS* x *PIXELS* pixels * *-v*: verbose output * *-V*: print version information diff --git a/mpd-notification.c b/mpd-notification.c index c271131..8713947 100644 --- a/mpd-notification.c +++ b/mpd-notification.c @@ -345,7 +345,15 @@ int main(int argc, char ** argv) { printf("%s: found artwork in or near media file: %s/%s\n", program, music_dir, uri); if (scale > 0) { - if ((copy = gdk_pixbuf_scale_simple (pixbuf, scale, scale, GDK_INTERP_BILINEAR)) != NULL) { + int x, y; + + x = gdk_pixbuf_get_width(pixbuf); + y = gdk_pixbuf_get_height(pixbuf); + + if ((copy = gdk_pixbuf_scale_simple (pixbuf, + (x > y ? scale : scale * x / y), + (y > x ? scale : scale * y / x), + GDK_INTERP_BILINEAR)) != NULL) { g_object_unref(pixbuf); pixbuf = copy; } -- cgit v1.2.3-54-g00ecf From 9c5d990ff88ac3055623f7b9b3429bce52a0e11d Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Wed, 5 Oct 2016 22:09:18 +0200 Subject: add notification file workaround --- README.md | 2 ++ mpd-notification.c | 17 ++++++++++++++--- mpd-notification.h | 2 ++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f834801..6025af8 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,8 @@ or `systemctl --user enable mpd-notification`. * *-h*: show help * *-H HOST*: connect to *HOST* * *-m MUSIC-DIR*: use *MUSIC-DIR* for artwork lookup +* *--notification-file-workaround*: write artwork to file for notification + daemons that do required it * *-o*: Notification text is one line (no line breaks) * *-p PORT*: connect to *PORT* * *-s PIXELS*: scale image to a maximum size *PIXELS* x *PIXELS* pixels, keeping diff --git a/mpd-notification.c b/mpd-notification.c index 8713947..840d4ab 100644 --- a/mpd-notification.c +++ b/mpd-notification.c @@ -19,6 +19,8 @@ const static struct option options_long[] = { { "timeout", required_argument, NULL, 't' }, { "verbose", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'V' }, + { "notification-file-workaround", + no_argument, NULL, OPT_FILE_WORKAROUND }, { 0, 0, 0, 0 } }; @@ -182,7 +184,7 @@ int main(int argc, char ** argv) { const char * mpd_host, * mpd_port_str, * music_dir, * uri = NULL; unsigned mpd_port = MPD_PORT, mpd_timeout = MPD_TIMEOUT, notification_timeout = NOTIFICATION_TIMEOUT; struct mpd_song * song = NULL; - unsigned int i, version = 0, help = 0, scale = 0; + unsigned int i, version = 0, help = 0, scale = 0, file_workaround = 0; program = argv[0]; @@ -254,6 +256,9 @@ int main(int argc, char ** argv) { if (verbose > 0) printf("%s: using notification-timeout %d\n", program, notification_timeout); break; + case OPT_FILE_WORKAROUND: + file_workaround++; + break; } } @@ -373,8 +378,14 @@ int main(int argc, char ** argv) { if (verbose > 0) printf("%s: %s\n", program, notifystr); - notify_notification_update(notification, TEXT_TOPIC, notifystr, - ICON_AUDIO_X_GENERIC); + /* Some notification daemons do not support handing pixbuf data. Write a PNG + * file and give the path. */ + if (file_workaround > 0 && pixbuf != NULL) { + gdk_pixbuf_save(pixbuf, "/tmp/.mpd-notification-artwork.png", "png", NULL, NULL); + + notify_notification_update(notification, TEXT_TOPIC, notifystr, "/tmp/.mpd-notification-artwork.png"); + } else + notify_notification_update(notification, TEXT_TOPIC, notifystr, ICON_AUDIO_X_GENERIC); /* Call this unconditionally! When pixbuf is NULL this clears old image. */ notify_notification_set_image_from_pixbuf(notification, pixbuf); diff --git a/mpd-notification.h b/mpd-notification.h index e11c359..0cbd370 100644 --- a/mpd-notification.h +++ b/mpd-notification.h @@ -31,6 +31,8 @@ #define PROGNAME "mpd-notification" +#define OPT_FILE_WORKAROUND UCHAR_MAX + 1 + /*** received_signal ***/ void received_signal(int signal); -- cgit v1.2.3-54-g00ecf From b04e44e2fd6d91641ad089160effe1e88e162847 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Wed, 5 Oct 2016 22:23:36 +0200 Subject: add scale option to help output --- mpd-notification.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpd-notification.c b/mpd-notification.c index 840d4ab..f504836 100644 --- a/mpd-notification.c +++ b/mpd-notification.c @@ -225,7 +225,7 @@ int main(int argc, char ** argv) { printf("%s: %s v%s (compiled: " __DATE__ ", " __TIME__ ")\n", program, PROGNAME, VERSION); if (help > 0) - fprintf(stderr, "usage: %s [-h] [-H HOST] [-p PORT] [-m MUSIC-DIR] [-t TIMEOUT] [-v] [-V]\n", program); + fprintf(stderr, "usage: %s [-h] [-H HOST] [-p PORT] [-m MUSIC-DIR] [-s PIXELS] [-t TIMEOUT] [-v] [-V]\n", program); if (version > 0 || help > 0) return EXIT_SUCCESS; -- cgit v1.2.3-54-g00ecf