aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Christian Hesse <mail@eworm.de>2016-10-05 23:38:36 +0200
committerGravatar Christian Hesse <mail@eworm.de>2016-10-05 23:38:36 +0200
commit90b01922ea7622de0eab2216912445040389ed5c (patch)
tree0a1b2b7817facd544b626cce87f345510f8bd5c7
parent854b9a8f8a78825dfe9a045588eccb7b47805f74 (diff)
parentb04e44e2fd6d91641ad089160effe1e88e162847 (diff)
downloadmpd-notification-90b01922ea7622de0eab2216912445040389ed5c.tar.gz
mpd-notification-90b01922ea7622de0eab2216912445040389ed5c.tar.zst
Merge branch 'pixbuf'
-rw-r--r--README.md4
-rw-r--r--mpd-notification.c134
-rw-r--r--mpd-notification.h11
3 files changed, 79 insertions, 70 deletions
diff --git a/README.md b/README.md
index 4f2bd8e..6025af8 100644
--- a/README.md
+++ b/README.md
@@ -59,8 +59,12 @@ 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
+ ratio
* *-t TIMEOUT*: notification timeout, *TIMEOUT* in seconds
* *-v*: verbose output
* *-V*: print version information
diff --git a/mpd-notification.c b/mpd-notification.c
index 0917270..f504836 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,9 +15,12 @@ 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' },
+ { "notification-file-workaround",
+ no_argument, NULL, OPT_FILE_WORKAROUND },
{ 0, 0, 0, 0 }
};
@@ -58,15 +61,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_album_art ***/
-GdkPixbuf * retrieve_album_art(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 +83,16 @@ GdkPixbuf * retrieve_album_art(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,44 +105,24 @@ GdkPixbuf * retrieve_album_art(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
-/*** get_icon ***/
-char * get_icon(const char * music_dir, const char * uri) {
- char * icon = NULL, * uri_dirname = NULL;
- DIR * dir;
- struct dirent * entry;
- regex_t regex;
-
- uri_dirname = strdup(uri);
+ /* cut the file name from path for current directory */
+ *strrchr(uri_path, '/') = 0;
- /* 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, ".");
-
- 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(&regex, REGEX_ARTWORK, REG_NOSUB + REG_ICASE) != 0) {
fprintf(stderr, "%s: Could not compile regex\n", program);
- return NULL;
+ goto fail;
}
while ((entry = readdir(dir))) {
@@ -143,8 +130,10 @@ char * get_icon(const char * music_dir, const char * uri) {
continue;
if (regexec(&regex, 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);
+ 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;
}
}
@@ -152,10 +141,15 @@ char * get_icon(const char * music_dir, const char * uri) {
regfree(&regex);
closedir(dir);
- if (uri_dirname)
- free(uri_dirname);
+done:
+fail:
+ avformat_close_input(&pFormatCtx);
+ avformat_free_context(pFormatCtx);
- return icon;
+ if (uri_path)
+ free(uri_path);
+
+ return pixbuf;
}
/*** append_string ***/
@@ -183,14 +177,14 @@ 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;
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, file_workaround = 0;
program = argv[0];
@@ -231,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;
@@ -254,11 +248,17 @@ 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)
printf("%s: using notification-timeout %d\n", program, notification_timeout);
break;
+ case OPT_FILE_WORKAROUND:
+ file_workaround++;
+ break;
}
}
@@ -342,18 +342,29 @@ int main(int argc, char ** argv) {
uri = mpd_song_get_uri(song);
if (music_dir != NULL && uri != NULL) {
-#ifdef HAVE_LIBAV
- pixbuf = retrieve_album_art(music_dir, uri);
+ GdkPixbuf * copy;
+
+ pixbuf = retrieve_artwork(music_dir, uri);
if (verbose > 0 && pixbuf != NULL)
- printf("%s: found artwork in media file: %s/%s\n", program, music_dir, uri);
+ printf("%s: found artwork in or near media file: %s/%s\n", program, music_dir, uri);
+
+ if (scale > 0) {
+ 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;
+ }
+ }
- if (pixbuf == NULL)
-#endif
- icon = get_icon(music_dir, uri);
- if (verbose > 0 && icon != NULL)
- printf("%s: found icon: %s\n", program, icon);
}
mpd_song_free(song);
@@ -367,13 +378,14 @@ 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);
+ /* 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);
@@ -408,10 +420,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..0cbd370 100644
--- a/mpd-notification.h
+++ b/mpd-notification.h
@@ -31,16 +31,13 @@
#define PROGNAME "mpd-notification"
+#define OPT_FILE_WORKAROUND UCHAR_MAX + 1
+
/*** received_signal ***/
void received_signal(int signal);
-/*** retrieve_album_art ***/
-#ifdef HAVE_LIBAV
-GdkPixbuf * retrieve_album_art(const char * music_dir, const char * uri);
-#endif
-
-/*** get_icon ***/
-char * get_icon(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);