2 * empathy-streamed-media-handler.c - Source for EmpathyStreamedMediaHandler
3 * Copyright (C) 2008-2011 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 <libempathy/empathy-utils.h>
34 #include <libempathy-gtk/empathy-call-utils.h>
36 #include "empathy-streamed-media-handler.h"
37 #include "src-marshal.h"
39 #define DEBUG_FLAG EMPATHY_DEBUG_VOIP
40 #include <libempathy/empathy-debug.h>
42 G_DEFINE_TYPE(EmpathyStreamedMediaHandler, empathy_streamed_media_handler, G_TYPE_OBJECT)
56 static guint signals[LAST_SIGNAL] = {0};
59 PROP_TP_STREAMED_MEDIA = 1,
64 PROP_SEND_AUDIO_CODEC,
65 PROP_SEND_VIDEO_CODEC,
66 PROP_RECV_AUDIO_CODECS,
67 PROP_RECV_VIDEO_CODECS,
68 PROP_AUDIO_REMOTE_CANDIDATE,
69 PROP_VIDEO_REMOTE_CANDIDATE,
70 PROP_AUDIO_LOCAL_CANDIDATE,
71 PROP_VIDEO_LOCAL_CANDIDATE,
74 /* private structure */
77 gboolean dispose_has_run;
78 EmpathyTpStreamedMedia *call;
79 EmpathyContact *contact;
81 gboolean initial_audio;
82 gboolean initial_video;
84 FsCodec *send_audio_codec;
85 FsCodec *send_video_codec;
86 GList *recv_audio_codecs;
87 GList *recv_video_codecs;
88 FsCandidate *audio_remote_candidate;
89 FsCandidate *video_remote_candidate;
90 FsCandidate *audio_local_candidate;
91 FsCandidate *video_local_candidate;
92 } EmpathyStreamedMediaHandlerPriv;
94 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyStreamedMediaHandler)
97 empathy_streamed_media_handler_dispose (GObject *object)
99 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (object);
101 if (priv->dispose_has_run)
104 priv->dispose_has_run = TRUE;
106 if (priv->contact != NULL)
107 g_object_unref (priv->contact);
109 priv->contact = NULL;
111 if (priv->tfchannel != NULL)
112 g_object_unref (priv->tfchannel);
114 priv->tfchannel = NULL;
116 if (priv->call != NULL)
118 empathy_tp_streamed_media_close (priv->call);
119 g_object_unref (priv->call);
124 /* release any references held by the object here */
125 if (G_OBJECT_CLASS (empathy_streamed_media_handler_parent_class)->dispose)
126 G_OBJECT_CLASS (empathy_streamed_media_handler_parent_class)->dispose (object);
130 empathy_streamed_media_handler_finalize (GObject *object)
132 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (object);
134 fs_codec_destroy (priv->send_audio_codec);
135 fs_codec_destroy (priv->send_video_codec);
136 fs_codec_list_destroy (priv->recv_audio_codecs);
137 fs_codec_list_destroy (priv->recv_video_codecs);
138 fs_candidate_destroy (priv->audio_remote_candidate);
139 fs_candidate_destroy (priv->video_remote_candidate);
140 fs_candidate_destroy (priv->audio_local_candidate);
141 fs_candidate_destroy (priv->video_local_candidate);
143 if (G_OBJECT_CLASS (empathy_streamed_media_handler_parent_class)->finalize)
144 G_OBJECT_CLASS (empathy_streamed_media_handler_parent_class)->finalize (object);
148 empathy_streamed_media_handler_init (EmpathyStreamedMediaHandler *obj)
150 EmpathyStreamedMediaHandlerPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj,
151 EMPATHY_TYPE_STREAMED_MEDIA_HANDLER, EmpathyStreamedMediaHandlerPriv);
157 empathy_streamed_media_handler_constructed (GObject *object)
159 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (object);
161 if (priv->contact == NULL)
163 g_object_get (priv->call, "contact", &(priv->contact), NULL);
168 empathy_streamed_media_handler_set_property (GObject *object,
169 guint property_id, const GValue *value, GParamSpec *pspec)
171 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (object);
176 priv->contact = g_value_dup_object (value);
178 case PROP_TP_STREAMED_MEDIA:
179 priv->call = g_value_dup_object (value);
181 case PROP_INITIAL_AUDIO:
182 priv->initial_audio = g_value_get_boolean (value);
184 case PROP_INITIAL_VIDEO:
185 priv->initial_video = g_value_get_boolean (value);
188 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
193 empathy_streamed_media_handler_get_property (GObject *object,
194 guint property_id, GValue *value, GParamSpec *pspec)
196 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (object);
201 g_value_set_object (value, priv->contact);
203 case PROP_TP_STREAMED_MEDIA:
204 g_value_set_object (value, priv->call);
206 case PROP_INITIAL_AUDIO:
207 g_value_set_boolean (value, priv->initial_audio);
209 case PROP_INITIAL_VIDEO:
210 g_value_set_boolean (value, priv->initial_video);
212 case PROP_SEND_AUDIO_CODEC:
213 g_value_set_boxed (value, priv->send_audio_codec);
215 case PROP_SEND_VIDEO_CODEC:
216 g_value_set_boxed (value, priv->send_video_codec);
218 case PROP_RECV_AUDIO_CODECS:
219 g_value_set_boxed (value, priv->recv_audio_codecs);
221 case PROP_RECV_VIDEO_CODECS:
222 g_value_set_boxed (value, priv->recv_video_codecs);
224 case PROP_AUDIO_REMOTE_CANDIDATE:
225 g_value_set_boxed (value, priv->audio_remote_candidate);
227 case PROP_VIDEO_REMOTE_CANDIDATE:
228 g_value_set_boxed (value, priv->video_remote_candidate);
230 case PROP_AUDIO_LOCAL_CANDIDATE:
231 g_value_set_boxed (value, priv->audio_local_candidate);
233 case PROP_VIDEO_LOCAL_CANDIDATE:
234 g_value_set_boxed (value, priv->video_local_candidate);
237 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
243 empathy_streamed_media_handler_class_init (EmpathyStreamedMediaHandlerClass *klass)
245 GObjectClass *object_class = G_OBJECT_CLASS (klass);
246 GParamSpec *param_spec;
248 g_type_class_add_private (klass, sizeof (EmpathyStreamedMediaHandlerPriv));
250 object_class->constructed = empathy_streamed_media_handler_constructed;
251 object_class->set_property = empathy_streamed_media_handler_set_property;
252 object_class->get_property = empathy_streamed_media_handler_get_property;
253 object_class->dispose = empathy_streamed_media_handler_dispose;
254 object_class->finalize = empathy_streamed_media_handler_finalize;
256 param_spec = g_param_spec_object ("contact",
257 "contact", "The remote contact",
258 EMPATHY_TYPE_CONTACT,
259 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
260 g_object_class_install_property (object_class, PROP_CONTACT, param_spec);
262 param_spec = g_param_spec_object ("tp-call",
263 "tp-call", "The calls channel wrapper",
264 EMPATHY_TYPE_TP_STREAMED_MEDIA,
265 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
266 g_object_class_install_property (object_class, PROP_TP_STREAMED_MEDIA, param_spec);
268 param_spec = g_param_spec_boolean ("initial-audio",
269 "initial-audio", "Whether the call should start with audio",
271 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
272 g_object_class_install_property (object_class, PROP_INITIAL_AUDIO,
275 param_spec = g_param_spec_boolean ("initial-video",
276 "initial-video", "Whether the call should start with video",
278 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
279 g_object_class_install_property (object_class, PROP_INITIAL_VIDEO,
282 param_spec = g_param_spec_boxed ("send-audio-codec",
283 "send audio codec", "Codec used to encode the outgoing video stream",
285 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
286 g_object_class_install_property (object_class, PROP_SEND_AUDIO_CODEC,
289 param_spec = g_param_spec_boxed ("send-video-codec",
290 "send video codec", "Codec used to encode the outgoing video stream",
292 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
293 g_object_class_install_property (object_class, PROP_SEND_VIDEO_CODEC,
296 param_spec = g_param_spec_boxed ("recv-audio-codecs",
297 "recvs audio codec", "Codecs used to decode the incoming audio stream",
299 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
300 g_object_class_install_property (object_class, PROP_RECV_AUDIO_CODECS,
303 param_spec = g_param_spec_boxed ("recv-video-codecs",
304 "recvs video codec", "Codecs used to decode the incoming video stream",
306 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
307 g_object_class_install_property (object_class, PROP_RECV_VIDEO_CODECS,
310 param_spec = g_param_spec_boxed ("audio-remote-candidate",
311 "audio remote candidate",
312 "Remote candidate used for the audio stream",
314 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
315 g_object_class_install_property (object_class,
316 PROP_AUDIO_REMOTE_CANDIDATE, param_spec);
318 param_spec = g_param_spec_boxed ("video-remote-candidate",
319 "video remote candidate",
320 "Remote candidate used for the video stream",
322 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
323 g_object_class_install_property (object_class,
324 PROP_VIDEO_REMOTE_CANDIDATE, param_spec);
326 param_spec = g_param_spec_boxed ("audio-local-candidate",
327 "audio local candidate",
328 "Local candidate used for the audio stream",
330 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
331 g_object_class_install_property (object_class,
332 PROP_AUDIO_REMOTE_CANDIDATE, param_spec);
334 param_spec = g_param_spec_boxed ("video-local-candidate",
335 "video local candidate",
336 "Local candidate used for the video stream",
338 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
339 g_object_class_install_property (object_class,
340 PROP_VIDEO_REMOTE_CANDIDATE, param_spec);
342 signals[CONFERENCE_ADDED] =
343 g_signal_new ("conference-added", G_TYPE_FROM_CLASS (klass),
344 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
345 g_cclosure_marshal_VOID__OBJECT,
347 1, FS_TYPE_CONFERENCE);
349 signals[SRC_PAD_ADDED] =
350 g_signal_new ("src-pad-added", G_TYPE_FROM_CLASS (klass),
351 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
352 _src_marshal_BOOLEAN__OBJECT_UINT,
354 2, GST_TYPE_PAD, G_TYPE_UINT);
356 signals[SINK_PAD_ADDED] =
357 g_signal_new ("sink-pad-added", G_TYPE_FROM_CLASS (klass),
358 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
359 _src_marshal_BOOLEAN__OBJECT_UINT,
361 2, GST_TYPE_PAD, G_TYPE_UINT);
363 signals[REQUEST_RESOURCE] =
364 g_signal_new ("request-resource", G_TYPE_FROM_CLASS (klass),
365 G_SIGNAL_RUN_LAST, 0,
366 g_signal_accumulator_true_handled, NULL,
367 _src_marshal_BOOLEAN__UINT_UINT,
368 G_TYPE_BOOLEAN, 2, G_TYPE_UINT, G_TYPE_UINT);
371 g_signal_new ("closed", G_TYPE_FROM_CLASS (klass),
372 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
373 g_cclosure_marshal_VOID__VOID,
377 signals[STREAM_CLOSED] =
378 g_signal_new ("stream-closed", G_TYPE_FROM_CLASS (klass),
379 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
380 g_cclosure_marshal_VOID__OBJECT,
381 G_TYPE_NONE, 1, TF_TYPE_STREAM);
383 signals[CANDIDATES_CHANGED] =
384 g_signal_new ("candidates-changed", G_TYPE_FROM_CLASS (klass),
385 G_SIGNAL_RUN_LAST, 0, NULL, NULL,
386 g_cclosure_marshal_VOID__UINT,
387 G_TYPE_NONE, 1, G_TYPE_UINT);
391 * empathy_streamed_media_handler_new_for_contact:
392 * @contact: an #EmpathyContact
394 * Creates a new #EmpathyStreamedMediaHandler with contact @contact.
396 * Return value: a new #EmpathyStreamedMediaHandler
398 EmpathyStreamedMediaHandler *
399 empathy_streamed_media_handler_new_for_contact (EmpathyContact *contact)
401 return EMPATHY_STREAMED_MEDIA_HANDLER (g_object_new (EMPATHY_TYPE_STREAMED_MEDIA_HANDLER,
402 "contact", contact, NULL));
405 EmpathyStreamedMediaHandler *
406 empathy_streamed_media_handler_new_for_channel (EmpathyTpStreamedMedia *call)
408 return EMPATHY_STREAMED_MEDIA_HANDLER (g_object_new (EMPATHY_TYPE_STREAMED_MEDIA_HANDLER,
410 "initial-video", empathy_tp_streamed_media_is_receiving_video (call),
415 update_sending_codec (EmpathyStreamedMediaHandler *self,
419 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
422 if (codec == NULL || session == NULL)
425 g_object_get (session, "media-type", &type, NULL);
427 if (type == FS_MEDIA_TYPE_AUDIO)
429 priv->send_audio_codec = fs_codec_copy (codec);
430 g_object_notify (G_OBJECT (self), "send-audio-codec");
432 else if (type == FS_MEDIA_TYPE_VIDEO)
434 priv->send_video_codec = fs_codec_copy (codec);
435 g_object_notify (G_OBJECT (self), "send-video-codec");
440 update_receiving_codec (EmpathyStreamedMediaHandler *self,
444 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
448 if (codecs == NULL || stream == NULL)
451 g_object_get (stream, "session", &session, NULL);
455 g_object_get (session, "media-type", &type, NULL);
457 if (type == FS_MEDIA_TYPE_AUDIO)
459 priv->recv_audio_codecs = fs_codec_list_copy (codecs);
460 g_object_notify (G_OBJECT (self), "recv-audio-codecs");
462 else if (type == FS_MEDIA_TYPE_VIDEO)
464 priv->recv_video_codecs = fs_codec_list_copy (codecs);
465 g_object_notify (G_OBJECT (self), "recv-video-codecs");
468 g_object_unref (session);
472 update_candidates (EmpathyStreamedMediaHandler *self,
473 FsCandidate *remote_candidate,
474 FsCandidate *local_candidate,
477 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
484 g_object_get (stream, "session", &session, NULL);
488 g_object_get (session, "media-type", &type, NULL);
490 if (type == FS_MEDIA_TYPE_AUDIO)
492 if (remote_candidate != NULL)
494 fs_candidate_destroy (priv->audio_remote_candidate);
495 priv->audio_remote_candidate = fs_candidate_copy (remote_candidate);
496 g_object_notify (G_OBJECT (self), "audio-remote-candidate");
499 if (local_candidate != NULL)
501 fs_candidate_destroy (priv->audio_local_candidate);
502 priv->audio_local_candidate = fs_candidate_copy (local_candidate);
503 g_object_notify (G_OBJECT (self), "audio-local-candidate");
506 g_signal_emit (G_OBJECT (self), signals[CANDIDATES_CHANGED], 0,
507 FS_MEDIA_TYPE_AUDIO);
509 else if (type == FS_MEDIA_TYPE_VIDEO)
511 if (remote_candidate != NULL)
513 fs_candidate_destroy (priv->video_remote_candidate);
514 priv->video_remote_candidate = fs_candidate_copy (remote_candidate);
515 g_object_notify (G_OBJECT (self), "video-remote-candidate");
518 if (local_candidate != NULL)
520 fs_candidate_destroy (priv->video_local_candidate);
521 priv->video_local_candidate = fs_candidate_copy (local_candidate);
522 g_object_notify (G_OBJECT (self), "video-local-candidate");
525 g_signal_emit (G_OBJECT (self), signals[CANDIDATES_CHANGED], 0,
526 FS_MEDIA_TYPE_VIDEO);
529 g_object_unref (session);
533 empathy_streamed_media_handler_bus_message (EmpathyStreamedMediaHandler *handler,
534 GstBus *bus, GstMessage *message)
536 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (handler);
537 const GstStructure *s = gst_message_get_structure (message);
539 if (priv->tfchannel == NULL)
543 gst_structure_has_name (s, "farsight-send-codec-changed"))
549 val = gst_structure_get_value (s, "codec");
550 codec = g_value_get_boxed (val);
552 val = gst_structure_get_value (s, "session");
553 session = g_value_get_object (val);
555 update_sending_codec (handler, codec, session);
557 else if (s != NULL &&
558 gst_structure_has_name (s, "farsight-recv-codecs-changed"))
564 val = gst_structure_get_value (s, "codecs");
565 codecs = g_value_get_boxed (val);
567 val = gst_structure_get_value (s, "stream");
568 stream = g_value_get_object (val);
570 update_receiving_codec (handler, codecs, stream);
572 else if (s != NULL &&
573 gst_structure_has_name (s, "farsight-new-active-candidate-pair"))
576 FsCandidate *remote_candidate, *local_candidate;
579 val = gst_structure_get_value (s, "remote-candidate");
580 remote_candidate = g_value_get_boxed (val);
582 val = gst_structure_get_value (s, "local-candidate");
583 local_candidate = g_value_get_boxed (val);
585 val = gst_structure_get_value (s, "stream");
586 stream = g_value_get_object (val);
588 update_candidates (handler, remote_candidate, local_candidate, stream);
591 tf_channel_bus_message (priv->tfchannel, message);
595 empathy_streamed_media_handler_tf_channel_session_created_cb (TfChannel *tfchannel,
596 FsConference *conference, FsParticipant *participant,
597 EmpathyStreamedMediaHandler *self)
599 g_signal_emit (G_OBJECT (self), signals[CONFERENCE_ADDED], 0,
600 GST_ELEMENT (conference));
604 src_pad_added_error_idle (gpointer data)
606 TfStream *stream = data;
608 tf_stream_error (stream, TP_MEDIA_STREAM_ERROR_MEDIA_ERROR,
609 "Could not link sink");
610 g_object_unref (stream);
616 empathy_streamed_media_handler_tf_stream_src_pad_added_cb (TfStream *stream,
617 GstPad *pad, FsCodec *codec, EmpathyStreamedMediaHandler *handler)
622 g_object_get (stream, "media-type", &media_type, NULL);
624 g_signal_emit (G_OBJECT (handler), signals[SRC_PAD_ADDED], 0,
625 pad, media_type, &retval);
628 g_idle_add (src_pad_added_error_idle, g_object_ref (stream));
633 empathy_streamed_media_handler_tf_stream_request_resource_cb (TfStream *stream,
634 guint direction, EmpathyTpStreamedMedia *call)
639 g_object_get (G_OBJECT (stream), "media-type", &media_type, NULL);
641 g_signal_emit (G_OBJECT (call),
642 signals[REQUEST_RESOURCE], 0, media_type, direction, &ret);
648 empathy_streamed_media_handler_tf_stream_closed_cb (TfStream *stream,
649 EmpathyStreamedMediaHandler *handler)
651 g_signal_emit (handler, signals[STREAM_CLOSED], 0, stream);
655 empathy_streamed_media_handler_tf_channel_stream_created_cb (TfChannel *tfchannel,
656 TfStream *stream, EmpathyStreamedMediaHandler *handler)
666 g_signal_connect (stream, "src-pad-added",
667 G_CALLBACK (empathy_streamed_media_handler_tf_stream_src_pad_added_cb), handler);
668 g_signal_connect (stream, "request-resource",
669 G_CALLBACK (empathy_streamed_media_handler_tf_stream_request_resource_cb),
671 g_signal_connect (stream, "closed",
672 G_CALLBACK (empathy_streamed_media_handler_tf_stream_closed_cb), handler);
674 g_object_get (stream, "media-type", &media_type,
675 "sink-pad", &spad, NULL);
677 g_signal_emit (G_OBJECT (handler), signals[SINK_PAD_ADDED], 0,
678 spad, media_type, &retval);
681 tf_stream_error (stream, TP_MEDIA_STREAM_ERROR_MEDIA_ERROR,
682 "Could not link source");
684 /* Get sending codec */
685 g_object_get (stream, "farsight-session", &session, NULL);
686 g_object_get (session, "current-send-codec", &codec, NULL);
688 update_sending_codec (handler, codec, session);
690 tp_clear_object (&session);
691 tp_clear_object (&codec);
693 /* Get receiving codec */
694 g_object_get (stream, "farsight-stream", &fs_stream, NULL);
695 g_object_get (fs_stream, "current-recv-codecs", &codecs, NULL);
697 update_receiving_codec (handler, codecs, fs_stream);
699 fs_codec_list_destroy (codecs);
700 tp_clear_object (&fs_stream);
702 gst_object_unref (spad);
706 empathy_streamed_media_handler_tf_channel_closed_cb (TfChannel *tfchannel,
707 EmpathyStreamedMediaHandler *handler)
709 g_signal_emit (G_OBJECT (handler), signals[CLOSED], 0);
713 empathy_streamed_media_handler_tf_channel_codec_config_cb (TfChannel *channel,
714 guint stream_id, FsMediaType media_type, guint direction, gpointer user_data)
716 gchar *filename = empathy_file_lookup ("codec-preferences", "data");
718 GError *error = NULL;
720 codecs = fs_codec_list_from_keyfile (filename, &error);
725 g_warning ("No codec-preferences file: %s",
726 error ? error->message : "No error message");
728 g_clear_error (&error);
734 empathy_streamed_media_handler_start_tpfs (EmpathyStreamedMediaHandler *self)
736 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
739 g_object_get (priv->call, "channel", &channel, NULL);
741 g_assert (channel != NULL);
743 priv->tfchannel = tf_channel_new (channel);
745 /* Set up the telepathy farsight channel */
746 g_signal_connect (priv->tfchannel, "session-created",
747 G_CALLBACK (empathy_streamed_media_handler_tf_channel_session_created_cb), self);
748 g_signal_connect (priv->tfchannel, "stream-created",
749 G_CALLBACK (empathy_streamed_media_handler_tf_channel_stream_created_cb), self);
750 g_signal_connect (priv->tfchannel, "closed",
751 G_CALLBACK (empathy_streamed_media_handler_tf_channel_closed_cb), self);
752 g_signal_connect (priv->tfchannel, "stream-get-codec-config",
753 G_CALLBACK (empathy_streamed_media_handler_tf_channel_codec_config_cb), self);
755 g_object_unref (channel);
759 empathy_streamed_media_handler_request_cb (GObject *source,
760 GAsyncResult *result,
763 EmpathyStreamedMediaHandler *self = EMPATHY_STREAMED_MEDIA_HANDLER (user_data);
764 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
766 GError *error = NULL;
767 TpAccountChannelRequest *req = TP_ACCOUNT_CHANNEL_REQUEST (source);
770 channel = tp_account_channel_request_create_and_handle_channel_finish (req,
771 result, NULL, &error);
774 DEBUG ("Failed to create the channel: %s", error->message);
775 g_error_free (error);
779 account = tp_account_channel_request_get_account (req);
781 priv->call = empathy_tp_streamed_media_new (account, channel);
783 g_object_notify (G_OBJECT (self), "tp-call");
785 empathy_streamed_media_handler_start_tpfs (self);
787 g_object_unref (channel);
791 empathy_streamed_media_handler_start_call (EmpathyStreamedMediaHandler *handler,
794 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (handler);
795 TpAccountChannelRequest *req;
799 if (priv->call != NULL)
801 empathy_streamed_media_handler_start_tpfs (handler);
802 empathy_tp_streamed_media_accept_incoming_call (priv->call);
806 /* No TpStreamedMedia object (we are redialing). Request a new media channel that
807 * will be used to create a new EmpathyTpStreamedMedia. */
808 g_assert (priv->contact != NULL);
810 account = empathy_contact_get_account (priv->contact);
811 request = empathy_call_create_streamed_media_request (
812 empathy_contact_get_id (priv->contact),
813 priv->initial_audio, priv->initial_video);
815 req = tp_account_channel_request_new (account, request, timestamp);
817 tp_account_channel_request_create_and_handle_channel_async (req, NULL,
818 empathy_streamed_media_handler_request_cb, handler);
820 g_object_unref (req);
821 g_hash_table_unref (request);
825 * empathy_streamed_media_handler_stop_call:
826 * @handler: an #EmpathyStreamedMediaHandler
828 * Closes the #EmpathyStreamedMediaHandler's call and frees its resources.
831 empathy_streamed_media_handler_stop_call (EmpathyStreamedMediaHandler *handler)
833 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (handler);
835 if (priv->call != NULL)
837 empathy_tp_streamed_media_leave (priv->call);
838 g_object_unref (priv->call);
845 * empathy_streamed_media_handler_has_initial_video:
846 * @handler: an #EmpathyStreamedMediaHandler
848 * Return %TRUE if the call managed by this #EmpathyStreamedMediaHandler was
849 * created with video enabled
851 * Return value: %TRUE if the call was created as a video conversation.
854 empathy_streamed_media_handler_has_initial_video (EmpathyStreamedMediaHandler *handler)
856 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (handler);
858 return priv->initial_video;
862 empathy_streamed_media_handler_get_send_audio_codec (EmpathyStreamedMediaHandler *self)
864 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
866 return priv->send_audio_codec;
870 empathy_streamed_media_handler_get_send_video_codec (EmpathyStreamedMediaHandler *self)
872 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
874 return priv->send_video_codec;
878 empathy_streamed_media_handler_get_recv_audio_codecs (EmpathyStreamedMediaHandler *self)
880 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
882 return priv->recv_audio_codecs;
886 empathy_streamed_media_handler_get_recv_video_codecs (EmpathyStreamedMediaHandler *self)
888 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
890 return priv->recv_video_codecs;
894 empathy_streamed_media_handler_get_audio_remote_candidate (
895 EmpathyStreamedMediaHandler *self)
897 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
899 return priv->audio_remote_candidate;
903 empathy_streamed_media_handler_get_audio_local_candidate (
904 EmpathyStreamedMediaHandler *self)
906 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
908 return priv->audio_local_candidate;
912 empathy_streamed_media_handler_get_video_remote_candidate (
913 EmpathyStreamedMediaHandler *self)
915 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
917 return priv->video_remote_candidate;
921 empathy_streamed_media_handler_get_video_local_candidate (
922 EmpathyStreamedMediaHandler *self)
924 EmpathyStreamedMediaHandlerPriv *priv = GET_PRIV (self);
926 return priv->video_local_candidate;