diff options
Diffstat (limited to 'mpd-notification.c')
-rw-r--r-- | mpd-notification.c | 157 |
1 files changed, 101 insertions, 56 deletions
diff --git a/mpd-notification.c b/mpd-notification.c index 2e48bb0..af8985a 100644 --- a/mpd-notification.c +++ b/mpd-notification.c @@ -18,13 +18,12 @@ #include "mpd-notification.h" -const static char optstring[] = "hH:m:op:s:t:vV"; +const static char optstring[] = "hH:m:p:s:t:vV"; const static struct option options_long[] = { /* name has_arg flag val */ { "help", no_argument, NULL, 'h' }, { "host", required_argument, NULL, 'H' }, { "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' }, @@ -41,7 +40,6 @@ NotifyNotification * notification = NULL; struct mpd_connection * conn = NULL; uint8_t doexit = 0; uint8_t verbose = 0; -uint8_t oneline = 0; #ifdef HAVE_LIBAV magic_t magic = NULL; #endif @@ -105,7 +103,10 @@ GdkPixbuf * retrieve_artwork(const char * music_dir, const char * uri) { if (verbose > 0) printf("%s: MIME type for %s is: %s\n", program, uri_path, magic_mime); - if (strcmp(magic_mime, "audio/mpeg") != 0) + /* Are there more mime-types supporting embedded artwork? Tell me! */ + if (strcmp(magic_mime, "audio/mp4") != 0 && + strcmp(magic_mime, "audio/mpeg") != 0 && + strcmp(magic_mime, "audio/x-m4a") != 0) goto image; if ((pFormatCtx = avformat_alloc_context()) == NULL) { @@ -118,11 +119,6 @@ GdkPixbuf * retrieve_artwork(const char * music_dir, const char * uri) { goto image; } - if (pFormatCtx->iformat->read_header(pFormatCtx) < 0) { - fprintf(stderr, "%s: Could not read the format header.\n", program); - goto image; - } - /* find the first attached picture, if available */ for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) { @@ -149,6 +145,9 @@ GdkPixbuf * retrieve_artwork(const char * music_dir, const char * uri) { } } + if (pixbuf == NULL && verbose > 0) + printf("%s: No artwork in media file.\n", program); + image: #endif @@ -208,26 +207,72 @@ done: return pixbuf; } -/*** append_string ***/ -char * append_string(char * string, const char * format, const char delim, const char * s) { - char * tmp, * offset; - - tmp = g_markup_escape_text(s, -1); - - string = realloc(string, strlen(string) + strlen(format) + strlen(tmp) + 2 /* delim + line break */); - - offset = string + strlen(string); - - if (delim > 0) { - *offset = delim; - offset++; - } - - sprintf(offset, format, tmp); +/*** format_text ***/ +char * format_text(const char* format, const char* title, const char* artist, const char* album, unsigned int duration) { + char * formatted, * tmp = NULL; + size_t len; + + if (format == NULL || strlen(format) == 0) + return NULL; + + formatted = strdup(""); + len = 0; + + do { + if (*format == '%') { + format++; + + switch (*format) { + case 'a': + tmp = g_markup_escape_text(artist, -1); + break; + + case 'A': + tmp = g_markup_escape_text(album, -1); + break; + + case 'd': + size_t size; + size = snprintf(tmp, 0, "%d:%02d", duration / 60, duration % 60) + 1; + tmp = malloc(size); + snprintf(tmp, size, "%d:%02d", duration / 60, duration % 60); + break; + + case 't': + tmp = g_markup_escape_text(title, -1); + break; + + default: + formatted = realloc(formatted, len + 2); + sprintf(formatted + len, "%%"); + format--; + break; + } - free(tmp); + if (tmp != NULL) { + formatted = realloc(formatted, len + strlen(tmp) + 1); + sprintf(formatted + len, "%s", tmp); + free(tmp); + tmp = NULL; + } + } else if (*format == '\\') { + format++; + formatted = realloc(formatted, len + 2); + + if (*format == 'n') { + sprintf(formatted + len, "\n"); + } else { + sprintf(formatted + len, "\\"); + format--; + } + } else { + formatted = realloc(formatted, len + 2); + sprintf(formatted + len, "%c", *format); + } + len = strlen(formatted); + } while (*format++); - return string; + return formatted; } /*** main ***/ @@ -238,10 +283,11 @@ int main(int argc, char ** argv) { GdkPixbuf * pixbuf = NULL; GError * error = NULL; enum mpd_state state = MPD_STATE_UNKNOWN, last_state = MPD_STATE_UNKNOWN; - const char * mpd_host, * mpd_port_str, * music_dir, * uri = NULL; + const char * mpd_host, * mpd_port_str, * music_dir, * text_topic = TEXT_TOPIC, + * text_play = TEXT_PLAY, * text_pause = TEXT_PAUSE, * text_stop = TEXT_STOP, * 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, file_workaround = 0; + unsigned int i, version = 0, help = 0, scale = 0, file_workaround = 0, duration; int rc = EXIT_FAILURE; program = argv[0]; @@ -268,8 +314,11 @@ int main(int argc, char ** argv) { mpd_port = iniparser_getint(ini, ":port", mpd_port); music_dir = iniparser_getstring(ini, ":music-dir", music_dir); notification_timeout = iniparser_getint(ini, ":timeout", notification_timeout); - oneline = iniparser_getboolean(ini, ":oneline", oneline); scale = iniparser_getint(ini, ":scale", scale); + text_topic = iniparser_getstring(ini, ":text-topic", text_topic); + text_play = iniparser_getstring(ini, ":text-play", text_play); + text_pause = iniparser_getstring(ini, ":text-pause", text_pause); + text_stop = iniparser_getstring(ini, ":text-stop", text_stop); } /* get the verbose status */ @@ -278,9 +327,6 @@ int main(int argc, char ** argv) { case 'h': help++; break; - case 'o': - oneline++; - break; case 'v': verbose++; break; @@ -306,7 +352,7 @@ int main(int argc, char ** argv) { " (compiled: " __DATE__ ", " __TIME__ ")\n", program, PROGNAME, VERSION); if (help > 0) - fprintf(stderr, "usage: %s [-h] [-H HOST] [-m MUSIC-DIR] [-o] [-p PORT] [-s PIXELS] [-t TIMEOUT] [-v] [-V]\n", program); + fprintf(stderr, "usage: %s [-h] [-H HOST] [-m MUSIC-DIR] [-p PORT] [-s PIXELS] [-t TIMEOUT] [-v] [-V]\n", program); if (version > 0 || help > 0) return EXIT_SUCCESS; @@ -387,18 +433,21 @@ int main(int argc, char ** argv) { notification = # if NOTIFY_CHECK_VERSION(0, 7, 0) - notify_notification_new(TEXT_TOPIC, TEXT_NONE, ICON_AUDIO_X_GENERIC); + notify_notification_new(text_topic, TEXT_NONE, ICON_AUDIO_X_GENERIC); # else - notify_notification_new(TEXT_TOPIC, TEXT_NONE, ICON_AUDIO_X_GENERIC, NULL); + notify_notification_new(text_topic, TEXT_NONE, ICON_AUDIO_X_GENERIC, NULL); # endif notify_notification_set_category(notification, PROGNAME); notify_notification_set_urgency(notification, NOTIFY_URGENCY_NORMAL); notify_notification_set_timeout(notification, notification_timeout * 1000); - signal(SIGHUP, received_signal); - signal(SIGINT, received_signal); - signal(SIGTERM, received_signal); - signal(SIGUSR1, received_signal); + struct sigaction act = { 0 }; + act.sa_handler = received_signal; + + sigaction(SIGHUP, &act, NULL); + sigaction(SIGINT, &act, NULL); + sigaction(SIGTERM, &act, NULL); + sigaction(SIGUSR1, &act, NULL); /* report ready to systemd */ #ifdef HAVE_SYSTEMD @@ -417,7 +466,7 @@ int main(int argc, char ** argv) { * too late, which results in issue with image date. Make sure to * show a notification without image data (just generic icon) first. */ if (last_state != MPD_STATE_PLAY && last_state != MPD_STATE_PAUSE) { - notify_notification_update(notification, TEXT_TOPIC, "Starting playback...", ICON_AUDIO_X_GENERIC); + notify_notification_update(notification, text_topic, "Starting playback...", ICON_AUDIO_X_GENERIC); notify_notification_show(notification, NULL); } @@ -425,7 +474,10 @@ int main(int argc, char ** argv) { song = mpd_recv_song(conn); - title = mpd_song_get_tag(song, MPD_TAG_TITLE, 0); + title = mpd_song_get_tag(song, MPD_TAG_TITLE, 0); + artist = mpd_song_get_tag(song, MPD_TAG_ARTIST, 0); + album = mpd_song_get_tag(song, MPD_TAG_ALBUM, 0); + duration = mpd_song_get_duration(song); /* ignore if we have no title */ if (title == NULL) @@ -435,16 +487,9 @@ int main(int argc, char ** argv) { sd_notifyf(0, "READY=1\nSTATUS=%s: %s", state == MPD_STATE_PLAY ? "Playing" : "Paused", title); #endif - /* initial allocation and string termination */ - notifystr = strdup(""); - notifystr = append_string(notifystr, TEXT_PLAY_PAUSE_STATE, 0, state == MPD_STATE_PLAY ? "Playing": "Paused"); - notifystr = append_string(notifystr, TEXT_PLAY_PAUSE_TITLE, 0, title); - - if ((artist = mpd_song_get_tag(song, MPD_TAG_ARTIST, 0)) != NULL) - notifystr = append_string(notifystr, TEXT_PLAY_PAUSE_ARTIST, oneline ? ' ' : '\n', artist); - - if ((album = mpd_song_get_tag(song, MPD_TAG_ALBUM, 0)) != NULL) - notifystr = append_string(notifystr, TEXT_PLAY_PAUSE_ALBUM, oneline ? ' ' : '\n', album); + /* get the formatted notification string */ + notifystr = format_text(state == MPD_STATE_PLAY ? text_play : text_pause, + title, artist ? artist : "unknown artist", album ? album : "unknown album", duration); uri = mpd_song_get_uri(song); @@ -473,9 +518,9 @@ int main(int argc, char ** argv) { mpd_song_free(song); } else if (state == MPD_STATE_STOP) { - notifystr = strdup(TEXT_STOP); + notifystr = strdup(text_stop); #ifdef HAVE_SYSTEMD - sd_notify(0, "READY=1\nSTATUS=" TEXT_STOP); + sd_notifyf(0, "READY=1\nSTATUS=%s", text_stop); #endif } else notifystr = strdup(TEXT_UNKNOWN); @@ -490,9 +535,9 @@ int main(int argc, char ** argv) { 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"); + notify_notification_update(notification, text_topic, notifystr, "/tmp/.mpd-notification-artwork.png"); } else - notify_notification_update(notification, TEXT_TOPIC, notifystr, ICON_AUDIO_X_GENERIC); + 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); |