No issues found
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
3 #include "shell-tp-client.h"
4
5 #include <string.h>
6
7 #include <telepathy-glib/telepathy-glib.h>
8
9 G_DEFINE_TYPE(ShellTpClient, shell_tp_client, TP_TYPE_BASE_CLIENT)
10
11 struct _ShellTpClientPrivate
12 {
13 ShellTpClientObserveChannelsImpl observe_impl;
14 gpointer user_data_obs;
15 GDestroyNotify destroy_obs;
16
17 ShellTpClientApproveChannelsImpl approve_channels_impl;
18 gpointer user_data_approve_channels;
19 GDestroyNotify destroy_approve_channels;
20
21 ShellTpClientHandleChannelsImpl handle_channels_impl;
22 gpointer user_data_handle_channels;
23 GDestroyNotify destroy_handle_channels;
24
25 ShellTpClientContactListChangedImpl contact_list_changed_impl;
26 gpointer user_data_contact_list_changed;
27 GDestroyNotify destroy_contact_list_changed;
28 };
29
30 /**
31 * ShellTpClientObserveChannelsImpl:
32 * @client: a #ShellTpClient instance
33 * @account: a #TpAccount having %TP_ACCOUNT_FEATURE_CORE prepared if possible
34 * @connection: a #TpConnection having %TP_CONNECTION_FEATURE_CORE prepared
35 * if possible
36 * @channels: (element-type TelepathyGLib.Channel): a #GList of #TpChannel,
37 * all having %TP_CHANNEL_FEATURE_CORE prepared if possible
38 * @dispatch_operation: (allow-none): a #TpChannelDispatchOperation or %NULL;
39 * the dispatch_operation is not guaranteed to be prepared
40 * @requests: (element-type TelepathyGLib.ChannelRequest): a #GList of
41 * #TpChannelRequest, all having their object-path defined but are not
42 * guaranteed to be prepared.
43 * @context: a #TpObserveChannelsContext representing the context of this
44 * D-Bus call
45 *
46 * Signature of the implementation of the ObserveChannels method.
47 */
48
49 /**
50 * ShellTpClientApproveChannelsImpl:
51 * @client: a #ShellTpClient instance
52 * @account: a #TpAccount having %TP_ACCOUNT_FEATURE_CORE prepared if possible
53 * @connection: a #TpConnection having %TP_CONNECTION_FEATURE_CORE prepared
54 * if possible
55 * @channels: (element-type TelepathyGLib.Channel): a #GList of #TpChannel,
56 * all having %TP_CHANNEL_FEATURE_CORE prepared if possible
57 * @dispatch_operation: (allow-none): a #TpChannelDispatchOperation or %NULL;
58 * the dispatch_operation is not guaranteed to be prepared
59 * @context: a #TpAddDispatchOperationContext representing the context of this
60 * D-Bus call
61 *
62 * Signature of the implementation of the AddDispatchOperation method.
63 */
64
65 /**
66 * ShellTpClientHandleChannelsImpl:
67 * @client: a #ShellTpClient instance
68 * @account: a #TpAccount having %TP_ACCOUNT_FEATURE_CORE prepared if possible
69 * @connection: a #TpConnection having %TP_CONNECTION_FEATURE_CORE prepared
70 * if possible
71 * @channels: (element-type TelepathyGLib.Channel): a #GList of #TpChannel,
72 * all having %TP_CHANNEL_FEATURE_CORE prepared if possible
73 * @requests_satisfied: (element-type TelepathyGLib.ChannelRequest): a #GList of
74 * #TpChannelRequest having their object-path defined but are not guaranteed
75 * to be prepared.
76 * @user_action_time: the time at which user action occurred, or one of the
77 * special values %TP_USER_ACTION_TIME_NOT_USER_ACTION or
78 * %TP_USER_ACTION_TIME_CURRENT_TIME
79 * (see #TpAccountChannelRequest:user-action-time for details)
80 * @context: a #TpHandleChannelsContext representing the context of this
81 * D-Bus call
82 *
83 * Signature of the implementation of the HandleChannels method.
84 */
85
86 /**
87 * ShellTpClientContactListChangedImpl:
88 * @connection: a #TpConnection having %TP_CONNECTION_FEATURE_CORE prepared
89 * if possible
90 * @added: (element-type TelepathyGLib.Contact): a #GPtrArray of added #TpContact
91 * @removed: (element-type TelepathyGLib.Contact): a #GPtrArray of removed #TpContact
92 *
93 * Signature of the implementation of the ContactListChanged method.
94 */
95
96 static void
97 shell_tp_client_init (ShellTpClient *self)
98 {
99 GHashTable *filter;
100
101 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SHELL_TYPE_TP_CLIENT,
102 ShellTpClientPrivate);
103
104 /* We only care about single-user text-based chats */
105 filter = tp_asv_new (
106 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
107 TP_IFACE_CHANNEL_TYPE_TEXT,
108 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
109 TP_HANDLE_TYPE_CONTACT,
110 NULL);
111
112 /* Observer */
113 tp_base_client_set_observer_recover (TP_BASE_CLIENT (self), TRUE);
114
115 tp_base_client_add_observer_filter (TP_BASE_CLIENT (self), filter);
116
117 /* Approver */
118 tp_base_client_add_approver_filter (TP_BASE_CLIENT (self), filter);
119
120 /* Approve room invitations. We don't handle or observe room channels so
121 * just register this filter for the approver. */
122 tp_base_client_take_approver_filter (TP_BASE_CLIENT (self), tp_asv_new (
123 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
124 TP_IFACE_CHANNEL_TYPE_TEXT,
125 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
126 TP_HANDLE_TYPE_ROOM,
127 NULL));
128
129 /* Approve calls. We let Empathy handle the call itself. */
130 tp_base_client_take_approver_filter (TP_BASE_CLIENT (self),
131 tp_asv_new (
132 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_CALL,
133 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
134 NULL));
135
136 /* Approve file transfers. We let Empathy handle the transfer itself. */
137 tp_base_client_take_approver_filter (TP_BASE_CLIENT (self),
138 tp_asv_new (
139 TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
140 TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER,
141 TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT,
142 NULL));
143
144 /* Handler */
145 tp_base_client_add_handler_filter (TP_BASE_CLIENT (self), filter);
146
147 g_hash_table_unref (filter);
148 }
149
150 static void
151 observe_channels (TpBaseClient *client,
152 TpAccount *account,
153 TpConnection *connection,
154 GList *channels,
155 TpChannelDispatchOperation *dispatch_operation,
156 GList *requests,
157 TpObserveChannelsContext *context)
158 {
159 ShellTpClient *self = (ShellTpClient *) client;
160
161 g_assert (self->priv->observe_impl != NULL);
162
163 self->priv->observe_impl (self, account, connection, channels,
164 dispatch_operation, requests, context, self->priv->user_data_obs);
165 }
166
167 static void
168 add_dispatch_operation (TpBaseClient *client,
169 TpAccount *account,
170 TpConnection *connection,
171 GList *channels,
172 TpChannelDispatchOperation *dispatch_operation,
173 TpAddDispatchOperationContext *context)
174 {
175 ShellTpClient *self = (ShellTpClient *) client;
176
177 g_assert (self->priv->approve_channels_impl != NULL);
178
179 self->priv->approve_channels_impl (self, account, connection, channels,
180 dispatch_operation, context, self->priv->user_data_approve_channels);
181 }
182
183 static void
184 handle_channels (TpBaseClient *client,
185 TpAccount *account,
186 TpConnection *connection,
187 GList *channels,
188 GList *requests_satisfied,
189 gint64 user_action_time,
190 TpHandleChannelsContext *context)
191 {
192 ShellTpClient *self = (ShellTpClient *) client;
193
194 g_assert (self->priv->handle_channels_impl != NULL);
195
196 self->priv->handle_channels_impl (self, account, connection, channels,
197 requests_satisfied, user_action_time, context,
198 self->priv->user_data_handle_channels);
199 }
200
201 static void
202 shell_tp_client_dispose (GObject *object)
203 {
204 ShellTpClient *self = SHELL_TP_CLIENT (object);
205 void (*dispose) (GObject *) =
206 G_OBJECT_CLASS (shell_tp_client_parent_class)->dispose;
207
208 if (self->priv->destroy_obs != NULL)
209 {
210 self->priv->destroy_obs (self->priv->user_data_obs);
211 self->priv->destroy_obs = NULL;
212 self->priv->user_data_obs = NULL;
213 }
214
215 if (self->priv->destroy_approve_channels != NULL)
216 {
217 self->priv->destroy_approve_channels (self->priv->user_data_approve_channels);
218 self->priv->destroy_approve_channels = NULL;
219 self->priv->user_data_approve_channels = NULL;
220 }
221
222 if (self->priv->destroy_handle_channels != NULL)
223 {
224 self->priv->destroy_handle_channels (self->priv->user_data_handle_channels);
225 self->priv->destroy_handle_channels = NULL;
226 self->priv->user_data_handle_channels = NULL;
227 }
228
229 if (self->priv->destroy_contact_list_changed != NULL)
230 {
231 self->priv->destroy_contact_list_changed (self->priv->user_data_contact_list_changed);
232 self->priv->destroy_contact_list_changed = NULL;
233 self->priv->user_data_contact_list_changed = NULL;
234 }
235
236 if (dispose != NULL)
237 dispose (object);
238 }
239
240 static void
241 shell_tp_client_class_init (ShellTpClientClass *cls)
242 {
243 GObjectClass *object_class = G_OBJECT_CLASS (cls);
244 TpBaseClientClass *base_clt_cls = TP_BASE_CLIENT_CLASS (cls);
245
246 g_type_class_add_private (cls, sizeof (ShellTpClientPrivate));
247
248 object_class->dispose = shell_tp_client_dispose;
249
250 base_clt_cls->observe_channels = observe_channels;
251 base_clt_cls->add_dispatch_operation = add_dispatch_operation;
252 base_clt_cls->handle_channels = handle_channels;
253 }
254
255 void
256 shell_tp_client_set_observe_channels_func (ShellTpClient *self,
257 ShellTpClientObserveChannelsImpl observe_impl,
258 gpointer user_data,
259 GDestroyNotify destroy)
260 {
261 g_assert (self->priv->observe_impl == NULL);
262
263 self->priv->observe_impl = observe_impl;
264 self->priv->user_data_obs = user_data;
265 self->priv->destroy_obs = destroy;
266 }
267
268 void
269 shell_tp_client_set_approve_channels_func (ShellTpClient *self,
270 ShellTpClientApproveChannelsImpl approve_channels_impl,
271 gpointer user_data,
272 GDestroyNotify destroy)
273 {
274 g_assert (self->priv->approve_channels_impl == NULL);
275
276 self->priv->approve_channels_impl = approve_channels_impl;
277 self->priv->user_data_approve_channels = user_data;
278 self->priv->destroy_approve_channels = destroy;
279 }
280
281 void
282 shell_tp_client_set_handle_channels_func (ShellTpClient *self,
283 ShellTpClientHandleChannelsImpl handle_channels_impl,
284 gpointer user_data,
285 GDestroyNotify destroy)
286 {
287 g_assert (self->priv->handle_channels_impl == NULL);
288
289 self->priv->handle_channels_impl = handle_channels_impl;
290 self->priv->user_data_handle_channels = user_data;
291 self->priv->destroy_handle_channels = destroy;
292 }
293
294 void
295 shell_tp_client_set_contact_list_changed_func (ShellTpClient *self,
296 ShellTpClientContactListChangedImpl contact_list_changed_impl,
297 gpointer user_data,
298 GDestroyNotify destroy)
299 {
300 g_assert (self->priv->contact_list_changed_impl == NULL);
301
302 self->priv->contact_list_changed_impl = contact_list_changed_impl;
303 self->priv->user_data_handle_channels = user_data;
304 self->priv->destroy_handle_channels = destroy;
305 }
306
307 static void
308 on_contact_list_changed (TpConnection *conn,
309 GPtrArray *added,
310 GPtrArray *removed,
311 gpointer user_data)
312 {
313 ShellTpClient *self = (ShellTpClient *) user_data;
314
315 g_assert (self->priv->contact_list_changed_impl != NULL);
316
317 self->priv->contact_list_changed_impl (conn,
318 added, removed,
319 self->priv->user_data_contact_list_changed);
320 }
321
322 void
323 shell_tp_client_grab_contact_list_changed (ShellTpClient *self,
324 TpConnection *conn)
325 {
326 g_signal_connect (conn, "contact-list-changed",
327 G_CALLBACK (on_contact_list_changed),
328 self);
329 }