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 }