# HG changeset patch # User yaz # Date 1156015736 25200 # Node ID 2229b67f1b89255bb6cee17b14167af3e009f070 # Parent 58f3eb64f3901ad127767f1aeb33d4f5f8082345 [svn] - xspf stores all meta data in tuples now. - at load time, tuple for each entry in a playlist can be constructed from xspf. it means no read access to meta data in each data file is needed. diff -r 58f3eb64f390 -r 2229b67f1b89 ChangeLog --- a/ChangeLog Fri Aug 18 14:56:52 2006 -0700 +++ b/ChangeLog Sat Aug 19 12:28:56 2006 -0700 @@ -1,3 +1,13 @@ +2006-08-18 21:56:52 +0000 William Pitcock + revision [2089] + - freebsd compatibility + + + Changes: Modified: + +9 -1 trunk/audacious/controlsocket.c + +11 -0 trunk/libaudacious/beepctrl.c + + 2006-08-15 00:55:44 +0000 William Pitcock revision [2079] - gcc 4.1.0, 4.1.1, 4.1.2 tree optimization workaround: diff -r 58f3eb64f390 -r 2229b67f1b89 Plugins/Container/xspf/xspf.c --- a/Plugins/Container/xspf/xspf.c Fri Aug 18 14:56:52 2006 -0700 +++ b/Plugins/Container/xspf/xspf.c Sat Aug 19 12:28:56 2006 -0700 @@ -44,13 +44,119 @@ #include static void +add_file(xmlNode *track, const gchar *filename, gint pos) +{ + xmlNode *nptr; + TitleInput *tuple; + gchar *locale_uri = NULL; + + XMMS_NEW_TITLEINPUT(tuple); + + // creator, album, title, duration, trackNum, annotation, image, + for(nptr = track->children; nptr != NULL; nptr = nptr->next){ + if(nptr->type == XML_ELEMENT_NODE && !strcmp(nptr->name, "location")){ + xmlChar *str = xmlNodeGetContent(nptr); + locale_uri = g_locale_from_utf8(str,-1,NULL,NULL,NULL); + if(!locale_uri){ + /* try ISO-8859-1 for last resort */ + locale_uri = g_convert(str, -1, "ISO-8859-1", "UTF-8", NULL, NULL, NULL); + } + xmlFree(str); + if(locale_uri){ + tuple->file_name = g_path_get_basename(locale_uri); + tuple->file_path = g_strdup(locale_uri); + } + } + else if(nptr->type == XML_ELEMENT_NODE && !strcmp(nptr->name, "creator")){ + tuple->performer = (gchar *)xmlNodeGetContent(nptr); + } + else if(nptr->type == XML_ELEMENT_NODE && !strcmp(nptr->name, "album")){ + tuple->album_name = (gchar *)xmlNodeGetContent(nptr); + } + else if(nptr->type == XML_ELEMENT_NODE && !strcmp(nptr->name, "title")){ + tuple->track_name = (gchar *)xmlNodeGetContent(nptr); + } + else if(nptr->type == XML_ELEMENT_NODE && !strcmp(nptr->name, "duration")){ + xmlChar *str = xmlNodeGetContent(nptr); + tuple->length = atol(str); + xmlFree(str); + } + else if(nptr->type == XML_ELEMENT_NODE && !strcmp(nptr->name, "trackNum")){ + xmlChar *str = xmlNodeGetContent(nptr); + tuple->track_number = atol(str); + xmlFree(str); + } + + // + // additional metadata + // + // year, date, genre, comment, file_ext, file_path, formatter + // + else if(nptr->type == XML_ELEMENT_NODE && !strcmp(nptr->name, "meta")){ + xmlChar *rel = NULL; + + rel = xmlGetProp(nptr, "rel"); + + if(!strcmp(rel, "year")){ + xmlChar *cont = xmlNodeGetContent(nptr); + tuple->year = atol(cont); + xmlFree(cont); + continue; + } + else if(!strcmp(rel, "date")){ + tuple->date = (gchar *)xmlNodeGetContent(nptr); + continue; + } + else if(!strcmp(rel, "genre")){ + tuple->genre = (gchar *)xmlNodeGetContent(nptr); + continue; + } + else if(!strcmp(rel, "comment")){ + tuple->comment = (gchar *)xmlNodeGetContent(nptr); + continue; + } + else if(!strcmp(rel, "file_ext")){ + tuple->file_ext = (gchar *)xmlNodeGetContent(nptr); + continue; + } + else if(!strcmp(rel, "file_path")){ + tuple->file_path = (gchar *)xmlNodeGetContent(nptr); + continue; + } + else if(!strcmp(rel, "formatter")){ + tuple->formatter = (gchar *)xmlNodeGetContent(nptr); + continue; + } + xmlFree(rel); + rel = NULL; + } + + } + // add file to playlist + playlist_load_ins_file_tuple(locale_uri, filename, pos, tuple); + pos++; + if(locale_uri) { + g_free(locale_uri); + locale_uri = NULL; + } +} + +static void +find_track(xmlNode *tracklist, const gchar *filename, gint pos) +{ + xmlNode *nptr; + for(nptr = tracklist->children; nptr != NULL; nptr = nptr->next){ + if(nptr->type == XML_ELEMENT_NODE && !strcmp(nptr->name, "track")){ + add_file(nptr, filename, pos); + } + } +} + +static void playlist_load_xspf(const gchar * filename, gint pos) { - xmlDocPtr doc; - xmlXPathObjectPtr xpathObj; - xmlXPathContextPtr xpathCtx; - xmlNodeSetPtr n; - gint i; + xmlDocPtr doc; + xmlNode *nptr, *nptr2; g_return_if_fail(filename != NULL); @@ -58,60 +164,22 @@ if (doc == NULL) return; - xpathCtx = xmlXPathNewContext(doc); - if (xpathCtx == NULL) - { - g_message("xpathCtx is NULL."); - return; - } + // find trackList + for(nptr = doc->children; nptr != NULL; nptr = nptr->next) { + if(nptr->type == XML_ELEMENT_NODE && !strcmp(nptr->name, "playlist")){ + for(nptr2 = nptr->children; nptr2 != NULL; nptr2 = nptr2->next){ + if(nptr2->type == XML_ELEMENT_NODE && !strcmp(nptr2->name, "trackList")){ + find_track(nptr2, filename, pos); + } + } - if (xmlXPathRegisterNs(xpathCtx, "xspf", "http://xspf.org/ns/0/") != 0) - { - g_message("Failed to register XSPF namespace."); - return; - } - - /* TODO: what about xspf:artist, xspf:title, xspf:length? */ - xpathObj = xmlXPathEvalExpression("//xspf:location", xpathCtx); - if (xpathObj == NULL) - { - g_message("XPath Expression failed to evaluate."); - return; + } } - xmlXPathFreeContext(xpathCtx); - - n = xpathObj->nodesetval; - if (n == NULL) - { - g_message("XPath Expression yielded no results."); - return; - } - - for (i = 0; i < n->nodeNr && n->nodeTab[i]->children != NULL; i++) - { - char *uri = XML_GET_CONTENT(n->nodeTab[i]->children); - gchar *locale_uri = NULL; - - if (uri == NULL) - continue; + xmlFreeDoc(doc); - ++pos; - locale_uri = g_locale_from_utf8(uri, -1, NULL, NULL, NULL); - if(!locale_uri){ - /* try ISO-8859-1 for last resort */ - locale_uri = g_convert(uri, -1, "ISO-8859-1", "UTF-8", NULL, NULL, NULL); - } - if(locale_uri) { - playlist_ins(locale_uri, pos); - g_free(locale_uri); - locale_uri = NULL; - } - g_free(uri); - } +} - xmlXPathFreeObject(xpathObj); -} #define XSPF_ROOT_NODE_NAME "playlist" #define XSPF_XMLNS "http://xspf.org/ns/0/" @@ -148,10 +216,14 @@ /* try locale encoding first */ utf_filename = g_locale_to_utf8(entry->filename, -1, NULL, NULL, NULL); + if (!utf_filename) { /* if above fails, try to guess */ utf_filename = str_to_utf8(entry->filename); } + + if(!g_utf8_validate(utf_filename, -1, NULL)) + continue; xmlAddChild(location, xmlNewText(utf_filename)); xmlAddChild(track, location); xmlAddChild(tracklist, track); @@ -159,26 +231,123 @@ /* do we have a tuple? */ if (entry->tuple != NULL) { - if (entry->tuple->performer != NULL) + if (entry->tuple->performer != NULL && + g_utf8_validate(entry->tuple->performer, -1, NULL)) { tmp = xmlNewNode(NULL, "creator"); xmlAddChild(tmp, xmlNewText(entry->tuple->performer)); xmlAddChild(track, tmp); } - if (entry->tuple->album_name != NULL) + 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)); xmlAddChild(track, tmp); } - if (entry->tuple->track_name != NULL) + 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)); xmlAddChild(track, tmp); } + + if (entry->tuple->length != 0) + { + gchar *str; + str = g_malloc(128); // XXX fix me. + tmp = xmlNewNode(NULL, "duration"); + sprintf(str, "%d", entry->tuple->length); + xmlAddChild(tmp, xmlNewText(str)); + g_free(str); + xmlAddChild(track, tmp); + } + + if (entry->tuple->track_number != 0) + { + gchar *str; + str = g_malloc(128); // XXX fix me. + tmp = xmlNewNode(NULL, "trackNum"); + sprintf(str, "%d", entry->tuple->track_number); + xmlAddChild(tmp, xmlNewText(str)); + g_free(str); + xmlAddChild(track, tmp); + } + + // + // additional metadata + // + // year, date, genre, comment, file_ext, file_path, formatter + // + if (entry->tuple->year != 0) + { + gchar *str; + str = g_malloc(128); // XXX fix me. + tmp = xmlNewNode(NULL, "meta"); + xmlSetProp(tmp, "rel", "year"); + sprintf(str, "%d", entry->tuple->year); + xmlAddChild(tmp, xmlNewText(str)); + xmlAddChild(track, tmp); + g_free(str); + } + + 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)); + 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)); + xmlAddChild(track, tmp); + } + + if (entry->tuple->comment != NULL && + g_utf8_validate(entry->tuple->comment, -1, NULL)) + { + tmp = xmlNewNode(NULL, "meta"); + xmlSetProp(tmp, "rel", "comment"); + xmlAddChild(tmp, xmlNewText(entry->tuple->comment)); + xmlAddChild(track, tmp); + } + + if (entry->tuple->file_ext != NULL && + g_utf8_validate(entry->tuple->file_ext, -1, NULL)) + { + tmp = xmlNewNode(NULL, "meta"); + xmlSetProp(tmp, "rel", "file_ext"); + xmlAddChild(tmp, xmlNewText(entry->tuple->file_ext)); + xmlAddChild(track, tmp); + } + + if (entry->tuple->file_path != NULL && + g_utf8_validate(entry->tuple->file_path, -1, NULL)) + { + tmp = xmlNewNode(NULL, "meta"); + xmlSetProp(tmp, "rel", "file_path"); + xmlAddChild(tmp, xmlNewText(entry->tuple->file_path)); + 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)); + xmlAddChild(track, tmp); + } + } if(utf_filename) { g_free(utf_filename); diff -r 58f3eb64f390 -r 2229b67f1b89 audacious/playlist.c --- a/audacious/playlist.c Fri Aug 18 14:56:52 2006 -0700 +++ b/audacious/playlist.c Sat Aug 19 12:28:56 2006 -0700 @@ -464,6 +464,50 @@ } static void +__playlist_ins_with_info_tuple(const gchar * filename, + gint pos, + TitleInput *tuple, + InputPlugin * dec) +{ + GList *node; + PlaylistEntry *entry; + + g_return_if_fail(filename != NULL); + + PLAYLIST_LOCK(); + playlist = g_list_insert(playlist, + playlist_entry_new(filename, tuple->track_name, tuple->length, dec), + pos); + + if(pos < 0 ) { + pos = g_list_length(playlist) - 1; /* last element. */ + } + + node = g_list_nth(playlist, pos); + entry = PLAYLIST_ENTRY(node->data); + + /* insufficient tuple */ + if(!tuple->track_name || !tuple->performer || !tuple->album_name || !tuple->genre + || !tuple->year || !tuple->track_number || !tuple->length){ +// printf("tuple discarded: %s\n", filename); + bmp_title_input_free(tuple); + + if (entry->decoder == NULL || entry->decoder->get_song_tuple == NULL) + tuple = input_get_song_tuple(entry->filename); + else + tuple = entry->decoder->get_song_tuple(entry->filename); + } + + entry->title = xmms_get_titlestring(tuple->formatter != NULL ? tuple->formatter : xmms_get_gentitle_format(), tuple); + entry->length = tuple->length; + entry->tuple = tuple; + + PLAYLIST_UNLOCK(); + + playlist_get_info_scan_active = TRUE; +} + +static void __playlist_ins(const gchar * filename, gint pos, InputPlugin *dec) { __playlist_ins_with_info(filename, pos, NULL, -1, dec); @@ -1333,6 +1377,61 @@ g_free(filename); } +void +playlist_load_ins_file_tuple(const gchar * filename_p, + const gchar * playlist_name, + gint pos, + TitleInput *tuple) +{ + gchar *filename; + gchar *tmp, *path; + InputPlugin *dec; /* for decoder cache */ + + g_return_if_fail(filename_p != NULL); + g_return_if_fail(playlist_name != NULL); + + filename = g_strchug(g_strdup(filename_p)); + + while ((tmp = strchr(filename, '\\')) != NULL) + *tmp = '/'; + + if (filename[0] != '/' && !strstr(filename, "://")) { + path = g_strdup(playlist_name); + if ((tmp = strrchr(path, '/'))) + *tmp = '\0'; + else { + if (loading_playlist != TRUE || cfg.playlist_detect == FALSE) + dec = input_check_file(filename, FALSE); + else + dec = NULL; + + __playlist_ins_with_info_tuple(filename, pos, tuple, dec); + return; + } + tmp = g_build_filename(path, filename, NULL); + + if (loading_playlist != TRUE && cfg.playlist_detect != TRUE) + dec = input_check_file(tmp, FALSE); + else + dec = NULL; + + __playlist_ins_with_info_tuple(tmp, pos, tuple, dec); + g_free(tmp); + g_free(path); + } + else + { + if (loading_playlist != TRUE && cfg.playlist_detect != TRUE) + dec = input_check_file(filename, FALSE); + else + dec = NULL; + + __playlist_ins_with_info_tuple(filename, pos, tuple, dec); + } + + g_free(filename); +} + static guint playlist_load_ins(const gchar * filename, gint pos) { diff -r 58f3eb64f390 -r 2229b67f1b89 audacious/playlist.h --- a/audacious/playlist.h Fri Aug 18 14:56:52 2006 -0700 +++ b/audacious/playlist.h Sat Aug 19 12:28:56 2006 -0700 @@ -175,4 +175,9 @@ const gchar * playlist_name, gint pos, const gchar * title, gint len); +extern void playlist_load_ins_file_tuple(const gchar * filename_p, + const gchar * playlist_name, gint pos, + TitleInput *tuple); + + #endif