add comment to strfsong parser
[libmpd.git] / src / libmpd-strfsong.c
blob5b6962715598b46637af6c7fedb47891a4987548
1 /*
2 * $Id: strfsong.c 1502 2004-06-15 15:32:18Z kaw $
4 * Based on mpc's songToFormatedString modified for glib and ncmpc
7 * (c) 2003-2004 by normalperson and Warren Dukes (shank@mercury.chem.pitt.edu)
8 * and Daniel Brown (danb@cs.utexas.edu)
9 * and Kalle Wallin (kaw@linux.se)
10 * and Qball Cow (Qball@qballcow.nl)
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <string.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 = malloc(max);
111 memset(temp, 0,max);
112 if( _strfsong(temp, max, p+1, song, &p) >0 )
114 strncat(s, temp, max-length);
115 length = strlen(s);
116 found = TRUE;
118 free(temp);
119 continue;
122 /* EXPRESSION END */
123 if (p[0] == ']')
125 if(last) *last = p+1;
126 if(!found && length)
128 memset(s, 0, max);
129 length = 0;
131 return length;
134 /* pass-through non-escaped portions of the format string */
135 if (p[0] != '#' && p[0] != '%' && length<max)
137 strncat(s, p, 1);
138 length++;
139 ++p;
140 continue;
143 /* let the escape character escape itself */
144 if (p[0] == '#' && p[1] != '\0' && length<max)
146 strncat(s, p+1, 1);
147 length++;
148 p+=2;
149 continue;
152 /* advance past the esc character */
154 /* find the extent of this format specifier (stop at \0, ' ', or esc) */
155 temp = NULL;
156 end = p+1;
157 while(*end >= 'a' && *end <= 'z')
159 end++;
161 n = end - p + 1;
162 if(*end != '%')
163 n--;
164 else if (memcmp("%file%", p, n) == 0)
165 temp = strdup(song->file);
166 else if (memcmp("%artist%", p, n) == 0)
167 temp = song->artist ? strdup(song->artist) : NULL;
168 else if (memcmp("%title%", p, n) == 0)
169 temp = song->title ? strdup(song->title) : NULL;
170 else if (memcmp("%album%", p, n) == 0)
171 temp = song->album ? strdup(song->album) : NULL;
172 else if (memcmp("%track%", p, n) == 0)
173 temp = song->track ? strdup(song->track) : NULL;
174 else if (memcmp("%name%", p, n) == 0)
175 temp = song->name ? strdup(song->name) : NULL;
176 else if (memcmp("%date%", p, n) == 0)
177 temp = song->date ? strdup(song->date) : NULL;
178 else if (memcmp("%genre%", p, n) == 0)
179 temp = song->genre ? strdup(song->genre) : NULL;
180 else if (memcmp("%performer%", p, n) == 0)
181 temp = song->performer ? strdup(song->performer) : NULL;
182 else if (memcmp("%composer%", p, n) == 0)
183 temp = song->composer ? strdup(song->composer) : NULL;
184 else if (memcmp("%track%",p,n) == 0)
185 temp = song->track? strdup(song->track): NULL;
186 else if (memcmp("%comment%", p, n) == 0)
187 temp = song->comment? strdup(song->comment): NULL;
188 else if (memcmp("%plpos%", p, n) == 0 || memcmp("%songpos%",p,n) == 0){
189 temp = NULL;
190 if(song->pos >= 0){
191 char str[32];
192 int length;
193 if((length = snprintf(str,32, "%i", song->pos)) >=0)
195 temp = strndup(str,length);
199 else if (memcmp("%shortfile%", p, n) == 0)
201 if( strstr(song->file, "://") )
202 temp = strdup(song->file);
203 else {
204 int i=strlen(song->file);
205 int ext =0;
206 for(;i>=0 && (song->file[i] != '/' && song->file[i] != '\\');i--){
207 if(song->file[i] == '.' && !ext) ext = i;
209 temp = strndup(&(song->file)[i+1],ext-i-1);
212 else if (memcmp("%time%", p, n) == 0)
214 temp = NULL;
215 if (song->time != MPD_SONG_NO_TIME) {
216 char str[32];
217 int length;
218 if((length = snprintf(str,32, "%02d:%02d", song->time/60, song->time%60))>=0)
220 temp = strndup(str,length);
224 else if (memcmp("%disc%", p, n) == 0)
226 temp = song->disc? strdup(song->disc) : NULL;
228 if(temp != NULL) {
229 unsigned int templen = strlen(temp);
230 found = TRUE;
231 if( length+templen > max )
232 templen = max-length;
233 strncat(s, temp, templen);
234 length+=templen;
235 free(temp);
238 /* advance past the specifier */
239 p += n;
242 for(i=0; i < length;i++)
244 if(s[i] == '_') s[i] = ' ';
247 if(last) *last = p;
249 return length;
252 unsigned int mpd_song_markup(char *s, unsigned int max,const char *format, mpd_Song *song)
254 return _strfsong(s, max, format, song, NULL);