Code

code style, indent with tabs XI
[ncmpc.git] / src / strfsong.c
1 /*
2  * Based on mpc's songToFormatedString modified for glib and ncmpc
3  *
4  *
5  * (c) 2003-2004 by normalperson and Warren Dukes (shank@mercury.chem.pitt.edu)
6  *              and Daniel Brown (danb@cs.utexas.edu)
7  *              and Kalle Wallin (kaw@linux.se)
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
23 #include "strfsong.h"
24 #include "charset.h"
26 #include <string.h>
28 static const gchar *
29 skip(const gchar * p)
30 {
31         gint stack = 0;
33         while (*p != '\0') {
34                 if (*p == '[')
35                         stack++;
36                 if (*p == '#' && p[1] != '\0') {
37                         /* skip escaped stuff */
38                         ++p;
39                 } else if (stack) {
40                         if(*p == ']') stack--;
41                 } else {
42                         if(*p == '&' || *p == '|' || *p == ']') {
43                                 break;
44                         }
45                 }
46                 ++p;
47         }
49         return p;
50 }
52 static gsize
53 _strfsong(gchar *s,
54           gsize max,
55           const gchar *format,
56           const struct mpd_song *song,
57           const gchar **last)
58 {
59         const gchar *p, *end;
60         gchar *temp;
61         gsize n, length = 0;
62         gboolean found = FALSE;
64         memset(s, 0, max);
65         if (song == NULL)
66                 return 0;
68         for (p = format; *p != '\0' && length<max;) {
69                 /* OR */
70                 if (p[0] == '|') {
71                         ++p;
72                         if(!found) {
73                                 memset(s, 0, max);
74                                 length = 0;
75                         } else {
76                                 p = skip(p);
77                         }
78                         continue;
79                 }
81                 /* AND */
82                 if (p[0] == '&') {
83                         ++p;
84                         if(!found) {
85                                 p = skip(p);
86                         } else {
87                                 found = FALSE;
88                         }
89                         continue;
90                 }
92                 /* EXPRESSION START */
93                 if (p[0] == '[') {
94                         temp = g_malloc0(max);
95                         if( _strfsong(temp, max, p+1, song, &p) >0 ) {
96                                 g_strlcat(s, temp, max);
97                                 length = strlen(s);
98                                 found = TRUE;
99                         }
100                         g_free(temp);
101                         continue;
102                 }
104                 /* EXPRESSION END */
105                 if (p[0] == ']') {
106                         if(last) *last = p+1;
107                         if(!found && length) {
108                                 memset(s, 0, max);
109                                 length = 0;
110                         }
111                         return length;
112                 }
114                 /* pass-through non-escaped portions of the format string */
115                 if (p[0] != '#' && p[0] != '%' && length<max) {
116                         s[length++] = *p;
117                         p++;
118                         continue;
119                 }
121                 /* let the escape character escape itself */
122                 if (p[0] == '#' && p[1] != '\0' && length<max) {
123                         s[length++] = *(p+1);
124                         p+=2;
125                         continue;
126                 }
128                 /* advance past the esc character */
130                 /* find the extent of this format specifier (stop at \0, ' ', or esc) */
131                 temp = NULL;
132                 end  = p+1;
133                 while(*end >= 'a' && *end <= 'z') {
134                         end++;
135                 }
136                 n = end - p + 1;
137                 if(*end != '%')
138                         n--;
139                 else if (strncmp("%file%", p, n) == 0)
140                         temp = utf8_to_locale(song->file);
141                 else if (strncmp("%artist%", p, n) == 0)
142                         temp = song->artist ? utf8_to_locale(song->artist) : NULL;
143                 else if (strncmp("%title%", p, n) == 0)
144                         temp = song->title ? utf8_to_locale(song->title) : NULL;
145                 else if (strncmp("%album%", p, n) == 0)
146                         temp = song->album ? utf8_to_locale(song->album) : NULL;
147                 else if (strncmp("%shortalbum%", p, n) == 0) {
148                         temp = song->album ? utf8_to_locale(song->album) : NULL;
149                         if (temp) {
150                                 gchar *temp2 = g_strndup(temp, 25);
151                                 if (strlen(temp) > 25) {
152                                         temp2[24] = '.';
153                                         temp2[23] = '.';
154                                         temp2[22] = '.';
155                                 }
156                                 g_free(temp);
157                                 temp = temp2;
158                         }
159                 }
160                 else if (strncmp("%track%", p, n) == 0)
161                         temp = song->track ? utf8_to_locale(song->track) : NULL;
162                 else if (strncmp("%name%", p, n) == 0)
163                         temp = song->name ? utf8_to_locale(song->name) : NULL;
164                 else if (strncmp("%date%", p, n) == 0)
165                         temp = song->date ? utf8_to_locale(song->date) : NULL;
166                 else if (strncmp("%genre%", p, n) == 0)
167                         temp = song->genre ? utf8_to_locale(song->genre) : NULL;
168                 else if (strncmp("%shortfile%", p, n) == 0) {
169                         if( strstr(song->file, "://") )
170                                 temp = utf8_to_locale(song->file);
171                         else
172                                 temp = utf8_to_locale(g_basename(song->file));
173                 } else if (strncmp("%time%", p, n) == 0) {
174                         if (song->time != MPD_SONG_NO_TIME)  {
175                                 if (song->time > 3600) {
176                                         temp = g_strdup_printf("%d:%02d:%02d",
177                                                                song->time / 3600,
178                                                                (song->time % 3600) / 60,
179                                                                song->time % 60);
180                                 } else {
181                                         temp = g_strdup_printf("%d:%02d",
182                                                                song->time / 60,
183                                                                song->time % 60);
184                                 }
185                         }
186                 }
188                 if( temp == NULL) {
189                         gsize templen=n;
190                         /* just pass-through any unknown specifiers (including esc) */
191                         /* drop a null char in so printf stops at the end of this specifier,
192                            but put the real character back in (pseudo-const) */
193                         if( length+templen > max )
194                                 templen = max-length;
195                         g_strlcat(s, p,max);
196                         length+=templen;
197                 } else {
198                         gsize templen = strlen(temp);
200                         found = TRUE;
201                         if( length+templen > max )
202                                 templen = max-length;
203                         g_strlcat(s, temp, max);
204                         length+=templen;
205                         g_free(temp);
206                 }
208                 /* advance past the specifier */
209                 p += n;
210         }
212         if(last) *last = p;
214         return length;
217 gsize
218 strfsong(gchar *s, gsize max, const gchar *format,
219          const struct mpd_song *song)
221         return _strfsong(s, max, format, song, NULL);