Skip to content
Commits on Source (14)
include:
- remote: "https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/290b79e0e78eab67a83766f4e9691be554fc4afd/templates/ci-fairy.yml"
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/290b79e0e78eab67a83766f4e9691be554fc4afd/templates/fedora.yml'
- remote: "https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/0c312d9c7255f46e741d43bcd1930f09cd12efe7/templates/ci-fairy.yml"
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/0c312d9c7255f46e741d43bcd1930f09cd12efe7/templates/fedora.yml'
variables:
MESON_TEST_TIMEOUT_MULTIPLIER: 3
......@@ -61,23 +61,23 @@ check-merge-request:
.gupnp_tools.fedora@common:
variables:
BASE_TAG: '2021-06-19.0'
BASE_TAG: '2022-05-20.0'
FDO_UPSTREAM_REPO: GNOME/gupnp-tools
FDO_DISTRIBUTION_PACKAGES: 'clang clang-analyzer gcovr git libasan libubsan python3-gobject python3-pip xmlto gobject-introspection-devel gtk-doc libsoup-devel libuuid-devel libxml2-devel vala ninja-build gtk3-devel gtksourceview4-devel'
FDO_DISTRIBUTION_PACKAGES: 'clang clang-analyzer gcovr git libasan libubsan python3-gobject python3-pip xmlto gobject-introspection-devel gtk-doc libsoup3-devel libuuid-devel libxml2-devel vala ninja-build gtk3-devel gtksourceview4-devel'
FDO_DISTRIBUTION_EXEC: |
dnf clean all &&
pip3 install meson
.gupnp_tools.fedora:34@x86_64:
.gupnp_tools.fedora:36@x86_64:
extends: .gupnp_tools.fedora@common
variables:
FDO_DISTRIBUTION_VERSION: 34
FDO_DISTRIBUTION_VERSION: 36
FDO_DISTRIBUTION_TAG: "x86_64-${BASE_TAG}"
build-fedora-container@x86_64:
extends:
- .fdo.container-build@fedora
- .gupnp_tools.fedora:34@x86_64
- .gupnp_tools.fedora:36@x86_64
stage: prepare
variables:
GIT_STRATEGY: none
......@@ -86,7 +86,7 @@ build-fedora-container@x86_64:
build-fedora@x86_64:
extends:
- .fdo.distribution-image@fedora
- .gupnp_tools.fedora:34@x86_64
- .gupnp_tools.fedora:36@x86_64
needs:
- build-fedora-container@x86_64
<<: *build
......@@ -128,7 +128,7 @@ build-fedora@x86_64:
test-fedora@x86_64:
extends:
- .fdo.distribution-image@fedora
- .gupnp_tools.fedora:34@x86_64
- .gupnp_tools.fedora:36@x86_64
needs:
- build-fedora@x86_64
<<: *test
......@@ -144,7 +144,7 @@ test-fedora@x86_64:
#coverage-analysis:
# extends:
# - .fdo.distribution-image@fedora
# - .gupnp_tools.fedora:34@x86_64
# - .gupnp_tools.fedora:36@x86_64
# stage: analysis
# allow_failure: true
# script:
......@@ -162,7 +162,7 @@ test-fedora@x86_64:
static-scan:
extends:
- .fdo.distribution-image@fedora
- .gupnp_tools.fedora:34@x86_64
- .gupnp_tools.fedora:36@x86_64
stage: analysis
needs:
- build-fedora-container@x86_64
......@@ -177,7 +177,7 @@ static-scan:
#pages:
# extends:
# - .fdo.distribution-image@fedora
# - .gupnp_tools.fedora:34@x86_64
# - .gupnp_tools.fedora:36@x86_64
# stage: website
# script:
# - meson doc-build -Dgtk_doc=true
......
0.10.3 (stable)
0.12.0 (stable)
===============
- Fix deprecated function calls
- Fix empty icon for devices with no icons
- Translation updates
Dependency changes:
- GLib required is now 2.68
- GUPnP requirement up to 1.6
- Libsoup requirement up to 3.0
- All
- Port to GUPnP 1.6 and Libsoup3
- Fix inconsistencies regarding action errors
- Use more g_autoptr
- Drop gupnp_get_uuid() where used.
- Translation updates
- Common
- Fix potential NULL pointer dereference
- Use GUPnP utility functions for download of icons
- Universal CP:
- Fix missing icon on download error
- Fix uninitialized out value
- Event Dumper:
- Added new tool for dumping UPnP events on command line
Bugs fixed in this release:
- https://gitlab.gnome.org/GNOME/gupnp-tools/issues/23
Merge requests included in this release:
- https://gitlab.gnome.org/GNOME/gupnp-tools/merge_requests/4
All contributors to this release:
- Jens Georg <mail@jensge.org>
- Jürgen Benvenuti <gastornis@posteo.org>
- Sabri Ünal <libreajans@gmail.com>
- Hugo Carvalho <hugokarvalho@hotmail.com>
- Luming Zh <lumingzh@qq.com>
......@@ -18,6 +41,7 @@ All contributors to this release:
Added/updated translations:
- da.po, courtesy of Alan Mortensen
- de.po, courtesy of Jürgen Benvenuti
- eu.po, courtesy of Asier Sarasua Garmendia
- pt.po, courtesy of Hugo Carvalho
- tr.po, courtesy of Sabri Ünal
......
......@@ -5,3 +5,5 @@
#mesondefine DATA_DIR
#mesondefine GETTEXT_PACKAGE
#mesondefine LOCALEDIR
#mesondefine GLIB_VERSION_MIN_REQUIRED
#mesondefine GLIB_VERSION_MAX_ALLOWED
project('gupnp-tools', ['c'], version: '0.10.3')
project('gupnp-tools', ['c'], version: '0.12.0')
gnome = import('gnome')
i18n = import('i18n')
......@@ -7,17 +7,18 @@ if host_machine.system() == 'windows'
win = import('windows')
endif
gssdp = dependency('gssdp-1.2', version: '>= 1.2.0', default_options: ['sniffer=false'])
gupnp = dependency('gupnp-1.2', version: '>= 1.4.0')
soup = dependency('libsoup-2.4', version: '>= 2.42')
gssdp = dependency('gssdp-1.6', version: '>= 1.6.0', default_options: ['sniffer=false'])
gupnp = dependency('gupnp-1.6', version: '>= 1.6.0')
soup = dependency('libsoup-3.0', version: '>= 3.0')
gupnp_av = dependency('gupnp-av-1.0', version: '>= 0.5.5', required: get_option('av-tools'))
gtk = dependency('gtk+-3.0', version: '>= 3.10')
glib = dependency('glib-2.0', version: '>= 2.24')
gio = dependency('gio-2.0', version: '>= 2.24')
glib_version = '2.68'
glib = dependency('glib-2.0', version: '>= ' + glib_version)
gio = dependency('gio-2.0', version: '>= ' + glib_version)
libxml = dependency('libxml-2.0', version: '>= 2.0')
gobject = dependency('gobject-2.0', version: '>= 2.24')
gobject = dependency('gobject-2.0', version: '>= ' + glib_version)
# Check for gtksourceview (used for XML syntax highlighting)
# Check for gtksourceview (used for XML syntax highlighting)
gtksourceview = dependency('gtksourceview-4', required: false)
if not gtksourceview.found()
gtksourceview = dependency('gtksourceview-3.0', version: '>= 3.2.0', required: false)
......@@ -42,9 +43,14 @@ conf.set('DATA_DIR', '"@0@"'.format(shareddir))
conf.set('HAVE_GTK_SOURCEVIEW', gtksourceview.found())
conf.set('GETTEXT_PACKAGE', '"@0@"'.format(meson.project_name()))
conf.set('LOCALEDIR', '"@0@"'.format(localedir))
cc = meson.get_compiler('c')
add_project_arguments(cc.get_supported_arguments('-Werror=deprecated-declarations'), language: 'c')
conf.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_@0@'.format(glib_version.underscorify()))
conf.set('GLIB_VERSION_MAX_ALLOWED', 'GLIB_VERSION_@0@'.format(glib_version.underscorify()))
configure_file(input: 'config.h.meson', output: 'config.h', configuration: conf)
config_header = declare_dependency(compile_args : '-DHAVE_CONFIG_H=1', include_directories : include_directories('.'))
config_header = declare_dependency(include_directories : include_directories('.'))
subdir('data')
subdir('src')
......
......@@ -3,21 +3,22 @@
# This file is distributed under the same license as the gupnp-tools package.
# Mario Blättermann <mario.blaettermann@gmail.com>, 2013, 2016-2018.
# Christian Kirbach <christian.kirbach@gmail.com>, 2013.
# Jürgen Benvenuti <gastornis@posteo.org>, 2022.
#
msgid ""
msgstr ""
"Project-Id-Version: gupnp-tools master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gupnp-tools/issues\n"
"POT-Creation-Date: 2018-12-02 11:50+0000\n"
"PO-Revision-Date: 2019-03-02 21:19+0100\n"
"Last-Translator: Bernd Homuth <dev@hmt.im>\n"
"POT-Creation-Date: 2022-05-14 11:52+0000\n"
"PO-Revision-Date: 2022-07-12 10:27+0200\n"
"Last-Translator: Jürgen Benvenuti <gastornis@posteo.org>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.2.1\n"
"X-Generator: Poedit 3.1\n"
#: data/didl-lite-dialog.ui.in:9
msgid "GUPnP AV CP - Metadata View"
......@@ -31,11 +32,6 @@ msgstr "UPnP AV-Kontrollpunkt"
msgid "Browse and control UPnP multimedia devices"
msgstr "UPnP-Multimediageräte durchsuchen und steuern"
#. Translators: Do NOT translate or transliterate this text (this is an icon file name)!
#: data/gupnp-av-cp.desktop.in:9
msgid "av-cp"
msgstr "av-cp"
#: data/gupnp-av-cp.ui:22 data/gupnp-av-cp.ui:208
msgid "_Play"
msgstr "_Wiedergabe"
......@@ -140,7 +136,8 @@ msgstr "GUPnP-Homepage"
msgid "translator-credits"
msgstr ""
"Christian Kirbach <christian.kirbach@gmail.com>\n"
"Mario Blättermann <mario.blaettermann@gmail.com>"
"Mario Blättermann <mario.blaettermann@gmail.com>\n"
"Jürgen Benvenuti <gastornis@posteo.org>"
#: data/gupnp-network-light.desktop.in:4
msgid "UPnP Network Light"
......@@ -150,11 +147,6 @@ msgstr "UPnP Network Light"
msgid "Sample UPnP application for controlling lights"
msgstr "UPnP-Beispielanwendung zur Lichtsteuerung"
#. Translators: Do NOT translate or transliterate this text (this is an icon file name)!
#: data/gupnp-network-light.desktop.in:9
msgid "network-light-256x256"
msgstr "network-light-256x256"
#: data/gupnp-network-light.ui:8
msgid ""
"A virtual network light bulb based on GUPnP framework.\n"
......@@ -193,11 +185,6 @@ msgid "Inspect and control UPnP devices across your local network"
msgstr ""
"UPnP-Multimediageräte in Ihrem lokalen Netzwerk untersuchen und steuern"
#. Translators: Do NOT translate or transliterate this text (this is an icon file name)!
#: data/gupnp-universal-cp.desktop.in:9
msgid "universal-cp"
msgstr "universal-cp"
#: data/gupnp-universal-cp.ui:9
msgid ""
"A Generic Control Point based on GUPnP framework.\n"
......@@ -291,86 +278,118 @@ msgstr "_Ansicht"
msgid "Event _log"
msgstr "_Ereignismitschnitt"
#: data/search-dialog.ui:12
msgid "Show _DIDL…"
msgstr "_DIDL anzeigen …"
#: data/search-dialog.ui:49
#: data/search-dialog.ui:39
msgid "_Close"
msgstr "S_chließen"
#: data/search-dialog.ui:81
#: data/search-dialog.ui:71
msgid "UPnP search expression"
msgstr "UPnP-Suchausdruck"
#: data/search-dialog.ui:107
#: data/search-dialog.ui:98
msgid "column"
msgstr "Spalte"
#: src/av-cp/main.c:49 src/network-light/main.c:48 src/universal-cp/main.c:41
#: src/av-cp/main.c:52 src/network-light/main.c:51 src/universal-cp/main.c:51
msgid "Network PORT to use for UPnP"
msgstr "Netzwerk-Port, der für UPnP-Kommunikation verwendet werden soll"
#: src/av-cp/main.c:50 src/network-light/main.c:49 src/universal-cp/main.c:42
#: src/av-cp/main.c:53 src/network-light/main.c:52 src/universal-cp/main.c:52
msgid "Network interfaces to use for UPnP communication"
msgstr ""
"Netzwerkschnittstellen, die für UPnP-Kommunikation verwendet werden sollen"
#: src/av-cp/main.c:51
#: src/av-cp/main.c:54
msgid "Application part of the User-Agent header to use for UPnP communication"
msgstr ""
"Anwendungsbezeichnung im Kopf des User-Agents, die für UPnP-Kommunikation "
"verwendet werden soll"
#: src/av-cp/main.c:225 src/network-light/main.c:104
#: src/universal-cp/main.c:149
#: src/av-cp/main.c:55 src/universal-cp/main.c:53
msgid "Use the IPv4 protocol family"
msgstr "Die IPv4-Protokoll-Familie verwenden"
#: src/av-cp/main.c:56 src/universal-cp/main.c:54
msgid "Use the IPv6 protocol family"
msgstr "Die IPv6-Protokoll-Familie verwenden"
#: src/av-cp/main.c:57 src/universal-cp/main.c:55
msgid "Do not use the IPv4 protocol family"
msgstr "Die IPv4-Protokoll-Familie nicht verwenden"
#: src/av-cp/main.c:58 src/universal-cp/main.c:56
msgid "Do not use the IPv6 protocol family"
msgstr "Die IPv6-Protokoll-Familie nicht verwenden"
#: src/av-cp/main.c:241 src/network-light/main.c:112
#: src/universal-cp/main.c:194
msgid "- UPnP AV control point"
msgstr "- UPnP AV-Kontrollpunkt"
#: src/av-cp/main.c:230 src/network-light/main.c:109
#: src/universal-cp/main.c:154
#: src/av-cp/main.c:246 src/network-light/main.c:117
#: src/universal-cp/main.c:199
#, c-format
msgid "Could not parse options: %s\n"
msgstr "Optionen konnten nicht analysiert werden: %s\n"
#: src/av-cp/search-dialog.c:440 src/av-cp/search-dialog.c:579
#: src/av-cp/search-dialog.c:384
msgid "Show _DIDL…"
msgstr "_DIDL anzeigen …"
#: src/av-cp/search-dialog.c:478 src/av-cp/search-dialog.c:627
msgid "Search failed"
msgstr "Suche fehlgeschlagen"
#: src/av-cp/search-dialog.c:444
#: src/av-cp/search-dialog.c:482
#, c-format
msgid "Error message was: %s"
msgstr "Fehlermeldung war: %s"
#: src/av-cp/search-dialog.c:488
#: src/av-cp/search-dialog.c:530
#, c-format
msgid "Searching on %s"
msgstr "Suchen auf »%s«"
#: src/av-cp/search-dialog.c:491
#: src/av-cp/search-dialog.c:533
#, c-format
msgid "Searching in %s on %s"
msgstr "Suchen in »%s« auf »%s«"
#: src/av-cp/search-dialog.c:583
#: src/av-cp/search-dialog.c:631
#, c-format
msgid "Search criteria invalid: %s"
msgstr "Ungültige Suchkriterien angegeben: %s"
#: src/av-cp/search-dialog.c:689
#: src/av-cp/search-dialog.c:736
#, c-format
msgid "Error fetching detailed information: %s"
msgstr "Fehler beim Holen detaillierter Informationen: %s"
#: src/network-light/main.c:50
#: src/network-light/main.c:53
msgid "Friendly name for this UPnP light"
msgstr "Freundlicher Name für dieses UPnP-Light"
#: src/network-light/main.c:51
#: src/network-light/main.c:54
msgid "Apply change exclusively to this UPnP light"
msgstr "Änderung exklusiv auf dieses UPnP-Light anwenden"
#: src/universal-cp/action-dialog.c:693
#: src/network-light/main.c:55
msgid "Use IPv4"
msgstr "IPv4 verwenden"
#: src/network-light/main.c:56
msgid "Use IPv6"
msgstr "IPv6 verwenden"
#: src/network-light/main.c:57
msgid "Do not use IPv4"
msgstr "IPv4 nicht verwenden"
#: src/network-light/main.c:58
msgid "Do not use IPv6"
msgstr "IPv6 nicht verwenden"
#: src/universal-cp/action-dialog.c:690 src/universal-cp/action-dialog.c:709
#, c-format
msgid ""
"Action failed.\n"
......@@ -520,7 +539,7 @@ msgid "Presentation URL"
msgstr "Anzeigeadresse"
#: src/universal-cp/details-treeview.c:432
#: src/universal-cp/event-treeview.c:410
#: src/universal-cp/event-treeview.c:414
msgid "Value"
msgstr "Wert"
......@@ -536,30 +555,43 @@ msgstr "Version"
msgid "Author"
msgstr "Autor"
#: src/universal-cp/device-treeview.c:483
#: src/universal-cp/device-treeview.c:489
msgid "State variables"
msgstr "Zustandsvariablen"
#: src/universal-cp/device-treeview.c:524
#: src/universal-cp/device-treeview.c:530
msgid "Information not available"
msgstr "Information nicht verfügbar"
#: src/universal-cp/device-treeview.c:703
#: src/universal-cp/device-treeview.c:709
msgid "UPnP Network"
msgstr "UPnP-Netzwerk"
#: src/universal-cp/device-treeview.c:716 src/universal-cp/event-treeview.c:407
#: src/universal-cp/device-treeview.c:722 src/universal-cp/event-treeview.c:411
msgid "Device"
msgstr "Gerät"
#: src/universal-cp/event-treeview.c:406
#: src/universal-cp/event-treeview.c:410
msgid "Time"
msgstr "Zeit"
#: src/universal-cp/event-treeview.c:408
#: src/universal-cp/event-treeview.c:412
msgid "Service"
msgstr "Dienste"
#: src/universal-cp/event-treeview.c:409
#: src/universal-cp/event-treeview.c:413
msgid "State Variable"
msgstr "Zustandsvariable"
#: src/universal-cp/main.c:57
msgid "The UDA version to use"
msgstr "Die UDA-Version, die verwendet werden soll"
#~ msgid "av-cp"
#~ msgstr "av-cp"
#~ msgid "network-light-256x256"
#~ msgstr "network-light-256x256"
#~ msgid "universal-cp"
#~ msgstr "universal-cp"
......@@ -18,6 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <config.h>
#include "didl-dialog.h"
#include "pretty-print.h"
......
#include <config.h>
#include "entry-completion.h"
#include <libgupnp-av/gupnp-av.h>
......@@ -198,4 +200,4 @@ entry_completion_set_search_criteria (EntryCompletion *self, char const * const
-1);
it++;
}
}
\ No newline at end of file
}
......@@ -18,12 +18,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gmodule.h>
#include <stdlib.h>
#include <string.h>
#include "gui.h"
#include "playlist-treeview.h"
......
......@@ -20,9 +20,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <libgupnp/gupnp-control-point.h>
#include <libgupnp-av/gupnp-av.h>
......
......@@ -18,11 +18,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <config.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gmodule.h>
#include "playlist-treeview.h"
......@@ -1024,7 +1024,6 @@ remove_media_server (GUPnPDeviceProxy *proxy)
compare_media_server,
(gpointer) udn,
FALSE)) {
unschedule_icon_update (info);
gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
}
}
......
......@@ -18,11 +18,10 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include "renderer-combo.h"
#include "renderer-controls.h"
......@@ -340,12 +339,20 @@ set_duration (const gchar *udn,
}
static void
on_device_icon_available (GUPnPDeviceInfo *info,
GdkPixbuf *icon)
on_device_icon_available (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
GtkTreeModel *model;
GtkTreeIter iter;
const char *udn;
g_autoptr (GdkPixbuf) icon;
g_autoptr (GError) error = NULL;
icon = update_icon_finish (GUPNP_DEVICE_INFO (source), res, &error);
if (error != NULL) {
g_debug ("Failed to download icon: %s", error->message);
}
if (icon == NULL)
return;
......@@ -353,7 +360,7 @@ on_device_icon_available (GUPnPDeviceInfo *info,
model = gtk_combo_box_get_model (GTK_COMBO_BOX (renderer_combo));
g_assert (model != NULL);
udn = gupnp_device_info_get_udn (info);
udn = gupnp_device_info_get_udn (GUPNP_DEVICE_INFO (source));
if (find_renderer (model, udn, &iter)) {
gtk_list_store_set (GTK_LIST_STORE (model),
......@@ -362,7 +369,7 @@ on_device_icon_available (GUPnPDeviceInfo *info,
-1);
}
g_object_unref (icon);
g_object_set_data (source, "icon-download-cancellable", NULL);
}
static void
......@@ -516,7 +523,12 @@ append_media_renderer_to_tree (GUPnPDeviceProxy *proxy,
gupnp_service_proxy_set_subscribed (av_transport, TRUE);
gupnp_service_proxy_set_subscribed (rendering_control, TRUE);
schedule_icon_update (info, on_device_icon_available);
GCancellable *cancellable = g_cancellable_new ();
g_object_set_data_full (G_OBJECT (info),
"icon-download-cancellable",
cancellable,
g_object_unref);
update_icon_async (info, cancellable, on_device_icon_available, NULL);
if (was_empty)
gtk_combo_box_set_active_iter (combo, &iter);
......@@ -846,7 +858,16 @@ remove_media_renderer (GUPnPDeviceProxy *proxy)
model = gtk_combo_box_get_model (combo);
if (find_renderer (model, udn, &iter)) {
unschedule_icon_update (info);
GCancellable *cancellable =
g_object_get_data (G_OBJECT (info),
"icon-download-cancellable");
if (cancellable != NULL) {
g_cancellable_cancel (cancellable);
g_object_set_data (G_OBJECT (info),
"icon-download-cancellable",
NULL);
}
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
gtk_combo_box_set_active (combo, 0);
}
......
......@@ -18,11 +18,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <config.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gtk/gtk.h>
#include <gmodule.h>
......
......@@ -18,6 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <config.h>
#include <glib/gi18n.h>
#include <libgupnp-av/gupnp-av.h>
......
......@@ -18,6 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <config.h>
#include <string.h>
#include "server-device.h"
......@@ -150,8 +152,9 @@ av_cp_media_server_get_property (GObject *obj,
}
static void
av_cp_media_server_on_icon_updated (GUPnPDeviceInfo *info,
GdkPixbuf *icon);
av_cp_media_server_on_icon_updated (GObject *source,
GAsyncResult *res,
gpointer user_data);
static void
av_cp_media_server_on_get_sort_caps (GObject *object,
......@@ -308,13 +311,20 @@ av_cp_media_server_init (AVCPMediaServer *self)
}
static void
av_cp_media_server_on_icon_updated (GUPnPDeviceInfo *info,
GdkPixbuf *icon)
av_cp_media_server_on_icon_updated (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
AVCPMediaServer *self = AV_CP_MEDIA_SERVER (info);
AVCPMediaServer *self = AV_CP_MEDIA_SERVER (source);
AVCPMediaServerPrivate *priv = av_cp_media_server_get_instance_private (self);
g_autoptr (GError) error = NULL;
priv->icon =
update_icon_finish (GUPNP_DEVICE_INFO (source), res, &error);
if (error != NULL) {
g_debug ("Failed to download device icon: %s", error->message);
}
priv->icon = icon;
av_cp_media_server_get_content_directory (self);
if (priv->content_directory != NULL) {
......@@ -401,8 +411,10 @@ av_cp_media_server_init_finish (GAsyncInitable *initable,
static void
av_cp_media_server_introspect (AVCPMediaServer *self)
{
schedule_icon_update (GUPNP_DEVICE_INFO (self),
av_cp_media_server_on_icon_updated);
update_icon_async (GUPNP_DEVICE_INFO (self),
NULL,
av_cp_media_server_on_icon_updated,
NULL);
}
static void
......
......@@ -18,9 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <stdlib.h>
......@@ -39,11 +37,6 @@ static SoupSession *download_session;
static GList *pending_gets;
typedef struct {
GUPnPDeviceInfo *info;
DeviceIconAvailableCallback callback;
SoupMessage *message;
gchar *mime_type;
gint width;
gint height;
......@@ -52,35 +45,34 @@ typedef struct {
static void
get_icon_url_data_free (GetIconURLData *data)
{
g_object_unref (data->info);
g_free (data->mime_type);
g_slice_free (GetIconURLData, data);
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GetIconURLData, get_icon_url_data_free)
static GdkPixbuf *
get_icon_from_message (SoupMessage *msg,
GetIconURLData *data,
GError **error)
get_icon_from_bytes (GBytes *icon_data,
const char *mime,
int source_width,
int source_height,
GError **error)
{
GdkPixbufLoader *loader;
g_autoptr (GdkPixbufLoader) loader;
GdkPixbuf *pixbuf;
loader = gdk_pixbuf_loader_new_with_mime_type (data->mime_type, error);
loader = gdk_pixbuf_loader_new_with_mime_type (mime, error);
if (loader == NULL)
return NULL;
gdk_pixbuf_loader_write (loader,
(guchar *) msg->response_body->data,
msg->response_body->length,
error);
gdk_pixbuf_loader_write_bytes (loader, icon_data, error);
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
if (pixbuf) {
gfloat aspect_ratio;
gint height;
/* Preserve the aspect-ratio of the original image */
aspect_ratio = (gfloat) data->width / data->height;
aspect_ratio = (gfloat) source_width / source_height;
height = (gint) (PREFERED_WIDTH / aspect_ratio);
pixbuf = gdk_pixbuf_scale_simple (pixbuf,
PREFERED_WIDTH,
......@@ -89,7 +81,6 @@ get_icon_from_message (SoupMessage *msg,
}
gdk_pixbuf_loader_close (loader, NULL);
g_object_unref (loader);
return pixbuf;
}
......@@ -97,123 +88,72 @@ get_icon_from_message (SoupMessage *msg,
/**
* Icon downloaded.
**/
static void
got_icon_url (SoupSession *session,
SoupMessage *msg,
GetIconURLData *data)
{
GdkPixbuf *pixbuf = NULL;
if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
GError *error = NULL;
pixbuf = get_icon_from_message (msg, data, &error);
if (error) {
g_warning ("Failed to create icon for '%s': %s",
gupnp_device_info_get_udn (data->info),
error->message);
g_error_free (error);
} else if (!pixbuf) {
g_warning ("Failed to create icon for '%s'",
gupnp_device_info_get_udn (data->info));
}
}
data->callback (data->info, pixbuf);
pending_gets = g_list_remove (pending_gets, data);
get_icon_url_data_free (data);
}
static gboolean
on_icon_schedule_error (gpointer user_data)
static void
on_got_icon (GObject *source, GAsyncResult *res, gpointer user_data)
{
GetIconURLData *data = (GetIconURLData *) user_data;
GError *error = NULL;
g_autoptr (GTask) task = G_TASK (user_data);
g_autofree char *mime = NULL;
int width;
int height;
g_autoptr (GBytes) icon =
gupnp_device_info_get_icon_finish (GUPNP_DEVICE_INFO (source),
res,
&mime,
NULL,
&width,
&height,
&error);
data->callback (data->info, NULL);
g_object_unref (data->info);
g_slice_free (GetIconURLData, data);
if (error != NULL) {
g_task_return_error (task, error);
return FALSE;
}
void
schedule_icon_update (GUPnPDeviceInfo *info,
DeviceIconAvailableCallback callback)
{
GetIconURLData *data;
char *icon_url;
data = g_slice_new0 (GetIconURLData);
data->info = g_object_ref (info);
data->callback = callback;
icon_url = gupnp_device_info_get_icon_url
(info,
NULL,
PREFERED_DEPTH,
PREFERED_WIDTH,
PREFERED_HEIGHT,
TRUE,
&data->mime_type,
NULL,
&data->width,
&data->height);
if (icon_url == NULL) {
g_free (data->mime_type);
g_idle_add (on_icon_schedule_error, data);
return;
}
char *new_uri = gupnp_context_rewrite_uri (gupnp_device_info_get_context (info), icon_url);
g_free (icon_url);
data->message = soup_message_new (SOUP_METHOD_GET, new_uri);
if (data->message == NULL) {
g_warning ("Invalid URL icon for device '%s': %s",
gupnp_device_info_get_udn (info),
new_uri);
GdkPixbuf *device_icon = icon == NULL ? NULL
: get_icon_from_bytes (icon,
mime,
width,
height,
&error);
g_free (new_uri);
g_free (data->mime_type);
g_idle_add (on_icon_schedule_error, data);
if (error != NULL) {
g_task_return_error (task, error);
return;
}
pending_gets = g_list_prepend (pending_gets, data);
soup_session_queue_message (download_session,
data->message,
(SoupSessionCallback) got_icon_url,
data);
g_free (new_uri);
g_task_return_pointer (task, device_icon, g_object_unref);
}
void
unschedule_icon_update (GUPnPDeviceInfo *info)
update_icon_async (GUPnPDeviceInfo *info,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GList *gets;
for (gets = pending_gets; gets; gets = gets->next) {
GetIconURLData *data;
const char *udn1;
const char *udn2;
data = gets->data;
udn1 = gupnp_device_info_get_udn (info);
udn2 = gupnp_device_info_get_udn (data->info);
if (udn1 && udn2 && strcmp (udn1, udn2) == 0) {
soup_session_cancel_message (download_session,
data->message,
SOUP_STATUS_CANCELLED);
break;
}
}
GTask *task = g_task_new (info, cancellable, callback, user_data);
gupnp_device_info_get_icon_async (info,
NULL,
PREFERED_DEPTH,
PREFERED_WIDTH,
PREFERED_HEIGHT,
TRUE,
cancellable,
on_got_icon,
task);
}
GdkPixbuf *
update_icon_finish (GUPnPDeviceInfo *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);
}
GdkPixbuf *
......@@ -329,16 +269,6 @@ deinit_icons (void)
{
int i;
while (pending_gets) {
GetIconURLData *data;
data = pending_gets->data;
soup_session_cancel_message (download_session,
data->message,
SOUP_STATUS_CANCELLED);
}
g_object_unref (download_session);
for (i = 0; i < ICON_LAST; i++) {
......
......@@ -46,15 +46,14 @@ typedef enum
ICON_LAST
} IconID;
typedef void (* DeviceIconAvailableCallback) (GUPnPDeviceInfo *info,
GdkPixbuf *icon);
void
schedule_icon_update (GUPnPDeviceInfo *info,
DeviceIconAvailableCallback callback);
update_icon_async (GUPnPDeviceInfo *info,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
void
unschedule_icon_update (GUPnPDeviceInfo *info);
GdkPixbuf *
update_icon_finish (GUPnPDeviceInfo *info, GAsyncResult *res, GError **error);
GdkPixbuf *
get_icon_by_id (IconID icon_id);
......
......@@ -7,6 +7,6 @@ util_resource = gnome.compile_resources('common-resource',
)
libutil = static_library('util', ['icons.c', 'icons.h', 'pretty-print.c', 'pretty-print.h'] + util_resource,
dependencies : [libxml, soup, gupnp, gtk])
dependencies : [libxml, soup, gupnp, gtk, config_header])
util = declare_dependency(link_with: libutil, include_directories : include_directories('.'))
......@@ -18,6 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <config.h>
#include "pretty-print.h"
#include <libxml/xmlreader.h>
......
......@@ -21,6 +21,8 @@
* Boston, MA 02111-1307, USA.
*/
#include <config.h>
#include <glib.h>
#include <libgssdp/gssdp.h>
#include <stdlib.h>
......@@ -87,10 +89,6 @@ int main (int argc, char *argv[]) {
GOptionContext *context;
GSSDPDiscover discover;
#if !GLIB_CHECK_VERSION(2, 35, 0)
g_type_init ();
#endif
context = g_option_context_new ("- discover devices using SSDP");
g_option_context_add_main_entries (context, entries, NULL);
......@@ -102,7 +100,11 @@ int main (int argc, char *argv[]) {
g_option_context_free (context);
discover.client = gssdp_client_new (interface, &error);
discover.client = gssdp_client_new_full (interface,
NULL,
0,
GSSDP_UDA_VERSION_1_0,
&error);
if (error != NULL) {
g_warning ("Failed to create GSSDP client: %s", error->message);
g_error_free (error);
......
executable('gssdp-discover', ['gssdp-discover.c'], dependencies : [gssdp, gobject], install: true)
executable('gssdp-discover', ['gssdp-discover.c'], dependencies : [gssdp, gobject, config_header], install: true)