81
87
G_DEFINE_TYPE (EmpathyTpCall, empathy_tp_call, G_TYPE_OBJECT)
84
tp_call_set_status (EmpathyTpCall *call,
85
EmpathyTpCallStatus status)
87
EmpathyTpCallPriv *priv = GET_PRIV (call);
89
priv->status = status;
90
g_object_notify (G_OBJECT (call), "status");
94
tp_call_set_property (GObject *object,
99
EmpathyTpCallPriv *priv = GET_PRIV (object);
103
priv->account = g_object_ref (g_value_get_object (value));
106
priv->tp_chan = g_object_ref (g_value_get_object (value));
109
tp_call_set_status (EMPATHY_TP_CALL (object),
110
g_value_get_enum (value));
113
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
119
tp_call_get_property (GObject *object,
124
EmpathyTpCallPriv *priv = GET_PRIV (object);
128
g_value_set_object (value, priv->account);
131
g_value_set_object (value, priv->tp_chan);
134
g_value_set_enum (value, priv->status);
137
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
143
tp_call_destroy_cb (TpChan *call_chan,
146
EmpathyTpCallPriv *priv = GET_PRIV (call);
148
empathy_debug (DEBUG_DOMAIN, "Channel Closed or CM crashed");
150
g_object_unref (priv->tp_chan);
151
priv->tp_chan = NULL;
152
priv->streamed_iface = NULL;
154
g_signal_emit (call, signals[DESTROY], 0);
158
tp_call_closed_cb (TpChan *call_chan,
161
EmpathyTpCallPriv *priv = GET_PRIV (call);
163
/* The channel is closed, do just like if the proxy was destroyed */
164
g_signal_handlers_disconnect_by_func (priv->tp_chan,
167
tp_call_destroy_cb (call_chan, call);
171
tp_call_stream_added_cb (DBusGProxy *streamed_iface,
173
guint contact_handle,
177
EmpathyTpCallPriv *priv = GET_PRIV (call);
179
empathy_debug (DEBUG_DOMAIN, "Stream added: id=%d, stream_type=%d",
180
stream_id, stream_type);
182
switch (stream_type) {
183
case TP_MEDIA_STREAM_TYPE_AUDIO:
184
priv->audio_stream = stream_id;
186
case TP_MEDIA_STREAM_TYPE_VIDEO:
187
priv->video_stream = stream_id;
190
empathy_debug (DEBUG_DOMAIN, "Unknown stream type: %d", stream_type);
196
tp_call_stream_removed_cb (DBusGProxy *streamed_iface,
200
EmpathyTpCallPriv *priv = GET_PRIV (call);
202
empathy_debug (DEBUG_DOMAIN, "Stream removed: %d", stream_id);
204
if (stream_id == priv->audio_stream) {
205
priv->audio_stream = 0;
207
else if (stream_id == priv->video_stream) {
208
priv->video_stream = 0;
213
tp_call_list_streams_cb (DBusGProxy *proxy,
221
empathy_debug (DEBUG_DOMAIN, "Failed to list streams: %s",
226
for (i = 0; i < streams->len; i++) {
229
guint contact_handle;
232
values = g_ptr_array_index (streams, i);
233
stream_id = g_value_get_uint (g_value_array_get_nth (values, 0));
234
contact_handle = g_value_get_uint (g_value_array_get_nth (values, 1));
235
stream_type = g_value_get_uint (g_value_array_get_nth (values, 2));
237
tp_call_stream_added_cb (proxy,
90
tp_call_stream_state_changed_cb (DBusGProxy *channel,
95
EmpathyTpCallPriv *priv = GET_PRIV (call);
97
empathy_debug (DEBUG_DOMAIN,
98
"Stream state changed - stream id: %d, state state: %d",
99
stream_id, stream_state);
101
if (stream_id == priv->audio->id)
103
priv->audio->state = stream_state;
105
else if (stream_id == priv->video->id)
107
priv->video->state = stream_state;
108
if (stream_state == TP_MEDIA_STREAM_STATE_CONNECTED)
110
if (priv->video->direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE)
112
empathy_debug (DEBUG_DOMAIN, "RECEIVING");
113
g_signal_emit (call, signals[RECEIVING_VIDEO_SIGNAL], 0, TRUE);
115
if (priv->video->direction & TP_MEDIA_STREAM_DIRECTION_SEND)
117
empathy_debug (DEBUG_DOMAIN, "SENDING");
118
g_signal_emit (call, signals[SENDING_VIDEO_SIGNAL], 0, TRUE);
123
g_signal_emit (call, signals[STATUS_CHANGED_SIGNAL], 0);
127
tp_call_identify_streams (EmpathyTpCall *call)
129
EmpathyTpCallPriv *priv = GET_PRIV (call);
130
GPtrArray *stream_infos;
131
DBusGProxy *streamed_iface;
132
GError *error = NULL;
135
empathy_debug (DEBUG_DOMAIN, "Identifying audio/video streams");
137
streamed_iface = tp_chan_get_interface (priv->channel,
138
TELEPATHY_CHAN_IFACE_STREAMED_QUARK);
140
if (!tp_chan_type_streamed_media_list_streams (streamed_iface, &stream_infos,
143
empathy_debug (DEBUG_DOMAIN, "Couldn't list audio/video streams: %s",
145
g_clear_error (&error);
149
for (i = 0; i < stream_infos->len; i++)
156
guint stream_direction;
158
values = g_ptr_array_index (stream_infos, i);
159
stream_id = g_value_get_uint (g_value_array_get_nth (values, 0));
160
stream_handle = g_value_get_uint (g_value_array_get_nth (values, 1));
161
stream_type = g_value_get_uint (g_value_array_get_nth (values, 2));
162
stream_state = g_value_get_uint (g_value_array_get_nth (values, 3));
163
stream_direction = g_value_get_uint (g_value_array_get_nth (values, 4));
167
case TP_MEDIA_STREAM_TYPE_AUDIO:
168
empathy_debug (DEBUG_DOMAIN,
169
"Audio stream - id: %d, state: %d, direction: %d",
170
stream_id, stream_state, stream_direction);
171
priv->audio->exists = TRUE;
172
priv->audio->id = stream_id;
173
priv->audio->state = stream_state;
174
priv->audio->direction = stream_direction;
176
case TP_MEDIA_STREAM_TYPE_VIDEO:
177
empathy_debug (DEBUG_DOMAIN,
178
"Video stream - id: %d, state: %d, direction: %d",
179
stream_id, stream_state, stream_direction);
180
priv->video->exists = TRUE;
181
priv->video->id = stream_id;
182
priv->video->state = stream_state;
183
priv->video->direction = stream_direction;
186
empathy_debug (DEBUG_DOMAIN, "Unknown stream type: %d",
190
g_value_array_free (values);
195
tp_call_stream_added_cb (DBusGProxy *channel,
197
guint contact_handle,
201
empathy_debug (DEBUG_DOMAIN,
202
"Stream added - stream id: %d, contact handle: %d, stream type: %d",
203
stream_id, contact_handle, stream_type);
205
tp_call_identify_streams (call);
210
tp_call_stream_removed_cb (DBusGProxy *channel,
214
EmpathyTpCallPriv *priv = GET_PRIV (call);
216
empathy_debug (DEBUG_DOMAIN, "Stream removed - stream id: %d", stream_id);
218
if (stream_id == priv->audio->id)
220
priv->audio->exists = FALSE;
222
else if (stream_id == priv->video->id)
224
priv->video->exists = FALSE;
229
tp_call_channel_closed_cb (TpChan *channel,
232
EmpathyTpCallPriv *priv = GET_PRIV (call);
233
DBusGProxy *streamed_iface;
234
DBusGProxy *group_iface;
236
empathy_debug (DEBUG_DOMAIN, "Channel closed");
238
priv->status = EMPATHY_TP_CALL_STATUS_CLOSED;
239
g_signal_emit (call, signals[STATUS_CHANGED_SIGNAL], 0);
241
streamed_iface = tp_chan_get_interface (priv->channel,
242
TELEPATHY_CHAN_IFACE_STREAMED_QUARK);
243
group_iface = tp_chan_get_interface (priv->channel,
244
TELEPATHY_CHAN_IFACE_GROUP_QUARK);
246
dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->channel), "Closed",
247
G_CALLBACK (tp_call_channel_closed_cb), (gpointer) call);
248
dbus_g_proxy_disconnect_signal (streamed_iface, "StreamStateChanged",
249
G_CALLBACK (tp_call_stream_state_changed_cb), (gpointer) call);
250
dbus_g_proxy_disconnect_signal (streamed_iface, "StreamAdded",
251
G_CALLBACK (tp_call_stream_added_cb), (gpointer) call);
252
dbus_g_proxy_disconnect_signal (streamed_iface, "StreamRemoved",
253
G_CALLBACK (tp_call_stream_removed_cb), (gpointer) call);
257
tp_call_stream_direction_changed_cb (DBusGProxy *channel,
259
guint stream_direction,
263
EmpathyTpCallPriv *priv = GET_PRIV (call);
265
empathy_debug (DEBUG_DOMAIN,
266
"Stream direction changed - stream: %d, direction: %d",
267
stream_id, stream_direction);
269
if (stream_id == priv->audio->id)
271
priv->audio->direction = stream_direction;
273
else if (stream_id == priv->video->id)
275
priv->video->direction = stream_direction;
277
if (stream_direction & TP_MEDIA_STREAM_DIRECTION_RECEIVE)
279
empathy_debug (DEBUG_DOMAIN, "RECEIVING");
280
g_signal_emit (call, signals[RECEIVING_VIDEO_SIGNAL], 0, TRUE);
284
empathy_debug (DEBUG_DOMAIN, "NOT RECEIVING");
285
g_signal_emit (call, signals[RECEIVING_VIDEO_SIGNAL], 0, FALSE);
288
if (stream_direction & TP_MEDIA_STREAM_DIRECTION_SEND)
290
empathy_debug (DEBUG_DOMAIN, "SENDING");
291
g_signal_emit (call, signals[SENDING_VIDEO_SIGNAL], 0, TRUE);
295
empathy_debug (DEBUG_DOMAIN, "NOT SENDING");
296
g_signal_emit (call, signals[SENDING_VIDEO_SIGNAL], 0, FALSE);
302
tp_call_request_streams_for_capabilities (EmpathyTpCall *call,
303
EmpathyCapabilities capabilities)
305
EmpathyTpCallPriv *priv = GET_PRIV (call);
306
DBusGProxy *streamed_iface;
307
GArray *stream_types;
310
GError *error = NULL;
312
empathy_debug (DEBUG_DOMAIN, "Requesting new stream for capabilities %d",
315
streamed_iface = tp_chan_get_interface (priv->channel,
316
TELEPATHY_CHAN_IFACE_STREAMED_QUARK);
317
stream_types = g_array_new (FALSE, FALSE, sizeof (guint));
318
handle = empathy_contact_get_handle (priv->contact);
320
if (capabilities & EMPATHY_CAPABILITIES_AUDIO)
322
stream_type = TP_MEDIA_STREAM_TYPE_AUDIO;
323
g_array_append_val (stream_types, stream_type);
325
if (capabilities & EMPATHY_CAPABILITIES_VIDEO)
327
stream_type = TP_MEDIA_STREAM_TYPE_VIDEO;
328
g_array_append_val (stream_types, stream_type);
331
if (!tp_chan_type_streamed_media_request_streams (streamed_iface, handle,
332
stream_types, NULL, &error))
334
empathy_debug (DEBUG_DOMAIN, "Couldn't request new stream: %s",
336
g_clear_error (&error);
339
g_array_free (stream_types, TRUE);
343
tp_call_request_streams_capabilities_cb (EmpathyContact *contact,
344
GParamSpec *property,
347
EmpathyTpCall *call = EMPATHY_TP_CALL (user_data);
349
g_signal_handlers_disconnect_by_func (contact,
350
tp_call_request_streams_capabilities_cb,
353
tp_call_request_streams_for_capabilities (call,
354
empathy_contact_get_capabilities (contact));
358
tp_call_request_streams (EmpathyTpCall *call)
360
EmpathyTpCallPriv *priv = GET_PRIV (call);
361
EmpathyCapabilities capabilities;
362
DBusGProxy *capabilities_iface;
364
empathy_debug (DEBUG_DOMAIN,
365
"Requesting appropriate audio/video streams from contact");
368
/* FIXME: SIP don't have capabilities interface but we know it supports
369
* only audio and not video. */
370
capabilities_iface = tp_conn_get_interface (priv->connection,
371
TP_IFACE_QUARK_CONNECTION_INTERFACE_CAPABILITIES);
372
if (!capabilities_iface)
374
capabilities = EMPATHY_CAPABILITIES_AUDIO;
378
capabilities = empathy_contact_get_capabilities (priv->contact);
379
if (capabilities == EMPATHY_CAPABILITIES_UNKNOWN)
381
g_signal_connect (priv->contact, "notify::capabilities",
382
G_CALLBACK (tp_call_request_streams_capabilities_cb), call);
387
tp_call_request_streams_for_capabilities (call, capabilities);
391
tp_call_is_ready (EmpathyTpCall *call)
393
EmpathyTpCallPriv *priv = GET_PRIV (call);
394
EmpathyContact *self_contact;
396
GList *local_pendings;
397
GList *remote_pendings;
399
if (priv->status > EMPATHY_TP_CALL_STATUS_READYING)
402
members = empathy_tp_group_get_members (priv->group);
406
self_contact = empathy_tp_group_get_self_contact (priv->group);
407
local_pendings = empathy_tp_group_get_local_pendings (priv->group);
408
remote_pendings = empathy_tp_group_get_remote_pendings (priv->group);
410
if (local_pendings &&
411
empathy_contact_equal (EMPATHY_CONTACT (((EmpathyPendingInfo *)
412
local_pendings->data)->member), self_contact))
414
empathy_debug (DEBUG_DOMAIN,
415
"Incoming call is ready - %p",
416
((EmpathyPendingInfo *) local_pendings->data)->member);
417
priv->is_incoming = TRUE;
418
priv->contact = g_object_ref (members->data);
420
else if (remote_pendings &&
421
empathy_contact_equal (EMPATHY_CONTACT (members->data), self_contact))
423
empathy_debug (DEBUG_DOMAIN,
424
"Outgoing call is ready - %p", remote_pendings->data);
425
priv->is_incoming = FALSE;
426
priv->contact = g_object_ref (remote_pendings->data);
427
tp_call_request_streams (call);
430
g_object_unref (self_contact);
431
g_list_foreach (members, (GFunc) g_object_unref, NULL);
432
g_list_free (members);
433
g_list_foreach (local_pendings, (GFunc) empathy_pending_info_free, NULL);
434
g_list_free (local_pendings);
435
g_list_foreach (remote_pendings, (GFunc) g_object_unref, NULL);
436
g_list_free (remote_pendings);
440
priv->status = EMPATHY_TP_CALL_STATUS_PENDING;
441
g_signal_emit (call, signals[STATUS_CHANGED_SIGNAL], 0);
246
446
tp_call_member_added_cb (EmpathyTpGroup *group,
247
EmpathyContact *contact,
248
EmpathyContact *actor,
250
const gchar *message,
253
EmpathyTpCallPriv *priv = GET_PRIV (call);
255
empathy_debug (DEBUG_DOMAIN, "Members added %s (%d)",
256
empathy_contact_get_id (contact),
257
empathy_contact_get_handle (contact));
259
if (!priv->contact) {
260
if (!empathy_contact_is_user (contact)) {
261
priv->is_incoming = TRUE;
262
priv->contact = g_object_ref (contact);
263
tp_call_set_status (call, EMPATHY_TP_CALL_STATUS_RINGING);
268
/* We already have the other contact, that means we now have 2 members,
269
* so we can start the call */
270
tp_call_set_status (call, EMPATHY_TP_CALL_STATUS_RUNNING);
447
EmpathyContact *contact,
448
EmpathyContact *actor,
450
const gchar *message,
453
EmpathyTpCallPriv *priv = GET_PRIV (call);
455
empathy_debug (DEBUG_DOMAIN, "New member added callback %p", contact);
456
tp_call_is_ready (call);
458
if (priv->status == EMPATHY_TP_CALL_STATUS_PENDING)
460
if ((priv->is_incoming &&
461
!empathy_contact_equal (contact, priv->contact))
462
|| (!priv->is_incoming &&
463
empathy_contact_equal (contact, priv->contact)))
465
priv->status = EMPATHY_TP_CALL_STATUS_ACCEPTED;
466
g_signal_emit (call, signals[STATUS_CHANGED_SIGNAL], 0);
472
tp_call_local_pending_cb (EmpathyTpGroup *group,
473
EmpathyContact *contact,
474
EmpathyContact *actor,
476
const gchar *message,
479
empathy_debug (DEBUG_DOMAIN, "New local pending added callback %p", contact);
480
tp_call_is_ready (call);
274
484
tp_call_remote_pending_cb (EmpathyTpGroup *group,
275
EmpathyContact *contact,
276
EmpathyContact *actor,
278
const gchar *message,
281
EmpathyTpCallPriv *priv = GET_PRIV (call);
283
empathy_debug (DEBUG_DOMAIN, "Remote pending: %s (%d)",
284
empathy_contact_get_id (contact),
285
empathy_contact_get_handle (contact));
287
if (!priv->contact) {
288
priv->is_incoming = FALSE;
289
priv->contact = g_object_ref (contact);
290
tp_call_set_status (call, EMPATHY_TP_CALL_STATUS_RINGING);
295
tp_call_async_cb (DBusGProxy *proxy,
300
empathy_debug (DEBUG_DOMAIN, "Failed to %s: %s",
485
EmpathyContact *contact,
486
EmpathyContact *actor,
488
const gchar *message,
491
empathy_debug (DEBUG_DOMAIN, "New remote pending added callback %p", contact);
492
tp_call_is_ready (call);
496
tp_call_async_cb (TpProxy *proxy,
503
empathy_debug (DEBUG_DOMAIN, "Error %s: %s",
504
user_data, error->message);
509
tp_call_invalidated_cb (TpProxy *stream_engine,
515
empathy_debug (DEBUG_DOMAIN, "Stream engine proxy invalidated: %s",
517
empathy_tp_call_close_channel (call);
521
tp_call_watch_name_owner_cb (TpDBusDaemon *daemon,
523
const gchar *new_owner,
526
if (G_STR_EMPTY (new_owner))
528
empathy_debug (DEBUG_DOMAIN, "Stream engine falled off the bus");
529
empathy_tp_call_close_channel (call);
534
tp_call_start_stream_engine (EmpathyTpCall *call)
536
EmpathyTpCallPriv *priv = GET_PRIV (call);
538
empathy_debug (DEBUG_DOMAIN, "Revving up the stream engine");
540
priv->stream_engine = g_object_new (TP_TYPE_PROXY,
541
"bus-name", STREAM_ENGINE_BUS_NAME,
542
"dbus-connection", tp_get_bus (),
543
"object-path", STREAM_ENGINE_OBJECT_PATH,
545
tp_proxy_add_interface_by_id (priv->stream_engine,
546
EMP_IFACE_QUARK_STREAM_ENGINE);
547
tp_proxy_add_interface_by_id (priv->stream_engine,
548
EMP_IFACE_QUARK_CHANNEL_HANDLER);
550
g_signal_connect (priv->stream_engine, "invalidated",
551
G_CALLBACK (tp_call_invalidated_cb),
554
/* FIXME: dbus daemon should be unique */
555
priv->dbus_daemon = tp_dbus_daemon_new (tp_get_bus ());
556
tp_dbus_daemon_watch_name_owner (priv->dbus_daemon, STREAM_ENGINE_BUS_NAME,
557
tp_call_watch_name_owner_cb,
560
emp_cli_channel_handler_call_handle_channel (priv->stream_engine, -1,
561
dbus_g_proxy_get_bus_name (DBUS_G_PROXY (priv->connection)),
562
dbus_g_proxy_get_path (DBUS_G_PROXY (priv->connection)),
564
dbus_g_proxy_get_path (DBUS_G_PROXY (priv->channel)),
565
priv->channel->handle_type, priv->channel->handle,
567
"calling handle channel", NULL,
307
tp_call_constructor (GType type,
309
GObjectConstructParam *props)
572
tp_call_constructor (GType type,
573
guint n_construct_params,
574
GObjectConstructParam *construct_params)
312
EmpathyTpCallPriv *priv;
316
call = G_OBJECT_CLASS (empathy_tp_call_parent_class)->constructor (type, n_props, props);
317
priv = GET_PRIV (call);
319
priv->group = empathy_tp_group_new (priv->account, priv->tp_chan);
320
priv->streamed_iface = tp_chan_get_interface (priv->tp_chan,
321
TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA);
323
/* Connect signals */
324
dbus_g_proxy_connect_signal (priv->streamed_iface, "StreamAdded",
325
G_CALLBACK (tp_call_stream_added_cb),
327
dbus_g_proxy_connect_signal (priv->streamed_iface, "StreamRemoved",
328
G_CALLBACK (tp_call_stream_removed_cb),
330
dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->tp_chan), "Closed",
331
G_CALLBACK (tp_call_closed_cb),
333
g_signal_connect (priv->tp_chan, "destroy",
334
G_CALLBACK (tp_call_destroy_cb),
336
g_signal_connect (priv->group, "member-added",
337
G_CALLBACK (tp_call_member_added_cb),
339
g_signal_connect (priv->group, "remote-pending",
340
G_CALLBACK (tp_call_remote_pending_cb),
343
/* Start stream engine */
344
mc = empathy_mission_control_new ();
345
tp_conn = mission_control_get_connection (mc, priv->account, NULL);
346
priv->se_ch_proxy = dbus_g_proxy_new_for_name (tp_get_bus (),
347
STREAM_ENGINE_BUS_NAME,
348
STREAM_ENGINE_OBJECT_PATH,
349
CHANNEL_HANDLER_INTERFACE);
350
priv->se_proxy = dbus_g_proxy_new_for_name (tp_get_bus (),
351
STREAM_ENGINE_BUS_NAME,
352
STREAM_ENGINE_OBJECT_PATH,
353
STREAM_ENGINE_INTERFACE);
354
org_freedesktop_Telepathy_ChannelHandler_handle_channel_async (priv->se_ch_proxy,
355
dbus_g_proxy_get_bus_name (DBUS_G_PROXY (tp_conn)),
356
dbus_g_proxy_get_path (DBUS_G_PROXY (tp_conn)),
358
dbus_g_proxy_get_path (DBUS_G_PROXY (priv->tp_chan)),
359
priv->tp_chan->handle_type,
360
priv->tp_chan->handle,
363
g_object_unref (tp_conn);
367
tp_chan_type_streamed_media_list_streams_async (priv->streamed_iface,
368
tp_call_list_streams_cb,
578
EmpathyTpCallPriv *priv;
579
DBusGProxy *streamed_iface;
583
object = G_OBJECT_CLASS (empathy_tp_call_parent_class)->constructor (type,
584
n_construct_params, construct_params);
586
call = EMPATHY_TP_CALL (object);
587
priv = GET_PRIV (call);
589
dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->channel), "Closed",
590
G_CALLBACK (tp_call_channel_closed_cb), (gpointer) call, NULL);
592
streamed_iface = tp_chan_get_interface (priv->channel,
593
TELEPATHY_CHAN_IFACE_STREAMED_QUARK);
594
dbus_g_proxy_connect_signal (streamed_iface, "StreamStateChanged",
595
G_CALLBACK (tp_call_stream_state_changed_cb),
596
(gpointer) call, NULL);
597
dbus_g_proxy_connect_signal (streamed_iface, "StreamDirectionChanged",
598
G_CALLBACK (tp_call_stream_direction_changed_cb),
599
(gpointer) call, NULL);
600
dbus_g_proxy_connect_signal (streamed_iface, "StreamAdded",
601
G_CALLBACK (tp_call_stream_added_cb), (gpointer) call, NULL);
602
dbus_g_proxy_connect_signal (streamed_iface, "StreamRemoved",
603
G_CALLBACK (tp_call_stream_removed_cb), (gpointer) call, NULL);
605
mc = empathy_mission_control_new ();
606
account = mission_control_get_account_for_connection (mc, priv->connection,
608
priv->group = empathy_tp_group_new (account, priv->channel);
611
g_signal_connect (G_OBJECT (priv->group), "member-added",
612
G_CALLBACK (tp_call_member_added_cb), (gpointer) call);
613
g_signal_connect (G_OBJECT (priv->group), "local-pending",
614
G_CALLBACK (tp_call_local_pending_cb), (gpointer) call);
615
g_signal_connect (G_OBJECT (priv->group), "remote-pending",
616
G_CALLBACK (tp_call_remote_pending_cb), (gpointer) call);
618
tp_call_start_stream_engine (call);
619
/* FIXME: unnecessary for outgoing? */
620
tp_call_identify_streams (call);
375
626
tp_call_finalize (GObject *object)
377
EmpathyTpCallPriv *priv = GET_PRIV (object);
379
empathy_debug (DEBUG_DOMAIN, "Finalizing: %p", object);
382
GError *error = NULL;
384
g_signal_handlers_disconnect_by_func (priv->tp_chan,
387
empathy_debug (DEBUG_DOMAIN, "Closing channel...");
388
if (!tp_chan_close (DBUS_G_PROXY (priv->tp_chan), &error)) {
389
empathy_debug (DEBUG_DOMAIN,
390
"Error closing text channel: %s",
391
error ? error->message : "No error given");
392
g_clear_error (&error);
394
g_object_unref (priv->tp_chan);
397
g_object_unref (priv->group);
398
g_object_unref (priv->contact);
399
g_object_unref (priv->account);
400
g_object_unref (priv->se_ch_proxy);
401
g_object_unref (priv->se_proxy);
403
G_OBJECT_CLASS (empathy_tp_call_parent_class)->finalize (object);
628
EmpathyTpCallPriv *priv = GET_PRIV (object);
630
empathy_debug (DEBUG_DOMAIN, "Finalizing: %p", object);
632
g_slice_free (EmpathyTpCallStream, priv->audio);
633
g_slice_free (EmpathyTpCallStream, priv->video);
634
g_object_unref (priv->group);
636
if (priv->connection != NULL)
637
g_object_unref (priv->connection);
639
if (priv->channel != NULL)
640
g_object_unref (priv->channel);
642
if (priv->stream_engine != NULL)
643
g_object_unref (priv->stream_engine);
645
if (priv->contact != NULL)
646
g_object_unref (priv->contact);
648
if (priv->dbus_daemon != NULL)
650
tp_dbus_daemon_cancel_name_owner_watch (priv->dbus_daemon,
651
STREAM_ENGINE_BUS_NAME,
652
tp_call_watch_name_owner_cb,
654
g_object_unref (priv->dbus_daemon);
657
(G_OBJECT_CLASS (empathy_tp_call_parent_class)->finalize) (object);
661
tp_call_set_property (GObject *object,
666
EmpathyTpCallPriv *priv = GET_PRIV (object);
670
case PROP_CONNECTION:
671
priv->connection = g_value_dup_object (value);
674
priv->channel = g_value_dup_object (value);
677
/* FIXME should this one be writable in the first place ? */
678
g_assert (priv->contact == NULL);
679
priv->contact = g_value_dup_object (value);
681
case PROP_IS_INCOMING:
682
priv->is_incoming = g_value_get_boolean (value);
685
priv->status = g_value_get_uint (value);
687
case PROP_AUDIO_STREAM:
688
priv->audio = g_value_get_pointer (value);
690
case PROP_VIDEO_STREAM:
691
priv->video = g_value_get_pointer (value);
694
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
701
tp_call_get_property (GObject *object,
706
EmpathyTpCallPriv *priv = GET_PRIV (object);
710
case PROP_CONNECTION:
711
g_value_set_object (value, priv->connection);
714
g_value_set_object (value, priv->channel);
717
g_value_set_object (value, priv->contact);
719
case PROP_IS_INCOMING:
720
g_value_set_boolean (value, priv->is_incoming);
723
g_value_set_uint (value, priv->status);
725
case PROP_AUDIO_STREAM:
726
g_value_set_pointer (value, priv->audio);
728
case PROP_VIDEO_STREAM:
729
g_value_set_pointer (value, priv->video);
732
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
407
738
empathy_tp_call_class_init (EmpathyTpCallClass *klass)
409
GObjectClass *object_class = G_OBJECT_CLASS (klass);
411
object_class->constructor = tp_call_constructor;
412
object_class->finalize = tp_call_finalize;
413
object_class->set_property = tp_call_set_property;
414
object_class->get_property = tp_call_get_property;
416
/* Construct-only properties */
417
g_object_class_install_property (object_class,
419
g_param_spec_object ("account",
421
"The account associated with the channel",
424
G_PARAM_CONSTRUCT_ONLY));
425
g_object_class_install_property (object_class,
427
g_param_spec_object ("tp-chan",
429
"The media channel for the call",
432
G_PARAM_CONSTRUCT_ONLY));
434
/* Normal properties */
435
g_object_class_install_property (object_class,
437
g_param_spec_enum ("status",
439
"The status of the call",
440
EMPATHY_TYPE_TP_CALL_STATUS,
441
EMPATHY_TP_CALL_STATUS_PREPARING,
446
g_signal_new ("destroy",
447
G_TYPE_FROM_CLASS (klass),
451
g_cclosure_marshal_VOID__VOID,
456
g_type_class_add_private (klass, sizeof (EmpathyTpCallPriv));
740
GObjectClass *object_class = G_OBJECT_CLASS (klass);
744
object_class->constructor = tp_call_constructor;
745
object_class->finalize = tp_call_finalize;
746
object_class->set_property = tp_call_set_property;
747
object_class->get_property = tp_call_get_property;
749
g_type_class_add_private (klass, sizeof (EmpathyTpCallPriv));
751
signals[STATUS_CHANGED_SIGNAL] =
752
g_signal_new ("status-changed", G_TYPE_FROM_CLASS (klass),
753
G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
755
signals[RECEIVING_VIDEO_SIGNAL] =
756
g_signal_new ("receiving-video", G_TYPE_FROM_CLASS (klass),
757
G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN,
758
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
759
signals[SENDING_VIDEO_SIGNAL] =
760
g_signal_new ("sending-video", G_TYPE_FROM_CLASS (klass),
761
G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN,
762
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
764
g_object_class_install_property (object_class, PROP_CONNECTION,
765
g_param_spec_object ("connection", "connection", "connection",
767
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
768
G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
769
g_object_class_install_property (object_class, PROP_CHANNEL,
770
g_param_spec_object ("channel", "channel", "channel",
772
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
773
G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
774
g_object_class_install_property (object_class, PROP_CONTACT,
775
g_param_spec_object ("contact", "Call contact", "Call contact",
776
EMPATHY_TYPE_CONTACT,
777
G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
778
g_object_class_install_property (object_class, PROP_IS_INCOMING,
779
g_param_spec_boolean ("is-incoming", "Is media stream incoming",
780
"Is media stream incoming", FALSE, G_PARAM_READABLE |
781
G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
782
g_object_class_install_property (object_class, PROP_STATUS,
783
g_param_spec_uint ("status", "Call status",
784
"Call status", 0, 255, 0, G_PARAM_READABLE | G_PARAM_STATIC_NICK |
785
G_PARAM_STATIC_BLURB));
786
g_object_class_install_property (object_class, PROP_AUDIO_STREAM,
787
g_param_spec_pointer ("audio-stream", "Audio stream data",
789
G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
790
g_object_class_install_property (object_class, PROP_VIDEO_STREAM,
791
g_param_spec_pointer ("video-stream", "Video stream data",
793
G_PARAM_READABLE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
460
797
empathy_tp_call_init (EmpathyTpCall *call)
799
EmpathyTpCallPriv *priv = GET_PRIV (call);
801
priv->status = EMPATHY_TP_CALL_STATUS_READYING;
802
priv->contact = NULL;
803
priv->audio = g_slice_new0 (EmpathyTpCallStream);
804
priv->video = g_slice_new0 (EmpathyTpCallStream);
805
priv->audio->exists = FALSE;
806
priv->video->exists = FALSE;
465
empathy_tp_call_new (McAccount *account, TpChan *channel)
467
return g_object_new (EMPATHY_TYPE_TP_CALL,
474
empathy_tp_call_is_incoming (EmpathyTpCall *call)
476
EmpathyTpCallPriv *priv = GET_PRIV (call);
478
return priv->is_incoming;
482
empathy_tp_call_get_status (EmpathyTpCall *call)
484
EmpathyTpCallPriv *priv = GET_PRIV (call);
490
empathy_tp_call_get_contact (EmpathyTpCall *call)
492
EmpathyTpCallPriv *priv = GET_PRIV (call);
494
return priv->contact;
498
empathy_tp_call_accept (EmpathyTpCall *call)
500
EmpathyTpCallPriv *priv = GET_PRIV (call);
501
EmpathyContact *contact;
503
contact = empathy_tp_group_get_self_contact (priv->group);
504
empathy_tp_group_add_member (priv->group, contact, "");
508
empathy_tp_call_invite (EmpathyTpCall *call,
509
EmpathyContact *contact)
511
EmpathyTpCallPriv *priv = GET_PRIV (call);
513
empathy_tp_group_add_member (priv->group, contact, "you're welcome");
517
empathy_tp_call_request_streams (EmpathyTpCall *call,
521
EmpathyTpCallPriv *priv = GET_PRIV (call);
522
GArray *stream_types;
526
empathy_debug (DEBUG_DOMAIN, "Requesting streams for audio=%s video=%s",
527
audio ? "Yes" : "No",
528
video ? "Yes" : "No");
530
stream_types = g_array_new (FALSE, FALSE, sizeof (guint));
532
type = TP_MEDIA_STREAM_TYPE_AUDIO;
533
g_array_append_val (stream_types, type);
536
type = TP_MEDIA_STREAM_TYPE_VIDEO;
537
g_array_append_val (stream_types, type);
540
handle = empathy_contact_get_handle (priv->contact);
541
tp_chan_type_streamed_media_request_streams_async (priv->streamed_iface,
544
tp_call_list_streams_cb,
547
g_array_free (stream_types, TRUE);
551
empathy_tp_call_send_video (EmpathyTpCall *call,
554
EmpathyTpCallPriv *priv = GET_PRIV (call);
557
if (!priv->video_stream) {
562
new_direction = TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL;
564
new_direction = TP_MEDIA_STREAM_DIRECTION_RECEIVE;
567
tp_chan_type_streamed_media_request_stream_direction_async (priv->streamed_iface,
571
"request stream direction");
575
empathy_tp_call_add_preview_window (EmpathyTpCall *call,
578
EmpathyTpCallPriv *priv = GET_PRIV (call);
580
org_freedesktop_Telepathy_StreamEngine_add_preview_window_async (priv->se_proxy,
583
"add preview window");
587
empathy_tp_call_remove_preview_window (EmpathyTpCall *call,
590
EmpathyTpCallPriv *priv = GET_PRIV (call);
592
org_freedesktop_Telepathy_StreamEngine_remove_preview_window_async (priv->se_proxy,
595
"remove preview window");
599
empathy_tp_call_set_output_window (EmpathyTpCall *call,
602
EmpathyTpCallPriv *priv = GET_PRIV (call);
604
org_freedesktop_Telepathy_StreamEngine_set_output_window_async (priv->se_proxy,
605
dbus_g_proxy_get_path (DBUS_G_PROXY (priv->tp_chan)),
609
"set output window");
810
empathy_tp_call_new (TpConn *connection, TpChan *channel)
812
return g_object_new (EMPATHY_TYPE_TP_CALL,
813
"connection", connection,
819
empathy_tp_call_accept_incoming_call (EmpathyTpCall *call)
821
EmpathyTpCallPriv *priv = GET_PRIV (call);
822
GList *local_pendings;
824
empathy_debug (DEBUG_DOMAIN, "Accepting incoming call");
826
local_pendings = empathy_tp_group_get_local_pendings (priv->group);
828
empathy_tp_group_add_member (priv->group, EMPATHY_CONTACT
829
(((EmpathyPendingInfo *) local_pendings->data)->member), NULL);
831
g_list_foreach (local_pendings, (GFunc) empathy_pending_info_free, NULL);
832
g_list_free (local_pendings);
836
empathy_tp_call_request_video_stream_direction (EmpathyTpCall *call,
839
EmpathyTpCallPriv *priv = GET_PRIV (call);
840
DBusGProxy *streamed_iface;
842
GError *error = NULL;
844
empathy_debug (DEBUG_DOMAIN,
845
"Requesting video stream direction - is_sending: %d", is_sending);
847
if (!priv->video->exists)
849
tp_call_request_streams_for_capabilities (call, EMPATHY_CAPABILITIES_VIDEO);
853
streamed_iface = tp_chan_get_interface (priv->channel,
854
TELEPATHY_CHAN_IFACE_STREAMED_QUARK);
858
new_direction = priv->video->direction | TP_MEDIA_STREAM_DIRECTION_SEND;
862
new_direction = priv->video->direction & ~TP_MEDIA_STREAM_DIRECTION_SEND;
865
if (!tp_chan_type_streamed_media_request_stream_direction (streamed_iface,
866
priv->video->id, new_direction, &error))
868
empathy_debug (DEBUG_DOMAIN,
869
"Couldn't request video stream direction: %s", error->message);
870
g_clear_error (&error);
875
empathy_tp_call_close_channel (EmpathyTpCall *call)
877
EmpathyTpCallPriv *priv = GET_PRIV (call);
878
GError *error = NULL;
880
if (priv->status == EMPATHY_TP_CALL_STATUS_CLOSED)
883
empathy_debug (DEBUG_DOMAIN, "Closing channel");
885
if (!tp_chan_close (DBUS_G_PROXY (priv->channel), &error))
887
empathy_debug (DEBUG_DOMAIN, "Error closing channel: %s",
888
error ? error->message : "No error given");
889
g_clear_error (&error);
892
priv->status = EMPATHY_TP_CALL_STATUS_CLOSED;
896
empathy_tp_call_add_preview_video (EmpathyTpCall *call,
897
guint preview_video_socket_id)
899
EmpathyTpCallPriv *priv = GET_PRIV (call);
901
empathy_debug (DEBUG_DOMAIN, "Adding preview video");
903
emp_cli_stream_engine_call_add_preview_window (priv->stream_engine, -1,
904
preview_video_socket_id,
906
"adding preview window", NULL,
911
empathy_tp_call_remove_preview_video (EmpathyTpCall *call,
912
guint preview_video_socket_id)
914
EmpathyTpCallPriv *priv = GET_PRIV (call);
916
empathy_debug (DEBUG_DOMAIN, "Removing preview video");
918
emp_cli_stream_engine_call_remove_preview_window (priv->stream_engine, -1,
919
preview_video_socket_id,
921
"removing preview window", NULL,
926
empathy_tp_call_add_output_video (EmpathyTpCall *call,
927
guint output_video_socket_id)
929
EmpathyTpCallPriv *priv = GET_PRIV (call);
931
empathy_debug (DEBUG_DOMAIN, "Adding output video - socket: %d",
932
output_video_socket_id);
934
emp_cli_stream_engine_call_set_output_window (priv->stream_engine, -1,
935
dbus_g_proxy_get_path (DBUS_G_PROXY (priv->channel)),
936
priv->video->id, output_video_socket_id,
938
"setting output window", NULL,
613
943
empathy_tp_call_set_output_volume (EmpathyTpCall *call,
616
EmpathyTpCallPriv *priv = GET_PRIV (call);
618
org_freedesktop_Telepathy_StreamEngine_set_output_volume_async (priv->se_proxy,
619
dbus_g_proxy_get_path (DBUS_G_PROXY (priv->tp_chan)),
623
"set output volume");
946
EmpathyTpCallPriv *priv = GET_PRIV (call);
948
if (priv->status == EMPATHY_TP_CALL_STATUS_CLOSED)
951
empathy_debug (DEBUG_DOMAIN, "Setting output volume: %d", volume);
953
emp_cli_stream_engine_call_set_output_volume (priv->stream_engine, -1,
954
dbus_g_proxy_get_path (DBUS_G_PROXY (priv->channel)),
955
priv->audio->id, volume,
957
"setting output volume", NULL,
628
962
empathy_tp_call_mute_output (EmpathyTpCall *call,
631
EmpathyTpCallPriv *priv = GET_PRIV (call);
633
org_freedesktop_Telepathy_StreamEngine_mute_output_async (priv->se_proxy,
634
dbus_g_proxy_get_path (DBUS_G_PROXY (priv->tp_chan)),
965
EmpathyTpCallPriv *priv = GET_PRIV (call);
967
if (priv->status == EMPATHY_TP_CALL_STATUS_CLOSED)
970
empathy_debug (DEBUG_DOMAIN, "Setting output mute: %d", is_muted);
972
emp_cli_stream_engine_call_mute_output (priv->stream_engine, -1,
973
dbus_g_proxy_get_path (DBUS_G_PROXY (priv->channel)),
974
priv->audio->id, is_muted,
976
"muting output", NULL,
643
981
empathy_tp_call_mute_input (EmpathyTpCall *call,
646
EmpathyTpCallPriv *priv = GET_PRIV (call);
648
org_freedesktop_Telepathy_StreamEngine_mute_input_async (priv->se_proxy,
649
dbus_g_proxy_get_path (DBUS_G_PROXY (priv->tp_chan)),
984
EmpathyTpCallPriv *priv = GET_PRIV (call);
986
if (priv->status == EMPATHY_TP_CALL_STATUS_CLOSED)
989
empathy_debug (DEBUG_DOMAIN, "Setting input mute: %d", is_muted);
991
emp_cli_stream_engine_call_mute_input (priv->stream_engine, -1,
992
dbus_g_proxy_get_path (DBUS_G_PROXY (priv->channel)),
993
priv->audio->id, is_muted,
995
"muting input", NULL,