summaryrefslogtreecommitdiff
path: root/libgupnp-av
diff options
context:
space:
mode:
authorMark Ryan <mark.d.ryan@intel.com>2012-09-14 17:06:27 +0200
committerMark Ryan <mark.d.ryan@intel.com>2012-09-14 17:06:27 +0200
commita4715d2e8aa44865a0b11fd0ac27ae7049cf5170 (patch)
tree44ad3fdd902545b93cb2ada1b643016accc0d0bb /libgupnp-av
downloadGUPnP-AV-a4715d2e8aa44865a0b11fd0ac27ae7049cf5170.tar.gz
GUPnP-AV-a4715d2e8aa44865a0b11fd0ac27ae7049cf5170.tar.bz2
GUPnP-AV-a4715d2e8aa44865a0b11fd0ac27ae7049cf5170.zip
Diffstat (limited to 'libgupnp-av')
-rw-r--r--libgupnp-av/Makefile.am114
-rw-r--r--libgupnp-av/Makefile.in765
-rw-r--r--libgupnp-av/gupnp-av-error.c48
-rw-r--r--libgupnp-av/gupnp-av-error.h52
-rw-r--r--libgupnp-av/gupnp-av-marshal.c110
-rw-r--r--libgupnp-av/gupnp-av-marshal.h20
-rw-r--r--libgupnp-av/gupnp-av-marshal.list1
-rw-r--r--libgupnp-av/gupnp-av.h35
-rw-r--r--libgupnp-av/gupnp-didl-lite-container.c575
-rw-r--r--libgupnp-av/gupnp-didl-lite-container.h126
-rw-r--r--libgupnp-av/gupnp-didl-lite-contributor-private.h39
-rw-r--r--libgupnp-av/gupnp-didl-lite-contributor.c360
-rw-r--r--libgupnp-av/gupnp-didl-lite-contributor.h93
-rw-r--r--libgupnp-av/gupnp-didl-lite-descriptor-private.h39
-rw-r--r--libgupnp-av/gupnp-didl-lite-descriptor.c506
-rw-r--r--libgupnp-av/gupnp-didl-lite-descriptor.h112
-rw-r--r--libgupnp-av/gupnp-didl-lite-item.c168
-rw-r--r--libgupnp-av/gupnp-didl-lite-item.h78
-rw-r--r--libgupnp-av/gupnp-didl-lite-object-private.h40
-rw-r--r--libgupnp-av/gupnp-didl-lite-object.c1966
-rw-r--r--libgupnp-av/gupnp-didl-lite-object.h255
-rw-r--r--libgupnp-av/gupnp-didl-lite-parser.c334
-rw-r--r--libgupnp-av/gupnp-didl-lite-parser.h90
-rw-r--r--libgupnp-av/gupnp-didl-lite-resource-private.h38
-rw-r--r--libgupnp-av/gupnp-didl-lite-resource.c1419
-rw-r--r--libgupnp-av/gupnp-didl-lite-resource.h194
-rw-r--r--libgupnp-av/gupnp-didl-lite-writer.c640
-rw-r--r--libgupnp-av/gupnp-didl-lite-writer.h111
-rw-r--r--libgupnp-av/gupnp-dlna.c167
-rw-r--r--libgupnp-av/gupnp-dlna.h145
-rw-r--r--libgupnp-av/gupnp-last-change-parser.c252
-rw-r--r--libgupnp-av/gupnp-last-change-parser.h91
-rw-r--r--libgupnp-av/gupnp-protocol-info.c1029
-rw-r--r--libgupnp-av/gupnp-protocol-info.h149
-rw-r--r--libgupnp-av/gupnp-search-criteria-parser.c607
-rw-r--r--libgupnp-av/gupnp-search-criteria-parser.h140
-rw-r--r--libgupnp-av/gvalue-util.c153
-rw-r--r--libgupnp-av/gvalue-util.h32
-rw-r--r--libgupnp-av/xml-util.c236
-rw-r--r--libgupnp-av/xml-util.h83
40 files changed, 11412 insertions, 0 deletions
diff --git a/libgupnp-av/Makefile.am b/libgupnp-av/Makefile.am
new file mode 100644
index 0000000..40475ed
--- /dev/null
+++ b/libgupnp-av/Makefile.am
@@ -0,0 +1,114 @@
+# Version format current:revision:age
+# If the library source code has changed at all since the last update, then
+# increment revision (‘c:r:a’ becomes ‘c:r+1:a’).
+# If any interfaces have been added, removed, or changed since the last update,
+# increment current, and set revision to 0.
+# If any interfaces have been added since the last public release, then
+# increment age.
+# If any interfaces have been removed since the last public release, then set
+# age to 0.
+LTVERSION = 2:0:0
+
+AM_CFLAGS = $(LIBGUPNP_CFLAGS) -I$(top_srcdir)
+
+libgupnp_av_incdir = $(includedir)/gupnp-av-1.0/libgupnp-av
+
+lib_LTLIBRARIES = libgupnp-av-1.0.la
+
+libgupnp_av_inc_HEADERS = gupnp-didl-lite-object.h \
+ gupnp-didl-lite-item.h \
+ gupnp-didl-lite-container.h \
+ gupnp-didl-lite-parser.h \
+ gupnp-didl-lite-resource.h \
+ gupnp-didl-lite-descriptor.h \
+ gupnp-didl-lite-contributor.h \
+ gupnp-didl-lite-writer.h \
+ gupnp-protocol-info.h \
+ gupnp-search-criteria-parser.h \
+ gupnp-last-change-parser.h \
+ gupnp-dlna.h \
+ gupnp-av-error.h \
+ gupnp-av.h
+
+
+gupnp-av-marshal.c: gupnp-av-marshal.list
+ $(AM_V_GEN) \
+ $(GLIB_GENMARSHAL) --prefix=gupnp_av_marshal $(srcdir)/gupnp-av-marshal.list --header --body > gupnp-av-marshal.c
+
+gupnp-av-marshal.h: gupnp-av-marshal.list
+ $(AM_V_GEN) \
+ $(GLIB_GENMARSHAL) --prefix=gupnp_av_marshal $(srcdir)/gupnp-av-marshal.list --header > gupnp-av-marshal.h
+
+BUILT_SOURCES = gupnp-av-marshal.c gupnp-av-marshal.h
+
+libgupnp_av_1_0_la_LDFLAGS = -version-info $(LTVERSION) -no-undefined
+
+libgupnp_av_1_0_la_SOURCES = gupnp-didl-lite-object.c \
+ gupnp-didl-lite-object-private.h \
+ gupnp-didl-lite-item.c \
+ gupnp-didl-lite-container.c \
+ gupnp-didl-lite-parser.c \
+ gupnp-didl-lite-resource.c \
+ gupnp-didl-lite-resource-private.h \
+ gupnp-didl-lite-descriptor.c \
+ gupnp-didl-lite-descriptor-private.h \
+ gupnp-didl-lite-contributor.c \
+ gupnp-didl-lite-contributor-private.h \
+ gupnp-didl-lite-writer.c \
+ gupnp-protocol-info.c \
+ gupnp-search-criteria-parser.c \
+ gupnp-last-change-parser.c \
+ gupnp-dlna.c \
+ gupnp-av-error.c \
+ xml-util.c \
+ xml-util.h \
+ gvalue-util.c \
+ gvalue-util.h \
+ $(BUILT_SOURCES)
+
+libgupnp_av_1_0_la_LIBADD = $(LIBGUPNP_LIBS)
+
+EXTRA_DIST = gupnp-av-marshal.list
+
+-include $(INTROSPECTION_MAKEFILE)
+INTROSPECTION_GIRS =
+INTROSPECTION_SCANNER_ARGS = --warn-all --add-include-path=$(srcdir)
+INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
+
+if HAVE_INTROSPECTION
+introspection_sources = \
+ $(addprefix $(top_srcdir)/libgupnp-av/, \
+ $(libgupnp_av_inc_HEADERS)) \
+ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-object.c \
+ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-item.c \
+ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-container.c \
+ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-parser.c \
+ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-resource.c \
+ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-descriptor.c \
+ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-contributor.c \
+ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-writer.c \
+ $(top_srcdir)/libgupnp-av/gupnp-protocol-info.c \
+ $(top_srcdir)/libgupnp-av/gupnp-search-criteria-parser.c \
+ $(top_srcdir)/libgupnp-av/gupnp-last-change-parser.c \
+ $(top_srcdir)/libgupnp-av/gupnp-dlna.c \
+ $(top_srcdir)/libgupnp-av/gupnp-av-error.c
+
+GUPnPAV-1.0.gir: libgupnp-av-1.0.la
+GUPnPAV_1_0_gir_INCLUDES = GObject-2.0 GSSDP-1.0 Soup-2.4 libxml2-2.0 GUPnP-1.0
+GUPnPAV_1_0_gir_CFLAGS = $(AM_CFLAGS)
+GUPnPAV_1_0_gir_LIBS = libgupnp-av-1.0.la
+GUPnPAV_1_0_gir_SCANNERFLAGS = --identifier-prefix=GUPnP --symbol-prefix=gupnp --pkg-export=gupnp-av-1.0
+GUPnPAV_1_0_gir_FILES = $(introspection_sources)
+INTROSPECTION_GIRS += GUPnPAV-1.0.gir
+
+girdir = $(INTROSPECTION_GIRDIR)
+gir_DATA = $(INTROSPECTION_GIRS)
+
+typelibdir = $(INTROSPECTION_TYPELIBDIR)
+typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+endif
+
+CLEANFILES = $(BUILT_SOURCES) $(gir_DATA) $(typelib_DATA)
+DISTCLEANFILES = $(BUILT_SOURCES)
+MAINTAINERCLEANFILES = Makefile.in $(BUILT_SOURCES)
+
diff --git a/libgupnp-av/Makefile.in b/libgupnp-av/Makefile.in
new file mode 100644
index 0000000..4b8de7c
--- /dev/null
+++ b/libgupnp-av/Makefile.in
@@ -0,0 +1,765 @@
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+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 = :
+build_triplet = @build@
+host_triplet = @host@
+@HAVE_INTROSPECTION_TRUE@am__append_1 = GUPnPAV-1.0.gir
+subdir = libgupnp-av
+DIST_COMMON = $(libgupnp_av_inc_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \
+ $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \
+ "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(libgupnp_av_incdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgupnp_av_1_0_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__objects_1 = gupnp-av-marshal.lo
+am_libgupnp_av_1_0_la_OBJECTS = gupnp-didl-lite-object.lo \
+ gupnp-didl-lite-item.lo gupnp-didl-lite-container.lo \
+ gupnp-didl-lite-parser.lo gupnp-didl-lite-resource.lo \
+ gupnp-didl-lite-descriptor.lo gupnp-didl-lite-contributor.lo \
+ gupnp-didl-lite-writer.lo gupnp-protocol-info.lo \
+ gupnp-search-criteria-parser.lo gupnp-last-change-parser.lo \
+ gupnp-dlna.lo gupnp-av-error.lo xml-util.lo gvalue-util.lo \
+ $(am__objects_1)
+libgupnp_av_1_0_la_OBJECTS = $(am_libgupnp_av_1_0_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libgupnp_av_1_0_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libgupnp_av_1_0_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libgupnp_av_1_0_la_SOURCES)
+DIST_SOURCES = $(libgupnp_av_1_0_la_SOURCES)
+DATA = $(gir_DATA) $(typelib_DATA)
+HEADERS = $(libgupnp_av_inc_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBGUPNP_CFLAGS = @LIBGUPNP_CFLAGS@
+LIBGUPNP_LIBS = @LIBGUPNP_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# Version format current:revision:age
+# If the library source code has changed at all since the last update, then
+# increment revision (‘c:r:a’ becomes ‘c:r+1:a’).
+# If any interfaces have been added, removed, or changed since the last update,
+# increment current, and set revision to 0.
+# If any interfaces have been added since the last public release, then
+# increment age.
+# If any interfaces have been removed since the last public release, then set
+# age to 0.
+LTVERSION = 2:0:0
+AM_CFLAGS = $(LIBGUPNP_CFLAGS) -I$(top_srcdir)
+libgupnp_av_incdir = $(includedir)/gupnp-av-1.0/libgupnp-av
+lib_LTLIBRARIES = libgupnp-av-1.0.la
+libgupnp_av_inc_HEADERS = gupnp-didl-lite-object.h \
+ gupnp-didl-lite-item.h \
+ gupnp-didl-lite-container.h \
+ gupnp-didl-lite-parser.h \
+ gupnp-didl-lite-resource.h \
+ gupnp-didl-lite-descriptor.h \
+ gupnp-didl-lite-contributor.h \
+ gupnp-didl-lite-writer.h \
+ gupnp-protocol-info.h \
+ gupnp-search-criteria-parser.h \
+ gupnp-last-change-parser.h \
+ gupnp-dlna.h \
+ gupnp-av-error.h \
+ gupnp-av.h
+
+BUILT_SOURCES = gupnp-av-marshal.c gupnp-av-marshal.h
+libgupnp_av_1_0_la_LDFLAGS = -version-info $(LTVERSION) -no-undefined
+libgupnp_av_1_0_la_SOURCES = gupnp-didl-lite-object.c \
+ gupnp-didl-lite-object-private.h \
+ gupnp-didl-lite-item.c \
+ gupnp-didl-lite-container.c \
+ gupnp-didl-lite-parser.c \
+ gupnp-didl-lite-resource.c \
+ gupnp-didl-lite-resource-private.h \
+ gupnp-didl-lite-descriptor.c \
+ gupnp-didl-lite-descriptor-private.h \
+ gupnp-didl-lite-contributor.c \
+ gupnp-didl-lite-contributor-private.h \
+ gupnp-didl-lite-writer.c \
+ gupnp-protocol-info.c \
+ gupnp-search-criteria-parser.c \
+ gupnp-last-change-parser.c \
+ gupnp-dlna.c \
+ gupnp-av-error.c \
+ xml-util.c \
+ xml-util.h \
+ gvalue-util.c \
+ gvalue-util.h \
+ $(BUILT_SOURCES)
+
+libgupnp_av_1_0_la_LIBADD = $(LIBGUPNP_LIBS)
+EXTRA_DIST = gupnp-av-marshal.list
+INTROSPECTION_GIRS = $(am__append_1)
+INTROSPECTION_SCANNER_ARGS = --warn-all --add-include-path=$(srcdir)
+INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
+@HAVE_INTROSPECTION_TRUE@introspection_sources = \
+@HAVE_INTROSPECTION_TRUE@ $(addprefix $(top_srcdir)/libgupnp-av/, \
+@HAVE_INTROSPECTION_TRUE@ $(libgupnp_av_inc_HEADERS)) \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-object.c \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-item.c \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-container.c \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-parser.c \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-resource.c \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-descriptor.c \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-contributor.c \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-didl-lite-writer.c \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-protocol-info.c \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-search-criteria-parser.c \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-last-change-parser.c \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-dlna.c \
+@HAVE_INTROSPECTION_TRUE@ $(top_srcdir)/libgupnp-av/gupnp-av-error.c
+
+@HAVE_INTROSPECTION_TRUE@GUPnPAV_1_0_gir_INCLUDES = GObject-2.0 GSSDP-1.0 Soup-2.4 libxml2-2.0 GUPnP-1.0
+@HAVE_INTROSPECTION_TRUE@GUPnPAV_1_0_gir_CFLAGS = $(AM_CFLAGS)
+@HAVE_INTROSPECTION_TRUE@GUPnPAV_1_0_gir_LIBS = libgupnp-av-1.0.la
+@HAVE_INTROSPECTION_TRUE@GUPnPAV_1_0_gir_SCANNERFLAGS = --identifier-prefix=GUPnP --symbol-prefix=gupnp --pkg-export=gupnp-av-1.0
+@HAVE_INTROSPECTION_TRUE@GUPnPAV_1_0_gir_FILES = $(introspection_sources)
+@HAVE_INTROSPECTION_TRUE@girdir = $(INTROSPECTION_GIRDIR)
+@HAVE_INTROSPECTION_TRUE@gir_DATA = $(INTROSPECTION_GIRS)
+@HAVE_INTROSPECTION_TRUE@typelibdir = $(INTROSPECTION_TYPELIBDIR)
+@HAVE_INTROSPECTION_TRUE@typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+CLEANFILES = $(BUILT_SOURCES) $(gir_DATA) $(typelib_DATA)
+DISTCLEANFILES = $(BUILT_SOURCES)
+MAINTAINERCLEANFILES = Makefile.in $(BUILT_SOURCES)
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libgupnp-av/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu libgupnp-av/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgupnp-av-1.0.la: $(libgupnp_av_1_0_la_OBJECTS) $(libgupnp_av_1_0_la_DEPENDENCIES) $(EXTRA_libgupnp_av_1_0_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgupnp_av_1_0_la_LINK) -rpath $(libdir) $(libgupnp_av_1_0_la_OBJECTS) $(libgupnp_av_1_0_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-av-error.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-av-marshal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-didl-lite-container.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-didl-lite-contributor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-didl-lite-descriptor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-didl-lite-item.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-didl-lite-object.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-didl-lite-parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-didl-lite-resource.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-didl-lite-writer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-dlna.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-last-change-parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-protocol-info.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gupnp-search-criteria-parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gvalue-util.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml-util.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-girDATA: $(gir_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(girdir)" || $(MKDIR_P) "$(DESTDIR)$(girdir)"
+ @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \
+ done
+
+uninstall-girDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir)
+install-typelibDATA: $(typelib_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(typelibdir)" || $(MKDIR_P) "$(DESTDIR)$(typelibdir)"
+ @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibdir)" || exit $$?; \
+ done
+
+uninstall-typelibDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(typelibdir)'; $(am__uninstall_files_from_dir)
+install-libgupnp_av_incHEADERS: $(libgupnp_av_inc_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libgupnp_av_incdir)" || $(MKDIR_P) "$(DESTDIR)$(libgupnp_av_incdir)"
+ @list='$(libgupnp_av_inc_HEADERS)'; test -n "$(libgupnp_av_incdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libgupnp_av_incdir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgupnp_av_incdir)" || exit $$?; \
+ done
+
+uninstall-libgupnp_av_incHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libgupnp_av_inc_HEADERS)'; test -n "$(libgupnp_av_incdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(libgupnp_av_incdir)'; $(am__uninstall_files_from_dir)
+
+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; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ 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; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ 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; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$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 $(LTLIBRARIES) $(DATA) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(libgupnp_av_incdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+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:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+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)
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-girDATA install-libgupnp_av_incHEADERS \
+ install-typelibDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+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-girDATA uninstall-libLTLIBRARIES \
+ uninstall-libgupnp_av_incHEADERS uninstall-typelibDATA
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-girDATA \
+ install-html install-html-am install-info install-info-am \
+ install-libLTLIBRARIES install-libgupnp_av_incHEADERS \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip install-typelibDATA 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-girDATA \
+ uninstall-libLTLIBRARIES uninstall-libgupnp_av_incHEADERS \
+ uninstall-typelibDATA
+
+
+gupnp-av-marshal.c: gupnp-av-marshal.list
+ $(AM_V_GEN) \
+ $(GLIB_GENMARSHAL) --prefix=gupnp_av_marshal $(srcdir)/gupnp-av-marshal.list --header --body > gupnp-av-marshal.c
+
+gupnp-av-marshal.h: gupnp-av-marshal.list
+ $(AM_V_GEN) \
+ $(GLIB_GENMARSHAL) --prefix=gupnp_av_marshal $(srcdir)/gupnp-av-marshal.list --header > gupnp-av-marshal.h
+
+-include $(INTROSPECTION_MAKEFILE)
+
+@HAVE_INTROSPECTION_TRUE@GUPnPAV-1.0.gir: libgupnp-av-1.0.la
+
+# 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:
diff --git a/libgupnp-av/gupnp-av-error.c b/libgupnp-av/gupnp-av-error.c
new file mode 100644
index 0000000..d205997
--- /dev/null
+++ b/libgupnp-av/gupnp-av-error.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009, Nokia Corporation.
+ * Copyright (C) 2006, 2007 OpenedHand Ltd.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ * <zeeshan.ali@nokia.com>
+ * Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "gupnp-av-error.h"
+
+/**
+ * SECTION:gupnp-av-error
+ * @short_description: Error domains and codes.
+ */
+
+/**
+ * GUPNP_PROTOCOL_ERROR:
+ *
+ * The #GQuark uniquely used by GUPnP AV protocol related errors.
+ *
+ * Returns: a #GQuark uniquely used by GUPnP AV protocol related errors.
+ **/
+GQuark
+gupnp_protocol_error_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (!quark)
+ quark = g_quark_from_static_string ("gupnp-protocol-error");
+
+ return quark;
+}
diff --git a/libgupnp-av/gupnp-av-error.h b/libgupnp-av/gupnp-av-error.h
new file mode 100644
index 0000000..20b0477
--- /dev/null
+++ b/libgupnp-av/gupnp-av-error.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009, Nokia Corporation.
+ * Copyright (C) 2006, 2007 OpenedHand Ltd.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ * <zeeshan.ali@nokia.com>
+ * Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_AV_ERROR_H__
+#define __GUPNP_AV_ERROR_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+GQuark
+gupnp_protocol_error_quark (void) G_GNUC_CONST;
+
+#define GUPNP_PROTOCOL_ERROR (gupnp_protocol_error_quark ())
+
+/**
+ * GUPnPProtocolError:
+ * @GUPNP_PROTOCOL_ERROR_INVALID_SYNTAX: Invalid syntax.
+ * @GUPNP_PROTOCOL_ERROR_OTHER: Unknown/unhandled protocol related errors.
+ *
+ * #GError codes used for errors in the #GUPNP_PROTOCOL_ERROR domain, upon any
+ * protocol related errors.
+ */
+typedef enum {
+ GUPNP_PROTOCOL_ERROR_INVALID_SYNTAX,
+ GUPNP_PROTOCOL_ERROR_OTHER
+} GUPnPProtocolError;
+
+G_END_DECLS
+
+#endif /* __GUPNP_AV_ERROR_H__ */
diff --git a/libgupnp-av/gupnp-av-marshal.c b/libgupnp-av/gupnp-av-marshal.c
new file mode 100644
index 0000000..dcc0a24
--- /dev/null
+++ b/libgupnp-av/gupnp-av-marshal.c
@@ -0,0 +1,110 @@
+
+#ifndef __gupnp_av_marshal_MARSHAL_H__
+#define __gupnp_av_marshal_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_schar (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#define g_marshal_value_peek_variant(v) g_value_get_variant (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* BOOLEAN:STRING,UINT,STRING,POINTER (./gupnp-av-marshal.list:1) */
+extern void gupnp_av_marshal_BOOLEAN__STRING_UINT_STRING_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+void
+gupnp_av_marshal_BOOLEAN__STRING_UINT_STRING_POINTER (GClosure *closure,
+ GValue *return_value G_GNUC_UNUSED,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint G_GNUC_UNUSED,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__STRING_UINT_STRING_POINTER) (gpointer data1,
+ gpointer arg_1,
+ guint arg_2,
+ gpointer arg_3,
+ gpointer arg_4,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__STRING_UINT_STRING_POINTER callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 5);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__STRING_UINT_STRING_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ g_marshal_value_peek_string (param_values + 1),
+ g_marshal_value_peek_uint (param_values + 2),
+ g_marshal_value_peek_string (param_values + 3),
+ g_marshal_value_peek_pointer (param_values + 4),
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+G_END_DECLS
+
+#endif /* __gupnp_av_marshal_MARSHAL_H__ */
+
diff --git a/libgupnp-av/gupnp-av-marshal.h b/libgupnp-av/gupnp-av-marshal.h
new file mode 100644
index 0000000..fc9c825
--- /dev/null
+++ b/libgupnp-av/gupnp-av-marshal.h
@@ -0,0 +1,20 @@
+
+#ifndef __gupnp_av_marshal_MARSHAL_H__
+#define __gupnp_av_marshal_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* BOOLEAN:STRING,UINT,STRING,POINTER (./gupnp-av-marshal.list:1) */
+extern void gupnp_av_marshal_BOOLEAN__STRING_UINT_STRING_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+G_END_DECLS
+
+#endif /* __gupnp_av_marshal_MARSHAL_H__ */
+
diff --git a/libgupnp-av/gupnp-av-marshal.list b/libgupnp-av/gupnp-av-marshal.list
new file mode 100644
index 0000000..e66081d
--- /dev/null
+++ b/libgupnp-av/gupnp-av-marshal.list
@@ -0,0 +1 @@
+BOOLEAN:STRING,UINT,STRING,POINTER
diff --git a/libgupnp-av/gupnp-av.h b/libgupnp-av/gupnp-av.h
new file mode 100644
index 0000000..63ee485
--- /dev/null
+++ b/libgupnp-av/gupnp-av.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd.
+ *
+ * Author: Zeeshan Ali Khattak <zeenix@gstreamer.net>
+ * Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "gupnp-didl-lite-object.h"
+#include "gupnp-didl-lite-container.h"
+#include "gupnp-didl-lite-item.h"
+#include "gupnp-didl-lite-parser.h"
+#include "gupnp-didl-lite-resource.h"
+#include "gupnp-didl-lite-descriptor.h"
+#include "gupnp-didl-lite-writer.h"
+#include "gupnp-protocol-info.h"
+#include "gupnp-search-criteria-parser.h"
+#include "gupnp-last-change-parser.h"
+#include "gupnp-dlna.h"
+
diff --git a/libgupnp-av/gupnp-didl-lite-container.c b/libgupnp-av/gupnp-didl-lite-container.c
new file mode 100644
index 0000000..1a0abf4
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-container.c
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gupnp-didl-lite-container
+ * @short_description: DIDL-Lite Container
+ *
+ * #GUPnPDIDLLiteContainer respresents a DIDL-Lite container element.
+ */
+
+#include <string.h>
+
+#include "gupnp-didl-lite-container.h"
+#include "xml-util.h"
+
+G_DEFINE_TYPE (GUPnPDIDLLiteContainer,
+ gupnp_didl_lite_container,
+ GUPNP_TYPE_DIDL_LITE_OBJECT);
+
+enum {
+ PROP_0,
+ PROP_SEARCHABLE,
+ PROP_CHILD_COUNT,
+ PROP_STORAGE_USED
+};
+
+static void
+gupnp_didl_lite_container_init (GUPnPDIDLLiteContainer *container)
+{
+ /* Nothing to initialize, yay! */
+}
+
+static void
+gupnp_didl_lite_container_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPDIDLLiteContainer *container;
+
+ container = GUPNP_DIDL_LITE_CONTAINER (object);
+
+ switch (property_id) {
+ case PROP_SEARCHABLE:
+ g_value_set_boolean
+ (value,
+ gupnp_didl_lite_container_get_searchable (container));
+ break;
+ case PROP_CHILD_COUNT:
+ g_value_set_int
+ (value,
+ gupnp_didl_lite_container_get_child_count (container));
+ break;
+ case PROP_STORAGE_USED:
+ g_value_set_long
+ (value,
+ gupnp_didl_lite_container_get_storage_used (container));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_container_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+
+{
+ GUPnPDIDLLiteContainer *container;
+
+ container = GUPNP_DIDL_LITE_CONTAINER (object);
+
+ switch (property_id) {
+ case PROP_SEARCHABLE:
+ gupnp_didl_lite_container_set_searchable
+ (container,
+ g_value_get_boolean (value));
+ break;
+ case PROP_CHILD_COUNT:
+ gupnp_didl_lite_container_set_child_count
+ (container,
+ g_value_get_int (value));
+ break;
+ case PROP_STORAGE_USED:
+ gupnp_didl_lite_container_set_storage_used
+ (container,
+ g_value_get_int64 (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_container_class_init (GUPnPDIDLLiteContainerClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gupnp_didl_lite_container_get_property;
+ object_class->set_property = gupnp_didl_lite_container_set_property;
+
+ /**
+ * GUPnPDIDLLiteContainer:searchable:
+ *
+ * Whether this container is searchable.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_SEARCHABLE,
+ g_param_spec_boolean ("searchable",
+ "Searchable",
+ "Whether this container is searchable.",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteContainer:child-count:
+ *
+ * The child count of this container.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_CHILD_COUNT,
+ g_param_spec_int ("child-count",
+ "ChildCount",
+ "The child count of this container.",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteContainer:storage-used:
+ *
+ * The number of bytes used by all child items of this container.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_STORAGE_USED,
+ g_param_spec_int64 ("storage-used",
+ "Storage Used",
+ "The Number of bytes used by all child "
+ "items of this container.",
+ -1,
+ G_MAXINT64,
+ -1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+}
+
+/**
+ * gupnp_didl_lite_container_get_searchable:
+ * @container: #GUPnPDIDLLiteContainer
+ *
+ * Checks whether @container is searchable.
+ *
+ * Return value: #TRUE if @container is searchable.
+ **/
+gboolean
+gupnp_didl_lite_container_get_searchable (GUPnPDIDLLiteContainer *container)
+{
+ xmlNode *xml_node;
+
+ g_return_val_if_fail (container != NULL, FALSE);
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_CONTAINER (container), FALSE);
+
+ xml_node = gupnp_didl_lite_object_get_xml_node
+ (GUPNP_DIDL_LITE_OBJECT (container));
+
+ return xml_util_get_boolean_attribute (xml_node, "searchable");
+}
+
+/**
+ * gupnp_didl_lite_container_get_child_count:
+ * @container: #GUPnPDIDLLiteContainer
+ *
+ * Get the child count of the @container. If the child count is unknown, -1 is
+ * returned.
+ *
+ * Return value: The child count of the @container, or -1 if it is unknown.
+ **/
+gint
+gupnp_didl_lite_container_get_child_count (GUPnPDIDLLiteContainer *container)
+{
+ xmlNode *xml_node;
+
+ g_return_val_if_fail (container != NULL, 0);
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_CONTAINER (container), 0);
+
+ xml_node = gupnp_didl_lite_object_get_xml_node
+ (GUPNP_DIDL_LITE_OBJECT (container));
+
+ return xml_util_get_int_attribute (xml_node, "childCount", -1);
+}
+
+/**
+ * gupnp_didl_lite_container_get_create_classes:
+ * @container: #GUPnPDIDLLiteContainer
+ *
+ * Gets the list of create classes of the @object.
+ *
+ * Returns: (element-type utf8) (transfer full): The list of create classes
+ * belonging to @object, or %NULL.
+ * #g_list_free the returned list after usage and #g_free each string in it.
+ **/
+GList *
+gupnp_didl_lite_container_get_create_classes (GUPnPDIDLLiteContainer *container)
+{
+ GList *classes = NULL;
+ GList *ret = NULL;
+ GList *l;
+
+ g_return_val_if_fail (container != NULL, NULL);
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_CONTAINER (container), NULL);
+
+ classes = gupnp_didl_lite_object_get_properties (
+ GUPNP_DIDL_LITE_OBJECT (container),
+ "createClass");
+
+ for (l = classes; l; l = l->next) {
+ char *create_class;
+ xmlNode *node;
+
+ node = (xmlNode *) l->data;
+ if (node->children != NULL) {
+ create_class = g_strdup ((const char *) node->children->content);
+
+ ret = g_list_append (ret, create_class);
+ }
+ }
+
+ g_list_free (classes);
+
+ return ret;
+}
+
+/**
+ * gupnp_didl_lite_container_get_search_classes:
+ * @container: #GUPnPDIDLLiteContainer
+ *
+ * Gets the list of search classes of the @object.
+ *
+ * Return value: (element-type utf8) (transfer full): The list of search classes
+ * belonging to @object, or %NULL. #g_list_free the returned list after usage
+ * and #g_free each string in it.
+ **/
+GList *
+gupnp_didl_lite_container_get_search_classes (GUPnPDIDLLiteContainer *container)
+{
+ GList *classes = NULL;
+ GList *ret = NULL;
+ GList *l;
+
+ g_return_val_if_fail (container != NULL, NULL);
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_CONTAINER (container), NULL);
+
+ classes = gupnp_didl_lite_object_get_properties (
+ GUPNP_DIDL_LITE_OBJECT (container),
+ "searchClass");
+
+ for (l = classes; l; l = l->next) {
+ char *search_class;
+ xmlNode *node;
+
+ node = (xmlNode *) l->data;
+ if (node->children != NULL) {
+ search_class = g_strdup ((const char *) node->children->content);
+
+ ret = g_list_append (ret, search_class);
+ }
+ }
+
+ g_list_free (classes);
+
+ return ret;
+}
+
+/**
+ * gupnp_didl_lite_container_get_storage_used:
+ * @container: #GUPnPDIDLLiteContainer
+ *
+ * Get the number of bytes used by all child items of the @container.
+ * If storage used is unknown, -1 is returned.
+ *
+ * Return value: The number of bytes used by all children of the @container,
+ * or -1 if it is unknown.
+ **/
+gint64
+gupnp_didl_lite_container_get_storage_used (GUPnPDIDLLiteContainer *container)
+{
+ GList *storage = NULL;
+ xmlNode *xml_node;
+ const char *str;
+
+ g_return_val_if_fail (container != NULL, 0);
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_CONTAINER (container), 0);
+
+ storage = gupnp_didl_lite_object_get_properties (
+ GUPNP_DIDL_LITE_OBJECT (container),
+ "storageUsed");
+ if (storage == NULL)
+ return -1;
+
+ /* only return value from first node */
+ xml_node = (xmlNode *) storage->data;
+
+ g_list_free (storage);
+
+ str = (const char *) xml_node->content;
+
+ return g_ascii_strtoll (str, NULL, 10);
+}
+/**
+ * gupnp_didl_lite_container_set_searchable:
+ * @container: #GUPnPDIDLLiteContainer
+ * @searchable: The searchibility
+ *
+ * (Un)set the searchibility of @container.
+ **/
+void
+gupnp_didl_lite_container_set_searchable (GUPnPDIDLLiteContainer *container,
+ gboolean searchable)
+{
+ xmlNode *xml_node;
+ const char *str;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_CONTAINER (container));
+
+ xml_node = gupnp_didl_lite_object_get_xml_node
+ (GUPNP_DIDL_LITE_OBJECT (container));
+
+ if (searchable)
+ str = "1";
+ else
+ str = "0";
+ xmlSetProp (xml_node,
+ (unsigned char *) "searchable",
+ (unsigned char *) str);
+
+ g_object_notify (G_OBJECT (container), "searchable");
+}
+
+/**
+ * gupnp_didl_lite_container_set_child_count:
+ * @container: #GUPnPDIDLLiteContainer
+ * @child_count: The child count
+ *
+ * Set the child count of the @container.
+ **/
+void
+gupnp_didl_lite_container_set_child_count (GUPnPDIDLLiteContainer *container,
+ gint child_count)
+{
+ xmlNode *xml_node;
+ char *str;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_CONTAINER (container));
+
+ xml_node = gupnp_didl_lite_object_get_xml_node
+ (GUPNP_DIDL_LITE_OBJECT (container));
+
+ str = g_strdup_printf ("%d", child_count);
+ xmlSetProp (xml_node,
+ (unsigned char *) "childCount",
+ (unsigned char *) str);
+ g_free (str);
+
+ g_object_notify (G_OBJECT (container), "child-count");
+}
+
+/**
+ * gupnp_didl_lite_container_add_create_class:
+ * @container: #GUPnPDIDLLiteContainer
+ * @create_class: The createClass to add.
+ *
+ * Add a new create class to the @object. includeDerived defaults to "0".
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_container_add_create_class (
+ GUPnPDIDLLiteContainer *container,
+ const char *create_class)
+{
+ gupnp_didl_lite_container_add_create_class_full (container,
+ create_class,
+ FALSE);
+}
+
+/**
+ * gupnp_didl_lite_container_add_create_class_full:
+ * @container: #GUPnPDIDLLiteContainer
+ * @create_class: The createClass to add.
+ * @include_derived: Whether object with dervied classes may be created in
+ * this container or not.
+ *
+ * Add a new create class to the @object.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_container_add_create_class_full (
+ GUPnPDIDLLiteContainer *container,
+ const char *create_class,
+ gboolean include_derived)
+{
+ xmlNode *container_node, *new_node;
+ xmlNs *namespace;
+ const char *str;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_CONTAINER (container));
+
+ container_node = gupnp_didl_lite_object_get_xml_node
+ (GUPNP_DIDL_LITE_OBJECT (container));
+ namespace = gupnp_didl_lite_object_get_upnp_namespace
+ (GUPNP_DIDL_LITE_OBJECT (container));
+
+ new_node = xmlNewChild (container_node,
+ namespace,
+ (unsigned char *) "createClass",
+ (unsigned char *) create_class);
+ if (include_derived)
+ str = "1";
+ else
+ str = "0";
+
+ xmlSetProp (new_node,
+ (unsigned char *) "includeDerived",
+ (unsigned char *) str);
+}
+
+/**
+ * gupnp_didl_lite_container_add_search_class:
+ * @container: #GUPnPDIDLLiteContainer
+ * @search_class: The searchClass to add.
+ *
+ * Add a new search class to the @object.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_container_add_search_class (
+ GUPnPDIDLLiteContainer *container,
+ const char *search_class)
+{
+ gupnp_didl_lite_container_add_search_class_full (container,
+ search_class,
+ TRUE);
+}
+
+/**
+ * gupnp_didl_lite_container_add_search_class_full:
+ * @container: #GUPnPDIDLLiteContainer
+ * @search_class: The searchClass to add.
+ * @include_derived: includeDerived attribute of the DIDL
+ *
+ * Add a new search class to the @object.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_container_add_search_class_full (
+ GUPnPDIDLLiteContainer *container,
+ const char *search_class,
+ gboolean include_derived)
+{
+ xmlNode *xml_node;
+ xmlNode *new_xml_node;
+ xmlNs *namespace;
+ const char *str;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_CONTAINER (container));
+
+ xml_node = gupnp_didl_lite_object_get_xml_node
+ (GUPNP_DIDL_LITE_OBJECT (container));
+ namespace = gupnp_didl_lite_object_get_upnp_namespace
+ (GUPNP_DIDL_LITE_OBJECT (container));
+
+ new_xml_node = xmlNewChild (xml_node,
+ namespace,
+ (unsigned char *) "searchClass",
+ (unsigned char *) search_class);
+
+ if (include_derived)
+ str = "1";
+ else
+ str = "0";
+
+ xmlSetProp (new_xml_node,
+ (unsigned char*) "includeDerived",
+ (unsigned char*) str);
+}
+
+/**
+ * gupnp_didl_lite_container_set_storage_used:
+ * @container: #GUPnPDIDLLiteContainer
+ * @storage_used: The number of bytes used by all child items of the
+ * @container or -1 if unknown.
+ *
+ * Set the number of bytes used by all child items of the @container.
+ **/
+void
+gupnp_didl_lite_container_set_storage_used (
+ GUPnPDIDLLiteContainer *container,
+ gint64 storage_used)
+{
+ GList *storage = NULL;
+ xmlNode *xml_node;
+ xmlNs *namespace;
+ char *str;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_CONTAINER (container));
+
+ xml_node = gupnp_didl_lite_object_get_xml_node
+ (GUPNP_DIDL_LITE_OBJECT (container));
+
+ namespace = gupnp_didl_lite_object_get_upnp_namespace
+ (GUPNP_DIDL_LITE_OBJECT (container));
+
+ str = g_strdup_printf ("%"G_GINT64_FORMAT, storage_used);
+
+ storage = gupnp_didl_lite_object_get_properties (
+ GUPNP_DIDL_LITE_OBJECT (container),
+ "storageUsed");
+ if (storage == NULL)
+ xmlNewChild (xml_node,
+ namespace,
+ (unsigned char *) "storageUsed",
+ (unsigned char *) str);
+ else
+ xmlNodeSetContent ((xmlNode *) storage->data,
+ (unsigned char *) str);
+
+ g_free (str);
+
+ g_object_notify (G_OBJECT (container), "storage-used");
+}
diff --git a/libgupnp-av/gupnp-didl-lite-container.h b/libgupnp-av/gupnp-didl-lite-container.h
new file mode 100644
index 0000000..e1af1cd
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-container.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DIDL_LITE_CONTAINER_H__
+#define __GUPNP_DIDL_LITE_CONTAINER_H__
+
+#include <glib-object.h>
+#include "gupnp-didl-lite-object.h"
+
+G_BEGIN_DECLS
+
+GType
+gupnp_didl_lite_container_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_DIDL_LITE_CONTAINER \
+ (gupnp_didl_lite_container_get_type ())
+#define GUPNP_DIDL_LITE_CONTAINER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_CONTAINER, \
+ GUPnPDIDLLiteContainer))
+#define GUPNP_DIDL_LITE_CONTAINER_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_CONTAINER, \
+ GUPnPDIDLLiteContainerClass))
+#define GUPNP_IS_DIDL_LITE_CONTAINER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_CONTAINER))
+#define GUPNP_IS_DIDL_LITE_CONTAINER_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_CONTAINER))
+#define GUPNP_DIDL_LITE_CONTAINER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_DIDL_LITE_CONTAINER, \
+ GUPnPDIDLLiteContainerClass))
+
+typedef struct {
+ GUPnPDIDLLiteObject parent;
+} GUPnPDIDLLiteContainer;
+
+typedef struct {
+ GUPnPDIDLLiteObjectClass parent_class;
+
+ /* future padding */
+ void (* _gupnp_reserved1) (void);
+ void (* _gupnp_reserved2) (void);
+ void (* _gupnp_reserved3) (void);
+ void (* _gupnp_reserved4) (void);
+} GUPnPDIDLLiteContainerClass;
+
+gboolean
+gupnp_didl_lite_container_get_searchable
+ (GUPnPDIDLLiteContainer *container);
+
+gint
+gupnp_didl_lite_container_get_child_count
+ (GUPnPDIDLLiteContainer *container);
+
+GList *
+gupnp_didl_lite_container_get_create_classes
+ (GUPnPDIDLLiteContainer *container);
+
+GList *
+gupnp_didl_lite_container_get_search_classes
+ (GUPnPDIDLLiteContainer *container);
+
+void
+gupnp_didl_lite_container_set_searchable
+ (GUPnPDIDLLiteContainer *container,
+ gboolean searchable);
+
+void
+gupnp_didl_lite_container_set_child_count
+ (GUPnPDIDLLiteContainer *container,
+ gint child_count);
+
+void
+gupnp_didl_lite_container_add_create_class
+ (GUPnPDIDLLiteContainer *container,
+ const char *create_class);
+
+void
+gupnp_didl_lite_container_add_create_class_full
+ (GUPnPDIDLLiteContainer *container,
+ const char *create_class,
+ gboolean include_derived);
+
+void
+gupnp_didl_lite_container_add_search_class
+ (GUPnPDIDLLiteContainer *container,
+ const char *search_class);
+void
+gupnp_didl_lite_container_add_search_class_full
+ (GUPnPDIDLLiteContainer *container,
+ const char *search_class,
+ gboolean include_derived);
+
+gint64
+gupnp_didl_lite_container_get_storage_used
+ (GUPnPDIDLLiteContainer *container);
+
+void
+gupnp_didl_lite_container_set_storage_used
+ (GUPnPDIDLLiteContainer *container,
+ gint64 storage_used);
+G_END_DECLS
+
+#endif /* __GUPNP_DIDL_LITE_CONTAINER_H__ */
diff --git a/libgupnp-av/gupnp-didl-lite-contributor-private.h b/libgupnp-av/gupnp-didl-lite-contributor-private.h
new file mode 100644
index 0000000..0bb6451
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-contributor-private.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DIDL_LITE_CONTRIBUTOR_PRIVATE_H__
+#define __GUPNP_DIDL_LITE_CONTRIBUTOR_PRIVATE_H__
+
+#include <glib-object.h>
+#include <libxml/tree.h>
+
+#include "gupnp-didl-lite-contributor.h"
+
+G_BEGIN_DECLS
+
+GUPnPDIDLLiteContributor *
+gupnp_didl_lite_contributor_new_from_xml (xmlNode *xml_node,
+ GUPnPXMLDoc *xml_doc);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DIDL_LITE_CONTRIBUTOR_PRIVATE_H__ */
diff --git a/libgupnp-av/gupnp-didl-lite-contributor.c b/libgupnp-av/gupnp-didl-lite-contributor.c
new file mode 100644
index 0000000..11f453e
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-contributor.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gupnp-didl-lite-contributor
+ * @short_description: DIDL-Lite Contributor
+ *
+ * #GUPnPDIDLLiteContributor respresents a contributor (artist, author, actor,
+ * producer, director, producer and contributor) property in a DIDL-Lite object.
+ */
+
+#include <libgupnp/gupnp.h>
+
+#include "gupnp-didl-lite-contributor.h"
+#include "xml-util.h"
+
+G_DEFINE_TYPE (GUPnPDIDLLiteContributor,
+ gupnp_didl_lite_contributor,
+ G_TYPE_OBJECT);
+
+struct _GUPnPDIDLLiteContributorPrivate {
+ xmlNode *xml_node;
+ GUPnPXMLDoc *xml_doc;
+};
+
+enum {
+ PROP_0,
+ PROP_XML_NODE,
+ PROP_XML_DOC,
+ PROP_ROLE,
+ PROP_NAME
+};
+
+static void
+gupnp_didl_lite_contributor_init (GUPnPDIDLLiteContributor *contributor)
+{
+ contributor->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (contributor,
+ GUPNP_TYPE_DIDL_LITE_CONTRIBUTOR,
+ GUPnPDIDLLiteContributorPrivate);
+}
+
+static void
+gupnp_didl_lite_contributor_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPDIDLLiteContributor *contributor;
+
+ contributor = GUPNP_DIDL_LITE_CONTRIBUTOR (object);
+
+ switch (property_id) {
+ case PROP_XML_NODE:
+ g_value_set_pointer
+ (value,
+ gupnp_didl_lite_contributor_get_xml_node
+ (contributor));
+ break;
+ case PROP_ROLE:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_contributor_get_role (contributor));
+ break;
+ case PROP_NAME:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_contributor_get_name (contributor));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_contributor_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+
+{
+ GUPnPDIDLLiteContributor *contributor;
+
+ contributor = GUPNP_DIDL_LITE_CONTRIBUTOR (object);
+
+ switch (property_id) {
+ case PROP_XML_NODE:
+ contributor->priv->xml_node = g_value_get_pointer (value);
+ break;
+ case PROP_XML_DOC:
+ contributor->priv->xml_doc = g_value_dup_object (value);
+ break;
+ case PROP_ROLE:
+ gupnp_didl_lite_contributor_set_role
+ (contributor,
+ g_value_get_string (value));
+ break;
+ case PROP_NAME:
+ gupnp_didl_lite_contributor_set_name
+ (contributor,
+ g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_contributor_dispose (GObject *object)
+{
+ GObjectClass *object_class;
+ GUPnPDIDLLiteContributorPrivate *priv;
+
+ priv = GUPNP_DIDL_LITE_CONTRIBUTOR (object)->priv;
+
+ if (priv->xml_doc) {
+ g_object_unref (priv->xml_doc);
+ priv->xml_doc = NULL;
+ }
+
+ object_class = G_OBJECT_CLASS
+ (gupnp_didl_lite_contributor_parent_class);
+ object_class->dispose (object);
+}
+
+static void
+gupnp_didl_lite_contributor_class_init (GUPnPDIDLLiteContributorClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gupnp_didl_lite_contributor_get_property;
+ object_class->set_property = gupnp_didl_lite_contributor_set_property;
+ object_class->dispose = gupnp_didl_lite_contributor_dispose;
+
+ g_type_class_add_private (klass,
+ sizeof (GUPnPDIDLLiteContributorPrivate));
+
+ /**
+ * GUPnPDIDLLiteContributor:xml-node:
+ *
+ * The pointer to object node in XML document.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_XML_NODE,
+ g_param_spec_pointer ("xml-node",
+ "XMLNode",
+ "The pointer to contributor node in XML"
+ " document.",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteContributor:xml-doc:
+ *
+ * The reference to XML document containing this object.
+ *
+ * Internal property.
+ *
+ * Stability: Private
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_XML_DOC,
+ g_param_spec_object ("xml-doc",
+ "XMLDoc",
+ "The reference to XML document"
+ " containing this contributor.",
+ GUPNP_TYPE_XML_DOC,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteContributor:role:
+ *
+ * The role of this contributor.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_ROLE,
+ g_param_spec_string ("role",
+ "Role",
+ "The role of this contributor.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteContributor:name:
+ *
+ * The name of this contributor.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_NAME,
+ g_param_spec_string ("name",
+ "Name",
+ "The name of this contributor.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+}
+
+/**
+ * gupnp_didl_lite_contributor_get_role:
+ * @contributor: #GUPnPDIDLLiteContributor
+ *
+ * Get the role of the @contributor.
+ *
+ * Return value: The role of the @contributor, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_contributor_get_role (GUPnPDIDLLiteContributor *contributor)
+{
+ g_return_val_if_fail (contributor != NULL, NULL);
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_CONTRIBUTOR (contributor),
+ NULL);
+
+ return xml_util_get_attribute_content (contributor->priv->xml_node,
+ "role");
+}
+
+/**
+ * gupnp_didl_lite_contributor_get_name:
+ * @contributor: A #GUPnPDIDLLiteContributor
+ *
+ * Get the name of the @contributor.
+ *
+ * Return value: The name of the @contributor or %NULL.
+ **/
+const char *
+gupnp_didl_lite_contributor_get_name (GUPnPDIDLLiteContributor *contributor)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_CONTRIBUTOR (contributor),
+ NULL);
+
+ return (const char *) contributor->priv->xml_node->children->content;
+}
+
+/**
+ * gupnp_didl_lite_contributor_set_role:
+ * @contributor: #GUPnPDIDLLiteContributor
+ * @role: The role of the @contributor
+ *
+ * Set the role of the @contributor to @role.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_contributor_set_role (GUPnPDIDLLiteContributor *contributor,
+ const char *role)
+{
+ g_return_if_fail (contributor != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_CONTRIBUTOR (contributor));
+
+ xmlSetProp (contributor->priv->xml_node,
+ (unsigned char *) "role",
+ (unsigned char *) role);
+
+ g_object_notify (G_OBJECT (contributor), "role");
+}
+
+/**
+ * gupnp_didl_lite_contributor_set_name:
+ * @contributor: A #GUPnPDIDLLiteContributor
+ * @name: The name of the contributor
+ *
+ * Set the name of the @contributor to @name.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_contributor_set_name (GUPnPDIDLLiteContributor *contributor,
+ const char *name)
+{
+ xmlChar *escaped;
+
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_CONTRIBUTOR (contributor));
+ g_return_if_fail (name != NULL);
+
+ escaped = xmlEncodeSpecialChars (contributor->priv->xml_doc->doc,
+ (const unsigned char *) name);
+ xmlNodeSetContent (contributor->priv->xml_node, escaped);
+ xmlFree (escaped);
+
+ g_object_notify (G_OBJECT (contributor), "name");
+}
+
+/**
+ * gupnp_didl_lite_contributor_new_from_xml:
+ * @xml_node: The pointer to relevant node in XML document
+ * @xml_doc: The reference to containing XML document
+ *
+ * Creates a new #GUPnPDIDLLiteContributor for the @xml_node.
+ *
+ * Return value: A new #GUPnPDIDLLiteContributor object. Unref after usage.
+ **/
+GUPnPDIDLLiteContributor *
+gupnp_didl_lite_contributor_new_from_xml (xmlNode *xml_node,
+ GUPnPXMLDoc *xml_doc)
+{
+ GUPnPDIDLLiteContributor *contributor;
+
+ return g_object_new (GUPNP_TYPE_DIDL_LITE_CONTRIBUTOR,
+ "xml-node", xml_node,
+ "xml-doc", xml_doc,
+ NULL);
+
+ return contributor;
+}
+
+/**
+ * gupnp_didl_lite_contributor_get_xml_node:
+ * @contributor: The #GUPnPDIDLLiteContributor
+ *
+ * Get the pointer to relevant node in XML document.
+ *
+ * Returns: (transfer none): The pointer to relevant node in XML document.
+ **/
+xmlNode *
+gupnp_didl_lite_contributor_get_xml_node (GUPnPDIDLLiteContributor *contributor)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_CONTRIBUTOR (contributor),
+ NULL);
+
+ return contributor->priv->xml_node;
+}
diff --git a/libgupnp-av/gupnp-didl-lite-contributor.h b/libgupnp-av/gupnp-didl-lite-contributor.h
new file mode 100644
index 0000000..dbedae7
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-contributor.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DIDL_LITE_CONTRIBUTOR_H__
+#define __GUPNP_DIDL_LITE_CONTRIBUTOR_H__
+
+#include <glib-object.h>
+#include <libxml/tree.h>
+
+G_BEGIN_DECLS
+
+GType
+gupnp_didl_lite_contributor_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_DIDL_LITE_CONTRIBUTOR \
+ (gupnp_didl_lite_contributor_get_type ())
+#define GUPNP_DIDL_LITE_CONTRIBUTOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_CONTRIBUTOR, \
+ GUPnPDIDLLiteContributor))
+#define GUPNP_DIDL_LITE_CONTRIBUTOR_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_CONTRIBUTOR, \
+ GUPnPDIDLLiteContributorClass))
+#define GUPNP_IS_DIDL_LITE_CONTRIBUTOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_CONTRIBUTOR))
+#define GUPNP_IS_DIDL_LITE_CONTRIBUTOR_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_CONTRIBUTOR))
+#define GUPNP_DIDL_LITE_CONTRIBUTOR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_DIDL_LITE_CONTRIBUTOR, \
+ GUPnPDIDLLiteContributorClass))
+
+typedef struct _GUPnPDIDLLiteContributorPrivate GUPnPDIDLLiteContributorPrivate;
+
+typedef struct {
+ GObject parent;
+
+ GUPnPDIDLLiteContributorPrivate *priv;
+} GUPnPDIDLLiteContributor;
+
+typedef struct {
+ GObjectClass parent_class;
+
+ /* future padding */
+ void (* _gupnp_reserved1) (void);
+ void (* _gupnp_reserved2) (void);
+ void (* _gupnp_reserved3) (void);
+ void (* _gupnp_reserved4) (void);
+} GUPnPDIDLLiteContributorClass;
+
+const char *
+gupnp_didl_lite_contributor_get_role (GUPnPDIDLLiteContributor *contributor);
+
+const char *
+gupnp_didl_lite_contributor_get_name (GUPnPDIDLLiteContributor *contributor);
+
+void
+gupnp_didl_lite_contributor_set_role (GUPnPDIDLLiteContributor *contributor,
+ const char *role);
+
+void
+gupnp_didl_lite_contributor_set_name (GUPnPDIDLLiteContributor *contributor,
+ const char *name);
+
+xmlNode *
+gupnp_didl_lite_contributor_get_xml_node
+ (GUPnPDIDLLiteContributor *contributor);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DIDL_LITE_CONTRIBUTOR_H__ */
diff --git a/libgupnp-av/gupnp-didl-lite-descriptor-private.h b/libgupnp-av/gupnp-didl-lite-descriptor-private.h
new file mode 100644
index 0000000..1ed983c
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-descriptor-private.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DIDL_LITE_DESCRIPTOR_PRIVATE_H__
+#define __GUPNP_DIDL_LITE_DESCRIPTOR_PRIVATE_H__
+
+#include <stdarg.h>
+#include <glib-object.h>
+#include <libxml/tree.h>
+#include <libgupnp/gupnp.h>
+
+G_BEGIN_DECLS
+
+GUPnPDIDLLiteDescriptor *
+gupnp_didl_lite_descriptor_new_from_xml (xmlNode *xml_node,
+ GUPnPXMLDoc *xml_doc);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DIDL_LITE_DESCRIPTOR_PRIVATE_H__ */
diff --git a/libgupnp-av/gupnp-didl-lite-descriptor.c b/libgupnp-av/gupnp-didl-lite-descriptor.c
new file mode 100644
index 0000000..c9b4581
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-descriptor.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gupnp-didl-lite-descriptor
+ * @short_description: DIDL-Lite Descriptor
+ *
+ * #GUPnPDIDLLiteDescriptor respresent a DIDL-Lite descriptor (desc) element.
+ */
+
+#include <string.h>
+
+#include "gupnp-didl-lite-descriptor.h"
+#include "xml-util.h"
+
+G_DEFINE_TYPE (GUPnPDIDLLiteDescriptor,
+ gupnp_didl_lite_descriptor,
+ G_TYPE_OBJECT);
+
+struct _GUPnPDIDLLiteDescriptorPrivate {
+ xmlNode *xml_node;
+ GUPnPXMLDoc *xml_doc;
+};
+
+enum {
+ PROP_0,
+ PROP_XML_NODE,
+ PROP_XML_DOC,
+
+ PROP_ID,
+ PROP_METADATA_TYPE,
+ PROP_NAME_SPACE,
+ PROP_CONTENT
+};
+
+static void
+gupnp_didl_lite_descriptor_init (GUPnPDIDLLiteDescriptor *descriptor)
+{
+ descriptor->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (descriptor,
+ GUPNP_TYPE_DIDL_LITE_DESCRIPTOR,
+ GUPnPDIDLLiteDescriptorPrivate);
+}
+
+static void
+gupnp_didl_lite_descriptor_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPDIDLLiteDescriptor *descriptor;
+
+ descriptor = GUPNP_DIDL_LITE_DESCRIPTOR (object);
+
+ switch (property_id) {
+ case PROP_XML_NODE:
+ descriptor->priv->xml_node = g_value_get_pointer (value);
+ break;
+ case PROP_XML_DOC:
+ descriptor->priv->xml_doc = g_value_dup_object (value);
+ break;
+ case PROP_ID:
+ gupnp_didl_lite_descriptor_set_id
+ (descriptor,
+ g_value_get_string (value));
+ break;
+ case PROP_METADATA_TYPE:
+ gupnp_didl_lite_descriptor_set_metadata_type
+ (descriptor,
+ g_value_get_string (value));
+ break;
+ case PROP_NAME_SPACE:
+ gupnp_didl_lite_descriptor_set_name_space
+ (descriptor,
+ g_value_get_string (value));
+ break;
+ case PROP_CONTENT:
+ gupnp_didl_lite_descriptor_set_content
+ (descriptor,
+ g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_descriptor_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPDIDLLiteDescriptor *descriptor;
+
+ descriptor = GUPNP_DIDL_LITE_DESCRIPTOR (object);
+
+ switch (property_id) {
+ case PROP_XML_NODE:
+ g_value_set_pointer
+ (value,
+ gupnp_didl_lite_descriptor_get_xml_node (descriptor));
+ break;
+ case PROP_ID:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_descriptor_get_id (descriptor));
+ break;
+ case PROP_METADATA_TYPE:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_descriptor_get_metadata_type
+ (descriptor));
+ break;
+ case PROP_NAME_SPACE:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_descriptor_get_name_space
+ (descriptor));
+ break;
+ case PROP_CONTENT:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_descriptor_get_content (descriptor));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_descriptor_dispose (GObject *object)
+{
+ GObjectClass *object_class;
+ GUPnPDIDLLiteDescriptorPrivate *priv;
+
+ priv = GUPNP_DIDL_LITE_DESCRIPTOR (object)->priv;
+
+ if (priv->xml_doc) {
+ g_object_unref (priv->xml_doc);
+ priv->xml_doc = NULL;
+ }
+
+ object_class = G_OBJECT_CLASS (gupnp_didl_lite_descriptor_parent_class);
+ object_class->dispose (object);
+}
+
+static void
+gupnp_didl_lite_descriptor_class_init (GUPnPDIDLLiteDescriptorClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = gupnp_didl_lite_descriptor_set_property;
+ object_class->get_property = gupnp_didl_lite_descriptor_get_property;
+ object_class->dispose = gupnp_didl_lite_descriptor_dispose;
+
+ g_type_class_add_private (klass,
+ sizeof (GUPnPDIDLLiteDescriptorPrivate));
+
+ /**
+ * GUPnPDIDLLiteDescriptor:xml-node:
+ *
+ * The pointer to desc node in XML document.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_XML_NODE,
+ g_param_spec_pointer ("xml-node",
+ "XMLNode",
+ "The pointer to desc node in XML"
+ " document.",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteDescriptor:xml-doc:
+ *
+ * The reference to XML document containing this object.
+ *
+ * Internal property.
+ *
+ * Stability: Private
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_XML_DOC,
+ g_param_spec_object ("xml-doc",
+ "XMLDoc",
+ "The reference to XML document"
+ " containing this object.",
+ GUPNP_TYPE_XML_DOC,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteDescriptor:name-space:
+ *
+ * The name space associated with this descriptor.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_NAME_SPACE,
+ g_param_spec_string ("name-space",
+ "NameSpace",
+ "The name space associated with this"
+ " descriptor",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteDescriptor:id:
+ *
+ * The ID of this descriptor.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_ID,
+ g_param_spec_string ("id",
+ "ID",
+ "The ID of this descriptor",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteDescriptor:metadata-type:
+ *
+ * The type of this descriptor.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_METADATA_TYPE,
+ g_param_spec_string ("metadata-type",
+ "MetadataType",
+ "The metadata type of this descriptor",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteDescriptor:content:
+ *
+ * The content of this descriptor.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_CONTENT,
+ g_param_spec_string ("content",
+ "Content",
+ "The content of this descriptor",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+}
+
+/**
+ * gupnp_didl_lite_descriptor_new:
+ *
+ * Return value: A new #GUPnPDIDLLiteDescriptor object. Unref after usage.
+ **/
+GUPnPDIDLLiteDescriptor *
+gupnp_didl_lite_descriptor_new (void)
+{
+ return g_object_new (GUPNP_TYPE_DIDL_LITE_DESCRIPTOR,
+ NULL);
+}
+
+/**
+ * gupnp_didl_lite_descriptor_new_from_xml:
+ * @xml_node: The pointer to 'desc' node in XML document
+ * @xml_doc: The reference to XML document containing this descriptor
+ *
+ * Creates a new #GUPnPDIDLLiteDescriptor for the @xml_node.
+ *
+ * Return value: A new #GUPnPDIDLLiteDescriptor object. Unref after usage.
+ **/
+GUPnPDIDLLiteDescriptor *
+gupnp_didl_lite_descriptor_new_from_xml (xmlNode *xml_node,
+ GUPnPXMLDoc *xml_doc)
+{
+ GUPnPDIDLLiteDescriptor *descriptor;
+
+ return g_object_new (GUPNP_TYPE_DIDL_LITE_DESCRIPTOR,
+ "xml-node", xml_node,
+ "xml-doc", xml_doc,
+ NULL);
+
+ return descriptor;
+}
+
+/**
+ * gupnp_didl_lite_descriptor_get_xml_node:
+ * @descriptor: The #GUPnPDIDLLiteDescriptor
+ *
+ * Get the pointer to desc node in XML document.
+ *
+ * Returns: (transfer none): The pointer to desc node in XML document.
+ **/
+xmlNode *
+gupnp_didl_lite_descriptor_get_xml_node (GUPnPDIDLLiteDescriptor *descriptor)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_DESCRIPTOR (descriptor), NULL);
+
+ return descriptor->priv->xml_node;
+}
+
+/**
+ * gupnp_didl_lite_descriptor_get_content:
+ * @descriptor: A #GUPnPDIDLLiteDescriptor
+ *
+ * Get the content of the @descriptor.
+ *
+ * Return value: The content of the @descriptor or %NULL.
+ **/
+const char *
+gupnp_didl_lite_descriptor_get_content (GUPnPDIDLLiteDescriptor *descriptor)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_DESCRIPTOR (descriptor), NULL);
+
+ return (const char *) descriptor->priv->xml_node->children;
+}
+
+/**
+ * gupnp_didl_lite_descriptor_get_id:
+ * @descriptor: A #GUPnPDIDLLiteDescriptor
+ *
+ * Get the ID of the @descriptor.
+ *
+ * Return value: The ID string or %NULL.
+ **/
+const char *
+gupnp_didl_lite_descriptor_get_id (GUPnPDIDLLiteDescriptor *descriptor)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_DESCRIPTOR (descriptor), NULL);
+
+ return xml_util_get_attribute_content (descriptor->priv->xml_node,
+ "id");
+}
+
+/**
+ * gupnp_didl_lite_descriptor_get_metadata_type:
+ * @descriptor: A #GUPnPDIDLLiteDescriptor
+ *
+ * Get the metadata type of the @descriptor.
+ *
+ * Return value: The type as string or %NULL.
+ **/
+const char *
+gupnp_didl_lite_descriptor_get_metadata_type
+ (GUPnPDIDLLiteDescriptor *descriptor)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_DESCRIPTOR (descriptor), NULL);
+
+ return xml_util_get_attribute_content (descriptor->priv->xml_node,
+ "type");
+}
+
+/**
+ * gupnp_didl_lite_descriptor_get_name_space:
+ * @descriptor: A #GUPnPDIDLLiteDescriptor
+ *
+ * Get the name space associated with the @descriptor.
+ *
+ * Return value: The name space or %NULL.
+ **/
+const char *
+gupnp_didl_lite_descriptor_get_name_space (GUPnPDIDLLiteDescriptor *descriptor)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_DESCRIPTOR (descriptor), NULL);
+
+ return xml_util_get_attribute_content (descriptor->priv->xml_node,
+ "nameSpace");
+}
+
+/**
+ * gupnp_didl_lite_descriptor_set_content:
+ * @descriptor: A #GUPnPDIDLLiteDescriptor
+ * @content: The content as string
+ *
+ * Set the content of the @descriptor.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_descriptor_set_content (GUPnPDIDLLiteDescriptor *descriptor,
+ const char *content)
+{
+ xmlChar *escaped;
+
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_DESCRIPTOR (descriptor));
+ g_return_if_fail (content != NULL);
+
+ escaped = xmlEncodeSpecialChars (descriptor->priv->xml_doc->doc,
+ (const unsigned char *) content);
+ xmlNodeSetContent (descriptor->priv->xml_node, escaped);
+ xmlFree (escaped);
+
+ g_object_notify (G_OBJECT (descriptor), "content");
+}
+
+/**
+ * gupnp_didl_lite_descriptor_set_id:
+ * @descriptor: A #GUPnPDIDLLiteDescriptor
+ * @id: The ID as string
+ *
+ * Set the ID of the @descriptor.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_descriptor_set_id (GUPnPDIDLLiteDescriptor *descriptor,
+ const char *id)
+{
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_DESCRIPTOR (descriptor));
+ g_return_if_fail (id != NULL);
+
+ xmlSetProp (descriptor->priv->xml_node,
+ (unsigned char *) "id",
+ (const unsigned char *) id);
+
+ g_object_notify (G_OBJECT (descriptor), "id");
+}
+
+/**
+ * gupnp_didl_lite_descriptor_set_metadata_type:
+ * @descriptor: A #GUPnPDIDLLiteDescriptor
+ * @type: The metadata type as string
+ *
+ * Set the metadata type of the @descriptor.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_descriptor_set_metadata_type
+ (GUPnPDIDLLiteDescriptor *descriptor,
+ const char *type)
+{
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_DESCRIPTOR (descriptor));
+ g_return_if_fail (type != NULL);
+
+ xmlSetProp (descriptor->priv->xml_node,
+ (unsigned char *) "type",
+ (const unsigned char *) type);
+
+ g_object_notify (G_OBJECT (descriptor), "metadata-type");
+}
+
+/**
+ * gupnp_didl_lite_descriptor_set_name_space:
+ * @descriptor: A #GUPnPDIDLLiteDescriptor
+ * @name_space: The name space URI as string
+ *
+ * Set the name space associated with the @descriptor.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_descriptor_set_name_space (GUPnPDIDLLiteDescriptor *descriptor,
+ const char *name_space)
+{
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_DESCRIPTOR (descriptor));
+ g_return_if_fail (name_space != NULL);
+
+ xmlSetProp (descriptor->priv->xml_node,
+ (unsigned char *) "nameSpace",
+ (const unsigned char *) name_space);
+
+ g_object_notify (G_OBJECT (descriptor), "name-space");
+}
diff --git a/libgupnp-av/gupnp-didl-lite-descriptor.h b/libgupnp-av/gupnp-didl-lite-descriptor.h
new file mode 100644
index 0000000..2b685d6
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-descriptor.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DIDL_LITE_DESCRIPTOR_H__
+#define __GUPNP_DIDL_LITE_DESCRIPTOR_H__
+
+#include <stdarg.h>
+#include <glib-object.h>
+#include <libxml/tree.h>
+#include <libgupnp/gupnp.h>
+
+G_BEGIN_DECLS
+
+GType
+gupnp_didl_lite_descriptor_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_DIDL_LITE_DESCRIPTOR \
+ (gupnp_didl_lite_descriptor_get_type ())
+#define GUPNP_DIDL_LITE_DESCRIPTOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_DESCRIPTOR, \
+ GUPnPDIDLLiteDescriptor))
+#define GUPNP_DIDL_LITE_DESCRIPTOR_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_DESCRIPTOR, \
+ GUPnPDIDLLiteDescriptorClass))
+#define GUPNP_IS_DIDL_LITE_DESCRIPTOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_DESCRIPTOR))
+#define GUPNP_IS_DIDL_LITE_DESCRIPTOR_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_DESCRIPTOR))
+#define GUPNP_DIDL_LITE_DESCRIPTOR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_DIDL_LITE_DESCRIPTOR, \
+ GUPnPDIDLLiteDescriptorClass))
+
+typedef struct _GUPnPDIDLLiteDescriptorPrivate GUPnPDIDLLiteDescriptorPrivate;
+
+typedef struct {
+ GObject parent;
+
+ GUPnPDIDLLiteDescriptorPrivate *priv;
+} GUPnPDIDLLiteDescriptor;
+
+typedef struct {
+ GObjectClass parent_class;
+
+ /* future padding */
+ void (* _gupnp_reserved1) (void);
+ void (* _gupnp_reserved2) (void);
+ void (* _gupnp_reserved3) (void);
+ void (* _gupnp_reserved4) (void);
+} GUPnPDIDLLiteDescriptorClass;
+
+xmlNode *
+gupnp_didl_lite_descriptor_get_xml_node (GUPnPDIDLLiteDescriptor *descriptor);
+
+const char *
+gupnp_didl_lite_descriptor_get_content (GUPnPDIDLLiteDescriptor *descriptor);
+
+const char *
+gupnp_didl_lite_descriptor_get_id (GUPnPDIDLLiteDescriptor *descriptor);
+
+const char *
+gupnp_didl_lite_descriptor_get_metadata_type
+ (GUPnPDIDLLiteDescriptor *descriptor);
+
+const char *
+gupnp_didl_lite_descriptor_get_name_space
+ (GUPnPDIDLLiteDescriptor *descriptor);
+
+void
+gupnp_didl_lite_descriptor_set_content (GUPnPDIDLLiteDescriptor *descriptor,
+ const char *content);
+
+void
+gupnp_didl_lite_descriptor_set_id (GUPnPDIDLLiteDescriptor *descriptor,
+ const char *id);
+
+void
+gupnp_didl_lite_descriptor_set_metadata_type
+ (GUPnPDIDLLiteDescriptor *descriptor,
+ const char *type);
+
+void
+gupnp_didl_lite_descriptor_set_name_space
+ (GUPnPDIDLLiteDescriptor *descriptor,
+ const char *name_space);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DIDL_LITE_DESCRIPTOR_H__ */
diff --git a/libgupnp-av/gupnp-didl-lite-item.c b/libgupnp-av/gupnp-didl-lite-item.c
new file mode 100644
index 0000000..9e5d34c
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-item.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gupnp-didl-lite-item
+ * @short_description: DIDL-Lite Item
+ *
+ * #GUPnPDIDLLiteItem respresents a DIDL-Lite item element.
+ */
+
+#include <string.h>
+
+#include "gupnp-didl-lite-item.h"
+#include "xml-util.h"
+
+G_DEFINE_TYPE (GUPnPDIDLLiteItem,
+ gupnp_didl_lite_item,
+ GUPNP_TYPE_DIDL_LITE_OBJECT);
+
+enum {
+ PROP_0,
+ PROP_REF_ID
+};
+
+static void
+gupnp_didl_lite_item_init (GUPnPDIDLLiteItem *item)
+{
+ /* Nothing to initialize, yay! */
+}
+
+static void
+gupnp_didl_lite_item_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPDIDLLiteItem *item;
+
+ item = GUPNP_DIDL_LITE_ITEM (object);
+
+ switch (property_id) {
+ case PROP_REF_ID:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_item_get_ref_id (item));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_item_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+
+{
+ GUPnPDIDLLiteItem *item;
+
+ item = GUPNP_DIDL_LITE_ITEM (object);
+
+ switch (property_id) {
+ case PROP_REF_ID:
+ gupnp_didl_lite_item_set_ref_id (item,
+ g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_item_class_init (GUPnPDIDLLiteItemClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gupnp_didl_lite_item_get_property;
+ object_class->set_property = gupnp_didl_lite_item_set_property;
+
+ /**
+ * GUPnPDIDLLiteItem:ref-id:
+ *
+ * The ref ID of this item.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_REF_ID,
+ g_param_spec_string ("ref-id",
+ "RefID",
+ "The ref ID of this item.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+}
+
+/**
+ * gupnp_didl_lite_item_get_ref_id:
+ * @item: #GUPnPDIDLLiteItem
+ *
+ * Get the ref ID of the @item.
+ *
+ * Return value: The ref ID of the @item, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_item_get_ref_id (GUPnPDIDLLiteItem *item)
+{
+ xmlNode *xml_node;
+
+ g_return_val_if_fail (item != NULL, 0);
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_ITEM (item), NULL);
+
+ xml_node = gupnp_didl_lite_object_get_xml_node
+ (GUPNP_DIDL_LITE_OBJECT (item));
+
+ return xml_util_get_attribute_content (xml_node, "refID");
+}
+
+/**
+ * gupnp_didl_lite_item_set_ref_id:
+ * @item: #GUPnPDIDLLiteItem
+ * @ref_id: The ref ID
+ *
+ * Set the ref ID of the @item.
+ **/
+void
+gupnp_didl_lite_item_set_ref_id (GUPnPDIDLLiteItem *item,
+ const char *ref_id)
+{
+ xmlNode *xml_node;
+
+ g_return_if_fail (item != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_ITEM (item));
+
+ xml_node = gupnp_didl_lite_object_get_xml_node
+ (GUPNP_DIDL_LITE_OBJECT (item));
+
+ xmlSetProp (xml_node,
+ (unsigned char *) "refID",
+ (unsigned char *) ref_id);
+
+ g_object_notify (G_OBJECT (item), "ref-id");
+}
diff --git a/libgupnp-av/gupnp-didl-lite-item.h b/libgupnp-av/gupnp-didl-lite-item.h
new file mode 100644
index 0000000..1719729
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-item.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DIDL_LITE_ITEM_H__
+#define __GUPNP_DIDL_LITE_ITEM_H__
+
+#include <glib-object.h>
+#include "gupnp-didl-lite-object.h"
+
+G_BEGIN_DECLS
+
+GType
+gupnp_didl_lite_item_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_DIDL_LITE_ITEM \
+ (gupnp_didl_lite_item_get_type ())
+#define GUPNP_DIDL_LITE_ITEM(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_ITEM, \
+ GUPnPDIDLLiteItem))
+#define GUPNP_DIDL_LITE_ITEM_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_ITEM, \
+ GUPnPDIDLLiteItemClass))
+#define GUPNP_IS_DIDL_LITE_ITEM(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_ITEM))
+#define GUPNP_IS_DIDL_LITE_ITEM_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_ITEM))
+#define GUPNP_DIDL_LITE_ITEM_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_DIDL_LITE_ITEM, \
+ GUPnPDIDLLiteItemClass))
+
+typedef struct {
+ GUPnPDIDLLiteObject parent;
+} GUPnPDIDLLiteItem;
+
+typedef struct {
+ GUPnPDIDLLiteObjectClass parent_class;
+
+ /* future padding */
+ void (* _gupnp_reserved1) (void);
+ void (* _gupnp_reserved2) (void);
+ void (* _gupnp_reserved3) (void);
+ void (* _gupnp_reserved4) (void);
+} GUPnPDIDLLiteItemClass;
+
+const char *
+gupnp_didl_lite_item_get_ref_id (GUPnPDIDLLiteItem *item);
+
+void
+gupnp_didl_lite_item_set_ref_id (GUPnPDIDLLiteItem *item,
+ const char *ref_id);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DIDL_LITE_ITEM_H__ */
diff --git a/libgupnp-av/gupnp-didl-lite-object-private.h b/libgupnp-av/gupnp-didl-lite-object-private.h
new file mode 100644
index 0000000..780e495
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-object-private.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DIDL_LITE_OBJECT_PRIVATE_H__
+#define __GUPNP_DIDL_LITE_OBJECT_PRIVATE_H__
+
+#include <glib-object.h>
+#include <libxml/tree.h>
+
+G_BEGIN_DECLS
+
+G_GNUC_INTERNAL GUPnPDIDLLiteObject *
+gupnp_didl_lite_object_new_from_xml (xmlNode *xml_node,
+ GUPnPXMLDoc *xml_doc,
+ xmlNs *upnp_ns,
+ xmlNs *dc_ns,
+ xmlNs *dlna_ns);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DIDL_LITE_OBJECT_PRIVATE_H__ */
diff --git a/libgupnp-av/gupnp-didl-lite-object.c b/libgupnp-av/gupnp-didl-lite-object.c
new file mode 100644
index 0000000..5c916a6
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-object.c
@@ -0,0 +1,1966 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gupnp-didl-lite-object
+ * @short_description: DIDL-Lite Object
+ *
+ * #GUPnPDIDLLiteObject respresent a DIDL-Lite object element.
+ */
+
+#include <string.h>
+#include <libgupnp/gupnp.h>
+
+#include "gupnp-didl-lite-object.h"
+#include "gupnp-didl-lite-object-private.h"
+#include "gupnp-didl-lite-resource-private.h"
+#include "gupnp-didl-lite-descriptor-private.h"
+#include "gupnp-didl-lite-container.h"
+#include "gupnp-didl-lite-item.h"
+#include "gupnp-didl-lite-contributor-private.h"
+#include "xml-util.h"
+
+G_DEFINE_ABSTRACT_TYPE (GUPnPDIDLLiteObject,
+ gupnp_didl_lite_object,
+ G_TYPE_OBJECT);
+
+struct _GUPnPDIDLLiteObjectPrivate {
+ xmlNode *xml_node;
+ GUPnPXMLDoc *xml_doc;
+
+ xmlNs *upnp_ns;
+ xmlNs *dc_ns;
+ xmlNs *dlna_ns;
+};
+
+enum {
+ PROP_0,
+ PROP_XML_NODE,
+ PROP_XML_DOC,
+ PROP_UPNP_NAMESPACE,
+ PROP_DC_NAMESPACE,
+ PROP_DLNA_NAMESPACE,
+ PROP_ID,
+ PROP_PARENT_ID,
+ PROP_RESTRICTED,
+ PROP_TITLE,
+ PROP_UPNP_CLASS,
+ PROP_CREATOR,
+ PROP_ARTIST,
+ PROP_AUTHOR,
+ PROP_GENRE,
+ PROP_WRITE_STATUS,
+ PROP_ALBUM,
+ PROP_ALBUM_ART,
+ PROP_DESCRIPTION,
+ PROP_DATE,
+ PROP_TRACK_NUMBER,
+ PROP_DLNA_MANAGED,
+};
+
+static int
+is_non_transcoded_resource (GUPnPDIDLLiteResource *resource)
+{
+ GUPnPProtocolInfo *info;
+
+ info = gupnp_didl_lite_resource_get_protocol_info (resource);
+ if (G_UNLIKELY (info == NULL))
+ return -1;
+
+ return gupnp_protocol_info_get_dlna_conversion (info) &
+ GUPNP_DLNA_CONVERSION_TRANSCODED;
+}
+
+static void
+gupnp_didl_lite_object_init (GUPnPDIDLLiteObject *object)
+{
+ object->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (object,
+ GUPNP_TYPE_DIDL_LITE_OBJECT,
+ GUPnPDIDLLiteObjectPrivate);
+}
+
+static void
+gupnp_didl_lite_object_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+
+{
+ GUPnPDIDLLiteObject *didl_object;
+
+ didl_object = GUPNP_DIDL_LITE_OBJECT (object);
+
+ switch (property_id) {
+ case PROP_XML_NODE:
+ didl_object->priv->xml_node = g_value_get_pointer (value);
+ break;
+ case PROP_XML_DOC:
+ didl_object->priv->xml_doc = g_value_dup_object (value);
+ break;
+ case PROP_UPNP_NAMESPACE:
+ didl_object->priv->upnp_ns = g_value_get_pointer (value);
+ break;
+ case PROP_DC_NAMESPACE:
+ didl_object->priv->dc_ns = g_value_get_pointer (value);
+ break;
+ case PROP_DLNA_NAMESPACE:
+ didl_object->priv->dlna_ns = g_value_get_pointer (value);
+ break;
+ case PROP_ID:
+ gupnp_didl_lite_object_set_id (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_PARENT_ID:
+ gupnp_didl_lite_object_set_parent_id
+ (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_RESTRICTED:
+ gupnp_didl_lite_object_set_restricted
+ (didl_object,
+ g_value_get_boolean (value));
+ break;
+ case PROP_TITLE:
+ gupnp_didl_lite_object_set_title
+ (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_UPNP_CLASS:
+ gupnp_didl_lite_object_set_upnp_class
+ (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_CREATOR:
+ gupnp_didl_lite_object_set_creator
+ (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_ARTIST:
+ gupnp_didl_lite_object_set_artist
+ (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_AUTHOR:
+ gupnp_didl_lite_object_set_author
+ (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_GENRE:
+ gupnp_didl_lite_object_set_genre
+ (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_WRITE_STATUS:
+ gupnp_didl_lite_object_set_write_status
+ (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_ALBUM:
+ gupnp_didl_lite_object_set_album
+ (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_ALBUM_ART:
+ gupnp_didl_lite_object_set_album_art
+ (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_DESCRIPTION:
+ gupnp_didl_lite_object_set_description
+ (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_DATE:
+ gupnp_didl_lite_object_set_date
+ (didl_object,
+ g_value_get_string (value));
+ break;
+ case PROP_TRACK_NUMBER:
+ gupnp_didl_lite_object_set_track_number
+ (didl_object,
+ g_value_get_int (value));
+ break;
+ case PROP_DLNA_MANAGED:
+ gupnp_didl_lite_object_set_dlna_managed
+ (didl_object,
+ g_value_get_flags (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_object_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPDIDLLiteObject *didl_object;
+
+ didl_object = GUPNP_DIDL_LITE_OBJECT (object);
+
+ switch (property_id) {
+ case PROP_XML_NODE:
+ g_value_set_pointer
+ (value,
+ gupnp_didl_lite_object_get_xml_node (didl_object));
+ break;
+ case PROP_UPNP_NAMESPACE:
+ g_value_set_pointer
+ (value,
+ gupnp_didl_lite_object_get_upnp_namespace
+ (didl_object));
+ break;
+ case PROP_DC_NAMESPACE:
+ g_value_set_pointer
+ (value,
+ gupnp_didl_lite_object_get_dc_namespace
+ (didl_object));
+ break;
+ case PROP_DLNA_NAMESPACE:
+ g_value_set_pointer
+ (value,
+ gupnp_didl_lite_object_get_dlna_namespace
+ (didl_object));
+ break;
+ case PROP_ID:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_id (didl_object));
+ break;
+ case PROP_PARENT_ID:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_parent_id (didl_object));
+ break;
+ case PROP_RESTRICTED:
+ g_value_set_boolean
+ (value,
+ gupnp_didl_lite_object_get_restricted (didl_object));
+ break;
+ case PROP_TITLE:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_title (didl_object));
+ break;
+ case PROP_UPNP_CLASS:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_upnp_class (didl_object));
+ break;
+ case PROP_CREATOR:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_creator (didl_object));
+ break;
+ case PROP_ARTIST:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_artist (didl_object));
+ break;
+ case PROP_AUTHOR:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_author (didl_object));
+ break;
+ case PROP_GENRE:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_genre (didl_object));
+ break;
+ case PROP_WRITE_STATUS:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_write_status (didl_object));
+ break;
+ case PROP_ALBUM:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_album (didl_object));
+ break;
+ case PROP_ALBUM_ART:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_album_art (didl_object));
+ break;
+ case PROP_DESCRIPTION:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_description (didl_object));
+ break;
+ case PROP_DATE:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_object_get_date (didl_object));
+ break;
+ case PROP_TRACK_NUMBER:
+ g_value_set_int
+ (value,
+ gupnp_didl_lite_object_get_track_number (didl_object));
+ break;
+ case PROP_DLNA_MANAGED:
+ g_value_set_flags
+ (value,
+ gupnp_didl_lite_object_get_dlna_managed (didl_object));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_object_dispose (GObject *object)
+{
+ GObjectClass *object_class;
+ GUPnPDIDLLiteObjectPrivate *priv;
+
+ priv = GUPNP_DIDL_LITE_OBJECT (object)->priv;
+
+ if (priv->xml_doc) {
+ g_object_unref (priv->xml_doc);
+ priv->xml_doc = NULL;
+ }
+
+ object_class = G_OBJECT_CLASS (gupnp_didl_lite_object_parent_class);
+ object_class->dispose (object);
+}
+
+static void
+gupnp_didl_lite_object_class_init (GUPnPDIDLLiteObjectClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = gupnp_didl_lite_object_set_property;
+ object_class->get_property = gupnp_didl_lite_object_get_property;
+ object_class->dispose = gupnp_didl_lite_object_dispose;
+
+ g_type_class_add_private (klass, sizeof (GUPnPDIDLLiteObjectPrivate));
+
+ /**
+ * GUPnPDIDLLiteObject:xml-node:
+ *
+ * The pointer to object node in XML document.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_XML_NODE,
+ g_param_spec_pointer ("xml-node",
+ "XMLNode",
+ "The pointer to object node in XML"
+ " document.",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:xml-doc:
+ *
+ * The reference to XML document containing this object.
+ *
+ * Internal property.
+ *
+ * Stability: Private
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_XML_DOC,
+ g_param_spec_object ("xml-doc",
+ "XMLDoc",
+ "The reference to XML document"
+ " containing this object.",
+ GUPNP_TYPE_XML_DOC,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:upnp-namespace:
+ *
+ * Pointer to the UPnP namespace registered with the XML document
+ * containing this object.
+ *
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_UPNP_NAMESPACE,
+ g_param_spec_pointer ("upnp-namespace",
+ "XML namespace",
+ "Pointer to the UPnP XML namespace "
+ "registered with the XML document "
+ "containing this object.",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:dc-namespace:
+ *
+ * Pointer to the DublinCore namespace registered with the XML document
+ * containing this object.
+ *
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_DC_NAMESPACE,
+ g_param_spec_pointer ("dc-namespace",
+ "XML namespace",
+ "Pointer to the Dublin Core XML "
+ "namespace registered with the XML "
+ "document containing this object.",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:dlna-namespace:
+ *
+ * Pointer to the DLNA metadata namespace registered with the XML
+ * document containing this object.
+ *
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_DLNA_NAMESPACE,
+ g_param_spec_pointer ("dlna-namespace",
+ "XML namespace",
+ "Pointer to the DLNA metadata namespace "
+ "registered with the XML document "
+ "containing this object.",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:id:
+ *
+ * The ID of this object.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_ID,
+ g_param_spec_string ("id",
+ "ID",
+ "The ID of this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:parent-id:
+ *
+ * The ID of the parent container of this object.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_PARENT_ID,
+ g_param_spec_string ("parent-id",
+ "ParentID",
+ "The ID of the parent container of"
+ " this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:restricted:
+ *
+ * Whether this object is restricted.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_RESTRICTED,
+ g_param_spec_boolean ("restricted",
+ "Restricted",
+ "Whether this object is restricted.",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:title:
+ *
+ * The title of this object.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_TITLE,
+ g_param_spec_string ("title",
+ "Title",
+ "The title of this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:upnp-class:
+ *
+ * The UPnP class of this object.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_UPNP_CLASS,
+ g_param_spec_string ("upnp-class",
+ "UPnPClassName",
+ "The UPnP class of this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:creator:
+ *
+ * The creator of this object.
+ *
+ * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_creators and
+ * #gupnp_didl_lite_object_add_creator instead since unlike this
+ * property, they are capable of dealing with multiple creator nodes.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_CREATOR,
+ g_param_spec_string ("creator",
+ "Creator",
+ "The creator of this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:artist:
+ *
+ * The artist of this object.
+ *
+ * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_artists and
+ * #gupnp_didl_lite_object_add_artist instead since unlike this
+ * property, they are capable of dealing with multiple artist nodes.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_ARTIST,
+ g_param_spec_string ("artist",
+ "Artist",
+ "The artist of this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:author:
+ *
+ * The author of this object.
+ *
+ * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_authors and
+ * #gupnp_didl_lite_object_add_author instead since unlike this
+ * property, they are capable of dealing with multiple author nodes.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_AUTHOR,
+ g_param_spec_string ("author",
+ "Author",
+ "The author of this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:genre:
+ *
+ * The genre of this object.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_GENRE,
+ g_param_spec_string ("genre",
+ "Genre",
+ "The genre of this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:write-status:
+ *
+ * The write status of this object.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_WRITE_STATUS,
+ g_param_spec_string ("write-status",
+ "WriteStatus",
+ "The write status of this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:album:
+ *
+ * The album of this object.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_ALBUM,
+ g_param_spec_string ("album",
+ "Album",
+ "The album of this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:album-art:
+ *
+ * The URI to album art of this object.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_ALBUM_ART,
+ g_param_spec_string ("album-art",
+ "AlbumArt",
+ "The URI to album art of this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:description:
+ *
+ * The description of this object.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_DESCRIPTION,
+ g_param_spec_string ("description",
+ "Description",
+ "The description of this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:date:
+ *
+ * The date of this object.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_DATE,
+ g_param_spec_string ("date",
+ "Date",
+ "The date of this object.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:track-number:
+ *
+ * The original track number of this object.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_TRACK_NUMBER,
+ g_param_spec_int ("track-number",
+ "TrackNumber",
+ "The original track number of this object.",
+ -1, G_MAXINT, -1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteObject:dlna-managed:
+ *
+ * The 'dlna:dlnaManaged' attribute.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_DLNA_MANAGED,
+ g_param_spec_flags ("dlna-managed",
+ "DLNAManaged",
+ "The 'dlna:dlnaManaged' attribute",
+ GUPNP_TYPE_OCM_FLAGS,
+ GUPNP_OCM_FLAGS_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+}
+
+static gboolean
+is_resource_compatible (GUPnPDIDLLiteResource *resource,
+ const char *sink_protocol_info)
+{
+ gboolean ret = FALSE;
+ char **protocols, **it;
+
+ protocols = g_strsplit (sink_protocol_info, ",", 0);
+
+
+ for (it = protocols; *it != NULL && !ret; it++) {
+ GUPnPProtocolInfo *info;
+ GUPnPProtocolInfo *res_info;
+
+ info = gupnp_protocol_info_new_from_string (*it, NULL);
+ if (info == NULL)
+ continue;
+
+ res_info = gupnp_didl_lite_resource_get_protocol_info
+ (resource);
+ ret = gupnp_protocol_info_is_compatible (info, res_info);
+
+ g_object_unref (info);
+ }
+
+ g_strfreev (protocols);
+
+ return ret;
+}
+
+static GList *
+get_contributor_list_by_name (GUPnPDIDLLiteObject *object,
+ const char *name)
+{
+ GList *contributors = NULL;
+ GList *ret = NULL;
+ GList *l;
+
+ contributors = gupnp_didl_lite_object_get_properties (object, name);
+
+ for (l = contributors; l; l = l->next) {
+ GUPnPDIDLLiteContributor *contributor;
+ xmlNode *contributor_node;
+
+ contributor_node = (xmlNode *) l->data;
+ if (!contributor_node->children)
+ continue;
+
+ contributor = gupnp_didl_lite_contributor_new_from_xml
+ (contributor_node,
+ object->priv->xml_doc);
+
+ ret = g_list_append (ret, contributor);
+ }
+
+ g_list_free (contributors);
+
+ return ret;
+}
+
+/**
+ * gupnp_didl_lite_object_new_from_xml:
+ * @xml_node: The pointer to 'res' node in XML document
+ * @xml_doc: The reference to XML document containing this object
+ * @upnp_ns: The pointer to 'upnp' namespace in XML document
+ * @dc_ns: The pointer to 'dc' namespace in XML document
+ * @dlna_ns: The pointer to 'dlna' namespace in XML document
+ *
+ * Creates a new #GUPnPDIDLLiteObject for the @xml_node.
+ *
+ * Return value: A new #GUPnPDIDLLiteObject object. Unref after usage.
+ **/
+GUPnPDIDLLiteObject *
+gupnp_didl_lite_object_new_from_xml (xmlNode *xml_node,
+ GUPnPXMLDoc *xml_doc,
+ xmlNs *upnp_ns,
+ xmlNs *dc_ns,
+ xmlNs *dlna_ns)
+{
+ g_return_val_if_fail (xml_node != NULL, NULL);
+ g_return_val_if_fail (xml_node->name != NULL, NULL);
+ g_return_val_if_fail (upnp_ns != NULL, NULL);
+ g_return_val_if_fail (dc_ns != NULL, NULL);
+ g_return_val_if_fail (dlna_ns != NULL, NULL);
+
+ if (g_ascii_strcasecmp ((char *) xml_node->name, "container") == 0)
+ return g_object_new (GUPNP_TYPE_DIDL_LITE_CONTAINER,
+ "xml-node", xml_node,
+ "xml-doc", xml_doc,
+ "upnp-namespace", upnp_ns,
+ "dc-namespace", dc_ns,
+ "dlna-namespace", dlna_ns,
+ NULL);
+ else if (g_ascii_strcasecmp ((char *) xml_node->name, "item") == 0)
+ return g_object_new (GUPNP_TYPE_DIDL_LITE_ITEM,
+ "xml-node", xml_node,
+ "xml-doc", xml_doc,
+ "upnp-namespace", upnp_ns,
+ "dc-namespace", dc_ns,
+ "dlna-namespace", dlna_ns,
+ NULL);
+ else
+ return NULL;
+}
+
+/**
+ * gupnp_didl_lite_object_get_xml_node:
+ * @object: The #GUPnPDIDLLiteObject
+ *
+ * Get the pointer to object node in XML document.
+ *
+ * Returns: (transfer none): The pointer to object node in XML document.
+ **/
+xmlNode *
+gupnp_didl_lite_object_get_xml_node (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return object->priv->xml_node;
+}
+
+/**
+ * gupnp_didl_lite_object_get_upnp_namespace:
+ * @object: The #GUPnPDIDLLiteObject
+ *
+ * Get the pointer to the UPnP namespace registered with the XML document.
+ *
+ * Returns: (transfer none): The pointer to UPnP namespace in XML document.
+ **/
+xmlNsPtr
+gupnp_didl_lite_object_get_upnp_namespace (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return object->priv->upnp_ns;
+}
+
+/**
+ * gupnp_didl_lite_object_get_dc_namespace:
+ * @object: The #GUPnPDIDLLiteObject
+ *
+ * Get the pointer to the DublinCore namespace registered with the XML document
+ * containing this object.
+ *
+ * Returns: (transfer none): The pointer to DublinCore namespace in XML document.
+ **/
+xmlNsPtr
+gupnp_didl_lite_object_get_dc_namespace (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return object->priv->dc_ns;
+}
+
+/**
+ * gupnp_didl_lite_object_get_upnp_class:
+ * @object: The #GUPnPDIDLLiteObject
+ *
+ * Get the UPnP class of the @object.
+ *
+ * Return value: The class of @object, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_object_get_upnp_class (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_child_element_content (object->priv->xml_node,
+ "class");
+}
+
+/**
+ * gupnp_didl_lite_object_get_dlna_namespace:
+ * @object: The #GUPnPDIDLLiteObject
+ *
+ * Get the pointer to the DLNA metadata namespace registered with the XML
+ * document containing this object.
+ *
+ * Returns: (transfer none): The pointer to DLNA namespace in XML document.
+ **/
+xmlNsPtr
+gupnp_didl_lite_object_get_dlna_namespace (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return object->priv->dlna_ns;
+}
+
+/**
+ * gupnp_didl_lite_object_get_id:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the ID of the @object.
+ *
+ * Return value: The ID of the @object, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_object_get_id (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_attribute_content (object->priv->xml_node, "id");
+}
+
+/**
+ * gupnp_didl_lite_object_get_parent_id:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the ID of the parent of the @object.
+ *
+ * Return value: The ID of parent of the @object, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_object_get_parent_id (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_attribute_content (object->priv->xml_node,
+ "parentID");
+}
+
+/**
+ * gupnp_didl_lite_object_get_properties:
+ * @object: #GUPnPDIDLLiteObject
+ * @name: name of the properties
+ *
+ * Use this function to retreive property nodes by name.
+ *
+ * Return value: (element-type xmlNode*) (transfer container): The list of
+ * property nodes by the name @property_name belonging to @object, or %NULL.
+ * #g_list_free the returned list after usage but do not modify the contents.
+ **/
+GList *
+gupnp_didl_lite_object_get_properties (GUPnPDIDLLiteObject *object,
+ const char *name)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ return xml_util_get_child_elements_by_name (object->priv->xml_node,
+ name);
+}
+
+/**
+ * gupnp_didl_lite_object_get_restricted:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Whether the @object is restricted or not.
+ *
+ * Return value: #TRUE if @object is restricted.
+ **/
+gboolean
+gupnp_didl_lite_object_get_restricted (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), FALSE);
+
+ return xml_util_get_boolean_attribute (object->priv->xml_node,
+ "restricted");
+}
+
+/**
+ * gupnp_didl_lite_object_get_title:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the title of the @object.
+ *
+ * Return value: The title of the @object, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_object_get_title (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_child_element_content (object->priv->xml_node,
+ "title");
+}
+
+/**
+ * gupnp_didl_lite_object_get_creator:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the creator of the @object.
+ *
+ * Return value: The creator of the @object, or %NULL.
+ *
+ * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_creators instead.
+ **/
+const char *
+gupnp_didl_lite_object_get_creator (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_child_element_content (object->priv->xml_node,
+ "creator");
+}
+
+/**
+ * gupnp_didl_lite_object_get_creators:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the creators of the @object.
+ *
+ * Returns: (element-type GUPnPDIDLLiteContributor*) (transfer full): The list
+ * of creators belonging to @object, or %NULL.
+ * #g_list_free the returned list after usage and unref each object in it.
+ **/
+GList *
+gupnp_didl_lite_object_get_creators (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return get_contributor_list_by_name (object, "creator");
+}
+
+/**
+ * gupnp_didl_lite_object_get_artist:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the artist of the @object. If role is not %NULL, it is set to the role
+ * of the artist if available.
+ *
+ * Return value: The artist of the @object, or %NULL.
+ *
+ * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_artists instead.
+ **/
+const char *
+gupnp_didl_lite_object_get_artist (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_child_element_content (object->priv->xml_node,
+ "artist");
+}
+
+/**
+ * gupnp_didl_lite_object_get_artists:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the artists of the @object.
+ *
+ * Returns: (element-type GUPnPDIDLLiteContributor*) (transfer full): The list
+ * of artists belonging to @object, or %NULL.
+ * #g_list_free the returned list after usage and unref each object in it.
+ **/
+GList *
+gupnp_didl_lite_object_get_artists (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return get_contributor_list_by_name (object, "artist");
+}
+
+/**
+ * gupnp_didl_lite_object_get_author:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the author of the @object.
+ *
+ * Return value: The author of the @object, or %NULL.
+ *
+ * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_authors instead.
+ **/
+const char *
+gupnp_didl_lite_object_get_author (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_child_element_content (object->priv->xml_node,
+ "author");
+}
+
+/**
+ * gupnp_didl_lite_object_get_authors:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the authors of the @object.
+ *
+ * Returns: (element-type GUPnPDIDLLiteContributor*) (transfer full): The list
+ * of authors belonging to @object, or %NULL.
+ * #g_list_free the returned list after usage and unref each object in it.
+ **/
+GList *
+gupnp_didl_lite_object_get_authors (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return get_contributor_list_by_name (object, "author");
+}
+
+/**
+ * gupnp_didl_lite_object_get_descriptors:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the descriptors of the @object.
+ *
+ * Returns: (element-type GUPnPDIDLLiteDescriptor*) (transfer full): The list of
+ * descriptors belonging to @object, or %NULL.
+ * #g_list_free the returned list after usage and unref each object in it.
+ **/
+GList *
+gupnp_didl_lite_object_get_descriptors (GUPnPDIDLLiteObject *object)
+{
+ GList *descriptors = NULL;
+ GList *ret = NULL;
+ GList *l;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ descriptors = gupnp_didl_lite_object_get_properties (object, "desc");
+
+ for (l = descriptors; l; l = l->next) {
+ GUPnPDIDLLiteDescriptor *descriptor;
+ xmlNode *descriptor_node;
+
+ descriptor_node = (xmlNode *) l->data;
+
+ descriptor = gupnp_didl_lite_descriptor_new_from_xml
+ (descriptor_node,
+ object->priv->xml_doc);
+
+ ret = g_list_append (ret, descriptor);
+ }
+
+ g_list_free (descriptors);
+
+ return ret;
+}
+
+/**
+ * gupnp_didl_lite_object_get_genre:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the genre of the @object.
+ *
+ * Return value: The genre of the @object, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_object_get_genre (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_child_element_content (object->priv->xml_node,
+ "genre");
+}
+
+/**
+ * gupnp_didl_lite_object_get_write_status:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the write status of the @object.
+ *
+ * Return value: The write status of the @object, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_object_get_write_status (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_child_element_content (object->priv->xml_node,
+ "writeStatus");
+}
+
+/**
+ * gupnp_didl_lite_object_get_album:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the album of the @object.
+ *
+ * Return value: The album of the @object, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_object_get_album (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_child_element_content (object->priv->xml_node,
+ "album");
+}
+
+/**
+ * gupnp_didl_lite_object_get_album_art:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the URI to album art of the @object.
+ *
+ * Return value: The URI to album art of the @object, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_object_get_album_art (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_child_element_content (object->priv->xml_node,
+ "albumArtURI");
+}
+
+/**
+ * gupnp_didl_lite_object_get_description:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the description of the @object.
+ *
+ * Return value: The description of the @object, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_object_get_description (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_child_element_content (object->priv->xml_node,
+ "description");
+}
+
+/**
+ * gupnp_didl_lite_object_get_date:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the date of the @object.
+ *
+ * Return value: The date of the @object, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_object_get_date (GUPnPDIDLLiteObject *object)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ return xml_util_get_child_element_content (object->priv->xml_node,
+ "date");
+}
+
+/**
+ * gupnp_didl_lite_object_get_track_number:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the original track number of the @object.
+ *
+ * Return value: The original track number of the @object, or -1.
+ **/
+int
+gupnp_didl_lite_object_get_track_number (GUPnPDIDLLiteObject *object)
+{
+ const char *str;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), -1);
+
+ str = xml_util_get_child_element_content (object->priv->xml_node,
+ "originalTrackNumber");
+ if (str == NULL)
+ return -1;
+
+ return atoi (str);
+}
+
+/**
+ * gupnp_didl_lite_object_get_dlna_managed:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Get the 'dlna:dlnaManaged' attribute of the @object.
+ *
+ * Return value: The 'dlna:dlnaManaged' attribute of the @object.
+ **/
+GUPnPOCMFlags
+gupnp_didl_lite_object_get_dlna_managed (GUPnPDIDLLiteObject *object)
+{
+ const char *str;
+ GUPnPOCMFlags dlna_managed;
+
+ g_return_val_if_fail (object != NULL, GUPNP_OCM_FLAGS_NONE);
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object),
+ GUPNP_OCM_FLAGS_NONE);
+
+ str = xml_util_get_attribute_content (object->priv->xml_node,
+ "dlnaManaged");
+ if (str == NULL)
+ return GUPNP_OCM_FLAGS_NONE;
+
+ sscanf (str, "%08x", &dlna_managed);
+
+ return dlna_managed;
+}
+
+/**
+ * gupnp_didl_lite_object_get_resources:
+ * @object: #GUPnPDIDLLiteObject
+ *
+ * Use this function to retreive resources from the @object.
+ *
+ * Return value: (element-type GUPnPDIDLLiteResource*) (transfer full): The list
+ * of resources belonging to @object, or %NULL. #g_list_free the
+ * returned list after usage and unref each resource in it.
+ **/
+GList *
+gupnp_didl_lite_object_get_resources (GUPnPDIDLLiteObject *object)
+{
+ GList *resources = NULL;
+ GList *res = NULL;
+ GList *ret = NULL;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ resources = gupnp_didl_lite_object_get_properties (object, "res");
+
+ for (res = resources; res; res = res->next) {
+ GUPnPDIDLLiteResource *resource;
+ xmlNode *res_node;
+
+ res_node = (xmlNode *) res->data;
+
+ /* Create a resource struct out of DIDLLite XML */
+ resource = gupnp_didl_lite_resource_new_from_xml
+ (res_node,
+ object->priv->xml_doc);
+
+ ret = g_list_append (ret, resource);
+ }
+
+ g_list_free (resources);
+
+ return ret;
+}
+
+/**
+ * gupnp_didl_lite_object_get_compat_resource:
+ * @object: #GUPnPDIDLLiteObject
+ * @sink_protocol_info: The SinkProtocolInfo string from MediaRenderer
+ * @lenient: Enable lenient mode
+ *
+ * Use this function to get a resource from the @object that is compatible with
+ * any of the protocols specified in the @sink_protocol_info. The value of
+ * @sink_protocol_info will typically be acquired from 'Sink' argument of
+ * 'GetProtocolInfo' action or 'SinkProtocolInfo' state-variable of a
+ * ConnectionManager service.
+ *
+ * If @lenient is #TRUE, the first resource in the list is returned instead of
+ * %NULL if none of resources and protocols are found to be compatible.
+ *
+ * Returns: (transfer full): The resource belonging to @object that is comaptible with
+ * any of the protocols specified in @sink_protocol_info, or %NULL. Unref after
+ * usage.
+ **/
+GUPnPDIDLLiteResource *
+gupnp_didl_lite_object_get_compat_resource
+ (GUPnPDIDLLiteObject *object,
+ const char *sink_protocol_info,
+ gboolean lenient)
+{
+ GUPnPDIDLLiteResource *resource = NULL;
+ GList *resources = NULL;
+ GList *compat_resources = NULL;
+ GList *res;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+ g_return_val_if_fail (sink_protocol_info != NULL, NULL);
+
+ resources = gupnp_didl_lite_object_get_resources (object);
+ if (resources == NULL)
+ return NULL;
+
+ for (res = resources;
+ res != NULL;
+ res = res->next) {
+ resource = (GUPnPDIDLLiteResource *) res->data;
+
+ if (is_resource_compatible (resource, sink_protocol_info))
+ compat_resources = g_list_append (compat_resources,
+ resource);
+ }
+
+ resource = NULL;
+
+ if (compat_resources != NULL) {
+ /* Try to find non-transcoded resource */
+ res = g_list_find_custom (compat_resources,
+ NULL,
+ (GCompareFunc)
+ is_non_transcoded_resource);
+
+ if (res != NULL)
+ resource = (GUPnPDIDLLiteResource *) res->data;
+ else
+ /* Just use the first compatible resource */
+ resource = (GUPnPDIDLLiteResource *)
+ compat_resources->data;
+
+ } else if (lenient)
+ /* Just use the first resource */
+ resource = (GUPnPDIDLLiteResource *) resources->data;
+
+ /* Unref all resources except for the one we just took */
+ for (res = resources; res; res = res->next)
+ if (res->data != resource)
+ g_object_unref (res->data);
+ g_list_free (resources);
+ g_list_free (compat_resources);
+
+ return resource;
+}
+
+/**
+ * gupnp_didl_lite_object_set_upnp_class:
+ * @object: The #GUPnPDIDLLiteObject
+ * @upnp_class: The UPnP class as string.
+ *
+ * Set the UPnP class of the @object to @upnp_class.
+ **/
+void
+gupnp_didl_lite_object_set_upnp_class (GUPnPDIDLLiteObject *object,
+ const char *upnp_class)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ xml_util_set_child (object->priv->xml_node,
+ object->priv->upnp_ns,
+ object->priv->xml_doc->doc,
+ "class",
+ upnp_class);
+
+ g_object_notify (G_OBJECT (object), "upnp-class");
+}
+
+/**
+ * gupnp_didl_lite_object_set_id:
+ * @object: #GUPnPDIDLLiteObject
+ * @id: The ID
+ *
+ * Set the ID of the @object to @id.
+ **/
+void
+gupnp_didl_lite_object_set_id (GUPnPDIDLLiteObject *object,
+ const char *id)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ xmlSetProp (object->priv->xml_node,
+ (unsigned char *) "id",
+ (unsigned char *) id);
+
+ g_object_notify (G_OBJECT (object), "id");
+}
+
+/**
+ * gupnp_didl_lite_object_set_parent_id:
+ * @object: #GUPnPDIDLLiteObject
+ * @parent_id: The parent ID
+ *
+ * Set the ID of the parent of the @object to @parent_id.
+ **/
+void
+gupnp_didl_lite_object_set_parent_id (GUPnPDIDLLiteObject *object,
+ const char *parent_id)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ xmlSetProp (object->priv->xml_node,
+ (unsigned char *) "parentID",
+ (unsigned char *) parent_id);
+
+ g_object_notify (G_OBJECT (object), "parent-id");
+}
+
+/**
+ * gupnp_didl_lite_object_set_restricted:
+ * @object: #GUPnPDIDLLiteObject
+ * @restricted: The restricted status
+ *
+ * Set the restricted status of @object to @restricted.
+ **/
+void
+gupnp_didl_lite_object_set_restricted (GUPnPDIDLLiteObject *object,
+ gboolean restricted)
+{
+ const char *str;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ if (restricted)
+ str = "1";
+ else
+ str = "0";
+ xmlSetProp (object->priv->xml_node,
+ (unsigned char *) "restricted",
+ (unsigned char *) str);
+
+ g_object_notify (G_OBJECT (object), "restricted");
+}
+
+/**
+ * gupnp_didl_lite_object_set_title:
+ * @object: #GUPnPDIDLLiteObject
+ * @title: The title
+ *
+ * Set the title of the @object to @title.
+ **/
+void
+gupnp_didl_lite_object_set_title (GUPnPDIDLLiteObject *object,
+ const char *title)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ xml_util_set_child (object->priv->xml_node,
+ object->priv->dc_ns,
+ object->priv->xml_doc->doc,
+ "title",
+ title);
+
+ g_object_notify (G_OBJECT (object), "title");
+}
+
+/**
+ * gupnp_didl_lite_object_set_creator:
+ * @object: #GUPnPDIDLLiteObject
+ * @creator: The creator
+ *
+ * Set the creator of the @object to @creator.
+ *
+ * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_add_creator instead.
+ **/
+void
+gupnp_didl_lite_object_set_creator (GUPnPDIDLLiteObject *object,
+ const char *creator)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ xml_util_set_child (object->priv->xml_node,
+ object->priv->dc_ns,
+ object->priv->xml_doc->doc,
+ "creator",
+ creator);
+
+ g_object_notify (G_OBJECT (object), "creator");
+}
+
+/**
+ * gupnp_didl_lite_object_add_creator:
+ * @object: The #GUPnPDIDLLiteObject
+ *
+ * Add a new creator node to the @object and return the associated
+ * #GUPnPDIDLLiteContributor object.
+ *
+ * Returns: (transfer full): A new #GUPnPDIDLLiteContributor object. Unref after usage.
+ **/
+GUPnPDIDLLiteContributor *
+gupnp_didl_lite_object_add_creator (GUPnPDIDLLiteObject *object)
+{
+ xmlNode *res_node;
+
+ g_return_val_if_fail (object != NULL, NULL);
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ res_node = xmlNewChild (object->priv->xml_node,
+ object->priv->dc_ns,
+ (unsigned char *) "creator",
+ NULL);
+
+ return gupnp_didl_lite_contributor_new_from_xml (res_node,
+ object->priv->xml_doc);
+}
+
+
+/**
+ * gupnp_didl_lite_object_set_artist:
+ * @object: The #GUPnPDIDLLiteObject
+ * @artist: The Artist
+ *
+ * Set the Artist of the @object to @artist.
+ *
+ * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_add_artist instead.
+ **/
+void
+gupnp_didl_lite_object_set_artist (GUPnPDIDLLiteObject *object,
+ const char *artist)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ xml_util_set_child (object->priv->xml_node,
+ object->priv->upnp_ns,
+ object->priv->xml_doc->doc,
+ "artist",
+ artist);
+
+ g_object_notify (G_OBJECT (object), "artist");
+}
+
+/**
+ * gupnp_didl_lite_object_add_artist:
+ * @object: The #GUPnPDIDLLiteObject
+ *
+ * Add a new Artist node to the @object and return the associated
+ * #GUPnPDIDLLiteContributor object.
+ *
+ * Returns: (transfer full): A new #GUPnPDIDLLiteContributor object. Unref after usage.
+ **/
+GUPnPDIDLLiteContributor *
+gupnp_didl_lite_object_add_artist (GUPnPDIDLLiteObject *object)
+{
+ xmlNode *res_node;
+
+ g_return_val_if_fail (object != NULL, NULL);
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ res_node = xmlNewChild (object->priv->xml_node,
+ object->priv->upnp_ns,
+ (unsigned char *) "artist",
+ NULL);
+
+ return gupnp_didl_lite_contributor_new_from_xml (res_node,
+ object->priv->xml_doc);
+}
+
+/**
+ * gupnp_didl_lite_object_set_author:
+ * @object: The #GUPnPDIDLLiteObject
+ * @author: The Author
+ *
+ * Set the Author of the @object to @author.
+ *
+ * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_add_author instead.
+ **/
+void
+gupnp_didl_lite_object_set_author (GUPnPDIDLLiteObject *object,
+ const char *author)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ xml_util_set_child (object->priv->xml_node,
+ object->priv->upnp_ns,
+ object->priv->xml_doc->doc,
+ "author",
+ author);
+
+ g_object_notify (G_OBJECT (object), "author");
+}
+
+/**
+ * gupnp_didl_lite_object_add_author:
+ * @object: The #GUPnPDIDLLiteObject
+ *
+ * Add a new author node to the @object and return the associated
+ * #GUPnPDIDLLiteContributor object.
+ *
+ * Returns: (transfer full): A new #GUPnPDIDLLiteContributor object. Unref after usage.
+ **/
+GUPnPDIDLLiteContributor *
+gupnp_didl_lite_object_add_author (GUPnPDIDLLiteObject *object)
+{
+ xmlNode *res_node;
+
+ g_return_val_if_fail (object != NULL, NULL);
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ res_node = xmlNewChild (object->priv->xml_node,
+ object->priv->upnp_ns,
+ (unsigned char *) "author",
+ NULL);
+
+ return gupnp_didl_lite_contributor_new_from_xml (res_node,
+ object->priv->xml_doc);
+}
+
+/**
+ * gupnp_didl_lite_object_set_genre:
+ * @object: The #GUPnPDIDLLiteObject
+ * @genre: The Genre
+ *
+ * Set the genre of the @object to @genre.
+ **/
+void
+gupnp_didl_lite_object_set_genre (GUPnPDIDLLiteObject *object,
+ const char *genre)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ xml_util_set_child (object->priv->xml_node,
+ object->priv->upnp_ns,
+ object->priv->xml_doc->doc,
+ "genre",
+ genre);
+
+ g_object_notify (G_OBJECT (object), "genre");
+}
+
+/**
+ * gupnp_didl_lite_object_set_write_status:
+ * @object: #GUPnPDIDLLiteObject
+ * @write_status: The write status string
+ *
+ * Set the write status of the @object to @write_status.
+ **/
+void
+gupnp_didl_lite_object_set_write_status (GUPnPDIDLLiteObject *object,
+ const char *write_status)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ xml_util_set_child (object->priv->xml_node,
+ object->priv->dc_ns,
+ object->priv->xml_doc->doc,
+ "writeStatus",
+ write_status);
+
+ g_object_notify (G_OBJECT (object), "write-status");
+}
+
+/**
+ * gupnp_didl_lite_object_set_album:
+ * @object: #GUPnPDIDLLiteObject
+ * @album: The album string
+ *
+ * Set the album of the @object to @album.
+ **/
+void
+gupnp_didl_lite_object_set_album (GUPnPDIDLLiteObject *object,
+ const char *album)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ xml_util_set_child (object->priv->xml_node,
+ object->priv->upnp_ns,
+ object->priv->xml_doc->doc,
+ "album",
+ album);
+
+ g_object_notify (G_OBJECT (object), "album");
+}
+
+/**
+ * gupnp_didl_lite_object_set_album_art:
+ * @object: #GUPnPDIDLLiteObject
+ * @album_art: The URI of album art
+ *
+ * Set the URI to album art of the @object to @album_art.
+ **/
+void
+gupnp_didl_lite_object_set_album_art (GUPnPDIDLLiteObject *object,
+ const char *album_art)
+{
+ xmlNode *node;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ node = xml_util_set_child (object->priv->xml_node,
+ object->priv->upnp_ns,
+ object->priv->xml_doc->doc,
+ "albumArtURI",
+ album_art);
+ xmlSetNsProp (node,
+ object->priv->dlna_ns,
+ (const unsigned char *) "profileID",
+ (const unsigned char *) "JPEG_TN");
+
+ g_object_notify (G_OBJECT (object), "album-art");
+}
+
+/**
+ * gupnp_didl_lite_object_set_description:
+ * @object: #GUPnPDIDLLiteObject
+ * @description: The description string
+ *
+ * Set the description of the @object to @description.
+ **/
+void
+gupnp_didl_lite_object_set_description (GUPnPDIDLLiteObject *object,
+ const char *description)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ xml_util_set_child (object->priv->xml_node,
+ object->priv->dc_ns,
+ object->priv->xml_doc->doc,
+ "description",
+ description);
+
+ g_object_notify (G_OBJECT (object), "description");
+}
+
+/**
+ * gupnp_didl_lite_object_set_date:
+ * @object: #GUPnPDIDLLiteObject
+ * @date: The date string
+ *
+ * Set the date of the @object to @date.
+ **/
+void
+gupnp_didl_lite_object_set_date (GUPnPDIDLLiteObject *object,
+ const char *date)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ xml_util_set_child (object->priv->xml_node,
+ object->priv->dc_ns,
+ object->priv->xml_doc->doc,
+ "date",
+ date);
+
+ g_object_notify (G_OBJECT (object), "date");
+}
+
+/**
+ * gupnp_didl_lite_object_set_track_number:
+ * @object: #GUPnPDIDLLiteObject
+ * @track_number: The original track number
+ *
+ * Set the original track number of the @object to @track_number.
+ **/
+void
+gupnp_didl_lite_object_set_track_number (GUPnPDIDLLiteObject *object,
+ int track_number)
+{
+ char *str;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ str = g_strdup_printf ("%d", track_number);
+ xml_util_set_child (object->priv->xml_node,
+ object->priv->upnp_ns,
+ object->priv->xml_doc->doc,
+ "originalTrackNumber",
+ str);
+ g_free (str);
+
+ g_object_notify (G_OBJECT (object), "track-number");
+}
+
+/**
+ * gupnp_didl_lite_object_set_dlna_managed:
+ * @object: #GUPnPDIDLLiteObject
+ * @dlna_managed: The #GUPnPOCMFlags.
+ *
+ * Set the 'dlna:dlnaManaged' attribute of the @object to @dlna_managed.
+ **/
+void
+gupnp_didl_lite_object_set_dlna_managed (GUPnPDIDLLiteObject *object,
+ GUPnPOCMFlags dlna_managed)
+{
+ char *str;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
+
+ str = g_strdup_printf ("%08x", dlna_managed);
+ xmlSetNsProp (object->priv->xml_node,
+ object->priv->dlna_ns,
+ (const unsigned char *) "dlnaManaged",
+ (const unsigned char *) str);
+ g_free (str);
+
+ g_object_notify (G_OBJECT (object), "dlna-managed");
+}
+
+/**
+ * gupnp_didl_lite_object_add_resource:
+ * @object: A #GUPnPDIDLLiteObject
+ *
+ * Creates a new resource, attaches it to @object and returns it.
+ *
+ * Returns: (transfer full): A new #GUPnPDIDLLiteResource object. Unref after usage.
+ **/
+GUPnPDIDLLiteResource *
+gupnp_didl_lite_object_add_resource (GUPnPDIDLLiteObject *object)
+{
+ xmlNode *res_node;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ res_node = xmlNewChild (object->priv->xml_node,
+ NULL,
+ (unsigned char *) "res",
+ NULL);
+
+ return gupnp_didl_lite_resource_new_from_xml (res_node,
+ object->priv->xml_doc);
+}
+
+/**
+ * gupnp_didl_lite_object_add_descriptor:
+ * @object: A #GUPnPDIDLLiteObject
+ *
+ * Creates a new descriptor, attaches it to @object and returns it.
+ *
+ * Returns: (transfer full): A new #GUPnPDIDLLiteDescriptor object. Unref after usage.
+ **/
+GUPnPDIDLLiteDescriptor *
+gupnp_didl_lite_object_add_descriptor (GUPnPDIDLLiteObject *object)
+{
+ xmlNode *desc_node;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
+
+ desc_node = xmlNewChild (object->priv->xml_node,
+ NULL,
+ (unsigned char *) "desc",
+ NULL);
+
+ return gupnp_didl_lite_descriptor_new_from_xml (desc_node,
+ object->priv->xml_doc);
+}
+
diff --git a/libgupnp-av/gupnp-didl-lite-object.h b/libgupnp-av/gupnp-didl-lite-object.h
new file mode 100644
index 0000000..722e833
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-object.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2007, 2008 OpenedHand Ltd.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ * Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DIDL_LITE_OBJECT_H__
+#define __GUPNP_DIDL_LITE_OBJECT_H__
+
+#include <stdarg.h>
+#include <glib-object.h>
+#include <libxml/tree.h>
+
+#include "gupnp-didl-lite-resource.h"
+#include "gupnp-didl-lite-descriptor.h"
+#include "gupnp-didl-lite-contributor.h"
+
+G_BEGIN_DECLS
+
+GType
+gupnp_didl_lite_object_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_DIDL_LITE_OBJECT \
+ (gupnp_didl_lite_object_get_type ())
+#define GUPNP_DIDL_LITE_OBJECT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_OBJECT, \
+ GUPnPDIDLLiteObject))
+#define GUPNP_DIDL_LITE_OBJECT_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_OBJECT, \
+ GUPnPDIDLLiteObjectClass))
+#define GUPNP_IS_DIDL_LITE_OBJECT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_OBJECT))
+#define GUPNP_IS_DIDL_LITE_OBJECT_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_OBJECT))
+#define GUPNP_DIDL_LITE_OBJECT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_DIDL_LITE_OBJECT, \
+ GUPnPDIDLLiteObjectClass))
+
+typedef struct _GUPnPDIDLLiteObjectPrivate GUPnPDIDLLiteObjectPrivate;
+
+typedef struct {
+ GObject parent;
+
+ GUPnPDIDLLiteObjectPrivate *priv;
+} GUPnPDIDLLiteObject;
+
+typedef struct {
+ GObjectClass parent_class;
+
+ /* future padding */
+ void (* _gupnp_reserved1) (void);
+ void (* _gupnp_reserved2) (void);
+ void (* _gupnp_reserved3) (void);
+ void (* _gupnp_reserved4) (void);
+} GUPnPDIDLLiteObjectClass;
+
+xmlNode *
+gupnp_didl_lite_object_get_xml_node (GUPnPDIDLLiteObject *object);
+
+xmlNsPtr
+gupnp_didl_lite_object_get_upnp_namespace
+ (GUPnPDIDLLiteObject *object);
+
+xmlNsPtr
+gupnp_didl_lite_object_get_dc_namespace (GUPnPDIDLLiteObject *object);
+
+xmlNsPtr
+gupnp_didl_lite_object_get_dlna_namespace
+ (GUPnPDIDLLiteObject *object);
+
+const char *
+gupnp_didl_lite_object_get_upnp_class (GUPnPDIDLLiteObject *object);
+
+const char *
+gupnp_didl_lite_object_get_id (GUPnPDIDLLiteObject *object);
+
+const char *
+gupnp_didl_lite_object_get_parent_id (GUPnPDIDLLiteObject *object);
+
+GList *
+gupnp_didl_lite_object_get_properties (GUPnPDIDLLiteObject *object,
+ const char *name);
+
+gboolean
+gupnp_didl_lite_object_get_restricted (GUPnPDIDLLiteObject *object);
+
+const char *
+gupnp_didl_lite_object_get_title (GUPnPDIDLLiteObject *object);
+
+#ifndef GUPNP_DISABLE_DEPRECATED
+const char *
+gupnp_didl_lite_object_get_creator (GUPnPDIDLLiteObject *object);
+
+const char *
+gupnp_didl_lite_object_get_artist (GUPnPDIDLLiteObject *object);
+
+const char *
+gupnp_didl_lite_object_get_author (GUPnPDIDLLiteObject *object);
+
+#endif /* GUPNP_DISABLE_DEPRECATED */
+
+GList *
+gupnp_didl_lite_object_get_creators (GUPnPDIDLLiteObject *object);
+
+GList *
+gupnp_didl_lite_object_get_artists (GUPnPDIDLLiteObject *object);
+
+GList *
+gupnp_didl_lite_object_get_authors (GUPnPDIDLLiteObject *object);
+
+GList *
+gupnp_didl_lite_object_get_descriptors (GUPnPDIDLLiteObject *object);
+
+const char *
+gupnp_didl_lite_object_get_genre (GUPnPDIDLLiteObject *object);
+
+const char *
+gupnp_didl_lite_object_get_write_status (GUPnPDIDLLiteObject *object);
+
+const char *
+gupnp_didl_lite_object_get_album (GUPnPDIDLLiteObject *object);
+
+const char *
+gupnp_didl_lite_object_get_album_art (GUPnPDIDLLiteObject *object);
+
+const char *
+gupnp_didl_lite_object_get_description (GUPnPDIDLLiteObject *object);
+
+const char *
+gupnp_didl_lite_object_get_date (GUPnPDIDLLiteObject *object);
+
+int
+gupnp_didl_lite_object_get_track_number (GUPnPDIDLLiteObject *object);
+
+GUPnPOCMFlags
+gupnp_didl_lite_object_get_dlna_managed (GUPnPDIDLLiteObject *object);
+
+GList *
+gupnp_didl_lite_object_get_resources (GUPnPDIDLLiteObject *object);
+
+GUPnPDIDLLiteResource *
+gupnp_didl_lite_object_get_compat_resource
+ (GUPnPDIDLLiteObject *object,
+ const char
+ *sink_protocol_info,
+ gboolean lenient);
+
+GUPnPDIDLLiteResource *
+gupnp_didl_lite_object_add_resource (GUPnPDIDLLiteObject *object);
+
+GUPnPDIDLLiteDescriptor *
+gupnp_didl_lite_object_add_descriptor (GUPnPDIDLLiteObject *object);
+
+void
+gupnp_didl_lite_object_set_upnp_class (GUPnPDIDLLiteObject *object,
+ const char *upnp_class);
+
+void
+gupnp_didl_lite_object_set_id (GUPnPDIDLLiteObject *object,
+ const char *id);
+
+void
+gupnp_didl_lite_object_set_parent_id (GUPnPDIDLLiteObject *object,
+ const char *parent_id);
+
+void
+gupnp_didl_lite_object_set_restricted (GUPnPDIDLLiteObject *object,
+ gboolean restricted);
+
+void
+gupnp_didl_lite_object_set_title (GUPnPDIDLLiteObject *object,
+ const char *title);
+
+#ifndef GUPNP_DISABLE_DEPRECATED
+void
+gupnp_didl_lite_object_set_creator (GUPnPDIDLLiteObject *object,
+ const char *creator);
+
+void
+gupnp_didl_lite_object_set_artist (GUPnPDIDLLiteObject *object,
+ const char *artist);
+
+void
+gupnp_didl_lite_object_set_author (GUPnPDIDLLiteObject *object,
+ const char *author);
+
+#endif /* GUPNP_DISABLE_DEPRECATED */
+
+GUPnPDIDLLiteContributor *
+gupnp_didl_lite_object_add_creator (GUPnPDIDLLiteObject *object);
+
+GUPnPDIDLLiteContributor *
+gupnp_didl_lite_object_add_artist (GUPnPDIDLLiteObject *object);
+
+GUPnPDIDLLiteContributor *
+gupnp_didl_lite_object_add_author (GUPnPDIDLLiteObject *object);
+
+void
+gupnp_didl_lite_object_set_genre (GUPnPDIDLLiteObject *object,
+ const char *genre);
+
+void
+gupnp_didl_lite_object_set_write_status (GUPnPDIDLLiteObject *object,
+ const char *write_status);
+
+void
+gupnp_didl_lite_object_set_album (GUPnPDIDLLiteObject *object,
+ const char *album);
+
+void
+gupnp_didl_lite_object_set_album_art (GUPnPDIDLLiteObject *object,
+ const char *album_art);
+
+void
+gupnp_didl_lite_object_set_description (GUPnPDIDLLiteObject *object,
+ const char *description);
+
+void
+gupnp_didl_lite_object_set_date (GUPnPDIDLLiteObject *object,
+ const char *date);
+
+void
+gupnp_didl_lite_object_set_track_number (GUPnPDIDLLiteObject *object,
+ int track_number);
+
+void
+gupnp_didl_lite_object_set_dlna_managed (GUPnPDIDLLiteObject *object,
+ GUPnPOCMFlags dlna_managed);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DIDL_LITE_OBJECT_H__ */
diff --git a/libgupnp-av/gupnp-didl-lite-parser.c b/libgupnp-av/gupnp-didl-lite-parser.c
new file mode 100644
index 0000000..8b1088d
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-parser.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2007 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gupnp-didl-lite-parser
+ * @short_description: A/V DIDL-Lite XML parser
+ *
+ * #GUPnPDIDLLiteParser parses DIDL-Lite XML strings.
+ *
+ */
+
+#include <string.h>
+#include <ctype.h>
+#include "gupnp-av.h"
+#include "gupnp-didl-lite-object-private.h"
+#include "xml-util.h"
+
+G_DEFINE_TYPE (GUPnPDIDLLiteParser,
+ gupnp_didl_lite_parser,
+ G_TYPE_OBJECT);
+
+enum {
+ OBJECT_AVAILABLE,
+ ITEM_AVAILABLE,
+ CONTAINER_AVAILABLE,
+ SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST];
+
+static gboolean
+verify_didl_attributes (xmlNode *node)
+{
+ const char *content;
+
+ content = xml_util_get_child_element_content (node, "date");
+ if (content) {
+ /* try to roughly verify the passed date with ^\d{4}-\d{2}-\d{2} */
+ char *ptr = (char *) content;
+ int state = 0;
+ while (*ptr) {
+ if (state == 4 || state == 7) {
+ if (*ptr != '-')
+ return FALSE;
+ } else {
+ if (!isdigit (*ptr))
+ return FALSE;
+ }
+
+ ptr++;
+ state++;
+ if (state == 10)
+ break;
+ }
+ }
+
+ return xml_util_verify_attribute_is_boolean (node, "restricted");
+}
+
+static void
+gupnp_didl_lite_parser_init (GUPnPDIDLLiteParser *parser)
+{
+}
+
+static void
+gupnp_didl_lite_parser_dispose (GObject *object)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (gupnp_didl_lite_parser_parent_class);
+ gobject_class->dispose (object);
+}
+
+static void
+gupnp_didl_lite_parser_class_init (GUPnPDIDLLiteParserClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gupnp_didl_lite_parser_dispose;
+
+ /**
+ * GUPnPDIDLLiteParser::object-available:
+ * @parser: The #GUPnPDIDLLiteParser that received the signal
+ * @object: The now available #GUPnPDIDLLiteObject
+ *
+ * The ::object-available signal is emitted each time an object is
+ * found in the DIDL-Lite XML being parsed.
+ **/
+ signals[OBJECT_AVAILABLE] =
+ g_signal_new ("object-available",
+ GUPNP_TYPE_DIDL_LITE_PARSER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GUPnPDIDLLiteParserClass,
+ object_available),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1,
+ GUPNP_TYPE_DIDL_LITE_OBJECT);
+
+ /**
+ * GUPnPDIDLLiteParser::item-available:
+ * @parser: The #GUPnPDIDLLiteParser that received the signal
+ * @item: The now available #GUPnPDIDLLiteItem
+ *
+ * The ::item-available signal is emitted each time an item is found in
+ * the DIDL-Lite XML being parsed.
+ **/
+ signals[ITEM_AVAILABLE] =
+ g_signal_new ("item-available",
+ GUPNP_TYPE_DIDL_LITE_PARSER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GUPnPDIDLLiteParserClass,
+ item_available),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1,
+ GUPNP_TYPE_DIDL_LITE_ITEM);
+
+ /**
+ * GUPnPDIDLLiteParser::container-available:
+ * @parser: The #GUPnPDIDLLiteParser that received the signal
+ * @container: The now available #GUPnPDIDLLiteContainer
+ *
+ * The ::container-available signal is emitted each time a container is
+ * found in the DIDL-Lite XML being parsed.
+ **/
+ signals[CONTAINER_AVAILABLE] =
+ g_signal_new ("container-available",
+ GUPNP_TYPE_DIDL_LITE_PARSER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GUPnPDIDLLiteParserClass,
+ container_available),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1,
+ GUPNP_TYPE_DIDL_LITE_CONTAINER);
+}
+
+/**
+ * gupnp_didl_lite_parser_new:
+ *
+ * Return value: A new #GUPnPDIDLLiteParser object.
+ **/
+GUPnPDIDLLiteParser *
+gupnp_didl_lite_parser_new (void)
+{
+ return g_object_new (GUPNP_TYPE_DIDL_LITE_PARSER, NULL);
+}
+
+/**
+ * gupnp_didl_lite_parser_parse_didl:
+ * @parser: A #GUPnPDIDLLiteParser
+ * @didl: The DIDL-Lite XML string to be parsed
+ * @error: The location where to store any error, or NULL
+ *
+ * Parses DIDL-Lite XML string @didl, emitting the ::object-available,
+ * ::item-available and ::container-available signals appropriately during the
+ * process.
+ *
+ * Return value: TRUE on success.
+ **/
+gboolean
+gupnp_didl_lite_parser_parse_didl (GUPnPDIDLLiteParser *parser,
+ const char *didl,
+ GError **error)
+{
+ xmlDoc *doc;
+ xmlNode *element;
+ xmlNode *node;
+ xmlNs **ns_list;
+ xmlNs *upnp_ns = NULL;
+ xmlNs *dc_ns = NULL;
+ xmlNs *dlna_ns = NULL;
+ GUPnPXMLDoc *xml_doc;
+
+ doc = xmlRecoverMemory (didl, strlen (didl));
+ if (doc == NULL) {
+ g_set_error (error,
+ GUPNP_XML_ERROR,
+ GUPNP_XML_ERROR_PARSE,
+ "Could not parse DIDL-Lite XML:\n%s", didl);
+
+ return FALSE;
+ }
+
+ /* Get a pointer to root element */
+ element = xml_util_get_element ((xmlNode *) doc,
+ "DIDL-Lite",
+ NULL);
+ if (element == NULL) {
+ g_set_error (error,
+ GUPNP_XML_ERROR,
+ GUPNP_XML_ERROR_NO_NODE,
+ "No 'DIDL-Lite' node in the DIDL-Lite XML:\n%s",
+ didl);
+ xmlFreeDoc (doc);
+
+ return FALSE;
+ }
+
+ if (element->children == NULL) {
+ g_set_error (error,
+ GUPNP_XML_ERROR,
+ GUPNP_XML_ERROR_EMPTY_NODE,
+ "Empty 'DIDL-Lite' node in the DIDL-Lite XML:\n%s",
+ didl);
+ xmlFreeDoc (doc);
+
+ return FALSE;
+ }
+
+ /* Lookup UPnP and DC namespaces */
+ ns_list = xmlGetNsList (doc,
+ xmlDocGetRootElement (doc));
+
+ if (ns_list) {
+ short i;
+
+ for (i = 0; ns_list[i] != NULL; i++) {
+ const char *prefix = (const char *) ns_list[i]->prefix;
+
+ if (prefix == NULL)
+ continue;
+
+ if (! upnp_ns &&
+ g_ascii_strcasecmp (prefix, "upnp") == 0)
+ upnp_ns = ns_list[i];
+ else if (! dc_ns &&
+ g_ascii_strcasecmp (prefix, "dc") == 0)
+ dc_ns = ns_list[i];
+ else if (! dlna_ns &&
+ g_ascii_strcasecmp (prefix, "dlna") == 0)
+ dlna_ns = ns_list[i];
+ }
+
+ xmlFree (ns_list);
+ }
+
+ /* Create UPnP and DC namespaces if they don't exist */
+ if (! upnp_ns)
+ upnp_ns = xmlNewNs (xmlDocGetRootElement (doc),
+ (unsigned char *)
+ "urn:schemas-upnp-org:metadata-1-0/upnp/",
+ (unsigned char *)
+ GUPNP_DIDL_LITE_WRITER_NAMESPACE_UPNP);
+ if (! dc_ns)
+ dc_ns = xmlNewNs (xmlDocGetRootElement (doc),
+ (unsigned char *)
+ "http://purl.org/dc/elements/1.1/",
+ (unsigned char *)
+ GUPNP_DIDL_LITE_WRITER_NAMESPACE_DC);
+ if (! dlna_ns)
+ dlna_ns = xmlNewNs (xmlDocGetRootElement (doc),
+ (unsigned char *)
+ "urn:schemas-dlna-org:metadata-2-0/",
+ (unsigned char *)
+ GUPNP_DIDL_LITE_WRITER_NAMESPACE_DLNA);
+
+ xml_doc = gupnp_xml_doc_new (doc);
+
+ for (element = element->children; element; element = element->next) {
+ GUPnPDIDLLiteObject *object;
+
+ object = gupnp_didl_lite_object_new_from_xml (element, xml_doc,
+ upnp_ns, dc_ns,
+ dlna_ns);
+
+ if (object == NULL)
+ continue;
+
+ if (GUPNP_IS_DIDL_LITE_CONTAINER (object))
+ g_signal_emit (parser,
+ signals[CONTAINER_AVAILABLE],
+ 0,
+ object);
+ else if (GUPNP_IS_DIDL_LITE_ITEM (object)) {
+ node = gupnp_didl_lite_object_get_xml_node(object);
+ if (!verify_didl_attributes(node)) {
+ g_object_unref (object);
+ g_object_unref (xml_doc);
+ g_set_error (error,
+ GUPNP_XML_ERROR,
+ GUPNP_XML_ERROR_INVALID_ATTRIBUTE,
+ "Could not parse DIDL-Lite XML:\n%s",
+ didl);
+
+ return FALSE;
+ }
+
+ g_signal_emit (parser,
+ signals[ITEM_AVAILABLE],
+ 0,
+ object);
+ }
+
+ g_signal_emit (parser,
+ signals[OBJECT_AVAILABLE],
+ 0,
+ object);
+
+ g_object_unref (object);
+ }
+
+ g_object_unref (xml_doc);
+
+ return TRUE;
+}
+
diff --git a/libgupnp-av/gupnp-didl-lite-parser.h b/libgupnp-av/gupnp-didl-lite-parser.h
new file mode 100644
index 0000000..f7b3c4e
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-parser.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2007 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DIDL_LITE_PARSER_H__
+#define __GUPNP_DIDL_LITE_PARSER_H__
+
+#include <libgupnp/gupnp.h>
+#include "gupnp-didl-lite-container.h"
+#include "gupnp-didl-lite-item.h"
+
+G_BEGIN_DECLS
+
+GType
+gupnp_didl_lite_parser_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_DIDL_LITE_PARSER \
+ (gupnp_didl_lite_parser_get_type ())
+#define GUPNP_DIDL_LITE_PARSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_PARSER, \
+ GUPnPDIDLLiteParser))
+#define GUPNP_DIDL_LITE_PARSER_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_PARSER, \
+ GUPnPDIDLLiteParserClass))
+#define GUPNP_IS_DIDL_LITE_PARSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_PARSER))
+#define GUPNP_IS_DIDL_LITE_PARSER_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_PARSER))
+#define GUPNP_DIDL_LITE_PARSER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_DIDL_LITE_PARSER, \
+ GUPnPDIDLLiteParserClass))
+
+typedef struct {
+ GObject parent;
+
+ gpointer gupnp_reserved;
+} GUPnPDIDLLiteParser;
+
+typedef struct {
+ GObjectClass parent_class;
+
+ /* signals */
+ void (* object_available) (GUPnPDIDLLiteParser *parser,
+ GUPnPDIDLLiteObject *object);
+ void (* item_available) (GUPnPDIDLLiteParser *parser,
+ GUPnPDIDLLiteItem *item);
+ void (* container_available) (GUPnPDIDLLiteParser *parser,
+ GUPnPDIDLLiteContainer *container);
+
+ /* future padding */
+ void (* _gupnp_reserved1) (void);
+ void (* _gupnp_reserved2) (void);
+ void (* _gupnp_reserved3) (void);
+ void (* _gupnp_reserved4) (void);
+ void (* _gupnp_reserved5) (void);
+} GUPnPDIDLLiteParserClass;
+
+GUPnPDIDLLiteParser *
+gupnp_didl_lite_parser_new (void);
+
+gboolean
+gupnp_didl_lite_parser_parse_didl (GUPnPDIDLLiteParser *parser,
+ const char *didl,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DIDL_LITE_PARSER_H__ */
diff --git a/libgupnp-av/gupnp-didl-lite-resource-private.h b/libgupnp-av/gupnp-didl-lite-resource-private.h
new file mode 100644
index 0000000..eff4518
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-resource-private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DIDL_LITE_RESOURCE_PRIVATE_H__
+#define __GUPNP_DIDL_LITE_RESOURCE_PRIVATE_H__
+
+#include <stdarg.h>
+#include <glib-object.h>
+#include <libxml/tree.h>
+
+G_BEGIN_DECLS
+
+GUPnPDIDLLiteResource *
+gupnp_didl_lite_resource_new_from_xml (xmlNode *xml_node,
+ GUPnPXMLDoc *xml_doc);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DIDL_LITE_RESOURCE_PRIVATE_H__ */
diff --git a/libgupnp-av/gupnp-didl-lite-resource.c b/libgupnp-av/gupnp-didl-lite-resource.c
new file mode 100644
index 0000000..240b070
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-resource.c
@@ -0,0 +1,1419 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2007, 2008 OpenedHand Ltd.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ * Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gupnp-didl-lite-resource
+ * @short_description: DIDL-Lite Resource
+ *
+ * #GUPnPDIDLLiteResource respresent a DIDL-Lite resource (res) element.
+ */
+
+#include <string.h>
+
+#include "gupnp-didl-lite-resource.h"
+#include "xml-util.h"
+
+#define SEC_PER_MIN 60
+#define SEC_PER_HOUR 3600
+
+G_DEFINE_TYPE (GUPnPDIDLLiteResource,
+ gupnp_didl_lite_resource,
+ G_TYPE_OBJECT);
+
+struct _GUPnPDIDLLiteResourcePrivate {
+ xmlNode *xml_node;
+ GUPnPXMLDoc *xml_doc;
+
+ GUPnPProtocolInfo *protocol_info;
+};
+
+enum {
+ PROP_0,
+ PROP_XML_NODE,
+ PROP_XML_DOC,
+
+ PROP_URI,
+ PROP_IMPORT_URI,
+
+ PROP_PROTOCOL_INFO,
+
+ PROP_SIZE,
+ PROP_SIZE64,
+ PROP_DURATION,
+ PROP_BITRATE,
+ PROP_SAMPLE_FREQ,
+ PROP_BITS_PER_SAMPLE,
+ PROP_PROTECTION,
+
+ PROP_AUDIO_CHANNELS,
+
+ PROP_WIDTH,
+ PROP_HEIGHT,
+ PROP_COLOR_DEPTH
+};
+
+static void
+get_resolution_info (GUPnPDIDLLiteResource *resource,
+ int *width,
+ int *height)
+{
+ const char *resolution;
+ char **tokens;
+
+ resolution = xml_util_get_attribute_content (resource->priv->xml_node,
+ "resolution");
+ if (resolution == NULL)
+ return;
+
+ tokens = g_strsplit (resolution, "x", -1);
+ if (tokens == NULL || tokens[0] == NULL || tokens[1] == NULL) {
+ g_warning ("Failed to resolution string '%s'\n", resolution);
+
+ goto return_point;
+ }
+
+ if (width)
+ *width = atoi (tokens[0]);
+ if (height)
+ *height = atoi (tokens[1]);
+
+return_point:
+ g_strfreev (tokens);
+}
+
+static long
+seconds_from_time (const char *time_str)
+{
+ char **tokens;
+ gdouble seconds = -1;
+
+ if (time_str == NULL)
+ return -1;
+
+ tokens = g_strsplit (time_str, ":", -1);
+ if (tokens[0] == NULL ||
+ tokens[1] == NULL ||
+ tokens[2] == NULL)
+ goto return_point;
+
+ seconds = g_strtod (tokens[2], NULL);
+ seconds += g_strtod (tokens[1], NULL) * SEC_PER_MIN;
+ seconds += g_strtod (tokens[0], NULL) * SEC_PER_HOUR;
+
+return_point:
+ g_strfreev (tokens);
+
+ return (long) seconds;
+}
+
+static void
+on_protocol_info_changed (GUPnPProtocolInfo *info,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GUPnPDIDLLiteResource *resource = GUPNP_DIDL_LITE_RESOURCE (user_data);
+
+ gupnp_didl_lite_resource_set_protocol_info (resource, info);
+}
+
+static void
+gupnp_didl_lite_resource_init (GUPnPDIDLLiteResource *resource)
+{
+ resource->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (resource,
+ GUPNP_TYPE_DIDL_LITE_RESOURCE,
+ GUPnPDIDLLiteResourcePrivate);
+}
+
+static void
+gupnp_didl_lite_resource_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPDIDLLiteResource *resource;
+
+ resource = GUPNP_DIDL_LITE_RESOURCE (object);
+
+ switch (property_id) {
+ case PROP_XML_NODE:
+ resource->priv->xml_node = g_value_get_pointer (value);
+ break;
+ case PROP_XML_DOC:
+ resource->priv->xml_doc = g_value_dup_object (value);
+ break;
+ case PROP_URI:
+ gupnp_didl_lite_resource_set_uri (resource,
+ g_value_get_string (value));
+ break;
+ case PROP_IMPORT_URI:
+ gupnp_didl_lite_resource_set_import_uri
+ (resource,
+ g_value_get_string (value));
+ break;
+ case PROP_PROTOCOL_INFO:
+ gupnp_didl_lite_resource_set_protocol_info
+ (resource,
+ g_value_get_object (value));
+ break;
+ case PROP_SIZE:
+ gupnp_didl_lite_resource_set_size (resource,
+ g_value_get_long (value));
+ break;
+ case PROP_SIZE64:
+ gupnp_didl_lite_resource_set_size64 (resource,
+ g_value_get_int64 (value));
+ break;
+ case PROP_DURATION:
+ gupnp_didl_lite_resource_set_duration
+ (resource,
+ g_value_get_long (value));
+ break;
+ case PROP_BITRATE:
+ gupnp_didl_lite_resource_set_bitrate (resource,
+ g_value_get_int (value));
+ break;
+ case PROP_SAMPLE_FREQ:
+ gupnp_didl_lite_resource_set_sample_freq
+ (resource,
+ g_value_get_int (value));
+ break;
+ case PROP_BITS_PER_SAMPLE:
+ gupnp_didl_lite_resource_set_bits_per_sample
+ (resource,
+ g_value_get_int (value));
+ break;
+ case PROP_PROTECTION:
+ gupnp_didl_lite_resource_set_protection
+ (resource,
+ g_value_get_string (value));
+ break;
+ case PROP_AUDIO_CHANNELS:
+ gupnp_didl_lite_resource_set_audio_channels
+ (resource,
+ g_value_get_int (value));
+ break;
+ case PROP_WIDTH:
+ gupnp_didl_lite_resource_set_width (resource,
+ g_value_get_int (value));
+ break;
+ case PROP_HEIGHT:
+ gupnp_didl_lite_resource_set_height (resource,
+ g_value_get_int (value));
+ break;
+ case PROP_COLOR_DEPTH:
+ gupnp_didl_lite_resource_set_color_depth
+ (resource,
+ g_value_get_int (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_resource_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPDIDLLiteResource *resource;
+
+ resource = GUPNP_DIDL_LITE_RESOURCE (object);
+
+ switch (property_id) {
+ case PROP_XML_NODE:
+ g_value_set_pointer
+ (value,
+ gupnp_didl_lite_resource_get_xml_node (resource));
+ break;
+ case PROP_URI:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_resource_get_uri (resource));
+ break;
+ case PROP_IMPORT_URI:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_resource_get_import_uri (resource));
+ break;
+ case PROP_PROTOCOL_INFO:
+ g_value_set_object
+ (value,
+ gupnp_didl_lite_resource_get_protocol_info (resource));
+ break;
+ case PROP_SIZE:
+ g_value_set_long (value,
+ gupnp_didl_lite_resource_get_size (resource));
+ break;
+ case PROP_SIZE64:
+ g_value_set_int64 (value,
+ gupnp_didl_lite_resource_get_size64 (resource));
+ break;
+ case PROP_DURATION:
+ g_value_set_long
+ (value,
+ gupnp_didl_lite_resource_get_duration (resource));
+ break;
+ case PROP_BITRATE:
+ g_value_set_int
+ (value,
+ gupnp_didl_lite_resource_get_bitrate (resource));
+ break;
+ case PROP_BITS_PER_SAMPLE:
+ g_value_set_int
+ (value,
+ gupnp_didl_lite_resource_get_bits_per_sample
+ (resource));
+ break;
+ case PROP_SAMPLE_FREQ:
+ g_value_set_int
+ (value,
+ gupnp_didl_lite_resource_get_sample_freq (resource));
+ break;
+ case PROP_PROTECTION:
+ g_value_set_string
+ (value,
+ gupnp_didl_lite_resource_get_protection (resource));
+ break;
+ case PROP_AUDIO_CHANNELS:
+ g_value_set_int
+ (value,
+ gupnp_didl_lite_resource_get_audio_channels
+ (resource));
+ break;
+ case PROP_WIDTH:
+ g_value_set_int (value,
+ gupnp_didl_lite_resource_get_width (resource));
+ break;
+ case PROP_HEIGHT:
+ g_value_set_int
+ (value,
+ gupnp_didl_lite_resource_get_height (resource));
+ break;
+ case PROP_COLOR_DEPTH:
+ g_value_set_int
+ (value,
+ gupnp_didl_lite_resource_get_color_depth (resource));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_resource_dispose (GObject *object)
+{
+ GObjectClass *object_class;
+ GUPnPDIDLLiteResourcePrivate *priv;
+
+ priv = GUPNP_DIDL_LITE_RESOURCE (object)->priv;
+
+ if (priv->xml_doc) {
+ g_object_unref (priv->xml_doc);
+ priv->xml_doc = NULL;
+ }
+
+ if (priv->protocol_info != NULL) {
+ g_object_unref (priv->protocol_info);
+ priv->protocol_info = NULL;
+ }
+
+ object_class = G_OBJECT_CLASS (gupnp_didl_lite_resource_parent_class);
+ object_class->dispose (object);
+}
+
+static void
+gupnp_didl_lite_resource_class_init (GUPnPDIDLLiteResourceClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = gupnp_didl_lite_resource_set_property;
+ object_class->get_property = gupnp_didl_lite_resource_get_property;
+ object_class->dispose = gupnp_didl_lite_resource_dispose;
+
+ g_type_class_add_private (klass, sizeof (GUPnPDIDLLiteResourcePrivate));
+
+ /**
+ * GUPnPDIDLLiteResource:xml-node:
+ *
+ * The pointer to res node in XML document.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_XML_NODE,
+ g_param_spec_pointer ("xml-node",
+ "XMLNode",
+ "The pointer to res node in XML"
+ " document.",
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:xml-doc:
+ *
+ * The reference to XML document containing this object.
+ *
+ * Internal property.
+ *
+ * Stability: Private
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_XML_DOC,
+ g_param_spec_object ("xml-doc",
+ "XMLDoc",
+ "The reference to XML document"
+ " containing this object.",
+ GUPNP_TYPE_XML_DOC,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:uri:
+ *
+ * The URI associated with this resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_URI,
+ g_param_spec_string ("uri",
+ "URI",
+ "The URI associated with this resource",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:import-uri:
+ *
+ * The Import URI associated with this resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_IMPORT_URI,
+ g_param_spec_string ("import-uri",
+ "ImportURI",
+ "The import URI associated with this"
+ " resource",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:protocol-info:
+ *
+ * The protocol info associated with this resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_PROTOCOL_INFO,
+ g_param_spec_object ("protocol-info",
+ "ProtocolInfo",
+ "The protocol info associated with this"
+ " resource",
+ GUPNP_TYPE_PROTOCOL_INFO,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:size:
+ *
+ * The size (in bytes) of this resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_SIZE,
+ g_param_spec_long ("size",
+ "Size",
+ "The size (in bytes) of this resource.",
+ -1,
+ G_MAXLONG,
+ -1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:size64:
+ *
+ * The size (in bytes) of this resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_SIZE64,
+ g_param_spec_int64 ("size64",
+ "Size64",
+ "The size (in bytes) of this resource.",
+ -1,
+ G_MAXINT64,
+ -1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:duration:
+ *
+ * The duration (in seconds) of this resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_DURATION,
+ g_param_spec_long ("duration",
+ "Duration",
+ "The duration (in seconds) of this"
+ " resource.",
+ -1,
+ G_MAXLONG,
+ -1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:bitrate:
+ *
+ * The bitrate of this resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_BITRATE,
+ g_param_spec_int ("bitrate",
+ "Bitrate",
+ "The bitrate of this resource.",
+ -1,
+ G_MAXINT,
+ -1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:sample-freq:
+ *
+ * The sample frequency of this resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_SAMPLE_FREQ,
+ g_param_spec_int ("sample-freq",
+ "SampleFrequency",
+ "The sample frequency of this resource.",
+ -1,
+ G_MAXINT,
+ -1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:bits-per-sample:
+ *
+ * The sample size of this resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_BITS_PER_SAMPLE,
+ g_param_spec_int ("bits-per-sample",
+ "BitsPerSample",
+ "The sample size of this resource.",
+ -1,
+ G_MAXINT,
+ -1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:protection:
+ *
+ * The protection system used for this resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_PROTECTION,
+ g_param_spec_string ("protection",
+ "Protection",
+ "The protection system used by this"
+ " resource.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:audio-channels:
+ *
+ * The number of audio channels in this resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_AUDIO_CHANNELS,
+ g_param_spec_int ("audio-channels",
+ "AudioChannels",
+ "The number of audio channels in this"
+ " resource.",
+ -1,
+ G_MAXINT,
+ -1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:width:
+ *
+ * The width of this image/video resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_WIDTH,
+ g_param_spec_int ("width",
+ "Width",
+ "The width of this image/video resource.",
+ -1,
+ G_MAXINT,
+ -1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:height:
+ *
+ * The height of this image/video resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_HEIGHT,
+ g_param_spec_int ("height",
+ "Height",
+ "The height of this image/video resource.",
+ -1,
+ G_MAXINT,
+ -1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteResource:color-depth:
+ *
+ * The color-depth of this image/video resource.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_COLOR_DEPTH,
+ g_param_spec_int ("color-depth",
+ "ColorDepth",
+ "The color-depth of this image/video"
+ " resource.",
+ -1,
+ G_MAXINT,
+ -1,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+}
+
+/**
+ * gupnp_didl_lite_resource_new_from_xml:
+ * @xml_node: The pointer to 'res' node in XML document
+ * @xml_doc: The reference to XML document containing this resource
+ *
+ * Creates a new #GUPnPDIDLLiteResource for the @xml_node.
+ *
+ * Return value: A new #GUPnPDIDLLiteResource object. Unref after usage.
+ **/
+GUPnPDIDLLiteResource *
+gupnp_didl_lite_resource_new_from_xml (xmlNode *xml_node,
+ GUPnPXMLDoc *xml_doc)
+{
+ GUPnPDIDLLiteResource *resource;
+
+ return g_object_new (GUPNP_TYPE_DIDL_LITE_RESOURCE,
+ "xml-node", xml_node,
+ "xml-doc", xml_doc,
+ NULL);
+
+ return resource;
+}
+
+/**
+ * gupnp_didl_lite_resource_get_xml_node:
+ * @resource: The #GUPnPDIDLLiteResource
+ *
+ * Get the pointer to res node in XML document.
+ *
+ * Returns: (transfer none): The pointer to res node in XML document.
+ **/
+xmlNode *
+gupnp_didl_lite_resource_get_xml_node (GUPnPDIDLLiteResource *resource)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), NULL);
+
+ return resource->priv->xml_node;
+}
+
+/**
+ * gupnp_didl_lite_resource_get_uri:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the URI associated with the @resource.
+ *
+ * Return value: The of URI the @resource or %NULL.
+ **/
+const char *
+gupnp_didl_lite_resource_get_uri (GUPnPDIDLLiteResource *resource)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), NULL);
+
+ if (G_UNLIKELY (resource->priv->xml_node->children == NULL))
+ return NULL;
+
+ return (const char *) resource->priv->xml_node->children->content;
+}
+
+/**
+ * gupnp_didl_lite_resource_get_import_uri:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the import URI associated with the @resource.
+ *
+ * Return value: The import URI or %NULL.
+ **/
+const char *
+gupnp_didl_lite_resource_get_import_uri (GUPnPDIDLLiteResource *resource)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), NULL);
+
+ return xml_util_get_attribute_content (resource->priv->xml_node,
+ "importUri");
+}
+
+/**
+ * gupnp_didl_lite_resource_get_protocol_info:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the protocol info associated with the @resource.
+ *
+ * Returns: (transfer none): The protocol info associated with the @resource or %NULL. The
+ * returned object must not be unrefed.
+ **/
+GUPnPProtocolInfo *
+gupnp_didl_lite_resource_get_protocol_info (GUPnPDIDLLiteResource *resource)
+{
+ GUPnPProtocolInfo *info;
+ const char *protocol_info;
+ GError *error;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), NULL);
+
+ if (resource->priv->protocol_info != NULL)
+ return resource->priv->protocol_info;
+
+ protocol_info = xml_util_get_attribute_content
+ (resource->priv->xml_node,
+ "protocolInfo");
+ g_return_val_if_fail (protocol_info != NULL, NULL);
+
+ error = NULL;
+ info = gupnp_protocol_info_new_from_string (protocol_info, &error);
+ if (info == NULL) {
+ g_warning ("Error parsing protocolInfo '%s': %s",
+ protocol_info,
+ error->message);
+
+ g_error_free (error);
+ }
+
+ resource->priv->protocol_info = info;
+
+ return info;
+}
+
+/**
+ * gupnp_didl_lite_resource_get_size:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the size (in bytes) of the @resource.
+ *
+ * Return value: The size (in bytes) of the @resource or -1.
+ **/
+long
+gupnp_didl_lite_resource_get_size (GUPnPDIDLLiteResource *resource)
+{
+ return (long) gupnp_didl_lite_resource_get_size64 (resource);
+}
+
+/**
+ * gupnp_didl_lite_resource_get_size64:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the size (in bytes) of the @resource.
+ *
+ * Return value: The size (in bytes) of the @resource or -1.
+ **/
+gint64
+gupnp_didl_lite_resource_get_size64 (GUPnPDIDLLiteResource *resource)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), -1);
+
+ return xml_util_get_int64_attribute (resource->priv->xml_node,
+ "size",
+ -1);
+}
+
+
+/**
+ * gupnp_didl_lite_resource_get_duration:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the duration (in seconds) of the @resource.
+ *
+ * Return value: The duration (in seconds) of the @resource or -1.
+ **/
+long
+gupnp_didl_lite_resource_get_duration (GUPnPDIDLLiteResource *resource)
+{
+ const char *duration_str;
+ long duration;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), -1);
+
+ duration_str = xml_util_get_attribute_content (resource->priv->xml_node,
+ "duration");
+ duration = seconds_from_time (duration_str);
+
+ return duration;
+}
+
+/**
+ * gupnp_didl_lite_resource_get_bitrate:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the bitrate (in bytes per second) of the @resource.
+ *
+ * Return value: The bitrate (in bytes per second) of the @resource or -1.
+ **/
+int
+gupnp_didl_lite_resource_get_bitrate (GUPnPDIDLLiteResource *resource)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), -1);
+
+ return xml_util_get_long_attribute (resource->priv->xml_node,
+ "bitrate",
+ -1);
+}
+
+/**
+ * gupnp_didl_lite_resource_get_sample_freq:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the sample frequency of the @resource.
+ *
+ * Return value: The sample frequency of the @resource or -1.
+ **/
+int
+gupnp_didl_lite_resource_get_sample_freq (GUPnPDIDLLiteResource *resource)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), -1);
+
+ return xml_util_get_long_attribute (resource->priv->xml_node,
+ "sampleFrequency",
+ -1);
+}
+
+/**
+ * gupnp_didl_lite_resource_get_bits_per_sample:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the sample size of the @resource.
+ *
+ * Return value: The number of bits per sample of the @resource or -1.
+ **/
+int
+gupnp_didl_lite_resource_get_bits_per_sample (GUPnPDIDLLiteResource *resource)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), -1);
+
+ return xml_util_get_long_attribute (resource->priv->xml_node,
+ "bitsPerSample",
+ -1);
+}
+
+/**
+ * gupnp_didl_lite_resource_get_protection:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the protection system used by the @resource.
+ *
+ * Return value: The protection system in use by the @resource or %NULL.
+ **/
+const char *
+gupnp_didl_lite_resource_get_protection (GUPnPDIDLLiteResource *resource)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), NULL);
+
+ return xml_util_get_attribute_content (resource->priv->xml_node,
+ "protection");
+}
+
+/**
+ * gupnp_didl_lite_resource_get_audio_channels:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the number of audio channels in the @resource.
+ *
+ * Return value: The number of audio channels in the @resource or -1.
+ **/
+int
+gupnp_didl_lite_resource_get_audio_channels (GUPnPDIDLLiteResource *resource)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), -1);
+
+ return xml_util_get_long_attribute (resource->priv->xml_node,
+ "nrAudioChannels",
+ -1);
+}
+
+/**
+ * gupnp_didl_lite_resource_get_width:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the width of this image/video resource.
+ *
+ * Return value: The width of this image/video resource or -1.
+ **/
+int
+gupnp_didl_lite_resource_get_width (GUPnPDIDLLiteResource *resource)
+{
+ int width = -1;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), -1);
+
+ get_resolution_info (resource, &width, NULL);
+
+ return width;
+}
+
+/**
+ * gupnp_didl_lite_resource_get_height:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the height of this image/video resource.
+ *
+ * Return value: The height of the @resource or -1.
+ **/
+int
+gupnp_didl_lite_resource_get_height (GUPnPDIDLLiteResource *resource)
+{
+ int height = -1;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), -1);
+
+ get_resolution_info (resource, NULL, &height);
+
+ return height;
+}
+
+/**
+ * gupnp_didl_lite_resource_get_color_depth:
+ * @resource: A #GUPnPDIDLLiteResource
+ *
+ * Get the color-depth of this image/video resource.
+ *
+ * Return value: The color depth of the @resource or -1.
+ **/
+int
+gupnp_didl_lite_resource_get_color_depth (GUPnPDIDLLiteResource *resource)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource), -1);
+
+ return xml_util_get_long_attribute (resource->priv->xml_node,
+ "colorDepth",
+ -1);
+}
+
+/**
+ * gupnp_didl_lite_resource_set_uri:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @uri: The URI as string
+ *
+ * Set the URI associated with the @resource.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_uri (GUPnPDIDLLiteResource *resource,
+ const char *uri)
+{
+ xmlChar *escaped;
+
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+ g_return_if_fail (uri != NULL);
+
+ escaped = xmlEncodeSpecialChars (resource->priv->xml_doc->doc,
+ (const unsigned char *) uri);
+ xmlNodeSetContent (resource->priv->xml_node, escaped);
+ xmlFree (escaped);
+
+ g_object_notify (G_OBJECT (resource), "uri");
+}
+
+/**
+ * gupnp_didl_lite_resource_set_import_uri:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @import_uri: The URI as string
+ *
+ * Set the import URI associated with the @resource.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_import_uri (GUPnPDIDLLiteResource *resource,
+ const char *import_uri)
+{
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+
+ xmlSetProp (resource->priv->xml_node,
+ (unsigned char *) "importUri",
+ (unsigned char *) import_uri);
+
+ g_object_notify (G_OBJECT (resource), "import-uri");
+}
+
+/**
+ * gupnp_didl_lite_resource_set_protocol_info:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @info: The protocol string
+ *
+ * Set the protocol info associated with the @resource.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_protocol_info (GUPnPDIDLLiteResource *resource,
+ GUPnPProtocolInfo *info)
+{
+ char *str;
+
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+ g_return_if_fail (GUPNP_IS_PROTOCOL_INFO (info));
+
+ str = gupnp_protocol_info_to_string (info);
+ xmlSetProp (resource->priv->xml_node,
+ (unsigned char *) "protocolInfo",
+ (unsigned char *) str);
+ g_free (str);
+
+ /* Get a ref first in case it's the same object that we already have */
+ g_object_ref (info);
+ if (resource->priv->protocol_info != NULL)
+ g_object_unref (resource->priv->protocol_info);
+ resource->priv->protocol_info = info;
+
+ /* We need to listen to changes to properties so we update the
+ * corresponding xml property.
+ */
+ g_signal_handlers_disconnect_by_func (info,
+ on_protocol_info_changed,
+ resource);
+ g_signal_connect (info,
+ "notify",
+ G_CALLBACK (on_protocol_info_changed),
+ resource);
+
+ g_object_notify (G_OBJECT (resource), "protocol-info");
+}
+
+/**
+ * gupnp_didl_lite_resource_set_size:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @size: The size (in bytes)
+ *
+ * Set the size (in bytes) of the @resource. Passing a negative number will
+ * unset this property.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_size (GUPnPDIDLLiteResource *resource,
+ long size)
+{
+ gupnp_didl_lite_resource_set_size64 (resource, size);
+}
+
+/**
+ * gupnp_didl_lite_resource_set_size64:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @size: The size (in bytes)
+ *
+ * Set the size (in bytes) of the @resource. Passing a negative number will
+ * unset this property.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_size64 (GUPnPDIDLLiteResource *resource,
+ gint64 size)
+{
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+
+ if (size < 0)
+ xmlUnsetProp (resource->priv->xml_node,
+ (unsigned char *) "size");
+ else {
+ char *str;
+
+ str = g_strdup_printf ("%" G_GINT64_FORMAT, size);
+ xmlSetProp (resource->priv->xml_node,
+ (unsigned char *) "size",
+ (unsigned char *) str);
+ g_free (str);
+ }
+
+ g_object_notify (G_OBJECT (resource), "size64");
+ g_object_notify (G_OBJECT (resource), "size");
+}
+
+
+/**
+ * gupnp_didl_lite_resource_set_duration:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @duration: The duration (in seconds)
+ *
+ * Set the duration (in seconds) of the @resource. Passing a negative number
+ * will unset this property.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_duration (GUPnPDIDLLiteResource *resource,
+ long duration)
+{
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+
+ if (duration < 0)
+ xmlUnsetProp (resource->priv->xml_node,
+ (unsigned char *) "duration");
+ else {
+ char *str;
+
+ str = g_strdup_printf ("%ld:%.2ld:%.2ld.000",
+ duration / (60 * 60),
+ (duration / 60) % 60,
+ duration % 60);
+ xmlSetProp (resource->priv->xml_node,
+ (unsigned char *) "duration",
+ (unsigned char *) str);
+ g_free (str);
+ }
+
+ g_object_notify (G_OBJECT (resource), "duration");
+}
+
+/**
+ * gupnp_didl_lite_resource_set_bitrate:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @bitrate: The bitrate
+ *
+ * Set the bitrate (in bytes per second) of the @resource. Passing a negative
+ * number will unset this property.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_bitrate (GUPnPDIDLLiteResource *resource,
+ int bitrate)
+{
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+
+ if (bitrate < 0)
+ xmlUnsetProp (resource->priv->xml_node,
+ (unsigned char *) "bitrate");
+ else {
+ char *str;
+
+ str = g_strdup_printf ("%d", bitrate);
+ xmlSetProp (resource->priv->xml_node,
+ (unsigned char *) "bitrate",
+ (unsigned char *) str);
+ g_free (str);
+ }
+
+ g_object_notify (G_OBJECT (resource), "bitrate");
+}
+
+/**
+ * gupnp_didl_lite_resource_set_sample_freq:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @sample_freq: The sample frequency
+ *
+ * Set the sample frequency of the @resource. Passing a negative number will
+ * unset this property.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_sample_freq (GUPnPDIDLLiteResource *resource,
+ int sample_freq)
+{
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+
+ if (sample_freq < 0)
+ xmlUnsetProp (resource->priv->xml_node,
+ (unsigned char *) "sampleFrequency");
+ else {
+ char *str;
+
+ str = g_strdup_printf ("%d", sample_freq);
+ xmlSetProp (resource->priv->xml_node,
+ (unsigned char *) "sampleFrequency",
+ (unsigned char *) str);
+ g_free (str);
+ }
+
+ g_object_notify (G_OBJECT (resource), "sample-freq");
+}
+
+/**
+ * gupnp_didl_lite_resource_set_bits_per_sample:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @sample_size: The number of bits per sample
+ *
+ * Set the sample size of the @resource. Passing a negative number will unset
+ * this property.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_bits_per_sample
+ (GUPnPDIDLLiteResource *resource,
+ int sample_size)
+{
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+
+ if (sample_size < 0)
+ xmlUnsetProp (resource->priv->xml_node,
+ (unsigned char *) "bitsPerSample");
+ else {
+ char *str;
+
+ str = g_strdup_printf ("%d", sample_size);
+ xmlSetProp (resource->priv->xml_node,
+ (unsigned char *) "bitsPerSample",
+ (unsigned char *) str);
+ g_free (str);
+ }
+
+ g_object_notify (G_OBJECT (resource), "bits-per-sample");
+}
+
+/**
+ * gupnp_didl_lite_resource_set_protection:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @protection: The protection system identifier as string
+ *
+ * Set the protection system used by the @resource. Passing a negative number
+ * will unset this property.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_protection (GUPnPDIDLLiteResource *resource,
+ const char *protection)
+{
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+
+ xmlSetProp (resource->priv->xml_node,
+ (unsigned char *) "protection",
+ (unsigned char *) protection);
+
+ g_object_notify (G_OBJECT (resource), "protection");
+}
+
+/**
+ * gupnp_didl_lite_resource_set_audio_channels:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @n_channels: The number of channels
+ *
+ * Set the number of audio channels in the @resource. Passing a negative number
+ * will unset this property.
+ *
+ * Return value: The number of audio channels in the @resource or -1.
+ **/
+void
+gupnp_didl_lite_resource_set_audio_channels (GUPnPDIDLLiteResource *resource,
+ int n_channels)
+{
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+
+ if (n_channels < 0)
+ xmlUnsetProp (resource->priv->xml_node,
+ (unsigned char *) "nrAudioChannels");
+ else {
+ char *str;
+
+ str = g_strdup_printf ("%d", n_channels);
+ xmlSetProp (resource->priv->xml_node,
+ (unsigned char *) "nrAudioChannels",
+ (unsigned char *) str);
+ g_free (str);
+ }
+
+ g_object_notify (G_OBJECT (resource), "audio-channels");
+}
+
+/**
+ * gupnp_didl_lite_resource_set_width:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @width: The width
+ *
+ * Set the width of this image/video resource. Setting both width and height to
+ * a negative number will unset the resolution property.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_width (GUPnPDIDLLiteResource *resource,
+ int width)
+{
+ char *resolution;
+ int height = -1;
+
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+
+ get_resolution_info (resource, NULL, &height);
+
+ if (width < 0 && height < 0)
+ xmlUnsetProp (resource->priv->xml_node,
+ (unsigned char *) "resolution");
+ else {
+ resolution = g_strdup_printf ("%dx%d", width, height);
+ xmlSetProp (resource->priv->xml_node,
+ (unsigned char *) "resolution",
+ (unsigned char *) resolution);
+ g_free (resolution);
+ }
+
+ g_object_notify (G_OBJECT (resource), "width");
+}
+
+/**
+ * gupnp_didl_lite_resource_set_height:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @height: The height
+ *
+ * Set the height of this image/video resource. Setting both width and height to
+ * a negative number will unset the resolution property.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_height (GUPnPDIDLLiteResource *resource,
+ int height)
+{
+ int width = -1;
+
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+
+ get_resolution_info (resource, &width, NULL);
+
+ if (width < 0 && height < 0)
+ xmlUnsetProp (resource->priv->xml_node,
+ (unsigned char *) "resolution");
+ else {
+ char *resolution;
+
+ resolution = g_strdup_printf ("%dx%d", width, height);
+ xmlSetProp (resource->priv->xml_node,
+ (unsigned char *) "resolution",
+ (unsigned char *) resolution);
+ g_free (resolution);
+ }
+
+ g_object_notify (G_OBJECT (resource), "height");
+}
+
+/**
+ * gupnp_didl_lite_resource_set_color_depth:
+ * @resource: A #GUPnPDIDLLiteResource
+ * @color_depth: The color-depth
+ *
+ * Set the color-depth of this image/video resource. Passing a negative number
+ * will unset this property.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_resource_set_color_depth (GUPnPDIDLLiteResource *resource,
+ int color_depth)
+{
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_RESOURCE (resource));
+
+ if (color_depth < 0)
+ xmlUnsetProp (resource->priv->xml_node,
+ (unsigned char *) "colorDepth");
+ else {
+ char *str;
+
+ str = g_strdup_printf ("%d", color_depth);
+ xmlSetProp (resource->priv->xml_node,
+ (unsigned char *) "colorDepth",
+ (unsigned char *) str);
+ g_free (str);
+ }
+
+ g_object_notify (G_OBJECT (resource), "color-depth");
+}
+
diff --git a/libgupnp-av/gupnp-didl-lite-resource.h b/libgupnp-av/gupnp-didl-lite-resource.h
new file mode 100644
index 0000000..1f3b8f3
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-resource.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2007, 2008 OpenedHand Ltd.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ * Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DIDL_LITE_RESOURCE_H__
+#define __GUPNP_DIDL_LITE_RESOURCE_H__
+
+#include <stdarg.h>
+#include <glib-object.h>
+#include <glib.h>
+#include <libxml/tree.h>
+#include <libgupnp/gupnp.h>
+
+#include "gupnp-dlna.h"
+#include "gupnp-protocol-info.h"
+
+G_BEGIN_DECLS
+
+GType
+gupnp_didl_lite_resource_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_DIDL_LITE_RESOURCE \
+ (gupnp_didl_lite_resource_get_type ())
+#define GUPNP_DIDL_LITE_RESOURCE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_RESOURCE, \
+ GUPnPDIDLLiteResource))
+#define GUPNP_DIDL_LITE_RESOURCE_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_RESOURCE, \
+ GUPnPDIDLLiteResourceClass))
+#define GUPNP_IS_DIDL_LITE_RESOURCE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_RESOURCE))
+#define GUPNP_IS_DIDL_LITE_RESOURCE_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_RESOURCE))
+#define GUPNP_DIDL_LITE_RESOURCE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_DIDL_LITE_RESOURCE, \
+ GUPnPDIDLLiteResourceClass))
+
+typedef struct _GUPnPDIDLLiteResourcePrivate GUPnPDIDLLiteResourcePrivate;
+
+typedef struct {
+ GObject parent;
+
+ GUPnPDIDLLiteResourcePrivate *priv;
+} GUPnPDIDLLiteResource;
+
+typedef struct {
+ GObjectClass parent_class;
+
+ /* future padding */
+ void (* _gupnp_reserved1) (void);
+ void (* _gupnp_reserved2) (void);
+ void (* _gupnp_reserved3) (void);
+ void (* _gupnp_reserved4) (void);
+} GUPnPDIDLLiteResourceClass;
+
+void
+gupnp_didl_lite_resource_set_uri (GUPnPDIDLLiteResource *resource,
+ const char *uri);
+
+void
+gupnp_didl_lite_resource_set_import_uri (GUPnPDIDLLiteResource *resource,
+ const char *import_uri);
+
+void
+gupnp_didl_lite_resource_set_protocol_info
+ (GUPnPDIDLLiteResource *resource,
+ GUPnPProtocolInfo *info);
+
+void
+gupnp_didl_lite_resource_set_size (GUPnPDIDLLiteResource *resource,
+ long size);
+
+void
+gupnp_didl_lite_resource_set_size64 (GUPnPDIDLLiteResource *resource,
+ gint64 size);
+
+void
+gupnp_didl_lite_resource_set_duration (GUPnPDIDLLiteResource *resource,
+ long duration);
+
+void
+gupnp_didl_lite_resource_set_bitrate (GUPnPDIDLLiteResource *resource,
+ int bitrate);
+
+void
+gupnp_didl_lite_resource_set_sample_freq
+ (GUPnPDIDLLiteResource *resource,
+ int sample_freq);
+
+void
+gupnp_didl_lite_resource_set_bits_per_sample
+ (GUPnPDIDLLiteResource *resource,
+ int sample_size);
+
+void
+gupnp_didl_lite_resource_set_protection (GUPnPDIDLLiteResource *resource,
+ const char *protection);
+
+void
+gupnp_didl_lite_resource_set_audio_channels
+ (GUPnPDIDLLiteResource *resource,
+ int n_channels);
+
+void
+gupnp_didl_lite_resource_set_width (GUPnPDIDLLiteResource *resource,
+ int width);
+
+void
+gupnp_didl_lite_resource_set_height (GUPnPDIDLLiteResource *resource,
+ int height);
+
+void
+gupnp_didl_lite_resource_set_color_depth
+ (GUPnPDIDLLiteResource *resource,
+ int color_depth);
+
+xmlNode *
+gupnp_didl_lite_resource_get_xml_node (GUPnPDIDLLiteResource *resource);
+
+const char *
+gupnp_didl_lite_resource_get_uri (GUPnPDIDLLiteResource *resource);
+
+const char *
+gupnp_didl_lite_resource_get_import_uri (GUPnPDIDLLiteResource *resource);
+
+GUPnPProtocolInfo *
+gupnp_didl_lite_resource_get_protocol_info
+ (GUPnPDIDLLiteResource *resource);
+
+long
+gupnp_didl_lite_resource_get_size (GUPnPDIDLLiteResource *resource);
+
+gint64
+gupnp_didl_lite_resource_get_size64 (GUPnPDIDLLiteResource *resource);
+
+long
+gupnp_didl_lite_resource_get_duration (GUPnPDIDLLiteResource *resource);
+
+int
+gupnp_didl_lite_resource_get_bitrate (GUPnPDIDLLiteResource *resource);
+
+int
+gupnp_didl_lite_resource_get_sample_freq
+ (GUPnPDIDLLiteResource *resource);
+
+int
+gupnp_didl_lite_resource_get_bits_per_sample
+ (GUPnPDIDLLiteResource *resource);
+
+const char *
+gupnp_didl_lite_resource_get_protection (GUPnPDIDLLiteResource *resource);
+
+int
+gupnp_didl_lite_resource_get_audio_channels
+ (GUPnPDIDLLiteResource *resource);
+
+int
+gupnp_didl_lite_resource_get_width (GUPnPDIDLLiteResource *resource);
+
+int
+gupnp_didl_lite_resource_get_height (GUPnPDIDLLiteResource *resource);
+
+int
+gupnp_didl_lite_resource_get_color_depth
+ (GUPnPDIDLLiteResource *resource);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DIDL_LITE_RESOURCE_H__ */
diff --git a/libgupnp-av/gupnp-didl-lite-writer.c b/libgupnp-av/gupnp-didl-lite-writer.c
new file mode 100644
index 0000000..baec6fc
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-writer.c
@@ -0,0 +1,640 @@
+/*
+ * Copyright (C) 2007, 2008 OpenedHand Ltd.
+ *
+ * Authors: Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gupnp-didl-lite-writer
+ * @short_description: DIDL-Lite fragment writer
+ *
+ * #GUPnPDIDLLiteWriter is a helper class for writing DIDL-Lite fragments.
+ */
+
+#include <string.h>
+
+#include "gupnp-didl-lite-writer.h"
+#include "gupnp-didl-lite-object.h"
+#include "gupnp-didl-lite-object-private.h"
+#include "gupnp-didl-lite-descriptor-private.h"
+
+#include "xml-util.h"
+
+G_DEFINE_TYPE (GUPnPDIDLLiteWriter,
+ gupnp_didl_lite_writer,
+ G_TYPE_OBJECT);
+
+struct _GUPnPDIDLLiteWriterPrivate {
+ xmlNode *xml_node;
+ GUPnPXMLDoc *xml_doc;
+
+ xmlNs *upnp_ns;
+ xmlNs *dc_ns;
+ xmlNs *dlna_ns;
+
+ char *language;
+};
+
+enum {
+ PROP_0,
+ PROP_XML_NODE,
+ PROP_LANGUAGE,
+};
+
+static int
+compare_prop (const char *a, xmlAttr *attr)
+{
+ const char *p;
+ char *parent_name;
+ char *attr_name;
+ int ret = -1;
+
+ if (attr->ns != NULL)
+ attr_name = g_strjoin (":", attr->ns->prefix, attr->name, NULL);
+ else
+ attr_name = g_strdup ((const char *) attr->name);
+
+ if (attr->parent->ns != NULL)
+ parent_name = g_strjoin (":",
+ attr->parent->ns->prefix,
+ attr->parent->name,
+ NULL);
+ else
+ parent_name = g_strdup ((const char *) attr->parent->name);
+
+ p = strstr (a, "@");
+ if (p)
+ if (p == a)
+ /* Top-level property */
+ ret = strcmp (a + 1, attr_name);
+ else
+ ret = strncmp (a, parent_name, p - a) ||
+ strcmp (p + 1, attr_name);
+ else
+ ret = strcmp (a, attr_name);
+
+ g_free (attr_name);
+ g_free (parent_name);
+
+ return ret;
+}
+
+static gboolean
+is_attribute_forbidden (xmlAttr *attr,
+ GList *allowed)
+{
+ return g_list_find_custom (allowed,
+ attr,
+ (GCompareFunc) compare_prop) == NULL;
+}
+
+static int
+compare_node_name (const char *a, const char *b)
+{
+ const char *p;
+ int len;
+
+ if (a[0] == '@')
+ /* Filer is for top-level property */
+ return -1;
+
+ p = strstr (a, "@");
+ if (p != NULL)
+ /* Compare only the string before '@' */
+ len = p - a;
+ else
+ len = strlen (a);
+
+ return strncmp (a, b, len);
+}
+
+static gboolean
+is_node_forbidden (xmlNode *node,
+ GList *allowed,
+ const char *ns)
+{
+ char *name;
+ gboolean ret;
+
+ if (ns != NULL)
+ name = g_strjoin (":", ns, node->name, NULL);
+ else
+ name = g_strdup ((const char *) node->name);
+
+ ret = g_list_find_custom (allowed,
+ name,
+ (GCompareFunc) compare_node_name) == NULL;
+
+ g_free (name);
+
+ return ret;
+}
+
+static gboolean
+is_container_standard_prop (const char *name,
+ const char *namespace,
+ const char *upnp_class)
+{
+ return g_strcmp0 (upnp_class, "object.container.storageFolder") == 0 &&
+ g_strcmp0 (namespace, "upnp") == 0 &&
+ strcmp (name, "storageUsed") == 0;
+}
+
+static gboolean
+is_standard_prop (const char *name,
+ const char *namespace,
+ const char *parent_name)
+{
+ return strcmp (name, "id") == 0 ||
+ strcmp (name, "parentID") == 0 ||
+ strcmp (name, "restricted") == 0 ||
+ (g_strcmp0 (namespace, "dc") == 0 &&
+ strcmp (name, "title") == 0) ||
+ (g_strcmp0 (namespace, "upnp") == 0 &&
+ strcmp (name, "class") == 0) ||
+ (g_strcmp0 (parent_name, "res") == 0 &&
+ strcmp (name, "protocolInfo") == 0);
+}
+
+static void
+filter_attributes (xmlNode *node,
+ GList *allowed,
+ GUPnPDIDLLiteWriter *writer)
+{
+ xmlAttr *attr;
+ GList *forbidden = NULL;
+ GList *l;
+
+ /* Find forbidden properties */
+ for (attr = node->properties; attr != NULL; attr = attr->next)
+ if (!is_standard_prop ((const char *) attr->name,
+ NULL,
+ (const char *) attr->parent->name) &&
+ is_attribute_forbidden (attr, allowed))
+ forbidden = g_list_append (forbidden, attr);
+
+ /* Now unset forbidden properties */
+ for (l = forbidden; l != NULL; l = l->next)
+ xmlRemoveProp ((xmlAttr *) l->data);
+
+ g_list_free (forbidden);
+}
+
+static void
+filter_node (xmlNode *node,
+ GList *allowed,
+ GUPnPDIDLLiteWriter *writer)
+{
+ xmlNode *child;
+ GList *forbidden = NULL;
+ GList *l;
+ gboolean is_container;
+ const char *container_class = NULL;
+
+ filter_attributes (node, allowed, writer);
+
+ if (strcmp ((const char *) node->name, "container") == 0) {
+ is_container = TRUE;
+ container_class = xml_util_get_child_element_content (node,
+ "class");
+ }
+
+ forbidden = NULL;
+ for (child = node->children; child != NULL; child = child->next) {
+ const char *ns = NULL;
+
+ if (xmlNodeIsText (child))
+ continue;
+
+ if (child->ns != NULL)
+ ns = (const char *) child->ns->prefix;
+
+ if (!(is_container && is_container_standard_prop
+ ((const char *) child->name,
+ ns,
+ container_class)) &&
+ !is_standard_prop ((const char *) child->name,
+ ns,
+ (const char *) node->name) &&
+ is_node_forbidden (child, allowed, ns))
+ forbidden = g_list_append (forbidden, child);
+ }
+
+ /* Now remove the forbidden nodes */
+ for (l = forbidden; l != NULL; l = l->next) {
+ xmlNode *n;
+
+ n = (xmlNode *) l->data;
+
+ xmlUnlinkNode (n);
+ xmlFreeNode (n);
+ }
+
+ g_list_free (forbidden);
+
+ /* Recurse */
+ for (child = node->children; child != NULL; child = child->next)
+ if (!xmlNodeIsText (child))
+ filter_node (child, allowed, writer);
+}
+
+static void
+gupnp_didl_lite_writer_init (GUPnPDIDLLiteWriter *writer)
+{
+ writer->priv = G_TYPE_INSTANCE_GET_PRIVATE (writer,
+ GUPNP_TYPE_DIDL_LITE_WRITER,
+ GUPnPDIDLLiteWriterPrivate);
+}
+
+static void
+gupnp_didl_lite_writer_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+
+{
+ GUPnPDIDLLiteWriter *writer;
+
+ writer = GUPNP_DIDL_LITE_WRITER (object);
+
+ switch (property_id) {
+ case PROP_LANGUAGE:
+ writer->priv->language = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_writer_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPDIDLLiteWriter *writer;
+
+ writer = GUPNP_DIDL_LITE_WRITER (object);
+
+ switch (property_id) {
+ case PROP_XML_NODE:
+ g_value_set_pointer
+ (value, gupnp_didl_lite_writer_get_xml_node (writer));
+ break;
+ case PROP_LANGUAGE:
+ g_value_set_string
+ (value, gupnp_didl_lite_writer_get_language (writer));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_didl_lite_writer_constructed (GObject *object)
+{
+ GObjectClass *object_class;
+ GUPnPDIDLLiteWriterPrivate *priv;
+ xmlDoc *doc;
+
+ priv = GUPNP_DIDL_LITE_WRITER (object)->priv;
+
+ doc = xmlNewDoc ((unsigned char *) "1.0");
+ priv->xml_doc = gupnp_xml_doc_new (doc);
+
+ priv->xml_node = xmlNewDocNode (priv->xml_doc->doc,
+ NULL,
+ (unsigned char *) "DIDL-Lite",
+ NULL);
+ xmlDocSetRootElement (priv->xml_doc->doc, priv->xml_node);
+ priv->dc_ns = xmlNewNs (priv->xml_node,
+ (unsigned char *)
+ "http://purl.org/dc/elements/1.1/",
+ (unsigned char *)
+ GUPNP_DIDL_LITE_WRITER_NAMESPACE_DC);
+ priv->upnp_ns = xmlNewNs (priv->xml_node,
+ (unsigned char *)
+ "urn:schemas-upnp-org:metadata-1-0/upnp/",
+ (unsigned char *)
+ GUPNP_DIDL_LITE_WRITER_NAMESPACE_UPNP);
+ priv->dlna_ns = xmlNewNs (priv->xml_node,
+ (unsigned char *)
+ "urn:schemas-dlna-org:metadata-1-0/",
+ (unsigned char *)
+ GUPNP_DIDL_LITE_WRITER_NAMESPACE_DLNA);
+ xmlNewNs (priv->xml_node,
+ (unsigned char *)
+ "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/",
+ NULL);
+
+ if (priv->language)
+ xmlSetProp (priv->xml_node,
+ (unsigned char *) "lang",
+ (unsigned char *) priv->language);
+
+ object_class = G_OBJECT_CLASS (gupnp_didl_lite_writer_parent_class);
+ if (object_class->constructed != NULL)
+ object_class->constructed (object);
+}
+
+static void
+gupnp_didl_lite_writer_dispose (GObject *object)
+{
+ GObjectClass *object_class;
+ GUPnPDIDLLiteWriterPrivate *priv;
+
+ priv = GUPNP_DIDL_LITE_WRITER (object)->priv;
+
+ if (priv->xml_doc) {
+ g_object_unref (priv->xml_doc);
+ priv->xml_doc = NULL;
+ }
+
+ object_class = G_OBJECT_CLASS (gupnp_didl_lite_writer_parent_class);
+ object_class->dispose (object);
+}
+
+static void
+gupnp_didl_lite_writer_finalize (GObject *object)
+{
+ GObjectClass *object_class;
+ GUPnPDIDLLiteWriterPrivate *priv;
+
+ priv = GUPNP_DIDL_LITE_WRITER (object)->priv;
+
+ if (priv->language)
+ g_free (priv->language);
+
+ object_class = G_OBJECT_CLASS (gupnp_didl_lite_writer_parent_class);
+ object_class->finalize (object);
+}
+
+static void
+gupnp_didl_lite_writer_class_init (GUPnPDIDLLiteWriterClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = gupnp_didl_lite_writer_set_property;
+ object_class->get_property = gupnp_didl_lite_writer_get_property;
+ object_class->constructed = gupnp_didl_lite_writer_constructed;
+ object_class->dispose = gupnp_didl_lite_writer_dispose;
+ object_class->finalize = gupnp_didl_lite_writer_finalize;
+
+ g_type_class_add_private (klass, sizeof (GUPnPDIDLLiteWriterPrivate));
+
+ /**
+ * GUPnPDIDLLiteWriter:xml-node:
+ *
+ * The pointer to root node in XML document.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_XML_NODE,
+ g_param_spec_pointer ("xml-node",
+ "XMLNode",
+ "The pointer to root node in XML"
+ " document.",
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPDIDLLiteWriter:language:
+ *
+ * The language the DIDL-Lite fragment is in.
+ *
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_LANGUAGE,
+ g_param_spec_string ("language",
+ "Language",
+ "The language the DIDL-Lite fragment"
+ " is in.",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+}
+
+/**
+ * gupnp_didl_lite_writer_new:
+ * @language: The language the DIDL-Lite fragment is in, or NULL
+ *
+ * Return value: A new #GUPnPDIDLLiteWriter object.
+ **/
+GUPnPDIDLLiteWriter *
+gupnp_didl_lite_writer_new (const char *language)
+{
+ return g_object_new (GUPNP_TYPE_DIDL_LITE_WRITER,
+ "language", language,
+ NULL);
+}
+
+/**
+ * gupnp_didl_lite_writer_add_item:
+ * @writer: A #GUPnPDIDLLiteWriter
+ *
+ * Creates a new item, attaches it to @writer and returns it.
+ *
+ * Returns: (transfer full): A new #GUPnPDIDLLiteItem object. Unref after usage.
+ **/
+GUPnPDIDLLiteItem *
+gupnp_didl_lite_writer_add_item (GUPnPDIDLLiteWriter *writer)
+{
+ xmlNode *item_node;
+ GUPnPDIDLLiteObject *object;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer), NULL);
+
+ item_node = xmlNewChild (writer->priv->xml_node,
+ NULL,
+ (unsigned char *) "item",
+ NULL);
+
+ object = gupnp_didl_lite_object_new_from_xml (item_node,
+ writer->priv->xml_doc,
+ writer->priv->upnp_ns,
+ writer->priv->dc_ns,
+ writer->priv->dlna_ns);
+ return GUPNP_DIDL_LITE_ITEM (object);
+}
+
+/**
+ * gupnp_didl_lite_writer_add_container:
+ * @writer: A #GUPnPDIDLLiteWriter
+ *
+ * Creates a new container, attaches it to @writer and returns it.
+ *
+ * Returns: (transfer full): A new #GUPnPDIDLLiteContainer object. Unref after usage.
+ **/
+GUPnPDIDLLiteContainer *
+gupnp_didl_lite_writer_add_container (GUPnPDIDLLiteWriter *writer)
+{
+ xmlNode *container_node;
+ GUPnPDIDLLiteObject *object;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer), NULL);
+
+ container_node = xmlNewChild (writer->priv->xml_node,
+ NULL,
+ (unsigned char *) "container",
+ NULL);
+
+ object = gupnp_didl_lite_object_new_from_xml (container_node,
+ writer->priv->xml_doc,
+ writer->priv->upnp_ns,
+ writer->priv->dc_ns,
+ writer->priv->dlna_ns);
+ return GUPNP_DIDL_LITE_CONTAINER (object);
+}
+
+/**
+ * gupnp_didl_lite_writer_add_descriptor:
+ * @writer: A #GUPnPDIDLLiteWriter
+ *
+ * Creates a new descriptor, attaches it to @object and returns it.
+ *
+ * Returns: (transfer full): A new #GUPnPDIDLLiteDescriptor object. Unref after usage.
+ **/
+GUPnPDIDLLiteDescriptor *
+gupnp_didl_lite_writer_add_descriptor (GUPnPDIDLLiteWriter *writer)
+{
+ xmlNode *desc_node;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer), NULL);
+
+ desc_node = xmlNewChild (writer->priv->xml_node,
+ NULL,
+ (unsigned char *) "desc",
+ NULL);
+
+ return gupnp_didl_lite_descriptor_new_from_xml (desc_node,
+ writer->priv->xml_doc);
+}
+
+/**
+ * gupnp_didl_lite_writer_get_string:
+ * @writer: A #GUPnPDIDLLiteWriter
+ *
+ * Creates a string representation of the DIDL-Lite XML document.
+ *
+ * Return value: The DIDL-Lite XML string, or %NULL. #g_free after usage.
+ **/
+char *
+gupnp_didl_lite_writer_get_string (GUPnPDIDLLiteWriter *writer)
+{
+ xmlBuffer *buffer;
+ char *ret;
+
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer), NULL);
+
+ buffer = xmlBufferCreate ();
+ xmlNodeDump (buffer,
+ writer->priv->xml_doc->doc,
+ writer->priv->xml_node,
+ 0,
+ 0);
+ ret = g_strndup ((char *) xmlBufferContent (buffer),
+ xmlBufferLength (buffer));
+ xmlBufferFree (buffer);
+
+ return ret;
+}
+
+/**
+ * gupnp_didl_lite_writer_get_xml_node:
+ * @writer: The #GUPnPDIDLLiteWriter
+ *
+ * Get the pointer to root node in XML document.
+ *
+ * Returns: (transfer none): The pointer to root node in XML document.
+ **/
+xmlNode *
+gupnp_didl_lite_writer_get_xml_node (GUPnPDIDLLiteWriter *writer)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer), NULL);
+
+ return writer->priv->xml_node;
+}
+
+/**
+ * gupnp_didl_lite_writer_get_language:
+ * @writer: #GUPnPDIDLLiteWriter
+ *
+ * Get the language the DIDL-Lite fragment is in.
+ *
+ * Returns: (transfer none): The language of the @writer, or %NULL.
+ **/
+const char *
+gupnp_didl_lite_writer_get_language (GUPnPDIDLLiteWriter *writer)
+{
+ g_return_val_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer), NULL);
+
+ return writer->priv->language;
+}
+
+/**
+ * gupnp_didl_lite_writer_filter:
+ * @writer: A #GUPnPDIDLLiteWriter
+ * @filter: A filter string
+ *
+ * Clears the DIDL-Lite XML document of the properties not specified in the
+ * @filter. The passed filter string would typically come from the 'Filter'
+ * argument of Browse or Search actions from a ContentDirectory control point.
+ * Please refer to Section 2.3.15 of UPnP AV ContentDirectory version 3
+ * specification for details on this string.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_didl_lite_writer_filter (GUPnPDIDLLiteWriter *writer,
+ const char *filter)
+{
+ char **tokens;
+ GList *allowed = NULL;
+ unsigned short i;
+ xmlNode *node;
+
+ g_return_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer));
+ g_return_if_fail (filter != NULL);
+
+ if (filter[0] == '*')
+ return; /* Wildcard */
+
+ tokens = g_strsplit (filter, ",", -1);
+ g_return_if_fail (tokens != NULL);
+
+ for (i = 0; tokens[i] != NULL; i++)
+ allowed = g_list_append (allowed, tokens[i]);
+
+ for (node = writer->priv->xml_node->children;
+ node != NULL;
+ node = node->next)
+ filter_node (node, allowed, writer);
+
+ g_list_free (allowed);
+ g_strfreev (tokens);
+}
diff --git a/libgupnp-av/gupnp-didl-lite-writer.h b/libgupnp-av/gupnp-didl-lite-writer.h
new file mode 100644
index 0000000..33da37f
--- /dev/null
+++ b/libgupnp-av/gupnp-didl-lite-writer.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2007, 2008 OpenedHand Ltd.
+ *
+ * Authors: Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DIDL_LITE_WRITER_H__
+#define __GUPNP_DIDL_LITE_WRITER_H__
+
+
+#include <stdarg.h>
+#include <glib-object.h>
+#include <libsoup/soup-uri.h>
+
+#include "gupnp-dlna.h"
+#include "gupnp-didl-lite-item.h"
+#include "gupnp-didl-lite-container.h"
+#include "gupnp-didl-lite-resource.h"
+#include "gupnp-didl-lite-descriptor.h"
+
+G_BEGIN_DECLS
+
+GType
+gupnp_didl_lite_writer_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_DIDL_LITE_WRITER \
+ (gupnp_didl_lite_writer_get_type ())
+#define GUPNP_DIDL_LITE_WRITER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_WRITER, \
+ GUPnPDIDLLiteWriter))
+#define GUPNP_DIDL_LITE_WRITER_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_CAST ((obj), \
+ GUPNP_TYPE_DIDL_LITE_WRITER, \
+ GUPnPDIDLLiteWriterClass))
+#define GUPNP_IS_DIDL_LITE_WRITER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_WRITER))
+#define GUPNP_IS_DIDL_LITE_WRITER_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+ GUPNP_TYPE_DIDL_LITE_WRITER))
+#define GUPNP_DIDL_LITE_WRITER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_DIDL_LITE_WRITER, \
+ GUPnPDIDLLiteWriterClass))
+
+typedef struct _GUPnPDIDLLiteWriterPrivate GUPnPDIDLLiteWriterPrivate;
+
+typedef struct {
+ GObject parent;
+
+ GUPnPDIDLLiteWriterPrivate *priv;
+} GUPnPDIDLLiteWriter;
+
+typedef struct {
+ GObjectClass parent_class;
+
+ /* future padding */
+ void (* _gupnp_reserved1) (void);
+ void (* _gupnp_reserved2) (void);
+ void (* _gupnp_reserved3) (void);
+ void (* _gupnp_reserved4) (void);
+} GUPnPDIDLLiteWriterClass;
+
+#define GUPNP_DIDL_LITE_WRITER_NAMESPACE_DC "dc"
+#define GUPNP_DIDL_LITE_WRITER_NAMESPACE_UPNP "upnp"
+#define GUPNP_DIDL_LITE_WRITER_NAMESPACE_DLNA "dlna"
+
+GUPnPDIDLLiteWriter *
+gupnp_didl_lite_writer_new (const char *language);
+
+GUPnPDIDLLiteItem *
+gupnp_didl_lite_writer_add_item (GUPnPDIDLLiteWriter *writer);
+
+GUPnPDIDLLiteContainer *
+gupnp_didl_lite_writer_add_container (GUPnPDIDLLiteWriter *writer);
+
+GUPnPDIDLLiteDescriptor *
+gupnp_didl_lite_writer_add_descriptor (GUPnPDIDLLiteWriter *writer);
+
+xmlNode *
+gupnp_didl_lite_writer_get_xml_node (GUPnPDIDLLiteWriter *writer);
+
+char *
+gupnp_didl_lite_writer_get_string (GUPnPDIDLLiteWriter *writer);
+
+const char *
+gupnp_didl_lite_writer_get_language (GUPnPDIDLLiteWriter *writer);
+
+void
+gupnp_didl_lite_writer_filter (GUPnPDIDLLiteWriter *writer,
+ const char *filter);
+
+G_END_DECLS
+
+#endif /* __GUPNP_DIDL_LITE_WRITER_H__ */
diff --git a/libgupnp-av/gupnp-dlna.c b/libgupnp-av/gupnp-dlna.c
new file mode 100644
index 0000000..97ff080
--- /dev/null
+++ b/libgupnp-av/gupnp-dlna.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Authors: Zeeshan Ali <zeeshanak@gnome.org>
+ * <zeeshan.ali@nokia.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "gupnp-dlna.h"
+
+GType
+gupnp_dlna_conversion_get_type (void)
+{
+ static GType type = 0;
+
+ if (type == 0) {
+ static const GFlagsValue values[] = {
+ { GUPNP_DLNA_CONVERSION_NONE,
+ "GUPNP_DLNA_CONVERSION_NONE",
+ "none" },
+ { GUPNP_DLNA_CONVERSION_TRANSCODED,
+ "GUPNP_DLNA_CONVERSION_TRANSCODED",
+ "transcoded" },
+ { 0, NULL, NULL }
+ };
+
+ type = g_flags_register_static
+ (g_intern_static_string ("GUPnPDLNAConversion"),
+ values);
+ }
+
+ return type;
+}
+
+GType
+gupnp_dlna_operation_get_type (void)
+{
+ static GType type = 0;
+
+ if (type == 0) {
+ static const GFlagsValue values[] = {
+ { GUPNP_DLNA_OPERATION_NONE,
+ "GUPNP_DLNA_OPERATION_NONE",
+ "none" },
+ { GUPNP_DLNA_OPERATION_RANGE,
+ "GUPNP_DLNA_OPERATION_RANGE",
+ "range" },
+ { GUPNP_DLNA_OPERATION_TIMESEEK,
+ "GUPNP_DLNA_OPERATION_TIMESEEK",
+ "timeseek" },
+ { 0, NULL, NULL }
+ };
+
+ type = g_flags_register_static
+ (g_intern_static_string ("GUPnPDLNAOperation"),
+ values);
+ }
+
+ return type;
+}
+
+GType
+gupnp_dlna_flags_get_type (void)
+{
+ static GType type = 0;
+
+ if (type == 0) {
+ static const GFlagsValue values[] = {
+ { GUPNP_DLNA_FLAGS_NONE,
+ "GUPNP_DLNA_FLAGS_NONE",
+ "none" },
+ { GUPNP_DLNA_FLAGS_SENDER_PACED,
+ "GUPNP_DLNA_FLAGS_SENDER_PACED",
+ "sender-paced" },
+ { GUPNP_DLNA_FLAGS_TIME_BASED_SEEK,
+ "GUPNP_DLNA_FLAGS_TIME_BASED_SEEK",
+ "time-based-seek" },
+ { GUPNP_DLNA_FLAGS_BYTE_BASED_SEEK,
+ "GUPNP_DLNA_FLAGS_BYTE_BASED_SEEK",
+ "byte-based-seek" },
+ { GUPNP_DLNA_FLAGS_PLAY_CONTAINER,
+ "GUPNP_DLNA_FLAGS_PLAY_CONTAINER",
+ "play-container" },
+ { GUPNP_DLNA_FLAGS_S0_INCREASE,
+ "GUPNP_DLNA_FLAGS_S0_INCREASE",
+ "s0-increase" },
+ { GUPNP_DLNA_FLAGS_SN_INCREASE,
+ "GUPNP_DLNA_FLAGS_SN_INCREASE",
+ "sn-increase" },
+ { GUPNP_DLNA_FLAGS_RTSP_PAUSE,
+ "GUPNP_DLNA_FLAGS_RTSP_PAUSE",
+ "rtsp-pause" },
+ { GUPNP_DLNA_FLAGS_STREAMING_TRANSFER_MODE,
+ "GUPNP_DLNA_FLAGS_STREAMING_TRANSFER_MODE",
+ "streaming-transfer-mode" },
+ { GUPNP_DLNA_FLAGS_INTERACTIVE_TRANSFER_MODE,
+ "GUPNP_DLNA_FLAGS_INTERACTIVE_TRANSFER_MODE",
+ "interactive-transfer-mode" },
+ { GUPNP_DLNA_FLAGS_BACKGROUND_TRANSFER_MODE,
+ "GUPNP_DLNA_FLAGS_BACKGROUND_TRANSFER_MODE",
+ "background-transfer-mode" },
+ { GUPNP_DLNA_FLAGS_CONNECTION_STALL,
+ "GUPNP_DLNA_FLAGS_CONNECTION_STALL",
+ "connection-stall" },
+ { GUPNP_DLNA_FLAGS_DLNA_V15,
+ "GUPNP_DLNA_FLAGS_DLNA_V15",
+ "dlna-v15" },
+ { 0, NULL, NULL }
+ };
+
+ type = g_flags_register_static
+ (g_intern_static_string ("GUPnPDLNAFlags"),
+ values);
+ }
+
+ return type;
+}
+
+GType
+gupnp_ocm_flags_get_type (void)
+{
+ static GType type = 0;
+
+ if (type == 0) {
+ static const GFlagsValue values[] = {
+ { GUPNP_OCM_FLAGS_NONE,
+ "GUPNP_OCM_FLAGS_NONE",
+ "none" },
+ { GUPNP_OCM_FLAGS_UPLOAD,
+ "GUPNP_OCM_FLAGS_UPLOAD",
+ "upload" },
+ { GUPNP_OCM_FLAGS_CREATE_CONTAINER,
+ "GUPNP_OCM_FLAGS_CREATE_CONTAINER",
+ "create-container" },
+ { GUPNP_OCM_FLAGS_DESTROYABLE,
+ "GUPNP_OCM_FLAGS_DESTROYABLE",
+ "destroyable" },
+ { GUPNP_OCM_FLAGS_UPLOAD_DESTROYABLE,
+ "GUPNP_OCM_FLAGS_UPLOAD_DESTROYABLE",
+ "upload-destroyable" },
+ { GUPNP_OCM_FLAGS_CHANGE_METADATA,
+ "GUPNP_OCM_FLAGS_CHANGE_METADATA",
+ "change-metadata" },
+ { 0, NULL, NULL }
+ };
+
+ type = g_flags_register_static
+ (g_intern_static_string ("GUPnPOCMFlags"),
+ values);
+ }
+
+ return type;
+}
diff --git a/libgupnp-av/gupnp-dlna.h b/libgupnp-av/gupnp-dlna.h
new file mode 100644
index 0000000..c0beb20
--- /dev/null
+++ b/libgupnp-av/gupnp-dlna.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2007, 2008 OpenedHand Ltd.
+ *
+ * Authors: Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_DLNA_H__
+#define __GUPNP_DLNA_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+GType
+gupnp_dlna_conversion_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_DLNA_CONVERSION (gupnp_dlna_conversion_get_type ())
+
+/**
+ * GUPnPDLNAConversion:
+ * @GUPNP_DLNA_CONVERSION_NONE: Content is in original source format
+ * @GUPNP_DLNA_CONVERSION_TRANSCODED: Content is transcoded
+ *
+ * The DLNA conversion flags for a resource.
+ *
+ **/
+typedef enum {
+ GUPNP_DLNA_CONVERSION_NONE = 0,
+ GUPNP_DLNA_CONVERSION_TRANSCODED = 1
+} GUPnPDLNAConversion;
+
+GType
+gupnp_dlna_operation_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_DLNA_OPERATION (gupnp_dlna_operation_get_type ())
+
+/**
+ * GUPnPDLNAOperation:
+ * @GUPNP_DLNA_OPERATION_NONE: Resource does not support seeking of any type
+ * @GUPNP_DLNA_OPERATION_RANGE: Resource supports byte-seek
+ * @GUPNP_DLNA_OPERATION_TIMESEEK: Resource supports time-seek
+ *
+ * The seek operations supported by a resource.
+ *
+ **/
+typedef enum {
+ GUPNP_DLNA_OPERATION_NONE = 0x00,
+ GUPNP_DLNA_OPERATION_RANGE = 0x01,
+ GUPNP_DLNA_OPERATION_TIMESEEK = 0x10
+} GUPnPDLNAOperation;
+
+GType
+gupnp_dlna_flags_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_DLNA_FLAGS (gupnp_dlna_flags_get_type ())
+
+/**
+ * GUPnPDLNAFlags:
+ * @GUPNP_DLNA_FLAGS_NONE: No flags
+ * @GUPNP_DLNA_FLAGS_SENDER_PACED: Content source is the clock source during
+ * transport
+ * @GUPNP_DLNA_FLAGS_TIME_BASED_SEEK: Limited Operation: time-seek supported
+ * @GUPNP_DLNA_FLAGS_BYTE_BASED_SEEK: Limited Operation: byte-seek supported
+ * @GUPNP_DLNA_FLAGS_PLAY_CONTAINER: Resource supports 'Container Playback'
+ * @GUPNP_DLNA_FLAGS_S0_INCREASE: Content does not have a fixed beginning
+ * @GUPNP_DLNA_FLAGS_SN_INCREASE: Content does not have a fixed end
+ * @GUPNP_DLNA_FLAGS_RTSP_PAUSE: RTSP resource supports pausing of media
+ * transfer
+ * @GUPNP_DLNA_FLAGS_STREAMING_TRANSFER_MODE: Streaming transfer mode supported
+ * @GUPNP_DLNA_FLAGS_INTERACTIVE_TRANSFER_MODE: Interactive transfer mode
+ * supported
+ * @GUPNP_DLNA_FLAGS_BACKGROUND_TRANSFER_MODE: Background transfer mode
+ * supported
+ * @GUPNP_DLNA_FLAGS_CONNECTION_STALL: No content transfer when paused.
+ * @GUPNP_DLNA_FLAGS_DLNA_V15: DLNAv1.5 version flag
+ *
+ * The miscellaneous operations supported by a resource. For details on these
+ * flags please refer to section 7.3.37.2 of DLNA Networked Device
+ * Interoperability Guidelines Volume 1, October 2006.
+ *
+ **/
+typedef enum {
+ GUPNP_DLNA_FLAGS_NONE = 0,
+ GUPNP_DLNA_FLAGS_SENDER_PACED = (1 << 31),
+ GUPNP_DLNA_FLAGS_TIME_BASED_SEEK = (1 << 30),
+ GUPNP_DLNA_FLAGS_BYTE_BASED_SEEK = (1 << 29),
+ GUPNP_DLNA_FLAGS_PLAY_CONTAINER = (1 << 28),
+ GUPNP_DLNA_FLAGS_S0_INCREASE = (1 << 27),
+ GUPNP_DLNA_FLAGS_SN_INCREASE = (1 << 26),
+ GUPNP_DLNA_FLAGS_RTSP_PAUSE = (1 << 25),
+ GUPNP_DLNA_FLAGS_STREAMING_TRANSFER_MODE = (1 << 24),
+ GUPNP_DLNA_FLAGS_INTERACTIVE_TRANSFER_MODE = (1 << 23),
+ GUPNP_DLNA_FLAGS_BACKGROUND_TRANSFER_MODE = (1 << 22),
+ GUPNP_DLNA_FLAGS_CONNECTION_STALL = (1 << 21),
+ GUPNP_DLNA_FLAGS_DLNA_V15 = (1 << 20)
+} GUPnPDLNAFlags;
+
+/**
+ * GUPnPOCMFlags:
+ * @GUPNP_OCM_FLAGS_NONE: No flags
+ * @GUPNP_OCM_FLAGS_UPLOAD: Indicates support for content upload.
+ * @GUPNP_OCM_FLAGS_CREATE_CONTAINER: Indicates support for creation of child
+ * container.
+ * @GUPNP_OCM_FLAGS_DESTROYABLE: This object is destroyable.
+ * @GUPNP_OCM_FLAGS_UPLOAD_DESTROYABLE: Indicates support for upload of
+ * destroyable content.
+ * @GUPNP_OCM_FLAGS_CHANGE_METADATA: Indicates support for changing metadata.
+ *
+ * The DLNA OCM flags supported by a DIDL-Lite Object. For details on these
+ * flags please refer to section 7.3.118.4 of DLNA Networked Device
+ * Interoperability Guidelines Volume 1, October 2006.
+ *
+ **/
+typedef enum {
+ GUPNP_OCM_FLAGS_NONE = 0x0,
+ GUPNP_OCM_FLAGS_UPLOAD = 0x01,
+ GUPNP_OCM_FLAGS_CREATE_CONTAINER = 0x02,
+ GUPNP_OCM_FLAGS_DESTROYABLE = 0x04,
+ GUPNP_OCM_FLAGS_UPLOAD_DESTROYABLE = 0x08,
+ GUPNP_OCM_FLAGS_CHANGE_METADATA = 0x10
+} GUPnPOCMFlags;
+
+GType
+gupnp_ocm_flags_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_OCM_FLAGS (gupnp_ocm_flags_get_type ())
+
+G_END_DECLS
+
+#endif /* __GUPNP_DLNA_H__ */
diff --git a/libgupnp-av/gupnp-last-change-parser.c b/libgupnp-av/gupnp-last-change-parser.c
new file mode 100644
index 0000000..43aabe7
--- /dev/null
+++ b/libgupnp-av/gupnp-last-change-parser.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2007 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ * Copyright (C) 2007 OpenedHand Ltd
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ * Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gupnp-last-change-parser
+ * @short_description: A/V LastChange event XML parser
+ *
+ * #GUPnPLastChangeParser parses XML strings from LastChange events that are
+ * generated by AVTransport and RenderingControl services.
+ *
+ */
+
+
+#include <gobject/gvaluecollector.h>
+
+#include "gupnp-last-change-parser.h"
+#include "gvalue-util.h"
+#include "xml-util.h"
+
+G_DEFINE_TYPE (GUPnPLastChangeParser,
+ gupnp_last_change_parser,
+ G_TYPE_OBJECT);
+
+static void
+gupnp_last_change_parser_init (GUPnPLastChangeParser *parser)
+{
+}
+
+static void
+gupnp_last_change_parser_dispose (GObject *object)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (gupnp_last_change_parser_parent_class);
+ gobject_class->dispose (object);
+}
+
+static void
+gupnp_last_change_parser_class_init (GUPnPLastChangeParserClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gupnp_last_change_parser_dispose;
+}
+
+/* Reads a value of state variable @variable_name to an initialised GValue pair
+ * from the InstanceID node of a LastChange xml doc */
+static gboolean
+read_state_variable (const char *variable_name,
+ GValue *value,
+ xmlNode *instance_node)
+{
+ xmlNode *variable_node;
+ const char *val_str;
+
+ variable_node = xml_util_get_element (instance_node,
+ "InstanceID",
+ variable_name,
+ NULL);
+ if (!variable_node)
+ return FALSE;
+
+ val_str = xml_util_get_attribute_content (variable_node, "val");
+ if (!val_str) {
+ g_warning ("No value provided for variable \"%s\" in "
+ "LastChange event",
+ variable_name);
+
+ return FALSE;
+ }
+
+ gvalue_util_set_value_from_string (value, val_str);
+
+ return TRUE;
+}
+
+static xmlNode *
+get_instance_node (xmlDoc *doc,
+ guint instance_id)
+{
+ xmlNode *node;
+
+ for (node = doc->children;
+ node;
+ node = node->next) {
+ guint id;
+
+ id = xml_util_get_uint_attribute (node, "val", 0);
+ if (id == instance_id)
+ break;
+ }
+
+ return node;
+}
+
+/**
+ * gupnp_last_change_parser_new:
+ *
+ * Return value: A new #GUPnPLastChangeParser
+ **/
+GUPnPLastChangeParser *
+gupnp_last_change_parser_new (void)
+{
+ return g_object_new (GUPNP_TYPE_LAST_CHANGE_PARSER,
+ NULL);
+}
+
+/**
+ * gupnp_last_change_parser_parse_last_change_valist:
+ * @parser: A #GUPnPLastChangeParser
+ * @instance_id: The ID of the AV instance caller is interested in
+ * @last_change_xml: The xml from the "LastChange" event to parse
+ * @error: The location where to store any error, or NULL
+ * @var_args: A va_list of tuples of state variable name, state variable type,
+ * and state variable value location, terminated with NULL. The state variable
+ * values should be freed after use
+ *
+ * See gupnp_last_change_parser_parse_last_change(); this version takes a
+ * va_list for use by language bindings.
+ *
+ * Return value: TRUE on success.
+ **/
+gboolean
+gupnp_last_change_parser_parse_last_change_valist
+ (GUPnPLastChangeParser *parser,
+ guint instance_id,
+ const char *last_change_xml,
+ GError **error,
+ va_list var_args)
+{
+ const char *variable_name;
+ xmlDoc *doc;
+ xmlNode *instance_node;
+
+ g_return_val_if_fail (last_change_xml, FALSE);
+
+ doc = xmlParseDoc ((const xmlChar *) last_change_xml);
+ if (doc == NULL) {
+ g_set_error (error,
+ GUPNP_XML_ERROR,
+ GUPNP_XML_ERROR_PARSE,
+ "Could not parse LastChange xml");
+
+ return FALSE;
+ }
+
+ instance_node = get_instance_node (doc, instance_id);
+ if (instance_node == NULL) {
+ /* This is not an error since the caller of this function
+ * doesn't (need to) know if the instance of his interest is
+ * part of the LastChange event received.
+ */
+ xmlFreeDoc (doc);
+
+ return FALSE;
+ }
+
+ /* Variables */
+ variable_name = va_arg (var_args, const char *);
+ while (variable_name) {
+ GType variable_type;
+ GValue value = { 0, };
+ char *copy_error = NULL;
+
+ variable_type = va_arg (var_args, GType);
+
+ g_value_init (&value, variable_type);
+
+ if (read_state_variable (variable_name,
+ &value,
+ instance_node)) {
+ G_VALUE_LCOPY (&value, var_args, 0, &copy_error);
+ } else {
+ va_arg (var_args, gpointer);
+ }
+
+ g_value_unset (&value);
+
+ if (copy_error) {
+ g_warning ("Error copying value: %s", copy_error);
+
+ g_free (copy_error);
+ }
+
+ variable_name = va_arg (var_args, const char *);
+ }
+
+ /* Cleanup */
+ xmlFreeDoc (doc);
+
+ return TRUE;
+}
+
+/**
+ * gupnp_last_change_parser_parse_last_change:
+ * @parser: A #GUPnPLastChangeParser
+ * @instance_id: The ID of the AV instance caller is interested in
+ * @last_change_xml: The xml from the "LastChange" event to parse
+ * @error: The location where to store any error, or NULL
+ * @Varargs: tuples of state variable name, state variable type, and state
+ * variable value location, terminated with NULL. The state variable values
+ * should be freed after use.
+ *
+ * Parses the xml fragment from a LastChange event.
+ *
+ * Return value: TRUE on success.
+ **/
+gboolean
+gupnp_last_change_parser_parse_last_change
+ (GUPnPLastChangeParser *parser,
+ guint instance_id,
+ const char *last_change_xml,
+ GError **error,
+ ...)
+{
+ va_list var_args;
+ gboolean ret;
+
+ va_start (var_args, error);
+ ret = gupnp_last_change_parser_parse_last_change_valist
+ (parser,
+ instance_id,
+ last_change_xml,
+ error,
+ var_args);
+ va_end (var_args);
+
+ return ret;
+}
+
diff --git a/libgupnp-av/gupnp-last-change-parser.h b/libgupnp-av/gupnp-last-change-parser.h
new file mode 100644
index 0000000..de82ebc
--- /dev/null
+++ b/libgupnp-av/gupnp-last-change-parser.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ * Copyright (C) 2007 OpenedHand Ltd
+ *
+ * Authors: Zeeshan Ali Khattak <zeenix@gstreamer.net>
+ * Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_LAST_CHANGE_PARSER_H__
+#define __GUPNP_LAST_CHANGE_PARSER_H__
+
+#include <libgupnp/gupnp.h>
+
+G_BEGIN_DECLS
+
+GType
+gupnp_last_change_parser_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_LAST_CHANGE_PARSER \
+ (gupnp_last_change_parser_get_type ())
+#define GUPNP_LAST_CHANGE_PARSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_LAST_CHANGE_PARSER, \
+ GUPnPLastChangeParser))
+#define GUPNP_LAST_CHANGE_PARSER_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_CAST ((obj), \
+ GUPNP_TYPE_LAST_CHANGE_PARSER, \
+ GUPnPLastChangeParserClass))
+#define GUPNP_IS_LAST_CHANGE_PARSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_LAST_CHANGE_PARSER))
+#define GUPNP_IS_LAST_CHANGE_PARSER_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+ GUPNP_TYPE_LAST_CHANGE_PARSER))
+#define GUPNP_LAST_CHANGE_PARSER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_LAST_CHANGE_PARSER, \
+ GUPnPLastChangeParserClass))
+
+typedef struct {
+ GObject parent;
+} GUPnPLastChangeParser;
+
+typedef struct {
+ GObjectClass parent_class;
+
+ /* future padding */
+ void (* _gupnp_reserved1) (void);
+ void (* _gupnp_reserved2) (void);
+ void (* _gupnp_reserved3) (void);
+ void (* _gupnp_reserved4) (void);
+} GUPnPLastChangeParserClass;
+
+GUPnPLastChangeParser *
+gupnp_last_change_parser_new (void);
+
+gboolean
+gupnp_last_change_parser_parse_last_change_valist
+ (GUPnPLastChangeParser *parser,
+ guint instance_id,
+ const char *last_change_xml,
+ GError **error,
+ va_list var_args);
+
+gboolean
+gupnp_last_change_parser_parse_last_change
+ (GUPnPLastChangeParser *parser,
+ guint instance_id,
+ const char *last_change_xml,
+ GError **error,
+ ...) G_GNUC_NULL_TERMINATED;
+
+G_END_DECLS
+
+#endif /* __GUPNP_LAST_CHANGE_PARSER_H__ */
+
diff --git a/libgupnp-av/gupnp-protocol-info.c b/libgupnp-av/gupnp-protocol-info.c
new file mode 100644
index 0000000..73975c7
--- /dev/null
+++ b/libgupnp-av/gupnp-protocol-info.c
@@ -0,0 +1,1029 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2007, 2008 OpenedHand Ltd.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ * Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gupnp-protocol-info
+ * @short_description: UPnP AV ProtocolInfo
+ *
+ * #GUPnPProtocolInfo provides a convenient API to deal with ProtocolInfo
+ * strings used in UPnP AV specifications.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <libgupnp/gupnp.h>
+#include "gupnp-protocol-info.h"
+#include "gupnp-av-error.h"
+
+G_DEFINE_TYPE (GUPnPProtocolInfo,
+ gupnp_protocol_info,
+ G_TYPE_OBJECT);
+
+struct _GUPnPProtocolInfoPrivate {
+ char *protocol;
+ char *network;
+ char *mime_type;
+ char *dlna_profile;
+ char **play_speeds;
+
+ GUPnPDLNAConversion dlna_conversion;
+ GUPnPDLNAOperation dlna_operation;
+ GUPnPDLNAFlags dlna_flags;
+};
+
+enum {
+ PROP_0,
+ PROP_PROTOCOL,
+ PROP_NETWORK,
+ PROP_MIME_TYPE,
+ PROP_DLNA_PROFILE,
+ PROP_PLAY_SPEEDS,
+
+ PROP_DLNA_CONVERSION,
+ PROP_DLNA_OPERATION,
+ PROP_DLNA_FLAGS
+};
+
+static void
+parse_additional_info (const char *additional_info,
+ GUPnPProtocolInfo *info)
+{
+ GUPnPProtocolInfoPrivate *priv;
+ char **tokens = NULL;
+ short i;
+
+ priv = info->priv;
+
+ if (strcmp (additional_info, "*") == 0)
+ return;
+
+ tokens = g_strsplit (additional_info, ";", -1);
+ if (tokens == NULL) {
+ g_warning ("Invalid additional info in DIDL-Lite info: %s",
+ additional_info);
+
+ return;
+ }
+
+ for (i = 0; tokens[i]; i++) {
+ char *p;
+
+ p = g_strstr_len (tokens[i],
+ strlen (tokens[i]),
+ "DLNA.ORG_PN=");
+ if (p != NULL) {
+ p += 12; /* end of "DLNA.ORG_PN=" */
+ gupnp_protocol_info_set_dlna_profile (info, p);
+
+ continue;
+ }
+
+ p = g_strstr_len (tokens[i],
+ strlen (tokens[i]),
+ "DLNA.ORG_PS=");
+ if (p != NULL) {
+ char **play_speeds;
+
+ p += 12; /* end of "DLNA.ORG_PS=" */
+
+ play_speeds = g_strsplit (p, ",", -1);
+ gupnp_protocol_info_set_play_speeds
+ (info,
+ (const char **) play_speeds);
+ g_strfreev (play_speeds);
+
+ continue;
+ }
+
+ p = g_strstr_len (tokens[i],
+ strlen (tokens[i]),
+ "DLNA.ORG_CI=");
+ if (p != NULL) {
+ p += 12; /* end of "DLNA.ORG_CI=" */
+
+ gupnp_protocol_info_set_dlna_conversion (info,
+ atoi (p));
+
+ continue;
+ }
+
+ p = g_strstr_len (tokens[i],
+ strlen (tokens[i]),
+ "DLNA.ORG_OP=");
+ if (p != NULL) {
+ p += 12; /* end of "DLNA.ORG_OP=" */
+
+ gupnp_protocol_info_set_dlna_operation
+ (info,
+ strtoul (p, NULL, 16));
+
+ continue;
+ }
+
+ p = g_strstr_len (tokens[i],
+ strlen (tokens[i]),
+ "DLNA.ORG_FLAGS=");
+ if (p != NULL) {
+ p += 15; /* end of "DLNA.ORG_FLAGS=" */
+ if (strlen (p) > 8)
+ p[8] = '\0';
+ gupnp_protocol_info_set_dlna_flags
+ (info,
+ strtoul (p, NULL, 16));
+
+ continue;
+ }
+ }
+
+ g_strfreev (tokens);
+}
+
+static gboolean
+is_transport_compat (GUPnPProtocolInfo *info1,
+ GUPnPProtocolInfo *info2)
+{
+ const char *protocol1;
+ const char *protocol2;
+
+ protocol1 = gupnp_protocol_info_get_protocol (info1);
+ protocol2 = gupnp_protocol_info_get_protocol (info2);
+
+ if (protocol1[0] != '*' &&
+ protocol2[0] != '*' &&
+ g_ascii_strcasecmp (protocol1, protocol2) != 0)
+ return FALSE;
+ else if (g_ascii_strcasecmp ("internal", protocol1) == 0 &&
+ strcmp (gupnp_protocol_info_get_network (info1),
+ gupnp_protocol_info_get_network (info2)) != 0)
+ /* Host must be the same in case of INTERNAL protocol */
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static gboolean
+is_content_format_compat (GUPnPProtocolInfo *info1,
+ GUPnPProtocolInfo *info2)
+{
+ const char *mime_type1;
+ const char *mime_type2;
+
+ mime_type1 = gupnp_protocol_info_get_mime_type (info1);
+ mime_type2 = gupnp_protocol_info_get_mime_type (info2);
+
+ if (mime_type1 [0] != '*' &&
+ mime_type2 [0] != '*' &&
+ g_ascii_strcasecmp (mime_type1, mime_type2) != 0 &&
+ /* Handle special case for LPCM: It is the only content type that
+ * make use of mime-type parameters that we know of.
+ *
+ * Example: audio/L16;rate=44100;channels=2
+ */
+ !((g_ascii_strcasecmp (mime_type1, "audio/L16") == 0 &&
+ g_ascii_strncasecmp (mime_type2, "audio/L16", 9) == 0) ||
+ (g_ascii_strcasecmp (mime_type2, "audio/L16") == 0 &&
+ g_ascii_strncasecmp (mime_type1, "audio/L16", 9) == 0)))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+static gboolean
+is_additional_info_compat (GUPnPProtocolInfo *info1,
+ GUPnPProtocolInfo *info2)
+{
+ const char *profile1;
+ const char *profile2;
+
+ profile1 = gupnp_protocol_info_get_dlna_profile (info1);
+ profile2 = gupnp_protocol_info_get_dlna_profile (info2);
+
+ if (profile1 == NULL ||
+ profile2 == NULL ||
+ profile1 [0] == '*' ||
+ profile2 [0] == '*' ||
+ g_ascii_strcasecmp (profile1, profile2) == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+add_dlna_info (GString *str,
+ GUPnPProtocolInfo *info)
+{
+ const char *dlna_profile;
+ const char **speeds;
+ GUPnPDLNAConversion conversion;
+ GUPnPDLNAOperation operation;
+ GUPnPDLNAFlags flags;
+
+ dlna_profile = gupnp_protocol_info_get_dlna_profile (info);
+ if (dlna_profile == NULL) {
+ g_string_append_printf (str, ":");
+ } else {
+ g_string_append_printf (str, ":DLNA.ORG_PN=%s;", dlna_profile);
+ }
+
+ operation = gupnp_protocol_info_get_dlna_operation (info);
+ if (operation != GUPNP_DLNA_OPERATION_NONE &&
+ /* the OP parameter is only allowed for the "http-get"
+ * and "rtsp-rtp-udp" protocols
+ */
+ (strcmp (gupnp_protocol_info_get_protocol (info),
+ "http-get") == 0 ||
+ strcmp (gupnp_protocol_info_get_protocol (info),
+ "rtsp-rtp-udp") == 0))
+ g_string_append_printf (str, "DLNA.ORG_OP=%.2x;", operation);
+
+ /* Specify PS parameter if list of play speeds is provided */
+ speeds = gupnp_protocol_info_get_play_speeds (info);
+ if (speeds != NULL) {
+ int i;
+
+ g_string_append_printf (str, "DLNA.ORG_PS=;");
+
+ for (i = 0; speeds[i]; i++) {
+ g_string_append (str, speeds[i]);
+
+ if (speeds[i + 1])
+ g_string_append_c (str, ',');
+ }
+ }
+
+ conversion = gupnp_protocol_info_get_dlna_conversion (info);
+ /* omit the CI parameter for non-converted content */
+ if (conversion != GUPNP_DLNA_CONVERSION_NONE)
+ g_string_append_printf (str, "DLNA.ORG_CI=%d;", conversion);
+
+ flags = gupnp_protocol_info_get_dlna_flags (info);
+ /* Omit the FLAGS parameter if no or DLNA profile are set */
+ if (flags != GUPNP_DLNA_FLAGS_NONE && dlna_profile != NULL) {
+ g_string_append_printf (str, "DLNA.ORG_FLAGS=%.8x", flags);
+ /* append 24 reserved hex-digits */
+ g_string_append_printf (str,
+ "0000" "0000" "0000"
+ "0000" "0000" "0000");
+ }
+
+ /* if nothing of the above was set, use the "match all" rule */
+ switch (str->str[str->len - 1]) {
+ case ':':
+ g_string_append_c (str, '*');
+ break;
+ case ';':
+ g_string_erase (str, str->len - 1, 1);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+gupnp_protocol_info_init (GUPnPProtocolInfo *info)
+{
+ info->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (info,
+ GUPNP_TYPE_PROTOCOL_INFO,
+ GUPnPProtocolInfoPrivate);
+
+ info->priv->dlna_conversion = GUPNP_DLNA_CONVERSION_NONE;
+ info->priv->dlna_operation = GUPNP_DLNA_OPERATION_NONE;
+ info->priv->dlna_flags = GUPNP_DLNA_FLAGS_NONE;
+}
+
+static void
+gupnp_protocol_info_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPProtocolInfo *info;
+
+ info = GUPNP_PROTOCOL_INFO (object);
+
+ switch (property_id) {
+ case PROP_PROTOCOL:
+ gupnp_protocol_info_set_protocol (info,
+ g_value_get_string (value));
+ break;
+ case PROP_NETWORK:
+ gupnp_protocol_info_set_network (info,
+ g_value_get_string (value));
+ break;
+ case PROP_MIME_TYPE:
+ gupnp_protocol_info_set_mime_type (info,
+ g_value_get_string (value));
+ break;
+ case PROP_DLNA_PROFILE:
+ gupnp_protocol_info_set_dlna_profile
+ (info,
+ g_value_get_string (value));
+ break;
+ case PROP_PLAY_SPEEDS:
+ gupnp_protocol_info_set_play_speeds (info,
+ g_value_get_boxed (value));
+ break;
+ case PROP_DLNA_CONVERSION:
+ gupnp_protocol_info_set_dlna_conversion
+ (info,
+ g_value_get_flags (value));
+ break;
+ case PROP_DLNA_OPERATION:
+ gupnp_protocol_info_set_dlna_operation
+ (info,
+ g_value_get_flags (value));
+ break;
+ case PROP_DLNA_FLAGS:
+ gupnp_protocol_info_set_dlna_flags
+ (info,
+ g_value_get_flags (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_protocol_info_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GUPnPProtocolInfo *info;
+
+ info = GUPNP_PROTOCOL_INFO (object);
+
+ switch (property_id) {
+ case PROP_PROTOCOL:
+ g_value_set_string (value,
+ gupnp_protocol_info_get_protocol (info));
+ break;
+ case PROP_NETWORK:
+ g_value_set_string (value,
+ gupnp_protocol_info_get_network (info));
+ break;
+ case PROP_MIME_TYPE:
+ g_value_set_string (value,
+ gupnp_protocol_info_get_mime_type (info));
+ break;
+ case PROP_DLNA_PROFILE:
+ g_value_set_string
+ (value,
+ gupnp_protocol_info_get_dlna_profile (info));
+ break;
+ case PROP_PLAY_SPEEDS:
+ g_value_set_boxed (value,
+ gupnp_protocol_info_get_play_speeds (info));
+ break;
+ case PROP_DLNA_CONVERSION:
+ g_value_set_flags
+ (value,
+ gupnp_protocol_info_get_dlna_conversion
+ (info));
+ break;
+ case PROP_DLNA_OPERATION:
+ g_value_set_flags
+ (value,
+ gupnp_protocol_info_get_dlna_operation (info));
+ break;
+ case PROP_DLNA_FLAGS:
+ g_value_set_flags (value,
+ gupnp_protocol_info_get_dlna_flags (info));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gupnp_protocol_info_finalize (GObject *object)
+{
+ GObjectClass *object_class;
+ GUPnPProtocolInfoPrivate *priv;
+
+ priv = GUPNP_PROTOCOL_INFO (object)->priv;
+
+ if (priv->protocol)
+ g_free (priv->protocol);
+ if (priv->network)
+ g_free (priv->network);
+ if (priv->mime_type)
+ g_free (priv->mime_type);
+ if (priv->dlna_profile)
+ g_free (priv->dlna_profile);
+ if (priv->play_speeds)
+ g_strfreev (priv->play_speeds);
+
+ object_class = G_OBJECT_CLASS (gupnp_protocol_info_parent_class);
+ object_class->finalize (object);
+}
+
+static void
+gupnp_protocol_info_class_init (GUPnPProtocolInfoClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = gupnp_protocol_info_set_property;
+ object_class->get_property = gupnp_protocol_info_get_property;
+ object_class->finalize = gupnp_protocol_info_finalize;
+
+ g_type_class_add_private (klass, sizeof (GUPnPProtocolInfoPrivate));
+
+ /**
+ * GUPnPProtocolInfo:protocol:
+ *
+ * The protocol of this info.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_PROTOCOL,
+ g_param_spec_string ("protocol",
+ "Protocol",
+ "The protocol of this info.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPProtocolInfo:network:
+ *
+ * The network this info is associated with.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_NETWORK,
+ g_param_spec_string ("network",
+ "Network",
+ "The network this info is associated"
+ " with.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPProtocolInfo:mime-type:
+ *
+ * The MIME-type of this info.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_MIME_TYPE,
+ g_param_spec_string ("mime-type",
+ "MIMEType",
+ "The MIME-type of this info.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPProtocolInfo:dlna-profile:
+ *
+ * The DLNA profile of this info.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_DLNA_PROFILE,
+ g_param_spec_string ("dlna-profile",
+ "DLNAProfile",
+ "The DLNA profile of this info.",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPProtocolInfo:play-speeds:
+ *
+ * The allowed play speeds on this info in the form of array of
+ * strings.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_PLAY_SPEEDS,
+ g_param_spec_boxed ("play-speeds",
+ "PlaySpeeds",
+ "The allowed play speeds on this"
+ " info in the form of array of"
+ " strings.",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPProtocolInfo:dlna-conversion:
+ *
+ * The DLNA conversion flags.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_DLNA_CONVERSION,
+ g_param_spec_flags ("dlna-conversion",
+ "DLNAConversion",
+ "The DLNA conversion flags.",
+ GUPNP_TYPE_DLNA_CONVERSION,
+ GUPNP_DLNA_CONVERSION_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPProtocolInfo:dlna-operation:
+ *
+ * The DLNA operation flags.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_DLNA_OPERATION,
+ g_param_spec_flags ("dlna-operation",
+ "DLNAOperation",
+ "The DLNA operation flags.",
+ GUPNP_TYPE_DLNA_OPERATION,
+ GUPNP_DLNA_OPERATION_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+
+ /**
+ * GUPnPProtocolInfo:dlna-flags:
+ *
+ * Various generic DLNA flags.
+ **/
+ g_object_class_install_property
+ (object_class,
+ PROP_DLNA_FLAGS,
+ g_param_spec_flags ("dlna-flags",
+ "DLNAFlags",
+ "Various generic DLNA flags.",
+ GUPNP_TYPE_DLNA_FLAGS,
+ GUPNP_DLNA_FLAGS_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB));
+}
+
+/**
+ * gupnp_protocol_info_new:
+ *
+ * Return value: A new #GUPnPProtocolInfo object. Unref after usage.
+ **/
+GUPnPProtocolInfo *
+gupnp_protocol_info_new ()
+{
+ return g_object_new (GUPNP_TYPE_PROTOCOL_INFO,
+ NULL);
+}
+
+/**
+ * gupnp_protocol_info_new_from_string:
+ * @protocol_info: The protocol info string
+ * @error: The location where to store any error, or NULL
+ *
+ * Parses the @protocol_info string and creates a new #GUPnPProtocolInfo object
+ * as a result.
+ *
+ * Return value: A new #GUPnPProtocolInfo object. Unref after usage.
+ **/
+GUPnPProtocolInfo *
+gupnp_protocol_info_new_from_string (const char *protocol_info,
+ GError **error)
+{
+ GUPnPProtocolInfo *info;
+ char **tokens;
+
+ g_return_val_if_fail (protocol_info != NULL, NULL);
+
+ tokens = g_strsplit (protocol_info, ":", 4);
+ if (tokens[0] == NULL ||
+ tokens[1] == NULL ||
+ tokens[2] == NULL ||
+ tokens[3] == NULL) {
+ g_set_error (error,
+ GUPNP_PROTOCOL_ERROR,
+ GUPNP_PROTOCOL_ERROR_INVALID_SYNTAX,
+ "Failed to parse protocolInfo string: \n%s",
+ protocol_info);
+
+ g_strfreev (tokens);
+
+ return NULL;
+ }
+
+ info = gupnp_protocol_info_new ();
+
+ gupnp_protocol_info_set_protocol (info, tokens[0]);
+ gupnp_protocol_info_set_network (info, tokens[1]);
+ gupnp_protocol_info_set_mime_type (info, tokens[2]);
+
+ parse_additional_info (tokens[3], info);
+
+ g_strfreev (tokens);
+
+ return info;
+}
+
+/**
+ * gupnp_protocol_info_to_string:
+ * @info: The #GUPnPProtocolInfo
+ *
+ * Provides the string representation of @info.
+ *
+ * Return value: String representation of @info. #g_free after usage.
+ **/
+char *
+gupnp_protocol_info_to_string (GUPnPProtocolInfo *info)
+{
+ GString *str;
+ const char *protocol;
+ const char *mime_type;
+ const char *network;
+
+ g_return_val_if_fail (GUPNP_IS_PROTOCOL_INFO (info), NULL);
+
+ protocol = gupnp_protocol_info_get_protocol (info);
+ mime_type = gupnp_protocol_info_get_mime_type (info);
+ network = gupnp_protocol_info_get_network (info);
+
+ g_return_val_if_fail (protocol != NULL, NULL);
+ g_return_val_if_fail (mime_type != NULL, NULL);
+
+ str = g_string_new ("");
+
+ g_string_append (str, protocol);
+ g_string_append_c (str, ':');
+ if (network != NULL)
+ g_string_append (str, network);
+ else
+ g_string_append_c (str, '*');
+ g_string_append_c (str, ':');
+ g_string_append (str, mime_type);
+
+ add_dlna_info (str, info);
+
+ return g_string_free (str, FALSE);
+}
+
+/**
+ * gupnp_protocol_info_get_protocol:
+ * @info: A #GUPnPProtocolInfo
+ *
+ * Get the protocol of this info.
+ *
+ * Return value: The protocol of this info or %NULL. This string should not
+ * be freed.
+ **/
+const char *
+gupnp_protocol_info_get_protocol (GUPnPProtocolInfo *info)
+{
+ g_return_val_if_fail (GUPNP_IS_PROTOCOL_INFO (info), NULL);
+
+ return info->priv->protocol;
+}
+
+/**
+ * gupnp_protocol_info_get_network:
+ * @info: A #GUPnPProtocolInfo
+ *
+ * Get the network this info is associated with.
+ *
+ * Return value: The network string or %NULL. This string should not be freed.
+ **/
+const char *
+gupnp_protocol_info_get_network (GUPnPProtocolInfo *info)
+{
+ g_return_val_if_fail (GUPNP_IS_PROTOCOL_INFO (info), NULL);
+
+ return info->priv->network;
+}
+
+/**
+ * gupnp_protocol_info_get_mime_type:
+ * @info: A #GUPnPProtocolInfo
+ *
+ * Get the MIME-type of this info.
+ *
+ * Return value: The MIME-type of this info or %NULL. This string should not
+ * be freed.
+ **/
+const char *
+gupnp_protocol_info_get_mime_type (GUPnPProtocolInfo *info)
+{
+ g_return_val_if_fail (GUPNP_IS_PROTOCOL_INFO (info), NULL);
+
+ return info->priv->mime_type;
+}
+
+/**
+ * gupnp_protocol_info_get_dlna_profile:
+ * @info: A #GUPnPProtocolInfo
+ *
+ * Get the DLNA profile of this info.
+ *
+ * Return value: The DLNA profile of this info or %NULL. This string should
+ * not be freed.
+ **/
+const char *
+gupnp_protocol_info_get_dlna_profile (GUPnPProtocolInfo *info)
+{
+ g_return_val_if_fail (GUPNP_IS_PROTOCOL_INFO (info), NULL);
+
+ return info->priv->dlna_profile;
+}
+
+/**
+ * gupnp_protocol_info_get_play_speeds:
+ * @info: A #GUPnPProtocolInfo
+ *
+ * Get the allowed play speeds on this info in the form of array of strings.
+ *
+ * Returns: (transfer none): The allowed play speeds as array of strings or %NULL. This
+ * return array and it's content must not be modified or freed.
+ **/
+const char **
+gupnp_protocol_info_get_play_speeds (GUPnPProtocolInfo *info)
+{
+ g_return_val_if_fail (GUPNP_IS_PROTOCOL_INFO (info), NULL);
+
+ return (const char **) info->priv->play_speeds;
+}
+
+/**
+ * gupnp_protocol_info_get_dlna_conversion:
+ * @info: A #GUPnPProtocolInfo
+ *
+ * Get the DLNA conversion flags.
+ *
+ * Return value: The DLNA conversion flags.
+ **/
+GUPnPDLNAConversion
+gupnp_protocol_info_get_dlna_conversion (GUPnPProtocolInfo *info)
+{
+ g_return_val_if_fail (GUPNP_IS_PROTOCOL_INFO (info),
+ GUPNP_DLNA_CONVERSION_NONE);
+
+ return info->priv->dlna_conversion;
+}
+
+/**
+ * gupnp_protocol_info_get_dlna_operation:
+ * @info: A #GUPnPProtocolInfo
+ *
+ * Get the DLNA operation flags.
+ *
+ * Return value: The DLNA operation flags.
+ **/
+GUPnPDLNAOperation
+gupnp_protocol_info_get_dlna_operation (GUPnPProtocolInfo *info)
+{
+ g_return_val_if_fail (GUPNP_IS_PROTOCOL_INFO (info),
+ GUPNP_DLNA_OPERATION_NONE);
+
+ return info->priv->dlna_operation;
+}
+
+/**
+ * gupnp_protocol_info_get_dlna_flags:
+ * @info: A #GUPnPProtocolInfo
+ *
+ * Get the gereric DLNA flags.
+ *
+ * Return value: The generic DLNA flags.
+ **/
+GUPnPDLNAFlags
+gupnp_protocol_info_get_dlna_flags (GUPnPProtocolInfo *info)
+{
+ g_return_val_if_fail (GUPNP_IS_PROTOCOL_INFO (info),
+ GUPNP_DLNA_FLAGS_NONE);
+
+ return info->priv->dlna_flags;
+}
+
+/**
+ * gupnp_protocol_info_set_protocol:
+ * @info: A #GUPnPProtocolInfo
+ * @protocol: The protocol string
+ *
+ * Set the protocol of this info.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_protocol_info_set_protocol (GUPnPProtocolInfo *info,
+ const char *protocol)
+{
+ g_return_if_fail (GUPNP_IS_PROTOCOL_INFO (info));
+
+ if (info->priv->protocol)
+ g_free (info->priv->protocol);
+ info->priv->protocol = g_strdup (protocol);
+
+ g_object_notify (G_OBJECT (info), "protocol");
+}
+
+/**
+ * gupnp_protocol_info_set_network:
+ * @info: A #GUPnPProtocolInfo
+ * @network: The network string
+ *
+ * Set the network this info is associated with.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_protocol_info_set_network (GUPnPProtocolInfo *info,
+ const char *network)
+{
+ g_return_if_fail (GUPNP_IS_PROTOCOL_INFO (info));
+
+ if (info->priv->network)
+ g_free (info->priv->network);
+ info->priv->network = g_strdup (network);
+
+ g_object_notify (G_OBJECT (info), "network");
+}
+
+/**
+ * gupnp_protocol_info_set_mime_type:
+ * @info: A #GUPnPProtocolInfo
+ * @mime_type: The MIME-type string
+ *
+ * Set the MIME-type of this info.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_protocol_info_set_mime_type (GUPnPProtocolInfo *info,
+ const char *mime_type)
+{
+ g_return_if_fail (GUPNP_IS_PROTOCOL_INFO (info));
+
+ if (info->priv->mime_type)
+ g_free (info->priv->mime_type);
+ info->priv->mime_type = g_strdup (mime_type);
+
+ g_object_notify (G_OBJECT (info), "mime-type");
+}
+
+/**
+ * gupnp_protocol_info_set_dlna_profile:
+ * @info: A #GUPnPProtocolInfo
+ * @profile: The DLNA profile string
+ *
+ * Set the DLNA profile of this info.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_protocol_info_set_dlna_profile (GUPnPProtocolInfo *info,
+ const char *profile)
+{
+ g_return_if_fail (GUPNP_IS_PROTOCOL_INFO (info));
+
+ if (info->priv->dlna_profile)
+ g_free (info->priv->dlna_profile);
+ info->priv->dlna_profile = g_strdup (profile);
+
+ g_object_notify (G_OBJECT (info), "dlna-profile");
+}
+
+/**
+ * gupnp_protocol_info_set_play_speeds:
+ * @info: A #GUPnPProtocolInfo
+ * @speeds: The allowed play speeds
+ *
+ * Set the allowed play speeds on this info in the form of array of strings.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_protocol_info_set_play_speeds (GUPnPProtocolInfo *info,
+ const char **speeds)
+{
+ g_return_if_fail (GUPNP_IS_PROTOCOL_INFO (info));
+
+ if (info->priv->play_speeds)
+ g_strfreev (info->priv->play_speeds);
+ info->priv->play_speeds = (char **) g_boxed_copy (G_TYPE_STRV, speeds);
+
+ g_object_notify (G_OBJECT (info), "play-speeds");
+}
+
+/**
+ * gupnp_protocol_info_set_dlna_conversion:
+ * @info: A #GUPnPProtocolInfo
+ * @conversion: The bitwise OR of one or more DLNA conversion flags
+ *
+ * Set the DLNA conversion flags.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_protocol_info_set_dlna_conversion (GUPnPProtocolInfo *info,
+ GUPnPDLNAConversion conversion)
+{
+ g_return_if_fail (GUPNP_IS_PROTOCOL_INFO (info));
+
+ info->priv->dlna_conversion = conversion;
+
+ g_object_notify (G_OBJECT (info), "dlna-conversion");
+}
+
+/**
+ * gupnp_protocol_info_set_dlna_operation:
+ * @info: A #GUPnPProtocolInfo
+ * @operation: The bitwise OR of one or more DLNA operation flags
+ *
+ * Set the DLNA operation flags.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_protocol_info_set_dlna_operation (GUPnPProtocolInfo *info,
+ GUPnPDLNAOperation operation)
+{
+ g_return_if_fail (GUPNP_IS_PROTOCOL_INFO (info));
+
+ info->priv->dlna_operation = operation;
+
+ g_object_notify (G_OBJECT (info), "dlna-operation");
+}
+
+/**
+ * gupnp_protocol_info_set_dlna_flags:
+ * @info: A #GUPnPProtocolInfo
+ * @flags: The bitwise OR of one or more generic DLNA flags
+ *
+ * Set the gereric DLNA flags.
+ *
+ * Return value: None.
+ **/
+void
+gupnp_protocol_info_set_dlna_flags (GUPnPProtocolInfo *info,
+ GUPnPDLNAFlags flags)
+{
+ g_return_if_fail (GUPNP_IS_PROTOCOL_INFO (info));
+
+ info->priv->dlna_flags = flags;
+
+ g_object_notify (G_OBJECT (info), "dlna-flags");
+}
+
+/**
+ * gupnp_protocol_info_is_compatible:
+ * @info1: The first #GUPnPProtocolInfo
+ * @info2: The second #GUPnPProtocolInfo
+ *
+ * Checks if the given protocolInfo string is compatible with @info.
+ *
+ * Return value: #TRUE if @protocol_info is compatible with @info, otherwise
+ * #FALSE.
+ **/
+gboolean
+gupnp_protocol_info_is_compatible (GUPnPProtocolInfo *info1,
+ GUPnPProtocolInfo *info2)
+{
+ g_return_val_if_fail (GUPNP_IS_PROTOCOL_INFO (info1), FALSE);
+ g_return_val_if_fail (GUPNP_IS_PROTOCOL_INFO (info2), FALSE);
+
+ return is_transport_compat (info1, info2) &&
+ is_content_format_compat (info1, info2) &&
+ is_additional_info_compat (info1, info2);
+}
+
diff --git a/libgupnp-av/gupnp-protocol-info.h b/libgupnp-av/gupnp-protocol-info.h
new file mode 100644
index 0000000..078ad4e
--- /dev/null
+++ b/libgupnp-av/gupnp-protocol-info.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ * Copyright (C) 2007, 2008 OpenedHand Ltd.
+ *
+ * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
+ * <zeeshanak@gnome.org>
+ * Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_PROTOCOL_INFO_H__
+#define __GUPNP_PROTOCOL_INFO_H__
+
+#include <stdarg.h>
+#include <glib-object.h>
+
+#include "gupnp-dlna.h"
+
+G_BEGIN_DECLS
+
+GType
+gupnp_protocol_info_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_PROTOCOL_INFO \
+ (gupnp_protocol_info_get_type ())
+#define GUPNP_PROTOCOL_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_PROTOCOL_INFO, \
+ GUPnPProtocolInfo))
+#define GUPNP_PROTOCOL_INFO_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_CAST ((obj), \
+ GUPNP_TYPE_PROTOCOL_INFO, \
+ GUPnPProtocolInfoClass))
+#define GUPNP_IS_PROTOCOL_INFO(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_PROTOCOL_INFO))
+#define GUPNP_IS_PROTOCOL_INFO_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+ GUPNP_TYPE_PROTOCOL_INFO))
+#define GUPNP_PROTOCOL_INFO_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_PROTOCOL_INFO, \
+ GUPnPProtocolInfoClass))
+
+typedef struct _GUPnPProtocolInfoPrivate GUPnPProtocolInfoPrivate;
+
+typedef struct {
+ GObject parent;
+
+ GUPnPProtocolInfoPrivate *priv;
+} GUPnPProtocolInfo;
+
+typedef struct {
+ GObjectClass parent_class;
+
+ /* future padding */
+ void (* _gupnp_reserved1) (void);
+ void (* _gupnp_reserved2) (void);
+ void (* _gupnp_reserved3) (void);
+ void (* _gupnp_reserved4) (void);
+} GUPnPProtocolInfoClass;
+
+GUPnPProtocolInfo *
+gupnp_protocol_info_new (void);
+
+GUPnPProtocolInfo *
+gupnp_protocol_info_new_from_string (const char *protocol_info,
+ GError **error);
+
+char *
+gupnp_protocol_info_to_string (GUPnPProtocolInfo *info);
+
+gboolean
+gupnp_protocol_info_is_compatible (GUPnPProtocolInfo *info1,
+ GUPnPProtocolInfo *info2);
+
+void
+gupnp_protocol_info_set_protocol (GUPnPProtocolInfo *info,
+ const char *protocol);
+
+void
+gupnp_protocol_info_set_network (GUPnPProtocolInfo *info,
+ const char *network);
+
+void
+gupnp_protocol_info_set_mime_type (GUPnPProtocolInfo *info,
+ const char *mime_type);
+
+void
+gupnp_protocol_info_set_dlna_profile (GUPnPProtocolInfo *info,
+ const char *profile);
+
+void
+gupnp_protocol_info_set_play_speeds (GUPnPProtocolInfo *info,
+ const char **speeds);
+
+void
+gupnp_protocol_info_set_dlna_conversion (GUPnPProtocolInfo *info,
+ GUPnPDLNAConversion conversion);
+
+void
+gupnp_protocol_info_set_dlna_operation (GUPnPProtocolInfo *info,
+ GUPnPDLNAOperation operation);
+
+void
+gupnp_protocol_info_set_dlna_flags (GUPnPProtocolInfo *info,
+ GUPnPDLNAFlags flags);
+
+const char *
+gupnp_protocol_info_get_protocol (GUPnPProtocolInfo *info);
+
+const char *
+gupnp_protocol_info_get_network (GUPnPProtocolInfo *info);
+
+const char *
+gupnp_protocol_info_get_mime_type (GUPnPProtocolInfo *info);
+
+const char *
+gupnp_protocol_info_get_dlna_profile (GUPnPProtocolInfo *info);
+
+const char **
+gupnp_protocol_info_get_play_speeds (GUPnPProtocolInfo *info);
+
+GUPnPDLNAConversion
+gupnp_protocol_info_get_dlna_conversion (GUPnPProtocolInfo *info);
+
+GUPnPDLNAOperation
+gupnp_protocol_info_get_dlna_operation (GUPnPProtocolInfo *info);
+
+GUPnPDLNAFlags
+gupnp_protocol_info_get_dlna_flags (GUPnPProtocolInfo *info);
+
+G_END_DECLS
+
+#endif /* __GUPNP_PROTOCOL_INFO_H__ */
diff --git a/libgupnp-av/gupnp-search-criteria-parser.c b/libgupnp-av/gupnp-search-criteria-parser.c
new file mode 100644
index 0000000..9e4dbda
--- /dev/null
+++ b/libgupnp-av/gupnp-search-criteria-parser.c
@@ -0,0 +1,607 @@
+/*
+ * Copyright (C) 2008 OpenedHand Ltd.
+ *
+ * Authors: Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gupnp-search-criteria-parser
+ * @short_description: A/V search criteria parser
+ *
+ * #GUPnPSearchCriteriaParser parses ContentDirectory search criteria
+ * strings.
+ *
+ * Note that no signals will be emitted if a wildcard is specified,
+ * and that the user is responsible for ensuring precedence of conjunction
+ * over disjunction.
+ */
+
+#include <string.h>
+
+#include "gupnp-search-criteria-parser.h"
+#include "gupnp-av-marshal.h"
+
+/* GType for GUPNPSearchCriteriaOp */
+GType
+gupnp_search_criteria_op_get_type (void)
+{
+ static GType type = 0;
+
+ if (type == 0) {
+ static const GEnumValue values[] = {
+ { GUPNP_SEARCH_CRITERIA_OP_EQ,
+ "GUPNP_SEARCH_CRITERIA_OP_EQ",
+ "none" },
+ { GUPNP_SEARCH_CRITERIA_OP_NEQ,
+ "GUPNP_SEARCH_CRITERIA_OP_NEQ",
+ "none" },
+ { GUPNP_SEARCH_CRITERIA_OP_LESS,
+ "GUPNP_SEARCH_CRITERIA_OP_LESS",
+ "none" },
+ { GUPNP_SEARCH_CRITERIA_OP_LEQ,
+ "GUPNP_SEARCH_CRITERIA_OP_LEQ",
+ "none" },
+ { GUPNP_SEARCH_CRITERIA_OP_GREATER,
+ "GUPNP_SEARCH_CRITERIA_OP_GREATER",
+ "none" },
+ { GUPNP_SEARCH_CRITERIA_OP_GEQ,
+ "GUPNP_SEARCH_CRITERIA_OP_GEQ",
+ "none" },
+ { GUPNP_SEARCH_CRITERIA_OP_CONTAINS,
+ "GUPNP_SEARCH_CRITERIA_OP_CONTAINS",
+ "none" },
+ { GUPNP_SEARCH_CRITERIA_OP_DOES_NOT_CONTAIN,
+ "GUPNP_SEARCH_CRITERIA_OP_DOES_NOT_CONTAIN",
+ "none" },
+ { GUPNP_SEARCH_CRITERIA_OP_DERIVED_FROM,
+ "GUPNP_SEARCH_CRITERIA_OP_DERIVED_FROM",
+ "none" },
+ { GUPNP_SEARCH_CRITERIA_OP_EXISTS,
+ "GUPNP_SEARCH_CRITERIA_OP_EXISTS",
+ "none" },
+ { 0, NULL, NULL }
+ };
+
+ type = g_enum_register_static
+ (g_intern_static_string (
+ "GUPnPSearchCriteriaOp"),
+ values);
+ }
+
+ return type;
+}
+
+/* GUPnPSearchCriteriaParserError */
+GQuark
+gupnp_search_criteria_parser_error_quark (void)
+{
+ return g_quark_from_static_string
+ ("gupnp-search-criteria-parser-error-quark");
+}
+
+/* GUPnPSearchCriteriaParser */
+G_DEFINE_TYPE (GUPnPSearchCriteriaParser,
+ gupnp_search_criteria_parser,
+ G_TYPE_OBJECT);
+
+struct _GUPnPSearchCriteriaParserPrivate {
+ GScanner *scanner;
+};
+
+enum {
+ BEGIN_PARENS,
+ END_PARENS,
+ CONJUNCTION,
+ DISJUNCTION,
+ EXPRESSION,
+ SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST];
+
+/* Additional parsable symbols */
+enum {
+ SYMBOL_ASTERISK = G_TOKEN_LAST + 11,
+ SYMBOL_AND = G_TOKEN_LAST + 12,
+ SYMBOL_OR = G_TOKEN_LAST + 13,
+ SYMBOL_TRUE = G_TOKEN_LAST + 14,
+ SYMBOL_FALSE = G_TOKEN_LAST + 15
+};
+
+#define NUM_SYMBOLS 15
+
+struct {
+ const char *name;
+ int token;
+} symbols[NUM_SYMBOLS] = {
+ { "*",
+ SYMBOL_ASTERISK },
+
+ { "and",
+ SYMBOL_AND },
+ { "or",
+ SYMBOL_OR },
+
+ { "=",
+ GUPNP_SEARCH_CRITERIA_OP_EQ },
+ { "!=",
+ GUPNP_SEARCH_CRITERIA_OP_NEQ },
+ { "<",
+ GUPNP_SEARCH_CRITERIA_OP_LESS },
+ { "<=",
+ GUPNP_SEARCH_CRITERIA_OP_LEQ },
+ { ">",
+ GUPNP_SEARCH_CRITERIA_OP_GREATER },
+ { ">=",
+ GUPNP_SEARCH_CRITERIA_OP_GEQ },
+
+ { "contains",
+ GUPNP_SEARCH_CRITERIA_OP_CONTAINS },
+ { "doesNotContain",
+ GUPNP_SEARCH_CRITERIA_OP_DOES_NOT_CONTAIN },
+ { "derivedfrom",
+ GUPNP_SEARCH_CRITERIA_OP_DERIVED_FROM },
+
+ { "exists",
+ GUPNP_SEARCH_CRITERIA_OP_EXISTS },
+
+ { "true",
+ SYMBOL_TRUE },
+ { "false",
+ SYMBOL_FALSE }
+};
+
+static void
+gupnp_search_criteria_parser_init (GUPnPSearchCriteriaParser *parser)
+{
+ int i;
+
+ parser->priv = G_TYPE_INSTANCE_GET_PRIVATE
+ (parser,
+ GUPNP_TYPE_SEARCH_CRITERIA_PARSER,
+ GUPnPSearchCriteriaParserPrivate);
+
+ /* Set up GScanner */
+ parser->priv->scanner = g_scanner_new (NULL);
+
+ parser->priv->scanner->config->cset_skip_characters = " \t\n\r\012"
+ "\013\014\015";
+ parser->priv->scanner->config->scan_identifier_1char = TRUE;
+ parser->priv->scanner->config->cset_identifier_first = G_CSET_a_2_z
+ "_*<>=!@"
+ G_CSET_A_2_Z;
+ parser->priv->scanner->config->cset_identifier_nth = G_CSET_a_2_z
+ "_0123456789=:@"
+ G_CSET_A_2_Z
+ G_CSET_LATINS
+ G_CSET_LATINC;
+ parser->priv->scanner->config->symbol_2_token = TRUE;
+
+ /* Add symbols */
+ for (i = 0; i < NUM_SYMBOLS; i++) {
+ g_scanner_scope_add_symbol (parser->priv->scanner,
+ 0,
+ symbols[i].name,
+ GINT_TO_POINTER (symbols[i].token));
+ }
+}
+
+static void
+gupnp_search_criteria_parser_finalize (GObject *object)
+{
+ GObjectClass *gobject_class;
+ GUPnPSearchCriteriaParser *parser;
+
+ parser = GUPNP_SEARCH_CRITERIA_PARSER (object);
+
+ /* Destroy GScanner */
+ g_scanner_destroy (parser->priv->scanner);
+
+ gobject_class =
+ G_OBJECT_CLASS (gupnp_search_criteria_parser_parent_class);
+ gobject_class->dispose (object);
+}
+
+static void
+gupnp_search_criteria_parser_class_init
+ (GUPnPSearchCriteriaParserClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gupnp_search_criteria_parser_finalize;
+
+ /**
+ * GUPnPSearchCriteriaParser::begin-parens:
+ * @parser: The #GUPnPSearchCriteriaParser that received the signal
+ *
+ * The ::begin_parens signal is emitted to mark the beginning of a
+ * parenthetical expression.
+ **/
+ signals[BEGIN_PARENS] =
+ g_signal_new ("begin-parens",
+ GUPNP_TYPE_SEARCH_CRITERIA_PARSER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GUPnPSearchCriteriaParserClass,
+ begin_parens),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ /**
+ * GUPnPSearchCriteriaParser::end-parens:
+ * @parser: The #GUPnPSearchCriteriaParser that received the signal
+ *
+ * The ::end_parens signal is emitted to mark the end of a parenthetical
+ * expression.
+ **/
+ signals[END_PARENS] =
+ g_signal_new ("end-parens",
+ GUPNP_TYPE_SEARCH_CRITERIA_PARSER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GUPnPSearchCriteriaParserClass,
+ end_parens),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ /**
+ * GUPnPSearchCriteriaParser::conjunction:
+ * @parser: The #GUPnPSearchCriteriaParser that received the signal
+ *
+ * The ::conjuction signal is emitted whenever a conjuction marker
+ * &lpar;and&rpar; is parsed.
+ **/
+ signals[CONJUNCTION] =
+ g_signal_new ("conjunction",
+ GUPNP_TYPE_SEARCH_CRITERIA_PARSER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GUPnPSearchCriteriaParserClass,
+ conjunction),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ /**
+ * GUPnPSearchCriteriaParser::disjunction:
+ * @parser: The #GUPnPSearchCriteriaParser that received the signal
+ *
+ * The ::disjuction signal is emitted whenever a disjuction marker
+ * &lpar;or&rpar is parsed.
+ **/
+ signals[DISJUNCTION] =
+ g_signal_new ("disjunction",
+ GUPNP_TYPE_SEARCH_CRITERIA_PARSER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GUPnPSearchCriteriaParserClass,
+ disjunction),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ /**
+ * GUPnPSearchCriteriaParser::expression:
+ * @parser: The #GUPnPSearchCriteriaParser that received the signal
+ * @property: The property
+ * @op: The operator as #GUPnPSearchCriteriaOp
+ * @value: The value as string
+ * @error: Place-holder for any possible errors from handler
+ *
+ * The ::expression signal is emitted whenever an expression is parsed.
+ * Set @error and return %FALSE if an error occurred.
+ **/
+ signals[EXPRESSION] =
+ g_signal_new ("expression",
+ GUPNP_TYPE_SEARCH_CRITERIA_PARSER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GUPnPSearchCriteriaParserClass,
+ expression),
+ NULL,
+ NULL,
+ gupnp_av_marshal_BOOLEAN__STRING_UINT_STRING_POINTER,
+ G_TYPE_BOOLEAN,
+ 4,
+ G_TYPE_STRING,
+ GUPNP_TYPE_SEARCH_CRITERIA_OP,
+ G_TYPE_STRING,
+ G_TYPE_POINTER);
+
+ g_type_class_add_private (klass,
+ sizeof (GUPnPSearchCriteriaParserPrivate));
+}
+
+/**
+ * gupnp_search_criteria_parser_new:
+ *
+ * Return value: A new #GUPnPSearchCriteriaParser object.
+ **/
+GUPnPSearchCriteriaParser *
+gupnp_search_criteria_parser_new (void)
+{
+ return g_object_new (GUPNP_TYPE_SEARCH_CRITERIA_PARSER, NULL);
+}
+
+/* Scan a relExp portion of a search criteria string */
+static gboolean
+scan_rel_exp (GUPnPSearchCriteriaParser *parser,
+ GError **error)
+{
+ GTokenValue value;
+ gboolean ret;
+ guint token;
+ GUPnPSearchCriteriaOp op;
+ char *arg1;
+
+ token = g_scanner_get_next_token (parser->priv->scanner);
+ g_assert (token == G_TOKEN_IDENTIFIER); /* Already checked */
+
+ value = g_scanner_cur_value (parser->priv->scanner);
+ arg1 = g_strdup (value.v_string);
+
+ token = g_scanner_get_next_token (parser->priv->scanner);
+ switch (token) {
+ case GUPNP_SEARCH_CRITERIA_OP_EQ:
+ case GUPNP_SEARCH_CRITERIA_OP_NEQ:
+ case GUPNP_SEARCH_CRITERIA_OP_LESS:
+ case GUPNP_SEARCH_CRITERIA_OP_LEQ:
+ case GUPNP_SEARCH_CRITERIA_OP_GREATER:
+ case GUPNP_SEARCH_CRITERIA_OP_GEQ:
+ case GUPNP_SEARCH_CRITERIA_OP_CONTAINS:
+ case GUPNP_SEARCH_CRITERIA_OP_DOES_NOT_CONTAIN:
+ case GUPNP_SEARCH_CRITERIA_OP_DERIVED_FROM:
+ op = token;
+
+ token = g_scanner_get_next_token (parser->priv->scanner);
+ if (token != G_TOKEN_STRING) {
+ g_set_error
+ (error,
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR,
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED,
+ "Expected quoted string at position %u",
+ g_scanner_cur_position
+ (parser->priv->scanner));
+
+ ret = FALSE;
+
+ break;
+ }
+
+ value = g_scanner_cur_value (parser->priv->scanner);
+
+ g_signal_emit (parser, signals[EXPRESSION], 0,
+ arg1, op, value.v_string, error, &ret);
+
+ break;
+
+ case GUPNP_SEARCH_CRITERIA_OP_EXISTS:
+ op = token;
+
+ token = g_scanner_get_next_token (parser->priv->scanner);
+ switch (token) {
+ case SYMBOL_TRUE:
+ g_signal_emit (parser, signals[EXPRESSION], 0,
+ arg1, op, "true", error, &ret);
+
+ break;
+ case SYMBOL_FALSE:
+ g_signal_emit (parser, signals[EXPRESSION], 0,
+ arg1, op, "false", error, &ret);
+
+ break;
+ default:
+ g_set_error
+ (error,
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR,
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED,
+ "Expected boolean value at position %u",
+ g_scanner_cur_position
+ (parser->priv->scanner));
+
+ ret = FALSE;
+
+ break;
+ }
+
+ break;
+
+ default:
+ g_set_error (error,
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR,
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED,
+ "Expected operator at position %u",
+ g_scanner_cur_position
+ (parser->priv->scanner));
+
+ ret = FALSE;
+ }
+
+ g_free (arg1);
+
+ return ret;
+}
+
+static gboolean
+scan_search_exp (GUPnPSearchCriteriaParser *parser,
+ GError **error);
+
+/* Scan a Logical operator and the part after that */
+static gboolean
+scan_logical_op (GUPnPSearchCriteriaParser *parser,
+ GError **error)
+{
+ gboolean ret;
+ guint token;
+
+ token = g_scanner_peek_next_token (parser->priv->scanner);
+
+ switch (token) {
+ case SYMBOL_AND:
+ g_scanner_get_next_token (parser->priv->scanner);
+
+ g_signal_emit (parser, signals[CONJUNCTION], 0);
+
+ ret = scan_search_exp (parser, error);
+
+ break;
+
+ case SYMBOL_OR:
+ g_scanner_get_next_token (parser->priv->scanner);
+
+ g_signal_emit (parser, signals[DISJUNCTION], 0);
+
+ ret = scan_search_exp (parser, error);
+
+ break;
+
+ default:
+
+ ret = TRUE;
+
+ break;
+
+ }
+
+ return ret;
+}
+
+/* Scan a searchExp portion of a search criteria string */
+static gboolean
+scan_search_exp (GUPnPSearchCriteriaParser *parser,
+ GError **error)
+{
+ gboolean ret;
+ guint token;
+
+ token = g_scanner_peek_next_token (parser->priv->scanner);
+ switch (token) {
+ case G_TOKEN_LEFT_PAREN:
+ g_scanner_get_next_token (parser->priv->scanner);
+
+ g_signal_emit (parser, signals[BEGIN_PARENS], 0);
+
+ ret = scan_search_exp (parser, error);
+ if (ret == FALSE)
+ break;
+
+ token = g_scanner_get_next_token (parser->priv->scanner);
+ if (token != G_TOKEN_RIGHT_PAREN) {
+ g_set_error
+ (error,
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR,
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED,
+ "Expected right parenthesis at position %u",
+ g_scanner_cur_position
+ (parser->priv->scanner));
+
+ ret = FALSE;
+
+ break;
+ }
+
+ g_signal_emit (parser, signals[END_PARENS], 0);
+
+ ret = scan_logical_op (parser, error);
+
+ break;
+
+ case G_TOKEN_IDENTIFIER:
+ ret = scan_rel_exp (parser, error);
+ if (ret == FALSE)
+ break;
+
+ ret = scan_logical_op (parser, error);
+
+ break;
+
+ default:
+ g_scanner_get_next_token (parser->priv->scanner);
+
+ g_set_error (error,
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR,
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED,
+ "Expected property name or left parenthesis at "
+ "position %u",
+ g_scanner_cur_position (parser->priv->scanner));
+
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+/**
+ * gupnp_search_criteria_parser_parse_text:
+ * @parser: A #GUPnPSearchCriteriaParser
+ * @text: The search criteria string to be parsed
+ * @error: The location where to store the error information if any, or NULL
+ *
+ * Parses @text, emitting the various defined signals on the way. If an
+ * error occured @error will be set.
+ *
+ * Return value: TRUE on success.
+ **/
+gboolean
+gupnp_search_criteria_parser_parse_text (GUPnPSearchCriteriaParser *parser,
+ const char *text,
+ GError **error)
+{
+ gboolean ret;
+ guint token;
+
+ g_return_val_if_fail (GUPNP_IS_SEARCH_CRITERIA_PARSER (parser),
+ FALSE);
+ g_return_val_if_fail (text != NULL, FALSE);
+
+ /* Feed into scanner */
+ g_scanner_input_text (parser->priv->scanner, text, strlen (text));
+
+ token = g_scanner_peek_next_token (parser->priv->scanner);
+ if (token == SYMBOL_ASTERISK) {
+ g_scanner_get_next_token (parser->priv->scanner);
+
+ /* Do nothing. */
+
+ ret = TRUE;
+ } else
+ ret = scan_search_exp (parser, error);
+
+ if (ret == TRUE) {
+ /* Confirm that we have EOF now */
+ token = g_scanner_get_next_token (parser->priv->scanner);
+ if (token != G_TOKEN_EOF) {
+ g_set_error
+ (error,
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR,
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED,
+ "Expected EOF at position %u",
+ g_scanner_cur_position
+ (parser->priv->scanner));
+ }
+ }
+
+ return ret;
+}
diff --git a/libgupnp-av/gupnp-search-criteria-parser.h b/libgupnp-av/gupnp-search-criteria-parser.h
new file mode 100644
index 0000000..ec9fa32
--- /dev/null
+++ b/libgupnp-av/gupnp-search-criteria-parser.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2008 OpenedHand Ltd.
+ *
+ * Authors: Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GUPNP_SEARCH_CRITERIA_PARSER_H__
+#define __GUPNP_SEARCH_CRITERIA_PARSER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+GType
+gupnp_search_criteria_parser_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_SEARCH_CRITERIA_PARSER \
+ (gupnp_search_criteria_parser_get_type ())
+#define GUPNP_SEARCH_CRITERIA_PARSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ GUPNP_TYPE_SEARCH_CRITERIA_PARSER, \
+ GUPnPSearchCriteriaParser))
+#define GUPNP_SEARCH_CRITERIA_PARSER_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_CAST ((obj), \
+ GUPNP_TYPE_SEARCH_CRITERIA_PARSER, \
+ GUPnPSearchCriteriaParserClass))
+#define GUPNP_IS_SEARCH_CRITERIA_PARSER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ GUPNP_TYPE_SEARCH_CRITERIA_PARSER))
+#define GUPNP_IS_SEARCH_CRITERIA_PARSER_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE ((obj), \
+ GUPNP_TYPE_SEARCH_CRITERIA_PARSER))
+#define GUPNP_SEARCH_CRITERIA_PARSER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ GUPNP_TYPE_SEARCH_CRITERIA_PARSER, \
+ GUPnPSearchCriteriaParserClass))
+
+/**
+ * GUPnPSearchCriteriaOp:
+ * @GUPNP_SEARCH_CRITERIA_OP_EQ: '='
+ * @GUPNP_SEARCH_CRITERIA_OP_NEQ: '!='
+ * @GUPNP_SEARCH_CRITERIA_OP_LESS: '<'
+ * @GUPNP_SEARCH_CRITERIA_OP_LEQ: '<='
+ * @GUPNP_SEARCH_CRITERIA_OP_GREATER: '>'
+ * @GUPNP_SEARCH_CRITERIA_OP_GEQ: '>='
+ * @GUPNP_SEARCH_CRITERIA_OP_CONTAINS: 'contains'
+ * @GUPNP_SEARCH_CRITERIA_OP_DOES_NOT_CONTAIN: 'doesNotContain'
+ * @GUPNP_SEARCH_CRITERIA_OP_DERIVED_FROM: 'derivedFrom'
+ * @GUPNP_SEARCH_CRITERIA_OP_EXISTS: 'exists'
+ *
+ * The possible operators in SearchCriteria strings.
+ *
+ **/
+typedef enum {
+ /* G_TYPE_STRING */
+ GUPNP_SEARCH_CRITERIA_OP_EQ = G_TOKEN_LAST + 1,
+ GUPNP_SEARCH_CRITERIA_OP_NEQ = G_TOKEN_LAST + 2,
+ GUPNP_SEARCH_CRITERIA_OP_LESS = G_TOKEN_LAST + 3,
+ GUPNP_SEARCH_CRITERIA_OP_LEQ = G_TOKEN_LAST + 4,
+ GUPNP_SEARCH_CRITERIA_OP_GREATER = G_TOKEN_LAST + 5,
+ GUPNP_SEARCH_CRITERIA_OP_GEQ = G_TOKEN_LAST + 6,
+ GUPNP_SEARCH_CRITERIA_OP_CONTAINS = G_TOKEN_LAST + 7,
+ GUPNP_SEARCH_CRITERIA_OP_DOES_NOT_CONTAIN = G_TOKEN_LAST + 8,
+ GUPNP_SEARCH_CRITERIA_OP_DERIVED_FROM = G_TOKEN_LAST + 9,
+
+ /* G_TYPE_BOOLEAN */
+ GUPNP_SEARCH_CRITERIA_OP_EXISTS = G_TOKEN_LAST + 10
+} GUPnPSearchCriteriaOp;
+
+GType
+gupnp_search_criteria_op_get_type (void) G_GNUC_CONST;
+
+#define GUPNP_TYPE_SEARCH_CRITERIA_OP (gupnp_search_criteria_op_get_type ())
+
+#define GUPNP_SEARCH_CRITERIA_PARSER_ERROR \
+ (gupnp_search_criteria_parser_error_quark ())
+
+GQuark
+gupnp_search_criteria_parser_error_quark (void);
+
+typedef enum {
+ GUPNP_SEARCH_CRITERIA_PARSER_ERROR_FAILED
+} GUPnPSearchCriteriaParserError;
+
+typedef struct _GUPnPSearchCriteriaParserPrivate
+ GUPnPSearchCriteriaParserPrivate;
+
+typedef struct {
+ GObject parent;
+
+ GUPnPSearchCriteriaParserPrivate *priv;
+} GUPnPSearchCriteriaParser;
+
+typedef struct {
+ GObjectClass parent_class;
+
+ /* signals */
+ void (* begin_parens) (GUPnPSearchCriteriaParser *parser);
+ void (* end_parens) (GUPnPSearchCriteriaParser *parser);
+ void (* conjunction) (GUPnPSearchCriteriaParser *parser);
+ void (* disjunction) (GUPnPSearchCriteriaParser *parser);
+ gboolean (* expression) (GUPnPSearchCriteriaParser *parser,
+ const char *property,
+ GUPnPSearchCriteriaOp op,
+ const char *value,
+ GError **error);
+
+ /* future padding */
+ void (* _gupnp_reserved1) (void);
+ void (* _gupnp_reserved2) (void);
+ void (* _gupnp_reserved3) (void);
+ void (* _gupnp_reserved4) (void);
+} GUPnPSearchCriteriaParserClass;
+
+GUPnPSearchCriteriaParser *
+gupnp_search_criteria_parser_new (void);
+
+gboolean
+gupnp_search_criteria_parser_parse_text (GUPnPSearchCriteriaParser *parser,
+ const char *text,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __GUPNP_SEARCH_CRITERIA_PARSER_H__ */
diff --git a/libgupnp-av/gvalue-util.c b/libgupnp-av/gvalue-util.c
new file mode 100644
index 0000000..4017648
--- /dev/null
+++ b/libgupnp-av/gvalue-util.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2007 OpenedHand Ltd.
+ *
+ * Author: Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "gvalue-util.h"
+
+gboolean
+gvalue_util_set_value_from_string (GValue *value,
+ const char *str)
+{
+ GValue tmp_value = {0, };
+ int i;
+ long l;
+ double d;
+
+ g_return_val_if_fail (str != NULL, FALSE);
+
+ switch (G_VALUE_TYPE (value)) {
+ case G_TYPE_STRING:
+ g_value_set_string (value, str);
+
+ break;
+
+ case G_TYPE_CHAR:
+ g_value_set_char (value, *str);
+
+ break;
+
+ case G_TYPE_UCHAR:
+ g_value_set_uchar (value, *str);
+
+ break;
+
+ case G_TYPE_INT:
+ i = atoi (str);
+ g_value_set_int (value, i);
+
+ break;
+
+ case G_TYPE_UINT:
+ i = atoi (str);
+ g_value_set_uint (value, (guint) i);
+
+ break;
+
+ case G_TYPE_INT64:
+ i = atoi (str);
+ g_value_set_int64 (value, (gint64) i);
+
+ break;
+
+ case G_TYPE_UINT64:
+ i = atoi (str);
+ g_value_set_uint64 (value, (guint64) i);
+
+ break;
+
+ case G_TYPE_LONG:
+ l = atol (str);
+ g_value_set_long (value, l);
+
+ break;
+
+ case G_TYPE_ULONG:
+ l = atol (str);
+ g_value_set_ulong (value, (gulong) l);
+
+ break;
+
+ case G_TYPE_FLOAT:
+ d = atof (str);
+ g_value_set_float (value, (float) d);
+
+ break;
+
+ case G_TYPE_DOUBLE:
+ d = atof (str);
+ g_value_set_float (value, d);
+
+ break;
+
+ case G_TYPE_BOOLEAN:
+ if (g_ascii_strcasecmp (str, "true") == 0 ||
+ g_ascii_strcasecmp (str, "yes") == 0)
+ g_value_set_boolean (value, TRUE);
+ else if (g_ascii_strcasecmp (str, "false") == 0 ||
+ g_ascii_strcasecmp (str, "no") == 0)
+ g_value_set_boolean (value, FALSE);
+ else {
+ int i;
+
+ i = atoi (str);
+ g_value_set_boolean (value, i ? TRUE : FALSE);
+ }
+
+ break;
+
+ default:
+ /* Try to convert */
+ if (g_value_type_transformable (G_TYPE_STRING,
+ G_VALUE_TYPE (value))) {
+ g_value_init (&tmp_value, G_TYPE_STRING);
+ g_value_set_static_string (&tmp_value, str);
+
+ g_value_transform (&tmp_value, value);
+
+ g_value_unset (&tmp_value);
+
+ } else if (g_value_type_transformable (G_TYPE_INT,
+ G_VALUE_TYPE (value))) {
+ i = atoi (str);
+
+ g_value_init (&tmp_value, G_TYPE_INT);
+ g_value_set_int (&tmp_value, i);
+
+ g_value_transform (&tmp_value, value);
+
+ g_value_unset (&tmp_value);
+
+ } else {
+ g_warning ("Failed to transform integer "
+ "value to type %s",
+ G_VALUE_TYPE_NAME (value));
+
+ return FALSE;
+ }
+
+ break;
+ }
+
+ return TRUE;
+}
+
diff --git a/libgupnp-av/gvalue-util.h b/libgupnp-av/gvalue-util.h
new file mode 100644
index 0000000..c3b883a
--- /dev/null
+++ b/libgupnp-av/gvalue-util.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2007 OpenedHand Ltd.
+ *
+ * Author: Jorn Baayen <jorn@openedhand.com>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GVALUE_UTIL_H__
+#define __GVALUE_UTIL_H__
+
+#include <glib-object.h>
+
+G_GNUC_INTERNAL gboolean
+gvalue_util_set_value_from_string (GValue *value,
+ const char *str);
+
+#endif /* __GVALUE_UTIL_H__ */
+
diff --git a/libgupnp-av/xml-util.c b/libgupnp-av/xml-util.c
new file mode 100644
index 0000000..92e71bb
--- /dev/null
+++ b/libgupnp-av/xml-util.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2006, 2007 OpenedHand Ltd.
+ * Copyright (C) 2007 Zeeshan Ali.
+ *
+ * Author: Jorn Baayen <jorn@openedhand.com>
+ * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <string.h>
+
+#include "xml-util.h"
+
+xmlNode *
+xml_util_get_element (xmlNode *node,
+ ...)
+{
+ va_list var_args;
+
+ va_start (var_args, node);
+
+ while (TRUE) {
+ const char *arg;
+
+ arg = va_arg (var_args, const char *);
+ if (!arg)
+ break;
+
+ for (node = node->children; node; node = node->next) {
+ if (node->name == NULL)
+ continue;
+
+ if (!g_ascii_strcasecmp (arg, (char *) node->name))
+ break;
+ }
+
+ if (!node)
+ break;
+ }
+
+ va_end (var_args);
+
+ return node;
+}
+
+GList *
+xml_util_get_child_elements_by_name (xmlNode *node, const char *name)
+{
+ GList *children = NULL;
+
+ for (node = node->children; node; node = node->next) {
+ if (node->name == NULL) {
+ continue;
+ }
+
+ if (strcmp (name, (char *) node->name) == 0) {
+ children = g_list_append (children, node);
+ }
+ }
+
+ return children;
+}
+
+const char *
+xml_util_get_child_element_content (xmlNode *node,
+ const char *child_name)
+{
+ xmlNode *child_node;
+ const char *content;
+
+ child_node = xml_util_get_element (node, child_name, NULL);
+ if (!child_node || !(child_node->children))
+ return NULL;
+
+ content = (const char *) child_node->children->content;
+ if (!content)
+ return NULL;
+
+ return content;
+}
+
+const char *
+xml_util_get_attribute_content (xmlNode *node,
+ const char *attribute_name)
+{
+ xmlAttr *attribute;
+
+ for (attribute = node->properties;
+ attribute;
+ attribute = attribute->next) {
+ if (attribute->name == NULL)
+ continue;
+
+ if (strcmp (attribute_name, (char *) attribute->name) == 0)
+ break;
+ }
+
+ if (attribute)
+ return (const char *) attribute->children->content;
+ else
+ return NULL;
+}
+
+gboolean
+xml_util_get_boolean_attribute (xmlNode *node,
+ const char *attribute_name)
+{
+ const char *content;
+ gchar *str;
+ gboolean ret;
+
+ content = xml_util_get_attribute_content (node, attribute_name);
+ if (!content)
+ return FALSE;
+
+ str = (char *) content;
+ if (g_ascii_strcasecmp (str, "true") == 0 ||
+ g_ascii_strcasecmp (str, "yes") == 0)
+ ret = TRUE;
+ else if (g_ascii_strcasecmp (str, "false") == 0 ||
+ g_ascii_strcasecmp (str, "no") == 0)
+ ret = FALSE;
+ else {
+ int i;
+
+ i = atoi (str);
+ ret = i ? TRUE : FALSE;
+ }
+
+ return ret;
+}
+
+guint
+xml_util_get_uint_attribute (xmlNode *node,
+ const char *attribute_name,
+ guint default_value)
+{
+ return (guint) xml_util_get_long_attribute (node,
+ attribute_name,
+ (glong) default_value);
+}
+
+gint
+xml_util_get_int_attribute (xmlNode *node,
+ const char *attribute_name,
+ gint default_value)
+{
+ return (gint) xml_util_get_long_attribute (node,
+ attribute_name,
+ (glong) default_value);
+}
+
+glong
+xml_util_get_long_attribute (xmlNode *node,
+ const char *attribute_name,
+ glong default_value)
+{
+ return (glong) xml_util_get_int64_attribute (node,
+ attribute_name,
+ (gint64) default_value);
+}
+
+gint64
+xml_util_get_int64_attribute (xmlNode *node,
+ const char *attribute_name,
+ gint64 default_value)
+{
+ const char *content;
+
+ content = xml_util_get_attribute_content (node, attribute_name);
+ if (!content)
+ return default_value;
+
+ return g_ascii_strtoll (content, NULL, 0);
+}
+
+xmlNode *
+xml_util_set_child (xmlNode *parent_node,
+ xmlNs *namespace,
+ xmlDoc *doc,
+ const char *name,
+ const char *value)
+{
+ xmlNode *node;
+ xmlChar *escaped;
+
+ node = xml_util_get_element (parent_node, name, NULL);
+ if (node == NULL) {
+ node = xmlNewChild (parent_node,
+ namespace,
+ (unsigned char *) name,
+ NULL);
+ }
+
+ escaped = xmlEncodeSpecialChars (doc, (const unsigned char *) value);
+ xmlNodeSetContent (node, escaped);
+ xmlFree (escaped);
+
+ return node;
+}
+
+gboolean
+xml_util_verify_attribute_is_boolean (xmlNode *node,
+ const char *attribute_name)
+{
+ const char *content;
+ char *str;
+
+ content = xml_util_get_attribute_content (node, attribute_name);
+ if (content == NULL)
+ return FALSE;
+
+ str = (char *) content;
+
+ return g_ascii_strcasecmp (str, "true") == 0 ||
+ g_ascii_strcasecmp (str, "yes") == 0 ||
+ g_ascii_strcasecmp (str, "false") == 0 ||
+ g_ascii_strcasecmp (str, "no") == 0 ||
+ g_ascii_strcasecmp (str, "0") == 0 ||
+ g_ascii_strcasecmp (str, "1") == 0;
+}
+
diff --git a/libgupnp-av/xml-util.h b/libgupnp-av/xml-util.h
new file mode 100644
index 0000000..e50066c
--- /dev/null
+++ b/libgupnp-av/xml-util.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2006, 2007 OpenedHand Ltd.
+ * Copyright (C) 2007 Zeeshan Ali.
+ *
+ * Author: Jorn Baayen <jorn@openedhand.com>
+ * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ *
+ * 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __XML_UTIL_H__
+#define __XML_UTIL_H__
+
+#include <glib.h>
+#include <libxml/tree.h>
+#include <stdarg.h>
+
+/* Misc utilities for inspecting xmlNodes */
+G_GNUC_INTERNAL xmlNode *
+xml_util_get_element (xmlNode *node,
+ ...) G_GNUC_NULL_TERMINATED;
+
+G_GNUC_INTERNAL GList *
+xml_util_get_child_elements_by_name (xmlNode *node,
+ const char *name);
+
+G_GNUC_INTERNAL const char *
+xml_util_get_child_element_content (xmlNode *node,
+ const char *child_name);
+
+G_GNUC_INTERNAL const char *
+xml_util_get_attribute_content (xmlNode *node,
+ const char *attribute_name);
+
+G_GNUC_INTERNAL gboolean
+xml_util_get_boolean_attribute (xmlNode *node,
+ const char *attribute_name);
+
+G_GNUC_INTERNAL guint
+xml_util_get_uint_attribute (xmlNode *node,
+ const char *attribute_name,
+ guint default_value);
+
+G_GNUC_INTERNAL gint
+xml_util_get_int_attribute (xmlNode *node,
+ const char *attribute_name,
+ gint default_value);
+
+G_GNUC_INTERNAL glong
+xml_util_get_long_attribute (xmlNode *node,
+ const char *attribute_name,
+ glong default_value);
+
+G_GNUC_INTERNAL gint64
+xml_util_get_int64_attribute (xmlNode *node,
+ const char *attribute_name,
+ gint64 default_value);
+
+G_GNUC_INTERNAL xmlNode *
+xml_util_set_child (xmlNode *parent_node,
+ xmlNs *namespace,
+ xmlDoc *doc,
+ const char *name,
+ const char *value);
+
+G_GNUC_INTERNAL gboolean
+xml_util_verify_attribute_is_boolean (xmlNode *node,
+ const char *attribute_name);
+
+#endif /* __XML_UTIL_H__ */