small updates
[libmpd.git] / src / libmpd-strfsong.c
blob4aa1199707a22bd83ed8828ae1e0fd8401306511
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 <glib.h>
32 #include "libmpd.h"
33 #include "libmpd-internal.h"
35 static char * skip(char * p)
37 int stack = 0;
39 while (*p != '\0') {
40 if(*p == '[') stack++;
41 if(*p == '#' && p[1] != '\0') {
42 /* skip escaped stuff */
43 ++p;
45 else if(stack) {
46 if(*p == ']') stack--;
48 else {
49 if(*p == '&' || *p == '|' || *p == ']') {
50 break;
53 ++p;
56 return p;
59 static unsigned int _strfsong(char *s,
60 unsigned int max,
61 const char *format,
62 mpd_Song *song,
63 char **last)
65 char *p, *end;
66 char *temp;
67 unsigned int n, length = 0;
68 int i;
69 short int found = FALSE;
71 memset(s, 0, max);
72 if( song==NULL )
73 return 0;
75 for( p=(char *) format; *p != '\0' && length<max; )
77 /* OR */
78 if (p[0] == '|')
80 ++p;
81 if(!found)
83 memset(s, 0, max);
84 length = 0;
86 else
88 p = skip(p);
90 continue;
93 /* AND */
94 if (p[0] == '&')
96 ++p;
97 if(!found)
99 p = skip(p);
101 else
103 found = FALSE;
105 continue;
108 /* EXPRESSION START */
109 if (p[0] == '[')
111 temp = g_malloc0(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 g_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 = g_strdup(song->file);
166 else if (memcmp("%artist%", p, n) == 0)
167 temp = song->artist ? g_strdup(song->artist) : NULL;
168 else if (memcmp("%title%", p, n) == 0)
169 temp = song->title ? g_strdup(song->title) : NULL;
170 else if (memcmp("%album%", p, n) == 0)
171 temp = song->album ? g_strdup(song->album) : NULL;
172 else if (memcmp("%track%", p, n) == 0)
173 temp = song->track ? g_strdup(song->track) : NULL;
174 else if (memcmp("%name%", p, n) == 0)
175 temp = song->name ? g_strdup(song->name) : NULL;
176 else if (memcmp("%date%", p, n) == 0)
177 temp = song->date ? g_strdup(song->date) : NULL;
178 else if (memcmp("%genre%", p, n) == 0)
179 temp = song->genre ? g_strdup(song->genre) : NULL;
180 else if (memcmp("%performer%", p, n) == 0)
181 temp = song->performer ? g_strdup(song->performer) : NULL;
182 else if (memcmp("%composer%", p, n) == 0)
183 temp = song->composer ? g_strdup(song->composer) : NULL;
184 else if (memcmp("%track%",p,n) == 0)
185 temp = song->track? g_strdup(song->track): NULL;
186 else if (memcmp("%comment%", p, n) == 0)
187 temp = song->comment? g_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 = g_strndup(str,length);
199 else if (memcmp("%shortfile%", p, n) == 0)
201 /*if( strstr(song->file, "://") )
202 temp = g_strdup(song->file);
203 else */{
204 int i=strlen(song->file);
205 int ext =i;
206 char *temp2 = NULL;
207 for(;i>=0 && (song->file[i] != '/' && song->file[i] != '\\');i--){
208 if(song->file[i] == '.' && !ext) ext = i;
210 temp2 = g_strndup(&(song->file)[i+1],(gsize)(ext-i-1));
211 temp = g_uri_unescape_string(temp2, "");
212 g_free(temp2);
215 else if (memcmp("%time%", p, n) == 0)
217 temp = NULL;
218 if (song->time != MPD_SONG_NO_TIME) {
219 char str[32];
220 int length;
221 if((length = snprintf(str,32, "%02d:%02d", song->time/60, song->time%60))>=0)
223 temp = g_strndup(str,length);
227 else if (memcmp("%disc%", p, n) == 0)
229 temp = song->disc? g_strdup(song->disc) : NULL;
231 if(temp != NULL) {
232 unsigned int templen = strlen(temp);
233 found = TRUE;
234 if( length+templen > max )
235 templen = max-length;
236 strncat(s, temp, templen);
237 length+=templen;
238 g_free(temp);
241 /* advance past the specifier */
242 p += n;
245 for(i=0; i < length;i++)
247 if(s[i] == '_') s[i] = ' ';
250 if(last) *last = p;
252 return length;
255 unsigned int mpd_song_markup(char *s, unsigned int max,const char *format, mpd_Song *song)
257 return _strfsong(s, max, format, song, NULL);