Code

utils: move format_duration_*() to time_format.c
[ncmpc.git] / src / strfsong.c
index e3d4eb98cda560fd56d291bee98ff18207f56499..b64c350ba6dace76d83b8c70f0dd49d591b1eefc 100644 (file)
@@ -1,5 +1,5 @@
 /* ncmpc (Ncurses MPD Client)
- * (c) 2004-2010 The Music Player Daemon Project
+ * (c) 2004-2017 The Music Player Daemon Project
  * Project homepage: http://musicpd.org
  *
  * This program is free software; you can redistribute it and/or modify
@@ -19,7 +19,7 @@
 
 #include "strfsong.h"
 #include "charset.h"
-#include "utils.h"
+#include "time_format.h"
 
 #include <mpd/client.h>
 
@@ -62,15 +62,13 @@ song_more_tag_values(const struct mpd_song *song, enum mpd_tag_type tag,
                     const char *first)
 {
        const char *p = mpd_song_get_tag(song, tag, 1);
-       char *buffer, *prev;
-
        if (p == NULL)
                return NULL;
 
-       buffer = concat_tag_values(first, p);
+       char *buffer = concat_tag_values(first, p);
        for (unsigned i = 2; (p = mpd_song_get_tag(song, tag, i)) != NULL;
             ++i) {
-               prev = buffer;
+               char *prev = buffer;
                buffer = concat_tag_values(buffer, p);
                g_free(prev);
        }
@@ -84,21 +82,16 @@ static char *
 song_tag_locale(const struct mpd_song *song, enum mpd_tag_type tag)
 {
        const char *value = mpd_song_get_tag(song, tag, 0);
-       char *result;
-#ifndef NCMPC_MINI
-       char *all;
-#endif /* !NCMPC_MINI */
-
        if (value == NULL)
                return NULL;
 
 #ifndef NCMPC_MINI
-       all = song_more_tag_values(song, tag, value);
+       char *all = song_more_tag_values(song, tag, value);
        if (all != NULL)
                value = all;
 #endif /* !NCMPC_MINI */
 
-       result = utf8_to_locale(value);
+       char *result = utf8_to_locale(value);
 
 #ifndef NCMPC_MINI
        g_free(all);
@@ -114,22 +107,26 @@ _strfsong(gchar *s,
          const struct mpd_song *song,
          const gchar **last)
 {
-       const gchar *p, *end;
-       gchar *temp;
-       gsize n, length = 0;
-       gboolean found = FALSE;
+       bool found = false;
+       /* "missed" helps handling the case of mere literal text like
+          found==true instead of found==false. */
+       bool missed = false;
+
+       s[0] = '\0';
 
-       memset(s, 0, max);
        if (song == NULL)
                return 0;
 
+       const char *p;
+       size_t length = 0;
        for (p = format; *p != '\0' && length<max;) {
                /* OR */
                if (p[0] == '|') {
                        ++p;
-                       if(!found) {
-                               memset(s, 0, max);
+                       if(missed && !found) {
+                               s[0] = '\0';
                                length = 0;
+                               missed = false;
                        } else {
                                p = skip(p);
                        }
@@ -139,21 +136,24 @@ _strfsong(gchar *s,
                /* AND */
                if (p[0] == '&') {
                        ++p;
-                       if(!found) {
+                       if(missed && !found) {
                                p = skip(p);
                        } else {
-                               found = FALSE;
+                               found = false;
+                               missed = false;
                        }
                        continue;
                }
 
                /* EXPRESSION START */
                if (p[0] == '[') {
-                       temp = g_malloc0(max);
+                       char *temp = g_malloc0(max);
                        if( _strfsong(temp, max, p+1, song, &p) >0 ) {
                                g_strlcat(s, temp, max);
                                length = strlen(s);
-                               found = TRUE;
+                               found = true;
+                       } else {
+                               missed = true;
                        }
                        g_free(temp);
                        continue;
@@ -162,8 +162,8 @@ _strfsong(gchar *s,
                /* EXPRESSION END */
                if (p[0] == ']') {
                        if(last) *last = p+1;
-                       if(!found && length) {
-                               memset(s, 0, max);
+                       if(missed && !found && length) {
+                               s[0] = '\0';
                                length = 0;
                        }
                        return length;
@@ -172,6 +172,7 @@ _strfsong(gchar *s,
                /* pass-through non-escaped portions of the format string */
                if (p[0] != '#' && p[0] != '%' && length<max) {
                        s[length++] = *p;
+                       s[length] = '\0';
                        p++;
                        continue;
                }
@@ -179,6 +180,7 @@ _strfsong(gchar *s,
                /* let the escape character escape itself */
                if (p[0] == '#' && p[1] != '\0' && length<max) {
                        s[length++] = *(p+1);
+                       s[length] = '\0';
                        p+=2;
                        continue;
                }
@@ -186,21 +188,34 @@ _strfsong(gchar *s,
                /* advance past the esc character */
 
                /* find the extent of this format specifier (stop at \0, ' ', or esc) */
-               temp = NULL;
-               end  = p+1;
+               char *temp = NULL;
+               const char *end = p + 1;
                while(*end >= 'a' && *end <= 'z') {
                        end++;
                }
-               n = end - p + 1;
+               size_t n = end - p + 1;
                if(*end != '%')
                        n--;
                else if (strncmp("%file%", p, n) == 0)
                        temp = utf8_to_locale(mpd_song_get_uri(song));
-               else if (strncmp("%artist%", p, n) == 0)
+               else if (strncmp("%artist%", p, n) == 0) {
                        temp = song_tag_locale(song, MPD_TAG_ARTIST);
-               else if (strncmp("%title%", p, n) == 0)
+                       if (temp == NULL) {
+                               temp = song_tag_locale(song, MPD_TAG_PERFORMER);
+                               if (temp == NULL)
+                                       temp = song_tag_locale(song, MPD_TAG_COMPOSER);
+                       }
+               } else if (strncmp("%albumartist", p, n) == 0)
+                       temp = song_tag_locale(song, MPD_TAG_ALBUM_ARTIST);
+               else if (strncmp("%composer%", p, n) == 0)
+                       temp = song_tag_locale(song, MPD_TAG_COMPOSER);
+               else if (strncmp("%performer%", p, n) == 0)
+                       temp = song_tag_locale(song, MPD_TAG_PERFORMER);
+               else if (strncmp("%title%", p, n) == 0) {
                        temp = song_tag_locale(song, MPD_TAG_TITLE);
-               else if (strncmp("%album%", p, n) == 0)
+                       if (temp == NULL)
+                               temp = song_tag_locale(song, MPD_TAG_NAME);
+               } else if (strncmp("%album%", p, n) == 0)
                        temp = song_tag_locale(song, MPD_TAG_ALBUM);
                else if (strncmp("%shortalbum%", p, n) == 0) {
                        temp = song_tag_locale(song, MPD_TAG_ALBUM);
@@ -217,6 +232,8 @@ _strfsong(gchar *s,
                }
                else if (strncmp("%track%", p, n) == 0)
                        temp = song_tag_locale(song, MPD_TAG_TRACK);
+               else if (strncmp("%disc%", p, n) == 0)
+                       temp = song_tag_locale(song, MPD_TAG_DISC);
                else if (strncmp("%name%", p, n) == 0)
                        temp = song_tag_locale(song, MPD_TAG_NAME);
                else if (strncmp("%date%", p, n) == 0)
@@ -249,10 +266,12 @@ _strfsong(gchar *s,
                        g_strlcat(s, ident, max);
                        length+=templen;
                        g_free(ident);
+
+                       missed = true;
                } else {
                        gsize templen = strlen(temp);
 
-                       found = TRUE;
+                       found = true;
                        if( length+templen > max )
                                templen = max-length;
                        g_strlcat(s, temp, max);