2 * empathy-call-handler.c - Source for EmpathyCallHandler
3 * Copyright (C) 2008-2009 Collabora Ltd.
4 * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <telepathy-glib/account-channel-request.h>
26 #include <telepathy-glib/util.h>
27 #include <telepathy-glib/interfaces.h>
29 #include <telepathy-farsight/channel.h>
30 #include <telepathy-farsight/stream.h>
32 #include "empathy-call-handler.h"
33 #include "empathy-call-factory.h"
34 #include "empathy-marshal.h"
35 #include "empathy-utils.h"
37 #define DEBUG_FLAG EMPATHY_DEBUG_VOIP
38 #include <libempathy/empathy-debug.h>
40 G_DEFINE_TYPE(EmpathyCallHandler, empathy_call_handler, G_TYPE_OBJECT)
54 static guint signals[LAST_SIGNAL] = {0};
62 PROP_SEND_AUDIO_CODEC,
63 PROP_SEND_VIDEO_CODEC,
64 PROP_RECV_AUDIO_CODECS,
65 PROP_RECV_VIDEO_CODECS,
66 PROP_AUDIO_REMOTE_CANDIDATE,
67 PROP_VIDEO_REMOTE_CANDIDATE,
68 PROP_AUDIO_LOCAL_CANDIDATE,
69 PROP_VIDEO_LOCAL_CANDIDATE,
72 /* private structure */
75 gboolean dispose_has_run;
77 EmpathyContact *contact;
79 gboolean initial_audio;
80 gboolean initial_video;
82 FsCodec *send_audio_codec;
83 FsCodec *send_video_codec;
84 GList *recv_audio_codecs;
85 GList *recv_video_codecs;
86 FsCandidate *audio_remote_candidate;
87 FsCandidate *video_remote_candidate;
88 FsCandidate *audio_local_candidate;
89 FsCandidate *video_local_candidate;
90 } EmpathyCallHandlerPriv;
92 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyCallHandler)
95 empathy_call_handler_dispose (GObject *object)
97 EmpathyCallHandlerPriv *priv = GET_PRIV (object);
99 if (priv->dispose_has_run)
102 priv->dispose_has_run = TRUE;
104 if (priv->contact != NULL)
105 g_object_unref (priv->contact);
107 priv->contact = NULL;
109 if (priv->tfchannel != NULL)
110 g_object_unref (priv->tfchannel);
112 priv->tfchannel = NULL;
114 if (priv->call != NULL)
116 empathy_tp_call_close (priv->call);
117 g_object_unref (priv->call);
122 /* release any references held by the object here */
123 if (G_OBJECT_CLASS (empathy_call_handler_parent_class)->dispose)
124 G_OBJECT_CLASS (empathy_call_handler_parent_class)->dispose (object);
128 empathy_call_handler_finalize (GObject *object)
130 EmpathyCallHandlerPriv *priv = GET_PRIV (object);
132 fs_codec_destroy (priv->send_audio_codec);
133 fs_codec_destroy (priv->send_video_codec);
134 fs_codec_list_destroy (priv->recv_audio_codecs);
135 fs_codec_list_destroy (priv->recv_video_codecs);
136 fs_candidate_destroy (priv->audio_remote_candidate);
137 fs_candidate_destroy (priv->video_remote_candidate);
138 fs_candidate_destroy (priv->audio_local_candidate);
139 fs_candidate_destroy (priv->video_local_candidate);
141 if (G_OBJECT_CLASS (empathy_call_handler_parent_class)->finalize)
142 G_OBJECT_CLASS (empathy_call_handler_parent_class)->finalize (object);
146 empathy_call_handler_init (EmpathyCallHandler *obj)
148 EmpathyCallHandlerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj,
149 EMPATHY_TYPE_CALL_HANDLER, EmpathyCallHandlerPriv);
155 empathy_call_handler_constructed (GObject *object)
157 EmpathyCallHandlerPriv *priv = GET_PRIV (object);
159 if (priv->contact == NULL)
161 g_object_get (priv->call, "contact", &(priv->contact), NULL);
166 empathy_call_handler_set_property (GObject *object,
167 guint property_id, const GValue *value, GParamSpec *pspec)
169 EmpathyCallHandlerPriv *priv = GET_PRIV (object);
174 priv->contact = g_value_dup_object (value);
177 priv->call = g_value_dup_object (value);
179 case PROP_INITIAL_AUDIO:
180 priv->initial_audio = g_value_get_boolean (value);
182 case PROP_INITIAL_VIDEO:
183 priv->initial_video = g_value_get_boolean (value);
186 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
191 empathy_call_handler_get_property (GObject *object,
192 guint property_id, GValue *value, GParamSpec *pspec)
194 EmpathyCallHandlerPriv *priv = GET_PRIV (object);
199 g_value_set_object (value, priv->contact);
202 g_value_set_object (value, priv->call);
204 case PROP_INITIAL_AUDIO:
205 g_value_set_boolean (value, priv->initial_audio);
207 case PROP_INITIAL_VIDEO:
208 g_value_set_boolean (value, priv->initial_video);
210 case PROP_SEND_AUDIO_CODEC:
211 g_value_set_boxed (value, priv->send_audio_codec);
213 case PROP_SEND_VIDEO_CODEC:
214 g_value_set_boxed (value, priv->send_video_codec);
216 case PROP_RECV_AUDIO_CODECS:
217 g_value_set_boxed (value, priv->recv_audio_codecs);
219 case PROP_RECV_VIDEO_CODECS:
220 g_value_set_boxed (value, priv->recv_video_codecs);
222 case PROP_AUDIO_REMOTE_CANDIDATE:
223 g_value_set_boxed (value, priv->audio_remote_candidate);
225 case PROP_VIDEO_REMOTE_CANDIDATE:
226 g_value_set_boxed (value, priv->video_remote_candidate);
228 case PROP_AUDIO_LOCAL_CANDIDATE:
229 g_value_set_boxed (value, priv->audio_local_candidate);
231 case PROP_VIDEO_LOCAL_CANDIDATE:
232 g_value_set_boxed (value, priv->video_local_candidate);
235 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
241 empathy_call_handler_class_init (EmpathyCallHandlerClass *klass)
243 GObjectClass *object_class = G_OBJECT_CLASS (klass);
244 GParamSpec *param_spec;
246 g_type_class_add_private (klass, sizeof (EmpathyCallHandlerPriv));
248 object_class->constructed = empathy_call_handler_constructed;
249 object_class->set_property = empathy_call_handler_set_property;
250 object_class->get_property = empathy_call_handler_get_property;
251 object_class->dispose = empathy_call_handler_dispose;
252 object_class->finalize = empathy_call_handler_finalize;
254 param_spec = g_param_spec_object ("contact",
255 "contact", "The remote contact",
256 EMPATHY_TYPE_CONTACT,
257 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
258 g_object_class_install_property (object_class, PROP_CONTACT, param_spec);
260 param_spec = g_param_spec_object ("tp-call",
261 "tp-call", "The calls channel wrapper",
262 EMPATHY_TYPE_TP_CALL,
263 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
264 g_object_class_install_property (object_class, PROP_TP_CALL, param_spec);
266 param_spec = g_param_spec_boolean ("initial-audio",
267 "initial-audio", "Whether the call should start with audio",
269 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
270 g_object_class_install_property (object_class, PROP_INITIAL_AUDIO,
273 param_spec = g_param_spec_boolean ("initial-video",
274 "initial-video", "Whether the call should start with video",
276 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
277 g_object_class_install_property (object_class, PROP_INITIAL_VIDEO,
280 param_spec = g_param_spec_boxed ("send-audio-codec",
281 "send audio codec", "Codec used to encode the outgoing video stream",
283 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
284 g_object_class_install_property (object_class, PROP_SEND_AUDIO_CODEC,
287 param_spec = g_param_spec_boxed ("send-video-codec",
288 "send video codec", "Codec used to encode the outgoing video stream",
290 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
291 g_object_class_install_property (object_class, PROP_SEND_VIDEO_CODEC,
294 param_spec = g_param_spec_boxed ("recv-audio-codecs",
295 "recvs audio codec", "Codecs used to decode the incoming audio stream",
297 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
298 g_object_class_install_property (object_class, PROP_RECV_AUDIO_CODECS,
301 param_spec = g_param_spec_boxed ("recv-video-codecs",
302 "recvs video codec", "Codecs used to decode the incoming video stream",
304 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
305 g_object_class_install_property (object_class, PROP_RECV_VIDEO_CODECS,
308 param_spec = g_param_spec_boxed ("audio-remote-candidate",
309 "audio remote candidate",
310 "Remote candidate used for the audio stream",
312 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
313 g_object_class_install_property (object_class,
314 PROP_AUDIO_REMOTE_CANDIDATE, param_spec);
316 param_spec = g_param_spec_boxed ("video-remote-candidate",
317 "video remote candidate",
318 "Remote candidate used for the video stream",
320 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
321 g_object_class_install_property (object_class,
322 PROP_VIDEO_REMOTE_CANDIDATE, param_spec);
324 param_spec = g_param_spec_boxed ("audio-local-candidate",
325 "audio local candidate",
326 "Local candidate used for the audio stream",
328 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
329 g_object_class_install_property (object_class,
330 PROP_AUDIO_REMOTE_CANDIDATE, param_spec);
332 param_spec = g_param_spec_boxed ("video-local-candidate",
333 "video local candidate",
334 "Local candidate used for the video stream",
336 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
337 g_object_class_install_property (object_class,
338 PROP_VIDEO_REMOTE_CANDIDATE, param_spec);
340 signals[CONFERENCE_ADDED] =
341 g_signal_new ("conference-added", G_TYPE_FROM_CLASS (klass),
342 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
343 g_cclosure_marshal_VOID__OBJECT,
345 1, FS_TYPE_CONFERENCE);
347 signals[SRC_PAD_ADDED] =
348 g_signal_new ("src-pad-added", G_TYPE_FROM_CLASS (klass),
349 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
350 _empathy_marshal_BOOLEAN__OBJECT_UINT,
352 2, GST_TYPE_PAD, G_TYPE_UINT);
354 signals[SINK_PAD_ADDED] =
355 g_signal_new ("sink-pad-added", G_TYPE_FROM_CLASS (klass),
356 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
357 _empathy_marshal_BOOLEAN__OBJECT_UINT,
359 2, GST_TYPE_PAD, G_TYPE_UINT);
361 signals[REQUEST_RESOURCE] =
362 g_signal_new ("request-resource", G_TYPE_FROM_CLASS (klass),
363 G_SIGNAL_RUN_LAST, 0,
364 g_signal_accumulator_true_handled, NULL,
365 _empathy_marshal_BOOLEAN__UINT_UINT,
366 G_TYPE_BOOLEAN, 2, G_TYPE_UINT, G_TYPE_UINT);
369 g_signal_new ("closed", G_TYPE_FROM_CLASS (klass),
370 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
371 g_cclosure_marshal_VOID__VOID,
375 signals[STREAM_CLOSED] =
376 g_signal_new ("stream-closed", G_TYPE_FROM_CLASS (klass),
377 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
378 g_cclosure_marshal_VOID__OBJECT,
379 G_TYPE_NONE, 1, TF_TYPE_STREAM);
381 signals[CANDIDATES_CHANGED] =
382 g_signal_new ("candidates-changed", G_TYPE_FROM_CLASS (klass),
383 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
384 g_cclosure_marshal_VOID__UINT,
385 G_TYPE_NONE, 1, G_TYPE_UINT);
389 * empathy_call_handler_new_for_contact:
390 * @contact: an #EmpathyContact
392 * Creates a new #EmpathyCallHandler with contact @contact.
394 * Return value: a new #EmpathyCallHandler
397 empathy_call_handler_new_for_contact (EmpathyContact *contact)
399 return EMPATHY_CALL_HANDLER (g_object_new (EMPATHY_TYPE_CALL_HANDLER,
400 "contact", contact, NULL));
404 empathy_call_handler_new_for_channel (EmpathyTpCall *call)
406 return EMPATHY_CALL_HANDLER (g_object_new (EMPATHY_TYPE_CALL_HANDLER,
408 "initial-video", empathy_tp_call_is_receiving_video (call),
413 update_sending_codec (EmpathyCallHandler *self,
417 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
420 if (codec == NULL || session == NULL)
423 g_object_get (session, "media-type", &type, NULL);
425 if (type == FS_MEDIA_TYPE_AUDIO)
427 priv->send_audio_codec = fs_codec_copy (codec);
428 g_object_notify (G_OBJECT (self), "send-audio-codec");
430 else if (type == FS_MEDIA_TYPE_VIDEO)
432 priv->send_video_codec = fs_codec_copy (codec);
433 g_object_notify (G_OBJECT (self), "send-video-codec");
438 update_receiving_codec (EmpathyCallHandler *self,
442 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
446 if (codecs == NULL || stream == NULL)
449 g_object_get (stream, "session", &session, NULL);
453 g_object_get (session, "media-type", &type, NULL);
455 if (type == FS_MEDIA_TYPE_AUDIO)
457 priv->recv_audio_codecs = fs_codec_list_copy (codecs);
458 g_object_notify (G_OBJECT (self), "recv-audio-codecs");
460 else if (type == FS_MEDIA_TYPE_VIDEO)
462 priv->recv_video_codecs = fs_codec_list_copy (codecs);
463 g_object_notify (G_OBJECT (self), "recv-video-codecs");
466 g_object_unref (session);
470 update_candidates (EmpathyCallHandler *self,
471 FsCandidate *remote_candidate,
472 FsCandidate *local_candidate,
475 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
482 g_object_get (stream, "session", &session, NULL);
486 g_object_get (session, "media-type", &type, NULL);
488 if (type == FS_MEDIA_TYPE_AUDIO)
490 if (remote_candidate != NULL)
492 fs_candidate_destroy (priv->audio_remote_candidate);
493 priv->audio_remote_candidate = fs_candidate_copy (remote_candidate);
494 g_object_notify (G_OBJECT (self), "audio-remote-candidate");
497 if (local_candidate != NULL)
499 fs_candidate_destroy (priv->audio_local_candidate);
500 priv->audio_local_candidate = fs_candidate_copy (local_candidate);
501 g_object_notify (G_OBJECT (self), "audio-local-candidate");
504 g_signal_emit (G_OBJECT (self), signals[CANDIDATES_CHANGED], 0,
505 FS_MEDIA_TYPE_AUDIO);
507 else if (type == FS_MEDIA_TYPE_VIDEO)
509 if (remote_candidate != NULL)
511 fs_candidate_destroy (priv->video_remote_candidate);
512 priv->video_remote_candidate = fs_candidate_copy (remote_candidate);
513 g_object_notify (G_OBJECT (self), "video-remote-candidate");
516 if (local_candidate != NULL)
518 fs_candidate_destroy (priv->video_local_candidate);
519 priv->video_local_candidate = fs_candidate_copy (local_candidate);
520 g_object_notify (G_OBJECT (self), "video-local-candidate");
523 g_signal_emit (G_OBJECT (self), signals[CANDIDATES_CHANGED], 0,
524 FS_MEDIA_TYPE_VIDEO);
527 g_object_unref (session);
531 empathy_call_handler_bus_message (EmpathyCallHandler *handler,
532 GstBus *bus, GstMessage *message)
534 EmpathyCallHandlerPriv *priv = GET_PRIV (handler);
535 const GstStructure *s = gst_message_get_structure (message);
537 if (priv->tfchannel == NULL)
541 gst_structure_has_name (s, "farsight-send-codec-changed"))
547 val = gst_structure_get_value (s, "codec");
548 codec = g_value_get_boxed (val);
550 val = gst_structure_get_value (s, "session");
551 session = g_value_get_object (val);
553 update_sending_codec (handler, codec, session);
555 else if (s != NULL &&
556 gst_structure_has_name (s, "farsight-recv-codecs-changed"))
562 val = gst_structure_get_value (s, "codecs");
563 codecs = g_value_get_boxed (val);
565 val = gst_structure_get_value (s, "stream");
566 stream = g_value_get_object (val);
568 update_receiving_codec (handler, codecs, stream);
570 else if (s != NULL &&
571 gst_structure_has_name (s, "farsight-new-active-candidate-pair"))
574 FsCandidate *remote_candidate, *local_candidate;
577 val = gst_structure_get_value (s, "remote-candidate");
578 remote_candidate = g_value_get_boxed (val);
580 val = gst_structure_get_value (s, "local-candidate");
581 local_candidate = g_value_get_boxed (val);
583 val = gst_structure_get_value (s, "stream");
584 stream = g_value_get_object (val);
586 update_candidates (handler, remote_candidate, local_candidate, stream);
589 tf_channel_bus_message (priv->tfchannel, message);
593 empathy_call_handler_tf_channel_session_created_cb (TfChannel *tfchannel,
594 FsConference *conference, FsParticipant *participant,
595 EmpathyCallHandler *self)
597 g_signal_emit (G_OBJECT (self), signals[CONFERENCE_ADDED], 0,
598 GST_ELEMENT (conference));
602 src_pad_added_error_idle (gpointer data)
604 TfStream *stream = data;
606 tf_stream_error (stream, TP_MEDIA_STREAM_ERROR_MEDIA_ERROR,
607 "Could not link sink");
608 g_object_unref (stream);
614 empathy_call_handler_tf_stream_src_pad_added_cb (TfStream *stream,
615 GstPad *pad, FsCodec *codec, EmpathyCallHandler *handler)
620 g_object_get (stream, "media-type", &media_type, NULL);
622 g_signal_emit (G_OBJECT (handler), signals[SRC_PAD_ADDED], 0,
623 pad, media_type, &retval);
626 g_idle_add (src_pad_added_error_idle, g_object_ref (stream));
631 empathy_call_handler_tf_stream_request_resource_cb (TfStream *stream,
632 guint direction, EmpathyTpCall *call)
637 g_object_get (G_OBJECT (stream), "media-type", &media_type, NULL);
639 g_signal_emit (G_OBJECT (call),
640 signals[REQUEST_RESOURCE], 0, media_type, direction, &ret);
646 empathy_call_handler_tf_stream_closed_cb (TfStream *stream,
647 EmpathyCallHandler *handler)
649 g_signal_emit (handler, signals[STREAM_CLOSED], 0, stream);
653 empathy_call_handler_tf_channel_stream_created_cb (TfChannel *tfchannel,
654 TfStream *stream, EmpathyCallHandler *handler)
664 g_signal_connect (stream, "src-pad-added",
665 G_CALLBACK (empathy_call_handler_tf_stream_src_pad_added_cb), handler);
666 g_signal_connect (stream, "request-resource",
667 G_CALLBACK (empathy_call_handler_tf_stream_request_resource_cb),
669 g_signal_connect (stream, "closed",
670 G_CALLBACK (empathy_call_handler_tf_stream_closed_cb), handler);
672 g_object_get (stream, "media-type", &media_type,
673 "sink-pad", &spad, NULL);
675 g_signal_emit (G_OBJECT (handler), signals[SINK_PAD_ADDED], 0,
676 spad, media_type, &retval);
679 tf_stream_error (stream, TP_MEDIA_STREAM_ERROR_MEDIA_ERROR,
680 "Could not link source");
682 /* Get sending codec */
683 g_object_get (stream, "farsight-session", &session, NULL);
684 g_object_get (session, "current-send-codec", &codec, NULL);
686 update_sending_codec (handler, codec, session);
688 tp_clear_object (&session);
689 tp_clear_object (&codec);
691 /* Get receiving codec */
692 g_object_get (stream, "farsight-stream", &fs_stream, NULL);
693 g_object_get (fs_stream, "current-recv-codecs", &codecs, NULL);
695 update_receiving_codec (handler, codecs, fs_stream);
697 fs_codec_list_destroy (codecs);
698 tp_clear_object (&fs_stream);
700 gst_object_unref (spad);
704 empathy_call_handler_tf_channel_closed_cb (TfChannel *tfchannel,
705 EmpathyCallHandler *handler)
707 g_signal_emit (G_OBJECT (handler), signals[CLOSED], 0);
711 empathy_call_handler_tf_channel_codec_config_cb (TfChannel *channel,
712 guint stream_id, FsMediaType media_type, guint direction, gpointer user_data)
714 gchar *filename = empathy_file_lookup ("codec-preferences", "data");
716 GError *error = NULL;
718 codecs = fs_codec_list_from_keyfile (filename, &error);
723 g_warning ("No codec-preferences file: %s",
724 error ? error->message : "No error message");
726 g_clear_error (&error);
732 empathy_call_handler_start_tpfs (EmpathyCallHandler *self)
734 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
737 g_object_get (priv->call, "channel", &channel, NULL);
739 g_assert (channel != NULL);
741 priv->tfchannel = tf_channel_new (channel);
743 /* Set up the telepathy farsight channel */
744 g_signal_connect (priv->tfchannel, "session-created",
745 G_CALLBACK (empathy_call_handler_tf_channel_session_created_cb), self);
746 g_signal_connect (priv->tfchannel, "stream-created",
747 G_CALLBACK (empathy_call_handler_tf_channel_stream_created_cb), self);
748 g_signal_connect (priv->tfchannel, "closed",
749 G_CALLBACK (empathy_call_handler_tf_channel_closed_cb), self);
750 g_signal_connect (priv->tfchannel, "stream-get-codec-config",
751 G_CALLBACK (empathy_call_handler_tf_channel_codec_config_cb), self);
753 g_object_unref (channel);
757 empathy_call_handler_request_cb (GObject *source,
758 GAsyncResult *result,
761 EmpathyCallHandler *self = EMPATHY_CALL_HANDLER (user_data);
762 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
764 GError *error = NULL;
765 TpAccountChannelRequest *req = TP_ACCOUNT_CHANNEL_REQUEST (source);
768 channel = tp_account_channel_request_create_and_handle_channel_finish (req,
769 result, NULL, &error);
772 DEBUG ("Failed to create the channel: %s", error->message);
773 g_error_free (error);
777 account = tp_account_channel_request_get_account (req);
779 priv->call = empathy_tp_call_new (account, channel);
781 g_object_notify (G_OBJECT (self), "tp-call");
783 empathy_call_handler_start_tpfs (self);
785 g_object_unref (channel);
789 empathy_call_handler_start_call (EmpathyCallHandler *handler,
792 EmpathyCallHandlerPriv *priv = GET_PRIV (handler);
793 TpAccountChannelRequest *req;
797 if (priv->call != NULL)
799 empathy_call_handler_start_tpfs (handler);
800 empathy_tp_call_accept_incoming_call (priv->call);
804 /* No TpCall object (we are redialing). Request a new media channel that
805 * will be used to create a new EmpathyTpCall. */
806 g_assert (priv->contact != NULL);
808 account = empathy_contact_get_account (priv->contact);
809 request = empathy_call_factory_create_request (priv->contact,
810 priv->initial_audio, priv->initial_video);
812 req = tp_account_channel_request_new (account, request, timestamp);
814 tp_account_channel_request_create_and_handle_channel_async (req, NULL,
815 empathy_call_handler_request_cb, handler);
817 g_object_unref (req);
818 g_hash_table_unref (request);
822 * empathy_call_handler_stop_call:
823 * @handler: an #EmpathyCallHandler
825 * Closes the #EmpathyCallHandler's call and frees its resources.
828 empathy_call_handler_stop_call (EmpathyCallHandler *handler)
830 EmpathyCallHandlerPriv *priv = GET_PRIV (handler);
832 if (priv->call != NULL)
834 empathy_tp_call_leave (priv->call);
835 g_object_unref (priv->call);
842 * empathy_call_handler_has_initial_video:
843 * @handler: an #EmpathyCallHandler
845 * Return %TRUE if the call managed by this #EmpathyCallHandler was
846 * created with video enabled
848 * Return value: %TRUE if the call was created as a video conversation.
851 empathy_call_handler_has_initial_video (EmpathyCallHandler *handler)
853 EmpathyCallHandlerPriv *priv = GET_PRIV (handler);
855 return priv->initial_video;
859 empathy_call_handler_get_send_audio_codec (EmpathyCallHandler *self)
861 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
863 return priv->send_audio_codec;
867 empathy_call_handler_get_send_video_codec (EmpathyCallHandler *self)
869 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
871 return priv->send_video_codec;
875 empathy_call_handler_get_recv_audio_codecs (EmpathyCallHandler *self)
877 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
879 return priv->recv_audio_codecs;
883 empathy_call_handler_get_recv_video_codecs (EmpathyCallHandler *self)
885 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
887 return priv->recv_video_codecs;
891 empathy_call_handler_get_audio_remote_candidate (
892 EmpathyCallHandler *self)
894 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
896 return priv->audio_remote_candidate;
900 empathy_call_handler_get_audio_local_candidate (
901 EmpathyCallHandler *self)
903 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
905 return priv->audio_local_candidate;
909 empathy_call_handler_get_video_remote_candidate (
910 EmpathyCallHandler *self)
912 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
914 return priv->video_remote_candidate;
918 empathy_call_handler_get_video_local_candidate (
919 EmpathyCallHandler *self)
921 EmpathyCallHandlerPriv *priv = GET_PRIV (self);
923 return priv->video_local_candidate;