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"
38 #define DEBUG_FLAG EMPATHY_DEBUG_VOIP
39 #include <libempathy/empathy-debug.h>
41 G_DEFINE_TYPE(EmpathyStreamedMediaHandler
, empathy_streamed_media_handler
, G_TYPE_OBJECT
)
55 static guint signals
[LAST_SIGNAL
] = {0};
58 PROP_TP_STREAMED_MEDIA
= 1,
63 PROP_SEND_AUDIO_CODEC
,
64 PROP_SEND_VIDEO_CODEC
,
65 PROP_RECV_AUDIO_CODECS
,
66 PROP_RECV_VIDEO_CODECS
,
67 PROP_AUDIO_REMOTE_CANDIDATE
,
68 PROP_VIDEO_REMOTE_CANDIDATE
,
69 PROP_AUDIO_LOCAL_CANDIDATE
,
70 PROP_VIDEO_LOCAL_CANDIDATE
,
73 /* private structure */
76 gboolean dispose_has_run
;
77 EmpathyTpStreamedMedia
*call
;
78 EmpathyContact
*contact
;
80 gboolean initial_audio
;
81 gboolean initial_video
;
83 FsCodec
*send_audio_codec
;
84 FsCodec
*send_video_codec
;
85 GList
*recv_audio_codecs
;
86 GList
*recv_video_codecs
;
87 FsCandidate
*audio_remote_candidate
;
88 FsCandidate
*video_remote_candidate
;
89 FsCandidate
*audio_local_candidate
;
90 FsCandidate
*video_local_candidate
;
91 } EmpathyStreamedMediaHandlerPriv
;
93 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyStreamedMediaHandler)
96 empathy_streamed_media_handler_dispose (GObject
*object
)
98 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (object
);
100 if (priv
->dispose_has_run
)
103 priv
->dispose_has_run
= TRUE
;
105 if (priv
->contact
!= NULL
)
106 g_object_unref (priv
->contact
);
108 priv
->contact
= NULL
;
110 if (priv
->tfchannel
!= NULL
)
111 g_object_unref (priv
->tfchannel
);
113 priv
->tfchannel
= NULL
;
115 if (priv
->call
!= NULL
)
117 empathy_tp_streamed_media_close (priv
->call
);
118 g_object_unref (priv
->call
);
123 /* release any references held by the object here */
124 if (G_OBJECT_CLASS (empathy_streamed_media_handler_parent_class
)->dispose
)
125 G_OBJECT_CLASS (empathy_streamed_media_handler_parent_class
)->dispose (object
);
129 empathy_streamed_media_handler_finalize (GObject
*object
)
131 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (object
);
133 fs_codec_destroy (priv
->send_audio_codec
);
134 fs_codec_destroy (priv
->send_video_codec
);
135 fs_codec_list_destroy (priv
->recv_audio_codecs
);
136 fs_codec_list_destroy (priv
->recv_video_codecs
);
137 fs_candidate_destroy (priv
->audio_remote_candidate
);
138 fs_candidate_destroy (priv
->video_remote_candidate
);
139 fs_candidate_destroy (priv
->audio_local_candidate
);
140 fs_candidate_destroy (priv
->video_local_candidate
);
142 if (G_OBJECT_CLASS (empathy_streamed_media_handler_parent_class
)->finalize
)
143 G_OBJECT_CLASS (empathy_streamed_media_handler_parent_class
)->finalize (object
);
147 empathy_streamed_media_handler_init (EmpathyStreamedMediaHandler
*obj
)
149 EmpathyStreamedMediaHandlerPriv
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (obj
,
150 EMPATHY_TYPE_STREAMED_MEDIA_HANDLER
, EmpathyStreamedMediaHandlerPriv
);
156 empathy_streamed_media_handler_constructed (GObject
*object
)
158 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (object
);
160 if (priv
->contact
== NULL
)
162 g_object_get (priv
->call
, "contact", &(priv
->contact
), NULL
);
167 empathy_streamed_media_handler_set_property (GObject
*object
,
168 guint property_id
, const GValue
*value
, GParamSpec
*pspec
)
170 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (object
);
175 priv
->contact
= g_value_dup_object (value
);
177 case PROP_TP_STREAMED_MEDIA
:
178 priv
->call
= g_value_dup_object (value
);
180 case PROP_INITIAL_AUDIO
:
181 priv
->initial_audio
= g_value_get_boolean (value
);
183 case PROP_INITIAL_VIDEO
:
184 priv
->initial_video
= g_value_get_boolean (value
);
187 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
192 empathy_streamed_media_handler_get_property (GObject
*object
,
193 guint property_id
, GValue
*value
, GParamSpec
*pspec
)
195 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (object
);
200 g_value_set_object (value
, priv
->contact
);
202 case PROP_TP_STREAMED_MEDIA
:
203 g_value_set_object (value
, priv
->call
);
205 case PROP_INITIAL_AUDIO
:
206 g_value_set_boolean (value
, priv
->initial_audio
);
208 case PROP_INITIAL_VIDEO
:
209 g_value_set_boolean (value
, priv
->initial_video
);
211 case PROP_SEND_AUDIO_CODEC
:
212 g_value_set_boxed (value
, priv
->send_audio_codec
);
214 case PROP_SEND_VIDEO_CODEC
:
215 g_value_set_boxed (value
, priv
->send_video_codec
);
217 case PROP_RECV_AUDIO_CODECS
:
218 g_value_set_boxed (value
, priv
->recv_audio_codecs
);
220 case PROP_RECV_VIDEO_CODECS
:
221 g_value_set_boxed (value
, priv
->recv_video_codecs
);
223 case PROP_AUDIO_REMOTE_CANDIDATE
:
224 g_value_set_boxed (value
, priv
->audio_remote_candidate
);
226 case PROP_VIDEO_REMOTE_CANDIDATE
:
227 g_value_set_boxed (value
, priv
->video_remote_candidate
);
229 case PROP_AUDIO_LOCAL_CANDIDATE
:
230 g_value_set_boxed (value
, priv
->audio_local_candidate
);
232 case PROP_VIDEO_LOCAL_CANDIDATE
:
233 g_value_set_boxed (value
, priv
->video_local_candidate
);
236 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
242 empathy_streamed_media_handler_class_init (EmpathyStreamedMediaHandlerClass
*klass
)
244 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
245 GParamSpec
*param_spec
;
247 g_type_class_add_private (klass
, sizeof (EmpathyStreamedMediaHandlerPriv
));
249 object_class
->constructed
= empathy_streamed_media_handler_constructed
;
250 object_class
->set_property
= empathy_streamed_media_handler_set_property
;
251 object_class
->get_property
= empathy_streamed_media_handler_get_property
;
252 object_class
->dispose
= empathy_streamed_media_handler_dispose
;
253 object_class
->finalize
= empathy_streamed_media_handler_finalize
;
255 param_spec
= g_param_spec_object ("contact",
256 "contact", "The remote contact",
257 EMPATHY_TYPE_CONTACT
,
258 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
| G_PARAM_STATIC_STRINGS
);
259 g_object_class_install_property (object_class
, PROP_CONTACT
, param_spec
);
261 param_spec
= g_param_spec_object ("tp-call",
262 "tp-call", "The calls channel wrapper",
263 EMPATHY_TYPE_TP_STREAMED_MEDIA
,
264 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
| G_PARAM_STATIC_STRINGS
);
265 g_object_class_install_property (object_class
, PROP_TP_STREAMED_MEDIA
, param_spec
);
267 param_spec
= g_param_spec_boolean ("initial-audio",
268 "initial-audio", "Whether the call should start with audio",
270 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
| G_PARAM_STATIC_STRINGS
);
271 g_object_class_install_property (object_class
, PROP_INITIAL_AUDIO
,
274 param_spec
= g_param_spec_boolean ("initial-video",
275 "initial-video", "Whether the call should start with video",
277 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
| G_PARAM_STATIC_STRINGS
);
278 g_object_class_install_property (object_class
, PROP_INITIAL_VIDEO
,
281 param_spec
= g_param_spec_boxed ("send-audio-codec",
282 "send audio codec", "Codec used to encode the outgoing video stream",
284 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
285 g_object_class_install_property (object_class
, PROP_SEND_AUDIO_CODEC
,
288 param_spec
= g_param_spec_boxed ("send-video-codec",
289 "send video codec", "Codec used to encode the outgoing video stream",
291 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
292 g_object_class_install_property (object_class
, PROP_SEND_VIDEO_CODEC
,
295 param_spec
= g_param_spec_boxed ("recv-audio-codecs",
296 "recvs audio codec", "Codecs used to decode the incoming audio stream",
298 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
299 g_object_class_install_property (object_class
, PROP_RECV_AUDIO_CODECS
,
302 param_spec
= g_param_spec_boxed ("recv-video-codecs",
303 "recvs video codec", "Codecs used to decode the incoming video stream",
305 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
306 g_object_class_install_property (object_class
, PROP_RECV_VIDEO_CODECS
,
309 param_spec
= g_param_spec_boxed ("audio-remote-candidate",
310 "audio remote candidate",
311 "Remote candidate used for the audio stream",
313 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
314 g_object_class_install_property (object_class
,
315 PROP_AUDIO_REMOTE_CANDIDATE
, param_spec
);
317 param_spec
= g_param_spec_boxed ("video-remote-candidate",
318 "video remote candidate",
319 "Remote candidate used for the video stream",
321 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
322 g_object_class_install_property (object_class
,
323 PROP_VIDEO_REMOTE_CANDIDATE
, param_spec
);
325 param_spec
= g_param_spec_boxed ("audio-local-candidate",
326 "audio local candidate",
327 "Local candidate used for the audio stream",
329 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
330 g_object_class_install_property (object_class
,
331 PROP_AUDIO_REMOTE_CANDIDATE
, param_spec
);
333 param_spec
= g_param_spec_boxed ("video-local-candidate",
334 "video local candidate",
335 "Local candidate used for the video stream",
337 G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS
);
338 g_object_class_install_property (object_class
,
339 PROP_VIDEO_REMOTE_CANDIDATE
, param_spec
);
341 signals
[CONFERENCE_ADDED
] =
342 g_signal_new ("conference-added", G_TYPE_FROM_CLASS (klass
),
343 G_SIGNAL_RUN_LAST
, 0, NULL
, NULL
,
344 g_cclosure_marshal_generic
,
346 1, FS_TYPE_CONFERENCE
);
348 signals
[SRC_PAD_ADDED
] =
349 g_signal_new ("src-pad-added", G_TYPE_FROM_CLASS (klass
),
350 G_SIGNAL_RUN_LAST
, 0, NULL
, NULL
,
351 g_cclosure_marshal_generic
,
353 2, GST_TYPE_PAD
, G_TYPE_UINT
);
355 signals
[SINK_PAD_ADDED
] =
356 g_signal_new ("sink-pad-added", G_TYPE_FROM_CLASS (klass
),
357 G_SIGNAL_RUN_LAST
, 0, NULL
, NULL
,
358 g_cclosure_marshal_generic
,
360 2, GST_TYPE_PAD
, G_TYPE_UINT
);
362 signals
[REQUEST_RESOURCE
] =
363 g_signal_new ("request-resource", G_TYPE_FROM_CLASS (klass
),
364 G_SIGNAL_RUN_LAST
, 0,
365 g_signal_accumulator_true_handled
, NULL
,
366 g_cclosure_marshal_generic
,
367 G_TYPE_BOOLEAN
, 2, G_TYPE_UINT
, G_TYPE_UINT
);
370 g_signal_new ("closed", G_TYPE_FROM_CLASS (klass
),
371 G_SIGNAL_RUN_LAST
, 0, NULL
, NULL
,
372 g_cclosure_marshal_generic
,
376 signals
[STREAM_CLOSED
] =
377 g_signal_new ("stream-closed", G_TYPE_FROM_CLASS (klass
),
378 G_SIGNAL_RUN_LAST
, 0, NULL
, NULL
,
379 g_cclosure_marshal_generic
,
380 G_TYPE_NONE
, 1, TF_TYPE_STREAM
);
382 signals
[CANDIDATES_CHANGED
] =
383 g_signal_new ("candidates-changed", G_TYPE_FROM_CLASS (klass
),
384 G_SIGNAL_RUN_LAST
, 0, NULL
, NULL
,
385 g_cclosure_marshal_generic
,
386 G_TYPE_NONE
, 1, G_TYPE_UINT
);
390 * empathy_streamed_media_handler_new_for_contact:
391 * @contact: an #EmpathyContact
393 * Creates a new #EmpathyStreamedMediaHandler with contact @contact.
395 * Return value: a new #EmpathyStreamedMediaHandler
397 EmpathyStreamedMediaHandler
*
398 empathy_streamed_media_handler_new_for_contact (EmpathyContact
*contact
)
400 return EMPATHY_STREAMED_MEDIA_HANDLER (g_object_new (EMPATHY_TYPE_STREAMED_MEDIA_HANDLER
,
401 "contact", contact
, NULL
));
404 EmpathyStreamedMediaHandler
*
405 empathy_streamed_media_handler_new_for_channel (EmpathyTpStreamedMedia
*call
)
407 return EMPATHY_STREAMED_MEDIA_HANDLER (g_object_new (EMPATHY_TYPE_STREAMED_MEDIA_HANDLER
,
409 "initial-video", empathy_tp_streamed_media_is_receiving_video (call
),
414 update_sending_codec (EmpathyStreamedMediaHandler
*self
,
418 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
421 if (codec
== NULL
|| session
== NULL
)
424 g_object_get (session
, "media-type", &type
, NULL
);
426 if (type
== FS_MEDIA_TYPE_AUDIO
)
428 priv
->send_audio_codec
= fs_codec_copy (codec
);
429 g_object_notify (G_OBJECT (self
), "send-audio-codec");
431 else if (type
== FS_MEDIA_TYPE_VIDEO
)
433 priv
->send_video_codec
= fs_codec_copy (codec
);
434 g_object_notify (G_OBJECT (self
), "send-video-codec");
439 update_receiving_codec (EmpathyStreamedMediaHandler
*self
,
443 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
447 if (codecs
== NULL
|| stream
== NULL
)
450 g_object_get (stream
, "session", &session
, NULL
);
454 g_object_get (session
, "media-type", &type
, NULL
);
456 if (type
== FS_MEDIA_TYPE_AUDIO
)
458 priv
->recv_audio_codecs
= fs_codec_list_copy (codecs
);
459 g_object_notify (G_OBJECT (self
), "recv-audio-codecs");
461 else if (type
== FS_MEDIA_TYPE_VIDEO
)
463 priv
->recv_video_codecs
= fs_codec_list_copy (codecs
);
464 g_object_notify (G_OBJECT (self
), "recv-video-codecs");
467 g_object_unref (session
);
471 update_candidates (EmpathyStreamedMediaHandler
*self
,
472 FsCandidate
*remote_candidate
,
473 FsCandidate
*local_candidate
,
476 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
483 g_object_get (stream
, "session", &session
, NULL
);
487 g_object_get (session
, "media-type", &type
, NULL
);
489 if (type
== FS_MEDIA_TYPE_AUDIO
)
491 if (remote_candidate
!= NULL
)
493 fs_candidate_destroy (priv
->audio_remote_candidate
);
494 priv
->audio_remote_candidate
= fs_candidate_copy (remote_candidate
);
495 g_object_notify (G_OBJECT (self
), "audio-remote-candidate");
498 if (local_candidate
!= NULL
)
500 fs_candidate_destroy (priv
->audio_local_candidate
);
501 priv
->audio_local_candidate
= fs_candidate_copy (local_candidate
);
502 g_object_notify (G_OBJECT (self
), "audio-local-candidate");
505 g_signal_emit (G_OBJECT (self
), signals
[CANDIDATES_CHANGED
], 0,
506 FS_MEDIA_TYPE_AUDIO
);
508 else if (type
== FS_MEDIA_TYPE_VIDEO
)
510 if (remote_candidate
!= NULL
)
512 fs_candidate_destroy (priv
->video_remote_candidate
);
513 priv
->video_remote_candidate
= fs_candidate_copy (remote_candidate
);
514 g_object_notify (G_OBJECT (self
), "video-remote-candidate");
517 if (local_candidate
!= NULL
)
519 fs_candidate_destroy (priv
->video_local_candidate
);
520 priv
->video_local_candidate
= fs_candidate_copy (local_candidate
);
521 g_object_notify (G_OBJECT (self
), "video-local-candidate");
524 g_signal_emit (G_OBJECT (self
), signals
[CANDIDATES_CHANGED
], 0,
525 FS_MEDIA_TYPE_VIDEO
);
528 g_object_unref (session
);
532 empathy_streamed_media_handler_bus_message (EmpathyStreamedMediaHandler
*handler
,
533 GstBus
*bus
, GstMessage
*message
)
535 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (handler
);
536 const GstStructure
*s
= gst_message_get_structure (message
);
538 if (priv
->tfchannel
== NULL
)
542 gst_structure_has_name (s
, "farsight-send-codec-changed"))
548 val
= gst_structure_get_value (s
, "codec");
549 codec
= g_value_get_boxed (val
);
551 val
= gst_structure_get_value (s
, "session");
552 session
= g_value_get_object (val
);
554 update_sending_codec (handler
, codec
, session
);
556 else if (s
!= NULL
&&
557 gst_structure_has_name (s
, "farsight-recv-codecs-changed"))
563 val
= gst_structure_get_value (s
, "codecs");
564 codecs
= g_value_get_boxed (val
);
566 val
= gst_structure_get_value (s
, "stream");
567 stream
= g_value_get_object (val
);
569 update_receiving_codec (handler
, codecs
, stream
);
571 else if (s
!= NULL
&&
572 gst_structure_has_name (s
, "farsight-new-active-candidate-pair"))
575 FsCandidate
*remote_candidate
, *local_candidate
;
578 val
= gst_structure_get_value (s
, "remote-candidate");
579 remote_candidate
= g_value_get_boxed (val
);
581 val
= gst_structure_get_value (s
, "local-candidate");
582 local_candidate
= g_value_get_boxed (val
);
584 val
= gst_structure_get_value (s
, "stream");
585 stream
= g_value_get_object (val
);
587 update_candidates (handler
, remote_candidate
, local_candidate
, stream
);
590 tf_channel_bus_message (priv
->tfchannel
, message
);
594 empathy_streamed_media_handler_tf_channel_session_created_cb (TfChannel
*tfchannel
,
595 FsConference
*conference
, FsParticipant
*participant
,
596 EmpathyStreamedMediaHandler
*self
)
598 g_signal_emit (G_OBJECT (self
), signals
[CONFERENCE_ADDED
], 0,
599 GST_ELEMENT (conference
));
603 src_pad_added_error_idle (gpointer data
)
605 TfStream
*stream
= data
;
607 tf_stream_error (stream
, TP_MEDIA_STREAM_ERROR_MEDIA_ERROR
,
608 "Could not link sink");
609 g_object_unref (stream
);
615 empathy_streamed_media_handler_tf_stream_src_pad_added_cb (TfStream
*stream
,
616 GstPad
*pad
, FsCodec
*codec
, EmpathyStreamedMediaHandler
*handler
)
621 g_object_get (stream
, "media-type", &media_type
, NULL
);
623 g_signal_emit (G_OBJECT (handler
), signals
[SRC_PAD_ADDED
], 0,
624 pad
, media_type
, &retval
);
627 g_idle_add (src_pad_added_error_idle
, g_object_ref (stream
));
632 empathy_streamed_media_handler_tf_stream_request_resource_cb (TfStream
*stream
,
633 guint direction
, EmpathyTpStreamedMedia
*call
)
638 g_object_get (G_OBJECT (stream
), "media-type", &media_type
, NULL
);
640 g_signal_emit (G_OBJECT (call
),
641 signals
[REQUEST_RESOURCE
], 0, media_type
, direction
, &ret
);
647 empathy_streamed_media_handler_tf_stream_closed_cb (TfStream
*stream
,
648 EmpathyStreamedMediaHandler
*handler
)
650 g_signal_emit (handler
, signals
[STREAM_CLOSED
], 0, stream
);
654 empathy_streamed_media_handler_tf_channel_stream_created_cb (TfChannel
*tfchannel
,
655 TfStream
*stream
, EmpathyStreamedMediaHandler
*handler
)
665 g_signal_connect (stream
, "src-pad-added",
666 G_CALLBACK (empathy_streamed_media_handler_tf_stream_src_pad_added_cb
), handler
);
667 g_signal_connect (stream
, "request-resource",
668 G_CALLBACK (empathy_streamed_media_handler_tf_stream_request_resource_cb
),
670 g_signal_connect (stream
, "closed",
671 G_CALLBACK (empathy_streamed_media_handler_tf_stream_closed_cb
), handler
);
673 g_object_get (stream
, "media-type", &media_type
,
674 "sink-pad", &spad
, NULL
);
676 g_signal_emit (G_OBJECT (handler
), signals
[SINK_PAD_ADDED
], 0,
677 spad
, media_type
, &retval
);
680 tf_stream_error (stream
, TP_MEDIA_STREAM_ERROR_MEDIA_ERROR
,
681 "Could not link source");
683 /* Get sending codec */
684 g_object_get (stream
, "farsight-session", &session
, NULL
);
685 g_object_get (session
, "current-send-codec", &codec
, NULL
);
687 update_sending_codec (handler
, codec
, session
);
689 tp_clear_object (&session
);
690 tp_clear_object (&codec
);
692 /* Get receiving codec */
693 g_object_get (stream
, "farsight-stream", &fs_stream
, NULL
);
694 g_object_get (fs_stream
, "current-recv-codecs", &codecs
, NULL
);
696 update_receiving_codec (handler
, codecs
, fs_stream
);
698 fs_codec_list_destroy (codecs
);
699 tp_clear_object (&fs_stream
);
701 gst_object_unref (spad
);
705 empathy_streamed_media_handler_tf_channel_closed_cb (TfChannel
*tfchannel
,
706 EmpathyStreamedMediaHandler
*handler
)
708 g_signal_emit (G_OBJECT (handler
), signals
[CLOSED
], 0);
712 empathy_streamed_media_handler_start_tpfs (EmpathyStreamedMediaHandler
*self
)
714 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
717 g_object_get (priv
->call
, "channel", &channel
, NULL
);
719 g_assert (channel
!= NULL
);
721 priv
->tfchannel
= tf_channel_new (channel
);
723 /* Set up the telepathy farsight channel */
724 g_signal_connect (priv
->tfchannel
, "session-created",
725 G_CALLBACK (empathy_streamed_media_handler_tf_channel_session_created_cb
), self
);
726 g_signal_connect (priv
->tfchannel
, "stream-created",
727 G_CALLBACK (empathy_streamed_media_handler_tf_channel_stream_created_cb
), self
);
728 g_signal_connect (priv
->tfchannel
, "closed",
729 G_CALLBACK (empathy_streamed_media_handler_tf_channel_closed_cb
), self
);
731 g_object_unref (channel
);
735 empathy_streamed_media_handler_request_cb (GObject
*source
,
736 GAsyncResult
*result
,
739 EmpathyStreamedMediaHandler
*self
= EMPATHY_STREAMED_MEDIA_HANDLER (user_data
);
740 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
742 GError
*error
= NULL
;
743 TpAccountChannelRequest
*req
= TP_ACCOUNT_CHANNEL_REQUEST (source
);
746 channel
= tp_account_channel_request_create_and_handle_channel_finish (req
,
747 result
, NULL
, &error
);
750 DEBUG ("Failed to create the channel: %s", error
->message
);
751 g_error_free (error
);
755 account
= tp_account_channel_request_get_account (req
);
757 priv
->call
= empathy_tp_streamed_media_new (account
, channel
);
759 g_object_notify (G_OBJECT (self
), "tp-call");
761 empathy_streamed_media_handler_start_tpfs (self
);
763 g_object_unref (channel
);
767 empathy_streamed_media_handler_start_call (EmpathyStreamedMediaHandler
*handler
,
770 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (handler
);
771 TpAccountChannelRequest
*req
;
775 if (priv
->call
!= NULL
)
777 empathy_streamed_media_handler_start_tpfs (handler
);
778 empathy_tp_streamed_media_accept_incoming_call (priv
->call
);
782 /* No TpStreamedMedia object (we are redialing). Request a new media channel that
783 * will be used to create a new EmpathyTpStreamedMedia. */
784 g_assert (priv
->contact
!= NULL
);
786 account
= empathy_contact_get_account (priv
->contact
);
787 request
= empathy_call_create_streamed_media_request (
788 empathy_contact_get_id (priv
->contact
),
789 priv
->initial_audio
, priv
->initial_video
);
791 req
= tp_account_channel_request_new (account
, request
, timestamp
);
793 tp_account_channel_request_create_and_handle_channel_async (req
, NULL
,
794 empathy_streamed_media_handler_request_cb
, handler
);
796 g_object_unref (req
);
797 g_hash_table_unref (request
);
801 * empathy_streamed_media_handler_stop_call:
802 * @handler: an #EmpathyStreamedMediaHandler
804 * Closes the #EmpathyStreamedMediaHandler's call and frees its resources.
807 empathy_streamed_media_handler_stop_call (EmpathyStreamedMediaHandler
*handler
)
809 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (handler
);
811 if (priv
->call
!= NULL
)
813 empathy_tp_streamed_media_leave (priv
->call
);
814 g_object_unref (priv
->call
);
821 * empathy_streamed_media_handler_has_initial_video:
822 * @handler: an #EmpathyStreamedMediaHandler
824 * Return %TRUE if the call managed by this #EmpathyStreamedMediaHandler was
825 * created with video enabled
827 * Return value: %TRUE if the call was created as a video conversation.
830 empathy_streamed_media_handler_has_initial_video (EmpathyStreamedMediaHandler
*handler
)
832 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (handler
);
834 return priv
->initial_video
;
838 empathy_streamed_media_handler_get_send_audio_codec (EmpathyStreamedMediaHandler
*self
)
840 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
842 return priv
->send_audio_codec
;
846 empathy_streamed_media_handler_get_send_video_codec (EmpathyStreamedMediaHandler
*self
)
848 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
850 return priv
->send_video_codec
;
854 empathy_streamed_media_handler_get_recv_audio_codecs (EmpathyStreamedMediaHandler
*self
)
856 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
858 return priv
->recv_audio_codecs
;
862 empathy_streamed_media_handler_get_recv_video_codecs (EmpathyStreamedMediaHandler
*self
)
864 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
866 return priv
->recv_video_codecs
;
870 empathy_streamed_media_handler_get_audio_remote_candidate (
871 EmpathyStreamedMediaHandler
*self
)
873 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
875 return priv
->audio_remote_candidate
;
879 empathy_streamed_media_handler_get_audio_local_candidate (
880 EmpathyStreamedMediaHandler
*self
)
882 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
884 return priv
->audio_local_candidate
;
888 empathy_streamed_media_handler_get_video_remote_candidate (
889 EmpathyStreamedMediaHandler
*self
)
891 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
893 return priv
->video_remote_candidate
;
897 empathy_streamed_media_handler_get_video_local_candidate (
898 EmpathyStreamedMediaHandler
*self
)
900 EmpathyStreamedMediaHandlerPriv
*priv
= GET_PRIV (self
);
902 return priv
->video_local_candidate
;