bac6d472f734fe8df06e8119382bbddb258074c3
1 /*
2 * $Id$
3 *
4 * Based on mpc's songToFormatedString modified for glib and ncmpc
5 *
6 *
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 *
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.
15 *
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.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <glib.h>
32 #include "config.h"
33 #include "libmpdclient.h"
34 #include "support.h"
35 #include "strfsong.h"
37 static gchar *
38 skip(gchar * p)
39 {
40 gint stack = 0;
42 while (*p != '\0') {
43 if(*p == '[') stack++;
44 if(*p == '#' && p[1] != '\0') {
45 /* skip escaped stuff */
46 ++p;
47 }
48 else if(stack) {
49 if(*p == ']') stack--;
50 }
51 else {
52 if(*p == '&' || *p == '|' || *p == ']') {
53 break;
54 }
55 }
56 ++p;
57 }
59 return p;
60 }
62 static gsize
63 _strfsong(gchar *s,
64 gsize max,
65 const gchar *format,
66 mpd_Song *song,
67 gchar **last)
68 {
69 gchar *p, *end;
70 gchar *temp;
71 gsize n, length = 0;
72 gboolean found = FALSE;
74 memset(s, 0, max);
75 if( song==NULL )
76 return 0;
78 for( p=(gchar *) format; *p != '\0' && length<max; )
79 {
80 /* OR */
81 if (p[0] == '|')
82 {
83 ++p;
84 if(!found)
85 {
86 memset(s, 0, max);
87 length = 0;
88 }
89 else
90 {
91 p = skip(p);
92 }
93 continue;
94 }
96 /* AND */
97 if (p[0] == '&')
98 {
99 ++p;
100 if(!found)
101 {
102 p = skip(p);
103 }
104 else
105 {
106 found = FALSE;
107 }
108 continue;
109 }
111 /* EXPRESSION START */
112 if (p[0] == '[')
113 {
114 temp = g_malloc0(max);
115 if( _strfsong(temp, max, p+1, song, &p) >0 )
116 {
117 g_strlcat(s, temp, max);
118 length = strlen(s);
119 found = TRUE;
120 }
121 g_free(temp);
122 continue;
123 }
125 /* EXPRESSION END */
126 if (p[0] == ']')
127 {
128 if(last) *last = p+1;
129 if(!found && length)
130 {
131 memset(s, 0, max);
132 length = 0;
133 }
134 return length;
135 }
137 /* pass-through non-escaped portions of the format string */
138 if (p[0] != '#' && p[0] != '%' && length<max)
139 {
140 s[length++] = *p;
141 p++;
142 continue;
143 }
145 /* let the escape character escape itself */
146 if (p[0] == '#' && p[1] != '\0' && length<max)
147 {
148 s[length++] = *(p+1);
149 p+=2;
150 continue;
151 }
153 /* advance past the esc character */
155 /* find the extent of this format specifier (stop at \0, ' ', or esc) */
156 temp = NULL;
157 end = p+1;
158 while(*end >= 'a' && *end <= 'z')
159 {
160 end++;
161 }
162 n = end - p + 1;
163 if(*end != '%')
164 n--;
165 else if (strncmp("%file%", p, n) == 0)
166 temp = utf8_to_locale(song->file);
167 else if (strncmp("%artist%", p, n) == 0)
168 temp = song->artist ? utf8_to_locale(song->artist) : NULL;
169 else if (strncmp("%title%", p, n) == 0)
170 temp = song->title ? utf8_to_locale(song->title) : NULL;
171 else if (strncmp("%album%", p, n) == 0)
172 temp = song->album ? utf8_to_locale(song->album) : NULL;
173 else if (strncmp("%track%", p, n) == 0)
174 temp = song->track ? utf8_to_locale(song->track) : NULL;
175 else if (strncmp("%name%", p, n) == 0)
176 temp = song->name ? utf8_to_locale(song->name) : NULL;
177 else if (strncmp("%shortfile%", p, n) == 0)
178 {
179 if( strstr(song->file, "://") )
180 temp = utf8_to_locale(song->file);
181 else
182 temp = utf8_to_locale(basename(song->file));
183 }
184 else if (strncmp("%time%", p, n) == 0)
185 {
186 if (song->time != MPD_SONG_NO_TIME)
187 temp = g_strdup_printf("%d:%d",
188 song->time / 60,
189 song->time % 60 + 1);
190 }
192 if( temp == NULL)
193 {
194 gsize templen=n;
195 /* just pass-through any unknown specifiers (including esc) */
196 /* drop a null char in so printf stops at the end of this specifier,
197 but put the real character back in (pseudo-const) */
198 if( length+templen > max )
199 templen = max-length;
200 g_strlcat(s, p,max);
201 length+=templen;
202 }
203 else {
204 gsize templen = strlen(temp);
206 found = TRUE;
207 if( length+templen > max )
208 templen = max-length;
209 g_strlcat(s, temp, max);
210 length+=templen;
211 g_free(temp);
212 }
214 /* advance past the specifier */
215 p += n;
216 }
218 if(last) *last = p;
220 return length;
221 }
223 gsize
224 strfsong(gchar *s, gsize max, const gchar *format, mpd_Song *song)
225 {
226 return _strfsong(s, max, format, song, NULL);
227 }