1 /*
2 * account.c - proxy for an account in the Telepathy account manager
3 *
4 * Copyright © 2009–2012 Collabora Ltd. <http://www.collabora.co.uk/>
5 * Copyright © 2009–2010 Nokia Corporation
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "config.h"
23
24 #include <string.h>
25
26 #include "telepathy-glib/account-internal.h"
27 #include "telepathy-glib/account.h"
28
29 #include <telepathy-glib/dbus.h>
30 #include <telepathy-glib/defs.h>
31 #include <telepathy-glib/errors.h>
32 #include <telepathy-glib/gtypes.h>
33 #include <telepathy-glib/interfaces.h>
34 #include <telepathy-glib/proxy-subclass.h>
35 #include <telepathy-glib/util.h>
36
37 #define DEBUG_FLAG TP_DEBUG_ACCOUNTS
38 #include "telepathy-glib/connection-internal.h"
39 #include "telepathy-glib/dbus-internal.h"
40 #include "telepathy-glib/debug-internal.h"
41 #include "telepathy-glib/proxy-internal.h"
42 #include "telepathy-glib/simple-client-factory-internal.h"
43 #include "telepathy-glib/util-internal.h"
44 #include "telepathy-glib/variant-util-internal.h"
45
46 #include "telepathy-glib/_gen/tp-cli-account-body.h"
47
48 /**
49 * SECTION:account
50 * @title: TpAccount
51 * @short_description: proxy object for an account in the Telepathy account
52 * manager
53 * @see_also: #TpAccountManager
54 *
55 * The Telepathy Account Manager stores the user's configured real-time
56 * communication accounts. The #TpAccount object represents a stored account.
57 *
58 * Since: 0.7.32
59 */
60
61 /**
62 * TpAccount:
63 *
64 * The Telepathy Account Manager stores the user's configured real-time
65 * communication accounts. This object represents a stored account.
66 *
67 * If this account is deleted from the account manager, the
68 * #TpProxy::invalidated signal will be emitted
69 * with the domain %TP_DBUS_ERRORS and the error code
70 * %TP_DBUS_ERROR_OBJECT_REMOVED.
71 *
72 * One can connect to the #GObject::notify signal to get change notifications
73 * for many of the properties on this object. Refer to each property's
74 * documentation for whether it can be used in this way.
75 *
76 * #TpAccount objects should normally be obtained from the #TpAccountManager.
77 *
78 * Since 0.16, #TpAccount always has a non-%NULL #TpProxy:factory, and its
79 * #TpProxy:factory will be propagated to its #TpConnection
80 * (if any). If a #TpAccount is created without going via the
81 * #TpAccountManager or specifying a #TpProxy:factory, the default
82 * is to use a new #TpAutomaticClientFactory.
83 *
84 * Since: 0.7.32
85 */
86
87 /**
88 * TpAccountClass:
89 *
90 * The class of a #TpAccount.
91 */
92
93 struct _TpAccountPrivate {
94 gboolean dispose_has_run;
95
96 TpConnection *connection;
97 gchar *connection_object_path;
98
99 TpConnectionStatus connection_status;
100 TpConnectionStatusReason reason;
101 gchar *error;
102 GHashTable *error_details;
103
104 TpConnectionPresenceType cur_presence;
105 gchar *cur_status;
106 gchar *cur_message;
107
108 TpConnectionPresenceType requested_presence;
109 gchar *requested_status;
110 gchar *requested_message;
111
112 TpConnectionPresenceType auto_presence;
113 gchar *auto_status;
114 gchar *auto_message;
115
116 gboolean changing_presence;
117 gboolean connect_automatically;
118 gboolean has_been_online;
119
120 gchar *normalized_name;
121 gchar *nickname;
122
123 gboolean enabled;
124 gboolean valid;
125 gboolean removed;
126
127 gchar *cm_name;
128 gchar *proto_name;
129 gchar *icon_name;
130 gchar *service;
131
132 gchar *display_name;
133 GStrv supersedes;
134
135 GHashTable *parameters;
136
137 gchar *storage_provider;
138 GValue *storage_identifier;
139 TpStorageRestrictionFlags storage_restrictions;
140
141 GStrv uri_schemes;
142
143 gboolean connection_prepared;
144 };
145
146 G_DEFINE_TYPE (TpAccount, tp_account, TP_TYPE_PROXY)
147
148 /* signals */
149 enum {
150 STATUS_CHANGED,
151 PRESENCE_CHANGED,
152 AVATAR_CHANGED,
153 LAST_SIGNAL
154 };
155
156 static guint signals[LAST_SIGNAL];
157
158 /* properties */
159 enum {
160 PROP_ENABLED = 1,
161 PROP_CHANGING_PRESENCE,
162 PROP_CURRENT_PRESENCE_TYPE,
163 PROP_CURRENT_STATUS,
164 PROP_CURRENT_STATUS_MESSAGE,
165 PROP_CONNECTION_STATUS,
166 PROP_CONNECTION_STATUS_REASON,
167 PROP_CONNECTION_ERROR,
168 PROP_CONNECTION_ERROR_DETAILS,
169 PROP_CONNECTION,
170 PROP_DISPLAY_NAME,
171 PROP_CONNECTION_MANAGER,
172 PROP_CM_NAME,
173 PROP_PROTOCOL,
174 PROP_PROTOCOL_NAME,
175 PROP_ICON_NAME,
176 PROP_CONNECT_AUTOMATICALLY,
177 PROP_HAS_BEEN_ONLINE,
178 PROP_SERVICE,
179 PROP_VALID,
180 PROP_REQUESTED_PRESENCE_TYPE,
181 PROP_REQUESTED_STATUS,
182 PROP_REQUESTED_STATUS_MESSAGE,
183 PROP_NICKNAME,
184 PROP_AUTOMATIC_PRESENCE_TYPE,
185 PROP_AUTOMATIC_STATUS,
186 PROP_AUTOMATIC_STATUS_MESSAGE,
187 PROP_NORMALIZED_NAME,
188 PROP_STORAGE_PROVIDER,
189 PROP_STORAGE_IDENTIFIER,
190 PROP_STORAGE_IDENTIFIER_VARIANT,
191 PROP_STORAGE_RESTRICTIONS,
192 PROP_SUPERSEDES,
193 PROP_URI_SCHEMES,
194 N_PROPS
195 };
196
197 static void tp_account_prepare_connection_async (TpProxy *proxy,
198 const TpProxyFeature *feature,
199 GAsyncReadyCallback callback,
200 gpointer user_data);
201
202 static void tp_account_prepare_addressing_async (TpProxy *proxy,
203 const TpProxyFeature *feature,
204 GAsyncReadyCallback callback,
205 gpointer user_data);
206
207 static void tp_account_prepare_storage_async (TpProxy *proxy,
208 const TpProxyFeature *feature,
209 GAsyncReadyCallback callback,
210 gpointer user_data);
211
212 static gboolean
connection_is_internal(TpAccount * self)213 connection_is_internal (TpAccount *self)
214 {
215 if (!tp_proxy_is_prepared (self, TP_ACCOUNT_FEATURE_CONNECTION))
216 return FALSE;
217
218 return !self->priv->connection_prepared;
219 }
220
221 /**
222 * TP_ACCOUNT_FEATURE_CORE:
223 *
224 * Expands to a call to a function that returns a quark for the "core" feature
225 * on a #TpAccount.
226 *
227 * When this feature is prepared, the basic properties of the Account have
228 * been retrieved and are available for use, and change-notification has been
229 * set up.
230 *
231 * One can ask for a feature to be prepared using the
232 * tp_proxy_prepare_async() function, and waiting for it to callback.
233 *
234 * Since: 0.9.0
235 */
236
237 /**
238 * TP_ACCOUNT_FEATURE_CONNECTION:
239 *
240 * Expands to a call to a function that returns a quark for the "connection"
241 * feature on a #TpAccount.
242 *
243 * When this feature is prepared, it is guaranteed that #TpAccount:connection
244 * will always be either %NULL or prepared. The account's #TpProxy:factory
245 * will be used to create the #TpConnection object and to determine its
246 * desired connection features. Change notification of the
247 * #TpAccount:connection property will be delayed until all features (at least
248 * %TP_CONNECTION_FEATURE_CORE) are prepared. See
249 * tp_simple_client_factory_add_account_features() to define which features
250 * needs to be prepared.
251 *
252 * One can ask for a feature to be prepared using the
253 * tp_proxy_prepare_async() function, and waiting for it to callback.
254 *
255 * Since: 0.15.5
256 */
257
258 /**
259 * TP_ACCOUNT_FEATURE_STORAGE:
260 *
261 * Expands to a call to a function that returns a quark for the "storage"
262 * feature on a #TpAccount.
263 *
264 * When this feature is prepared, the Account.Interface.Storage properties have
265 * been retrieved and are available for use.
266 *
267 * One can ask for a feature to be prepared using the
268 * tp_proxy_prepare_async() function, and waiting for it to callback.
269 *
270 * Since: 0.13.2
271 */
272
273 /**
274 * TP_ACCOUNT_FEATURE_ADDRESSING:
275 *
276 * Expands to a call to a function that returns a quark for the "addressing"
277 * feature on a #TpAccount.
278 *
279 * When this feature is prepared, the list of URI schemes from
280 * Account.Interface.Addressing has been retrieved and is available for use.
281 *
282 * One can ask for a feature to be prepared using the
283 * tp_proxy_prepare_async() function, and waiting for it to callback.
284 *
285 * Since: 0.13.8
286 */
287
288 /**
289 * tp_account_get_feature_quark_core:
290 *
291 * <!-- -->
292 *
293 * Returns: the quark used for representing the core feature of a
294 * #TpAccount
295 *
296 * Since: 0.9.0
297 */
298 GQuark
tp_account_get_feature_quark_core(void)299 tp_account_get_feature_quark_core (void)
300 {
301 return g_quark_from_static_string ("tp-account-feature-core");
302 }
303
304 /**
305 * tp_account_get_feature_quark_connection:
306 *
307 * <!-- -->
308 *
309 * Returns: the quark used for representing the connection feature of a
310 * #TpAccount
311 *
312 * Since: 0.15.5
313 */
314 GQuark
tp_account_get_feature_quark_connection(void)315 tp_account_get_feature_quark_connection (void)
316 {
317 return g_quark_from_static_string ("tp-account-feature-connection");
318 }
319
320 /**
321 * tp_account_get_feature_quark_storage:
322 *
323 * <!-- -->
324 *
325 * Returns: the quark used for representing the storage interface of a
326 * #TpAccount
327 *
328 * Since: 0.13.2
329 */
330 GQuark
tp_account_get_feature_quark_storage(void)331 tp_account_get_feature_quark_storage (void)
332 {
333 return g_quark_from_static_string ("tp-account-feature-storage");
334 }
335
336 GQuark
tp_account_get_feature_quark_addressing(void)337 tp_account_get_feature_quark_addressing (void)
338 {
339 return g_quark_from_static_string ("tp-account-feature-addressing");
340 }
341
342 enum {
343 FEAT_CORE,
344 FEAT_CONNECTION,
345 FEAT_ADDRESSING,
346 FEAT_STORAGE,
347 N_FEAT
348 };
349
350 static const TpProxyFeature *
_tp_account_list_features(TpProxyClass * cls G_GNUC_UNUSED)351 _tp_account_list_features (TpProxyClass *cls G_GNUC_UNUSED)
352 {
353 static TpProxyFeature features[N_FEAT + 1] = { { 0 } };
354
355 if (G_UNLIKELY (features[0].name == 0))
356 {
357 features[FEAT_CORE].name = TP_ACCOUNT_FEATURE_CORE;
358 features[FEAT_CORE].core = TRUE;
359 /* no need for a prepare_async function - the constructor starts it */
360
361 features[FEAT_CONNECTION].name = TP_ACCOUNT_FEATURE_CONNECTION;
362 features[FEAT_CONNECTION].prepare_async =
363 tp_account_prepare_connection_async;
364
365 features[FEAT_ADDRESSING].name = TP_ACCOUNT_FEATURE_ADDRESSING;
366 features[FEAT_ADDRESSING].prepare_async =
367 tp_account_prepare_addressing_async;
368
369 features[FEAT_STORAGE].name = TP_ACCOUNT_FEATURE_STORAGE;
370 features[FEAT_STORAGE].prepare_async =
371 tp_account_prepare_storage_async;
372
373 /* assert that the terminator at the end is there */
374 g_assert (features[N_FEAT].name == 0);
375 }
376
377 return features;
378 }
379
380 static void
tp_account_init(TpAccount * self)381 tp_account_init (TpAccount *self)
382 {
383 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TYPE_ACCOUNT,
384 TpAccountPrivate);
385
386 self->priv->connection_status = TP_CONNECTION_STATUS_DISCONNECTED;
387 self->priv->error = g_strdup (TP_ERROR_STR_DISCONNECTED);
388 self->priv->error_details = g_hash_table_new_full (g_str_hash, g_str_equal,
389 g_free, (GDestroyNotify) tp_g_value_slice_free);
390 self->priv->supersedes = g_new0 (gchar *, 1);
391 }
392
393 static void
_tp_account_invalidated_cb(TpAccount * self,guint domain,guint code,gchar * message)394 _tp_account_invalidated_cb (TpAccount *self,
395 guint domain,
396 guint code,
397 gchar *message)
398 {
399 TpAccountPrivate *priv = self->priv;
400
401 /* The connection will get disconnected as a result of account deletion,
402 * but by then we will no longer be telling the API user about changes -
403 * so claim the disconnection already happened (see fd.o#25149) */
404 if (priv->connection_status != TP_CONNECTION_STATUS_DISCONNECTED)
405 {
406 priv->connection_status = TP_CONNECTION_STATUS_DISCONNECTED;
407 tp_clear_pointer (&priv->error, g_free);
408 g_hash_table_remove_all (priv->error_details);
409
410 if (domain == TP_DBUS_ERRORS && code == TP_DBUS_ERROR_OBJECT_REMOVED)
411 {
412 /* presumably the user asked for it to be deleted... */
413 priv->reason = TP_CONNECTION_STATUS_REASON_REQUESTED;
414 priv->error = g_strdup (TP_ERROR_STR_CANCELLED);
415 g_hash_table_insert (priv->error_details,
416 g_strdup ("debug-message"),
417 tp_g_value_slice_new_static_string ("TpAccount was removed"));
418 }
419 else
420 {
421 gchar *s;
422
423 priv->reason = TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED;
424 priv->error = g_strdup (TP_ERROR_STR_DISCONNECTED);
425 s = g_strdup_printf ("TpAccount was invalidated: %s #%u: %s",
426 g_quark_to_string (domain), code, message);
427 g_hash_table_insert (priv->error_details,
428 g_strdup ("debug-message"),
429 tp_g_value_slice_new_take_string (s));
430 }
431
432 g_object_notify ((GObject *) self, "connection-status");
433 g_object_notify ((GObject *) self, "connection-status-reason");
434 g_object_notify ((GObject *) self, "connection-error");
435 g_object_notify ((GObject *) self, "connection-error-details");
436 }
437 }
438
439 static void
_tp_account_removed_cb(TpAccount * self,gpointer unused G_GNUC_UNUSED,GObject * object G_GNUC_UNUSED)440 _tp_account_removed_cb (TpAccount *self,
441 gpointer unused G_GNUC_UNUSED,
442 GObject *object G_GNUC_UNUSED)
443 {
444 GError e = { TP_DBUS_ERRORS, TP_DBUS_ERROR_OBJECT_REMOVED,
445 "Account removed" };
446
447 if (self->priv->removed)
448 return;
449
450 self->priv->removed = TRUE;
451
452 tp_proxy_invalidate ((TpProxy *) self, &e);
453 }
454
455 static void
set_connection_prepare_cb(GObject * object,GAsyncResult * res,gpointer user_data)456 set_connection_prepare_cb (GObject *object,
457 GAsyncResult *res,
458 gpointer user_data)
459 {
460 TpConnection *connection = (TpConnection *) object;
461 TpAccount *self = user_data;
462 GError *error = NULL;
463
464 if (!tp_proxy_prepare_finish (object, res, &error))
465 {
466 DEBUG ("Error preparing connection: %s", error->message);
467 g_clear_error (&error);
468 goto OUT;
469 }
470
471 /* Connection could have changed again while we were preparing it */
472 if (self->priv->connection == connection)
473 {
474 self->priv->connection_prepared = TRUE;
475 g_object_notify ((GObject *) self, "connection");
476 }
477
478 OUT:
479 g_object_unref (self);
480 }
481
482 static void _tp_account_set_connection (TpAccount *account, const gchar *path);
483
484 static void
connection_invalidated_cb(TpConnection * connection,guint domain,gint code,gchar * message,TpAccount * account)485 connection_invalidated_cb (TpConnection *connection,
486 guint domain,
487 gint code,
488 gchar *message,
489 TpAccount *account)
490 {
491 _tp_account_set_connection (account, "/");
492 }
493
494 static void
_tp_account_set_connection(TpAccount * account,const gchar * path)495 _tp_account_set_connection (TpAccount *account,
496 const gchar *path)
497 {
498 TpAccountPrivate *priv = account->priv;
499 gboolean had_public_connection;
500 gboolean have_public_connection;
501 GError *error = NULL;
502
503 if (priv->connection != NULL)
504 {
505 const gchar *current;
506
507 /* Do nothing if we already have a connection for the same path */
508 current = tp_proxy_get_object_path (priv->connection);
509 if (!tp_strdiff (current, path))
510 return;
511
512 g_signal_handlers_disconnect_by_func (priv->connection,
513 connection_invalidated_cb, account);
514 }
515
516 had_public_connection = (priv->connection != NULL &&
517 !connection_is_internal (account));
518
519 tp_clear_object (&account->priv->connection);
520 g_free (priv->connection_object_path);
521 priv->connection_object_path = g_strdup (path);
522 priv->connection_prepared = FALSE;
523
524 /* The account has no connection */
525 if (!tp_strdiff ("/", path))
526 {
527 /* Do not emit change notifications if the connection was not yet made
528 * public */
529 if (had_public_connection)
530 g_object_notify (G_OBJECT (account), "connection");
531
532 return;
533 }
534
535 priv->connection = tp_simple_client_factory_ensure_connection (
536 tp_proxy_get_factory (account), path, NULL, &error);
537
538 if (priv->connection == NULL)
539 {
540 DEBUG ("Failed to create a new TpConnection: %s",
541 error->message);
542 g_error_free (error);
543 }
544 else
545 {
546 tp_g_signal_connect_object (priv->connection, "invalidated",
547 G_CALLBACK (connection_invalidated_cb), account, 0);
548
549 _tp_connection_set_account (priv->connection, account);
550 if (tp_proxy_is_prepared (account, TP_ACCOUNT_FEATURE_CONNECTION))
551 {
552 GArray *features;
553
554 features = tp_simple_client_factory_dup_connection_features (
555 tp_proxy_get_factory (account), priv->connection);
556
557 tp_proxy_prepare_async (priv->connection, (GQuark *) features->data,
558 set_connection_prepare_cb, g_object_ref (account));
559
560 g_array_unref (features);
561 }
562 }
563
564 have_public_connection = (priv->connection != NULL &&
565 !connection_is_internal (account));
566
567 /* Do not emit signal if connection wasn't public and still isn't */
568 if (had_public_connection || have_public_connection)
569 g_object_notify (G_OBJECT (account), "connection");
570 }
571
572 static void
_tp_account_got_all_storage_cb(TpProxy * proxy,GHashTable * properties,const GError * error,gpointer user_data,GObject * object)573 _tp_account_got_all_storage_cb (TpProxy *proxy,
574 GHashTable *properties,
575 const GError *error,
576 gpointer user_data,
577 GObject *object)
578 {
579 TpAccount *self = TP_ACCOUNT (proxy);
580 GSimpleAsyncResult *result = user_data;
581
582 if (error != NULL)
583 DEBUG ("Error getting Storage properties: %s", error->message);
584
585 if (properties == NULL)
586 self->priv->storage_provider = NULL;
587 else
588 self->priv->storage_provider = g_strdup (tp_asv_get_string (properties,
589 "StorageProvider"));
590
591 if (!tp_str_empty (self->priv->storage_provider))
592 {
593 self->priv->storage_identifier = tp_g_value_slice_dup (
594 tp_asv_get_boxed (properties, "StorageIdentifier", G_TYPE_VALUE));
595 self->priv->storage_restrictions = tp_asv_get_uint32 (properties,
596 "StorageRestrictions", NULL);
597 }
598
599 /* if the StorageProvider isn't known, set it to the empty string */
600 if (self->priv->storage_provider == NULL)
601 self->priv->storage_provider = g_strdup ("");
602
603 g_simple_async_result_complete_in_idle (result);
604 }
605
606 static void
tp_account_prepare_storage_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)607 tp_account_prepare_storage_async (TpProxy *proxy,
608 const TpProxyFeature *feature,
609 GAsyncReadyCallback callback,
610 gpointer user_data)
611 {
612 TpAccount *self = TP_ACCOUNT (proxy);
613 GSimpleAsyncResult *result;
614
615 result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
616 tp_account_prepare_storage_async);
617
618 g_assert (self->priv->storage_provider == NULL);
619
620 tp_cli_dbus_properties_call_get_all (self, -1,
621 TP_IFACE_ACCOUNT_INTERFACE_STORAGE,
622 _tp_account_got_all_storage_cb, result, g_object_unref, G_OBJECT (self));
623 }
624
625 static void
_tp_account_update(TpAccount * account,GHashTable * properties)626 _tp_account_update (TpAccount *account,
627 GHashTable *properties)
628 {
629 TpProxy *proxy = TP_PROXY (account);
630 TpAccountPrivate *priv = account->priv;
631 GValueArray *arr;
632 TpConnectionStatus old_s = priv->connection_status;
633 gboolean status_changed = FALSE;
634 gboolean presence_changed = FALSE;
635 const gchar *status;
636 const gchar *message;
637
638 tp_proxy_add_interfaces (proxy, tp_asv_get_strv (properties, "Interfaces"));
639
640 if (g_hash_table_lookup (properties, "ConnectionStatus") != NULL)
641 {
642 priv->connection_status =
643 tp_asv_get_uint32 (properties, "ConnectionStatus", NULL);
644
645 if (old_s != priv->connection_status)
646 status_changed = TRUE;
647 }
648
649 if (g_hash_table_lookup (properties, "ConnectionStatusReason") != NULL)
650 {
651 TpConnectionStatusReason old = priv->reason;
652
653 priv->reason =
654 tp_asv_get_uint32 (properties, "ConnectionStatusReason", NULL);
655
656 if (old != priv->reason)
657 status_changed = TRUE;
658 }
659
660 if (g_hash_table_lookup (properties, "ConnectionError") != NULL)
661 {
662 const gchar *new_error = tp_asv_get_string (properties,
663 "ConnectionError");
664
665 if (tp_str_empty (new_error))
666 new_error = NULL;
667
668 if (tp_strdiff (new_error, priv->error))
669 {
670 tp_clear_pointer (&priv->error, g_free);
671 priv->error = g_strdup (new_error);
672 status_changed = TRUE;
673 }
674 }
675
676 if (g_hash_table_lookup (properties, "ConnectionErrorDetails") != NULL)
677 {
678 const GHashTable *details = tp_asv_get_boxed (properties,
679 "ConnectionErrorDetails", TP_HASH_TYPE_STRING_VARIANT_MAP);
680
681 if ((details != NULL && tp_asv_size (details) > 0) ||
682 tp_asv_size (priv->error_details) > 0)
683 {
684 g_hash_table_remove_all (priv->error_details);
685
686 if (details != NULL)
687 tp_g_hash_table_update (priv->error_details,
688 (GHashTable *) details,
689 (GBoxedCopyFunc) g_strdup,
690 (GBoxedCopyFunc) tp_g_value_slice_dup);
691
692 status_changed = TRUE;
693 }
694 }
695
696 if (status_changed)
697 {
698 if (priv->connection_status == TP_CONNECTION_STATUS_CONNECTED)
699 {
700 /* our connection status is CONNECTED - clear any error we may
701 * have recorded previously */
702 g_hash_table_remove_all (priv->error_details);
703 tp_clear_pointer (&priv->error, g_free);
704 }
705 else if (priv->error == NULL)
706 {
707 /* our connection status is worse than CONNECTED but the
708 * AccountManager didn't tell us why, so attempt to guess
709 * a detailed error from the status reason */
710 const gchar *guessed = NULL;
711
712 _tp_connection_status_reason_to_gerror (priv->reason,
713 old_s, &guessed, NULL);
714
715 if (guessed == NULL)
716 guessed = TP_ERROR_STR_DISCONNECTED;
717
718 priv->error = g_strdup (guessed);
719 }
720 }
721
722 if (g_hash_table_lookup (properties, "CurrentPresence") != NULL)
723 {
724 presence_changed = TRUE;
725 arr = tp_asv_get_boxed (properties, "CurrentPresence",
726 TP_STRUCT_TYPE_SIMPLE_PRESENCE);
727
728 tp_value_array_unpack (arr, 3,
729 &priv->cur_presence,
730 &status,
731 &message);
732 g_free (priv->cur_status);
733 priv->cur_status = g_strdup (status);
734 g_free (priv->cur_message);
735 priv->cur_message = g_strdup (message);
736 }
737
738 if (g_hash_table_lookup (properties, "RequestedPresence") != NULL)
739 {
740 arr = tp_asv_get_boxed (properties, "RequestedPresence",
741 TP_STRUCT_TYPE_SIMPLE_PRESENCE);
742
743 tp_value_array_unpack (arr, 3,
744 &priv->requested_presence,
745 &status,
746 &message);
747 g_free (priv->requested_status);
748 priv->requested_status = g_strdup (status);
749 g_free (priv->requested_message);
750 priv->requested_message = g_strdup (message);
751
752 g_object_notify (G_OBJECT (account), "requested-presence-type");
753 g_object_notify (G_OBJECT (account), "requested-status");
754 g_object_notify (G_OBJECT (account), "requested-status-message");
755 }
756
757 if (g_hash_table_lookup (properties, "AutomaticPresence") != NULL)
758 {
759 arr = tp_asv_get_boxed (properties, "AutomaticPresence",
760 TP_STRUCT_TYPE_SIMPLE_PRESENCE);
761
762 tp_value_array_unpack (arr, 3,
763 &priv->auto_presence,
764 &status,
765 &message);
766 g_free (priv->auto_status);
767 priv->auto_status = g_strdup (status);
768 g_free (priv->auto_message);
769 priv->auto_message = g_strdup (message);
770
771 g_object_notify (G_OBJECT (account), "automatic-presence-type");
772 g_object_notify (G_OBJECT (account), "automatic-status");
773 g_object_notify (G_OBJECT (account), "automatic-status-message");
774 }
775
776 if (g_hash_table_lookup (properties, "DisplayName") != NULL)
777 {
778 gchar *old = priv->display_name;
779
780 priv->display_name =
781 g_strdup (tp_asv_get_string (properties, "DisplayName"));
782
783 if (tp_strdiff (old, priv->display_name))
784 g_object_notify (G_OBJECT (account), "display-name");
785
786 g_free (old);
787 }
788
789 if (g_hash_table_lookup (properties, "Nickname") != NULL)
790 {
791 gchar *old = priv->nickname;
792
793 priv->nickname = g_strdup (tp_asv_get_string (properties, "Nickname"));
794
795 if (tp_strdiff (old, priv->nickname))
796 g_object_notify (G_OBJECT (account), "nickname");
797
798 g_free (old);
799 }
800
801 if (g_hash_table_lookup (properties, "Supersedes") != NULL)
802 {
803 GStrv old = priv->supersedes;
804 GPtrArray *new_arr = tp_asv_get_boxed (properties, "Supersedes",
805 TP_ARRAY_TYPE_OBJECT_PATH_LIST);
806 gboolean changed = FALSE;
807 guint i;
808
809 if (new_arr == NULL)
810 {
811 priv->supersedes = g_new0 (gchar *, 1);
812 }
813 else
814 {
815 priv->supersedes = g_new0 (gchar *, new_arr->len + 1);
816
817 for (i = 0; i < new_arr->len; i++)
818 priv->supersedes[i] = g_strdup (g_ptr_array_index (new_arr, i));
819 }
820
821 if (new_arr == NULL || new_arr->len == 0)
822 {
823 changed = (old != NULL && *old != NULL);
824 }
825 else if (old == NULL || *old == NULL ||
826 g_strv_length (old) != new_arr->len)
827 {
828 changed = TRUE;
829 }
830 else
831 {
832 for (i = 0; i < new_arr->len; i++)
833 {
834 if (tp_strdiff (old[i], priv->supersedes[i]))
835 {
836 changed = TRUE;
837 break;
838 }
839 }
840 }
841
842 if (changed)
843 g_object_notify (G_OBJECT (account), "supersedes");
844
845 g_strfreev (old);
846 }
847
848 if (g_hash_table_lookup (properties, "NormalizedName") != NULL)
849 {
850 gchar *old = priv->normalized_name;
851
852 priv->normalized_name = g_strdup (tp_asv_get_string (properties,
853 "NormalizedName"));
854
855 if (tp_strdiff (old, priv->normalized_name))
856 g_object_notify (G_OBJECT (account), "normalized-name");
857
858 g_free (old);
859 }
860
861 if (g_hash_table_lookup (properties, "Icon") != NULL)
862 {
863 const gchar *icon_name;
864 gchar *old = priv->icon_name;
865
866 icon_name = tp_asv_get_string (properties, "Icon");
867
868 if (tp_str_empty (icon_name))
869 priv->icon_name = g_strdup_printf ("im-%s", priv->proto_name);
870 else
871 priv->icon_name = g_strdup (icon_name);
872
873 if (tp_strdiff (old, priv->icon_name))
874 g_object_notify (G_OBJECT (account), "icon-name");
875
876 g_free (old);
877 }
878
879 if (g_hash_table_lookup (properties, "Enabled") != NULL)
880 {
881 gboolean enabled = tp_asv_get_boolean (properties, "Enabled", NULL);
882 if (priv->enabled != enabled)
883 {
884 priv->enabled = enabled;
885 g_object_notify (G_OBJECT (account), "enabled");
886 }
887 }
888
889 if (g_hash_table_lookup (properties, "Service") != NULL)
890 {
891 const gchar *service;
892 gchar *old = priv->service;
893
894 service = tp_asv_get_string (properties, "Service");
895
896 if (tp_str_empty (service))
897 priv->service = g_strdup (priv->proto_name);
898 else
899 priv->service = g_strdup (service);
900
901 if (tp_strdiff (old, priv->service))
902 g_object_notify (G_OBJECT (account), "service");
903
904 g_free (old);
905 }
906
907 if (g_hash_table_lookup (properties, "Valid") != NULL)
908 {
909 gboolean old = priv->valid;
910
911 priv->valid = tp_asv_get_boolean (properties, "Valid", NULL);
912
913 if (old != priv->valid)
914 g_object_notify (G_OBJECT (account), "valid");
915 }
916
917 if (g_hash_table_lookup (properties, "Parameters") != NULL)
918 {
919 GHashTable *parameters;
920
921 parameters = tp_asv_get_boxed (properties, "Parameters",
922 TP_HASH_TYPE_STRING_VARIANT_MAP);
923
924 if (priv->parameters != NULL)
925 g_hash_table_unref (priv->parameters);
926
927 priv->parameters = g_boxed_copy (TP_HASH_TYPE_STRING_VARIANT_MAP,
928 parameters);
929 /* this isn't a property, so we don't notify */
930 }
931
932 if (status_changed)
933 {
934 g_signal_emit (account, signals[STATUS_CHANGED], 0,
935 old_s, priv->connection_status, priv->reason, priv->error,
936 priv->error_details);
937
938 g_object_notify (G_OBJECT (account), "connection-status");
939 g_object_notify (G_OBJECT (account), "connection-status-reason");
940 g_object_notify (G_OBJECT (account), "connection-error");
941 g_object_notify (G_OBJECT (account), "connection-error-details");
942 }
943
944 if (presence_changed)
945 {
946 g_signal_emit (account, signals[PRESENCE_CHANGED], 0,
947 priv->cur_presence, priv->cur_status, priv->cur_message);
948 g_object_notify (G_OBJECT (account), "current-presence-type");
949 g_object_notify (G_OBJECT (account), "current-status");
950 g_object_notify (G_OBJECT (account), "current-status-message");
951 }
952
953 if (g_hash_table_lookup (properties, "Connection") != NULL)
954 {
955 const gchar *path = tp_asv_get_object_path (properties, "Connection");
956
957 _tp_account_set_connection (account, path);
958 }
959
960 if (g_hash_table_lookup (properties, "ChangingPresence") != NULL)
961 {
962 gboolean old = priv->changing_presence;
963
964 priv->changing_presence =
965 tp_asv_get_boolean (properties, "ChangingPresence", NULL);
966
967 if (old != priv->changing_presence)
968 g_object_notify (G_OBJECT (account), "changing-presence");
969 }
970
971 if (g_hash_table_lookup (properties, "ConnectAutomatically") != NULL)
972 {
973 gboolean old = priv->connect_automatically;
974
975 priv->connect_automatically =
976 tp_asv_get_boolean (properties, "ConnectAutomatically", NULL);
977
978 if (old != priv->connect_automatically)
979 g_object_notify (G_OBJECT (account), "connect-automatically");
980 }
981
982 if (g_hash_table_lookup (properties, "HasBeenOnline") != NULL)
983 {
984 gboolean old = priv->has_been_online;
985
986 priv->has_been_online =
987 tp_asv_get_boolean (properties, "HasBeenOnline", NULL);
988
989 if (old != priv->has_been_online)
990 g_object_notify (G_OBJECT (account), "has-been-online");
991 }
992
993 _tp_proxy_set_feature_prepared (proxy, TP_ACCOUNT_FEATURE_CORE, TRUE);
994 }
995
996 static void
_tp_account_properties_changed(TpAccount * proxy,GHashTable * properties,gpointer user_data,GObject * weak_object)997 _tp_account_properties_changed (TpAccount *proxy,
998 GHashTable *properties,
999 gpointer user_data,
1000 GObject *weak_object)
1001 {
1002 TpAccount *self = TP_ACCOUNT (weak_object);
1003
1004 if (!tp_proxy_is_prepared (self, TP_ACCOUNT_FEATURE_CORE))
1005 return;
1006
1007 _tp_account_update (self, properties);
1008 }
1009
1010 static void
avatar_changed_cb(TpAccount * self,gpointer user_data,GObject * weak_object)1011 avatar_changed_cb (TpAccount *self,
1012 gpointer user_data,
1013 GObject *weak_object)
1014 {
1015 g_signal_emit (self, signals[AVATAR_CHANGED], 0);
1016 }
1017
1018 static void
_tp_account_got_all_cb(TpProxy * proxy,GHashTable * properties,const GError * error,gpointer user_data,GObject * weak_object)1019 _tp_account_got_all_cb (TpProxy *proxy,
1020 GHashTable *properties,
1021 const GError *error,
1022 gpointer user_data,
1023 GObject *weak_object)
1024 {
1025 TpAccount *self = TP_ACCOUNT (weak_object);
1026
1027 DEBUG ("Got whole set of properties for %s",
1028 tp_proxy_get_object_path (self));
1029
1030 if (error != NULL)
1031 {
1032 DEBUG ("Failed to get the initial set of account properties: %s",
1033 error->message);
1034 tp_proxy_invalidate ((TpProxy *) self, error);
1035 return;
1036 }
1037
1038 _tp_account_update (self, properties);
1039
1040 /* We can't try connecting this signal earlier as tp_proxy_add_interfaces()
1041 * has to be called first if we support the Avatar interface. */
1042 tp_cli_account_interface_avatar_connect_to_avatar_changed (self,
1043 avatar_changed_cb, NULL, NULL, G_OBJECT (self), NULL);
1044 }
1045
1046 static void
addressing_props_changed(TpAccount * self,GHashTable * changed_properties)1047 addressing_props_changed (TpAccount *self,
1048 GHashTable *changed_properties)
1049 {
1050 const gchar * const * v;
1051
1052 if (self->priv->uri_schemes == NULL)
1053 /* We did not fetch the initial value yet, ignoring */
1054 return;
1055
1056 v = tp_asv_get_strv (changed_properties, "URISchemes");
1057 if (v == NULL)
1058 return;
1059
1060 g_strfreev (self->priv->uri_schemes);
1061 self->priv->uri_schemes = g_strdupv ((GStrv) v);
1062
1063 g_object_notify (G_OBJECT (self), "uri-schemes");
1064 }
1065
1066 static void
dbus_properties_changed_cb(TpProxy * proxy,const gchar * interface_name,GHashTable * changed_properties,const gchar ** invalidated_properties,gpointer user_data,GObject * weak_object)1067 dbus_properties_changed_cb (TpProxy *proxy,
1068 const gchar *interface_name,
1069 GHashTable *changed_properties,
1070 const gchar **invalidated_properties,
1071 gpointer user_data,
1072 GObject *weak_object)
1073 {
1074 TpAccount *self = TP_ACCOUNT (weak_object);
1075
1076 if (!tp_strdiff (interface_name, TP_IFACE_ACCOUNT_INTERFACE_ADDRESSING))
1077 {
1078 addressing_props_changed (self, changed_properties);
1079 }
1080 }
1081
1082 static void
_tp_account_constructed(GObject * object)1083 _tp_account_constructed (GObject *object)
1084 {
1085 TpAccount *self = TP_ACCOUNT (object);
1086 TpAccountPrivate *priv = self->priv;
1087 void (*chain_up) (GObject *) =
1088 ((GObjectClass *) tp_account_parent_class)->constructed;
1089 GError *error = NULL;
1090 TpProxySignalConnection *sc;
1091
1092 if (chain_up != NULL)
1093 chain_up (object);
1094
1095 g_return_if_fail (tp_proxy_get_dbus_daemon (self) != NULL);
1096
1097 _tp_proxy_ensure_factory (self, NULL);
1098
1099 sc = tp_cli_account_connect_to_removed (self, _tp_account_removed_cb,
1100 NULL, NULL, NULL, &error);
1101
1102 if (sc == NULL)
1103 {
1104 CRITICAL ("Couldn't connect to Removed: %s", error->message);
1105 g_error_free (error);
1106 }
1107
1108 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1109 tp_account_parse_object_path (tp_proxy_get_object_path (self),
1110 &(priv->cm_name), &(priv->proto_name), NULL, NULL);
1111 G_GNUC_END_IGNORE_DEPRECATIONS
1112
1113 priv->icon_name = g_strdup_printf ("im-%s", priv->proto_name);
1114 priv->service = g_strdup (priv->proto_name);
1115
1116 g_signal_connect (self, "invalidated",
1117 G_CALLBACK (_tp_account_invalidated_cb), NULL);
1118
1119 tp_cli_account_connect_to_account_property_changed (self,
1120 _tp_account_properties_changed, NULL, NULL, object, NULL);
1121
1122 tp_cli_dbus_properties_connect_to_properties_changed (self,
1123 dbus_properties_changed_cb, NULL, NULL, object, NULL);
1124
1125 tp_cli_dbus_properties_call_get_all (self, -1, TP_IFACE_ACCOUNT,
1126 _tp_account_got_all_cb, NULL, NULL, G_OBJECT (self));
1127 }
1128
1129 static void
_tp_account_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1130 _tp_account_get_property (GObject *object,
1131 guint prop_id,
1132 GValue *value,
1133 GParamSpec *pspec)
1134 {
1135 TpAccount *self = TP_ACCOUNT (object);
1136
1137 switch (prop_id)
1138 {
1139 case PROP_ENABLED:
1140 g_value_set_boolean (value, self->priv->enabled);
1141 break;
1142 case PROP_CURRENT_PRESENCE_TYPE:
1143 g_value_set_uint (value, self->priv->cur_presence);
1144 break;
1145 case PROP_CURRENT_STATUS:
1146 g_value_set_string (value, self->priv->cur_status);
1147 break;
1148 case PROP_CURRENT_STATUS_MESSAGE:
1149 g_value_set_string (value, self->priv->cur_message);
1150 break;
1151 case PROP_CONNECTION_STATUS:
1152 g_value_set_uint (value, self->priv->connection_status);
1153 break;
1154 case PROP_CONNECTION_STATUS_REASON:
1155 g_value_set_uint (value, self->priv->reason);
1156 break;
1157 case PROP_CONNECTION_ERROR:
1158 g_value_set_string (value, self->priv->error);
1159 break;
1160 case PROP_CONNECTION_ERROR_DETAILS:
1161 g_value_set_boxed (value, self->priv->error_details);
1162 break;
1163 case PROP_CONNECTION:
1164 g_value_set_object (value,
1165 tp_account_get_connection (self));
1166 break;
1167 case PROP_DISPLAY_NAME:
1168 g_value_set_string (value,
1169 tp_account_get_display_name (self));
1170 break;
1171 case PROP_CONNECTION_MANAGER:
1172 g_value_set_string (value, self->priv->cm_name);
1173 break;
1174 case PROP_CM_NAME:
1175 g_value_set_string (value, self->priv->cm_name);
1176 break;
1177 case PROP_PROTOCOL:
1178 g_value_set_string (value, self->priv->proto_name);
1179 break;
1180 case PROP_PROTOCOL_NAME:
1181 g_value_set_string (value, self->priv->proto_name);
1182 break;
1183 case PROP_ICON_NAME:
1184 g_value_set_string (value, self->priv->icon_name);
1185 break;
1186 case PROP_CHANGING_PRESENCE:
1187 g_value_set_boolean (value, self->priv->changing_presence);
1188 break;
1189 case PROP_CONNECT_AUTOMATICALLY:
1190 g_value_set_boolean (value, self->priv->connect_automatically);
1191 break;
1192 case PROP_HAS_BEEN_ONLINE:
1193 g_value_set_boolean (value, self->priv->has_been_online);
1194 break;
1195 case PROP_SERVICE:
1196 g_value_set_string (value, self->priv->service);
1197 break;
1198 case PROP_VALID:
1199 g_value_set_boolean (value, self->priv->valid);
1200 break;
1201 case PROP_REQUESTED_PRESENCE_TYPE:
1202 g_value_set_uint (value, self->priv->requested_presence);
1203 break;
1204 case PROP_REQUESTED_STATUS:
1205 g_value_set_string (value, self->priv->requested_status);
1206 break;
1207 case PROP_REQUESTED_STATUS_MESSAGE:
1208 g_value_set_string (value, self->priv->requested_message);
1209 break;
1210 case PROP_NICKNAME:
1211 g_value_set_string (value, self->priv->nickname);
1212 break;
1213 case PROP_SUPERSEDES:
1214 g_value_set_boxed (value, self->priv->supersedes);
1215 break;
1216 case PROP_URI_SCHEMES:
1217 g_value_set_boxed (value, self->priv->uri_schemes);
1218 break;
1219 case PROP_AUTOMATIC_PRESENCE_TYPE:
1220 g_value_set_uint (value, self->priv->auto_presence);
1221 break;
1222 case PROP_AUTOMATIC_STATUS:
1223 g_value_set_string (value, self->priv->auto_status);
1224 break;
1225 case PROP_AUTOMATIC_STATUS_MESSAGE:
1226 g_value_set_string (value, self->priv->auto_message);
1227 break;
1228 case PROP_NORMALIZED_NAME:
1229 g_value_set_string (value,
1230 tp_account_get_normalized_name (self));
1231 break;
1232 case PROP_STORAGE_PROVIDER:
1233 g_value_set_string (value, self->priv->storage_provider);
1234 break;
1235 case PROP_STORAGE_IDENTIFIER:
1236 g_value_set_boxed (value, self->priv->storage_identifier);
1237 break;
1238 case PROP_STORAGE_IDENTIFIER_VARIANT:
1239 g_value_take_variant (value,
1240 tp_account_dup_storage_identifier_variant (self));
1241 break;
1242 case PROP_STORAGE_RESTRICTIONS:
1243 g_value_set_uint (value, self->priv->storage_restrictions);
1244 break;
1245 default:
1246 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1247 break;
1248 }
1249 }
1250
1251 static void
_tp_account_dispose(GObject * object)1252 _tp_account_dispose (GObject *object)
1253 {
1254 TpAccount *self = TP_ACCOUNT (object);
1255 TpAccountPrivate *priv = self->priv;
1256
1257 if (priv->dispose_has_run)
1258 return;
1259
1260 priv->dispose_has_run = TRUE;
1261
1262 _tp_account_set_connection (self, "/");
1263
1264 /* release any references held by the object here */
1265 if (G_OBJECT_CLASS (tp_account_parent_class)->dispose != NULL)
1266 G_OBJECT_CLASS (tp_account_parent_class)->dispose (object);
1267 }
1268
1269 static void
_tp_account_finalize(GObject * object)1270 _tp_account_finalize (GObject *object)
1271 {
1272 TpAccount *self = TP_ACCOUNT (object);
1273 TpAccountPrivate *priv = self->priv;
1274
1275 g_free (priv->connection_object_path);
1276 g_free (priv->cur_status);
1277 g_free (priv->cur_message);
1278 g_free (priv->requested_status);
1279 g_free (priv->requested_message);
1280 g_free (priv->error);
1281 g_free (priv->auto_status);
1282 g_free (priv->auto_message);
1283 g_free (priv->normalized_name);
1284
1285 g_free (priv->nickname);
1286 g_strfreev (priv->supersedes);
1287
1288 g_free (priv->cm_name);
1289 g_free (priv->proto_name);
1290 g_free (priv->icon_name);
1291 g_free (priv->display_name);
1292 g_free (priv->service);
1293
1294 tp_clear_pointer (&priv->parameters, g_hash_table_unref);
1295 tp_clear_pointer (&priv->error_details, g_hash_table_unref);
1296
1297 g_free (priv->storage_provider);
1298 tp_clear_pointer (&priv->storage_identifier, tp_g_value_slice_free);
1299
1300 g_strfreev (priv->uri_schemes);
1301
1302 /* free any data held directly by the object here */
1303 if (G_OBJECT_CLASS (tp_account_parent_class)->finalize != NULL)
1304 G_OBJECT_CLASS (tp_account_parent_class)->finalize (object);
1305 }
1306
1307 static void
tp_account_class_init(TpAccountClass * klass)1308 tp_account_class_init (TpAccountClass *klass)
1309 {
1310 TpProxyClass *proxy_class = (TpProxyClass *) klass;
1311 GObjectClass *object_class = (GObjectClass *) klass;
1312
1313 g_type_class_add_private (klass, sizeof (TpAccountPrivate));
1314
1315 object_class->constructed = _tp_account_constructed;
1316 object_class->get_property = _tp_account_get_property;
1317 object_class->dispose = _tp_account_dispose;
1318 object_class->finalize = _tp_account_finalize;
1319
1320 /**
1321 * TpAccount:enabled:
1322 *
1323 * Whether this account is enabled or not.
1324 *
1325 * One can receive change notifications on this property by connecting
1326 * to the #GObject::notify signal and using this property as the signal
1327 * detail.
1328 *
1329 * This is not guaranteed to have been retrieved until
1330 * tp_proxy_prepare_async() has finished; until then, the value is FALSE.
1331 *
1332 * Since: 0.9.0
1333 */
1334 g_object_class_install_property (object_class, PROP_ENABLED,
1335 g_param_spec_boolean ("enabled",
1336 "Enabled",
1337 "Whether this account is enabled or not",
1338 FALSE,
1339 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1340
1341 /**
1342 * TpAccount:current-presence-type:
1343 *
1344 * The account connection's current presence type
1345 * (a %TpConnectionPresenceType).
1346 *
1347 * One can receive change notifications on this property by connecting
1348 * to the #GObject::notify signal and using this property as the signal
1349 * detail. Change notifications for current-presence-type,
1350 * current-status and current-status-message are always emitted together,
1351 * so it is sufficient to connect to one of the notification signals.
1352 *
1353 * This is not guaranteed to have been retrieved until
1354 * tp_proxy_prepare_async() has finished; until then, the value is
1355 * %TP_CONNECTION_PRESENCE_TYPE_UNSET.
1356 *
1357 * Since: 0.9.0
1358 */
1359 g_object_class_install_property (object_class, PROP_CURRENT_PRESENCE_TYPE,
1360 g_param_spec_uint ("current-presence-type",
1361 "Presence",
1362 "The account connection's current presence type",
1363 0,
1364 TP_NUM_CONNECTION_PRESENCE_TYPES,
1365 TP_CONNECTION_PRESENCE_TYPE_UNSET,
1366 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1367
1368 /**
1369 * TpAccount:current-status:
1370 *
1371 * The current Status string of the account.
1372 *
1373 * One can receive change notifications on this property by connecting
1374 * to the #GObject::notify signal and using this property as the signal
1375 * detail. Change notifications for current-presence-type,
1376 * current-status and current-status-message are always emitted together,
1377 * so it is sufficient to connect to one of the notification signals.
1378 *
1379 * This is not guaranteed to have been retrieved until
1380 * tp_proxy_prepare_async() has finished; until then, the value is
1381 * %NULL.
1382 *
1383 * Since: 0.9.0
1384 */
1385 g_object_class_install_property (object_class, PROP_CURRENT_STATUS,
1386 g_param_spec_string ("current-status",
1387 "Current Status",
1388 "The Status string of the account",
1389 NULL,
1390 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1391
1392 /**
1393 * TpAccount:current-status-message:
1394 *
1395 * The current status message message of the account.
1396 *
1397 * One can receive change notifications on this property by connecting
1398 * to the #GObject::notify signal and using this property as the signal
1399 * detail. Change notifications for current-presence-type,
1400 * current-status and current-status-message are always emitted together,
1401 * so it is sufficient to connect to one of the notification signals.
1402 *
1403 * This is not guaranteed to have been retrieved until
1404 * tp_proxy_prepare_async() has finished; until then, the value is
1405 * %NULL.
1406 *
1407 * Since: 0.9.0
1408 */
1409 g_object_class_install_property (object_class, PROP_CURRENT_STATUS_MESSAGE,
1410 g_param_spec_string ("current-status-message",
1411 "current-status-message",
1412 "The Status message string of the account",
1413 NULL,
1414 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1415
1416 /**
1417 * TpAccount:changing-presence:
1418 *
1419 * %TRUE if an attempt is currently being made to change the account's
1420 * presence (#TpAccount:current-presence-type, #TpAccount:current-status
1421 * and #TpAccount:current-status-message) to match its requested presence
1422 * (#TpAccount:requested-presence-type, #TpAccount:requested-status
1423 * and #TpAccount:requested-status-message).
1424 *
1425 * One can receive change notifications on this property by connecting
1426 * to the #GObject::notify signal and using this property as the signal
1427 * detail.
1428 *
1429 * This is not guaranteed to have been retrieved until
1430 * tp_proxy_prepare_async() has finished; until then, the value is
1431 * %FALSE.
1432 *
1433 * Since: 0.11.6
1434 */
1435 g_object_class_install_property (object_class, PROP_CHANGING_PRESENCE,
1436 g_param_spec_boolean ("changing-presence",
1437 "Changing Presence",
1438 "TRUE if presence is changing",
1439 FALSE,
1440 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1441
1442 /**
1443 * TpAccount:connection-status:
1444 *
1445 * The account's connection status type (a %TpConnectionStatus).
1446 *
1447 * One can receive change notifications on this property by connecting
1448 * to the #TpAccount::status-changed signal, or by connecting
1449 * to the #GObject::notify signal and using this property as the signal
1450 * detail.
1451 *
1452 * This is not guaranteed to have been retrieved until
1453 * tp_proxy_prepare_async() has finished; until then, the value is
1454 * %TP_CONNECTION_STATUS_DISCONNECTED.
1455 *
1456 * Since: 0.9.0
1457 */
1458 g_object_class_install_property (object_class, PROP_CONNECTION_STATUS,
1459 g_param_spec_uint ("connection-status",
1460 "ConnectionStatus",
1461 "The account's connection status type",
1462 0,
1463 TP_NUM_CONNECTION_STATUSES,
1464 TP_CONNECTION_STATUS_DISCONNECTED,
1465 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1466
1467 /**
1468 * TpAccount:connection-status-reason:
1469 *
1470 * The account's connection status reason (a %TpConnectionStatusReason).
1471 *
1472 * One can receive change notifications on this property by connecting
1473 * to the #TpAccount::status-changed signal, or by connecting
1474 * to the #GObject::notify signal and using this property as the signal
1475 * detail.
1476 *
1477 * This is not guaranteed to have been retrieved until
1478 * tp_proxy_prepare_async() has finished; until then, the value is
1479 * %TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED.
1480 *
1481 * Since: 0.9.0
1482 */
1483 g_object_class_install_property (object_class, PROP_CONNECTION_STATUS_REASON,
1484 g_param_spec_uint ("connection-status-reason",
1485 "ConnectionStatusReason",
1486 "The account's connection status reason",
1487 0,
1488 TP_NUM_CONNECTION_STATUS_REASONS,
1489 TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED,
1490 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1491
1492 /**
1493 * TpAccount:connection-error:
1494 *
1495 * The D-Bus error name for the last disconnection or connection failure,
1496 * (in particular, %TP_ERROR_STR_CANCELLED if it was disconnected by user
1497 * request), or %NULL if the account is connected.
1498 *
1499 * One can receive change notifications on this property by connecting
1500 * to the #TpAccount::status-changed signal, or by connecting
1501 * to the #GObject::notify signal and using this property as the signal
1502 * detail.
1503 *
1504 * This is not guaranteed to have been retrieved until
1505 * tp_proxy_prepare_async() has finished; until then, the value is
1506 * %NULL.
1507 *
1508 * Since: 0.11.7
1509 */
1510 g_object_class_install_property (object_class, PROP_CONNECTION_ERROR,
1511 g_param_spec_string ("connection-error",
1512 "ConnectionError",
1513 "The account's last connection error",
1514 NULL,
1515 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1516
1517 /**
1518 * TpAccount:connection-error-details:
1519 *
1520 * A map from string to #GValue containing extensible error details
1521 * related to #TpAccount:connection-error. Functions like tp_asv_get_string()
1522 * can be used to read from this map.
1523 *
1524 * The keys for this map are defined by
1525 * <ulink url="http://telepathy.freedesktop.org/spec/">the Telepathy D-Bus
1526 * Interface Specification</ulink>. They will typically include
1527 * <literal>debug-message</literal>, which is a debugging message in the C
1528 * locale, analogous to #GError<!-- -->.message.
1529 *
1530 * One can receive change notifications on this property by connecting
1531 * to the #TpAccount::status-changed signal, or by connecting
1532 * to the #GObject::notify signal and using this property as the signal
1533 * detail.
1534 *
1535 * This is not guaranteed to have been retrieved until
1536 * tp_proxy_prepare_async() has finished; until then, the value is
1537 * an empty map.
1538 *
1539 * Since: 0.11.7
1540 */
1541 g_object_class_install_property (object_class, PROP_CONNECTION_ERROR_DETAILS,
1542 g_param_spec_boxed ("connection-error-details",
1543 "ConnectionErrorDetails",
1544 "Extensible details of the account's last connection error",
1545 G_TYPE_HASH_TABLE,
1546 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1547
1548 /**
1549 * TpAccount:connection:
1550 *
1551 * The connection of the account, or %NULL if account is offline.
1552 * Note that the returned #TpConnection is not guaranteed to have any
1553 * features pre-prepared (not even %TP_CONNECTION_FEATURE_CORE) unless
1554 * %TP_ACCOUNT_FEATURE_CONNECTION has been prepared on the account
1555 *
1556 * One can receive change notifications on this property by connecting
1557 * to the #GObject::notify signal and using this property as the signal
1558 * detail. If %TP_ACCOUNT_FEATURE_CONNECTION has been prepared, this signal
1559 * will be delayed until the connection is ready.
1560 *
1561 * This is not guaranteed to have been retrieved until
1562 * tp_proxy_prepare_async() has finished; until then, the value is
1563 * %NULL.
1564 *
1565 * Since: 0.9.0
1566 */
1567 g_object_class_install_property (object_class, PROP_CONNECTION,
1568 g_param_spec_object ("connection",
1569 "Connection",
1570 "The account's connection",
1571 TP_TYPE_CONNECTION,
1572 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1573
1574 /**
1575 * TpAccount:display-name:
1576 *
1577 * The account's display name, from the DisplayName property.
1578 *
1579 * One can receive change notifications on this property by connecting
1580 * to the #GObject::notify signal and using this property as the signal
1581 * detail.
1582 *
1583 * This is not guaranteed to have been retrieved until
1584 * tp_proxy_prepare_async() has finished; until then, the value is
1585 * %NULL.
1586 *
1587 * Since: 0.9.0
1588 */
1589 g_object_class_install_property (object_class, PROP_DISPLAY_NAME,
1590 g_param_spec_string ("display-name",
1591 "DisplayName",
1592 "The account's display name",
1593 NULL,
1594 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1595
1596 /**
1597 * TpAccount:connection-manager:
1598 *
1599 * The account's connection manager name.
1600 *
1601 * Since: 0.9.0
1602 * Deprecated: Use #TpAccount:cm-name instead.
1603 */
1604 g_object_class_install_property (object_class, PROP_CONNECTION_MANAGER,
1605 g_param_spec_string ("connection-manager",
1606 "Connection manager",
1607 "The account's connection manager name",
1608 NULL,
1609 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1610
1611 /**
1612 * TpAccount:protocol:
1613 *
1614 * The account's machine-readable protocol name, such as "jabber", "msn" or
1615 * "local-xmpp". Recommended names for most protocols can be found in the
1616 * Telepathy D-Bus Interface Specification.
1617 *
1618 * Since: 0.9.0
1619 * Deprecated: Use #TpAccount:protocol-name instead.
1620 */
1621 g_object_class_install_property (object_class, PROP_PROTOCOL,
1622 g_param_spec_string ("protocol",
1623 "Protocol",
1624 "The account's protocol name",
1625 NULL,
1626 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1627
1628 /**
1629 * TpAccount:cm-name:
1630 *
1631 * The account's connection manager name.
1632 *
1633 * Since: 0.19.3
1634 */
1635 g_object_class_install_property (object_class, PROP_CM_NAME,
1636 g_param_spec_string ("cm-name",
1637 "Connection manager",
1638 "The account's connection manager name",
1639 NULL,
1640 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1641
1642 /**
1643 * TpAccount:protocol-name:
1644 *
1645 * The account's machine-readable protocol name, such as "jabber", "msn" or
1646 * "local-xmpp". Recommended names for most protocols can be found in the
1647 * Telepathy D-Bus Interface Specification.
1648 *
1649 * Since: 0.19.3
1650 */
1651 g_object_class_install_property (object_class, PROP_PROTOCOL_NAME,
1652 g_param_spec_string ("protocol-name",
1653 "Protocol",
1654 "The account's protocol name",
1655 NULL,
1656 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1657
1658 /**
1659 * TpAccount:service:
1660 *
1661 * A machine-readable name identifying a specific service to which this
1662 * account connects, or a copy of #TpAccount:protocol if there is no more
1663 * specific service.
1664 *
1665 * Well-known names for various services can be found in the Telepathy D-Bus
1666 * Interface Specification.
1667 *
1668 * For instance, accounts for the "jabber" protocol should have the service
1669 * names "google-talk", "ovi-chat", "facebook" and "lj-talk" for accounts
1670 * that connect to Google Talk, Ovi Chat, Facebook and Livejournal,
1671 * respectively, and this property will be "jabber" for accounts that
1672 * connect to a generic Jabber server.
1673 *
1674 * To change this property, use
1675 * tp_account_set_service_async().
1676 *
1677 * Since: 0.11.9
1678 */
1679 g_object_class_install_property (object_class, PROP_SERVICE,
1680 g_param_spec_string ("service",
1681 "Service",
1682 "The account's service name",
1683 NULL,
1684 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1685
1686 /**
1687 * TpAccount:icon-name:
1688 *
1689 * The account's icon name. To change this propery, use
1690 * tp_account_set_icon_name_async().
1691 *
1692 * One can receive change notifications on this property by connecting
1693 * to the #GObject::notify signal and using this property as the signal
1694 * detail.
1695 *
1696 * This is not guaranteed to have been retrieved until
1697 * tp_proxy_prepare_async() has finished; until then, the value is
1698 * %NULL.
1699 *
1700 * Since: 0.9.0
1701 */
1702 g_object_class_install_property (object_class, PROP_ICON_NAME,
1703 g_param_spec_string ("icon-name",
1704 "Icon",
1705 "The account's icon name",
1706 NULL,
1707 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1708
1709 /**
1710 * TpAccount:connect-automatically:
1711 *
1712 * Whether the account should connect automatically or not. To change this
1713 * property, use tp_account_set_connect_automatically_async().
1714 *
1715 * One can receive change notifications on this property by connecting
1716 * to the #GObject::notify signal and using this property as the signal
1717 * detail.
1718 *
1719 * This is not guaranteed to have been retrieved until
1720 * tp_proxy_prepare_async() has finished; until then, the value is
1721 * %FALSE.
1722 *
1723 * Since: 0.9.0
1724 */
1725 g_object_class_install_property (object_class, PROP_CONNECT_AUTOMATICALLY,
1726 g_param_spec_boolean ("connect-automatically",
1727 "ConnectAutomatically",
1728 "Whether this account should connect automatically or not",
1729 FALSE,
1730 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1731
1732 /**
1733 * TpAccount:has-been-online:
1734 *
1735 * Whether this account has been online or not.
1736 *
1737 * One can receive change notifications on this property by connecting
1738 * to the #GObject::notify signal and using this property as the signal
1739 * detail.
1740 *
1741 * This is not guaranteed to have been retrieved until
1742 * tp_proxy_prepare_async() has finished; until then, the value is
1743 * %FALSE.
1744 *
1745 * Since: 0.9.0
1746 */
1747 g_object_class_install_property (object_class, PROP_HAS_BEEN_ONLINE,
1748 g_param_spec_boolean ("has-been-online",
1749 "HasBeenOnline",
1750 "Whether this account has been online or not",
1751 FALSE,
1752 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1753
1754 /**
1755 * TpAccount:valid:
1756 *
1757 * Whether this account is valid.
1758 *
1759 * One can receive change notifications on this property by connecting
1760 * to the #GObject::notify signal and using this property as the signal
1761 * detail.
1762 *
1763 * This is not guaranteed to have been retrieved until
1764 * tp_proxy_prepare_async() has finished; until then, the value is
1765 * %FALSE.
1766 *
1767 * Since: 0.9.0
1768 */
1769 g_object_class_install_property (object_class, PROP_VALID,
1770 g_param_spec_boolean ("valid",
1771 "Valid",
1772 "Whether this account is valid",
1773 FALSE,
1774 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1775
1776 /**
1777 * TpAccount:requested-presence-type:
1778 *
1779 * The account's requested presence type (a #TpConnectionPresenceType).
1780 *
1781 * Since 0.13.8,
1782 * one can receive change notifications on this property by connecting
1783 * to the #GObject::notify signal and using this property as the signal
1784 * detail. Change notifications for requested-presence-type,
1785 * requested-status and requested-status-message are always emitted together,
1786 * so it is sufficient to connect to one of the notification signals.
1787 *
1788 * This is not guaranteed to have been retrieved until
1789 * tp_proxy_prepare_async() has finished; until then, the value is
1790 * %NULL.
1791 *
1792 * Since: 0.9.0
1793 */
1794 g_object_class_install_property (object_class, PROP_REQUESTED_PRESENCE_TYPE,
1795 g_param_spec_uint ("requested-presence-type",
1796 "RequestedPresence",
1797 "The account's requested presence type",
1798 0,
1799 TP_NUM_CONNECTION_PRESENCE_TYPES,
1800 TP_CONNECTION_PRESENCE_TYPE_UNSET,
1801 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1802
1803 /**
1804 * TpAccount:requested-status:
1805 *
1806 * The requested Status string of the account.
1807 *
1808 * Since 0.13.8,
1809 * one can receive change notifications on this property by connecting
1810 * to the #GObject::notify signal and using this property as the signal
1811 * detail. Change notifications for requested-presence-type,
1812 * requested-status and requested-status-message are always emitted together,
1813 * so it is sufficient to connect to one of the notification signals.
1814 *
1815 * This is not guaranteed to have been retrieved until
1816 * tp_proxy_prepare_async() has finished; until then, the value is
1817 * %NULL.
1818 *
1819 * Since: 0.9.0
1820 */
1821 g_object_class_install_property (object_class, PROP_REQUESTED_STATUS,
1822 g_param_spec_string ("requested-status",
1823 "RequestedStatus",
1824 "The account's requested status string",
1825 NULL,
1826 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1827
1828 /**
1829 * TpAccount:requested-status-message:
1830 *
1831 * The requested status message message of the account.
1832 *
1833 * Since 0.13.8,
1834 * one can receive change notifications on this property by connecting
1835 * to the #GObject::notify signal and using this property as the signal
1836 * detail. Change notifications for requested-presence-type,
1837 * requested-status and requested-status-message are always emitted together,
1838 * so it is sufficient to connect to one of the notification signals.
1839 *
1840 * This is not guaranteed to have been retrieved until
1841 * tp_proxy_prepare_async() has finished; until then, the value is
1842 * %NULL.
1843 *
1844 * Since: 0.9.0
1845 */
1846 g_object_class_install_property (object_class, PROP_REQUESTED_STATUS_MESSAGE,
1847 g_param_spec_string ("requested-status-message",
1848 "RequestedStatusMessage",
1849 "The requested Status message string of the account",
1850 NULL,
1851 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1852
1853 /**
1854 * TpAccount:nickname:
1855 *
1856 * The nickname that should be set for the user on this account.
1857 *
1858 * One can receive change notifications on this property by connecting
1859 * to the #GObject::notify signal and using this property as the signal
1860 * detail.
1861 *
1862 * This is not guaranteed to have been retrieved until
1863 * tp_proxy_prepare_async() has finished; until then, the value is
1864 * %NULL.
1865 *
1866 * Since: 0.9.0
1867 */
1868 g_object_class_install_property (object_class, PROP_NICKNAME,
1869 g_param_spec_string ("nickname",
1870 "Nickname",
1871 "The account's nickname",
1872 NULL,
1873 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1874
1875 /**
1876 * TpAccount:automatic-presence-type:
1877 *
1878 * The account's automatic presence type (a #TpConnectionPresenceType).
1879 *
1880 * When the account is put online automatically, for instance to make a
1881 * channel request or because network connectivity becomes available,
1882 * the automatic presence type, status and message will be copied to
1883 * their "requested" counterparts.
1884 *
1885 * One can receive change notifications on this property by connecting
1886 * to the #GObject::notify signal and using this property as the signal
1887 * detail. Change notifications for automatic-presence-type,
1888 * automatic-status and automatic-status-message are always emitted together,
1889 * so it is sufficient to connect to one of the notification signals.
1890 *
1891 * This is not guaranteed to have been retrieved until
1892 * tp_proxy_prepare_async() has finished; until then, the value is
1893 * %TP_CONNECTION_PRESENCE_TYPE_UNSET.
1894 *
1895 * Since: 0.13.8
1896 */
1897 g_object_class_install_property (object_class, PROP_AUTOMATIC_PRESENCE_TYPE,
1898 g_param_spec_uint ("automatic-presence-type",
1899 "AutomaticPresence type",
1900 "Presence type used to put the account online automatically",
1901 0,
1902 TP_NUM_CONNECTION_PRESENCE_TYPES,
1903 TP_CONNECTION_PRESENCE_TYPE_UNSET,
1904 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1905
1906 /**
1907 * TpAccount:automatic-status:
1908 *
1909 * The string status name to use in conjunction with the
1910 * #TpAccount:automatic-presence-type.
1911 *
1912 * One can receive change notifications on this property by connecting
1913 * to the #GObject::notify signal and using this property as the signal
1914 * detail. Change notifications for automatic-presence-type,
1915 * automatic-status and automatic-status-message are always emitted together,
1916 * so it is sufficient to connect to one of the notification signals.
1917 *
1918 * This is not guaranteed to have been retrieved until
1919 * tp_proxy_prepare_async() has finished; until then, the value is
1920 * %NULL.
1921 *
1922 * Since: 0.13.8
1923 */
1924 g_object_class_install_property (object_class, PROP_AUTOMATIC_STATUS,
1925 g_param_spec_string ("automatic-status",
1926 "AutomaticPresence status",
1927 "Presence status used to put the account online automatically",
1928 NULL,
1929 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1930
1931 /**
1932 * TpAccount:automatic-status-message:
1933 *
1934 * The user-defined message to use in conjunction with the
1935 * #TpAccount:automatic-presence-type.
1936 *
1937 * One can receive change notifications on this property by connecting
1938 * to the #GObject::notify signal and using this property as the signal
1939 * detail. Change notifications for automatic-presence-type,
1940 * automatic-status and automatic-status-message are always emitted together,
1941 * so it is sufficient to connect to one of the notification signals.
1942 *
1943 * This is not guaranteed to have been retrieved until
1944 * tp_proxy_prepare_async() has finished; until then, the value is
1945 * %NULL.
1946 *
1947 * Since: 0.13.8
1948 */
1949 g_object_class_install_property (object_class, PROP_AUTOMATIC_STATUS_MESSAGE,
1950 g_param_spec_string ("automatic-status-message",
1951 "AutomaticPresence message",
1952 "User-defined message used to put the account online automatically",
1953 NULL,
1954 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1955
1956 /**
1957 * TpAccount:normalized-name:
1958 *
1959 * The normalized form of the user's own unique identifier on this
1960 * protocol. For example, on XMPP accounts this is the user's JID; on
1961 * ICQ this is the user's UIN; and so on.
1962 *
1963 * One can receive change notifications on this property by connecting
1964 * to the #GObject::notify signal and using this property as the signal
1965 * detail.
1966 *
1967 * This is not guaranteed to have been retrieved until
1968 * tp_proxy_prepare_async() has finished; until then, the value is
1969 * %NULL.
1970 *
1971 * Since: 0.13.8
1972 */
1973 g_object_class_install_property (object_class, PROP_NORMALIZED_NAME,
1974 g_param_spec_string ("normalized-name",
1975 "NormalizedName",
1976 "The normalized identifier of the user",
1977 NULL,
1978 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
1979
1980 /**
1981 * TpAccount:storage-provider:
1982 *
1983 * The storage provider for this account.
1984 *
1985 * The name of the account storage implementation. When this
1986 * is the empty string the account is internally stored.
1987 *
1988 * This property cannot change once an Account has been created.
1989 *
1990 * This is not guaranteed to have been retrieved until the
1991 * %TP_ACCOUNT_FEATURE_STORAGE feature has been prepared; until then,
1992 * the value is %NULL.
1993 *
1994 * Since: 0.13.2
1995 */
1996 g_object_class_install_property (object_class, PROP_STORAGE_PROVIDER,
1997 g_param_spec_string ("storage-provider",
1998 "StorageProvider",
1999 "The storage provider for this account",
2000 NULL,
2001 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
2002
2003 /**
2004 * TpAccount:storage-identifier:
2005 *
2006 * The storage identifier for this account.
2007 *
2008 * A provider-specific variant type used to identify this account with the
2009 * provider. This value will be %NULL if #TpAccount:storage-provider is
2010 * an empty string.
2011 *
2012 * This property cannot change once an Account has been created.
2013 *
2014 * This is not guaranteed to have been retrieved until the
2015 * %TP_ACCOUNT_FEATURE_STORAGE feature has been prepared; until then,
2016 * the value is %NULL.
2017 *
2018 * Since: 0.13.2
2019 */
2020 g_object_class_install_property (object_class, PROP_STORAGE_IDENTIFIER,
2021 g_param_spec_boxed ("storage-identifier",
2022 "StorageIdentifier",
2023 "The storage identifier for this account",
2024 G_TYPE_VALUE,
2025 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
2026
2027 /**
2028 * TpAccount:storage-identifier-variant:
2029 *
2030 * Provider-specific information used to identify this
2031 * account. Use g_variant_get_type() to check that the type
2032 * is what you expect. For instance, if you use a
2033 * #TpAccount:storage-provider with numeric identifiers for accounts,
2034 * this variant might have type %G_VARIANT_TYPE_UINT32;
2035 * if the storage provider has string-based identifiers, it should
2036 * have type %G_VARIANT_TYPE_STRING.
2037 *
2038 * This property cannot change once an Account has been created.
2039 *
2040 * This is not guaranteed to have been retrieved until the
2041 * %TP_ACCOUNT_FEATURE_STORAGE feature has been prepared; until then,
2042 * the value is %NULL.
2043 *
2044 * Since: 0.13.2
2045 */
2046 g_object_class_install_property (object_class,
2047 PROP_STORAGE_IDENTIFIER_VARIANT,
2048 g_param_spec_variant ("storage-identifier-variant",
2049 "StorageIdentifier as variant",
2050 "The storage identifier for this account",
2051 G_VARIANT_TYPE_ANY,
2052 NULL,
2053 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
2054
2055 /**
2056 * TpAccount:storage-restrictions:
2057 *
2058 * The storage restrictions for this account.
2059 *
2060 * A bitfield of #TpStorageRestrictionFlags that give the limitations of
2061 * this account imposed by the storage provider. This value will be 0
2062 * if #TpAccount:storage-provider is an empty string.
2063 *
2064 * This property cannot change once an Account has been created.
2065 *
2066 * This is not guaranteed to have been retrieved until the
2067 * %TP_ACCOUNT_FEATURE_STORAGE feature has been prepared; until then,
2068 * the value is 0.
2069 *
2070 * Since: 0.13.2
2071 */
2072 g_object_class_install_property (object_class, PROP_STORAGE_RESTRICTIONS,
2073 g_param_spec_uint ("storage-restrictions",
2074 "StorageRestrictions",
2075 "The storage restrictions for this account",
2076 0, G_MAXUINT, 0,
2077 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
2078
2079 /**
2080 * TpAccount:supersedes:
2081 *
2082 * The object paths of previously-active accounts superseded by this one.
2083 * For instance, this can be used in a logger to read old logs for an
2084 * account that has been migrated from one connection manager to another.
2085 *
2086 * This is not guaranteed to have been retrieved until the
2087 * %TP_ACCOUNT_FEATURE_CORE feature has been prepared; until then,
2088 * the value is NULL.
2089 *
2090 * Since: 0.17.5
2091 */
2092 g_object_class_install_property (object_class, PROP_SUPERSEDES,
2093 g_param_spec_boxed ("supersedes",
2094 "Supersedes",
2095 "Accounts superseded by this one",
2096 G_TYPE_STRV,
2097 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
2098
2099 /**
2100 * TpAccount:uri-schemes:
2101 *
2102 * If the %TP_ACCOUNT_FEATURE_ADDRESSING feature has been prepared
2103 * successfully, a list of additional URI schemes for which this
2104 * account should be used if possible. Otherwise %NULL.
2105 *
2106 * For instance, a SIP or Skype account might have "tel" in this list if the
2107 * user would like to use that account to call phone numbers.
2108 *
2109 * This list should not contain the primary URI scheme(s) for the account's
2110 * protocol (for instance, "xmpp" for XMPP, or "sip" or "sips" for SIP),
2111 * since it should be assumed to be useful for those schemes in any case.
2112 *
2113 * The notify::uri-schemes signal cannot be relied on if the Account Manager
2114 * is Mission Control version 5.14.0 or older.
2115 *
2116 * Since: 0.21.0
2117 */
2118 g_object_class_install_property (object_class, PROP_URI_SCHEMES,
2119 g_param_spec_boxed ("uri-schemes",
2120 "URISchemes",
2121 "URISchemes",
2122 G_TYPE_STRV,
2123 G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
2124
2125 /**
2126 * TpAccount::status-changed:
2127 * @account: the #TpAccount
2128 * @old_status: old #TpAccount:connection-status
2129 * @new_status: new #TpAccount:connection-status
2130 * @reason: the #TpAccount:connection-status-reason
2131 * @dbus_error_name: (allow-none): the #TpAccount:connection-error
2132 * @details: (element-type utf8 GObject.Value): the
2133 * #TpAccount:connection-error-details
2134 *
2135 * Emitted when the connection status on the account changes.
2136 *
2137 * The @dbus_error_name and @details parameters were present, but
2138 * non-functional (always %NULL), in older versions. They have been
2139 * available with their current behaviour since version 0.11.7.
2140 *
2141 * Since: 0.9.0
2142 */
2143 signals[STATUS_CHANGED] = g_signal_new ("status-changed",
2144 G_TYPE_FROM_CLASS (object_class),
2145 G_SIGNAL_RUN_LAST,
2146 0, NULL, NULL, NULL,
2147 G_TYPE_NONE, 5, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING,
2148 G_TYPE_HASH_TABLE);
2149
2150 /**
2151 * TpAccount::presence-changed:
2152 * @account: the #TpAccount
2153 * @presence: the new presence
2154 * @status: the new presence status
2155 * @status_message: the new presence status message
2156 *
2157 * Emitted when the presence of the account changes.
2158 *
2159 * Since: 0.9.0
2160 */
2161 signals[PRESENCE_CHANGED] = g_signal_new ("presence-changed",
2162 G_TYPE_FROM_CLASS (object_class),
2163 G_SIGNAL_RUN_LAST,
2164 0, NULL, NULL, NULL,
2165 G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING);
2166
2167 /**
2168 * TpAccount::avatar-changed:
2169 * @self: a #TpAccount
2170 *
2171 * Emitted when the avatar changes. Call tp_account_get_avatar_async()
2172 * to get the new avatar data.
2173 *
2174 * Since: 0.23.0
2175 */
2176 signals[AVATAR_CHANGED] = g_signal_new ("avatar-changed",
2177 G_OBJECT_CLASS_TYPE (klass),
2178 G_SIGNAL_RUN_LAST,
2179 0, NULL, NULL, NULL,
2180 G_TYPE_NONE,
2181 0);
2182
2183 proxy_class->interface = TP_IFACE_QUARK_ACCOUNT;
2184 proxy_class->list_features = _tp_account_list_features;
2185 tp_account_init_known_interfaces ();
2186 }
2187
2188 /**
2189 * tp_account_init_known_interfaces:
2190 *
2191 * Ensure that the known interfaces for TpAccount have been set up.
2192 * This is done automatically when necessary, but for correct
2193 * overriding of library interfaces by local extensions, you should
2194 * call this function before calling
2195 * tp_proxy_or_subclass_hook_on_interface_add() with first argument
2196 * %TP_TYPE_ACCOUNT.
2197 *
2198 * Since: 0.7.32
2199 */
2200 void
tp_account_init_known_interfaces(void)2201 tp_account_init_known_interfaces (void)
2202 {
2203 static gsize once = 0;
2204
2205 if (g_once_init_enter (&once))
2206 {
2207 GType tp_type = TP_TYPE_ACCOUNT;
2208
2209 tp_proxy_init_known_interfaces ();
2210 tp_proxy_or_subclass_hook_on_interface_add (tp_type,
2211 tp_cli_account_add_signals);
2212 tp_proxy_subclass_add_error_mapping (tp_type,
2213 TP_ERROR_PREFIX, TP_ERROR, TP_TYPE_ERROR);
2214
2215 g_once_init_leave (&once, 1);
2216 }
2217 }
2218
2219 /**
2220 * tp_account_new:
2221 * @bus_daemon: Proxy for the D-Bus daemon
2222 * @object_path: The non-NULL object path of this account
2223 * @error: Used to raise an error if @object_path is not valid
2224 *
2225 * Convenience function to create a new account proxy. The returned #TpAccount
2226 * is not guaranteed to be ready at the point of return.
2227 *
2228 * Returns: a new reference to an account proxy, or %NULL if @object_path is
2229 * not valid
2230 * Deprecated: Use tp_simple_client_factory_ensure_account() instead.
2231 */
2232 TpAccount *
tp_account_new(TpDBusDaemon * bus_daemon,const gchar * object_path,GError ** error)2233 tp_account_new (TpDBusDaemon *bus_daemon,
2234 const gchar *object_path,
2235 GError **error)
2236 {
2237 return _tp_account_new_with_factory (NULL, bus_daemon, object_path, error);
2238 }
2239
2240 TpAccount *
_tp_account_new_with_factory(TpSimpleClientFactory * factory,TpDBusDaemon * bus_daemon,const gchar * object_path,GError ** error)2241 _tp_account_new_with_factory (TpSimpleClientFactory *factory,
2242 TpDBusDaemon *bus_daemon,
2243 const gchar *object_path,
2244 GError **error)
2245 {
2246 TpAccount *self;
2247
2248 g_return_val_if_fail (TP_IS_DBUS_DAEMON (bus_daemon), NULL);
2249 g_return_val_if_fail (object_path != NULL, NULL);
2250 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2251
2252 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2253 if (!tp_account_parse_object_path (object_path, NULL, NULL, NULL, error))
2254 return NULL;
2255 G_GNUC_END_IGNORE_DEPRECATIONS
2256
2257 self = TP_ACCOUNT (g_object_new (TP_TYPE_ACCOUNT,
2258 "dbus-daemon", bus_daemon,
2259 "dbus-connection", ((TpProxy *) bus_daemon)->dbus_connection,
2260 "bus-name", TP_ACCOUNT_MANAGER_BUS_NAME,
2261 "object-path", object_path,
2262 "factory", factory,
2263 NULL));
2264
2265 return self;
2266 }
2267
2268 static gchar *
unescape_protocol(gchar * protocol)2269 unescape_protocol (gchar *protocol)
2270 {
2271 if (strstr (protocol, "_2d") != NULL)
2272 {
2273 /* Work around MC5 bug where it escapes with tp_escape_as_identifier
2274 * rather than doing it properly. MC5 saves the object path in your
2275 * config, so if you've ever used a buggy MC5, the path will be wrong
2276 * forever.
2277 */
2278 gchar **chunks = g_strsplit (protocol, "_2d", 0);
2279 gchar *new = g_strjoinv ("-", chunks);
2280
2281 g_strfreev (chunks);
2282 g_free (protocol);
2283 protocol = new;
2284 }
2285
2286 g_strdelimit (protocol, "_", '-');
2287
2288 return protocol;
2289 }
2290
2291 /**
2292 * tp_account_get_connection:
2293 * @account: a #TpAccount
2294 *
2295 * <!-- -->
2296 *
2297 * Returns: (transfer none): the same as the #TpAccount:connection property
2298 *
2299 * Since: 0.9.0
2300 **/
2301 TpConnection *
tp_account_get_connection(TpAccount * account)2302 tp_account_get_connection (TpAccount *account)
2303 {
2304 TpAccountPrivate *priv;
2305
2306 g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
2307
2308 priv = account->priv;
2309
2310 /* If we want to expose only prepared connection */
2311 if (connection_is_internal (account))
2312 return NULL;
2313
2314 return priv->connection;
2315 }
2316
2317 /**
2318 * tp_account_ensure_connection:
2319 * @account: a #TpAccount
2320 * @path: the path to connection object for #TpAccount
2321 *
2322 * Set the connection of the account by specifying the connection object path.
2323 * This function does not return a new ref and it is not guaranteed that the
2324 * returned #TpConnection object is ready.
2325 *
2326 * The use-case for this function is in a HandleChannels callback and you
2327 * already know the object path for the connection, so you can let @account
2328 * create its #TpConnection and return it for use.
2329 *
2330 * Returns: (transfer none): the connection of the account, or %NULL if either
2331 * the object path @path is invalid or it is the null-value "/"
2332 *
2333 * Since: 0.9.0
2334 * Deprecated: New code should use tp_simple_client_factory_ensure_connection()
2335 * instead.
2336 **/
2337 TpConnection *
tp_account_ensure_connection(TpAccount * account,const gchar * path)2338 tp_account_ensure_connection (TpAccount *account,
2339 const gchar *path)
2340 {
2341 TpAccountPrivate *priv;
2342
2343 g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
2344
2345 priv = account->priv;
2346
2347 /* double-check that the object path is valid */
2348 if (!tp_dbus_check_valid_object_path (path, NULL))
2349 return NULL;
2350
2351 /* Should be a full object path, not the special "/" value */
2352 if (!tp_strdiff (path, "/"))
2353 return NULL;
2354
2355 _tp_account_set_connection (account, path);
2356
2357 return priv->connection;
2358 }
2359
2360 /**
2361 * tp_account_get_path_suffix:
2362 * @account: a #TpAccount
2363 *
2364 * Returns the portion of @account's object path after the standard
2365 * #TP_ACCOUNT_OBJECT_PATH_BASE prefix, of the form "cm/protocol/acct". This
2366 * string uniquely identifies the account.
2367 *
2368 * This function is only intended to be used when printing debug messages or in
2369 * tools for developer. For a string suitable for displaying to the user, see
2370 * tp_account_get_display_name(). To retrieve the connection manager and
2371 * protocol name parts of the object path, see
2372 * tp_account_get_connection_manager() and tp_account_get_protocol(). For
2373 * persistent identification of the account, use tp_proxy_get_object_path().
2374 *
2375 * Returns: a suffix of @account's object path, for debugging purposes.
2376 * Since: 0.13.9
2377 */
2378 const gchar *
tp_account_get_path_suffix(TpAccount * account)2379 tp_account_get_path_suffix (TpAccount *account)
2380 {
2381 const gchar *path;
2382
2383 g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
2384
2385 path = tp_proxy_get_object_path (account);
2386 g_return_val_if_fail (g_str_has_prefix (path, TP_ACCOUNT_OBJECT_PATH_BASE),
2387 path);
2388
2389 return path + strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
2390 }
2391
2392 /**
2393 * tp_account_get_display_name:
2394 * @account: a #TpAccount
2395 *
2396 * <!-- -->
2397 *
2398 * Returns: the same as the #TpAccount:display-name property
2399 *
2400 * Since: 0.9.0
2401 **/
2402 const gchar *
tp_account_get_display_name(TpAccount * account)2403 tp_account_get_display_name (TpAccount *account)
2404 {
2405 g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
2406
2407 return account->priv->display_name;
2408 }
2409
2410 /**
2411 * tp_account_is_valid:
2412 * @account: a #TpAccount
2413 *
2414 * <!-- -->
2415 *
2416 * Returns: the same as the #TpAccount:valid property
2417 *
2418 * Since: 0.9.0
2419 */
2420 gboolean
tp_account_is_valid(TpAccount * account)2421 tp_account_is_valid (TpAccount *account)
2422 {
2423 g_return_val_if_fail (TP_IS_ACCOUNT (account), FALSE);
2424
2425 return account->priv->valid;
2426 }
2427
2428 /**
2429 * tp_account_get_connection_manager:
2430 * @account: a #TpAccount
2431 *
2432 * <!-- -->
2433 *
2434 * Returns: the same as the #TpAccount:connection-manager property
2435 *
2436 * Since: 0.9.0
2437 * Deprecated: Use tp_account_get_cm_name() instead.
2438 */
2439 const gchar *
tp_account_get_connection_manager(TpAccount * account)2440 tp_account_get_connection_manager (TpAccount *account)
2441 {
2442 g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
2443
2444 return account->priv->cm_name;
2445 }
2446
2447 /**
2448 * tp_account_get_protocol:
2449 * @account: a #TpAccount
2450 *
2451 * <!-- -->
2452 *
2453 * Returns: the same as the #TpAccount:protocol property
2454 *
2455 * Since: 0.9.0
2456 * Deprecated: Use tp_account_get_cm_name() instead.
2457 */
2458 const gchar *
tp_account_get_protocol(TpAccount * account)2459 tp_account_get_protocol (TpAccount *account)
2460 {
2461 g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
2462
2463 return account->priv->proto_name;
2464 }
2465
2466 /**
2467 * tp_account_get_cm_name:
2468 * @account: a #TpAccount
2469 *
2470 * <!-- -->
2471 *
2472 * Returns: the same as the #TpAccount:cm-name property
2473 *
2474 * Since: 0.19.3
2475 */
2476 const gchar *
tp_account_get_cm_name(TpAccount * account)2477 tp_account_get_cm_name (TpAccount *account)
2478 {
2479 g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
2480
2481 return account->priv->cm_name;
2482 }
2483
2484 /**
2485 * tp_account_get_protocol_name:
2486 * @account: a #TpAccount
2487 *
2488 * <!-- -->
2489 *
2490 * Returns: the same as the #TpAccount:protocol-name property
2491 *
2492 * Since: 0.19.3
2493 */
2494 const gchar *
tp_account_get_protocol_name(TpAccount * account)2495 tp_account_get_protocol_name (TpAccount *account)
2496 {
2497 g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
2498
2499 return account->priv->proto_name;
2500 }
2501
2502 /**
2503 * tp_account_get_service:
2504 * @self: an account
2505 *
2506 * <!-- -->
2507 *
2508 * Returns: the same as the #TpAccount:service property
2509 *
2510 * Since: 0.11.9
2511 */
2512 const gchar *
tp_account_get_service(TpAccount * self)2513 tp_account_get_service (TpAccount *self)
2514 {
2515 g_return_val_if_fail (TP_IS_ACCOUNT (self), NULL);
2516
2517 return self->priv->service;
2518 }
2519
2520 /**
2521 * tp_account_get_icon_name:
2522 * @account: a #TpAccount
2523 *
2524 * <!-- -->
2525 *
2526 * Returns: the same as the #TpAccount:icon-name property
2527 *
2528 * Since: 0.9.0
2529 */
2530 const gchar *
tp_account_get_icon_name(TpAccount * account)2531 tp_account_get_icon_name (TpAccount *account)
2532 {
2533 g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
2534
2535 return account->priv->icon_name;
2536 }
2537
2538 /**
2539 * tp_account_get_parameters:
2540 * @account: a #TpAccount
2541 *
2542 * Returns the parameters of the account, in a hash table where each string
2543 * is the parameter name (account, password, require-encryption etc.), and
2544 * each value is a #GValue. Using the tp_asv_get family of functions
2545 * (tp_asv_get_uint32(), tp_asv_get_string() etc.) to access the parameters is
2546 * recommended.
2547 *
2548 * The allowed parameters depend on the connection manager, and can be found
2549 * via tp_connection_manager_get_protocol() and
2550 * tp_connection_manager_protocol_get_param(). Well-known parameters are
2551 * listed
2552 * <ulink url="http://telepathy.freedesktop.org/spec/org.freedesktop.Telepathy.ConnectionManager.html#org.freedesktop.Telepathy.ConnectionManager.RequestConnection">in
2553 * the Telepathy D-Bus Interface Specification</ulink>.
2554 *
2555 * Returns: (transfer none) (element-type utf8 GObject.Value): the hash table of
2556 * parameters on @account
2557 *
2558 * Since: 0.9.0
2559 */
2560 const GHashTable *
tp_account_get_parameters(TpAccount * account)2561 tp_account_get_parameters (TpAccount *account)
2562 {
2563 g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
2564
2565 return account->priv->parameters;
2566 }
2567
2568 /**
2569 * tp_account_dup_parameters_vardict:
2570 * @account: a #TpAccount
2571 *
2572 * Returns the parameters of the account, in a variant of type
2573 * %G_VARIANT_TYPE_VARDICT where the keys
2574 * are parameter names (account, password, require-encryption etc.).
2575 * Use g_variant_lookup() or g_variant_lookup_value() for convenient
2576 * access to the values.
2577 *
2578 * The allowed parameters depend on the connection manager, and can be found
2579 * via tp_connection_manager_get_protocol() and
2580 * tp_connection_manager_protocol_get_param(). Well-known parameters are
2581 * listed
2582 * <ulink url="http://telepathy.freedesktop.org/spec/org.freedesktop.Telepathy.ConnectionManager.html#org.freedesktop.Telepathy.ConnectionManager.RequestConnection">in
2583 * the Telepathy D-Bus Interface Specification</ulink>.
2584 *
2585 * Returns: (transfer full): the dictionary of
2586 * parameters on @account, of type %G_VARIANT_TYPE_VARDICT
2587 *
2588 * Since: 0.17.6
2589 */
2590 GVariant *
tp_account_dup_parameters_vardict(TpAccount * account)2591 tp_account_dup_parameters_vardict (TpAccount *account)
2592 {
2593 g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
2594
2595 return _tp_asv_to_vardict (account->priv->parameters);
2596 }
2597
2598 /**
2599 * tp_account_is_enabled:
2600 * @account: a #TpAccount
2601 *
2602 * <!-- -->
2603 *
2604 * Returns: the same as the #TpAccount:enabled property
2605 *
2606 * Since: 0.9.0
2607 */
2608 gboolean
tp_account_is_enabled(TpAccount * account)2609 tp_account_is_enabled (TpAccount *account)
2610 {
2611 g_return_val_if_fail (TP_IS_ACCOUNT (account), FALSE);
2612
2613 return account->priv->enabled;
2614 }
2615
2616 static void
_tp_account_property_set_cb(TpProxy * proxy,const GError * error,gpointer user_data,GObject * weak_object)2617 _tp_account_property_set_cb (TpProxy *proxy,
2618 const GError *error,
2619 gpointer user_data,
2620 GObject *weak_object)
2621 {
2622 GSimpleAsyncResult *result = user_data;
2623
2624 if (error != NULL)
2625 {
2626 DEBUG ("Failed to set property: %s", error->message);
2627 g_simple_async_result_set_from_error (result, error);
2628 }
2629
2630 g_simple_async_result_complete_in_idle (result);
2631 g_object_unref (result);
2632 }
2633
2634 /**
2635 * tp_account_set_enabled_finish:
2636 * @account: a #TpAccount
2637 * @result: a #GAsyncResult
2638 * @error: a #GError to fill
2639 *
2640 * Finishes an async set of the Enabled property.
2641 *
2642 * Returns: %TRUE if the set was successful, otherwise %FALSE
2643 *
2644 * Since: 0.9.0
2645 */
2646 gboolean
tp_account_set_enabled_finish(TpAccount * account,GAsyncResult * result,GError ** error)2647 tp_account_set_enabled_finish (TpAccount *account,
2648 GAsyncResult *result,
2649 GError **error)
2650 {
2651 _tp_implement_finish_void (account, tp_account_set_enabled_finish);
2652 }
2653
2654 /**
2655 * tp_account_set_enabled_async:
2656 * @account: a #TpAccount
2657 * @enabled: the new enabled value of @account
2658 * @callback: a callback to call when the request is satisfied
2659 * @user_data: data to pass to @callback
2660 *
2661 * Requests an asynchronous set of the Enabled property of @account. When the
2662 * operation is finished, @callback will be called. You can then call
2663 * tp_account_set_enabled_finish() to get the result of the operation.
2664 *
2665 * Since: 0.9.0
2666 */
2667 void
tp_account_set_enabled_async(TpAccount * account,gboolean enabled,GAsyncReadyCallback callback,gpointer user_data)2668 tp_account_set_enabled_async (TpAccount *account,
2669 gboolean enabled,
2670 GAsyncReadyCallback callback,
2671 gpointer user_data)
2672 {
2673 GValue value = {0, };
2674 GSimpleAsyncResult *result;
2675
2676 g_return_if_fail (TP_IS_ACCOUNT (account));
2677
2678 result = g_simple_async_result_new (G_OBJECT (account),
2679 callback, user_data, tp_account_set_enabled_finish);
2680
2681 g_value_init (&value, G_TYPE_BOOLEAN);
2682 g_value_set_boolean (&value, enabled);
2683
2684 tp_cli_dbus_properties_call_set (TP_PROXY (account),
2685 -1, TP_IFACE_ACCOUNT, "Enabled", &value,
2686 _tp_account_property_set_cb, result, NULL, G_OBJECT (account));
2687
2688 g_value_reset (&value);
2689 }
2690
2691 static void
_tp_account_void_cb(TpAccount * proxy,const GError * error,gpointer user_data,GObject * weak_object)2692 _tp_account_void_cb (TpAccount *proxy,
2693 const GError *error,
2694 gpointer user_data,
2695 GObject *weak_object)
2696 {
2697 GSimpleAsyncResult *result = user_data;
2698
2699 if (error != NULL)
2700 g_simple_async_result_set_from_error (result, error);
2701
2702 g_simple_async_result_complete_in_idle (result);
2703 g_object_unref (result);
2704 }
2705
2706 /**
2707 * tp_account_reconnect_finish:
2708 * @account: a #TpAccount
2709 * @result: a #GAsyncResult
2710 * @error: a #GError to be filled
2711 *
2712 * Finishes an async reconnect of @account.
2713 *
2714 * Returns: %TRUE if the reconnect call was successful, otherwise %FALSE
2715 *
2716 * Since: 0.9.0
2717 */
2718 gboolean
tp_account_reconnect_finish(TpAccount * account,GAsyncResult * result,GError ** error)2719 tp_account_reconnect_finish (TpAccount *account,
2720 GAsyncResult *result,
2721 GError **error)
2722 {
2723 _tp_implement_finish_void (account, tp_account_reconnect_finish);
2724 }
2725
2726 /**
2727 * tp_account_reconnect_async:
2728 * @account: a #TpAccount
2729 * @callback: a callback to call when the request is satisfied
2730 * @user_data: data to pass to @callback
2731 *
2732 * Requests an asynchronous reconnect of @account. When the operation is
2733 * finished, @callback will be called. You can then call
2734 * tp_account_reconnect_finish() to get the result of the operation.
2735 *
2736 * Since: 0.9.0
2737 */
2738 void
tp_account_reconnect_async(TpAccount * account,GAsyncReadyCallback callback,gpointer user_data)2739 tp_account_reconnect_async (TpAccount *account,
2740 GAsyncReadyCallback callback,
2741 gpointer user_data)
2742 {
2743 GSimpleAsyncResult *result;
2744
2745 g_return_if_fail (TP_IS_ACCOUNT (account));
2746
2747 result = g_simple_async_result_new (G_OBJECT (account),
2748 callback, user_data, tp_account_reconnect_finish);
2749
2750 tp_cli_account_call_reconnect (account, -1, _tp_account_void_cb,
2751 result, NULL, G_OBJECT (account));
2752 }
2753
2754 /**
2755 * tp_account_set_automatic_presence_finish:
2756 * @account: a #TpAccount
2757 * @result: a #GAsyncResult
2758 * @error: a #GError to fill
2759 *
2760 * Finishes an asynchronous request to change the automatic presence of
2761 * @account.
2762 *
2763 * Returns: %TRUE if the operation was successful, otherwise %FALSE
2764 *
2765 * Since: 0.13.8
2766 */
2767 gboolean
tp_account_set_automatic_presence_finish(TpAccount * account,GAsyncResult * result,GError ** error)2768 tp_account_set_automatic_presence_finish (TpAccount *account,
2769 GAsyncResult *result,
2770 GError **error)
2771 {
2772 _tp_implement_finish_void (account, tp_account_set_automatic_presence_async)
2773 }
2774
2775 /**
2776 * tp_account_set_automatic_presence_async:
2777 * @account: a #TpAccount
2778 * @type: the requested presence
2779 * @status: a status message to set, or %NULL
2780 * @message: a message for the change, or %NULL
2781 * @callback: a callback to call when the request is satisfied
2782 * @user_data: data to pass to @callback
2783 *
2784 * Requests an asynchronous change of @account's automatic presence. When the
2785 * operation is finished, @callback will be called. You can then call
2786 * tp_account_set_automatic_presence_finish() to get the result of the
2787 * operation.
2788 *
2789 * Since: 0.13.8
2790 */
2791 void
tp_account_set_automatic_presence_async(TpAccount * account,TpConnectionPresenceType type,const gchar * status,const gchar * message,GAsyncReadyCallback callback,gpointer user_data)2792 tp_account_set_automatic_presence_async (TpAccount *account,
2793 TpConnectionPresenceType type,
2794 const gchar *status,
2795 const gchar *message,
2796 GAsyncReadyCallback callback,
2797 gpointer user_data)
2798 {
2799 GValue value = {0, };
2800 GSimpleAsyncResult *result;
2801
2802 g_return_if_fail (TP_IS_ACCOUNT (account));
2803
2804 result = g_simple_async_result_new (G_OBJECT (account),
2805 callback, user_data, tp_account_set_automatic_presence_async);
2806
2807 g_value_init (&value, TP_STRUCT_TYPE_SIMPLE_PRESENCE);
2808 g_value_take_boxed (&value, tp_value_array_build (3,
2809 G_TYPE_UINT, type,
2810 G_TYPE_STRING, status,
2811 G_TYPE_STRING, message,
2812 G_TYPE_INVALID));
2813
2814 tp_cli_dbus_properties_call_set (TP_PROXY (account), -1,
2815 TP_IFACE_ACCOUNT, "AutomaticPresence", &value,
2816 _tp_account_property_set_cb, result, NULL, G_OBJECT (account));
2817
2818 g_value_unset (&value);
2819 }
2820
2821 /**
2822 * tp_account_request_presence_finish:
2823 * @account: a #TpAccount
2824 * @result: a #GAsyncResult
2825 * @error: a #GError to fill
2826 *
2827 * Finishes an async presence change request on @account.
2828 *
2829 * Returns: %TRUE if the operation was successful, otherwise %FALSE
2830 *
2831 * Since: 0.9.0
2832 */
2833 gboolean
tp_account_request_presence_finish(TpAccount * account,GAsyncResult * result,GError ** error)2834 tp_account_request_presence_finish (TpAccount *account,
2835 GAsyncResult *result,
2836 GError **error)
2837 {
2838 _tp_implement_finish_void (account, tp_account_request_presence_finish);
2839 }
2840
2841 /**
2842 * tp_account_request_presence_async:
2843 * @account: a #TpAccount
2844 * @type: the requested presence
2845 * @status: a status message to set, or %NULL
2846 * @message: a message for the change, or %NULL
2847 * @callback: a callback to call when the request is satisfied
2848 * @user_data: data to pass to @callback
2849 *
2850 * Requests an asynchronous change of presence on @account. When the
2851 * operation is finished, @callback will be called. You can then call
2852 * tp_account_request_presence_finish() to get the result of the operation.
2853 *
2854 * Since: 0.9.0
2855 */
2856 void
tp_account_request_presence_async(TpAccount * account,TpConnectionPresenceType type,const gchar * status,const gchar * message,GAsyncReadyCallback callback,gpointer user_data)2857 tp_account_request_presence_async (TpAccount *account,
2858 TpConnectionPresenceType type,
2859 const gchar *status,
2860 const gchar *message,
2861 GAsyncReadyCallback callback,
2862 gpointer user_data)
2863 {
2864 GValue value = {0, };
2865 GValueArray *arr;
2866 GSimpleAsyncResult *result;
2867
2868 g_return_if_fail (TP_IS_ACCOUNT (account));
2869
2870 result = g_simple_async_result_new (G_OBJECT (account),
2871 callback, user_data, tp_account_request_presence_finish);
2872
2873 g_value_init (&value, TP_STRUCT_TYPE_SIMPLE_PRESENCE);
2874 g_value_take_boxed (&value, dbus_g_type_specialized_construct (
2875 TP_STRUCT_TYPE_SIMPLE_PRESENCE));
2876 arr = (GValueArray *) g_value_get_boxed (&value);
2877
2878 g_value_set_uint (arr->values, type);
2879 g_value_set_static_string (arr->values + 1, status);
2880 g_value_set_static_string (arr->values + 2, message);
2881
2882 tp_cli_dbus_properties_call_set (TP_PROXY (account), -1,
2883 TP_IFACE_ACCOUNT, "RequestedPresence", &value,
2884 _tp_account_property_set_cb, result, NULL, G_OBJECT (account));
2885
2886 g_value_unset (&value);
2887 }
2888
2889 static void
_tp_account_updated_cb(TpAccount * proxy,const gchar ** reconnect_required,const GError * error,gpointer user_data,GObject * weak_object)2890 _tp_account_updated_cb (TpAccount *proxy,
2891 const gchar **reconnect_required,
2892 const GError *error,
2893 gpointer user_data,
2894 GObject *weak_object)
2895 {
2896 GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
2897
2898 if (error != NULL)
2899 g_simple_async_result_set_from_error (result, error);
2900 else
2901 g_simple_async_result_set_op_res_gpointer (result,
2902 g_strdupv ((GStrv) reconnect_required), (GDestroyNotify) g_strfreev);
2903
2904 g_simple_async_result_complete_in_idle (result);
2905 g_object_unref (G_OBJECT (result));
2906 }
2907
2908 /**
2909 * tp_account_update_parameters_async:
2910 * @account: a #TpAccount
2911 * @parameters: (element-type utf8 GObject.Value) (transfer none): new
2912 * parameters to set on @account
2913 * @unset_parameters: list of parameters to unset on @account
2914 * @callback: a callback to call when the request is satisfied
2915 * @user_data: data to pass to @callback
2916 *
2917 * Requests an asynchronous update of parameters of @account. When the
2918 * operation is finished, @callback will be called. You can then call
2919 * tp_account_update_parameters_finish() to get the result of the operation.
2920 *
2921 * Since: 0.9.0
2922 */
2923 void
tp_account_update_parameters_async(TpAccount * account,GHashTable * parameters,const gchar ** unset_parameters,GAsyncReadyCallback callback,gpointer user_data)2924 tp_account_update_parameters_async (TpAccount *account,
2925 GHashTable *parameters,
2926 const gchar **unset_parameters,
2927 GAsyncReadyCallback callback,
2928 gpointer user_data)
2929 {
2930 GSimpleAsyncResult *result;
2931
2932 g_return_if_fail (TP_IS_ACCOUNT (account));
2933
2934 result = g_simple_async_result_new (G_OBJECT (account),
2935 callback, user_data, tp_account_update_parameters_finish);
2936
2937 tp_cli_account_call_update_parameters (account, -1, parameters,
2938 unset_parameters, _tp_account_updated_cb, result,
2939 NULL, G_OBJECT (account));
2940 }
2941
2942 /**
2943 * tp_account_update_parameters_finish:
2944 * @account: a #TpAccount
2945 * @result: a #GAsyncResult
2946 * @reconnect_required: (out) (array zero-terminated=1) (transfer full): a #GStrv to
2947 * fill with properties that need a reconnect to take effect
2948 * @error: a #GError to fill
2949 *
2950 * Finishes an async update of the parameters on @account.
2951 *
2952 * Returns: %TRUE if the request succeeded, otherwise %FALSE
2953 *
2954 * Since: 0.9.0
2955 */
2956 gboolean
tp_account_update_parameters_finish(TpAccount * account,GAsyncResult * result,gchar *** reconnect_required,GError ** error)2957 tp_account_update_parameters_finish (TpAccount *account,
2958 GAsyncResult *result,
2959 gchar ***reconnect_required,
2960 GError **error)
2961 {
2962 _tp_implement_finish_copy_pointer (account,
2963 tp_account_update_parameters_finish, g_strdupv,
2964 reconnect_required);
2965 }
2966
2967 /**
2968 * tp_account_update_parameters_vardict_async:
2969 * @account: a #TpAccount
2970 * @parameters: (transfer none): a variant of type %G_VARIANT_TYPE_VARDICT
2971 * containing new parameters to set on @account
2972 * @unset_parameters: (array zero-terminated=1): list of parameters to unset on @account
2973 * @callback: a callback to call when the request is satisfied
2974 * @user_data: data to pass to @callback
2975 *
2976 * Requests an asynchronous update of parameters of @account. When the
2977 * operation is finished, @callback will be called. You can then call
2978 * tp_account_update_parameters_finish() to get the result of the operation.
2979 *
2980 * If @parameters is a floating reference (see g_variant_ref_sink()),
2981 * ownership of @parameters is taken by this function. This means
2982 * you can pass the result of g_variant_new() or g_variant_new_parsed()
2983 * directly to this function without additional reference-count management.
2984 *
2985 * Since: 0.17.6
2986 */
2987 void
tp_account_update_parameters_vardict_async(TpAccount * account,GVariant * parameters,const gchar ** unset_parameters,GAsyncReadyCallback callback,gpointer user_data)2988 tp_account_update_parameters_vardict_async (TpAccount *account,
2989 GVariant *parameters,
2990 const gchar **unset_parameters,
2991 GAsyncReadyCallback callback,
2992 gpointer user_data)
2993 {
2994 GHashTable *hash;
2995
2996 hash = _tp_asv_from_vardict (parameters);
2997
2998 g_variant_ref_sink (parameters);
2999
3000 tp_account_update_parameters_async (account, hash,
3001 unset_parameters, callback, user_data);
3002 g_variant_unref (parameters);
3003 g_hash_table_unref (hash);
3004 }
3005
3006 /**
3007 * tp_account_update_parameters_vardict_finish:
3008 * @account: a #TpAccount
3009 * @result: a #GAsyncResult
3010 * @reconnect_required: (out) (type GStrv) (transfer full): a #GStrv to
3011 * fill with properties that need a reconnect to take effect
3012 * @error: a #GError to fill
3013 *
3014 * Finishes an async update of the parameters on @account.
3015 *
3016 * Returns: %TRUE if the request succeeded, otherwise %FALSE
3017 *
3018 * Since: 0.17.6
3019 */
3020 gboolean
tp_account_update_parameters_vardict_finish(TpAccount * account,GAsyncResult * result,gchar *** reconnect_required,GError ** error)3021 tp_account_update_parameters_vardict_finish (TpAccount *account,
3022 GAsyncResult *result,
3023 gchar ***reconnect_required,
3024 GError **error)
3025 {
3026 /* share an implementation with the non-vardict version */
3027 return tp_account_update_parameters_finish (account, result,
3028 reconnect_required, error);
3029 }
3030
3031 /**
3032 * tp_account_set_display_name_async:
3033 * @account: a #TpAccount
3034 * @display_name: a new display name, or %NULL to unset the display name
3035 * @callback: a callback to call when the request is satisfied
3036 * @user_data: data to pass to @callback
3037 *
3038 * Requests an asynchronous set of the DisplayName property of @account. When
3039 * the operation is finished, @callback will be called. You can then call
3040 * tp_account_set_display_name_finish() to get the result of the operation.
3041 *
3042 * Since: 0.9.0
3043 */
3044 void
tp_account_set_display_name_async(TpAccount * account,const char * display_name,GAsyncReadyCallback callback,gpointer user_data)3045 tp_account_set_display_name_async (TpAccount *account,
3046 const char *display_name,
3047 GAsyncReadyCallback callback,
3048 gpointer user_data)
3049 {
3050 GSimpleAsyncResult *result;
3051 GValue value = {0, };
3052 const gchar *display_name_set;
3053
3054 g_return_if_fail (TP_IS_ACCOUNT (account));
3055
3056 if (display_name == NULL)
3057 display_name_set = "";
3058 else
3059 display_name_set = display_name;
3060
3061 result = g_simple_async_result_new (G_OBJECT (account), callback,
3062 user_data, tp_account_set_display_name_finish);
3063
3064 g_value_init (&value, G_TYPE_STRING);
3065 g_value_set_string (&value, display_name_set);
3066
3067 tp_cli_dbus_properties_call_set (account, -1, TP_IFACE_ACCOUNT,
3068 "DisplayName", &value, _tp_account_property_set_cb, result, NULL,
3069 G_OBJECT (account));
3070
3071 g_value_unset (&value);
3072 }
3073
3074 /**
3075 * tp_account_set_display_name_finish:
3076 * @account: a #TpAccount
3077 * @result: a #GAsyncResult
3078 * @error: a #GError to fill
3079 *
3080 * Finishes an async set of the DisplayName property.
3081 *
3082 * Returns: %TRUE if the call was successful, otherwise %FALSE
3083 *
3084 * Since: 0.9.0
3085 */
3086 gboolean
tp_account_set_display_name_finish(TpAccount * account,GAsyncResult * result,GError ** error)3087 tp_account_set_display_name_finish (TpAccount *account,
3088 GAsyncResult *result,
3089 GError **error)
3090 {
3091 _tp_implement_finish_void (account, tp_account_set_display_name_finish);
3092 }
3093
3094 /**
3095 * tp_account_set_service_async:
3096 * @self: a #TpAccount
3097 * @service: a new service name, or %NULL or the empty string to unset the
3098 * service name (which will result in the #TpAccount:service property
3099 * becoming the same as #TpAccount:protocol)
3100 * @callback: a callback to call when the request is satisfied
3101 * @user_data: data to pass to @callback
3102 *
3103 * Requests an asynchronous set of the Service property on @self. When
3104 * the operation is finished, @callback will be called. You can then call
3105 * tp_account_set_service_finish() to get the result of the operation.
3106 *
3107 * Since: 0.11.9
3108 */
3109 void
tp_account_set_service_async(TpAccount * self,const char * service,GAsyncReadyCallback callback,gpointer user_data)3110 tp_account_set_service_async (TpAccount *self,
3111 const char *service,
3112 GAsyncReadyCallback callback,
3113 gpointer user_data)
3114 {
3115 GSimpleAsyncResult *result;
3116 GValue value = {0, };
3117
3118 g_return_if_fail (TP_IS_ACCOUNT (self));
3119
3120 if (service == NULL)
3121 service = "";
3122
3123 result = g_simple_async_result_new (G_OBJECT (self), callback,
3124 user_data, tp_account_set_service_async);
3125
3126 g_value_init (&value, G_TYPE_STRING);
3127 g_value_set_string (&value, service);
3128
3129 tp_cli_dbus_properties_call_set (self, -1, TP_IFACE_ACCOUNT,
3130 "Service", &value, _tp_account_property_set_cb, result, NULL,
3131 G_OBJECT (self));
3132
3133 g_value_unset (&value);
3134 }
3135
3136 /**
3137 * tp_account_set_service_finish:
3138 * @self: a #TpAccount
3139 * @result: a #GAsyncResult
3140 * @error: a #GError to fill
3141 *
3142 * Finishes an async set of the Service parameter.
3143 *
3144 * Returns: %TRUE if the operation was successful, otherwise %FALSE
3145 *
3146 * Since: 0.11.9
3147 */
3148 gboolean
tp_account_set_service_finish(TpAccount * self,GAsyncResult * result,GError ** error)3149 tp_account_set_service_finish (TpAccount *self,
3150 GAsyncResult *result,
3151 GError **error)
3152 {
3153 _tp_implement_finish_void (self, tp_account_set_service_async);
3154 }
3155
3156 /**
3157 * tp_account_set_icon_name_async:
3158 * @account: a #TpAccount
3159 * @icon_name: a new icon name, or %NULL to unset the icon name
3160 * @callback: a callback to call when the request is satisfied
3161 * @user_data: data to pass to @callback
3162 *
3163 * Requests an asynchronous set of the Icon property of @account. When
3164 * the operation is finished, @callback will be called. You can then call
3165 * tp_account_set_icon_name_finish() to get the result of the operation.
3166 *
3167 * Since: 0.9.0
3168 */
3169 void
tp_account_set_icon_name_async(TpAccount * account,const char * icon_name,GAsyncReadyCallback callback,gpointer user_data)3170 tp_account_set_icon_name_async (TpAccount *account,
3171 const char *icon_name,
3172 GAsyncReadyCallback callback,
3173 gpointer user_data)
3174 {
3175 GSimpleAsyncResult *result;
3176 GValue value = {0, };
3177 const char *icon_name_set;
3178
3179 g_return_if_fail (TP_IS_ACCOUNT (account));
3180
3181 if (icon_name == NULL)
3182 /* settings an empty icon name is allowed */
3183 icon_name_set = "";
3184 else
3185 icon_name_set = icon_name;
3186
3187 result = g_simple_async_result_new (G_OBJECT (account), callback,
3188 user_data, tp_account_set_icon_name_finish);
3189
3190 g_value_init (&value, G_TYPE_STRING);
3191 g_value_set_string (&value, icon_name_set);
3192
3193 tp_cli_dbus_properties_call_set (account, -1, TP_IFACE_ACCOUNT,
3194 "Icon", &value, _tp_account_property_set_cb, result, NULL,
3195 G_OBJECT (account));
3196
3197 g_value_unset (&value);
3198 }
3199
3200 /**
3201 * tp_account_set_icon_name_finish:
3202 * @account: a #TpAccount
3203 * @result: a #GAsyncResult
3204 * @error: a #GError to fill
3205 *
3206 * Finishes an async set of the Icon parameter.
3207 *
3208 * Returns: %TRUE if the operation was successful, otherwise %FALSE
3209 *
3210 * Since: 0.9.0
3211 */
3212 gboolean
tp_account_set_icon_name_finish(TpAccount * account,GAsyncResult * result,GError ** error)3213 tp_account_set_icon_name_finish (TpAccount *account,
3214 GAsyncResult *result,
3215 GError **error)
3216 {
3217 _tp_implement_finish_void (account, tp_account_set_icon_name_finish);
3218 }
3219
3220 /**
3221 * tp_account_remove_async:
3222 * @account: a #TpAccount
3223 * @callback: a callback to call when the request is satisfied
3224 * @user_data: data to pass to @callback
3225 *
3226 * Requests an asynchronous removal of @account. When the operation is
3227 * finished, @callback will be called. You can then call
3228 * tp_account_remove_finish() to get the result of the operation.
3229 *
3230 * Since: 0.9.0
3231 */
3232 void
tp_account_remove_async(TpAccount * account,GAsyncReadyCallback callback,gpointer user_data)3233 tp_account_remove_async (TpAccount *account,
3234 GAsyncReadyCallback callback,
3235 gpointer user_data)
3236 {
3237 GSimpleAsyncResult *result;
3238
3239 g_return_if_fail (TP_IS_ACCOUNT (account));
3240
3241 result = g_simple_async_result_new (G_OBJECT (account),
3242 callback, user_data, tp_account_remove_finish);
3243
3244 tp_cli_account_call_remove (account, -1, _tp_account_void_cb, result, NULL,
3245 G_OBJECT (account));
3246 }
3247
3248 /**
3249 * tp_account_remove_finish:
3250 * @account: a #TpAccount
3251 * @result: a #GAsyncResult
3252 * @error: a #GError to fill
3253 *
3254 * Finishes an async removal of @account.
3255 *
3256 * Returns: %TRUE if the operation was successful, otherwise %FALSE
3257 *
3258 * Since: 0.9.0
3259 */
3260 gboolean
tp_account_remove_finish(TpAccount * account,GAsyncResult * result,GError ** error)3261 tp_account_remove_finish (TpAccount *account,
3262 GAsyncResult *result,
3263 GError **error)
3264 {
3265 _tp_implement_finish_void (account, tp_account_remove_finish);
3266 }
3267
3268 /**
3269 * tp_account_get_changing_presence:
3270 * @self: an account
3271 *
3272 * <!-- -->
3273 *
3274 * Returns: the same as the #TpAccount:changing-presence property
3275 *
3276 * Since: 0.11.6
3277 */
3278 gboolean
tp_account_get_changing_presence(TpAccount * self)3279 tp_account_get_changing_presence (TpAccount *self)
3280 {
3281 g_return_val_if_fail (TP_IS_ACCOUNT (self), FALSE);
3282
3283 return self->priv->changing_presence;
3284 }
3285
3286 /**
3287 * tp_account_get_connect_automatically:
3288 * @account: a #TpAccount
3289 *
3290 * <!-- -->
3291 *
3292 * Returns: the same as the #TpAccount:connect-automatically property
3293 *
3294 * Since: 0.9.0
3295 */
3296 gboolean
tp_account_get_connect_automatically(TpAccount * account)3297 tp_account_get_connect_automatically (TpAccount *account)
3298 {
3299 g_return_val_if_fail (TP_IS_ACCOUNT (account), FALSE);
3300
3301 return account->priv->connect_automatically;
3302 }
3303
3304 /**
3305 * tp_account_set_connect_automatically_async:
3306 * @account: a #TpAccount
3307 * @connect_automatically: new value for the parameter
3308 * @callback: a callback to call when the request is satisfied
3309 * @user_data: data to pass to @callback
3310 *
3311 * Requests an asynchronous set of the ConnectAutomatically property of
3312 * @account. When the operation is finished, @callback will be called. You can
3313 * then call tp_account_set_display_name_finish() to get the result of the
3314 * operation.
3315 *
3316 * Since: 0.9.0
3317 */
3318 void
tp_account_set_connect_automatically_async(TpAccount * account,gboolean connect_automatically,GAsyncReadyCallback callback,gpointer user_data)3319 tp_account_set_connect_automatically_async (TpAccount *account,
3320 gboolean connect_automatically,
3321 GAsyncReadyCallback callback,
3322 gpointer user_data)
3323 {
3324 GSimpleAsyncResult *result;
3325 GValue value = {0, };
3326
3327 g_return_if_fail (TP_IS_ACCOUNT (account));
3328
3329 result = g_simple_async_result_new (G_OBJECT (account), callback,
3330 user_data, tp_account_set_connect_automatically_finish);
3331
3332 g_value_init (&value, G_TYPE_BOOLEAN);
3333 g_value_set_boolean (&value, connect_automatically);
3334
3335 tp_cli_dbus_properties_call_set (account, -1, TP_IFACE_ACCOUNT,
3336 "ConnectAutomatically", &value, _tp_account_property_set_cb, result,
3337 NULL, G_OBJECT (account));
3338
3339 g_value_unset (&value);
3340 }
3341
3342 /**
3343 * tp_account_set_connect_automatically_finish:
3344 * @account: a #TpAccount
3345 * @result: a #GAsyncResult
3346 * @error: a #GError to fill
3347 *
3348 * Finishes an async set of the ConnectAutomatically property.
3349 *
3350 * Returns: %TRUE if the call was successful, otherwise %FALSE
3351 *
3352 * Since: 0.9.0
3353 */
3354 gboolean
tp_account_set_connect_automatically_finish(TpAccount * account,GAsyncResult * result,GError ** error)3355 tp_account_set_connect_automatically_finish (TpAccount *account,
3356 GAsyncResult *result,
3357 GError **error)
3358 {
3359 _tp_implement_finish_void (account,
3360 tp_account_set_connect_automatically_finish);
3361 }
3362
3363 /**
3364 * tp_account_get_has_been_online:
3365 * @account: a #TpAccount
3366 *
3367 * <!-- -->
3368 *
3369 * Returns: the same as the #TpAccount:has-been-online property
3370 *
3371 * Since: 0.9.0
3372 */
3373 gboolean
tp_account_get_has_been_online(TpAccount * account)3374 tp_account_get_has_been_online (TpAccount *account)
3375 {
3376 g_return_val_if_fail (TP_IS_ACCOUNT (account), FALSE);
3377
3378 return account->priv->has_been_online;
3379 }
3380
3381 /**
3382 * tp_account_get_connection_status:
3383 * @account: a #TpAccount
3384 * @reason: (out): a #TpConnectionStatusReason to fill, or %NULL
3385 *
3386 * Gets the connection status and reason from @account. The two values
3387 * are the same as the #TpAccount:connection-status and
3388 * #TpAccount:connection-status-reason properties.
3389 *
3390 * Returns: the same as the #TpAccount:connection-status property
3391 *
3392 * Since: 0.9.0
3393 */
3394 TpConnectionStatus
tp_account_get_connection_status(TpAccount * account,TpConnectionStatusReason * reason)3395 tp_account_get_connection_status (TpAccount *account,
3396 TpConnectionStatusReason *reason)
3397 {
3398 g_return_val_if_fail (TP_IS_ACCOUNT (account),
3399 TP_CONNECTION_STATUS_DISCONNECTED); /* there's no _UNSET */
3400
3401 if (reason != NULL)
3402 *reason = account->priv->reason;
3403
3404 return account->priv->connection_status;
3405 }
3406
3407 /**
3408 * tp_account_get_current_presence:
3409 * @account: a #TpAccount
3410 * @status: (out) (transfer full): return location for the current status
3411 * @status_message: (out) (transfer full): return location for the current
3412 * status message
3413 *
3414 * Gets the current presence, status and status message of @account. These
3415 * values are the same as the #TpAccount:current-presence-type,
3416 * #TpAccount:current-status and #TpAccount:current-status-message properties.
3417 *
3418 * Returns: the same as the #TpAccount:current-presence-type property
3419 *
3420 * Since: 0.9.0
3421 */
3422 TpConnectionPresenceType
tp_account_get_current_presence(TpAccount * account,gchar ** status,gchar ** status_message)3423 tp_account_get_current_presence (TpAccount *account,
3424 gchar **status,
3425 gchar **status_message)
3426 {
3427 g_return_val_if_fail (TP_IS_ACCOUNT (account),
3428 TP_CONNECTION_PRESENCE_TYPE_UNSET);
3429
3430 if (status != NULL)
3431 *status = g_strdup (account->priv->cur_status);
3432
3433 if (status_message != NULL)
3434 *status_message = g_strdup (account->priv->cur_message);
3435
3436 return account->priv->cur_presence;
3437 }
3438
3439 /**
3440 * tp_account_get_requested_presence:
3441 * @account: a #TpAccount
3442 * @status: (out) (transfer none): return location for the requested status
3443 * @status_message: (out) (transfer full): return location for the requested
3444 * status message
3445 *
3446 * Gets the requested presence, status and status message of @account. These
3447 * values are the same as the #TpAccount:requested-presence-type,
3448 * #TpAccount:requested-status and #TpAccount:requested-status-message
3449 * properties.
3450 *
3451 * Returns: the same as the #TpAccount:requested-presence-type property
3452 *
3453 * Since: 0.9.0
3454 */
3455 TpConnectionPresenceType
tp_account_get_requested_presence(TpAccount * account,gchar ** status,gchar ** status_message)3456 tp_account_get_requested_presence (TpAccount *account,
3457 gchar **status,
3458 gchar **status_message)
3459 {
3460 g_return_val_if_fail (TP_IS_ACCOUNT (account),
3461 TP_CONNECTION_PRESENCE_TYPE_UNSET);
3462
3463 if (status != NULL)
3464 *status = g_strdup (account->priv->requested_status);
3465
3466 if (status_message != NULL)
3467 *status_message = g_strdup (account->priv->requested_message);
3468
3469 return account->priv->requested_presence;
3470 }
3471
3472 /**
3473 * tp_account_get_nickname:
3474 * @account: a #TpAccount
3475 *
3476 * <!-- -->
3477 *
3478 * Returns: the same as the #TpAccount:nickname property
3479 *
3480 * Since: 0.9.0
3481 */
3482 const gchar *
tp_account_get_nickname(TpAccount * account)3483 tp_account_get_nickname (TpAccount *account)
3484 {
3485 g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL);
3486
3487 return account->priv->nickname;
3488 }
3489
3490 /**
3491 * tp_account_set_nickname_finish:
3492 * @account: a #TpAccount
3493 * @result: a #GAsyncResult
3494 * @error: a #GError to fill
3495 *
3496 * Finishes an async nickname change request on @account.
3497 *
3498 * Returns: %TRUE if the operation was successful, otherwise %FALSE
3499 *
3500 * Since: 0.9.0
3501 */
3502 gboolean
tp_account_set_nickname_finish(TpAccount * account,GAsyncResult * result,GError ** error)3503 tp_account_set_nickname_finish (TpAccount *account,
3504 GAsyncResult *result,
3505 GError **error)
3506 {
3507 _tp_implement_finish_void (account, tp_account_set_nickname_finish);
3508 }
3509
3510 /**
3511 * tp_account_set_nickname_async:
3512 * @account: a #TpAccount
3513 * @nickname: a new nickname to set
3514 * @callback: a callback to call when the request is satisfied
3515 * @user_data: data to pass to @callback
3516 *
3517 * Requests an asynchronous change of the Nickname parameter on @account. When
3518 * the operation is finished, @callback will be called. You can then call
3519 * tp_account_set_nickname_finish() to get the result of the operation.
3520 *
3521 * Since: 0.9.0
3522 */
3523 void
tp_account_set_nickname_async(TpAccount * account,const gchar * nickname,GAsyncReadyCallback callback,gpointer user_data)3524 tp_account_set_nickname_async (TpAccount *account,
3525 const gchar *nickname,
3526 GAsyncReadyCallback callback,
3527 gpointer user_data)
3528 {
3529 GValue value = {0, };
3530 GSimpleAsyncResult *result;
3531
3532 g_return_if_fail (TP_IS_ACCOUNT (account));
3533 g_return_if_fail (nickname != NULL);
3534
3535 result = g_simple_async_result_new (G_OBJECT (account),
3536 callback, user_data, tp_account_set_nickname_finish);
3537
3538 if (nickname == NULL)
3539 {
3540 g_simple_async_report_error_in_idle (G_OBJECT (account),
3541 callback, user_data, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
3542 "Can't set an empty nickname");
3543 return;
3544 }
3545
3546 g_value_init (&value, G_TYPE_STRING);
3547 g_value_set_string (&value, nickname);
3548
3549 tp_cli_dbus_properties_call_set (TP_PROXY (account), -1,
3550 TP_IFACE_ACCOUNT, "Nickname", &value,
3551 _tp_account_property_set_cb, result, NULL, G_OBJECT (account));
3552
3553 g_value_unset (&value);
3554 }
3555
3556 /**
3557 * tp_account_get_supersedes:
3558 * @self: a #TpAccount
3559 *
3560 * Return the same thing as the #TpAccount:supersedes property, in a way
3561 * that may be more convenient for C code.
3562 *
3563 * The returned pointers are not guaranteed to remain valid after the
3564 * main loop has been re-entered.
3565 *
3566 * Returns: (transfer none): the same as the #TpAccount:supersedes property
3567 *
3568 * Since: 0.17.5
3569 */
3570 const gchar * const *
tp_account_get_supersedes(TpAccount * self)3571 tp_account_get_supersedes (TpAccount *self)
3572 {
3573 g_return_val_if_fail (TP_IS_ACCOUNT (self), NULL);
3574
3575 return (const gchar * const *) self->priv->supersedes;
3576 }
3577
3578 static void
_tp_account_got_avatar_cb(TpProxy * proxy,const GValue * out_Value,const GError * error,gpointer user_data,GObject * weak_object)3579 _tp_account_got_avatar_cb (TpProxy *proxy,
3580 const GValue *out_Value,
3581 const GError *error,
3582 gpointer user_data,
3583 GObject *weak_object)
3584 {
3585 GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
3586
3587 if (error != NULL)
3588 {
3589 DEBUG ("Failed to get avatar: %s", error->message);
3590 g_simple_async_result_set_from_error (result, error);
3591 }
3592 else if (!G_VALUE_HOLDS (out_Value, TP_STRUCT_TYPE_AVATAR))
3593 {
3594 DEBUG ("Avatar had wrong type: %s", G_VALUE_TYPE_NAME (out_Value));
3595 g_simple_async_result_set_error (result, TP_ERROR, TP_ERROR_CONFUSED,
3596 "Incorrect type for Avatar property");
3597 }
3598 else
3599 {
3600 GValueArray *avatar;
3601 GArray *res;
3602 const GArray *tmp;
3603 const gchar *mime_type;
3604
3605 avatar = g_value_get_boxed (out_Value);
3606 tp_value_array_unpack (avatar, 2,
3607 &tmp,
3608 &mime_type);
3609
3610 res = g_array_sized_new (FALSE, FALSE, 1, tmp->len);
3611 g_array_append_vals (res, tmp->data, tmp->len);
3612 g_simple_async_result_set_op_res_gpointer (result, res,
3613 (GDestroyNotify) g_array_unref);
3614 }
3615
3616 g_simple_async_result_complete_in_idle (result);
3617 g_object_unref (result);
3618 }
3619
3620 /**
3621 * tp_account_get_avatar_async:
3622 * @account: a #TpAccount
3623 * @callback: a callback to call when the request is satisfied
3624 * @user_data: data to pass to @callback
3625 *
3626 * Requests an asynchronous get of @account's avatar. When
3627 * the operation is finished, @callback will be called. You can then call
3628 * tp_account_get_avatar_finish() to get the result of the operation.
3629 *
3630 * Since: 0.9.0
3631 */
3632 void
tp_account_get_avatar_async(TpAccount * account,GAsyncReadyCallback callback,gpointer user_data)3633 tp_account_get_avatar_async (TpAccount *account,
3634 GAsyncReadyCallback callback,
3635 gpointer user_data)
3636 {
3637 GSimpleAsyncResult *result;
3638
3639 g_return_if_fail (TP_IS_ACCOUNT (account));
3640
3641 result = g_simple_async_result_new (G_OBJECT (account),
3642 callback, user_data, tp_account_get_avatar_finish);
3643
3644 tp_cli_dbus_properties_call_get (account, -1,
3645 TP_IFACE_ACCOUNT_INTERFACE_AVATAR, "Avatar", _tp_account_got_avatar_cb,
3646 result, NULL, G_OBJECT (account));
3647 }
3648
3649 /**
3650 * tp_account_get_avatar_finish:
3651 * @account: a #TpAccount
3652 * @result: a #GAsyncResult
3653 * @error: a #GError to fill
3654 *
3655 * Finishes an async get operation of @account's avatar.
3656 *
3657 * Beware that the returned value is only valid until @result is freed.
3658 * Copy it with g_array_ref() if you need to keep it for longer.
3659 *
3660 * Returns: (element-type guchar) (transfer none): a #GArray of #guchar
3661 * containing the bytes of the account's avatar, or %NULL on failure
3662 *
3663 * Since: 0.9.0
3664 */
3665 const GArray *
tp_account_get_avatar_finish(TpAccount * account,GAsyncResult * result,GError ** error)3666 tp_account_get_avatar_finish (TpAccount *account,
3667 GAsyncResult *result,
3668 GError **error)
3669 {
3670 _tp_implement_finish_return_copy_pointer (account,
3671 tp_account_get_avatar_finish, /* do not copy */);
3672 }
3673
3674 /**
3675 * tp_account_is_prepared: (skip)
3676 * @account: a #TpAccount
3677 * @feature: a feature which is required
3678 *
3679 * <!-- -->
3680 *
3681 * Returns: the same thing as tp_proxy_is_prepared()
3682 *
3683 * Since: 0.9.0
3684 * Deprecated: since 0.23.0, use tp_proxy_is_prepared() instead.
3685 */
3686 gboolean
tp_account_is_prepared(TpAccount * account,GQuark feature)3687 tp_account_is_prepared (TpAccount *account,
3688 GQuark feature)
3689 {
3690 return tp_proxy_is_prepared (account, feature);
3691 }
3692
3693 /**
3694 * tp_account_prepare_async: (skip)
3695 * @account: a #TpAccount
3696 * @features: a 0-terminated list of features, or %NULL
3697 * @callback: a callback to call when the request is satisfied
3698 * @user_data: data to pass to @callback
3699 *
3700 * Requests an asynchronous preparation of @account with the features specified
3701 * by @features. When the operation is finished, @callback will be called. You
3702 * can then call tp_account_prepare_finish() to get the result of the
3703 * operation.
3704 *
3705 * If @features is %NULL, then @callback will be called when the implied
3706 * %TP_ACCOUNT_FEATURE_CORE feature is ready.
3707 *
3708 * If %NULL is given to @callback, then no callback will be called when the
3709 * operation is finished. Instead, it will simply set @features on @manager.
3710 * Note that if @callback is %NULL, then @user_data must also be %NULL.
3711 *
3712 * Since 0.11.3, this is equivalent to calling the new function
3713 * tp_proxy_prepare_async() with the same arguments.
3714 *
3715 * Since: 0.9.0
3716 * Deprecated: since 0.15.6, use tp_proxy_prepare_async() instead.
3717 */
3718 void
tp_account_prepare_async(TpAccount * account,const GQuark * features,GAsyncReadyCallback callback,gpointer user_data)3719 tp_account_prepare_async (TpAccount *account,
3720 const GQuark *features,
3721 GAsyncReadyCallback callback,
3722 gpointer user_data)
3723 {
3724 tp_proxy_prepare_async (account, features, callback, user_data);
3725 }
3726
3727 /**
3728 * tp_account_prepare_finish: (skip)
3729 * @account: a #TpAccount
3730 * @result: a #GAsyncResult
3731 * @error: a #GError to fill
3732 *
3733 * Finishes an async preparation of the account @account.
3734 *
3735 * Returns: %TRUE if the preparation was successful, otherwise %FALSE
3736 *
3737 * Since: 0.9.0
3738 * Deprecated: since 0.15.6, use tp_proxy_prepare_finish() instead.
3739 */
3740 gboolean
tp_account_prepare_finish(TpAccount * account,GAsyncResult * result,GError ** error)3741 tp_account_prepare_finish (TpAccount *account,
3742 GAsyncResult *result,
3743 GError **error)
3744 {
3745 return tp_proxy_prepare_finish (account, result, error);
3746 }
3747
3748 static void
set_or_free(gchar ** target,gchar * source)3749 set_or_free (gchar **target,
3750 gchar *source)
3751 {
3752 if (target != NULL)
3753 *target = source;
3754 else
3755 g_free (source);
3756 }
3757
3758 /**
3759 * tp_account_parse_object_path:
3760 * @object_path: a Telepathy Account's object path
3761 * @cm: (out) (transfer full): location at which to store the account's
3762 * connection manager's name
3763 * @protocol: (out) (transfer full): location at which to store the account's
3764 * protocol
3765 * @account_id: (out) (transfer full): location at which to store the account's
3766 * unique identifier
3767 * @error: location at which to return an error
3768 *
3769 * Validates and parses a Telepathy Account's object path, extracting the
3770 * connection manager's name, the protocol, and the account's unique identifier
3771 * from the path. This includes replacing underscores with hyphens in the
3772 * protocol name, as defined in the Account specification.
3773 *
3774 * Any of the out parameters may be %NULL if not needed. If %TRUE is returned,
3775 * the caller is responsible for freeing the strings stored in any non-%NULL
3776 * out parameters, using g_free().
3777 *
3778 * Returns: %TRUE if @object_path was successfully parsed; %FALSE and sets
3779 * @error otherwise.
3780 *
3781 * Since: 0.9.0
3782 * Deprecated: Use tp_account_get_protocol() and
3783 * tp_account_get_connection_manager() instead.
3784 */
3785 gboolean
tp_account_parse_object_path(const gchar * object_path,gchar ** cm,gchar ** protocol,gchar ** account_id,GError ** error)3786 tp_account_parse_object_path (const gchar *object_path,
3787 gchar **cm,
3788 gchar **protocol,
3789 gchar **account_id,
3790 GError **error)
3791 {
3792 const gchar *suffix;
3793 gchar **segments;
3794
3795 if (!tp_dbus_check_valid_object_path (object_path, error))
3796 return FALSE;
3797
3798 if (!g_str_has_prefix (object_path, TP_ACCOUNT_OBJECT_PATH_BASE))
3799 {
3800 g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
3801 "Account path does not start with the right prefix: %s",
3802 object_path);
3803 return FALSE;
3804 }
3805
3806 suffix = object_path + strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
3807
3808 segments = g_strsplit (suffix, "/", 0);
3809
3810 if (g_strv_length (segments) != 3)
3811 {
3812 g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
3813 "Account path '%s' is malformed: should have 3 trailing components, "
3814 "not %u", object_path, g_strv_length (segments));
3815 goto free_segments_and_fail;
3816 }
3817
3818 if (!g_ascii_isalpha (segments[0][0]))
3819 {
3820 g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
3821 "Account path '%s' is malformed: CM name should start with a letter",
3822 object_path);
3823 goto free_segments_and_fail;
3824 }
3825
3826 if (!g_ascii_isalpha (segments[1][0]))
3827 {
3828 g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
3829 "Account path '%s' is malformed: "
3830 "protocol name should start with a letter",
3831 object_path);
3832 goto free_segments_and_fail;
3833 }
3834
3835 if (!g_ascii_isalpha (segments[2][0]) && segments[2][0] != '_')
3836 {
3837 g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
3838 "Account path '%s' is malformed: "
3839 "account ID should start with a letter or underscore",
3840 object_path);
3841 goto free_segments_and_fail;
3842 }
3843
3844 set_or_free (cm, segments[0]);
3845 set_or_free (protocol, unescape_protocol (segments[1]));
3846 set_or_free (account_id, segments[2]);
3847
3848 /* Not g_strfreev because we stole or freed the individual strings */
3849 g_free (segments);
3850 return TRUE;
3851
3852 free_segments_and_fail:
3853 g_strfreev (segments);
3854 return FALSE;
3855 }
3856
3857 /**
3858 * _tp_account_refresh_properties:
3859 * @account: a #TpAccount
3860 *
3861 * Refreshes @account's hashtable of properties with what actually exists on
3862 * the account manager.
3863 *
3864 * Since: 0.9.0
3865 */
3866 void
_tp_account_refresh_properties(TpAccount * account)3867 _tp_account_refresh_properties (TpAccount *account)
3868 {
3869 g_return_if_fail (TP_IS_ACCOUNT (account));
3870
3871 tp_cli_dbus_properties_call_get_all (account, -1, TP_IFACE_ACCOUNT,
3872 _tp_account_got_all_cb, NULL, NULL, G_OBJECT (account));
3873 }
3874
3875 /**
3876 * tp_account_set_avatar_finish:
3877 * @self: a #TpAccount
3878 * @result: a #GAsyncResult
3879 * @error: a #GError to fill
3880 *
3881 * Finishes an async avatar change request on @account.
3882 *
3883 * Returns: %TRUE if the operation was successful, otherwise %FALSE
3884 *
3885 * Since: 0.11.1
3886 */
3887 gboolean
tp_account_set_avatar_finish(TpAccount * self,GAsyncResult * result,GError ** error)3888 tp_account_set_avatar_finish (TpAccount *self,
3889 GAsyncResult *result,
3890 GError **error)
3891 {
3892 _tp_implement_finish_void (self, tp_account_set_avatar_async);
3893 }
3894
3895 /**
3896 * tp_account_set_avatar_async:
3897 * @self: a #TpAccount
3898 * @avatar: (allow-none) (array length=len): a new avatar to set; can be %NULL
3899 * only if @len equals 0
3900 * @len: the length of the new avatar
3901 * @mime_type: (allow-none): the MIME type of the new avatar; can be %NULL
3902 * only if @len equals 0
3903 * @callback: a callback to call when the request is satisfied
3904 * @user_data: data to pass to @callback
3905 *
3906 * Requests an asynchronous change of the Avatar parameter on @self. When
3907 * the operation is finished, @callback will be called. You can then call
3908 * tp_account_set_avatar_finish() to get the result of the operation.
3909 *
3910 * If @len equals 0, the avatar is cleared.
3911 *
3912 * Since: 0.11.1
3913 */
3914 void
tp_account_set_avatar_async(TpAccount * self,const guchar * avatar,gsize len,const gchar * mime_type,GAsyncReadyCallback callback,gpointer user_data)3915 tp_account_set_avatar_async (TpAccount *self,
3916 const guchar *avatar,
3917 gsize len,
3918 const gchar *mime_type,
3919 GAsyncReadyCallback callback,
3920 gpointer user_data)
3921 {
3922 GValue value = {0, };
3923 GSimpleAsyncResult *result;
3924 GValueArray *arr;
3925 GArray *tmp;
3926
3927 g_return_if_fail (TP_IS_ACCOUNT (self));
3928 g_return_if_fail (avatar != NULL || len == 0);
3929 g_return_if_fail (mime_type != NULL || len == 0);
3930
3931 result = g_simple_async_result_new (G_OBJECT (self),
3932 callback, user_data, tp_account_set_avatar_async);
3933
3934 tmp = g_array_new (FALSE, FALSE, sizeof (guchar));
3935
3936 if (len > 0)
3937 g_array_append_vals (tmp, avatar, len);
3938
3939 arr = tp_value_array_build (2,
3940 TP_TYPE_UCHAR_ARRAY, tmp,
3941 G_TYPE_STRING, mime_type,
3942 G_TYPE_INVALID);
3943
3944 g_value_init (&value, TP_STRUCT_TYPE_AVATAR);
3945 g_value_take_boxed (&value, arr);
3946
3947 tp_cli_dbus_properties_call_set (self, -1,
3948 TP_IFACE_ACCOUNT_INTERFACE_AVATAR, "Avatar", &value,
3949 _tp_account_property_set_cb, result, NULL, NULL);
3950
3951 g_value_unset (&value);
3952 }
3953
3954 /**
3955 * tp_account_get_detailed_error: (skip)
3956 * @self: an account
3957 * @details: (out) (allow-none) (element-type utf8 GObject.Value) (transfer none):
3958 * optionally used to return a map from string to #GValue, which must not be
3959 * modified, destroyed or unreffed by the caller
3960 *
3961 * If the account's connection is not connected, return the D-Bus error name
3962 * with which it last disconnected or failed to connect (in particular, this
3963 * is %TP_ERROR_STR_CANCELLED if it was disconnected by a user request).
3964 * This is the same as #TpAccount:connection-error.
3965 *
3966 * If @details is not %NULL, it will be used to return additional details about
3967 * the error (the same as #TpAccount:connection-error-details).
3968 *
3969 * Otherwise, return %NULL, without altering @details.
3970 *
3971 * The returned string and @details may become invalid when the main loop is
3972 * re-entered or the account is destroyed.
3973 *
3974 * Returns: (transfer none) (allow-none): a D-Bus error name, or %NULL.
3975 *
3976 * Since: 0.11.7
3977 */
3978 const gchar *
tp_account_get_detailed_error(TpAccount * self,const GHashTable ** details)3979 tp_account_get_detailed_error (TpAccount *self,
3980 const GHashTable **details)
3981 {
3982 g_return_val_if_fail (TP_IS_ACCOUNT (self), NULL);
3983
3984 if (self->priv->connection_status == TP_CONNECTION_STATUS_CONNECTED)
3985 return NULL;
3986
3987 if (details != NULL)
3988 *details = self->priv->error_details;
3989
3990 return self->priv->error;
3991 }
3992
3993 /**
3994 * tp_account_dup_detailed_error_vardict:
3995 * @self: an account
3996 * @details: (out) (allow-none) (transfer full):
3997 * optionally used to return a variant of type %G_VARIANT_TYPE_VARDICT,
3998 * which must be unreffed by the caller with g_variant_unref()
3999 *
4000 * If the account's connection is not connected, return the D-Bus error name
4001 * with which it last disconnected or failed to connect (in particular, this
4002 * is %TP_ERROR_STR_CANCELLED if it was disconnected by a user request).
4003 * This is the same as #TpAccount:connection-error.
4004 *
4005 * If @details is not %NULL, it will be used to return additional details about
4006 * the error (the same as #TpAccount:connection-error-details).
4007 *
4008 * Otherwise, return %NULL, without altering @details.
4009 *
4010 * The returned string and @details may become invalid when the main loop is
4011 * re-entered or the account is destroyed.
4012 *
4013 * Returns: (transfer full) (allow-none): a D-Bus error name, or %NULL.
4014 *
4015 * Since: 0.17.6
4016 */
4017 gchar *
tp_account_dup_detailed_error_vardict(TpAccount * self,GVariant ** details)4018 tp_account_dup_detailed_error_vardict (TpAccount *self,
4019 GVariant **details)
4020 {
4021 g_return_val_if_fail (TP_IS_ACCOUNT (self), NULL);
4022
4023 if (self->priv->connection_status == TP_CONNECTION_STATUS_CONNECTED)
4024 return NULL;
4025
4026 if (details != NULL)
4027 *details = _tp_asv_to_vardict (self->priv->error_details);
4028
4029 return g_strdup (self->priv->error);
4030 }
4031
4032 /**
4033 * tp_account_get_storage_provider:
4034 * @self: a #TpAccount
4035 *
4036 * <!-- -->
4037 *
4038 * Returns: the same as the #TpAccount:storage-provider property
4039 *
4040 * Since: 0.13.2
4041 */
4042 const gchar *
tp_account_get_storage_provider(TpAccount * self)4043 tp_account_get_storage_provider (TpAccount *self)
4044 {
4045 g_return_val_if_fail (TP_IS_ACCOUNT (self), NULL);
4046
4047 return self->priv->storage_provider;
4048 }
4049
4050 /* FIXME: in 1.0, remove */
4051 /**
4052 * tp_account_get_storage_identifier:
4053 * @self: a #TpAccount
4054 *
4055 * <!-- -->
4056 *
4057 * Returns: the same as the #TpAccount:storage-identifier property
4058 *
4059 * Since: 0.13.2
4060 */
4061 const GValue *
tp_account_get_storage_identifier(TpAccount * self)4062 tp_account_get_storage_identifier (TpAccount *self)
4063 {
4064 g_return_val_if_fail (TP_IS_ACCOUNT (self), NULL);
4065
4066 return self->priv->storage_identifier;
4067 }
4068
4069 /* FIXME: in 1.0, rename to tp_account_get_storage_identifier */
4070 /**
4071 * tp_account_dup_storage_identifier_variant:
4072 * @self: a #TpAccount
4073 *
4074 * Return provider-specific information used to identify this
4075 * account. Use g_variant_get_type() to check that the type
4076 * is what you expect; for instance, if the
4077 * #TpAccount:storage-provider has string-based user identifiers,
4078 * this variant should have type %G_VARIANT_TYPE_STRING.
4079 *
4080 * Returns: (transfer full): the same as the
4081 * #TpAccount:storage-identifier-variant property
4082 *
4083 * Since: 0.13.2
4084 */
4085 GVariant *
tp_account_dup_storage_identifier_variant(TpAccount * self)4086 tp_account_dup_storage_identifier_variant (TpAccount *self)
4087 {
4088 g_return_val_if_fail (TP_IS_ACCOUNT (self), NULL);
4089
4090 if (self->priv->storage_identifier == NULL)
4091 return NULL;
4092
4093 return g_variant_ref_sink (dbus_g_value_build_g_variant (
4094 self->priv->storage_identifier));
4095 }
4096
4097 /**
4098 * tp_account_get_storage_restrictions:
4099 * @self: a #TpAccount
4100 *
4101 * <!-- -->
4102 *
4103 * Returns: the same as the #TpAccount:storage-restrictions property
4104 *
4105 * Since: 0.13.2
4106 */
4107 TpStorageRestrictionFlags
tp_account_get_storage_restrictions(TpAccount * self)4108 tp_account_get_storage_restrictions (TpAccount *self)
4109 {
4110 g_return_val_if_fail (TP_IS_ACCOUNT (self), 0);
4111
4112 return self->priv->storage_restrictions;
4113 }
4114
4115 static void
_tp_account_get_storage_specific_information_cb(TpProxy * self,const GValue * value,const GError * error,gpointer user_data,GObject * weak_obj)4116 _tp_account_get_storage_specific_information_cb (TpProxy *self,
4117 const GValue *value,
4118 const GError *error,
4119 gpointer user_data,
4120 GObject *weak_obj)
4121 {
4122 GSimpleAsyncResult *result = user_data;
4123
4124 if (error != NULL)
4125 {
4126 DEBUG ("Failed to retrieve StorageSpecificInformation: %s",
4127 error->message);
4128 g_simple_async_result_set_from_error (result, error);
4129 }
4130 else
4131 {
4132 g_simple_async_result_set_op_res_gpointer (result,
4133 g_value_dup_boxed (value),
4134 (GDestroyNotify) g_hash_table_unref);
4135 }
4136
4137 g_simple_async_result_complete_in_idle (result);
4138 g_object_unref (result);
4139 }
4140
4141 /* FIXME: in Telepathy 1.0, remove this */
4142 /**
4143 * tp_account_get_storage_specific_information_async:
4144 * @self: a #TpAccount
4145 * @callback: a callback to call when the request is satisfied
4146 * @user_data: data to pass to @callback
4147 *
4148 * Makes an asynchronous request of @self's StorageSpecificInformation
4149 * property (part of the Account.Interface.Storage interface).
4150 *
4151 * When the operation is finished, @callback will be called. You must then
4152 * call tp_account_get_storage_specific_information_finish() to get the
4153 * result of the request.
4154 *
4155 * Since: 0.13.2
4156 */
4157 void
tp_account_get_storage_specific_information_async(TpAccount * self,GAsyncReadyCallback callback,gpointer user_data)4158 tp_account_get_storage_specific_information_async (TpAccount *self,
4159 GAsyncReadyCallback callback,
4160 gpointer user_data)
4161 {
4162 GSimpleAsyncResult *result;
4163
4164 g_return_if_fail (TP_IS_ACCOUNT (self));
4165
4166 result = g_simple_async_result_new (G_OBJECT (self),
4167 callback, user_data, tp_account_get_storage_specific_information_async);
4168
4169 tp_cli_dbus_properties_call_get (self, -1,
4170 TP_IFACE_ACCOUNT_INTERFACE_STORAGE, "StorageSpecificInformation",
4171 _tp_account_get_storage_specific_information_cb, result, NULL, NULL);
4172 }
4173
4174 /* FIXME: in Telepathy 1.0, rename to ...get_storage_specific_information... */
4175 /**
4176 * tp_account_dup_storage_specific_information_vardict_async:
4177 * @self: a #TpAccount
4178 * @callback: a callback to call when the request is satisfied
4179 * @user_data: data to pass to @callback
4180 *
4181 * Makes an asynchronous request of @self's StorageSpecificInformation
4182 * property (part of the Account.Interface.Storage interface).
4183 *
4184 * When the operation is finished, @callback will be called. You must then
4185 * call tp_account_dup_storage_specific_information_vardict_finish() to get the
4186 * result of the request.
4187 *
4188 * Since: 0.17.6
4189 */
4190 void
tp_account_dup_storage_specific_information_vardict_async(TpAccount * self,GAsyncReadyCallback callback,gpointer user_data)4191 tp_account_dup_storage_specific_information_vardict_async (TpAccount *self,
4192 GAsyncReadyCallback callback,
4193 gpointer user_data)
4194 {
4195 /* we share an implementation */
4196 tp_account_get_storage_specific_information_async (self, callback,
4197 user_data);
4198 }
4199
4200 /* FIXME: in Telepathy 1.0, remove this */
4201 /**
4202 * tp_account_get_storage_specific_information_finish:
4203 * @self: a #TpAccount
4204 * @result: a #GAsyncResult
4205 * @error: a #GError to fill
4206 *
4207 * Retrieve the value of the request begun with
4208 * tp_account_get_storage_specific_information_async().
4209 *
4210 * Beware that the returned value is only valid until @result is freed.
4211 * Copy it with g_hash_table_ref() if you need to keep it for longer.
4212 *
4213 * Returns: (element-type utf8 GObject.Value) (transfer none): a #GHashTable
4214 * of strings to GValues representing the D-Bus type a{sv}.
4215 *
4216 * Since: 0.13.2
4217 */
4218 GHashTable *
tp_account_get_storage_specific_information_finish(TpAccount * self,GAsyncResult * result,GError ** error)4219 tp_account_get_storage_specific_information_finish (TpAccount *self,
4220 GAsyncResult *result,
4221 GError **error)
4222 {
4223 _tp_implement_finish_return_copy_pointer (self,
4224 tp_account_get_storage_specific_information_async, /* do not copy */);
4225 }
4226
4227 /* FIXME: in Telepathy 1.0, rename to ...get_storage_specific_information... */
4228 /**
4229 * tp_account_dup_storage_specific_information_vardict_finish:
4230 * @self: a #TpAccount
4231 * @result: a #GAsyncResult
4232 * @error: a #GError to fill
4233 *
4234 * Retrieve the value of the request begun with
4235 * tp_account_dup_storage_specific_information_vardict_async().
4236 *
4237 * Returns: (transfer full): a map from strings to variants,
4238 * of type %G_VARIANT_TYPE_VARDICT
4239 *
4240 * Since: 0.17.6
4241 */
4242 GVariant *
tp_account_dup_storage_specific_information_vardict_finish(TpAccount * self,GAsyncResult * result,GError ** error)4243 tp_account_dup_storage_specific_information_vardict_finish (TpAccount *self,
4244 GAsyncResult *result,
4245 GError **error)
4246 {
4247 /* we share the source tag with the non-vardict version */
4248 _tp_implement_finish_return_copy_pointer (self,
4249 tp_account_get_storage_specific_information_async, _tp_asv_to_vardict);
4250 }
4251
4252 static void
_tp_account_got_all_addressing_cb(TpProxy * proxy,GHashTable * properties,const GError * error,gpointer user_data,GObject * object)4253 _tp_account_got_all_addressing_cb (TpProxy *proxy,
4254 GHashTable *properties,
4255 const GError *error,
4256 gpointer user_data,
4257 GObject *object)
4258 {
4259 TpAccount *self = TP_ACCOUNT (proxy);
4260 GSimpleAsyncResult *result = user_data;
4261
4262 if (error != NULL)
4263 {
4264 DEBUG ("Error getting Addressing properties: %s", error->message);
4265 }
4266 else
4267 {
4268 self->priv->uri_schemes = g_strdupv (tp_asv_get_boxed (properties,
4269 "URISchemes", G_TYPE_STRV));
4270 }
4271
4272 if (self->priv->uri_schemes == NULL)
4273 self->priv->uri_schemes = g_new0 (gchar *, 1);
4274
4275 g_simple_async_result_complete_in_idle (result);
4276 }
4277
4278 static void
connection_prepare_cb(GObject * object,GAsyncResult * res,gpointer user_data)4279 connection_prepare_cb (GObject *object,
4280 GAsyncResult *res,
4281 gpointer user_data)
4282 {
4283 TpConnection *connection = (TpConnection *) object;
4284 TpAccount *self = tp_connection_get_account (connection);
4285 GSimpleAsyncResult *result = user_data;
4286 GError *error = NULL;
4287
4288 self->priv->connection_prepared = TRUE;
4289
4290 if (!tp_proxy_prepare_finish (object, res, &error))
4291 {
4292 DEBUG ("Error preparing connection: %s", error->message);
4293 g_simple_async_result_take_error (result, error);
4294 }
4295 g_simple_async_result_complete (result);
4296
4297 g_object_unref (result);
4298 }
4299
4300 static void
tp_account_prepare_connection_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)4301 tp_account_prepare_connection_async (TpProxy *proxy,
4302 const TpProxyFeature *feature,
4303 GAsyncReadyCallback callback,
4304 gpointer user_data)
4305 {
4306 TpAccount *self = TP_ACCOUNT (proxy);
4307 GSimpleAsyncResult *result;
4308 GArray *features;
4309
4310 result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
4311 tp_account_prepare_connection_async);
4312
4313 if (self->priv->connection == NULL)
4314 {
4315 g_simple_async_result_complete_in_idle (result);
4316 g_object_unref (result);
4317 return;
4318 }
4319
4320 features = tp_simple_client_factory_dup_connection_features (
4321 tp_proxy_get_factory (self), self->priv->connection);
4322
4323 tp_proxy_prepare_async (self->priv->connection, (GQuark *) features->data,
4324 connection_prepare_cb, result);
4325
4326 g_array_unref (features);
4327 }
4328
4329 static void
tp_account_prepare_addressing_async(TpProxy * proxy,const TpProxyFeature * feature,GAsyncReadyCallback callback,gpointer user_data)4330 tp_account_prepare_addressing_async (TpProxy *proxy,
4331 const TpProxyFeature *feature,
4332 GAsyncReadyCallback callback,
4333 gpointer user_data)
4334 {
4335 TpAccount *self = TP_ACCOUNT (proxy);
4336 GSimpleAsyncResult *result;
4337
4338 result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
4339 tp_account_prepare_addressing_async);
4340
4341 g_assert (self->priv->uri_schemes == NULL);
4342
4343 tp_cli_dbus_properties_call_get_all (self, -1,
4344 TP_IFACE_ACCOUNT_INTERFACE_ADDRESSING,
4345 _tp_account_got_all_addressing_cb, result, g_object_unref, NULL);
4346 }
4347
4348 /**
4349 * tp_account_get_uri_schemes:
4350 * @self: a #TpAccount
4351 *
4352 * Return the #TpAccount:uri-schemes property
4353 *
4354 * Returns: (transfer none): the value of #TpAccount:uri_schemes property
4355 *
4356 * Since: 0.13.8
4357 */
4358 const gchar * const *
tp_account_get_uri_schemes(TpAccount * self)4359 tp_account_get_uri_schemes (TpAccount *self)
4360 {
4361 g_return_val_if_fail (TP_IS_ACCOUNT (self), NULL);
4362
4363 return (const gchar * const *) self->priv->uri_schemes;
4364 }
4365
4366 /**
4367 * tp_account_associated_with_uri_scheme:
4368 * @self: a #TpAccount
4369 * @scheme: (transfer none): a URI scheme such as "tel", "sip" or "xmpp"
4370 *
4371 * <!-- -->
4372 *
4373 * Returns: %TRUE if the result of tp_account_get_uri_schemes() would include
4374 * @scheme
4375 *
4376 * Since: 0.13.8
4377 */
4378 gboolean
tp_account_associated_with_uri_scheme(TpAccount * self,const gchar * scheme)4379 tp_account_associated_with_uri_scheme (TpAccount *self,
4380 const gchar *scheme)
4381 {
4382 return tp_strv_contains (tp_account_get_uri_schemes (self), scheme);
4383 }
4384
4385 /**
4386 * tp_account_set_uri_scheme_association_async:
4387 * @self: a #TpAccount
4388 * @scheme: a non-%NULL URI scheme such as "tel"
4389 * @associate: %TRUE to use this account for @scheme, or %FALSE to not use it
4390 * @callback: a callback to call when the request is satisfied
4391 * @user_data: data to pass to @callback
4392 *
4393 * Add @scheme to the list of additional URI schemes that would be returned
4394 * by tp_account_get_uri_schemes(), or remove it from that list.
4395 *
4396 * @scheme should not be the primary URI scheme for the account's
4397 * protocol (for instance, "xmpp" for XMPP, or "sip" or "sips" for SIP),
4398 * since the account should be assumed to be useful for those schemes
4399 * regardless of the contents of the list.
4400 *
4401 * Calling this method does not require the %TP_ACCOUNT_FEATURE_ADDRESSING
4402 * feature to be enabled, but the change will not be reflected in the result
4403 * of tp_account_get_uri_schemes() or tp_account_associated_with_uri_scheme()
4404 * unless that feature has been enabled.
4405 *
4406 * Since: 0.13.8
4407 */
4408 void
tp_account_set_uri_scheme_association_async(TpAccount * self,const gchar * scheme,gboolean associate,GAsyncReadyCallback callback,gpointer user_data)4409 tp_account_set_uri_scheme_association_async (TpAccount *self,
4410 const gchar *scheme,
4411 gboolean associate,
4412 GAsyncReadyCallback callback,
4413 gpointer user_data)
4414 {
4415 GSimpleAsyncResult *result;
4416
4417 g_return_if_fail (TP_IS_ACCOUNT (self));
4418 g_return_if_fail (scheme != NULL);
4419
4420 result = g_simple_async_result_new (G_OBJECT (self), callback,
4421 user_data, tp_account_set_uri_scheme_association_async);
4422
4423 tp_cli_account_interface_addressing_call_set_uri_scheme_association (
4424 self, -1, scheme, associate,
4425 _tp_account_void_cb, result, NULL, NULL);
4426 }
4427
4428 /**
4429 * tp_account_set_uri_scheme_association_finish:
4430 * @self: a #TpAccount
4431 * @result: a #GAsyncResult
4432 * @error: a #GError to fill
4433 *
4434 * Interpret the result of tp_account_set_uri_scheme_association_async().
4435 *
4436 * Returns: %TRUE if the call was successful, otherwise %FALSE
4437 *
4438 * Since: 0.13.8
4439 */
4440 gboolean
tp_account_set_uri_scheme_association_finish(TpAccount * self,GAsyncResult * result,GError ** error)4441 tp_account_set_uri_scheme_association_finish (TpAccount *self,
4442 GAsyncResult *result,
4443 GError **error)
4444 {
4445 _tp_implement_finish_void (self, tp_account_set_uri_scheme_association_async);
4446 }
4447
4448 /**
4449 * tp_account_get_automatic_presence:
4450 * @self: an account
4451 * @status: (out) (transfer none): return location for the presence status
4452 * @status_message: (out) (transfer full): return location for the
4453 * user-defined message
4454 *
4455 * Gets the automatic presence, status and status message of @account. These
4456 * values are the same as the #TpAccount:automatic-presence-type,
4457 * #TpAccount:automatic-status and #TpAccount:automatic-status-message
4458 * properties, and are the values that will be used if the account should
4459 * be put online automatically.
4460 *
4461 * Returns: the same as the #TpAccount:automatic-presence-type property
4462 *
4463 * Since: 0.13.8
4464 */
4465 TpConnectionPresenceType
tp_account_get_automatic_presence(TpAccount * self,gchar ** status,gchar ** status_message)4466 tp_account_get_automatic_presence (TpAccount *self,
4467 gchar **status,
4468 gchar **status_message)
4469 {
4470 g_return_val_if_fail (TP_IS_ACCOUNT (self),
4471 TP_CONNECTION_PRESENCE_TYPE_UNSET);
4472
4473 if (status != NULL)
4474 *status = g_strdup (self->priv->auto_status);
4475
4476 if (status_message != NULL)
4477 *status_message = g_strdup (self->priv->auto_message);
4478
4479 return self->priv->auto_presence;
4480 }
4481
4482 /**
4483 * tp_account_get_normalized_name:
4484 * @self: a #TpAccount
4485 *
4486 * <!-- -->
4487 *
4488 * Returns: (transfer none): the same as the #TpAccount:normalized-name
4489 * property
4490 *
4491 * Since: 0.13.8
4492 **/
4493 const gchar *
tp_account_get_normalized_name(TpAccount * self)4494 tp_account_get_normalized_name (TpAccount *self)
4495 {
4496 g_return_val_if_fail (TP_IS_ACCOUNT (self), NULL);
4497
4498 return self->priv->normalized_name;
4499 }
4500
4501 /**
4502 * tp_account_bind_connection_status_to_property:
4503 * @self: a #TpAccount
4504 * @target: the target #GObject
4505 * @target_property: the property on @target to bind (must be %G_TYPE_BOOLEAN)
4506 * @invert: %TRUE if you wish to invert the value of @target_property
4507 * (i.e. %FALSE if connected)
4508 *
4509 * Binds the :connection-status of @self to the boolean property of another
4510 * object using a #GBinding such that the @target_property will be set to
4511 * %TRUE when @self is connected (and @invert is %FALSE).
4512 *
4513 * @target_property will be synchronised immediately (%G_BINDING_SYNC_CREATE).
4514 * @invert can be interpreted as analogous to %G_BINDING_INVERT_BOOLEAN.
4515 *
4516 * For instance, this function can be used to bind the GtkWidget:sensitive
4517 * property to only make a widget sensitive when the account is connected.
4518 *
4519 * See g_object_bind_property() for more information.
4520 *
4521 * Returns: (transfer none): the #GBinding instance representing the binding
4522 * between the @self and the @target. The binding is released whenever the
4523 * #GBinding reference count reaches zero.
4524 * Since: 0.13.16
4525 */
4526 GBinding *
tp_account_bind_connection_status_to_property(TpAccount * self,gpointer target,const char * target_property,gboolean invert)4527 tp_account_bind_connection_status_to_property (TpAccount *self,
4528 gpointer target,
4529 const char *target_property,
4530 gboolean invert)
4531 {
4532 g_return_val_if_fail (TP_IS_ACCOUNT (self), NULL);
4533
4534 return g_object_bind_property_full (self, "connection-status",
4535 target, target_property,
4536 G_BINDING_SYNC_CREATE,
4537 _tp_bind_connection_status_to_boolean,
4538 NULL, GUINT_TO_POINTER (invert), NULL);
4539 }
4540