!1 Package init with 0.6.0

From: @weijin-deng
Reviewed-by: @dwl301
Signed-off-by: @dwl301
This commit is contained in:
openeuler-ci-bot 2021-07-02 03:07:35 +00:00 committed by Gitee
commit d4a468047c
6 changed files with 1738 additions and 0 deletions

264
0001-Add-a-manual.patch Normal file
View 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

View File

@ -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
View 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 */

Binary file not shown.

View File

@ -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
View 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