Code

include cleanup
[ncmpc.git] / src / strfsong.c
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  */
25 #include "strfsong.h"
26 #include "support.h"
28 #include <string.h>
30 static const gchar *
31 skip(const gchar * p)
32 {
33         gint stack = 0;
35         while (*p != '\0') {
36                 if(*p == '[') stack++;
37                 if(*p == '#' && p[1] != '\0') {
38                         /* skip escaped stuff */
39                         ++p;
40                 } else if(stack) {
41                         if(*p == ']') stack--;
42                 } else {
43                         if(*p == '&' || *p == '|' || *p == ']') {
44                                 break;
45                         }
46                 }
47                 ++p;
48         }
50         return p;
51 }
53 static gsize
54 _strfsong(gchar *s,
55           gsize max,
56           const gchar *format,
57           mpd_Song *song,
58           const gchar **last)
59 {
60         const gchar *p, *end;
61         gchar *temp;
62         gsize n, length = 0;
63         gboolean found = FALSE;
65         memset(s, 0, max);
66         if( song==NULL )
67                 return 0;
69         for (p = format; *p != '\0' && length<max;) {
70                 /* OR */
71                 if (p[0] == '|') {
72                         ++p;
73                         if(!found) {
74                                 memset(s, 0, max);
75                                 length = 0;
76                         } else {
77                                 p = skip(p);
78                         }
79                         continue;
80                 }
82                 /* AND */
83                 if (p[0] == '&') {
84                         ++p;
85                         if(!found) {
86                                 p = skip(p);
87                         } else {
88                                 found = FALSE;
89                         }
90                         continue;
91                 }
93                 /* EXPRESSION START */
94                 if (p[0] == '[') {
95                         temp = g_malloc0(max);
96                         if( _strfsong(temp, max, p+1, song, &p) >0 ) {
97                                 g_strlcat(s, temp, max);
98                                 length = strlen(s);
99                                 found = TRUE;
100                         }
101                         g_free(temp);
102                         continue;
103                 }
105                 /* EXPRESSION END */
106                 if (p[0] == ']') {
107                         if(last) *last = p+1;
108                         if(!found && length) {
109                                 memset(s, 0, max);
110                                 length = 0;
111                         }
112                         return length;
113                 }
115                 /* pass-through non-escaped portions of the format string */
116                 if (p[0] != '#' && p[0] != '%' && length<max) {
117                         s[length++] = *p;
118                         p++;
119                         continue;
120                 }
122                 /* let the escape character escape itself */
123                 if (p[0] == '#' && p[1] != '\0' && length<max) {
124                         s[length++] = *(p+1);
125                         p+=2;
126                         continue;
127                 }
129                 /* advance past the esc character */
131                 /* find the extent of this format specifier (stop at \0, ' ', or esc) */
132                 temp = NULL;
133                 end  = p+1;
134                 while(*end >= 'a' && *end <= 'z') {
135                         end++;
136                 }
137                 n = end - p + 1;
138                 if(*end != '%')
139                         n--;
140                 else if (strncmp("%file%", p, n) == 0)
141                         temp = utf8_to_locale(song->file);
142                 else if (strncmp("%artist%", p, n) == 0)
143                         temp = song->artist ? utf8_to_locale(song->artist) : NULL;
144                 else if (strncmp("%title%", p, n) == 0)
145                         temp = song->title ? utf8_to_locale(song->title) : NULL;
146                 else if (strncmp("%album%", p, n) == 0)
147                         temp = song->album ? utf8_to_locale(song->album) : NULL;
148                 else if (strncmp("%shortalbum%", p, n) == 0) {
149                         temp = song->album ? utf8_to_locale(song->album) : NULL;
150                         if (temp) {
151                                 gchar *temp2 = g_strndup(temp, 25);
152                                 if (strlen(temp) > 25) {
153                                         temp2[24] = '.';
154                                         temp2[23] = '.';
155                                         temp2[22] = '.';
156                                 }
157                                 g_free(temp);
158                                 temp = temp2;
159                         }
160                 }
161                 else if (strncmp("%track%", p, n) == 0)
162                         temp = song->track ? utf8_to_locale(song->track) : NULL;
163                 else if (strncmp("%name%", p, n) == 0)
164                         temp = song->name ? utf8_to_locale(song->name) : NULL;
165                 else if (strncmp("%date%", p, n) == 0)
166                         temp = song->date ? utf8_to_locale(song->date) : NULL;
167                 else if (strncmp("%genre%", p, n) == 0)
168                         temp = song->genre ? utf8_to_locale(song->genre) : NULL;
169                 else if (strncmp("%shortfile%", p, n) == 0) {
170                         if( strstr(song->file, "://") )
171                                 temp = utf8_to_locale(song->file);
172                         else
173                                 temp = utf8_to_locale(basename(song->file));
174                 } else if (strncmp("%time%", p, n) == 0) {
175                         if (song->time != MPD_SONG_NO_TIME)  {
176                                 if (song->time > 3600) {
177                                         temp = g_strdup_printf("%d:%02d:%02d",
178                                                                song->time / 3600,
179                                                                (song->time % 3600) / 60,
180                                                                song->time % 60);
181                                 } else {
182                                         temp = g_strdup_printf("%d:%02d",
183                                                                song->time / 60,
184                                                                song->time % 60);
185                                 }
186                         }
187                 }
189                 if( temp == NULL) {
190                         gsize templen=n;
191                         /* just pass-through any unknown specifiers (including esc) */
192                         /* drop a null char in so printf stops at the end of this specifier,
193                            but put the real character back in (pseudo-const) */
194                         if( length+templen > max )
195                                 templen = max-length;
196                         g_strlcat(s, p,max);
197                         length+=templen;
198                 } else {
199                         gsize templen = strlen(temp);
201                         found = TRUE;
202                         if( length+templen > max )
203                                 templen = max-length;
204                         g_strlcat(s, temp, max);
205                         length+=templen;
206                         g_free(temp);
207                 }
209                 /* advance past the specifier */
210                 p += n;
211         }
213         if(last) *last = p;
215         return length;
218 gsize
219 strfsong(gchar *s, gsize max, const gchar *format, mpd_Song *song)
221   return _strfsong(s, max, format, song, NULL);
223