--- rhythmbox-0.9.2.orig/Makefile.am 2005-12-04 15:26:01.000000000 -0800 +++ rhythmbox-0.9.2.orig/Makefile.am 2005-12-04 17:17:11.000000000 -0800 @@ -5,7 +5,7 @@ DISTCHECK_CONFIGURE_FLAGS = --disable-schemas-install --enable-gtk-doc distuninstallcheck_listfiles = find . -type f -print | grep -v '^\./var/scrollkeeper' -SUBDIRS = macros lib metadata player rhythmdb widgets sources iradio podcast remote daapsharing shell data po help tests doc +SUBDIRS = macros lib metadata player rhythmdb widgets plparse sources iradio podcast remote daapsharing shell data po help tests doc EXTRA_DIST = \ autogen.sh \ --- rhythmbox-0.9.2.orig/configure.ac 2005-12-04 15:26:01.000000000 -0800 +++ rhythmbox-0.9.2.orig/configure.ac 2005-12-04 17:17:11.000000000 -0800 @@ -54,10 +54,10 @@ gnome-vfs-2.0 >= $GNOME_VFS_REQS \ gnome-vfs-module-2.0) -PKG_CHECK_MODULES(TOTEM_PLPARSER, totem-plparser >= $TOTEM_PLPARSER_REQS, have_totem_plparser=yes, have_totem_plparser=no) -if test x$have_totem_plparser != xyes; then - AC_MSG_ERROR([totem playlist parsing library not found or too old]) -fi +# PKG_CHECK_MODULES(TOTEM_PLPARSER, totem-plparser >= $TOTEM_PLPARSER_REQS, have_totem_plparser=yes, have_totem_plparser=no) +# if test x$have_totem_plparser != xyes; then +# AC_MSG_ERROR([totem playlist parsing library not found or too old]) +# fi dnl iPod support @@ -578,6 +578,7 @@ player/Makefile rhythmdb/Makefile widgets/Makefile +plparse/Makefile iradio/Makefile podcast/Makefile remote/Makefile --- rhythmbox-0.9.2.orig/plparse/Makefile.am 1969-12-31 16:00:00.000000000 -0800 +++ rhythmbox-0.9.2.orig/plparse/Makefile.am 2005-12-04 17:17:11.000000000 -0800 @@ -0,0 +1,60 @@ +noinst_LIBRARIES = libtotem-plparser.a + +libtotem_plparser_a_SOURCES = \ + totem-pl-parser-builtins.c \ + totemplparser-marshal.c \ + totemplparser-marshal.h \ + totem-disc.c \ + totem-pl-parser.c + +# libtotem_plparser_a_LDFLAGS = \ +# $(TOTEM_PLPARSER_LIBS) + +INCLUDES = $(RHYTHMBOX_CFLAGS) + +MARSHALFILES = totemplparser-marshal.c totemplparser-marshal.h +GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0` +BUILT_SOURCES = $(MARSHALFILES) + +totemplparser-marshal.c: totemplparser-marshal.h + ( $(GLIB_GENMARSHAL) --prefix=totemplparser_marshal $(srcdir)/totemplparser-marshal.list --header --body > totemplparser-marshal.c ) +totemplparser-marshal.h: totemplparser-marshal.list + ( $(GLIB_GENMARSHAL) --prefix=totemplparser_marshal $(srcdir)/totemplparser-marshal.list --header > totemplparser-marshal.h ) + +GLIB_MKENUMS=`pkg-config --variable=glib_mkenums glib-2.0` +totem-pl-parser-builtins.h: stamp-totem-pl-parser-builtins.h + @true + +stamp-totem-pl-parser-builtins.h: totem-pl-parser.h Makefile + (cd $(srcdir) && $(GLIB_MKENUMS) \ + --fhead "#ifndef __TOTEM_PL_PARSER_BUILTINS_H__\n#define __TOTEM_PL_PARSER_BUILTINS_H__\n\n#include \n\nG_BEGIN_DECLS\n" \ + --fprod "/* enumerations from \"@filename@\" */\n" \ + --vhead "GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define TOTEM_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "G_END_DECLS\n\n#endif /* __TOTEM_PL_PARSER_BUILTINS_H__ */" totem-pl-parser.h) >> xgen-gtbh \ + && (cmp -s xgen-gtbh totem-pl-parser-builtins.h || cp xgen-gtbh totem-pl-parser-builtins.h ) \ + && rm -f xgen-gtbh \ + && echo timestamp > $(@F) + +totem-pl-parser-builtins.c: totem-pl-parser.h Makefile totem-pl-parser-builtins.h + (cd $(srcdir) && $(GLIB_MKENUMS) \ + --fhead "#include \"totem-pl-parser.h\"\n#include \"totem-pl-parser-builtins.h\"" \ + --fprod "\n/* enumerations from \"@filename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ + totem-pl-parser.h ) > xgen-gtbc \ + && cp xgen-gtbc totem-pl-parser-builtins.c \ + && rm -f xgen-gtbc + +CLEANFILES = \ + totem-pl-parser-builtins.h \ + totem-pl-parser-builtins.c \ + stamp-totem-pl-parser-builtins.h \ + $(BUILT_SOURCES) + +EXTRA_DIST = \ + totemplparser-marshal.list \ + totem-disc.h \ + totem-pl-parser-builtins.h \ + totem-pl-parser.h + --- rhythmbox-0.9.2.orig/plparse/Makefile.in 1969-12-31 16:00:00.000000000 -0800 +++ rhythmbox-0.9.2.orig/plparse/Makefile.in 2005-12-04 17:17:11.000000000 -0800 @@ -0,0 +1,574 @@ +# Makefile.in generated by automake 1.7.9 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUDIOCD_INCLUDES = @AUDIOCD_INCLUDES@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BONOBO_ACTIVATION_IDL = @BONOBO_ACTIVATION_IDL@ +BONOBO_CFLAGS = @BONOBO_CFLAGS@ +BONOBO_LIBS = @BONOBO_LIBS@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GCONFTOOL = @GCONFTOOL@ +GCONF_SCHEMAS_INSTALL_FALSE = @GCONF_SCHEMAS_INSTALL_FALSE@ +GCONF_SCHEMAS_INSTALL_TRUE = @GCONF_SCHEMAS_INSTALL_TRUE@ +GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ +GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ +GDA_CFLAGS = @GDA_CFLAGS@ +GDA_LIBS = @GDA_LIBS@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_GENMARSHAL = `pkg-config --variable=glib_genmarshal glib-2.0` +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GST_INSPECT = @GST_INSPECT@ +HAL_CFLAGS = @HAL_CFLAGS@ +HAL_LIBS = @HAL_LIBS@ +HAVE_AUDIOCD_FALSE = @HAVE_AUDIOCD_FALSE@ +HAVE_AUDIOCD_TRUE = @HAVE_AUDIOCD_TRUE@ +HAVE_LINUX_CDROM_FALSE = @HAVE_LINUX_CDROM_FALSE@ +HAVE_LINUX_CDROM_TRUE = @HAVE_LINUX_CDROM_TRUE@ +HAVE_MUSICBRAINZ_FALSE = @HAVE_MUSICBRAINZ_FALSE@ +HAVE_MUSICBRAINZ_TRUE = @HAVE_MUSICBRAINZ_TRUE@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@ +INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@ +INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_ICONV = @INTLTOOL_ICONV@ +INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@ +INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_MSGFMT = @INTLTOOL_MSGFMT@ +INTLTOOL_MSGMERGE = @INTLTOOL_MSGMERGE@ +INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@ +INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@ +INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@ +INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@ +INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@ +INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@ +INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@ +INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@ +INTLTOOL_XGETTEXT = @INTLTOOL_XGETTEXT@ +INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@ +INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@ +LDFLAGS = @LDFLAGS@ +LIBBONOBO_IDL = @LIBBONOBO_IDL@ +LIBNAUTILUS_BURN_CFLAGS = @LIBNAUTILUS_BURN_CFLAGS@ +LIBNAUTILUS_BURN_LIBS = @LIBNAUTILUS_BURN_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKEINFO = @MAKEINFO@ +MKDTEMP_MISSING_FALSE = @MKDTEMP_MISSING_FALSE@ +MKDTEMP_MISSING_TRUE = @MKDTEMP_MISSING_TRUE@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MUSICBRAINZ_CFLAGS = @MUSICBRAINZ_CFLAGS@ +MUSICBRAINZ_LIBS = @MUSICBRAINZ_LIBS@ +OBJEXT = @OBJEXT@ +ORBIT_IDL = @ORBIT_IDL@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POFILES = @POFILES@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +RANLIB = @RANLIB@ +RHYTHMBOX_CFLAGS = @RHYTHMBOX_CFLAGS@ +RHYTHMBOX_LIBS = @RHYTHMBOX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOUNDSYSTEM_CFLAGS = @SOUNDSYSTEM_CFLAGS@ +SOUNDSYSTEM_DEPS = @SOUNDSYSTEM_DEPS@ +SOUNDSYSTEM_LIBS = @SOUNDSYSTEM_LIBS@ +STRIP = @STRIP@ +USE_CD_BURNER_FALSE = @USE_CD_BURNER_FALSE@ +USE_CD_BURNER_TRUE = @USE_CD_BURNER_TRUE@ +USE_GDADB_FALSE = @USE_GDADB_FALSE@ +USE_GDADB_TRUE = @USE_GDADB_TRUE@ +USE_IPOD_FALSE = @USE_IPOD_FALSE@ +USE_IPOD_TRUE = @USE_IPOD_TRUE@ +USE_NLS = @USE_NLS@ +USE_TREEDB_FALSE = @USE_TREEDB_FALSE@ +USE_TREEDB_TRUE = @USE_TREEDB_TRUE@ +VERSION = @VERSION@ +WITH_BONOBO_FALSE = @WITH_BONOBO_FALSE@ +WITH_BONOBO_TRUE = @WITH_BONOBO_TRUE@ +WITH_DASHBOARD_FALSE = @WITH_DASHBOARD_FALSE@ +WITH_DASHBOARD_TRUE = @WITH_DASHBOARD_TRUE@ +WITH_DBUS_FALSE = @WITH_DBUS_FALSE@ +WITH_DBUS_TRUE = @WITH_DBUS_TRUE@ +XGETTEXT = @XGETTEXT@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +noinst_LIBRARIES = libtotem-plparser.a + +libtotem_plparser_a_SOURCES = \ + totem-pl-parser-builtins.c \ + totemplparser-marshal.c \ + totemplparser-marshal.h \ + totem-disc.c \ + totem-pl-parser.c + + + +# libtotem_plparser_a_LDFLAGS = \ +# $(TOTEM_PLPARSER_LIBS) +INCLUDES = $(RHYTHMBOX_CFLAGS) + +MARSHALFILES = totemplparser-marshal.c totemplparser-marshal.h +BUILT_SOURCES = $(MARSHALFILES) + +GLIB_MKENUMS = `pkg-config --variable=glib_mkenums glib-2.0` + +CLEANFILES = \ + totem-pl-parser-builtins.h \ + totem-pl-parser-builtins.c \ + stamp-totem-pl-parser-builtins.h \ + $(BUILT_SOURCES) + + +EXTRA_DIST = \ + totemplparser-marshal.list \ + totem-disc.h \ + totem-pl-parser-builtins.h \ + totem-pl-parser.h + +subdir = plparse +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libtotem_plparser_a_AR = $(AR) cru +libtotem_plparser_a_LIBADD = +am_libtotem_plparser_a_OBJECTS = totem-pl-parser-builtins.$(OBJEXT) \ + totemplparser-marshal.$(OBJEXT) totem-disc.$(OBJEXT) \ + totem-pl-parser.$(OBJEXT) +libtotem_plparser_a_OBJECTS = $(am_libtotem_plparser_a_OBJECTS) + +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/totem-disc.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/totem-pl-parser-builtins.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/totem-pl-parser.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/totemplparser-marshal.Po +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ + $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libtotem_plparser_a_SOURCES) +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am +SOURCES = $(libtotem_plparser_a_SOURCES) + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu plparse/Makefile +Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +libtotem-plparser.a: $(libtotem_plparser_a_OBJECTS) $(libtotem_plparser_a_DEPENDENCIES) + -rm -f libtotem-plparser.a + $(libtotem_plparser_a_AR) libtotem-plparser.a $(libtotem_plparser_a_OBJECTS) $(libtotem_plparser_a_LIBADD) + $(RANLIB) libtotem-plparser.a + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/totem-disc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/totem-pl-parser-builtins.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/totem-pl-parser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/totemplparser-marshal.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCC_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCC_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` + +.c.lo: +@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \ +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCC_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LIBRARIES) + +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool pdf \ + pdf-am ps ps-am tags uninstall uninstall-am uninstall-info-am + + +totemplparser-marshal.c: totemplparser-marshal.h + ( $(GLIB_GENMARSHAL) --prefix=totemplparser_marshal $(srcdir)/totemplparser-marshal.list --header --body > totemplparser-marshal.c ) +totemplparser-marshal.h: totemplparser-marshal.list + ( $(GLIB_GENMARSHAL) --prefix=totemplparser_marshal $(srcdir)/totemplparser-marshal.list --header > totemplparser-marshal.h ) +totem-pl-parser-builtins.h: stamp-totem-pl-parser-builtins.h + @true + +stamp-totem-pl-parser-builtins.h: totem-pl-parser.h Makefile + (cd $(srcdir) && $(GLIB_MKENUMS) \ + --fhead "#ifndef __TOTEM_PL_PARSER_BUILTINS_H__\n#define __TOTEM_PL_PARSER_BUILTINS_H__\n\n#include \n\nG_BEGIN_DECLS\n" \ + --fprod "/* enumerations from \"@filename@\" */\n" \ + --vhead "GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define TOTEM_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "G_END_DECLS\n\n#endif /* __TOTEM_PL_PARSER_BUILTINS_H__ */" totem-pl-parser.h) >> xgen-gtbh \ + && (cmp -s xgen-gtbh totem-pl-parser-builtins.h || cp xgen-gtbh totem-pl-parser-builtins.h ) \ + && rm -f xgen-gtbh \ + && echo timestamp > $(@F) + +totem-pl-parser-builtins.c: totem-pl-parser.h Makefile totem-pl-parser-builtins.h + (cd $(srcdir) && $(GLIB_MKENUMS) \ + --fhead "#include \"totem-pl-parser.h\"\n#include \"totem-pl-parser-builtins.h\"" \ + --fprod "\n/* enumerations from \"@filename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ + totem-pl-parser.h ) > xgen-gtbc \ + && cp xgen-gtbc totem-pl-parser-builtins.c \ + && rm -f xgen-gtbc +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: --- rhythmbox-0.9.2.orig/plparse/totem-disc.c 1969-12-31 16:00:00.000000000 -0800 +++ rhythmbox-0.9.2.orig/plparse/totem-disc.c 2005-12-04 17:17:11.000000000 -0800 @@ -0,0 +1,710 @@ +/* Totem Disc Content Detection + * (c) 2004 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * The Totem project hereby grant permission for non-gpl compatible GStreamer + * plugins to be used and distributed together with GStreamer and Totem. This + * permission are above and beyond the permissions granted by the GPL license + * Totem is covered by. + * + * Monday 7th February 2005: Christian Schaller: Add excemption clause. + * See license_change file for details. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include "totem-disc.h" + +typedef struct _CdCache { + /* device node and mountpoint */ + char *device, *mountpoint; + GnomeVFSDrive *drive; + + /* file descriptor to the device */ + int fd; + + /* capabilities of the device */ + int cap; + + /* if we're checking a media, or a dir */ + gboolean is_media; + + /* indicates if we mounted this mountpoint ourselves or if it + * was already mounted. */ + gboolean self_mounted; + gboolean mounted; +} CdCache; + +/* + * Resolve relative paths + */ + +static char * +totem_disc_resolve_link (const char *dev, const char *buf) +{ + char *parent, *new, *result; + + /* is it an absolute path? */ + if (g_path_is_absolute (buf) != FALSE) { + result = realpath (buf, NULL); + if (result == NULL) + result = g_strdup (buf); + } else { + parent = g_path_get_dirname (dev); + new = g_build_filename (parent, buf, NULL); + result = realpath (new, NULL); + if (result == NULL) + result = g_strdup (new); + g_free (new); + g_free (parent); + } + + return result; +} + +/* + * So, devices can be symlinks and that screws up. + */ + +static char * +get_device (const char *device, + GError **error) +{ + char *buf; + char *dev = g_strdup (device); + struct stat st; + + while (1) { + char *new; + + if (lstat (dev, &st) != 0) { + g_set_error (error, 0, 0, + _("Failed to find real device node for %s: %s"), + dev, g_strerror (errno)); + g_free (dev); + return NULL; + } + + if (!S_ISLNK (st.st_mode)) + break; + + if (!(buf = g_file_read_link (dev, NULL))) { + g_set_error (error, 0, 0, + _("Failed to read symbolic link %s: %s"), + dev, g_strerror (errno)); + g_free (dev); + return NULL; + } + new = totem_disc_resolve_link (dev, buf); + g_free (dev); + g_free (buf); + dev = new; + } + + return dev; +} + +static gboolean +cd_cache_get_dev_from_volumes (GnomeVFSVolumeMonitor *mon, const char *device, + char **mountpoint) +{ + gboolean found; + GnomeVFSVolume *volume = NULL; + GList *list, *or; + + found = FALSE; + + for (or = list = gnome_vfs_volume_monitor_get_mounted_volumes (mon); + list != NULL; list = list->next) { + char *pdev, *pdev2; + + volume = list->data; + if (!(pdev = gnome_vfs_volume_get_device_path (volume))) + continue; + if (!(pdev2 = get_device (pdev, NULL))) { + g_free (pdev); + continue; + } + g_free (pdev); + + if (strcmp (pdev2, device) == 0) { + char *mnt; + + mnt = gnome_vfs_volume_get_activation_uri (volume); + if (mnt && strncmp (mnt, "file://", 7) == 0) { + g_free (pdev2); + *mountpoint = g_strdup (mnt + 7); + g_free (mnt); + found = TRUE; + break; + } else if (mnt && strncmp (mnt, "cdda://", 7) == 0) { + g_free (pdev2); + *mountpoint = NULL; + g_free (mnt); + found = TRUE; + break; + } + g_free (mnt); + } + g_free (pdev2); + } + g_list_foreach (or, (GFunc) gnome_vfs_volume_unref, NULL); + g_list_free (or); + + return found; +} +static gboolean +cd_cache_get_dev_from_drives (GnomeVFSVolumeMonitor *mon, const char *device, + char **mountpoint, GnomeVFSDrive **d) +{ + gboolean found; + GnomeVFSDrive *drive = NULL; + GList *list, *or; + + found = FALSE; + + for (or = list = gnome_vfs_volume_monitor_get_connected_drives (mon); + list != NULL; list = list->next) { + char *pdev, *pdev2; + + drive = list->data; + if (!(pdev = gnome_vfs_drive_get_device_path (drive))) + continue; + if (!(pdev2 = get_device (pdev, NULL))) { + g_free (pdev); + continue; + } + g_free (pdev); + + if (strcmp (pdev2, device) == 0) { + char *mnt; + + mnt = gnome_vfs_drive_get_activation_uri (drive); + if (mnt && strncmp (mnt, "file://", 7) == 0) { + g_free (pdev2); + *mountpoint = g_strdup (mnt + 7); + g_free (mnt); + gnome_vfs_drive_ref (drive); + found = TRUE; + break; + } else if (mnt && strncmp (mnt, "cdda://", 7) == 0) { + g_free (pdev2); + *mountpoint = NULL; + g_free (mnt); + gnome_vfs_drive_ref (drive); + found = TRUE; + break; + } + g_free (mnt); + } + g_free (pdev2); + } + g_list_foreach (or, (GFunc) gnome_vfs_drive_unref, NULL); + g_list_free (or); + + *d = drive; + + return found; +} + +static CdCache * +cd_cache_new (const char *dev, + GError **error) +{ + CdCache *cache; + char *mountpoint = NULL, *device, *local; + GnomeVFSVolumeMonitor *mon; + GnomeVFSDrive *drive = NULL; + gboolean is_dir, found; + + if (g_str_has_prefix (dev, "file://") != FALSE) + local = g_filename_from_uri (dev, NULL, NULL); + else + local = g_strdup (dev); + + g_assert (local != NULL); + + is_dir = g_file_test (local, G_FILE_TEST_IS_DIR); + + if (is_dir) { + cache = g_new0 (CdCache, 1); + cache->mountpoint = local; + cache->fd = -1; + cache->is_media = FALSE; + + return cache; + } + + /* retrieve mountpoint (/etc/fstab) */ + device = get_device (local, error); + g_free (local); + if (!device) + return NULL; + mon = gnome_vfs_get_volume_monitor (); + found = cd_cache_get_dev_from_drives (mon, device, &mountpoint, &drive); + if (!found) { + drive = NULL; + found = cd_cache_get_dev_from_volumes (mon, device, &mountpoint); + } + + if (!found) { + g_set_error (error, 0, 0, + _("Failed to find mountpoint for device %s in /etc/fstab"), + device); + return NULL; + } + + /* create struture */ + cache = g_new0 (CdCache, 1); + cache->device = device; + cache->mountpoint = mountpoint; + cache->fd = -1; + cache->self_mounted = FALSE; + cache->drive = drive; + cache->is_media = TRUE; + + return cache; +} + +static gboolean +cd_cache_open_device (CdCache *cache, + GError **error) +{ + int drive, err; + + /* not a medium? */ + if (cache->is_media == FALSE) { + cache->cap = CDC_DVD; + return TRUE; + } + + /* already open? */ + if (cache->fd > 0) + return TRUE; + + /* try to open the CD before creating anything */ + if ((cache->fd = open (cache->device, O_RDONLY)) < 0) { + err = errno; + if (err == ENOMEDIUM) { + g_set_error (error, 0, 0, + _("Please check that a disc is present in the drive.")); + } else { + g_set_error (error, 0, 0, + _("Failed to open device %s for reading: %s"), + cache->device, g_strerror (err)); + } + return FALSE; + } + + /* get capabilities */ + if ((cache->cap = ioctl (cache->fd, CDROM_GET_CAPABILITY, NULL)) < 0) { + close (cache->fd); + cache->fd = -1; + g_set_error (error, 0, 0, + _("Failed to retrieve capabilities of device %s: %s"), + cache->device, g_strerror (errno)); + return FALSE; + } + + /* is there a disc in the tray? */ + if ((drive = ioctl (cache->fd, CDROM_DRIVE_STATUS, NULL)) != CDS_DISC_OK) { + const char *drive_s; + + close (cache->fd); + cache->fd = -1; + + switch (drive) { + case CDS_NO_INFO: + drive_s = "Not implemented"; + break; + case CDS_NO_DISC: + drive_s = "No disc in tray"; + break; + case CDS_TRAY_OPEN: + drive_s = "Tray open"; + break; + case CDS_DRIVE_NOT_READY: + drive_s = "Drive not ready"; + break; + case CDS_DISC_OK: + drive_s = "OK"; + break; + default: + drive_s = "Unknown"; + break; + } + g_set_error (error, 0, 0, + _("Drive status 0x%x (%s) - check disc"), + drive, drive_s); + return FALSE; + } + + return TRUE; +} + +static gboolean +cd_cache_open_mountpoint (CdCache *cache, + GError **error) +{ + /* already opened? */ + if (cache->mounted || cache->is_media == FALSE) + return TRUE; + + /* check for mounting - assume we'll mount ourselves */ + if (cache->drive == NULL) + return TRUE; + cache->self_mounted = !gnome_vfs_drive_is_mounted (cache->drive); + + /* mount if we have to */ + if (cache->self_mounted) { + char *command; + int status; + + command = g_strdup_printf ("mount %s", cache->mountpoint); + if (!g_spawn_command_line_sync (command, + NULL, NULL, &status, error)) { + g_free (command); + return FALSE; + } + g_free (command); + if (status != 0) { + g_set_error (error, 0, 0, + _("Unexpected error status %d while mounting %s"), + status, cache->mountpoint); + return FALSE; + } + } + + cache->mounted = TRUE; + return TRUE; +} + +static void +cd_cache_free (CdCache *cache) +{ + /* umount if we mounted */ + if (cache->self_mounted && cache->mounted) { + char *command; + + command = g_strdup_printf ("umount %s", cache->mountpoint); + g_spawn_command_line_sync (command, NULL, NULL, NULL, NULL); + g_free (command); + } + + /* close file descriptor to device */ + if (cache->fd > 0) { + close (cache->fd); + } + + /* free mem */ + if (cache->drive) + gnome_vfs_drive_unref (cache->drive); + g_free (cache->mountpoint); + g_free (cache->device); + g_free (cache); +} + +static MediaType +cd_cache_disc_is_cdda (CdCache *cache, + GError **error) +{ + MediaType type = MEDIA_TYPE_DATA; + int disc; + const char *disc_s; + + /* We can't have audio CDs on disc, yet */ + if (cache->is_media == FALSE) + return type; + + /* open disc and open mount */ + if (!cd_cache_open_device (cache, error)) + return MEDIA_TYPE_ERROR; + + if ((disc = ioctl (cache->fd, CDROM_DISC_STATUS, NULL)) < 0) { + g_set_error (error, 0, 0, + _("Error getting %s disc status: %s"), + cache->device, g_strerror (errno)); + return MEDIA_TYPE_ERROR; + } + + switch (disc) { + case CDS_NO_INFO: + /* The drive doesn't implement CDROM_DISC_STATUS */ + break; + case CDS_NO_DISC: + disc_s = "No disc in tray"; + type = MEDIA_TYPE_ERROR; + break; + case CDS_AUDIO: + case CDS_MIXED: + type = MEDIA_TYPE_CDDA; + break; + case CDS_DATA_1: + case CDS_DATA_2: + case CDS_XA_2_1: + case CDS_XA_2_2: + break; + default: + disc_s = "Unknown"; + type = MEDIA_TYPE_ERROR; + break; + } + if (type == MEDIA_TYPE_ERROR) { + g_set_error (error, 0, 0, + _("Unexpected/unknown cd type 0x%x (%s)"), + disc, disc_s); + return MEDIA_TYPE_ERROR; + } + + return type; +} + +static gboolean +cd_cache_file_exists (CdCache *cache, const char *subdir, const char *filename) +{ + char *path, *dir; + gboolean ret; + + dir = NULL; + + /* Check whether the directory exists, for a start */ + path = g_build_filename (cache->mountpoint, subdir, NULL); + ret = g_file_test (path, G_FILE_TEST_IS_DIR); + if (ret == FALSE) { + char *subdir_low; + + g_free (path); + subdir_low = g_ascii_strdown (subdir, -1); + path = g_build_filename (cache->mountpoint, subdir_low, NULL); + ret = g_file_test (path, G_FILE_TEST_IS_DIR); + g_free (path); + if (ret) { + dir = subdir_low; + } else { + g_free (subdir_low); + return FALSE; + } + } else { + g_free (path); + dir = g_strdup (subdir); + } + + /* And now the file */ + path = g_build_filename (cache->mountpoint, dir, filename, NULL); + ret = g_file_test (path, G_FILE_TEST_IS_REGULAR); + if (ret == FALSE) { + char *fname_low; + + g_free (path); + fname_low = g_ascii_strdown (filename, -1); + path = g_build_filename (cache->mountpoint, dir, fname_low, NULL); + ret = g_file_test (path, G_FILE_TEST_IS_REGULAR); + g_free (fname_low); + } + + g_free (dir); + g_free (path); + + return ret; +} + +static MediaType +cd_cache_disc_is_vcd (CdCache *cache, + GError **error) +{ + if (!cache->mountpoint) + return MEDIA_TYPE_ERROR; + /* open disc and open mount */ + if (!cd_cache_open_device (cache, error)) + return MEDIA_TYPE_ERROR; + if (!cd_cache_open_mountpoint (cache, error)) + return MEDIA_TYPE_ERROR; + /* first is VCD, second is SVCD */ + if (cd_cache_file_exists (cache, "MPEGAV", "AVSEQ01.DAT") || + cd_cache_file_exists (cache, "MPEG2", "AVSEQ01.MPG")) + return MEDIA_TYPE_VCD; + + return MEDIA_TYPE_DATA; +} + +static MediaType +cd_cache_disc_is_dvd (CdCache *cache, + GError **error) +{ + if (!cache->mountpoint) + return MEDIA_TYPE_ERROR; + /* open disc, check capabilities and open mount */ + if (!cd_cache_open_device (cache, error)) + return MEDIA_TYPE_ERROR; + if (!(cache->cap & CDC_DVD)) + return MEDIA_TYPE_DATA; + if (!cd_cache_open_mountpoint (cache, error)) + return MEDIA_TYPE_ERROR; + if (cd_cache_file_exists (cache, "VIDEO_TS", "VIDEO_TS.IFO")) + return MEDIA_TYPE_DVD; + + return MEDIA_TYPE_DATA; +} + +static char * +totem_cd_mrl_from_type (const char *scheme, const char *dir) +{ + char *retval; + + if (g_str_has_prefix (dir, "file://") != FALSE) { + char *local; + local = g_filename_from_uri (dir, NULL, NULL); + retval = g_strdup_printf ("%s://%s", scheme, local); + g_free (local); + } else { + retval = g_strdup_printf ("%s://%s", scheme, dir); + } + return retval; +} + +MediaType +totem_cd_detect_type_from_dir (const char *dir, char **url, GError **error) +{ + CdCache *cache; + MediaType type; + + g_return_val_if_fail (dir != NULL, MEDIA_TYPE_ERROR); + + if (dir[0] != '/' && g_str_has_prefix (dir, "file://") == FALSE) + return MEDIA_TYPE_ERROR; + + if (!(cache = cd_cache_new (dir, error))) + return MEDIA_TYPE_ERROR; + if ((type = cd_cache_disc_is_vcd (cache, error)) == MEDIA_TYPE_DATA && + (type = cd_cache_disc_is_dvd (cache, error)) == MEDIA_TYPE_DATA) { + /* crap, nothing found */ + cd_cache_free (cache); + return type; + } + cd_cache_free (cache); + + if (url == NULL) { + return type; + } + + if (type == MEDIA_TYPE_DVD) { + *url = totem_cd_mrl_from_type ("dvd", dir); + } else if (type == MEDIA_TYPE_VCD) { + *url = totem_cd_mrl_from_type ("vcd", dir); + } + + return type; +} + +MediaType +totem_cd_detect_type_with_url (const char *device, + char **url, + GError **error) +{ + CdCache *cache; + MediaType type; + + if (url != NULL) + *url = NULL; + + if (!(cache = cd_cache_new (device, error))) + return MEDIA_TYPE_ERROR; + + type = cd_cache_disc_is_cdda (cache, error); + if (type == MEDIA_TYPE_ERROR && *error != NULL) + return type; + + if ((type == MEDIA_TYPE_DATA || type == MEDIA_TYPE_ERROR) && + (type = cd_cache_disc_is_vcd (cache, error)) == MEDIA_TYPE_DATA && + (type = cd_cache_disc_is_dvd (cache, error)) == MEDIA_TYPE_DATA) { + /* crap, nothing found */ + } + + if (url == NULL) { + cd_cache_free (cache); + return type; + } + + switch (type) { + case MEDIA_TYPE_DVD: + *url = totem_cd_mrl_from_type ("dvd", device); + break; + case MEDIA_TYPE_VCD: + *url = totem_cd_mrl_from_type ("vcd", device); + break; + case MEDIA_TYPE_CDDA: + *url = totem_cd_mrl_from_type ("cdda", device); + break; + case MEDIA_TYPE_DATA: + *url = g_strdup (cache->mountpoint); + break; + default: + break; + } + + cd_cache_free (cache); + + return type; +} + +MediaType +totem_cd_detect_type (const char *device, + GError **error) +{ + return totem_cd_detect_type_with_url (device, NULL, error); +} + +const char * +totem_cd_get_human_readable_name (MediaType type) +{ + switch (type) + { + case MEDIA_TYPE_CDDA: + return N_("Audio CD"); + case MEDIA_TYPE_VCD: + return N_("Video CD"); + case MEDIA_TYPE_DVD: + return N_("DVD"); + default: + g_assert_not_reached (); + } + + return NULL; +} + +/* + * vim: sw=2 ts=8 cindent noai bs=2 + */ --- rhythmbox-0.9.2.orig/plparse/totem-disc.h 1969-12-31 16:00:00.000000000 -0800 +++ rhythmbox-0.9.2.orig/plparse/totem-disc.h 2005-12-04 17:17:11.000000000 -0800 @@ -0,0 +1,49 @@ +/* Totem Disc Content Detection + * (c) 2004 Ronald Bultje + * + * totem-disc.h: media content detection + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef TOTEM_DISC_H +#define TOTEM_DISC_H + +#include + +G_BEGIN_DECLS + +typedef enum { + MEDIA_TYPE_ERROR = -1, /* error */ + MEDIA_TYPE_DATA = 1, + MEDIA_TYPE_CDDA, + MEDIA_TYPE_VCD, + MEDIA_TYPE_DVD +} MediaType; + +MediaType totem_cd_detect_type (const char *device, + GError **error); +MediaType totem_cd_detect_type_with_url (const char *device, + char **url, + GError **error); +MediaType totem_cd_detect_type_from_dir (const char *dir, + char **url, + GError **error); +const char * totem_cd_get_human_readable_name (MediaType type); + +G_END_DECLS + +#endif /* TOTEM_DISC_H */ --- rhythmbox-0.9.2.orig/plparse/totem-pl-parser.c 1969-12-31 16:00:00.000000000 -0800 +++ rhythmbox-0.9.2.orig/plparse/totem-pl-parser.c 2005-12-04 17:17:11.000000000 -0800 @@ -0,0 +1,1632 @@ +/* + arch-tag: Implementation of Rhythmbox playlist parser + + Copyright (C) 2002, 2003, 2004 Bastien Nocera + Copyright (C) 2003,2004 Colin Walters + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Bastien Nocera + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "totem-pl-parser.h" + +#include "totemplparser-marshal.h" +#include "totem-disc.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define READ_CHUNK_SIZE 8192 +#define MIME_READ_CHUNK_SIZE 1024 +#define RECURSE_LEVEL_MAX 4 + +typedef TotemPlParserResult (*PlaylistCallback) (TotemPlParser *parser, const char *url, gpointer data); +static gboolean totem_pl_parser_scheme_is_ignored (TotemPlParser *parser, const char *url); +static gboolean totem_pl_parser_ignore (TotemPlParser *parser, const char *url); +static TotemPlParserResult totem_pl_parser_parse_internal (TotemPlParser *parser, const char *url); +static TotemPlParserResult totem_pl_parser_add_asx (TotemPlParser *parser, const char *url, gpointer data); + +typedef struct { + char *mimetype; + PlaylistCallback func; +} PlaylistTypes; + +struct TotemPlParserPrivate +{ + GList *ignore_schemes; + GList *ignore_mimetypes; + guint recurse_level; + gboolean fallback; +}; + +/* Signals */ +enum { + ENTRY, + PLAYLIST_START, + PLAYLIST_END, + LAST_SIGNAL +}; + +static int totem_pl_parser_table_signals[LAST_SIGNAL] = { 0 }; + +static GObjectClass *parent_class = NULL; + +static void totem_pl_parser_class_init (TotemPlParserClass *class); +static void totem_pl_parser_init (TotemPlParser *parser); +static void totem_pl_parser_finalize (GObject *object); + +G_DEFINE_TYPE(TotemPlParser, totem_pl_parser, G_TYPE_OBJECT) + +static void +totem_pl_parser_class_init (TotemPlParserClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->finalize = totem_pl_parser_finalize; + + /* Signals */ + totem_pl_parser_table_signals[ENTRY] = + g_signal_new ("entry", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (TotemPlParserClass, entry), + NULL, NULL, + totemplparser_marshal_VOID__STRING_STRING_STRING, + G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + totem_pl_parser_table_signals[PLAYLIST_START] = + g_signal_new ("playlist-start", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (TotemPlParserClass, playlist_start), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + totem_pl_parser_table_signals[PLAYLIST_END] = + g_signal_new ("playlist-end", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (TotemPlParserClass, playlist_end), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); +} + +GQuark +totem_pl_parser_error_quark (void) +{ + static GQuark quark; + if (!quark) + quark = g_quark_from_static_string ("totem_pl_parser_error"); + + return quark; +} + +TotemPlParser * +totem_pl_parser_new (void) +{ + return TOTEM_PL_PARSER (g_object_new (TOTEM_TYPE_PL_PARSER, NULL)); +} + +static const char * +my_gnome_vfs_get_mime_type_with_data (const char *uri, gpointer *data) +{ + GnomeVFSResult result; + GnomeVFSHandle *handle; + char *buffer; + const char *mimetype; + GnomeVFSFileSize total_bytes_read; + GnomeVFSFileSize bytes_read; + + *data = NULL; + + /* Open the file. */ + result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ); + if (result != GNOME_VFS_OK) + return NULL; + + /* Read the whole thing, up to MIME_READ_CHUNK_SIZE */ + buffer = NULL; + total_bytes_read = 0; + do { + buffer = g_realloc (buffer, total_bytes_read + + MIME_READ_CHUNK_SIZE); + result = gnome_vfs_read (handle, + buffer + total_bytes_read, + MIME_READ_CHUNK_SIZE, + &bytes_read); + if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_EOF) { + g_free (buffer); + gnome_vfs_close (handle); + return NULL; + } + + /* Check for overflow. */ + if (total_bytes_read + bytes_read < total_bytes_read) { + g_free (buffer); + gnome_vfs_close (handle); + return NULL; + } + + total_bytes_read += bytes_read; + } while (result == GNOME_VFS_OK + && total_bytes_read < MIME_READ_CHUNK_SIZE); + + /* Close the file. */ + result = gnome_vfs_close (handle); + if (result != GNOME_VFS_OK) { + g_free (buffer); + return NULL; + } + + /* Return the file null-terminated. */ + buffer = g_realloc (buffer, total_bytes_read + 1); + buffer[total_bytes_read] = '\0'; + *data = buffer; + + mimetype = gnome_vfs_get_mime_type_for_data (*data, total_bytes_read); + + return mimetype; +} + +static char* +totem_pl_parser_base_url (const char *url) +{ + /* Yay, let's reconstruct the base by hand */ + GnomeVFSURI *uri, *parent; + char *base; + + uri = gnome_vfs_uri_new (url); + if (uri == NULL) + return NULL; + + parent = gnome_vfs_uri_get_parent (uri); + if (!parent) { + parent = uri; + } + base = gnome_vfs_uri_to_string (parent, 0); + + gnome_vfs_uri_unref (uri); + if (parent != uri) { + gnome_vfs_uri_unref (parent); + } + + return base; +} + +static gboolean +write_string (GnomeVFSHandle *handle, const char *buf, GError **error) +{ + GnomeVFSResult res; + GnomeVFSFileSize written; + guint len; + + len = strlen (buf); + res = gnome_vfs_write (handle, buf, len, &written); + if (res != GNOME_VFS_OK || written < len) { + g_set_error (error, + TOTEM_PL_PARSER_ERROR, + TOTEM_PL_PARSER_ERROR_VFS_WRITE, + _("Couldn't write parser: %s"), + gnome_vfs_result_to_string (res)); + gnome_vfs_close (handle); + return FALSE; + } + + return TRUE; +} + +static int +totem_pl_parser_num_entries (TotemPlParser *parser, GtkTreeModel *model, + TotemPlParserIterFunc func, gpointer user_data) +{ + int num_entries, i, ignored; + + num_entries = gtk_tree_model_iter_n_children (model, NULL); + ignored = 0; + + for (i = 1; i <= num_entries; i++) + { + GtkTreeIter iter; + char *path, *url, *title; + + path = g_strdup_printf ("%d", i - 1); + gtk_tree_model_get_iter_from_string (model, &iter, path); + g_free (path); + + func (model, &iter, &url, &title, user_data); + if (totem_pl_parser_scheme_is_ignored (parser, url) != FALSE) + ignored++; + + g_free (url); + g_free (title); + } + + return num_entries - ignored; +} + +static char * +totem_pl_parser_relative (const char *url, const char *output) +{ + char *url_base, *output_base; + char *base, *needle; + + base = NULL; + url_base = totem_pl_parser_base_url (url); + if (url_base == NULL) + return NULL; + + output_base = totem_pl_parser_base_url (output); + + needle = strstr (url_base, output_base); + if (needle != NULL) + { + GnomeVFSURI *uri; + char *newurl; + + uri = gnome_vfs_uri_new (url); + newurl = gnome_vfs_uri_to_string (uri, 0); + if (newurl[strlen (output_base)] == '/') { + base = g_strdup (newurl + strlen (output_base) + 1); + } else { + base = g_strdup (newurl + strlen (output_base)); + } + gnome_vfs_uri_unref (uri); + g_free (newurl); + + /* And finally unescape the string */ + newurl = gnome_vfs_unescape_string (base, NULL); + g_free (base); + base = newurl; + } + + g_free (url_base); + g_free (output_base); + + return base; +} + +static gboolean +totem_pl_parser_write_pls (TotemPlParser *parser, GtkTreeModel *model, + TotemPlParserIterFunc func, + const char *output, const char *title, + gpointer user_data, GError **error) +{ + GnomeVFSHandle *handle; + GnomeVFSResult res; + int num_entries_total, num_entries, i; + char *buf; + gboolean success; + + num_entries = totem_pl_parser_num_entries (parser, model, func, user_data); + num_entries_total = gtk_tree_model_iter_n_children (model, NULL); + + res = gnome_vfs_open (&handle, output, GNOME_VFS_OPEN_WRITE); + if (res == GNOME_VFS_ERROR_NOT_FOUND) { + res = gnome_vfs_create (&handle, output, + GNOME_VFS_OPEN_WRITE, FALSE, + GNOME_VFS_PERM_USER_WRITE + | GNOME_VFS_PERM_USER_READ + | GNOME_VFS_PERM_GROUP_READ); + } + + if (res != GNOME_VFS_OK) { + g_set_error(error, + TOTEM_PL_PARSER_ERROR, + TOTEM_PL_PARSER_ERROR_VFS_OPEN, + _("Couldn't open file '%s': %s"), + output, gnome_vfs_result_to_string (res)); + return FALSE; + } + + buf = g_strdup ("[playlist]\n"); + success = write_string (handle, buf, error); + g_free (buf); + if (success == FALSE) + return FALSE; + + if (title != NULL) { + buf = g_strdup_printf ("X-GNOME-Title=%s\n", title); + success = write_string (handle, buf, error); + g_free (buf); + if (success == FALSE) + { + gnome_vfs_close (handle); + return FALSE; + } + } + + buf = g_strdup_printf ("NumberOfEntries=%d\n", num_entries); + success = write_string (handle, buf, error); + g_free (buf); + if (success == FALSE) + { + gnome_vfs_close (handle); + return FALSE; + } + + for (i = 1; i <= num_entries_total; i++) { + GtkTreeIter iter; + char *path, *url, *title, *relative; + + path = g_strdup_printf ("%d", i - 1); + gtk_tree_model_get_iter_from_string (model, &iter, path); + g_free (path); + + func (model, &iter, &url, &title, user_data); + + if (totem_pl_parser_scheme_is_ignored (parser, url) != FALSE) + { + g_free (url); + g_free (title); + continue; + } + + relative = totem_pl_parser_relative (url, output); + buf = g_strdup_printf ("File%d=%s\n", i, + relative ? relative : url); + g_free (relative); + g_free (url); + success = write_string (handle, buf, error); + g_free (buf); + if (success == FALSE) + { + gnome_vfs_close (handle); + g_free (title); + return FALSE; + } + + buf = g_strdup_printf ("Title%d=%s\n", i, title); + success = write_string (handle, buf, error); + g_free (buf); + g_free (title); + if (success == FALSE) + { + gnome_vfs_close (handle); + return FALSE; + } + } + + gnome_vfs_close (handle); + return TRUE; +} + +static char * +totem_pl_parser_url_to_dos (const char *url, const char *output) +{ + char *retval, *i; + + retval = totem_pl_parser_relative (url, output); + + if (retval == NULL) + retval = g_strdup (url); + + /* Don't change URIs, but change smb:// */ + if (g_str_has_prefix (retval, "smb://") != FALSE) + { + char *tmp; + tmp = g_strdup (retval + strlen ("smb:")); + g_free (retval); + retval = tmp; + } + + if (strstr (retval, "://") != NULL) + return retval; + + i = retval; + while (*i != '\0') + { + if (*i == '/') + *i = '\\'; + i++; + } + + return retval; +} + +static gboolean +totem_pl_parser_write_m3u (TotemPlParser *parser, GtkTreeModel *model, + TotemPlParserIterFunc func, const char *output, + gboolean dos_compatible, gpointer user_data, GError **error) +{ + GnomeVFSHandle *handle; + GnomeVFSResult res; + int num_entries_total, i; + gboolean success; + char *buf; + + res = gnome_vfs_open (&handle, output, GNOME_VFS_OPEN_WRITE); + if (res == GNOME_VFS_ERROR_NOT_FOUND) { + res = gnome_vfs_create (&handle, output, + GNOME_VFS_OPEN_WRITE, FALSE, + GNOME_VFS_PERM_USER_WRITE + | GNOME_VFS_PERM_USER_READ + | GNOME_VFS_PERM_GROUP_READ); + } + + if (res != GNOME_VFS_OK) { + g_set_error(error, + TOTEM_PL_PARSER_ERROR, + TOTEM_PL_PARSER_ERROR_VFS_OPEN, + _("Couldn't open file '%s': %s"), + output, gnome_vfs_result_to_string (res)); + return FALSE; + } + + num_entries_total = gtk_tree_model_iter_n_children (model, NULL); + + for (i = 1; i <= num_entries_total; i++) { + GtkTreeIter iter; + char *path, *url, *title; + + path = g_strdup_printf ("%d", i - 1); + gtk_tree_model_get_iter_from_string (model, &iter, path); + g_free (path); + + func (model, &iter, &url, &title, user_data); + + if (totem_pl_parser_scheme_is_ignored (parser, url) != FALSE) + { + g_free (url); + g_free (title); + continue; + } + + if (dos_compatible != FALSE) + { + char *dos; + + dos = totem_pl_parser_url_to_dos (url, output); + buf = g_strdup_printf ("%s\r\n", dos); + g_free (dos); + } else { + char *relative; + + relative = totem_pl_parser_relative (url, output); + buf = g_strdup_printf ("%s\n", relative); + g_free (relative); + } + + success = write_string (handle, url, error); + + if (success == FALSE) + { + gnome_vfs_close (handle); + return FALSE; + } + } + + return TRUE; +} + +gboolean +totem_pl_parser_write_with_title (TotemPlParser *parser, GtkTreeModel *model, + TotemPlParserIterFunc func, + const char *output, const char *title, + TotemPlParserType type, + gpointer user_data, GError **error) +{ + switch (type) + { + case TOTEM_PL_PARSER_PLS: + return totem_pl_parser_write_pls (parser, model, func, + output, title, user_data, error); + case TOTEM_PL_PARSER_M3U: + case TOTEM_PL_PARSER_M3U_DOS: + return totem_pl_parser_write_m3u (parser, model, func, + output, (type == TOTEM_PL_PARSER_M3U_DOS), + user_data, error); + default: + g_assert_not_reached (); + } + + return FALSE; +} + +gboolean +totem_pl_parser_write (TotemPlParser *parser, GtkTreeModel *model, + TotemPlParserIterFunc func, + const char *output, TotemPlParserType type, + gpointer user_data, + GError **error) +{ + return totem_pl_parser_write_with_title (parser, model, func, output, + NULL, type, user_data, error); +} + +static int +read_ini_line_int (char **lines, const char *key) +{ + int retval = -1; + int i; + + if (lines == NULL || key == NULL) + return -1; + + for (i = 0; (lines[i] != NULL && retval == -1); i++) { + if (g_ascii_strncasecmp (lines[i], key, strlen (key)) == 0) { + char **bits; + + bits = g_strsplit (lines[i], "=", 2); + if (bits[0] == NULL || bits [1] == NULL) { + g_strfreev (bits); + return -1; + } + + retval = (gint) g_strtod (bits[1], NULL); + g_strfreev (bits); + } + } + + return retval; +} + +static char* +read_ini_line_string (char **lines, const char *key, gboolean dos_mode) +{ + char *retval = NULL; + int i; + + if (lines == NULL || key == NULL) + return NULL; + + for (i = 0; (lines[i] != NULL && retval == NULL); i++) { + if (g_ascii_strncasecmp (lines[i], key, strlen (key)) == 0) { + char **bits; + ssize_t len; + + bits = g_strsplit (lines[i], "=", 2); + if (bits[0] == NULL || bits [1] == NULL) { + g_strfreev (bits); + return NULL; + } + + retval = g_strdup (bits[1]); + len = strlen (retval); + if (dos_mode && len >= 2 && retval[len-2] == '\r') { + retval[len-2] = '\n'; + retval[len-1] = '\0'; + } + + g_strfreev (bits); + } + } + + return retval; +} + +static void +totem_pl_parser_init (TotemPlParser *parser) +{ + parser->priv = g_new0 (TotemPlParserPrivate, 1); +} + +static void +totem_pl_parser_finalize (GObject *object) +{ + TotemPlParser *parser = TOTEM_PL_PARSER (object); + + g_return_if_fail (object != NULL); + g_return_if_fail (parser->priv != NULL); + + g_list_foreach (parser->priv->ignore_schemes, (GFunc) g_free, NULL); + g_list_free (parser->priv->ignore_schemes); + + g_list_foreach (parser->priv->ignore_mimetypes, (GFunc) g_free, NULL); + g_list_free (parser->priv->ignore_mimetypes); + + g_free (parser->priv); + parser->priv = NULL; + + if (G_OBJECT_CLASS (parent_class)->finalize != NULL) { + (* G_OBJECT_CLASS (parent_class)->finalize) (object); + } +} + +static gboolean +totem_pl_parser_check_utf8 (const char *title) +{ + return title ? g_utf8_validate (title, -1, NULL) : FALSE; +} + +static void +totem_pl_parser_add_one_url (TotemPlParser *parser, const char *url, const char *title) +{ + g_signal_emit (G_OBJECT (parser), totem_pl_parser_table_signals[ENTRY], + 0, url, + totem_pl_parser_check_utf8 (title) ? title : NULL, + NULL); +} + +static void +totem_pl_parser_add_one_url_ext (TotemPlParser *parser, const char *url, + const char *title, const char *genre) +{ + g_signal_emit (G_OBJECT (parser), totem_pl_parser_table_signals[ENTRY], + 0, url, + totem_pl_parser_check_utf8 (title) ? title : NULL, + genre); +} + +static TotemPlParserResult +totem_pl_parser_add_ram (TotemPlParser *parser, const char *url, gpointer data) +{ + gboolean retval = TOTEM_PL_PARSER_RESULT_UNHANDLED; + char *contents, **lines; + int size, i; + const char *split_char; + + if (gnome_vfs_read_entire_file (url, &size, &contents) != GNOME_VFS_OK) + return TOTEM_PL_PARSER_RESULT_ERROR; + + /* figure out whether we're a unix or dos RAM file */ + if (strstr(contents,"\x0d") == NULL) + split_char = "\n"; + else + split_char = "\x0d\n"; + + lines = g_strsplit (contents, split_char, 0); + g_free (contents); + + for (i = 0; lines[i] != NULL; i++) { + if (strcmp (lines[i], "") == 0) + continue; + + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + + /* Either it's a URI, or it has a proper path ... */ + if (strstr(lines[i], "://") != NULL + || lines[i][0] == G_DIR_SEPARATOR) { + /* .ram files can contain .smil entries */ + if (totem_pl_parser_parse_internal (parser, lines[i]) != TOTEM_PL_PARSER_RESULT_SUCCESS) + { + totem_pl_parser_add_one_url (parser, + lines[i], NULL); + } + } else if (strcmp (lines[i], "--stop--") == 0) { + /* For Real Media playlists, handle the stop command */ + break; + } else { + char *fullpath, *base; + + /* Try with a base */ + base = totem_pl_parser_base_url (url); + + fullpath = g_strdup_printf ("%s/%s", base, lines[i]); + if (totem_pl_parser_parse_internal (parser, fullpath) != TOTEM_PL_PARSER_RESULT_SUCCESS) + { + totem_pl_parser_add_one_url (parser, fullpath, NULL); + } + g_free (fullpath); + g_free (base); + } + } + + g_strfreev (lines); + + return retval; +} + +static const char * +totem_pl_parser_get_extinfo_title (gboolean extinfo, char **lines, int i) +{ + const char *retval; + + if (extinfo == FALSE || lines == NULL) + return NULL; + + if (i == 0) + return NULL; + + retval = strstr (lines[i-1], "#EXTINF:"); + retval = strstr (retval, ","); + if (retval == NULL || retval[0] == '\0') + return NULL; + + retval++; + + return retval; +} + +static TotemPlParserResult +totem_pl_parser_add_m3u (TotemPlParser *parser, const char *url, gpointer data) +{ + gboolean retval = TOTEM_PL_PARSER_RESULT_UNHANDLED; + char *contents, **lines; + int size, i; + const char *split_char; + gboolean extinfo; + + if (gnome_vfs_read_entire_file (url, &size, &contents) != GNOME_VFS_OK) + return FALSE; + + /* is TRUE if there's an EXTINF on the previous line */ + extinfo = FALSE; + + /* figure out whether we're a unix m3u or dos m3u */ + if (strstr(contents,"\x0d") == NULL) + split_char = "\n"; + else + split_char = "\x0d\n"; + + lines = g_strsplit (contents, split_char, 0); + g_free (contents); + + for (i = 0; lines[i] != NULL; i++) { + if (lines[i][0] == '\0') + continue; + + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + + /* Ignore comments, but mark it if we have extra info */ + if (lines[i][0] == '#') { + if (strstr (lines[i], "#EXTINF") != NULL) + extinfo = TRUE; + continue; + } + + /* Either it's a URI, or it has a proper path ... */ + if (strstr(lines[i], "://") != NULL + || lines[i][0] == G_DIR_SEPARATOR) { + totem_pl_parser_add_one_url (parser, lines[i], + totem_pl_parser_get_extinfo_title (extinfo, lines, i)); + extinfo = FALSE; + } else if (lines[i][0] == '\\' && lines[i][1] == '\\') { + /* ... Or it's in the windows smb form + * (\\machine\share\filename), Note drive names + * (C:\ D:\ etc) are unhandled (unknown base for + * drive letters) */ + char *tmpurl; + + lines[i] = g_strdelimit (lines[i], "\\", '/'); + tmpurl = g_strjoin (NULL, "smb:", lines[i], NULL); + + totem_pl_parser_add_one_url (parser, lines[i], + totem_pl_parser_get_extinfo_title (extinfo, lines, i)); + extinfo = FALSE; + + g_free (tmpurl); + } else { + /* Try with a base */ + char *fullpath, *base, sep; + + base = totem_pl_parser_base_url (url); + sep = (split_char[0] == '\n' ? '/' : '\\'); + if (sep == '\\') + lines[i] = g_strdelimit (lines[i], "\\", '/'); + fullpath = g_strdup_printf ("%s/%s", base, lines[i]); + totem_pl_parser_add_one_url (parser, fullpath, + totem_pl_parser_get_extinfo_title (extinfo, lines, i)); + g_free (fullpath); + g_free (base); + extinfo = FALSE; + } + } + + g_strfreev (lines); + + return retval; +} + +static TotemPlParserResult +totem_pl_parser_add_asf_reference_parser (TotemPlParser *parser, + const char *url, gpointer data) +{ + gboolean retval = TOTEM_PL_PARSER_RESULT_UNHANDLED; + char *contents, **lines, *ref, *split_char; + int size; + + if (gnome_vfs_read_entire_file (url, &size, &contents) != GNOME_VFS_OK) + return TOTEM_PL_PARSER_RESULT_ERROR; + + if (strstr(contents,"\x0d") == NULL) { + split_char = "\n"; + } else { + split_char = "\x0d\n"; + } + + lines = g_strsplit (contents, split_char, 0); + g_free (contents); + + ref = read_ini_line_string (lines, "Ref1", FALSE); + + if (ref == NULL) { + g_strfreev (lines); + return totem_pl_parser_add_asx (parser, url, data); + } + + /* change http to mmsh, thanks Microsoft */ + if (g_str_has_prefix (ref, "http") != FALSE) + memcpy(ref, "mmsh", 4); + + totem_pl_parser_add_one_url (parser, ref, NULL); + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + g_free (ref); + + g_strfreev (lines); + + return retval; +} + +static TotemPlParserResult +totem_pl_parser_add_asf_parser (TotemPlParser *parser, + const char *url, gpointer data) +{ + gboolean retval = TOTEM_PL_PARSER_RESULT_UNHANDLED; + char *contents, *ref; + int size; + + if (g_str_has_prefix (data, "ASF ") == FALSE) { + return totem_pl_parser_add_asf_reference_parser (parser, url, data); + } + + if (gnome_vfs_read_entire_file (url, &size, &contents) != GNOME_VFS_OK) + return TOTEM_PL_PARSER_RESULT_ERROR; + + if (size <= 4) { + g_free (contents); + return TOTEM_PL_PARSER_RESULT_ERROR; + } + + /* Skip 'ASF ' */ + ref = contents + 4; + if (g_str_has_prefix (ref, "http") != FALSE) { + memcpy(ref, "mmsh", 4); + totem_pl_parser_add_one_url (parser, ref, NULL); + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + } + + g_free (contents); + return retval; +} + +static TotemPlParserResult +totem_pl_parser_add_pls (TotemPlParser *parser, const char *url, gpointer data) +{ + gboolean retval = TOTEM_PL_PARSER_RESULT_UNHANDLED; + char *contents, **lines; + int size, i, num_entries; + char *split_char, *playlist_title; + gboolean dos_mode = FALSE; + + if (gnome_vfs_read_entire_file (url, &size, &contents) != GNOME_VFS_OK) + return TOTEM_PL_PARSER_RESULT_ERROR; + + if (size == 0) + { + g_free (contents); + return TOTEM_PL_PARSER_RESULT_SUCCESS; + } + + /* figure out whether we're a unix pls or dos pls */ + if (strstr(contents,"\x0d") == NULL) { + split_char = "\n"; + } else { + split_char = "\x0d\n"; + dos_mode = TRUE; + } + lines = g_strsplit (contents, split_char, 0); + g_free (contents); + + /* [playlist] */ + i = 0; + playlist_title = NULL; + + /* Ignore empty lines */ + while (lines[i] != NULL && strcmp (lines[i], "") == 0) + i++; + + if (lines[i] == NULL + || g_ascii_strncasecmp (lines[i], "[playlist]", + (gsize)strlen ("[playlist]")) != 0) + goto bail; + + playlist_title = read_ini_line_string (lines, + "X-GNOME-Title", dos_mode); + + if (playlist_title != NULL) { + g_signal_emit (G_OBJECT (parser), + totem_pl_parser_table_signals[PLAYLIST_START], + 0, playlist_title); + } + + /* numberofentries=? */ + num_entries = read_ini_line_int (lines, "numberofentries"); + if (num_entries == -1) + goto bail; + + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + + for (i = 1; i <= num_entries; i++) { + char *file, *title, *genre; + char *file_key, *title_key, *genre_key; + + file_key = g_strdup_printf ("file%d", i); + title_key = g_strdup_printf ("title%d", i); + /* Genre is our own little extension */ + genre_key = g_strdup_printf ("genre%d", i); + + file = read_ini_line_string (lines, (const char*)file_key, dos_mode); + title = read_ini_line_string (lines, (const char*)title_key, dos_mode); + genre = read_ini_line_string (lines, (const char*)genre_key, dos_mode); + + g_free (file_key); + g_free (title_key); + g_free (genre_key); + + if (file == NULL) + { + g_free (file); + g_free (title); + g_free (genre); + continue; + } + + if (strstr (file, "://") != NULL + || file[0] == G_DIR_SEPARATOR) { + totem_pl_parser_add_one_url_ext (parser, + file, title, genre); + } else { + char *uri, *base, *escaped; + + /* Try with a base */ + base = totem_pl_parser_base_url (url); + escaped = gnome_vfs_escape_path_string (file); + + uri = g_strdup_printf ("%s/%s", base, escaped); + + totem_pl_parser_add_one_url_ext (parser, + uri, title, genre); + + g_free (escaped); + g_free (uri); + g_free (base); + } + + g_free (file); + g_free (title); + g_free (genre); + } + + if (playlist_title != NULL) { + g_signal_emit (G_OBJECT (parser), + totem_pl_parser_table_signals[PLAYLIST_END], + 0, playlist_title); + } + +bail: + g_free (playlist_title); + g_strfreev (lines); + + return retval; +} + +static gboolean +parse_asx_entry (TotemPlParser *parser, char *base, xmlDocPtr doc, + xmlNodePtr parent, const char *pl_title) +{ + xmlNodePtr node; + guchar *title, *url; + gboolean retval = FALSE; + char *fullpath = NULL; + + title = NULL; + url = NULL; + + for (node = parent->children; node != NULL; node = node->next) { + if (node->name == NULL) + continue; + + /* ENTRY should only have one ref and one title nodes */ + if (g_ascii_strcasecmp ((char *)node->name, "ref") == 0 + || g_ascii_strcasecmp ((char *)node->name, "entryref") == 0) { + url = xmlGetProp (node, (guchar *)"href"); + if (url == NULL) + url = xmlGetProp (node, (guchar *)"HREF"); + continue; + } + + if (g_ascii_strcasecmp ((char *)node->name, "title") == 0) + title = xmlNodeListGetString(doc, node->children, 1); + } + + if (url == NULL) { + g_free (title); + return FALSE; + } + + if (strstr ((char *)url, "://") == NULL && url[0] != '/') { + fullpath = g_strdup_printf ("%s/%s", base, url); + } else { + fullpath = g_strdup ((char *)url); + } + + /* .asx files can contain references to other .asx files */ + if (totem_pl_parser_parse_internal (parser, fullpath) != TOTEM_PL_PARSER_RESULT_SUCCESS) { + totem_pl_parser_add_one_url (parser, fullpath, + (char *)title ? (char *)title : pl_title); + } + + g_free (fullpath); + g_free (title); + g_free (url); + + return retval; +} + +static gboolean +parse_asx_entries (TotemPlParser *parser, char *base, xmlDocPtr doc, + xmlNodePtr parent) +{ + guchar *title = NULL; + xmlNodePtr node; + gboolean retval = FALSE; + + for (node = parent->children; node != NULL; node = node->next) { + if (node->name == NULL) + continue; + + if (g_ascii_strcasecmp ((char *)node->name, "title") == 0) { + title = xmlNodeListGetString(doc, node->children, 1); + } + + if (g_ascii_strcasecmp ((char *)node->name, "entry") == 0) { + /* Whee found an entry here, find the REF and TITLE */ + if (parse_asx_entry (parser, base, doc, node, (char *)title) != FALSE) + retval = TRUE; + } + if (g_ascii_strcasecmp ((char *)node->name, "entryref") == 0) { + /* Found an entryref, give the parent instead of the + * children to the parser */ + if (parse_asx_entry (parser, base, doc, parent, (char *)title) != FALSE) + retval = TRUE; + } + if (g_ascii_strcasecmp ((char *)node->name, "repeat") == 0) { + /* Repeat at the top-level */ + if (parse_asx_entries (parser, base, doc, node) != FALSE) + retval = TRUE; + } + } + + g_free (title); + + return retval; +} + +static TotemPlParserResult +totem_pl_parser_add_asx (TotemPlParser *parser, const char *url, gpointer data) +{ + xmlDocPtr doc; + xmlNodePtr node; + char *contents = NULL, *base; + int size; + gboolean retval = TOTEM_PL_PARSER_RESULT_UNHANDLED; + + if (gnome_vfs_read_entire_file (url, &size, &contents) != GNOME_VFS_OK) + return FALSE; + + doc = xmlParseMemory (contents, size); + if (doc == NULL) + doc = xmlRecoverMemory (contents, size); + g_free (contents); + + /* If the document has no root, or no name */ + if(!doc || !doc->children || !doc->children->name) { + if (doc != NULL) + xmlFreeDoc(doc); + return TOTEM_PL_PARSER_RESULT_ERROR; + } + + base = totem_pl_parser_base_url (url); + + for (node = doc->children; node != NULL; node = node->next) + if (parse_asx_entries (parser, base, doc, node) != FALSE) + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + + g_free (base); + xmlFreeDoc(doc); + return retval; +} + +static TotemPlParserResult +totem_pl_parser_add_ra (TotemPlParser *parser, const char *url, gpointer data) +{ + if (data == NULL + || (g_str_has_prefix (data, "http://") == FALSE + && g_str_has_prefix (data, "rtsp://") == FALSE + && g_str_has_prefix (data, "pnm://") == FALSE)) { + totem_pl_parser_add_one_url (parser, url, NULL); + return TOTEM_PL_PARSER_RESULT_SUCCESS; + } + + return totem_pl_parser_add_ram (parser, url, NULL); +} + +static gboolean +parse_smil_video_entry (TotemPlParser *parser, char *base, + char *url, char *title) +{ + if (strstr (url, "://") != NULL || url[0] == '/') { + totem_pl_parser_add_one_url (parser, url, title); + } else { + char *fullpath; + + fullpath = g_strdup_printf ("%s/%s", base, url); + totem_pl_parser_add_one_url (parser, fullpath, title); + + g_free (fullpath); + } + + return TRUE; +} + +static gboolean +parse_smil_entry (TotemPlParser *parser, char *base, xmlDocPtr doc, + xmlNodePtr parent) +{ + xmlNodePtr node; + guchar *title, *url; + gboolean retval = FALSE; + + title = NULL; + url = NULL; + + for (node = parent->children; node != NULL; node = node->next) + { + if (node->name == NULL) + continue; + + /* ENTRY should only have one ref and one title nodes */ + if (g_ascii_strcasecmp ((char *)node->name, "video") == 0) { + url = xmlGetProp (node, (guchar *)"src"); + title = xmlGetProp (node, (guchar *)"title"); + + if (url != NULL) { + if (parse_smil_video_entry (parser, + base, (char *)url, (char *)title) != FALSE) + retval = TRUE; + } + + g_free (title); + g_free (url); + } else { + if (parse_smil_entry (parser, + base, doc, node) != FALSE) + retval = TRUE; + } + } + + return retval; +} + +static gboolean +parse_smil_entries (TotemPlParser *parser, char *base, xmlDocPtr doc, + xmlNodePtr parent) +{ + xmlNodePtr node; + gboolean retval = FALSE; + + for (node = parent->children; node != NULL; node = node->next) { + if (node->name == NULL) + continue; + + if (g_ascii_strcasecmp ((char *)node->name, "body") == 0) { + if (parse_smil_entry (parser, base, + doc, node) != FALSE) + retval = TRUE; + } + + } + + return retval; +} + +static TotemPlParserResult +totem_pl_parser_add_smil (TotemPlParser *parser, const char *url, gpointer data) +{ + xmlDocPtr doc; + xmlNodePtr node; + char *contents = NULL, *base; + int size; + gboolean retval = TOTEM_PL_PARSER_RESULT_UNHANDLED; + + if (gnome_vfs_read_entire_file (url, &size, &contents) != GNOME_VFS_OK) + return TOTEM_PL_PARSER_RESULT_ERROR; + + doc = xmlParseMemory (contents, size); + if (doc == NULL) + doc = xmlRecoverMemory (contents, size); + g_free (contents); + + /* If the document has no root, or no name */ + if(!doc || !doc->children + || !doc->children->name + || g_ascii_strcasecmp ((char *)doc->children->name, + "smil") != 0) { + if (doc != NULL) + xmlFreeDoc (doc); + return TOTEM_PL_PARSER_RESULT_ERROR; + } + + base = totem_pl_parser_base_url (url); + + for (node = doc->children; node != NULL; node = node->next) + if (parse_smil_entries (parser, base, doc, node) != FALSE) + retval = TOTEM_PL_PARSER_RESULT_SUCCESS; + + g_free (base); + xmlFreeDoc (doc); + + return retval; +} + +static TotemPlParserResult +totem_pl_parser_add_asf (TotemPlParser *parser, const char *url, gpointer data) +{ + if (data != NULL && + (g_str_has_prefix (data, "[Reference]") == FALSE + && g_ascii_strncasecmp (data, "name == NULL) { + if (b->name == NULL) + return 0; + else + return -1; + } else { + if (b->name == NULL) + return 1; + else + return strcmp (a->name, b->name); + } +} + +static TotemPlParserResult +totem_pl_parser_add_directory (TotemPlParser *parser, const char *url, + gpointer data) +{ + MediaType type; + GList *list, *l; + GnomeVFSResult res; + + if (parser->priv->recurse_level == 1) { + char *media_url; + + type = totem_cd_detect_type_from_dir (url, &media_url, NULL); + if (type != MEDIA_TYPE_DATA && type != MEDIA_TYPE_ERROR) { + if (media_url != NULL) { + totem_pl_parser_add_one_url (parser, media_url, NULL); + g_free (media_url); + return TOTEM_PL_PARSER_RESULT_SUCCESS; + } + } + } + + res = gnome_vfs_directory_list_load (&list, url, + GNOME_VFS_FILE_INFO_DEFAULT); + if (res != GNOME_VFS_OK) + return TOTEM_PL_PARSER_RESULT_ERROR; + + list = g_list_sort (list, (GCompareFunc) totem_pl_parser_dir_compare); + l = list; + + while (l != NULL) { + char *name, *fullpath; + GnomeVFSFileInfo *info = l->data; + TotemPlParserResult ret; + + if (info->name != NULL && (strcmp (info->name, ".") == 0 + || strcmp (info->name, "..") == 0)) { + l = l->next; + continue; + } + + name = gnome_vfs_escape_string (info->name); + fullpath = g_strconcat (url, "/", name, NULL); + g_free (name); + + ret = totem_pl_parser_parse_internal (parser, fullpath); + if (ret != TOTEM_PL_PARSER_RESULT_SUCCESS && ret != TOTEM_PL_PARSER_RESULT_IGNORED) + totem_pl_parser_add_one_url (parser, fullpath, NULL); + + l = l->next; + } + + g_list_foreach (list, (GFunc) gnome_vfs_file_info_unref, NULL); + g_list_free (list); + + return TOTEM_PL_PARSER_RESULT_SUCCESS; +} + +/* These ones need a special treatment, mostly parser formats */ +static PlaylistTypes special_types[] = { + { "audio/x-mpegurl", totem_pl_parser_add_m3u }, + { "audio/playlist", totem_pl_parser_add_m3u }, + { "audio/x-ms-asx", totem_pl_parser_add_asx }, + { "audio/x-scpls", totem_pl_parser_add_pls }, + { "application/x-smil", totem_pl_parser_add_smil }, + { "application/x-gnome-app-info", totem_pl_parser_add_desktop }, + { "application/x-desktop", totem_pl_parser_add_desktop }, + { "x-directory/normal", totem_pl_parser_add_directory }, + { "video/x-ms-wvx", totem_pl_parser_add_asx }, + { "audio/x-ms-wax", totem_pl_parser_add_asx }, +}; + +static PlaylistTypes ignore_types[] = { + { "image/*", NULL }, + { "text/plain", NULL }, + { "application/x-rar", NULL }, + { "application/zip", NULL }, +}; + +/* These ones are "dual" types, might be a video, might be a parser */ +static PlaylistTypes dual_types[] = { + { "audio/x-real-audio", totem_pl_parser_add_ra }, + { "audio/x-pn-realaudio", totem_pl_parser_add_ra }, + { "application/vnd.rn-realmedia", totem_pl_parser_add_ra }, + { "audio/x-pn-realaudio-plugin", totem_pl_parser_add_ra }, + { "text/plain", totem_pl_parser_add_ra }, + { "video/x-ms-asf", totem_pl_parser_add_asf }, + { "video/x-ms-wmv", totem_pl_parser_add_asf }, +}; + +static gboolean +totem_pl_parser_scheme_is_ignored (TotemPlParser *parser, const char *url) +{ + GList *l; + + if (parser->priv->ignore_schemes == NULL) + return FALSE; + + for (l = parser->priv->ignore_schemes; l != NULL; l = l->next) + { + const char *scheme = l->data; + if (g_str_has_prefix (url, scheme) != FALSE) + return TRUE; + } + + return FALSE; +} + +static gboolean +totem_pl_parser_mimetype_is_ignored (TotemPlParser *parser, + const char *mimetype) +{ + GList *l; + + if (parser->priv->ignore_mimetypes == NULL) + return FALSE; + + for (l = parser->priv->ignore_mimetypes; l != NULL; l = l->next) + { + const char *item = l->data; + if (strcmp (mimetype, item) == 0) + return TRUE; + } + + return FALSE; + +} + +static gboolean +totem_pl_parser_ignore (TotemPlParser *parser, const char *url) +{ + const char *mimetype; + guint i; + + if (totem_pl_parser_scheme_is_ignored (parser, url) != FALSE) + return TRUE; + + mimetype = gnome_vfs_get_file_mime_type (url, NULL, TRUE); + if (mimetype == NULL || strcmp (mimetype, "application/octet-stream") == 0) + return FALSE; + + for (i = 0; i < G_N_ELEMENTS (special_types); i++) + if (strcmp (special_types[i].mimetype, mimetype) == 0) + return FALSE; + + for (i = 0; i < G_N_ELEMENTS (dual_types); i++) + if (strcmp (dual_types[i].mimetype, mimetype) == 0) + return FALSE; + + /* It's a remote file that could be an m3u file */ + if (strcmp (mimetype, "audio/x-mp3") == 0) + { + if (strstr (url, "m3u") != NULL) + return FALSE; + } + + return TRUE; +} + +static TotemPlParserResult +totem_pl_parser_parse_internal (TotemPlParser *parser, const char *url) +{ + const char *mimetype; + guint i; + gpointer data = NULL; + gboolean ret = FALSE; + char *super; + + if (parser->priv->recurse_level > RECURSE_LEVEL_MAX) + return TOTEM_PL_PARSER_RESULT_ERROR; + + mimetype = gnome_vfs_get_mime_type (url); + if (!mimetype) + mimetype = my_gnome_vfs_get_mime_type_with_data (url, &data); + + if (mimetype == NULL) + return TOTEM_PL_PARSER_RESULT_UNHANDLED; + + if (totem_pl_parser_mimetype_is_ignored (parser, mimetype) != FALSE) { + g_free (data); + return TOTEM_PL_PARSER_RESULT_IGNORED; + } + + super = gnome_vfs_get_supertype_from_mime_type (mimetype); + for (i = 0; i < G_N_ELEMENTS (ignore_types); i++) { + if (gnome_vfs_mime_type_is_supertype (ignore_types[i].mimetype) != FALSE) { + if (strcmp (super, ignore_types[i].mimetype) == 0) { + g_free (data); + g_free (super); + return TOTEM_PL_PARSER_RESULT_IGNORED; + } + } else { + GnomeVFSMimeEquivalence eq; + + eq = gnome_vfs_mime_type_get_equivalence (mimetype, ignore_types[i].mimetype); + if (eq == GNOME_VFS_MIME_PARENT || eq == GNOME_VFS_MIME_IDENTICAL) { + g_free (data); + return TOTEM_PL_PARSER_RESULT_IGNORED; + } + } + } + + parser->priv->recurse_level++; + + for (i = 0; i < G_N_ELEMENTS(special_types); i++) { + if (strcmp (special_types[i].mimetype, mimetype) == 0) { + ret = (* special_types[i].func) (parser, url, data); + g_free (data); + break; + } + } + + for (i = 0; i < G_N_ELEMENTS(dual_types); i++) { + if (strcmp (dual_types[i].mimetype, mimetype) == 0) { + if (data == NULL) { + mimetype = my_gnome_vfs_get_mime_type_with_data (url, &data); + } + ret = (* dual_types[i].func) (parser, url, data); + g_free (data); + break; + } + } + + parser->priv->recurse_level--; + + if (ret == FALSE && parser->priv->fallback) { + totem_pl_parser_add_one_url (parser, url, NULL); + return TOTEM_PL_PARSER_RESULT_SUCCESS; + } + + if (ret) + return TOTEM_PL_PARSER_RESULT_SUCCESS; + else + return TOTEM_PL_PARSER_RESULT_UNHANDLED; +} + +TotemPlParserResult +totem_pl_parser_parse (TotemPlParser *parser, const char *url, + gboolean fallback) +{ + g_return_val_if_fail (TOTEM_IS_PL_PARSER (parser), TOTEM_PL_PARSER_RESULT_UNHANDLED); + g_return_val_if_fail (url != NULL, TOTEM_PL_PARSER_RESULT_UNHANDLED); + + if (totem_pl_parser_scheme_is_ignored (parser, url) != FALSE) + return TOTEM_PL_PARSER_RESULT_UNHANDLED; + + g_return_val_if_fail (strstr (url, "://") != NULL, + TOTEM_PL_PARSER_RESULT_IGNORED); + + parser->priv->recurse_level = 0; + parser->priv->fallback = fallback; + return totem_pl_parser_parse_internal (parser, url); +} + +void +totem_pl_parser_add_ignored_scheme (TotemPlParser *parser, + const char *scheme) +{ + g_return_if_fail (TOTEM_IS_PL_PARSER (parser)); + + parser->priv->ignore_schemes = g_list_prepend + (parser->priv->ignore_schemes, g_strdup (scheme)); +} + +void +totem_pl_parser_add_ignored_mimetype (TotemPlParser *parser, + const char *mimetype) +{ + g_return_if_fail (TOTEM_IS_PL_PARSER (parser)); + + parser->priv->ignore_mimetypes = g_list_prepend + (parser->priv->ignore_mimetypes, g_strdup (mimetype)); +} + --- rhythmbox-0.9.2.orig/plparse/totem-pl-parser.h 1969-12-31 16:00:00.000000000 -0800 +++ rhythmbox-0.9.2.orig/plparse/totem-pl-parser.h 2005-12-04 17:17:11.000000000 -0800 @@ -0,0 +1,115 @@ +/* + arch-tag: Header for Rhythmbox playlist parser + + Copyright (C) 2002, 2003 Bastien Nocera + Copyright (C) 2003 Colin Walters + + The Gnome Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Gnome Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the Gnome Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Bastien Nocera + */ + +#ifndef TOTEM_PL_PARSER_H +#define TOTEM_PL_PARSER_H + +#include +#include + +#include "totem-pl-parser-builtins.h" + +G_BEGIN_DECLS + +#define TOTEM_TYPE_PL_PARSER (totem_pl_parser_get_type ()) +#define TOTEM_PL_PARSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TOTEM_TYPE_PL_PARSER, TotemPlParser)) +#define TOTEM_PL_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TOTEM_TYPE_PL_PARSER, TotemPlParserClass)) +#define TOTEM_IS_PL_PARSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TOTEM_TYPE_PL_PARSER)) +#define TOTEM_IS_PL_PARSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TOTEM_TYPE_PL_PARSER)) + +typedef enum +{ + TOTEM_PL_PARSER_RESULT_UNHANDLED, + TOTEM_PL_PARSER_RESULT_ERROR, + TOTEM_PL_PARSER_RESULT_SUCCESS, + TOTEM_PL_PARSER_RESULT_IGNORED +} TotemPlParserResult; + +typedef struct TotemPlParser TotemPlParser; +typedef struct TotemPlParserClass TotemPlParserClass; +typedef struct TotemPlParserPrivate TotemPlParserPrivate; + +struct TotemPlParser { + GObject parent; + TotemPlParserPrivate *priv; +}; + +struct TotemPlParserClass { + GObjectClass parent_class; + + /* signals */ + void (*entry) (TotemPlParser *parser, const char *uri, + const char *title, const char *genre); + void (*playlist_start) (TotemPlParser *parser, const char *title); + void (*playlist_end) (TotemPlParser *parser, const char *title); +}; + +typedef enum +{ + TOTEM_PL_PARSER_PLS, + TOTEM_PL_PARSER_M3U, + TOTEM_PL_PARSER_M3U_DOS, +} TotemPlParserType; + +typedef enum +{ + TOTEM_PL_PARSER_ERROR_VFS_OPEN, + TOTEM_PL_PARSER_ERROR_VFS_WRITE, +} TotemPlParserError; + +#define TOTEM_PL_PARSER_ERROR (totem_pl_parser_error_quark ()) + +GQuark totem_pl_parser_error_quark (void); + +typedef void (*TotemPlParserIterFunc) (GtkTreeModel *model, GtkTreeIter *iter, + char **uri, char **title, gpointer user_data); + +GType totem_pl_parser_get_type (void); + +gboolean totem_pl_parser_write (TotemPlParser *parser, GtkTreeModel *model, + TotemPlParserIterFunc func, + const char *output, TotemPlParserType type, + gpointer user_data, + GError **error); + +gboolean totem_pl_parser_write_with_title (TotemPlParser *parser, + GtkTreeModel *model, + TotemPlParserIterFunc func, + const char *output, + const char *title, + TotemPlParserType type, + gpointer user_data, + GError **error); + +void totem_pl_parser_add_ignored_scheme (TotemPlParser *parser, + const char *scheme); +void totem_pl_parser_add_ignored_mimetype (TotemPlParser *parser, + const char *mimetype); +TotemPlParserResult totem_pl_parser_parse (TotemPlParser *parser, const char *url, gboolean fallback); + +TotemPlParser *totem_pl_parser_new (void); + +G_END_DECLS + +#endif /* TOTEM_PL_PARSER_H */ --- rhythmbox-0.9.2.orig/plparse/totemplparser-marshal.list 1969-12-31 16:00:00.000000000 -0800 +++ rhythmbox-0.9.2.orig/plparse/totemplparser-marshal.list 2005-12-04 17:17:11.000000000 -0800 @@ -0,0 +1, @@ +VOID:STRING,STRING,STRING --- rhythmbox-0.9.2.orig/shell/Makefile.am 2005-12-04 15:26:01.000000000 -0800 +++ rhythmbox-0.9.2.orig/shell/Makefile.am 2005-12-04 17:17:11.000000000 -0800 @@ -76,6 +76,7 @@ rhythmbox_LDADD = \ librbshell.la \ + $(top_builddir)/plparse/libtotem-plparser.a \ $(top_builddir)/sources/libsources.la \ $(top_builddir)/sources/libsourcesimpl.la \ $(top_builddir)/rhythmdb/librhythmdb.la \ --- rhythmbox-0.9.2.orig/shell/rb-playlist-manager.c 2005-12-04 15:26:01.000000000 -0800 +++ rhythmbox-0.9.2.orig/shell/rb-playlist-manager.c 2005-12-04 17:17:11.000000000 -0800 @@ -36,7 +36,7 @@ #include "rb-sourcelist.h" #include "rb-sourcelist-model.h" #include "rb-query-creator.h" -#include "totem-pl-parser.h" +#include "plparse/totem-pl-parser.h" #include "rb-file-helpers.h" #include "rb-debug.h" --- rhythmbox-0.9.2.orig/shell/rb-shell-player.c 2005-12-04 15:26:01.000000000 -0800 +++ rhythmbox-0.9.2.orig/shell/rb-shell-player.c 2005-12-04 17:17:11.000000000 -0800 @@ -49,7 +49,7 @@ #include "rb-debug.h" #include "rb-player.h" #include "rb-header.h" -#include "totem-pl-parser.h" +#include "plparse/totem-pl-parser.h" #include "rb-metadata.h" #include "bacon-volume.h" #include "rb-remote.h" --- rhythmbox-0.9.2.orig/shell/rb-shell.c 2005-12-04 15:26:01.000000000 -0800 +++ rhythmbox-0.9.2.orig/shell/rb-shell.c 2005-12-04 17:17:11.000000000 -0800 @@ -67,7 +67,7 @@ #include "rb-shell-preferences.h" #include "rb-library-source.h" #include "rb-podcast-source.h" -#include "totem-pl-parser.h" +#include "plparse/totem-pl-parser.h" #ifdef WITH_DAAP_SUPPORT #include "rb-daap-source.h" #include "rb-daap-sharing.h" --- rhythmbox-0.9.2.orig/sources/Makefile.am 2005-12-04 15:26:01.000000000 -0800 +++ rhythmbox-0.9.2.orig/sources/Makefile.am 2005-12-04 17:18:01.000000000 -0800 @@ -36,6 +36,7 @@ -I$(top_srcdir)/widgets \ -I$(top_srcdir)/library \ -I$(top_srcdir)/player \ + -I$(top_srcdir)/plparse \ -I$(top_srcdir)/iradio \ -I$(top_srcdir)/podcast \ -I$(top_srcdir)/shell \ --- rhythmbox-0.9.2.orig/sources/rb-iradio-source.c 2005-12-04 15:26:01.000000000 -0800 +++ rhythmbox-0.9.2.orig/sources/rb-iradio-source.c 2005-12-04 17:17:11.000000000 -0800 @@ -36,7 +36,7 @@ #include "rb-property-view.h" #include "rb-util.h" #include "rb-file-helpers.h" -#include "totem-pl-parser.h" +#include "plparse/totem-pl-parser.h" #include "rb-preferences.h" #include "rb-dialog.h" #include "rb-station-properties-dialog.h" --- rhythmbox-0.9.2.orig/sources/rb-playlist-source.c 2005-12-04 15:26:01.000000000 -0800 +++ rhythmbox-0.9.2.orig/sources/rb-playlist-source.c 2005-12-04 17:17:11.000000000 -0800 @@ -25,11 +25,11 @@ #include #include #include -#include #include #include #include +#include "plparse/totem-pl-parser.h" #include "rb-stock-icons.h" #include "rb-entry-view.h" #include "rb-search-entry.h"