summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Georg <mail@jensge.org>2022-01-03 11:07:59 +0100
committerJens Georg <mail@jensge.org>2022-01-03 19:10:51 +0100
commitd2ad83d588759d005c7a3bae87f7523666e9a733 (patch)
tree35de8ceeb48fe817dfc03c5026150b7c35af1c8f
parent79a2cb24cd0079e9a025809d11dce13edce68bdd (diff)
downloadgupnp-d2ad83d588759d005c7a3bae87f7523666e9a733.tar.gz
docs: Use gi-docgen instead of gtk-doc
-rw-r--r--doc/choosing-a-context-manager.md20
-rw-r--r--doc/client-tutorial.md215
-rw-r--r--doc/glossary.md115
-rw-r--r--doc/gupnp.toml.in54
-rw-r--r--doc/images/gupnp-logo-short.svg126
-rw-r--r--doc/meson.build67
-rw-r--r--doc/server-tutorial.md373
-rw-r--r--doc/urlmap.js4
-rw-r--r--libgupnp/gupnp-acl.c59
-rw-r--r--libgupnp/gupnp-acl.h21
-rw-r--r--libgupnp/gupnp-connman-manager.c5
-rw-r--r--libgupnp/gupnp-context-filter.c66
-rw-r--r--libgupnp/gupnp-context-manager.c94
-rw-r--r--libgupnp/gupnp-context.c43
-rw-r--r--libgupnp/gupnp-context.h9
-rw-r--r--libgupnp/gupnp-control-point.c64
-rw-r--r--libgupnp/gupnp-device-info.c234
-rw-r--r--libgupnp/gupnp-device-proxy.c15
-rw-r--r--libgupnp/gupnp-device.c18
-rw-r--r--libgupnp/gupnp-error.h24
-rw-r--r--libgupnp/gupnp-linux-context-manager.c2
-rw-r--r--libgupnp/gupnp-resource-factory.c18
-rw-r--r--libgupnp/gupnp-root-device.c66
-rw-r--r--libgupnp/gupnp-root-device.h6
-rw-r--r--libgupnp/gupnp-service-action.c4
-rw-r--r--libgupnp/gupnp-service-info.c30
-rw-r--r--libgupnp/gupnp-service-info.h7
-rw-r--r--libgupnp/gupnp-service-introspection.c43
-rw-r--r--libgupnp/gupnp-service-introspection.h2
-rw-r--r--libgupnp/gupnp-service-proxy-action.c32
-rw-r--r--libgupnp/gupnp-service-proxy.c42
-rw-r--r--libgupnp/gupnp-service-proxy.h8
-rw-r--r--libgupnp/gupnp-service.c182
-rw-r--r--libgupnp/gupnp-service.h14
-rw-r--r--libgupnp/gupnp-types.h12
-rw-r--r--meson.build6
-rw-r--r--subprojects/gi-docgen.wrap7
37 files changed, 1622 insertions, 485 deletions
diff --git a/doc/choosing-a-context-manager.md b/doc/choosing-a-context-manager.md
new file mode 100644
index 0000000..bc98595
--- /dev/null
+++ b/doc/choosing-a-context-manager.md
@@ -0,0 +1,20 @@
+-----
+Title: Choosing a Context Manager Implementation
+-----
+
+# Choosing a Context Manager Implementation
+
+Ususally it is fine to trust the auto-detection. If the operating system is not Linux,
+there is only one choice anyway.
+
+For Linux, four different implementations exist:
+
+ - A basic polling implementation, the fall-back if nothing else works.
+ - A Netlink-based implementation
+ - Using NetworkManager to identify available network interfaces
+ - Using Connman to identify the available interfaces
+ - An Android-specific implementation
+
+With the exception of Android, It is generally recommended to use the Netlink-based implementation.
+It should co-exist with any other network management implementation.
+
diff --git a/doc/client-tutorial.md b/doc/client-tutorial.md
new file mode 100644
index 0000000..5d0b71e
--- /dev/null
+++ b/doc/client-tutorial.md
@@ -0,0 +1,215 @@
+---
+Title: Interacting with remote UPnP devices
+---
+
+# UPnP Client Tutorial
+
+This chapter explains how to write an application which fetches the external IP address
+from an UPnP-compliant modem. To do this, a Control Point is created, which searches for
+services of the type `urn:schemas-upnp-org:service:WANIPConnection:1` which is part of
+the Internet Gateway Devce specification.
+
+As services are discovered, ServiceProxy objects are created by GUPnP to allow interaction
+with the service, on which we can invoke the action `GetExternalIPAddress` to fetch the
+external IP address.
+
+## Finding Services
+
+First, we initialize GUPnP and create a control point targeting the service type.
+Then we connect a signal handler so that we are notified when services we are interested in
+are found.
+
+
+```c
+#include <ibgupnp/gupnp-control-point.h>
+
+static GMainLoop *main_loop;
+
+static void
+service_proxy_available_cb (GUPnPControlPoint *cp,
+ GUPnPServiceProxy *proxy,
+ gpointer userdata)
+{
+ /* ... */
+}
+
+int
+main (int argc, char **argv)
+{
+ GUPnPContext *context;
+ GUPnPControlPoint *cp;
+
+ /* Create a new GUPnP Context. By here we are using the default GLib main
+ context, and connecting to the current machine&apos;s default IP on an
+ automatically generated port. */
+ context = gupnp_context_new (NULL, 0, NULL);
+
+ /* Create a Control Point targeting WAN IP Connection services */
+ cp = gupnp_control_point_new
+ (context, "urn:schemas-upnp-org:service:WANIPConnection:1");
+
+ /* The service-proxy-available signal is emitted when any services which match
+ our target are found, so connect to it */
+ g_signal_connect (cp,
+ "service-proxy-available2,
+ G_CALLBACK (service_proxy_available_cb),
+ NULL);
+
+ /* Tell the Control Point to start searching */
+ gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (cp), TRUE);
+
+ /* Enter the main loop. This will start the search and result in callbacks to
+ service_proxy_available_cb. */
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (main_loop);
+
+ /* Clean up */
+ g_main_loop_unref (main_loop);
+ g_object_unref (cp);
+ g_object_unref (context);
+
+ return 0;
+}
+```
+
+## Invoking Actions
+Now we have an application which searches for the service we specified and
+calls `service_proxy_available_cb` for each one it
+found. To get the external IP address we need to invoke the
+`GetExternalIPAddress` action. This action takes no in
+arguments, and has a single out argument called "NewExternalIPAddress".
+GUPnP has a set of methods to invoke actions where you pass a
+`NULL`-terminated varargs list of (name, GType, value)
+tuples for the in arguments, then a `NULL`-terminated
+varargs list of (name, GType, return location) tuples for the out
+arguments.
+
+```c
+static void
+service_proxy_available_cb (GUPnPControlPoint *cp,
+ GUPnPServiceProxy *proxy,
+ gpointer userdata)
+{
+ GError *error = NULL;
+ char *ip = NULL;
+ GUPnPServiceProxyAction *action = NULL;
+
+ action = gupnp_service_proxy_action_new (
+ /* Action name */
+ "GetExternalIPAddress",
+ /* IN args */
+ NULL);
+ gupnp_service_proxy_call_action (proxy,
+ action,
+ NULL,
+ &error);
+ if (error != NULL) {
+ goto out;
+ }
+
+ gupnp_service_proxy_action_get_result (action,
+ /* Error location */
+ &error,
+ /* OUT args */
+ "NewExternalIPAddress",
+ G_TYPE_STRING, &ip,
+ NULL);
+
+ if (error == NULL) {
+ g_print ("External IP address is %s\n", ip);
+ g_free (ip);
+ }
+
+out:
+ if (error != NULL) {
+ g_printerr ("Error: %s\n", error->message);
+ g_error_free (error);
+ }
+
+ gupnp_service_proxy_action_unref (action);
+ g_main_loop_quit (main_loop);
+}
+```
+
+Note that `gupnp_service_proxy_call_action()` blocks until the service has
+replied. If you need to make non-blocking calls then use
+`gupnp_service_proxy_call_action_async()`, which takes a callback that will be
+called from the mainloop when the reply is received.
+
+
+## Subscribing to state variable change notifications
+It is possible to get change notifications for the service state variables
+that have attribute `sendEvents="yes"`. We'll demonstrate
+this by modifying `service_proxy_available_cb` and using
+`gupnp_service_proxy_add_notify()` to setup a notification callback:
+
+
+```c
+static void
+external_ip_address_changed (GUPnPServiceProxy *proxy,
+ const char *variable,
+ GValue *value,
+ gpointer userdata)
+{
+ g_print ("External IP address changed: %s\n", g_value_get_string (value));
+}
+
+static void
+service_proxy_available_cb (GUPnPControlPoint *cp,
+ GUPnPServiceProxy *proxy,
+ gpointer userdata)
+{
+ g_print ("Found a WAN IP Connection service\n");
+
+ gupnp_service_proxy_set_subscribed (proxy, TRUE);
+ if (!gupnp_service_proxy_add_notify (proxy,
+ "ExternalIPAddress",
+ G_TYPE_STRING,
+ external_ip_address_changed,
+ NULL)) {
+ g_printerr ("Failed to add notify");
+ }
+}
+```
+
+## Generating wrappers
+
+Using `gupnp_service_proxy_call_action()` and `gupnp_service_proxy_add_notify()`
+can become tedious, because of the requirement to specify the types and deal
+with GValues. An
+alternative is to use `gupnp-binding-tool`, which
+generates wrappers that hide the boilerplate code from you. Using a
+wrapper generated with prefix "ipconn" would replace
+`gupnp_service_proxy_call_action()` with this code:
+
+```c
+ipconn_get_external_ip_address (proxy, &ip, &error);
+```
+
+State variable change notifications are friendlier with wrappers as well:
+
+```c
+static void
+external_ip_address_changed (GUPnPServiceProxy *proxy,
+ const gchar *external_ip_address,
+ gpointer userdata)
+{
+ g_print ("External IP address changed: &apos;%s&apos;\n", external_ip_address);
+}
+
+static void
+service_proxy_available_cb (GUPnPControlPoint *cp,
+ GUPnPServiceProxy *proxy
+ gpointer userdata)
+{
+ g_print ("Found a WAN IP Connection service\n");
+
+ gupnp_service_proxy_set_subscribed (proxy, TRUE);
+ if (!ipconn_external_ip_address_add_notify (proxy,
+ external_ip_address_changed,
+ NULL)) {
+ g_printerr ("Failed to add notify");
+ }
+}
+```
+
diff --git a/doc/glossary.md b/doc/glossary.md
new file mode 100644
index 0000000..0b9dbb2
--- /dev/null
+++ b/doc/glossary.md
@@ -0,0 +1,115 @@
+---
+Title: UPnP Glossary
+---
+
+# Action
+
+> An Action is a method call on a Service, which encapsulated a single piece of
+functionality. Actions can have multiple input and output arguments, and
+can return error codes. UPnP allows one of the output arguments to be
+marked as the return value, but GUPnP doesn't treat return values specially.
+
+> Every action argument has a related State Variable,
+which determines the type of the argument. Note that even if the argument
+wouldn't need a state variable it is still required, due to historical
+reasons.
+
+# Control Point
+
+> A Control Point is an entity on the network which
+communicates with other Devices and
+Services. In the client/server model the control
+point is a client and the Service is a server,
+although it is common for devices to also be a control point because
+whilst a single control point/service connection is client/server, the
+UPnP network as whole is peer-to-peer.
+
+# Device
+> A Device is an entity on the network which
+communicates using the UPnP standards. This can be a dedicated physical
+device such as a router or printer, or a PC which is running software
+implementing the UPnP standards.
+
+> A Device can contain sub-devices, for example a combination
+printer/scanner could appear as a general device with a printer
+sub-device and a scanner sub-device.
+
+> Every device has zero or more Services. UPnP defines many standard
+device types, which specify services which are required to be implemented.
+Alternatively, a non-standard device type could be used. Examples of
+standard device types are `MediaRenderer` or
+`InternetGatewayDevice`.
+
+# DIDL-Lite
+
+> Digital Item Declaration Language - Lite
+
+> An XML schema used to represent digital content metadata. Defined by
+the UPnP Forum.
+
+# Service
+
+> A Service is a collection of related methods
+(called Actions) and public variables (called
+State Variables) which together form a logical interface.
+> UPnP defines standard services that define actions and variables which
+must be present and their semantics. Examples of these are
+`AVTransport` and `WANIPConnection`.
+
+See also:
+
+- [Action](#action)
+- [Device](#device)
+- [State Variable](#state-variable)
+
+# SCDP
+> Service Control Protocol Document
+
+
+> An XML document which defines the set of <glossterm>Actions</glossterm>
+and <glossterm>State Variables</glossterm> that a
+<glossterm>Service</glossterm> implements.
+
+See also:
+
+- [Action](#action)
+- [Device](#device)
+- [State Variable](#state-variable)
+
+# SSDP
+> <glossterm>Simple Service Discovery Protocol</glossterm>
+
+> UPnP device discovery protocol. Specifies how <glossterm>Devices</glossterm>
+advertise their <glossterm>Services</glossterm> in the network and also how
+<glossterm>Control Points</glossterm> search for
+services and devices respond.
+
+See also:
+
+- [Device](#device)
+- [Action](#controlpoint)
+- [Service](#service)
+
+# State Variable
+
+> A <firstterm>State Variable</firstterm> is a public variable exposing some
+aspect of the service's state. State variables are typed and optionally
+are <firstterm>evented</firstterm>, which means that any changes will be
+notified. Control points are said to <firstterm>subscribe</firstterm> to
+a state variable to receive change notifications.
+
+
+# UDN
+> Unique Device Name
+
+> An unique identifier which is <emphasis>unique</emphasis> for every
+device but <emphasis>never changes</emphasis> for each particular
+device.
+
+> A common practise is to generate a unique UDN on first boot from a
+random seed, or use some unique and persistent property such as the
+device's MAC address to create the UDN.
+
+See also:
+
+- [Device](#device)
diff --git a/doc/gupnp.toml.in b/doc/gupnp.toml.in
new file mode 100644
index 0000000..e416445
--- /dev/null
+++ b/doc/gupnp.toml.in
@@ -0,0 +1,54 @@
+[library]
+namespace = "GUPnP"
+version = "@VERSION@"
+browse_url = "https://gitlab.gnome.org/GNOME/gssdp/"
+repository_url = "https://gitlab.gnome.org/GNOME/gssdp.git"
+website_url = "https://gupnp.org"
+logo_url = "gupnp-logo-short.svg"
+license = "LGPL-2.1-or-later"
+description = "UPnP implementation using GObject"
+dependencies = [ "GObject-2.0", "GSSDP-1.2", "Soup-2.4", "libxml2-2.0" ]
+devhelp = true
+search_index = true
+authors = "The GUPnP developers"
+
+[theme]
+name="basic"
+show_index_summary = true
+
+[source-location]
+base_url = "https://gitlab.gnome.org/GNOME/gupnp/-/blob/master"
+
+[dependencies."GObject-2.0"]
+name = "GObject"
+description = "The base type system library"
+docs_url = "https://developer.gnome.org/gobject/stable"
+
+[dependencies."GSSDP-1.2"]
+name = "GSSDP"
+description = "SSDP implementation using GObject"
+docs_url = "https://gnome.pages.gitlab.gnome.org/gssdp/docs/"
+
+[dependencies."Soup-2.4"]
+name = "Soup"
+description = "A HTTP handling library"
+docs_url = "https://developer.gnome.org/libsoup/stable"
+
+[dependencies."libxml2-2.0"]
+name = "LibXML2"
+description = "A XML handling library"
+docs_url = "http://www.xmlsoft.org/html/index.html"
+
+[extra]
+content_files = [
+ "client-tutorial.md",
+ "server-tutorial.md",
+ "choosing-a-context-manager.md",
+ "glossary.md"
+]
+
+content_images = [
+ "images/gupnp-logo-short.svg"
+]
+
+urlmap_file = "urlmap.js"
diff --git a/doc/images/gupnp-logo-short.svg b/doc/images/gupnp-logo-short.svg
new file mode 100644
index 0000000..6386c74
--- /dev/null
+++ b/doc/images/gupnp-logo-short.svg
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ id="svg4194"
+ version="1.1"
+ inkscape:version="1.1 (c68e22c387, 2021-05-23)"
+ width="89.339256mm"
+ height="37.64888mm"
+ viewBox="0 0 316.55642 133.40154"
+ sodipodi:docname="gupnp-logo-short.svg"
+ inkscape:export-filename="/home/jgeorg/gupnp-logo-v1.svg.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <metadata
+ id="metadata4200">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <cc:license
+ rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs4198" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1011"
+ id="namedview4196"
+ showgrid="false"
+ showguides="true"
+ inkscape:snap-page="false"
+ inkscape:zoom="1.6897519"
+ inkscape:cx="106.82042"
+ inkscape:cy="36.691777"
+ inkscape:window-x="0"
+ inkscape:window-y="32"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg4194"
+ inkscape:guide-bbox="true"
+ inkscape:pagecheckerboard="0"
+ units="mm"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:document-units="mm">
+ <inkscape:grid
+ type="xygrid"
+ id="grid5354"
+ originx="-2.7774772"
+ originy="-2.2013303"
+ spacingx="1"
+ spacingy="1" />
+ <sodipodi:guide
+ position="311.44403,45.237576"
+ orientation="0,1"
+ id="guide4237"
+ inkscape:locked="false" />
+ <sodipodi:guide
+ position="316.24124,64.031713"
+ orientation="1,0"
+ id="guide14" />
+ </sodipodi:namedview>
+ <path
+ inkscape:connector-curvature="0"
+ id="path4222"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:111.914px;line-height:125%;font-family:moderna;-inkscape-font-specification:moderna;letter-spacing:0px;word-spacing:0px;fill:#204a87;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 59.874011,60.321668 q 0,12.7582 -9.176951,21.487495 9.288865,8.841209 9.288865,21.711327 0,16.11562 -13.205856,24.84491 -7.722069,5.03614 -16.675192,5.03614 -16.003708,0 -24.8449171,-13.31778 -5.1480458,-7.61015 -5.1480458,-16.56327 0,-5.819533 2.2382807,-11.191407 L 16.33945,97.92479 q -1.11914,2.68593 -1.11914,5.5957 0,6.15527 4.364647,10.408 4.476562,4.36465 10.51992,4.36465 6.043358,0 10.408006,-4.36465 4.364647,-4.36464 4.364647,-10.408 0,-9.848438 -9.288865,-13.76543 -2.797851,0.55957 -5.595702,0.55957 -12.534373,0 -21.2636682,-8.729295 Q 0,72.85604 0,60.321668 0,47.899209 8.7292948,39.169914 17.570504,30.440619 29.992963,30.440619 l 8.729295,-20.7040974 11.862888,5.0361324 -7.833983,18.57773 q 7.833983,3.805078 12.422459,11.07949 4.700389,7.274413 4.700389,15.891794 z m -15.108395,0 q 0,-6.043358 -4.364647,-10.408006 -4.364648,-4.364647 -10.408006,-4.364647 -6.155272,0 -10.51992,4.364647 -4.364647,4.252734 -4.364647,10.408006 0,6.155272 4.364647,10.519919 4.364648,4.364648 10.51992,4.364648 6.155272,0 10.408006,-4.364648 4.364647,-4.364647 4.364647,-10.519919 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4224"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:111.914px;line-height:125%;font-family:moderna;-inkscape-font-specification:moderna;letter-spacing:0px;word-spacing:0px;fill:#204a87;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 97.753413,73.527524 q -6.15527,0 -10.519918,-4.252733 -4.252733,-4.364648 -4.252733,-10.51992 L 82.868848,0 H 67.760452 v 58.754871 q 0,12.422459 8.729296,21.151754 8.841209,8.729295 21.263665,8.729295 12.422457,0 21.151757,-8.729295 8.8412,-8.729295 8.8412,-21.151754 V 0 h -15.10839 v 58.754871 q 0,6.155272 -4.36465,10.51992 -4.36465,4.252733 -10.519917,4.252733 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4226"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:111.914px;line-height:125%;font-family:moderna;-inkscape-font-specification:moderna;letter-spacing:0px;word-spacing:0px;fill:#204a87;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 190.13495,30.216791 Q 190.24687,17.682419 181.51757,9.0650376 172.78828,0.3357421 160.2539,0.2238281 L 135.5209,0.111914 V 88.63592 h 15.22031 V 59.985926 h 9.40078 q 12.42246,0 21.15175,-8.617381 8.7293,-8.729296 8.84121,-21.151754 z m -15.10839,-0.111914 q -0.11192,6.267186 -4.36465,10.51992 -4.25273,4.252733 -10.51992,4.252733 H 150.6293 V 15.22031 l 9.6246,0.111914 q 6.26719,0.111914 10.51992,4.364647 4.36465,4.252734 4.25274,10.408006 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4228"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:111.914px;line-height:125%;font-family:moderna;-inkscape-font-specification:moderna;letter-spacing:0px;word-spacing:0px;fill:#204a87;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 221.80976,45.549015 q 6.04336,0 10.40801,4.364647 4.36465,4.364648 4.36465,10.408006 l 0.11191,28.314252 h 15.1084 V 60.321668 q 0,-12.422459 -8.84121,-21.151754 -8.7293,-8.729295 -21.15176,-8.729295 -12.42246,0 -21.26366,8.729295 -8.7293,8.729295 -8.7293,21.151754 V 88.63592 h 15.1084 V 60.321668 q 0,-6.155272 4.36464,-10.408006 4.36465,-4.364647 10.51992,-4.364647 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4230"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:111.914px;line-height:125%;font-family:moderna;-inkscape-font-specification:moderna;letter-spacing:0px;word-spacing:0px;fill:#204a87;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 314.19132,30.216791 Q 314.30323,17.682419 305.57394,9.0650376 296.84464,0.3357421 284.31027,0.2238281 L 259.57727,0.111914 V 88.63592 h 15.22031 V 59.985926 h 9.40078 q 12.42245,0 21.15175,-8.617381 8.7293,-8.729296 8.84121,-21.151754 z m -15.1084,-0.111914 q -0.11191,6.267186 -4.36464,10.51992 -4.25274,4.252733 -10.51992,4.252733 h -9.5127 V 15.22031 l 9.62461,0.111914 q 6.26719,0.111914 10.51992,4.364647 4.36465,4.252734 4.25273,10.408006 z" />
+ <rect
+ style="fill:#204a87;fill-opacity:1;stroke:#204a87;stroke-width:0.630386;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1"
+ id="rect5352"
+ width="248.92432"
+ height="15.959336"
+ x="67.316925"
+ y="104.33861"
+ ry="0" />
+</svg>
diff --git a/doc/meson.build b/doc/meson.build
index c3b8fb3..c5ebbc0 100644
--- a/doc/meson.build
+++ b/doc/meson.build
@@ -1,5 +1,6 @@
entities = configuration_data()
entities.set('VERSION', meson.project_version())
+
version_xml = configure_file(input: 'version.xml.in',
output: 'version.xml', configuration:
entities)
@@ -12,36 +13,42 @@ docbook_man_page = configure_file(
)
if get_option('gtk_doc')
- gnome.gtkdoc('gupnp',
- content_files : files(
- 'client-tutorial.xml',
- 'fdl-1.1.xml',
- 'glossary.xml',
- 'gupnp-docs.xml',
- 'overview.xml',
- 'server-tutorial.xml'
- ),
- main_xml : 'gupnp-docs.xml',
- src_dir : ['libgupnp'],
- dependencies : [libgupnp, version_xml, docbook_man_page],
- scan_args : ['--ignore-decorators', 'G_DEPRECATED|G_GNUC_DEPRECATED,G_DEPRECATED_FOR'],
- ignore_headers : [
- 'gena-protocol.h',
- 'xml-util.h',
- 'gvalue-util.h',
- 'http-headers.h',
- 'gupnp-context-private.h',
- 'gupnp-linux-context-manager.h',
- 'gupnp-network-manager.h',
- 'gupnp-unix-context-manager.h',
- 'gupnp-device-info-private.h',
- 'gupnp-error-private.h',
- 'gupnp-resource-factory-private.h',
- 'gupnp-service-introspection-private.h',
- 'gupnp-service-proxy-action-private.h',
- 'gupnp-types-private.h'
- ],
- install : true)
+ gidocgen = find_program('gi-docgen', required: true)
+
+ gupnp_toml = configure_file (
+ input: 'gupnp.toml.in',
+ output: 'gupnp.toml',
+ configuration: entities
+ )
+
+ docs_dir = join_paths(get_option('prefix'), get_option('datadir')) / 'doc/gupnp-1.2/reference'
+
+ custom_target(
+ 'gupnp-doc',
+ input: [ gupnp_toml, gir[0] ],
+ output: 'GUPnP',
+ command : [
+ gidocgen,
+ 'generate',
+ '--quiet',
+ '--add-include-path=@0@'.format(meson.current_build_dir() / '../libgupnp'),
+ '--config', gupnp_toml,
+ '--output-dir=@OUTPUT@',
+ '--no-namespace-dir',
+ '--content-dir=@0@'.format(meson.current_source_dir()),
+ '@INPUT1@',
+ ],
+ depend_files : [
+ gupnp_toml,
+ 'client-tutorial.md',
+ 'server-tutorial.md',
+ 'choosing-a-context-manager.md',
+ 'glossary.md',
+ ],
+ build_by_default: true,
+ install: true,
+ install_dir : docs_dir,
+ )
endif
xsltproc = find_program('xsltproc', required: false)
diff --git a/doc/server-tutorial.md b/doc/server-tutorial.md
new file mode 100644
index 0000000..d0c0ce2
--- /dev/null
+++ b/doc/server-tutorial.md
@@ -0,0 +1,373 @@
+---
+Title: Implementing UPnP devices
+---
+
+# UPnP Server Tutorial
+
+This chapter explains how to implement an UPnP service using GUPnP. For
+this example we will create a virtual UPnP-enabled light bulb.
+
+Before any code can be written, the device and services that it implement
+need to be described in XML. Although this can be frustrating, if you are
+implementing a standardised service then the service description is
+already written for you and the device description is trivial. UPnP has
+standardised Lighting Controls, so we'll be using the device and service types defined
+there.
+
+## Defining the Device
+
+The first step is to write the _device description_
+file. This is a short XML document which describes the device and what
+services it provides (for more details see the [UPnP Device Architecture specification](http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0.pdf), section 2.1). We'll be using
+the `BinaryLight1` device type, but if none of the
+existing device types are suitable a custom device type can be created.
+
+```xml
+<?xml version="1.0" encoding="utf-8"?>
+<root xmlns="urn:schemas-upnp-org:device-1-0">
+ <specVersion>
+ <major>1</major>
+ <minor>0</minor>
+ </specVersion>
+
+ <device>
+ <deviceType>urn:schemas-upnp-org:device:BinaryLight:1</deviceType>
+ <friendlyName>Kitchen Lights</friendlyName>
+ <manufacturer>OpenedHand</manufacturer>
+ <modelName>Virtual Light</modelName>
+ <UDN>uuid:cc93d8e6-6b8b-4f60-87ca-228c36b5b0e8</UDN>
+
+ <serviceList>
+ <service>
+ <serviceType>urn:schemas-upnp-org:service:SwitchPower:1</serviceType>
+ <serviceId>urn:upnp-org:serviceId:SwitchPower:1</serviceId>
+ <SCPDURL>/SwitchPower1.xml</SCPDURL>
+ <controlURL>/SwitchPower/Control</controlURL>
+ <eventSubURL>/SwitchPower/Event</eventSubURL>
+ </service>
+ </serviceList>
+ </device>
+</root>
+```
+The `<specVersion>` tag defines what version of the UPnP
+Device Architecture the document conforms to. At the time of writing the
+only version is 1.0.
+
+Next there is the root `<device>` tag. This contains
+metadata about the device, lists the services it provides and any
+sub-devices present (there are none in this example). The
+`<deviceType>` tag specifies the type of the device.
+
+Next we have `<friendlyName>`, `<manufacturer>` and `<modelName>`. The
+friendly name is a human-readable name for the device, the manufacturer
+and model name are self-explanatory.
+
+Next there is the UDN, or _Unique Device Name_. This
+is an identifier which is unique for each device but persistent for each
+particular device. Although it has to start with `uuid:`
+note that it doesn't have to be an UUID. There are several alternatives
+here: for example it could be computed at built-time if the software will
+only be used on a single machine, or it could be calculated using the
+device's serial number or MAC address.
+
+Finally we have the `<serviceList>` which describes the
+services this device provides. Each service has a service type (again
+there are types defined for standardised services or you can create your
+own), service identifier, and three URLs. As a service type we're using
+the standard `SwitchPower1` service. The
+`<SCPDURL>` field specifies where the _Service
+Control Protocol Document_ can be found, this describes the
+service in more detail and will be covered next. Finally there are the
+control and event URLs, which need to be unique on the device and will be
+managed by GUPnP.
+
+## Defining Services
+
+Because we are using a standard service we can use the service description
+from the specification. This is the `SwitchPower1`
+service description file:
+
+```xml
+<?xml version="1.0" encoding="utf-8"?>
+<scpd xmlns="urn:schemas-upnp-org:service-1-0">
+ <specVersion>
+ <major>1</major>
+ <minor>0</minor>
+ </specVersion>
+ <actionList>
+ <action>
+ <name>SetTarget</name>
+ <argumentList>
+ <argument>
+ <name>newTargetValue</name>
+ <relatedStateVariable>Target</relatedStateVariable>
+ <direction>in</direction>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetTarget</name>
+ <argumentList>
+ <argument>
+ <name>RetTargetValue</name>
+ <relatedStateVariable>Target</relatedStateVariable>
+ <direction>out</direction>
+ </argument>
+ </argumentList>
+ </action>
+ <action>
+ <name>GetStatus</name>
+ <argumentList>
+ <argument>
+ <name>ResultStatus</name>
+ <relatedStateVariable>Status</relatedStateVariable>
+ <direction>out</direction>
+ </argument>
+ </argumentList>
+ </action>
+ </actionList>
+ <serviceStateTable>
+ <stateVariable sendEvents="no">
+ <name>Target</name>
+ <dataType>boolean</dataType>
+ <defaultValue>0</defaultValue>
+ </stateVariable>
+ <stateVariable sendEvents="yes">
+ <name>Status</name>
+ <dataType>boolean</dataType>
+ <defaultValue>0</defaultValue>
+ </stateVariable>
+ </serviceStateTable>
+</scpd>
+```
+
+Again, the `<specVersion>` tag defines the UPnP version
+that is being used. The rest of the document consists of an
+`<actionList>` defining the actions available and a
+`<serviceStateTable>` defining the state variables.
+
+Every `<action>` has a `<name>` and a list
+of `<argument>`s. Arguments also have a name, a direction
+(`in` or `out` for input or output
+ arguments) and a related state variable. The state variable is used to
+determine the type of the argument, and as such is a required element.
+This can lead to the creation of otherwise unused state variables to
+define the type for an argument (the `WANIPConnection`
+service is a good example of this), thanks to the legacy behind UPnP.
+
+`<stateVariable>`s need to specify their
+`<name>` and `<dataType>`. State variables
+by default send notifications when they change, to specify that a variable
+doesn't do this set the `<sendEvents>` attribute to
+`no`. Finally there are optional
+`<defaultValue>`, `<allowedValueList>` and
+`<allowedValueRange>` elements which specify what the
+default and valid values for the variable.
+
+For the full specification of the service definition file, including a
+complete list of valid `<dataType>`s, see section 2.3 of
+the [UPnP Device Architecture](http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.0.pdf)
+
+## Implementing the Device
+
+Before starting to implement the device, some boilerplate code is needed
+to initialise GUPnP. A GUPnP context can be created using `gupnp_context_new()`.
+
+```c
+GUPnPContext *context;
+/* Create the GUPnP context with default host and port */
+context = gupnp_context_new (NULL, 0, NULL);
+```
+Next the root device can be created. The name of the device description
+file can be passed as an absolute file path or a relative path to the
+second parameter of `gupnp_root_device_new()`. The service description
+files referenced in the device description are expected to be at the path
+given there as well.
+
+```c
+GUPnPRootDevice *dev;
+/* Create the root device object */
+dev = gupnp_root_device_new (context, "BinaryLight1.xml", ".");
+/* Activate the root device, so that it announces itself */
+gupnp_root_device_set_available (dev, TRUE);
+```
+
+GUPnP scans the device description and any service description files it
+refers to, so if the main loop was entered now the device and service
+would be available on the network, albeit with no functionality. The
+remaining task is to implement the services.
+
+## Implementing a Service
+
+To implement a service we first fetch the #GUPnPService from the root
+device using gupnp_device_info_get_service() (#GUPnPRootDevice is a
+subclass of #GUPnPDevice, which implements #GUPnPDeviceInfo). This
+returns a #GUPnPServiceInfo which again is an interface, implemented by
+#GUPnPService (on the server) and #GUPnPServiceProxy (on the client).
+
+```c
+GUPnPServiceInfo *service;
+service = gupnp_device_info_get_service (GUPNP_DEVICE_INFO (dev), "urn:schemas-upnp-org:service:SwitchPower:1");
+```
+
+GUPnPService handles interacting with the network itself, leaving the
+implementation of the service itself to signal handlers that we need to
+connect. There are two signals: #GUPnPService::action-invoked and
+#GUPnPService::query-variable. #GUPnPService::action-invoked is emitted
+when a client invokes an action: the handler is passed a
+#GUPnPServiceAction object that identifies which action was invoked, and
+is used to return values using `gupnp_service_action_set()`.
+#GUPnPService::query-variable is emitted for evented variables when a
+control point subscribes to the service (to announce the initial value),
+or whenever a client queries the value of a state variable (note that this
+is now deprecated behaviour for UPnP control points): the handler is
+passed the variable name and a #GValue which should be set to the current
+value of the variable.
+
+Handlers should be targetted at specific actions or variables by using
+the signal detail when connecting. For example,
+this causes `on_get_status_action` to be called when
+the `GetStatus` action is invoked:
+
+```c
+static void on_get_status_action (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data);
+// ...
+g_signal_connect (service, "action-invoked::GetStatus", G_CALLBACK (on_get_status_action), NULL);
+```
+
+The implementation of action handlers is quite simple. The handler is
+passed a #GUPnPServiceAction object which represents the in-progress
+action. If required it can be queried using
+gupnp_service_action_get_name() to identify the action (this isn't
+required if detailed signals were connected). Any
+in arguments can be retrieving using
+`gupnp_service_action_get()`, and then return values can be set using
+`gupnp_service_action_set()`. Once the action has been performed, either
+`gupnp_service_action_return()` or `gupnp_service_action_return_error()`
+should be called to either return successfully or return an error code.
+
+If any evented state variables were modified during the action then a
+notification should be emitted using `gupnp_service_notify()`. This is an
+example implementation of `GetStatus` and `SetTarget`
+
+```c
+static gboolean status;
+
+static void
+get_status_cb (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data)
+{
+ gupnp_service_action_set (action,
+ "ResultStatus", G_TYPE_BOOLEAN, status,
+ NULL);
+ gupnp_service_action_return (action);
+}
+
+void
+set_target_cb (GUPnPService *service, GUPnPServiceAction *action, gpointer user_data)
+{
+ gupnp_service_action_get (action,
+ "NewTargetValue", G_TYPE_BOOLEAN, &status,
+ NULL);
+ gupnp_service_action_return (action);
+ gupnp_service_notify (service, "Status", G_TYPE_STRING, status, NULL);
+}
+
+//...
+
+g_signal_connect (service, "action-invoked::GetStatus", G_CALLBACK (get_status_cb), NULL);
+g_signal_connect (service, "action-invoked::SetTarget", G_CALLBACK (set_target_cb), NULL);
+```
+
+State variable query handlers are called with the name of the variable and
+a #GValue. This value should be initialized with the relevant type and
+then set to the current value. Again signal detail can be used to connect
+handlers to specific state variable callbacks.
+
+```c
+static gboolean status;
+
+static void
+query_status_cb (GUPnPService *service, char *variable, GValue *value, gpointer user_data)
+{
+ g_value_init (value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (value, status);
+}
+
+// ...
+
+g_signal_connect (service, "query-variable::Status", G_CALLBACK (query_status_cb), NULL);
+```
+
+The service is now fully implemented. To complete it, enter a GLib main
+loop and wait for a client to connect. The complete source code for this
+example is available as [examples/light-server.c](https://gitlab.gnome.org/GNOME/gupnp/-/blob/master/examples/light-server.c) in
+the GUPnP sources.
+
+For services which have many actions and variables there is a convenience
+method [method@GUPnP.Service.signals_autoconnect] which will automatically
+connect specially named handlers to signals. See the documentation for
+full details on how it works.
+
+## Generating Service-specific Wrappers
+
+Using service-specific wrappers can simplify the implementation of a service.
+Wrappers can be generated with gupnp-binding-tool
+using the option `--mode server`.
+
+In the following examples the wrapper has been created with
+ `--mode server --prefix switch`. Please note that the callback handlers
+ (`get_status_cb` and `set_target_cb`) are not automatically
+ generated by gupnp-binding-tool for you.
+
+```c
+static gboolean status;
+
+static void
+get_status_cb (GUPnPService *service,
+ GUPnPServiceAction *action,
+ gpointer user_data)
+{
+ switch_get_status_action_set (action, status);
+
+ gupnp_service_action_return (action);
+}
+
+static void
+set_target_cb (GUPnPService *service,
+ GUPnPServiceAction *action,
+ gpointer user_data)
+{
+ switch_set_target_action_get (action, &status);
+ switch_status_variable_notify (service, status);
+
+ gupnp_service_action_return (action);
+}
+
+// ...
+
+switch_get_status_action_connect (service, G_CALLBACK(get_status_cb), NULL);
+switch_set_target_action_connect (service, G_CALLBACK(set_target_cb), NULL);
+```
+
+Note how many possible problem situations that were run-time errors are
+actually compile-time errors when wrappers are used: Action names,
+argument names and argument types are easier to get correct (and available
+in editor autocompletion).
+
+State variable query handlers are implemented in a similar manner, but
+they are even simpler as the return value of the handler is the state
+variable value.
+
+```c
+static gboolean
+query_status_cb (GUPnPService *service,
+ gpointer user_data)
+{
+ return status;
+}
+
+// ...
+
+
+switch_status_query_connect (service, query_status_cb, NULL);
+```
diff --git a/doc/urlmap.js b/doc/urlmap.js
new file mode 100644
index 0000000..4e19607
--- /dev/null
+++ b/doc/urlmap.js
@@ -0,0 +1,4 @@
+// A map between namespaces and base URLs for their online documentation
+baseURLs = [
+ [ 'GSSDP', 'https://gnome.pages.gitlab.gnome.org/gssdp/docs/' ],
+]
diff --git a/libgupnp/gupnp-acl.c b/libgupnp/gupnp-acl.c
index 4a337c6..6a4cd1b 100644
--- a/libgupnp/gupnp-acl.c
+++ b/libgupnp/gupnp-acl.c
@@ -6,23 +6,23 @@
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
-/**
- * SECTION:gupnp-acl
- * @short_description: Object providing a simple access control list for
- * GUPnP.
- *
- * #GUPnPAcl provides either synchronous or asynchronous functions to check
- * whether a peer sould be able to access a resource or not.
- *
- * Since: 0.20.11
- */
-
#include <config.h>
#include "gupnp-acl.h"
#include "gupnp-acl-private.h"
#include "gupnp-device.h"
+/**
+ * GUPnPAcl:
+ *
+ * Access control provider for [class@GUPnP.Context]
+ *
+ * GUPnPAcl provides either synchronous or asynchronous functions to check
+ * whether a peer should be able to access a resource that is hosted by GUPnP or not.
+ *
+ * Since: 0.20.11
+ */
+
G_DEFINE_INTERFACE(GUPnPAcl, gupnp_acl, G_TYPE_OBJECT)
static void
@@ -33,14 +33,13 @@ gupnp_acl_default_init (GUPnPAclInterface *klass)
/**
* gupnp_acl_is_allowed:
* @self: an instance of #GUPnPAcl
- * @device: (nullable): The #GUPnPDevice associated with @path or %NULL if
+ * @device: (nullable): The [class@GUPnP.Device] associated with @path or %NULL if
* unknown.
- * @service: (nullable): The #GUPnPService associated with @path or %NULL if
+ * @service: (nullable): The [class@GUPnP.Service] associated with @path or %NULL if
* unknown.
* @path: The path being served.
* @address: IP address of the peer.
- * @agent: (nullable): The User-Agent header of the peer or %NULL if not
- * unknown.
+ * @agent: (nullable): The User-Agent header of the peer or %NULL if unknown.
* @returns %TRUE if the peer is allowed, %FALSE otherwise
*
* Check whether an IP address is allowed to access this resource.
@@ -68,26 +67,30 @@ gupnp_acl_is_allowed (GUPnPAcl *self,
/**
* gupnp_acl_is_allowed_async:
* @self: a #GUPnPAcl
- * @device: (nullable): The #GUPnPDevice associated with @path or %NULL if
+ * @device: (nullable): The [class@GUPnP.Device] associated with @path or %NULL if
* unknown.
- * @service: (nullable): The #GUPnPService associated with @path or %NULL if
+ * @service: (nullable): The [class@GUPnP.Service] associated with @path or %NULL if
* unknown.
* @path: The path being served.
* @address: IP address of the peer
* @agent: (nullable): The User-Agent header of the peer or %NULL if not
* unknown.
- * @cancellable: (nullable): A #GCancellable which can be used to cancel the
+ * @cancellable: (nullable): A cancellable which can be used to cancel the
* operation.
* @callback: Callback to call after the function is done.
* @user_data: Some user data.
*
- * Optional. Check asynchronously whether an IP address is allowed to access
- * this resource. Use this function if the process of verifying the access right
- * is expected to take some time, for example when using D-Bus etc.
+ * Check asynchronously whether an IP address is allowed to access
+ * this resource.
+ *
+ * This function is optional. [method@GUPnP.Acl.can_sync] should return %TRUE
+ * if the implementing class supports it. If it is supported, GUPnP will
+ * prefer to use this function over [method@GUPnP.Acl.is_allowed].
*
- * If this function is supported, gupnp_acl_can_sync() should return %TRUE.
+ * Implement this function if the process of verifying the access right
+ * is expected to take some time, for example when using D-Bus etc.
*
- * Use gupnp_acl_is_allowed_finish() to retrieve the result.
+ * Use [method@GUPnP.Acl.is_allowed_finish] to retrieve the result.
*
* Since: 0.20.11
*/
@@ -118,11 +121,13 @@ gupnp_acl_is_allowed_async (GUPnPAcl *self,
/**
* gupnp_acl_is_allowed_finish:
* @self: An instance of #GUPnPAcl
- * @res: %GAsyncResult obtained from the callback in gupnp_acl_is_allowed_async()
+ * @res: [iface@Gio.AsyncResult] obtained from the callback passed to [method@GUPnP.Acl.is_allowed_async]
* @error: (inout)(optional)(nullable): A return location for a #GError describing the failure
* @returns %TRUE if the authentication was successful, %FALSE otherwise and on
* error. Check @error for details.
*
+ * Get the result of [method@GUPnP.Acl.is_allowed_async].
+ *
* Since: 0.20.11
*/
gboolean
@@ -143,7 +148,7 @@ gupnp_acl_is_allowed_finish (GUPnPAcl *self,
* @returns %TRUE, if gupnp_acl_is_allowed_async() is supported, %FALSE
* otherwise.
*
- * Check whether gupnp_acl_is_allowed_async() is supported.
+ * Check whether [method@GUPnP.Acl.is_allowed_async] is supported.
*
* Since: 0.20.11
*/
@@ -155,6 +160,10 @@ gupnp_acl_can_sync (GUPnPAcl *self)
return GUPNP_ACL_GET_IFACE (self)->can_sync (self);
}
+///////////////////////////////////////////////////////////////////
+// Internal helper functions
+//
+
/**
* acl_server_handler_new:
* @service: (nullable): A #GUPnPContext or %NULL if unknown
diff --git a/libgupnp/gupnp-acl.h b/libgupnp/gupnp-acl.h
index c382c9f..74d8ce5 100644
--- a/libgupnp/gupnp-acl.h
+++ b/libgupnp/gupnp-acl.h
@@ -18,25 +18,8 @@ G_BEGIN_DECLS
#define GUPNP_TYPE_ACL (gupnp_acl_get_type())
G_DECLARE_INTERFACE (GUPnPAcl, gupnp_acl, GUPNP, ACL, GObject)
-/**
- * GUPnPAcl:
- *
- * Handle to an object implementing the #GUPnPAclInterface interface.
- */
-typedef struct _GUPnPAcl GUPnPAcl;
-/**
- * GUPnPAclInterface:
- * @parent: The parent interface.
- * @is_allowed: Check whether access to the resource is granted.
- * @is_allowed_async: Asynchronously check whether the access is granted.
- * @is_allowed_finish: Conclude the @is_allowed_async operation.
- * @can_sync: Whether the ACL can do sync queries.
- *
- * Implement a simple access control list for GUPnP.
- *
- * Since: 0.20.11
- */
+typedef struct _GUPnPAcl GUPnPAcl;
typedef struct _GUPnPAclInterface GUPnPAclInterface;
/* Forward declarations to avoid recursive includes */
@@ -71,11 +54,13 @@ struct _GUPnPAclInterface {
/*< private >*/
+#ifndef GOBJECT_INTROSPECTION_SKIP
/* future padding */
void (* _gupnp_reserved1) (void);
void (* _gupnp_reserved2) (void);
void (* _gupnp_reserved3) (void);
void (* _gupnp_reserved4) (void);
+#endif
};
gboolean
diff --git a/libgupnp/gupnp-connman-manager.c b/libgupnp/gupnp-connman-manager.c
index f64e1b9..4dbd02c 100644
--- a/libgupnp/gupnp-connman-manager.c
+++ b/libgupnp/gupnp-connman-manager.c
@@ -54,6 +54,11 @@ struct _GUPnPConnmanManagerPrivate {
typedef struct _GUPnPConnmanManagerPrivate GUPnPConnmanManagerPrivate;
+/**
+ * GUPnPConnmanManager:
+ *
+ * Connman-based implementation of a [class@GUPnP.ContextManager]
+ */
struct _GUPnPConnmanManager {
GUPnPContextManager parent;
};
diff --git a/libgupnp/gupnp-context-filter.c b/libgupnp/gupnp-context-filter.c
index e23f0eb..4770689 100644
--- a/libgupnp/gupnp-context-filter.c
+++ b/libgupnp/gupnp-context-filter.c
@@ -6,18 +6,6 @@
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
-/**
- * SECTION:gupnp-context-filter
- * @short_description: Class for network filtering.
- *
- * #GUPnPContextFilter handles network filtering. It provides API to manage a
- * list of entries that will be used to filter networks. The #GUPnPContextFilter
- * could be enabled or not. If it's enabled but the entries list is empty, it
- * behaves as disabled.
- *
- * Since: 1.4.0
- */
-
#include "gupnp-context-filter.h"
#include <string.h>
@@ -31,12 +19,44 @@ typedef struct _GUPnPContextFilterPrivate GUPnPContextFilterPrivate;
/**
* GUPnPContextFilter:
*
- * Class for network context filtering.
+ * Network context filter, used by [class@GUPnP.ContextManager]
*
* #GUPnPContextFilter handles network filtering. It provides API to manage a
* list of entries that will be used to filter networks. The #GUPnPContextFilter
* could be enabled or not. If it's enabled but the entries list is empty, it
- * behaves as disabled.
+ * behaves as if being disabled.
+ *
+ * The GUPnPContextFilter is used with the [class@GUPnP.ContextManager]
+ * to narrow down the contexts that are notified by it.
+ *
+ * Contexts can be filtered by the following criteria:
+ *
+ * - Their IP addresses
+ * - The network device they will live on
+ * - The name of the network the context would join
+ *
+ * To add or modify a context filter, you need to retrieve the current context filter
+ * from the context manger using [method@GUPnP.ContextManager.get_context_filter].
+ *
+ * By default, a context filter is empty and disabled.
+ *
+ * For example, to only react to contexts that are appearing on eth0 or when being in the WiFi network with
+ * the SSID "HomeNetwork", and on IPv6 localhost, you should do:
+ *
+ *
+ * ```c
+ * GUPnPContextFilter* filter;
+ *
+ * filter = gupnp_context_manager_get_context_filter (manager);
+ * const char *filter_entries[] = {
+ * "eth0",
+ * "HomeNetwork",
+ * "::1",
+ * NULL
+ * };
+ * gupnp_context_filter_add_entryv (filter, filter_entries);
+ * gupnp_context_filter_set_enabled (filter, TRUE);
+ * ```
*
* Since: 1.4.0
*/
@@ -142,7 +162,7 @@ gupnp_context_filter_class_init (GUPnPContextFilterClass *klass)
object_class->finalize = gupnp_context_filter_class_finalize;
/**
- * GUPnPContextFilter:enabled:
+ * GUPnPContextFilter:enabled:(attributes org.gtk.Property.get=gupnp_context_filter_get_enabled org.gtk.Property.set=gupnp_context_filter_set_enabled)
*
* Whether this context filter is active or not.
*
@@ -159,7 +179,7 @@ gupnp_context_filter_class_init (GUPnPContextFilterClass *klass)
G_PARAM_STATIC_STRINGS));
/**
- * GUPnPContextFilter:entries: (type GList(utf8))
+ * GUPnPContextFilter:entries: (type GList(utf8))(attributes org.gtk.Property.get=gupnp_context_filter_get_entries)
*
* A list of items to filter for.
*
@@ -170,7 +190,7 @@ gupnp_context_filter_class_init (GUPnPContextFilterClass *klass)
PROP_ENTRIES,
g_param_spec_pointer (
"entries",
- "Entries",
+ "Filter entries",
"GList of strings that compose the context filter.",
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
@@ -193,7 +213,7 @@ gupnp_context_filter_new (void)
}
/**
- * gupnp_context_filter_set_enabled:
+ * gupnp_context_filter_set_enabled:(attributes org.gtk.Method.set_property=enabled)
* @context_filter: A #GUPnPContextFilter
* @enable: %TRUE to enable @context_filter, %FALSE otherwise
*
@@ -215,7 +235,7 @@ gupnp_context_filter_set_enabled (GUPnPContextFilter *context_filter,
}
/**
- * gupnp_context_filter_get_enabled:
+ * gupnp_context_filter_get_enabled:(attributes org.gtk.Method.get_property=enabled)
* @context_filter: A #GUPnPContextFilter
*
* Return the status of the #GUPnPContextFilter
@@ -297,8 +317,8 @@ gupnp_context_filter_add_entry (GUPnPContextFilter *context_filter,
* @entries: (array zero-terminated=1): A %NULL-terminated list of strings
*
* Add a list of entries to a #GUPnPContextFilter. This is a helper function to
- * directly add a %NULL-terminated array of string usually aquired from
- * commandline args.
+ * directly add a %NULL-terminated array of string usually acquired from
+ * command line arguments.
*
* Since: 1.4.0
*/
@@ -400,11 +420,11 @@ gupnp_context_filter_clear (GUPnPContextFilter *context_filter)
* @context: A #GUPnPContext to test.
*
* It will check if the @context is allowed or not. The @context_filter will
- * check all its entries againt #GUPnPContext interface, host ip and network
+ * check all its entries against #GUPnPContext interface, host IP and network
* fields information. This function doesn't take into account the
* @context_filter status (enabled or not).
*
- * Return value: %TRUE if @context is matching the @context_filter criterias,
+ * Return value: %TRUE if @context is matching the @context_filter criteria,
* %FALSE otherwise.
*
* Since: 1.4.0
diff --git a/libgupnp/gupnp-context-manager.c b/libgupnp/gupnp-context-manager.c
index 35c2e50..5092005 100644
--- a/libgupnp/gupnp-context-manager.c
+++ b/libgupnp/gupnp-context-manager.c
@@ -11,17 +11,6 @@
*
*/
-/**
- * SECTION:gupnp-context-manager
- * @short_description: Manages GUPnPContext objects.
- *
- * A Utility class that takes care of creation and destruction of
- * #GUPnPContext objects for all available network interfaces as they go up
- * (connect) and down (disconnect), respectively.
- *
- * Since: 0.13.0
- */
-
#define G_LOG_DOMAIN "gupnp-context-manager"
#include <config.h>
@@ -65,6 +54,23 @@ struct _GUPnPContextManagerPrivate {
};
typedef struct _GUPnPContextManagerPrivate GUPnPContextManagerPrivate;
+/**
+ * GUPnPContextManager:
+ *
+ * A manager for [class@GUPnP.Context] instances.
+ *
+ * This utility class that takes care of dynamic creation and destruction of
+ * #GUPnPContext objects for all available network interfaces as they go up
+ * (connect) and down (disconnect), respectively.
+ *
+ * The final implementation depends either on the underlying operating system
+ * or can configured during compile time.
+ *
+ * It also provides a simple filtering facility if required. See [method@GUPnP.ContextManager.get_context_filter] and
+ * [class@GUPnP.ContextFilter] for details.
+ *
+ * Since: 0.14.0
+ */
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GUPnPContextManager,
gupnp_context_manager,
G_TYPE_OBJECT)
@@ -483,7 +489,7 @@ gupnp_context_manager_class_init (GUPnPContextManagerClass *klass)
object_class->dispose = gupnp_context_manager_dispose;
/**
- * GUPnPContextManager:port:
+ * GUPnPContextManager:port:(attributes org.gtk.Property.get=gupnp_context_manager_get_port)
*
* Port the contexts listen on, or 0 if you don't care what
* port is used by #GUPnPContext objects created by this object.
@@ -502,7 +508,7 @@ gupnp_context_manager_class_init (GUPnPContextManagerClass *klass)
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
/**
- * GUPnPContextManager:family:
+ * GUPnPContextManager:family:(attributes org.gtk.Property.get=gupnp_context_manager_get_socket_family)
*
* The socket family to create contexts for. Use %G_SOCKET_FAMILY_INVALID
* for any or %G_SOCKET_FAMILY_IPV4 for IPv4 contexts or
@@ -523,7 +529,7 @@ gupnp_context_manager_class_init (GUPnPContextManagerClass *klass)
G_PARAM_STATIC_STRINGS));
/**
- * GUPnPContextManager:uda-version:
+ * GUPnPContextManager:uda-version:(attributes org.gtk.Property.get=gupnp_context_manager_get_uda_version)
*
* The UDA version the contexts will support. Use %GSSDP_UDA_VERSION_UNSPECIFIED
* for using the default UDA version.
@@ -543,7 +549,7 @@ gupnp_context_manager_class_init (GUPnPContextManagerClass *klass)
G_PARAM_STATIC_STRINGS));
/**
- * GUPnPContextManager:context-filter:
+ * GUPnPContextManager:context-filter:(attributes org.gtk.Property.get=gupnp_context_manager_get_context_filter)
*
* The context filter to use.
**/
@@ -606,7 +612,7 @@ gupnp_context_manager_class_init (GUPnPContextManagerClass *klass)
*
* Factory-method to create a new #GUPnPContextManager. The final type of the
* #GUPnPContextManager depends on the compile-time selection or - in case of
- * NetworkManager - on its availability during runtime. If it is not available,
+ * NetworkManager - on its availability during run-time. If it is not available,
* the implementation falls back to the basic Unix context manager instead.
*
* Equivalent to calling #gupnp_context_manager_create_full (%GSSDP_UDA_VERSION_1_0, %G_SOCKET_FAMILY_IPV4, port);
@@ -632,7 +638,7 @@ gupnp_context_manager_create (guint port)
*
* Factory-method to create a new #GUPnPContextManager. The final type of the
* #GUPnPContextManager depends on the compile-time selection or - in case of
- * NetworkManager - on its availability during runtime. If it is not available,
+ * NetworkManager - on its availability during run-time. If it is not available,
* the implementation falls back to the basic Unix context manager instead.
*
* Returns: (transfer full): A new #GUPnPContextManager object.
@@ -739,9 +745,23 @@ gupnp_context_manager_rescan_control_points (GUPnPContextManager *manager)
*
* By calling this function, you are asking @manager to keep a reference to
* @control_point until its associated #GUPnPContext is no longer available.
- * You usually want to call this function from
- * #GUPnPContextManager::context-available handler after you create a
+ * You usually want to call this function from your
+ * [signal@GUPnP.ContextManager::context-available] handler after you create a
* #GUPnPControlPoint object for the newly available context.
+ * You usually then give up your own reference to the control point so it will be
+ * automatically destroyed if its context is no longer available.
+ *
+ * This function is mainly useful when implementing an UPnP client.
+ *
+ * ```c
+ * void on_context_available (GUPnPContextManager *manager, GUPnPContext *context, gpointer user_data)
+ * {
+ * GUPnPControlPoint *cp = gupnp_control_point_new (context, "urn:schemas-upnp-org:device:MediaRenderer:1");
+ * gupnp_context_manager_manage_control_point (manager, cp);
+ * // Subscribe to control point's signals etc.
+ * g_object_unref (cp);
+ * }
+ * ```
*
* Since: 0.14.0
**/
@@ -767,9 +787,25 @@ gupnp_context_manager_manage_control_point (GUPnPContextManager *manager,
* By calling this function, you are asking @manager to keep a reference to
* @root_device when its associated #GUPnPContext is no longer available. You
* usually want to call this function from
- * #GUPnPContextManager::context-available handler after you create a
+ * [signal@GUPnP.ContextManager::context-available] handler after you create a
* #GUPnPRootDevice object for the newly available context.
*
+ * You usually then give up your own reference to the root device so it will be
+ * automatically destroyed if its context is no longer available.
+ *
+ * This function is mainly useful when implementing an UPnP client.
+ *
+ * ```c
+ * void on_context_available (GUPnPContextManager *manager, GUPnPContext *context, gpointer user_data)
+ * {
+ * GError *error = NULL;
+ *
+ * GUPnPRootDevice *rd = gupnp_root_device_new (context, "BasicLight1.xml", ".", &error);
+ * gupnp_context_manager_manage_root_device (manager, rd);
+ * // Subscribe to control point's signals etc.
+ * g_object_unref (rd);
+ * }
+ * ```
* Since: 0.14.0
**/
void
@@ -787,11 +823,11 @@ gupnp_context_manager_manage_root_device (GUPnPContextManager *manager,
}
/**
- * gupnp_context_manager_get_port:
+ * gupnp_context_manager_get_port:(attributes org.gtk.Method.get_property=port)
* @manager: A #GUPnPContextManager
*
* Get the network port associated with this context manager.
- * Returns: The network port asssociated with this context manager.
+ * Returns: The network port associated with this context manager.
*
* Since: 0.20.0
*/
@@ -808,13 +844,15 @@ gupnp_context_manager_get_port (GUPnPContextManager *manager)
}
/**
- * gupnp_context_manager_get_context_filter:
+ * gupnp_context_manager_get_context_filter:(attributes org.gtk.Method.get_property=context-filter)
* @manager: A #GUPnPContextManager
*
* Get the #GUPnPContextFilter associated with @manager.
*
- * Returns: (transfer none): The #GUPnPContextFilter asssociated with this
+ * Returns: (transfer none): The #GUPnPContextFilter associated with this
* context manager.
+ *
+ * Since: 1.4.0
*/
GUPnPContextFilter *
gupnp_context_manager_get_context_filter (GUPnPContextManager *manager)
@@ -834,9 +872,9 @@ gupnp_context_manager_get_context_filter (GUPnPContextManager *manager)
*
* Get the #GUPnPContextFilter associated with @manager.
*
- * Returns: (transfer none): The #GUPnPContextFilter asssociated with this
+ * Returns: (transfer none): The #GUPnPContextFilter associated with this
* context manager.
- * Deprecated: 1.4.0: Use gupnp_context_manager_get_context_filter() instead.
+ * Deprecated: 1.4.0: Use [method@GUPnP.ContextManager.get_context_filter] instead.
*/
GUPnPWhiteList *
gupnp_context_manager_get_white_list (GUPnPContextManager *manager)
@@ -845,7 +883,7 @@ gupnp_context_manager_get_white_list (GUPnPContextManager *manager)
}
/**
- * gupnp_context_manager_get_socket_family:
+ * gupnp_context_manager_get_socket_family:(attributes org.gtk.Method.get_property=family)
* @manager: A #GUPnPContextManager
*
* Get the #GSocketFamily the contexts are created for. Can be
@@ -869,7 +907,7 @@ gupnp_context_manager_get_socket_family (GUPnPContextManager *manager)
}
/**
- * gupnp_context_manager_get_uda_version:
+ * gupnp_context_manager_get_uda_version:(attributes org.gtk.Method.get_property=uda-version)
* @manager: A #GUPnPContextManager
*
* Get the UDA protocol version the contexts are implementing
diff --git a/libgupnp/gupnp-context.c b/libgupnp/gupnp-context.c
index 335cce8..bef53f8 100644
--- a/libgupnp/gupnp-context.c
+++ b/libgupnp/gupnp-context.c
@@ -11,14 +11,15 @@
*/
/**
- * SECTION:gupnp-context
- * @short_description: Context object wrapping shared networking bits.
+ * GUPnPContext:
+ *
+ * Context object wrapping shared networking bits.
*
* #GUPnPContext wraps the networking bits that are used by the various
* GUPnP classes. It automatically starts a web server on demand.
*
* For debugging, it is possible to see the messages being sent and received by
- * exporting <envar>GUPNP_DEBUG</envar>.
+ * setting the environment variable `GUPNP_DEBUG`.
*/
#define G_LOG_DOMAIN "gupnp-context"
@@ -362,7 +363,7 @@ gupnp_context_class_init (GUPnPContextClass *klass)
object_class->finalize = gupnp_context_finalize;
/**
- * GUPnPContext:server:
+ * GUPnPContext:server:(attributes org.gtk.Property.get=gupnp_context_get_server)
*
* The #SoupServer HTTP server used by GUPnP.
**/
@@ -379,7 +380,7 @@ gupnp_context_class_init (GUPnPContextClass *klass)
G_PARAM_STATIC_BLURB));
/**
- * GUPnPContext:session:
+ * GUPnPContext:session:(attributes org.gtk.Property.get=gupnp_context_get_session)
*
* The #SoupSession object used by GUPnP.
**/
@@ -396,7 +397,7 @@ gupnp_context_class_init (GUPnPContextClass *klass)
G_PARAM_STATIC_BLURB));
/**
- * GUPnPContext:subscription-timeout:
+ * GUPnPContext:subscription-timeout:(attributes org.gtk.Property.get=gupnp_context_get_subscription_timeout org.gtk.Property.set=gupnp_context_set_subscription_timeout)
*
* The preferred subscription timeout: the number of seconds after
* which subscriptions are renewed. Set to '0' if subscriptions
@@ -417,7 +418,7 @@ gupnp_context_class_init (GUPnPContextClass *klass)
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
/**
- * GUPnPContext:default-language:
+ * GUPnPContext:default-language:(attributes org.gtk.Property.get=gupnp_context_get_default_language org.gtk.Property.set=gupnp_context_set_default_language)
*
* The content of the Content-Language header id the client
* sends Accept-Language and no language-specific pages to serve
@@ -439,7 +440,7 @@ gupnp_context_class_init (GUPnPContextClass *klass)
G_PARAM_STATIC_BLURB));
/**
- * GUPnPContext:acl:
+ * GUPnPContext:acl:(attributes org.gtk.Property.get=gupnp_context_get_acl org.gtk.Property.set=gupnp_context_set_acl)
*
* An access control list.
*
@@ -458,7 +459,7 @@ gupnp_context_class_init (GUPnPContextClass *klass)
}
/**
- * gupnp_context_get_session:
+ * gupnp_context_get_session:(attributes org.gtk.Method.get_property=session)
* @context: A #GUPnPContext
*
* Get the #SoupSession object that GUPnP is using.
@@ -496,7 +497,7 @@ default_server_handler (G_GNUC_UNUSED SoupServer *server,
}
/**
- * gupnp_context_get_server:
+ * gupnp_context_get_server:(attributes org.gtk.Method.get_property=server)
* @context: A #GUPnPContext
*
* Get the #SoupServer HTTP server that GUPnP is using.
@@ -613,6 +614,7 @@ gupnp_context_new (const char *iface,
NULL);
}
+\
/**
* gupnp_context_get_port:
* @context: A #GUPnPContext
@@ -624,19 +626,16 @@ gupnp_context_new (const char *iface,
guint
gupnp_context_get_port (GUPnPContext *context)
{
- GUPnPContextPrivate *priv;
-
g_return_val_if_fail (GUPNP_IS_CONTEXT (context), 0);
- priv = gupnp_context_get_instance_private (context);
- if (priv->server_uri == NULL)
- priv->server_uri = make_server_uri (context);
+ GUri *uri = _gupnp_context_get_server_uri (context);
+ g_uri_unref (uri);
- return g_uri_get_port (priv->server_uri);
+ return g_uri_get_port (uri);
}
/**
- * gupnp_context_set_subscription_timeout:
+ * gupnp_context_set_subscription_timeout:(attributes org.gtk.Method.set_property=subscription-timeout)
* @context: A #GUPnPContext
* @timeout: Event subscription timeout in seconds
*
@@ -659,7 +658,7 @@ gupnp_context_set_subscription_timeout (GUPnPContext *context,
}
/**
- * gupnp_context_get_subscription_timeout:
+ * gupnp_context_get_subscription_timeout:(attributes org.gtk.Method.get_property=subscription-timeout)
* @context: A #GUPnPContext
*
* Get the event subscription timeout (in seconds), or 0 meaning there is no
@@ -693,7 +692,7 @@ host_path_data_set_language (HostPathData *data, const char *language)
}
/**
- * gupnp_context_set_default_language:
+ * gupnp_context_set_default_language:(attributes org.gtk.Method.set_property=default-language)
* @context: A #GUPnPContext
* @language: A language tag as defined in RFC 2616 3.10
*
@@ -733,7 +732,7 @@ gupnp_context_set_default_language (GUPnPContext *context,
}
/**
- * gupnp_context_get_default_language:
+ * gupnp_context_get_default_language:(attributes org.gtk.Method.get_property=default-language)
* @context: A #GUPnPContext
*
* Get the default Content-Language header for this context.
@@ -1334,7 +1333,7 @@ gupnp_context_unhost_path (GUPnPContext *context,
}
/**
- * gupnp_context_get_acl:
+ * gupnp_context_get_acl:(attributes org.gtk.Method.get_property=acl)
* @context: A #GUPnPContext
*
* Access the #GUPnPAcl associated with this client. If there isn't any,
@@ -1357,7 +1356,7 @@ gupnp_context_get_acl (GUPnPContext *context)
}
/**
- * gupnp_context_set_acl:
+ * gupnp_context_set_acl:(attributes org.gtk.Method.set_property=acl)
* @context: A #GUPnPContext
* @acl: (nullable): The new access control list or %NULL to remove the
* current list.
diff --git a/libgupnp/gupnp-context.h b/libgupnp/gupnp-context.h
index d722ed7..79b3e30 100644
--- a/libgupnp/gupnp-context.h
+++ b/libgupnp/gupnp-context.h
@@ -26,7 +26,16 @@ struct _GUPnPContextClass {
GSSDPClientClass parent_class;
/* future padding */
+ /*<private>*/
+ /**
+ * _gupnp_reserved1:(skip):
+ *
+ * Padding
+ */
void (* _gupnp_reserved1) (void);
+ /**
+ * _gupnp_reserved2:(skip):
+ */
void (* _gupnp_reserved2) (void);
void (* _gupnp_reserved3) (void);
void (* _gupnp_reserved4) (void);
diff --git a/libgupnp/gupnp-control-point.c b/libgupnp/gupnp-control-point.c
index 97bdfa5..41d56c6 100644
--- a/libgupnp/gupnp-control-point.c
+++ b/libgupnp/gupnp-control-point.c
@@ -8,13 +8,16 @@
*/
/**
- * SECTION:gupnp-control-point
- * @short_description: Class for resource discovery.
+ * GUPnPControlPoint:
+ *
+ * Network resource discovery.
*
* #GUPnPControlPoint handles device and service discovery. After creating
- * a control point and activating it using gssdp_resource_browser_set_active(),
- * the ::device-proxy-available, ::service-proxy-available,
- * ::device-proxy-unavailable and ::service-proxy-unavailable signals will
+ * a control point and activating it using [method@GSSDP.ResourceBrowser.set_active],
+ * the [signal@GUPnP.ControlPoint::device-proxy-available],
+ * [signal@GUPnP.ControlPoint::service-proxy-available],
+ * [signal@GUPnP.ControlPoint::device-proxy-unavailable] and
+ * [signal@GUPnP.ControlPoint::service-proxy-unavailable] signals will
* be emitted whenever the availability of a device or service matching
* the specified discovery target changes.
*/
@@ -1044,7 +1047,7 @@ gupnp_control_point_class_init (GUPnPControlPointClass *klass)
gupnp_control_point_resource_unavailable;
/**
- * GUPnPControlPoint:resource-factory:
+ * GUPnPControlPoint:resource-factory:(attributes org.gtk.Property.get=gupnp_control_point_get_resource_factory)
*
* The resource factory to use. Set to NULL for default factory.
**/
@@ -1154,8 +1157,8 @@ gupnp_control_point_class_init (GUPnPControlPointClass *klass)
* Create a new #GUPnPControlPoint with the specified @context and @target.
*
* @target should be a service or device name, such as
- * <literal>urn:schemas-upnp-org:service:WANIPConnection:1</literal> or
- * <literal>urn:schemas-upnp-org:device:MediaRenderer:1</literal>.
+ * `urn:schemas-upnp-org:service:WANIPConnection:1` or
+ * `urn:schemas-upnp-org:device:MediaRenderer:1`.
*
* Return value: A new #GUPnPControlPoint object.
**/
@@ -1182,8 +1185,12 @@ gupnp_control_point_new (GUPnPContext *context,
* @target.
*
* @target should be a service or device name, such as
- * <literal>urn:schemas-upnp-org:service:WANIPConnection:1</literal> or
- * <literal>urn:schemas-upnp-org:device:MediaRenderer:1</literal>.
+ * `urn:schemas-upnp-org:service:WANIPConnection:1` or
+ * `urn:schemas-upnp-org:device:MediaRenderer:1`.
+ *
+ * By passing a custom `GUPnPResourceFactory`, the proxies handed out in ::device-available and
+ * ::service-available can be overridden to hand out custom classes instead of the generic
+ * [class@GUPnP.ServiceProxy] and [class@GUPnP.DeviceProxy].
*
* Return value: A new #GUPnPControlPoint object.
**/
@@ -1211,6 +1218,7 @@ gupnp_control_point_new_full (GUPnPContext *context,
* Get the #GUPnPControlPoint associated with @control_point.
*
* Returns: (transfer none): The #GUPnPContext.
+ * Deprecated: 1.4.0: Use [method@GSSDP.ResourceBrowser.get_client] instead.
**/
GUPnPContext *
gupnp_control_point_get_context (GUPnPControlPoint *control_point)
@@ -1229,11 +1237,17 @@ gupnp_control_point_get_context (GUPnPControlPoint *control_point)
* gupnp_control_point_list_device_proxies:
* @control_point: A #GUPnPControlPoint
*
- * Get the #GList of discovered #GUPnPDeviceProxy objects. Do not free the list
- * nor its elements.
+ * Get the list of #GUPnPDeviceProxy objects the control point currently assumes to
+ * be active.
+ *
+ * Since a device might have gone offline without signalizing it, but
+ * the automatic resource timeout has not happened yet, it is possible that some of
+ * the devices listed are not available anymore on the network.
*
- * Return value: (element-type GUPnP.DeviceProxy) (transfer none): a #GList of
- * #GUPnPDeviceProxy objects.
+ * Do not free the list nor its elements.
+ *
+ * Return value: (element-type GUPnP.DeviceProxy) (transfer none): Device proxies
+ * currently assumed to be active.
**/
const GList *
gupnp_control_point_list_device_proxies (GUPnPControlPoint *control_point)
@@ -1251,11 +1265,17 @@ gupnp_control_point_list_device_proxies (GUPnPControlPoint *control_point)
* gupnp_control_point_list_service_proxies:
* @control_point: A #GUPnPControlPoint
*
- * Get the #GList of discovered #GUPnPServiceProxy objects. Do not free the
- * list nor its elements.
+ * Get the list of discovered #GUPnPServiceProxy objects the control point currently assumes to
+ * be active.
+ *
+ * Since a device might have gone offline without signalizing it, but
+ * the automatic resource timeout has not happened yet, it is possible that some of
+ * the services listed are not available anymore on the network.
+ *
+ * Do not free the list nor its elements.
*
- * Return value: (element-type GUPnP.ServiceProxy) (transfer none): a #GList
- * of #GUPnPServiceProxy objects.
+ * Return value: (element-type GUPnP.ServiceProxy) (transfer none): Service proxies
+ * currently assumed to be active.
**/
const GList *
gupnp_control_point_list_service_proxies (GUPnPControlPoint *control_point)
@@ -1270,12 +1290,14 @@ gupnp_control_point_list_service_proxies (GUPnPControlPoint *control_point)
}
/**
- * gupnp_control_point_get_resource_factory:
+ * gupnp_control_point_get_resource_factory:(attributes org.gtk.Method.get_property=resource-factory)
* @control_point: A #GUPnPControlPoint
*
- * Get the #GUPnPResourceFactory used by the @control_point.
+ * Get the #GUPnPResourceFactory used by the @control_point. If none was set during construction
+ * by calling [ctor@GUPnP.ControlPoint.new_full], equivalent to calling
+ * [func@GUPnP.ResourceFactory.get_default]
*
- * Returns: (transfer none): A #GUPnPResourceFactory.
+ * Returns: (transfer none): The #GUPnPResourceFactory used by this control point
**/
GUPnPResourceFactory *
gupnp_control_point_get_resource_factory (GUPnPControlPoint *control_point)
diff --git a/libgupnp/gupnp-device-info.c b/libgupnp/gupnp-device-info.c
index b329748..09e17e3 100644
--- a/libgupnp/gupnp-device-info.c
+++ b/libgupnp/gupnp-device-info.c
@@ -7,13 +7,7 @@
*
*/
-/**
- * SECTION:gupnp-device-info
- * @short_description: Base abstract class for querying device information.
- *
- * The #GUPnPDeviceInfo base abstract class provides methods for querying
- * device information.
- */
+
#include <config.h>
#include <string.h>
@@ -39,6 +33,15 @@ struct _GUPnPDeviceInfoPrivate {
};
typedef struct _GUPnPDeviceInfoPrivate GUPnPDeviceInfoPrivate;
+/**
+ * GUPnPDeviceInfo:
+ *
+ * Device information shared by local and remote devices
+ *
+ * This class aggregates the information that is shared between remote and local
+ * devices.
+ */
+
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GUPnPDeviceInfo,
gupnp_device_info,
G_TYPE_OBJECT)
@@ -195,98 +198,87 @@ gupnp_device_info_class_init (GUPnPDeviceInfoClass *klass)
object_class->finalize = gupnp_device_info_finalize;
/**
- * GUPnPDeviceInfo:resource-factory:
+ * GUPnPDeviceInfo:resource-factory:(attributes org.gtk.Property.get=gupnp_device_info_get_resource_factory):
*
* The resource factory to use. Set to NULL for default factory.
**/
- g_object_class_install_property
- (object_class,
- PROP_RESOURCE_FACTORY,
- g_param_spec_object ("resource-factory",
- "Resource Factory",
- "The resource factory to use",
- GUPNP_TYPE_RESOURCE_FACTORY,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (
+ object_class,
+ PROP_RESOURCE_FACTORY,
+ g_param_spec_object ("resource-factory",
+ "Resource Factory",
+ "The resource factory to use",
+ GUPNP_TYPE_RESOURCE_FACTORY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
/**
- * GUPnPDeviceInfo:context:
+ * GUPnPDeviceInfo:context:(attributes org.gtk.Property.get=gupnp_device_info_get_context):
*
* The #GUPnPContext to use.
**/
- g_object_class_install_property
- (object_class,
- PROP_CONTEXT,
- g_param_spec_object ("context",
- "Context",
- "The GUPnPContext",
- GUPNP_TYPE_CONTEXT,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (
+ object_class,
+ PROP_CONTEXT,
+ g_param_spec_object ("context",
+ "Context",
+ "The GUPnPContext",
+ GUPNP_TYPE_CONTEXT,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
/**
- * GUPnPDeviceInfo:location:
+ * GUPnPDeviceInfo:location:(attributes org.gtk.Property.get=gupnp_device_info_get_location):
*
* The location of the device description file.
**/
- g_object_class_install_property
- (object_class,
- PROP_LOCATION,
- g_param_spec_string ("location",
- "Location",
- "The location of the device description "
- "file",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (
+ object_class,
+ PROP_LOCATION,
+ g_param_spec_string ("location",
+ "Location",
+ "The location of the device description "
+ "file",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
/**
- * GUPnPDeviceInfo:udn:
+ * GUPnPDeviceInfo:udn:(attributes org.gtk.Property.get=gupnp_device_info_get_udn):
*
* The UDN of this device.
**/
- g_object_class_install_property
- (object_class,
- PROP_UDN,
- g_param_spec_string ("udn",
- "UDN",
- "The UDN",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (
+ object_class,
+ PROP_UDN,
+ g_param_spec_string ("udn",
+ "UDN",
+ "The Unique Device Name",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
/**
- * GUPnPDeviceInfo:device-type:
+ * GUPnPDeviceInfo:device-type:(attributes org.gtk.Property.get=gupnp_device_info_get_device_type):
*
- * The device type.
+ * The device type, e.g. `urn:schemas-upnp-org:device:InternetGatewayDevice:1`
**/
- g_object_class_install_property
- (object_class,
- PROP_DEVICE_TYPE,
- g_param_spec_string ("device-type",
- "Device type",
- "The device type",
- NULL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (
+ object_class,
+ PROP_DEVICE_TYPE,
+ g_param_spec_string ("device-type",
+ "Device type",
+ "The device type",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
/**
- * GUPnPDeviceInfo:url-base:
+ * GUPnPDeviceInfo:url-base:(attributes org.gtk.Property.get=gupnp_device_info_get_url_base):
*
* The URL base (#SoupURI).
**/
@@ -298,9 +290,7 @@ gupnp_device_info_class_init (GUPnPDeviceInfoClass *klass)
"The URL base",
G_TYPE_URI,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB));
+ G_PARAM_STATIC_STRINGS));
/**
* GUPnPDeviceInfo:document:
@@ -318,9 +308,7 @@ gupnp_device_info_class_init (GUPnPDeviceInfoClass *klass)
"device",
GUPNP_TYPE_XML_DOC,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB));
+ G_PARAM_STATIC_STRINGS));
/**
* GUPnPDeviceInfo:element:
@@ -329,18 +317,15 @@ gupnp_device_info_class_init (GUPnPDeviceInfoClass *klass)
*
* Stability: Private
**/
- g_object_class_install_property
- (object_class,
- PROP_ELEMENT,
- g_param_spec_pointer ("element",
- "Element",
- "The XML element related to this "
- "device",
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB));
+ g_object_class_install_property (
+ object_class,
+ PROP_ELEMENT,
+ g_param_spec_pointer ("element",
+ "Element",
+ "The XML element related to this "
+ "device",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
}
/**
@@ -399,7 +384,7 @@ gupnp_device_info_create_service_instance (GUPnPDeviceInfo *info,
}
/**
- * gupnp_device_info_get_resource_factory:
+ * gupnp_device_info_get_resource_factory:(attributes org.gtk.Method.get_property=resource-factory):
* @device_info: A #GUPnPDeviceInfo
*
* Get the #GUPnPResourceFactory used by the @device_info.
@@ -419,12 +404,12 @@ gupnp_device_info_get_resource_factory (GUPnPDeviceInfo *info)
}
/**
- * gupnp_device_info_get_context:
+ * gupnp_device_info_get_context:(attributes org.gtk.Method.get_property=context):
* @info: A #GUPnPDeviceInfo
*
* Get the associated #GUPnPContext.
*
- * Returns: (transfer none): A #GUPnPContext.
+ * Returns: (transfer none): The #GUPnPContext the devices is operating on.
**/
GUPnPContext *
gupnp_device_info_get_context (GUPnPDeviceInfo *info)
@@ -442,9 +427,9 @@ gupnp_device_info_get_context (GUPnPDeviceInfo *info)
* gupnp_device_info_get_location:
* @info: A #GUPnPDeviceInfo
*
- * Get the location of the device description file.
+ * Get the URL of the device file
*
- * Returns: A constant string.
+ * Returns: A s
**/
const char *
gupnp_device_info_get_location (GUPnPDeviceInfo *info)
@@ -459,7 +444,7 @@ gupnp_device_info_get_location (GUPnPDeviceInfo *info)
}
/**
- * gupnp_device_info_get_url_base:
+ * gupnp_device_info_get_url_base:(attributes org.gtk.Method.get_property=url-base):
* @info: A #GUPnPDeviceInfo
*
* Get the URL base of this device.
@@ -479,7 +464,7 @@ gupnp_device_info_get_url_base (GUPnPDeviceInfo *info)
}
/**
- * gupnp_device_info_get_udn:
+ * gupnp_device_info_get_udn:(attributes org.gtk.Method.get_property=udn):
* @info: A #GUPnPDeviceInfo
*
* Get the Unique Device Name of the device.
@@ -504,10 +489,10 @@ gupnp_device_info_get_udn (GUPnPDeviceInfo *info)
}
/**
- * gupnp_device_info_get_device_type:
+ * gupnp_device_info_get_device_type:(attributes org.gtk.Method.get_property=device-type):
* @info: A #GUPnPDeviceInfo
*
- * Get the UPnP device type.
+ * Get the UPnP device type of this #GUPnPDeviceInfo, e.g. `urn:schemas-upnp-org:device:InternetGatewayDevice:1`
*
* Returns: A constant string, or %NULL.
**/
@@ -534,7 +519,8 @@ gupnp_device_info_get_device_type (GUPnPDeviceInfo *info)
*
* Get the friendly name of the device.
*
- * Return value: A string, or %NULL. g_free() after use.
+ * Return value:(nullable)(transfer full):A newly allocated string containing the
+ * "friendly name" of the device, or %NULL if not available. g_free() after use.
**/
char *
gupnp_device_info_get_friendly_name (GUPnPDeviceInfo *info)
@@ -555,7 +541,8 @@ gupnp_device_info_get_friendly_name (GUPnPDeviceInfo *info)
*
* Get the manufacturer of the device.
*
- * Return value:(nullable)(transfer full): A string, or %NULL. g_free() after use.
+ * Return value:(nullable)(transfer full): A newly allocated string containing the
+ * manufacturer of the device, or %NULL if not available. g_free() after use.
**/
char *
gupnp_device_info_get_manufacturer (GUPnPDeviceInfo *info)
@@ -724,7 +711,7 @@ gupnp_device_info_get_upc (GUPnPDeviceInfo *info)
* @info: A #GUPnPDeviceInfo
*
* Get an URL pointing to the device's presentation page, for web-based
- * administration.
+ * administration, if available.
*
* Return value:(nullable)(transfer full): A string, or %NULL. g_free() after use.
**/
@@ -776,12 +763,8 @@ icon_parse (xmlNode *element)
static void
icon_free (Icon *icon)
{
- if (icon->mime_type)
- xmlFree (icon->mime_type);
-
- if (icon->url)
- xmlFree (icon->url);
-
+ g_clear_pointer (&icon->mime_type, xmlFree);
+ g_clear_pointer (&icon->url, xmlFree);
g_slice_free (Icon, icon);
}
@@ -806,7 +789,9 @@ icon_free (Icon *icon)
* returned icon, or %NULL
*
* Get an URL pointing to the icon most closely matching the
- * given criteria, or %NULL. If @requested_mime_type is set, only icons with
+ * given criteria, or %NULL.
+ *
+ * If @requested_mime_type is set, only icons with
* this mime type will be returned. If @requested_depth is set, only icons with
* this or lower depth will be returned. If @requested_width and/or
* @requested_height are set, only icons that are this size or smaller are
@@ -1053,11 +1038,12 @@ resource_type_match (const char *query,
* gupnp_device_info_list_dlna_device_class_identifier:
* @info: A #GUPnPDeviceInfo
*
- * Get a #GList of strings that represent the device class and version as
- * announced in the device description file using the &lt;dlna:X_DLNADOC&gt;
- * element.
+ * Get a list of strings that represent the device class and version as
+ * announced in the device description file using the `<dlna:X_DLNADOC>`
+ * element, e.g. `DMS-1.51`, `M-DMS-1.51` and so on.
+ *
* Returns:(nullable)(transfer full) (element-type utf8): a #GList of newly allocated strings or
- * %NULL if the device description doesn't contain the &lt;dlna:X_DLNADOC&gt;
+ * %NULL if the device description doesn't contain any `<dlna:X_DLNADOC>`
* element.
*
* Since: 0.20.4
@@ -1163,8 +1149,8 @@ gupnp_device_info_list_dlna_capabilities (GUPnPDeviceInfo *info)
* This function provides generic access to the contents of arbitrary elements
* in the device description file.
*
- * Return value:(nullable)(transfer full): a newly allocated string or %NULL if the device
- * description doesn't contain the given @element
+ * Return value:(nullable)(transfer full): a newly allocated string containing the
+ * requested value or %NULL if the device description doesn't contain the given @element
*
* Since: 0.14.0
**/
@@ -1188,8 +1174,7 @@ gupnp_device_info_get_description_value (GUPnPDeviceInfo *info,
* @info: A #GUPnPDeviceInfo
*
* Get a #GList of new objects implementing #GUPnPDeviceInfo
- * representing the devices directly contained in @info. The returned list
- * should be g_list_free()'d and the elements should be g_object_unref()'d.
+ * representing the devices directly contained in @info, excluding itself.
*
* Note that devices are not cached internally, so that every time you
* call this function new objects are created. The application
@@ -1197,7 +1182,7 @@ gupnp_device_info_get_description_value (GUPnPDeviceInfo *info,
* them.
*
* Return value:(nullable)(element-type GUPnP.DeviceInfo) (transfer full): a #GList of
- * new #GUPnPDeviceInfo objects.
+ * new #GUPnPDeviceInfo objects or %NULL if no devices are
**/
GList *
gupnp_device_info_list_devices (GUPnPDeviceInfo *info)
@@ -1285,7 +1270,7 @@ gupnp_device_info_list_device_types (GUPnPDeviceInfo *info)
* @info: A #GUPnPDeviceInfo
* @type: The type of the device to be retrieved.
*
- * Get the service with type @type directly contained in @info as
+ * Get the device with type @type directly contained in @info as
* a new object implementing #GUPnPDeviceInfo, or %NULL if no such device
* was found. The returned object should be unreffed when done.
*
@@ -1406,7 +1391,7 @@ gupnp_device_info_list_services (GUPnPDeviceInfo *info)
* @info: A #GUPnPDeviceInfo
*
* Get a #GList of strings representing the types of the services
- * directly contained in @info.
+ * directly contained in @info, but not in its subdevices.
*
* Return value: (nullable)(element-type utf8) (transfer full): A #GList of strings. The
* elements should be g_free()'d and the list should be g_list_free()'d.
@@ -1452,8 +1437,7 @@ gupnp_device_info_list_service_types (GUPnPDeviceInfo *info)
* @type: The type of the service to be retrieved.
*
* Get the service with type @type directly contained in @info as a new object
- * implementing #GUPnPServiceInfo, or %NULL if no such device was found. The
- * returned object should be unreffed when done.
+ * implementing #GUPnPServiceInfo, or %NULL if no such device was found.
*
* Note that services are not cached internally, so that every time you call
* this function a new object is created. The application must cache any used
diff --git a/libgupnp/gupnp-device-proxy.c b/libgupnp/gupnp-device-proxy.c
index cb87904..fde10ec 100644
--- a/libgupnp/gupnp-device-proxy.c
+++ b/libgupnp/gupnp-device-proxy.c
@@ -7,13 +7,6 @@
*
*/
-/**
- * SECTION:gupnp-device-proxy
- * @short_description: Proxy class for remote devices.
- *
- * #GUPnPDeviceProxy allows for retrieving proxies for a device's subdevices
- * and services. #GUPnPDeviceProxy implements the #GUPnPDeviceInfo interface.
- */
#include <config.h>
#include <string.h>
@@ -23,6 +16,14 @@
#include "gupnp-resource-factory-private.h"
#include "xml-util.h"
+/**
+ * GUPnPDeviceProxy:
+ *
+ * Interaction with remote UPnP devices.
+ *
+ * #GUPnPDeviceProxy allows for retrieving proxies for a device's sub-devices
+ * and services. It implements the [class@GUPnP.DeviceInfo] abstract class.
+ */
G_DEFINE_TYPE (GUPnPDeviceProxy,
gupnp_device_proxy,
GUPNP_TYPE_DEVICE_INFO)
diff --git a/libgupnp/gupnp-device.c b/libgupnp/gupnp-device.c
index 523a248..893a647 100644
--- a/libgupnp/gupnp-device.c
+++ b/libgupnp/gupnp-device.c
@@ -7,15 +7,6 @@
*
*/
-/**
- * SECTION:gupnp-device
- * @short_description: Class for device implementations.
- *
- * #GUPnPDevice allows for retrieving a device's subdevices
- * and services. #GUPnPDevice implements the #GUPnPDeviceInfo
- * interface.
- */
-
#include <config.h>
#include <string.h>
@@ -30,6 +21,15 @@ struct _GUPnPDevicePrivate {
};
typedef struct _GUPnPDevicePrivate GUPnPDevicePrivate;
+/**
+ * GUPnPDevice:
+ *
+ * Base class for UPnP device implementations.
+ *
+ * #GUPnPDevice allows for retrieving a device's sub-devices
+ * and services. #GUPnPDevice implements the #GUPnPDeviceInfo
+ * interface.
+ */
G_DEFINE_TYPE_WITH_PRIVATE (GUPnPDevice,
gupnp_device,
GUPNP_TYPE_DEVICE_INFO)
diff --git a/libgupnp/gupnp-error.h b/libgupnp/gupnp-error.h
index 2baa4ff..ad84064 100644
--- a/libgupnp/gupnp-error.h
+++ b/libgupnp/gupnp-error.h
@@ -27,8 +27,7 @@ gupnp_server_error_quark (void) G_GNUC_CONST;
* @GUPNP_SERVER_ERROR_INVALID_URL: Invalid URL.
* @GUPNP_SERVER_ERROR_OTHER: Unknown/unhandled error.
*
- * #GError codes used for errors in the #GUPNP_SERVER_ERROR domain, when there
- * is communication with another server.
+ * Error codes during communication with another server.
*/
typedef enum {
GUPNP_SERVER_ERROR_INTERNAL_SERVER_ERROR,
@@ -50,8 +49,7 @@ gupnp_eventing_error_quark (void) G_GNUC_CONST;
* @GUPNP_EVENTING_ERROR_SUBSCRIPTION_LOST: The subscription was lost.
* @GUPNP_EVENTING_ERROR_NOTIFY_FAILED: The notification failed.
*
- * #GError codes used for errors in the #GUPNP_EVENTING_ERROR domain, during
- * eventing of state variables.
+ * Error codes during eventing of state variables.
*/
typedef enum {
GUPNP_EVENTING_ERROR_SUBSCRIPTION_FAILED,
@@ -71,8 +69,7 @@ gupnp_control_error_quark (void) G_GNUC_CONST;
* @GUPNP_CONTROL_ERROR_OUT_OF_SYNC: Out of sync (deprecated).
* @GUPNP_CONTROL_ERROR_ACTION_FAILED: The action failed.
*
- * #GError codes used for errors in the #GUPNP_CONTROL_ERROR domain, during
- * invocation of service actions.
+ * Error codes used during invocation of service actions.
*/
typedef enum {
GUPNP_CONTROL_ERROR_INVALID_ACTION = 401,
@@ -94,8 +91,7 @@ gupnp_xml_error_quark (void) G_GNUC_CONST;
* @GUPNP_XML_ERROR_INVALID_ATTRIBUTE: An XML node has an unknown attribute.
* @GUPNP_XML_ERROR_OTHER: Unknown/unhandled XML related errors.
*
- * #GError codes used for errors in the #GUPNP_XML_ERROR domain, during
- * processing of XML data.
+ * Errors during occuring during processing of XML data.
*/
typedef enum {
GUPNP_XML_ERROR_PARSE,
@@ -111,13 +107,13 @@ gupnp_rootdevice_error_quark (void) G_GNUC_CONST;
#define GUPNP_ROOT_DEVICE_ERROR (gupnp_rootdevice_error_quark ())
/**
- * GUPnPRootDeviceError:
+ * GUPnPRootdeviceError:
* @GUPNP_ROOT_DEVICE_ERROR_NO_CONTEXT: No #GUPnPContext was passed to the root device.
* @GUPNP_ROOT_DEVICE_ERROR_NO_DESCRIPTION_PATH: Device description path was missing
* @GUPNP_ROOT_DEVICE_ERROR_NO_DESCRIPTION_FOLDER: Description folder was missing
* @GUPNP_ROOT_DEVICE_ERROR_NO_NETWORK: Network interface is not usable
*
- * #GError codes used for errors during #GUPnPRootDevice creation
+ * Errors during [class@GUPnP.RootDevice] creation
*/
typedef enum {
GUPNP_ROOT_DEVICE_ERROR_NO_CONTEXT,
@@ -135,7 +131,9 @@ gupnp_service_introspection_error_quark (void) G_GNUC_CONST;
/**
* GUPnPServiceIntrospectionError:
- * @GUPNP_SERVICE_INTROSPECTION_ERROR_OTHER@: Unknown error
+ * @GUPNP_SERVICE_INTROSPECTION_ERROR_OTHER: Unknown error
+ *
+ * Errors during service introspection
*/
typedef enum
{
@@ -151,7 +149,9 @@ gupnp_service_error_quark (void) G_GNUC_CONST;
/**
* GUPnPServiceError:
- * @GUPNP_SERVICE_ERROR_AUTOCONNECT@: [method@GUPnP.Service.signals_autoconnect] failed
+ * @GUPNP_SERVICE_ERROR_AUTOCONNECT: [method@GUPnP.Service.signals_autoconnect] failed
+ *
+ * Errors during service handling
*/
typedef enum
{
diff --git a/libgupnp/gupnp-linux-context-manager.c b/libgupnp/gupnp-linux-context-manager.c
index 04a464a..5d95a58 100644
--- a/libgupnp/gupnp-linux-context-manager.c
+++ b/libgupnp/gupnp-linux-context-manager.c
@@ -26,7 +26,7 @@
* accordingly.
*/
-#define G_LOG_DOMAIN "GUPnP-ContextManager-Linux"
+#define G_LOG_DOMAIN "gupnp-context-manager"
#include <config.h>
diff --git a/libgupnp/gupnp-resource-factory.c b/libgupnp/gupnp-resource-factory.c
index 9e441dc..b651f91 100644
--- a/libgupnp/gupnp-resource-factory.c
+++ b/libgupnp/gupnp-resource-factory.c
@@ -10,16 +10,19 @@
*/
/**
- * SECTION:gupnp-resource-factory
- * @short_description: Class for resource and resource proxy object creation.
+ * GUPnPResourceFactory:
*
- * #GUPnPResourceFactory objects are used by #GUPnPControlPoint,
- * #GUPnPDeviceProxy and #GUPnPDevice to create resource proxy and resource
- * objects. Register UPnP type - #GType pairs to have resource or resource proxy
+ * Associating custom Services, Devices, ServiceProxies and DeviceProxies with UPnP types.
+ *
+ * #GUPnPResourceFactory objects are used by [class@GUPnP.ControlPoint],
+ * [class@GUPnP.DeviceProxy] and [class@GUPnP.Device] to create resource proxy and resource
+ * objects.
+ *
+ * Register UPnP type - [alias@GLib.Type] pairs to have resource or resource proxy
* objects created with the specified #GType whenever an object for a resource
- * of the specified UPnP type is requested. The #GType<!-- -->s need
+ * of the specified UPnP type is requested. The #GType needs
* to be derived from the relevant resource or resource proxy type (e.g.
- * a device proxy type needs to be derived from #GUPnPDeviceProxy).
+ * a device proxy type needs to be derived from [class@GUPnP.DeviceProxy]).
*/
#include <config.h>
@@ -187,7 +190,6 @@ lookup_type_with_fallback (GHashTable *resource_types,
* @location: The location of the device description file
* @url_base: The URL base for this device, or %NULL if none
*
- *
* Create a #GUPnPDeviceProxy for the device with element @element, as
* read from the device description file specified by @location.
*
diff --git a/libgupnp/gupnp-root-device.c b/libgupnp/gupnp-root-device.c
index 73734a3..8430fa9 100644
--- a/libgupnp/gupnp-root-device.c
+++ b/libgupnp/gupnp-root-device.c
@@ -7,12 +7,7 @@
*
*/
-/**
- * SECTION:gupnp-root-device
- * @short_description: Class for root device implementations.
- *
- * #GUPnPRootDevice allows for implementing root devices.
- */
+
#include <config.h>
#include <string.h>
@@ -44,6 +39,13 @@ struct _GUPnPRootDevicePrivate {
};
typedef struct _GUPnPRootDevicePrivate GUPnPRootDevicePrivate;
+/**
+ * GUPnPRootDevice:
+ *
+ * Implementation of an UPnP root device.
+ *
+ * #GUPnPRootDevice allows for implementing root devices.
+ */
G_DEFINE_TYPE_EXTENDED (GUPnPRootDevice,
gupnp_root_device,
GUPNP_TYPE_DEVICE,
@@ -346,7 +348,7 @@ gupnp_root_device_initable_init (GInitable *initable,
g_set_error_literal (error,
GUPNP_XML_ERROR,
GUPNP_XML_ERROR_PARSE,
- "Coupld not parse description document");
+ "Could not parse description document");
goto DONE;
}
@@ -396,7 +398,7 @@ gupnp_root_device_initable_init (GInitable *initable,
priv->relative_location,
NULL);
- /* Host the description file and dir */
+ /* Host the description file and folder */
gupnp_context_host_path (context, desc_path, relative_location);
gupnp_context_host_path (context, priv->description_dir, "");
@@ -466,7 +468,7 @@ gupnp_root_device_class_init (GUPnPRootDeviceClass *klass)
object_class->finalize = gupnp_root_device_finalize;
/**
- * GUPnPRootDevice:description-path:
+ * GUPnPRootDevice:description-path:(attributes org.gtk.Property.get=gupnp_root_device_get_description_path)
*
* The path to device description document. This could either be an
* absolute path or path relative to GUPnPRootDevice:description-dir.
@@ -478,7 +480,7 @@ gupnp_root_device_class_init (GUPnPRootDeviceClass *klass)
PROP_DESCRIPTION_PATH,
g_param_spec_string ("description-path",
"Description Path",
- "The path to device descrition document",
+ "The path to device description document",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
@@ -487,9 +489,9 @@ gupnp_root_device_class_init (GUPnPRootDeviceClass *klass)
G_PARAM_STATIC_BLURB));
/**
- * GUPnPRootDevice:description-dir:
+ * GUPnPRootDevice:description-dir:(attributes org.gtk.Property.get=gupnp_root_device_get_description_dir)
*
- * The path to directory where description documents are provided.
+ * The path to a folder where description documents are provided.
**/
g_object_class_install_property
(object_class,
@@ -506,7 +508,7 @@ gupnp_root_device_class_init (GUPnPRootDeviceClass *klass)
G_PARAM_STATIC_BLURB));
/**
- * GUPnPRootDevice:available:
+ * GUPnPRootDevice:available:(attributes org.gtk.Property.get=gupnp_root_device_get_available org.gtk.Property.set=gupnp_root_device_set_available)
*
* TRUE if this device is available.
**/
@@ -527,8 +529,8 @@ gupnp_root_device_class_init (GUPnPRootDeviceClass *klass)
* gupnp_root_device_new:
* @context: The #GUPnPContext
* @description_path: Path to device description document. This could either
- * be an absolute path or path relative to @description_dir.
- * @description_dir: Path to directory where description documents are provided.
+ * be an absolute path or path relative to @description_folder.
+ * @description_folder: Path to directory where description documents are provided.
* @error: (inout)(optional)(nullable): The location for a #GError to report issue with
* creation on or %NULL.
*
@@ -540,7 +542,7 @@ gupnp_root_device_class_init (GUPnPRootDeviceClass *klass)
GUPnPRootDevice *
gupnp_root_device_new (GUPnPContext *context,
const char *description_path,
- const char *description_dir,
+ const char *description_folder,
GError **error)
{
GUPnPResourceFactory *factory;
@@ -551,7 +553,7 @@ gupnp_root_device_new (GUPnPContext *context,
factory,
NULL,
description_path,
- description_dir,
+ description_folder,
error);
}
@@ -562,7 +564,7 @@ gupnp_root_device_new (GUPnPContext *context,
* @description_doc: Device description document, or %NULL
* @description_path: Path to device description document. This could either
* be an absolute path or path relative to @description_dir.
- * @description_dir: Path to directory where description documents are provided.
+ * @description_folder: Path to folder where description documents are provided.
* @error: (inout)(optional)(nullable): The location for a #GError to report issue with
* creation on or %NULL.
*
@@ -577,7 +579,7 @@ gupnp_root_device_new_full (GUPnPContext *context,
GUPnPResourceFactory *factory,
GUPnPXMLDoc *description_doc,
const char *description_path,
- const char *description_dir,
+ const char *description_folder,
GError **error)
{
g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
@@ -597,16 +599,16 @@ gupnp_root_device_new_full (GUPnPContext *context,
"description-path",
description_path,
"description-dir",
- description_dir,
+ description_folder,
NULL);
}
/**
- * gupnp_root_device_set_available:
+ * gupnp_root_device_set_available:(attributes org.gtk.Method.get_property=available)
* @root_device: A #GUPnPRootDevice
* @available: %TRUE if @root_device should be available
*
- * Controls whether or not @root_device is available (announcing
+ * Sets the availability of @root_device on the network (announcing
* its presence).
**/
void
@@ -625,10 +627,10 @@ gupnp_root_device_set_available (GUPnPRootDevice *root_device,
}
/**
- * gupnp_root_device_get_available:
+ * gupnp_root_device_get_available:(attributes org.gtk.Method.get_property=available)
* @root_device: A #GUPnPRootDevice
*
- * Get whether or not @root_device is available (announcing its presence).
+ * Checks whether @root_device is available on the network (announcing its presence).
*
* Return value: %TRUE if @root_device is available, %FALSE otherwise.
**/
@@ -645,15 +647,15 @@ gupnp_root_device_get_available (GUPnPRootDevice *root_device)
}
/**
- * gupnp_root_device_get_relative_location:
+ * gupnp_root_device_get_description_document_name:
* @root_device: A #GUPnPRootDevice
*
- * Get the relative location of @root_device.
+ * Gets the name of the description document as hosted via HTTP.
*
* Return value: The relative location of @root_device.
**/
const char *
-gupnp_root_device_get_relative_location (GUPnPRootDevice *root_device)
+gupnp_root_device_get_description_document_name (GUPnPRootDevice *root_device)
{
GUPnPRootDevicePrivate *priv;
@@ -665,10 +667,10 @@ gupnp_root_device_get_relative_location (GUPnPRootDevice *root_device)
}
/**
- * gupnp_root_device_get_description_path:
+ * gupnp_root_device_get_description_path:(attributes org.gtk.Method.get_property=description-path)
* @root_device: A #GUPnPRootDevice
*
- * Get the path to the device description document of @root_device.
+ * Gets the path to the device description document of @root_device.
*
* Return value: The path to device description document of @root_device.
**/
@@ -685,10 +687,10 @@ gupnp_root_device_get_description_path (GUPnPRootDevice *root_device)
}
/**
- * gupnp_root_device_get_description_dir:
+ * gupnp_root_device_get_description_dir:(attributes org.gtk.Method.get_property=description-dir)
* @root_device: A #GUPnPRootDevice
*
- * Get the path to the directory containing description documents related to
+ * Gets the path to the directory containing description documents related to
* @root_device.
*
* Return value: The path to description document directory of @root_device.
@@ -709,7 +711,7 @@ gupnp_root_device_get_description_dir (GUPnPRootDevice *root_device)
* gupnp_root_device_get_ssdp_resource_group:
* @root_device: A #GUPnPRootDevice
*
- * Get the #GSSDPResourceGroup used by @root_device.
+ * Gets the #GSSDPResourceGroup used by @root_device.
*
* Returns: (transfer none): The #GSSDPResourceGroup of @root_device.
*
diff --git a/libgupnp/gupnp-root-device.h b/libgupnp/gupnp-root-device.h
index ef53683..6e3dcd1 100644
--- a/libgupnp/gupnp-root-device.h
+++ b/libgupnp/gupnp-root-device.h
@@ -43,7 +43,7 @@ struct _GUPnPRootDeviceClass {
GUPnPRootDevice *
gupnp_root_device_new (GUPnPContext *context,
const char *description_path,
- const char *description_dir,
+ const char *description_folder,
GError **error);
GUPnPRootDevice *
@@ -51,7 +51,7 @@ gupnp_root_device_new_full (GUPnPContext *context,
GUPnPResourceFactory *factory,
GUPnPXMLDoc *description_doc,
const char *description_path,
- const char *description_dir,
+ const char *description_folder,
GError **error);
void
@@ -62,7 +62,7 @@ gboolean
gupnp_root_device_get_available (GUPnPRootDevice *root_device);
const char *
-gupnp_root_device_get_relative_location
+gupnp_root_device_get_description_document_name
(GUPnPRootDevice *root_device);
const char *
diff --git a/libgupnp/gupnp-service-action.c b/libgupnp/gupnp-service-action.c
index 4bcd032..cd5f52a 100644
--- a/libgupnp/gupnp-service-action.c
+++ b/libgupnp/gupnp-service-action.c
@@ -476,7 +476,7 @@ gupnp_service_action_set_value (GUPnPServiceAction *action,
* gupnp_service_action_return_success:
* @action: A #GUPnPServiceAction
*
- * Return succesfully.
+ * Return successfully.
*
* Since: 1.4.2
**/
@@ -485,7 +485,7 @@ gupnp_service_action_return_success (GUPnPServiceAction *action)
{
g_return_if_fail (action != NULL);
- soup_server_message_set_status (action->msg, SOUP_STATUS_OK, "Ok");
+ soup_server_message_set_status (action->msg, SOUP_STATUS_OK, NULL);
finalize_action (action);
}
diff --git a/libgupnp/gupnp-service-info.c b/libgupnp/gupnp-service-info.c
index 97ad4cc..39a0324 100644
--- a/libgupnp/gupnp-service-info.c
+++ b/libgupnp/gupnp-service-info.c
@@ -8,15 +8,8 @@
*
*/
-/**
- * SECTION:gupnp-service-info
- * @short_description: Base abstract class for querying service information.
- *
- * The #GUPnPDeviceInfo base abstract class provides methods for querying
- * service information.
- */
-#define G_LOG_DOMAIN "GUPnPServiceInfo"
+#define G_LOG_DOMAIN "gupnp-service-info"
#include <config.h>
#include <libsoup/soup.h>
@@ -50,6 +43,14 @@ struct _GUPnPServiceInfoPrivate {
typedef struct _GUPnPServiceInfoPrivate GUPnPServiceInfoPrivate;
+
+/**
+ * GUPnPServiceInfo:
+ *
+ * Service information shared by local and remote services.
+ *
+ * A class that contains the common parts between local and remote services.
+ */
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GUPnPServiceInfo,
gupnp_service_info,
G_TYPE_OBJECT)
@@ -205,8 +206,7 @@ gupnp_service_info_dispose (GObject *object)
}
/* Unref context */
- g_object_unref (priv->context);
- priv->context = NULL;
+ g_clear_object (&priv->context);
}
g_clear_object (&priv->doc);
@@ -707,7 +707,7 @@ gupnp_service_info_get_introspection_async
* gupnp_service_info_get_introspection_async_full:
* @info: A #GUPnPServiceInfo
* @callback: (scope async) : callback to be called when introspection object is ready.
- * @cancellable: GCancellable that can be used to cancel the call, or %NULL.
+ * @cancellable: (nullable): GCancellable that can be used to cancel the call.
* @user_data: user_data to be passed to the callback.
*
* Note that introspection object is created from the information in service
@@ -777,8 +777,6 @@ gupnp_service_info_get_introspection_async_full
g_main_context_get_thread_default ());
return;
-
- return;
}
@@ -827,8 +825,8 @@ prv_introspection_cb (GUPnPServiceInfo *info,
/**
* gupnp_service_info_introspect_async:
* @info: A #GUPnPServiceInfo
- * @cancellable: (nullable) : #GCancellable that can be used to cancel the call, or %NULL.
- * @callback: (scope async) : callback to be called when introspeciton object is ready.
+ * @cancellable: (nullable) : a #GCancellable that can be used to cancel the call.
+ * @callback: (scope async) : callback to be called when introspection object is ready.
* @user_data: user_data to be passed to the callback.
*
* Note that introspection object is created from the information in service
@@ -861,7 +859,7 @@ gupnp_service_info_introspect_async (GUPnPServiceInfo *info,
* gupnp_service_info_introspect_finish:
* @info: A GUPnPServiceInfo
* @res: A #GAsyncResult
- * @error: (inout)(optional)(nullable): Return location for a #GError, or %NULL
+ * @error: (inout)(optional): Return location for a #GError, or %NULL
*
* Finish an asynchronous call initiated with
* gupnp_service_info_introspect_async().
diff --git a/libgupnp/gupnp-service-info.h b/libgupnp/gupnp-service-info.h
index 2c561c0..0f346d1 100644
--- a/libgupnp/gupnp-service-info.h
+++ b/libgupnp/gupnp-service-info.h
@@ -16,8 +16,7 @@
G_BEGIN_DECLS
-#define GUPNP_TYPE_SERVICE_INFO \
- (gupnp_service_info_get_type ())
+#define GUPNP_TYPE_SERVICE_INFO (gupnp_service_info_get_type ())
G_DECLARE_DERIVABLE_TYPE (GUPnPServiceInfo,
gupnp_service_info,
@@ -38,8 +37,8 @@ struct _GUPnPServiceInfoClass {
/**
* GUPnPServiceIntrospectionCallback:
* @info: The #GUPnPServiceInfo introspection was requested for
- * @introspection: (nullable): The new #GUPnPServiceIntrospection object, or NULL
- * @error: (nullable): The #GError that occurred, or NULL
+ * @introspection: (nullable): The new #GUPnPServiceIntrospection object
+ * @error: (nullable): The #GError that occurred
* @user_data: User data
*
* Callback notifying that @introspection for @info has been obtained.
diff --git a/libgupnp/gupnp-service-introspection.c b/libgupnp/gupnp-service-introspection.c
index 68f09d7..a56d280 100644
--- a/libgupnp/gupnp-service-introspection.c
+++ b/libgupnp/gupnp-service-introspection.c
@@ -9,27 +9,6 @@
*
*/
-/**
- * SECTION:gupnp-service-introspection
- * @short_description: Service introspection class.
- *
- * The #GUPnPServiceIntrospection class provides methods for service
- * introspection based on information contained in its service description
- * document (SCPD). There is no constructor provided for this class, please use
- * #gupnp_service_info_get_introspection or
- * #gupnp_service_info_get_introspection_async to create an
- * #GUPnPServiceIntrospection object for a specific service.
- *
- * Note that all the introspection information is retreived from the service
- * description document (SCPD) provided by the service and hence can not be
- * guaranteed to be complete. A UPnP service is required to provide a SCPD but
- * unfortunately, many services either do not provide this document or the
- * document does not provide any or all of the introspection information.
- *
- * This class exposes internals of the UPnP protocol and should not need
- * to be used for regular device or control point development.
- *
- **/
#include <config.h>
#include <libsoup/soup.h>
@@ -67,6 +46,28 @@ static GInitableIface *initable_parent_iface = NULL;
static void
gupnp_service_introspection_initable_iface_init (gpointer g_iface, gpointer iface_data);
+
+/**
+ * GUPnPServiceIntrospection:
+ *
+ * Introspection of local and remote services..
+ *
+ * The #GUPnPServiceIntrospection class provides methods for service
+ * introspection based on information contained in its service description
+ * document (SCPD). There is no constructor provided for this class, please use
+ * [method@GUPnP.ServiceInfo.introspect_async] to create a
+ * #GUPnPServiceIntrospection object for a specific service.
+ *
+ * Note that all the introspection information is retrieved from the service
+ * description document (SCPD) provided by the service and hence can not be
+ * guaranteed to be complete. An UPnP service is required to provide a SCPD but
+ * unfortunately, many services either do not provide this document or the
+ * document does not provide any or all of the introspection information.
+ *
+ * This class exposes internals of the UPnP protocol and should not need
+ * to be used for regular device or control point development.
+ *
+ **/
G_DEFINE_TYPE_EXTENDED (
GUPnPServiceIntrospection,
gupnp_service_introspection,
diff --git a/libgupnp/gupnp-service-introspection.h b/libgupnp/gupnp-service-introspection.h
index fecfc8e..9036976 100644
--- a/libgupnp/gupnp-service-introspection.h
+++ b/libgupnp/gupnp-service-introspection.h
@@ -63,7 +63,7 @@ gupnp_service_action_arg_info_get_type (void);
/**
* GUPnPServiceActionInfo:
* @name: The name of the action argument.
- * @arguments: (type GList) (element-type GUPnP.ServiceActionArgInfo):A GList of all the arguments
+ * @arguments:(element-type GUPnP.ServiceActionArgInfo):A GList of all the arguments
* (of type #GUPnPServiceActionArgInfo) of this action.
*
* This structure contains information about a service action.
diff --git a/libgupnp/gupnp-service-proxy-action.c b/libgupnp/gupnp-service-proxy-action.c
index 15ba28c..aeb90cd 100644
--- a/libgupnp/gupnp-service-proxy-action.c
+++ b/libgupnp/gupnp-service-proxy-action.c
@@ -213,6 +213,16 @@ gupnp_service_proxy_action_new_internal (const char *action) {
return ret;
}
+
+/**
+ * gupnp_service_proxy_action_ref:
+ * @action: an action
+ *
+ * Increases reference count of `action`
+ *
+ * Returns: (nullable): @action with an increased reference count
+ * Since: 1.2.0
+ */
GUPnPServiceProxyAction *
gupnp_service_proxy_action_ref (GUPnPServiceProxyAction *action)
{
@@ -246,6 +256,15 @@ action_dispose (GUPnPServiceProxyAction *action)
g_free (action->name);
}
+/**
+ * gupnp_service_proxy_action_unref:
+ * @action: an action
+ *
+ * Decreases reference count of `action`. If reference count drops to 0,
+ * the action and its contents will be freed.
+ *
+ * Since: 1.2.0
+ */
void
gupnp_service_proxy_action_unref (GUPnPServiceProxyAction *action)
{
@@ -499,11 +518,11 @@ gupnp_service_proxy_action_serialize (GUPnPServiceProxyAction *action,
* @error:(inout)(optional)(nullable): The location where to store any error, or %NULL
*
* A variant of gupnp_service_proxy_action_get_result() that takes lists of
- * out-parameter names, types and place-holders for values. The returned list
- * in @out_values must be freed using #g_list_free and each element in it using
- * #g_value_unset and #g_free.
- * <informalexample>
- * <programlisting>
+ * out-parameter names, types and place-holders for values.
+ *
+ * The returned list in @out_values must be freed using `g_list_free` and each element
+ * in it using `g_value_unset` and `g_free`.
+ * ```c
* void on_action_finished(GObject *object, GAsyncResult *res, gpointer user_data)
* {
* GUPnPServiceProxyAction *action;
@@ -547,8 +566,7 @@ gupnp_service_proxy_action_serialize (GUPnPServiceProxyAction *action,
* }
* g_list_free (out_values);
* }
- * </programlisting>
- * </informalexample>
+ *```
*
* Return value : %TRUE on success.
*
diff --git a/libgupnp/gupnp-service-proxy.c b/libgupnp/gupnp-service-proxy.c
index 3c65414..4fce193 100644
--- a/libgupnp/gupnp-service-proxy.c
+++ b/libgupnp/gupnp-service-proxy.c
@@ -7,15 +7,6 @@
*
*/
-/**
- * SECTION:gupnp-service-proxy
- * @short_description: Proxy class for remote services.
- *
- * #GUPnPServiceProxy sends commands to a remote UPnP service and handles
- * incoming event notifications. #GUPnPServiceProxy implements the
- * #GUPnPServiceInfo interface.
- */
-
#include <config.h>
#include <libsoup/soup.h>
#include <gobject/gvaluecollector.h>
@@ -53,6 +44,14 @@ struct _GUPnPServiceProxyPrivate {
};
typedef struct _GUPnPServiceProxyPrivate GUPnPServiceProxyPrivate;
+/**
+ * GUPnPServiceProxy:
+ *
+ * Proxy class for remote services.
+ *
+ * #GUPnPServiceProxy sends commands to a remote UPnP service and handles
+ * incoming event notifications.
+ */
G_DEFINE_TYPE_WITH_PRIVATE (GUPnPServiceProxy,
gupnp_service_proxy,
GUPNP_TYPE_SERVICE_INFO)
@@ -375,10 +374,12 @@ gupnp_service_proxy_class_init (GUPnPServiceProxyClass *klass)
* out parameter type, and out parameter value location, terminated with %NULL
*
* Sends action @action with parameters @Varargs to the service exposed by
- * @proxy synchronously. If an error occurred, @error will be set. In case of
- * an UPnPError the error code will be the same in @error.
+ * @proxy synchronously.
*
- * Return value: %TRUE if sending the action was succesful.
+ * If an error occurred, @error will be set. In case of
+ * an UPnP error the error code will be the same in @error.
+ *
+ * Return value: %TRUE if sending the action was successful.
*
* Deprecated: 1.2.0: Use gupnp_service_proxy_action_new() and
* gupnp_service_proxy_call_action()
@@ -415,7 +416,7 @@ gupnp_service_proxy_send_action (GUPnPServiceProxy *proxy,
*
* See gupnp_service_proxy_send_action().
*
- * Return value: %TRUE if sending the action was succesful.
+ * Return value: %TRUE if sending the action was successful.
*
* Deprecated: 1.2.0
**/
@@ -486,10 +487,10 @@ out:
* (as #GValue) that line up with @out_names and @out_types.
* @error: (inout)(optional)(nullable): The location where to store any error, or %NULL
*
- * The synchronous variant of #gupnp_service_proxy_begin_action_list and
- * #gupnp_service_proxy_end_action_list.
+ * The synchronous variant of [class@GUPnP.ServiceProxy.begin_action_list] and
+ * [class@GUPnP.ServiceProxy.end_action_list].
*
- * Return value: %TRUE if sending the action was succesful.
+ * Return value: %TRUE if sending the action was successful.
*
* Deprecated: 1.2.0: Use gupnp_service_proxy_action_new_from_list() and gupnp_service_proxy_call_action()
*
@@ -994,7 +995,9 @@ gupnp_service_proxy_end_action_valist (GUPnPServiceProxy *proxy,
* (as #GValue) that line up with @out_names and @out_types.
*
* A variant of #gupnp_service_proxy_end_action that takes lists of
- * out-parameter names, types and place-holders for values. The returned list
+ * out-parameter names, types and place-holders for values.
+ *
+ * The returned list
* in @out_values must be freed using #g_list_free and each element in it using
* #g_value_unset and #g_slice_free.
*
@@ -1212,8 +1215,9 @@ gupnp_service_proxy_add_notify_full (GUPnPServiceProxy *proxy,
* @user_data: User data for @callback
* @notify: (allow-none): A #GDestroyNotify for @user_data
*
- * Get a notification for anything that happens on the peer. @value in
- * @callback will be of type #G_TYPE_POINTER and contain the pre-parsed
+ * Get a notification for anything that happens on the peer.
+ *
+ * @value in @callback will be of type #G_TYPE_POINTER and contain the pre-parsed
* #xmlDoc. Do NOT free or modify this document.
*
* Return value: %TRUE on success.
diff --git a/libgupnp/gupnp-service-proxy.h b/libgupnp/gupnp-service-proxy.h
index 107416a..7c4b8e9 100644
--- a/libgupnp/gupnp-service-proxy.h
+++ b/libgupnp/gupnp-service-proxy.h
@@ -30,14 +30,21 @@ struct _GUPnPServiceProxyClass {
GUPnPServiceInfoClass parent_class;
/* signals */
+ /**
+ * subscription_lost:
+ *
+ * Test
+ */
void (* subscription_lost) (GUPnPServiceProxy *proxy,
const GError *reason);
+#ifndef GOBJECT_INTROSPECTION_SKIP
/* future padding */
void (* _gupnp_reserved1) (void);
void (* _gupnp_reserved2) (void);
void (* _gupnp_reserved3) (void);
void (* _gupnp_reserved4) (void);
+#endif
};
/**
@@ -55,6 +62,7 @@ typedef struct _GUPnPServiceProxyAction GUPnPServiceProxyAction;
*
* Callback notifying that @action on @proxy has returned and
* gupnp_service_proxy_end_action() etc can be called.
+ * Deprecated: 1.2.0
**/
typedef void (* GUPnPServiceProxyActionCallback) (
GUPnPServiceProxy *proxy,
diff --git a/libgupnp/gupnp-service.c b/libgupnp/gupnp-service.c
index a20f2e1..d75a655 100644
--- a/libgupnp/gupnp-service.c
+++ b/libgupnp/gupnp-service.c
@@ -7,13 +7,6 @@
*
*/
-/**
- * SECTION:gupnp-service
- * @short_description: Class for service implementations.
- *
- * #GUPnPService allows for handling incoming actions and state variable
- * notification. #GUPnPService implements the #GUPnPServiceInfo interface.
- */
#include <config.h>
@@ -59,6 +52,21 @@ struct _GUPnPServicePrivate {
};
typedef struct _GUPnPServicePrivate GUPnPServicePrivate;
+
+/**
+ * GUPnPService:
+ *
+ * Implementation of an UPnP service
+ *
+ * #GUPnPService allows for handling incoming actions and state variable
+ * notification. It implements the [class@GUPnP.ServiceInfo] interface.
+ *
+ * To implement a service, you can either connect to the [signal@GUPnP.Service::action-invoked]
+ * and [signal@GUPnP.Service::query-variable] or derive from the `GUPnPService` class and override
+ * the virtual functions [vfunc@GUPnP.Service.action_invoked] and [vfunc@GUPnP.Service.query_variable].
+ *
+ * For more details, see the ["Implementing UPnP devices"](server-tutorial.html#implementing-a-service) document
+ */
G_DEFINE_TYPE_WITH_PRIVATE (GUPnPService,
gupnp_service,
GUPNP_TYPE_SERVICE_INFO)
@@ -1236,12 +1244,12 @@ gupnp_service_class_init (GUPnPServiceClass *klass)
/**
* GUPnPService::action-invoked:
- * @service: The #GUPnPService that received the signal
- * @action: The invoked #GUPnPServiceAction
+ * @service: the #GUPnPService that received the signal
+ * @action: the invoked #GUPnPServiceAction
*
* Emitted whenever an action is invoked. Handler should process
- * @action and must call either gupnp_service_action_return() or
- * gupnp_service_action_return_error().
+ * @action and must call either [method@GUPnP.ServiceAction.return_success] or
+ * [method@GUPnP.ServiceAction.return_error].
**/
signals[ACTION_INVOKED] =
g_signal_new ("action-invoked",
@@ -1258,9 +1266,9 @@ gupnp_service_class_init (GUPnPServiceClass *klass)
/**
* GUPnPService::query-variable:
- * @service: The #GUPnPService that received the signal
- * @variable: The variable that is being queried
- * @value: (type GValue)(inout):The location of the #GValue of the variable
+ * @service: the #GUPnPService that received the signal
+ * @variable: the variable that is being queried
+ * @value: (type GValue)(inout):the location of the #GValue of the variable
*
* Emitted whenever @service needs to know the value of @variable.
* Handler should fill @value with the value of @variable.
@@ -1282,9 +1290,9 @@ gupnp_service_class_init (GUPnPServiceClass *klass)
/**
* GUPnPService::notify-failed:
- * @service: The #GUPnPService that received the signal
- * @callback_url: (type GList)(element-type GUri):A #GList of callback URLs
- * @reason: (type GError): A pointer to a #GError describing why the notify failed
+ * @service: the #GUPnPService that received the signal
+ * @callback_url: (type GList)(element-type GUri):a #GList of callback URLs
+ * @reason: (type GError): a pointer to a #GError describing why the notify failed
*
* Emitted whenever notification of a client fails.
**/
@@ -1306,11 +1314,18 @@ gupnp_service_class_init (GUPnPServiceClass *klass)
/**
* gupnp_service_notify:
* @service: A #GUPnPService
- * @...: Tuples of variable name, variable type, and variable value,
+ * @...: a list of tuples, consisting of the variable name, variable type and variable value,
* terminated with %NULL.
*
- * Notifies listening clients that the properties listed in @Varargs
- * have changed to the specified values.
+ * Notifies remote clients that the properties have changed to the specified values.
+ *
+ * ```c
+ * gupnp_service_notify (service,
+ * "Volume", G_TYPE_FLOAT, 0.5,
+ * "PlaybackSpeed", G_TYPE_INT, -1,
+ * NULL);
+ *
+ * ```
**/
void
gupnp_service_notify (GUPnPService *service,
@@ -1548,11 +1563,11 @@ flush_notifications (GUPnPService *service)
/**
* gupnp_service_notify_value:
- * @service: A #GUPnPService
- * @variable: The name of the variable to notify
- * @value: The value of the variable
+ * @service: a #GUPnPService
+ * @variable: the name of the variable to notify
+ * @value: the value of the variable
*
- * Notifies listening clients that @variable has changed to @value.
+ * Notifies remote clients that @variable has changed to @value.
**/
void
gupnp_service_notify_value (GUPnPService *service,
@@ -1585,10 +1600,11 @@ gupnp_service_notify_value (GUPnPService *service,
/**
* gupnp_service_freeze_notify:
- * @service: A #GUPnPService
+ * @service: a #GUPnPService
*
- * Causes new notifications to be queued up until gupnp_service_thaw_notify()
- * is called.
+ * Stops sending out notifications to remote clients.
+ *
+ * It causes new notifications to be queued up until [method@GUPnP.Service.thaw_notify] is called.
**/
void
gupnp_service_freeze_notify (GUPnPService *service)
@@ -1604,7 +1620,7 @@ gupnp_service_freeze_notify (GUPnPService *service)
/**
* gupnp_service_thaw_notify:
- * @service: A #GUPnPService
+ * @service: a #GUPnPService
*
* Sends out any pending notifications, and stops queuing of new ones.
**/
@@ -1637,7 +1653,7 @@ strip_camel_case (char *camel_str)
for (i = 0, j = 0; i <= strlen (camel_str); i++) {
/* Convert every upper case letter to lower case and unless
- * it's the first character, the last charachter, in the
+ * it's the first character, the last character, in the
* middle of an abbreviation or there is already an underscore
* before it, add an underscore before it */
if (g_ascii_isupper (camel_str[i])) {
@@ -1745,35 +1761,39 @@ connect_names_to_signal_handlers (GUPnPService *service,
}
/**
- * gupnp_service_signals_autoconnect:
- * @service: A #GUPnPService
+ * gupnp_service_signals_autoconnect:(skip):
+ * @service: a #GUPnPService
* @user_data: the data to pass to each of the callbacks
- * @error: (inout)(optional)(nullable): return location for a #GError, or %NULL
+ * @error: (inout)(optional)(nullable): the return location for a #GError
+ *
+ * Connects call-back functions to the corresponding signals for variables and actions.
+ *
+ * It attempts to connect all possible [signal@GUPnP.Service::action-invoked] and
+ * [signal@GUPnP.Service::query-variable] signals to appropriate callbacks for
+ * the service.
*
- * A convenience function that attempts to connect all possible
- * #GUPnPService::action-invoked and #GUPnPService::query-variable signals to
- * appropriate callbacks for the service @service. It uses service introspection
- * and #GModule<!-- -->'s introspective features. It is very simillar to
- * gtk_builder_connect_signals() except that it attempts to guess the names of
- * the signal handlers on its own.
+ * It is very similar to [method@Gtk.Builder.connect_signals] except that it attempts
+ * to guess the names of the signal handlers on its own.
*
* For this function to do its magic, the application must name the callback
- * functions for #GUPnPService::action-invoked signals by striping the CamelCase
- * off the action names and either prepend "on_" or append "_cb" to them. Same
- * goes for #GUPnPService::query-variable signals, except that "query_" should
- * be prepended to the variable name. For example, callback function for
- * <varname>GetSystemUpdateID</varname> action should be either named as
- * "get_system_update_id_cb" or "on_get_system_update_id" and callback function
- * for the query of "SystemUpdateID" state variable should be named
- * <function>query_system_update_id_cb</function> or
- * <function>on_query_system_update_id</function>.
+ * functions for [signal@GUPnP.Service::action-invoked] signals by striping the CamelCase
+ * off the action names and either prefix them with `on_` or append `_cb` to them.
*
- * <note>This function will not work correctly if #GModule is not supported
- * on the platform or introspection is not available for @service.</note>
+ * Similar, for [signal@GUPnP.Service::query-variable] signals, except that the functions
+ * shoul be prefixed with `query_` to the variable name.
*
- * <warning>This function can not and therefore does not guarantee that the
+ * For example, the callback function for the `GetSystemUpdateID` action should be
+ * either named as
+ * `get_system_update_id_cb` or `on_get_system_update_id` and the callback function
+ * for the query of the `SystemUpdateID` state variable should be named
+ * `query_system_update_id_cb` or `on_query_system_update_id`.
+ *
+ * Note: This function will not work correctly if #GModule is not supported
+ * on the platform or introspection is not available for @service.
+ *
+ * Warning: This function can not and therefore does not guarantee that the
* resulting signal connections will be correct as it depends heavily on a
- * particular naming schemes described above.</warning>
+ * particular naming schemes described above.
**/
void
gupnp_service_signals_autoconnect (GUPnPService *service,
@@ -1832,3 +1852,63 @@ gupnp_service_signals_autoconnect (GUPnPService *service,
g_module_close (module);
}
+
+/**
+ * gupnp_service_action_invoked:
+ * @service: a `GUPnPService`
+ * @action: a `GUPnPServiceAction`
+ *
+ * Default handler for [signal@GUPnP.Service::action_invoked]. See its documentation for details.
+ *
+ * Can be overridden by child classes instead of connecting to the signal.
+ */
+void
+gupnp_service_action_invoked (GUPnPService *service, GUPnPServiceAction *action)
+{
+ g_return_if_fail (GUPNP_IS_SERVICE (service));
+
+ if (GUPNP_SERVICE_GET_CLASS (service)->action_invoked != NULL)
+ GUPNP_SERVICE_GET_CLASS (service)->action_invoked (service, action);
+}
+
+/**
+ * gupnp_service_query_variable:
+ * @service: a `GUPnPService`
+ * @variable: the name of the variable that was queried
+ * @value: a value that should be filled to the current value of @variable
+ *
+ * Default handler for [signal@GUPnP.Service::query_variable]. See its documentation for details.
+ *
+ * Can be overridden by child classes instead of connecting to the signal.
+ */
+void
+gupnp_service_query_variable (GUPnPService *service,
+ const char *variable,
+ GValue *value)
+{
+ g_return_if_fail (GUPNP_IS_SERVICE (service));
+
+ if (GUPNP_SERVICE_GET_CLASS (service)->query_variable != NULL)
+ GUPNP_SERVICE_GET_CLASS (service)->query_variable (service, variable, value);
+}
+
+/**
+ * gupnp_service_notify_failed:
+ * @service: a `GUPnPService`
+ * @callback_urls:(element-type GUri): a list of call-back urls that failed the notification
+ * @reason: An error that describes why the notification failed
+ *
+ * Default handler for [signal@GUPnP.Service::notify_failed]. See its documentation for details.
+ *
+ * Can be overridden by child classes instead of connecting to the signal.
+ */
+void
+gupnp_service_notify_failed (GUPnPService *service,
+ const GList *callback_urls,
+ const GError *reason)
+{
+ g_return_if_fail (GUPNP_IS_SERVICE (service));
+
+ if (GUPNP_SERVICE_GET_CLASS (service)->notify_failed != NULL)
+ GUPNP_SERVICE_GET_CLASS (service)->notify_failed (service, callback_urls, reason);
+}
diff --git a/libgupnp/gupnp-service.h b/libgupnp/gupnp-service.h
index e0db942..fc9d3a8 100644
--- a/libgupnp/gupnp-service.h
+++ b/libgupnp/gupnp-service.h
@@ -133,6 +133,20 @@ gupnp_service_signals_autoconnect (GUPnPService *service,
gpointer user_data,
GError **error);
+void
+gupnp_service_action_invoked (GUPnPService *service,
+ GUPnPServiceAction *action);
+
+void
+gupnp_service_query_variable (GUPnPService *service,
+ const char *variable,
+ GValue *value);
+
+void
+gupnp_service_notify_failed (GUPnPService *service,
+ const GList *callback_urls,
+ const GError *reason);
+
G_END_DECLS
#endif /* GUPNP_SERVICE_H */
diff --git a/libgupnp/gupnp-types.h b/libgupnp/gupnp-types.h
index 78f2fab..ea36c30 100644
--- a/libgupnp/gupnp-types.h
+++ b/libgupnp/gupnp-types.h
@@ -105,9 +105,21 @@ gupnp_uri_get_type (void) G_GNUC_CONST; /* string */
GType
gupnp_uuid_get_type (void) G_GNUC_CONST; /* string */
+/**
+ * gupnp_value_get_xml_node:
+ * @value: a [GLib.Value]
+ *
+ * Helper macro to get the xmlNode* from a `GValue`
+ */
#define gupnp_value_get_xml_node( value ) \
(xmlNode *) g_value_get_boxed ((value))
+/**
+ * gupnp_value_get_string:
+ * @value: a [GLib.Value]
+ *
+ * Helper macro to get a char* from a `GValue`
+ */
#define gupnp_value_get_string( value ) \
(const char *) g_value_get_boxed ((value))
diff --git a/meson.build b/meson.build
index 8dcda0c..5f7eebd 100644
--- a/meson.build
+++ b/meson.build
@@ -44,6 +44,12 @@ dependencies = [
subdir('libgupnp')
subdir('tests')
subdir('tools')
+
+gidocgen_dep = dependency('gi-docgen', version: '>= 2021.1',
+ fallback: ['gi-docgen', 'dummy_dep'],
+ required: get_option('gtk_doc') and get_option('introspection')
+ )
+
subdir('doc')
if get_option('vapi') and get_option('introspection')
diff --git a/subprojects/gi-docgen.wrap b/subprojects/gi-docgen.wrap
new file mode 100644
index 0000000..fb001c2
--- /dev/null
+++ b/subprojects/gi-docgen.wrap
@@ -0,0 +1,7 @@
+[wrap-git]
+directory=gi-docgen
+url=https://gitlab.gnome.org/GNOME/gi-docgen.git
+push-url=ssh://git@gitlab.gnome.org:GNOME/gi-docgen.git
+revision=main
+depth=1
+