Update dleyna to 0.2.0 (4bcad24)
authorRegis Merlino <regis.merlino@intel.com>
Mon, 10 Jun 2013 13:10:21 +0000 (15:10 +0200)
committerRegis Merlino <regis.merlino@intel.com>
Mon, 10 Jun 2013 13:10:21 +0000 (15:10 +0200)
66 files changed:
ChangeLog
configure
configure.ac
dleyna-connector-dbus/ChangeLog
dleyna-connector-dbus/Makefile.am
dleyna-connector-dbus/Makefile.in
dleyna-connector-dbus/README
dleyna-connector-dbus/configure
dleyna-connector-dbus/configure.ac
dleyna-connector-dbus/dleyna-connector-dbus-1.0.pc.in [new file with mode: 0644]
dleyna-connector-dbus/m4/compiler-flags.m4
dleyna-core/ChangeLog
dleyna-core/Makefile.am
dleyna-core/Makefile.in
dleyna-core/README
dleyna-core/configure
dleyna-core/configure.ac
dleyna-core/libdleyna/core/task-processor.c
dleyna-core/m4/compiler-flags.m4
dleyna-core/m4/log.m4
dleyna-renderer/ChangeLog
dleyna-renderer/Makefile.in
dleyna-renderer/README
dleyna-renderer/configure
dleyna-renderer/configure.ac
dleyna-renderer/libdleyna/renderer/Makefile.am
dleyna-renderer/libdleyna/renderer/Makefile.in
dleyna-renderer/libdleyna/renderer/device.c
dleyna-renderer/libdleyna/renderer/device.h
dleyna-renderer/libdleyna/renderer/dleyna-renderer-service.conf
dleyna-renderer/libdleyna/renderer/prop-defs.h
dleyna-renderer/libdleyna/renderer/server.c
dleyna-renderer/libdleyna/renderer/task.c
dleyna-renderer/libdleyna/renderer/task.h
dleyna-renderer/libdleyna/renderer/upnp.c
dleyna-renderer/libdleyna/renderer/upnp.h
dleyna-renderer/m4/compiler-flags.m4
dleyna-renderer/server/Makefile.am
dleyna-renderer/server/Makefile.in
dleyna-renderer/server/com.intel.dleyna-renderer.service.in
dleyna-server/ChangeLog
dleyna-server/Makefile.in
dleyna-server/README
dleyna-server/configure
dleyna-server/configure.ac
dleyna-server/libdleyna/server/Makefile.am
dleyna-server/libdleyna/server/Makefile.in
dleyna-server/libdleyna/server/async.c
dleyna-server/libdleyna/server/async.h
dleyna-server/libdleyna/server/device.c
dleyna-server/libdleyna/server/device.h
dleyna-server/libdleyna/server/dleyna-server-service.conf
dleyna-server/libdleyna/server/interface.h
dleyna-server/libdleyna/server/props.c
dleyna-server/libdleyna/server/props.h
dleyna-server/libdleyna/server/server.c
dleyna-server/libdleyna/server/task.c
dleyna-server/libdleyna/server/task.h
dleyna-server/libdleyna/server/upnp.c
dleyna-server/libdleyna/server/upnp.h
dleyna-server/m4/compiler-flags.m4
dleyna-server/server/Makefile.am
dleyna-server/server/Makefile.in
dleyna-server/server/com.intel.dleyna-server.service.in
dleyna-server/test/dbus/Makefile.in
packaging/dLeyna.spec

index 79ad023..ece835c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+version 0.1.0
+       - dleyna-connector-dbus v0.1.0
+       - dleyna-core           v0.1.0
+       - dleyna-renderer       v0.1.0
+       - dleyna-server         v0.1.0
+       - dleyna-control        v0.1.0
+
+version 0.0.2
+       - dleyna-connector-dbus v0.0.2
+       - dleyna-core           v0.0.2
+       - dleyna-renderer       v0.0.2
+       - dleyna-server         v0.0.2
+       - dleyna-control        v0.0.1
+       
 version 0.0.1
        - Initial version of dleyna-linux
 
index 982d80d..d808891 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for dleyna-linux 0.0.1.
+# Generated by GNU Autoconf 2.69 for dleyna-linux 0.2.0.
 #
 # Report bugs to <https://github.com/01org/dleyna-linux/issues/new>.
 #
@@ -579,8 +579,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='dleyna-linux'
 PACKAGE_TARNAME='dleyna-linux'
-PACKAGE_VERSION='0.0.1'
-PACKAGE_STRING='dleyna-linux 0.0.1'
+PACKAGE_VERSION='0.2.0'
+PACKAGE_STRING='dleyna-linux 0.2.0'
 PACKAGE_BUGREPORT='https://github.com/01org/dleyna-linux/issues/new'
 PACKAGE_URL='https://01.org/dleyna/'
 
@@ -1206,7 +1206,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures dleyna-linux 0.0.1 to adapt to many kinds of systems.
+\`configure' configures dleyna-linux 0.2.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1272,7 +1272,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of dleyna-linux 0.0.1:";;
+     short | recursive ) echo "Configuration of dleyna-linux 0.2.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1349,7 +1349,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-dleyna-linux configure 0.0.1
+dleyna-linux configure 0.2.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1366,7 +1366,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by dleyna-linux $as_me 0.0.1, which was
+It was created by dleyna-linux $as_me 0.2.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2188,7 +2188,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='dleyna-linux'
- VERSION='0.0.1'
+ VERSION='0.2.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2811,7 +2811,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by dleyna-linux $as_me 0.0.1, which was
+This file was extended by dleyna-linux $as_me 0.2.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -2874,7 +2874,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-dleyna-linux config.status 0.0.1
+dleyna-linux config.status 0.2.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index f31b73c..0f5fd77 100644 (file)
@@ -1,7 +1,7 @@
 AC_PREREQ([2.66])
 
 AC_INIT([dleyna-linux],
-       [0.0.1],
+       [0.2.0],
        [https://github.com/01org/dleyna-linux/issues/new],
        ,
        [https://01.org/dleyna/])
index 01d13ff..74aaf68 100644 (file)
@@ -1,3 +1,9 @@
+version 0.1.0
+       - Prepare for first stable branch
+
+version 0.0.2
+       - Add autogen.sh script to call `autoreconf -i`
+
 version 0.0.1
        - Initial version of dleyna-connector-dbus.
 
index 7f5ef76..97e07a2 100644 (file)
@@ -30,5 +30,11 @@ MAINTAINERCLEANFILES =       Makefile.in             \
                        build-aux/missing       \
                        build-aux/install-sh
 
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = dleyna-connector-dbus-1.0.pc
+
+CLEANFILES = $(pkgconfig_DATA)
+DISTCLEANFILES = $(pkgconfig_DATA)
+
 maintainer-clean-local:
        rm -rf build-aux
index 51de7cd..333217d 100644 (file)
@@ -15,6 +15,7 @@
 
 @SET_MAKE@
 
+
 VPATH = @srcdir@
 am__make_dryrun = \
   { \
@@ -54,6 +55,7 @@ host_triplet = @host@
 subdir = .
 DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
        $(srcdir)/Makefile.in $(srcdir)/config.h.in \
+       $(srcdir)/dleyna-connector-dbus-1.0.pc.in \
        $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
        build-aux/compile build-aux/config.guess build-aux/config.sub \
        build-aux/depcomp build-aux/install-sh build-aux/ltmain.sh \
@@ -70,7 +72,7 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
  configure.lineno config.status.lineno
 mkinstalldirs = $(install_sh) -d
 CONFIG_HEADER = config.h
-CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_FILES = dleyna-connector-dbus-1.0.pc
 CONFIG_CLEAN_VPATH_FILES =
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
 am__vpath_adj = case $$p in \
@@ -99,7 +101,8 @@ am__uninstall_files_from_dir = { \
     || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
          $(am__cd) "$$dir" && rm -f $$files; }; \
   }
-am__installdirs = "$(DESTDIR)$(connectordir)"
+am__installdirs = "$(DESTDIR)$(connectordir)" \
+       "$(DESTDIR)$(pkgconfigdir)"
 LTLIBRARIES = $(connector_LTLIBRARIES)
 am__DEPENDENCIES_1 =
 libdleyna_connector_dbus_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
@@ -148,6 +151,7 @@ am__can_run_installinfo = \
     n|no|NO) false;; \
     *) (install-info --version) >/dev/null 2>&1;; \
   esac
+DATA = $(pkgconfig_DATA)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -318,6 +322,10 @@ MAINTAINERCLEANFILES = Makefile.in         \
                        build-aux/missing       \
                        build-aux/install-sh
 
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = dleyna-connector-dbus-1.0.pc
+CLEANFILES = $(pkgconfig_DATA)
+DISTCLEANFILES = $(pkgconfig_DATA)
 all: config.h
        $(MAKE) $(AM_MAKEFLAGS) all-am
 
@@ -372,6 +380,8 @@ $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
 
 distclean-hdr:
        -rm -f config.h stamp-h1
+dleyna-connector-dbus-1.0.pc: $(top_builddir)/config.status $(srcdir)/dleyna-connector-dbus-1.0.pc.in
+       cd $(top_builddir) && $(SHELL) ./config.status $@
 install-connectorLTLIBRARIES: $(connector_LTLIBRARIES)
        @$(NORMAL_INSTALL)
        @list='$(connector_LTLIBRARIES)'; test -n "$(connectordir)" || list=; \
@@ -458,6 +468,27 @@ clean-libtool:
 
 distclean-libtool:
        -rm -f libtool config.lt
+install-pkgconfigDATA: $(pkgconfig_DATA)
+       @$(NORMAL_INSTALL)
+       @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
+       fi; \
+       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)$(pkgconfigdir)'"; \
+         $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
+       done
+
+uninstall-pkgconfigDATA:
+       @$(NORMAL_UNINSTALL)
+       @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+       dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
 
 ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
        list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -675,9 +706,9 @@ distcleancheck: distclean
               exit 1; } >&2
 check-am: all-am
 check: check-am
-all-am: Makefile $(LTLIBRARIES) config.h
+all-am: Makefile $(LTLIBRARIES) $(DATA) config.h
 installdirs:
-       for dir in "$(DESTDIR)$(connectordir)"; do \
+       for dir in "$(DESTDIR)$(connectordir)" "$(DESTDIR)$(pkgconfigdir)"; do \
          test -z "$$dir" || $(MKDIR_P) "$$dir"; \
        done
 install: install-am
@@ -702,12 +733,14 @@ install-strip:
 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)
        -rm -f src/$(DEPDIR)/$(am__dirstamp)
        -rm -f src/$(am__dirstamp)
+       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
 
 maintainer-clean-generic:
        @echo "This command is intended for maintainers to use"
@@ -737,7 +770,7 @@ info: info-am
 
 info-am:
 
-install-data-am: install-connectorLTLIBRARIES
+install-data-am: install-connectorLTLIBRARIES install-pkgconfigDATA
 
 install-dvi: install-dvi-am
 
@@ -786,7 +819,7 @@ ps: ps-am
 
 ps-am:
 
-uninstall-am: uninstall-connectorLTLIBRARIES
+uninstall-am: uninstall-connectorLTLIBRARIES uninstall-pkgconfigDATA
 
 .MAKE: all install-am install-strip
 
@@ -801,12 +834,12 @@ uninstall-am: uninstall-connectorLTLIBRARIES
        install-data-am install-dvi install-dvi-am install-exec \
        install-exec-am install-html install-html-am install-info \
        install-info-am install-man install-pdf install-pdf-am \
-       install-ps install-ps-am install-strip installcheck \
-       installcheck-am installdirs maintainer-clean \
+       install-pkgconfigDATA install-ps install-ps-am install-strip \
+       installcheck installcheck-am installdirs maintainer-clean \
        maintainer-clean-generic maintainer-clean-local mostlyclean \
        mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
        pdf pdf-am ps ps-am tags uninstall uninstall-am \
-       uninstall-connectorLTLIBRARIES
+       uninstall-connectorLTLIBRARIES uninstall-pkgconfigDATA
 
 
 maintainer-clean-local:
index f1149e0..928e492 100644 (file)
@@ -19,8 +19,7 @@ follows:
      # cd dleyna-connector-dbus
 
    Configure and build
-     # ./autoreconf -i
-     # ./configure
+     # ./autogen.sh
      # make
 
    Final installation
index b3f6ecf..65bee6e 100755 (executable)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for dleyna-connector-dbus 0.0.1.
+# Generated by GNU Autoconf 2.69 for dleyna-connector-dbus 0.1.0.
 #
 # Report bugs to <https://github.com/01org/dleyna-connector-dbus/issues/new>.
 #
@@ -591,8 +591,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='dleyna-connector-dbus'
 PACKAGE_TARNAME='dleyna-connector-dbus'
-PACKAGE_VERSION='0.0.1'
-PACKAGE_STRING='dleyna-connector-dbus 0.0.1'
+PACKAGE_VERSION='0.1.0'
+PACKAGE_STRING='dleyna-connector-dbus 0.1.0'
 PACKAGE_BUGREPORT='https://github.com/01org/dleyna-connector-dbus/issues/new'
 PACKAGE_URL='https://01.org/dleyna/'
 
@@ -1343,7 +1343,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures dleyna-connector-dbus 0.0.1 to adapt to many kinds of systems.
+\`configure' configures dleyna-connector-dbus 0.1.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1414,7 +1414,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of dleyna-connector-dbus 0.0.1:";;
+     short | recursive ) echo "Configuration of dleyna-connector-dbus 0.1.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1542,7 +1542,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-dleyna-connector-dbus configure 0.0.1
+dleyna-connector-dbus configure 0.1.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2019,7 +2019,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by dleyna-connector-dbus $as_me 0.0.1, which was
+It was created by dleyna-connector-dbus $as_me 0.1.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2842,7 +2842,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='dleyna-connector-dbus'
- VERSION='0.0.1'
+ VERSION='0.1.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -12673,7 +12673,7 @@ $as_echo "ok" >&6; }
 
 
 
-ac_config_files="$ac_config_files Makefile"
+ac_config_files="$ac_config_files Makefile dleyna-connector-dbus-1.0.pc"
 
 
 cat >confcache <<\_ACEOF
@@ -13202,7 +13202,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by dleyna-connector-dbus $as_me 0.0.1, which was
+This file was extended by dleyna-connector-dbus $as_me 0.1.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -13269,7 +13269,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-dleyna-connector-dbus config.status 0.0.1
+dleyna-connector-dbus config.status 0.1.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -13679,6 +13679,7 @@ do
     "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
     "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "dleyna-connector-dbus-1.0.pc") CONFIG_FILES="$CONFIG_FILES dleyna-connector-dbus-1.0.pc" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
index a5bce0a..81edb3f 100644 (file)
@@ -1,7 +1,7 @@
 AC_PREREQ([2.66])
 
 AC_INIT([dleyna-connector-dbus],
-       [0.0.1],
+       [0.1.0],
        [https://github.com/01org/dleyna-connector-dbus/issues/new],
        ,
        [https://01.org/dleyna/])
@@ -138,7 +138,9 @@ AC_ARG_WITH(log-level,
 
 DLEYNA_LOG_LEVEL_CHECK([${with_log_level}])
 
-AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([Makefile      \
+               dleyna-connector-dbus-1.0.pc
+               ])
 
 AC_OUTPUT
 
diff --git a/dleyna-connector-dbus/dleyna-connector-dbus-1.0.pc.in b/dleyna-connector-dbus/dleyna-connector-dbus-1.0.pc.in
new file mode 100644 (file)
index 0000000..8860d22
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libexecdir=@libexecdir@
+includedir=${prefix}/include
+libdir=@libdir@
+
+Name: @PACKAGE@
+Description: dLeyna dbus connector
+Libs: -L${libdir}/dleyna-1.0/connectors -ldleyna-connector-dbus
+Requires.private: glib-2.0 gio-2.0 dbus-1
+Version: @VERSION@
\ No newline at end of file
index de8aa1c..5158ec4 100644 (file)
@@ -1,7 +1,7 @@
 dnl
-dnl dleyna-connector-dbus
+dnl dLeyna
 dnl
-dnl Copyright (C) 2013 Intel Corporation. All rights reserved.
+dnl Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
 dnl
 dnl This program is free software; you can redistribute it and/or modify it
 dnl under the terms and conditions of the GNU Lesser General Public License,
@@ -16,6 +16,7 @@ dnl You should have received a copy of the GNU Lesser General Public License
 dnl along with this program; if not, write to the Free Software Foundation, Inc.,
 dnl 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 dnl
+dnl Ludovic Ferrandis <ludovic.ferrandis@intel.com>
 dnl Regis Merlino <regis.merlino@intel.com>
 dnl
 
index caf3436..513201a 100644 (file)
@@ -1,3 +1,11 @@
+version 0.1.0
+       - Prepare for first stable branch
+       
+version 0.0.2
+       - Add autogen.sh script to call `autoreconf -i`
+       - Fixed bug : dLeyna-renderer can crash on shutdown
+         https://github.com/01org/dleyna-renderer/issues/69
+
 version 0.0.1
        - Initial version of dleyna-core.
        - Enable support of deleyna-core as git submodules.
index 45a6fb1..c166e83 100644 (file)
@@ -2,7 +2,7 @@ libdleyna_coreincdir = $(includedir)/dleyna-1.0/libdleyna/core
 connectordir = $(libdir)/dleyna-1.0/connectors
 sysconfigdir = $(sysconfdir)
 
-DLEYNA_CORE_VERSION = 1:0:0
+DLEYNA_CORE_VERSION = 1:2:0
 
 AM_CFLAGS =    $(GLIB_CFLAGS)                          \
                $(GIO_CFLAGS)                           \
index e4740d3..9a9693c 100644 (file)
@@ -309,7 +309,7 @@ with_log_level = @with_log_level@
 libdleyna_coreincdir = $(includedir)/dleyna-1.0/libdleyna/core
 connectordir = $(libdir)/dleyna-1.0/connectors
 sysconfigdir = $(sysconfdir)
-DLEYNA_CORE_VERSION = 1:0:0
+DLEYNA_CORE_VERSION = 1:2:0
 AM_CFLAGS = $(GLIB_CFLAGS)                             \
                $(GIO_CFLAGS)                           \
                $(GMODULE_CFLAGS)                       \
index 7569ece..3031deb 100644 (file)
@@ -19,8 +19,7 @@ follows:
      # cd dleyna-core
 
    Configure and build
-     # ./autoreconf -i
-     # ./configure
+     # ./autogen.sh
      # make
 
    Final installation
index 1428302..fc3fbe6 100755 (executable)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for dleyna-core 0.0.1.
+# Generated by GNU Autoconf 2.69 for dleyna-core 0.1.0.
 #
 # Report bugs to <https://github.com/01org/dleyna-core/issues/new>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='dleyna-core'
 PACKAGE_TARNAME='dleyna-core'
-PACKAGE_VERSION='0.0.1'
-PACKAGE_STRING='dleyna-core 0.0.1'
+PACKAGE_VERSION='0.1.0'
+PACKAGE_STRING='dleyna-core 0.1.0'
 PACKAGE_BUGREPORT='https://github.com/01org/dleyna-core/issues/new'
 PACKAGE_URL='https://01.org/dleyna/'
 
@@ -1345,7 +1345,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures dleyna-core 0.0.1 to adapt to many kinds of systems.
+\`configure' configures dleyna-core 0.1.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1415,7 +1415,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of dleyna-core 0.0.1:";;
+     short | recursive ) echo "Configuration of dleyna-core 0.1.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1543,7 +1543,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-dleyna-core configure 0.0.1
+dleyna-core configure 0.1.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2020,7 +2020,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by dleyna-core $as_me 0.0.1, which was
+It was created by dleyna-core $as_me 0.1.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2843,7 +2843,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='dleyna-core'
- VERSION='0.0.1'
+ VERSION='0.1.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -13220,7 +13220,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by dleyna-core $as_me 0.0.1, which was
+This file was extended by dleyna-core $as_me 0.1.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -13287,7 +13287,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-dleyna-core config.status 0.0.1
+dleyna-core config.status 0.1.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index ad3a35a..1f3bc84 100644 (file)
@@ -1,7 +1,7 @@
 AC_PREREQ([2.66])
 
 AC_INIT([dleyna-core],
-       [0.0.1],
+       [0.1.0],
        [https://github.com/01org/dleyna-core/issues/new],
        ,
        [https://01.org/dleyna/])
index cb01f26..efbd9ab 100644 (file)
@@ -90,18 +90,6 @@ static void prv_task_free_cb(gpointer data, gpointer user_data)
        task_queue->task_delete_cb(data, task_queue->user_data);
 }
 
-static gboolean prv_finally_cb(gpointer data)
-{
-       dleyna_task_queue_t *task_queue = data;
-
-       task_queue->task_queue_finally_cb(task_queue->cancelled,
-                                         task_queue->user_data);
-
-       g_free(task_queue);
-
-       return FALSE;
-}
-
 static void prv_free_cb(gpointer data)
 {
        dleyna_task_queue_t *task_queue = data;
@@ -112,9 +100,10 @@ static void prv_free_cb(gpointer data)
        g_ptr_array_unref(task_queue->tasks);
 
        if (task_queue->task_queue_finally_cb)
-               g_idle_add(prv_finally_cb, task_queue);
-       else
-               g_free(task_queue);
+               task_queue->task_queue_finally_cb(task_queue->cancelled,
+                                                 task_queue->user_data);
+
+       g_free(task_queue);
 
        DLEYNA_LOG_DEBUG("Exit");
 }
@@ -191,9 +180,14 @@ static void prv_task_cancel_and_free_cb(gpointer data, gpointer user_data)
        task_queue->task_delete_cb(data, task_queue->user_data);
 }
 
-static void prv_cancel(const dleyna_task_queue_key_t *queue_id,
-                                 dleyna_task_queue_t *task_queue)
+static gboolean prv_cancel_only(const dleyna_task_queue_key_t *queue_id,
+                               dleyna_task_queue_t *task_queue)
 {
+       gboolean remove_queue = FALSE;
+
+       if (task_queue->cancelled)
+               goto out;
+
        task_queue->cancelled = TRUE;
 
        g_ptr_array_foreach(task_queue->tasks, prv_task_cancel_and_free_cb,
@@ -205,29 +199,50 @@ static void prv_cancel(const dleyna_task_queue_key_t *queue_id,
                task_queue->idle_id = 0;
        }
 
-       if (task_queue->current_task) {
+       if (task_queue->current_task)
                task_queue->task_cancel_cb(task_queue->current_task,
                                           task_queue->user_data);
-       } else if (task_queue->flags & DLEYNA_TASK_QUEUE_FLAG_AUTO_REMOVE) {
+       else
+               remove_queue = task_queue->flags &
+                       DLEYNA_TASK_QUEUE_FLAG_AUTO_REMOVE;
+
+out:
+
+       return remove_queue;
+}
+
+
+static void prv_cancel(const dleyna_task_queue_key_t *queue_id,
+                      dleyna_task_queue_t *task_queue)
+{
+       if (prv_cancel_only(queue_id, task_queue)) {
                DLEYNA_LOG_DEBUG("Removing queue <%s,%s>",
                                 queue_id->source, queue_id->sink);
                g_hash_table_remove(queue_id->processor->task_queues, queue_id);
        }
 }
 
-static void prv_cancel_cb(gpointer key, gpointer value, gpointer user_data)
+static gboolean prv_cancel_cb(gpointer key, gpointer value, gpointer user_data)
 {
        dleyna_task_queue_key_t *queue_id = key;
        dleyna_task_queue_t *task_queue = value;
+       gboolean retval = prv_cancel_only(queue_id, task_queue);
 
-       prv_cancel(queue_id, task_queue);
+#if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
+       if (retval)
+               DLEYNA_LOG_DEBUG("Removing queue <%s,%s>", queue_id->source,
+                                queue_id->sink);
+#endif
+
+       return retval;
 }
 
 static void prv_cancel_all_queues(dleyna_task_processor_t *processor)
 {
        DLEYNA_LOG_DEBUG("Enter");
 
-       g_hash_table_foreach(processor->task_queues, prv_cancel_cb, NULL);
+       g_hash_table_foreach_remove(processor->task_queues, prv_cancel_cb,
+                                   NULL);
 
        DLEYNA_LOG_DEBUG("Exit");
 }
@@ -238,9 +253,9 @@ void dleyna_task_processor_set_quitting(dleyna_task_processor_t *processor)
 
        processor->quitting = TRUE;
 
-       if (processor->running_tasks > 0)
-               prv_cancel_all_queues(processor);
-       else
+       prv_cancel_all_queues(processor);
+
+       if (processor->running_tasks == 0)
                g_idle_add(processor->on_quit_cb, NULL);
 
        DLEYNA_LOG_DEBUG("Exit");
@@ -374,18 +389,28 @@ static gboolean prv_process_task(gpointer user_data)
 void dleyna_task_queue_start(const dleyna_task_queue_key_t *queue_id)
 {
        dleyna_task_queue_t *queue;
+       dleyna_task_processor_t *processor = queue_id->processor;
 
        DLEYNA_LOG_DEBUG("Enter - Starting queue <%s,%s>", queue_id->source,
                         queue_id->sink);
 
-       queue = g_hash_table_lookup(queue_id->processor->task_queues, queue_id);
+       if (processor->quitting)
+               goto exit;
+
+       queue = g_hash_table_lookup(processor->task_queues, queue_id);
 
        if (queue->defer_remove)
                goto exit;
 
-       if (!queue->current_task && !queue->idle_id)
-               queue->idle_id = g_idle_add(prv_process_task,
-                                           (gpointer)queue_id);
+       if (queue->tasks->len > 0) {
+               if (!queue->current_task && !queue->idle_id)
+                       queue->idle_id = g_idle_add(prv_process_task,
+                                                   (gpointer)queue_id);
+       } else if (queue->flags & DLEYNA_TASK_QUEUE_FLAG_AUTO_REMOVE) {
+                       DLEYNA_LOG_DEBUG("Removing queue <%s,%s>",
+                                        queue_id->source, queue_id->sink);
+                       g_hash_table_remove(processor->task_queues, queue_id);
+       }
 
 exit:
        DLEYNA_LOG_DEBUG("Exit");
index 04e5a14..4f2bad1 100644 (file)
@@ -1,7 +1,7 @@
 dnl
-dnl dleyna-core
+dnl dLeyna
 dnl
-dnl Copyright (C) 2013 Intel Corporation. All rights reserved.
+dnl Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
 dnl
 dnl This program is free software; you can redistribute it and/or modify it
 dnl under the terms and conditions of the GNU Lesser General Public License,
@@ -16,6 +16,7 @@ dnl You should have received a copy of the GNU Lesser General Public License
 dnl along with this program; if not, write to the Free Software Foundation, Inc.,
 dnl 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 dnl
+dnl Ludovic Ferrandis <ludovic.ferrandis@intel.com>
 dnl Regis Merlino <regis.merlino@intel.com>
 dnl
 
index 36082cc..dce4c2b 100644 (file)
@@ -1,7 +1,7 @@
 dnl
-dnl dleyna-core
+dnl dLeyna
 dnl
-dnl Copyright (C) 2012 Intel Corporation. All rights reserved.
+dnl Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
 dnl
 dnl This program is free software; you can redistribute it and/or modify it
 dnl under the terms and conditions of the GNU Lesser General Public License,
index 7340474..dc6054a 100644 (file)
@@ -1,3 +1,31 @@
+version 0.1.0
+       - Prepare for first stable branch
+
+version 0.0.2
+       - Add R/W Mute property support, Mute states are received via
+         the LastChange event, Mute value is set with a SetMute action.
+       - Add a new player interface method OpenUriEx, which is the same as
+         the existing OpenUri one, with an additional metadata parameter to pass
+         the URI description information in DIDL-Lite XML format.
+       - Add the X_DLNA_PS transport action support to allow the
+         playspeeds provided by the renderer once we have provided it a
+         URI (SetAVTransportURI()) in addition to the renderer default
+         playspeeds retrieved via the introspection.
+       - Two new methods have been added to the Manager class, renderer_from_name
+         and renderer_from_udn.  These methods can be used to construct
+         Renderer objects from UDNs or friendly names
+       - Fix bug: dleyna-renderer can fail to discover a device if a network
+         connection is lost during device construction
+         https://github.com/01org/dleyna-renderer/issues/11
+       - Add a Rescan method to Manager interface 
+       - Add autogen.sh script to call `autoreconf -i` 
+       - Renamed a function and two signals in com.intel.dLeynaRenderer.Manager:
+         GetServers() renamed GetRenderers()
+         FoundServer renamed FoundRenderer
+         LostServer renamed LostRenderer
+       - A GetIcon() method is added to the com.intel.dLeynaRenderer.RendererDevice
+         interface
+
 version 0.0.1
        - Initial version of dleyna-renderer.
        - Enable support of deleyna-renderer as git submodules.
index ead73e3..d713e25 100644 (file)
@@ -154,9 +154,7 @@ CFLAGS = @CFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CYGPATH_W = @CYGPATH_W@
-DBUS_CFLAGS = @DBUS_CFLAGS@
-DBUS_LIBS = @DBUS_LIBS@
-DBUS_SESSION_DIR = @DBUS_SESSION_DIR@
+DBUS_SERVICE_DIR = @DBUS_SERVICE_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DLEYNA_CORE_CFLAGS = @DLEYNA_CORE_CFLAGS@
index c218641..0deb8e7 100644 (file)
@@ -11,16 +11,15 @@ TODO
 Working with the source code repository
 ---------------------------------------
 
-dleyna-server can be downloaded, compiled and installed as
+dleyna-renderer can be downloaded, compiled and installed as
 follows:
 
    Clone repository
-     # git clone git://github.com/01org/dleyna-server.git
+     # git clone git://github.com/01org/dleyna-renderer.git
      # cd dleyna-server
 
    Configure and build
-     # ./autoreconf -i
-     # ./configure
+     # ./autogen.sh
      # make
 
    Final installation
@@ -88,3 +87,11 @@ Set the IPC mechanism to be used.
 
 This option is disabled by default. To enable use --enable-lib-only.
 When enabled, only the libdleyna-renderer library is built.
+
+--with-ua-prefix
+
+This option allows a prefix to be added to the SOUP session user agent.
+For example, --with-ua-prefix=MyPrefix can be used to change a default user
+agent string from "dLeyna/0.0.1 GUPnP/0.19.4 DLNADOC/1.50" to
+"MyPrefix dLeyna/0.0.1 GUPnP/0.19.4 DLNADOC/1.50".
+
index 9a45f7f..bbd8e56 100755 (executable)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for dleyna-renderer 0.0.1.
+# Generated by GNU Autoconf 2.69 for dleyna-renderer 0.2.0.
 #
 # Report bugs to <https://github.com/01org/dleyna-renderer/issues/new>.
 #
@@ -591,8 +591,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='dleyna-renderer'
 PACKAGE_TARNAME='dleyna-renderer'
-PACKAGE_VERSION='0.0.1'
-PACKAGE_STRING='dleyna-renderer 0.0.1'
+PACKAGE_VERSION='0.2.0'
+PACKAGE_STRING='dleyna-renderer 0.2.0'
 PACKAGE_BUGREPORT='https://github.com/01org/dleyna-renderer/issues/new'
 PACKAGE_URL='https://01.org/dleyna/'
 
@@ -647,9 +647,7 @@ DLEYNA_SERVER_INTERFACE_MANAGER
 DLEYNA_SERVER_NAME
 BUILD_SERVER_FALSE
 BUILD_SERVER_TRUE
-DBUS_SESSION_DIR
-DBUS_LIBS
-DBUS_CFLAGS
+DBUS_SERVICE_DIR
 DLEYNA_CORE_LIBS
 DLEYNA_CORE_CFLAGS
 LIBOBJS
@@ -807,6 +805,7 @@ with_connector_name
 with_log_level
 with_log_type
 with_ua_prefix
+with_dbus_service_dir
 enable_lib_only
 '
       ac_precious_vars='build_alias
@@ -836,9 +835,7 @@ GUPNPDLNA_LIBS
 SOUP_CFLAGS
 SOUP_LIBS
 DLEYNA_CORE_CFLAGS
-DLEYNA_CORE_LIBS
-DBUS_CFLAGS
-DBUS_LIBS'
+DLEYNA_CORE_LIBS'
 
 
 # Initialize some variables set by options.
@@ -1379,7 +1376,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures dleyna-renderer 0.0.1 to adapt to many kinds of systems.
+\`configure' configures dleyna-renderer 0.2.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1449,7 +1446,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of dleyna-renderer 0.0.1:";;
+     short | recursive ) echo "Configuration of dleyna-renderer 0.2.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1489,6 +1486,9 @@ Optional Packages:
                           comma separated list of log level
   --with-log-type         Select log output technology 0=syslog 1=GLib
   --with-ua-prefix        Specify a user agent prefix
+  --with-dbus-service-dir=PATH
+                          choose directory for dbus service files,
+                          [default=PREFIX/share/dbus-1/services]
 
 Some influential environment variables:
   CC          C compiler command
@@ -1528,8 +1528,6 @@ Some influential environment variables:
               C compiler flags for DLEYNA_CORE, overriding pkg-config
   DLEYNA_CORE_LIBS
               linker flags for DLEYNA_CORE, overriding pkg-config
-  DBUS_CFLAGS C compiler flags for DBUS, overriding pkg-config
-  DBUS_LIBS   linker flags for DBUS, overriding pkg-config
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -1598,7 +1596,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-dleyna-renderer configure 0.0.1
+dleyna-renderer configure 0.2.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2075,7 +2073,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by dleyna-renderer $as_me 0.0.1, which was
+It was created by dleyna-renderer $as_me 0.2.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2898,7 +2896,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='dleyna-renderer'
- VERSION='0.0.1'
+ VERSION='0.2.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -12157,12 +12155,12 @@ if test -n "$GUPNP_CFLAGS"; then
     pkg_cv_GUPNP_CFLAGS="$GUPNP_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gupnp-1.0 >= 0.19.1\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gupnp-1.0 >= 0.19.1") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gupnp-1.0 >= 0.20.3\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gupnp-1.0 >= 0.20.3") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_GUPNP_CFLAGS=`$PKG_CONFIG --cflags "gupnp-1.0 >= 0.19.1" 2>/dev/null`
+  pkg_cv_GUPNP_CFLAGS=`$PKG_CONFIG --cflags "gupnp-1.0 >= 0.20.3" 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -12174,12 +12172,12 @@ if test -n "$GUPNP_LIBS"; then
     pkg_cv_GUPNP_LIBS="$GUPNP_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gupnp-1.0 >= 0.19.1\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gupnp-1.0 >= 0.19.1") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gupnp-1.0 >= 0.20.3\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gupnp-1.0 >= 0.20.3") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_GUPNP_LIBS=`$PKG_CONFIG --libs "gupnp-1.0 >= 0.19.1" 2>/dev/null`
+  pkg_cv_GUPNP_LIBS=`$PKG_CONFIG --libs "gupnp-1.0 >= 0.20.3" 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -12200,14 +12198,14 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               GUPNP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gupnp-1.0 >= 0.19.1" 2>&1`
+               GUPNP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gupnp-1.0 >= 0.20.3" 2>&1`
         else
-               GUPNP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gupnp-1.0 >= 0.19.1" 2>&1`
+               GUPNP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gupnp-1.0 >= 0.20.3" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$GUPNP_PKG_ERRORS" >&5
 
-       as_fn_error $? "Package requirements (gupnp-1.0 >= 0.19.1) were not met:
+       as_fn_error $? "Package requirements (gupnp-1.0 >= 0.20.3) were not met:
 
 $GUPNP_PKG_ERRORS
 
 
 
 
-# Check whether --enable-lib-only was given.
-if test "${enable_lib_only+set}" = set; then :
-  enableval=$enable_lib_only;
-else
-  enable_lib_only=no
-fi
-
-
-if test "x$enable_lib_only" = "xno"; then :
-
-pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DBUS" >&5
-$as_echo_n "checking for DBUS... " >&6; }
-
-if test -n "$DBUS_CFLAGS"; then
-    pkg_cv_DBUS_CFLAGS="$DBUS_CFLAGS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_DBUS_CFLAGS=`$PKG_CONFIG --cflags "dbus-1" 2>/dev/null`
-                     test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-if test -n "$DBUS_LIBS"; then
-    pkg_cv_DBUS_LIBS="$DBUS_LIBS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_DBUS_LIBS=`$PKG_CONFIG --libs "dbus-1" 2>/dev/null`
-                     test "x$?" != "x0" && pkg_failed=yes
+# Check whether --with-dbus_service_dir was given.
+if test "${with_dbus_service_dir+set}" = set; then :
+  withval=$with_dbus_service_dir; with_dbus_service_dir="$withval"
 else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
+  with_dbus_service_dir=$datadir/dbus-1/services
 fi
 
+DBUS_SERVICE_DIR=$with_dbus_service_dir
 
 
-if test $pkg_failed = yes; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
-        _pkg_short_errors_supported=yes
-else
-        _pkg_short_errors_supported=no
-fi
-        if test $_pkg_short_errors_supported = yes; then
-               DBUS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "dbus-1" 2>&1`
-        else
-               DBUS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "dbus-1" 2>&1`
-        fi
-       # Put the nasty error message in config.log where it belongs
-       echo "$DBUS_PKG_ERRORS" >&5
-
-       enable_lib_only=yes
-elif test $pkg_failed = untried; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-       enable_lib_only=yes
+# Check whether --enable-lib-only was given.
+if test "${enable_lib_only+set}" = set; then :
+  enableval=$enable_lib_only;
 else
-       DBUS_CFLAGS=$pkg_cv_DBUS_CFLAGS
-       DBUS_LIBS=$pkg_cv_DBUS_LIBS
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-       DBUS_SESSION_DIR=`$PKG_CONFIG --variable=session_bus_services_dir dbus-1`;
-
-
+  enable_lib_only=no
 fi
 
-fi
 
  if test "x$enable_lib_only" = "xno"; then
   BUILD_SERVER_TRUE=
@@ -13295,7 +13226,7 @@ $as_echo "#define DLEYNA_INTERFACE_PUSH_HOST \"com.intel.dLeynaRenderer.PushHost
 
 
 
-ac_config_files="$ac_config_files Makefile libdleyna/renderer/Makefile libdleyna/renderer/dleyna-renderer-1.0.pc libdleyna/renderer/dleyna-renderer-service.conf server/com.intel.dleyna-renderer.service server/dleyna-renderer-service-1.0.pc server/Makefile"
+ac_config_files="$ac_config_files Makefile libdleyna/renderer/Makefile libdleyna/renderer/dleyna-renderer-1.0.pc libdleyna/renderer/dleyna-renderer-service.conf server/dleyna-renderer-service-1.0.pc server/Makefile"
 
 
 cat >confcache <<\_ACEOF
@@ -13828,7 +13759,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by dleyna-renderer $as_me 0.0.1, which was
+This file was extended by dleyna-renderer $as_me 0.2.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -13895,7 +13826,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-dleyna-renderer config.status 0.0.1
+dleyna-renderer config.status 0.2.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -14308,7 +14239,6 @@ do
     "libdleyna/renderer/Makefile") CONFIG_FILES="$CONFIG_FILES libdleyna/renderer/Makefile" ;;
     "libdleyna/renderer/dleyna-renderer-1.0.pc") CONFIG_FILES="$CONFIG_FILES libdleyna/renderer/dleyna-renderer-1.0.pc" ;;
     "libdleyna/renderer/dleyna-renderer-service.conf") CONFIG_FILES="$CONFIG_FILES libdleyna/renderer/dleyna-renderer-service.conf" ;;
-    "server/com.intel.dleyna-renderer.service") CONFIG_FILES="$CONFIG_FILES server/com.intel.dleyna-renderer.service" ;;
     "server/dleyna-renderer-service-1.0.pc") CONFIG_FILES="$CONFIG_FILES server/dleyna-renderer-service-1.0.pc" ;;
     "server/Makefile") CONFIG_FILES="$CONFIG_FILES server/Makefile" ;;
 
index 0490912..9bf518a 100644 (file)
@@ -1,7 +1,7 @@
 AC_PREREQ([2.66])
 
 AC_INIT([dleyna-renderer],
-       [0.0.1],
+       [0.2.0],
        [https://github.com/01org/dleyna-renderer/issues/new],
        ,
        [https://01.org/dleyna/])
@@ -39,7 +39,7 @@ PKG_PROG_PKG_CONFIG(0.16)
 PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28])
 PKG_CHECK_MODULES([GIO], [gio-2.0 >= 2.28])
 PKG_CHECK_MODULES([GSSDP], [gssdp-1.0 >= 0.13.2])
-PKG_CHECK_MODULES([GUPNP], [gupnp-1.0 >= 0.19.1])
+PKG_CHECK_MODULES([GUPNP], [gupnp-1.0 >= 0.20.3])
 PKG_CHECK_MODULES([GUPNPAV], [gupnp-av-1.0 >= 0.11.5])
 PKG_CHECK_MODULES([GUPNPDLNA], [gupnp-dlna-2.0 >= 0.9.4])
 PKG_CHECK_MODULES([SOUP], [libsoup-2.4 >= 2.28.2])
@@ -185,6 +185,11 @@ AC_ARG_WITH(ua-prefix,
                [with_ua_prefix = "$withval"; AC_DEFINE_UNQUOTED([UA_PREFIX], "$with_ua_prefix", [User Agent prefix])],
                [])
 
+AC_ARG_WITH(dbus_service_dir,
+            AS_HELP_STRING([--with-dbus-service-dir=PATH],[choose directory for dbus service files, [default=PREFIX/share/dbus-1/services]]),
+            with_dbus_service_dir="$withval", with_dbus_service_dir=$datadir/dbus-1/services)
+DBUS_SERVICE_DIR=$with_dbus_service_dir
+AC_SUBST(DBUS_SERVICE_DIR)
 
 AC_ARG_ENABLE(lib-only,
                AS_HELP_STRING(
@@ -193,15 +198,7 @@ AC_ARG_ENABLE(lib-only,
                [],
                [enable_lib_only=no])
 
-AS_IF([test "x$[]enable_lib_only" = "xno"],
-      [PKG_CHECK_MODULES([DBUS], [dbus-1],
-                        [DBUS_SESSION_DIR=`$PKG_CONFIG --variable=session_bus_services_dir dbus-1`;
-                         AC_SUBST(DBUS_SESSION_DIR)
-                        ],
-                        [enable_lib_only=yes])
-      ])
-
-AM_CONDITIONAL([BUILD_SERVER], [test "x$[]enable_lib_only" = "xno"])
+AM_CONDITIONAL([BUILD_SERVER], [test "x$enable_lib_only" = "xno"])
 
 
 AC_DEFINE([DLEYNA_SERVER_OBJECT], "/com/intel/dLeynaRenderer", [Name of object exposed by dleyna-renderer])
@@ -237,7 +234,6 @@ AC_CONFIG_FILES([Makefile                                           \
                 libdleyna/renderer/Makefile                            \
                 libdleyna/renderer/dleyna-renderer-1.0.pc              \
                 libdleyna/renderer/dleyna-renderer-service.conf        \
-                server/com.intel.dleyna-renderer.service               \
                 server/dleyna-renderer-service-1.0.pc                  \
                 server/Makefile
                ])
index f4343d5..5c42daf 100644 (file)
@@ -1,6 +1,6 @@
 libdleyna_rendererincdir = $(includedir)/dleyna-1.0/libdleyna/renderer
 
-DLEYNA_RENDERER_VERSION = 1:0:0
+DLEYNA_RENDERER_VERSION = 1:2:0
 
 AM_CFLAGS =    $(GLIB_CFLAGS)                          \
                $(GIO_CFLAGS)                           \
index 88d9a44..793f579 100644 (file)
@@ -171,9 +171,7 @@ CFLAGS = @CFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CYGPATH_W = @CYGPATH_W@
-DBUS_CFLAGS = @DBUS_CFLAGS@
-DBUS_LIBS = @DBUS_LIBS@
-DBUS_SESSION_DIR = @DBUS_SESSION_DIR@
+DBUS_SERVICE_DIR = @DBUS_SERVICE_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DLEYNA_CORE_CFLAGS = @DLEYNA_CORE_CFLAGS@
@@ -303,7 +301,7 @@ with_connector_name = @with_connector_name@
 with_log_level = @with_log_level@
 with_log_type = @with_log_type@
 libdleyna_rendererincdir = $(includedir)/dleyna-1.0/libdleyna/renderer
-DLEYNA_RENDERER_VERSION = 1:0:0
+DLEYNA_RENDERER_VERSION = 1:2:0
 AM_CFLAGS = $(GLIB_CFLAGS)                             \
                $(GIO_CFLAGS)                           \
                $(DLEYNA_CORE_CFLAGS)                   \
index 7ff06b8..ff463db 100644 (file)
@@ -24,6 +24,7 @@
 #include <string.h>
 #include <math.h>
 
+#include <libsoup/soup.h>
 #include <libgupnp/gupnp-control-point.h>
 #include <libgupnp-av/gupnp-av.h>
 
@@ -50,6 +51,13 @@ struct prv_new_device_ct_t_ {
        const dleyna_connector_dispatch_cb_t *dispatch_table;
 };
 
+typedef struct prv_download_info_t_ prv_download_info_t;
+struct prv_download_info_t_ {
+       SoupSession *session;
+       SoupMessage *msg;
+       dlr_async_task_t *task;
+};
+
 static void prv_last_change_cb(GUPnPServiceProxy *proxy,
                               const char *variable,
                               GValue *value,
@@ -67,6 +75,18 @@ static void prv_rc_last_change_cb(GUPnPServiceProxy *proxy,
 
 static void prv_props_update(dlr_device_t *device, dlr_task_t *task);
 
+static void prv_get_rates_values(GList *allowed_tp_speeds,
+                                GVariant **mpris_tp_speeds,
+                                GPtrArray **upnp_tp_speeds,
+                                double *min_rate, double *max_rate);
+
+static void prv_add_player_speed_props(GHashTable *player_props,
+                                      double min_rate, double max_rate,
+                                      GVariant *mpris_transport_play_speeds,
+                                      GVariantBuilder *changed_props_vb);
+
+static gint prv_compare_rationals(const gchar *a, const gchar *b);
+
 static void prv_unref_variant(gpointer variant)
 {
        GVariant *var = variant;
@@ -369,7 +389,15 @@ void dlr_device_delete(void *device)
 
                if (dev->transport_play_speeds != NULL)
                        g_ptr_array_free(dev->transport_play_speeds, TRUE);
+               if (dev->dlna_transport_play_speeds != NULL)
+                       g_ptr_array_free(dev->dlna_transport_play_speeds, TRUE);
+               if (dev->mpris_transport_play_speeds)
+                       g_variant_unref(dev->mpris_transport_play_speeds);
                g_free(dev->rate);
+
+               g_free(dev->icon.mime_type);
+               g_free(dev->icon.bytes);
+
                g_free(dev);
        }
 }
@@ -631,15 +659,20 @@ static void prv_get_protocol_info_cb(GUPnPServiceProxy *proxy,
                                     gpointer user_data)
 {
        gchar *result = NULL;
+       gboolean end;
        GError *error = NULL;
        prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data;
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(proxy, action, &error, "Sink",
-                                           G_TYPE_STRING, &result, NULL)) {
+       priv_t->dev->construct_step++;
+
+       end = gupnp_service_proxy_end_action(proxy, action, &error, "Sink",
+                                            G_TYPE_STRING, &result, NULL);
+       if (!end || (result == NULL)) {
                DLEYNA_LOG_WARNING("GetProtocolInfo operation failed: %s",
-                                  error->message);
+                                  ((error != NULL) ? error->message
+                                                   : "Invalid result"));
                goto on_error;
        }
 
@@ -678,6 +711,7 @@ static GUPnPServiceProxyAction *prv_subscribe(dleyna_service_task_t *task,
 
        device = (dlr_device_t *)dleyna_service_task_get_user_data(task);
 
+       device->construct_step++;
        prv_device_subscribe_context(device);
 
        *failed = FALSE;
@@ -702,6 +736,7 @@ static GUPnPServiceProxyAction *prv_declare(dleyna_service_task_t *task,
 
        priv_t = (prv_new_device_ct_t *)dleyna_service_task_get_user_data(task);
        device = priv_t->dev;
+       device->construct_step++;
 
        table = priv_t->dispatch_table;
 
@@ -726,6 +761,43 @@ DLEYNA_LOG_DEBUG("Exit");
        return NULL;
 }
 
+void dlr_device_construct(
+                       dlr_device_t *dev,
+                       dlr_device_context_t *context,
+                       dleyna_connector_id_t connection,
+                       const dleyna_connector_dispatch_cb_t *dispatch_table,
+                       const dleyna_task_queue_key_t *queue_id)
+{
+       prv_new_device_ct_t *priv_t;
+       GUPnPServiceProxy *s_proxy;
+
+       DLEYNA_LOG_DEBUG("Current step: %d", dev->construct_step);
+
+       priv_t = g_new0(prv_new_device_ct_t, 1);
+
+       priv_t->dev = dev;
+       priv_t->dispatch_table = dispatch_table;
+
+       s_proxy = context->service_proxies.cm_proxy;
+
+       if (dev->construct_step < 1)
+               dleyna_service_task_add(queue_id, prv_get_protocol_info,
+                                       s_proxy, prv_get_protocol_info_cb,
+                                       NULL, priv_t);
+
+       /* The following task should always be completed */
+       dleyna_service_task_add(queue_id, prv_subscribe, s_proxy,
+                               NULL, NULL, dev);
+
+       if (dev->construct_step < 3)
+               dleyna_service_task_add(queue_id, prv_declare, s_proxy,
+                                       NULL, g_free, priv_t);
+
+       dleyna_task_queue_start(queue_id);
+
+       DLEYNA_LOG_DEBUG("Exit");
+}
+
 dlr_device_t *dlr_device_new(
                        dleyna_connector_id_t connection,
                        GUPnPDeviceProxy *proxy,
@@ -734,11 +806,9 @@ dlr_device_t *dlr_device_new(
                        const dleyna_connector_dispatch_cb_t *dispatch_table,
                        const dleyna_task_queue_key_t *queue_id)
 {
-       dlr_device_t *dev = g_new0(dlr_device_t, 1);
-       prv_new_device_ct_t *priv_t;
+       dlr_device_t *dev;
        gchar *new_path;
        dlr_device_context_t *context;
-       GUPnPServiceProxy *s_proxy;
 
        DLEYNA_LOG_DEBUG("New Device on %s", ip_address);
 
@@ -746,33 +816,20 @@ dlr_device_t *dlr_device_new(
        DLEYNA_LOG_DEBUG("Server Path %s", new_path);
 
        dev = g_new0(dlr_device_t, 1);
-       priv_t = g_new0(prv_new_device_ct_t, 1);
 
        dev->connection = connection;
        dev->contexts = g_ptr_array_new_with_free_func(prv_dlr_context_delete);
        dev->path = new_path;
        dev->rate = g_strdup("1");
 
-       priv_t->dev = dev;
-       priv_t->dispatch_table = dispatch_table;
-
        prv_props_init(&dev->props);
 
        prv_device_append_new_context(dev, ip_address, proxy);
 
        context = dlr_device_get_context(dev);
-       s_proxy = context->service_proxies.cm_proxy;
-
-       dleyna_service_task_add(queue_id, prv_get_protocol_info, s_proxy,
-                               prv_get_protocol_info_cb, NULL, priv_t);
-
-       dleyna_service_task_add(queue_id, prv_subscribe, s_proxy,
-                               NULL, NULL, dev);
-
-       dleyna_service_task_add(queue_id, prv_declare, s_proxy,
-                               NULL, g_free, priv_t);
 
-       dleyna_task_queue_start(queue_id);
+       dlr_device_construct(dev, context, connection,
+                            dispatch_table, queue_id);
 
        DLEYNA_LOG_DEBUG("Exit");
 
@@ -970,6 +1027,52 @@ on_error:
        return retval;
 }
 
+static gint compare_speeds(gconstpointer a, gconstpointer b)
+{
+       return prv_compare_rationals((const gchar *)a, (const gchar *)b);
+}
+
+static void prv_add_dlna_speeds(dlr_device_t *device,
+                               gchar **dlna_speeds,
+                               GVariantBuilder *changed_props_vb)
+{
+       GList *allowed_tp_speeds = NULL;
+       double min_rate = 0;
+       double max_rate = 0;
+       GVariant *mpris_tp_speeds = NULL;
+       unsigned int i = 0;
+       gchar *speed;
+
+       if (dlna_speeds == NULL)
+               goto exit;
+
+       allowed_tp_speeds = g_list_prepend(allowed_tp_speeds, g_strdup("1"));
+
+       while (dlna_speeds[i]) {
+               speed = g_strstrip(g_strdup(dlna_speeds[i]));
+               allowed_tp_speeds = g_list_prepend(allowed_tp_speeds, speed);
+               ++i;
+       }
+
+       allowed_tp_speeds = g_list_sort(allowed_tp_speeds, compare_speeds);
+
+       prv_get_rates_values(allowed_tp_speeds,
+                            &mpris_tp_speeds,
+                            &device->dlna_transport_play_speeds,
+                            &min_rate, &max_rate);
+
+       prv_add_player_speed_props(device->props.player_props,
+                                  min_rate, max_rate,
+                                  mpris_tp_speeds,
+                                  changed_props_vb);
+
+exit:
+       if (allowed_tp_speeds != NULL)
+               g_list_free_full(allowed_tp_speeds, g_free);
+
+       return;
+}
+
 static void prv_add_actions(dlr_device_t *device,
                            const gchar *actions,
                            GVariantBuilder *changed_props_vb)
@@ -984,8 +1087,15 @@ static void prv_add_actions(dlr_device_t *device,
        gboolean next = FALSE;
        gboolean previous = FALSE;
        GVariant *val;
+       GRegex *regex;
+       gchar *tmp_str;
+       gchar **speeds;
 
-       parts = g_strsplit(actions, ",", 0);
+       regex = g_regex_new("\\\\,", 0, 0, NULL);
+       tmp_str = g_regex_replace_literal(regex, actions, -1, 0, "*", 0, NULL);
+       parts = g_strsplit(tmp_str, ",", 0);
+       g_free(tmp_str);
+       g_regex_unref(regex);
 
        true_val = g_variant_ref_sink(g_variant_new_boolean(TRUE));
        false_val = g_variant_ref_sink(g_variant_new_boolean(FALSE));
@@ -993,16 +1103,23 @@ static void prv_add_actions(dlr_device_t *device,
        while (parts[i]) {
                g_strstrip(parts[i]);
 
-               if (!strcmp(parts[i], "Play"))
+               if (!strcmp(parts[i], "Play")) {
                        play = TRUE;
-               else if (!strcmp(parts[i], "Pause"))
+               } else if (!strcmp(parts[i], "Pause")) {
                        ppause = TRUE;
-               else if (!strcmp(parts[i], "Seek"))
+               } else if (!strcmp(parts[i], "Seek")) {
                        seek = TRUE;
-               else if (!strcmp(parts[i], "Next"))
+               } else if (!strcmp(parts[i], "Next")) {
                        next = TRUE;
-               else if (!strcmp(parts[i], "Previous"))
+               } else if (!strcmp(parts[i], "Previous")) {
                        previous = TRUE;
+               } else if (!strncmp(parts[i], "X_DLNA_PS=",
+                        strlen("X_DLNA_PS="))) {
+                       speeds = g_strsplit(parts[i] + strlen("X_DLNA_PS="),
+                                           "*", 0);
+                       prv_add_dlna_speeds(device, speeds, changed_props_vb);
+                       g_strfreev(speeds);
+               }
                ++i;
        }
 
@@ -1409,8 +1526,9 @@ static void prv_rc_last_change_cb(GUPnPServiceProxy *proxy,
        GVariantBuilder *changed_props_vb;
        GVariant *changed_props;
        GVariant *val;
-       guint device_volume;
+       guint dev_volume = G_MAXUINT;
        double mpris_volume;
+       guint mute = G_MAXUINT;
 
        parser = gupnp_last_change_parser_new();
 
@@ -1418,7 +1536,8 @@ static void prv_rc_last_change_cb(GUPnPServiceProxy *proxy,
                    parser, 0,
                    g_value_get_string(value),
                    NULL,
-                   "Volume", G_TYPE_UINT, &device_volume,
+                   "Volume", G_TYPE_UINT, &dev_volume,
+                   "Mute", G_TYPE_UINT, &mute,
                    NULL))
                goto on_error;
 
@@ -1430,11 +1549,21 @@ static void prv_rc_last_change_cb(GUPnPServiceProxy *proxy,
 
        changed_props_vb = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
 
-       mpris_volume = (double)device_volume / (double)device->max_volume;
-       val = g_variant_ref_sink(g_variant_new_double(mpris_volume));
-       prv_change_props(device->props.player_props,
-                        DLR_INTERFACE_PROP_VOLUME, val,
-                        changed_props_vb);
+       if (dev_volume != G_MAXUINT) {
+               mpris_volume = (double)dev_volume / (double)device->max_volume;
+               val = g_variant_ref_sink(g_variant_new_double(mpris_volume));
+               prv_change_props(device->props.player_props,
+                                DLR_INTERFACE_PROP_VOLUME, val,
+                                changed_props_vb);
+       }
+
+       if (mute != G_MAXUINT) {
+               val = g_variant_ref_sink(
+                               g_variant_new_boolean(mute ? TRUE : FALSE));
+               prv_change_props(device->props.player_props,
+                                DLR_INTERFACE_PROP_MUTE, val,
+                                changed_props_vb);
+       }
 
        changed_props = g_variant_ref_sink(
                                g_variant_builder_end(changed_props_vb));
@@ -1468,22 +1597,23 @@ static void prv_get_position_info_cb(GUPnPServiceProxy *proxy,
                                     gpointer user_data)
 {
        gchar *rel_pos = NULL;
+       const gchar *message;
+       gboolean end;
        dlr_async_task_t *cb_data = user_data;
-       GError *upnp_error = NULL;
+       GError *error = NULL;
        dlr_device_data_t *device_data = cb_data->private;
        GVariantBuilder *changed_props_vb;
        GVariant *changed_props;
 
-       if (!gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
-                                           &upnp_error,
-                                           "RelTime",
-                                           G_TYPE_STRING, &rel_pos, NULL)) {
+       end = gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
+                                            &error, "RelTime",
+                                            G_TYPE_STRING, &rel_pos, NULL);
+       if (!end || (rel_pos == NULL)) {
+               message = (error != NULL) ? error->message : "Invalid result";
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
                                             "GetPositionInfo operation failed: %s",
-                                            upnp_error->message);
-               g_error_free(upnp_error);
-
+                                            message);
                goto on_error;
        }
 
@@ -1503,6 +1633,9 @@ static void prv_get_position_info_cb(GUPnPServiceProxy *proxy,
 
 on_error:
 
+       if (error != NULL)
+               g_error_free(error);
+
        device_data->local_cb(cb_data);
 }
 
@@ -1592,7 +1725,7 @@ static gint prv_compare_rationals(const gchar *a, const gchar *b)
        return (a_numerator * b_denominator) - (b_numerator * a_denominator);
 }
 
-static void prv_get_rates_values(const GUPnPServiceStateVariableInfo *svi,
+static void prv_get_rates_values(GList *allowed_tp_speeds,
                                 GVariant **mpris_tp_speeds,
                                 GPtrArray **upnp_tp_speeds,
                                 double *min_rate, double *max_rate)
@@ -1604,12 +1737,12 @@ static void prv_get_rates_values(const GUPnPServiceStateVariableInfo *svi,
        GVariantBuilder vb;
        const double precision = 0.01;
 
-       if ((svi == NULL) || (svi->allowed_values == NULL))
+       if (allowed_tp_speeds == NULL)
                goto exit;
 
        g_variant_builder_init(&vb, G_VARIANT_TYPE("ad"));
 
-       list = svi->allowed_values;
+       list = allowed_tp_speeds;
 
        min_rate_str = list->data;
        max_rate_str = min_rate_str;
@@ -1654,6 +1787,8 @@ static void prv_get_av_service_states_values(GUPnPServiceProxy *av_proxy,
        const GUPnPServiceStateVariableInfo *svi;
        GUPnPServiceIntrospection *introspection;
        GError *error = NULL;
+       GVariant *speeds = NULL;
+       GList *allowed_values;
 
        introspection = gupnp_service_info_get_introspection(
                                                GUPNP_SERVICE_INFO(av_proxy),
@@ -1671,9 +1806,16 @@ static void prv_get_av_service_states_values(GUPnPServiceProxy *av_proxy,
                                                        introspection,
                                                        "TransportPlaySpeed");
 
-       prv_get_rates_values(svi,
-                            mpris_tp_speeds, upnp_tp_speeds,
-                            min_rate, max_rate);
+       if (svi && svi->allowed_values) {
+               allowed_values = svi->allowed_values;
+
+               allowed_values = g_list_sort(allowed_values, compare_speeds);
+
+               prv_get_rates_values(allowed_values, &speeds, upnp_tp_speeds,
+                                    min_rate, max_rate);
+
+               *mpris_tp_speeds = g_variant_ref_sink(speeds);
+       }
 
        g_object_unref(introspection);
 
@@ -1774,6 +1916,35 @@ static void prv_update_device_props(GUPnPDeviceInfo *proxy, GHashTable *props)
 
 }
 
+static void prv_add_player_speed_props(GHashTable *player_props,
+                                      double min_rate, double max_rate,
+                                      GVariant *mpris_transport_play_speeds,
+                                      GVariantBuilder *changed_props_vb)
+{
+       GVariant *val;
+
+       if (min_rate != 0) {
+               val = g_variant_ref_sink(g_variant_new_double(min_rate));
+               prv_change_props(player_props,
+                                DLR_INTERFACE_PROP_MINIMUM_RATE,
+                                val, changed_props_vb);
+       }
+
+       if (max_rate != 0) {
+               val = g_variant_ref_sink(g_variant_new_double(max_rate));
+               prv_change_props(player_props,
+                                DLR_INTERFACE_PROP_MAXIMUM_RATE,
+                                val, changed_props_vb);
+       }
+
+       if (mpris_transport_play_speeds != NULL) {
+               val = g_variant_ref_sink(mpris_transport_play_speeds);
+               prv_change_props(player_props,
+                                DLR_INTERFACE_PROP_TRANSPORT_PLAY_SPEEDS,
+                                val, changed_props_vb);
+       }
+}
+
 static void prv_props_update(dlr_device_t *device, dlr_task_t *task)
 {
        GVariant *val;
@@ -1783,9 +1954,6 @@ static void prv_props_update(dlr_device_t *device, dlr_task_t *task)
        dlr_props_t *props = &device->props;
        GVariantBuilder *changed_props_vb;
        GVariant *changed_props;
-       double min_rate = 0;
-       double max_rate = 0;
-       GVariant *mpris_transport_play_speeds = NULL;
 
        context = dlr_device_get_context(device);
 
@@ -1818,36 +1986,21 @@ static void prv_props_update(dlr_device_t *device, dlr_task_t *task)
        service_proxies = &context->service_proxies;
 
        if (service_proxies->av_proxy)
-               prv_get_av_service_states_values(service_proxies->av_proxy,
-                                                &mpris_transport_play_speeds,
-                                                &device->transport_play_speeds,
-                                                &min_rate,
-                                                &max_rate);
+               prv_get_av_service_states_values(
+                                       service_proxies->av_proxy,
+                                       &device->mpris_transport_play_speeds,
+                                       &device->transport_play_speeds,
+                                       &device->min_rate,
+                                       &device->max_rate);
 
        if (service_proxies->rc_proxy)
                prv_get_rc_service_states_values(service_proxies->rc_proxy,
                                                 &device->max_volume);
 
-       if (min_rate != 0) {
-               val = g_variant_ref_sink(g_variant_new_double(min_rate));
-               prv_change_props(device->props.player_props,
-                                DLR_INTERFACE_PROP_MINIMUM_RATE, val,
-                                changed_props_vb);
-       }
-
-       if (max_rate != 0) {
-               val = g_variant_ref_sink(g_variant_new_double(max_rate));
-               prv_change_props(device->props.player_props,
-                                DLR_INTERFACE_PROP_MAXIMUM_RATE,
-                                val, changed_props_vb);
-       }
-
-       if (mpris_transport_play_speeds != NULL) {
-               val = g_variant_ref_sink(mpris_transport_play_speeds);
-               prv_change_props(device->props.player_props,
-                                DLR_INTERFACE_PROP_TRANSPORT_PLAY_SPEEDS,
-                                val, changed_props_vb);
-       }
+       prv_add_player_speed_props(device->props.player_props,
+                                  device->min_rate, device->max_rate,
+                                  device->mpris_transport_play_speeds,
+                                  changed_props_vb);
 
        prv_add_all_actions(device, changed_props_vb);
        device->props.synced = TRUE;
@@ -1915,32 +2068,59 @@ static void prv_set_volume(dlr_async_task_t *cb_data, GVariant *params)
                                                 NULL);
 }
 
+static void prv_set_mute(dlr_async_task_t *cb_data, GVariant *params)
+{
+       gboolean mute;
+
+       mute = g_variant_get_boolean(params);
+
+       DLEYNA_LOG_INFO("Set device mute state to %s", mute ? "TRUE" : "FALSE");
+
+       cb_data->action =
+               gupnp_service_proxy_begin_action(cb_data->proxy, "SetMute",
+                                                prv_simple_call_cb, cb_data,
+                                                "InstanceID", G_TYPE_INT, 0,
+                                                "Channel",
+                                                G_TYPE_STRING, "Master",
+                                                "DesiredMute",
+                                                G_TYPE_BOOLEAN, mute,
+                                                NULL);
+}
+
 static GVariant *prv_get_rate_value_from_double(GVariant *params,
                                                gchar **upnp_rate,
                                                dlr_async_task_t *cb_data)
 {
+       dlr_device_t *dev = cb_data->device;
        GVariant *val = NULL;
        GVariant *tps;
        GVariantIter iter;
        double tps_value;
        double mpris_rate;
-       GPtrArray *upnp_tp_speeds;
+       GPtrArray *tp_speeds;
        int i;
 
-       tps = g_hash_table_lookup(cb_data->device->props.player_props,
-                                 DLR_INTERFACE_PROP_TRANSPORT_PLAY_SPEEDS);
+       if (dev->dlna_transport_play_speeds != NULL) {
+               tps = g_hash_table_lookup(dev->props.player_props,
+                               DLR_INTERFACE_PROP_TRANSPORT_PLAY_SPEEDS);
+
+               tp_speeds = dev->dlna_transport_play_speeds;
+       } else {
+               tps = dev->mpris_transport_play_speeds;
+
+               tp_speeds = dev->transport_play_speeds;
+       }
 
        if (tps == NULL) {
-               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
-                                            DLEYNA_ERROR_OPERATION_FAILED,
-                                            "TransportPlaySpeeds list is empty");
+               cb_data->error =
+                       g_error_new(DLEYNA_SERVER_ERROR,
+                                   DLEYNA_ERROR_OPERATION_FAILED,
+                                   "TransportPlaySpeeds list is empty");
                goto exit;
        }
 
        mpris_rate = g_variant_get_double(params);
 
-       upnp_tp_speeds = cb_data->device->transport_play_speeds;
-
        i = 0;
 
        g_variant_iter_init(&iter, tps);
@@ -1950,7 +2130,7 @@ static GVariant *prv_get_rate_value_from_double(GVariant *params,
                        val = g_variant_ref_sink(
                                g_variant_new_double(tps_value));
 
-                       *upnp_rate = g_ptr_array_index(upnp_tp_speeds, i);
+                       *upnp_rate = g_ptr_array_index(tp_speeds, i);
 
                        break;
                }
@@ -1971,6 +2151,8 @@ exit:
 
 static void prv_set_rate(GVariant *params, dlr_async_task_t *cb_data)
 {
+       GVariantBuilder *changed_props_vb;
+       GVariant *changed_props;
        GVariant *val;
        gchar *rate;
 
@@ -1987,14 +2169,29 @@ static void prv_set_rate(GVariant *params, dlr_async_task_t *cb_data)
        if (val == NULL)
                goto exit;
 
+       DLEYNA_LOG_INFO("Set device rate to %s", rate);
+
+       if (!strcmp(cb_data->device->rate, rate)) {
+               g_variant_unref(val);
+
+               goto exit;
+       }
+
        g_free(cb_data->device->rate);
        cb_data->device->rate = g_strdup(rate);
 
-       DLEYNA_LOG_INFO("Set device rate to %s", cb_data->device->rate);
+       changed_props_vb = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
 
        prv_change_props(cb_data->device->props.player_props,
-                        DLR_INTERFACE_PROP_RATE, val, NULL);
+                        DLR_INTERFACE_PROP_RATE, val, changed_props_vb);
 
+       changed_props = g_variant_ref_sink(
+                               g_variant_builder_end(changed_props_vb));
+       prv_emit_signal_properties_changed(cb_data->device,
+                                          DLR_INTERFACE_PLAYER,
+                                          changed_props);
+       g_variant_unref(changed_props);
+       g_variant_builder_unref(changed_props_vb);
 exit:
 
        return;
@@ -2024,7 +2221,8 @@ void dlr_device_set_prop(dlr_device_t *device, dlr_task_t *task,
                goto exit;
        }
 
-       if (g_strcmp0(set_prop->prop_name, DLR_INTERFACE_PROP_VOLUME) != 0) {
+       if ((g_strcmp0(set_prop->prop_name, DLR_INTERFACE_PROP_VOLUME) != 0) &&
+           (g_strcmp0(set_prop->prop_name, DLR_INTERFACE_PROP_MUTE) != 0)) {
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_UNKNOWN_PROPERTY,
                                             "Property %s not managed for setting",
@@ -2043,7 +2241,11 @@ void dlr_device_set_prop(dlr_device_t *device, dlr_task_t *task,
        g_object_add_weak_pointer((G_OBJECT(context->service_proxies.rc_proxy)),
                                  (gpointer *)&cb_data->proxy);
 
-       prv_set_volume(cb_data, set_prop->params);
+       if (g_strcmp0(set_prop->prop_name, DLR_INTERFACE_PROP_MUTE) == 0)
+               prv_set_mute(cb_data, set_prop->params);
+       else
+               prv_set_volume(cb_data, set_prop->params);
+
        return;
 
 exit:
@@ -2224,14 +2426,105 @@ void dlr_device_previous(dlr_device_t *device, dlr_task_t *task,
        prv_simple_command(device, task, "Previous", cb);
 }
 
+static void prv_reset_transport_speed_props(dlr_device_t *device)
+{
+       GVariantBuilder *changed_props_vb;
+       GVariant *changed_props;
+       GVariant *val;
+       double min_rate;
+       double max_rate;
+       gboolean props_changed = FALSE;
+
+       changed_props_vb = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+
+       if (device->dlna_transport_play_speeds != NULL) {
+               g_ptr_array_free(device->dlna_transport_play_speeds, TRUE);
+               device->dlna_transport_play_speeds = NULL;
+       }
+
+       val = g_hash_table_lookup(device->props.player_props,
+                                 DLR_INTERFACE_PROP_TRANSPORT_PLAY_SPEEDS);
+       if (!val ||
+           !g_variant_equal(val, device->mpris_transport_play_speeds)) {
+               min_rate = 0;
+               val = g_hash_table_lookup(device->props.player_props,
+                                         DLR_INTERFACE_PROP_MINIMUM_RATE);
+               if (!val || (g_variant_get_double(val) != device->min_rate))
+                       min_rate = device->min_rate;
+
+               max_rate = 0;
+               val = g_hash_table_lookup(device->props.player_props,
+                                         DLR_INTERFACE_PROP_MAXIMUM_RATE);
+               if (!val || (g_variant_get_double(val) != device->max_rate))
+                       max_rate = device->max_rate;
+
+               prv_add_player_speed_props(device->props.player_props,
+                                          min_rate, max_rate,
+                                          device->mpris_transport_play_speeds,
+                                          changed_props_vb);
+
+               props_changed = TRUE;
+       }
+
+       if (!device->rate || g_strcmp0(device->rate, "1") != 0) {
+               g_free(device->rate);
+               device->rate = g_strdup("1");
+
+               val = g_variant_ref_sink(g_variant_new_double(
+                                       prv_map_transport_speed(device->rate)));
+               prv_change_props(device->props.player_props,
+                                DLR_INTERFACE_PROP_RATE, val,
+                                changed_props_vb);
+
+               props_changed = TRUE;
+       }
+
+       changed_props = g_variant_ref_sink(
+                               g_variant_builder_end(changed_props_vb));
+       if (props_changed)
+               prv_emit_signal_properties_changed(device,
+                                                  DLR_INTERFACE_PLAYER,
+                                                  changed_props);
+       g_variant_unref(changed_props);
+       g_variant_builder_unref(changed_props_vb);
+}
+
+static void prv_open_uri_cb(GUPnPServiceProxy *proxy,
+                              GUPnPServiceProxyAction *action,
+                              gpointer user_data)
+{
+       dlr_async_task_t *cb_data = user_data;
+       GError *upnp_error = NULL;
+
+       if (!gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
+                                           &upnp_error, NULL)) {
+               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                            DLEYNA_ERROR_OPERATION_FAILED,
+                                            "Operation failed: %s",
+                                            upnp_error->message);
+               g_error_free(upnp_error);
+
+               goto exit;
+       }
+
+       prv_reset_transport_speed_props(cb_data->device);
+
+exit:
+
+       (void) g_idle_add(dlr_async_task_complete, cb_data);
+       g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id);
+}
+
 void dlr_device_open_uri(dlr_device_t *device, dlr_task_t *task,
                         dlr_upnp_task_complete_t cb)
 {
        dlr_device_context_t *context;
        dlr_async_task_t *cb_data = (dlr_async_task_t *)task;
        dlr_task_open_uri_t *open_uri_data = &task->ut.open_uri;
+       gchar *metadata = open_uri_data->metadata;
 
        DLEYNA_LOG_INFO("URI: %s", open_uri_data->uri);
+       DLEYNA_LOG_INFO("METADATA: %s", metadata ? metadata : "Not provided");
 
        context = dlr_device_get_context(device);
        cb_data->cb = cb;
@@ -2249,13 +2542,14 @@ void dlr_device_open_uri(dlr_device_t *device, dlr_task_t *task,
        cb_data->action =
                gupnp_service_proxy_begin_action(cb_data->proxy,
                                                 "SetAVTransportURI",
-                                                prv_simple_call_cb,
+                                                prv_open_uri_cb,
                                                 cb_data,
                                                 "InstanceID", G_TYPE_INT, 0,
                                                 "CurrentURI", G_TYPE_STRING,
                                                 open_uri_data->uri,
                                                 "CurrentURIMetaData",
-                                                G_TYPE_STRING, "",
+                                                G_TYPE_STRING,
+                                                metadata ? metadata : "",
                                                 NULL);
 }
 
@@ -2371,3 +2665,137 @@ void dlr_device_remove_uri(dlr_device_t *device, dlr_task_t *task,
 
        (void) g_idle_add(dlr_async_task_complete, cb_data);
 }
+
+static void prv_build_icon_result(dlr_device_t *device, dlr_task_t *task)
+{
+       GVariant *out_p[2];
+
+       out_p[0] = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
+                                            device->icon.bytes,
+                                            device->icon.size,
+                                            1);
+       out_p[1] = g_variant_new_string(device->icon.mime_type);
+       task->result = g_variant_ref_sink(g_variant_new_tuple(out_p, 2));
+}
+
+static void prv_get_icon_cancelled(GCancellable *cancellable,
+                                  gpointer user_data)
+{
+       prv_download_info_t *download = (prv_download_info_t *)user_data;
+
+       dlr_async_task_cancelled(cancellable, download->task);
+
+       if (download->msg) {
+               soup_session_cancel_message(download->session, download->msg,
+                                           SOUP_STATUS_CANCELLED);
+               DLEYNA_LOG_DEBUG("Cancelling device icon download");
+       }
+}
+
+static void prv_free_download_info(prv_download_info_t *download)
+{
+       if (download->msg)
+               g_object_unref(download->msg);
+       g_object_unref(download->session);
+       g_free(download);
+}
+
+static void prv_get_icon_session_cb(SoupSession *session,
+                                   SoupMessage *msg,
+                                   gpointer user_data)
+{
+       prv_download_info_t *download = (prv_download_info_t *)user_data;
+       dlr_async_task_t *cb_data = (dlr_async_task_t *)download->task;
+       dlr_device_t *device = (dlr_device_t *)cb_data->device;
+
+       if (msg->status_code == SOUP_STATUS_CANCELLED)
+               goto out;
+
+       if (SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) {
+               device->icon.size = msg->response_body->length;
+               device->icon.bytes = g_malloc(device->icon.size);
+               memcpy(device->icon.bytes, msg->response_body->data,
+                      device->icon.size);
+
+               prv_build_icon_result(device, &cb_data->task);
+       } else {
+               DLEYNA_LOG_DEBUG("Failed to GET device icon: %s",
+                                msg->reason_phrase);
+
+               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                            DLEYNA_ERROR_OPERATION_FAILED,
+                                            "Failed to GET device icon");
+       }
+
+       (void) g_idle_add(dlr_async_task_complete, cb_data);
+       g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id);
+
+out:
+
+       prv_free_download_info(download);
+}
+
+void dlr_device_get_icon(dlr_device_t *device, dlr_task_t *task,
+                        dlr_upnp_task_complete_t cb)
+{
+       GUPnPDeviceInfo *info;
+       dlr_device_context_t *context;
+       dlr_async_task_t *cb_data = (dlr_async_task_t *)task;
+       gchar *url;
+       prv_download_info_t *download;
+
+       cb_data->cb = cb;
+       cb_data->device = device;
+
+       if (device->icon.size != 0) {
+               prv_build_icon_result(device, task);
+               goto end;
+       }
+
+       context = dlr_device_get_context(device);
+       info = (GUPnPDeviceInfo *)context->device_proxy;
+
+       url = gupnp_device_info_get_icon_url(info, NULL, -1, -1, -1, FALSE,
+                                            &device->icon.mime_type, NULL,
+                                            NULL, NULL);
+       if (url == NULL) {
+               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                            DLEYNA_ERROR_NOT_SUPPORTED,
+                                            "No icon available");
+               goto end;
+       }
+
+       download = g_new0(prv_download_info_t, 1);
+       download->session = soup_session_async_new();
+       download->msg = soup_message_new(SOUP_METHOD_GET, url);
+       download->task = cb_data;
+
+       if (!download->msg) {
+               DLEYNA_LOG_WARNING("Invalid URL %s", url);
+
+               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                            DLEYNA_ERROR_BAD_RESULT,
+                                            "Invalid URL %s", url);
+               prv_free_download_info(download);
+               g_free(url);
+
+               goto end;
+       }
+
+       cb_data->cancel_id =
+               g_cancellable_connect(cb_data->cancellable,
+                                     G_CALLBACK(prv_get_icon_cancelled),
+                                     download, NULL);
+
+       g_object_ref(download->msg);
+       soup_session_queue_message(download->session, download->msg,
+                                  prv_get_icon_session_cb, download);
+
+       g_free(url);
+
+       return;
+
+end:
+
+       (void) g_idle_add(dlr_async_task_complete, cb_data);
+}
index a0c1bf0..2fef1fb 100644 (file)
@@ -64,6 +64,13 @@ struct dlr_props_t_ {
        gboolean synced;
 };
 
+typedef struct dlr_device_icon_t_ dlr_device_icon_t;
+struct dlr_device_icon_t_ {
+       gchar *mime_type;
+       guchar *bytes;
+       gsize size;
+};
+
 struct dlr_device_t_ {
        dleyna_connector_id_t connection;
        guint ids[DLR_INTERFACE_INFO_MAX];
@@ -73,9 +80,22 @@ struct dlr_device_t_ {
        guint timeout_id;
        guint max_volume;
        GPtrArray *transport_play_speeds;
+       GPtrArray *dlna_transport_play_speeds;
+       GVariant *mpris_transport_play_speeds;
        gchar *rate;
+       double min_rate;
+       double max_rate;
+       guint construct_step;
+       dlr_device_icon_t icon;
 };
 
+void dlr_device_construct(
+                       dlr_device_t *dev,
+                       dlr_device_context_t *context,
+                       dleyna_connector_id_t connection,
+                       const dleyna_connector_dispatch_cb_t *dispatch_table,
+                       const dleyna_task_queue_key_t *queue_id);
+
 dlr_device_t *dlr_device_new(
                        dleyna_connector_id_t connection,
                        GUPnPDeviceProxy *proxy,
@@ -146,4 +166,7 @@ void dlr_device_remove_uri(dlr_device_t *device, dlr_task_t *task,
                           dlr_host_service_t *host_service,
                           dlr_upnp_task_complete_t cb);
 
+void dlr_device_get_icon(dlr_device_t *device, dlr_task_t *task,
+                        dlr_upnp_task_complete_t cb);
+
 #endif /* DLR_DEVICE_H__ */
index ebaba65..ae38bc5 100644 (file)
@@ -34,4 +34,4 @@ log-type=0
 # IMPORTANT: This log level is a subset of the log level defined at compile time
 # You can't enable levels disabled at compile time
 # level=8 means all level flags defined at compile time.
-log-level=8
+log-level=7
index ae2f313..d9164ae 100644 (file)
@@ -53,6 +53,7 @@
 #define DLR_INTERFACE_PROP_VOLUME "Volume"
 #define DLR_INTERFACE_PROP_CURRENT_TRACK "CurrentTrack"
 #define DLR_INTERFACE_PROP_NUMBER_OF_TRACKS "NumberOfTracks"
+#define DLR_INTERFACE_PROP_MUTE "Mute"
 
 #define DLR_INTERFACE_PROP_DEVICE_TYPE "DeviceType"
 #define DLR_INTERFACE_PROP_UDN "UDN"
index 75bb358..f8fa47e 100644 (file)
 #endif
 
 #define DLR_INTERFACE_GET_VERSION "GetVersion"
-#define DLR_INTERFACE_GET_SERVERS "GetServers"
+#define DLR_INTERFACE_GET_RENDERERS "GetRenderers"
+#define DLR_INTERFACE_RESCAN "Rescan"
 #define DLR_INTERFACE_RELEASE "Release"
 
-#define DLR_INTERFACE_FOUND_SERVER "FoundServer"
-#define DLR_INTERFACE_LOST_SERVER "LostServer"
+#define DLR_INTERFACE_FOUND_RENDERER "FoundRenderer"
+#define DLR_INTERFACE_LOST_RENDERER "LostRenderer"
 
 #define DLR_INTERFACE_HOST_FILE "HostFile"
 #define DLR_INTERFACE_REMOVE_FILE "RemoveFile"
 
 #define DLR_INTERFACE_VERSION "Version"
-#define DLR_INTERFACE_SERVERS "Servers"
+#define DLR_INTERFACE_RENDERERS "Renderers"
 
 #define DLR_INTERFACE_PATH "Path"
 #define DLR_INTERFACE_URI "Uri"
 #define DLR_INTERFACE_ID "Id"
+#define DLR_INTERFACE_METADATA "Metadata"
 
 #define DLR_INTERFACE_CHANGED_PROPERTIES "changed_properties"
 #define DLR_INTERFACE_INVALIDATED_PROPERTIES "invalidated_properties"
 #define DLR_INTERFACE_PAUSE "Pause"
 #define DLR_INTERFACE_STOP "Stop"
 #define DLR_INTERFACE_OPEN_URI "OpenUri"
+#define DLR_INTERFACE_OPEN_URI_EX "OpenUriEx"
 #define DLR_INTERFACE_SEEK "Seek"
 #define DLR_INTERFACE_SET_POSITION "SetPosition"
 #define DLR_INTERFACE_GOTO_TRACK "GotoTrack"
 
 #define DLR_INTERFACE_CANCEL "Cancel"
+#define DLR_INTERFACE_GET_ICON "GetIcon"
+#define DLR_INTERFACE_RESOLUTION "Resolution"
+#define DLR_INTERFACE_ICON_BYTES "Bytes"
+#define DLR_INTERFACE_MIME_TYPE "MimeType"
+#define DLR_INTERFACE_REQ_MIME_TYPE "RequestedMimeType"
 
 typedef struct dlr_context_t_ dlr_context_t;
 struct dlr_context_t_ {
@@ -117,14 +125,16 @@ static const gchar g_root_introspection[] =
        "    </method>"
        "    <method name='"DLR_INTERFACE_RELEASE"'>"
        "    </method>"
-       "    <method name='"DLR_INTERFACE_GET_SERVERS"'>"
-       "      <arg type='as' name='"DLR_INTERFACE_SERVERS"'"
+       "    <method name='"DLR_INTERFACE_GET_RENDERERS"'>"
+       "      <arg type='as' name='"DLR_INTERFACE_RENDERERS"'"
        "           direction='out'/>"
        "    </method>"
-       "    <signal name='"DLR_INTERFACE_FOUND_SERVER"'>"
+       "    <method name='"DLR_INTERFACE_RESCAN"'>"
+       "    </method>"
+       "    <signal name='"DLR_INTERFACE_FOUND_RENDERER"'>"
        "      <arg type='s' name='"DLR_INTERFACE_PATH"'/>"
        "    </signal>"
-       "    <signal name='"DLR_INTERFACE_LOST_SERVER"'>"
+       "    <signal name='"DLR_INTERFACE_LOST_RENDERER"'>"
        "      <arg type='s' name='"DLR_INTERFACE_PATH"'/>"
        "    </signal>"
        "  </interface>"
@@ -198,6 +208,12 @@ static const gchar g_server_introspection[] =
        "      <arg type='s' name='"DLR_INTERFACE_URI"'"
        "           direction='in'/>"
        "    </method>"
+       "    <method name='"DLR_INTERFACE_OPEN_URI_EX"'>"
+       "      <arg type='s' name='"DLR_INTERFACE_URI"'"
+       "           direction='in'/>"
+       "      <arg type='s' name='"DLR_INTERFACE_METADATA"'"
+       "           direction='in'/>"
+       "    </method>"
        "    <method name='"DLR_INTERFACE_SEEK"'>"
        "      <arg type='x' name='"DLR_INTERFACE_OFFSET"'"
        "           direction='in'/>"
@@ -245,6 +261,8 @@ static const gchar g_server_introspection[] =
        "       access='read'/>"
        "    <property type='u' name='"DLR_INTERFACE_PROP_NUMBER_OF_TRACKS"'"
        "       access='read'/>"
+       "    <property type='b' name='"DLR_INTERFACE_PROP_MUTE"'"
+       "       access='readwrite'/>"
        "  </interface>"
        "  <interface name='"DLEYNA_INTERFACE_PUSH_HOST"'>"
        "    <method name='"DLR_INTERFACE_HOST_FILE"'>"
@@ -261,6 +279,16 @@ static const gchar g_server_introspection[] =
        "  <interface name='"DLEYNA_SERVER_INTERFACE_RENDERER_DEVICE"'>"
        "    <method name='"DLR_INTERFACE_CANCEL"'>"
        "    </method>"
+       "    <method name='"DLR_INTERFACE_GET_ICON"'>"
+       "      <arg type='s' name='"DLR_INTERFACE_REQ_MIME_TYPE"'"
+       "           direction='in'/>"
+       "      <arg type='s' name='"DLR_INTERFACE_RESOLUTION"'"
+       "           direction='in'/>"
+       "      <arg type='ay' name='"DLR_INTERFACE_ICON_BYTES"'"
+       "           direction='out'/>"
+       "      <arg type='s' name='"DLR_INTERFACE_MIME_TYPE"'"
+       "           direction='out'/>"
+       "    </method>"
        "    <property type='s' name='"DLR_INTERFACE_PROP_DEVICE_TYPE"'"
        "       access='read'/>"
        "    <property type='s' name='"DLR_INTERFACE_PROP_UDN"'"
@@ -382,6 +410,11 @@ static void prv_process_sync_task(dlr_task_t *task)
                dlr_task_complete(task);
                dleyna_task_queue_task_completed(task->atom.queue_id);
                break;
+       case DLR_TASK_RESCAN:
+               dlr_upnp_rescan(g_context.upnp);
+               dlr_task_complete(task);
+               dleyna_task_queue_task_completed(task->atom.queue_id);
+               break;
        case DLR_TASK_RAISE:
        case DLR_TASK_QUIT:
                error = g_error_new(DLEYNA_SERVER_ERROR,
@@ -481,6 +514,10 @@ static void prv_process_async_task(dlr_task_t *task)
                dlr_upnp_remove_uri(g_context.upnp, task,
                                    prv_async_task_complete);
                break;
+       case DLR_TASK_GET_ICON:
+               dlr_upnp_get_icon(g_context.upnp, task,
+                                 prv_async_task_complete);
+               break;
        default:
                break;
        }
@@ -543,10 +580,10 @@ static void prv_control_point_initialize(const dleyna_connector_t *connector,
 
 static void prv_control_point_stop_service(void)
 {
-       dlr_upnp_unsubscribe(g_context.upnp);
-
-       if (g_context.upnp)
+       if (g_context.upnp) {
+               dlr_upnp_unsubscribe(g_context.upnp);
                dlr_upnp_delete(g_context.upnp);
+       }
 
        if (g_context.connection) {
                if (g_context.dlr_id)
@@ -600,8 +637,10 @@ static void prv_dlr_method_call(dleyna_connector_id_t conn,
        } else {
                if (!strcmp(method, DLR_INTERFACE_GET_VERSION))
                        task = dlr_task_get_version_new(invocation);
-               else if (!strcmp(method, DLR_INTERFACE_GET_SERVERS))
+               else if (!strcmp(method, DLR_INTERFACE_GET_RENDERERS))
                        task = dlr_task_get_servers_new(invocation);
+               else if (!strcmp(method, DLR_INTERFACE_RESCAN))
+                       task = dlr_task_rescan_new(invocation);
                else
                        goto finished;
 
@@ -741,6 +780,8 @@ static void prv_dlr_player_method_call(dleyna_connector_id_t conn,
                task = dlr_task_previous_new(invocation, object);
        else if (!strcmp(method, DLR_INTERFACE_OPEN_URI))
                task = dlr_task_open_uri_new(invocation, object, parameters);
+       else if (!strcmp(method, DLR_INTERFACE_OPEN_URI_EX))
+               task = dlr_task_open_uri_ex_new(invocation, object, parameters);
        else if (!strcmp(method, DLR_INTERFACE_SEEK))
                task = dlr_task_seek_new(invocation, object, parameters);
        else if (!strcmp(method, DLR_INTERFACE_SET_POSITION))
@@ -803,6 +844,7 @@ static void prv_renderer_device_method_call(
                                        GVariant *parameters,
                                        dleyna_connector_msg_id_t invocation)
 {
+       dlr_task_t *task;
        const gchar *device_id = NULL;
        GError *error = NULL;
        const dleyna_task_queue_key_t *queue_id;
@@ -823,11 +865,15 @@ static void prv_renderer_device_method_call(
                        dleyna_task_processor_cancel_queue(queue_id);
 
                g_context.connector->return_response(invocation, NULL);
+       } else if (!strcmp(method, DLR_INTERFACE_GET_ICON)) {
+               task = dlr_task_get_icon_new(invocation, object, parameters);
+
+               prv_add_task(task, sender, device_id);
        }
 
 finished:
 
-               return;
+       return;
 }
 
 static void prv_found_media_server(const gchar *path)
@@ -837,7 +883,7 @@ static void prv_found_media_server(const gchar *path)
        (void) g_context.connector->notify(g_context.connection,
                                           DLEYNA_SERVER_OBJECT,
                                           DLEYNA_SERVER_INTERFACE_MANAGER,
-                                          DLR_INTERFACE_FOUND_SERVER,
+                                          DLR_INTERFACE_FOUND_RENDERER,
                                           g_variant_new("(s)", path),
                                           NULL);
 }
@@ -849,7 +895,7 @@ static void prv_lost_media_server(const gchar *path)
        (void) g_context.connector->notify(g_context.connection,
                                           DLEYNA_SERVER_OBJECT,
                                           DLEYNA_SERVER_INTERFACE_MANAGER,
-                                          DLR_INTERFACE_LOST_SERVER,
+                                          DLR_INTERFACE_LOST_RENDERER,
                                           g_variant_new("(s)", path),
                                           NULL);
 
index f461824..6e5c8cd 100644 (file)
 #include "async.h"
 #include "server.h"
 
+dlr_task_t *dlr_task_rescan_new(dleyna_connector_msg_id_t invocation)
+{
+       dlr_task_t *task = g_new0(dlr_task_t, 1);
+
+       task->type = DLR_TASK_RESCAN;
+       task->invocation = invocation;
+       task->synchronous = TRUE;
+
+       return task;
+}
+
 dlr_task_t *dlr_task_get_version_new(dleyna_connector_msg_id_t invocation)
 {
        dlr_task_t *task = g_new0(dlr_task_t, 1);
@@ -93,12 +104,17 @@ static void prv_dlr_task_delete(dlr_task_t *task)
                break;
        case DLR_TASK_OPEN_URI:
                g_free(task->ut.open_uri.uri);
+               g_free(task->ut.open_uri.metadata);
                break;
        case DLR_TASK_HOST_URI:
        case DLR_TASK_REMOVE_URI:
                g_free(task->ut.host_uri.uri);
                g_free(task->ut.host_uri.client);
                break;
+       case DLR_TASK_GET_ICON:
+               g_free(task->ut.get_icon.mime_type);
+               g_free(task->ut.get_icon.resolution);
+               break;
        default:
                break;
        }
@@ -255,6 +271,24 @@ dlr_task_t *dlr_task_open_uri_new(dleyna_connector_msg_id_t invocation,
        g_variant_get(parameters, "(s)", &task->ut.open_uri.uri);
        g_strstrip(task->ut.open_uri.uri);
 
+       task->ut.open_uri.metadata = NULL;
+
+       return task;
+}
+
+dlr_task_t *dlr_task_open_uri_ex_new(dleyna_connector_msg_id_t invocation,
+                                    const gchar *path, GVariant *parameters)
+{
+       dlr_task_t *task;
+
+       task = prv_device_task_new(DLR_TASK_OPEN_URI, invocation, path,
+                                  NULL);
+
+       g_variant_get(parameters, "(ss)",
+                     &task->ut.open_uri.uri, &task->ut.open_uri.metadata);
+       g_strstrip(task->ut.open_uri.uri);
+       g_strstrip(task->ut.open_uri.metadata);
+
        return task;
 }
 
@@ -291,21 +325,42 @@ dlr_task_t *dlr_task_remove_uri_new(dleyna_connector_msg_id_t invocation,
        return task;
 }
 
+dlr_task_t *dlr_task_get_icon_new(dleyna_connector_msg_id_t invocation,
+                                 const gchar *path, GVariant *parameters)
+{
+       dlr_task_t *task;
+
+       task = prv_device_task_new(DLR_TASK_GET_ICON, invocation, path,
+                                  "(@ays)");
+       task->multiple_retvals = TRUE;
+
+       g_variant_get(parameters, "(ss)", &task->ut.get_icon.mime_type,
+                     &task->ut.get_icon.resolution);
+
+       return task;
+}
+
 void dlr_task_complete(dlr_task_t *task)
 {
+       GVariant *result;
+
        if (!task)
                goto finished;
 
        if (task->invocation) {
-               if (task->result_format && task->result)
+               if (task->result_format && task->result) {
+                       if (task->multiple_retvals)
+                               result = task->result;
+                       else
+                               result = g_variant_new(task->result_format,
+                                                      task->result);
                        dlr_renderer_get_connector()->return_response(
-                               task->invocation,
-                               g_variant_new(task->result_format,
-                                             task->result));
-               else
+                                               task->invocation, result);
+               } else {
                        dlr_renderer_get_connector()->return_response(
                                                        task->invocation,
                                                        NULL);
+               }
 
                task->invocation = NULL;
        }
index 4fd11b9..3aa8c8b 100644 (file)
@@ -32,6 +32,7 @@
 enum dlr_task_type_t_ {
        DLR_TASK_GET_VERSION,
        DLR_TASK_GET_SERVERS,
+       DLR_TASK_RESCAN,
        DLR_TASK_RAISE,
        DLR_TASK_QUIT,
        DLR_TASK_SET_PROP,
@@ -48,7 +49,8 @@ enum dlr_task_type_t_ {
        DLR_TASK_SET_POSITION,
        DLR_TASK_GOTO_TRACK,
        DLR_TASK_HOST_URI,
-       DLR_TASK_REMOVE_URI
+       DLR_TASK_REMOVE_URI,
+       DLR_TASK_GET_ICON
 };
 typedef enum dlr_task_type_t_ dlr_task_type_t;
 
@@ -75,6 +77,7 @@ struct dlr_task_set_prop_t_ {
 typedef struct dlr_task_open_uri_t_ dlr_task_open_uri_t;
 struct dlr_task_open_uri_t_ {
        gchar *uri;
+       gchar *metadata;
 };
 
 typedef struct dlr_task_seek_t_ dlr_task_seek_t;
@@ -89,6 +92,12 @@ struct dlr_task_host_uri_t_ {
        gchar *client;
 };
 
+typedef struct dlr_task_get_icon_t_ dlr_task_get_icon_t;
+struct dlr_task_get_icon_t_ {
+       gchar *mime_type;
+       gchar *resolution;
+};
+
 typedef struct dlr_task_t_ dlr_task_t;
 struct dlr_task_t_ {
        dleyna_task_atom_t atom; /* pseudo inheritance - MUST be first field */
@@ -98,6 +107,7 @@ struct dlr_task_t_ {
        GVariant *result;
        dleyna_connector_msg_id_t invocation;
        gboolean synchronous;
+       gboolean multiple_retvals;
        union {
                dlr_task_get_props_t get_props;
                dlr_task_get_prop_t get_prop;
@@ -105,9 +115,12 @@ struct dlr_task_t_ {
                dlr_task_open_uri_t open_uri;
                dlr_task_host_uri_t host_uri;
                dlr_task_seek_t seek;
+               dlr_task_get_icon_t get_icon;
        } ut;
 };
 
+dlr_task_t *dlr_task_rescan_new(dleyna_connector_msg_id_t invocation);
+
 dlr_task_t *dlr_task_get_version_new(dleyna_connector_msg_id_t invocation);
 
 dlr_task_t *dlr_task_get_servers_new(dleyna_connector_msg_id_t invocation);
@@ -155,6 +168,9 @@ dlr_task_t *dlr_task_goto_track_new(dleyna_connector_msg_id_t invocation,
 dlr_task_t *dlr_task_open_uri_new(dleyna_connector_msg_id_t invocation,
                                  const gchar *path, GVariant *parameters);
 
+dlr_task_t *dlr_task_open_uri_ex_new(dleyna_connector_msg_id_t invocation,
+                                    const gchar *path, GVariant *parameters);
+
 dlr_task_t *dlr_task_host_uri_new(dleyna_connector_msg_id_t invocation,
                                  const gchar *path, const gchar *sender,
                                  GVariant *parameters);
@@ -163,6 +179,9 @@ dlr_task_t *dlr_task_remove_uri_new(dleyna_connector_msg_id_t invocation,
                                    const gchar *path, const gchar *sender,
                                    GVariant *parameters);
 
+dlr_task_t *dlr_task_get_icon_new(dleyna_connector_msg_id_t invocation,
+                                 const gchar *path, GVariant *parameters);
+
 void dlr_task_complete(dlr_task_t *task);
 
 void dlr_task_fail(dlr_task_t *task, GError *error);
index e6d905f..ee45166 100644 (file)
@@ -54,6 +54,7 @@ typedef struct prv_device_new_ct_t_ prv_device_new_ct_t;
 struct prv_device_new_ct_t_ {
        dlr_upnp_t *upnp;
        char *udn;
+       gchar *ip_address;
        dlr_device_t *device;
        const dleyna_task_queue_key_t *queue_id;
 };
@@ -62,6 +63,7 @@ static void prv_device_new_free(prv_device_new_ct_t *priv_t)
 {
        if (priv_t) {
                g_free(priv_t->udn);
+               g_free(priv_t->ip_address);
                g_free(priv_t);
        }
 }
@@ -95,6 +97,54 @@ on_clear:
        DLEYNA_LOG_DEBUG_NL();
 }
 
+static void prv_device_context_switch_end(gboolean cancelled, gpointer data)
+{
+       prv_device_new_ct_t *priv_t = (prv_device_new_ct_t *)data;
+
+       DLEYNA_LOG_DEBUG("Enter");
+
+       prv_device_new_free(priv_t);
+
+       DLEYNA_LOG_DEBUG("Exit");
+}
+
+static const dleyna_task_queue_key_t *prv_create_device_queue(
+                                               prv_device_new_ct_t **priv_t)
+{
+       const dleyna_task_queue_key_t *queue_id;
+
+       *priv_t = g_new0(prv_device_new_ct_t, 1);
+
+       queue_id = dleyna_task_processor_add_queue(
+                       dlr_renderer_service_get_task_processor(),
+                       dleyna_service_task_create_source(),
+                       DLR_RENDERER_SINK,
+                       DLEYNA_TASK_QUEUE_FLAG_AUTO_REMOVE,
+                       dleyna_service_task_process_cb,
+                       dleyna_service_task_cancel_cb,
+                       dleyna_service_task_delete_cb);
+       dleyna_task_queue_set_finally(queue_id, prv_device_chain_end);
+       dleyna_task_queue_set_user_data(queue_id, *priv_t);
+
+
+       return queue_id;
+}
+
+static void prv_update_device_context(prv_device_new_ct_t *priv_t,
+                                     dlr_upnp_t *upnp, const char *udn,
+                                     dlr_device_t *device,
+                                     const gchar *ip_address,
+                                     const dleyna_task_queue_key_t *queue_id)
+{
+       priv_t->upnp = upnp;
+       priv_t->udn = g_strdup(udn);
+       priv_t->ip_address = g_strdup(ip_address);
+       priv_t->queue_id = queue_id;
+       priv_t->device = device;
+
+       g_hash_table_insert(upnp->server_uc_map, g_strdup(udn), priv_t);
+}
+
 static void prv_server_available_cb(GUPnPControlPoint *cp,
                                    GUPnPDeviceProxy *proxy,
                                    gpointer user_data)
@@ -133,32 +183,17 @@ static void prv_server_available_cb(GUPnPControlPoint *cp,
        if (!device) {
                DLEYNA_LOG_DEBUG("Device not found. Adding");
 
-               priv_t = g_new0(prv_device_new_ct_t, 1);
-
-               queue_id = dleyna_task_processor_add_queue(
-                               dlr_renderer_service_get_task_processor(),
-                               dleyna_service_task_create_source(),
-                               DLR_RENDERER_SINK,
-                               DLEYNA_TASK_QUEUE_FLAG_AUTO_REMOVE,
-                               dleyna_service_task_process_cb,
-                               dleyna_service_task_cancel_cb,
-                               dleyna_service_task_delete_cb);
-               dleyna_task_queue_set_finally(queue_id, prv_device_chain_end);
-               dleyna_task_queue_set_user_data(queue_id, priv_t);
+               queue_id = prv_create_device_queue(&priv_t);
 
                device = dlr_device_new(upnp->connection, proxy, ip_address,
                                        upnp->counter,
                                        upnp->interface_info,
                                        queue_id);
 
-               upnp->counter++;
-
-               priv_t->upnp = upnp;
-               priv_t->udn = g_strdup(udn);
-               priv_t->queue_id = queue_id;
-               priv_t->device = device;
+               prv_update_device_context(priv_t, upnp, udn, device, ip_address,
+                                         queue_id);
 
-               g_hash_table_insert(upnp->server_uc_map, g_strdup(udn), priv_t);
+               upnp->counter++;
        } else {
                DLEYNA_LOG_DEBUG("Device Found");
 
@@ -206,6 +241,8 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
        gboolean subscribed;
        gboolean under_construction = FALSE;
        prv_device_new_ct_t *priv_t;
+       gboolean construction_ctx = FALSE;
+       const dleyna_task_queue_key_t *queue_id;
 
        DLEYNA_LOG_DEBUG("Enter");
 
@@ -245,6 +282,10 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
        if (i < device->contexts->len) {
                subscribed = (context->subscribed_av || context->subscribed_cm);
 
+               if (under_construction)
+                       construction_ctx = !strcmp(context->ip_address,
+                                                  priv_t->ip_address);
+
                (void) g_ptr_array_remove_index(device->contexts, i);
 
                if (device->contexts->len == 0) {
@@ -261,6 +302,28 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
                                dleyna_task_processor_cancel_queue(
                                                        priv_t->queue_id);
                        }
+               } else if (under_construction && construction_ctx) {
+                       DLEYNA_LOG_WARNING(
+                               "Device under construction. Switching context");
+
+                       /* Cancel previous contruction task chain */
+                       g_hash_table_remove(priv_t->upnp->server_uc_map,
+                                           priv_t->udn);
+                       dleyna_task_queue_set_finally(
+                                               priv_t->queue_id,
+                                               prv_device_context_switch_end);
+                       dleyna_task_processor_cancel_queue(priv_t->queue_id);
+
+                       /* Create a new construction task chain */
+                       context = dlr_device_get_context(device);
+                       queue_id = prv_create_device_queue(&priv_t);
+                       prv_update_device_context(priv_t, upnp, udn, device,
+                                                 context->ip_address,
+                                                 queue_id);
+
+                       /* Start tasks from current construction step */
+                       dlr_device_construct(device, context, upnp->connection,
+                                            upnp->interface_info, queue_id);
                } else if (subscribed && !device->timeout_id) {
                        DLEYNA_LOG_DEBUG("Subscribe on new context");
 
@@ -732,6 +795,32 @@ void dlr_upnp_remove_uri(dlr_upnp_t *upnp, dlr_task_t *task,
        DLEYNA_LOG_DEBUG("Exit");
 }
 
+void dlr_upnp_get_icon(dlr_upnp_t *upnp, dlr_task_t *task,
+                      dlr_upnp_task_complete_t cb)
+{
+       dlr_device_t *device;
+       dlr_async_task_t *cb_data = (dlr_async_task_t *)task;
+
+       DLEYNA_LOG_DEBUG("Enter");
+
+       device = dlr_device_from_path(task->path, upnp->server_udn_map);
+
+       if (!device) {
+               DLEYNA_LOG_WARNING("Cannot locate device");
+
+               cb_data->cb = cb;
+               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                            DLEYNA_ERROR_OBJECT_NOT_FOUND,
+                                            "Cannot locate a device for the specified object");
+
+               (void) g_idle_add(dlr_async_task_complete, cb_data);
+       } else {
+               dlr_device_get_icon(device, task, cb);
+       }
+
+       DLEYNA_LOG_DEBUG("Exit");
+}
+
 void dlr_upnp_lost_client(dlr_upnp_t *upnp, const gchar *client_name)
 {
        dlr_host_service_lost_client(upnp->host_service, client_name);
@@ -750,3 +839,10 @@ void dlr_upnp_unsubscribe(dlr_upnp_t *upnp)
 
        DLEYNA_LOG_DEBUG("Exit");
 }
+
+void dlr_upnp_rescan(dlr_upnp_t *upnp)
+{
+       DLEYNA_LOG_DEBUG("re-scanning control points");
+
+       gupnp_context_manager_rescan_control_points(upnp->context_manager);
+}
index 9e19163..db98bd3 100644 (file)
@@ -96,8 +96,13 @@ void dlr_upnp_host_uri(dlr_upnp_t *upnp, dlr_task_t *task,
 void dlr_upnp_remove_uri(dlr_upnp_t *upnp, dlr_task_t *task,
                         dlr_upnp_task_complete_t cb);
 
+void dlr_upnp_get_icon(dlr_upnp_t *upnp, dlr_task_t *task,
+                      dlr_upnp_task_complete_t cb);
+
 void dlr_upnp_lost_client(dlr_upnp_t *upnp, const gchar *client_name);
 
 void dlr_upnp_unsubscribe(dlr_upnp_t *upnp);
 
+void dlr_upnp_rescan(dlr_upnp_t *upnp);
+
 #endif /* DLR_UPNP_H__ */
index e539ade..b1b7f1a 100644 (file)
@@ -1,7 +1,7 @@
 dnl
-dnl dleyna-server
+dnl dLeyna
 dnl
-dnl Copyright (C) 2013 Intel Corporation. All rights reserved.
+dnl Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
 dnl
 dnl This program is free software; you can redistribute it and/or modify it
 dnl under the terms and conditions of the GNU Lesser General Public License,
@@ -16,6 +16,7 @@ dnl You should have received a copy of the GNU Lesser General Public License
 dnl along with this program; if not, write to the Free Software Foundation, Inc.,
 dnl 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 dnl
+dnl Ludovic Ferrandis <ludovic.ferrandis@intel.com>
 dnl Regis Merlino <regis.merlino@intel.com>
 dnl
 
index df7ea7b..f1efefd 100644 (file)
@@ -14,14 +14,19 @@ dleyna_renderer_service_LDADD =     $(GLIB_LIBS)                                                    \
                                $(GIO_LIBS)                                                     \
                                $(DLEYNA_CORE_LIBS)                                             \
                                $(top_builddir)/libdleyna/renderer/libdleyna-renderer-1.0.la
-                       
-                       
-dbussessiondir = @DBUS_SESSION_DIR@
-dbussession_DATA = com.intel.dleyna-renderer.service
+
+dbusservicedir = $(DBUS_SERVICE_DIR)
+dbusservice_in_files = com.intel.dleyna-renderer.service.in
+dbusservice_DATA = com.intel.dleyna-renderer.service
+
+# Replace the 'libexecdir' marker with its fully expanded value
+%.service: %.service.in Makefile
+       $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = dleyna-renderer-service-1.0.pc
 
-CLEANFILES = $(dbussession_DATA) $(pkgconfig_DATA)
-DISTCLEANFILES = $(dbussession_DATA) $(pkgconfig_DATA)
-                       
+EXTRA_DIST = $(dbusservice_in_files)
+
+CLEANFILES = $(dbusservice_DATA)
+DISTCLEANFILES = $(pkgconfig_DATA)
index ce7c97e..7017e34 100644 (file)
@@ -55,7 +55,6 @@ host_triplet = @host@
 libexec_PROGRAMS = dleyna-renderer-service$(EXEEXT)
 subdir = server
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
-       $(srcdir)/com.intel.dleyna-renderer.service.in \
        $(srcdir)/dleyna-renderer-service-1.0.pc.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/compiler-flags.m4 \
@@ -67,11 +66,10 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
 CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES = com.intel.dleyna-renderer.service \
-       dleyna-renderer-service-1.0.pc
+CONFIG_CLEAN_FILES = dleyna-renderer-service-1.0.pc
 CONFIG_CLEAN_VPATH_FILES =
 am__installdirs = "$(DESTDIR)$(libexecdir)" \
-       "$(DESTDIR)$(dbussessiondir)" "$(DESTDIR)$(pkgconfigdir)"
+       "$(DESTDIR)$(dbusservicedir)" "$(DESTDIR)$(pkgconfigdir)"
 PROGRAMS = $(libexec_PROGRAMS)
 am_dleyna_renderer_service_OBJECTS = daemon.$(OBJEXT)
 dleyna_renderer_service_OBJECTS =  \
@@ -143,7 +141,7 @@ am__uninstall_files_from_dir = { \
     || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
          $(am__cd) "$$dir" && rm -f $$files; }; \
   }
-DATA = $(dbussession_DATA) $(pkgconfig_DATA)
+DATA = $(dbusservice_DATA) $(pkgconfig_DATA)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -161,9 +159,7 @@ CFLAGS = @CFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CYGPATH_W = @CYGPATH_W@
-DBUS_CFLAGS = @DBUS_CFLAGS@
-DBUS_LIBS = @DBUS_LIBS@
-DBUS_SESSION_DIR = @DBUS_SESSION_DIR@
+DBUS_SERVICE_DIR = @DBUS_SERVICE_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DLEYNA_CORE_CFLAGS = @DLEYNA_CORE_CFLAGS@
@@ -305,12 +301,14 @@ dleyna_renderer_service_LDADD = $(GLIB_LIBS)                                                      \
                                $(DLEYNA_CORE_LIBS)                                             \
                                $(top_builddir)/libdleyna/renderer/libdleyna-renderer-1.0.la
 
-dbussessiondir = @DBUS_SESSION_DIR@
-dbussession_DATA = com.intel.dleyna-renderer.service
+dbusservicedir = $(DBUS_SERVICE_DIR)
+dbusservice_in_files = com.intel.dleyna-renderer.service.in
+dbusservice_DATA = com.intel.dleyna-renderer.service
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = dleyna-renderer-service-1.0.pc
-CLEANFILES = $(dbussession_DATA) $(pkgconfig_DATA)
-DISTCLEANFILES = $(dbussession_DATA) $(pkgconfig_DATA)
+EXTRA_DIST = $(dbusservice_in_files)
+CLEANFILES = $(dbusservice_DATA)
+DISTCLEANFILES = $(pkgconfig_DATA)
 all: all-am
 
 .SUFFIXES:
@@ -345,8 +343,6 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
 $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 $(am__aclocal_m4_deps):
-com.intel.dleyna-renderer.service: $(top_builddir)/config.status $(srcdir)/com.intel.dleyna-renderer.service.in
-       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 dleyna-renderer-service-1.0.pc: $(top_builddir)/config.status $(srcdir)/dleyna-renderer-service-1.0.pc.in
        cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 install-libexecPROGRAMS: $(libexec_PROGRAMS)
@@ -436,27 +432,27 @@ mostlyclean-libtool:
 
 clean-libtool:
        -rm -rf .libs _libs
-install-dbussessionDATA: $(dbussession_DATA)
+install-dbusserviceDATA: $(dbusservice_DATA)
        @$(NORMAL_INSTALL)
-       @list='$(dbussession_DATA)'; test -n "$(dbussessiondir)" || list=; \
+       @list='$(dbusservice_DATA)'; test -n "$(dbusservicedir)" || list=; \
        if test -n "$$list"; then \
-         echo " $(MKDIR_P) '$(DESTDIR)$(dbussessiondir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(dbussessiondir)" || exit 1; \
+         echo " $(MKDIR_P) '$(DESTDIR)$(dbusservicedir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(dbusservicedir)" || exit 1; \
        fi; \
        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)$(dbussessiondir)'"; \
-         $(INSTALL_DATA) $$files "$(DESTDIR)$(dbussessiondir)" || exit $$?; \
+         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dbusservicedir)'"; \
+         $(INSTALL_DATA) $$files "$(DESTDIR)$(dbusservicedir)" || exit $$?; \
        done
 
-uninstall-dbussessionDATA:
+uninstall-dbusserviceDATA:
        @$(NORMAL_UNINSTALL)
-       @list='$(dbussession_DATA)'; test -n "$(dbussessiondir)" || list=; \
+       @list='$(dbusservice_DATA)'; test -n "$(dbusservicedir)" || list=; \
        files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-       dir='$(DESTDIR)$(dbussessiondir)'; $(am__uninstall_files_from_dir)
+       dir='$(DESTDIR)$(dbusservicedir)'; $(am__uninstall_files_from_dir)
 install-pkgconfigDATA: $(pkgconfig_DATA)
        @$(NORMAL_INSTALL)
        @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
@@ -565,7 +561,7 @@ check-am: all-am
 check: check-am
 all-am: Makefile $(PROGRAMS) $(DATA)
 installdirs:
-       for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(dbussessiondir)" "$(DESTDIR)$(pkgconfigdir)"; do \
+       for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(dbusservicedir)" "$(DESTDIR)$(pkgconfigdir)"; do \
          test -z "$$dir" || $(MKDIR_P) "$$dir"; \
        done
 install: install-am
@@ -623,7 +619,7 @@ info: info-am
 
 info-am:
 
-install-data-am: install-dbussessionDATA install-pkgconfigDATA
+install-data-am: install-dbusserviceDATA install-pkgconfigDATA
 
 install-dvi: install-dvi-am
 
@@ -669,7 +665,7 @@ ps: ps-am
 
 ps-am:
 
-uninstall-am: uninstall-dbussessionDATA uninstall-libexecPROGRAMS \
+uninstall-am: uninstall-dbusserviceDATA uninstall-libexecPROGRAMS \
        uninstall-pkgconfigDATA
 
 .MAKE: install-am install-strip
@@ -679,7 +675,7 @@ uninstall-am: uninstall-dbussessionDATA uninstall-libexecPROGRAMS \
        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-dbussessionDATA install-dvi install-dvi-am \
+       install-dbusserviceDATA install-dvi install-dvi-am \
        install-exec install-exec-am install-html install-html-am \
        install-info install-info-am install-libexecPROGRAMS \
        install-man install-pdf install-pdf-am install-pkgconfigDATA \
@@ -687,10 +683,14 @@ uninstall-am: uninstall-dbussessionDATA uninstall-libexecPROGRAMS \
        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-dbussessionDATA \
+       tags uninstall uninstall-am uninstall-dbusserviceDATA \
        uninstall-libexecPROGRAMS uninstall-pkgconfigDATA
 
 
+# Replace the 'libexecdir' marker with its fully expanded value
+%.service: %.service.in Makefile
+       $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
 # 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:
index 77907af..081785e 100644 (file)
@@ -1,4 +1,3 @@
 [D-BUS Service]
 Name=com.intel.dleyna-renderer
-Exec=@prefix@/libexec/dleyna-renderer-service
-
+Exec=@libexecdir@/dleyna-renderer-service
index 0ccac63..f88001f 100644 (file)
@@ -1,3 +1,46 @@
+version 0.1.0
+       - Prepare for first stable branch
+
+version 0.0.2
+       - Add a new method GetMetaData to the org.gnome.UPnP.MediaObject2 interface
+         to allow the retrieval of the Meta data information of an object in
+         DIDL-Lite XML format
+       - Handle wild cards for SortCaps & SearchCaps properties
+       - Add a new property and a new function to media container objects:
+         Resource and GetCompatibleResource()
+       - Fixed bug: CreateContainer does not specify the correct DLNAManaged flags
+         https://github.com/01org/dleyna-server/issues/24
+       - Add MediaItem2 resource properties to container objects:
+         URLs, Size, DLNAProfile & MimeType
+       - Fixed bug: ObjectUpdateID and ContainerUpdateID are reported on all
+         objects and containers
+         https://github.com/01org/dleyna-server/issues/27
+       - Fixed bug: dleyna-server can fail to discover a device if a network
+         connection is lost during device construction
+         https://github.com/01org/dleyna-server/issues/14
+       - Fixed bug: We don't display media with invalid metadata
+         https://github.com/01org/dleyna-renderer/issues/30
+       - Fixed bug: MediaConnect DMS crashes dLeyna
+         https://github.com/01org/dleyna-server/issues/49
+       - Two new methods have been added to the UPNP class, server_from_name and
+         server_from_udn.  These methods can be used to construct Device objects
+         from UDNs or friendly names
+       - Add new org.gnome.MediaContainer2 properties:
+         DLNAConversion, DLNAFlags & DLNAOperation
+       - Add a Rescan method to Manager interface
+       - Add autogen.sh script to call `autoreconf -i`
+       - Remove CreatePlayListInAnyContainer() from
+         com.intel.dLeynaServer.MediaDevice
+       - Remove CreatePlayList() from org.gnome.MediaContainer2
+       - Add CreateReference method to org.gnome.MediaContainer2
+       - Add support for object.container.playlistContainer and
+         object.container.storageFolder object classes
+       - Fixed bug: The dLeyna-server CreateClasses property is incorrect
+         https://github.com/01org/dleyna-server/issues/94
+       - Fixed bug: Incorrect Parent Path reported for XBMC
+         https://github.com/01org/dleyna-server/issues/32
+       - Add a GetIcon() method to com.intel.dLeynaServer.MediaDevice
+
 version 0.0.1
        - Initial version of dleyna-server.
        - Enable support of deleyna-server as git submodules.
index e4cfcdf..8e2b93d 100644 (file)
@@ -154,9 +154,7 @@ CFLAGS = @CFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CYGPATH_W = @CYGPATH_W@
-DBUS_CFLAGS = @DBUS_CFLAGS@
-DBUS_LIBS = @DBUS_LIBS@
-DBUS_SESSION_DIR = @DBUS_SESSION_DIR@
+DBUS_SERVICE_DIR = @DBUS_SERVICE_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DLEYNA_CORE_CFLAGS = @DLEYNA_CORE_CFLAGS@
index 2506c4c..5348c52 100644 (file)
@@ -19,8 +19,7 @@ follows:
      # cd dleyna-server
 
    Configure and build
-     # ./autoreconf -i
-     # ./configure
+     # ./autogen.sh
      # make
 
    Final installation
@@ -88,3 +87,15 @@ Set the IPC mechanism to be used.
 
 This option is disabled by default. To enable use --enable-lib-only.
 When enabled, only the libdleyna-server library is built.
+
+--with-ua-prefix
+
+This option allows a prefix to be added to the SOUP session user agent.
+For example, --with-ua-prefix=MyPrefix can be used to change a default user
+agent string from "dLeyna/0.0.1 GUPnP/0.19.4 DLNADOC/1.50" to
+"MyPrefix dLeyna/0.0.1 GUPnP/0.19.4 DLNADOC/1.50".
+
+--with-dbus-service-dir
+
+By default, the dbus service files are installed in $(datadir)/dbus-1/services.
+This option allows to choose another installation directory.
index dab7fd9..d7f98a4 100755 (executable)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for dleyna-server 0.0.1.
+# Generated by GNU Autoconf 2.69 for dleyna-server 0.2.0.
 #
 # Report bugs to <https://github.com/01org/dleyna-server/issues/new>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='dleyna-server'
 PACKAGE_TARNAME='dleyna-server'
-PACKAGE_VERSION='0.0.1'
-PACKAGE_STRING='dleyna-server 0.0.1'
+PACKAGE_VERSION='0.2.0'
+PACKAGE_STRING='dleyna-server 0.2.0'
 PACKAGE_BUGREPORT='https://github.com/01org/dleyna-server/issues/new'
 PACKAGE_URL='https://01.org/dleyna/'
 
@@ -645,9 +645,7 @@ DLEYNA_SERVER_INTERFACE_MANAGER
 DLEYNA_SERVER_NAME
 BUILD_SERVER_FALSE
 BUILD_SERVER_TRUE
-DBUS_SESSION_DIR
-DBUS_LIBS
-DBUS_CFLAGS
+DBUS_SERVICE_DIR
 DLEYNA_CORE_LIBS
 DLEYNA_CORE_CFLAGS
 LIBOBJS
@@ -805,6 +803,7 @@ with_connector_name
 with_log_level
 with_log_type
 with_ua_prefix
+with_dbus_service_dir
 enable_lib_only
 '
       ac_precious_vars='build_alias
@@ -834,9 +833,7 @@ GUPNPDLNA_LIBS
 SOUP_CFLAGS
 SOUP_LIBS
 DLEYNA_CORE_CFLAGS
-DLEYNA_CORE_LIBS
-DBUS_CFLAGS
-DBUS_LIBS'
+DLEYNA_CORE_LIBS'
 
 
 # Initialize some variables set by options.
@@ -1377,7 +1374,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures dleyna-server 0.0.1 to adapt to many kinds of systems.
+\`configure' configures dleyna-server 0.2.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1447,7 +1444,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of dleyna-server 0.0.1:";;
+     short | recursive ) echo "Configuration of dleyna-server 0.2.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1487,6 +1484,9 @@ Optional Packages:
                           comma separated list of log level
   --with-log-type         Select log output technology 0=syslog 1=GLib
   --with-ua-prefix        Specify a user agent prefix
+  --with-dbus-service-dir=PATH
+                          choose directory for dbus service files,
+                          [default=PREFIX/share/dbus-1/services]
 
 Some influential environment variables:
   CC          C compiler command
@@ -1526,8 +1526,6 @@ Some influential environment variables:
               C compiler flags for DLEYNA_CORE, overriding pkg-config
   DLEYNA_CORE_LIBS
               linker flags for DLEYNA_CORE, overriding pkg-config
-  DBUS_CFLAGS C compiler flags for DBUS, overriding pkg-config
-  DBUS_LIBS   linker flags for DBUS, overriding pkg-config
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -1596,7 +1594,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-dleyna-server configure 0.0.1
+dleyna-server configure 0.2.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2073,7 +2071,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by dleyna-server $as_me 0.0.1, which was
+It was created by dleyna-server $as_me 0.2.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2896,7 +2894,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='dleyna-server'
- VERSION='0.0.1'
+ VERSION='0.2.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -12155,12 +12153,12 @@ if test -n "$GUPNP_CFLAGS"; then
     pkg_cv_GUPNP_CFLAGS="$GUPNP_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gupnp-1.0 >= 0.19.1\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gupnp-1.0 >= 0.19.1") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gupnp-1.0 >= 0.20.3\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gupnp-1.0 >= 0.20.3") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_GUPNP_CFLAGS=`$PKG_CONFIG --cflags "gupnp-1.0 >= 0.19.1" 2>/dev/null`
+  pkg_cv_GUPNP_CFLAGS=`$PKG_CONFIG --cflags "gupnp-1.0 >= 0.20.3" 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -12172,12 +12170,12 @@ if test -n "$GUPNP_LIBS"; then
     pkg_cv_GUPNP_LIBS="$GUPNP_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gupnp-1.0 >= 0.19.1\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gupnp-1.0 >= 0.19.1") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gupnp-1.0 >= 0.20.3\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gupnp-1.0 >= 0.20.3") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_GUPNP_LIBS=`$PKG_CONFIG --libs "gupnp-1.0 >= 0.19.1" 2>/dev/null`
+  pkg_cv_GUPNP_LIBS=`$PKG_CONFIG --libs "gupnp-1.0 >= 0.20.3" 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -12198,14 +12196,14 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               GUPNP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gupnp-1.0 >= 0.19.1" 2>&1`
+               GUPNP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gupnp-1.0 >= 0.20.3" 2>&1`
         else
-               GUPNP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gupnp-1.0 >= 0.19.1" 2>&1`
+               GUPNP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gupnp-1.0 >= 0.20.3" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$GUPNP_PKG_ERRORS" >&5
 
-       as_fn_error $? "Package requirements (gupnp-1.0 >= 0.19.1) were not met:
+       as_fn_error $? "Package requirements (gupnp-1.0 >= 0.20.3) were not met:
 
 $GUPNP_PKG_ERRORS
 
 
 
 
-
-# Check whether --enable-lib-only was given.
-if test "${enable_lib_only+set}" = set; then :
-  enableval=$enable_lib_only;
-else
-  enable_lib_only=no
-fi
-
-
-if test "x$enable_lib_only" = "xno"; then :
-
-pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DBUS" >&5
-$as_echo_n "checking for DBUS... " >&6; }
-
-if test -n "$DBUS_CFLAGS"; then
-    pkg_cv_DBUS_CFLAGS="$DBUS_CFLAGS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_DBUS_CFLAGS=`$PKG_CONFIG --cflags "dbus-1" 2>/dev/null`
-                     test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-if test -n "$DBUS_LIBS"; then
-    pkg_cv_DBUS_LIBS="$DBUS_LIBS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "dbus-1") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_DBUS_LIBS=`$PKG_CONFIG --libs "dbus-1" 2>/dev/null`
-                     test "x$?" != "x0" && pkg_failed=yes
+# Check whether --with-dbus_service_dir was given.
+if test "${with_dbus_service_dir+set}" = set; then :
+  withval=$with_dbus_service_dir; with_dbus_service_dir="$withval"
 else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
+  with_dbus_service_dir=$datadir/dbus-1/services
 fi
 
+DBUS_SERVICE_DIR=$with_dbus_service_dir
 
 
-if test $pkg_failed = yes; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
-        _pkg_short_errors_supported=yes
-else
-        _pkg_short_errors_supported=no
-fi
-        if test $_pkg_short_errors_supported = yes; then
-               DBUS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "dbus-1" 2>&1`
-        else
-               DBUS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "dbus-1" 2>&1`
-        fi
-       # Put the nasty error message in config.log where it belongs
-       echo "$DBUS_PKG_ERRORS" >&5
 
-       enable_lib_only=yes
-elif test $pkg_failed = untried; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-       enable_lib_only=yes
+# Check whether --enable-lib-only was given.
+if test "${enable_lib_only+set}" = set; then :
+  enableval=$enable_lib_only;
 else
-       DBUS_CFLAGS=$pkg_cv_DBUS_CFLAGS
-       DBUS_LIBS=$pkg_cv_DBUS_LIBS
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-       DBUS_SESSION_DIR=`$PKG_CONFIG --variable=session_bus_services_dir dbus-1`;
-
-
+  enable_lib_only=no
 fi
 
-fi
 
  if test "x$enable_lib_only" = "xno"; then
   BUILD_SERVER_TRUE=
@@ -13286,7 +13217,7 @@ $as_echo "#define DLEYNA_SERVER_INTERFACE_MEDIA_DEVICE \"com.intel.dLeynaServer.
 
 
 
-ac_config_files="$ac_config_files Makefile libdleyna/server/Makefile libdleyna/server/dleyna-server-1.0.pc libdleyna/server/dleyna-server-service.conf server/com.intel.dleyna-server.service server/dleyna-server-service-1.0.pc server/Makefile test/dbus/Makefile"
+ac_config_files="$ac_config_files Makefile libdleyna/server/Makefile libdleyna/server/dleyna-server-1.0.pc libdleyna/server/dleyna-server-service.conf server/dleyna-server-service-1.0.pc server/Makefile test/dbus/Makefile"
 
 
 cat >confcache <<\_ACEOF
@@ -13819,7 +13750,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by dleyna-server $as_me 0.0.1, which was
+This file was extended by dleyna-server $as_me 0.2.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -13886,7 +13817,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-dleyna-server config.status 0.0.1
+dleyna-server config.status 0.2.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -14299,7 +14230,6 @@ do
     "libdleyna/server/Makefile") CONFIG_FILES="$CONFIG_FILES libdleyna/server/Makefile" ;;
     "libdleyna/server/dleyna-server-1.0.pc") CONFIG_FILES="$CONFIG_FILES libdleyna/server/dleyna-server-1.0.pc" ;;
     "libdleyna/server/dleyna-server-service.conf") CONFIG_FILES="$CONFIG_FILES libdleyna/server/dleyna-server-service.conf" ;;
-    "server/com.intel.dleyna-server.service") CONFIG_FILES="$CONFIG_FILES server/com.intel.dleyna-server.service" ;;
     "server/dleyna-server-service-1.0.pc") CONFIG_FILES="$CONFIG_FILES server/dleyna-server-service-1.0.pc" ;;
     "server/Makefile") CONFIG_FILES="$CONFIG_FILES server/Makefile" ;;
     "test/dbus/Makefile") CONFIG_FILES="$CONFIG_FILES test/dbus/Makefile" ;;
@@ -15671,14 +15601,15 @@ Compiler  : '${CC}'
 CFLAGS    : '${CFLAGS}'
 
 -Package features:
-       - enable-werror       : ${enable_werror}
-       - enable-debug        : ${enable_debug}
-       - enable-never-quit   : ${enable_never_quit}
-       - with_connector-name : ${with_connector_name}
-       - disable-optimization: ${disable_optimization}
-       - with-log-level      : ${with_log_level}
-       - with-log-type       : ${with_log_type}
-       - with-ua-prefix      : ${with_ua_prefix}
-       - enable-lib-only     : ${enable_lib_only}
+       - enable-werror         : ${enable_werror}
+       - enable-debug          : ${enable_debug}
+       - enable-never-quit     : ${enable_never_quit}
+       - with_connector-name   : ${with_connector_name}
+       - disable-optimization  : ${disable_optimization}
+       - with-log-level        : ${with_log_level}
+       - with-log-type         : ${with_log_type}
+       - with-ua-prefix        : ${with_ua_prefix}
+       - enable-lib-only       : ${enable_lib_only}
+       - with-dbus-service-dir : ${with_dbus_service_dir}
 
 --------------------------------------------------"
index 693911d..4641653 100644 (file)
@@ -1,7 +1,7 @@
 AC_PREREQ([2.66])
 
 AC_INIT([dleyna-server],
-       [0.0.1],
+       [0.2.0],
        [https://github.com/01org/dleyna-server/issues/new],
        ,
        [https://01.org/dleyna/])
@@ -39,7 +39,7 @@ PKG_PROG_PKG_CONFIG(0.16)
 PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28])
 PKG_CHECK_MODULES([GIO], [gio-2.0 >= 2.28])
 PKG_CHECK_MODULES([GSSDP], [gssdp-1.0 >= 0.13.2])
-PKG_CHECK_MODULES([GUPNP], [gupnp-1.0 >= 0.19.1])
+PKG_CHECK_MODULES([GUPNP], [gupnp-1.0 >= 0.20.3])
 PKG_CHECK_MODULES([GUPNPAV], [gupnp-av-1.0 >= 0.11.5])
 PKG_CHECK_MODULES([GUPNPDLNA], [gupnp-dlna-2.0 >= 0.9.4])
 PKG_CHECK_MODULES([SOUP], [libsoup-2.4 >= 2.28.2])
@@ -184,8 +184,13 @@ AC_ARG_WITH(ua-prefix,
                        [Specify a user agent prefix]),
                [with_ua_prefix = "$withval"; AC_DEFINE_UNQUOTED([UA_PREFIX], "$with_ua_prefix", [User Agent prefix])],
                [])
-               
-               
+
+AC_ARG_WITH(dbus_service_dir,
+            AS_HELP_STRING([--with-dbus-service-dir=PATH],[choose directory for dbus service files, [default=PREFIX/share/dbus-1/services]]),
+            with_dbus_service_dir="$withval", with_dbus_service_dir=$datadir/dbus-1/services)
+DBUS_SERVICE_DIR=$with_dbus_service_dir
+AC_SUBST(DBUS_SERVICE_DIR)
+
 
 AC_ARG_ENABLE(lib-only,
                AS_HELP_STRING(
@@ -194,15 +199,7 @@ AC_ARG_ENABLE(lib-only,
                [],
                [enable_lib_only=no])
 
-AS_IF([test "x$[]enable_lib_only" = "xno"],
-      [PKG_CHECK_MODULES([DBUS], [dbus-1],
-                        [DBUS_SESSION_DIR=`$PKG_CONFIG --variable=session_bus_services_dir dbus-1`;
-                         AC_SUBST(DBUS_SESSION_DIR)
-                        ],
-                        [enable_lib_only=yes])
-      ])
-
-AM_CONDITIONAL([BUILD_SERVER], [test "x$[]enable_lib_only" = "xno"])
+AM_CONDITIONAL([BUILD_SERVER], [test "x$enable_lib_only" = "xno"])
 
 AC_DEFINE([DLEYNA_SERVER_OBJECT], "/com/intel/dLeynaServer", [Name of object exposed by dleyna-server])
 AC_DEFINE([DLEYNA_SERVER_PATH], "/com/intel/dLeynaServer/server", [Path of server objects])
@@ -231,7 +228,6 @@ AC_CONFIG_FILES([Makefile                                   \
                 libdleyna/server/Makefile                      \
                 libdleyna/server/dleyna-server-1.0.pc          \
                 libdleyna/server/dleyna-server-service.conf    \
-                server/com.intel.dleyna-server.service         \
                 server/dleyna-server-service-1.0.pc            \
                 server/Makefile                                \
                 test/dbus/Makefile
@@ -248,14 +244,15 @@ Compiler  : '${CC}'
 CFLAGS    : '${CFLAGS}'
 
 -Package features:
-       - enable-werror       : ${enable_werror}
-       - enable-debug        : ${enable_debug}
-       - enable-never-quit   : ${enable_never_quit}
-       - with_connector-name : ${with_connector_name}
-       - disable-optimization: ${disable_optimization}
-       - with-log-level      : ${with_log_level}
-       - with-log-type       : ${with_log_type}
-       - with-ua-prefix      : ${with_ua_prefix}
-       - enable-lib-only     : ${enable_lib_only}
+       - enable-werror         : ${enable_werror}
+       - enable-debug          : ${enable_debug}
+       - enable-never-quit     : ${enable_never_quit}
+       - with_connector-name   : ${with_connector_name}
+       - disable-optimization  : ${disable_optimization}
+       - with-log-level        : ${with_log_level}
+       - with-log-type         : ${with_log_type}
+       - with-ua-prefix        : ${with_ua_prefix}
+       - enable-lib-only       : ${enable_lib_only}
+       - with-dbus-service-dir : ${with_dbus_service_dir}
 
 --------------------------------------------------"])
index a0c5b75..7b2996d 100644 (file)
@@ -1,6 +1,6 @@
 libdleyna_serverincdir = $(includedir)/dleyna-1.0/libdleyna/server
 
-DLEYNA_SERVER_VERSION = 1:0:0
+DLEYNA_SERVER_VERSION = 1:2:0
 
 AM_CFLAGS =    $(GLIB_CFLAGS)                          \
                $(GIO_CFLAGS)                           \
index 9396454..58002b5 100644 (file)
@@ -171,9 +171,7 @@ CFLAGS = @CFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CYGPATH_W = @CYGPATH_W@
-DBUS_CFLAGS = @DBUS_CFLAGS@
-DBUS_LIBS = @DBUS_LIBS@
-DBUS_SESSION_DIR = @DBUS_SESSION_DIR@
+DBUS_SERVICE_DIR = @DBUS_SERVICE_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DLEYNA_CORE_CFLAGS = @DLEYNA_CORE_CFLAGS@
@@ -302,7 +300,7 @@ with_connector_name = @with_connector_name@
 with_log_level = @with_log_level@
 with_log_type = @with_log_type@
 libdleyna_serverincdir = $(includedir)/dleyna-1.0/libdleyna/server
-DLEYNA_SERVER_VERSION = 1:0:0
+DLEYNA_SERVER_VERSION = 1:2:0
 AM_CFLAGS = $(GLIB_CFLAGS)                             \
                $(GIO_CFLAGS)                           \
                $(DLEYNA_CORE_CFLAGS)                   \
index fcdbe9a..324e8ee 100644 (file)
@@ -47,12 +47,6 @@ void dls_async_task_delete(dls_async_task_t *cb_data)
                g_free(cb_data->ut.update.current_tag_value);
                g_free(cb_data->ut.update.new_tag_value);
                break;
-       case DLS_TASK_CREATE_PLAYLIST:
-       case DLS_TASK_CREATE_PLAYLIST_IN_ANY:
-               g_free(cb_data->ut.playlist.didl);
-               if (cb_data->ut.playlist.collection)
-                       g_object_unref(cb_data->ut.playlist.collection);
-               break;
        default:
                break;
        }
index 8efb8c5..e14db6e 100644 (file)
@@ -77,13 +77,6 @@ struct dls_async_update_t_ {
        GHashTable *map;
 };
 
-typedef struct dls_async_playlist_t_ dls_async_playlist_t;
-struct dls_async_playlist_t_ {
-       const dleyna_task_queue_key_t *queue_id;
-       GUPnPMediaCollection *collection;
-       gchar *didl;
-};
-
 struct dls_async_task_t_ {
        dls_task_t task; /* pseudo inheritance - MUST be first field */
        dls_upnp_task_complete_t cb;
@@ -98,7 +91,6 @@ struct dls_async_task_t_ {
                dls_async_get_all_t get_all;
                dls_async_upload_t upload;
                dls_async_update_t update;
-               dls_async_playlist_t playlist;
        } ut;
 };
 
index c6b7dc4..1c3b6a4 100644 (file)
@@ -82,6 +82,13 @@ struct dls_device_upload_job_t_ {
        guint remove_idle;
 };
 
+typedef struct dls_device_download_t_ dls_device_download_t;
+struct dls_device_download_t_ {
+       SoupSession *session;
+       SoupMessage *msg;
+       dls_async_task_t *task;
+};
+
 /* Private structure used in chain task */
 typedef struct prv_new_device_ct_t_ prv_new_device_ct_t;
 struct prv_new_device_ct_t_ {
@@ -91,13 +98,6 @@ struct prv_new_device_ct_t_ {
        GHashTable *property_map;
 };
 
-typedef struct prv_new_playlist_ct_t_ prv_new_playlist_ct_t;
-struct prv_new_playlist_ct_t_ {
-       dls_async_task_t *cb_data;
-       gchar *id;
-       gchar *parent_id;
-};
-
 static void prv_get_child_count(dls_async_task_t *cb_data,
                                dls_device_count_cb_t cb, const gchar *id);
 static void prv_retrieve_child_count_for_list(dls_async_task_t *cb_data);
@@ -221,6 +221,8 @@ void dls_device_delete(void *device)
        dls_device_t *dev = device;
 
        if (dev) {
+               DLEYNA_LOG_DEBUG("Deleting device");
+
                dev->shutting_down = TRUE;
                g_hash_table_unref(dev->upload_jobs);
                g_hash_table_unref(dev->uploads);
@@ -238,6 +240,8 @@ void dls_device_delete(void *device)
                g_variant_unref(dev->sort_caps);
                g_variant_unref(dev->sort_ext_caps);
                g_variant_unref(dev->feature_list);
+               g_free(dev->icon.mime_type);
+               g_free(dev->icon.bytes);
                g_free(dev);
        }
 }
@@ -625,14 +629,19 @@ static void prv_get_feature_list_cb(GUPnPServiceProxy *proxy,
                                    gpointer user_data)
 {
        gchar *result = NULL;
+       gboolean end;
        GError *error = NULL;
        prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data;
 
-       if (!gupnp_service_proxy_end_action(proxy, action, &error,
-                                           "FeatureList", G_TYPE_STRING,
-                                           &result, NULL)) {
+       priv_t->dev->construct_step++;
+       end = gupnp_service_proxy_end_action(proxy, action, &error,
+                                            "FeatureList", G_TYPE_STRING,
+                                            &result, NULL);
+
+       if (!end || (result == NULL)) {
                DLEYNA_LOG_WARNING("GetFeatureList operation failed: %s",
-                                  error->message);
+                                  ((error != NULL) ? error->message
+                                                   : "Invalid result"));
                goto on_error;
        }
 
@@ -698,15 +707,19 @@ static void prv_get_sort_ext_capabilities_cb(GUPnPServiceProxy *proxy,
                                           gpointer user_data)
 {
        gchar *result = NULL;
+       gboolean end;
        GError *error = NULL;
        prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data;
 
-       if (!gupnp_service_proxy_end_action(proxy, action, &error,
-                                           "SortExtensionCaps",
-                                           G_TYPE_STRING, &result, NULL)) {
+       priv_t->dev->construct_step++;
+       end = gupnp_service_proxy_end_action(proxy, action, &error,
+                                            "SortExtensionCaps",
+                                            G_TYPE_STRING, &result, NULL);
+
+       if (!end || (result == NULL)) {
                DLEYNA_LOG_WARNING(
                        "GetSortExtensionCapabilities operation failed: %s",
-                       error->message);
+                       ((error != NULL) ? error->message : "Invalid result"));
                goto on_error;
        }
 
@@ -747,19 +760,23 @@ static void prv_get_capabilities_analyze(GHashTable *property_map,
 
        g_variant_builder_init(&caps_vb, G_VARIANT_TYPE("as"));
 
-       caps = g_strsplit(result, ",", 0);
-       saved = caps;
+       if (!strcmp(result, "*")) {
+               g_variant_builder_add(&caps_vb, "s", "*");
+       } else {
+               caps = g_strsplit(result, ",", 0);
+               saved = caps;
 
-       while (caps && *caps) {
-               prop_name = g_hash_table_lookup(property_map, *caps);
+               while (caps && *caps) {
+                       prop_name = g_hash_table_lookup(property_map, *caps);
 
-               if (prop_name)
-                       g_variant_builder_add(&caps_vb, "s", prop_name);
+                       if (prop_name)
+                               g_variant_builder_add(&caps_vb, "s", prop_name);
 
-               caps++;
-       }
+                       caps++;
+               }
 
-       g_strfreev(saved);
+               g_strfreev(saved);
+       }
 
        *variant = g_variant_ref_sink(g_variant_builder_end(&caps_vb));
 
@@ -775,13 +792,18 @@ static void prv_get_sort_capabilities_cb(GUPnPServiceProxy *proxy,
                                         gpointer user_data)
 {
        gchar *result = NULL;
+       gboolean end;
        GError *error = NULL;
        prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data;
 
-       if (!gupnp_service_proxy_end_action(proxy, action, &error, "SortCaps",
-                                           G_TYPE_STRING, &result, NULL)) {
+       priv_t->dev->construct_step++;
+       end = gupnp_service_proxy_end_action(proxy, action, &error, "SortCaps",
+                                            G_TYPE_STRING, &result, NULL);
+
+       if (!end || (result == NULL)) {
                DLEYNA_LOG_WARNING("GetSortCapabilities operation failed: %s",
-                                  error->message);
+                                  ((error != NULL) ? error->message
+                                                   : "Invalid result"));
                goto on_error;
        }
 
@@ -817,13 +839,19 @@ static void prv_get_search_capabilities_cb(GUPnPServiceProxy *proxy,
                                           gpointer user_data)
 {
        gchar *result = NULL;
+       gboolean end;
        GError *error = NULL;
        prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data;
 
-       if (!gupnp_service_proxy_end_action(proxy, action, &error, "SearchCaps",
-                                           G_TYPE_STRING, &result, NULL)) {
+       priv_t->dev->construct_step++;
+       end = gupnp_service_proxy_end_action(proxy, action, &error,
+                                            "SearchCaps", G_TYPE_STRING,
+                                            &result, NULL);
+
+       if (!end || (result == NULL)) {
                DLEYNA_LOG_WARNING("GetSearchCapabilities operation failed: %s",
-                                  error->message);
+                                  ((error != NULL) ? error->message
+                                                   : "Invalid result"));
                goto on_error;
        }
 
@@ -860,6 +888,8 @@ static GUPnPServiceProxyAction *prv_subscribe(dleyna_service_task_t *task,
        dls_device_t *device;
 
        device = (dls_device_t *)dleyna_service_task_get_user_data(task);
+
+       device->construct_step++;
        dls_device_subscribe_to_contents_change(device);
 
        *failed = FALSE;
@@ -912,6 +942,7 @@ static GUPnPServiceProxyAction *prv_declare(dleyna_service_task_t *task,
 
        priv_t = (prv_new_device_ct_t *)dleyna_service_task_get_user_data(task);
        device = priv_t->dev;
+       device->construct_step++;
 
        id = dls_server_get_connector()->publish_subtree(priv_t->connection,
                                                  device->path,
@@ -941,6 +972,61 @@ static GUPnPServiceProxyAction *prv_declare(dleyna_service_task_t *task,
        return NULL;
 }
 
+void dls_device_construct(
+                       dls_device_t *dev,
+                       dls_device_context_t *context,
+                       dleyna_connector_id_t connection,
+                       const dleyna_connector_dispatch_cb_t *dispatch_table,
+                       GHashTable *property_map,
+                       const dleyna_task_queue_key_t *queue_id)
+{
+       prv_new_device_ct_t *priv_t;
+       GUPnPServiceProxy *s_proxy;
+
+       DLEYNA_LOG_DEBUG("Current step: %d", dev->construct_step);
+
+       priv_t = g_new0(prv_new_device_ct_t, 1);
+
+       priv_t->dev = dev;
+       priv_t->connection = connection;
+       priv_t->vtable = dispatch_table;
+       priv_t->property_map = property_map;
+
+       s_proxy = context->service_proxy;
+
+       if (dev->construct_step < 1)
+               dleyna_service_task_add(queue_id, prv_get_search_capabilities,
+                                       s_proxy,
+                                       prv_get_search_capabilities_cb, NULL,
+                                       priv_t);
+
+       if (dev->construct_step < 2)
+               dleyna_service_task_add(queue_id, prv_get_sort_capabilities,
+                                       s_proxy,
+                                       prv_get_sort_capabilities_cb, NULL,
+                                       priv_t);
+
+       if (dev->construct_step < 3)
+               dleyna_service_task_add(queue_id, prv_get_sort_ext_capabilities,
+                                       s_proxy,
+                                       prv_get_sort_ext_capabilities_cb, NULL,
+                                       priv_t);
+
+       if (dev->construct_step < 4)
+               dleyna_service_task_add(queue_id, prv_get_feature_list, s_proxy,
+                                       prv_get_feature_list_cb, NULL, priv_t);
+
+       /* The following task should always be completed */
+       dleyna_service_task_add(queue_id, prv_subscribe, s_proxy,
+                               NULL, NULL, dev);
+
+       if (dev->construct_step < 6)
+               dleyna_service_task_add(queue_id, prv_declare, s_proxy,
+                                       NULL, g_free, priv_t);
+
+       dleyna_task_queue_start(queue_id);
+}
+
 dls_device_t *dls_device_new(
                        dleyna_connector_id_t connection,
                        GUPnPDeviceProxy *proxy,
@@ -951,10 +1037,8 @@ dls_device_t *dls_device_new(
                        const dleyna_task_queue_key_t *queue_id)
 {
        dls_device_t *dev;
-       prv_new_device_ct_t *priv_t;
        gchar *new_path;
        dls_device_context_t *context;
-       GUPnPServiceProxy *s_proxy;
 
        DLEYNA_LOG_DEBUG("New Device on %s", ip_address);
 
@@ -962,42 +1046,15 @@ dls_device_t *dls_device_new(
        DLEYNA_LOG_DEBUG("Server Path %s", new_path);
 
        dev = g_new0(dls_device_t, 1);
-       priv_t = g_new0(prv_new_device_ct_t, 1);
 
        dev->connection = connection;
        dev->contexts = g_ptr_array_new_with_free_func(prv_context_delete);
        dev->path = new_path;
 
-       priv_t->dev = dev;
-       priv_t->connection = connection;
-       priv_t->vtable = dispatch_table;
-       priv_t->property_map = property_map;
-
        context = dls_device_append_new_context(dev, ip_address, proxy);
-       s_proxy = context->service_proxy;
-
-       dleyna_service_task_add(queue_id, prv_get_search_capabilities,
-                               s_proxy,
-                               prv_get_search_capabilities_cb, NULL, priv_t);
-
-       dleyna_service_task_add(queue_id, prv_get_sort_capabilities,
-                               s_proxy,
-                               prv_get_sort_capabilities_cb, NULL, priv_t);
-
-       dleyna_service_task_add(queue_id, prv_get_sort_ext_capabilities,
-                               s_proxy,
-                               prv_get_sort_ext_capabilities_cb, NULL, priv_t);
 
-       dleyna_service_task_add(queue_id, prv_get_feature_list, s_proxy,
-                               prv_get_feature_list_cb, NULL, priv_t);
-
-       dleyna_service_task_add(queue_id, prv_subscribe, s_proxy,
-                               NULL, NULL, dev);
-
-       dleyna_service_task_add(queue_id, prv_declare, s_proxy,
-                               NULL, g_free, priv_t);
-
-       dleyna_task_queue_start(queue_id);
+       dls_device_construct(dev, context, connection, dispatch_table,
+                            property_map, queue_id);
 
        return dev;
 }
@@ -1097,6 +1154,7 @@ static void prv_found_child(GUPnPDIDLLiteParser *parser,
                dls_props_add_container(builder->vb,
                                        (GUPnPDIDLLiteContainer *)object,
                                        cb_task_data->filter_mask,
+                                       cb_task_data->protocol_info,
                                        &have_child_count);
 
                if (!have_child_count && (cb_task_data->filter_mask &
@@ -1203,24 +1261,27 @@ static void prv_get_children_cb(GUPnPServiceProxy *proxy,
                                gpointer user_data)
 {
        gchar *result = NULL;
+       const gchar *message;
+       gboolean end;
        GUPnPDIDLLiteParser *parser = NULL;
-       GError *upnp_error = NULL;
+       GError *error = NULL;
        dls_async_task_t *cb_data = user_data;
        dls_async_bas_t *cb_task_data = &cb_data->ut.bas;
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
-                                           &upnp_error,
-                                           "Result", G_TYPE_STRING,
-                                           &result, NULL)) {
-               DLEYNA_LOG_WARNING("Browse operation failed: %s",
-                                  upnp_error->message);
+       end = gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
+                                            &error, "Result",
+                                            G_TYPE_STRING, &result, NULL);
+
+       if (!end || (result == NULL)) {
+               message = (error != NULL) ? error->message : "Invalid result";
+               DLEYNA_LOG_WARNING("Browse operation failed: %s", message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
                                             "Browse operation failed: %s",
-                                            upnp_error->message);
+                                            message);
                goto on_error;
        }
 
@@ -1234,15 +1295,15 @@ static void prv_get_children_cb(GUPnPServiceProxy *proxy,
        cb_task_data->vbs = g_ptr_array_new_with_free_func(
                prv_object_builder_delete);
 
-       if (!gupnp_didl_lite_parser_parse_didl(parser, result, &upnp_error) &&
-           upnp_error->code != GUPNP_XML_ERROR_EMPTY_NODE) {
+       if (!gupnp_didl_lite_parser_parse_didl(parser, result, &error) &&
+           error->code != GUPNP_XML_ERROR_EMPTY_NODE) {
                DLEYNA_LOG_WARNING("Unable to parse results of browse: %s",
-                                  upnp_error->message);
+                                  error->message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
                                             "Unable to parse results of browse: %s",
-                                            upnp_error->message);
+                                            error->message);
                goto on_error;
        }
 
@@ -1263,8 +1324,8 @@ on_error:
 
 no_complete:
 
-       if (upnp_error)
-               g_error_free(upnp_error);
+       if (error)
+               g_error_free(error);
 
        if (parser)
                g_object_unref(parser);
@@ -1350,6 +1411,7 @@ static void prv_get_container(GUPnPDIDLLiteParser *parser,
                dls_props_add_container(cb_task_data->vb,
                                        (GUPnPDIDLLiteContainer *)object,
                                        DLS_UPNP_MASK_ALL_PROPS,
+                                       cb_task_data->protocol_info,
                                        &have_child_count);
                if (!have_child_count)
                        cb_task_data->need_child_count = TRUE;
@@ -1366,25 +1428,41 @@ static void prv_get_object(GUPnPDIDLLiteParser *parser,
 {
        dls_async_task_t *cb_data = user_data;
        dls_async_get_all_t *cb_task_data = &cb_data->ut.get_all;
-       const char *id;
+       const char *object_id;
+       const char *parent_id;
        const char *parent_path;
        gchar *path = NULL;
 
-       id = gupnp_didl_lite_object_get_parent_id(object);
+       object_id = gupnp_didl_lite_object_get_id(object);
+       if (!object_id)
+               goto on_error;
+
+       parent_id = gupnp_didl_lite_object_get_parent_id(object);
+       if (!parent_id)
+               goto on_error;
 
-       if (!id || !strcmp(id, "-1") || !strcmp(id, "")) {
+       if (!strcmp(object_id, "0") || !strcmp(parent_id, "-1")) {
                parent_path = cb_data->task.target.root_path;
        } else {
-               path = dls_path_from_id(cb_data->task.target.root_path, id);
+               path = dls_path_from_id(cb_data->task.target.root_path,
+                                       parent_id);
                parent_path = path;
        }
 
        if (!dls_props_add_object(cb_task_data->vb, object,
                                  cb_data->task.target.root_path,
                                  parent_path, DLS_UPNP_MASK_ALL_PROPS))
-               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
-                                            DLEYNA_ERROR_BAD_RESULT,
-                                            "Unable to retrieve mandatory object properties");
+               goto on_error;
+
+       g_free(path);
+
+       return;
+
+on_error:
+
+       cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                    DLEYNA_ERROR_BAD_RESULT,
+                                    "Unable to retrieve mandatory object properties");
        g_free(path);
 }
 
@@ -1404,6 +1482,7 @@ static void prv_get_all(GUPnPDIDLLiteParser *parser,
                                cb_task_data->vb,
                                (GUPnPDIDLLiteContainer *)
                                object, DLS_UPNP_MASK_ALL_PROPS,
+                               cb_task_data->protocol_info,
                                &have_child_count);
                        if (!have_child_count)
                                cb_task_data->need_child_count = TRUE;
@@ -1438,25 +1517,27 @@ static void prv_system_update_id_for_prop_cb(GUPnPServiceProxy *proxy,
                                    GUPnPServiceProxyAction *action,
                                    gpointer user_data)
 {
-       GError *upnp_error = NULL;
-       guint id;
+       GError *error = NULL;
+       const gchar *message;
+       gboolean end;
+       guint id = G_MAXUINT32;
        dls_async_task_t *cb_data = user_data;
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(proxy, action, &upnp_error,
-                                           "Id", G_TYPE_UINT,
-                                           &id,
-                                           NULL)) {
-               DLEYNA_LOG_WARNING("Unable to retrieve ServiceUpdateID: %s %s",
-                                  g_quark_to_string(upnp_error->domain),
-                                  upnp_error->message);
+       end = gupnp_service_proxy_end_action(proxy, action, &error,
+                                            "Id", G_TYPE_UINT, &id, NULL);
+
+       if (!end || (id == G_MAXUINT32)) {
+               message = (error != NULL) ? error->message : "Invalid result";
+               DLEYNA_LOG_WARNING("Unable to retrieve SystemUpdateID: %s",
+                                  message);
 
                cb_data->error = g_error_new(
                                        DLEYNA_SERVER_ERROR,
                                        DLEYNA_ERROR_OPERATION_FAILED,
-                                       "Unable to retrieve ServiceUpdateID: %s",
-                                       upnp_error->message);
+                                       "Unable to retrieve SystemUpdateID: %s",
+                                       message);
 
                goto on_complete;
        }
@@ -1468,8 +1549,8 @@ on_complete:
        (void) g_idle_add(dls_async_task_complete, cb_data);
        g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id);
 
-       if (upnp_error)
-               g_error_free(upnp_error);
+       if (error)
+               g_error_free(error);
 
        DLEYNA_LOG_DEBUG("Exit");
 }
@@ -1493,13 +1574,13 @@ static void prv_get_system_update_id_for_prop(GUPnPServiceProxy *proxy,
                goto on_complete;
        }
 
-       gupnp_service_proxy_begin_action(proxy, "GetSystemUpdateID",
-                                        prv_system_update_id_for_prop_cb,
-                                        cb_data,
-                                        NULL);
+       cb_data->action = gupnp_service_proxy_begin_action(
+                                       proxy, "GetSystemUpdateID",
+                                       prv_system_update_id_for_prop_cb,
+                                       cb_data,
+                                       NULL);
 
        cb_data->proxy = proxy;
-
        g_object_add_weak_pointer((G_OBJECT(proxy)),
                                  (gpointer *)&cb_data->proxy);
 
@@ -1517,26 +1598,27 @@ static void prv_system_update_id_for_props_cb(GUPnPServiceProxy *proxy,
                                    GUPnPServiceProxyAction *action,
                                    gpointer user_data)
 {
-       GError *upnp_error = NULL;
-       guint id;
+       GError *error = NULL;
+       const gchar *message;
+       gboolean end;
+       guint id = G_MAXUINT32;
        dls_async_task_t *cb_data = user_data;
        dls_async_get_all_t *cb_task_data = &cb_data->ut.get_all;
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(proxy, action, &upnp_error,
-                                           "Id", G_TYPE_UINT,
-                                           &id,
-                                           NULL)) {
-               DLEYNA_LOG_WARNING("Unable to retrieve ServiceUpdateID: %s %s",
-                                  g_quark_to_string(upnp_error->domain),
-                                  upnp_error->message);
+       end = gupnp_service_proxy_end_action(proxy, action, &error,
+                                           "Id", G_TYPE_UINT, &id, NULL);
 
-               cb_data->error = g_error_new(
-                                       DLEYNA_SERVER_ERROR,
-                                       DLEYNA_ERROR_OPERATION_FAILED,
-                                       "Unable to retrieve ServiceUpdateID: %s",
-                                       upnp_error->message);
+       if (!end || (id == G_MAXUINT32)) {
+               message = (error != NULL) ? error->message : "Invalid result";
+               DLEYNA_LOG_WARNING("Unable to retrieve SystemUpdateID: %s",
+                                  message);
+
+               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                            DLEYNA_ERROR_OPERATION_FAILED,
+                                            "Unable to retrieve SystemUpdateID: %s",
+                                            message);
 
                goto on_complete;
        }
@@ -1559,8 +1641,8 @@ on_complete:
                                         cb_data->cancel_id);
        }
 
-       if (upnp_error)
-               g_error_free(upnp_error);
+       if (error)
+               g_error_free(error);
 
        DLEYNA_LOG_DEBUG("Exit");
 }
@@ -1588,17 +1670,22 @@ static void prv_get_system_update_id_for_props(GUPnPServiceProxy *proxy,
                goto on_complete;
        }
 
-       gupnp_service_proxy_begin_action(proxy, "GetSystemUpdateID",
-                                        prv_system_update_id_for_props_cb,
-                                        cb_data,
-                                        NULL);
+       cb_data->action = gupnp_service_proxy_begin_action(
+                                       proxy, "GetSystemUpdateID",
+                                       prv_system_update_id_for_props_cb,
+                                       cb_data,
+                                       NULL);
 
-       cb_data->proxy = proxy;
+       if (cb_data->proxy != NULL)
+               g_object_remove_weak_pointer((G_OBJECT(cb_data->proxy)),
+                                            (gpointer *)&cb_data->proxy);
 
+       cb_data->proxy = proxy;
        g_object_add_weak_pointer((G_OBJECT(proxy)),
                                  (gpointer *)&cb_data->proxy);
 
-       cb_data->cancel_id = g_cancellable_connect(
+       if (!cb_data->cancel_id)
+               cb_data->cancel_id = g_cancellable_connect(
                                        cb_data->cancellable,
                                        G_CALLBACK(dls_async_task_cancelled_cb),
                                        cb_data, NULL);
@@ -1634,26 +1721,27 @@ static void prv_service_reset_for_prop_cb(GUPnPServiceProxy *proxy,
                                          GUPnPServiceProxyAction *action,
                                          gpointer user_data)
 {
-       GError *upnp_error = NULL;
+       GError *error = NULL;
+       const gchar *message;
        gchar *token = NULL;
+       gboolean end;
        dls_async_task_t *cb_data = user_data;
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(proxy, action, &upnp_error,
-                                           "ResetToken", G_TYPE_STRING,
-                                           &token,
-                                           NULL)) {
-               DLEYNA_LOG_WARNING(
-                       "Unable to retrieve ServiceResetToken: %s %s",
-                       g_quark_to_string(upnp_error->domain),
-                       upnp_error->message);
+       end = gupnp_service_proxy_end_action(proxy, action, &error,
+                                            "ResetToken", G_TYPE_STRING,
+                                            &token, NULL);
 
+       if (!end || (token == NULL)) {
+               message = (error != NULL) ? error->message : "Invalid result";
+               DLEYNA_LOG_WARNING("Unable to retrieve ServiceResetToken: %s",
+                                  message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
                                             "GetServiceResetToken failed: %s",
-                                            upnp_error->message);
+                                            message);
 
                goto on_complete;
        }
@@ -1669,8 +1757,8 @@ on_complete:
        (void) g_idle_add(dls_async_task_complete, cb_data);
        g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id);
 
-       if (upnp_error)
-               g_error_free(upnp_error);
+       if (error)
+               g_error_free(error);
 
        DLEYNA_LOG_DEBUG("Exit");
 }
@@ -1691,13 +1779,13 @@ static void prv_get_sr_token_for_prop(GUPnPServiceProxy *proxy,
                goto on_error;
        }
 
-       gupnp_service_proxy_begin_action(proxy, "GetServiceResetToken",
-                                        prv_service_reset_for_prop_cb,
-                                        cb_data,
-                                        NULL);
+       cb_data->action = gupnp_service_proxy_begin_action(
+                                       proxy, "GetServiceResetToken",
+                                       prv_service_reset_for_prop_cb,
+                                       cb_data,
+                                       NULL);
 
        cb_data->proxy = proxy;
-
        g_object_add_weak_pointer((G_OBJECT(proxy)),
                                  (gpointer *)&cb_data->proxy);
 
@@ -1715,27 +1803,28 @@ static void prv_service_reset_for_props_cb(GUPnPServiceProxy *proxy,
                                          GUPnPServiceProxyAction *action,
                                          gpointer user_data)
 {
-       GError *upnp_error = NULL;
+       GError *error = NULL;
+       const gchar *message;
        gchar *token = NULL;
+       gboolean end;
        dls_async_task_t *cb_data = user_data;
        dls_async_get_all_t *cb_task_data;
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(proxy, action, &upnp_error,
+       end = gupnp_service_proxy_end_action(proxy, action, &error,
                                            "ResetToken", G_TYPE_STRING,
-                                           &token,
-                                           NULL)) {
-               DLEYNA_LOG_WARNING(
-                       "Unable to retrieve ServiceResetToken: %s %s",
-                       g_quark_to_string(upnp_error->domain),
-                       upnp_error->message);
+                                           &token, NULL);
+
+       if (!end || (token == NULL)) {
+               message = (error != NULL) ? error->message : "Invalid result";
+               DLEYNA_LOG_WARNING("Unable to retrieve ServiceResetToken: %s",
+                                  message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
                                             "GetServiceResetToken failed: %s",
-                                            upnp_error->message);
-
+                                            message);
                goto on_complete;
        }
 
@@ -1756,8 +1845,8 @@ on_complete:
        (void) g_idle_add(dls_async_task_complete, cb_data);
        g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id);
 
-       if (upnp_error)
-               g_error_free(upnp_error);
+       if (error)
+               g_error_free(error);
 
        DLEYNA_LOG_DEBUG("Exit");
 }
@@ -1779,17 +1868,22 @@ static void prv_get_sr_token_for_props(GUPnPServiceProxy *proxy,
                goto on_complete; /* No error here, just skip the property */
        }
 
-       gupnp_service_proxy_begin_action(proxy, "GetServiceResetToken",
-                                        prv_service_reset_for_props_cb,
-                                        cb_data,
-                                        NULL);
+       cb_data->action = gupnp_service_proxy_begin_action(
+                                       proxy, "GetServiceResetToken",
+                                       prv_service_reset_for_props_cb,
+                                       cb_data,
+                                       NULL);
+
+       if (cb_data->proxy != NULL)
+               g_object_remove_weak_pointer((G_OBJECT(cb_data->proxy)),
+                                            (gpointer *)&cb_data->proxy);
 
        cb_data->proxy = proxy;
-
        g_object_add_weak_pointer((G_OBJECT(proxy)),
                                  (gpointer *)&cb_data->proxy);
 
-       cb_data->cancel_id = g_cancellable_connect(
+       if (!cb_data->cancel_id)
+               cb_data->cancel_id = g_cancellable_connect(
                                        cb_data->cancellable,
                                        G_CALLBACK(dls_async_task_cancelled_cb),
                                        cb_data, NULL);
@@ -1826,25 +1920,28 @@ static void prv_get_all_ms2spec_props_cb(GUPnPServiceProxy *proxy,
                                         GUPnPServiceProxyAction *action,
                                         gpointer user_data)
 {
-       GError *upnp_error = NULL;
+       GError *error = NULL;
+       const gchar *message;
        gchar *result = NULL;
+       gboolean end;
        GUPnPDIDLLiteParser *parser = NULL;
        dls_async_task_t *cb_data = user_data;
        dls_async_get_all_t *cb_task_data = &cb_data->ut.get_all;
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
-                                           &upnp_error,
-                                           "Result", G_TYPE_STRING,
-                                           &result, NULL)) {
-               DLEYNA_LOG_WARNING("Browse operation failed: %s",
-                                  upnp_error->message);
+       end = gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
+                                           &error, "Result",
+                                           G_TYPE_STRING, &result, NULL);
+
+       if (!end || (result == NULL)) {
+               message = (error != NULL) ? error->message : "Invalid result";
+               DLEYNA_LOG_WARNING("Browse operation failed: %s", message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
                                             "Browse operation failed: %s",
-                                            upnp_error->message);
+                                            message);
                goto on_error;
        }
 
@@ -1855,8 +1952,8 @@ static void prv_get_all_ms2spec_props_cb(GUPnPServiceProxy *proxy,
        g_signal_connect(parser, "object-available" , cb_task_data->prop_func,
                         cb_data);
 
-       if (!gupnp_didl_lite_parser_parse_didl(parser, result, &upnp_error)) {
-               if (upnp_error->code == GUPNP_XML_ERROR_EMPTY_NODE) {
+       if (!gupnp_didl_lite_parser_parse_didl(parser, result, &error)) {
+               if (error->code == GUPNP_XML_ERROR_EMPTY_NODE) {
                        DLEYNA_LOG_WARNING("Property not defined for object");
 
                        cb_data->error =
@@ -1866,13 +1963,13 @@ static void prv_get_all_ms2spec_props_cb(GUPnPServiceProxy *proxy,
                } else {
                        DLEYNA_LOG_WARNING(
                                "Unable to parse results of browse: %s",
-                               upnp_error->message);
+                               error->message);
 
                        cb_data->error =
                                g_error_new(DLEYNA_SERVER_ERROR,
                                            DLEYNA_ERROR_OPERATION_FAILED,
                                            "Unable to parse results of browse: %s",
-                                           upnp_error->message);
+                                           error->message);
                }
                goto on_error;
        }
@@ -1906,8 +2003,8 @@ on_error:
 
 no_complete:
 
-       if (upnp_error)
-               g_error_free(upnp_error);
+       if (error)
+               g_error_free(error);
 
        if (parser)
                g_object_unref(parser);
@@ -2084,13 +2181,15 @@ static void prv_get_container_property(GUPnPDIDLLiteParser *parser,
        dls_async_task_t *cb_data = user_data;
        dls_task_t *task = &cb_data->task;
        dls_task_get_prop_t *task_data = &task->ut.get_prop;
+       dls_async_get_prop_t *cb_task_data = &cb_data->ut.get_prop;
 
        if (cb_data->task.result)
                goto on_error;
 
        cb_data->task.result = dls_props_get_container_prop(
-                                                       task_data->prop_name,
-                                                       object);
+                                               task_data->prop_name,
+                                               object,
+                                               cb_task_data->protocol_info);
 
 on_error:
 
@@ -2139,24 +2238,27 @@ static void prv_count_children_cb(GUPnPServiceProxy *proxy,
 {
        dls_device_count_data_t *count_data = user_data;
        dls_async_task_t *cb_data = count_data->cb_data;
-       GError *upnp_error = NULL;
-       gint count;
+       GError *error = NULL;
+       const gchar *message;
+       guint count = G_MAXUINT32;
        gboolean complete = FALSE;
+       gboolean end;
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
-                                           &upnp_error,
-                                           "TotalMatches", G_TYPE_INT,
-                                           &count,
-                                           NULL)) {
-               DLEYNA_LOG_WARNING("Browse operation failed: %s",
-                                  upnp_error->message);
+       end = gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
+                                           &error,
+                                           "TotalMatches", G_TYPE_UINT, &count,
+                                           NULL);
+
+       if (!end || (count == G_MAXUINT32)) {
+               message = (error != NULL) ? error->message : "Invalid result";
+               DLEYNA_LOG_WARNING("Browse operation failed: %s", message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
                                             "Browse operation failed: %s",
-                                            upnp_error->message);
+                                            message);
                goto on_error;
        }
 
@@ -2172,8 +2274,8 @@ on_error:
                                         cb_data->cancel_id);
        }
 
-       if (upnp_error)
-               g_error_free(upnp_error);
+       if (error)
+               g_error_free(error);
 
        DLEYNA_LOG_DEBUG("Exit");
 }
@@ -2216,8 +2318,10 @@ static void prv_get_ms2spec_prop_cb(GUPnPServiceProxy *proxy,
                                    GUPnPServiceProxyAction *action,
                                    gpointer user_data)
 {
-       GError *upnp_error = NULL;
+       GError *error = NULL;
+       const gchar *message;
        gchar *result = NULL;
+       gboolean end;
        GUPnPDIDLLiteParser *parser = NULL;
        dls_async_task_t *cb_data = user_data;
        dls_async_get_prop_t *cb_task_data = &cb_data->ut.get_prop;
@@ -2225,17 +2329,18 @@ static void prv_get_ms2spec_prop_cb(GUPnPServiceProxy *proxy,
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
-                                           &upnp_error,
-                                           "Result", G_TYPE_STRING,
-                                           &result, NULL)) {
-               DLEYNA_LOG_WARNING("Browse operation failed: %s",
-                                  upnp_error->message);
+       end = gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
+                                           &error, "Result",
+                                           G_TYPE_STRING, &result, NULL);
+
+       if (!end || (result == NULL)) {
+               message = (error != NULL) ? error->message : "Invalid result";
+               DLEYNA_LOG_WARNING("Browse operation failed: %s", message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
                                             "Browse operation failed: %s",
-                                            upnp_error->message);
+                                            message);
                goto on_error;
        }
 
@@ -2246,8 +2351,8 @@ static void prv_get_ms2spec_prop_cb(GUPnPServiceProxy *proxy,
        g_signal_connect(parser, "object-available" , cb_task_data->prop_func,
                         cb_data);
 
-       if (!gupnp_didl_lite_parser_parse_didl(parser, result, &upnp_error)) {
-               if (upnp_error->code == GUPNP_XML_ERROR_EMPTY_NODE) {
+       if (!gupnp_didl_lite_parser_parse_didl(parser, result, &error)) {
+               if (error->code == GUPNP_XML_ERROR_EMPTY_NODE) {
                        DLEYNA_LOG_WARNING("Property not defined for object");
 
                        cb_data->error =
@@ -2257,13 +2362,13 @@ static void prv_get_ms2spec_prop_cb(GUPnPServiceProxy *proxy,
                } else {
                        DLEYNA_LOG_WARNING(
                                "Unable to parse results of browse: %s",
-                               upnp_error->message);
+                               error->message);
 
                        cb_data->error =
                                g_error_new(DLEYNA_SERVER_ERROR,
                                            DLEYNA_ERROR_OPERATION_FAILED,
                                            "Unable to parse results of browse: %s",
-                                           upnp_error->message);
+                                           error->message);
                }
                goto on_error;
        }
@@ -2292,8 +2397,8 @@ on_error:
                                         cb_data->cancel_id);
        }
 
-       if (upnp_error)
-               g_error_free(upnp_error);
+       if (error)
+               g_error_free(error);
 
        if (parser)
                g_object_unref(parser);
@@ -2491,7 +2596,8 @@ static void prv_found_target(GUPnPDIDLLiteParser *parser,
 {
        dls_async_task_t *cb_data = user_data;
        dls_async_bas_t *cb_task_data = &cb_data->ut.bas;
-       const char *id;
+       const char *object_id;
+       const char *parent_id;
        const char *parent_path;
        gchar *path = NULL;
        gboolean have_child_count;
@@ -2501,12 +2607,19 @@ static void prv_found_target(GUPnPDIDLLiteParser *parser,
 
        builder = g_new0(dls_device_object_builder_t, 1);
 
-       id = gupnp_didl_lite_object_get_parent_id(object);
+       object_id = gupnp_didl_lite_object_get_id(object);
+       if (!object_id)
+               goto on_error;
+
+       parent_id = gupnp_didl_lite_object_get_parent_id(object);
+       if (!parent_id)
+               goto on_error;
 
-       if (!id || !strcmp(id, "-1") || !strcmp(id, "")) {
+       if (!strcmp(object_id, "0") || !strcmp(parent_id, "-1")) {
                parent_path = cb_data->task.target.root_path;
        } else {
-               path = dls_path_from_id(cb_data->task.target.root_path, id);
+               path = dls_path_from_id(cb_data->task.target.root_path,
+                                       parent_id);
                parent_path = path;
        }
 
@@ -2521,6 +2634,7 @@ static void prv_found_target(GUPnPDIDLLiteParser *parser,
                dls_props_add_container(builder->vb,
                                        (GUPnPDIDLLiteContainer *)object,
                                        cb_task_data->filter_mask,
+                                       cb_task_data->protocol_info,
                                        &have_child_count);
 
                if (!have_child_count && (cb_task_data->filter_mask &
@@ -2558,31 +2672,35 @@ static void prv_search_cb(GUPnPServiceProxy *proxy,
                          gpointer user_data)
 {
        gchar *result = NULL;
+       const gchar *message;
+       gboolean end;
+       guint count = G_MAXUINT32;
        GUPnPDIDLLiteParser *parser = NULL;
-       GError *upnp_error = NULL;
+       GError *error = NULL;
        dls_async_task_t *cb_data = user_data;
        dls_async_bas_t *cb_task_data = &cb_data->ut.bas;
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
-                                           &upnp_error,
-                                           "Result", G_TYPE_STRING,
-                                           &result,
-                                           "TotalMatches", G_TYPE_INT,
-                                           &cb_task_data->max_count,
-                                           NULL)) {
+       end = gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
+                                            &error,
+                                            "Result", G_TYPE_STRING, &result,
+                                            "TotalMatches", G_TYPE_UINT,
+                                            &count, NULL);
 
-               DLEYNA_LOG_WARNING("Search operation failed %s",
-                                  upnp_error->message);
+       if (!end || (result == NULL) || (count == G_MAXUINT32)) {
+               message = (error != NULL) ? error->message : "Invalid result";
+               DLEYNA_LOG_WARNING("Search operation failed %s", message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
                                             "Search operation failed: %s",
-                                            upnp_error->message);
+                                            message);
                goto on_error;
        }
 
+       cb_task_data->max_count = count;
+
        parser = gupnp_didl_lite_parser_new();
 
        cb_task_data->vbs = g_ptr_array_new_with_free_func(
@@ -2593,15 +2711,15 @@ static void prv_search_cb(GUPnPServiceProxy *proxy,
 
        DLEYNA_LOG_DEBUG("Server Search result: %s", result);
 
-       if (!gupnp_didl_lite_parser_parse_didl(parser, result, &upnp_error) &&
-           upnp_error->code != GUPNP_XML_ERROR_EMPTY_NODE) {
+       if (!gupnp_didl_lite_parser_parse_didl(parser, result, &error) &&
+           error->code != GUPNP_XML_ERROR_EMPTY_NODE) {
                DLEYNA_LOG_WARNING("Unable to parse results of search: %s",
-                                  upnp_error->message);
+                                  error->message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
                                             "Unable to parse results of search: %s",
-                                            upnp_error->message);
+                                            error->message);
                goto on_error;
        }
 
@@ -2634,8 +2752,8 @@ no_complete:
 
        g_free(result);
 
-       if (upnp_error)
-               g_error_free(upnp_error);
+       if (error)
+               g_error_free(error);
 
        DLEYNA_LOG_DEBUG("Exit");
 }
@@ -2738,10 +2856,16 @@ static gchar *prv_create_new_container_didl(const gchar *parent_id,
        GUPnPDIDLLiteWriter *writer;
        GUPnPDIDLLiteObject *item;
        GUPnPDIDLLiteContainer *container;
-       gchar *retval;
        GVariantIter iter;
        GVariant *child_type;
        const gchar *actual_type;
+       GUPnPOCMFlags flags;
+       gchar *retval = NULL;
+
+       actual_type = dls_props_media_spec_to_upnp_class(
+                                               task->ut.create_container.type);
+       if (!actual_type)
+               goto on_error;
 
        writer = gupnp_didl_lite_writer_new(NULL);
        item = GUPNP_DIDL_LITE_OBJECT(
@@ -2753,11 +2877,16 @@ static gchar *prv_create_new_container_didl(const gchar *parent_id,
                                        item,
                                        task->ut.create_container.display_name);
        gupnp_didl_lite_object_set_parent_id(item, parent_id);
-       actual_type = dls_props_media_spec_to_upnp_class(
-                                               task->ut.create_container.type);
        gupnp_didl_lite_object_set_upnp_class(item, actual_type);
        gupnp_didl_lite_object_set_restricted(item, FALSE);
-       gupnp_didl_lite_object_set_dlna_managed(item, GUPNP_OCM_FLAGS_UPLOAD);
+
+       flags = GUPNP_OCM_FLAGS_UPLOAD |
+               GUPNP_OCM_FLAGS_CREATE_CONTAINER |
+               GUPNP_OCM_FLAGS_DESTROYABLE |
+               GUPNP_OCM_FLAGS_UPLOAD_DESTROYABLE |
+               GUPNP_OCM_FLAGS_CHANGE_METADATA;
+
+       gupnp_didl_lite_object_set_dlna_managed(item, flags);
 
        g_variant_iter_init(&iter, task->ut.create_container.child_types);
        while ((child_type = g_variant_iter_next_value(&iter))) {
@@ -2774,6 +2903,8 @@ static gchar *prv_create_new_container_didl(const gchar *parent_id,
        g_object_unref(item);
        g_object_unref(writer);
 
+on_error:
+
        return retval;
 }
 
@@ -3166,27 +3297,30 @@ static void prv_create_container_cb(GUPnPServiceProxy *proxy,
                 gpointer user_data)
 {
        dls_async_task_t *cb_data = user_data;
-       GError *upnp_error = NULL;
+       const gchar *message;
+       GError *error = NULL;
        gchar *result = NULL;
        gchar *object_id = NULL;
        gchar *object_path;
+       gboolean end;
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
-                                           &upnp_error,
-                                           "ObjectID", G_TYPE_STRING,
-                                           &object_id,
-                                           "Result", G_TYPE_STRING,
-                                           &result,
-                                           NULL)) {
+       end = gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
+                                            &error, "ObjectID",
+                                            G_TYPE_STRING, &object_id,
+                                            "Result", G_TYPE_STRING, &result,
+                                            NULL);
+
+       if (!end || (object_id == NULL)) {
+               message = (error != NULL) ? error->message : "Invalid result";
                DLEYNA_LOG_WARNING("Create Object operation failed: %s",
-                                  upnp_error->message);
+                                  message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
                                             "Create Object operation failed: %s",
-                                            upnp_error->message);
+                                            message);
                goto on_error;
        }
 
@@ -3201,14 +3335,11 @@ on_error:
        (void) g_idle_add(dls_async_task_complete, cb_data);
        g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id);
 
-       if (object_id)
-               g_free(object_id);
-
-       if (result)
-               g_free(result);
+       g_free(object_id);
+       g_free(result);
 
-       if (upnp_error)
-               g_error_free(upnp_error);
+       if (error)
+               g_error_free(error);
 
        DLEYNA_LOG_DEBUG("Exit");
 }
@@ -3223,8 +3354,10 @@ static void prv_generic_upload_cb(dls_async_task_t *cb_data,
        gchar *result = NULL;
        gchar *import_uri = NULL;
        gchar *object_path;
+       const gchar *message;
        GError *error = NULL;
        gboolean delete_needed = FALSE;
+       gboolean end;
        gint *upload_id;
        GUPnPDIDLLiteParser *parser = NULL;
        GVariant *out_p[2];
@@ -3233,21 +3366,21 @@ static void prv_generic_upload_cb(dls_async_task_t *cb_data,
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
-                                           &error,
-                                           "ObjectID", G_TYPE_STRING,
-                                           &object_id,
-                                           "Result", G_TYPE_STRING,
-                                           &result,
-                                           NULL)) {
+       end = gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
+                                            &error, "ObjectID",
+                                            G_TYPE_STRING, &object_id,
+                                            "Result", G_TYPE_STRING, &result,
+                                            NULL);
+
+       if (!end || (object_id == NULL) || (result == NULL)) {
+               message = (error != NULL) ? error->message : "Invalid result";
                DLEYNA_LOG_WARNING("Create Object operation failed: %s",
-                                  error->message);
+                                  message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
-                                            "Create Object operation "
-                                            " failed: %s",
-                                            error->message);
+                                            "Create Object operation failed: %s",
+                                            message);
                goto on_error;
        }
 
@@ -3264,7 +3397,6 @@ static void prv_generic_upload_cb(dls_async_task_t *cb_data,
 
        if (!gupnp_didl_lite_parser_parse_didl(parser, result, &error) &&
            error->code != GUPNP_XML_ERROR_EMPTY_NODE) {
-
                DLEYNA_LOG_WARNING(
                                "Unable to parse results of CreateObject: %s",
                                error->message);
@@ -3574,6 +3706,14 @@ void dls_device_create_container(dls_client_t *client,
        context = dls_device_get_context(task->target.device, client);
 
        didl = prv_create_new_container_didl(parent_id, task);
+       if (!didl) {
+               DLEYNA_LOG_WARNING("Unable to create didl");
+
+               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                            DLEYNA_ERROR_OPERATION_FAILED,
+                                            "Unable to create didl");
+               goto on_error;
+       }
 
        DLEYNA_LOG_DEBUG("DIDL: %s", didl);
 
@@ -3596,7 +3736,11 @@ void dls_device_create_container(dls_client_t *client,
 
        g_free(didl);
 
+on_error:
+
        DLEYNA_LOG_DEBUG("Exit");
+
+       return;
 }
 
 static void prv_update_object_update_cb(GUPnPServiceProxy *proxy,
@@ -3684,11 +3828,13 @@ static gchar *prv_get_new_xml_fragment(GUPnPDIDLLiteObject *object,
        } else if (mask & DLS_UPNP_MASK_PROP_TYPE) {
                upnp_class = dls_props_media_spec_to_upnp_class(
                                        g_variant_get_string(value, NULL));
+               if (!upnp_class)
+                       goto on_error;
 
                gupnp_didl_lite_object_set_upnp_class(object, upnp_class);
 
                retval = gupnp_didl_lite_object_get_upnp_class_xml_string(
-                                                               object);
+                       object);
        } else if (mask & DLS_UPNP_MASK_PROP_TRACK_NUMBER) {
                gupnp_didl_lite_object_set_track_number(
                                                object,
@@ -3711,6 +3857,8 @@ static gchar *prv_get_new_xml_fragment(GUPnPDIDLLiteObject *object,
                retval = gupnp_didl_lite_object_get_artists_xml_string(object);
        }
 
+on_error:
+
        return retval;
 }
 
@@ -3750,7 +3898,6 @@ static void prv_get_xml_fragments(GUPnPDIDLLiteParser *parser,
        (void) g_variant_iter_init(&viter, task_data->to_add_update);
 
        while (g_variant_iter_next(&viter, "{&sv}", &prop, &value)) {
-
                DLEYNA_LOG_DEBUG("to_add_update = %s", prop);
 
                prop_map = g_hash_table_lookup(cb_task_data->map, prop);
@@ -3819,25 +3966,30 @@ static void prv_update_object_browse_cb(GUPnPServiceProxy *proxy,
                                        GUPnPServiceProxyAction *action,
                                        gpointer user_data)
 {
-       GError *upnp_error = NULL;
+       GError *error = NULL;
        dls_async_task_t *cb_data = user_data;
        dls_async_update_t *cb_task_data = &cb_data->ut.update;
        GUPnPDIDLLiteParser *parser = NULL;
        gchar *result = NULL;
+       const gchar *message;
+       gboolean end;
 
        DLEYNA_LOG_DEBUG("Enter");
 
-       if (!gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
-                                           &upnp_error,
-                                           "Result", G_TYPE_STRING,
-                                           &result, NULL)) {
+       end = gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
+                                            &error,
+                                            "Result", G_TYPE_STRING, &result,
+                                            NULL);
+
+       if (!end || (result == NULL)) {
+               message = (error != NULL) ? error->message : "Invalid result";
                DLEYNA_LOG_WARNING("Browse Object operation failed: %s",
-                                  upnp_error->message);
+                                  message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
                                             "Browse operation failed: %s",
-                                            upnp_error->message);
+                                            message);
                goto on_error;
        }
 
@@ -3849,8 +4001,8 @@ static void prv_update_object_browse_cb(GUPnPServiceProxy *proxy,
                         G_CALLBACK(prv_get_xml_fragments),
                         cb_data);
 
-       if (!gupnp_didl_lite_parser_parse_didl(parser, result, &upnp_error)) {
-               if (upnp_error->code == GUPNP_XML_ERROR_EMPTY_NODE) {
+       if (!gupnp_didl_lite_parser_parse_didl(parser, result, &error)) {
+               if (error->code == GUPNP_XML_ERROR_EMPTY_NODE) {
                        DLEYNA_LOG_WARNING("Property not defined for object");
 
                        cb_data->error =
@@ -3860,13 +4012,13 @@ static void prv_update_object_browse_cb(GUPnPServiceProxy *proxy,
                } else {
                        DLEYNA_LOG_WARNING(
                                        "Unable to parse results of browse: %s",
-                                       upnp_error->message);
+                                       error->message);
 
                        cb_data->error =
                                g_error_new(DLEYNA_SERVER_ERROR,
                                            DLEYNA_ERROR_OPERATION_FAILED,
                                            "Unable to parse results of browse: %s",
-                                           upnp_error->message);
+                                           error->message);
                }
 
                goto on_error;
@@ -3895,8 +4047,8 @@ no_complete:
 
        g_free(result);
 
-       if (upnp_error)
-               g_error_free(upnp_error);
+       if (error)
+               g_error_free(error);
 
        DLEYNA_LOG_DEBUG("Exit");
 }
@@ -3935,414 +4087,318 @@ void dls_device_update_object(dls_client_t *client,
        DLEYNA_LOG_DEBUG("Exit");
 }
 
-static void prv_didls_free(gpointer data)
+static void prv_get_object_metadata_cb(GUPnPServiceProxy *proxy,
+                                      GUPnPServiceProxyAction *action,
+                                      gpointer user_data)
 {
-       prv_new_playlist_ct_t *priv_t = (prv_new_playlist_ct_t *)data;
+       GError *error = NULL;
+       dls_async_task_t *cb_data = user_data;
+       gchar *result = NULL;
+       const gchar *message;
+       gboolean end;
 
-       if (priv_t) {
-               g_free(priv_t->id);
-               g_free(priv_t->parent_id);
-               g_free(priv_t);
-       }
-}
+       DLEYNA_LOG_DEBUG("Enter");
 
-static void prv_playlist_upload_cb(GUPnPServiceProxy *proxy,
-                                  GUPnPServiceProxyAction *action,
-                                  gpointer user_data)
-{
-       dls_async_task_t *cb_data = user_data;
-       gchar *didls;
+       end = gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
+                                            &error,
+                                            "Result", G_TYPE_STRING, &result,
+                                            NULL);
 
-       didls = gupnp_media_collection_get_string(
-                                       cb_data->ut.playlist.collection);
+       if (!end || (result == NULL)) {
+               message = (error != NULL) ? error->message : "Invalid result";
+               DLEYNA_LOG_WARNING("Browse Object operation failed: %s",
+                                  message);
 
-       DLEYNA_LOG_DEBUG_NL();
-       DLEYNA_LOG_DEBUG("Collection: %s", didls);
-       DLEYNA_LOG_DEBUG_NL();
+               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                            DLEYNA_ERROR_OPERATION_FAILED,
+                                            "Browse operation failed: %s",
+                                            message);
+               goto on_complete;
+       }
 
-       prv_generic_upload_cb(cb_data, NULL, didls, strlen(didls), "text/xml");
-}
+       cb_data->task.result = g_variant_ref_sink(g_variant_new_string(result));
 
-static void prv_create_didls_item_parse_object(GUPnPDIDLLiteParser *parser,
-                                              GUPnPDIDLLiteObject *object,
-                                              gpointer user_data)
-{
-       const char *class;
-       const char *title;
-       const char *artist;
-       const char *album;
-       const char *uri = NULL;
-       GList *resources;
-       GUPnPDIDLLiteObject *item_obj;
-       GUPnPDIDLLiteItem *item;
-       GUPnPDIDLLiteResource *res;
-       GUPnPMediaCollection *collection = user_data;
+       DLEYNA_LOG_DEBUG("prv_get_object_metadata_cb result: %s", result);
 
-       if (GUPNP_IS_DIDL_LITE_CONTAINER(object))
-               goto exit;
+       g_free(result);
 
-       class = gupnp_didl_lite_object_get_upnp_class(object);
-       title = gupnp_didl_lite_object_get_title(object);
-       artist = gupnp_didl_lite_object_get_artist(object);
-       album = gupnp_didl_lite_object_get_album(object);
-       resources = gupnp_didl_lite_object_get_resources(object);
+on_complete:
 
-       if (resources != NULL) {
-               if (resources->data != NULL)
-                       uri = gupnp_didl_lite_resource_get_uri(resources->data);
+       (void) g_idle_add(dls_async_task_complete, cb_data);
+       g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id);
 
-               g_list_free_full(resources, g_object_unref);
-       }
+       if (error)
+               g_error_free(error);
 
-       DLEYNA_LOG_DEBUG("Create DIDL_S Item");
-       DLEYNA_LOG_DEBUG("title: %s", title);
-       DLEYNA_LOG_DEBUG("class: %s", class);
-       DLEYNA_LOG_DEBUG("Artist: %s", artist);
-       DLEYNA_LOG_DEBUG("album: %s", album);
-       DLEYNA_LOG_DEBUG("URI: %s", uri);
-       DLEYNA_LOG_DEBUG_NL();
+       DLEYNA_LOG_DEBUG("Exit");
+}
 
-       item = gupnp_media_collection_add_item(collection);
-       item_obj = GUPNP_DIDL_LITE_OBJECT(item);
+void dls_device_get_object_metadata(dls_client_t *client,
+                                   dls_task_t *task,
+                                   const gchar *upnp_filter)
+{
+       dls_async_task_t *cb_data = (dls_async_task_t *)task;
+       dls_device_context_t *context;
 
-       if (title  && *title)
-               gupnp_didl_lite_object_set_title(item_obj, title);
+       DLEYNA_LOG_DEBUG("Enter");
 
-       if (class && *class)
-               gupnp_didl_lite_object_set_upnp_class(item_obj, class);
+       context = dls_device_get_context(task->target.device, client);
 
-       if (artist && *artist)
-               gupnp_didl_lite_object_set_artist(item_obj, artist);
+       cb_data->action = gupnp_service_proxy_begin_action(
+                               context->service_proxy, "Browse",
+                               prv_get_object_metadata_cb, cb_data,
+                               "ObjectID", G_TYPE_STRING, task->target.id,
+                               "BrowseFlag", G_TYPE_STRING, "BrowseMetadata",
+                               "Filter", G_TYPE_STRING, "*",
+                               "StartingIndex", G_TYPE_INT, 0,
+                               "RequestedCount", G_TYPE_INT, 0,
+                               "SortCriteria", G_TYPE_STRING, "",
+                               NULL);
 
-       if (album && *album)
-               gupnp_didl_lite_object_set_album(item_obj, album);
+       cb_data->proxy = context->service_proxy;
 
-       if (uri && *uri) {
-               res = gupnp_didl_lite_object_add_resource(item_obj);
-               gupnp_didl_lite_resource_set_uri(res, uri);
-               g_object_unref(res);
-       }
+       g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
+                                 (gpointer *)&cb_data->proxy);
 
-       g_object_unref(item);
+       cb_data->cancel_id = g_cancellable_connect(cb_data->cancellable,
+                                       G_CALLBACK(dls_async_task_cancelled_cb),
+                                       cb_data, NULL);
 
-exit:
-       return;
+       DLEYNA_LOG_DEBUG("Exit");
 }
 
-static void prv_create_didls_item_browse_cb(GUPnPServiceProxy *proxy,
-                                           GUPnPServiceProxyAction *action,
-                                           gpointer user_data)
+static void prv_create_reference_cb(GUPnPServiceProxy *proxy,
+                                   GUPnPServiceProxyAction *action,
+                                   gpointer user_data)
 {
        GError *error = NULL;
-       prv_new_playlist_ct_t *priv_t = user_data;
-       dls_async_task_t *cb_data = priv_t->cb_data;
-       GUPnPDIDLLiteParser *parser = NULL;
-       gchar *result = NULL;
+       dls_async_task_t *cb_data = user_data;
+       const gchar *message;
+       gchar *object_id = NULL;
+       gchar *object_path;
+       gboolean end;
 
-       if (!gupnp_service_proxy_end_action(proxy, action, &error,
-                                           "Result", G_TYPE_STRING,
-                                           &result, NULL)) {
-               DLEYNA_LOG_WARNING("Browse Object operation failed: %s",
-                                  error->message);
-               DLEYNA_LOG_DEBUG_NL();
+       DLEYNA_LOG_DEBUG("Enter");
+
+       end = gupnp_service_proxy_end_action(cb_data->proxy, cb_data->action,
+                                           &error,
+                                           "NewID", G_TYPE_STRING, &object_id,
+                                           NULL);
+       if (!end || (object_id == NULL)) {
+               message = (error != NULL) ? error->message : "Invalid result";
+               DLEYNA_LOG_WARNING("CreateReference operation failed: %s",
+                                  message);
 
                cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
                                             DLEYNA_ERROR_OPERATION_FAILED,
-                                            "Browse operation failed: %s",
-                                            error->message);
-               goto on_exit;
-       }
-
-       DLEYNA_LOG_DEBUG_NL();
-       DLEYNA_LOG_DEBUG("Result: %s", result);
-       DLEYNA_LOG_DEBUG_NL();
-
-       parser = gupnp_didl_lite_parser_new();
-
-       g_signal_connect(parser, "object-available",
-                        G_CALLBACK(prv_create_didls_item_parse_object),
-                        cb_data->ut.playlist.collection);
+                                            "Update Object operation "
+                                            " failed: %s",
+                                            message);
 
-       if (gupnp_didl_lite_parser_parse_didl(parser, result, &error))
-               goto on_exit;
+               goto on_error;
+       }
 
-       if (error->code == GUPNP_XML_ERROR_EMPTY_NODE) {
-               DLEYNA_LOG_WARNING("Property not defined for object");
+       object_path = dls_path_from_id(cb_data->task.target.root_path,
+                                      object_id);
 
-               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
-                                            DLEYNA_ERROR_UNKNOWN_PROPERTY,
-                                            "Property not defined for object");
-       } else {
-               DLEYNA_LOG_WARNING("Unable to parse results of browse: %s",
-                                  error->message);
+       DLEYNA_LOG_DEBUG("Result @id: %s - Path: %s", object_id, object_path);
 
-               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
-                                            DLEYNA_ERROR_OPERATION_FAILED,
-                                            "Unable to parse results of browse: %s",
-                                            error->message);
-       }
+       cb_data->task.result = g_variant_ref_sink(g_variant_new_object_path(
+                                                               object_path));
+       g_free(object_path);
 
-on_exit:
+on_error:
 
-       if (cb_data->error != NULL)
-               dleyna_task_processor_cancel_queue(
-                                               cb_data->ut.playlist.queue_id);
+       (void) g_idle_add(dls_async_task_complete, cb_data);
+       g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id);
 
-       if (parser)
-               g_object_unref(parser);
+       g_free(object_id);
 
-       if (error)
+       if (error != NULL)
                g_error_free(error);
 
-       g_free(result);
+       DLEYNA_LOG_DEBUG("Exit");
 }
 
-static GUPnPServiceProxyAction *prv_create_didls_item_browse(
-                                       dleyna_service_task_t *task,
-                                       GUPnPServiceProxy *proxy,
-                                       gboolean *failed)
+void dls_device_create_reference(dls_client_t *client,
+                                dls_task_t *task)
 {
-       prv_new_playlist_ct_t *priv_t;
+       dls_async_task_t *cb_data = (dls_async_task_t *)task;
+       dls_device_context_t *context;
+       gchar *i_root = NULL;
+       gchar *i_id = NULL;
+       gchar *path = cb_data->task.ut.create_reference.item_path;
 
-       priv_t = (prv_new_playlist_ct_t *)dleyna_service_task_get_user_data(
-                                                                       task);
-       *failed = FALSE;
+       DLEYNA_LOG_DEBUG("Enter");
+       DLEYNA_LOG_DEBUG("Create Reference for path: %s", path);
 
-       DLEYNA_LOG_DEBUG("Browse for ID: %s", priv_t->id);
+       if (!dls_path_get_path_and_id(path, &i_root, &i_id, NULL)) {
+               DLEYNA_LOG_DEBUG("Can't get id for path %s", path);
+               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                            DLEYNA_ERROR_OBJECT_NOT_FOUND,
+                                            "Unable to find object for path: %s",
+                                            path);
+               goto on_error;
+       }
 
-       return gupnp_service_proxy_begin_action(
-                       proxy, "Browse",
-                       dleyna_service_task_begin_action_cb, task,
-                       "ObjectID", G_TYPE_STRING, priv_t->id,
-                       "BrowseFlag", G_TYPE_STRING, "BrowseMetadata",
-                       "Filter", G_TYPE_STRING, "upnp:artist,upnp:album,res",
-                       "StartingIndex", G_TYPE_INT, 0,
-                       "RequestedCount", G_TYPE_INT, 1,
-                       "SortCriteria", G_TYPE_STRING, "", NULL);
-}
+       DLEYNA_LOG_DEBUG("Create Reference for @id: %s", i_id);
+       DLEYNA_LOG_DEBUG("        In Container @id: %s", task->target.id);
 
-static gboolean prv_create_chain_didls_items(dls_task_t *task,
-                                            GUPnPServiceProxy *proxy,
-                                            dls_async_task_t *cb_data)
-{
-       gchar *root_path = NULL;
-       gchar *path;
-       gchar *id = NULL;
-       prv_new_playlist_ct_t *priv_t;
-       dls_async_playlist_t *a_playlist = &cb_data->ut.playlist;
-       GVariantIter iter;
+       context = dls_device_get_context(task->target.device, client);
 
-       DLEYNA_LOG_DEBUG_NL();
+       cb_data->action = gupnp_service_proxy_begin_action(
+                               context->service_proxy, "CreateReference",
+                               prv_create_reference_cb, cb_data,
+                               "ContainerID", G_TYPE_STRING, task->target.id,
+                               "ObjectID", G_TYPE_STRING, i_id,
+                               NULL);
 
-       a_playlist->collection = gupnp_media_collection_new();
-       gupnp_media_collection_set_title(a_playlist->collection,
-                                        task->ut.playlist.title);
-       gupnp_media_collection_set_author(a_playlist->collection,
-                                         task->ut.playlist.creator);
-
-       g_variant_iter_init(&iter, task->ut.playlist.item_path);
-
-       while (g_variant_iter_next(&iter, "&o", &path)) {
-               if (!dls_path_get_path_and_id(path, &root_path, &id, NULL)) {
-                       DLEYNA_LOG_DEBUG("Can't get id for path %s", path);
-                       cb_data->error = g_error_new(
-                                               DLEYNA_SERVER_ERROR,
-                                               DLEYNA_ERROR_OBJECT_NOT_FOUND,
-                                               "Unable to find object for path: %s",
-                                               path);
-                       goto on_error;
-               }
+       cb_data->proxy = context->service_proxy;
 
-               DLEYNA_LOG_DEBUG("Create Task: @id: %s - Root: %s",
-                                id, root_path);
+       g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
+                                 (gpointer *)&cb_data->proxy);
 
-               g_free(root_path);
+       cb_data->cancel_id = g_cancellable_connect(
+                                       cb_data->cancellable,
+                                       G_CALLBACK(dls_async_task_cancelled_cb),
+                                       cb_data, NULL);
 
-               priv_t = g_new0(prv_new_playlist_ct_t, 1);
-               priv_t->cb_data = cb_data;
-               priv_t->id = id;
+on_error:
 
-               dleyna_service_task_add(a_playlist->queue_id,
-                                       prv_create_didls_item_browse,
-                                       proxy,
-                                       prv_create_didls_item_browse_cb,
-                                       prv_didls_free, priv_t);
-       }
+       g_free(i_root);
+       g_free(i_id);
 
-       DLEYNA_LOG_DEBUG_NL();
-       return TRUE;
+       DLEYNA_LOG_DEBUG("Exit");
+}
 
-on_error:
+static void prv_build_icon_result(dls_device_t *device, dls_task_t *task)
+{
+       GVariant *out_p[2];
 
-       return FALSE;
+       out_p[0] = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
+                                            device->icon.bytes,
+                                            device->icon.size,
+                                            1);
+       out_p[1] = g_variant_new_string(device->icon.mime_type);
+       task->result = g_variant_ref_sink(g_variant_new_tuple(out_p, 2));
 }
 
-static void prv_create_playlist_object(dls_task_create_playlist_t *t_playlist,
-                                      dls_async_playlist_t *a_playlist,
-                                      char *parent_id)
+static void prv_get_icon_cancelled(GCancellable *cancellable,
+                                  gpointer user_data)
 {
-       GUPnPDIDLLiteWriter *writer;
-       GUPnPDIDLLiteObject *item;
-       GUPnPProtocolInfo *protocol_info;
-       GUPnPDIDLLiteResource *res;
-       GUPnPDIDLLiteContributor *creator;
-       GUPnPDIDLLiteContributor *author;
-       GTimeVal time_v;
-       gchar *time_c;
+       dls_device_download_t *download = (dls_device_download_t *)user_data;
 
-       writer = gupnp_didl_lite_writer_new(NULL);
-       item = GUPNP_DIDL_LITE_OBJECT(gupnp_didl_lite_writer_add_item(writer));
+       dls_async_task_cancelled_cb(cancellable, download->task);
 
-       gupnp_didl_lite_object_set_id(item, "");
-       gupnp_didl_lite_object_set_title(item, t_playlist->title);
-       gupnp_didl_lite_object_set_genre(item, t_playlist->genre);
-       gupnp_didl_lite_object_set_description(item, t_playlist->desc);
+       if (download->msg) {
+               soup_session_cancel_message(download->session, download->msg,
+                                           SOUP_STATUS_CANCELLED);
+               DLEYNA_LOG_DEBUG("Cancelling device icon download");
+       }
+}
 
-       creator = gupnp_didl_lite_object_add_creator(item);
-       author = gupnp_didl_lite_object_add_author(item);
-       gupnp_didl_lite_contributor_set_name(creator, t_playlist->creator);
-       gupnp_didl_lite_contributor_set_name(author, t_playlist->creator);
+static void prv_free_download_info(dls_device_download_t *download)
+{
+       if (download->msg)
+               g_object_unref(download->msg);
+       g_object_unref(download->session);
+       g_free(download);
+}
 
-       gupnp_didl_lite_object_set_parent_id(item, parent_id);
-       gupnp_didl_lite_object_set_upnp_class(item, "object.item.playlistItem");
-       gupnp_didl_lite_object_set_restricted(item, FALSE);
+static void prv_get_icon_session_cb(SoupSession *session,
+                                   SoupMessage *msg,
+                                   gpointer user_data)
+{
+       dls_device_download_t *download = (dls_device_download_t *)user_data;
+       dls_async_task_t *cb_data = (dls_async_task_t *)download->task;
+       dls_device_t *device = (dls_device_t *)cb_data->task.target.device;
 
-       protocol_info = gupnp_protocol_info_new();
-       gupnp_protocol_info_set_mime_type(protocol_info, "text/xml");
-       gupnp_protocol_info_set_protocol(protocol_info, "*");
-       gupnp_protocol_info_set_network(protocol_info, "*");
-       gupnp_protocol_info_set_dlna_profile(protocol_info, "DIDL_S");
+       if (msg->status_code == SOUP_STATUS_CANCELLED)
+               goto out;
 
-       res = gupnp_didl_lite_object_add_resource(item);
-       gupnp_didl_lite_resource_set_protocol_info(res, protocol_info);
+       if (SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) {
+               device->icon.size = msg->response_body->length;
+               device->icon.bytes = g_malloc(device->icon.size);
+               memcpy(device->icon.bytes, msg->response_body->data,
+                      device->icon.size);
 
-       g_get_current_time(&time_v);
-       time_c = g_time_val_to_iso8601(&time_v);
-       gupnp_didl_lite_object_set_date(item, time_c);
+               prv_build_icon_result(device, &cb_data->task);
+       } else {
+               DLEYNA_LOG_DEBUG("Failed to GET device icon: %s",
+                                msg->reason_phrase);
 
-       /* TODO: Need to compute DLNA Profile */
+               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                            DLEYNA_ERROR_OPERATION_FAILED,
+                                            "Failed to GET device icon");
+       }
 
-       a_playlist->didl = gupnp_didl_lite_writer_get_string(writer);
+       (void) g_idle_add(dls_async_task_complete, cb_data);
+       g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id);
 
-       DLEYNA_LOG_DEBUG("Playlist object %s created", t_playlist->title);
+out:
 
-       g_object_unref(res);
-       g_object_unref(protocol_info);
-       g_object_unref(creator);
-       g_object_unref(author);
-       g_object_unref(item);
-       g_object_unref(writer);
-       g_free(time_c);
+       prv_free_download_info(download);
 }
 
-static void prv_create_didls_chain_end(gboolean cancelled, gpointer data)
+void dls_device_get_icon(dls_client_t *client,
+                        dls_task_t *task)
 {
-       prv_new_playlist_ct_t *priv_t = data;
-       dls_async_task_t *cb_data = priv_t->cb_data;
-       dls_async_playlist_t *a_playlist;
-       dls_task_create_playlist_t *t_playlist;
-
-       DLEYNA_LOG_DEBUG("Enter");
+       GUPnPDeviceInfo *info;
+       dls_device_context_t *context;
+       dls_async_task_t *cb_data = (dls_async_task_t *)task;
+       dls_device_t *device = task->target.device;
+       gchar *url;
+       dls_device_download_t *download;
 
-       if (cb_data->cancel_id) {
-               if (!g_cancellable_is_cancelled(cb_data->cancellable))
-                       g_cancellable_disconnect(cb_data->cancellable,
-                                                cb_data->cancel_id);
-               cb_data->cancel_id = 0;
+       if (device->icon.size != 0) {
+               prv_build_icon_result(device, task);
+               goto end;
        }
 
-       if (cancelled)
-               goto on_clear;
-
-       t_playlist = &cb_data->task.ut.playlist;
-       a_playlist = &cb_data->ut.playlist;
-       prv_create_playlist_object(t_playlist, a_playlist, priv_t->parent_id);
-
-       DLEYNA_LOG_DEBUG("Creating object");
-       cb_data->action = gupnp_service_proxy_begin_action(
-                               cb_data->proxy,
-                               "CreateObject",
-                               prv_playlist_upload_cb, cb_data,
-                               "ContainerID", G_TYPE_STRING, priv_t->parent_id,
-                               "Elements", G_TYPE_STRING, a_playlist->didl,
-                               NULL);
-
-       cb_data->cancel_id = g_cancellable_connect(
-                                       cb_data->cancellable,
-                                       G_CALLBACK(dls_async_task_cancelled_cb),
-                                       cb_data, NULL);
-on_clear:
+       context = dls_device_get_context(device, client);
+       info = (GUPnPDeviceInfo *)context->device_proxy;
 
-       if (cancelled) {
-               if (!cb_data->error)
-                       cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
-                                                    DLEYNA_ERROR_CANCELLED,
-                                                    "Operation cancelled.");
-               (void) g_idle_add(dls_async_task_complete, cb_data);
+       url = gupnp_device_info_get_icon_url(info, NULL, -1, -1, -1, FALSE,
+                                            &device->icon.mime_type, NULL,
+                                            NULL, NULL);
+       if (url == NULL) {
+               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                            DLEYNA_ERROR_NOT_SUPPORTED,
+                                            "No icon available");
+               goto end;
        }
 
-       prv_didls_free(priv_t);
+       download = g_new0(dls_device_download_t, 1);
+       download->session = soup_session_async_new();
+       download->msg = soup_message_new(SOUP_METHOD_GET, url);
+       download->task = cb_data;
 
-       cb_data->ut.playlist.queue_id = NULL;
+       if (!download->msg) {
+               DLEYNA_LOG_WARNING("Invalid URL %s", url);
 
-       DLEYNA_LOG_DEBUG("Exit");
-}
-
-static void prv_create_chain_cancelled(GCancellable *cancellable,
-                                      gpointer user_data)
-{
-       dls_async_task_t *cb_data = user_data;
-       const dleyna_task_queue_key_t *queue_id = cb_data->ut.playlist.queue_id;
-
-       DLEYNA_LOG_DEBUG("Enter");
-
-       dleyna_task_processor_cancel_queue(queue_id);
-}
+               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
+                                            DLEYNA_ERROR_BAD_RESULT,
+                                            "Invalid URL %s", url);
+               prv_free_download_info(download);
+               g_free(url);
 
-void dls_device_playlist_upload(dls_client_t *client,
-                               dls_task_t *task,
-                               const gchar *parent_id)
-{
-       dls_async_task_t *cb_data = (dls_async_task_t *)task;
-       dls_device_context_t *context;
-       prv_new_playlist_ct_t *priv_t;
-       const dleyna_task_queue_key_t *queue_id;
+               goto end;
+       }
 
-       DLEYNA_LOG_DEBUG("Enter");
-       DLEYNA_LOG_DEBUG("Uploading playlist to %s", parent_id);
-
-       priv_t = g_new0(prv_new_playlist_ct_t, 1);
-       priv_t->cb_data = cb_data;
-       priv_t->parent_id = g_strdup(parent_id);
-
-       queue_id = dleyna_task_processor_add_queue(
-                       dls_server_get_task_processor(),
-                       dleyna_service_task_create_source(),
-                       DLS_SERVER_SINK,
-                       DLEYNA_TASK_QUEUE_FLAG_AUTO_REMOVE,
-                       dleyna_service_task_process_cb,
-                       dleyna_service_task_cancel_cb,
-                       dleyna_service_task_delete_cb);
-       dleyna_task_queue_set_finally(queue_id, prv_create_didls_chain_end);
-       dleyna_task_queue_set_user_data(queue_id, priv_t);
+       cb_data->cancel_id =
+               g_cancellable_connect(cb_data->cancellable,
+                                     G_CALLBACK(prv_get_icon_cancelled),
+                                     download, NULL);
 
-       context = dls_device_get_context(task->target.device, client);
+       g_object_ref(download->msg);
+       soup_session_queue_message(download->session, download->msg,
+                                  prv_get_icon_session_cb, download);
 
-       cb_data->proxy = context->service_proxy;
-       cb_data->ut.playlist.queue_id = queue_id;
+       g_free(url);
 
-       g_object_add_weak_pointer((G_OBJECT(context->service_proxy)),
-                                 (gpointer *)&cb_data->proxy);
+       return;
 
-       if (prv_create_chain_didls_items(task, cb_data->proxy, cb_data)) {
-               cb_data->cancel_id = g_cancellable_connect(
-                                       cb_data->cancellable,
-                                       G_CALLBACK(prv_create_chain_cancelled),
-                                       cb_data, NULL);
-               dleyna_task_queue_start(queue_id);
-       } else {
-               (void) g_idle_add(dls_async_task_complete, cb_data);
-       }
+end:
 
-       DLEYNA_LOG_DEBUG("Exit");
+       (void) g_idle_add(dls_async_task_complete, cb_data);
 }
index ef3e3df..30788db 100644 (file)
@@ -41,6 +41,13 @@ struct dls_device_context_t_ {
        guint timeout_id;
 };
 
+typedef struct dls_device_icon_t_ dls_device_icon_t;
+struct dls_device_icon_t_ {
+       gchar *mime_type;
+       guchar *bytes;
+       gsize size;
+};
+
 struct dls_device_t_ {
        dleyna_connector_id_t connection;
        guint id;
@@ -56,6 +63,8 @@ struct dls_device_t_ {
        GVariant *sort_ext_caps;
        GVariant *feature_list;
        gboolean shutting_down;
+       guint construct_step;
+       dls_device_icon_t icon;
 };
 
 dls_device_context_t *dls_device_append_new_context(dls_device_t *device,
@@ -65,6 +74,14 @@ void dls_device_delete(void *device);
 
 void dls_device_unsubscribe(void *device);
 
+void dls_device_construct(
+                       dls_device_t *dev,
+                       dls_device_context_t *context,
+                       dleyna_connector_id_t connection,
+                       const dleyna_connector_dispatch_cb_t *dispatch_table,
+                       GHashTable *property_map,
+                       const dleyna_task_queue_key_t *queue_id);
+
 dls_device_t *dls_device_new(
                        dleyna_connector_id_t connection,
                        GUPnPDeviceProxy *proxy,
@@ -122,8 +139,14 @@ void dls_device_update_object(dls_client_t *client,
                              dls_task_t *task,
                              const gchar *upnp_filter);
 
-void dls_device_playlist_upload(dls_client_t *client,
-                               dls_task_t *task,
-                               const gchar *parent_id);
+void dls_device_get_object_metadata(dls_client_t *client,
+                                   dls_task_t *task,
+                                   const gchar *parent_id);
+
+void dls_device_create_reference(dls_client_t *client,
+                                dls_task_t *task);
+
+void dls_device_get_icon(dls_client_t *client,
+                        dls_task_t *task);
 
 #endif /* DLS_DEVICE_H__ */
index 2e0e882..1a2fe6d 100644 (file)
@@ -34,4 +34,4 @@ log-type=0
 # IMPORTANT: This log level is a subset of the log level defined at compile time
 # You can't enable levels disabled at compile time
 # level=8 means all level flags defined at compile time.
-log-level=8
+log-level=7
index fb2695e..14a214b 100644 (file)
@@ -89,6 +89,9 @@ enum dls_interface_type_ {
 /* Resources Properties */
 #define DLS_INTERFACE_PROP_MIME_TYPE "MIMEType"
 #define DLS_INTERFACE_PROP_DLNA_PROFILE "DLNAProfile"
+#define DLS_INTERFACE_PROP_DLNA_CONVERSION "DLNAConversion"
+#define DLS_INTERFACE_PROP_DLNA_OPERATION "DLNAOperation"
+#define DLS_INTERFACE_PROP_DLNA_FLAGS "DLNAFlags"
 #define DLS_INTERFACE_PROP_SIZE "Size"
 #define DLS_INTERFACE_PROP_DURATION "Duration"
 #define DLS_INTERFACE_PROP_BITRATE "Bitrate"
@@ -106,6 +109,7 @@ enum dls_interface_type_ {
 
 #define DLS_INTERFACE_GET_VERSION "GetVersion"
 #define DLS_INTERFACE_GET_SERVERS "GetServers"
+#define DLS_INTERFACE_RESCAN "Rescan"
 #define DLS_INTERFACE_RELEASE "Release"
 #define DLS_INTERFACE_SET_PROTOCOL_INFO "SetProtocolInfo"
 #define DLS_INTERFACE_PREFER_LOCAL_ADDRESSES "PreferLocalAddresses"
@@ -178,14 +182,16 @@ enum dls_interface_type_ {
 #define DLS_INTERFACE_TO_ADD_UPDATE "ToAddUpdate"
 #define DLS_INTERFACE_TO_DELETE "ToDelete"
 #define DLS_INTERFACE_CANCEL "Cancel"
+#define DLS_INTERFACE_GET_ICON "GetIcon"
+#define DLS_INTERFACE_RESOLUTION "Resolution"
+#define DLS_INTERFACE_ICON_BYTES "Bytes"
+#define DLS_INTERFACE_MIME_TYPE "MimeType"
+#define DLS_INTERFACE_REQ_MIME_TYPE "RequestedMimeType"
 
-#define DLS_INTERFACE_CREATE_PLAYLIST "CreatePlaylist"
-#define DLS_INTERFACE_CREATE_PLAYLIST_TO_ANY "CreatePlaylistInAnyContainer"
-#define DLS_INTERFACE_TITLE "Title"
-#define DLS_INTERFACE_CREATOR "Creator"
-#define DLS_INTERFACE_GENRE "Genre"
-#define DLS_INTERFACE_DESCRIPTION "Description"
-#define DLS_INTERFACE_PLAYLIST_ITEMS "PlaylistItems"
+#define DLS_INTERFACE_GET_METADATA "GetMetaData"
+#define DLS_INTERFACE_METADATA "MetaData"
 
+#define DLS_INTERFACE_CREATE_REFERENCE "CreateReference"
+#define DLS_INTERFACE_REFPATH "RefPath"
 
 #endif /* DLEYNA_SERVER_INTERFACE_H__ */
index 2dbd63b..ad36174 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <string.h>
 #include <libgupnp-av/gupnp-didl-lite-contributor.h>
+#include <libgupnp-av/gupnp-dlna.h>
+#include <libgupnp-av/gupnp-protocol-info.h>
 
 #include <libdleyna/core/log.h>
 
@@ -34,6 +36,8 @@ static const gchar gUPnPContainer[] = "object.container";
 static const gchar gUPnPAlbum[] = "object.container.album";
 static const gchar gUPnPPerson[] = "object.container.person";
 static const gchar gUPnPGenre[] = "object.container.genre";
+static const gchar gUPnPPlaylist[] = "object.container.playlistContainer";
+static const gchar gUPnPStorage[] = "object.container.storageFolder";
 static const gchar gUPnPAudioItem[] = "object.item.audioItem";
 static const gchar gUPnPVideoItem[] = "object.item.videoItem";
 static const gchar gUPnPImageItem[] = "object.item.imageItem";
@@ -48,6 +52,10 @@ static const unsigned int gUPnPPersonLen =
        (sizeof(gUPnPPerson) / sizeof(gchar)) - 1;
 static const unsigned int gUPnPGenreLen =
        (sizeof(gUPnPGenre) / sizeof(gchar)) - 1;
+static const unsigned int gUPnPPlaylistLen =
+       (sizeof(gUPnPPlaylist) / sizeof(gchar)) - 1;
+static const unsigned int gUPnPStorageLen =
+       (sizeof(gUPnPStorage) / sizeof(gchar)) - 1;
 static const unsigned int gUPnPAudioItemLen =
        (sizeof(gUPnPAudioItem) / sizeof(gchar)) - 1;
 static const unsigned int gUPnPVideoItemLen =
@@ -86,22 +94,66 @@ static const gchar gMediaSpec2GenreMovie[] = "genre.movie";
 static const gchar gMediaSpec2GenreMusic[] = "genre.music";
 static const gchar gMediaSpec2AudioMusic[] = "audio.music";
 static const gchar gMediaSpec2AudioBroadcast[] = "audio.broadcast";
-static const gchar gMediaSpec2AudioBook[] = "audio.book";
 static const gchar gMediaSpec2Audio[] = "audio";
+static const gchar gMediaSpec2AudioBook[] = "audio.book";
+static const gchar gMediaSpec2Video[] = "video";
 static const gchar gMediaSpec2VideoMovie[] = "video.movie";
 static const gchar gMediaSpec2VideoMusicClip[] = "video.musicclip";
 static const gchar gMediaSpec2VideoBroadcast[] = "video.broadcast";
-static const gchar gMediaSpec2Video[] = "video";
-static const gchar gMediaSpec2ImagePhoto[] = "image.photo";
 static const gchar gMediaSpec2Image[] = "image";
+static const gchar gMediaSpec2ImagePhoto[] = "image.photo";
 static const gchar gMediaSpec2Playlist[] = "playlist";
+static const gchar gMediaSpec2PlaylistItem[] = "item.playlist";
 static const gchar gMediaSpec2Item[] = "item";
+static const gchar gMediaSpec2Storage[] = "storage";
+
+typedef struct dls_prop_dlna_t_ dls_prop_dlna_t;
+struct dls_prop_dlna_t_ {
+       guint dlna_flag;
+       const gchar *prop_name;
+};
+
+static const dls_prop_dlna_t g_prop_dlna_ci[] = {
+{GUPNP_DLNA_CONVERSION_TRANSCODED,             "Transcoded"},
+{0,                                            NULL}
+};
+
+static const dls_prop_dlna_t g_prop_dlna_op[] = {
+{GUPNP_DLNA_OPERATION_RANGE,                   "RangeSeek"},
+{GUPNP_DLNA_OPERATION_TIMESEEK,                        "TimeSeek"},
+{0,                                            NULL}
+};
+
+static const dls_prop_dlna_t g_prop_dlna_flags[] = {
+{GUPNP_DLNA_FLAGS_SENDER_PACED,                        "SenderPaced"},
+{GUPNP_DLNA_FLAGS_TIME_BASED_SEEK,             "TimeBased"},
+{GUPNP_DLNA_FLAGS_BYTE_BASED_SEEK,             "ByteBased"},
+{GUPNP_DLNA_FLAGS_PLAY_CONTAINER,              "PlayContainer"},
+{GUPNP_DLNA_FLAGS_S0_INCREASE,                 "S0Increase"},
+{GUPNP_DLNA_FLAGS_SN_INCREASE,                 "SNIncrease"},
+{GUPNP_DLNA_FLAGS_RTSP_PAUSE,                  "RTSPPause"},
+{GUPNP_DLNA_FLAGS_STREAMING_TRANSFER_MODE,     "StreamingTM"},
+{GUPNP_DLNA_FLAGS_INTERACTIVE_TRANSFER_MODE,   "InteractiveTM"},
+{GUPNP_DLNA_FLAGS_BACKGROUND_TRANSFER_MODE,    "BackgroundTM"},
+{GUPNP_DLNA_FLAGS_CONNECTION_STALL,            "ConnectionStall"},
+{GUPNP_DLNA_FLAGS_DLNA_V15,                    "DLNA_V15"},
+{0,                                            NULL}
+};
+
+static const dls_prop_dlna_t g_prop_dlna_ocm[] = {
+{GUPNP_OCM_FLAGS_UPLOAD,                       "Upload"},
+{GUPNP_OCM_FLAGS_CREATE_CONTAINER,             "CreateContainer"},
+{GUPNP_OCM_FLAGS_DESTROYABLE,                  "Delete"},
+{GUPNP_OCM_FLAGS_UPLOAD_DESTROYABLE,           "UploadDelete"},
+{GUPNP_OCM_FLAGS_CHANGE_METADATA,              "ChangeMeta"},
+{0,                                            NULL}
+};
 
 static dls_prop_map_t *prv_prop_map_new(const gchar *prop_name,
-                                           dls_upnp_prop_mask type,
-                                           gboolean filter,
-                                           gboolean searchable,
-                                           gboolean updateable)
+                                       dls_upnp_prop_mask type,
+                                       gboolean filter,
+                                       gboolean searchable,
+                                       gboolean updateable)
 {
        dls_prop_map_t *retval = g_new(dls_prop_map_t, 1);
        retval->upnp_prop_name = prop_name;
@@ -252,6 +304,24 @@ void dls_prop_maps_new(GHashTable **property_map, GHashTable **filter_map)
                                       TRUE, FALSE, FALSE);
        g_hash_table_insert(f_map, DLS_INTERFACE_PROP_DLNA_PROFILE, prop_t);
 
+       /* res@protocolInfo - DLNA CONVERSION*/
+       prop_t = prv_prop_map_new("res@protocolInfo",
+                                      DLS_UPNP_MASK_PROP_DLNA_CONVERSION,
+                                      TRUE, FALSE, FALSE);
+       g_hash_table_insert(f_map, DLS_INTERFACE_PROP_DLNA_CONVERSION, prop_t);
+
+               /* res@protocolInfo - DLNA OPERATION*/
+       prop_t = prv_prop_map_new("res@protocolInfo",
+                                      DLS_UPNP_MASK_PROP_DLNA_OPERATION,
+                                      TRUE, FALSE, FALSE);
+       g_hash_table_insert(f_map, DLS_INTERFACE_PROP_DLNA_OPERATION, prop_t);
+
+               /* res@protocolInfo - DLNA FLAGS*/
+       prop_t = prv_prop_map_new("res@protocolInfo",
+                                      DLS_UPNP_MASK_PROP_DLNA_FLAGS,
+                                      TRUE, FALSE, FALSE);
+       g_hash_table_insert(f_map, DLS_INTERFACE_PROP_DLNA_FLAGS, prop_t);
+
        /* res@protocolInfo - MIME TYPES*/
        prop_t = prv_prop_map_new("res@protocolInfo",
                                        DLS_UPNP_MASK_PROP_MIME_TYPE,
@@ -540,7 +610,7 @@ static void prv_add_string_prop(GVariantBuilder *vb, const gchar *key,
 static void prv_add_strv_prop(GVariantBuilder *vb, const gchar *key,
                              const gchar **value, unsigned int len)
 {
-       if (len > 0)
+       if (value && *value && len > 0)
                g_variant_builder_add(vb, "{sv}", key,
                                      g_variant_new_strv(value, len));
 }
@@ -636,6 +706,24 @@ static GVariant *prv_add_list_dlna_prop(GList *list)
        return g_variant_builder_end(&vb);
 }
 
+static GVariant *prv_props_get_dlna_info_dict(guint flags,
+                                             const dls_prop_dlna_t *dfa)
+{
+       GVariantBuilder builder;
+       gboolean set;
+       gint i = 0;
+
+       g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sb}"));
+
+       while (dfa[i].dlna_flag) {
+               set = (flags & dfa[i].dlna_flag) != 0;
+               g_variant_builder_add(&builder, "{sb}", dfa[i].prop_name, set);
+               i++;
+       }
+
+       return g_variant_builder_end(&builder);
+}
+
 static void prv_add_list_artists_str(gpointer data, gpointer user_data)
 {
        GVariantBuilder *vb = (GVariantBuilder *)user_data;
@@ -930,21 +1018,77 @@ static GUPnPDIDLLiteResource *prv_get_matching_resource
        return retval;
 }
 
-static void prv_parse_resources(GVariantBuilder *item_vb,
-                               GUPnPDIDLLiteResource *res,
-                               dls_upnp_prop_mask filter_mask)
+static void prv_parse_common_resources(GVariantBuilder *item_vb,
+                                      GUPnPDIDLLiteResource *res,
+                                      dls_upnp_prop_mask filter_mask)
 {
        GUPnPProtocolInfo *protocol_info;
-       int int_val;
        gint64 int64_val;
-       const char *str_val;
        guint uint_val;
+       const char *str_val;
+       GUPnPDLNAConversion conv;
+       GUPnPDLNAOperation ope;
+       GUPnPDLNAFlags flags;
 
        if (filter_mask & DLS_UPNP_MASK_PROP_SIZE) {
                int64_val = gupnp_didl_lite_resource_get_size64(res);
                prv_add_int64_prop(item_vb, DLS_INTERFACE_PROP_SIZE, int64_val);
        }
 
+       if ((filter_mask & DLS_UPNP_MASK_PROP_UPDATE_COUNT) &&
+           gupnp_didl_lite_resource_update_count_is_set(res)) {
+               uint_val = gupnp_didl_lite_resource_get_update_count(res);
+               prv_add_uint_prop(item_vb, DLS_INTERFACE_PROP_UPDATE_COUNT,
+                                 uint_val);
+       }
+
+       protocol_info = gupnp_didl_lite_resource_get_protocol_info(res);
+
+       if (filter_mask & DLS_UPNP_MASK_PROP_DLNA_PROFILE) {
+               str_val = gupnp_protocol_info_get_dlna_profile(protocol_info);
+               prv_add_string_prop(item_vb, DLS_INTERFACE_PROP_DLNA_PROFILE,
+                                   str_val);
+       }
+
+       if (filter_mask & DLS_UPNP_MASK_PROP_DLNA_CONVERSION) {
+               conv = gupnp_protocol_info_get_dlna_conversion(protocol_info);
+               prv_add_variant_prop(item_vb,
+                                    DLS_INTERFACE_PROP_DLNA_CONVERSION,
+                                    prv_props_get_dlna_info_dict(
+                                               conv, g_prop_dlna_ci));
+       }
+
+       if (filter_mask & DLS_UPNP_MASK_PROP_DLNA_OPERATION) {
+               ope = gupnp_protocol_info_get_dlna_operation(protocol_info);
+               prv_add_variant_prop(item_vb,
+                                    DLS_INTERFACE_PROP_DLNA_OPERATION,
+                                    prv_props_get_dlna_info_dict(
+                                               ope, g_prop_dlna_op));
+       }
+
+       if (filter_mask & DLS_UPNP_MASK_PROP_DLNA_FLAGS) {
+               flags = gupnp_protocol_info_get_dlna_flags(protocol_info);
+               prv_add_variant_prop(item_vb,
+                                    DLS_INTERFACE_PROP_DLNA_FLAGS,
+                                    prv_props_get_dlna_info_dict(
+                                               flags, g_prop_dlna_flags));
+       }
+
+       if (filter_mask & DLS_UPNP_MASK_PROP_MIME_TYPE) {
+               str_val = gupnp_protocol_info_get_mime_type(protocol_info);
+               prv_add_string_prop(item_vb, DLS_INTERFACE_PROP_MIME_TYPE,
+                                   str_val);
+       }
+}
+
+static void prv_parse_all_resources(GVariantBuilder *item_vb,
+                                   GUPnPDIDLLiteResource *res,
+                                   dls_upnp_prop_mask filter_mask)
+{
+       int int_val;
+
+       prv_parse_common_resources(item_vb, res, filter_mask);
+
        if (filter_mask & DLS_UPNP_MASK_PROP_BITRATE) {
                int_val = gupnp_didl_lite_resource_get_bitrate(res);
                prv_add_int_prop(item_vb, DLS_INTERFACE_PROP_BITRATE, int_val);
@@ -982,26 +1126,6 @@ static void prv_parse_resources(GVariantBuilder *item_vb,
                prv_add_int_prop(item_vb, DLS_INTERFACE_PROP_COLOR_DEPTH,
                                 int_val);
        }
-
-       if (filter_mask & DLS_UPNP_MASK_PROP_UPDATE_COUNT) {
-               uint_val = gupnp_didl_lite_resource_get_update_count(res);
-               prv_add_uint_prop(item_vb, DLS_INTERFACE_PROP_UPDATE_COUNT,
-                                 uint_val);
-       }
-
-       protocol_info = gupnp_didl_lite_resource_get_protocol_info(res);
-
-       if (filter_mask & DLS_UPNP_MASK_PROP_DLNA_PROFILE) {
-               str_val = gupnp_protocol_info_get_dlna_profile(protocol_info);
-               prv_add_string_prop(item_vb, DLS_INTERFACE_PROP_DLNA_PROFILE,
-                                   str_val);
-       }
-
-       if (filter_mask & DLS_UPNP_MASK_PROP_MIME_TYPE) {
-               str_val = gupnp_protocol_info_get_mime_type(protocol_info);
-               prv_add_string_prop(item_vb, DLS_INTERFACE_PROP_MIME_TYPE,
-                                   str_val);
-       }
 }
 
 static GVariant *prv_compute_create_classes(GUPnPDIDLLiteContainer *container)
@@ -1011,6 +1135,7 @@ static GVariant *prv_compute_create_classes(GUPnPDIDLLiteContainer *container)
        GList *ptr;
        GUPnPDIDLLiteCreateClass *create_class;
        const char *content;
+       const char *ms2_class;
        gboolean inc_derived;
 
        g_variant_builder_init(&create_classes_vb, G_VARIANT_TYPE("a(sb)"));
@@ -1022,10 +1147,11 @@ static GVariant *prv_compute_create_classes(GUPnPDIDLLiteContainer *container)
                create_class = ptr->data;
                content = gupnp_didl_lite_create_class_get_content(
                                                                 create_class);
+               ms2_class = dls_props_upnp_class_to_media_spec(content);
                inc_derived = gupnp_didl_lite_create_class_get_include_derived(
                                                                 create_class);
                g_variant_builder_add(&create_classes_vb,
-                                     "(sb)", content, inc_derived);
+                                     "(sb)", ms2_class, inc_derived);
                g_object_unref(ptr->data);
                ptr = g_list_next(ptr);
        }
@@ -1038,6 +1164,9 @@ const gchar *dls_props_media_spec_to_upnp_class(const gchar *m2spec_class)
 {
        const gchar *retval = NULL;
 
+       if (!m2spec_class)
+               goto on_error;
+
        if (!strcmp(m2spec_class, gMediaSpec2AlbumPhoto))
                retval = gUPnPPhotoAlbum;
        else if (!strcmp(m2spec_class, gMediaSpec2AlbumMusic))
@@ -1077,9 +1206,15 @@ const gchar *dls_props_media_spec_to_upnp_class(const gchar *m2spec_class)
        else if (!strcmp(m2spec_class, gMediaSpec2Image))
                retval = gUPnPImageItem;
        else if (!strcmp(m2spec_class, gMediaSpec2Playlist))
+               retval = gUPnPPlaylist;
+       else if (!strcmp(m2spec_class, gMediaSpec2PlaylistItem))
                retval = gUPnPPlaylistItem;
        else if (!strcmp(m2spec_class, gMediaSpec2Item))
                retval = gUPnPItem;
+       else if (!strcmp(m2spec_class, gMediaSpec2Storage))
+               retval = gUPnPStorage;
+
+on_error:
 
        return retval;
 }
@@ -1089,6 +1224,9 @@ const gchar *dls_props_upnp_class_to_media_spec(const gchar *upnp_class)
        const gchar *retval = NULL;
        const gchar *ptr;
 
+       if (!upnp_class)
+               goto on_error;
+
        if (!strncmp(upnp_class, gUPnPAlbum, gUPnPAlbumLen)) {
                ptr = upnp_class + gUPnPAlbumLen;
                if (!strcmp(ptr, ".photoAlbum"))
@@ -1141,41 +1279,81 @@ const gchar *dls_props_upnp_class_to_media_spec(const gchar *upnp_class)
                        retval = gMediaSpec2ImagePhoto;
                else
                        retval = gMediaSpec2Image;
+       }  else if (!strncmp(upnp_class, gUPnPPlaylist,
+                            gUPnPPlaylistLen)) {
+               retval = gMediaSpec2Playlist;
        }  else if (!strncmp(upnp_class, gUPnPPlaylistItem,
                             gUPnPPlaylistItemLen)) {
-               retval = gMediaSpec2Playlist;
+               retval = gMediaSpec2PlaylistItem;
        } else if (!strncmp(upnp_class, gUPnPItem, gUPnPItemLen)) {
                ptr = upnp_class + gUPnPItemLen;
                if (!*ptr || *ptr == '.')
                        retval = gMediaSpec2Item;
+       }  else if (!strncmp(upnp_class, gUPnPStorage,
+                            gUPnPStorageLen)) {
+               retval = gMediaSpec2Storage;
        }
 
+on_error:
+
        return retval;
 }
 
-static GVariant *prv_props_get_dlna_managed_dict(GUPnPOCMFlags flags)
+static GVariant *prv_compute_resources(GUPnPDIDLLiteObject *object,
+                                      dls_upnp_prop_mask filter_mask,
+                                      gboolean all_res)
 {
-       GVariantBuilder builder;
-       gboolean managed;
+       GUPnPDIDLLiteResource *res = NULL;
+       GList *resources;
+       GList *ptr;
+       GVariantBuilder *res_array_vb;
+       GVariantBuilder *res_vb;
+       const char *str_val;
+       GVariant *retval;
 
-       g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sb}"));
+       res_array_vb = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
 
-       managed = (flags & GUPNP_OCM_FLAGS_UPLOAD);
-       g_variant_builder_add(&builder, "{sb}", "Upload", managed);
+       resources = gupnp_didl_lite_object_get_resources(object);
+       ptr = resources;
 
-       managed = (flags & GUPNP_OCM_FLAGS_CREATE_CONTAINER);
-       g_variant_builder_add(&builder, "{sb}", "CreateContainer", managed);
+       while (ptr) {
+               res = ptr->data;
+               res_vb = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+               if (filter_mask & DLS_UPNP_MASK_PROP_URL) {
+                       str_val = gupnp_didl_lite_resource_get_uri(res);
+                       prv_add_string_prop(res_vb, DLS_INTERFACE_PROP_URL,
+                                           str_val);
+               }
 
-       managed = (flags & GUPNP_OCM_FLAGS_DESTROYABLE);
-       g_variant_builder_add(&builder, "{sb}", "Delete", managed);
+               if (all_res)
+                       prv_parse_all_resources(res_vb, res, filter_mask);
+               else
+                       prv_parse_common_resources(res_vb, res, filter_mask);
 
-       managed = (flags & GUPNP_OCM_FLAGS_UPLOAD_DESTROYABLE);
-       g_variant_builder_add(&builder, "{sb}", "UploadDelete", managed);
+               g_variant_builder_add(res_array_vb, "@a{sv}",
+                                     g_variant_builder_end(res_vb));
+               g_variant_builder_unref(res_vb);
+               g_object_unref(ptr->data);
+               ptr = g_list_next(ptr);
+       }
+       retval = g_variant_builder_end(res_array_vb);
+       g_variant_builder_unref(res_array_vb);
 
-       managed = (flags & GUPNP_OCM_FLAGS_CHANGE_METADATA);
-       g_variant_builder_add(&builder, "{sb}", "ChangeMeta", managed);
+       g_list_free(resources);
 
-       return g_variant_builder_end(&builder);
+       return retval;
+}
+
+static void prv_add_resources(GVariantBuilder *item_vb,
+                             GUPnPDIDLLiteObject *object,
+                             dls_upnp_prop_mask filter_mask,
+                             gboolean all_res)
+{
+       GVariant *val;
+
+       val = prv_compute_resources(object, filter_mask, all_res);
+       g_variant_builder_add(item_vb, "{sv}", DLS_INTERFACE_PROP_RESOURCES,
+                             val);
 }
 
 gboolean dls_props_add_object(GVariantBuilder *item_vb,
@@ -1236,10 +1414,12 @@ gboolean dls_props_add_object(GVariantBuilder *item_vb,
                flags = gupnp_didl_lite_object_get_dlna_managed(object);
                prv_add_variant_prop(item_vb,
                                     DLS_INTERFACE_PROP_DLNA_MANAGED,
-                                    prv_props_get_dlna_managed_dict(flags));
+                                    prv_props_get_dlna_info_dict(
+                                               flags, g_prop_dlna_ocm));
        }
 
-       if (filter_mask & DLS_UPNP_MASK_PROP_OBJECT_UPDATE_ID) {
+       if ((filter_mask & DLS_UPNP_MASK_PROP_OBJECT_UPDATE_ID) &&
+           gupnp_didl_lite_object_update_id_is_set(object)) {
                uint_val = gupnp_didl_lite_object_get_update_id(object);
                prv_add_uint_prop(item_vb, DLS_INTERFACE_PROP_OBJECT_UPDATE_ID,
                                  uint_val);
@@ -1257,11 +1437,14 @@ on_error:
 void dls_props_add_container(GVariantBuilder *item_vb,
                             GUPnPDIDLLiteContainer *object,
                             dls_upnp_prop_mask filter_mask,
+                            const gchar *protocol_info,
                             gboolean *have_child_count)
 {
        int child_count;
        gboolean searchable;
        guint uint_val;
+       GUPnPDIDLLiteResource *res;
+       const char *str_val;
 
        *have_child_count = FALSE;
        if (filter_mask & DLS_UPNP_MASK_PROP_CHILD_COUNT) {
@@ -1285,7 +1468,8 @@ void dls_props_add_container(GVariantBuilder *item_vb,
                                     DLS_INTERFACE_PROP_CREATE_CLASSES,
                                     prv_compute_create_classes(object));
 
-       if (filter_mask & DLS_UPNP_MASK_PROP_CONTAINER_UPDATE_ID) {
+       if ((filter_mask & DLS_UPNP_MASK_PROP_CONTAINER_UPDATE_ID) &&
+           gupnp_didl_lite_container_container_update_id_is_set(object)) {
                uint_val = gupnp_didl_lite_container_get_container_update_id(
                                                                        object);
                prv_add_uint_prop(item_vb,
@@ -1293,65 +1477,32 @@ void dls_props_add_container(GVariantBuilder *item_vb,
                                  uint_val);
        }
 
-       if (filter_mask & DLS_UPNP_MASK_PROP_TOTAL_DELETED_CHILD_COUNT) {
+       if ((filter_mask & DLS_UPNP_MASK_PROP_TOTAL_DELETED_CHILD_COUNT) &&
+           gupnp_didl_lite_container_total_deleted_child_count_is_set(
+                                                               object)) {
                uint_val =
                gupnp_didl_lite_container_get_total_deleted_child_count(object);
+
                prv_add_uint_prop(item_vb,
                                  DLS_INTERFACE_PROP_TOTAL_DELETED_CHILD_COUNT,
                                  uint_val);
        }
-}
 
-static GVariant *prv_compute_resources(GUPnPDIDLLiteObject *object,
-                                      dls_upnp_prop_mask filter_mask)
-{
-       GUPnPDIDLLiteResource *res = NULL;
-       GList *resources;
-       GList *ptr;
-       GVariantBuilder *res_array_vb;
-       GVariantBuilder *res_vb;
-       const char *str_val;
-       GVariant *retval;
-
-       res_array_vb = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
-
-       resources = gupnp_didl_lite_object_get_resources(object);
-       ptr = resources;
+       if (filter_mask & DLS_UPNP_MASK_PROP_RESOURCES)
+               prv_add_resources(item_vb, GUPNP_DIDL_LITE_OBJECT(object),
+                                 filter_mask, FALSE);
 
-       while (ptr) {
-               res = ptr->data;
-               res_vb = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
-               if (filter_mask & DLS_UPNP_MASK_PROP_URL) {
+       res = prv_get_matching_resource(GUPNP_DIDL_LITE_OBJECT(object),
+                                       protocol_info);
+       if (res) {
+               if (filter_mask & DLS_UPNP_MASK_PROP_URLS) {
                        str_val = gupnp_didl_lite_resource_get_uri(res);
-                       if (str_val)
-                               prv_add_string_prop(res_vb,
-                                                   DLS_INTERFACE_PROP_URL,
-                                                   str_val);
+                       prv_add_strv_prop(item_vb, DLS_INTERFACE_PROP_URLS,
+                                         &str_val, 1);
                }
-               prv_parse_resources(res_vb, res, filter_mask);
-               g_variant_builder_add(res_array_vb, "@a{sv}",
-                                     g_variant_builder_end(res_vb));
-               g_variant_builder_unref(res_vb);
-               g_object_unref(ptr->data);
-               ptr = g_list_next(ptr);
+               prv_parse_common_resources(item_vb, res, filter_mask);
+               g_object_unref(res);
        }
-       retval = g_variant_builder_end(res_array_vb);
-       g_variant_builder_unref(res_array_vb);
-
-       g_list_free(resources);
-
-       return retval;
-}
-
-static void prv_add_resources(GVariantBuilder *item_vb,
-                             GUPnPDIDLLiteObject *object,
-                             dls_upnp_prop_mask filter_mask)
-{
-       GVariant *val;
-
-       val = prv_compute_resources(object, filter_mask);
-       g_variant_builder_add(item_vb, "{sv}", DLS_INTERFACE_PROP_RESOURCES,
-                             val);
 }
 
 void dls_props_add_item(GVariantBuilder *item_vb,
@@ -1417,17 +1568,15 @@ void dls_props_add_item(GVariantBuilder *item_vb,
        if (res) {
                if (filter_mask & DLS_UPNP_MASK_PROP_URLS) {
                        str_val = gupnp_didl_lite_resource_get_uri(res);
-                       if (str_val)
-                               prv_add_strv_prop(item_vb,
-                                                 DLS_INTERFACE_PROP_URLS,
-                                                 &str_val, 1);
+                       prv_add_strv_prop(item_vb, DLS_INTERFACE_PROP_URLS,
+                                         &str_val, 1);
                }
-               prv_parse_resources(item_vb, res, filter_mask);
+               prv_parse_all_resources(item_vb, res, filter_mask);
                g_object_unref(res);
        }
 
        if (filter_mask & DLS_UPNP_MASK_PROP_RESOURCES)
-               prv_add_resources(item_vb, object, filter_mask);
+               prv_add_resources(item_vb, object, filter_mask, TRUE);
 }
 
 void dls_props_add_resource(GVariantBuilder *item_vb,
@@ -1442,25 +1591,31 @@ void dls_props_add_resource(GVariantBuilder *item_vb,
        if (res) {
                if (filter_mask & DLS_UPNP_MASK_PROP_URL) {
                        str_val = gupnp_didl_lite_resource_get_uri(res);
-                       if (str_val)
-                               prv_add_string_prop(item_vb,
-                                                   DLS_INTERFACE_PROP_URL,
-                                                   str_val);
+                       prv_add_string_prop(item_vb, DLS_INTERFACE_PROP_URL,
+                                           str_val);
                }
-               prv_parse_resources(item_vb, res, filter_mask);
+
+               if (GUPNP_IS_DIDL_LITE_CONTAINER(object))
+                       prv_parse_common_resources(item_vb, res, filter_mask);
+               else
+                       prv_parse_all_resources(item_vb, res, filter_mask);
+
                g_object_unref(res);
        }
 }
 
 
-static GVariant *prv_get_resource_property(const gchar *prop,
-                                          GUPnPDIDLLiteResource *res)
+static GVariant *prv_get_common_resource_property(const gchar *prop,
+                                               GUPnPDIDLLiteResource *res)
 {
-       int int_val;
        gint64 int64_val;
+       guint uint_val;
        const char *str_val;
        GVariant *retval = NULL;
        GUPnPProtocolInfo *protocol_info;
+       GUPnPDLNAConversion conv;
+       GUPnPDLNAOperation ope;
+       GUPnPDLNAFlags flags;
 
        if (!strcmp(prop, DLS_INTERFACE_PROP_DLNA_PROFILE)) {
                protocol_info = gupnp_didl_lite_resource_get_protocol_info(res);
@@ -1470,6 +1625,25 @@ static GVariant *prv_get_resource_property(const gchar *prop,
                if (!str_val)
                        goto on_error;
                retval = g_variant_ref_sink(g_variant_new_string(str_val));
+       } else if (!strcmp(prop, DLS_INTERFACE_PROP_DLNA_CONVERSION)) {
+               protocol_info = gupnp_didl_lite_resource_get_protocol_info(res);
+               conv = gupnp_protocol_info_get_dlna_conversion(protocol_info);
+               retval = prv_props_get_dlna_info_dict(conv, g_prop_dlna_ci);
+               if (retval)
+                       retval = g_variant_ref_sink(retval);
+       } else if (!strcmp(prop, DLS_INTERFACE_PROP_DLNA_OPERATION)) {
+               protocol_info = gupnp_didl_lite_resource_get_protocol_info(res);
+               ope = gupnp_protocol_info_get_dlna_operation(protocol_info);
+               retval = prv_props_get_dlna_info_dict(ope, g_prop_dlna_op);
+               if (retval)
+                       retval = g_variant_ref_sink(retval);
+       } else if (!strcmp(prop, DLS_INTERFACE_PROP_DLNA_FLAGS)) {
+               protocol_info = gupnp_didl_lite_resource_get_protocol_info(res);
+               flags = gupnp_protocol_info_get_dlna_flags(protocol_info);
+               retval =  prv_props_get_dlna_info_dict(flags,
+                                                      g_prop_dlna_flags);
+               if (retval)
+                       retval = g_variant_ref_sink(retval);
        } else if (!strcmp(prop, DLS_INTERFACE_PROP_MIME_TYPE)) {
                protocol_info = gupnp_didl_lite_resource_get_protocol_info(res);
                if (!protocol_info)
@@ -1483,48 +1657,71 @@ static GVariant *prv_get_resource_property(const gchar *prop,
                if (int64_val == -1)
                        goto on_error;
                retval = g_variant_ref_sink(g_variant_new_int64(int64_val));
-       } else if (!strcmp(prop, DLS_INTERFACE_PROP_DURATION)) {
+       } else if (!strcmp(prop, DLS_INTERFACE_PROP_URLS)) {
+               str_val = gupnp_didl_lite_resource_get_uri(res);
+               if (str_val)
+                       retval = g_variant_ref_sink(g_variant_new_strv(&str_val,
+                                                                      1));
+       } else if (!strcmp(prop, DLS_INTERFACE_PROP_UPDATE_COUNT) &&
+                  gupnp_didl_lite_resource_update_count_is_set(res)) {
+               uint_val = gupnp_didl_lite_resource_get_update_count(res);
+               retval = g_variant_ref_sink(g_variant_new_uint32(uint_val));
+       }
+
+on_error:
+
+       return retval;
+}
+
+static GVariant *prv_get_item_resource_property(const gchar *prop,
+                                               GUPnPDIDLLiteResource *res)
+{
+       int int_val;
+       GVariant *retval;
+
+       retval = prv_get_common_resource_property(prop, res);
+
+       if (retval)
+               goto on_exit;
+
+       if (!strcmp(prop, DLS_INTERFACE_PROP_DURATION)) {
                int_val = (int) gupnp_didl_lite_resource_get_duration(res);
                if (int_val == -1)
-                       goto on_error;
+                       goto on_exit;
                retval = g_variant_ref_sink(g_variant_new_int32(int_val));
        } else if (!strcmp(prop, DLS_INTERFACE_PROP_BITRATE)) {
                int_val = gupnp_didl_lite_resource_get_bitrate(res);
                if (int_val == -1)
-                       goto on_error;
+                       goto on_exit;
                retval = g_variant_ref_sink(g_variant_new_int32(int_val));
        } else if (!strcmp(prop, DLS_INTERFACE_PROP_SAMPLE_RATE)) {
                int_val = gupnp_didl_lite_resource_get_sample_freq(res);
                if (int_val == -1)
-                       goto on_error;
+                       goto on_exit;
                retval = g_variant_ref_sink(g_variant_new_int32(int_val));
        } else if (!strcmp(prop, DLS_INTERFACE_PROP_BITS_PER_SAMPLE)) {
                int_val = gupnp_didl_lite_resource_get_bits_per_sample(res);
                if (int_val == -1)
-                       goto on_error;
+                       goto on_exit;
                retval = g_variant_ref_sink(g_variant_new_int32(int_val));
        } else if (!strcmp(prop, DLS_INTERFACE_PROP_WIDTH)) {
                int_val = (int) gupnp_didl_lite_resource_get_width(res);
                if (int_val == -1)
-                       goto on_error;
+                       goto on_exit;
                retval = g_variant_ref_sink(g_variant_new_int32(int_val));
        } else if (!strcmp(prop, DLS_INTERFACE_PROP_HEIGHT)) {
                int_val = (int) gupnp_didl_lite_resource_get_height(res);
                if (int_val == -1)
-                       goto on_error;
+                       goto on_exit;
                retval = g_variant_ref_sink(g_variant_new_int32(int_val));
        } else if (!strcmp(prop, DLS_INTERFACE_PROP_COLOR_DEPTH)) {
                int_val = (int) gupnp_didl_lite_resource_get_color_depth(res);
                if (int_val == -1)
-                       goto on_error;
+                       goto on_exit;
                retval = g_variant_ref_sink(g_variant_new_int32(int_val));
-       } else if (!strcmp(prop, DLS_INTERFACE_PROP_URLS)) {
-               str_val = gupnp_didl_lite_resource_get_uri(res);
-               if (str_val)
-                       retval = g_variant_new_strv(&str_val, 1);
        }
 
-on_error:
+on_exit:
 
        return retval;
 }
@@ -1532,7 +1729,8 @@ on_error:
 GVariant *dls_props_get_object_prop(const gchar *prop, const gchar *root_path,
                                    GUPnPDIDLLiteObject *object)
 {
-       const char *id;
+       const char *object_id;
+       const char *parent_id;
        gchar *path;
        const char *upnp_class;
        const char *media_spec_type;
@@ -1543,14 +1741,21 @@ GVariant *dls_props_get_object_prop(const gchar *prop, const gchar *root_path,
        guint uint_val;
 
        if (!strcmp(prop, DLS_INTERFACE_PROP_PARENT)) {
-               id = gupnp_didl_lite_object_get_parent_id(object);
-               if (!id || !strcmp(id, "-1")) {
+               object_id = gupnp_didl_lite_object_get_id(object);
+               if (!object_id)
+                       goto on_error;
+
+               parent_id = gupnp_didl_lite_object_get_parent_id(object);
+               if (!parent_id)
+                       goto on_error;
+
+               if (!strcmp(object_id, "0") || !strcmp(parent_id, "-1")) {
                        DLEYNA_LOG_DEBUG("Prop %s = %s", prop, root_path);
 
                        retval = g_variant_ref_sink(g_variant_new_string(
                                                            root_path));
                } else {
-                       path = dls_path_from_id(root_path, id);
+                       path = dls_path_from_id(root_path, parent_id);
 
                        DLEYNA_LOG_DEBUG("Prop %s = %s", prop, path);
 
@@ -1559,11 +1764,11 @@ GVariant *dls_props_get_object_prop(const gchar *prop, const gchar *root_path,
                        g_free(path);
                }
        } else if (!strcmp(prop, DLS_INTERFACE_PROP_PATH)) {
-               id = gupnp_didl_lite_object_get_id(object);
-               if (!id)
+               object_id = gupnp_didl_lite_object_get_id(object);
+               if (!object_id)
                        goto on_error;
 
-               path = dls_path_from_id(root_path, id);
+               path = dls_path_from_id(root_path, object_id);
 
                DLEYNA_LOG_DEBUG("Prop %s = %s", prop, path);
 
@@ -1607,9 +1812,10 @@ GVariant *dls_props_get_object_prop(const gchar *prop, const gchar *root_path,
 
                DLEYNA_LOG_DEBUG("Prop %s = %0x", prop, dlna_managed);
 
-               retval = g_variant_ref_sink(
-                               prv_props_get_dlna_managed_dict(dlna_managed));
-       } else if (!strcmp(prop, DLS_INTERFACE_PROP_OBJECT_UPDATE_ID)) {
+               retval = g_variant_ref_sink(prv_props_get_dlna_info_dict(
+                                               dlna_managed, g_prop_dlna_ocm));
+       } else if (!strcmp(prop, DLS_INTERFACE_PROP_OBJECT_UPDATE_ID) &&
+                  gupnp_didl_lite_object_update_id_is_set(object)) {
                uint_val = gupnp_didl_lite_object_get_update_id(object);
 
                DLEYNA_LOG_DEBUG("Prop %s = %u", prop, uint_val);
@@ -1632,6 +1838,9 @@ GVariant *dls_props_get_item_prop(const gchar *prop, const gchar *root_path,
        GUPnPDIDLLiteResource *res;
        GVariant *retval = NULL;
        GList *list;
+#if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
+       gchar *prop_str;
+#endif
 
        if (GUPNP_IS_DIDL_LITE_CONTAINER(object))
                goto on_error;
@@ -1653,9 +1862,9 @@ GVariant *dls_props_get_item_prop(const gchar *prop, const gchar *root_path,
                g_list_free_full(list, g_object_unref);
 
 #if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
-               path = g_variant_print(retval, FALSE);
-               DLEYNA_LOG_DEBUG("Prop %s = %s", prop, path);
-               g_free(path);
+               prop_str = g_variant_print(retval, FALSE);
+               DLEYNA_LOG_DEBUG("Prop %s = %s", prop, prop_str);
+               g_free(prop_str);
 #endif
        } else if (!strcmp(prop, DLS_INTERFACE_PROP_ALBUM)) {
                str = gupnp_didl_lite_object_get_album(object);
@@ -1711,14 +1920,27 @@ GVariant *dls_props_get_item_prop(const gchar *prop, const gchar *root_path,
                g_free(path);
        } else if (!strcmp(prop, DLS_INTERFACE_PROP_RESOURCES)) {
                retval = g_variant_ref_sink(
-                       prv_compute_resources(object, DLS_UPNP_MASK_ALL_PROPS));
+                       prv_compute_resources(object, DLS_UPNP_MASK_ALL_PROPS,
+                                             TRUE));
+#if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
+               prop_str = g_variant_print(retval, FALSE);
+               DLEYNA_LOG_DEBUG("Prop %s = %s", prop, prop_str);
+               g_free(prop_str);
+#endif
        } else {
                res = prv_get_matching_resource(object, protocol_info);
                if (!res)
                        goto on_error;
 
-               retval = prv_get_resource_property(prop, res);
+               retval = prv_get_item_resource_property(prop, res);
 
+#if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
+               if (retval) {
+                       prop_str = g_variant_print(retval, FALSE);
+                       DLEYNA_LOG_DEBUG("Prop %s = %s", prop, prop_str);
+                       g_free(prop_str);
+               }
+#endif
                g_object_unref(res);
        }
 
@@ -1728,15 +1950,17 @@ on_error:
 }
 
 GVariant *dls_props_get_container_prop(const gchar *prop,
-                                      GUPnPDIDLLiteObject *object)
+                                      GUPnPDIDLLiteObject *object,
+                                      const gchar *protocol_info)
 {
        gint child_count;
        gboolean searchable;
        GUPnPDIDLLiteContainer *container;
        GVariant *retval = NULL;
        guint uint_val;
+       GUPnPDIDLLiteResource *res;
 #if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
-       gchar *create_classes;
+       gchar *prop_str;
 #endif
        if (!GUPNP_IS_DIDL_LITE_CONTAINER(object))
                goto on_error;
@@ -1764,11 +1988,13 @@ GVariant *dls_props_get_container_prop(const gchar *prop,
                retval = g_variant_ref_sink(
                        prv_compute_create_classes(container));
 #if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
-               create_classes = g_variant_print(retval, FALSE);
-               DLEYNA_LOG_DEBUG("Prop %s = %s", prop, create_classes);
-               g_free(create_classes);
+               prop_str = g_variant_print(retval, FALSE);
+               DLEYNA_LOG_DEBUG("Prop %s = %s", prop, prop_str);
+               g_free(prop_str);
 #endif
-       } else if (!strcmp(prop, DLS_INTERFACE_PROP_CONTAINER_UPDATE_ID)) {
+       } else if (!strcmp(prop, DLS_INTERFACE_PROP_CONTAINER_UPDATE_ID) &&
+               gupnp_didl_lite_container_container_update_id_is_set(
+                                                               container)) {
                uint_val = gupnp_didl_lite_container_get_container_update_id(
                                                                container);
 
@@ -1776,7 +2002,9 @@ GVariant *dls_props_get_container_prop(const gchar *prop,
 
                retval = g_variant_ref_sink(g_variant_new_uint32(uint_val));
        } else if (!strcmp(prop,
-                               DLS_INTERFACE_PROP_TOTAL_DELETED_CHILD_COUNT)) {
+                               DLS_INTERFACE_PROP_TOTAL_DELETED_CHILD_COUNT) &&
+                  gupnp_didl_lite_container_total_deleted_child_count_is_set(
+                                                               container)) {
                uint_val =
                        gupnp_didl_lite_container_get_total_deleted_child_count(
                                                                container);
@@ -1784,6 +2012,30 @@ GVariant *dls_props_get_container_prop(const gchar *prop,
                DLEYNA_LOG_DEBUG("Prop %s = %u", prop, uint_val);
 
                retval = g_variant_ref_sink(g_variant_new_uint32(uint_val));
+       } else if (!strcmp(prop, DLS_INTERFACE_PROP_RESOURCES)) {
+               retval = g_variant_ref_sink(
+                       prv_compute_resources(object, DLS_UPNP_MASK_ALL_PROPS,
+                                             FALSE));
+#if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
+               prop_str = g_variant_print(retval, FALSE);
+               DLEYNA_LOG_DEBUG("Prop %s = %s", prop, prop_str);
+               g_free(prop_str);
+#endif
+       } else {
+               res = prv_get_matching_resource(object, protocol_info);
+               if (!res)
+                       goto on_error;
+
+               retval = prv_get_common_resource_property(prop, res);
+
+#if DLEYNA_LOG_LEVEL & DLEYNA_LOG_LEVEL_DEBUG
+               if (retval) {
+                       prop_str = g_variant_print(retval, FALSE);
+                       DLEYNA_LOG_DEBUG("Prop %s = %s", prop, prop_str);
+                       g_free(prop_str);
+               }
+#endif
+               g_object_unref(res);
        }
 
 on_error:
index 610fcea..f219573 100644 (file)
@@ -48,7 +48,7 @@
 #define DLS_UPNP_MASK_PROP_WIDTH                       (1LL << 19)
 #define DLS_UPNP_MASK_PROP_HEIGHT                      (1LL << 20)
 #define DLS_UPNP_MASK_PROP_COLOR_DEPTH                 (1LL << 21)
-#define DLS_UPNP_MASK_PROP_ALBUM_ART_URL               (1LL << 22)
+#define DLS_UPNP_MASK_PROP_ALBUM_ART_URL                       (1LL << 22)
 #define DLS_UPNP_MASK_PROP_RESOURCES                   (1LL << 23)
 #define DLS_UPNP_MASK_PROP_URL                         (1LL << 24)
 #define DLS_UPNP_MASK_PROP_REFPATH                     (1LL << 25)
@@ -61,6 +61,9 @@
 #define DLS_UPNP_MASK_PROP_UPDATE_COUNT                        (1LL << 32)
 #define DLS_UPNP_MASK_PROP_CONTAINER_UPDATE_ID         (1LL << 33)
 #define DLS_UPNP_MASK_PROP_TOTAL_DELETED_CHILD_COUNT   (1LL << 34)
+#define DLS_UPNP_MASK_PROP_DLNA_CONVERSION             (1LL << 35)
+#define DLS_UPNP_MASK_PROP_DLNA_OPERATION              (1LL << 36)
+#define DLS_UPNP_MASK_PROP_DLNA_FLAGS                  (1LL << 37)
 
 #define DLS_UPNP_MASK_ALL_PROPS 0xffffffffffffffff
 
@@ -105,12 +108,14 @@ GVariant *dls_props_get_object_prop(const gchar *prop, const gchar *root_path,
 void dls_props_add_container(GVariantBuilder *item_vb,
                             GUPnPDIDLLiteContainer *object,
                             dls_upnp_prop_mask filter_mask,
+                            const gchar *protocol_info,
                             gboolean *have_child_count);
 
 void dls_props_add_child_count(GVariantBuilder *item_vb, gint value);
 
 GVariant *dls_props_get_container_prop(const gchar *prop,
-                                      GUPnPDIDLLiteObject *object);
+                                      GUPnPDIDLLiteObject *object,
+                                      const gchar *protocol_info);
 
 void dls_props_add_resource(GVariantBuilder *item_vb,
                            GUPnPDIDLLiteObject *object,
index 6cfa036..4db03e4 100644 (file)
@@ -72,6 +72,8 @@ static const gchar g_root_introspection[] =
        "      <arg type='ao' name='"DLS_INTERFACE_SERVERS"'"
        "           direction='out'/>"
        "    </method>"
+       "    <method name='"DLS_INTERFACE_RESCAN"'>"
+       "    </method>"
        "    <method name='"DLS_INTERFACE_SET_PROTOCOL_INFO"'>"
        "      <arg type='s' name='"DLS_INTERFACE_PROTOCOL_INFO"'"
        "           direction='in'/>"
@@ -138,6 +140,10 @@ static const gchar g_server_introspection[] =
        "      <arg type='as' name='"DLS_INTERFACE_TO_DELETE"'"
        "           direction='in'/>"
        "    </method>"
+       "    <method name='"DLS_INTERFACE_GET_METADATA"'>"
+       "      <arg type='s' name='"DLS_INTERFACE_METADATA"'"
+       "           direction='out'/>"
+       "    </method>"
        "  </interface>"
        "  <interface name='"DLS_INTERFACE_MEDIA_CONTAINER"'>"
        "    <method name='"DLS_INTERFACE_LIST_CHILDREN"'>"
@@ -254,35 +260,47 @@ static const gchar g_server_introspection[] =
        "      <arg type='o' name='"DLS_INTERFACE_PATH"'"
        "           direction='out'/>"
        "    </method>"
-       "    <method name='"DLS_INTERFACE_CREATE_PLAYLIST"'>"
-       "      <arg type='s' name='"DLS_INTERFACE_TITLE"'"
-       "           direction='in'/>"
-       "      <arg type='s' name='"DLS_INTERFACE_CREATOR"'"
-       "           direction='in'/>"
-       "      <arg type='s' name='"DLS_INTERFACE_GENRE"'"
-       "           direction='in'/>"
-       "      <arg type='s' name='"DLS_INTERFACE_DESCRIPTION"'"
+       "    <method name='"DLS_INTERFACE_GET_COMPATIBLE_RESOURCE"'>"
+       "      <arg type='s' name='"DLS_INTERFACE_PROTOCOL_INFO"'"
        "           direction='in'/>"
-       "      <arg type='ao' name='"DLS_INTERFACE_PLAYLIST_ITEMS"'"
+       "      <arg type='as' name='"DLS_INTERFACE_FILTER"'"
        "           direction='in'/>"
-       "      <arg type='u' name='"DLS_INTERFACE_UPLOAD_ID"'"
+       "      <arg type='a{sv}' name='"DLS_INTERFACE_PROPERTIES_VALUE"'"
        "           direction='out'/>"
+       "    </method>"
+       "    <method name='"DLS_INTERFACE_CREATE_REFERENCE"'>"
        "      <arg type='o' name='"DLS_INTERFACE_PATH"'"
+       "           direction='in'/>"
+       "      <arg type='o' name='"DLS_INTERFACE_REFPATH"'"
        "           direction='out'/>"
        "    </method>"
        "    <property type='u' name='"DLS_INTERFACE_PROP_CHILD_COUNT"'"
        "       access='read'/>"
        "    <property type='b' name='"DLS_INTERFACE_PROP_SEARCHABLE"'"
        "       access='read'/>"
-       "    <property type='a(sb)' name='"
-       DLS_INTERFACE_PROP_CREATE_CLASSES"'"
+       "    <property type='a(sb)' name='"DLS_INTERFACE_PROP_CREATE_CLASSES"'"
        "       access='read'/>"
-       "    <property type='u' name='"
-       DLS_INTERFACE_PROP_CONTAINER_UPDATE_ID"'"
+       "    <property type='u' name='"DLS_INTERFACE_PROP_CONTAINER_UPDATE_ID"'"
        "       access='read'/>"
        "    <property type='u' name='"
        DLS_INTERFACE_PROP_TOTAL_DELETED_CHILD_COUNT"'"
        "       access='read'/>"
+       "    <property type='aa{sv}' name='"DLS_INTERFACE_PROP_RESOURCES"'"
+       "       access='read'/>"
+       "    <property type='as' name='"DLS_INTERFACE_PROP_URLS"'"
+       "       access='read'/>"
+       "    <property type='s' name='"DLS_INTERFACE_PROP_MIME_TYPE"'"
+       "       access='read'/>"
+       "    <property type='s' name='"DLS_INTERFACE_PROP_DLNA_PROFILE"'"
+       "       access='read'/>"
+       "    <property type='a{sb}' name='"DLS_INTERFACE_PROP_DLNA_CONVERSION"'"
+       "       access='read'/>"
+       "    <property type='a{sb}' name='"DLS_INTERFACE_PROP_DLNA_OPERATION"'"
+       "       access='read'/>"
+       "    <property type='a{sb}' name='"DLS_INTERFACE_PROP_DLNA_FLAGS"'"
+       "       access='read'/>"
+       "    <property type='x' name='"DLS_INTERFACE_PROP_SIZE"'"
+       "       access='read'/>"
        "  </interface>"
        "  <interface name='"DLS_INTERFACE_MEDIA_ITEM"'>"
        "    <method name='"DLS_INTERFACE_GET_COMPATIBLE_RESOURCE"'>"
@@ -309,6 +327,12 @@ static const gchar g_server_introspection[] =
        "       access='read'/>"
        "    <property type='s' name='"DLS_INTERFACE_PROP_DLNA_PROFILE"'"
        "       access='read'/>"
+       "    <property type='a{sb}' name='"DLS_INTERFACE_PROP_DLNA_CONVERSION"'"
+       "       access='read'/>"
+       "    <property type='a{sb}' name='"DLS_INTERFACE_PROP_DLNA_OPERATION"'"
+       "       access='read'/>"
+       "    <property type='a{sb}' name='"DLS_INTERFACE_PROP_DLNA_FLAGS"'"
+       "       access='read'/>"
        "    <property type='i' name='"DLS_INTERFACE_PROP_TRACK_NUMBER"'"
        "       access='read'/>"
        "    <property type='x' name='"DLS_INTERFACE_PROP_SIZE"'"
@@ -375,20 +399,14 @@ static const gchar g_server_introspection[] =
        "    </method>"
        "    <method name='"DLS_INTERFACE_CANCEL"'>"
        "    </method>"
-       "    <method name='"DLS_INTERFACE_CREATE_PLAYLIST_TO_ANY"'>"
-       "      <arg type='s' name='"DLS_INTERFACE_TITLE"'"
-       "           direction='in'/>"
-       "      <arg type='s' name='"DLS_INTERFACE_CREATOR"'"
-       "           direction='in'/>"
-       "      <arg type='s' name='"DLS_INTERFACE_GENRE"'"
-       "           direction='in'/>"
-       "      <arg type='s' name='"DLS_INTERFACE_DESCRIPTION"'"
+       "    <method name='"DLS_INTERFACE_GET_ICON"'>"
+       "      <arg type='s' name='"DLS_INTERFACE_REQ_MIME_TYPE"'"
        "           direction='in'/>"
-       "      <arg type='ao' name='"DLS_INTERFACE_PLAYLIST_ITEMS"'"
+       "      <arg type='s' name='"DLS_INTERFACE_RESOLUTION"'"
        "           direction='in'/>"
-       "      <arg type='u' name='"DLS_INTERFACE_UPLOAD_ID"'"
+       "      <arg type='ay' name='"DLS_INTERFACE_ICON_BYTES"'"
        "           direction='out'/>"
-       "      <arg type='o' name='"DLS_INTERFACE_PATH"'"
+       "      <arg type='s' name='"DLS_INTERFACE_MIME_TYPE"'"
        "           direction='out'/>"
        "    </method>"
        "    <property type='s' name='"DLS_INTERFACE_PROP_LOCATION"'"
@@ -485,6 +503,10 @@ static void prv_process_sync_task(dls_task_t *task)
                task->result = dls_upnp_get_server_ids(g_context.upnp);
                prv_sync_task_complete(task);
                break;
+       case DLS_TASK_RESCAN:
+               dls_upnp_rescan(g_context.upnp);
+               prv_sync_task_complete(task);
+               break;
        case DLS_TASK_SET_PROTOCOL_INFO:
                client_name = dleyna_task_queue_get_source(task->atom.queue_id);
                client = g_hash_table_lookup(g_context.watchers, client_name);
@@ -599,13 +621,17 @@ static void prv_process_async_task(dls_task_t *task)
                dls_upnp_update_object(g_context.upnp, client, task,
                                       prv_async_task_complete);
                break;
-       case DLS_TASK_CREATE_PLAYLIST:
-               dls_upnp_create_playlist(g_context.upnp, client, task,
-                                        prv_async_task_complete);
+       case DLS_TASK_GET_OBJECT_METADATA:
+               dls_upnp_get_object_metadata(g_context.upnp, client, task,
+                                            prv_async_task_complete);
+               break;
+       case DLS_TASK_CREATE_REFERENCE:
+               dls_upnp_create_reference(g_context.upnp, client, task,
+                                         prv_async_task_complete);
                break;
-       case DLS_TASK_CREATE_PLAYLIST_IN_ANY:
-               dls_upnp_create_playlist_in_any(g_context.upnp, client, task,
-                                               prv_async_task_complete);
+       case DLS_TASK_GET_ICON:
+               dls_upnp_get_icon(g_context.upnp, client, task,
+                                 prv_async_task_complete);
                break;
        default:
                break;
@@ -635,12 +661,12 @@ static void prv_delete_task(dleyna_task_atom_t *task, gpointer user_data)
 }
 
 static void prv_method_call(dleyna_connector_id_t conn,
-                               const gchar *sender,
-                               const gchar *object,
-                               const gchar *interface,
-                               const gchar *method,
-                               GVariant *parameters,
-                               dleyna_connector_msg_id_t invocation);
+                           const gchar *sender,
+                           const gchar *object,
+                           const gchar *interface,
+                           const gchar *method,
+                           GVariant *parameters,
+                           dleyna_connector_msg_id_t invocation);
 
 static void prv_object_method_call(dleyna_connector_id_t conn,
                                   const gchar *sender,
@@ -755,6 +781,9 @@ static void prv_method_call(dleyna_connector_id_t conn,
        if (!strcmp(method, DLS_INTERFACE_RELEASE)) {
                prv_remove_client(sender);
                g_context.connector->return_response(invocation, NULL);
+       } else if (!strcmp(method, DLS_INTERFACE_RESCAN)) {
+               task = dls_task_rescan_new(invocation);
+               prv_add_task(task, sender, DLS_SERVER_SINK);
        } else if (!strcmp(method, DLS_INTERFACE_GET_VERSION)) {
                task = dls_task_get_version_new(invocation);
                prv_add_task(task, sender, DLS_SERVER_SINK);
@@ -843,6 +872,8 @@ static void prv_object_method_call(dleyna_connector_id_t conn,
        else if (!strcmp(method, DLS_INTERFACE_UPDATE))
                task = dls_task_update_new(invocation, object,
                                           parameters, &error);
+       else if (!strcmp(method, DLS_INTERFACE_GET_METADATA))
+               task = dls_task_get_metadata_new(invocation, object, &error);
        else
                goto finished;
 
@@ -937,9 +968,12 @@ static void prv_con_method_call(dleyna_connector_id_t conn,
                task = dls_task_create_container_new_generic(invocation,
                                                DLS_TASK_CREATE_CONTAINER,
                                                object, parameters, &error);
-       else if (!strcmp(method, DLS_INTERFACE_CREATE_PLAYLIST))
-               task = dls_task_create_playlist_new(invocation,
-                                                   DLS_TASK_CREATE_PLAYLIST,
+       else if (!strcmp(method, DLS_INTERFACE_GET_COMPATIBLE_RESOURCE))
+               task = dls_task_get_resource_new(invocation, object,
+                                                parameters, &error);
+       else if (!strcmp(method, DLS_INTERFACE_CREATE_REFERENCE))
+               task = dls_task_create_reference_new(invocation,
+                                                   DLS_TASK_CREATE_REFERENCE,
                                                    object, parameters, &error);
        else
                goto finished;
@@ -1021,11 +1055,9 @@ static void prv_device_method_call(dleyna_connector_id_t conn,
        } else if (!strcmp(method, DLS_INTERFACE_CANCEL_UPLOAD)) {
                task = dls_task_cancel_upload_new(invocation, object,
                                                  parameters, &error);
-       } else if (!strcmp(method, DLS_INTERFACE_CREATE_PLAYLIST_TO_ANY)) {
-               task = dls_task_create_playlist_new(
-                                               invocation,
-                                               DLS_TASK_CREATE_PLAYLIST_IN_ANY,
-                                               object, parameters, &error);
+       } else if (!strcmp(method, DLS_INTERFACE_GET_ICON)) {
+               task = dls_task_get_icon_new(invocation, object, parameters,
+                                            &error);
        } else if (!strcmp(method, DLS_INTERFACE_CANCEL)) {
                task = NULL;
 
@@ -1132,9 +1164,10 @@ out:
 
 static void prv_control_point_stop_service(void)
 {
-       dls_upnp_unsubscribe(g_context.upnp);
-
-       dls_upnp_delete(g_context.upnp);
+       if (g_context.upnp) {
+               dls_upnp_unsubscribe(g_context.upnp);
+               dls_upnp_delete(g_context.upnp);
+       }
 
        if (g_context.connection) {
                if (g_context.dls_id)
index 6a8cf85..94f4cf2 100644 (file)
 
 #include "async.h"
 
+dls_task_t *dls_task_rescan_new(dleyna_connector_msg_id_t invocation)
+{
+       dls_task_t *task = g_new0(dls_task_t, 1);
+
+       task->type = DLS_TASK_RESCAN;
+       task->invocation = invocation;
+       task->synchronous = TRUE;
+
+       return task;
+}
+
 dls_task_t *dls_task_get_version_new(dleyna_connector_msg_id_t invocation)
 {
        dls_task_t *task = g_new0(dls_task_t, 1);
@@ -91,7 +102,8 @@ static void prv_delete(dls_task_t *task)
        case DLS_TASK_CREATE_CONTAINER_IN_ANY:
                g_free(task->ut.create_container.display_name);
                g_free(task->ut.create_container.type);
-               g_variant_unref(task->ut.create_container.child_types);
+               if (task->ut.create_container.child_types)
+                       g_variant_unref(task->ut.create_container.child_types);
                break;
        case DLS_TASK_UPDATE_OBJECT:
                if (task->ut.update.to_add_update)
@@ -99,14 +111,12 @@ static void prv_delete(dls_task_t *task)
                if (task->ut.update.to_delete)
                        g_variant_unref(task->ut.update.to_delete);
                break;
-       case DLS_TASK_CREATE_PLAYLIST:
-       case DLS_TASK_CREATE_PLAYLIST_IN_ANY:
-               g_free(task->ut.playlist.title);
-               g_free(task->ut.playlist.creator);
-               g_free(task->ut.playlist.genre);
-               g_free(task->ut.playlist.desc);
-               if (task->ut.playlist.item_path)
-                       g_variant_unref(task->ut.playlist.item_path);
+       case DLS_TASK_CREATE_REFERENCE:
+               g_free(task->ut.create_reference.item_path);
+               break;
+       case DLS_TASK_GET_ICON:
+               g_free(task->ut.get_icon.resolution);
+               g_free(task->ut.get_icon.mime_type);
                break;
        default:
                break;
@@ -419,10 +429,6 @@ dls_task_t *dls_task_get_upload_ids_new(dleyna_connector_msg_id_t invocation,
 
        task = prv_m2spec_task_new(DLS_TASK_GET_UPLOAD_IDS, invocation, path,
                                   "(@au)", error, TRUE);
-       if (!task)
-               goto finished;
-
-finished:
 
        return task;
 }
@@ -482,32 +488,25 @@ finished:
        return task;
 }
 
-dls_task_t *dls_task_create_playlist_new(dleyna_connector_msg_id_t invocation,
-                                        dls_task_type_t type,
-                                        const gchar *path,
-                                        GVariant *parameters,
-                                        GError **error)
+dls_task_t *dls_task_create_reference_new(dleyna_connector_msg_id_t invocation,
+                                         dls_task_type_t type,
+                                         const gchar *path,
+                                         GVariant *parameters,
+                                         GError **error)
 {
        dls_task_t *task;
 
        task = prv_m2spec_task_new(type, invocation, path,
-                                  "(uo)", error, FALSE);
+                                  "(@o)", error, FALSE);
        if (!task)
                goto finished;
 
-       g_variant_get(parameters, "(ssss@ao)",
-                     &task->ut.playlist.title,
-                     &task->ut.playlist.creator,
-                     &task->ut.playlist.genre,
-                     &task->ut.playlist.desc,
-                     &task->ut.playlist.item_path);
-
-       task->multiple_retvals = TRUE;
+       g_variant_get(parameters, "(o)", &task->ut.create_reference.item_path);
+       (void) g_strstrip(task->ut.create_reference.item_path);
 
 finished:
 
        return task;
-
 }
 
 dls_task_t *dls_task_update_new(dleyna_connector_msg_id_t invocation,
@@ -530,6 +529,38 @@ finished:
        return task;
 }
 
+dls_task_t *dls_task_get_metadata_new(dleyna_connector_msg_id_t invocation,
+                               const gchar *path, GError **error)
+{
+       dls_task_t *task;
+
+       task = prv_m2spec_task_new(DLS_TASK_GET_OBJECT_METADATA, invocation,
+                                  path, "(@s)", error, FALSE);
+
+       return task;
+}
+
+dls_task_t *dls_task_get_icon_new(dleyna_connector_msg_id_t invocation,
+                                 const gchar *path, GVariant *parameters,
+                                 GError **error)
+{
+       dls_task_t *task;
+
+       task = prv_m2spec_task_new(DLS_TASK_GET_ICON, invocation, path,
+                                  "(@ays)", error, FALSE);
+       if (!task)
+               goto finished;
+
+       task->multiple_retvals = TRUE;
+
+       g_variant_get(parameters, "(ss)", &task->ut.get_icon.mime_type,
+                     &task->ut.get_icon.resolution);
+
+finished:
+
+       return task;
+}
+
 void dls_task_complete(dls_task_t *task)
 {
        GVariant *variant = NULL;
index 0257a9f..bf9f3ba 100644 (file)
@@ -34,6 +34,7 @@
 enum dls_task_type_t_ {
        DLS_TASK_GET_VERSION,
        DLS_TASK_GET_SERVERS,
+       DLS_TASK_RESCAN,
        DLS_TASK_GET_CHILDREN,
        DLS_TASK_GET_ALL_PROPS,
        DLS_TASK_GET_PROP,
@@ -50,8 +51,9 @@ enum dls_task_type_t_ {
        DLS_TASK_CREATE_CONTAINER,
        DLS_TASK_CREATE_CONTAINER_IN_ANY,
        DLS_TASK_UPDATE_OBJECT,
-       DLS_TASK_CREATE_PLAYLIST,
-       DLS_TASK_CREATE_PLAYLIST_IN_ANY
+       DLS_TASK_GET_OBJECT_METADATA,
+       DLS_TASK_CREATE_REFERENCE,
+       DLS_TASK_GET_ICON
 };
 typedef enum dls_task_type_t_ dls_task_type_t;
 
@@ -128,13 +130,9 @@ struct dls_task_update_t_ {
        GVariant *to_delete;
 };
 
-typedef struct dls_task_create_playlist_t_ dls_task_create_playlist_t;
-struct dls_task_create_playlist_t_ {
-       gchar *title;
-       gchar *creator;
-       gchar *genre;
-       gchar *desc;
-       GVariant *item_path;
+typedef struct dls_task_create_reference_t_ dls_task_create_reference_t;
+struct dls_task_create_reference_t_ {
+       gchar *item_path;
 };
 
 typedef struct dls_task_target_info_t_ dls_task_target_info_t;
@@ -145,6 +143,12 @@ struct dls_task_target_info_t_ {
        dls_device_t *device;
 };
 
+typedef struct dls_task_get_icon_t_ dls_task_get_icon_t;
+struct dls_task_get_icon_t_ {
+       gchar *mime_type;
+       gchar *resolution;
+};
+
 typedef struct dls_task_t_ dls_task_t;
 struct dls_task_t_ {
        dleyna_task_atom_t atom; /* pseudo inheritance - MUST be first field */
@@ -167,10 +171,13 @@ struct dls_task_t_ {
                dls_task_upload_action_t upload_action;
                dls_task_create_container_t create_container;
                dls_task_update_t update;
-               dls_task_create_playlist_t playlist;
+               dls_task_create_reference_t create_reference;
+               dls_task_get_icon_t get_icon;
        } ut;
 };
 
+dls_task_t *dls_task_rescan_new(dleyna_connector_msg_id_t invocation);
+
 dls_task_t *dls_task_get_version_new(dleyna_connector_msg_id_t invocation);
 
 dls_task_t *dls_task_get_servers_new(dleyna_connector_msg_id_t invocation);
@@ -246,16 +253,24 @@ dls_task_t *dls_task_create_container_new_generic(
                                        GVariant *parameters,
                                        GError **error);
 
-dls_task_t *dls_task_create_playlist_new(dleyna_connector_msg_id_t invocation,
-                                        dls_task_type_t type,
-                                        const gchar *path,
-                                        GVariant *parameters,
-                                        GError **error);
+dls_task_t *dls_task_create_reference_new(dleyna_connector_msg_id_t invocation,
+                                         dls_task_type_t type,
+                                         const gchar *path,
+                                         GVariant *parameters,
+                                         GError **error);
 
 dls_task_t *dls_task_update_new(dleyna_connector_msg_id_t invocation,
                                const gchar *path, GVariant *parameters,
                                GError **error);
 
+dls_task_t *dls_task_get_metadata_new(dleyna_connector_msg_id_t invocation,
+                                     const gchar *path,
+                                     GError **error);
+
+dls_task_t *dls_task_get_icon_new(dleyna_connector_msg_id_t invocation,
+                                 const gchar *path, GVariant *parameters,
+                                 GError **error);
+
 void dls_task_cancel(dls_task_t *task);
 
 void dls_task_complete(dls_task_t *task);
index dcb9876..92b3943 100644 (file)
@@ -57,6 +57,7 @@ typedef struct prv_device_new_ct_t_ prv_device_new_ct_t;
 struct prv_device_new_ct_t_ {
        dls_upnp_t *upnp;
        char *udn;
+       gchar *ip_address;
        dls_device_t *device;
        const dleyna_task_queue_key_t *queue_id;
 };
@@ -65,6 +66,7 @@ static void prv_device_new_free(prv_device_new_ct_t *priv_t)
 {
        if (priv_t) {
                g_free(priv_t->udn);
+               g_free(priv_t->ip_address);
                g_free(priv_t);
        }
 }
@@ -89,14 +91,64 @@ static void prv_device_chain_end(gboolean cancelled, gpointer data)
 on_clear:
 
        g_hash_table_remove(priv_t->upnp->server_uc_map, priv_t->udn);
-       prv_device_new_free(priv_t);
 
        if (cancelled)
                dls_device_delete(device);
 
+       prv_device_new_free(priv_t);
+
        DLEYNA_LOG_DEBUG_NL();
 }
 
+static void prv_device_context_switch_end(gboolean cancelled, gpointer data)
+{
+       prv_device_new_ct_t *priv_t = (prv_device_new_ct_t *)data;
+
+       DLEYNA_LOG_DEBUG("Enter");
+
+       g_hash_table_remove(priv_t->upnp->server_uc_map, priv_t->udn);
+       prv_device_new_free(priv_t);
+
+       DLEYNA_LOG_DEBUG("Exit");
+}
+
+static const dleyna_task_queue_key_t *prv_create_device_queue(
+                                               prv_device_new_ct_t **priv_t)
+{
+       const dleyna_task_queue_key_t *queue_id;
+
+       *priv_t = g_new0(prv_device_new_ct_t, 1);
+
+       queue_id = dleyna_task_processor_add_queue(
+                       dls_server_get_task_processor(),
+                       dleyna_service_task_create_source(),
+                       DLS_SERVER_SINK,
+                       DLEYNA_TASK_QUEUE_FLAG_AUTO_REMOVE,
+                       dleyna_service_task_process_cb,
+                       dleyna_service_task_cancel_cb,
+                       dleyna_service_task_delete_cb);
+       dleyna_task_queue_set_finally(queue_id, prv_device_chain_end);
+       dleyna_task_queue_set_user_data(queue_id, *priv_t);
+
+
+       return queue_id;
+}
+
+static void prv_update_device_context(prv_device_new_ct_t *priv_t,
+                                     dls_upnp_t *upnp, const char *udn,
+                                     dls_device_t *device,
+                                     const gchar *ip_address,
+                                     const dleyna_task_queue_key_t *queue_id)
+{
+       priv_t->upnp = upnp;
+       priv_t->udn = g_strdup(udn);
+       priv_t->ip_address = g_strdup(ip_address);
+       priv_t->queue_id = queue_id;
+       priv_t->device = device;
+
+       g_hash_table_insert(upnp->server_uc_map, g_strdup(udn), priv_t);
+}
+
 static void prv_server_available_cb(GUPnPControlPoint *cp,
                                    GUPnPDeviceProxy *proxy,
                                    gpointer user_data)
@@ -133,32 +185,17 @@ static void prv_server_available_cb(GUPnPControlPoint *cp,
                DLEYNA_LOG_DEBUG("Device not found. Adding");
                DLEYNA_LOG_DEBUG_NL();
 
-               priv_t = g_new0(prv_device_new_ct_t, 1);
-
-               queue_id = dleyna_task_processor_add_queue(
-                               dls_server_get_task_processor(),
-                               dleyna_service_task_create_source(),
-                               DLS_SERVER_SINK,
-                               DLEYNA_TASK_QUEUE_FLAG_AUTO_REMOVE,
-                               dleyna_service_task_process_cb,
-                               dleyna_service_task_cancel_cb,
-                               dleyna_service_task_delete_cb);
-               dleyna_task_queue_set_finally(queue_id, prv_device_chain_end);
-               dleyna_task_queue_set_user_data(queue_id, priv_t);
+               queue_id = prv_create_device_queue(&priv_t);
 
                device = dls_device_new(upnp->connection, proxy, ip_address,
                                        upnp->interface_info,
                                        upnp->property_map, upnp->counter,
                                        queue_id);
 
-               upnp->counter++;
-
-               priv_t->upnp = upnp;
-               priv_t->udn = g_strdup(udn);
-               priv_t->queue_id = queue_id;
-               priv_t->device = device;
+               prv_update_device_context(priv_t, upnp, udn, device, ip_address,
+                                         queue_id);
 
-               g_hash_table_insert(upnp->server_uc_map, g_strdup(udn), priv_t);
+               upnp->counter++;
        } else {
                DLEYNA_LOG_DEBUG("Device Found");
 
@@ -203,8 +240,10 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
        unsigned int i;
        dls_device_context_t *context;
        gboolean subscribed;
+       gboolean construction_ctx = FALSE;
        gboolean under_construction = FALSE;
        prv_device_new_ct_t *priv_t;
+       const dleyna_task_queue_key_t *queue_id;
 
        DLEYNA_LOG_DEBUG("Enter");
 
@@ -244,6 +283,9 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
                goto on_error;
 
        subscribed = context->subscribed;
+       if (under_construction)
+               construction_ctx = !strcmp(context->ip_address,
+                                          priv_t->ip_address);
 
        (void) g_ptr_array_remove_index(device->contexts, i);
 
@@ -258,6 +300,30 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
 
                        dleyna_task_processor_cancel_queue(priv_t->queue_id);
                }
+       } else if (under_construction && construction_ctx) {
+               DLEYNA_LOG_WARNING(
+                       "Device under construction. Switching context");
+
+               /* Cancel previous contruction task chain */
+               g_hash_table_remove(priv_t->upnp->server_uc_map, priv_t->udn);
+               dleyna_task_queue_set_finally(priv_t->queue_id,
+                                             prv_device_context_switch_end);
+               dleyna_task_processor_cancel_queue(priv_t->queue_id);
+
+               /* Create a new construction task chain */
+               context = dls_device_get_context(device, NULL);
+               queue_id = prv_create_device_queue(&priv_t);
+               prv_update_device_context(priv_t, upnp, udn, device,
+                                         context->ip_address, queue_id);
+
+               /* Start tasks from current construction step */
+               dls_device_construct(device,
+                                    context,
+                                    upnp->connection,
+                                    upnp->interface_info,
+                                    upnp->property_map,
+                                    queue_id);
+
        } else if (subscribed && !device->timeout_id) {
                DLEYNA_LOG_DEBUG("Subscribe on new context");
 
@@ -580,6 +646,8 @@ void dls_upnp_get_resource(dls_upnp_t *upnp, dls_client_t *client,
 
        dls_device_get_resource(client, task, upnp_filter);
 
+       g_free(upnp_filter);
+
        DLEYNA_LOG_DEBUG("Exit");
 }
 
@@ -591,7 +659,6 @@ static gboolean prv_compute_mime_and_class(dls_task_t *task,
 
        if (!g_file_test(task->ut.upload.file_path,
                         G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS)) {
-
                DLEYNA_LOG_WARNING(
                        "File %s does not exist or is not a regular file",
                        task->ut.upload.file_path);
@@ -607,7 +674,6 @@ static gboolean prv_compute_mime_and_class(dls_task_t *task,
                                            NULL);
 
        if (!content_type) {
-
                DLEYNA_LOG_WARNING("Unable to determine Content Type for %s",
                                   task->ut.upload.file_path);
 
@@ -621,7 +687,6 @@ static gboolean prv_compute_mime_and_class(dls_task_t *task,
        g_free(content_type);
 
        if (!cb_task_data->mime_type) {
-
                DLEYNA_LOG_WARNING("Unable to determine MIME Type for %s",
                                   task->ut.upload.file_path);
 
@@ -638,7 +703,6 @@ static gboolean prv_compute_mime_and_class(dls_task_t *task,
        } else if (g_content_type_is_a(cb_task_data->mime_type, "video/*")) {
                cb_task_data->object_class = "object.item.videoItem";
        } else {
-
                DLEYNA_LOG_WARNING("Unsupported MIME Type %s",
                                   cb_task_data->mime_type);
 
@@ -848,6 +912,9 @@ void dls_upnp_create_container(dls_upnp_t *upnp, dls_client_t *client,
 
        dls_device_create_container(client, task, task->target.id);
 
+       if (!cb_data->action)
+               (void) g_idle_add(dls_async_task_complete, cb_data);
+
        DLEYNA_LOG_DEBUG("Exit");
 }
 
@@ -941,109 +1008,56 @@ on_error:
        DLEYNA_LOG_DEBUG("Exit");
 }
 
-void dls_upnp_create_playlist(dls_upnp_t *upnp, dls_client_t *client,
-                             dls_task_t *task,
-                             dls_upnp_task_complete_t cb)
+void dls_upnp_get_object_metadata(dls_upnp_t *upnp, dls_client_t *client,
+                                 dls_task_t *task, dls_upnp_task_complete_t cb)
 {
        dls_async_task_t *cb_data = (dls_async_task_t *)task;
-       dls_task_create_playlist_t *task_data;
 
        DLEYNA_LOG_DEBUG("Enter");
 
        cb_data->cb = cb;
-       task_data = &task->ut.playlist;
 
-       DLEYNA_LOG_DEBUG("Root Path: %s - Id: %s", task->target.root_path,
+       DLEYNA_LOG_DEBUG("Root Path %s Id %s", task->target.root_path,
                         task->target.id);
 
-       if (!task_data->title || !*task_data->title)
-               goto on_param_error;
-
-       if (!g_variant_n_children(task_data->item_path))
-               goto on_param_error;
-
-       DLEYNA_LOG_DEBUG_NL();
-       DLEYNA_LOG_DEBUG("Title = %s", task_data->title);
-       DLEYNA_LOG_DEBUG("Creator = %s", task_data->creator);
-       DLEYNA_LOG_DEBUG("Genre = %s", task_data->genre);
-       DLEYNA_LOG_DEBUG("Desc = %s", task_data->desc);
-       DLEYNA_LOG_DEBUG_NL();
-
-       dls_device_playlist_upload(client, task, task->target.id);
+       dls_device_get_object_metadata(client, task, task->target.id);
 
        DLEYNA_LOG_DEBUG("Exit");
-
-       return;
-
-on_param_error:
-
-       DLEYNA_LOG_WARNING("Invalid Parameter");
-
-       cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
-                                    DLEYNA_ERROR_OPERATION_FAILED,
-                                    "Invalid Parameter");
-
-       (void) g_idle_add(dls_async_task_complete, cb_data);
-
-       DLEYNA_LOG_DEBUG("Exit failure");
 }
 
-void dls_upnp_create_playlist_in_any(dls_upnp_t *upnp, dls_client_t *client,
-                                    dls_task_t *task,
-                                    dls_upnp_task_complete_t cb)
+void dls_upnp_create_reference(dls_upnp_t *upnp, dls_client_t *client,
+                              dls_task_t *task,
+                              dls_upnp_task_complete_t cb)
 {
        dls_async_task_t *cb_data = (dls_async_task_t *)task;
-       dls_task_create_playlist_t *task_data;
 
        DLEYNA_LOG_DEBUG("Enter");
 
        cb_data->cb = cb;
-       task_data = &task->ut.playlist;
 
        DLEYNA_LOG_DEBUG("Root Path: %s - Id: %s", task->target.root_path,
                         task->target.id);
 
-       if (strcmp(task->target.id, "0")) {
-               DLEYNA_LOG_WARNING("Bad path %s", task->target.path);
-
-               cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
-                                            DLEYNA_ERROR_BAD_PATH,
-                                            "CreatePlayListInAny must be executed on a root path");
-
-               goto on_error;
-       }
-
-       if (!task_data->title || !*task_data->title)
-               goto on_param_error;
-
-       if (!g_variant_n_children(task_data->item_path))
-               goto on_param_error;
-
-       DLEYNA_LOG_DEBUG_NL();
-       DLEYNA_LOG_DEBUG("Title = %s", task_data->title);
-       DLEYNA_LOG_DEBUG("Creator = %s", task_data->creator);
-       DLEYNA_LOG_DEBUG("Genre = %s", task_data->genre);
-       DLEYNA_LOG_DEBUG("Desc = %s", task_data->desc);
-       DLEYNA_LOG_DEBUG_NL();
-
-       dls_device_playlist_upload(client, task, "DLNA.ORG_AnyContainer");
+       dls_device_create_reference(client, task);
 
        DLEYNA_LOG_DEBUG("Exit");
 
        return;
+}
 
-on_param_error:
+void dls_upnp_get_icon(dls_upnp_t *upnp, dls_client_t *client,
+                      dls_task_t *task,
+                      dls_upnp_task_complete_t cb)
+{
+       dls_async_task_t *cb_data = (dls_async_task_t *)task;
 
-       DLEYNA_LOG_WARNING("Invalid Parameter");
+       DLEYNA_LOG_DEBUG("Enter");
 
-       cb_data->error = g_error_new(DLEYNA_SERVER_ERROR,
-                                    DLEYNA_ERROR_OPERATION_FAILED,
-                                    "Invalid Parameter");
-on_error:
+       cb_data->cb = cb;
 
-       (void) g_idle_add(dls_async_task_complete, cb_data);
+       dls_device_get_icon(client, task);
 
-       DLEYNA_LOG_DEBUG("Exit failure");
+       DLEYNA_LOG_DEBUG("Exit");
 }
 
 void dls_upnp_unsubscribe(dls_upnp_t *upnp)
@@ -1108,3 +1122,10 @@ gboolean dls_upnp_device_context_exist(dls_device_t *device,
 on_exit:
        return found;
 }
+
+void dls_upnp_rescan(dls_upnp_t *upnp)
+{
+       DLEYNA_LOG_DEBUG("re-scanning control points");
+
+       gupnp_context_manager_rescan_control_points(upnp->context_manager);
+}
index dfe2d1b..833723f 100644 (file)
@@ -93,17 +93,23 @@ void dls_upnp_update_object(dls_upnp_t *upnp, dls_client_t *client,
                            dls_task_t *task,
                            dls_upnp_task_complete_t cb);
 
-void dls_upnp_create_playlist(dls_upnp_t *upnp, dls_client_t *client,
-                             dls_task_t *task,
-                             dls_upnp_task_complete_t cb);
+void dls_upnp_get_object_metadata(dls_upnp_t *upnp, dls_client_t *client,
+                                 dls_task_t *task,
+                                 dls_upnp_task_complete_t cb);
 
-void dls_upnp_create_playlist_in_any(dls_upnp_t *upnp, dls_client_t *client,
-                                    dls_task_t *task,
-                                    dls_upnp_task_complete_t cb);
+void dls_upnp_create_reference(dls_upnp_t *upnp, dls_client_t *client,
+                              dls_task_t *task,
+                              dls_upnp_task_complete_t cb);
+
+void dls_upnp_get_icon(dls_upnp_t *upnp, dls_client_t *client,
+                      dls_task_t *task,
+                      dls_upnp_task_complete_t cb);
 
 void dls_upnp_unsubscribe(dls_upnp_t *upnp);
 
 gboolean dls_upnp_device_context_exist(dls_device_t *device,
                                       dls_device_context_t *context);
 
+void dls_upnp_rescan(dls_upnp_t *upnp);
+
 #endif /* DLS_UPNP_H__ */
index e539ade..b1b7f1a 100644 (file)
@@ -1,7 +1,7 @@
 dnl
-dnl dleyna-server
+dnl dLeyna
 dnl
-dnl Copyright (C) 2013 Intel Corporation. All rights reserved.
+dnl Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
 dnl
 dnl This program is free software; you can redistribute it and/or modify it
 dnl under the terms and conditions of the GNU Lesser General Public License,
@@ -16,6 +16,7 @@ dnl You should have received a copy of the GNU Lesser General Public License
 dnl along with this program; if not, write to the Free Software Foundation, Inc.,
 dnl 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 dnl
+dnl Ludovic Ferrandis <ludovic.ferrandis@intel.com>
 dnl Regis Merlino <regis.merlino@intel.com>
 dnl
 
index 01821d6..ad8a7b7 100644 (file)
@@ -15,11 +15,18 @@ dleyna_server_service_LDADD =       $(GLIB_LIBS)                                                    \
                                $(DLEYNA_CORE_LIBS)                                             \
                                $(top_builddir)/libdleyna/server/libdleyna-server-1.0.la
                        
-dbussessiondir = @DBUS_SESSION_DIR@
-dbussession_DATA = com.intel.dleyna-server.service
+dbusservicedir = $(DBUS_SERVICE_DIR)
+dbusservice_in_files = com.intel.dleyna-server.service.in
+dbusservice_DATA = com.intel.dleyna-server.service
+
+# Replace the 'libexecdir' marker with its fully expanded value
+%.service: %.service.in Makefile
+       $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = dleyna-server-service-1.0.pc
 
-CLEANFILES = $(dbussession_DATA) $(pkgconfig_DATA)
-DISTCLEANFILES = $(dbussession_DATA) $(pkgconfig_DATA)
+EXTRA_DIST = $(dbusservice_in_files)
+
+CLEANFILES = $(dbusservice_DATA)
+DISTCLEANFILES = $(dbusservice_DATA)
index cb80658..78ecc65 100644 (file)
@@ -55,7 +55,6 @@ host_triplet = @host@
 libexec_PROGRAMS = dleyna-server-service$(EXEEXT)
 subdir = server
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
-       $(srcdir)/com.intel.dleyna-server.service.in \
        $(srcdir)/dleyna-server-service-1.0.pc.in
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/compiler-flags.m4 \
@@ -67,11 +66,10 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
        $(ACLOCAL_M4)
 mkinstalldirs = $(install_sh) -d
 CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES = com.intel.dleyna-server.service \
-       dleyna-server-service-1.0.pc
+CONFIG_CLEAN_FILES = dleyna-server-service-1.0.pc
 CONFIG_CLEAN_VPATH_FILES =
 am__installdirs = "$(DESTDIR)$(libexecdir)" \
-       "$(DESTDIR)$(dbussessiondir)" "$(DESTDIR)$(pkgconfigdir)"
+       "$(DESTDIR)$(dbusservicedir)" "$(DESTDIR)$(pkgconfigdir)"
 PROGRAMS = $(libexec_PROGRAMS)
 am_dleyna_server_service_OBJECTS = daemon.$(OBJEXT)
 dleyna_server_service_OBJECTS = $(am_dleyna_server_service_OBJECTS)
@@ -142,7 +140,7 @@ am__uninstall_files_from_dir = { \
     || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
          $(am__cd) "$$dir" && rm -f $$files; }; \
   }
-DATA = $(dbussession_DATA) $(pkgconfig_DATA)
+DATA = $(dbusservice_DATA) $(pkgconfig_DATA)
 ETAGS = etags
 CTAGS = ctags
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -160,9 +158,7 @@ CFLAGS = @CFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CYGPATH_W = @CYGPATH_W@
-DBUS_CFLAGS = @DBUS_CFLAGS@
-DBUS_LIBS = @DBUS_LIBS@
-DBUS_SESSION_DIR = @DBUS_SESSION_DIR@
+DBUS_SERVICE_DIR = @DBUS_SERVICE_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DLEYNA_CORE_CFLAGS = @DLEYNA_CORE_CFLAGS@
@@ -303,12 +299,14 @@ dleyna_server_service_LDADD = $(GLIB_LIBS)                                                        \
                                $(DLEYNA_CORE_LIBS)                                             \
                                $(top_builddir)/libdleyna/server/libdleyna-server-1.0.la
 
-dbussessiondir = @DBUS_SESSION_DIR@
-dbussession_DATA = com.intel.dleyna-server.service
+dbusservicedir = $(DBUS_SERVICE_DIR)
+dbusservice_in_files = com.intel.dleyna-server.service.in
+dbusservice_DATA = com.intel.dleyna-server.service
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = dleyna-server-service-1.0.pc
-CLEANFILES = $(dbussession_DATA) $(pkgconfig_DATA)
-DISTCLEANFILES = $(dbussession_DATA) $(pkgconfig_DATA)
+EXTRA_DIST = $(dbusservice_in_files)
+CLEANFILES = $(dbusservice_DATA)
+DISTCLEANFILES = $(dbusservice_DATA)
 all: all-am
 
 .SUFFIXES:
@@ -343,8 +341,6 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
 $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
        cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 $(am__aclocal_m4_deps):
-com.intel.dleyna-server.service: $(top_builddir)/config.status $(srcdir)/com.intel.dleyna-server.service.in
-       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 dleyna-server-service-1.0.pc: $(top_builddir)/config.status $(srcdir)/dleyna-server-service-1.0.pc.in
        cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 install-libexecPROGRAMS: $(libexec_PROGRAMS)
@@ -434,27 +430,27 @@ mostlyclean-libtool:
 
 clean-libtool:
        -rm -rf .libs _libs
-install-dbussessionDATA: $(dbussession_DATA)
+install-dbusserviceDATA: $(dbusservice_DATA)
        @$(NORMAL_INSTALL)
-       @list='$(dbussession_DATA)'; test -n "$(dbussessiondir)" || list=; \
+       @list='$(dbusservice_DATA)'; test -n "$(dbusservicedir)" || list=; \
        if test -n "$$list"; then \
-         echo " $(MKDIR_P) '$(DESTDIR)$(dbussessiondir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(dbussessiondir)" || exit 1; \
+         echo " $(MKDIR_P) '$(DESTDIR)$(dbusservicedir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(dbusservicedir)" || exit 1; \
        fi; \
        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)$(dbussessiondir)'"; \
-         $(INSTALL_DATA) $$files "$(DESTDIR)$(dbussessiondir)" || exit $$?; \
+         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dbusservicedir)'"; \
+         $(INSTALL_DATA) $$files "$(DESTDIR)$(dbusservicedir)" || exit $$?; \
        done
 
-uninstall-dbussessionDATA:
+uninstall-dbusserviceDATA:
        @$(NORMAL_UNINSTALL)
-       @list='$(dbussession_DATA)'; test -n "$(dbussessiondir)" || list=; \
+       @list='$(dbusservice_DATA)'; test -n "$(dbusservicedir)" || list=; \
        files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-       dir='$(DESTDIR)$(dbussessiondir)'; $(am__uninstall_files_from_dir)
+       dir='$(DESTDIR)$(dbusservicedir)'; $(am__uninstall_files_from_dir)
 install-pkgconfigDATA: $(pkgconfig_DATA)
        @$(NORMAL_INSTALL)
        @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
@@ -563,7 +559,7 @@ check-am: all-am
 check: check-am
 all-am: Makefile $(PROGRAMS) $(DATA)
 installdirs:
-       for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(dbussessiondir)" "$(DESTDIR)$(pkgconfigdir)"; do \
+       for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(dbusservicedir)" "$(DESTDIR)$(pkgconfigdir)"; do \
          test -z "$$dir" || $(MKDIR_P) "$$dir"; \
        done
 install: install-am
@@ -621,7 +617,7 @@ info: info-am
 
 info-am:
 
-install-data-am: install-dbussessionDATA install-pkgconfigDATA
+install-data-am: install-dbusserviceDATA install-pkgconfigDATA
 
 install-dvi: install-dvi-am
 
@@ -667,7 +663,7 @@ ps: ps-am
 
 ps-am:
 
-uninstall-am: uninstall-dbussessionDATA uninstall-libexecPROGRAMS \
+uninstall-am: uninstall-dbusserviceDATA uninstall-libexecPROGRAMS \
        uninstall-pkgconfigDATA
 
 .MAKE: install-am install-strip
@@ -677,7 +673,7 @@ uninstall-am: uninstall-dbussessionDATA uninstall-libexecPROGRAMS \
        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-dbussessionDATA install-dvi install-dvi-am \
+       install-dbusserviceDATA install-dvi install-dvi-am \
        install-exec install-exec-am install-html install-html-am \
        install-info install-info-am install-libexecPROGRAMS \
        install-man install-pdf install-pdf-am install-pkgconfigDATA \
@@ -685,10 +681,14 @@ uninstall-am: uninstall-dbussessionDATA uninstall-libexecPROGRAMS \
        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-dbussessionDATA \
+       tags uninstall uninstall-am uninstall-dbusserviceDATA \
        uninstall-libexecPROGRAMS uninstall-pkgconfigDATA
 
 
+# Replace the 'libexecdir' marker with its fully expanded value
+%.service: %.service.in Makefile
+       $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
 # 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:
index b81e6cd..68014c0 100644 (file)
@@ -1,4 +1,4 @@
 [D-BUS Service]
 Name=com.intel.dleyna-server
-Exec=@prefix@/libexec/dleyna-server-service
+Exec=@libexecdir@/dleyna-server-service
 
index e2764dc..87950cb 100644 (file)
@@ -128,9 +128,7 @@ CFLAGS = @CFLAGS@
 CPP = @CPP@
 CPPFLAGS = @CPPFLAGS@
 CYGPATH_W = @CYGPATH_W@
-DBUS_CFLAGS = @DBUS_CFLAGS@
-DBUS_LIBS = @DBUS_LIBS@
-DBUS_SESSION_DIR = @DBUS_SESSION_DIR@
+DBUS_SERVICE_DIR = @DBUS_SERVICE_DIR@
 DEFS = @DEFS@
 DEPDIR = @DEPDIR@
 DLEYNA_CORE_CFLAGS = @DLEYNA_CORE_CFLAGS@
index a60a41a..2836d28 100644 (file)
@@ -7,14 +7,14 @@
 
 Name:       dleyna
 Summary:    dLeyna hosts a number of DLNA middleware components
-Version:    0.0.1
+Version:    0.2.0
 Release:    0
 Group:      System/Libraries
 License:    LGPLv2+
 URL:        https://01.org/dleyna/
 Source0:    %{name}-%{version}.tar.gz
 Requires:   dbus
-Requires:   libsoup2.4
+Requires:   libsoup
 Requires(post): /sbin/ldconfig
 Requires(postun): /sbin/ldconfig
 BuildRequires:  pkgconfig(dbus-1)
@@ -102,6 +102,7 @@ rm -rf %{buildroot}
 %{_libdir}/libdleyna-core-1.0.so
 %{_libdir}/libdleyna-server-1.0.so
 %{_libdir}/libdleyna-renderer-1.0.so
+%{_libdir}/pkgconfig/dleyna-connector-dbus-1.0.pc
 %{_libdir}/pkgconfig/dleyna-core-1.0.pc
 %{_libdir}/pkgconfig/dleyna-server-1.0.pc
 %{_libdir}/pkgconfig/dleyna-renderer-1.0.pc