(root)/
glib-2.79.0/
gio/
tests/
gdbus-example-proxy-subclass.c
       1  
       2  #include <gio/gio.h>
       3  
       4  /* ---------------------------------------------------------------------------------------------------- */
       5  /* The D-Bus interface definition we want to create a GDBusProxy-derived type for: */
       6  /* ---------------------------------------------------------------------------------------------------- */
       7  
       8  static const gchar introspection_xml[] =
       9    "<node>"
      10    "  <interface name='org.freedesktop.Accounts.User'>"
      11    "    <method name='Frobnicate'>"
      12    "      <arg name='flux' type='s' direction='in'/>"
      13    "      <arg name='baz' type='s' direction='in'/>"
      14    "      <arg name='result' type='s' direction='out'/>"
      15    "    </method>"
      16    "    <signal name='Changed'/>"
      17    "    <property name='AutomaticLogin' type='b' access='readwrite'/>"
      18    "    <property name='RealName' type='s' access='read'/>"
      19    "    <property name='UserName' type='s' access='read'/>"
      20    "  </interface>"
      21    "</node>";
      22  
      23  /* ---------------------------------------------------------------------------------------------------- */
      24  /* Definition of the AccountsUser type */
      25  /* ---------------------------------------------------------------------------------------------------- */
      26  
      27  #define ACCOUNTS_TYPE_USER         (accounts_user_get_type ())
      28  #define ACCOUNTS_USER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), ACCOUNTS_TYPE_USER, AccountsUser))
      29  #define ACCOUNTS_USER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), ACCOUNTS_TYPE_USER, AccountsUserClass))
      30  #define ACCOUNTS_USER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ACCOUNTS_TYPE_USER, AccountsUserClass))
      31  #define ACCOUNTS_IS_USER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), ACCOUNTS_TYPE_USER))
      32  #define ACCOUNTS_IS_USER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), ACCOUNTS_TYPE_USER))
      33  
      34  typedef struct _AccountsUser        AccountsUser;
      35  typedef struct _AccountsUserClass   AccountsUserClass;
      36  typedef struct _AccountsUserPrivate AccountsUserPrivate;
      37  
      38  struct _AccountsUser
      39  {
      40    /*< private >*/
      41    GDBusProxy parent_instance;
      42    AccountsUserPrivate *priv;
      43  };
      44  
      45  struct _AccountsUserClass
      46  {
      47    /*< private >*/
      48    GDBusProxyClass parent_class;
      49    void (*changed) (AccountsUser *user);
      50  };
      51  
      52  GType        accounts_user_get_type            (void) G_GNUC_CONST;
      53  
      54  const gchar *accounts_user_get_user_name       (AccountsUser        *user);
      55  const gchar *accounts_user_get_real_name       (AccountsUser        *user);
      56  gboolean     accounts_user_get_automatic_login (AccountsUser        *user);
      57  
      58  void         accounts_user_frobnicate          (AccountsUser        *user,
      59                                                  const gchar         *flux,
      60                                                  gint                 baz,
      61                                                  GCancellable        *cancellable,
      62                                                  GAsyncReadyCallback  callback,
      63                                                  gpointer             user_data);
      64  gchar       *accounts_user_frobnicate_finish   (AccountsUser        *user,
      65                                                  GAsyncResult        *res,
      66                                                  GError             **error);
      67  gchar       *accounts_user_frobnicate_sync     (AccountsUser        *user,
      68                                                  const gchar         *flux,
      69                                                  gint                 baz,
      70                                                  GCancellable        *cancellable,
      71                                                  GError             **error);
      72  
      73  /* ---------------------------------------------------------------------------------------------------- */
      74  /* Implementation of the AccountsUser type */
      75  /* ---------------------------------------------------------------------------------------------------- */
      76  
      77  /* A more efficient approach than parsing XML is to use const static
      78   * GDBusInterfaceInfo, GDBusMethodInfo, ... structures
      79   */
      80  static GDBusInterfaceInfo *
      81  accounts_user_get_interface_info (void)
      82  {
      83    static gsize has_info = 0;
      84    static GDBusInterfaceInfo *info = NULL;
      85    if (g_once_init_enter (&has_info))
      86      {
      87        GDBusNodeInfo *introspection_data;
      88        introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
      89        info = introspection_data->interfaces[0];
      90        g_once_init_leave (&has_info, 1);
      91      }
      92    return info;
      93  }
      94  
      95  enum
      96  {
      97    PROP_0,
      98    PROP_USER_NAME,
      99    PROP_REAL_NAME,
     100    PROP_AUTOMATIC_LOGIN,
     101  };
     102  
     103  enum
     104  {
     105    CHANGED_SIGNAL,
     106    LAST_SIGNAL
     107  };
     108  
     109  static guint signals[LAST_SIGNAL] = {0};
     110  
     111  G_DEFINE_TYPE (AccountsUser, accounts_user, G_TYPE_DBUS_PROXY)
     112  
     113  static void
     114  accounts_user_init (AccountsUser *user)
     115  {
     116    /* Sets the expected interface */
     117    g_dbus_proxy_set_interface_info (G_DBUS_PROXY (user), accounts_user_get_interface_info ());
     118  }
     119  
     120  static void
     121  accounts_user_get_property (GObject    *object,
     122                              guint       prop_id,
     123                              GValue     *value,
     124                              GParamSpec *pspec)
     125  {
     126    AccountsUser *user = ACCOUNTS_USER (object);
     127  
     128    switch (prop_id)
     129      {
     130      case PROP_USER_NAME:
     131        g_value_set_string (value, accounts_user_get_user_name (user));
     132        break;
     133  
     134      case PROP_REAL_NAME:
     135        g_value_set_string (value, accounts_user_get_real_name (user));
     136        break;
     137  
     138      case PROP_AUTOMATIC_LOGIN:
     139        g_value_set_boolean (value, accounts_user_get_automatic_login (user));
     140        break;
     141  
     142      default:
     143        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     144        break;
     145      }
     146  }
     147  
     148  const gchar *
     149  accounts_user_get_user_name (AccountsUser *user)
     150  {
     151    GVariant *value;
     152    const gchar *ret;
     153    g_return_val_if_fail (ACCOUNTS_IS_USER (user), NULL);
     154    value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (user), "UserName");
     155    ret = g_variant_get_string (value, NULL);
     156    g_variant_unref (value);
     157    return ret;
     158  }
     159  
     160  const gchar *
     161  accounts_user_get_real_name (AccountsUser *user)
     162  {
     163    GVariant *value;
     164    const gchar *ret;
     165    g_return_val_if_fail (ACCOUNTS_IS_USER (user), NULL);
     166    value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (user), "RealName");
     167    ret = g_variant_get_string (value, NULL);
     168    g_variant_unref (value);
     169    return ret;
     170  }
     171  
     172  gboolean
     173  accounts_user_get_automatic_login (AccountsUser *user)
     174  {
     175    GVariant *value;
     176    gboolean ret;
     177    g_return_val_if_fail (ACCOUNTS_IS_USER (user), FALSE);
     178    value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (user), "AutomaticLogin");
     179    ret = g_variant_get_boolean (value);
     180    g_variant_unref (value);
     181    return ret;
     182  }
     183  
     184  static void
     185  accounts_user_g_signal (GDBusProxy   *proxy,
     186                          const gchar  *sender_name,
     187                          const gchar  *signal_name,
     188                          GVariant     *parameters)
     189  {
     190    AccountsUser *user = ACCOUNTS_USER (proxy);
     191    if (g_strcmp0 (signal_name, "Changed") == 0)
     192      g_signal_emit (user, signals[CHANGED_SIGNAL], 0);
     193  }
     194  
     195  static void
     196  accounts_user_g_properties_changed (GDBusProxy          *proxy,
     197                                      GVariant            *changed_properties,
     198                                      const gchar* const  *invalidated_properties)
     199  {
     200    AccountsUser *user = ACCOUNTS_USER (proxy);
     201    GVariantIter *iter;
     202    const gchar *key;
     203  
     204    if (changed_properties != NULL)
     205      {
     206        g_variant_get (changed_properties, "a{sv}", &iter);
     207        while (g_variant_iter_next (iter, "{&sv}", &key, NULL))
     208          {
     209            if (g_strcmp0 (key, "AutomaticLogin") == 0)
     210              g_object_notify (G_OBJECT (user), "automatic-login");
     211            else if (g_strcmp0 (key, "RealName") == 0)
     212              g_object_notify (G_OBJECT (user), "real-name");
     213            else if (g_strcmp0 (key, "UserName") == 0)
     214              g_object_notify (G_OBJECT (user), "user-name");
     215          }
     216        g_variant_iter_free (iter);
     217      }
     218  }
     219  
     220  static void
     221  accounts_user_class_init (AccountsUserClass *klass)
     222  {
     223    GObjectClass *gobject_class;
     224    GDBusProxyClass *proxy_class;
     225  
     226    gobject_class = G_OBJECT_CLASS (klass);
     227    gobject_class->get_property = accounts_user_get_property;
     228  
     229    proxy_class = G_DBUS_PROXY_CLASS (klass);
     230    proxy_class->g_signal             = accounts_user_g_signal;
     231    proxy_class->g_properties_changed = accounts_user_g_properties_changed;
     232  
     233    g_object_class_install_property (gobject_class,
     234                                     PROP_USER_NAME,
     235                                     g_param_spec_string ("user-name",
     236                                                          "User Name",
     237                                                          "The user name of the user",
     238                                                          NULL,
     239                                                          G_PARAM_READABLE |
     240                                                          G_PARAM_STATIC_STRINGS));
     241  
     242    g_object_class_install_property (gobject_class,
     243                                     PROP_REAL_NAME,
     244                                     g_param_spec_string ("real-name",
     245                                                          "Real Name",
     246                                                          "The real name of the user",
     247                                                          NULL,
     248                                                          G_PARAM_READABLE |
     249                                                          G_PARAM_STATIC_STRINGS));
     250  
     251    g_object_class_install_property (gobject_class,
     252                                     PROP_AUTOMATIC_LOGIN,
     253                                     g_param_spec_boolean ("automatic-login",
     254                                                           "Automatic Login",
     255                                                           "Whether the user is automatically logged in",
     256                                                           FALSE,
     257                                                           G_PARAM_READABLE |
     258                                                           G_PARAM_STATIC_STRINGS));
     259  
     260    signals[CHANGED_SIGNAL] = g_signal_new ("changed",
     261                                            ACCOUNTS_TYPE_USER,
     262                                            G_SIGNAL_RUN_LAST,
     263                                            G_STRUCT_OFFSET (AccountsUserClass, changed),
     264                                            NULL,
     265                                            NULL,
     266                                            g_cclosure_marshal_VOID__VOID,
     267                                            G_TYPE_NONE,
     268                                            0);
     269  }
     270  
     271  gchar *
     272  accounts_user_frobnicate_sync (AccountsUser        *user,
     273                                 const gchar         *flux,
     274                                 gint                 baz,
     275                                 GCancellable        *cancellable,
     276                                 GError             **error)
     277  {
     278    gchar *ret;
     279    GVariant *value;
     280  
     281    g_return_val_if_fail (ACCOUNTS_IS_USER (user), NULL);
     282  
     283    ret = NULL;
     284  
     285    value = g_dbus_proxy_call_sync (G_DBUS_PROXY (user),
     286                                    "Frobnicate",
     287                                    g_variant_new ("(si)",
     288                                                   flux,
     289                                                   baz),
     290                                    G_DBUS_CALL_FLAGS_NONE,
     291                                    -1,
     292                                    cancellable,
     293                                    error);
     294    if (value != NULL)
     295      {
     296        g_variant_get (value, "(s)", &ret);
     297        g_variant_unref (value);
     298      }
     299    return ret;
     300  }
     301  
     302  void
     303  accounts_user_frobnicate (AccountsUser        *user,
     304                            const gchar         *flux,
     305                            gint                 baz,
     306                            GCancellable        *cancellable,
     307                            GAsyncReadyCallback  callback,
     308                            gpointer             user_data)
     309  {
     310    g_return_if_fail (ACCOUNTS_IS_USER (user));
     311    g_dbus_proxy_call (G_DBUS_PROXY (user),
     312                       "Frobnicate",
     313                       g_variant_new ("(si)",
     314                                      flux,
     315                                      baz),
     316                       G_DBUS_CALL_FLAGS_NONE,
     317                       -1,
     318                       cancellable,
     319                       callback,
     320                       user_data);
     321  }
     322  
     323  
     324  gchar *
     325  accounts_user_frobnicate_finish (AccountsUser        *user,
     326                                   GAsyncResult        *res,
     327                                   GError             **error)
     328  {
     329    gchar *ret;
     330    GVariant *value;
     331  
     332    ret = NULL;
     333    value = g_dbus_proxy_call_finish (G_DBUS_PROXY (user), res, error);
     334    if (value != NULL)
     335      {
     336        g_variant_get (value, "(s)", &ret);
     337        g_variant_unref (value);
     338      }
     339    return ret;
     340  }
     341  
     342  /* ---------------------------------------------------------------------------------------------------- */
     343  /* Example usage of the AccountsUser type */
     344  /* ---------------------------------------------------------------------------------------------------- */
     345  
     346  static void
     347  print_user (AccountsUser *user)
     348  {
     349    g_print ("  user-name       = `%s'\n", accounts_user_get_user_name (user));
     350    g_print ("  real-name       = `%s'\n", accounts_user_get_real_name (user));
     351    g_print ("  automatic-login = %s\n", accounts_user_get_automatic_login (user) ? "true" : "false");
     352  }
     353  
     354  static void
     355  on_changed (AccountsUser *user,
     356              gpointer      user_data)
     357  {
     358    g_print ("+++ Received the AccountsUser::changed signal\n");
     359    print_user (user);
     360  }
     361  
     362  static void
     363  on_notify (GObject    *object,
     364             GParamSpec *pspec,
     365             gpointer    user_data)
     366  {
     367    AccountsUser *user = ACCOUNTS_USER (object);
     368    g_print ("+++ Received the GObject::notify signal for property `%s'\n",
     369             pspec->name);
     370    print_user (user);
     371  }
     372  
     373  static void
     374  on_accounts_proxy_available (GObject      *object,
     375                               GAsyncResult *result,
     376                               gpointer      user_data)
     377  {
     378    GError *error = NULL;
     379    GObject *user_object;
     380    AccountsUser *user;
     381  
     382    user_object = g_async_initable_new_finish (G_ASYNC_INITABLE (object),
     383                                               result,
     384                                               &error);
     385    if (!user_object)
     386      {
     387        g_error ("Failed to create proxy: %s", error->message);
     388        g_clear_error (&error);
     389        return;
     390      }
     391    user = ACCOUNTS_USER (user_object);
     392  
     393    g_print ("+++ Acquired proxy for user\n");
     394    print_user (user);
     395  
     396    g_signal_connect (user,
     397                      "notify",
     398                      G_CALLBACK (on_notify),
     399                      NULL);
     400    g_signal_connect (user,
     401                      "changed",
     402                      G_CALLBACK (on_changed),
     403                      NULL);
     404  }
     405  
     406  static void
     407  on_accounts_appeared (GDBusConnection *connection,
     408                        const gchar     *name,
     409                        const gchar     *name_owner,
     410                        gpointer         user_data)
     411  {
     412    g_async_initable_new_async (ACCOUNTS_TYPE_USER, 0, NULL,
     413                                on_accounts_proxy_available,
     414                                "g-flags", 0,
     415                                "g-interface-info", NULL,
     416                                "g-unique-bus-name", name_owner,
     417                                "g-connection", connection,
     418                                "g-object-path", "/org/freedesktop/Accounts/User500",
     419                                "g-interface-name", "org.freedesktop.Accounts.User");
     420  }
     421  
     422  static void
     423  on_accounts_vanished (GDBusConnection *connection,
     424                        const gchar     *name,
     425                        gpointer         user_data)
     426  {
     427  }
     428  
     429  /* ---------------------------------------------------------------------------------------------------- */
     430  
     431  gint
     432  main (gint argc, gchar *argv[])
     433  {
     434    guint watcher_id;
     435    GMainLoop *loop;
     436  
     437    watcher_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
     438                                   "org.freedesktop.Accounts",
     439                                   G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
     440                                   on_accounts_appeared,
     441                                   on_accounts_vanished,
     442                                   NULL, NULL);
     443  
     444    loop = g_main_loop_new (NULL, FALSE);
     445    g_main_loop_run (loop);
     446    g_main_loop_unref (loop);
     447    g_bus_unwatch_name (watcher_id);
     448  
     449    return 0;
     450  }