GtkApplication: Add a profiler dbus api
authorMatthias Clasen <mclasen@redhat.com>
Sat, 19 May 2018 19:36:00 +0000 (20:36 +0100)
committerMatthias Clasen <mclasen@redhat.com>
Tue, 7 May 2019 16:37:59 +0000 (09:37 -0700)
Implement the org.gnome.Sysprof2.Profiler D-Bus
api to let sysprof start and stop tracing at runtime,
and get the data directly, via a passed fd.

gtk/gtkapplication.c
gtk/gtkapplicationprivate.h

index 7adfc70f03265aedd5ebb35ef15f4b5b1f69b8b2..944d7fc8d93ace920881234739a31ce01289e5c1 100644 (file)
 #include "config.h"
 
 #include "gtkapplication.h"
+#include "gdkprofilerprivate.h"
+
+#ifdef G_OS_UNIX
+#include <gio/gunixfdlist.h>
+#endif
 
 #include <stdlib.h>
 
@@ -603,6 +608,148 @@ gtk_application_finalize (GObject *object)
   G_OBJECT_CLASS (gtk_application_parent_class)->finalize (object);
 }
 
+#ifdef G_OS_UNIX
+
+static const gchar org_gnome_Sysprof2_Profiler_xml[] =
+  "<node>"
+    "<interface name='org.gnome.Sysprof2.Profiler'>"
+      "<method name='Start'>"
+        "<arg type='h' name='fd' direction='in'/>"
+      "</method>"
+      "<method name='Stop'>"
+      "</method>"
+    "</interface>"
+  "</node>";
+
+static GDBusInterfaceInfo *org_gnome_Sysprof2_Profiler;
+
+static void
+sysprof_profiler_method_call (GDBusConnection       *connection,
+                              const gchar           *sender,
+                              const gchar           *object_path,
+                              const gchar           *interface_name,
+                              const gchar           *method_name,
+                              GVariant              *parameters,
+                              GDBusMethodInvocation *invocation,
+                              gpointer               user_data)
+{
+  if (strcmp (method_name, "Start") == 0)
+    {
+      GDBusMessage *message;
+      GUnixFDList *fd_list;
+      int fd = -1;
+      int idx;
+
+      if (gdk_profiler_is_running ())
+        {
+          g_dbus_method_invocation_return_error (invocation,
+                                                 G_DBUS_ERROR,
+                                                 G_DBUS_ERROR_FAILED,
+                                                 "Profiler already running");
+          return;
+        }
+
+      g_variant_get (parameters, "(h)", &idx);
+
+      message = g_dbus_method_invocation_get_message (invocation);
+      fd_list = g_dbus_message_get_unix_fd_list (message);
+      if (fd_list)
+        fd = g_unix_fd_list_get (fd_list, idx, NULL);
+
+      gdk_profiler_start (fd);
+    }
+  else if (strcmp (method_name, "Stop") == 0)
+    {
+      if (!gdk_profiler_is_running ())
+        {
+          g_dbus_method_invocation_return_error (invocation,
+                                                 G_DBUS_ERROR,
+                                                 G_DBUS_ERROR_FAILED,
+                                                 "Profiler not running");
+          return;
+        }
+
+      gdk_profiler_stop ();
+    }
+  else
+    {
+      g_dbus_method_invocation_return_error (invocation,
+                                             G_DBUS_ERROR,
+                                             G_DBUS_ERROR_UNKNOWN_METHOD,
+                                             "Unknown method");
+      return;
+    }
+
+  g_dbus_method_invocation_return_value (invocation, NULL);
+}
+
+static gboolean
+gtk_application_dbus_register (GApplication     *application,
+                               GDBusConnection  *connection,
+                               const char       *obect_path,
+                               GError          **error)
+{
+  GtkApplicationImplDBus *dbus = (GtkApplicationImplDBus *) application;
+  GDBusInterfaceVTable vtable = {
+    sysprof_profiler_method_call,
+    NULL,
+    NULL
+  };
+
+  if (org_gnome_Sysprof2_Profiler == NULL)
+    {
+      GDBusNodeInfo *info;
+
+      info = g_dbus_node_info_new_for_xml (org_gnome_Sysprof2_Profiler_xml, error);
+      if (info == NULL)
+        return FALSE;
+
+      org_gnome_Sysprof2_Profiler = g_dbus_node_info_lookup_interface (info, "org.gnome.Sysprof2.Profiler");
+      g_dbus_interface_info_ref (org_gnome_Sysprof2_Profiler);
+      g_dbus_node_info_unref (info);
+    }
+
+  dbus->profiler_id = g_dbus_connection_register_object (connection,
+                                                         "/org/gtk/Profiler",
+                                                         org_gnome_Sysprof2_Profiler,
+                                                         &vtable,
+                                                         NULL,
+                                                         NULL,
+                                                         error);
+
+  return TRUE;
+}
+
+static void
+gtk_application_dbus_unregister (GApplication     *application,
+                                 GDBusConnection  *connection,
+                                 const char       *obect_path)
+{
+  GtkApplicationImplDBus *dbus = (GtkApplicationImplDBus *) application;
+
+  g_dbus_connection_unregister_object (connection, dbus->profiler_id);
+}
+
+#else
+
+static gboolean
+gtk_application_dbus_register (GApplication     *application,
+                               GDBusConnection  *connection,
+                               const char       *obect_path,
+                               GError          **error)
+{
+  return TRUE;
+}
+
+static void
+gtk_application_dbus_unregister (GApplication     *application,
+                                 GDBusConnection  *connection,
+                                 const char       *obect_path)
+{
+}
+
+#endif
+
 static void
 gtk_application_class_init (GtkApplicationClass *class)
 {
@@ -619,6 +766,8 @@ gtk_application_class_init (GtkApplicationClass *class)
   application_class->after_emit = gtk_application_after_emit;
   application_class->startup = gtk_application_startup;
   application_class->shutdown = gtk_application_shutdown;
+  application_class->dbus_register = gtk_application_dbus_register;
+  application_class->dbus_unregister = gtk_application_dbus_unregister;
 
   class->window_added = gtk_application_window_added;
   class->window_removed = gtk_application_window_removed;
index 24ef7c4a4021874fff36a79e1e64506b7810bc2a..f167c7436298a061f398627bd335ddf04cdbe72f 100644 (file)
@@ -127,6 +127,7 @@ typedef struct
 
   gchar           *menubar_path;
   guint            menubar_id;
+  guint            profiler_id;
 
   /* Session management... */
   GDBusProxy      *sm_proxy;