Update supported tags before telling the world that/if we support it
[libmpd.git] / src / libmpd-strfsong.c
blob7d47bed256cca324b21ee16719d76efc8a74ccbb
1 /* libmpd (high level libmpdclient library)
2 * Copyright (C) 2004-2009 Qball Cow <qball@sarine.nl>
3 * Project homepage: http://gmpcwiki.sarine.nl/
5 * Based on mpc's songToFormatedString modified for glib and ncmpc
6 * (c) 2003-2004 by normalperson and Warren Dukes (shank@mercury.chem.pitt.edu)
7 * and Daniel Brown (danb@cs.utexas.edu)
8 * and Kalle Wallin (kaw@linux.se)
9 * and Qball Cow (Qball@qballcow.nl)
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <glib.h>
31 #include "libmpd.h"
32 #include "libmpd-internal.h"
34 static char * skip(char * p)
36 int stack = 0;
38 while (*p != '\0') {
39 if(*p == '[') stack++;
40 if(*p == '#' && p[1] != '\0') {
41 /* skip escaped stuff */
42 ++p;
44 else if(stack) {
45 if(*p == ']') stack--;
47 else {
48 if(*p == '&' || *p == '|' || *p == ']') {
49 break;
52 ++p;
55 return p;
58 static unsigned int _strfsong(char *s,
59 unsigned int max,
60 const char *format,
61 mpd_Song *song,
62 char **last)
64 char *p, *end;
65 char *temp;
66 unsigned int n, length = 0;
67 int i;
68 short int found = FALSE;
70 memset(s, 0, max);
71 if( song==NULL )
72 return 0;
74 for( p=(char *) format; *p != '\0' && length<max; )
76 /* OR */
77 if (p[0] == '|')
79 ++p;
80 if(!found)
82 memset(s, 0, max);
83 length = 0;
85 else
87 p = skip(p);
89 continue;
92 /* AND */
93 if (p[0] == '&')
95 ++p;
96 if(!found)
98 p = skip(p);
100 else
102 found = FALSE;
104 continue;
107 /* EXPRESSION START */
108 if (p[0] == '[')
110 temp = g_malloc0(max);
111 if( _strfsong(temp, max, p+1, song, &p) >0 )
113 strncat(s, temp, max-length);
114 length = strlen(s);
115 found = TRUE;
117 g_free(temp);
118 continue;
121 /* EXPRESSION END */
122 if (p[0] == ']')
124 if(last) *last = p+1;
125 if(!found && length)
127 memset(s, 0, max);
128 length = 0;
130 return length;
133 /* pass-through non-escaped portions of the format string */
134 if (p[0] != '#' && p[0] != '%' && length<max)
136 strncat(s, p, 1);
137 length++;
138 ++p;
139 continue;
142 /* let the escape character escape itself */
143 if (p[0] == '#' && p[1] != '\0' && length<max)
145 strncat(s, p+1, 1);
146 length++;
147 p+=2;
148 continue;
151 /* advance past the esc character */
153 /* find the extent of this format specifier (stop at \0, ' ', or esc) */
154 temp = NULL;
155 end = p+1;
156 while(*end >= 'a' && *end <= 'z')
158 end++;
160 n = end - p + 1;
161 if(*end != '%')
162 n--;
163 else if (memcmp("%file%", p, n) == 0)
164 temp = g_strdup(song->file);
165 else if (memcmp("%artist%", p, n) == 0)
166 temp = song->artist ? g_strdup(song->artist) : NULL;
167 else if (memcmp("%title%", p, n) == 0)
168 temp = song->title ? g_strdup(song->title) : NULL;
169 else if (memcmp("%album%", p, n) == 0)
170 temp = song->album ? g_strdup(song->album) : NULL;
171 else if (memcmp("%track%", p, n) == 0)
172 temp = song->track ? g_strdup(song->track) : NULL;
173 else if (memcmp("%name%", p, n) == 0)
174 temp = song->name ? g_strdup(song->name) : NULL;
175 else if (memcmp("%date%", p, n) == 0)
176 temp = song->date ? g_strdup(song->date) : NULL;
177 else if (memcmp("%genre%", p, n) == 0)
178 temp = song->genre ? g_strdup(song->genre) : NULL;
179 else if (memcmp("%performer%", p, n) == 0)
180 temp = song->performer ? g_strdup(song->performer) : NULL;
181 else if (memcmp("%composer%", p, n) == 0)
182 temp = song->composer ? g_strdup(song->composer) : NULL;
183 else if (memcmp("%track%",p,n) == 0)
184 temp = song->track? g_strdup(song->track): NULL;
185 else if (memcmp("%comment%", p, n) == 0)
186 temp = song->comment? g_strdup(song->comment): NULL;
187 else if (memcmp("%plpos%", p, n) == 0 || memcmp("%songpos%",p,n) == 0){
188 temp = NULL;
189 if(song->pos >= 0){
190 char str[32];
191 int length;
192 if((length = snprintf(str,32, "%i", song->pos)) >=0)
194 temp = g_strndup(str,length);
198 else if (memcmp("%shortfile%", p, n) == 0)
200 /*if( strstr(song->file, "://") )
201 temp = g_strdup(song->file);
202 else */{
203 int i=strlen(song->file);
204 int ext =i;
205 int found = 0;
206 char *temp2 = NULL;
207 for(;i>=0 && (song->file[i] != '/' && song->file[i] != '\\');i--){
208 if(song->file[i] == '.' && !found) {
209 ext = i;
210 found = 1;
213 temp2 = g_strndup(&(song->file)[i+1],(gsize)(ext-i-1));
214 temp = g_uri_unescape_string(temp2, "");
215 g_free(temp2);
218 else if (memcmp("%time%", p, n) == 0)
220 temp = NULL;
221 if (song->time != MPD_SONG_NO_TIME) {
222 char str[32];
223 int length;
224 if((length = snprintf(str,32, "%02d:%02d", song->time/60, song->time%60))>=0)
226 temp = g_strndup(str,length);
230 else if (memcmp("%disc%", p, n) == 0)
232 temp = song->disc? g_strdup(song->disc) : NULL;
234 if(temp != NULL) {
235 unsigned int templen = strlen(temp);
236 found = TRUE;
237 if( length+templen > max )
238 templen = max-length;
239 strncat(s, temp, templen);
240 length+=templen;
241 g_free(temp);
244 /* advance past the specifier */
245 p += n;
248 for(i=0; i < length;i++)
250 if(s[i] == '_') s[i] = ' ';
253 if(last) *last = p;
255 return length;
258 unsigned int mpd_song_markup(char *s, unsigned int max,const char *format, mpd_Song *song)
260 return _strfsong(s, max, format, song, NULL);