!1 Package init with 0.6.0
From: @weijin-deng Reviewed-by: @dwl301 Signed-off-by: @dwl301
This commit is contained in:
commit
d4a468047c
264
0001-Add-a-manual.patch
Normal file
264
0001-Add-a-manual.patch
Normal file
@ -0,0 +1,264 @@
|
||||
From 3c8e85a522516437151bc2c441ddc3eb406593ea Mon Sep 17 00:00:00 2001
|
||||
From: Debarshi Ray <debarshir@freedesktop.org>
|
||||
Date: Mon, 22 Jun 2020 17:02:42 +0200
|
||||
Subject: [PATCH] Add a manual
|
||||
|
||||
https://github.com/phako/dleyna-renderer/pull/1
|
||||
---
|
||||
Makefile.am | 2 +-
|
||||
configure.ac | 6 +
|
||||
doc/Makefile.am | 18 +++
|
||||
doc/dleyna-renderer-service.conf.xml | 182 +++++++++++++++++++++++++++
|
||||
4 files changed, 207 insertions(+), 1 deletion(-)
|
||||
create mode 100644 doc/Makefile.am
|
||||
create mode 100644 doc/dleyna-renderer-service.conf.xml
|
||||
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index 200e1967f0e5..35bd628faf47 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -1,4 +1,4 @@
|
||||
-SUBDIRS = libdleyna/renderer
|
||||
+SUBDIRS = doc libdleyna/renderer
|
||||
|
||||
if BUILD_SERVER
|
||||
SUBDIRS += server
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 364659d30383..b224ac7c832b 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -34,6 +34,11 @@ LT_PREREQ([2.2.6])
|
||||
LT_INIT([dlopen disable-static])
|
||||
LT_LANG([C])
|
||||
|
||||
+AC_PATH_PROG([XSLTPROC], [xsltproc])
|
||||
+if test -z "$XSLTPROC"; then
|
||||
+ AC_MSG_ERROR([xsltproc not found])
|
||||
+fi
|
||||
+
|
||||
# Checks for libraries.
|
||||
PKG_PROG_PKG_CONFIG(0.16)
|
||||
PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28])
|
||||
@@ -231,6 +236,7 @@ AC_SUBST([with_log_level])
|
||||
AC_SUBST([with_log_type])
|
||||
|
||||
AC_CONFIG_FILES([Makefile \
|
||||
+ doc/Makefile \
|
||||
libdleyna/renderer/Makefile \
|
||||
libdleyna/renderer/dleyna-renderer-service.conf \
|
||||
server/dleyna-renderer-service-1.0.pc \
|
||||
diff --git a/doc/Makefile.am b/doc/Makefile.am
|
||||
new file mode 100644
|
||||
index 000000000000..80069b1c82e7
|
||||
--- /dev/null
|
||||
+++ b/doc/Makefile.am
|
||||
@@ -0,0 +1,18 @@
|
||||
+XSLTPROC_FLAGS = \
|
||||
+ --nonet \
|
||||
+ --stringparam man.output.quietly 1 \
|
||||
+ --stringparam funcsynopsis.style ansi \
|
||||
+ --stringparam man.authors.section.enabled 0 \
|
||||
+ --stringparam man.copyright.section.enabled 0
|
||||
+
|
||||
+.xml.5:
|
||||
+ $(AM_V_GEN) $(XSLTPROC) $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
|
||||
+
|
||||
+man_MANS = \
|
||||
+ dleyna-renderer-service.conf.5
|
||||
+
|
||||
+xml_files = $(man_MANS:.5=.xml)
|
||||
+
|
||||
+EXTRA_DIST = $(xml_files)
|
||||
+
|
||||
+CLEANFILES = $(man_MANS)
|
||||
diff --git a/doc/dleyna-renderer-service.conf.xml b/doc/dleyna-renderer-service.conf.xml
|
||||
new file mode 100644
|
||||
index 000000000000..e6be27411cf9
|
||||
--- /dev/null
|
||||
+++ b/doc/dleyna-renderer-service.conf.xml
|
||||
@@ -0,0 +1,182 @@
|
||||
+<?xml version="1.0" encoding="UTF-8"?>
|
||||
+<refentry id="dleyna-renderer-service.conf.5">
|
||||
+ <refentryinfo>
|
||||
+ <title>dleyna-renderer-service.conf</title>
|
||||
+ <date>June 2020</date>
|
||||
+ <productname>dLeyna</productname>
|
||||
+ </refentryinfo>
|
||||
+
|
||||
+ <refmeta>
|
||||
+ <refentrytitle>dleyna-renderer-service.conf</refentrytitle>
|
||||
+ <manvolnum>5</manvolnum>
|
||||
+ <refmiscinfo class="manual">Linux Programmer's Manual</refmiscinfo>
|
||||
+ </refmeta>
|
||||
+
|
||||
+ <refnamediv>
|
||||
+ <refname>dleyna-renderer-service.conf</refname>
|
||||
+ <refpurpose>Configuration file for dleyna-renderer</refpurpose>
|
||||
+ </refnamediv>
|
||||
+
|
||||
+ <refsynopsisdiv>
|
||||
+ <cmdsynopsis>
|
||||
+ <command>/etc/dleyna-renderer-service.conf</command>
|
||||
+ </cmdsynopsis>
|
||||
+ </refsynopsisdiv>
|
||||
+
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>DESCRIPTION</title>
|
||||
+ <para>
|
||||
+ The <command>dleyna-renderer-service</command> program provides the
|
||||
+ <emphasis>com.intel.dleyna-renderer</emphasis> name on the session
|
||||
+ message bus. It is a service for discovering and manipulating DLNA
|
||||
+ Digital Media Renderers (or DMRs).
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ Users or administrators should never need to start this daemon as it will
|
||||
+ be automatically started by
|
||||
+ <citerefentry><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
+ whenever a process sends a D-Bus message to the
|
||||
+ <emphasis>com.intel.dleyna-renderer</emphasis> name on the session bus.
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ This file can be used to configure the behaviour of the
|
||||
+ <command>dleyna-renderer-service</command> program.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>FILE FORMAT</title>
|
||||
+ <para>
|
||||
+ The configuration file format is the so-called key file (sort of
|
||||
+ ini-style) format. It consists of sections (or groups) of key-value
|
||||
+ Lines beginning with a '#' and blank lines are considered comments.
|
||||
+ Sections are started by a header line containing the section enclosed
|
||||
+ in '[' and ']', and ended implicitly by the start of the next section
|
||||
+ or the end of the file. Each key-value pair must be contained in a
|
||||
+ section.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>GENERAL SECTION</title>
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><option>connector-name=dbus</option></term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ The name of the inter-process communication method to be used.
|
||||
+ The only supported value is <emphasis>dbus</emphasis>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><option>never-quit=false|true</option></term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Whether the process should stay alive forever or quit when the
|
||||
+ last client disconnects. The default value is
|
||||
+ <emphasis>false</emphasis>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><option>port</option></term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Source port for Simple Service Discovery Protocol (or SSDP)
|
||||
+ messages. The default value is <emphasis>0</emphasis> which
|
||||
+ means that a random available port will be used.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><option>push-host-port</option></term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Port for push host file server. The default value is
|
||||
+ <emphasis>0</emphasis> which means that a random available
|
||||
+ port will be used.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>LOG SECTION</title>
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><option>log-type=0|1|2</option></term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ The logging method to be used. Three technologies are supported.
|
||||
+ 0 for syslog, 1 for GLib, and 2 for file. The default value is
|
||||
+ <emphasis>0</emphasis>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><option>log-level=0|1|2|...|8</option></term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Comma-separated list of logging levels. The levels are 1 for
|
||||
+ critical, 2 for error, 3 for warning, 4 for message, 5 for info
|
||||
+ and 6 for debug. 0 excludes all levels, 7 is a combination of
|
||||
+ critical, error and info, and 8 includes all levels.
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ The default value is <emphasis>7</emphasis>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>NETF SECTION</title>
|
||||
+ <variablelist>
|
||||
+ <varlistentry>
|
||||
+ <term><option>netf-enabled=false|true</option></term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Whether network filtering should be enabled or not. The default
|
||||
+ values is <emphasis>false</emphasis>.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ <varlistentry>
|
||||
+ <term><option>netf-list</option></term>
|
||||
+ <listitem>
|
||||
+ <para>
|
||||
+ Comma-separated list of interface names, service set identifiers
|
||||
+ (or SSIDs), and Internet Protocol (or IP) addresses. If network
|
||||
+ filtering is requested but the list is empty, then filtering
|
||||
+ remains disabled.
|
||||
+ </para>
|
||||
+ <para>
|
||||
+ The list is empty by default.
|
||||
+ </para>
|
||||
+ </listitem>
|
||||
+ </varlistentry>
|
||||
+ </variablelist>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>BUGS</title>
|
||||
+ <para>
|
||||
+ Please send bug reports to either the distribution bug tracker
|
||||
+ or the upstream bug tracker at
|
||||
+ <ulink url="https://github.com/intel/dleyna-renderer/issues"></ulink>.
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+
|
||||
+ <refsect1>
|
||||
+ <title>SEE ALSO</title>
|
||||
+ <para>
|
||||
+ <citerefentry>
|
||||
+ <refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum>
|
||||
+ </citerefentry>
|
||||
+ </para>
|
||||
+ </refsect1>
|
||||
+</refentry>
|
||||
--
|
||||
2.28.0
|
||||
|
||||
@ -0,0 +1,77 @@
|
||||
From 916daa1bf04bfb1d8823c3f677a021bf41df1db0 Mon Sep 17 00:00:00 2001
|
||||
From: Debarshi Ray <debarshir@freedesktop.org>
|
||||
Date: Tue, 20 Jan 2015 13:59:33 +0100
|
||||
Subject: [PATCH] Disconnect signal handlers during destruction
|
||||
|
||||
A GUPnPContextManager can outlive a dlr_upnp_t because it might be
|
||||
using asynchronous operations during its construction (eg.,
|
||||
GUPnPNetworkManager) which retain references to it. This can be
|
||||
demonstrated if the service is spawned as a result of the following
|
||||
command:
|
||||
$ gdbus call \
|
||||
--session \
|
||||
--dest com.intel.dleyna-renderer \
|
||||
--object-path /com/intel/dLeynaRenderer \
|
||||
--method com.intel.dLeynaRenderer.Manager.Release
|
||||
|
||||
This leads to the signal handlers being invoked with an invalid
|
||||
dlr_upnp_t and the outcome is a crash.
|
||||
|
||||
To avoid this, we should disconnect the callbacks listening to the
|
||||
context manager and the control points belonging to it.
|
||||
---
|
||||
libdleyna/renderer/upnp.c | 20 ++++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
diff --git a/libdleyna/renderer/upnp.c b/libdleyna/renderer/upnp.c
|
||||
index 17cbda720bc1..707dc09aaf5a 100644
|
||||
--- a/libdleyna/renderer/upnp.c
|
||||
+++ b/libdleyna/renderer/upnp.c
|
||||
@@ -45,6 +45,7 @@ struct dlr_upnp_t_ {
|
||||
void *user_data;
|
||||
GHashTable *server_udn_map;
|
||||
GHashTable *server_uc_map;
|
||||
+ GList *cps;
|
||||
dlr_host_service_t *host_service;
|
||||
};
|
||||
|
||||
@@ -352,6 +353,7 @@ static void prv_on_context_available(GUPnPContextManager *context_manager,
|
||||
|
||||
gssdp_resource_browser_set_active(GSSDP_RESOURCE_BROWSER(cp), TRUE);
|
||||
gupnp_context_manager_manage_control_point(upnp->context_manager, cp);
|
||||
+ upnp->cps = g_list_prepend (upnp->cps, g_object_ref (cp));
|
||||
g_object_unref(cp);
|
||||
}
|
||||
|
||||
@@ -390,10 +392,28 @@ dlr_upnp_t *dlr_upnp_new(dleyna_connector_id_t connection,
|
||||
void dlr_upnp_delete(dlr_upnp_t *upnp)
|
||||
{
|
||||
if (upnp) {
|
||||
+ GList *l;
|
||||
+
|
||||
+ for (l = upnp->cps; l != NULL; l = l->next) {
|
||||
+ GUPnPControlPoint *cp = GUPNP_CONTROL_POINT (l->data);
|
||||
+
|
||||
+ g_signal_handlers_disconnect_by_func (cp,
|
||||
+ prv_server_available_cb,
|
||||
+ upnp);
|
||||
+ g_signal_handlers_disconnect_by_func (cp,
|
||||
+ prv_server_unavailable_cb,
|
||||
+ upnp);
|
||||
+ }
|
||||
+
|
||||
+ g_signal_handlers_disconnect_by_func (upnp->context_manager,
|
||||
+ prv_on_context_available,
|
||||
+ upnp);
|
||||
+
|
||||
dlr_host_service_delete(upnp->host_service);
|
||||
g_object_unref(upnp->context_manager);
|
||||
g_hash_table_unref(upnp->server_udn_map);
|
||||
g_hash_table_unref(upnp->server_uc_map);
|
||||
+ g_list_free_full (upnp->cps, g_object_unref);
|
||||
|
||||
g_free(upnp);
|
||||
}
|
||||
--
|
||||
2.9.5
|
||||
|
||||
942
167.patch
Normal file
942
167.patch
Normal file
@ -0,0 +1,942 @@
|
||||
From 594015eac2757f629a32d043c9a9b10ff6c5f95f Mon Sep 17 00:00:00 2001
|
||||
From: Jens Georg <mail@jensge.org>
|
||||
Date: Mon, 5 Nov 2018 22:07:09 +0100
|
||||
Subject: [PATCH 1/4] Use english for logging
|
||||
|
||||
---
|
||||
libdleyna/renderer/device.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libdleyna/renderer/device.c b/libdleyna/renderer/device.c
|
||||
index 7acef89..032d394 100644
|
||||
--- a/libdleyna/renderer/device.c
|
||||
+++ b/libdleyna/renderer/device.c
|
||||
@@ -1201,7 +1201,7 @@ static void prv_add_actions(dlr_device_t *device,
|
||||
continue;
|
||||
}
|
||||
|
||||
- DLEYNA_LOG_DEBUG("DLNA version ≥ 1.50 pour %s",
|
||||
+ DLEYNA_LOG_DEBUG("DLNA version ≥ 1.50 for %s",
|
||||
device->path);
|
||||
timeseek_missing = TRUE;
|
||||
g_free(dlna_device_class);
|
||||
|
||||
From a588dd11e4c6d2ff6a7c1789fad913ab9c2519b5 Mon Sep 17 00:00:00 2001
|
||||
From: Jens Georg <mail@jensge.org>
|
||||
Date: Sat, 21 Sep 2019 20:36:04 +0200
|
||||
Subject: [PATCH 2/4] Do service introspection on device creation
|
||||
|
||||
Fixes #104
|
||||
Fixes #164
|
||||
---
|
||||
libdleyna/renderer/Makefile.am | 2 +
|
||||
libdleyna/renderer/device.c | 411 ++++++++++++++++---------------
|
||||
libdleyna/renderer/gasync-task.c | 135 ++++++++++
|
||||
libdleyna/renderer/gasync-task.h | 57 +++++
|
||||
libdleyna/renderer/manager.c | 1 -
|
||||
libdleyna/renderer/upnp.c | 14 +-
|
||||
6 files changed, 419 insertions(+), 201 deletions(-)
|
||||
create mode 100644 libdleyna/renderer/gasync-task.c
|
||||
create mode 100644 libdleyna/renderer/gasync-task.h
|
||||
|
||||
diff --git a/libdleyna/renderer/Makefile.am b/libdleyna/renderer/Makefile.am
|
||||
index ca601c7..ce4dc41 100644
|
||||
--- a/libdleyna/renderer/Makefile.am
|
||||
+++ b/libdleyna/renderer/Makefile.am
|
||||
@@ -22,6 +22,7 @@ libdleyna_renderer_1_0_la_LDFLAGS = -version-info $(DLEYNA_RENDERER_VERSION) \
|
||||
libdleyna_renderer_1_0_la_SOURCES = $(libdleyna_rendererinc_HEADERS) \
|
||||
async.c \
|
||||
device.c \
|
||||
+ gasync-task.c \
|
||||
host-service.c \
|
||||
manager.c \
|
||||
server.c \
|
||||
@@ -53,6 +54,7 @@ sysconf_DATA = dleyna-renderer-service.conf
|
||||
EXTRA_DIST = $(sysconf_DATA) \
|
||||
async.h \
|
||||
device.h \
|
||||
+ gasync-task.h \
|
||||
host-service.h \
|
||||
prop-defs.h \
|
||||
manager.h \
|
||||
diff --git a/libdleyna/renderer/device.c b/libdleyna/renderer/device.c
|
||||
index 032d394..73b3dd3 100644
|
||||
--- a/libdleyna/renderer/device.c
|
||||
+++ b/libdleyna/renderer/device.c
|
||||
@@ -26,15 +26,16 @@
|
||||
|
||||
#include <libsoup/soup.h>
|
||||
#include <libgupnp/gupnp-control-point.h>
|
||||
+#include <libgupnp/gupnp-service-proxy.h>
|
||||
#include <libgupnp-av/gupnp-av.h>
|
||||
|
||||
#include <libdleyna/core/core.h>
|
||||
#include <libdleyna/core/error.h>
|
||||
#include <libdleyna/core/log.h>
|
||||
-#include <libdleyna/core/service-task.h>
|
||||
|
||||
#include "async.h"
|
||||
#include "device.h"
|
||||
+#include "gasync-task.h"
|
||||
#include "prop-defs.h"
|
||||
#include "server.h"
|
||||
|
||||
@@ -675,21 +676,30 @@ static void prv_process_protocol_info(dlr_device_t *device,
|
||||
DLEYNA_LOG_DEBUG("Exit");
|
||||
}
|
||||
|
||||
-static void prv_get_protocol_info_cb(GUPnPServiceProxy *proxy,
|
||||
- GUPnPServiceProxyAction *action,
|
||||
+static void prv_get_protocol_info_cb(GObject *target,
|
||||
+ GAsyncResult *res,
|
||||
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;
|
||||
+ GUPnPServiceProxyAction *action;
|
||||
|
||||
DLEYNA_LOG_DEBUG("Enter");
|
||||
|
||||
priv_t->dev->construct_step++;
|
||||
|
||||
- end = gupnp_service_proxy_end_action(proxy, action, &error, "Sink",
|
||||
- G_TYPE_STRING, &result, NULL);
|
||||
+ action = gupnp_service_proxy_call_action_finish(GUPNP_SERVICE_PROXY(target), res, &error);
|
||||
+
|
||||
+ if (action == NULL || (error != NULL)) {
|
||||
+ DLEYNA_LOG_WARNING("GetProtocolInfo operation failed: %s",
|
||||
+ ((error != NULL) ? error->message
|
||||
+ : "Invalid result"));
|
||||
+ goto on_error;
|
||||
+ }
|
||||
+
|
||||
+ end = gupnp_service_proxy_action_get_result (action, &error, "Sink", G_TYPE_STRING, &result, NULL);
|
||||
if (!end || (result == NULL)) {
|
||||
DLEYNA_LOG_WARNING("GetProtocolInfo operation failed: %s",
|
||||
((error != NULL) ? error->message
|
||||
@@ -701,6 +711,10 @@ static void prv_get_protocol_info_cb(GUPnPServiceProxy *proxy,
|
||||
|
||||
on_error:
|
||||
|
||||
+ if (action) {
|
||||
+ gupnp_service_proxy_action_unref(action);
|
||||
+ }
|
||||
+
|
||||
if (error)
|
||||
g_error_free(error);
|
||||
|
||||
@@ -709,53 +723,193 @@ static void prv_get_protocol_info_cb(GUPnPServiceProxy *proxy,
|
||||
DLEYNA_LOG_DEBUG("Exit");
|
||||
}
|
||||
|
||||
-static GUPnPServiceProxyAction *prv_get_protocol_info(
|
||||
- dleyna_service_task_t *task,
|
||||
- GUPnPServiceProxy *proxy,
|
||||
- gboolean *failed)
|
||||
+static void prv_introspection_wrap_cb (GUPnPServiceInfo *info,
|
||||
+ GUPnPServiceIntrospection *introspection,
|
||||
+ const GError *error,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ if (error != NULL) {
|
||||
+ g_task_return_error (G_TASK (user_data),
|
||||
+ g_error_copy (error));
|
||||
+ } else {
|
||||
+ g_task_return_pointer (G_TASK (user_data),
|
||||
+ introspection,
|
||||
+ g_object_unref);
|
||||
+ }
|
||||
+
|
||||
+ g_object_unref (G_OBJECT (user_data));
|
||||
+}
|
||||
+
|
||||
+void prv_introspect_async (GUPnPServiceInfo *info,
|
||||
+ GCancellable *cancellable,
|
||||
+ GAsyncReadyCallback callback,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ GTask *task = g_task_new (info, cancellable, callback, user_data);
|
||||
+
|
||||
+ gupnp_service_info_get_introspection_async_full (info,
|
||||
+ prv_introspection_wrap_cb,
|
||||
+ cancellable,
|
||||
+ task);
|
||||
+}
|
||||
+
|
||||
+static GUPnPServiceIntrospection *prv_introspect_finish
|
||||
+ (GUPnPServiceInfo *info,
|
||||
+ GAsyncResult *res,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ g_return_val_if_fail (g_task_is_valid (res, info), NULL);
|
||||
+
|
||||
+ return g_task_propagate_pointer (G_TASK (res), error);
|
||||
+}
|
||||
+
|
||||
+static gint compare_speeds(gconstpointer a, gconstpointer b);
|
||||
+
|
||||
+static void prv_introspect_av_cb (GObject *target,
|
||||
+ GAsyncResult *res,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data;
|
||||
+ GError *error = NULL;
|
||||
+ GUPnPServiceIntrospection *introspection;
|
||||
+ const GUPnPServiceStateVariableInfo *svi;
|
||||
+ GList *allowed_values;
|
||||
+ GVariant *speeds = NULL;
|
||||
+ const GUPnPServiceActionInfo *sai;
|
||||
+
|
||||
+ DLEYNA_LOG_DEBUG("Enter");
|
||||
+
|
||||
+ priv_t->dev->construct_step++;
|
||||
+
|
||||
+ introspection = prv_introspect_finish (GUPNP_SERVICE_INFO (target), res, &error);
|
||||
+
|
||||
+ if (introspection == NULL || (error != NULL)) {
|
||||
+ DLEYNA_LOG_WARNING("GetProtocolInfo operation failed: %s",
|
||||
+ ((error != NULL) ? error->message
|
||||
+ : "Invalid result"));
|
||||
+ goto on_error;
|
||||
+ }
|
||||
+
|
||||
+ svi = gupnp_service_introspection_get_state_variable(
|
||||
+ introspection,
|
||||
+ "TransportPlaySpeed");
|
||||
+
|
||||
+ 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,
|
||||
+ &priv_t->dev->transport_play_speeds,
|
||||
+ &priv_t->dev->min_rate,
|
||||
+ &priv_t->dev->max_rate);
|
||||
+
|
||||
+ priv_t->dev->mpris_transport_play_speeds = g_variant_ref_sink(speeds);
|
||||
+ }
|
||||
+
|
||||
+ sai = gupnp_service_introspection_get_action(
|
||||
+ introspection,
|
||||
+ "X_DLNA_GetBytePositionInfo");
|
||||
+
|
||||
+ priv_t->dev->can_get_byte_position = (sai != NULL);
|
||||
+
|
||||
+on_error:
|
||||
+ g_clear_object(&introspection);
|
||||
+
|
||||
+ g_clear_error(&error);
|
||||
+
|
||||
+ DLEYNA_LOG_DEBUG("Exit");
|
||||
+}
|
||||
+
|
||||
+static void prv_introspect_rc_cb (GObject *target,
|
||||
+ GAsyncResult *res,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data;
|
||||
+ GError *error = NULL;
|
||||
+ GUPnPServiceIntrospection *introspection;
|
||||
+ const GUPnPServiceStateVariableInfo *svi;
|
||||
+
|
||||
+ DLEYNA_LOG_DEBUG("Enter");
|
||||
+
|
||||
+ priv_t->dev->construct_step++;
|
||||
+
|
||||
+ introspection = prv_introspect_finish (GUPNP_SERVICE_INFO (target), res, &error);
|
||||
+
|
||||
+ if (introspection == NULL || (error != NULL)) {
|
||||
+ DLEYNA_LOG_WARNING("GetProtocolInfo operation failed: %s",
|
||||
+ ((error != NULL) ? error->message
|
||||
+ : "Invalid result"));
|
||||
+ goto on_error;
|
||||
+ }
|
||||
+
|
||||
+ svi = gupnp_service_introspection_get_state_variable(introspection,
|
||||
+ "Volume");
|
||||
+ if (svi != NULL)
|
||||
+ priv_t->dev->max_volume = g_value_get_uint(&svi->maximum);
|
||||
+
|
||||
+on_error:
|
||||
+ g_clear_object(&introspection);
|
||||
+
|
||||
+ g_clear_error(&error);
|
||||
+
|
||||
+ DLEYNA_LOG_DEBUG("Exit");
|
||||
+}
|
||||
+
|
||||
+static gboolean prv_get_protocol_info(
|
||||
+ dleyna_gasync_task_t *task,
|
||||
+ GObject *target)
|
||||
{
|
||||
- *failed = FALSE;
|
||||
+ GUPnPServiceProxyAction *action;
|
||||
|
||||
- return gupnp_service_proxy_begin_action(
|
||||
- proxy, "GetProtocolInfo",
|
||||
- dleyna_service_task_begin_action_cb,
|
||||
- task, NULL);
|
||||
+ action = gupnp_service_proxy_action_new("GetProtocolInfo", NULL);
|
||||
+
|
||||
+ gupnp_service_proxy_call_action_async(GUPNP_SERVICE_PROXY (target), action,
|
||||
+ dleyna_gasync_task_get_cancellable (task),
|
||||
+ dleyna_gasync_task_ready_cb,
|
||||
+ task);
|
||||
+
|
||||
+ return FALSE;
|
||||
+}
|
||||
+
|
||||
+static gboolean prv_introspect(dleyna_gasync_task_t *task, GObject *target)
|
||||
+{
|
||||
+ prv_introspect_async (GUPNP_SERVICE_INFO (target),
|
||||
+ dleyna_gasync_task_get_cancellable (task),
|
||||
+ dleyna_gasync_task_ready_cb,
|
||||
+ task);
|
||||
+
|
||||
+ return FALSE;
|
||||
}
|
||||
|
||||
-static GUPnPServiceProxyAction *prv_subscribe(dleyna_service_task_t *task,
|
||||
- GUPnPServiceProxy *proxy,
|
||||
- gboolean *failed)
|
||||
+static gboolean prv_subscribe(dleyna_gasync_task_t *task, GObject *target)
|
||||
{
|
||||
dlr_device_t *device;
|
||||
|
||||
DLEYNA_LOG_DEBUG("Enter");
|
||||
|
||||
- device = (dlr_device_t *)dleyna_service_task_get_user_data(task);
|
||||
+ device = (dlr_device_t *)dleyna_gasync_task_get_user_data(task);
|
||||
|
||||
device->construct_step++;
|
||||
prv_device_subscribe_context(device);
|
||||
|
||||
- *failed = FALSE;
|
||||
-
|
||||
DLEYNA_LOG_DEBUG("Exit");
|
||||
|
||||
- return NULL;
|
||||
+ return FALSE;
|
||||
}
|
||||
|
||||
-static GUPnPServiceProxyAction *prv_declare(dleyna_service_task_t *task,
|
||||
- GUPnPServiceProxy *proxy,
|
||||
- gboolean *failed)
|
||||
+static gboolean prv_declare(dleyna_gasync_task_t *task,
|
||||
+ GObject *target)
|
||||
{
|
||||
unsigned int i;
|
||||
dlr_device_t *device;
|
||||
prv_new_device_ct_t *priv_t;
|
||||
const dleyna_connector_dispatch_cb_t *table;
|
||||
+ gboolean result = FALSE;
|
||||
|
||||
DLEYNA_LOG_DEBUG("Enter");
|
||||
|
||||
- *failed = FALSE;
|
||||
-
|
||||
- priv_t = (prv_new_device_ct_t *)dleyna_service_task_get_user_data(task);
|
||||
+ priv_t = (prv_new_device_ct_t *)dleyna_gasync_task_get_user_data(task);
|
||||
device = priv_t->dev;
|
||||
device->construct_step++;
|
||||
|
||||
@@ -770,16 +924,16 @@ static GUPnPServiceProxyAction *prv_declare(dleyna_service_task_t *task,
|
||||
table + i);
|
||||
|
||||
if (!device->ids[i]) {
|
||||
- *failed = TRUE;
|
||||
+ result = TRUE;
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
on_error:
|
||||
|
||||
-DLEYNA_LOG_DEBUG("Exit");
|
||||
+ DLEYNA_LOG_DEBUG("Exit");
|
||||
|
||||
- return NULL;
|
||||
+ return result;
|
||||
}
|
||||
|
||||
static void prv_free_rc_event(gpointer user_data)
|
||||
@@ -800,6 +954,9 @@ void dlr_device_construct(
|
||||
{
|
||||
prv_new_device_ct_t *priv_t;
|
||||
GUPnPServiceProxy *s_proxy;
|
||||
+ GUPnPServiceProxy *av_proxy;
|
||||
+ GUPnPServiceProxy *rc_proxy;
|
||||
+ GCancellable *cancellable;
|
||||
|
||||
DLEYNA_LOG_DEBUG("Current step: %d", dev->construct_step);
|
||||
|
||||
@@ -809,19 +966,42 @@ void dlr_device_construct(
|
||||
priv_t->dispatch_table = dispatch_table;
|
||||
|
||||
s_proxy = context->service_proxies.cm_proxy;
|
||||
+ cancellable = g_cancellable_new ();
|
||||
|
||||
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);
|
||||
+ dleyna_gasync_task_add(queue_id,
|
||||
+ prv_get_protocol_info,
|
||||
+ G_OBJECT(s_proxy),
|
||||
+ prv_get_protocol_info_cb,
|
||||
+ cancellable,
|
||||
+ NULL, priv_t);
|
||||
+
|
||||
+ av_proxy = context->service_proxies.av_proxy;
|
||||
+ if (dev->construct_step < 2)
|
||||
+ dleyna_gasync_task_add(queue_id,
|
||||
+ prv_introspect,
|
||||
+ G_OBJECT(av_proxy),
|
||||
+ prv_introspect_av_cb,
|
||||
+ cancellable,
|
||||
+ NULL, priv_t);
|
||||
+
|
||||
+ rc_proxy = context->service_proxies.rc_proxy;
|
||||
+ if (dev->construct_step < 3)
|
||||
+ dleyna_gasync_task_add(queue_id,
|
||||
+ prv_introspect,
|
||||
+ G_OBJECT(rc_proxy),
|
||||
+ prv_introspect_rc_cb,
|
||||
+ cancellable,
|
||||
+ NULL, priv_t);
|
||||
+
|
||||
|
||||
/* The following task should always be completed */
|
||||
- dleyna_service_task_add(queue_id, prv_subscribe, s_proxy,
|
||||
- NULL, NULL, dev);
|
||||
+ dleyna_gasync_task_add(queue_id, prv_subscribe, G_OBJECT(s_proxy),
|
||||
+ NULL, NULL, NULL, dev);
|
||||
|
||||
- if (dev->construct_step < 3)
|
||||
- dleyna_service_task_add(queue_id, prv_declare, s_proxy,
|
||||
- NULL, g_free, priv_t);
|
||||
+ if (dev->construct_step < 5)
|
||||
+ dleyna_gasync_task_add(queue_id, prv_declare, G_OBJECT(s_proxy),
|
||||
+ NULL, NULL, g_free, priv_t);
|
||||
|
||||
dleyna_task_queue_start(queue_id);
|
||||
|
||||
@@ -2121,133 +2301,6 @@ static void prv_get_rates_values(GList *allowed_tp_speeds,
|
||||
return;
|
||||
}
|
||||
|
||||
-static gboolean prv_get_av_service_states_values(GUPnPServiceProxy *av_proxy,
|
||||
- GVariant **mpris_tp_speeds,
|
||||
- GPtrArray **upnp_tp_speeds,
|
||||
- double *min_rate,
|
||||
- double *max_rate,
|
||||
- gboolean *can_get_byte_pos)
|
||||
-{
|
||||
- const GUPnPServiceStateVariableInfo *svi;
|
||||
- const GUPnPServiceActionInfo *sai;
|
||||
- GUPnPServiceIntrospection *introspection;
|
||||
- GError *error = NULL;
|
||||
- GVariant *speeds = NULL;
|
||||
- GList *allowed_values;
|
||||
- gpointer weak_ref = NULL;
|
||||
- gboolean device_alive = TRUE;
|
||||
-
|
||||
- /* TODO: this weak_ref hack is needed as
|
||||
- gupnp_service_info_get_introspection iterates the main loop.
|
||||
- This can result in our device getting deleted before this
|
||||
- function returns. Ultimately, this code needs to be re-written
|
||||
- to use gupnp_service_info_get_introspection_async but this cannot
|
||||
- really be done until GUPnP provides a way to cancel this function. */
|
||||
-
|
||||
- weak_ref = av_proxy;
|
||||
- g_object_add_weak_pointer(G_OBJECT(av_proxy), &weak_ref);
|
||||
-
|
||||
- introspection = gupnp_service_info_get_introspection(
|
||||
- GUPNP_SERVICE_INFO(av_proxy),
|
||||
- &error);
|
||||
-
|
||||
- if (!weak_ref) {
|
||||
- DLEYNA_LOG_WARNING("Lost device during introspection call");
|
||||
- device_alive = FALSE;
|
||||
- goto exit;
|
||||
- }
|
||||
-
|
||||
- g_object_remove_weak_pointer(G_OBJECT(av_proxy), &weak_ref);
|
||||
-
|
||||
- if (error != NULL) {
|
||||
- DLEYNA_LOG_DEBUG(
|
||||
- "failed to fetch AV service introspection file");
|
||||
-
|
||||
- g_error_free(error);
|
||||
-
|
||||
- goto exit;
|
||||
- }
|
||||
-
|
||||
- svi = gupnp_service_introspection_get_state_variable(
|
||||
- introspection,
|
||||
- "TransportPlaySpeed");
|
||||
-
|
||||
- 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);
|
||||
- }
|
||||
-
|
||||
- sai = gupnp_service_introspection_get_action(
|
||||
- introspection,
|
||||
- "X_DLNA_GetBytePositionInfo");
|
||||
-
|
||||
- *can_get_byte_pos = (sai != NULL);
|
||||
-
|
||||
- g_object_unref(introspection);
|
||||
-
|
||||
-exit:
|
||||
-
|
||||
- return device_alive;
|
||||
-}
|
||||
-
|
||||
-static gboolean prv_get_rc_service_states_values(GUPnPServiceProxy *rc_proxy,
|
||||
- guint *max_volume)
|
||||
-{
|
||||
- const GUPnPServiceStateVariableInfo *svi;
|
||||
- GUPnPServiceIntrospection *introspection;
|
||||
- GError *error = NULL;
|
||||
- gpointer weak_ref = NULL;
|
||||
- gboolean device_alive = TRUE;
|
||||
-
|
||||
- /* TODO: this weak_ref hack is needed as
|
||||
- gupnp_service_info_get_introspection iterates the main loop.
|
||||
- This can result in our device getting deleted before this
|
||||
- function returns. Ultimately, this code needs to be re-written
|
||||
- to use gupnp_service_info_get_introspection_async but this cannot
|
||||
- really be done until GUPnP provides a way to cancel this function. */
|
||||
-
|
||||
- weak_ref = rc_proxy;
|
||||
- g_object_add_weak_pointer(G_OBJECT(rc_proxy), &weak_ref);
|
||||
-
|
||||
- introspection = gupnp_service_info_get_introspection(
|
||||
- GUPNP_SERVICE_INFO(rc_proxy),
|
||||
- &error);
|
||||
-
|
||||
- if (!weak_ref) {
|
||||
- DLEYNA_LOG_WARNING("Lost device during introspection call");
|
||||
- device_alive = FALSE;
|
||||
- goto exit;
|
||||
- }
|
||||
-
|
||||
- g_object_remove_weak_pointer(G_OBJECT(rc_proxy), &weak_ref);
|
||||
-
|
||||
- if (error != NULL) {
|
||||
- DLEYNA_LOG_DEBUG(
|
||||
- "failed to fetch RC service introspection file");
|
||||
-
|
||||
- g_error_free(error);
|
||||
-
|
||||
- goto exit;
|
||||
- }
|
||||
-
|
||||
- svi = gupnp_service_introspection_get_state_variable(introspection,
|
||||
- "Volume");
|
||||
- if (svi != NULL)
|
||||
- *max_volume = g_value_get_uint(&svi->maximum);
|
||||
-
|
||||
- g_object_unref(introspection);
|
||||
-
|
||||
-exit:
|
||||
-
|
||||
- return device_alive;
|
||||
-}
|
||||
-
|
||||
static void prv_update_device_props(GUPnPDeviceInfo *proxy, GHashTable *props)
|
||||
{
|
||||
GVariant *val;
|
||||
@@ -2378,34 +2431,6 @@ static gboolean prv_props_update(dlr_device_t *device, dlr_task_t *task)
|
||||
|
||||
service_proxies = &context->service_proxies;
|
||||
|
||||
- /* TODO: We should not retrieve these values here. They should be
|
||||
- retrieved during device construction. */
|
||||
-
|
||||
- if (service_proxies->av_proxy)
|
||||
- if (!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,
|
||||
- &device->can_get_byte_position)) {
|
||||
- DLEYNA_LOG_DEBUG("Lost Device AV");
|
||||
-
|
||||
- device_alive = FALSE;
|
||||
- goto on_lost_device;
|
||||
- }
|
||||
-
|
||||
- /* TODO: We should not retrieve these values here. They should be
|
||||
- retrieved during device construction. */
|
||||
-
|
||||
- if (service_proxies->rc_proxy)
|
||||
- if (!prv_get_rc_service_states_values(service_proxies->rc_proxy,
|
||||
- &device->max_volume)) {
|
||||
- DLEYNA_LOG_DEBUG("Lost Device RC");
|
||||
- device_alive = FALSE;
|
||||
- goto on_lost_device;
|
||||
- }
|
||||
-
|
||||
changed_props_vb = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
|
||||
|
||||
prv_add_player_speed_props(device->props.player_props,
|
||||
diff --git a/libdleyna/renderer/gasync-task.c b/libdleyna/renderer/gasync-task.c
|
||||
new file mode 100644
|
||||
index 0000000..47a0ad5
|
||||
--- /dev/null
|
||||
+++ b/libdleyna/renderer/gasync-task.c
|
||||
@@ -0,0 +1,135 @@
|
||||
+/*
|
||||
+ * dLeyna
|
||||
+ *
|
||||
+ * Copyright (c) 2019 Jens Georg <mail@jensge.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms and conditions of the GNU Lesser General Public License,
|
||||
+ * version 2.1, as published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * This program is distributed in the hope it will be useful, but WITHOUT
|
||||
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Lesser General Public License
|
||||
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include "gasync-task.h"
|
||||
+#include <libdleyna/core/task-processor.h>
|
||||
+
|
||||
+struct dleyna_gasync_task_t_ {
|
||||
+ dleyna_task_atom_t base;
|
||||
+ dleyna_gasync_task_action action;
|
||||
+ GObject *target;
|
||||
+ GAsyncReadyCallback callback;
|
||||
+ GCancellable *cancellable;
|
||||
+ GDestroyNotify free_func;
|
||||
+ gpointer cb_user_data;
|
||||
+};
|
||||
+
|
||||
+const char *dleyna_gasync_task_create_source(void)
|
||||
+{
|
||||
+ static unsigned int cpt = 1;
|
||||
+ static char source[27];
|
||||
+
|
||||
+ g_snprintf(source, 27, "gasync-source-%d", cpt);
|
||||
+ cpt++;
|
||||
+
|
||||
+ return source;
|
||||
+}
|
||||
+
|
||||
+void dleyna_gasync_task_add(const dleyna_task_queue_key_t *queue_id,
|
||||
+ dleyna_gasync_task_action action,
|
||||
+ GObject *target,
|
||||
+ GAsyncReadyCallback callback,
|
||||
+ GCancellable *cancellable,
|
||||
+ GDestroyNotify free_func,
|
||||
+ gpointer cb_user_data)
|
||||
+{
|
||||
+ dleyna_gasync_task_t *task;
|
||||
+
|
||||
+ task = g_new0(dleyna_gasync_task_t, 1);
|
||||
+
|
||||
+ task->action = action;
|
||||
+ task->callback = callback;
|
||||
+ task->cancellable = cancellable;
|
||||
+ task->free_func = free_func;
|
||||
+ task->cb_user_data = cb_user_data;
|
||||
+ task->target = target;
|
||||
+
|
||||
+ if (target != NULL) {
|
||||
+ g_object_add_weak_pointer (target, (gpointer *)(&task->target));
|
||||
+ }
|
||||
+
|
||||
+ dleyna_task_queue_add_task(queue_id, &task->base);
|
||||
+}
|
||||
+
|
||||
+void dleyna_gasync_task_ready_cb(GObject *source, GAsyncResult *res, gpointer user_data)
|
||||
+{
|
||||
+ dleyna_gasync_task_t *task = (dleyna_gasync_task_t *)user_data;
|
||||
+
|
||||
+ task->callback(source, res, task->cb_user_data);
|
||||
+
|
||||
+ dleyna_task_queue_task_completed(task->base.queue_id);
|
||||
+}
|
||||
+
|
||||
+void dleyna_gasync_task_process_cb(dleyna_task_atom_t *atom,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ gboolean failed = FALSE;
|
||||
+
|
||||
+ dleyna_gasync_task_t *task = (dleyna_gasync_task_t *)atom;
|
||||
+
|
||||
+ failed = task->action(task, task->target);
|
||||
+
|
||||
+ if (failed) {
|
||||
+ dleyna_task_processor_cancel_queue(task->base.queue_id);
|
||||
+ dleyna_task_queue_task_completed(task->base.queue_id);
|
||||
+ }
|
||||
+
|
||||
+ if (task->callback == NULL) {
|
||||
+ dleyna_task_queue_task_completed(task->base.queue_id);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void dleyna_gasync_task_cancel_cb(dleyna_task_atom_t *atom,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ dleyna_gasync_task_t *task = (dleyna_gasync_task_t *)atom;
|
||||
+
|
||||
+ if (task->cancellable) {
|
||||
+ g_cancellable_cancel (task->cancellable);
|
||||
+ task->cancellable = NULL;
|
||||
+
|
||||
+ dleyna_task_queue_task_completed(task->base.queue_id);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void dleyna_gasync_task_delete_cb(dleyna_task_atom_t *atom,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ dleyna_gasync_task_t *task = (dleyna_gasync_task_t *)atom;
|
||||
+
|
||||
+ if (task->free_func != NULL)
|
||||
+ task->free_func(task->cb_user_data);
|
||||
+
|
||||
+ if (task->target != NULL) {
|
||||
+ g_object_remove_weak_pointer(task->target, (gpointer *)&task->target);
|
||||
+ }
|
||||
+
|
||||
+ g_free(task);
|
||||
+}
|
||||
+
|
||||
+gpointer dleyna_gasync_task_get_user_data(dleyna_gasync_task_t *task)
|
||||
+{
|
||||
+ return task->cb_user_data;
|
||||
+}
|
||||
+
|
||||
+GCancellable *dleyna_gasync_task_get_cancellable(dleyna_gasync_task_t *task)
|
||||
+{
|
||||
+ return task->cancellable;
|
||||
+}
|
||||
diff --git a/libdleyna/renderer/gasync-task.h b/libdleyna/renderer/gasync-task.h
|
||||
new file mode 100644
|
||||
index 0000000..629e48c
|
||||
--- /dev/null
|
||||
+++ b/libdleyna/renderer/gasync-task.h
|
||||
@@ -0,0 +1,57 @@
|
||||
+/*
|
||||
+ * dLeyna
|
||||
+ *
|
||||
+ * Copyright (c) 2019 Jens Georg <mail@jensge.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify it
|
||||
+ * under the terms and conditions of the GNU Lesser General Public License,
|
||||
+ * version 2.1, as published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * This program is distributed in the hope it will be useful, but WITHOUT
|
||||
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU Lesser General Public License
|
||||
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#pragma once
|
||||
+
|
||||
+#include <libdleyna/core/task-atom.h>
|
||||
+
|
||||
+#include <glib.h>
|
||||
+#include <gio/gio.h>
|
||||
+
|
||||
+typedef struct dleyna_gasync_task_t_ dleyna_gasync_task_t;
|
||||
+
|
||||
+typedef gboolean (*dleyna_gasync_task_action)
|
||||
+ (dleyna_gasync_task_t *task,
|
||||
+ GObject *target);
|
||||
+
|
||||
+const char *dleyna_gasync_task_create_source(void);
|
||||
+
|
||||
+void dleyna_gasync_task_add(const dleyna_task_queue_key_t *queue_id,
|
||||
+ dleyna_gasync_task_action action,
|
||||
+ GObject *target,
|
||||
+ GAsyncReadyCallback callback,
|
||||
+ GCancellable *cancellable,
|
||||
+ GDestroyNotify free_func,
|
||||
+ gpointer cb_user_data);
|
||||
+
|
||||
+void dleyna_gasync_task_ready_cb(GObject *source, GAsyncResult *res, gpointer user_data);
|
||||
+
|
||||
+void dleyna_gasync_task_process_cb(dleyna_task_atom_t *atom,
|
||||
+ gpointer user_data);
|
||||
+
|
||||
+void dleyna_gasync_task_cancel_cb(dleyna_task_atom_t *atom,
|
||||
+ gpointer user_data);
|
||||
+
|
||||
+void dleyna_gasync_task_delete_cb(dleyna_task_atom_t *atom,
|
||||
+ gpointer user_data);
|
||||
+
|
||||
+gpointer dleyna_gasync_task_get_user_data(dleyna_gasync_task_t *task);
|
||||
+
|
||||
+GCancellable *dleyna_gasync_task_get_cancellable(dleyna_gasync_task_t *task);
|
||||
diff --git a/libdleyna/renderer/manager.c b/libdleyna/renderer/manager.c
|
||||
index 74052f5..bea9935 100644
|
||||
--- a/libdleyna/renderer/manager.c
|
||||
+++ b/libdleyna/renderer/manager.c
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include <libdleyna/core/error.h>
|
||||
#include <libdleyna/core/log.h>
|
||||
-#include <libdleyna/core/service-task.h>
|
||||
#include <libdleyna/core/white-list.h>
|
||||
|
||||
#include "async.h"
|
||||
diff --git a/libdleyna/renderer/upnp.c b/libdleyna/renderer/upnp.c
|
||||
index 17cbda7..0e9d483 100644
|
||||
--- a/libdleyna/renderer/upnp.c
|
||||
+++ b/libdleyna/renderer/upnp.c
|
||||
@@ -28,10 +28,10 @@
|
||||
|
||||
#include <libdleyna/core/error.h>
|
||||
#include <libdleyna/core/log.h>
|
||||
-#include <libdleyna/core/service-task.h>
|
||||
|
||||
#include "async.h"
|
||||
#include "device.h"
|
||||
+#include "gasync-task.h"
|
||||
#include "host-service.h"
|
||||
#include "prop-defs.h"
|
||||
#include "upnp.h"
|
||||
@@ -116,12 +116,12 @@ static const dleyna_task_queue_key_t *prv_create_device_queue(
|
||||
|
||||
queue_id = dleyna_task_processor_add_queue(
|
||||
dlr_renderer_service_get_task_processor(),
|
||||
- dleyna_service_task_create_source(),
|
||||
+ dleyna_gasync_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_gasync_task_process_cb,
|
||||
+ dleyna_gasync_task_cancel_cb,
|
||||
+ dleyna_gasync_task_delete_cb);
|
||||
dleyna_task_queue_set_finally(queue_id, prv_device_chain_end);
|
||||
dleyna_task_queue_set_user_data(queue_id, *priv_t);
|
||||
|
||||
@@ -243,8 +243,8 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
|
||||
|
||||
udn = gupnp_device_info_get_udn((GUPnPDeviceInfo *)proxy);
|
||||
|
||||
- ip_address = gupnp_context_get_host_ip(
|
||||
- gupnp_control_point_get_context(cp));
|
||||
+ ip_address = gssdp_client_get_host_ip(
|
||||
+ GSSDP_CLIENT(gupnp_control_point_get_context(cp)));
|
||||
|
||||
if (!udn || !ip_address)
|
||||
goto on_error;
|
||||
|
||||
From 79593067cf40ed58a3bd95311c7fa108feafcb46 Mon Sep 17 00:00:00 2001
|
||||
From: Jens Georg <mail@jensge.org>
|
||||
Date: Sat, 21 Sep 2019 20:37:33 +0200
|
||||
Subject: [PATCH 3/4] Move to GUPnP 1.2
|
||||
|
||||
Fixes #166
|
||||
---
|
||||
configure.ac | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 271ee92..364659d 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -38,8 +38,8 @@ LT_LANG([C])
|
||||
PKG_PROG_PKG_CONFIG(0.16)
|
||||
PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28])
|
||||
PKG_CHECK_MODULES([GIO], [gio-2.0 >= 2.28])
|
||||
-PKG_CHECK_MODULES([GSSDP], [gssdp-1.0 >= 0.13.2])
|
||||
-PKG_CHECK_MODULES([GUPNP], [gupnp-1.0 >= 0.20.5])
|
||||
+PKG_CHECK_MODULES([GSSDP], [gssdp-1.2 >= 1.2.0])
|
||||
+PKG_CHECK_MODULES([GUPNP], [gupnp-1.2 >= 1.2.0])
|
||||
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])
|
||||
|
||||
From 66e755a89cdcd7f10a535131a340c3f3ab371194 Mon Sep 17 00:00:00 2001
|
||||
From: Jens Georg <mail@jensge.org>
|
||||
Date: Mon, 23 Sep 2019 00:08:38 +0200
|
||||
Subject: [PATCH 4/4] Protect introspection calls against missing proxies
|
||||
|
||||
---
|
||||
libdleyna/renderer/device.c | 38 +++++++++++++++++++++++--------------
|
||||
1 file changed, 24 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/libdleyna/renderer/device.c b/libdleyna/renderer/device.c
|
||||
index 73b3dd3..525a23d 100644
|
||||
--- a/libdleyna/renderer/device.c
|
||||
+++ b/libdleyna/renderer/device.c
|
||||
@@ -977,22 +977,32 @@ void dlr_device_construct(
|
||||
NULL, priv_t);
|
||||
|
||||
av_proxy = context->service_proxies.av_proxy;
|
||||
- if (dev->construct_step < 2)
|
||||
- dleyna_gasync_task_add(queue_id,
|
||||
- prv_introspect,
|
||||
- G_OBJECT(av_proxy),
|
||||
- prv_introspect_av_cb,
|
||||
- cancellable,
|
||||
- NULL, priv_t);
|
||||
+ if (dev->construct_step < 2) {
|
||||
+ if (av_proxy == NULL) {
|
||||
+ dev->construct_step++;
|
||||
+ } else {
|
||||
+ dleyna_gasync_task_add(queue_id,
|
||||
+ prv_introspect,
|
||||
+ G_OBJECT(av_proxy),
|
||||
+ prv_introspect_av_cb,
|
||||
+ cancellable,
|
||||
+ NULL, priv_t);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
rc_proxy = context->service_proxies.rc_proxy;
|
||||
- if (dev->construct_step < 3)
|
||||
- dleyna_gasync_task_add(queue_id,
|
||||
- prv_introspect,
|
||||
- G_OBJECT(rc_proxy),
|
||||
- prv_introspect_rc_cb,
|
||||
- cancellable,
|
||||
- NULL, priv_t);
|
||||
+ if (dev->construct_step < 3) {
|
||||
+ if (rc_proxy == NULL) {
|
||||
+ dev->construct_step++;
|
||||
+ } else {
|
||||
+ dleyna_gasync_task_add(queue_id,
|
||||
+ prv_introspect,
|
||||
+ G_OBJECT(rc_proxy),
|
||||
+ prv_introspect_rc_cb,
|
||||
+ cancellable,
|
||||
+ NULL, priv_t);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
|
||||
/* The following task should always be completed */
|
||||
BIN
dleyna-renderer-0.6.0.tar_2.gz
Normal file
BIN
dleyna-renderer-0.6.0.tar_2.gz
Normal file
Binary file not shown.
@ -0,0 +1,385 @@
|
||||
From cc2e5d5f51e354e43c80ae0bbaf96f8bb4c9a3aa Mon Sep 17 00:00:00 2001
|
||||
From: Debarshi Ray <debarshir@freedesktop.org>
|
||||
Date: Fri, 4 Dec 2020 20:54:47 +0100
|
||||
Subject: [PATCH] Fix the cancellation of dleyna_gasync_task_t tasks
|
||||
|
||||
When a GAsyncResult-based asynchronous operation is cancelled, by
|
||||
convention, it will always asynchronously invoke the
|
||||
GAsyncReadyCallback with the error set to G_IO_ERROR_CANCELLED.
|
||||
However, when the queues in a dleyna_task_processor_t are cancelled,
|
||||
the tasks within them are immediately destroyed. This means that a
|
||||
GAsyncReadyCallback shouldn't try to access a task after cancellation
|
||||
because it would be pointing to invalid memory.
|
||||
|
||||
Here's an example:
|
||||
|
||||
%0 prv_introspect_rc_cb (target=0x556be880d9f0,
|
||||
res=0x556be8840280,
|
||||
user_data=0x556be88fef70)
|
||||
at device.c:835
|
||||
%1 dleyna_gasync_task_ready_cb (source=<optimized out>,
|
||||
res=<optimized out>,
|
||||
user_data=0x556be89a0ac0)
|
||||
at gasync-task.c:75
|
||||
%2 g_task_return_now (task=0x556be8840280) at ../gio/gtask.c:1215
|
||||
%3 complete_in_idle_cb (task=task@entry=0x556be8840280)
|
||||
at ../gio/gtask.c:1229
|
||||
%4 g_idle_dispatch (source=source@entry=0x556be8844e40,
|
||||
callback=0x7f87cd82b380 <complete_in_idle_cb>,
|
||||
user_data=0x556be8840280)
|
||||
at ../glib/gmain.c:5836
|
||||
%5 g_main_dispatch (context=0x556be87e6be0) at ../glib/gmain.c:3325
|
||||
%6 g_main_context_dispatch (context=0x556be87e6be0)
|
||||
at ../glib/gmain.c:4043
|
||||
%7 g_main_context_iterate.constprop.0 (context=0x556be87e6be0,
|
||||
block=block@entry=1,
|
||||
dispatch=dispatch@entry=1,
|
||||
self=<optimized out>)
|
||||
at ../glib/gmain.c:4119
|
||||
%8 g_main_loop_run (loop=0x556be8828130) at ../glib/gmain.c:4317
|
||||
%9 dleyna_main_loop_start (server=<optimized out>,
|
||||
control_point=<optimized out>,
|
||||
user_data=<optimized out>)
|
||||
at libdleyna/core/main-loop.c:154
|
||||
%10 __libc_start_main (main=0x556be79fe0d0 <main>,
|
||||
argc=1, argv=0x7ffeb4610d98,
|
||||
init=<optimized out>,
|
||||
fini=<optimized out>,
|
||||
rtld_fini=<optimized out>,
|
||||
stack_end=0x7ffeb4610d88)
|
||||
at ../csu/libc-start.c:314
|
||||
%11 0x0000556be79fe14e in _start ()
|
||||
|
||||
Till now, dleyna_gasync_task_ready_cb was being used as the common
|
||||
GAsyncReadyCallback for all tasks. However, it doesn't support
|
||||
cancellation because that requires the use of the 'finish' counterpart
|
||||
of the specific asynchronous operation in question. Therefore, instead
|
||||
of a common GAsyncReadyCallback, each task needs to provide its own.
|
||||
|
||||
Secondly, when cancelling a dleyna_gasync_task_t through
|
||||
dleyna_gasync_task_cancel_cb, dleyna_task_queue_task_completed should
|
||||
be called only if the task was current. Calling it for tasks that were
|
||||
waiting in the queue breaks the semantics of the processor because the
|
||||
running_tasks counter is an unsigned integer and can't accommodate
|
||||
negative values.
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1900645
|
||||
https://github.com/phako/dleyna-renderer/pull/4
|
||||
---
|
||||
libdleyna/renderer/device.c | 83 ++++++++++++++++++++++++--------
|
||||
libdleyna/renderer/gasync-task.c | 30 ++----------
|
||||
libdleyna/renderer/gasync-task.h | 1 -
|
||||
3 files changed, 69 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/libdleyna/renderer/device.c b/libdleyna/renderer/device.c
|
||||
index 525a23d978c7..4c0acb79c284 100644
|
||||
--- a/libdleyna/renderer/device.c
|
||||
+++ b/libdleyna/renderer/device.c
|
||||
@@ -683,15 +683,23 @@ static void prv_get_protocol_info_cb(GObject *target,
|
||||
gchar *result = NULL;
|
||||
gboolean end;
|
||||
GError *error = NULL;
|
||||
- prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data;
|
||||
+ dleyna_gasync_task_t *task = NULL;
|
||||
+ prv_new_device_ct_t *priv_t = NULL;
|
||||
GUPnPServiceProxyAction *action;
|
||||
|
||||
DLEYNA_LOG_DEBUG("Enter");
|
||||
|
||||
- priv_t->dev->construct_step++;
|
||||
-
|
||||
action = gupnp_service_proxy_call_action_finish(GUPNP_SERVICE_PROXY(target), res, &error);
|
||||
|
||||
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
+ DLEYNA_LOG_WARNING("GetProtocolInfo operation cancelled");
|
||||
+ goto on_error;
|
||||
+ }
|
||||
+
|
||||
+ task = (dleyna_gasync_task_t *) user_data;
|
||||
+ priv_t = (prv_new_device_ct_t *) dleyna_gasync_task_get_user_data (task);
|
||||
+ priv_t->dev->construct_step++;
|
||||
+
|
||||
if (action == NULL || (error != NULL)) {
|
||||
DLEYNA_LOG_WARNING("GetProtocolInfo operation failed: %s",
|
||||
((error != NULL) ? error->message
|
||||
@@ -711,6 +719,9 @@ static void prv_get_protocol_info_cb(GObject *target,
|
||||
|
||||
on_error:
|
||||
|
||||
+ if (task)
|
||||
+ dleyna_task_queue_task_completed (((dleyna_task_atom_t *) task)->queue_id);
|
||||
+
|
||||
if (action) {
|
||||
gupnp_service_proxy_action_unref(action);
|
||||
}
|
||||
@@ -769,7 +780,8 @@ static void prv_introspect_av_cb (GObject *target,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
- prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data;
|
||||
+ dleyna_gasync_task_t *task = NULL;
|
||||
+ prv_new_device_ct_t *priv_t = NULL;
|
||||
GError *error = NULL;
|
||||
GUPnPServiceIntrospection *introspection;
|
||||
const GUPnPServiceStateVariableInfo *svi;
|
||||
@@ -779,10 +791,17 @@ static void prv_introspect_av_cb (GObject *target,
|
||||
|
||||
DLEYNA_LOG_DEBUG("Enter");
|
||||
|
||||
- priv_t->dev->construct_step++;
|
||||
-
|
||||
introspection = prv_introspect_finish (GUPNP_SERVICE_INFO (target), res, &error);
|
||||
|
||||
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
+ DLEYNA_LOG_WARNING("GetProtocolInfo operation cancelled");
|
||||
+ goto on_error;
|
||||
+ }
|
||||
+
|
||||
+ task = (dleyna_gasync_task_t *) user_data;
|
||||
+ priv_t = (prv_new_device_ct_t *) dleyna_gasync_task_get_user_data (task);
|
||||
+ priv_t->dev->construct_step++;
|
||||
+
|
||||
if (introspection == NULL || (error != NULL)) {
|
||||
DLEYNA_LOG_WARNING("GetProtocolInfo operation failed: %s",
|
||||
((error != NULL) ? error->message
|
||||
@@ -814,6 +833,9 @@ static void prv_introspect_av_cb (GObject *target,
|
||||
priv_t->dev->can_get_byte_position = (sai != NULL);
|
||||
|
||||
on_error:
|
||||
+ if (task)
|
||||
+ dleyna_task_queue_task_completed (((dleyna_task_atom_t *) task)->queue_id);
|
||||
+
|
||||
g_clear_object(&introspection);
|
||||
|
||||
g_clear_error(&error);
|
||||
@@ -825,17 +847,25 @@ static void prv_introspect_rc_cb (GObject *target,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
- prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data;
|
||||
+ dleyna_gasync_task_t *task = NULL;
|
||||
+ prv_new_device_ct_t *priv_t = NULL;
|
||||
GError *error = NULL;
|
||||
GUPnPServiceIntrospection *introspection;
|
||||
const GUPnPServiceStateVariableInfo *svi;
|
||||
|
||||
DLEYNA_LOG_DEBUG("Enter");
|
||||
|
||||
- priv_t->dev->construct_step++;
|
||||
-
|
||||
introspection = prv_introspect_finish (GUPNP_SERVICE_INFO (target), res, &error);
|
||||
|
||||
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
+ DLEYNA_LOG_WARNING("GetProtocolInfo operation cancelled");
|
||||
+ goto on_error;
|
||||
+ }
|
||||
+
|
||||
+ task = (dleyna_gasync_task_t *) user_data;
|
||||
+ priv_t = (prv_new_device_ct_t *) dleyna_gasync_task_get_user_data (task);
|
||||
+ priv_t->dev->construct_step++;
|
||||
+
|
||||
if (introspection == NULL || (error != NULL)) {
|
||||
DLEYNA_LOG_WARNING("GetProtocolInfo operation failed: %s",
|
||||
((error != NULL) ? error->message
|
||||
@@ -849,6 +879,9 @@ static void prv_introspect_rc_cb (GObject *target,
|
||||
priv_t->dev->max_volume = g_value_get_uint(&svi->maximum);
|
||||
|
||||
on_error:
|
||||
+ if (task)
|
||||
+ dleyna_task_queue_task_completed (((dleyna_task_atom_t *) task)->queue_id);
|
||||
+
|
||||
g_clear_object(&introspection);
|
||||
|
||||
g_clear_error(&error);
|
||||
@@ -866,17 +899,27 @@ static gboolean prv_get_protocol_info(
|
||||
|
||||
gupnp_service_proxy_call_action_async(GUPNP_SERVICE_PROXY (target), action,
|
||||
dleyna_gasync_task_get_cancellable (task),
|
||||
- dleyna_gasync_task_ready_cb,
|
||||
+ prv_get_protocol_info_cb,
|
||||
task);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
-static gboolean prv_introspect(dleyna_gasync_task_t *task, GObject *target)
|
||||
+static gboolean prv_introspect_av(dleyna_gasync_task_t *task, GObject *target)
|
||||
{
|
||||
prv_introspect_async (GUPNP_SERVICE_INFO (target),
|
||||
dleyna_gasync_task_get_cancellable (task),
|
||||
- dleyna_gasync_task_ready_cb,
|
||||
+ prv_introspect_av_cb,
|
||||
+ task);
|
||||
+
|
||||
+ return FALSE;
|
||||
+}
|
||||
+
|
||||
+static gboolean prv_introspect_rc(dleyna_gasync_task_t *task, GObject *target)
|
||||
+{
|
||||
+ prv_introspect_async (GUPNP_SERVICE_INFO (target),
|
||||
+ dleyna_gasync_task_get_cancellable (task),
|
||||
+ prv_introspect_rc_cb,
|
||||
task);
|
||||
|
||||
return FALSE;
|
||||
@@ -893,6 +936,8 @@ static gboolean prv_subscribe(dleyna_gasync_task_t *task, GObject *target)
|
||||
device->construct_step++;
|
||||
prv_device_subscribe_context(device);
|
||||
|
||||
+ dleyna_task_queue_task_completed (((dleyna_task_atom_t *) task)->queue_id);
|
||||
+
|
||||
DLEYNA_LOG_DEBUG("Exit");
|
||||
|
||||
return FALSE;
|
||||
@@ -924,6 +969,7 @@ static gboolean prv_declare(dleyna_gasync_task_t *task,
|
||||
table + i);
|
||||
|
||||
if (!device->ids[i]) {
|
||||
+ dleyna_task_processor_cancel_queue (((dleyna_task_atom_t *) task)->queue_id);
|
||||
result = TRUE;
|
||||
goto on_error;
|
||||
}
|
||||
@@ -931,6 +977,8 @@ static gboolean prv_declare(dleyna_gasync_task_t *task,
|
||||
|
||||
on_error:
|
||||
|
||||
+ dleyna_task_queue_task_completed (((dleyna_task_atom_t *) task)->queue_id);
|
||||
+
|
||||
DLEYNA_LOG_DEBUG("Exit");
|
||||
|
||||
return result;
|
||||
@@ -972,7 +1020,6 @@ void dlr_device_construct(
|
||||
dleyna_gasync_task_add(queue_id,
|
||||
prv_get_protocol_info,
|
||||
G_OBJECT(s_proxy),
|
||||
- prv_get_protocol_info_cb,
|
||||
cancellable,
|
||||
NULL, priv_t);
|
||||
|
||||
@@ -982,9 +1029,8 @@ void dlr_device_construct(
|
||||
dev->construct_step++;
|
||||
} else {
|
||||
dleyna_gasync_task_add(queue_id,
|
||||
- prv_introspect,
|
||||
+ prv_introspect_av,
|
||||
G_OBJECT(av_proxy),
|
||||
- prv_introspect_av_cb,
|
||||
cancellable,
|
||||
NULL, priv_t);
|
||||
}
|
||||
@@ -996,9 +1042,8 @@ void dlr_device_construct(
|
||||
dev->construct_step++;
|
||||
} else {
|
||||
dleyna_gasync_task_add(queue_id,
|
||||
- prv_introspect,
|
||||
+ prv_introspect_rc,
|
||||
G_OBJECT(rc_proxy),
|
||||
- prv_introspect_rc_cb,
|
||||
cancellable,
|
||||
NULL, priv_t);
|
||||
}
|
||||
@@ -1007,11 +1052,11 @@ void dlr_device_construct(
|
||||
|
||||
/* The following task should always be completed */
|
||||
dleyna_gasync_task_add(queue_id, prv_subscribe, G_OBJECT(s_proxy),
|
||||
- NULL, NULL, NULL, dev);
|
||||
+ NULL, NULL, dev);
|
||||
|
||||
if (dev->construct_step < 5)
|
||||
dleyna_gasync_task_add(queue_id, prv_declare, G_OBJECT(s_proxy),
|
||||
- NULL, NULL, g_free, priv_t);
|
||||
+ NULL, g_free, priv_t);
|
||||
|
||||
dleyna_task_queue_start(queue_id);
|
||||
|
||||
diff --git a/libdleyna/renderer/gasync-task.c b/libdleyna/renderer/gasync-task.c
|
||||
index 47a0ad567cc2..0c65a22b6235 100644
|
||||
--- a/libdleyna/renderer/gasync-task.c
|
||||
+++ b/libdleyna/renderer/gasync-task.c
|
||||
@@ -25,9 +25,9 @@ struct dleyna_gasync_task_t_ {
|
||||
dleyna_task_atom_t base;
|
||||
dleyna_gasync_task_action action;
|
||||
GObject *target;
|
||||
- GAsyncReadyCallback callback;
|
||||
GCancellable *cancellable;
|
||||
GDestroyNotify free_func;
|
||||
+ gboolean current;
|
||||
gpointer cb_user_data;
|
||||
};
|
||||
|
||||
@@ -45,7 +45,6 @@ const char *dleyna_gasync_task_create_source(void)
|
||||
void dleyna_gasync_task_add(const dleyna_task_queue_key_t *queue_id,
|
||||
dleyna_gasync_task_action action,
|
||||
GObject *target,
|
||||
- GAsyncReadyCallback callback,
|
||||
GCancellable *cancellable,
|
||||
GDestroyNotify free_func,
|
||||
gpointer cb_user_data)
|
||||
@@ -55,7 +54,6 @@ void dleyna_gasync_task_add(const dleyna_task_queue_key_t *queue_id,
|
||||
task = g_new0(dleyna_gasync_task_t, 1);
|
||||
|
||||
task->action = action;
|
||||
- task->callback = callback;
|
||||
task->cancellable = cancellable;
|
||||
task->free_func = free_func;
|
||||
task->cb_user_data = cb_user_data;
|
||||
@@ -68,32 +66,13 @@ void dleyna_gasync_task_add(const dleyna_task_queue_key_t *queue_id,
|
||||
dleyna_task_queue_add_task(queue_id, &task->base);
|
||||
}
|
||||
|
||||
-void dleyna_gasync_task_ready_cb(GObject *source, GAsyncResult *res, gpointer user_data)
|
||||
-{
|
||||
- dleyna_gasync_task_t *task = (dleyna_gasync_task_t *)user_data;
|
||||
-
|
||||
- task->callback(source, res, task->cb_user_data);
|
||||
-
|
||||
- dleyna_task_queue_task_completed(task->base.queue_id);
|
||||
-}
|
||||
-
|
||||
void dleyna_gasync_task_process_cb(dleyna_task_atom_t *atom,
|
||||
gpointer user_data)
|
||||
{
|
||||
- gboolean failed = FALSE;
|
||||
-
|
||||
dleyna_gasync_task_t *task = (dleyna_gasync_task_t *)atom;
|
||||
|
||||
- failed = task->action(task, task->target);
|
||||
-
|
||||
- if (failed) {
|
||||
- dleyna_task_processor_cancel_queue(task->base.queue_id);
|
||||
- dleyna_task_queue_task_completed(task->base.queue_id);
|
||||
- }
|
||||
-
|
||||
- if (task->callback == NULL) {
|
||||
- dleyna_task_queue_task_completed(task->base.queue_id);
|
||||
- }
|
||||
+ task->current = TRUE;
|
||||
+ task->action(task, task->target);
|
||||
}
|
||||
|
||||
void dleyna_gasync_task_cancel_cb(dleyna_task_atom_t *atom,
|
||||
@@ -105,7 +84,8 @@ void dleyna_gasync_task_cancel_cb(dleyna_task_atom_t *atom,
|
||||
g_cancellable_cancel (task->cancellable);
|
||||
task->cancellable = NULL;
|
||||
|
||||
- dleyna_task_queue_task_completed(task->base.queue_id);
|
||||
+ if (task->current)
|
||||
+ dleyna_task_queue_task_completed(task->base.queue_id);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/libdleyna/renderer/gasync-task.h b/libdleyna/renderer/gasync-task.h
|
||||
index 629e48ce35a3..443c44153098 100644
|
||||
--- a/libdleyna/renderer/gasync-task.h
|
||||
+++ b/libdleyna/renderer/gasync-task.h
|
||||
@@ -36,7 +36,6 @@ const char *dleyna_gasync_task_create_source(void);
|
||||
void dleyna_gasync_task_add(const dleyna_task_queue_key_t *queue_id,
|
||||
dleyna_gasync_task_action action,
|
||||
GObject *target,
|
||||
- GAsyncReadyCallback callback,
|
||||
GCancellable *cancellable,
|
||||
GDestroyNotify free_func,
|
||||
gpointer cb_user_data);
|
||||
--
|
||||
2.28.0
|
||||
|
||||
70
dleyna-renderer.spec
Normal file
70
dleyna-renderer.spec
Normal file
@ -0,0 +1,70 @@
|
||||
%global api 1.0
|
||||
|
||||
Name: dleyna-renderer
|
||||
Version: 0.6.0
|
||||
Release: 1
|
||||
Summary: Service for interacting with Digital Media Renderers
|
||||
License: LGPLv2
|
||||
URL: https://01.org/dleyna/
|
||||
Source0: https://01.org/sites/default/files/downloads/dleyna/%{name}-%{version}.tar_2.gz
|
||||
Patch0: 0001-UPnP-Disconnect-signal-handlers-during-destruction.patch
|
||||
Patch1: 167.patch
|
||||
Patch2: 0001-Add-a-manual.patch
|
||||
Patch3: dleyna-renderer-Fix-the-cancellation-of-dleyna_gasync_task_t-tasks.patch
|
||||
|
||||
BuildRequires: autoconf automake docbook-style-xsl libtool libxslt pkgconfig pkgconfig(dleyna-core-1.0)
|
||||
BuildRequires: pkgconfig(gio-2.0) pkgconfig(glib-2.0) pkgconfig(gssdp-1.2) pkgconfig(gupnp-1.2)
|
||||
BuildRequires: pkgconfig(gupnp-av-1.0) pkgconfig(gupnp-dlna-2.0) pkgconfig(libsoup-2.4) make
|
||||
|
||||
Requires: dbus dleyna-connector-dbus
|
||||
|
||||
%description
|
||||
D-Bus service for clients to discover and manipulate DLNA Digital Media
|
||||
Renderers (DMRs).
|
||||
|
||||
%package devel
|
||||
Summary: Development files for %{name}
|
||||
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||
|
||||
%description devel
|
||||
The %{name}-devel package contains libraries and header files for
|
||||
developing applications that use %{name}.
|
||||
|
||||
%prep
|
||||
%autosetup -p1
|
||||
|
||||
%build
|
||||
autoreconf -f -i
|
||||
%configure \
|
||||
--disable-silent-rules \
|
||||
--disable-static
|
||||
|
||||
sed --in-place --expression 's! -shared ! -Wl,--as-needed\0!g' libtool
|
||||
|
||||
%make_build
|
||||
|
||||
%install
|
||||
%make_install
|
||||
find $RPM_BUILD_ROOT -name '*.la' -delete
|
||||
|
||||
rm -rf $RPM_BUILD_ROOT/%{_includedir}
|
||||
rm -f $RPM_BUILD_ROOT/%{_libdir}/%{name}/libdleyna-renderer-%{api}.so
|
||||
|
||||
%files
|
||||
%license COPYING
|
||||
%doc AUTHORS
|
||||
%doc ChangeLog
|
||||
%doc README
|
||||
%{_datadir}/dbus-1/services/com.intel.%{name}.service
|
||||
%{_datadir}/man/man5/%{name}-service.conf.5*
|
||||
%dir %{_libdir}/%{name}
|
||||
%{_libdir}/%{name}/libdleyna-renderer-%{api}.so.*
|
||||
%{_libexecdir}/%{name}-service
|
||||
%config(noreplace) %{_sysconfdir}/%{name}-service.conf
|
||||
|
||||
%files devel
|
||||
%{_libdir}/pkgconfig/dleyna-renderer-service-%{api}.pc
|
||||
|
||||
%changelog
|
||||
* Fri Jul 02 2021 weijin deng <weijin.deng@turbolinux.com.cn> - 0.6.0-1
|
||||
- Package init with 0.6.0
|
||||
Loading…
x
Reference in New Issue
Block a user