Code

code style, indent with tabs
[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  */
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                 } else if(stack) {
48                         if(*p == ']') stack--;
49                 } else {
50                         if(*p == '&' || *p == '|' || *p == ']') {
51                                 break;
52                         }
53                 }
54                 ++p;
55         }
57         return p;
58 }
60 static gsize
61 _strfsong(gchar *s,
62           gsize max,
63           const gchar *format,
64           mpd_Song *song,
65           gchar **last)
66 {
67         gchar *p, *end;
68         gchar *temp;
69         gsize n, length = 0;
70         gboolean found = FALSE;
72         memset(s, 0, max);
73         if( song==NULL )
74                 return 0;
76         for (p = (gchar *)format; *p != '\0' && length<max;) {
77                 /* OR */
78                 if (p[0] == '|') {
79                         ++p;
80                         if(!found) {
81                                 memset(s, 0, max);
82                                 length = 0;
83                         } else {
84                                 p = skip(p);
85                         }
86                         continue;
87                 }
89                 /* AND */
90                 if (p[0] == '&') {
91                         ++p;
92                         if(!found) {
93                                 p = skip(p);
94                         } else {
95                                 found = FALSE;
96                         }
97                         continue;
98                 }
100                 /* EXPRESSION START */
101                 if (p[0] == '[') {
102                         temp = g_malloc0(max);
103                         if( _strfsong(temp, max, p+1, song, &p) >0 ) {
104                                 g_strlcat(s, temp, max);
105                                 length = strlen(s);
106                                 found = TRUE;
107                         }
108                         g_free(temp);
109                         continue;
110                 }
112                 /* EXPRESSION END */
113                 if (p[0] == ']') {
114                         if(last) *last = p+1;
115                         if(!found && length) {
116                                 memset(s, 0, max);
117                                 length = 0;
118                         }
119                         return length;
120                 }
122                 /* pass-through non-escaped portions of the format string */
123                 if (p[0] != '#' && p[0] != '%' && length<max) {
124                         s[length++] = *p;
125                         p++;
126                         continue;
127                 }
129                 /* let the escape character escape itself */
130                 if (p[0] == '#' && p[1] != '\0' && length<max) {
131                         s[length++] = *(p+1);
132                         p+=2;
133                         continue;
134                 }
136                 /* advance past the esc character */
138                 /* find the extent of this format specifier (stop at \0, ' ', or esc) */
139                 temp = NULL;
140                 end  = p+1;
141                 while(*end >= 'a' && *end <= 'z') {
142                         end++;
143                 }
144                 n = end - p + 1;
145                 if(*end != '%')
146                         n--;
147                 else if (strncmp("%file%", p, n) == 0)
148                         temp = utf8_to_locale(song->file);
149                 else if (strncmp("%artist%", p, n) == 0)
150                         temp = song->artist ? utf8_to_locale(song->artist) : NULL;
151                 else if (strncmp("%title%", p, n) == 0)
152                         temp = song->title ? utf8_to_locale(song->title) : NULL;
153                 else if (strncmp("%album%", p, n) == 0)
154                         temp = song->album ? utf8_to_locale(song->album) : NULL;
155                 else if (strncmp("%shortalbum%", p, n) == 0) {
156                         temp = song->album ? utf8_to_locale(song->album) : NULL;
157                         if (temp) {
158                                 gchar *temp2 = g_strndup(temp, 25);
159                                 if (strlen(temp) > 25) {
160                                         temp2[24] = '.';
161                                         temp2[23] = '.';
162                                         temp2[22] = '.';
163                                 }
164                                 g_free(temp);
165                                 temp = temp2;
166                         }
167                 }
168                 else if (strncmp("%track%", p, n) == 0)
169                         temp = song->track ? utf8_to_locale(song->track) : NULL;
170                 else if (strncmp("%name%", p, n) == 0)
171                         temp = song->name ? utf8_to_locale(song->name) : NULL;
172                 else if (strncmp("%date%", p, n) == 0)
173                         temp = song->date ? utf8_to_locale(song->date) : NULL;
174                 else if (strncmp("%genre%", p, n) == 0)
175                         temp = song->genre ? utf8_to_locale(song->genre) : NULL;
176                 else if (strncmp("%shortfile%", p, n) == 0) {
177                         if( strstr(song->file, "://") )
178                                 temp = utf8_to_locale(song->file);
179                         else
180                                 temp = utf8_to_locale(basename(song->file));
181                 } else if (strncmp("%time%", p, n) == 0) {
182                         if (song->time != MPD_SONG_NO_TIME)  {
183                                 if (song->time > 3600) {
184                                         temp = g_strdup_printf("%d:%02d:%02d",
185                                                                song->time / 3600,
186                                                                (song->time % 3600) / 60,
187                                                                song->time % 60);
188                                 } else {
189                                         temp = g_strdup_printf("%d:%02d",
190                                                                song->time / 60,
191                                                                song->time % 60);
192                                 }
193                         }
194                 }
196                 if( temp == NULL) {
197                         gsize templen=n;
198                         /* just pass-through any unknown specifiers (including esc) */
199                         /* drop a null char in so printf stops at the end of this specifier,
200                            but put the real character back in (pseudo-const) */
201                         if( length+templen > max )
202                                 templen = max-length;
203                         g_strlcat(s, p,max);
204                         length+=templen;
205                 } else {
206                         gsize templen = strlen(temp);
208                         found = TRUE;
209                         if( length+templen > max )
210                                 templen = max-length;
211                         g_strlcat(s, temp, max);
212                         length+=templen;
213                         g_free(temp);
214                 }
216                 /* advance past the specifier */
217                 p += n;
218         }
220         if(last) *last = p;
222         return length;
225 gsize
226 strfsong(gchar *s, gsize max, const gchar *format, mpd_Song *song)
228   return _strfsong(s, max, format, song, NULL);
230