comparison libpurple/media/backend-fs2.c @ 31105:0485aed45f5b

This patch fixes #12758. If the user starts two parallel video calls, then ends one of them some time later, the user can still see and hear the participant from the non-ended call, but the other participant no longer receives the user's video or audio. The problem lies in purple_media_backend_fs2_dispose(), which calls gst_element_set_state() in such a way that the media sources stop sending data. Additional reference information is mentioned on #12758, comment 6 (http://developer.pidgin.im/ticket/12758#comment:6). committer: John Bailey <rekkanoryo@rekkanoryo.org>
author jakub.adam@ktknet.cz
date Sat, 08 Jan 2011 02:13:40 +0000
parents a8cc50c2279f
children 66fe4bda9a85
comparison
equal deleted inserted replaced
31104:43ab38a1f55c 31105:0485aed45f5b
124 FsSession *session; 124 FsSession *session;
125 125
126 GstElement *src; 126 GstElement *src;
127 GstElement *tee; 127 GstElement *tee;
128 128
129 GstPad *srcpad;
130
129 PurpleMediaSessionType type; 131 PurpleMediaSessionType type;
130 }; 132 };
131 133
132 struct _PurpleMediaBackendFs2Private 134 struct _PurpleMediaBackendFs2Private
133 { 135 {
165 if (priv->confbin) { 167 if (priv->confbin) {
166 GstElement *pipeline; 168 GstElement *pipeline;
167 169
168 pipeline = purple_media_manager_get_pipeline( 170 pipeline = purple_media_manager_get_pipeline(
169 purple_media_get_manager(priv->media)); 171 purple_media_get_manager(priv->media));
172
173 /* All connections to media sources should be blocked before confbin is
174 * removed, to prevent freezing of any other simultaneously running
175 * media calls. */
176 if (priv->sessions) {
177 GList *sessions = g_hash_table_get_values(priv->sessions);
178 for (; sessions; sessions =
179 g_list_delete_link(sessions, sessions)) {
180 PurpleMediaBackendFs2Session *session = sessions->data;
181 if (session->srcpad) {
182 gst_pad_set_blocked(session->srcpad, TRUE);
183 gst_object_unref(session->srcpad);
184 session->srcpad = NULL;
185 }
186 }
187 }
170 188
171 gst_element_set_locked_state(priv->confbin, TRUE); 189 gst_element_set_locked_state(priv->confbin, TRUE);
172 gst_element_set_state(GST_ELEMENT(priv->confbin), 190 gst_element_set_state(GST_ELEMENT(priv->confbin),
173 GST_STATE_NULL); 191 GST_STATE_NULL);
174 192
1256 FsMediaType media_type = session_type_to_fs_media_type(type); 1274 FsMediaType media_type = session_type_to_fs_media_type(type);
1257 FsStreamDirection type_direction = 1275 FsStreamDirection type_direction =
1258 session_type_to_fs_stream_direction(type); 1276 session_type_to_fs_stream_direction(type);
1259 GstElement *src; 1277 GstElement *src;
1260 GstPad *sinkpad, *srcpad; 1278 GstPad *sinkpad, *srcpad;
1279 GstPad *ghost = NULL;
1261 1280
1262 if ((type_direction & FS_DIRECTION_SEND) == 0) 1281 if ((type_direction & FS_DIRECTION_SEND) == 0)
1263 return TRUE; 1282 return TRUE;
1264 1283
1265 session_type = session_type_from_fs( 1284 session_type = session_type_from_fs(
1295 1314
1296 /* This supposedly isn't necessary, but it silences some warnings */ 1315 /* This supposedly isn't necessary, but it silences some warnings */
1297 if (GST_ELEMENT_PARENT(priv->confbin) 1316 if (GST_ELEMENT_PARENT(priv->confbin)
1298 == GST_ELEMENT_PARENT(session->src)) { 1317 == GST_ELEMENT_PARENT(session->src)) {
1299 GstPad *pad = gst_element_get_static_pad(session->tee, "sink"); 1318 GstPad *pad = gst_element_get_static_pad(session->tee, "sink");
1300 GstPad *ghost = gst_ghost_pad_new(NULL, pad); 1319 ghost = gst_ghost_pad_new(NULL, pad);
1301 gst_object_unref(pad); 1320 gst_object_unref(pad);
1302 gst_pad_set_active(ghost, TRUE); 1321 gst_pad_set_active(ghost, TRUE);
1303 gst_element_add_pad(priv->confbin, ghost); 1322 gst_element_add_pad(priv->confbin, ghost);
1304 } 1323 }
1305 1324
1306 gst_element_set_state(session->tee, GST_STATE_PLAYING); 1325 gst_element_set_state(session->tee, GST_STATE_PLAYING);
1307 gst_element_link(session->src, priv->confbin); 1326 gst_element_link(session->src, priv->confbin);
1327 if (ghost)
1328 session->srcpad = gst_pad_get_peer(ghost);
1308 1329
1309 g_object_get(session->session, "sink-pad", &sinkpad, NULL); 1330 g_object_get(session->session, "sink-pad", &sinkpad, NULL);
1310 if (session->type & PURPLE_MEDIA_SEND_AUDIO) { 1331 if (session->type & PURPLE_MEDIA_SEND_AUDIO) {
1311 gchar *name = g_strdup_printf("volume_%s", session->id); 1332 gchar *name = g_strdup_printf("volume_%s", session->id);
1312 GstElement *level; 1333 GstElement *level;