Mercurial > audlegacy
changeset 1568:0a927f814a12 trunk
[svn] - experimental XSPF support
author | nenolod |
---|---|
date | Thu, 10 Aug 2006 22:26:50 -0700 |
parents | bbc9d6fad927 |
children | 3af18d169044 |
files | ChangeLog Plugins/Container/xspf/Makefile Plugins/Container/xspf/xspf.c configure.ac |
diffstat | 4 files changed, 307 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Thu Aug 10 21:00:59 2006 -0700 +++ b/ChangeLog Thu Aug 10 22:26:50 2006 -0700 @@ -1,3 +1,12 @@ +2006-08-11 04:00:59 +0000 William Pitcock <nenolod@nenolod.net> + revision [2048] + - add missing $(CONTAINER_PLUGINS). + + + Changes: Modified: + +1 -0 trunk/mk/rules.mk.in + + 2006-08-11 03:44:47 +0000 William Pitcock <nenolod@nenolod.net> revision [2046] - pls and m3u is now fully modular
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Container/xspf/Makefile Thu Aug 10 22:26:50 2006 -0700 @@ -0,0 +1,16 @@ +include ../../../mk/rules.mk +include ../../../mk/objective.mk + +OBJECTIVE_LIBS = libxspf.so + +LIBDIR = $(plugindir)/$(CONTAINER_PLUGIN_DIR) + +SOURCES = xspf.c + +OBJECTS = ${SOURCES:.c=.o} + +CFLAGS += -fPIC -DPIC $(GTK_CFLAGS) $(ARCH_DEFINES) $(XML_CPPFLAGS) -I../../../intl -I../../.. + +CXXFLAGS = $(CFLAGS) + +LIBADD = $(GTK_LIBS) $(XML_LIBS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Plugins/Container/xspf/xspf.c Thu Aug 10 22:26:50 2006 -0700 @@ -0,0 +1,264 @@ +/* + * Audacious: A cross-platform multimedia player + * Copyright (c) 2006 William Pitcock, Tony Vroon, George Averill, + * Giacomo Lozito, Derek Pomery and Yoshiki Yazawa. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <glib.h> +#include <string.h> +#include <glib.h> +#include <glib/gprintf.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/errno.h> + +#include "audacious/main.h" +#include "audacious/util.h" +#include "audacious/playlist.h" +#include "audacious/playlist_container.h" +#include "audacious/plugin.h" + +#include <libxml/tree.h> +#include <libxml/parser.h> +#include <libxml/xmlreader.h> +#include <libxml/xpath.h> +#include <libxml/xpathInternals.h> + +/* Borrowed from BMPx. */ +static int +register_namespaces (xmlXPathContextPtr xpathCtx, const xmlChar* nsList) +{ + xmlChar* nsListDup; + xmlChar* prefix; + xmlChar* href; + xmlChar* next; + + nsListDup = xmlStrdup(nsList); + if(nsListDup == NULL) + { + g_warning (G_STRLOC ": unable to strdup namespaces list"); + return(-1); + } + + next = nsListDup; + while (next != NULL) + { + while((*next) == ' ') next++; + if((*next) == '\0') break; + + prefix = next; + next = (xmlChar*)xmlStrchr(next, '='); + + if (next == NULL) + { + g_warning (G_STRLOC ": invalid namespaces list format"); + xmlFree (nsListDup); + return(-1); + } + *(next++) = '\0'; + + href = next; + next = (xmlChar*)xmlStrchr(next, ' '); + if (next != NULL) + { + *(next++) = '\0'; + } + + // do register namespace + if(xmlXPathRegisterNs(xpathCtx, prefix, href) != 0) + { + g_warning (G_STRLOC ": unable to register NS with prefix=\"%s\" and href=\"%s\"", prefix, href); + xmlFree(nsListDup); + return(-1); + } + } + + xmlFree(nsListDup); + return(0); +} + +/* Also borrowed from BMPx. */ +xmlXPathObjectPtr +xml_execute_xpath_expression (xmlDocPtr doc, + const xmlChar * xpathExpr, + const xmlChar * nsList) +{ + xmlXPathContextPtr xpathCtx; + xmlXPathObjectPtr xpathObj; + + /* + * Create xpath evaluation context + */ + xpathCtx = xmlXPathNewContext (doc); + if (xpathCtx == NULL) + { + return NULL; + } + + if (nsList) + register_namespaces (xpathCtx, nsList); + + /* + * Evaluate xpath expression + */ + xpathObj = xmlXPathEvalExpression (xpathExpr, xpathCtx); + if (xpathObj == NULL) + { + xmlXPathFreeContext (xpathCtx); + return NULL; + } + + /* + * Cleanup + */ + xmlXPathFreeContext (xpathCtx); + + return xpathObj; +} + +static void +playlist_load_xspf(const gchar * filename, gint pos) +{ + xmlDocPtr doc; + xmlXPathObjectPtr xpathObj; + xmlNodeSetPtr n; + gint i; + + doc = xmlParseFile(filename); + if (doc == NULL) + return; + + /* TODO: what about xspf:artist, xspf:title, xspf:length? */ + xpathObj = xml_execute_xpath_expression(doc, "//xspf:location", "xspf=http://xspf.org/ns/0/"); + if (xpathObj == NULL) + return; + + n = xpathObj->nodesetval; + if (n == NULL) + return; + + for (i = 0; i < n->nodeNr; i++) + { + char *uri = (char *)XML_GET_CONTENT(n->nodeTab[i]->children); + playlist_ins(uri, pos); + ++pos; + g_free(uri); + } + + xmlXPathFreeObject(xpathObj); +} + +#define XSPF_ROOT_NODE_NAME "playlist" +#define XSPF_XMLNS "http://xspf.org/ns/0/" + +static void +playlist_save_xspf(const gchar *filename, gint pos) +{ + xmlDocPtr doc; + xmlNodePtr rootnode, tmp, tracklist; + GList *node; + + doc = xmlNewDoc("1.0"); + + rootnode = xmlNewNode(NULL, XSPF_ROOT_NODE_NAME); + xmlSetProp(rootnode, "xmlns", XSPF_XMLNS); + xmlSetProp(rootnode, "version", "1"); + xmlDocSetRootElement(doc, rootnode); + + tmp = xmlNewNode(NULL, "creator"); + xmlAddChild(tmp, xmlNewText(PACKAGE "-" VERSION)); + xmlAddChild(rootnode, tmp); + + tracklist = xmlNewNode(NULL, "trackList"); + xmlAddChild(rootnode, tracklist); + + for (node = playlist_get(); node != NULL; node = g_list_next(node)) + { + PlaylistEntry *entry = PLAYLIST_ENTRY(node->data); + xmlNodePtr track, location; + + track = xmlNewNode(NULL, "track"); + location = xmlNewNode(NULL, "location"); + + xmlAddChild(location, xmlNewText(entry->filename)); + xmlAddChild(track, location); + xmlAddChild(tracklist, track); + + /* do we have a tuple? */ + if (entry->tuple != NULL) + { + if (entry->tuple->performer != NULL) + { + tmp = xmlNewNode(NULL, "creator"); + xmlAddChild(tmp, xmlNewText(entry->tuple->performer)); + xmlAddChild(track, tmp); + } + + if (entry->tuple->album_name != NULL) + { + tmp = xmlNewNode(NULL, "album"); + xmlAddChild(tmp, xmlNewText(entry->tuple->album_name)); + xmlAddChild(track, tmp); + } + + if (entry->tuple->track_name != NULL) + { + tmp = xmlNewNode(NULL, "title"); + xmlAddChild(tmp, xmlNewText(entry->tuple->track_name)); + xmlAddChild(track, tmp); + } + } + } + + xmlSaveFile(filename, doc); + xmlFreeDoc(doc); +} + +PlaylistContainer plc_xspf = { + .name = "XSPF Playlist Format", + .ext = "xspf", + .plc_read = playlist_load_xspf, + .plc_write = playlist_save_xspf, +}; + +static void init(void) +{ + playlist_container_register(&plc_xspf); +} + +static void cleanup(void) +{ + playlist_container_unregister(&plc_xspf); +} + +LowlevelPlugin llp_xspf = { + NULL, + NULL, + "XSPF Playlist Format", + init, + cleanup, +}; + +LowlevelPlugin *get_lplugin_info(void) +{ + return &llp_xspf; +}
--- a/configure.ac Thu Aug 10 21:00:59 2006 -0700 +++ b/configure.ac Thu Aug 10 22:26:50 2006 -0700 @@ -914,29 +914,37 @@ AC_ARG_ENABLE(paranormal, [ --disable-paranormal disable paranormal vis plugin. (default=enabled)], [have_paranormal=$enableval], -[ - if test "x$ap_disable_paranormal" = "xyes"; then +[have_paranormal=yes]) + +if test "x$ap_disable_paranormal" = "xyes"; then have_paranormal=no AC_MSG_RESULT([*** paranormal plugin disabled by request ***]) - else +else have_paranormal=yes AM_PATH_SDL(1.2.5, , [ AC_MSG_WARN([*** SDL is not installed. Paranormal will not be built. ***]) have_paranormal="no" ]) +fi - AM_PATH_XML2(2.0.0, , [ - AC_MSG_WARN([*** libxml2 is not installed. Paranormal will not be built. ***]) +AC_ARG_ENABLE(xspf, +[ --disable-xspf disable XSPF support. (default=enabled)], +[have_xspf=$enableval], [have_xspf=yes]) + +AM_PATH_XML2(2.0.0, , [ + AC_MSG_WARN([*** libxml2 is not installed. Paranormal nor XSPF support will not be built. ***]) have_paranormal="no" - ]) - fi -] -) + have_xspf="no" +]) if test "$have_paranormal" = "yes"; then VISUALIZATION_PLUGINS="$VISUALIZATION_PLUGINS paranormal" fi +if test "$have_xspf" = "yes"; then + CONTAINER_PLUGINS="$CONTAINER_PLUGINS xspf" +fi + dnl *** End of all plugin checks *** AC_SUBST(ARCH_DEFINES) @@ -1156,6 +1164,7 @@ echo " -------------" echo " Winamp PLS playlist format (pls): yes" echo " M3U playlist format (m3u): yes" +echo " XML Sharable Playlist Format (xspf): $have_xspf" echo if test "$beep_cv_lib_xlibs_threadsafe" = "no"; then