(root)/
glib-2.79.0/
gio/
tests/
gdbus-example-export.c
       1  #include <gio/gio.h>
       2  #include <stdlib.h>
       3  
       4  /* ---------------------------------------------------------------------------------------------------- */
       5  
       6  /* The object we want to export */
       7  typedef struct _MyObjectClass MyObjectClass;
       8  typedef struct _MyObject MyObject;
       9  
      10  struct _MyObjectClass
      11  {
      12    GObjectClass parent_class;
      13  };
      14  
      15  struct _MyObject
      16  {
      17    GObject parent_instance;
      18  
      19    gint count;
      20    gchar *name;
      21  };
      22  
      23  enum
      24  {
      25    PROP_0,
      26    PROP_COUNT,
      27    PROP_NAME
      28  };
      29  
      30  static GType my_object_get_type (void);
      31  G_DEFINE_TYPE (MyObject, my_object, G_TYPE_OBJECT)
      32  
      33  static void
      34  my_object_finalize (GObject *object)
      35  {
      36    MyObject *myobj = (MyObject*)object;
      37  
      38    g_free (myobj->name);
      39  
      40    G_OBJECT_CLASS (my_object_parent_class)->finalize (object);
      41  }
      42  
      43  static void
      44  my_object_init (MyObject *object)
      45  {
      46    object->count = 0;
      47    object->name = NULL;
      48  }
      49  
      50  static void
      51  my_object_get_property (GObject    *object,
      52                          guint       prop_id,
      53                          GValue     *value,
      54                          GParamSpec *pspec)
      55  {
      56    MyObject *myobj = (MyObject*)object;
      57  
      58    switch (prop_id)
      59      {
      60      case PROP_COUNT:
      61        g_value_set_int (value, myobj->count);
      62        break;
      63  
      64      case PROP_NAME:
      65        g_value_set_string (value, myobj->name);
      66        break;
      67  
      68      default:
      69        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      70      }
      71  }
      72  
      73  static void
      74  my_object_set_property (GObject      *object,
      75                          guint         prop_id,
      76                          const GValue *value,
      77                          GParamSpec   *pspec)
      78  {
      79    MyObject *myobj = (MyObject*)object;
      80  
      81    switch (prop_id)
      82      {
      83      case PROP_COUNT:
      84        myobj->count = g_value_get_int (value);
      85        break;
      86  
      87      case PROP_NAME:
      88        g_free (myobj->name);
      89        myobj->name = g_value_dup_string (value);
      90        break;
      91  
      92      default:
      93        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      94      }
      95  }
      96  
      97  static void
      98  my_object_class_init (MyObjectClass *class)
      99  {
     100    GObjectClass *gobject_class = G_OBJECT_CLASS (class);
     101  
     102    gobject_class->finalize = my_object_finalize;
     103    gobject_class->set_property = my_object_set_property;
     104    gobject_class->get_property = my_object_get_property;
     105  
     106    g_object_class_install_property (gobject_class,
     107                                     PROP_COUNT,
     108                                     g_param_spec_int ("count",
     109                                                       "Count",
     110                                                       "Count",
     111                                                       0, 99999, 0,
     112                                                       G_PARAM_READWRITE));
     113  
     114    g_object_class_install_property (gobject_class,
     115                                     PROP_NAME,
     116                                     g_param_spec_string ("name",
     117                                                          "Name",
     118                                                          "Name",
     119                                                          NULL,
     120                                                          G_PARAM_READWRITE));
     121  }
     122  
     123  /* A method that we want to export */
     124  static void
     125  my_object_change_count (MyObject *myobj,
     126                          gint      change)
     127  {
     128    myobj->count = 2 * myobj->count + change;
     129  
     130    g_object_notify (G_OBJECT (myobj), "count");
     131  }
     132  
     133  /* ---------------------------------------------------------------------------------------------------- */
     134  
     135  static GDBusNodeInfo *introspection_data = NULL;
     136  
     137  /* Introspection data for the service we are exporting */
     138  static const gchar introspection_xml[] =
     139    "<node>"
     140    "  <interface name='org.myorg.MyObject'>"
     141    "    <method name='ChangeCount'>"
     142    "      <arg type='i' name='change' direction='in'/>"
     143    "    </method>"
     144    "    <property type='i' name='Count' access='read'/>"
     145    "    <property type='s' name='Name' access='readwrite'/>"
     146    "  </interface>"
     147    "</node>";
     148  
     149  
     150  static void
     151  handle_method_call (GDBusConnection       *connection,
     152                      const gchar           *sender,
     153                      const gchar           *object_path,
     154                      const gchar           *interface_name,
     155                      const gchar           *method_name,
     156                      GVariant              *parameters,
     157                      GDBusMethodInvocation *invocation,
     158                      gpointer               user_data)
     159  {
     160    MyObject *myobj = user_data;
     161  
     162    if (g_strcmp0 (method_name, "ChangeCount") == 0)
     163      {
     164        gint change;
     165        g_variant_get (parameters, "(i)", &change);
     166  
     167        my_object_change_count (myobj, change);
     168  
     169        g_dbus_method_invocation_return_value (invocation, NULL);
     170      }
     171  }
     172  
     173  static GVariant *
     174  handle_get_property (GDBusConnection  *connection,
     175                       const gchar      *sender,
     176                       const gchar      *object_path,
     177                       const gchar      *interface_name,
     178                       const gchar      *property_name,
     179                       GError          **error,
     180                       gpointer          user_data)
     181  {
     182    GVariant *ret;
     183    MyObject *myobj = user_data;
     184  
     185    ret = NULL;
     186    if (g_strcmp0 (property_name, "Count") == 0)
     187      {
     188        ret = g_variant_new_int32 (myobj->count);
     189      }
     190    else if (g_strcmp0 (property_name, "Name") == 0)
     191      {
     192        ret = g_variant_new_string (myobj->name ? myobj->name : "");
     193      }
     194  
     195    return ret;
     196  }
     197  
     198  static gboolean
     199  handle_set_property (GDBusConnection  *connection,
     200                       const gchar      *sender,
     201                       const gchar      *object_path,
     202                       const gchar      *interface_name,
     203                       const gchar      *property_name,
     204                       GVariant         *value,
     205                       GError          **error,
     206                       gpointer          user_data)
     207  {
     208    MyObject *myobj = user_data;
     209  
     210    if (g_strcmp0 (property_name, "Count") == 0)
     211      {
     212        g_object_set (myobj, "count", g_variant_get_int32 (value), NULL);
     213      }
     214    else if (g_strcmp0 (property_name, "Name") == 0)
     215      {
     216        g_object_set (myobj, "name", g_variant_get_string (value, NULL), NULL);
     217      }
     218  
     219    return TRUE;
     220  }
     221  
     222  
     223  /* for now */
     224  static const GDBusInterfaceVTable interface_vtable =
     225  {
     226    handle_method_call,
     227    handle_get_property,
     228    handle_set_property,
     229    { 0 }
     230  };
     231  
     232  static void
     233  send_property_change (GObject         *obj,
     234                        GParamSpec      *pspec,
     235                        GDBusConnection *connection)
     236  {
     237    GVariantBuilder *builder;
     238    GVariantBuilder *invalidated_builder;
     239    MyObject *myobj = (MyObject *)obj;
     240  
     241    builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
     242    invalidated_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
     243  
     244    if (g_strcmp0 (pspec->name, "count") == 0)
     245      g_variant_builder_add (builder,
     246                             "{sv}",
     247                             "Count", g_variant_new_int32 (myobj->count));
     248    else if (g_strcmp0 (pspec->name, "name") == 0)
     249      g_variant_builder_add (builder,
     250                             "{sv}",
     251                             "Name", g_variant_new_string (myobj->name ? myobj->name : ""));
     252  
     253    g_dbus_connection_emit_signal (connection,
     254                                   NULL,
     255                                   "/org/myorg/MyObject",
     256                                   "org.freedesktop.DBus.Properties",
     257                                   "PropertiesChanged",
     258                                   g_variant_new ("(sa{sv}as)",
     259                                                  "org.myorg.MyObject",
     260                                                  builder,
     261                                                  invalidated_builder),
     262                                   NULL);
     263  }
     264  
     265  static void
     266  on_bus_acquired (GDBusConnection *connection,
     267                   const gchar     *name,
     268                   gpointer         user_data)
     269  {
     270    MyObject *myobj = user_data;
     271    guint registration_id;
     272  
     273    g_signal_connect (myobj, "notify",
     274                      G_CALLBACK (send_property_change), connection);
     275    registration_id = g_dbus_connection_register_object (connection,
     276                                                         "/org/myorg/MyObject",
     277                                                         introspection_data->interfaces[0],
     278                                                         &interface_vtable,
     279                                                         myobj,
     280                                                         NULL,  /* user_data_free_func */
     281                                                         NULL); /* GError** */
     282    g_assert (registration_id > 0);
     283  }
     284  
     285  static void
     286  on_name_acquired (GDBusConnection *connection,
     287                    const gchar     *name,
     288                    gpointer         user_data)
     289  {
     290  }
     291  
     292  static void
     293  on_name_lost (GDBusConnection *connection,
     294                const gchar     *name,
     295                gpointer         user_data)
     296  {
     297    exit (1);
     298  }
     299  
     300  int
     301  main (int argc, char *argv[])
     302  {
     303    guint owner_id;
     304    GMainLoop *loop;
     305    MyObject *myobj;
     306  
     307    /* We are lazy here - we don't want to manually provide
     308     * the introspection data structures - so we just build
     309     * them from XML.
     310     */
     311    introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
     312    g_assert (introspection_data != NULL);
     313  
     314    myobj = g_object_new (my_object_get_type (), NULL);
     315  
     316    owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
     317                               "org.myorg.MyObject",
     318                               G_BUS_NAME_OWNER_FLAGS_NONE,
     319                               on_bus_acquired,
     320                               on_name_acquired,
     321                               on_name_lost,
     322                               myobj,
     323                               NULL);
     324  
     325    loop = g_main_loop_new (NULL, FALSE);
     326    g_main_loop_run (loop);
     327  
     328    g_bus_unown_name (owner_id);
     329  
     330    g_dbus_node_info_unref (introspection_data);
     331  
     332    g_object_unref (myobj);
     333  
     334    return 0;
     335  }