Code

Modified %shortfile% format to not shorten urls
[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;
41  
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;
77   
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               strncat(s, temp, max-length);
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           strncat(s, p, 1);
141           length++;
142           ++p;
143           continue;
144         }
146       /* let the escape character escape itself */
147       if (p[0] == '#' && p[1] != '\0' && length<max)
148         {
149           strncat(s, p+1, 1);
150           length++;
151           p+=2;
152           continue;
153         }
155       /* advance past the esc character */
157       /* find the extent of this format specifier (stop at \0, ' ', or esc) */
158       temp = NULL;
159       end  = p+1;
160       while(*end >= 'a' && *end <= 'z')
161         {
162           end++;
163         }
164       n = end - p + 1;
165       if(*end != '%')
166         n--;
167       else if (strncmp("%file%", p, n) == 0)
168         temp = utf8_to_locale(song->file);
169       else if (strncmp("%artist%", p, n) == 0)
170         temp = song->artist ? utf8_to_locale(song->artist) : NULL;
171       else if (strncmp("%title%", p, n) == 0)
172         temp = song->title ? utf8_to_locale(song->title) : NULL;
173       else if (strncmp("%album%", p, n) == 0)
174         temp = song->album ? utf8_to_locale(song->album) : NULL;
175       else if (strncmp("%track%", p, n) == 0)
176         temp = song->track ? utf8_to_locale(song->track) : NULL;
177       else if (strncmp("%name%", p, n) == 0)
178         temp = song->name ? utf8_to_locale(song->name) : NULL;
179       else if (strncmp("%shortfile%", p, n) == 0)
180         {
181           if( strstr(song->file, "://") )
182             temp = utf8_to_locale(song->file);
183           else
184             temp = utf8_to_locale(basename(song->file));
185         }
186       else if (strncmp("%time%", p, n) == 0)
187         {
188           if (song->time != MPD_SONG_NO_TIME) {
189             gchar s[10];
190             snprintf(s, 9, "%d:%d", song->time / 60, 
191                      song->time % 60 + 1);
192             /* nasty hack to use static buffer */
193             temp = g_strdup(s);
194           }
195         }
197       if( temp == NULL)
198         {
199           gsize templen=n;
200           /* just pass-through any unknown specifiers (including esc) */
201           /* drop a null char in so printf stops at the end of this specifier,
202              but put the real character back in (pseudo-const) */
203           if( length+templen > max )
204             templen = max-length;
205           strncat(s, p, templen);
206           length+=templen;
207         }
208       else {
209         gsize templen = strlen(temp);
211         found = TRUE;
212         if( length+templen > max )
213           templen = max-length;
214         strncat(s, temp, templen);
215         length+=templen;
216         g_free(temp);
217       }
219       /* advance past the specifier */
220       p += n;
221     }
223   if(last) *last = p;
225   return length;
228 gsize
229 strfsong(gchar *s, gsize max, const gchar *format, mpd_Song *song)
231   return _strfsong(s, max, format, song, NULL);
233