X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fstrfsong.c;h=b64c350ba6dace76d83b8c70f0dd49d591b1eefc;hb=f2b8b4378b3760e8ba5a1ed54a5f8635d3dac85e;hp=bac6d472f734fe8df06e8119382bbddb258074c3;hpb=9a500d13055f16b70796a5fce5ec6de4a2844187;p=ncmpc.git diff --git a/src/strfsong.c b/src/strfsong.c index bac6d47..b64c350 100644 --- a/src/strfsong.c +++ b/src/strfsong.c @@ -1,12 +1,6 @@ -/* - * $Id$ - * - * Based on mpc's songToFormatedString modified for glib and ncmpc - * - * - * (c) 2003-2004 by normalperson and Warren Dukes (shank@mercury.chem.pitt.edu) - * and Daniel Brown (danb@cs.utexas.edu) - * and Kalle Wallin (kaw@linux.se) +/* ncmpc (Ncurses MPD Client) + * (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 * it under the terms of the GNU General Public License as published by @@ -17,212 +11,287 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "strfsong.h" +#include "charset.h" +#include "time_format.h" + +#include -#include -#include -#include #include -#include -#include "config.h" -#include "libmpdclient.h" -#include "support.h" -#include "strfsong.h" +static const gchar * +skip(const gchar * p) +{ + gint stack = 0; + + while (*p != '\0') { + if (*p == '[') + stack++; + if (*p == '#' && p[1] != '\0') { + /* skip escaped stuff */ + ++p; + } else if (stack) { + if(*p == ']') stack--; + } else { + if(*p == '&' || *p == '|' || *p == ']') { + break; + } + } + ++p; + } + + return p; +} + +#ifndef NCMPC_MINI -static gchar * -skip(gchar * p) +static char * +concat_tag_values(const char *a, const char *b) { - gint stack = 0; - - while (*p != '\0') { - if(*p == '[') stack++; - if(*p == '#' && p[1] != '\0') { - /* skip escaped stuff */ - ++p; - } - else if(stack) { - if(*p == ']') stack--; - } - else { - if(*p == '&' || *p == '|' || *p == ']') { - break; - } - } - ++p; - } - - return p; + return g_strconcat(a, ", ", b, NULL); } -static gsize -_strfsong(gchar *s, - gsize max, - const gchar *format, - mpd_Song *song, - gchar **last) +static char * +song_more_tag_values(const struct mpd_song *song, enum mpd_tag_type tag, + const char *first) { - gchar *p, *end; - gchar *temp; - gsize n, length = 0; - gboolean found = FALSE; - - memset(s, 0, max); - if( song==NULL ) - return 0; - - for( p=(gchar *) format; *p != '\0' && length0 ) - { - g_strlcat(s, temp, max); - length = strlen(s); - found = TRUE; - } - g_free(temp); - continue; - } + return buffer; +} - /* EXPRESSION END */ - if (p[0] == ']') - { - if(last) *last = p+1; - if(!found && length) - { - memset(s, 0, max); - length = 0; - } - return length; - } +#endif /* !NCMPC_MINI */ - /* pass-through non-escaped portions of the format string */ - if (p[0] != '#' && p[0] != '%' && length= 'a' && *end <= 'z') - { - end++; - } - n = end - p + 1; - if(*end != '%') - n--; - else if (strncmp("%file%", p, n) == 0) - temp = utf8_to_locale(song->file); - else if (strncmp("%artist%", p, n) == 0) - temp = song->artist ? utf8_to_locale(song->artist) : NULL; - else if (strncmp("%title%", p, n) == 0) - temp = song->title ? utf8_to_locale(song->title) : NULL; - else if (strncmp("%album%", p, n) == 0) - temp = song->album ? utf8_to_locale(song->album) : NULL; - else if (strncmp("%track%", p, n) == 0) - temp = song->track ? utf8_to_locale(song->track) : NULL; - else if (strncmp("%name%", p, n) == 0) - temp = song->name ? utf8_to_locale(song->name) : NULL; - else if (strncmp("%shortfile%", p, n) == 0) - { - if( strstr(song->file, "://") ) - temp = utf8_to_locale(song->file); - else - temp = utf8_to_locale(basename(song->file)); - } - else if (strncmp("%time%", p, n) == 0) - { - if (song->time != MPD_SONG_NO_TIME) - temp = g_strdup_printf("%d:%d", - song->time / 60, - song->time % 60 + 1); - } +#ifndef NCMPC_MINI + g_free(all); +#endif /* !NCMPC_MINI */ - if( temp == NULL) - { - gsize templen=n; - /* just pass-through any unknown specifiers (including esc) */ - /* drop a null char in so printf stops at the end of this specifier, - but put the real character back in (pseudo-const) */ - if( length+templen > max ) - templen = max-length; - g_strlcat(s, p,max); - length+=templen; - } - else { - gsize templen = strlen(temp); + return result; +} + +static gsize +_strfsong(gchar *s, + gsize max, + const gchar *format, + const struct mpd_song *song, + const gchar **last) +{ + 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'; + + if (song == NULL) + return 0; + + const char *p; + size_t length = 0; + for (p = format; *p != '\0' && length max ) - templen = max-length; - g_strlcat(s, temp, max); - length+=templen; - g_free(temp); - } + /* EXPRESSION START */ + if (p[0] == '[') { + char *temp = g_malloc0(max); + if( _strfsong(temp, max, p+1, song, &p) >0 ) { + g_strlcat(s, temp, max); + length = strlen(s); + found = true; + } else { + missed = true; + } + g_free(temp); + continue; + } - /* advance past the specifier */ - p += n; - } + /* EXPRESSION END */ + if (p[0] == ']') { + if(last) *last = p+1; + if(missed && !found && length) { + s[0] = '\0'; + length = 0; + } + return length; + } - if(last) *last = p; + /* pass-through non-escaped portions of the format string */ + if (p[0] != '#' && p[0] != '%' && length= 'a' && *end <= 'z') { + end++; + } + 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) { + temp = song_tag_locale(song, MPD_TAG_ARTIST); + 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); + 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); + if (temp) { + gchar *temp2 = g_strndup(temp, 25); + if (strlen(temp) > 25) { + temp2[24] = '.'; + temp2[23] = '.'; + temp2[22] = '.'; + } + g_free(temp); + temp = temp2; + } + } + 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) + temp = song_tag_locale(song, MPD_TAG_DATE); + else if (strncmp("%genre%", p, n) == 0) + temp = song_tag_locale(song, MPD_TAG_GENRE); + else if (strncmp("%shortfile%", p, n) == 0) { + const char *uri = mpd_song_get_uri(song); + if (strstr(uri, "://") != NULL) + temp = utf8_to_locale(uri); + else + temp = utf8_to_locale(g_basename(uri)); + } else if (strncmp("%time%", p, n) == 0) { + unsigned duration = mpd_song_get_duration(song); + + if (duration > 0) { + char buffer[32]; + format_duration_short(buffer, sizeof(buffer), + duration); + temp = g_strdup(buffer); + } + } + + if( temp == NULL) { + gsize templen=n; + /* just pass-through any unknown specifiers (including esc) */ + if( length+templen > max ) + templen = max-length; + gchar *ident = g_strndup(p, templen); + g_strlcat(s, ident, max); + length+=templen; + g_free(ident); + + missed = true; + } else { + gsize templen = strlen(temp); + + found = true; + if( length+templen > max ) + templen = max-length; + g_strlcat(s, temp, max); + length+=templen; + g_free(temp); + } + + /* advance past the specifier */ + p += n; + } + + if(last) *last = p; + + return length; } gsize -strfsong(gchar *s, gsize max, const gchar *format, mpd_Song *song) +strfsong(gchar *s, gsize max, const gchar *format, + const struct mpd_song *song) { - return _strfsong(s, max, format, song, NULL); + return _strfsong(s, max, format, song, NULL); } - +