GDBus: Add ObjectManager example
authorDavid Zeuthen <davidz@redhat.com>
Mon, 11 Apr 2011 20:35:14 +0000 (16:35 -0400)
committerDavid Zeuthen <davidz@redhat.com>
Mon, 11 Apr 2011 20:35:14 +0000 (16:35 -0400)
Signed-off-by: David Zeuthen <davidz@redhat.com>
gio/tests/Makefile.am
gio/tests/gdbus-example-objectmanager-client.c [new file with mode: 0644]
gio/tests/gdbus-example-objectmanager-server.c [new file with mode: 0644]
gio/tests/gdbus-example-objectmanager.xml [new file with mode: 0644]

index 16c35bc..0d2928e 100644 (file)
@@ -1,4 +1,5 @@
 NULL =
+BUILT_SOURCES =
 
 include $(top_srcdir)/Makefile.decl
 
@@ -93,6 +94,8 @@ SAMPLE_PROGS =                                \
        gapplication-example-cmdline2   \
        gapplication-example-cmdline3   \
        gapplication-example-actions    \
+       gdbus-example-objectmanager-server \
+       gdbus-example-objectmanager-client \
        $(NULL)
 
 
@@ -254,6 +257,8 @@ gdbus-test-codegen-generated.h gdbus-test-codegen-generated.c : test-codegen.xml
                test-codegen.xml                                                                        \
                $(NULL)
 
+BUILT_SOURCES += gdbus-test-codegen-generated.c gdbus-test-codegen-generated.h
+
 gdbus_test_codegen_SOURCES  = gdbus-test-codegen.c gdbus-sessionbus.c gdbus-sessionbus.h gdbus-tests.h gdbus-tests.c
 gdbus_test_codegen_SOURCES += gdbus-test-codegen-generated.c gdbus-test-codegen-generated.h
 gdbus_test_codegen_LDADD = $(progs_ldadd)
@@ -434,6 +439,29 @@ proxy_SOURCES = proxy.c
 proxy_LDADD   = $(progs_ldadd) \
        $(top_builddir)/gthread/libgthread-2.0.la
 
+# ----------------------------------------------------------------------------------------------------
+
+gdbus-example-objectmanager-generated.h gdbus-example-objectmanager-generated.c : gdbus-example-objectmanager.xml
+       $(PYTHON) $(top_srcdir)/gio/gdbus-codegen/codegen_main.py               \
+               --c-namespace Example                                           \
+               --interface-prefix org.gtk.GDBus.Example.ObjectManager.         \
+               --generate-c-code gdbus-example-objectmanager-generated         \
+               --generate-docbook gdbus-example-objectmanager-generated        \
+               gdbus-example-objectmanager.xml                                 \
+               $(NULL)
+
+BUILT_SOURCES += gdbus-example-objectmanager-generated.h gdbus-example-objectmanager-generated.c
+
+gdbus_example_objectmanager_server_SOURCES  = gdbus-example-objectmanager-server.c
+gdbus_example_objectmanager_server_SOURCES += gdbus-example-objectmanager-generated.h gdbus-example-objectmanager-generated.c
+gdbus_example_objectmanager_server_LDADD= $(progs_ldadd)
+
+gdbus_example_objectmanager_client_SOURCES  = gdbus-example-objectmanager-client.c
+gdbus_example_objectmanager_client_SOURCES += gdbus-example-objectmanager-generated.h gdbus-example-objectmanager-generated.c
+gdbus_example_objectmanager_client_LDADD= $(progs_ldadd)
+
+# ----------------------------------------------------------------------------------------------------
+
 EXTRA_DIST += \
        socket-common.c                 \
        org.gtk.test.gschema            \
@@ -448,6 +476,7 @@ EXTRA_DIST += \
        appinfo-test-notgnome.desktop   \
        gdbus-testserver.py             \
        test-codegen.xml                \
+       gdbus-example-objectmanager.xml \
        $(NULL)
 
 MISC_STUFF = test.mo
diff --git a/gio/tests/gdbus-example-objectmanager-client.c b/gio/tests/gdbus-example-objectmanager-client.c
new file mode 100644 (file)
index 0000000..cdef0ae
--- /dev/null
@@ -0,0 +1,135 @@
+
+#include "gdbus-example-objectmanager-generated.h"
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_object_added (GDBusObjectManager *manager,
+                 GDBusObject        *object,
+                 gpointer            user_data)
+{
+  gchar *owner;
+  owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (manager));
+  g_debug ("added object at %s (owner %s)", g_dbus_object_get_object_path (object), owner);
+  g_free (owner);
+}
+
+static void
+on_object_removed (GDBusObjectManager *manager,
+                   GDBusObject        *object,
+                   gpointer            user_data)
+{
+  gchar *owner;
+  owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (manager));
+  g_debug ("removed object at %s (owner %s)", g_dbus_object_get_object_path (object), owner);
+  g_free (owner);
+}
+
+static void
+on_notify_name_owner (GObject    *object,
+                      GParamSpec *pspec,
+                      gpointer    user_data)
+{
+  GDBusObjectManagerClient *manager = G_DBUS_OBJECT_MANAGER_CLIENT (object);
+  gchar *name_owner;
+
+  name_owner = g_dbus_object_manager_client_get_name_owner (manager);
+  g_debug ("name-owner: %s", name_owner);
+  g_free (name_owner);
+}
+
+static void
+on_interface_proxy_properties_changed (GDBusObjectManagerClient *manager,
+                                       GDBusObjectProxy         *object_proxy,
+                                       GDBusProxy               *interface_proxy,
+                                       GVariant                 *changed_properties,
+                                       const gchar *const       *invalidated_properties,
+                                       gpointer                  user_data)
+{
+  GVariantIter iter;
+  const gchar *key;
+  GVariant *value;
+  gchar *s;
+
+  g_print ("Properties Changed on %s:\n", g_dbus_object_get_object_path (G_DBUS_OBJECT (object_proxy)));
+  g_variant_iter_init (&iter, changed_properties);
+  while (g_variant_iter_next (&iter, "{&sv}", &key, &value))
+    {
+      s = g_variant_print (value, TRUE);
+      g_print ("  %s -> %s\n", key, s);
+      g_variant_unref (value);
+      g_free (s);
+    }
+}
+
+gint
+main (gint argc, gchar *argv[])
+{
+  GDBusObjectManager *manager;
+  GMainLoop *loop;
+  GError *error;
+  gchar *name_owner;
+  GList *objects;
+  GList *l;
+
+  manager = NULL;
+  loop = NULL;
+
+  g_type_init ();
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  error = NULL;
+  manager = example_object_manager_client_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                            G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
+                                                            "org.gtk.GDBus.Examples.ObjectManager",
+                                                            "/example/Animals",
+                                                            NULL, /* GCancellable */
+                                                            &error);
+  if (manager == NULL)
+    {
+      g_printerr ("Error getting object manager client: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  name_owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (manager));
+  g_debug ("name-owner: %s", name_owner);
+  g_free (name_owner);
+
+  objects = g_dbus_object_manager_get_objects (manager);
+  for (l = objects; l != NULL; l = l->next)
+    {
+      GDBusObject *object = G_DBUS_OBJECT (l->data);
+      g_debug ("proxy has object at %s", g_dbus_object_get_object_path (object));
+    }
+  g_list_foreach (objects, (GFunc) g_object_unref, NULL);
+  g_list_free (objects);
+
+  g_signal_connect (manager,
+                    "notify::name-owner",
+                    G_CALLBACK (on_notify_name_owner),
+                    NULL);
+  g_signal_connect (manager,
+                    "object-added",
+                    G_CALLBACK (on_object_added),
+                    NULL);
+  g_signal_connect (manager,
+                    "object-removed",
+                    G_CALLBACK (on_object_removed),
+                    NULL);
+  g_signal_connect (manager,
+                    "interface-proxy-properties-changed",
+                    G_CALLBACK (on_interface_proxy_properties_changed),
+                    NULL);
+
+  g_main_loop_run (loop);
+
+ out:
+  if (manager != NULL)
+    g_object_unref (manager);
+  if (loop != NULL)
+    g_main_loop_unref (loop);
+
+  return 0;
+}
diff --git a/gio/tests/gdbus-example-objectmanager-server.c b/gio/tests/gdbus-example-objectmanager-server.c
new file mode 100644 (file)
index 0000000..f66839f
--- /dev/null
@@ -0,0 +1,141 @@
+
+#include "gdbus-example-objectmanager-generated.h"
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static GDBusObjectManagerServer *manager = NULL;
+
+static gboolean
+on_animal_poke (ExampleAnimal          *animal,
+                GDBusMethodInvocation  *invocation,
+                gboolean                make_sad,
+                gboolean                make_happy,
+                gpointer                user_data)
+{
+
+  if ((make_sad && make_happy) || (!make_sad && !make_happy))
+    {
+      g_dbus_method_invocation_return_dbus_error (invocation,
+                                                  "org.gtk.GDBus.Examples.ObjectManager.Error.Failed",
+                                                  "Exactly one of make_sad or make_happy must be TRUE");
+      goto out;
+    }
+
+  if (make_sad)
+    {
+      if (g_strcmp0 (example_animal_get_mood (animal), "Sad") == 0)
+        {
+          g_dbus_method_invocation_return_dbus_error (invocation,
+                                                      "org.gtk.GDBus.Examples.ObjectManager.Error.SadAnimalIsSad",
+                                                      "Sad animal is already sad");
+          goto out;
+        }
+
+      example_animal_set_mood (animal, "Sad");
+      example_animal_complete_poke (animal, invocation);
+      goto out;
+    }
+
+  if (make_happy)
+    {
+      if (g_strcmp0 (example_animal_get_mood (animal), "Happy") == 0)
+        {
+          g_dbus_method_invocation_return_dbus_error (invocation,
+                                                      "org.gtk.GDBus.Examples.ObjectManager.Error.HappyAnimalIsHappy",
+                                                      "Happy animal is already happy");
+          goto out;
+        }
+
+      example_animal_set_mood (animal, "Happy");
+      example_animal_complete_poke (animal, invocation);
+      goto out;
+    }
+
+  g_assert_not_reached ();
+
+ out:
+  return TRUE; /* to indicate that the method was handled */
+}
+
+
+static void
+on_bus_acquired (GDBusConnection *connection,
+                 const gchar     *name,
+                 gpointer         user_data)
+{
+  GDBusObjectStub *object;
+  guint n;
+
+  g_debug ("bus acquired");
+
+  manager = g_dbus_object_manager_server_new (connection, "/example/Animals");
+  for (n = 0; n < 10; n++)
+    {
+      gchar *s;
+      ExampleAnimal *animal;
+
+      s = g_strdup_printf ("/example/Animals/%03d", n);
+      object = g_dbus_object_stub_new (s);
+      g_free (s);
+
+      animal = example_animal_stub_new ();
+      example_animal_set_mood (animal, "Happy");
+
+      /* Handle Poke() method invocations */
+      g_signal_connect (animal,
+                        "handle-poke",
+                        G_CALLBACK (on_animal_poke),
+                        NULL); /* user_data */
+
+      g_dbus_object_stub_add_interface (object, G_DBUS_INTERFACE_STUB (animal));
+      g_object_unref (animal);
+
+      g_dbus_object_manager_server_export (manager, object);
+      g_object_unref (object);
+    }
+}
+
+static void
+on_name_acquired (GDBusConnection *connection,
+                  const gchar     *name,
+                  gpointer         user_data)
+{
+  g_debug ("name acquired");
+}
+
+static void
+on_name_lost (GDBusConnection *connection,
+              const gchar     *name,
+              gpointer         user_data)
+{
+  g_debug ("name lost");
+}
+
+
+gint
+main (gint argc, gchar *argv[])
+{
+  GMainLoop *loop;
+  guint id;
+
+  g_type_init ();
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  id = g_bus_own_name (G_BUS_TYPE_SESSION,
+                       "org.gtk.GDBus.Examples.ObjectManager",
+                       G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
+                       G_BUS_NAME_OWNER_FLAGS_REPLACE,
+                       on_bus_acquired,
+                       on_name_acquired,
+                       on_name_lost,
+                       loop,
+                       NULL);
+
+  g_main_loop_run (loop);
+
+  g_bus_unown_name (id);
+  g_main_loop_unref (loop);
+
+  return 0;
+}
diff --git a/gio/tests/gdbus-example-objectmanager.xml b/gio/tests/gdbus-example-objectmanager.xml
new file mode 100644 (file)
index 0000000..7ee0263
--- /dev/null
@@ -0,0 +1,33 @@
+<node>
+
+  <!-- org.gtk.GDBus.Example.ObjectManager.Animal:
+       @short_description: Simple Animal
+
+       This interface is used to describe a simple animal.
+    -->
+  <interface name="org.gtk.GDBus.Example.ObjectManager.Animal">
+
+    <!-- Mood: The mood of the animal.
+
+         Known values for this property include
+         <literal>Happy</literal> and <literal>Sad</literal>. Use the
+         org.gtk.GDBus.Example.ObjectManager.Animal.Poke() method to
+         change this property -->
+    <property name="Mood" type="s" access="read"/>
+
+    <!--
+        Poke:
+        @make_sad: Whether to make the animal sad.
+        @make_angry: Whether to make the animal angry.
+
+        Method used to changing the mood of the animal. See also the
+        #org.gtk.GDBus.Example.ObjectManager.Animal:Mood property.
+      -->
+    <method name="Poke">
+      <arg direction="in" type="b" name="make_sad"/>
+      <arg direction="in" type="b" name="make_happy"/>
+    </method>
+
+  </interface>
+
+</node>