2 * @file telepathy-status.c
6 * Copyright (C) 2012 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
23 #include <glib-object.h>
24 #include <telepathy-glib/base-connection.h>
25 #include <telepathy-glib/telepathy-glib.h>
27 #include "sipe-backend.h"
28 #include "sipe-common.h"
29 #include "sipe-core.h"
31 #include "telepathy-private.h"
33 static const TpPresenceStatusOptionalArgumentSpec args
[] = {
34 { .name
= "message", .dtype
= "s" },
35 { .name
= NULL
, .dtype
= NULL
}
38 /* Sipe core activity <-> Telepathy status mapping */
39 #define SIPE_TELEPATHY_STATUS(_name, _type, _self, _args) \
42 .presence_type = (_type), \
44 .optional_arguments = (_args), \
46 #define SIPE_TELEPATHY_STATUS_NONE(_name, _type, _self) \
47 SIPE_TELEPATHY_STATUS(_name, _type, _self, NULL)
48 #define SIPE_TELEPATHY_STATUS_MESSAGE(_name, _type, _self) \
49 SIPE_TELEPATHY_STATUS(_name, _type, _self, args)
50 static const TpPresenceStatusSpec statuses
[SIPE_ACTIVITY_NUM_TYPES
+ 1] = {
51 /* SIPE_ACTIVITY_UNSET */ SIPE_TELEPATHY_STATUS_NONE( "unset", TP_CONNECTION_PRESENCE_TYPE_UNSET
, FALSE
),
52 /* SIPE_ACTIVITY_AVAILABLE */ SIPE_TELEPATHY_STATUS_MESSAGE("available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE
, TRUE
),
53 /* SIPE_ACTIVITY_ONLINE */ SIPE_TELEPATHY_STATUS_MESSAGE("online", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE
, TRUE
),
54 /* SIPE_ACTIVITY_INACTIVE */ SIPE_TELEPATHY_STATUS_MESSAGE("idle", TP_CONNECTION_PRESENCE_TYPE_AWAY
, TRUE
),
55 /* SIPE_ACTIVITY_BUSY */ SIPE_TELEPATHY_STATUS_MESSAGE("busy", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
56 /* SIPE_ACTIVITY_BUSYIDLE */ SIPE_TELEPATHY_STATUS_MESSAGE("busyidle", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
57 /* SIPE_ACTIVITY_DND */ SIPE_TELEPATHY_STATUS_MESSAGE("do-not-disturb", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
58 /* SIPE_ACTIVITY_BRB */ SIPE_TELEPATHY_STATUS_MESSAGE("be-right-back", TP_CONNECTION_PRESENCE_TYPE_AWAY
, TRUE
),
59 /* SIPE_ACTIVITY_AWAY */ SIPE_TELEPATHY_STATUS_MESSAGE("away", TP_CONNECTION_PRESENCE_TYPE_AWAY
, TRUE
),
60 /* SIPE_ACTIVITY_LUNCH */ SIPE_TELEPATHY_STATUS_MESSAGE("out-to-lunch", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY
, TRUE
),
61 /* SIPE_ACTIVITY_INVISIBLE */ SIPE_TELEPATHY_STATUS_NONE( "invisible", TP_CONNECTION_PRESENCE_TYPE_HIDDEN
, TRUE
),
62 /* SIPE_ACTIVITY_OFFLINE */ SIPE_TELEPATHY_STATUS_NONE( "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE
, FALSE
),
63 /* SIPE_ACTIVITY_ON_PHONE */ SIPE_TELEPATHY_STATUS_MESSAGE("on-the-phone", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
64 /* SIPE_ACTIVITY_IN_CONF */ SIPE_TELEPATHY_STATUS_MESSAGE("in-a-conference", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
65 /* SIPE_ACTIVITY_IN_MEETING */ SIPE_TELEPATHY_STATUS_MESSAGE("in-a-meeting", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
66 /* SIPE_ACTIVITY_OOF */ SIPE_TELEPATHY_STATUS_MESSAGE("out-of-office", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY
, TRUE
),
67 /* SIPE_ACTIVITY_URGENT_ONLY */ SIPE_TELEPATHY_STATUS_MESSAGE("urgent-interruptions-only", TP_CONNECTION_PRESENCE_TYPE_BUSY
, TRUE
),
68 /* end-of-array indicator */ SIPE_TELEPATHY_STATUS_NONE( NULL
, 0, FALSE
)
71 static gboolean
status_available(SIPE_UNUSED_PARAMETER GObject
*object
,
75 * @TODO: what is this function supposed to do?
76 * - TRUE: index is one of the "user is available" statuses?
77 * - TRUE: index is a valid status?
79 return(statuses
[index
].name
!= NULL
);
82 static GHashTable
*get_contact_statuses(GObject
*object
,
83 const GArray
*contacts
,
84 SIPE_UNUSED_PARAMETER GError
**error
)
86 struct sipe_backend_private
*telepathy_private
= sipe_telepathy_connection_private(object
);
87 TpBaseConnection
*base
= TP_BASE_CONNECTION(object
);
88 GHashTable
*status_table
= g_hash_table_new(g_direct_hash
,
92 for (i
= 0; i
< contacts
->len
; i
++) {
93 TpHandle contact
= g_array_index(contacts
, guint
, i
);
95 GHashTable
*parameters
;
97 /* we get our own status from the connection, and everyone
98 * else's status from the contact lists */
99 if (contact
== tp_base_connection_get_self_handle(base
)) {
100 activity
= telepathy_private
->activity
;
103 activity
= sipe_telepathy_buddy_get_presence(telepathy_private
->contact_list
,
107 parameters
= g_hash_table_new_full(g_str_hash
,
110 (GDestroyNotify
) tp_g_value_slice_free
);
111 g_hash_table_insert(status_table
,
112 GUINT_TO_POINTER(contact
),
113 tp_presence_status_new(activity
,
115 g_hash_table_unref(parameters
);
118 return(status_table
);
121 static void update_status(struct sipe_backend_private
*telepathy_private
,
123 const gchar
*message
,
124 const TpPresenceStatus
*status
,
127 GObject
*connection
= G_OBJECT(telepathy_private
->connection
);
128 GHashTable
*presences
;
130 /* update internal status */
131 telepathy_private
->activity
= activity
;
132 g_free(telepathy_private
->message
);
133 telepathy_private
->message
= NULL
;
135 telepathy_private
->message
= g_strdup(message
);
137 /* outgoing status update */
139 sipe_core_status_set(telepathy_private
->public,
143 /* emit status update signal */
144 presences
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
145 g_hash_table_insert(presences
,
146 GUINT_TO_POINTER(tp_base_connection_get_self_handle(TP_BASE_CONNECTION(connection
))),
148 tp_presence_mixin_emit_presence_update(connection
, presences
);
149 g_hash_table_unref(presences
);
152 static gboolean
set_own_status(GObject
*object
,
153 const TpPresenceStatus
*status
,
154 SIPE_UNUSED_PARAMETER GError
**error
)
156 struct sipe_backend_private
*telepathy_private
= sipe_telepathy_connection_private(object
);
157 guint activity
= SIPE_ACTIVITY_AVAILABLE
;
158 const gchar
*message
= NULL
;
160 if (!telepathy_private
)
164 activity
= status
->index
;
166 if (status
->optional_arguments
)
167 message
= tp_asv_get_string(status
->optional_arguments
,
171 SIPE_DEBUG_INFO("set_own_status: %d '%s'", activity
,
172 message
? message
: "(none)");
173 update_status(telepathy_private
, activity
, message
, status
, TRUE
);
179 void sipe_telepathy_status_init(GObjectClass
*object_class
,
182 tp_presence_mixin_class_init(object_class
,
185 get_contact_statuses
,
192 * Backend adaptor functions
194 guint
sipe_backend_status(struct sipe_core_public
*sipe_public
)
196 return(sipe_public
->backend_private
->activity
);
199 gboolean
sipe_backend_status_changed(struct sipe_core_public
*sipe_public
,
201 const gchar
*message
)
203 struct sipe_backend_private
*telepathy_private
= sipe_public
->backend_private
;
205 if ((activity
== telepathy_private
->activity
) &&
206 sipe_strequal(message
, telepathy_private
->message
))
215 * - incoming status updates (roaming)
216 * - induced status updates (calendar)
218 void sipe_backend_status_and_note(struct sipe_core_public
*sipe_public
,
220 const gchar
*message
)
222 struct sipe_backend_private
*telepathy_private
= sipe_public
->backend_private
;
223 GHashTable
*optional
= NULL
;
224 TpPresenceStatus
*status
;
227 optional
= tp_asv_new("message", G_TYPE_STRING
, message
,
230 status
= tp_presence_status_new(activity
, optional
);
232 g_hash_table_unref(optional
);
234 update_status(telepathy_private
, activity
, message
, status
, FALSE
);
235 tp_presence_status_free(status
);