+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
#! /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>.
#
# 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/'
# 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]...
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
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.
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 $@
# Define the identity of the package.
PACKAGE='dleyna-linux'
- VERSION='0.0.1'
+ VERSION='0.2.0'
cat >>confdefs.h <<_ACEOF
# 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
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\\"
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/])
+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.
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
@SET_MAKE@
+
VPATH = @srcdir@
am__make_dryrun = \
{ \
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 \
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 \
|| { 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) \
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)
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
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=; \
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)'; \
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
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"
info-am:
-install-data-am: install-connectorLTLIBRARIES
+install-data-am: install-connectorLTLIBRARIES install-pkgconfigDATA
install-dvi: install-dvi-am
ps-am:
-uninstall-am: uninstall-connectorLTLIBRARIES
+uninstall-am: uninstall-connectorLTLIBRARIES uninstall-pkgconfigDATA
.MAKE: all install-am install-strip
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:
# cd dleyna-connector-dbus
Configure and build
- # ./autoreconf -i
- # ./configure
+ # ./autogen.sh
# make
Final installation
#! /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>.
#
# 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/'
# 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]...
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
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.
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 $@
# Define the identity of the package.
PACKAGE='dleyna-connector-dbus'
- VERSION='0.0.1'
+ VERSION='0.1.0'
cat >>confdefs.h <<_ACEOF
-ac_config_files="$ac_config_files Makefile"
+ac_config_files="$ac_config_files Makefile dleyna-connector-dbus-1.0.pc"
cat >confcache <<\_ACEOF
# 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
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\\"
"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
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/])
DLEYNA_LOG_LEVEL_CHECK([${with_log_level}])
-AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([Makefile \
+ dleyna-connector-dbus-1.0.pc
+ ])
AC_OUTPUT
--- /dev/null
+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
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,
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
+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.
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) \
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) \
# cd dleyna-core
Configure and build
- # ./autoreconf -i
- # ./configure
+ # ./autogen.sh
# make
Final installation
#! /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>.
#
# 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/'
# 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]...
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
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.
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 $@
# Define the identity of the package.
PACKAGE='dleyna-core'
- VERSION='0.0.1'
+ VERSION='0.1.0'
cat >>confdefs.h <<_ACEOF
# 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
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\\"
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/])
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;
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");
}
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,
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");
}
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");
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");
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,
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
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,
+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.
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@
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
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".
+
#! /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>.
#
# 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/'
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
with_log_level
with_log_type
with_ua_prefix
+with_dbus_service_dir
enable_lib_only
'
ac_precious_vars='build_alias
SOUP_CFLAGS
SOUP_LIBS
DLEYNA_CORE_CFLAGS
-DLEYNA_CORE_LIBS
-DBUS_CFLAGS
-DBUS_LIBS'
+DLEYNA_CORE_LIBS'
# Initialize some variables set by options.
# 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]...
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
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
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.
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.
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 $@
# Define the identity of the package.
PACKAGE='dleyna-renderer'
- VERSION='0.0.1'
+ VERSION='0.2.0'
cat >>confdefs.h <<_ACEOF
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
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
_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=
-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
# 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
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\\"
"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" ;;
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/])
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])
[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(
[],
[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])
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
])
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) \
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@
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) \
#include <string.h>
#include <math.h>
+#include <libsoup/soup.h>
#include <libgupnp/gupnp-control-point.h>
#include <libgupnp-av/gupnp-av.h>
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,
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;
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);
}
}
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;
}
device = (dlr_device_t *)dleyna_service_task_get_user_data(task);
+ device->construct_step++;
prv_device_subscribe_context(device);
*failed = FALSE;
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;
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,
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);
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");
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)
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));
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;
}
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();
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;
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));
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;
}
on_error:
+ if (error != NULL)
+ g_error_free(error);
+
device_data->local_cb(cb_data);
}
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)
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;
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),
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);
}
+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;
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);
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;
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);
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;
}
static void prv_set_rate(GVariant *params, dlr_async_task_t *cb_data)
{
+ GVariantBuilder *changed_props_vb;
+ GVariant *changed_props;
GVariant *val;
gchar *rate;
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;
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",
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:
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;
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);
}
(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);
+}
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];
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,
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__ */
# 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
#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"
#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_ {
" </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>"
" <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'/>"
" 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"'>"
" <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"'"
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,
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;
}
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)
} 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;
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))
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;
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)
(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);
}
(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);
#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);
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;
}
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;
}
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;
}
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,
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;
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;
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 */
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;
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);
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);
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);
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;
};
{
if (priv_t) {
g_free(priv_t->udn);
+ g_free(priv_t->ip_address);
g_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");
+
+ 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)
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");
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");
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) {
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");
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);
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);
+}
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__ */
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,
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
$(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)
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 \
$(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 = \
|| { 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)
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@
$(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:
$(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)
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=; \
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
info-am:
-install-data-am: install-dbussessionDATA install-pkgconfigDATA
+install-data-am: install-dbusserviceDATA install-pkgconfigDATA
install-dvi: install-dvi-am
ps-am:
-uninstall-am: uninstall-dbussessionDATA uninstall-libexecPROGRAMS \
+uninstall-am: uninstall-dbusserviceDATA uninstall-libexecPROGRAMS \
uninstall-pkgconfigDATA
.MAKE: install-am install-strip
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 \
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:
[D-BUS Service]
Name=com.intel.dleyna-renderer
-Exec=@prefix@/libexec/dleyna-renderer-service
-
+Exec=@libexecdir@/dleyna-renderer-service
+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.
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@
# cd dleyna-server
Configure and build
- # ./autoreconf -i
- # ./configure
+ # ./autogen.sh
# make
Final installation
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.
#! /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>.
#
# 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/'
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
with_log_level
with_log_type
with_ua_prefix
+with_dbus_service_dir
enable_lib_only
'
ac_precious_vars='build_alias
SOUP_CFLAGS
SOUP_LIBS
DLEYNA_CORE_CFLAGS
-DLEYNA_CORE_LIBS
-DBUS_CFLAGS
-DBUS_LIBS'
+DLEYNA_CORE_LIBS'
# Initialize some variables set by options.
# 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]...
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
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
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.
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.
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 $@
# Define the identity of the package.
PACKAGE='dleyna-server'
- VERSION='0.0.1'
+ VERSION='0.2.0'
cat >>confdefs.h <<_ACEOF
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
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
_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=
-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
# 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
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\\"
"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" ;;
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}
--------------------------------------------------"
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/])
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])
[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(
[],
[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])
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
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}
--------------------------------------------------"])
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) \
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@
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) \
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;
}
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;
dls_async_get_all_t get_all;
dls_async_upload_t upload;
dls_async_update_t update;
- dls_async_playlist_t playlist;
} ut;
};
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_ {
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);
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);
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);
}
}
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;
}
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;
}
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));
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;
}
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;
}
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;
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,
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,
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);
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;
}
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 &
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;
}
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;
}
no_complete:
- if (upnp_error)
- g_error_free(upnp_error);
+ if (error)
+ g_error_free(error);
if (parser)
g_object_unref(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;
{
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);
}
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;
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;
}
(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");
}
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);
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;
}
cb_data->cancel_id);
}
- if (upnp_error)
- g_error_free(upnp_error);
+ if (error)
+ g_error_free(error);
DLEYNA_LOG_DEBUG("Exit");
}
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);
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;
}
(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");
}
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);
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;
}
(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");
}
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);
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;
}
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 =
} 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;
}
no_complete:
- if (upnp_error)
- g_error_free(upnp_error);
+ if (error)
+ g_error_free(error);
if (parser)
g_object_unref(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:
{
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;
}
cb_data->cancel_id);
}
- if (upnp_error)
- g_error_free(upnp_error);
+ if (error)
+ g_error_free(error);
DLEYNA_LOG_DEBUG("Exit");
}
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;
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;
}
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 =
} 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;
}
cb_data->cancel_id);
}
- if (upnp_error)
- g_error_free(upnp_error);
+ if (error)
+ g_error_free(error);
if (parser)
g_object_unref(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;
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;
}
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 &
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(
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;
}
g_free(result);
- if (upnp_error)
- g_error_free(upnp_error);
+ if (error)
+ g_error_free(error);
DLEYNA_LOG_DEBUG("Exit");
}
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(
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))) {
g_object_unref(item);
g_object_unref(writer);
+on_error:
+
return retval;
}
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;
}
(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");
}
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];
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;
}
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);
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);
g_free(didl);
+on_error:
+
DLEYNA_LOG_DEBUG("Exit");
+
+ return;
}
static void prv_update_object_update_cb(GUPnPServiceProxy *proxy,
} 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,
retval = gupnp_didl_lite_object_get_artists_xml_string(object);
}
+on_error:
+
return retval;
}
(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);
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;
}
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 =
} 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;
g_free(result);
- if (upnp_error)
- g_error_free(upnp_error);
+ if (error)
+ g_error_free(error);
DLEYNA_LOG_DEBUG("Exit");
}
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);
}
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;
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,
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,
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__ */
# 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
/* 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"
#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"
#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__ */
#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>
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";
(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 =
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;
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,
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));
}
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;
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);
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)
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)"));
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);
}
{
const gchar *retval = NULL;
+ if (!m2spec_class)
+ goto on_error;
+
if (!strcmp(m2spec_class, gMediaSpec2AlbumPhoto))
retval = gUPnPPhotoAlbum;
else if (!strcmp(m2spec_class, gMediaSpec2AlbumMusic))
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;
}
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"))
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,
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);
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) {
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,
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,
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,
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);
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)
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;
}
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;
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);
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);
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);
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;
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);
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);
}
}
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;
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);
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);
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:
#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)
#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
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,
" <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'/>"
" <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"'>"
" <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"'>"
" 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"'"
" </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"'"
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);
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;
}
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,
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);
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;
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;
} 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;
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)
#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);
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)
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;
task = prv_m2spec_task_new(DLS_TASK_GET_UPLOAD_IDS, invocation, path,
"(@au)", error, TRUE);
- if (!task)
- goto finished;
-
-finished:
return task;
}
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,
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;
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,
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;
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;
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 */
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);
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);
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;
};
{
if (priv_t) {
g_free(priv_t->udn);
+ g_free(priv_t->ip_address);
g_free(priv_t);
}
}
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)
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");
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");
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);
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");
dls_device_get_resource(client, task, upnp_filter);
+ g_free(upnp_filter);
+
DLEYNA_LOG_DEBUG("Exit");
}
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);
NULL);
if (!content_type) {
-
DLEYNA_LOG_WARNING("Unable to determine Content Type for %s",
task->ut.upload.file_path);
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);
} 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);
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");
}
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)
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);
+}
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__ */
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,
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
$(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)
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 \
$(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)
|| { 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)
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@
$(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:
$(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)
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=; \
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
info-am:
-install-data-am: install-dbussessionDATA install-pkgconfigDATA
+install-data-am: install-dbusserviceDATA install-pkgconfigDATA
install-dvi: install-dvi-am
ps-am:
-uninstall-am: uninstall-dbussessionDATA uninstall-libexecPROGRAMS \
+uninstall-am: uninstall-dbusserviceDATA uninstall-libexecPROGRAMS \
uninstall-pkgconfigDATA
.MAKE: install-am install-strip
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 \
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:
[D-BUS Service]
Name=com.intel.dleyna-server
-Exec=@prefix@/libexec/dleyna-server-service
+Exec=@libexecdir@/dleyna-server-service
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@
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)
%{_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