Mercurial > audlegacy-plugins
comparison src/xspf/xspf.c @ 641:3f0a3c24f2b9 trunk
[svn] libxspf improvements:
- now libxspf can parse relative path with xml:base notation.
- backward compatibility support for base64 and locale_to_utf8 has been removed.
- make use of libxml2's url encoding/decoding.
- now mtime is always recorded even if the value is 0.
- tentative support for "staticlist".
-- if a mtime entry for each track is set to 0, metadata for corresponding track will not be updated automatically.
-- if there is an element shown below in the playlist-element, all mtime entries in the playlist will be regarded as 0 so that whole metadata in the playlist will be conserved.
staticlist element:
<extension application="audacious">
<options staticlist="true"/>
</extension>
author | yaz |
---|---|
date | Mon, 12 Feb 2007 20:02:17 -0800 |
parents | 2d20bc58a290 |
children | 2605c5515bab |
comparison
equal
deleted
inserted
replaced
640:0fde94f6285f | 641:3f0a3c24f2b9 |
---|---|
20 | 20 |
21 #include <config.h> | 21 #include <config.h> |
22 | 22 |
23 #include <glib.h> | 23 #include <glib.h> |
24 #include <string.h> | 24 #include <string.h> |
25 #include <glib.h> | |
26 #include <glib/gprintf.h> | |
27 #include <stdlib.h> | 25 #include <stdlib.h> |
28 #include <string.h> | |
29 #include <time.h> | 26 #include <time.h> |
30 | 27 |
31 #include <unistd.h> | 28 #include <unistd.h> |
32 #include <sys/types.h> | 29 #include <sys/types.h> |
33 #include <sys/stat.h> | 30 #include <sys/stat.h> |
42 #include <libxml/tree.h> | 39 #include <libxml/tree.h> |
43 #include <libxml/parser.h> | 40 #include <libxml/parser.h> |
44 #include <libxml/xmlreader.h> | 41 #include <libxml/xmlreader.h> |
45 #include <libxml/xpath.h> | 42 #include <libxml/xpath.h> |
46 #include <libxml/xpathInternals.h> | 43 #include <libxml/xpathInternals.h> |
47 | 44 #include <libxml/uri.h> |
48 #include "urlencode.h" | 45 |
49 #include "base64.h" | 46 #define XSPF_ROOT_NODE_NAME "playlist" |
47 #define XSPF_XMLNS "http://xspf.org/ns/0/" | |
50 | 48 |
51 #define TMP_BUF_LEN 128 | 49 #define TMP_BUF_LEN 128 |
50 | |
51 gchar *base = NULL; | |
52 gboolean override_mtime = FALSE; | |
52 | 53 |
53 static void | 54 static void |
54 add_file(xmlNode *track, const gchar *filename, gint pos) | 55 add_file(xmlNode *track, const gchar *filename, gint pos) |
55 { | 56 { |
56 xmlNode *nptr; | 57 xmlNode *nptr; |
57 TitleInput *tuple; | 58 TitleInput *tuple; |
58 gchar *location = NULL, *b64filename = NULL, *locale_uri = NULL; | 59 gchar *location = NULL; |
59 Playlist *playlist = playlist_get_active(); | 60 Playlist *playlist = playlist_get_active(); |
60 | 61 |
61 tuple = bmp_title_input_new(); | 62 tuple = bmp_title_input_new(); |
63 | |
64 // staticlist hack | |
65 tuple->mtime = -1; // mark as uninitialized. | |
62 | 66 |
63 // creator, album, title, duration, trackNum, annotation, image, | 67 // creator, album, title, duration, trackNum, annotation, image, |
64 for(nptr = track->children; nptr != NULL; nptr = nptr->next){ | 68 for(nptr = track->children; nptr != NULL; nptr = nptr->next){ |
65 if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "location")){ | 69 if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"location")){ |
66 GError *err = NULL; | 70 gchar *str = (gchar *)xmlNodeGetContent(nptr); |
67 gchar *tmp = NULL, *tmp2 = NULL; | 71 gchar *tmp = (gchar *)xmlURIUnescapeString(str, -1, NULL); |
68 xmlChar *str = xmlNodeGetContent(nptr); | 72 |
69 tmp = g_locale_from_utf8(str, -1, NULL, NULL, &err); //for backward compatibility | 73 if(strstr(tmp, "file://")){ |
70 if(err != NULL) { | 74 location = g_strdup_printf("%s%s", base ? base : "", tmp+7); |
71 tmp2 = xspf_url_decode(str); | |
72 } | 75 } |
73 else { | 76 else { |
74 tmp2= xspf_url_decode(tmp); | 77 location = g_strdup_printf("%s%s", base ? base : "", tmp); |
75 } | 78 } |
76 if(strstr(tmp2, "file://")){ | 79 xmlFree(str); g_free(tmp); |
77 location = g_strdup(tmp2+7); | 80 } |
78 } | 81 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"title")){ |
79 else { | |
80 location = g_strdup(tmp2); | |
81 } | |
82 xmlFree(str); | |
83 g_free(tmp); g_free(err); g_free(tmp2); | |
84 } | |
85 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "title")){ | |
86 tuple->track_name = (gchar *)xmlNodeGetContent(nptr); | 82 tuple->track_name = (gchar *)xmlNodeGetContent(nptr); |
87 } | 83 } |
88 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "creator")){ | 84 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"creator")){ |
89 tuple->performer = (gchar *)xmlNodeGetContent(nptr); | 85 tuple->performer = (gchar *)xmlNodeGetContent(nptr); |
90 } | 86 } |
91 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "annotation")){ | 87 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"annotation")){ |
92 tuple->comment = (gchar *)xmlNodeGetContent(nptr); | 88 tuple->comment = (gchar *)xmlNodeGetContent(nptr); |
93 continue; | 89 continue; |
94 } | 90 } |
95 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "album")){ | 91 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"album")){ |
96 tuple->album_name = (gchar *)xmlNodeGetContent(nptr); | 92 tuple->album_name = (gchar *)xmlNodeGetContent(nptr); |
97 } | 93 } |
98 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "trackNum")){ | 94 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"trackNum")){ |
99 xmlChar *str = xmlNodeGetContent(nptr); | 95 xmlChar *str = xmlNodeGetContent(nptr); |
100 tuple->track_number = atol(str); | 96 tuple->track_number = atol((char *)str); |
101 xmlFree(str); | 97 xmlFree(str); |
102 } | 98 } |
103 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "duration")){ | 99 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"duration")){ |
104 xmlChar *str = xmlNodeGetContent(nptr); | 100 xmlChar *str = xmlNodeGetContent(nptr); |
105 tuple->length = atol(str); | 101 tuple->length = atol((char *)str); |
106 xmlFree(str); | 102 xmlFree(str); |
107 } | 103 } |
108 | 104 |
109 // | 105 // |
110 // additional metadata | 106 // additional metadata |
111 // | 107 // |
112 // year, date, genre, formatter, mtime, b64filename | 108 // year, date, genre, formatter, mtime |
113 // | 109 // |
114 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "meta")){ | 110 else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"meta")){ |
115 xmlChar *rel = NULL; | 111 xmlChar *rel = NULL; |
116 | 112 |
117 rel = xmlGetProp(nptr, "rel"); | 113 rel = xmlGetProp(nptr, (xmlChar *)"rel"); |
118 | 114 |
119 if(!xmlStrcmp(rel, "year")){ | 115 if(!xmlStrcmp(rel, (xmlChar *)"year")){ |
120 xmlChar *cont = xmlNodeGetContent(nptr); | 116 xmlChar *cont = xmlNodeGetContent(nptr); |
121 tuple->year = atol(cont); | 117 tuple->year = atol((char *)cont); |
122 xmlFree(cont); | 118 xmlFree(cont); |
123 continue; | 119 continue; |
124 } | 120 } |
125 else if(!xmlStrcmp(rel, "date")){ | 121 else if(!xmlStrcmp(rel, (xmlChar *)"date")){ |
126 tuple->date = (gchar *)xmlNodeGetContent(nptr); | 122 tuple->date = (gchar *)xmlNodeGetContent(nptr); |
127 continue; | 123 continue; |
128 } | 124 } |
129 else if(!xmlStrcmp(rel, "genre")){ | 125 else if(!xmlStrcmp(rel, (xmlChar *)"genre")){ |
130 tuple->genre = (gchar *)xmlNodeGetContent(nptr); | 126 tuple->genre = (gchar *)xmlNodeGetContent(nptr); |
131 continue; | 127 continue; |
132 } | 128 } |
133 else if(!xmlStrcmp(rel, "formatter")){ | 129 else if(!xmlStrcmp(rel, (xmlChar *)"formatter")){ |
134 tuple->formatter = (gchar *)xmlNodeGetContent(nptr); | 130 tuple->formatter = (gchar *)xmlNodeGetContent(nptr); |
135 continue; | 131 continue; |
136 } | 132 } |
137 else if(!xmlStrcmp(rel, "mtime")){ | 133 else if(!xmlStrcmp(rel, (xmlChar *)"mtime")){ |
138 xmlChar *str = NULL; | 134 xmlChar *str = NULL; |
139 str = xmlNodeGetContent(nptr); | 135 str = xmlNodeGetContent(nptr); |
140 tuple->mtime = (time_t)atoll(str); | 136 tuple->mtime = (time_t)atoll((char *)str); |
141 xmlFree(str); | 137 xmlFree(str); |
142 continue; | 138 continue; |
143 } | 139 } |
144 else if(!xmlStrcmp(rel, "b64filename")){ //for backward compatibility | |
145 gchar *b64str = NULL; | |
146 b64str = (gchar *)xmlNodeGetContent(nptr); | |
147 b64filename = g_malloc0(strlen(b64str)*3/4+1); | |
148 from64tobits(b64filename, b64str); | |
149 g_free(b64str); | |
150 continue; | |
151 } | |
152 xmlFree(rel); | 140 xmlFree(rel); |
153 rel = NULL; | 141 rel = NULL; |
154 } | 142 } |
155 | 143 |
156 } | 144 } |
157 | 145 |
158 if (tuple->length == 0) { | 146 if (tuple->length == 0) { |
159 tuple->length = -1; | 147 tuple->length = -1; |
160 } | 148 } |
161 | 149 |
162 if (tuple->mtime == 0) { | 150 if(override_mtime) { |
163 tuple->mtime = -1; | 151 tuple->mtime = 0; //when mtime=0, scanning will be skipped. --yaz |
164 } | 152 } |
165 | 153 |
166 locale_uri = b64filename ? b64filename : location; | 154 if(location){ |
167 | 155 tuple->file_name = g_path_get_basename(location); |
168 if(locale_uri){ | 156 tuple->file_path = g_path_get_dirname(location); |
169 tuple->file_name = g_path_get_basename(locale_uri); | 157 tuple->file_ext = g_strdup(strrchr(location, '.')); |
170 tuple->file_path = g_path_get_dirname(locale_uri); | |
171 tuple->file_ext = g_strdup(strrchr(locale_uri, '.')); | |
172 // add file to playlist | 158 // add file to playlist |
173 playlist_load_ins_file_tuple(playlist, locale_uri, filename, pos, tuple); | 159 playlist_load_ins_file_tuple(playlist, location, filename, pos, tuple); |
174 pos++; | 160 pos++; |
175 } | 161 } |
176 | 162 |
177 g_free(location); g_free(b64filename); | 163 g_free(location); |
178 locale_uri = NULL; location = NULL; b64filename = NULL; | 164 location = NULL; |
179 } | 165 } |
180 | 166 |
181 static void | 167 static void |
182 find_track(xmlNode *tracklist, const gchar *filename, gint pos) | 168 find_track(xmlNode *tracklist, const gchar *filename, gint pos) |
183 { | 169 { |
184 xmlNode *nptr; | 170 xmlNode *nptr; |
185 for(nptr = tracklist->children; nptr != NULL; nptr = nptr->next){ | 171 for(nptr = tracklist->children; nptr != NULL; nptr = nptr->next){ |
186 if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "track")){ | 172 if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"track")){ |
187 add_file(nptr, filename, pos); | 173 add_file(nptr, filename, pos); |
174 } | |
175 } | |
176 } | |
177 | |
178 static void | |
179 find_audoptions(xmlNode *tracklist, const gchar *filename, gint pos) | |
180 { | |
181 xmlNode *nptr; | |
182 for(nptr = tracklist->children; nptr != NULL; nptr = nptr->next){ | |
183 if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"options")){ | |
184 xmlChar *opt = NULL; | |
185 | |
186 opt = xmlGetProp(nptr, (xmlChar *)"staticlist"); | |
187 if(!strcasecmp((char *)opt, "true")){ | |
188 override_mtime = TRUE; | |
189 } | |
190 xmlFree(opt); | |
191 opt = NULL; | |
188 } | 192 } |
189 } | 193 } |
190 } | 194 } |
191 | 195 |
192 static void | 196 static void |
199 | 203 |
200 doc = xmlParseFile(filename); | 204 doc = xmlParseFile(filename); |
201 if (doc == NULL) | 205 if (doc == NULL) |
202 return; | 206 return; |
203 | 207 |
208 xmlFree(base); | |
209 base = NULL; | |
210 | |
204 // find trackList | 211 // find trackList |
205 for(nptr = doc->children; nptr != NULL; nptr = nptr->next) { | 212 for(nptr = doc->children; nptr != NULL; nptr = nptr->next) { |
206 if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "playlist")){ | 213 if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"playlist")){ |
207 for(nptr2 = nptr->children; nptr2 != NULL; nptr2 = nptr2->next){ | 214 base = (gchar *)xmlNodeGetBase(doc, nptr); |
208 if(nptr2->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr2->name, "trackList")){ | 215 if(!strcmp(base, filename)) { |
216 xmlFree(base); | |
217 base = NULL; | |
218 } | |
219 | |
220 for(nptr2 = nptr->children; nptr2 != NULL; nptr2 = nptr2->next){ | |
221 | |
222 if(nptr2->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr2->name, (xmlChar *)"extension")){ | |
223 //check if application is audacious | |
224 xmlChar *app = NULL; | |
225 app = xmlGetProp(nptr2, (xmlChar *)"application"); | |
226 if(!xmlStrcmp(app, (xmlChar *)"audacious")) { | |
227 find_audoptions(nptr2, filename, pos); | |
228 } | |
229 xmlFree(app); | |
230 } | |
231 | |
232 if(nptr2->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr2->name, (xmlChar *)"trackList")){ | |
209 find_track(nptr2, filename, pos); | 233 find_track(nptr2, filename, pos); |
210 } | 234 } |
235 | |
211 } | 236 } |
212 | 237 |
213 } | 238 } |
214 } | 239 } |
215 | 240 |
216 xmlFreeDoc(doc); | 241 xmlFreeDoc(doc); |
217 | 242 |
218 } | 243 } |
219 | |
220 | |
221 #define XSPF_ROOT_NODE_NAME "playlist" | |
222 #define XSPF_XMLNS "http://xspf.org/ns/0/" | |
223 | 244 |
224 static void | 245 static void |
225 playlist_save_xspf(const gchar *filename, gint pos) | 246 playlist_save_xspf(const gchar *filename, gint pos) |
226 { | 247 { |
227 xmlDocPtr doc; | 248 xmlDocPtr doc; |
228 xmlNodePtr rootnode, tmp, tracklist; | 249 xmlNodePtr rootnode, tmp, tracklist; |
229 GList *node; | 250 GList *node; |
230 Playlist *playlist = playlist_get_active(); | 251 Playlist *playlist = playlist_get_active(); |
231 | 252 |
232 doc = xmlNewDoc("1.0"); | 253 doc = xmlNewDoc((xmlChar *)"1.0"); |
233 | 254 |
234 doc->charset = XML_CHAR_ENCODING_UTF8; | 255 doc->charset = XML_CHAR_ENCODING_UTF8; |
235 doc->encoding = xmlStrdup("UTF-8"); | 256 doc->encoding = xmlStrdup((xmlChar *)"UTF-8"); |
236 | 257 |
237 rootnode = xmlNewNode(NULL, XSPF_ROOT_NODE_NAME); | 258 rootnode = xmlNewNode(NULL, (xmlChar *)XSPF_ROOT_NODE_NAME); |
238 xmlSetProp(rootnode, "xmlns", XSPF_XMLNS); | 259 xmlSetProp(rootnode, (xmlChar *)"xmlns", (xmlChar *)XSPF_XMLNS); |
239 xmlSetProp(rootnode, "version", "1"); | 260 xmlSetProp(rootnode, (xmlChar *)"version", (xmlChar *)"1"); |
240 xmlDocSetRootElement(doc, rootnode); | 261 xmlDocSetRootElement(doc, rootnode); |
241 | 262 |
242 tmp = xmlNewNode(NULL, "creator"); | 263 tmp = xmlNewNode(NULL, (xmlChar *)"creator"); |
243 xmlAddChild(tmp, xmlNewText(PACKAGE "-" VERSION)); | 264 xmlAddChild(tmp, xmlNewText((xmlChar *)PACKAGE "-" VERSION)); |
244 xmlAddChild(rootnode, tmp); | 265 xmlAddChild(rootnode, tmp); |
245 | 266 |
246 tracklist = xmlNewNode(NULL, "trackList"); | 267 tracklist = xmlNewNode(NULL, (xmlChar *)"trackList"); |
247 xmlAddChild(rootnode, tracklist); | 268 xmlAddChild(rootnode, tracklist); |
248 | 269 |
249 PLAYLIST_LOCK(playlist->mutex); | 270 PLAYLIST_LOCK(playlist->mutex); |
250 | 271 |
251 for (node = playlist->entries; node != NULL; node = g_list_next(node)) | 272 for (node = playlist->entries; node != NULL; node = g_list_next(node)) |
252 { | 273 { |
253 PlaylistEntry *entry = PLAYLIST_ENTRY(node->data); | 274 PlaylistEntry *entry = PLAYLIST_ENTRY(node->data); |
254 xmlNodePtr track, location; | 275 xmlNodePtr track, location; |
255 gchar *filename = NULL; | 276 gchar *filename = NULL; |
256 | 277 |
257 track = xmlNewNode(NULL, "track"); | 278 track = xmlNewNode(NULL, (xmlChar *)"track"); |
258 location = xmlNewNode(NULL, "location"); | 279 location = xmlNewNode(NULL, (xmlChar *)"location"); |
259 | 280 |
260 /* url encode file name. exclude streaming for now. */ | 281 /* url encode file name. exclude streaming for now. */ |
261 if (strncasecmp("http://", entry->filename, 7) && | 282 if (strncasecmp("http://", entry->filename, 7) && |
262 strncasecmp("https://", entry->filename, 8)) { /* the rest */ | 283 strncasecmp("https://", entry->filename, 8)) { /* the rest */ |
263 gchar *tmp = (gchar *)xspf_url_encode(entry->filename); | 284 gchar *tmp = (gchar *)xmlPathToURI((const xmlChar *)entry->filename); |
285 printf("xmlPathToURI = %s\n", tmp); | |
264 filename = g_strdup_printf("file://%s", tmp); | 286 filename = g_strdup_printf("file://%s", tmp); |
265 g_free(tmp); | 287 g_free(tmp); |
266 } | 288 } |
267 else { /* streaming */ | 289 else { /* streaming */ |
268 filename = strdup(entry->filename); | 290 filename = (gchar *)xmlURIEscape((xmlChar *)entry->filename); |
269 } | 291 } |
270 | 292 |
271 if(!g_utf8_validate(filename, -1, NULL)) | 293 if(!g_utf8_validate(filename, -1, NULL)) |
272 continue; | 294 continue; |
273 | 295 |
274 xmlAddChild(location, xmlNewText(filename)); | 296 xmlAddChild(location, xmlNewText((xmlChar *)filename)); |
275 xmlAddChild(track, location); | 297 xmlAddChild(track, location); |
276 xmlAddChild(tracklist, track); | 298 xmlAddChild(tracklist, track); |
277 | 299 |
278 /* do we have a tuple? */ | 300 /* do we have a tuple? */ |
279 if (entry->tuple != NULL) | 301 if (entry->tuple != NULL) |
280 { | 302 { |
281 if (entry->tuple->track_name != NULL && | 303 if (entry->tuple->track_name != NULL && |
282 g_utf8_validate(entry->tuple->track_name, -1, NULL)) | 304 g_utf8_validate(entry->tuple->track_name, -1, NULL)) |
283 { | 305 { |
284 tmp = xmlNewNode(NULL, "title"); | 306 tmp = xmlNewNode(NULL, (xmlChar *)"title"); |
285 xmlAddChild(tmp, xmlNewText(entry->tuple->track_name)); | 307 xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->track_name)); |
286 xmlAddChild(track, tmp); | 308 xmlAddChild(track, tmp); |
287 } | 309 } |
288 | 310 |
289 if (entry->tuple->performer != NULL && | 311 if (entry->tuple->performer != NULL && |
290 g_utf8_validate(entry->tuple->performer, -1, NULL)) | 312 g_utf8_validate(entry->tuple->performer, -1, NULL)) |
291 { | 313 { |
292 tmp = xmlNewNode(NULL, "creator"); | 314 tmp = xmlNewNode(NULL, (xmlChar *)"creator"); |
293 xmlAddChild(tmp, xmlNewText(entry->tuple->performer)); | 315 xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->performer)); |
294 xmlAddChild(track, tmp); | 316 xmlAddChild(track, tmp); |
295 } | 317 } |
296 | 318 |
297 if (entry->tuple->comment != NULL && | 319 if (entry->tuple->comment != NULL && |
298 g_utf8_validate(entry->tuple->comment, -1, NULL)) | 320 g_utf8_validate(entry->tuple->comment, -1, NULL)) |
299 { | 321 { |
300 tmp = xmlNewNode(NULL, "annotation"); | 322 tmp = xmlNewNode(NULL, (xmlChar *)"annotation"); |
301 xmlAddChild(tmp, xmlNewText(entry->tuple->comment)); | 323 xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->comment)); |
302 xmlAddChild(track, tmp); | 324 xmlAddChild(track, tmp); |
303 } | 325 } |
304 | 326 |
305 if (entry->tuple->album_name != NULL && | 327 if (entry->tuple->album_name != NULL && |
306 g_utf8_validate(entry->tuple->album_name, -1, NULL)) | 328 g_utf8_validate(entry->tuple->album_name, -1, NULL)) |
307 { | 329 { |
308 tmp = xmlNewNode(NULL, "album"); | 330 tmp = xmlNewNode(NULL, (xmlChar *)"album"); |
309 xmlAddChild(tmp, xmlNewText(entry->tuple->album_name)); | 331 xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->album_name)); |
310 xmlAddChild(track, tmp); | 332 xmlAddChild(track, tmp); |
311 } | 333 } |
312 | 334 |
313 if (entry->tuple->track_number != 0) | 335 if (entry->tuple->track_number != 0) |
314 { | 336 { |
315 gchar *str; | 337 gchar *str; |
316 str = g_malloc(TMP_BUF_LEN); | 338 str = g_malloc(TMP_BUF_LEN); |
317 tmp = xmlNewNode(NULL, "trackNum"); | 339 tmp = xmlNewNode(NULL, (xmlChar *)"trackNum"); |
318 sprintf(str, "%d", entry->tuple->track_number); | 340 sprintf(str, "%d", entry->tuple->track_number); |
319 xmlAddChild(tmp, xmlNewText(str)); | 341 xmlAddChild(tmp, xmlNewText((xmlChar *)str)); |
320 g_free(str); | 342 g_free(str); |
321 xmlAddChild(track, tmp); | 343 xmlAddChild(track, tmp); |
322 } | 344 } |
323 | 345 |
324 if (entry->tuple->length > 0) | 346 if (entry->tuple->length > 0) |
325 { | 347 { |
326 gchar *str; | 348 gchar *str; |
327 str = g_malloc(TMP_BUF_LEN); | 349 str = g_malloc(TMP_BUF_LEN); |
328 tmp = xmlNewNode(NULL, "duration"); | 350 tmp = xmlNewNode(NULL, (xmlChar *)"duration"); |
329 sprintf(str, "%d", entry->tuple->length); | 351 sprintf(str, "%d", entry->tuple->length); |
330 xmlAddChild(tmp, xmlNewText(str)); | 352 xmlAddChild(tmp, xmlNewText((xmlChar *)str)); |
331 g_free(str); | 353 g_free(str); |
332 xmlAddChild(track, tmp); | 354 xmlAddChild(track, tmp); |
333 } | 355 } |
334 | 356 |
335 // | 357 // |
339 // | 361 // |
340 if (entry->tuple->year != 0) | 362 if (entry->tuple->year != 0) |
341 { | 363 { |
342 gchar *str; | 364 gchar *str; |
343 str = g_malloc(TMP_BUF_LEN); | 365 str = g_malloc(TMP_BUF_LEN); |
344 tmp = xmlNewNode(NULL, "meta"); | 366 tmp = xmlNewNode(NULL, (xmlChar *)"meta"); |
345 xmlSetProp(tmp, "rel", "year"); | 367 xmlSetProp(tmp, (xmlChar *)"rel", (xmlChar *)"year"); |
346 sprintf(str, "%d", entry->tuple->year); | 368 sprintf(str, "%d", entry->tuple->year); |
347 xmlAddChild(tmp, xmlNewText(str)); | 369 xmlAddChild(tmp, xmlNewText((xmlChar *)str)); |
348 xmlAddChild(track, tmp); | 370 xmlAddChild(track, tmp); |
349 g_free(str); | 371 g_free(str); |
350 } | 372 } |
351 | 373 |
352 if (entry->tuple->date != NULL && | 374 if (entry->tuple->date != NULL && |
353 g_utf8_validate(entry->tuple->date, -1, NULL)) | 375 g_utf8_validate(entry->tuple->date, -1, NULL)) |
354 { | 376 { |
355 tmp = xmlNewNode(NULL, "meta"); | 377 tmp = xmlNewNode(NULL, (xmlChar *)"meta"); |
356 xmlSetProp(tmp, "rel", "date"); | 378 xmlSetProp(tmp, (xmlChar *)"rel", (xmlChar *)"date"); |
357 xmlAddChild(tmp, xmlNewText(entry->tuple->date)); | 379 xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->date)); |
358 xmlAddChild(track, tmp); | 380 xmlAddChild(track, tmp); |
359 } | 381 } |
360 | 382 |
361 if (entry->tuple->genre != NULL && | 383 if (entry->tuple->genre != NULL && |
362 g_utf8_validate(entry->tuple->genre, -1, NULL)) | 384 g_utf8_validate(entry->tuple->genre, -1, NULL)) |
363 { | 385 { |
364 tmp = xmlNewNode(NULL, "meta"); | 386 tmp = xmlNewNode(NULL, (xmlChar *)"meta"); |
365 xmlSetProp(tmp, "rel", "genre"); | 387 xmlSetProp(tmp, (xmlChar *)"rel", (xmlChar *)"genre"); |
366 xmlAddChild(tmp, xmlNewText(entry->tuple->genre)); | 388 xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->genre)); |
367 xmlAddChild(track, tmp); | 389 xmlAddChild(track, tmp); |
368 } | 390 } |
369 | 391 |
370 if (entry->tuple->formatter != NULL && | 392 if (entry->tuple->formatter != NULL && |
371 g_utf8_validate(entry->tuple->formatter, -1, NULL)) | 393 g_utf8_validate(entry->tuple->formatter, -1, NULL)) |
372 { | 394 { |
373 tmp = xmlNewNode(NULL, "meta"); | 395 tmp = xmlNewNode(NULL, (xmlChar *)"meta"); |
374 xmlSetProp(tmp, "rel", "formatter"); | 396 xmlSetProp(tmp, (xmlChar *)"rel", (xmlChar *)"formatter"); |
375 xmlAddChild(tmp, xmlNewText(entry->tuple->formatter)); | 397 xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->formatter)); |
376 xmlAddChild(track, tmp); | 398 xmlAddChild(track, tmp); |
377 } | 399 } |
378 | 400 |
379 if (entry->tuple->mtime) { | 401 // mtime: write mtime unconditionally for staticlist hack. |
402 // if (entry->tuple->mtime) { | |
380 gchar *str; | 403 gchar *str; |
381 str = g_malloc(TMP_BUF_LEN); | 404 str = g_malloc(TMP_BUF_LEN); |
382 tmp = xmlNewNode(NULL, "meta"); | 405 tmp = xmlNewNode(NULL, (xmlChar *)"meta"); |
383 xmlSetProp(tmp, "rel", "mtime"); | 406 xmlSetProp(tmp, (xmlChar *)"rel", (xmlChar *)"mtime"); |
384 sprintf(str, "%ld", (long) entry->tuple->mtime); | 407 sprintf(str, "%ld", (long) entry->tuple->mtime); |
385 xmlAddChild(tmp, xmlNewText(str)); | 408 xmlAddChild(tmp, xmlNewText((xmlChar *)str)); |
386 xmlAddChild(track, tmp); | 409 xmlAddChild(track, tmp); |
387 g_free(str); | 410 g_free(str); |
388 } | 411 // } |
389 | 412 |
390 } | 413 } |
391 g_free(filename); | 414 g_free(filename); |
392 filename = NULL; | 415 filename = NULL; |
393 } | 416 } |