# HG changeset patch
# User yaz
# Date 1171339337 28800
# Node ID 3f0a3c24f2b9e8f95adae1c8dc4136fa0924b754
# Parent 0fde94f6285fc203ad7c3d4c926dc542b98159d7
[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:
diff -r 0fde94f6285f -r 3f0a3c24f2b9 ChangeLog
--- a/ChangeLog Mon Feb 12 12:54:12 2007 -0800
+++ b/ChangeLog Mon Feb 12 20:02:17 2007 -0800
@@ -1,3 +1,12 @@
+2007-02-12 20:54:12 +0000 William Pitcock
+ revision [1366]
+ - add Catalan translation file. Closes #787.
+
+ trunk/po/LINGUAS | 1
+ trunk/po/ca.po | 2126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 2127 insertions(+)
+
+
2007-02-12 18:12:29 +0000 Yoshiki Yazawa
revision [1364]
- follow the changes of libaudid3tag.
diff -r 0fde94f6285f -r 3f0a3c24f2b9 src/xspf/Makefile
--- a/src/xspf/Makefile Mon Feb 12 12:54:12 2007 -0800
+++ b/src/xspf/Makefile Mon Feb 12 20:02:17 2007 -0800
@@ -5,11 +5,11 @@
LIBDIR = $(plugindir)/$(CONTAINER_PLUGIN_DIR)
-SOURCES = xspf.c base64.c urlencode.c
+SOURCES = xspf.c
OBJECTS = ${SOURCES:.c=.o}
-CFLAGS += $(PICFLAGS) $(GTK_CFLAGS) $(GLIB_CFLAGS) $(PANGO_CFLAGS) $(ARCH_DEFINES) $(XML_CPPFLAGS) -I../../intl -I../..
+CFLAGS += $(PICFLAGS) $(GTK_CFLAGS) $(GLIB_CFLAGS) $(PANGO_CFLAGS) $(ARCH_DEFINES) $(XML_CPPFLAGS) -I../../intl -I../.. -Wall
CXXFLAGS = $(CFLAGS)
diff -r 0fde94f6285f -r 3f0a3c24f2b9 src/xspf/xspf.c
--- a/src/xspf/xspf.c Mon Feb 12 12:54:12 2007 -0800
+++ b/src/xspf/xspf.c Mon Feb 12 20:02:17 2007 -0800
@@ -22,10 +22,7 @@
#include
#include
-#include
-#include
#include
-#include
#include
#include
@@ -44,111 +41,102 @@
#include
#include
#include
+#include
-#include "urlencode.h"
-#include "base64.h"
+#define XSPF_ROOT_NODE_NAME "playlist"
+#define XSPF_XMLNS "http://xspf.org/ns/0/"
#define TMP_BUF_LEN 128
+gchar *base = NULL;
+gboolean override_mtime = FALSE;
+
static void
add_file(xmlNode *track, const gchar *filename, gint pos)
{
xmlNode *nptr;
TitleInput *tuple;
- gchar *location = NULL, *b64filename = NULL, *locale_uri = NULL;
+ gchar *location = NULL;
Playlist *playlist = playlist_get_active();
tuple = bmp_title_input_new();
+ // staticlist hack
+ tuple->mtime = -1; // mark as uninitialized.
+
// creator, album, title, duration, trackNum, annotation, image,
for(nptr = track->children; nptr != NULL; nptr = nptr->next){
- if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "location")){
- GError *err = NULL;
- gchar *tmp = NULL, *tmp2 = NULL;
- xmlChar *str = xmlNodeGetContent(nptr);
- tmp = g_locale_from_utf8(str, -1, NULL, NULL, &err); //for backward compatibility
- if(err != NULL) {
- tmp2 = xspf_url_decode(str);
+ if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"location")){
+ gchar *str = (gchar *)xmlNodeGetContent(nptr);
+ gchar *tmp = (gchar *)xmlURIUnescapeString(str, -1, NULL);
+
+ if(strstr(tmp, "file://")){
+ location = g_strdup_printf("%s%s", base ? base : "", tmp+7);
}
else {
- tmp2= xspf_url_decode(tmp);
- }
- if(strstr(tmp2, "file://")){
- location = g_strdup(tmp2+7);
+ location = g_strdup_printf("%s%s", base ? base : "", tmp);
}
- else {
- location = g_strdup(tmp2);
- }
- xmlFree(str);
- g_free(tmp); g_free(err); g_free(tmp2);
+ xmlFree(str); g_free(tmp);
}
- else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "title")){
+ else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"title")){
tuple->track_name = (gchar *)xmlNodeGetContent(nptr);
}
- else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "creator")){
+ else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"creator")){
tuple->performer = (gchar *)xmlNodeGetContent(nptr);
}
- else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "annotation")){
+ else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"annotation")){
tuple->comment = (gchar *)xmlNodeGetContent(nptr);
continue;
}
- else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "album")){
+ else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"album")){
tuple->album_name = (gchar *)xmlNodeGetContent(nptr);
}
- else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "trackNum")){
+ else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"trackNum")){
xmlChar *str = xmlNodeGetContent(nptr);
- tuple->track_number = atol(str);
+ tuple->track_number = atol((char *)str);
xmlFree(str);
}
- else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "duration")){
+ else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"duration")){
xmlChar *str = xmlNodeGetContent(nptr);
- tuple->length = atol(str);
+ tuple->length = atol((char *)str);
xmlFree(str);
}
//
// additional metadata
//
- // year, date, genre, formatter, mtime, b64filename
+ // year, date, genre, formatter, mtime
//
- else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "meta")){
+ else if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"meta")){
xmlChar *rel = NULL;
- rel = xmlGetProp(nptr, "rel");
+ rel = xmlGetProp(nptr, (xmlChar *)"rel");
- if(!xmlStrcmp(rel, "year")){
+ if(!xmlStrcmp(rel, (xmlChar *)"year")){
xmlChar *cont = xmlNodeGetContent(nptr);
- tuple->year = atol(cont);
+ tuple->year = atol((char *)cont);
xmlFree(cont);
continue;
}
- else if(!xmlStrcmp(rel, "date")){
+ else if(!xmlStrcmp(rel, (xmlChar *)"date")){
tuple->date = (gchar *)xmlNodeGetContent(nptr);
continue;
}
- else if(!xmlStrcmp(rel, "genre")){
+ else if(!xmlStrcmp(rel, (xmlChar *)"genre")){
tuple->genre = (gchar *)xmlNodeGetContent(nptr);
continue;
}
- else if(!xmlStrcmp(rel, "formatter")){
+ else if(!xmlStrcmp(rel, (xmlChar *)"formatter")){
tuple->formatter = (gchar *)xmlNodeGetContent(nptr);
continue;
}
- else if(!xmlStrcmp(rel, "mtime")){
+ else if(!xmlStrcmp(rel, (xmlChar *)"mtime")){
xmlChar *str = NULL;
str = xmlNodeGetContent(nptr);
- tuple->mtime = (time_t)atoll(str);
+ tuple->mtime = (time_t)atoll((char *)str);
xmlFree(str);
continue;
}
- else if(!xmlStrcmp(rel, "b64filename")){ //for backward compatibility
- gchar *b64str = NULL;
- b64str = (gchar *)xmlNodeGetContent(nptr);
- b64filename = g_malloc0(strlen(b64str)*3/4+1);
- from64tobits(b64filename, b64str);
- g_free(b64str);
- continue;
- }
xmlFree(rel);
rel = NULL;
}
@@ -159,23 +147,21 @@
tuple->length = -1;
}
- if (tuple->mtime == 0) {
- tuple->mtime = -1;
- }
-
- locale_uri = b64filename ? b64filename : location;
+ if(override_mtime) {
+ tuple->mtime = 0; //when mtime=0, scanning will be skipped. --yaz
+ }
- if(locale_uri){
- tuple->file_name = g_path_get_basename(locale_uri);
- tuple->file_path = g_path_get_dirname(locale_uri);
- tuple->file_ext = g_strdup(strrchr(locale_uri, '.'));
+ if(location){
+ tuple->file_name = g_path_get_basename(location);
+ tuple->file_path = g_path_get_dirname(location);
+ tuple->file_ext = g_strdup(strrchr(location, '.'));
// add file to playlist
- playlist_load_ins_file_tuple(playlist, locale_uri, filename, pos, tuple);
+ playlist_load_ins_file_tuple(playlist, location, filename, pos, tuple);
pos++;
}
- g_free(location); g_free(b64filename);
- locale_uri = NULL; location = NULL; b64filename = NULL;
+ g_free(location);
+ location = NULL;
}
static void
@@ -183,13 +169,31 @@
{
xmlNode *nptr;
for(nptr = tracklist->children; nptr != NULL; nptr = nptr->next){
- if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "track")){
+ if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"track")){
add_file(nptr, filename, pos);
}
}
}
static void
+find_audoptions(xmlNode *tracklist, const gchar *filename, gint pos)
+{
+ xmlNode *nptr;
+ for(nptr = tracklist->children; nptr != NULL; nptr = nptr->next){
+ if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"options")){
+ xmlChar *opt = NULL;
+
+ opt = xmlGetProp(nptr, (xmlChar *)"staticlist");
+ if(!strcasecmp((char *)opt, "true")){
+ override_mtime = TRUE;
+ }
+ xmlFree(opt);
+ opt = NULL;
+ }
+ }
+}
+
+static void
playlist_load_xspf(const gchar * filename, gint pos)
{
xmlDocPtr doc;
@@ -201,13 +205,34 @@
if (doc == NULL)
return;
+ xmlFree(base);
+ base = NULL;
+
// find trackList
for(nptr = doc->children; nptr != NULL; nptr = nptr->next) {
- if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, "playlist")){
- for(nptr2 = nptr->children; nptr2 != NULL; nptr2 = nptr2->next){
- if(nptr2->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr2->name, "trackList")){
+ if(nptr->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr->name, (xmlChar *)"playlist")){
+ base = (gchar *)xmlNodeGetBase(doc, nptr);
+ if(!strcmp(base, filename)) {
+ xmlFree(base);
+ base = NULL;
+ }
+
+ for(nptr2 = nptr->children; nptr2 != NULL; nptr2 = nptr2->next){
+
+ if(nptr2->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr2->name, (xmlChar *)"extension")){
+ //check if application is audacious
+ xmlChar *app = NULL;
+ app = xmlGetProp(nptr2, (xmlChar *)"application");
+ if(!xmlStrcmp(app, (xmlChar *)"audacious")) {
+ find_audoptions(nptr2, filename, pos);
+ }
+ xmlFree(app);
+ }
+
+ if(nptr2->type == XML_ELEMENT_NODE && !xmlStrcmp(nptr2->name, (xmlChar *)"trackList")){
find_track(nptr2, filename, pos);
}
+
}
}
@@ -217,10 +242,6 @@
}
-
-#define XSPF_ROOT_NODE_NAME "playlist"
-#define XSPF_XMLNS "http://xspf.org/ns/0/"
-
static void
playlist_save_xspf(const gchar *filename, gint pos)
{
@@ -229,21 +250,21 @@
GList *node;
Playlist *playlist = playlist_get_active();
- doc = xmlNewDoc("1.0");
+ doc = xmlNewDoc((xmlChar *)"1.0");
doc->charset = XML_CHAR_ENCODING_UTF8;
- doc->encoding = xmlStrdup("UTF-8");
+ doc->encoding = xmlStrdup((xmlChar *)"UTF-8");
- rootnode = xmlNewNode(NULL, XSPF_ROOT_NODE_NAME);
- xmlSetProp(rootnode, "xmlns", XSPF_XMLNS);
- xmlSetProp(rootnode, "version", "1");
+ rootnode = xmlNewNode(NULL, (xmlChar *)XSPF_ROOT_NODE_NAME);
+ xmlSetProp(rootnode, (xmlChar *)"xmlns", (xmlChar *)XSPF_XMLNS);
+ xmlSetProp(rootnode, (xmlChar *)"version", (xmlChar *)"1");
xmlDocSetRootElement(doc, rootnode);
- tmp = xmlNewNode(NULL, "creator");
- xmlAddChild(tmp, xmlNewText(PACKAGE "-" VERSION));
+ tmp = xmlNewNode(NULL, (xmlChar *)"creator");
+ xmlAddChild(tmp, xmlNewText((xmlChar *)PACKAGE "-" VERSION));
xmlAddChild(rootnode, tmp);
- tracklist = xmlNewNode(NULL, "trackList");
+ tracklist = xmlNewNode(NULL, (xmlChar *)"trackList");
xmlAddChild(rootnode, tracklist);
PLAYLIST_LOCK(playlist->mutex);
@@ -254,24 +275,25 @@
xmlNodePtr track, location;
gchar *filename = NULL;
- track = xmlNewNode(NULL, "track");
- location = xmlNewNode(NULL, "location");
+ track = xmlNewNode(NULL, (xmlChar *)"track");
+ location = xmlNewNode(NULL, (xmlChar *)"location");
/* url encode file name. exclude streaming for now. */
if (strncasecmp("http://", entry->filename, 7) &&
strncasecmp("https://", entry->filename, 8)) { /* the rest */
- gchar *tmp = (gchar *)xspf_url_encode(entry->filename);
+ gchar *tmp = (gchar *)xmlPathToURI((const xmlChar *)entry->filename);
+ printf("xmlPathToURI = %s\n", tmp);
filename = g_strdup_printf("file://%s", tmp);
g_free(tmp);
}
else { /* streaming */
- filename = strdup(entry->filename);
+ filename = (gchar *)xmlURIEscape((xmlChar *)entry->filename);
}
if(!g_utf8_validate(filename, -1, NULL))
continue;
- xmlAddChild(location, xmlNewText(filename));
+ xmlAddChild(location, xmlNewText((xmlChar *)filename));
xmlAddChild(track, location);
xmlAddChild(tracklist, track);
@@ -281,32 +303,32 @@
if (entry->tuple->track_name != NULL &&
g_utf8_validate(entry->tuple->track_name, -1, NULL))
{
- tmp = xmlNewNode(NULL, "title");
- xmlAddChild(tmp, xmlNewText(entry->tuple->track_name));
+ tmp = xmlNewNode(NULL, (xmlChar *)"title");
+ xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->track_name));
xmlAddChild(track, tmp);
}
if (entry->tuple->performer != NULL &&
g_utf8_validate(entry->tuple->performer, -1, NULL))
{
- tmp = xmlNewNode(NULL, "creator");
- xmlAddChild(tmp, xmlNewText(entry->tuple->performer));
+ tmp = xmlNewNode(NULL, (xmlChar *)"creator");
+ xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->performer));
xmlAddChild(track, tmp);
}
if (entry->tuple->comment != NULL &&
g_utf8_validate(entry->tuple->comment, -1, NULL))
{
- tmp = xmlNewNode(NULL, "annotation");
- xmlAddChild(tmp, xmlNewText(entry->tuple->comment));
+ tmp = xmlNewNode(NULL, (xmlChar *)"annotation");
+ xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->comment));
xmlAddChild(track, tmp);
}
if (entry->tuple->album_name != NULL &&
g_utf8_validate(entry->tuple->album_name, -1, NULL))
{
- tmp = xmlNewNode(NULL, "album");
- xmlAddChild(tmp, xmlNewText(entry->tuple->album_name));
+ tmp = xmlNewNode(NULL, (xmlChar *)"album");
+ xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->album_name));
xmlAddChild(track, tmp);
}
@@ -314,9 +336,9 @@
{
gchar *str;
str = g_malloc(TMP_BUF_LEN);
- tmp = xmlNewNode(NULL, "trackNum");
+ tmp = xmlNewNode(NULL, (xmlChar *)"trackNum");
sprintf(str, "%d", entry->tuple->track_number);
- xmlAddChild(tmp, xmlNewText(str));
+ xmlAddChild(tmp, xmlNewText((xmlChar *)str));
g_free(str);
xmlAddChild(track, tmp);
}
@@ -325,9 +347,9 @@
{
gchar *str;
str = g_malloc(TMP_BUF_LEN);
- tmp = xmlNewNode(NULL, "duration");
+ tmp = xmlNewNode(NULL, (xmlChar *)"duration");
sprintf(str, "%d", entry->tuple->length);
- xmlAddChild(tmp, xmlNewText(str));
+ xmlAddChild(tmp, xmlNewText((xmlChar *)str));
g_free(str);
xmlAddChild(track, tmp);
}
@@ -341,10 +363,10 @@
{
gchar *str;
str = g_malloc(TMP_BUF_LEN);
- tmp = xmlNewNode(NULL, "meta");
- xmlSetProp(tmp, "rel", "year");
+ tmp = xmlNewNode(NULL, (xmlChar *)"meta");
+ xmlSetProp(tmp, (xmlChar *)"rel", (xmlChar *)"year");
sprintf(str, "%d", entry->tuple->year);
- xmlAddChild(tmp, xmlNewText(str));
+ xmlAddChild(tmp, xmlNewText((xmlChar *)str));
xmlAddChild(track, tmp);
g_free(str);
}
@@ -352,40 +374,41 @@
if (entry->tuple->date != NULL &&
g_utf8_validate(entry->tuple->date, -1, NULL))
{
- tmp = xmlNewNode(NULL, "meta");
- xmlSetProp(tmp, "rel", "date");
- xmlAddChild(tmp, xmlNewText(entry->tuple->date));
+ tmp = xmlNewNode(NULL, (xmlChar *)"meta");
+ xmlSetProp(tmp, (xmlChar *)"rel", (xmlChar *)"date");
+ xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->date));
xmlAddChild(track, tmp);
}
if (entry->tuple->genre != NULL &&
g_utf8_validate(entry->tuple->genre, -1, NULL))
{
- tmp = xmlNewNode(NULL, "meta");
- xmlSetProp(tmp, "rel", "genre");
- xmlAddChild(tmp, xmlNewText(entry->tuple->genre));
+ tmp = xmlNewNode(NULL, (xmlChar *)"meta");
+ xmlSetProp(tmp, (xmlChar *)"rel", (xmlChar *)"genre");
+ xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->genre));
xmlAddChild(track, tmp);
}
if (entry->tuple->formatter != NULL &&
g_utf8_validate(entry->tuple->formatter, -1, NULL))
{
- tmp = xmlNewNode(NULL, "meta");
- xmlSetProp(tmp, "rel", "formatter");
- xmlAddChild(tmp, xmlNewText(entry->tuple->formatter));
+ tmp = xmlNewNode(NULL, (xmlChar *)"meta");
+ xmlSetProp(tmp, (xmlChar *)"rel", (xmlChar *)"formatter");
+ xmlAddChild(tmp, xmlNewText((xmlChar *)entry->tuple->formatter));
xmlAddChild(track, tmp);
}
- if (entry->tuple->mtime) {
+ // mtime: write mtime unconditionally for staticlist hack.
+// if (entry->tuple->mtime) {
gchar *str;
str = g_malloc(TMP_BUF_LEN);
- tmp = xmlNewNode(NULL, "meta");
- xmlSetProp(tmp, "rel", "mtime");
+ tmp = xmlNewNode(NULL, (xmlChar *)"meta");
+ xmlSetProp(tmp, (xmlChar *)"rel", (xmlChar *)"mtime");
sprintf(str, "%ld", (long) entry->tuple->mtime);
- xmlAddChild(tmp, xmlNewText(str));
+ xmlAddChild(tmp, xmlNewText((xmlChar *)str));
xmlAddChild(track, tmp);
g_free(str);
- }
+// }
}
g_free(filename);