comparison libpurple/media/backend-fs2.c @ 32766:fd1b4bbefc6b

Port to Farstream Farstream is the new name of Farsight. The changes to support Farstream are from ocrete. rlaager modified the patch to retain the Farsight code using #ifdef HAVE_FARSIGHT. committer: Richard Laager <rlaager@wiktel.com>
author olivier.crete@collabora.com
date Thu, 05 Apr 2012 03:18:40 +0000
parents 60bd913072f7
children cb2084b4a463
comparison
equal deleted inserted replaced
32765:60bd913072f7 32766:fd1b4bbefc6b
1 /** 1 /**
2 * @file backend-fs2.c Farsight 2 backend for media API 2 * @file backend-fs2.c Farstream backend for media API
3 * @ingroup core 3 * @ingroup core
4 */ 4 */
5 5
6 /* purple 6 /* purple
7 * 7 *
32 #include "backend-iface.h" 32 #include "backend-iface.h"
33 #include "debug.h" 33 #include "debug.h"
34 #include "network.h" 34 #include "network.h"
35 #include "media-gst.h" 35 #include "media-gst.h"
36 36
37 #ifdef HAVE_FARSIGHT
37 #include <gst/farsight/fs-conference-iface.h> 38 #include <gst/farsight/fs-conference-iface.h>
38 #include <gst/farsight/fs-element-added-notifier.h> 39 #include <gst/farsight/fs-element-added-notifier.h>
40 #else
41 #include <farstream/fs-conference.h>
42 #include <farstream/fs-element-added-notifier.h>
43 #include <farstream/fs-utils.h>
44 #endif
39 45
40 /** @copydoc _PurpleMediaBackendFs2Class */ 46 /** @copydoc _PurpleMediaBackendFs2Class */
41 typedef struct _PurpleMediaBackendFs2Class PurpleMediaBackendFs2Class; 47 typedef struct _PurpleMediaBackendFs2Class PurpleMediaBackendFs2Class;
42 /** @copydoc _PurpleMediaBackendFs2Private */ 48 /** @copydoc _PurpleMediaBackendFs2Private */
43 typedef struct _PurpleMediaBackendFs2Private PurpleMediaBackendFs2Private; 49 typedef struct _PurpleMediaBackendFs2Private PurpleMediaBackendFs2Private;
110 { 116 {
111 PurpleMediaBackendFs2Session *session; 117 PurpleMediaBackendFs2Session *session;
112 gchar *participant; 118 gchar *participant;
113 FsStream *stream; 119 FsStream *stream;
114 120
121 #ifndef HAVE_FARSIGHT
122 gboolean supports_add;
123 #endif
124
115 GstElement *src; 125 GstElement *src;
116 GstElement *tee; 126 GstElement *tee;
117 GstElement *volume; 127 GstElement *volume;
118 GstElement *level; 128 GstElement *level;
119 GstElement *fakesink; 129 GstElement *fakesink;
145 PurpleMedia *media; 155 PurpleMedia *media;
146 GstElement *confbin; 156 GstElement *confbin;
147 FsConference *conference; 157 FsConference *conference;
148 gchar *conference_type; 158 gchar *conference_type;
149 159
160 #ifndef HAVE_FARSIGHT
161 FsElementAddedNotifier *notifier;
162 #endif
163
150 GHashTable *sessions; 164 GHashTable *sessions;
151 GHashTable *participants; 165 GHashTable *participants;
152 166
153 GList *streams; 167 GList *streams;
154 168
209 PurpleMediaBackendFs2Private *priv = 223 PurpleMediaBackendFs2Private *priv =
210 PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(obj); 224 PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(obj);
211 GList *iter = NULL; 225 GList *iter = NULL;
212 226
213 purple_debug_info("backend-fs2", "purple_media_backend_fs2_dispose\n"); 227 purple_debug_info("backend-fs2", "purple_media_backend_fs2_dispose\n");
228
229 #ifndef HAVE_FARSIGHT
230 if (priv->notifier) {
231 g_object_unref(priv->notifier);
232 priv->notifier = NULL;
233 }
234 #endif
214 235
215 if (priv->confbin) { 236 if (priv->confbin) {
216 GstElement *pipeline; 237 GstElement *pipeline;
217 238
218 pipeline = purple_media_manager_get_pipeline( 239 pipeline = purple_media_manager_get_pipeline(
844 865
845 if (!FS_IS_CONFERENCE(src) || !PURPLE_IS_MEDIA_BACKEND(self) || 866 if (!FS_IS_CONFERENCE(src) || !PURPLE_IS_MEDIA_BACKEND(self) ||
846 priv->conference != FS_CONFERENCE(src)) 867 priv->conference != FS_CONFERENCE(src))
847 return; 868 return;
848 869
870 #ifdef HAVE_FARSIGHT
849 if (gst_structure_has_name(msg->structure, "farsight-error")) { 871 if (gst_structure_has_name(msg->structure, "farsight-error")) {
872 #else
873 if (gst_structure_has_name(msg->structure, "farstream-error")) {
874 #endif
850 FsError error_no; 875 FsError error_no;
851 gst_structure_get_enum(msg->structure, "error-no", 876 gst_structure_get_enum(msg->structure, "error-no",
852 FS_TYPE_ERROR, (gint*)&error_no); 877 FS_TYPE_ERROR, (gint*)&error_no);
853 switch (error_no) { 878 switch (error_no) {
854 case FS_ERROR_NO_CODECS: 879 case FS_ERROR_NO_CODECS:
857 " GStreamer codecs found" 882 " GStreamer codecs found"
858 " in GStreamer plugins" 883 " in GStreamer plugins"
859 " packages.")); 884 " packages."));
860 purple_media_end(priv->media, NULL, NULL); 885 purple_media_end(priv->media, NULL, NULL);
861 break; 886 break;
887 #ifdef HAVE_FARSIGHT
862 case FS_ERROR_NO_CODECS_LEFT: 888 case FS_ERROR_NO_CODECS_LEFT:
863 purple_media_error(priv->media, _("No codecs" 889 purple_media_error(priv->media, _("No codecs"
864 " left. Your codec" 890 " left. Your codec"
865 " preferences in" 891 " preferences in"
866 " fs-codecs.conf are too" 892 " fs-codecs.conf are too"
872 * Unknown CName is only a problem for the 898 * Unknown CName is only a problem for the
873 * multicast transmitter which isn't used. 899 * multicast transmitter which isn't used.
874 * It is also deprecated. 900 * It is also deprecated.
875 */ 901 */
876 break; 902 break;
903 #endif
877 default: 904 default:
878 purple_debug_error("backend-fs2", 905 purple_debug_error("backend-fs2",
906 #ifdef HAVE_FARSIGHT
879 "farsight-error: %i: %s\n", 907 "farsight-error: %i: %s\n",
908 #else
909 "farstream-error: %i: %s\n",
910 #endif
880 error_no, 911 error_no,
881 gst_structure_get_string( 912 gst_structure_get_string(
882 msg->structure, "error-msg")); 913 msg->structure, "error-msg"));
883 break; 914 break;
884 } 915 }
885 916
886 if (FS_ERROR_IS_FATAL(error_no)) { 917 if (FS_ERROR_IS_FATAL(error_no)) {
918 #ifdef HAVE_FARSIGHT
887 purple_media_error(priv->media, _("A non-recoverable " 919 purple_media_error(priv->media, _("A non-recoverable "
888 "Farsight2 error has occurred.")); 920 "Farsight2 error has occurred."));
921 #else
922 purple_media_error(priv->media, _("A non-recoverable "
923 "Farstream error has occurred."));
924 #endif
889 purple_media_end(priv->media, NULL, NULL); 925 purple_media_end(priv->media, NULL, NULL);
890 } 926 }
891 } else if (gst_structure_has_name(msg->structure, 927 } else if (gst_structure_has_name(msg->structure,
928 #ifdef HAVE_FARSIGHT
892 "farsight-new-local-candidate")) { 929 "farsight-new-local-candidate")) {
930 #else
931 "farstream-new-local-candidate")) {
932 #endif
893 const GValue *value; 933 const GValue *value;
894 FsStream *stream; 934 FsStream *stream;
895 FsCandidate *local_candidate; 935 FsCandidate *local_candidate;
896 PurpleMediaCandidate *candidate; 936 PurpleMediaCandidate *candidate;
897 FsParticipant *participant; 937 FsParticipant *participant;
922 candidate = candidate_from_fs(local_candidate); 962 candidate = candidate_from_fs(local_candidate);
923 g_signal_emit_by_name(self, "new-candidate", 963 g_signal_emit_by_name(self, "new-candidate",
924 session->id, name, candidate); 964 session->id, name, candidate);
925 g_object_unref(candidate); 965 g_object_unref(candidate);
926 } else if (gst_structure_has_name(msg->structure, 966 } else if (gst_structure_has_name(msg->structure,
967 #ifdef HAVE_FARSIGHT
927 "farsight-local-candidates-prepared")) { 968 "farsight-local-candidates-prepared")) {
969 #else
970 "farstream-local-candidates-prepared")) {
971 #endif
928 const GValue *value; 972 const GValue *value;
929 FsStream *stream; 973 FsStream *stream;
930 FsParticipant *participant; 974 FsParticipant *participant;
931 PurpleMediaBackendFs2Session *session; 975 PurpleMediaBackendFs2Session *session;
932 gchar *name; 976 gchar *name;
940 g_object_unref(participant); 984 g_object_unref(participant);
941 985
942 g_signal_emit_by_name(self, "candidates-prepared", 986 g_signal_emit_by_name(self, "candidates-prepared",
943 session->id, name); 987 session->id, name);
944 } else if (gst_structure_has_name(msg->structure, 988 } else if (gst_structure_has_name(msg->structure,
989 #ifdef HAVE_FARSIGHT
945 "farsight-new-active-candidate-pair")) { 990 "farsight-new-active-candidate-pair")) {
991 #else
992 "farstream-new-active-candidate-pair")) {
993 #endif
946 const GValue *value; 994 const GValue *value;
947 FsStream *stream; 995 FsStream *stream;
948 FsCandidate *local_candidate; 996 FsCandidate *local_candidate;
949 FsCandidate *remote_candidate; 997 FsCandidate *remote_candidate;
950 FsParticipant *participant; 998 FsParticipant *participant;
974 session->id, name, lcandidate, rcandidate); 1022 session->id, name, lcandidate, rcandidate);
975 1023
976 g_object_unref(lcandidate); 1024 g_object_unref(lcandidate);
977 g_object_unref(rcandidate); 1025 g_object_unref(rcandidate);
978 } else if (gst_structure_has_name(msg->structure, 1026 } else if (gst_structure_has_name(msg->structure,
1027 #ifdef HAVE_FARSIGHT
979 "farsight-recv-codecs-changed")) { 1028 "farsight-recv-codecs-changed")) {
1029 #else
1030 "farstream-recv-codecs-changed")) {
1031 #endif
980 const GValue *value; 1032 const GValue *value;
981 GList *codecs; 1033 GList *codecs;
982 FsCodec *codec; 1034 FsCodec *codec;
983 1035
984 value = gst_structure_get_value(msg->structure, "codecs"); 1036 value = gst_structure_get_value(msg->structure, "codecs");
985 codecs = g_value_get_boxed(value); 1037 codecs = g_value_get_boxed(value);
986 codec = codecs->data; 1038 codec = codecs->data;
987 1039
988 purple_debug_info("backend-fs2", 1040 purple_debug_info("backend-fs2",
1041 #ifdef HAVE_FARSIGHT
989 "farsight-recv-codecs-changed: %s\n", 1042 "farsight-recv-codecs-changed: %s\n",
1043 #else
1044 "farstream-recv-codecs-changed: %s\n",
1045 #endif
990 codec->encoding_name); 1046 codec->encoding_name);
991 } else if (gst_structure_has_name(msg->structure, 1047 } else if (gst_structure_has_name(msg->structure,
1048 #ifdef HAVE_FARSIGHT
992 "farsight-component-state-changed")) { 1049 "farsight-component-state-changed")) {
1050 #else
1051 "farstream-component-state-changed")) {
1052 #endif
993 const GValue *value; 1053 const GValue *value;
994 FsStreamState fsstate; 1054 FsStreamState fsstate;
995 guint component; 1055 guint component;
996 const gchar *state; 1056 const gchar *state;
997 1057
1023 state = "UNKNOWN"; 1083 state = "UNKNOWN";
1024 break; 1084 break;
1025 } 1085 }
1026 1086
1027 purple_debug_info("backend-fs2", 1087 purple_debug_info("backend-fs2",
1088 #ifdef HAVE_FARSIGHT
1028 "farsight-component-state-changed: " 1089 "farsight-component-state-changed: "
1090 #else
1091 "farstream-component-state-changed: "
1092 #endif
1029 "component: %u state: %s\n", 1093 "component: %u state: %s\n",
1030 component, state); 1094 component, state);
1031 } else if (gst_structure_has_name(msg->structure, 1095 } else if (gst_structure_has_name(msg->structure,
1096 #ifdef HAVE_FARSIGHT
1032 "farsight-send-codec-changed")) { 1097 "farsight-send-codec-changed")) {
1098 #else
1099 "farstream-send-codec-changed")) {
1100 #endif
1033 const GValue *value; 1101 const GValue *value;
1034 FsCodec *codec; 1102 FsCodec *codec;
1035 gchar *codec_str; 1103 gchar *codec_str;
1036 1104
1037 value = gst_structure_get_value(msg->structure, "codec"); 1105 value = gst_structure_get_value(msg->structure, "codec");
1038 codec = g_value_get_boxed(value); 1106 codec = g_value_get_boxed(value);
1039 codec_str = fs_codec_to_string(codec); 1107 codec_str = fs_codec_to_string(codec);
1040 1108
1041 purple_debug_info("backend-fs2", 1109 purple_debug_info("backend-fs2",
1110 #ifdef HAVE_FARSIGHT
1042 "farsight-send-codec-changed: codec: %s\n", 1111 "farsight-send-codec-changed: codec: %s\n",
1112 #else
1113 "farstream-send-codec-changed: codec: %s\n",
1114 #endif
1043 codec_str); 1115 codec_str);
1044 1116
1045 g_free(codec_str); 1117 g_free(codec_str);
1046 } else if (gst_structure_has_name(msg->structure, 1118 } else if (gst_structure_has_name(msg->structure,
1119 #ifdef HAVE_FARSIGHT
1047 "farsight-codecs-changed")) { 1120 "farsight-codecs-changed")) {
1121 #else
1122 "farstream-codecs-changed")) {
1123 #endif
1048 const GValue *value; 1124 const GValue *value;
1049 FsSession *fssession; 1125 FsSession *fssession;
1050 GList *sessions; 1126 GList *sessions;
1051 1127
1052 value = gst_structure_get_value(msg->structure, "session"); 1128 value = gst_structure_get_value(msg->structure, "session");
1218 1294
1219 if (stream->remote_candidates == NULL || 1295 if (stream->remote_candidates == NULL ||
1220 purple_media_is_initiator(media, sid, name)) 1296 purple_media_is_initiator(media, sid, name))
1221 return; 1297 return;
1222 1298
1299 #ifdef HAVE_FARSIGHT
1223 fs_stream_set_remote_candidates(stream->stream, 1300 fs_stream_set_remote_candidates(stream->stream,
1224 stream->remote_candidates, &err); 1301 stream->remote_candidates, &err);
1302 #else
1303 if (stream->supports_add)
1304 fs_stream_add_remote_candidates(stream->stream,
1305 stream->remote_candidates, &err);
1306 else
1307 fs_stream_force_remote_candidates(stream->stream,
1308 stream->remote_candidates, &err);
1309 #endif
1225 1310
1226 if (err == NULL) 1311 if (err == NULL)
1227 return; 1312 return;
1228 1313
1229 purple_debug_error("backend-fs2", "Error adding " 1314 purple_debug_error("backend-fs2", "Error adding "
1299 PurpleMediaBackendFs2Private *priv = 1384 PurpleMediaBackendFs2Private *priv =
1300 PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); 1385 PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
1301 GstElement *pipeline; 1386 GstElement *pipeline;
1302 GstBus *bus; 1387 GstBus *bus;
1303 gchar *name; 1388 gchar *name;
1389 #ifndef HAVE_FARSIGHT
1390 GKeyFile *default_props;
1391 #endif
1304 1392
1305 priv->conference = FS_CONFERENCE( 1393 priv->conference = FS_CONFERENCE(
1306 gst_element_factory_make(priv->conference_type, NULL)); 1394 gst_element_factory_make(priv->conference_type, NULL));
1307 1395
1308 if (priv->conference == NULL) { 1396 if (priv->conference == NULL) {
1340 if (bus == NULL) { 1428 if (bus == NULL) {
1341 purple_debug_error("backend-fs2", 1429 purple_debug_error("backend-fs2",
1342 "Couldn't get the pipeline's bus.\n"); 1430 "Couldn't get the pipeline's bus.\n");
1343 return FALSE; 1431 return FALSE;
1344 } 1432 }
1433
1434 #ifndef HAVE_FARSIGHT
1435 default_props = fs_utils_get_default_element_properties(GST_ELEMENT(priv->conference));
1436 if (default_props != NULL) {
1437 priv->notifier = fs_element_added_notifier_new();
1438 fs_element_added_notifier_add(priv->notifier,
1439 GST_BIN(priv->confbin));
1440 fs_element_added_notifier_set_properties_from_keyfile(priv->notifier, default_props);
1441 }
1442 #endif
1345 1443
1346 g_signal_connect(G_OBJECT(bus), "message", 1444 g_signal_connect(G_OBJECT(bus), "message",
1347 G_CALLBACK(gst_bus_cb), self); 1445 G_CALLBACK(gst_bus_cb), self);
1348 gst_object_unref(bus); 1446 gst_object_unref(bus);
1349 1447
1557 /* 1655 /*
1558 * Removes a 5-7 second delay before 1656 * Removes a 5-7 second delay before
1559 * receiving the src-pad-added signal. 1657 * receiving the src-pad-added signal.
1560 * Only works for non-multicast FsRtpSessions. 1658 * Only works for non-multicast FsRtpSessions.
1561 */ 1659 */
1660 #ifdef HAVE_FARSIGHT
1562 if (is_nice || !strcmp(transmitter, "rawudp")) 1661 if (is_nice || !strcmp(transmitter, "rawudp"))
1662 #else
1663 if (!!strcmp(transmitter, "multicast"))
1664 #endif
1563 g_object_set(G_OBJECT(session->session), 1665 g_object_set(G_OBJECT(session->session),
1564 "no-rtcp-timeout", 0, NULL); 1666 "no-rtcp-timeout", 0, NULL);
1565 1667
1566 /* 1668 /*
1567 * Hack to make x264 work with Gmail video. 1669 * Hack to make x264 work with Gmail video.
1610 PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); 1712 PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
1611 FsParticipant *participant; 1713 FsParticipant *participant;
1612 GError *err = NULL; 1714 GError *err = NULL;
1613 1715
1614 participant = fs_conference_new_participant( 1716 participant = fs_conference_new_participant(
1717 #ifdef HAVE_FARSIGHT
1615 priv->conference, name, &err); 1718 priv->conference, name, &err);
1719 #else
1720 priv->conference, &err);
1721 #endif
1616 1722
1617 if (err) { 1723 if (err) {
1618 purple_debug_error("backend-fs2", 1724 purple_debug_error("backend-fs2",
1619 "Error creating participant: %s\n", 1725 "Error creating participant: %s\n",
1620 err->message); 1726 err->message);
1621 g_error_free(err); 1727 g_error_free(err);
1622 return FALSE; 1728 return FALSE;
1623 } 1729 }
1730
1731 #ifndef HAVE_FARSIGHT
1732 if (g_object_class_find_property(G_OBJECT_GET_CLASS(participant),
1733 "cname")) {
1734 g_object_set(participant, "cname", name, NULL);
1735 }
1736 #endif
1624 1737
1625 if (!priv->participants) { 1738 if (!priv->participants) {
1626 purple_debug_info("backend-fs2", 1739 purple_debug_info("backend-fs2",
1627 "Creating hash table for participants\n"); 1740 "Creating hash table for participants\n");
1628 priv->participants = g_hash_table_new_full(g_str_hash, 1741 priv->participants = g_hash_table_new_full(g_str_hash,
1793 purple_debug_error("backend-fs2", "Couldn't find " 1906 purple_debug_error("backend-fs2", "Couldn't find "
1794 "participant to create stream.\n"); 1907 "participant to create stream.\n");
1795 return FALSE; 1908 return FALSE;
1796 } 1909 }
1797 1910
1798 for (i = 0 ; i < num_params ; i++) { 1911 #ifndef HAVE_FARSIGHT
1799 if (purple_strequal(params[i].name, "relay-info")) {
1800 got_turn_from_prpl = TRUE;
1801 break;
1802 }
1803 }
1804
1805 _params = g_new0(GParameter, num_params + 3);
1806 memcpy(_params, params, sizeof(GParameter) * num_params);
1807
1808 /* set the controlling mode parameter */
1809 _params[_num_params].name = "controlling-mode";
1810 g_value_init(&_params[_num_params].value, G_TYPE_BOOLEAN);
1811 g_value_set_boolean(&_params[_num_params].value, initiator);
1812 ++_num_params;
1813
1814 if (stun_ip) {
1815 purple_debug_info("backend-fs2",
1816 "Setting stun-ip on new stream: %s\n", stun_ip);
1817
1818 _params[_num_params].name = "stun-ip";
1819 g_value_init(&_params[_num_params].value, G_TYPE_STRING);
1820 g_value_set_string(&_params[_num_params].value, stun_ip);
1821 ++_num_params;
1822 }
1823
1824 if (turn_ip && !strcmp("nice", transmitter) && !got_turn_from_prpl) {
1825 GValueArray *relay_info = g_value_array_new(0);
1826 gint port;
1827 const gchar *username = purple_prefs_get_string(
1828 "/purple/network/turn_username");
1829 const gchar *password = purple_prefs_get_string(
1830 "/purple/network/turn_password");
1831
1832 /* UDP */
1833 port = purple_prefs_get_int("/purple/network/turn_port");
1834 if (port > 0) {
1835 relay_info = append_relay_info(relay_info, turn_ip, port, username,
1836 password, "udp");
1837 }
1838
1839 /* TCP */
1840 port = purple_prefs_get_int("/purple/network/turn_port_tcp");
1841 if (port > 0) {
1842 relay_info = append_relay_info(relay_info, turn_ip, port, username,
1843 password, "tcp");
1844 }
1845
1846 /* TURN over SSL is only supported by libnice for Google's "psuedo" SSL mode
1847 at this time */
1848
1849 purple_debug_info("backend-fs2",
1850 "Setting relay-info on new stream\n");
1851 _params[_num_params].name = "relay-info";
1852 g_value_init(&_params[_num_params].value,
1853 G_TYPE_VALUE_ARRAY);
1854 g_value_set_boxed(&_params[_num_params].value,
1855 relay_info);
1856 g_value_array_free(relay_info);
1857 _num_params++;
1858 }
1859
1860 fsstream = fs_session_new_stream(session->session, participant, 1912 fsstream = fs_session_new_stream(session->session, participant,
1861 initiator == TRUE ? type_direction : 1913 initiator == TRUE ? type_direction :
1862 (type_direction & FS_DIRECTION_RECV), transmitter, 1914 (type_direction & FS_DIRECTION_RECV), &err);
1863 _num_params, _params, &err);
1864 g_free(_params);
1865 1915
1866 if (fsstream == NULL) { 1916 if (fsstream == NULL) {
1867 if (err) { 1917 if (err) {
1868 purple_debug_error("backend-fs2", 1918 purple_debug_error("backend-fs2",
1869 "Error creating stream: %s\n", 1919 "Error creating stream: %s\n",
1873 } else 1923 } else
1874 purple_debug_error("backend-fs2", 1924 purple_debug_error("backend-fs2",
1875 "Error creating stream\n"); 1925 "Error creating stream\n");
1876 return FALSE; 1926 return FALSE;
1877 } 1927 }
1928 #endif
1929
1930 for (i = 0 ; i < num_params ; i++) {
1931 if (purple_strequal(params[i].name, "relay-info")) {
1932 got_turn_from_prpl = TRUE;
1933 break;
1934 }
1935 }
1936
1937 _params = g_new0(GParameter, num_params + 3);
1938 memcpy(_params, params, sizeof(GParameter) * num_params);
1939
1940 /* set the controlling mode parameter */
1941 _params[_num_params].name = "controlling-mode";
1942 g_value_init(&_params[_num_params].value, G_TYPE_BOOLEAN);
1943 g_value_set_boolean(&_params[_num_params].value, initiator);
1944 ++_num_params;
1945
1946 if (stun_ip) {
1947 purple_debug_info("backend-fs2",
1948 "Setting stun-ip on new stream: %s\n", stun_ip);
1949
1950 _params[_num_params].name = "stun-ip";
1951 g_value_init(&_params[_num_params].value, G_TYPE_STRING);
1952 g_value_set_string(&_params[_num_params].value, stun_ip);
1953 ++_num_params;
1954 }
1955
1956 if (turn_ip && !strcmp("nice", transmitter) && !got_turn_from_prpl) {
1957 GValueArray *relay_info = g_value_array_new(0);
1958 gint port;
1959 const gchar *username = purple_prefs_get_string(
1960 "/purple/network/turn_username");
1961 const gchar *password = purple_prefs_get_string(
1962 "/purple/network/turn_password");
1963
1964 /* UDP */
1965 port = purple_prefs_get_int("/purple/network/turn_port");
1966 if (port > 0) {
1967 relay_info = append_relay_info(relay_info, turn_ip, port, username,
1968 password, "udp");
1969 }
1970
1971 /* TCP */
1972 port = purple_prefs_get_int("/purple/network/turn_port_tcp");
1973 if (port > 0) {
1974 relay_info = append_relay_info(relay_info, turn_ip, port, username,
1975 password, "tcp");
1976 }
1977
1978 /* TURN over SSL is only supported by libnice for Google's "psuedo" SSL mode
1979 at this time */
1980
1981 purple_debug_info("backend-fs2",
1982 "Setting relay-info on new stream\n");
1983 _params[_num_params].name = "relay-info";
1984 g_value_init(&_params[_num_params].value,
1985 G_TYPE_VALUE_ARRAY);
1986 g_value_set_boxed(&_params[_num_params].value,
1987 relay_info);
1988 g_value_array_free(relay_info);
1989 _num_params++;
1990 }
1991
1992 #ifdef HAVE_FARSIGHT
1993 fsstream = fs_session_new_stream(session->session, participant,
1994 initiator == TRUE ? type_direction :
1995 (type_direction & FS_DIRECTION_RECV), transmitter,
1996 _num_params, _params, &err);
1997 g_free(_params);
1998
1999 if (fsstream == NULL) {
2000 if (err) {
2001 purple_debug_error("backend-fs2",
2002 "Error creating stream: %s\n",
2003 err && err->message ?
2004 err->message : "NULL");
2005 g_error_free(err);
2006 } else
2007 purple_debug_error("backend-fs2",
2008 "Error creating stream\n");
2009 return FALSE;
2010 }
2011 #else
2012 if (!fs_stream_set_transmitter(fsstream, transmitter,
2013 _params, _num_params, &err)) {
2014 purple_debug_error("backend-fs2",
2015 "Could not set transmitter %s: %s.\n",
2016 transmitter, err->message);
2017 g_clear_error(&err);
2018 g_free(_params);
2019 return FALSE;
2020 }
2021 g_free(_params);
2022 #endif
1878 2023
1879 stream = g_new0(PurpleMediaBackendFs2Stream, 1); 2024 stream = g_new0(PurpleMediaBackendFs2Stream, 1);
1880 stream->participant = g_strdup(who); 2025 stream->participant = g_strdup(who);
1881 stream->session = session; 2026 stream->session = session;
1882 stream->stream = fsstream; 2027 stream->stream = fsstream;
2028 #ifndef HAVE_FARSTREAM
2029 stream->supports_add = !strcmp(transmitter, "nice");
2030 #endif
1883 2031
1884 priv->streams = g_list_append(priv->streams, stream); 2032 priv->streams = g_list_append(priv->streams, stream);
1885 2033
1886 g_signal_connect(G_OBJECT(fsstream), "src-pad-added", 2034 g_signal_connect(G_OBJECT(fsstream), "src-pad-added",
1887 G_CALLBACK(src_pad_added_cb), stream); 2035 G_CALLBACK(src_pad_added_cb), stream);
1990 candidate_list_to_fs(remote_candidates)); 2138 candidate_list_to_fs(remote_candidates));
1991 2139
1992 if (purple_media_is_initiator(priv->media, sess_id, participant) || 2140 if (purple_media_is_initiator(priv->media, sess_id, participant) ||
1993 purple_media_accepted( 2141 purple_media_accepted(
1994 priv->media, sess_id, participant)) { 2142 priv->media, sess_id, participant)) {
2143 #ifdef HAVE_FARSIGHT
1995 fs_stream_set_remote_candidates(stream->stream, 2144 fs_stream_set_remote_candidates(stream->stream,
1996 stream->remote_candidates, &err); 2145 stream->remote_candidates, &err);
2146 #else
2147 if (stream->supports_add)
2148 fs_stream_add_remote_candidates(stream->stream,
2149 stream->remote_candidates, &err);
2150 else
2151 fs_stream_force_remote_candidates(stream->stream,
2152 stream->remote_candidates, &err);
2153 #endif
1997 2154
1998 if (err) { 2155 if (err) {
1999 purple_debug_error("backend-fs2", "Error adding remote" 2156 purple_debug_error("backend-fs2", "Error adding remote"
2000 " candidates: %s\n", err->message); 2157 " candidates: %s\n", err->message);
2001 g_error_free(err); 2158 g_error_free(err);
2021 if (session == NULL) 2178 if (session == NULL)
2022 return FALSE; 2179 return FALSE;
2023 2180
2024 if (session->type & (PURPLE_MEDIA_SEND_AUDIO | 2181 if (session->type & (PURPLE_MEDIA_SEND_AUDIO |
2025 PURPLE_MEDIA_SEND_VIDEO)) { 2182 PURPLE_MEDIA_SEND_VIDEO)) {
2183 #ifdef HAVE_FARSIGHT
2026 g_object_get(session->session, 2184 g_object_get(session->session,
2027 "codecs-ready", &ret, NULL); 2185 "codecs-ready", &ret, NULL);
2186 #else
2187 GList *codecs = NULL;
2188
2189 g_object_get(session->session,
2190 "codecs", &codecs, NULL);
2191 if (codecs) {
2192 fs_codec_list_destroy (codecs);
2193 ret = TRUE;
2194 }
2195 #endif
2028 } else 2196 } else
2029 ret = TRUE; 2197 ret = TRUE;
2030 } else { 2198 } else {
2031 GList *values = g_hash_table_get_values(priv->sessions); 2199 GList *values = g_hash_table_get_values(priv->sessions);
2032 2200
2033 for (; values; values = g_list_delete_link(values, values)) { 2201 for (; values; values = g_list_delete_link(values, values)) {
2034 PurpleMediaBackendFs2Session *session = values->data; 2202 PurpleMediaBackendFs2Session *session = values->data;
2203
2035 if (session->type & (PURPLE_MEDIA_SEND_AUDIO | 2204 if (session->type & (PURPLE_MEDIA_SEND_AUDIO |
2036 PURPLE_MEDIA_SEND_VIDEO)) { 2205 PURPLE_MEDIA_SEND_VIDEO)) {
2206 #ifdef HAVE_FARSIGHT
2037 g_object_get(session->session, 2207 g_object_get(session->session,
2038 "codecs-ready", &ret, NULL); 2208 "codecs-ready", &ret, NULL);
2039 if (ret == FALSE) 2209 if (ret == FALSE)
2040 break; 2210 break;
2211 #else
2212 GList *codecs = NULL;
2213
2214 g_object_get(session->session,
2215 "codecs", &codecs, NULL);
2216 if (codecs) {
2217 fs_codec_list_destroy (codecs);
2218 ret = TRUE;
2219 } else {
2220 ret = FALSE;
2221 break;
2222 }
2223 #endif
2041 } else 2224 } else
2042 ret = TRUE; 2225 ret = TRUE;
2043 } 2226 }
2044 2227
2045 if (values != NULL) 2228 if (values != NULL)