2 * @file telepathy-status.c
6 * Copyright (C) 2012-2019 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <glib-object.h>
28 #include <telepathy-glib/base-connection.h>
29 #include <telepathy-glib/telepathy-glib.h>
31 #include "sipe-backend.h"
32 #include "sipe-common.h"
33 #include "sipe-core.h"
35 #include "telepathy-private.h"
37 static const TpPresenceStatusOptionalArgumentSpec args
[] = {
38 { .name
= "message", .dtype
= "s" },
39 { .name
= NULL
, .dtype
= NULL
}
42 /* Sipe core activity <-> Telepathy status mapping */
43 #define SIPE_TELEPATHY_STATUS(_name, _type, _self, _args) \
46 .presence_type = (_type), \
48 .optional_arguments = (_args), \
50 #define SIPE_TELEPATHY_STATUS_NONE(_name, _type, _self) \
51 SIPE_TELEPATHY_STATUS(_name, _type, _self, NULL)
52 #define SIPE_TELEPATHY_STATUS_MESSAGE(_name, _type, _self) \
53 SIPE_TELEPATHY_STATUS(_name, _type, _self, args)
54 static const TpPresenceStatusSpec statuses
[SIPE_ACTIVITY_NUM_TYPES
+ 1] = {
55 /* SIPE_ACTIVITY_UNSET */ SIPE_TELEPATHY_STATUS_NONE( "unset", TP_CONNECTION_PRESENCE_TYPE_UNSET
, FALSE
),
56 /* SIPE_ACTIVITY_AVAILABLE */ SIPE_TELEPATHY_STATUS_MESSAGE("available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE
, TRUE
),
57 /* SIPE_ACTIVITY_ONLINE */ SIPE_TELEPATHY_STATUS_MESSAGE("online", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE
, TRUE
),
58 /* SIPE_ACTIVITY_INACTIVE */ SIPE_TELEPATHY_STATUS_MESSAGE("idle", TP_CONNECTION_PRESENCE_TYPE_AWAY
, TRUE
),
59 /* SIPE_ACTIVITY_BUSY */ SIPE_TELEPATHY_STATUS_MESSAGE("busy", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
60 /* SIPE_ACTIVITY_BUSYIDLE */ SIPE_TELEPATHY_STATUS_MESSAGE("busyidle", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
61 /* SIPE_ACTIVITY_DND */ SIPE_TELEPATHY_STATUS_MESSAGE("do-not-disturb", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
62 /* SIPE_ACTIVITY_BRB */ SIPE_TELEPATHY_STATUS_MESSAGE("be-right-back", TP_CONNECTION_PRESENCE_TYPE_AWAY
, TRUE
),
63 /* SIPE_ACTIVITY_AWAY */ SIPE_TELEPATHY_STATUS_MESSAGE("away", TP_CONNECTION_PRESENCE_TYPE_AWAY
, TRUE
),
64 /* SIPE_ACTIVITY_LUNCH */ SIPE_TELEPATHY_STATUS_MESSAGE("out-to-lunch", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY
, TRUE
),
65 /* SIPE_ACTIVITY_INVISIBLE */ SIPE_TELEPATHY_STATUS_NONE( "invisible", TP_CONNECTION_PRESENCE_TYPE_HIDDEN
, TRUE
),
66 /* SIPE_ACTIVITY_OFFLINE */ SIPE_TELEPATHY_STATUS_NONE( "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE
, FALSE
),
67 /* SIPE_ACTIVITY_ON_PHONE */ SIPE_TELEPATHY_STATUS_MESSAGE("on-the-phone", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
68 /* SIPE_ACTIVITY_IN_CONF */ SIPE_TELEPATHY_STATUS_MESSAGE("in-a-conference", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
69 /* SIPE_ACTIVITY_IN_MEETING */ SIPE_TELEPATHY_STATUS_MESSAGE("in-a-meeting", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
70 /* SIPE_ACTIVITY_OOF */ SIPE_TELEPATHY_STATUS_MESSAGE("out-of-office", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY
, TRUE
),
71 /* SIPE_ACTIVITY_URGENT_ONLY */ SIPE_TELEPATHY_STATUS_MESSAGE("urgent-interruptions-only", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
72 /* end-of-array indicator */ SIPE_TELEPATHY_STATUS_NONE( NULL
, 0, FALSE
)
75 static gboolean
status_available(SIPE_UNUSED_PARAMETER GObject
*object
,
79 * @TODO: what is this function supposed to do?
80 * - TRUE: index is one of the "user is available" statuses?
81 * - TRUE: index is a valid status?
83 return(statuses
[index
].name
!= NULL
);
86 static GHashTable
*get_contact_statuses(GObject
*object
,
87 const GArray
*contacts
,
88 SIPE_UNUSED_PARAMETER GError
**error
)
90 struct sipe_backend_private
*telepathy_private
= sipe_telepathy_connection_private(object
);
91 TpBaseConnection
*base
= TP_BASE_CONNECTION(object
);
92 GHashTable
*status_table
= g_hash_table_new(g_direct_hash
,
96 for (i
= 0; i
< contacts
->len
; i
++) {
97 TpHandle contact
= g_array_index(contacts
, guint
, i
);
99 GHashTable
*parameters
;
101 /* we get our own status from the connection, and everyone
102 * else's status from the contact lists */
103 if (contact
== tp_base_connection_get_self_handle(base
)) {
104 activity
= telepathy_private
->activity
;
107 activity
= sipe_telepathy_buddy_get_presence(telepathy_private
->contact_list
,
111 parameters
= g_hash_table_new_full(g_str_hash
,
114 (GDestroyNotify
) tp_g_value_slice_free
);
115 g_hash_table_insert(status_table
,
116 GUINT_TO_POINTER(contact
),
117 tp_presence_status_new(activity
,
119 g_hash_table_unref(parameters
);
122 return(status_table
);
125 static void update_status(struct sipe_backend_private
*telepathy_private
,
127 const gchar
*message
,
128 const TpPresenceStatus
*status
,
131 GObject
*connection
= G_OBJECT(telepathy_private
->connection
);
132 GHashTable
*presences
;
134 /* update internal status */
135 telepathy_private
->activity
= activity
;
136 g_free(telepathy_private
->message
);
137 telepathy_private
->message
= NULL
;
139 telepathy_private
->message
= g_strdup(message
);
141 /* outgoing status update */
143 sipe_core_status_set(telepathy_private
->public,
148 /* emit status update signal */
149 presences
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
150 g_hash_table_insert(presences
,
151 GUINT_TO_POINTER(tp_base_connection_get_self_handle(TP_BASE_CONNECTION(connection
))),
153 tp_presence_mixin_emit_presence_update(connection
, presences
);
154 g_hash_table_unref(presences
);
157 static gboolean
set_own_status(GObject
*object
,
158 const TpPresenceStatus
*status
,
159 SIPE_UNUSED_PARAMETER GError
**error
)
161 struct sipe_backend_private
*telepathy_private
= sipe_telepathy_connection_private(object
);
162 guint activity
= SIPE_ACTIVITY_AVAILABLE
;
163 const gchar
*message
= NULL
;
165 if (!telepathy_private
)
169 activity
= status
->index
;
171 if (status
->optional_arguments
)
172 message
= tp_asv_get_string(status
->optional_arguments
,
176 SIPE_DEBUG_INFO("set_own_status: %d '%s'", activity
,
177 message
? message
: "(none)");
178 update_status(telepathy_private
, activity
, message
, status
, TRUE
);
184 void sipe_telepathy_status_init(GObjectClass
*object_class
,
187 tp_presence_mixin_class_init(object_class
,
190 get_contact_statuses
,
197 * Backend adaptor functions
199 guint
sipe_backend_status(struct sipe_core_public
*sipe_public
)
201 return(sipe_public
->backend_private
->activity
);
204 gboolean
sipe_backend_status_changed(struct sipe_core_public
*sipe_public
,
206 const gchar
*message
)
208 struct sipe_backend_private
*telepathy_private
= sipe_public
->backend_private
;
210 if ((activity
== telepathy_private
->activity
) &&
211 sipe_strequal(message
, telepathy_private
->message
))
220 * - incoming status updates (roaming)
221 * - induced status updates (calendar)
223 void sipe_backend_status_and_note(struct sipe_core_public
*sipe_public
,
225 const gchar
*message
)
227 struct sipe_backend_private
*telepathy_private
= sipe_public
->backend_private
;
228 GHashTable
*optional
= NULL
;
229 TpPresenceStatus
*status
;
232 optional
= tp_asv_new("message", G_TYPE_STRING
, message
,
235 status
= tp_presence_status_new(activity
, optional
);
237 g_hash_table_unref(optional
);
239 update_status(telepathy_private
, activity
, message
, status
, FALSE
);
240 tp_presence_status_free(status
);