[gupnp-tools] event-dumper: New tool



commit ccb98911b5f4cdc40bc97b32ce3bfa83e212d869
Author: Jens Georg <mail jensge org>
Date:   Sun Jun 19 20:54:44 2022 +0200

    event-dumper: New tool

 src/event-dumper/event-dumper.c | 181 ++++++++++++++++++++++++++++++++++++++++
 src/event-dumper/meson.build    |   1 +
 src/meson.build                 |   1 +
 3 files changed, 183 insertions(+)
---
diff --git a/src/event-dumper/event-dumper.c b/src/event-dumper/event-dumper.c
new file mode 100644
index 0000000..77f901b
--- /dev/null
+++ b/src/event-dumper/event-dumper.c
@@ -0,0 +1,181 @@
+#include <glib-unix.h>
+#include <glib.h>
+#include <libgupnp/gupnp.h>
+
+#include <iso646.h>
+
+void
+on_variable_notify (GUPnPServiceProxy *proxy,
+                    const char *variable,
+                    GValue *value,
+                    gpointer user_data)
+{
+        g_autoptr (GDateTime) dt = g_date_time_new_now_local ();
+        g_autofree char *timestr = g_date_time_format_iso8601 (dt);
+        g_auto (GValue) v = G_VALUE_INIT;
+        g_value_init (&v, G_TYPE_STRING);
+        g_value_transform (value, &v);
+
+        g_print ("%s|%s|%s|%s|%s\n",
+                 timestr,
+                 gupnp_service_info_get_udn (GUPNP_SERVICE_INFO (user_data)),
+                 gupnp_service_info_get_id (GUPNP_SERVICE_INFO (user_data)),
+                 variable,
+                 g_value_get_string (&v));
+}
+
+void
+on_introspection (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+        g_autoptr (GError) error = NULL;
+
+        g_autoptr (GUPnPServiceIntrospection) is =
+                gupnp_service_info_introspect_finish (
+                        GUPNP_SERVICE_INFO (source),
+                        res,
+                        &error);
+
+        g_autofree char *id =
+                gupnp_service_info_get_id (GUPNP_SERVICE_INFO (source));
+
+        if (error != NULL) {
+                g_warning ("Failed to introspect service proxy %s: %s",
+                           id,
+                           error->message);
+
+                return;
+        } else {
+                g_info ("Got introspection for %s", id);
+        }
+
+        const GList *state_variables =
+                gupnp_service_introspection_list_state_variables (is);
+        for (const GList *it = state_variables; it != NULL;
+             it = g_list_next (it)) {
+                GUPnPServiceStateVariableInfo *info = it->data;
+                if (not info->send_events)
+                        continue;
+
+                g_info ("Subscribing to %s (type: %s)",
+                        info->name,
+                        g_type_name (info->type));
+
+                gupnp_service_proxy_add_notify (GUPNP_SERVICE_PROXY (source),
+                                                info->name,
+                                                info->type,
+                                                on_variable_notify,
+                                                source);
+        }
+}
+
+void
+subscribe_to_proxy (GUPnPServiceProxy *sp, gpointer user_data)
+{
+        g_object_ref (sp);
+        g_autofree char *id =
+                gupnp_service_info_get_id (GUPNP_SERVICE_INFO (sp));
+
+        g_info ("Found new service proxy %s", id);
+        gupnp_service_info_introspect_async (GUPNP_SERVICE_INFO (sp),
+                                             NULL,
+                                             on_introspection,
+                                             NULL);
+        gupnp_service_proxy_set_subscribed (sp, TRUE);
+}
+
+void
+on_proxy_available (GUPnPControlPoint *cp,
+                    GUPnPDeviceProxy *dp,
+                    gpointer user_data)
+{
+        g_autofree char *id =
+                gupnp_device_info_get_friendly_name (GUPNP_DEVICE_INFO (dp));
+
+        g_info ("New device %s, type %s at %s",
+                id,
+                gupnp_device_info_get_device_type (GUPNP_DEVICE_INFO (dp)),
+                gupnp_device_info_get_location (GUPNP_DEVICE_INFO (dp)));
+
+        GList *services =
+                gupnp_device_info_list_services (GUPNP_DEVICE_INFO (dp));
+
+        g_list_foreach ((GList *) services, (GFunc) subscribe_to_proxy, NULL);
+
+        // Shallow-free the list, so we keep a reference to each service
+        g_list_free_full (services, (GDestroyNotify) g_object_unref);
+
+        g_object_ref (dp);
+}
+
+void
+on_proxy_unavailable (GUPnPControlPoint *cp,
+                      GUPnPDeviceProxy *dp,
+                      gpointer user_data)
+{
+        g_autofree char *id =
+                gupnp_device_info_get_friendly_name (GUPNP_DEVICE_INFO (dp));
+
+        g_info ("Lost service proxy %s", id);
+
+        // Dropping the reference we added in on_proxy_available
+        g_object_unref (dp);
+}
+
+void
+on_context_available (GUPnPContextManager *cm,
+                      GUPnPContext *ctx,
+                      gpointer user_data)
+{
+
+        g_info ("New context: %s",
+                gssdp_client_get_host_ip (GSSDP_CLIENT (ctx)));
+        g_autoptr (GUPnPControlPoint) cp =
+                gupnp_control_point_new (ctx, "upnp:rootdevice");
+
+        g_signal_connect (cp,
+                          "device-proxy-available",
+                          G_CALLBACK (on_proxy_available),
+                          NULL);
+
+        g_signal_connect (cp,
+                          "device-proxy-unavailable",
+                          G_CALLBACK (on_proxy_unavailable),
+                          NULL);
+
+        gssdp_resource_browser_set_active (GSSDP_RESOURCE_BROWSER (cp), TRUE);
+
+        gupnp_context_manager_manage_control_point (cm, cp);
+}
+
+void
+on_context_unavailable (GUPnPContextManager *cm,
+                        GUPnPContext *ctx,
+                        gpointer user_data)
+{
+        g_info ("Context gone: %s",
+                gssdp_client_get_host_ip (GSSDP_CLIENT (ctx)));
+}
+
+int
+main (int argc, char *argv[])
+{
+        g_autoptr (GUPnPContextManager) cm = gupnp_context_manager_create (0);
+        g_autoptr (GMainLoop) loop = g_main_loop_new (NULL, FALSE);
+
+        g_signal_connect (cm,
+                          "context-available",
+                          G_CALLBACK (on_context_available),
+                          NULL);
+
+        g_signal_connect (cm,
+                          "context-unavailable",
+                          G_CALLBACK (on_context_unavailable),
+                          NULL);
+
+        g_unix_signal_add (SIGINT, (GSourceFunc) g_main_loop_quit, loop);
+        g_unix_signal_add (SIGTERM, (GSourceFunc) g_main_loop_quit, loop);
+
+        g_main_loop_run (loop);
+
+        return 0;
+}
diff --git a/src/event-dumper/meson.build b/src/event-dumper/meson.build
new file mode 100644
index 0000000..af358a7
--- /dev/null
+++ b/src/event-dumper/meson.build
@@ -0,0 +1 @@
+executable('gupnp-event-dumper', ['event-dumper.c'], dependencies : [gupnp, gobject], install: true)
diff --git a/src/meson.build b/src/meson.build
index 6601f45..ddca4d5 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -8,3 +8,4 @@ endif
 subdir('discover')
 subdir('network-light')
 subdir('universal-cp')
+subdir('event-dumper')


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]