Mercurial > pidgin.yaz
comparison libpurple/media/backend-fs2.c @ 29566:f600903f7811
Transfer creating Farsight 2 streams to the Fs2 media backend.
author | maiku@pidgin.im |
---|---|
date | Mon, 26 Oct 2009 21:35:11 +0000 |
parents | 7b0931b3e060 |
children | 983af0970bb2 |
comparison
equal
deleted
inserted
replaced
29565:eef5ec04a5bf | 29566:f600903f7811 |
---|---|
28 | 28 |
29 #include "internal.h" | 29 #include "internal.h" |
30 | 30 |
31 #include "backend-iface.h" | 31 #include "backend-iface.h" |
32 #include "debug.h" | 32 #include "debug.h" |
33 #include "network.h" | |
33 #include "media-gst.h" | 34 #include "media-gst.h" |
34 | 35 |
35 #include <gst/farsight/fs-conference-iface.h> | 36 #include <gst/farsight/fs-conference-iface.h> |
36 #include <gst/farsight/fs-element-added-notifier.h> | 37 #include <gst/farsight/fs-element-added-notifier.h> |
37 | 38 |
39 typedef struct _PurpleMediaBackendFs2Class PurpleMediaBackendFs2Class; | 40 typedef struct _PurpleMediaBackendFs2Class PurpleMediaBackendFs2Class; |
40 /** @copydoc _PurpleMediaBackendFs2Private */ | 41 /** @copydoc _PurpleMediaBackendFs2Private */ |
41 typedef struct _PurpleMediaBackendFs2Private PurpleMediaBackendFs2Private; | 42 typedef struct _PurpleMediaBackendFs2Private PurpleMediaBackendFs2Private; |
42 /** @copydoc _PurpleMediaBackendFs2Session */ | 43 /** @copydoc _PurpleMediaBackendFs2Session */ |
43 typedef struct _PurpleMediaBackendFs2Session PurpleMediaBackendFs2Session; | 44 typedef struct _PurpleMediaBackendFs2Session PurpleMediaBackendFs2Session; |
45 /** @copydoc _PurpleMediaBackendFs2Stream */ | |
46 typedef struct _PurpleMediaBackendFs2Stream PurpleMediaBackendFs2Stream; | |
44 | 47 |
45 #define PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(obj) \ | 48 #define PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(obj) \ |
46 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \ | 49 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \ |
47 PURPLE_TYPE_MEDIA_BACKEND_FS2, PurpleMediaBackendFs2Private)) | 50 PURPLE_TYPE_MEDIA_BACKEND_FS2, PurpleMediaBackendFs2Private)) |
48 | 51 |
91 | 94 |
92 G_DEFINE_TYPE_WITH_CODE(PurpleMediaBackendFs2, purple_media_backend_fs2, | 95 G_DEFINE_TYPE_WITH_CODE(PurpleMediaBackendFs2, purple_media_backend_fs2, |
93 G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE( | 96 G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE( |
94 PURPLE_TYPE_MEDIA_BACKEND, purple_media_backend_iface_init)); | 97 PURPLE_TYPE_MEDIA_BACKEND, purple_media_backend_iface_init)); |
95 | 98 |
99 struct _PurpleMediaBackendFs2Stream | |
100 { | |
101 PurpleMediaBackendFs2Session *session; | |
102 gchar *participant; | |
103 FsStream *stream; | |
104 | |
105 GList *local_candidates; | |
106 GList *remote_candidates; | |
107 | |
108 GList *active_local_candidates; | |
109 GList *active_remote_candidates; | |
110 | |
111 guint connected_cb_id; | |
112 | |
113 gboolean initiator; | |
114 gboolean accepted; | |
115 gboolean candidates_prepared; | |
116 }; | |
117 | |
96 struct _PurpleMediaBackendFs2Session | 118 struct _PurpleMediaBackendFs2Session |
97 { | 119 { |
98 PurpleMediaBackendFs2 *backend; | 120 PurpleMediaBackendFs2 *backend; |
99 gchar *id; | 121 gchar *id; |
100 gboolean initiator; | 122 gboolean initiator; |
109 FsConference *conference; | 131 FsConference *conference; |
110 gchar *conference_type; | 132 gchar *conference_type; |
111 | 133 |
112 GHashTable *sessions; | 134 GHashTable *sessions; |
113 GHashTable *participants; | 135 GHashTable *participants; |
136 | |
137 GList *streams; | |
114 }; | 138 }; |
115 | 139 |
116 enum { | 140 enum { |
117 PROP_0, | 141 PROP_0, |
118 PROP_CONFERENCE_TYPE, | 142 PROP_CONFERENCE_TYPE, |
321 return FS_MEDIA_TYPE_VIDEO; | 345 return FS_MEDIA_TYPE_VIDEO; |
322 else | 346 else |
323 return 0; | 347 return 0; |
324 } | 348 } |
325 | 349 |
326 #if 0 | |
327 static FsStreamDirection | 350 static FsStreamDirection |
328 _session_type_to_fs_stream_direction(PurpleMediaSessionType type) | 351 _session_type_to_fs_stream_direction(PurpleMediaSessionType type) |
329 { | 352 { |
330 if ((type & PURPLE_MEDIA_AUDIO) == PURPLE_MEDIA_AUDIO || | 353 if ((type & PURPLE_MEDIA_AUDIO) == PURPLE_MEDIA_AUDIO || |
331 (type & PURPLE_MEDIA_VIDEO) == PURPLE_MEDIA_VIDEO) | 354 (type & PURPLE_MEDIA_VIDEO) == PURPLE_MEDIA_VIDEO) |
338 return FS_DIRECTION_RECV; | 361 return FS_DIRECTION_RECV; |
339 else | 362 else |
340 return FS_DIRECTION_NONE; | 363 return FS_DIRECTION_NONE; |
341 } | 364 } |
342 | 365 |
366 #if 0 | |
343 static PurpleMediaSessionType | 367 static PurpleMediaSessionType |
344 _session_type_from_fs(FsMediaType type, FsStreamDirection direction) | 368 _session_type_from_fs(FsMediaType type, FsStreamDirection direction) |
345 { | 369 { |
346 PurpleMediaSessionType result = PURPLE_MEDIA_NONE; | 370 PurpleMediaSessionType result = PURPLE_MEDIA_NONE; |
347 if (type == FS_MEDIA_TYPE_AUDIO) { | 371 if (type == FS_MEDIA_TYPE_AUDIO) { |
459 | 483 |
460 if (priv->participants != NULL) | 484 if (priv->participants != NULL) |
461 participant = g_hash_table_lookup(priv->participants, name); | 485 participant = g_hash_table_lookup(priv->participants, name); |
462 | 486 |
463 return participant; | 487 return participant; |
488 } | |
489 | |
490 static PurpleMediaBackendFs2Stream * | |
491 _get_stream(PurpleMediaBackendFs2 *self, | |
492 const gchar *sess_id, const gchar *name) | |
493 { | |
494 PurpleMediaBackendFs2Private *priv; | |
495 GList *streams; | |
496 | |
497 g_return_val_if_fail(PURPLE_IS_MEDIA_BACKEND_FS2(self), NULL); | |
498 | |
499 priv = PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); | |
500 streams = priv->streams; | |
501 | |
502 for (; streams; streams = g_list_next(streams)) { | |
503 PurpleMediaBackendFs2Stream *stream = streams->data; | |
504 if (!strcmp(stream->session->id, sess_id) && | |
505 !strcmp(stream->participant, name)) | |
506 return stream; | |
507 } | |
508 | |
509 return NULL; | |
464 } | 510 } |
465 | 511 |
466 static PurpleMediaBackendFs2Session * | 512 static PurpleMediaBackendFs2Session * |
467 _get_session_from_fs_stream(PurpleMediaBackendFs2 *self, FsStream *stream) | 513 _get_session_from_fs_stream(PurpleMediaBackendFs2 *self, FsStream *stream) |
468 { | 514 { |
1021 | 1067 |
1022 return TRUE; | 1068 return TRUE; |
1023 } | 1069 } |
1024 | 1070 |
1025 static gboolean | 1071 static gboolean |
1072 _create_stream(PurpleMediaBackendFs2 *self, | |
1073 const gchar *sess_id, const gchar *who, | |
1074 PurpleMediaSessionType type, gboolean initiator, | |
1075 const gchar *transmitter, | |
1076 guint num_params, GParameter *params) | |
1077 { | |
1078 PurpleMediaBackendFs2Private *priv = | |
1079 PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); | |
1080 GError *err = NULL; | |
1081 FsStream *fsstream = NULL; | |
1082 const gchar *stun_ip = purple_network_get_stun_ip(); | |
1083 const gchar *turn_ip = purple_network_get_turn_ip(); | |
1084 guint _num_params = num_params; | |
1085 GParameter *_params = g_new0(GParameter, num_params + 2); | |
1086 FsStreamDirection type_direction = | |
1087 _session_type_to_fs_stream_direction(type); | |
1088 PurpleMediaBackendFs2Session *session; | |
1089 PurpleMediaBackendFs2Stream *stream; | |
1090 FsParticipant *participant; | |
1091 | |
1092 memcpy(_params, params, sizeof(GParameter) * num_params); | |
1093 | |
1094 if (stun_ip) { | |
1095 purple_debug_info("backend-fs2", | |
1096 "Setting stun-ip on new stream: %s\n", stun_ip); | |
1097 | |
1098 _params[_num_params].name = "stun-ip"; | |
1099 g_value_init(&_params[_num_params].value, G_TYPE_STRING); | |
1100 g_value_set_string(&_params[_num_params].value, stun_ip); | |
1101 ++_num_params; | |
1102 } | |
1103 | |
1104 if (turn_ip && !strcmp("nice", transmitter)) { | |
1105 GValueArray *relay_info = g_value_array_new(0); | |
1106 GValue value; | |
1107 gint turn_port = purple_prefs_get_int( | |
1108 "/purple/network/turn_port"); | |
1109 const gchar *username = purple_prefs_get_string( | |
1110 "/purple/network/turn_username"); | |
1111 const gchar *password = purple_prefs_get_string( | |
1112 "/purple/network/turn_password"); | |
1113 GstStructure *turn_setup = gst_structure_new("relay-info", | |
1114 "ip", G_TYPE_STRING, turn_ip, | |
1115 "port", G_TYPE_UINT, turn_port, | |
1116 "username", G_TYPE_STRING, username, | |
1117 "password", G_TYPE_STRING, password, | |
1118 NULL); | |
1119 | |
1120 if (!turn_setup) { | |
1121 purple_debug_error("backend-fs2", | |
1122 "Error creating relay info structure"); | |
1123 return FALSE; | |
1124 } | |
1125 | |
1126 memset(&value, 0, sizeof(GValue)); | |
1127 g_value_init(&value, GST_TYPE_STRUCTURE); | |
1128 gst_value_set_structure(&value, turn_setup); | |
1129 relay_info = g_value_array_append(relay_info, &value); | |
1130 gst_structure_free(turn_setup); | |
1131 | |
1132 purple_debug_info("backend-fs2", | |
1133 "Setting relay-info on new stream\n"); | |
1134 _params[_num_params].name = "relay-info"; | |
1135 g_value_init(&_params[_num_params].value, | |
1136 G_TYPE_VALUE_ARRAY); | |
1137 g_value_set_boxed(&_params[_num_params].value, | |
1138 relay_info); | |
1139 g_value_array_free(relay_info); | |
1140 } | |
1141 | |
1142 session = _get_session(self, sess_id); | |
1143 | |
1144 if (session == NULL) { | |
1145 purple_debug_error("backend-fs2", | |
1146 "Couldn't find session to create stream.\n"); | |
1147 return FALSE; | |
1148 } | |
1149 | |
1150 participant = _get_participant(self, who); | |
1151 | |
1152 if (participant == NULL) { | |
1153 purple_debug_error("backend-fs2", "Couldn't find " | |
1154 "participant to create stream.\n"); | |
1155 return FALSE; | |
1156 } | |
1157 | |
1158 fsstream = fs_session_new_stream(session->session, participant, | |
1159 type_direction & FS_DIRECTION_RECV, transmitter, | |
1160 _num_params, _params, &err); | |
1161 g_free(_params); | |
1162 | |
1163 if (fsstream == NULL) { | |
1164 if (err) { | |
1165 purple_debug_error("backend-fs2", | |
1166 "Error creating stream: %s\n", | |
1167 err && err->message ? | |
1168 err->message : "NULL"); | |
1169 g_error_free(err); | |
1170 } else | |
1171 purple_debug_error("backend-fs2", | |
1172 "Error creating stream\n"); | |
1173 return FALSE; | |
1174 } | |
1175 | |
1176 stream = g_new0(PurpleMediaBackendFs2Stream, 1); | |
1177 stream->initiator = initiator; | |
1178 stream->participant = g_strdup(who); | |
1179 stream->session = session; | |
1180 stream->stream = fsstream; | |
1181 | |
1182 priv->streams = g_list_append(priv->streams, stream); | |
1183 | |
1184 return TRUE; | |
1185 } | |
1186 | |
1187 static gboolean | |
1026 purple_media_backend_fs2_add_stream(PurpleMediaBackend *self, | 1188 purple_media_backend_fs2_add_stream(PurpleMediaBackend *self, |
1027 const gchar *sess_id, const gchar *who, | 1189 const gchar *sess_id, const gchar *who, |
1028 PurpleMediaSessionType type, gboolean initiator, | 1190 PurpleMediaSessionType type, gboolean initiator, |
1029 const gchar *transmitter, | 1191 const gchar *transmitter, |
1030 guint num_params, GParameter *params) | 1192 guint num_params, GParameter *params) |
1052 purple_debug_error("backend-fs2", | 1214 purple_debug_error("backend-fs2", |
1053 "Error creating the participant.\n"); | 1215 "Error creating the participant.\n"); |
1054 return FALSE; | 1216 return FALSE; |
1055 } | 1217 } |
1056 | 1218 |
1219 if (_get_stream(backend, sess_id, who) == NULL && | |
1220 !_create_stream(backend, sess_id, who, type, | |
1221 initiator, transmitter, num_params, params)) { | |
1222 purple_debug_error("backend-fs2", | |
1223 "Error creating the stream.\n"); | |
1224 return FALSE; | |
1225 } | |
1226 | |
1057 return TRUE; | 1227 return TRUE; |
1058 } | 1228 } |
1059 | 1229 |
1060 static void | 1230 static void |
1061 purple_media_backend_fs2_add_remote_candidates(PurpleMediaBackend *self, | 1231 purple_media_backend_fs2_add_remote_candidates(PurpleMediaBackend *self, |
1111 purple_media_backend_fs2_get_participant(PurpleMediaBackendFs2 *self, | 1281 purple_media_backend_fs2_get_participant(PurpleMediaBackendFs2 *self, |
1112 const gchar *name) | 1282 const gchar *name) |
1113 { | 1283 { |
1114 return _get_participant(self, name); | 1284 return _get_participant(self, name); |
1115 } | 1285 } |
1286 | |
1287 FsStream * | |
1288 purple_media_backend_fs2_get_stream(PurpleMediaBackendFs2 *self, | |
1289 const gchar *sess_id, const gchar *who) | |
1290 { | |
1291 PurpleMediaBackendFs2Stream *stream = | |
1292 _get_stream(self, sess_id, who); | |
1293 return stream != NULL? stream->stream : NULL; | |
1294 } |