| 298 g_free(priv->conference_type); |
303 g_free(priv->conference_type); |
| 299 |
304 |
| 300 for (; priv->streams; priv->streams = |
305 for (; priv->streams; priv->streams = |
| 301 g_list_delete_link(priv->streams, priv->streams)) { |
306 g_list_delete_link(priv->streams, priv->streams)) { |
| 302 PurpleMediaBackendFs2Stream *stream = priv->streams->data; |
307 PurpleMediaBackendFs2Stream *stream = priv->streams->data; |
| 303 |
308 free_stream(stream); |
| 304 /* Remove the connected_cb timeout */ |
|
| 305 if (stream->connected_cb_id != 0) |
|
| 306 purple_timeout_remove(stream->connected_cb_id); |
|
| 307 |
|
| 308 g_free(stream->participant); |
|
| 309 |
|
| 310 if (stream->local_candidates) |
|
| 311 fs_candidate_list_destroy(stream->local_candidates); |
|
| 312 |
|
| 313 if (stream->remote_candidates) |
|
| 314 fs_candidate_list_destroy(stream->remote_candidates); |
|
| 315 |
|
| 316 g_free(stream); |
|
| 317 } |
309 } |
| 318 |
310 |
| 319 if (priv->sessions) { |
311 if (priv->sessions) { |
| 320 GList *sessions = g_hash_table_get_values(priv->sessions); |
312 GList *sessions = g_hash_table_get_values(priv->sessions); |
| 321 |
313 |
| 322 for (; sessions; sessions = |
314 for (; sessions; sessions = |
| 323 g_list_delete_link(sessions, sessions)) { |
315 g_list_delete_link(sessions, sessions)) { |
| 324 PurpleMediaBackendFs2Session *session = |
316 PurpleMediaBackendFs2Session *session = |
| 325 sessions->data; |
317 sessions->data; |
| 326 g_free(session->id); |
318 free_session(session); |
| 327 g_free(session); |
|
| 328 } |
319 } |
| 329 |
320 |
| 330 g_hash_table_destroy(priv->sessions); |
321 g_hash_table_destroy(priv->sessions); |
| 331 } |
322 } |
| 332 |
323 |
| 1136 |
1127 |
| 1137 return TRUE; |
1128 return TRUE; |
| 1138 } |
1129 } |
| 1139 |
1130 |
| 1140 static void |
1131 static void |
| |
1132 remove_element(GstElement *element) |
| |
1133 { |
| |
1134 if (element) { |
| |
1135 gst_element_set_locked_state(element, TRUE); |
| |
1136 gst_element_set_state(element, GST_STATE_NULL); |
| |
1137 gst_bin_remove(GST_BIN(GST_ELEMENT_PARENT(element)), element); |
| |
1138 } |
| |
1139 } |
| |
1140 |
| |
1141 static void |
| 1141 state_changed_cb(PurpleMedia *media, PurpleMediaState state, |
1142 state_changed_cb(PurpleMedia *media, PurpleMediaState state, |
| 1142 gchar *sid, gchar *name, PurpleMediaBackendFs2 *self) |
1143 gchar *sid, gchar *name, PurpleMediaBackendFs2 *self) |
| 1143 { |
1144 { |
| |
1145 if (state == PURPLE_MEDIA_STATE_END) { |
| |
1146 PurpleMediaBackendFs2Private *priv = |
| |
1147 PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); |
| |
1148 |
| |
1149 if (sid && name) { |
| |
1150 PurpleMediaBackendFs2Stream *stream = get_stream(self, sid, name); |
| |
1151 gst_object_unref(stream->stream); |
| |
1152 |
| |
1153 priv->streams = g_list_remove(priv->streams, stream); |
| |
1154 |
| |
1155 remove_element(stream->src); |
| |
1156 remove_element(stream->tee); |
| |
1157 remove_element(stream->volume); |
| |
1158 remove_element(stream->level); |
| |
1159 remove_element(stream->fakesink); |
| |
1160 remove_element(stream->queue); |
| |
1161 |
| |
1162 free_stream(stream); |
| |
1163 } else if (sid && !name) { |
| |
1164 PurpleMediaBackendFs2Session *session = get_session(self, sid); |
| |
1165 GstPad *pad; |
| |
1166 |
| |
1167 g_object_get(session->session, "sink-pad", &pad, NULL); |
| |
1168 gst_pad_unlink(GST_PAD_PEER(pad), pad); |
| |
1169 gst_object_unref(pad); |
| |
1170 |
| |
1171 gst_object_unref(session->session); |
| |
1172 g_hash_table_remove(priv->sessions, session->id); |
| |
1173 |
| |
1174 pad = gst_pad_get_peer(session->srcpad); |
| |
1175 gst_element_remove_pad(GST_ELEMENT_PARENT(pad), pad); |
| |
1176 gst_object_unref(pad); |
| |
1177 gst_object_unref(session->srcpad); |
| |
1178 |
| |
1179 remove_element(session->srcvalve); |
| |
1180 remove_element(session->tee); |
| |
1181 |
| |
1182 free_session(session); |
| |
1183 } |
| |
1184 |
| |
1185 purple_media_manager_remove_output_windows( |
| |
1186 purple_media_get_manager(media), media, sid, name); |
| |
1187 } |
| 1144 } |
1188 } |
| 1145 |
1189 |
| 1146 static void |
1190 static void |
| 1147 stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type, |
1191 stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type, |
| 1148 gchar *sid, gchar *name, gboolean local, |
1192 gchar *sid, gchar *name, gboolean local, |
| 1418 purple_debug_info("backend-fs2", "connecting pad: %s\n", |
1462 purple_debug_info("backend-fs2", "connecting pad: %s\n", |
| 1419 gst_pad_link(srcpad, sinkpad) == GST_PAD_LINK_OK |
1463 gst_pad_link(srcpad, sinkpad) == GST_PAD_LINK_OK |
| 1420 ? "success" : "failure"); |
1464 ? "success" : "failure"); |
| 1421 gst_element_set_locked_state(session->src, FALSE); |
1465 gst_element_set_locked_state(session->src, FALSE); |
| 1422 gst_object_unref(session->src); |
1466 gst_object_unref(session->src); |
| |
1467 gst_object_unref(sinkpad); |
| 1423 |
1468 |
| 1424 gst_element_set_state(session->src, GST_STATE_PLAYING); |
1469 gst_element_set_state(session->src, GST_STATE_PLAYING); |
| 1425 |
1470 |
| 1426 purple_media_manager_create_output_window(purple_media_get_manager( |
1471 purple_media_manager_create_output_window(purple_media_get_manager( |
| 1427 priv->media), priv->media, sess_id, NULL); |
1472 priv->media), priv->media, sess_id, NULL); |
| 1601 |
1653 |
| 1602 if (stream->src == NULL) { |
1654 if (stream->src == NULL) { |
| 1603 GstElement *sink = NULL; |
1655 GstElement *sink = NULL; |
| 1604 |
1656 |
| 1605 if (codec->media_type == FS_MEDIA_TYPE_AUDIO) { |
1657 if (codec->media_type == FS_MEDIA_TYPE_AUDIO) { |
| 1606 GstElement *queue = NULL; |
|
| 1607 double output_volume = purple_prefs_get_int( |
1658 double output_volume = purple_prefs_get_int( |
| 1608 "/purple/media/audio/volume/output")/10.0; |
1659 "/purple/media/audio/volume/output")/10.0; |
| 1609 /* |
1660 /* |
| 1610 * Should this instead be: |
1661 * Should this instead be: |
| 1611 * audioconvert ! audioresample ! liveadder ! |
1662 * audioconvert ! audioresample ! liveadder ! |
| 1612 * audioresample ! audioconvert ! realsink |
1663 * audioresample ! audioconvert ! realsink |
| 1613 */ |
1664 */ |
| 1614 queue = gst_element_factory_make("queue", NULL); |
1665 stream->queue = gst_element_factory_make("queue", NULL); |
| 1615 stream->volume = gst_element_factory_make( |
1666 stream->volume = gst_element_factory_make( |
| 1616 "volume", NULL); |
1667 "volume", NULL); |
| 1617 g_object_set(stream->volume, "volume", |
1668 g_object_set(stream->volume, "volume", |
| 1618 output_volume, NULL); |
1669 output_volume, NULL); |
| 1619 stream->level = gst_element_factory_make( |
1670 stream->level = gst_element_factory_make( |
| 1623 sink = purple_media_manager_get_element( |
1674 sink = purple_media_manager_get_element( |
| 1624 purple_media_get_manager(priv->media), |
1675 purple_media_get_manager(priv->media), |
| 1625 PURPLE_MEDIA_RECV_AUDIO, priv->media, |
1676 PURPLE_MEDIA_RECV_AUDIO, priv->media, |
| 1626 stream->session->id, |
1677 stream->session->id, |
| 1627 stream->participant); |
1678 stream->participant); |
| 1628 gst_bin_add(GST_BIN(priv->confbin), queue); |
1679 gst_bin_add(GST_BIN(priv->confbin), stream->queue); |
| 1629 gst_bin_add(GST_BIN(priv->confbin), stream->volume); |
1680 gst_bin_add(GST_BIN(priv->confbin), stream->volume); |
| 1630 gst_bin_add(GST_BIN(priv->confbin), stream->level); |
1681 gst_bin_add(GST_BIN(priv->confbin), stream->level); |
| 1631 gst_bin_add(GST_BIN(priv->confbin), sink); |
1682 gst_bin_add(GST_BIN(priv->confbin), sink); |
| 1632 gst_element_set_state(sink, GST_STATE_PLAYING); |
1683 gst_element_set_state(sink, GST_STATE_PLAYING); |
| 1633 gst_element_set_state(stream->level, GST_STATE_PLAYING); |
1684 gst_element_set_state(stream->level, GST_STATE_PLAYING); |
| 1634 gst_element_set_state(stream->volume, GST_STATE_PLAYING); |
1685 gst_element_set_state(stream->volume, GST_STATE_PLAYING); |
| 1635 gst_element_set_state(queue, GST_STATE_PLAYING); |
1686 gst_element_set_state(stream->queue, GST_STATE_PLAYING); |
| 1636 gst_element_link(stream->level, sink); |
1687 gst_element_link(stream->level, sink); |
| 1637 gst_element_link(stream->volume, stream->level); |
1688 gst_element_link(stream->volume, stream->level); |
| 1638 gst_element_link(queue, stream->volume); |
1689 gst_element_link(stream->queue, stream->volume); |
| 1639 sink = queue; |
1690 sink = stream->queue; |
| 1640 } else if (codec->media_type == FS_MEDIA_TYPE_VIDEO) { |
1691 } else if (codec->media_type == FS_MEDIA_TYPE_VIDEO) { |
| 1641 stream->src = gst_element_factory_make( |
1692 stream->src = gst_element_factory_make( |
| 1642 "fsfunnel", NULL); |
1693 "fsfunnel", NULL); |
| 1643 sink = gst_element_factory_make( |
1694 sink = gst_element_factory_make( |
| 1644 "fakesink", NULL); |
1695 "fakesink", NULL); |
| 1645 g_object_set(G_OBJECT(sink), "async", FALSE, NULL); |
1696 g_object_set(G_OBJECT(sink), "async", FALSE, NULL); |
| 1646 gst_bin_add(GST_BIN(priv->confbin), sink); |
1697 gst_bin_add(GST_BIN(priv->confbin), sink); |
| 1647 gst_element_set_state(sink, GST_STATE_PLAYING); |
1698 gst_element_set_state(sink, GST_STATE_PLAYING); |
| |
1699 stream->fakesink = sink; |
| 1648 } |
1700 } |
| 1649 stream->tee = gst_element_factory_make("tee", NULL); |
1701 stream->tee = gst_element_factory_make("tee", NULL); |
| 1650 gst_bin_add_many(GST_BIN(priv->confbin), |
1702 gst_bin_add_many(GST_BIN(priv->confbin), |
| 1651 stream->src, stream->tee, NULL); |
1703 stream->src, stream->tee, NULL); |
| 1652 gst_element_set_state(stream->tee, GST_STATE_PLAYING); |
1704 gst_element_set_state(stream->tee, GST_STATE_PLAYING); |
| 1812 G_CALLBACK(src_pad_added_cb), stream); |
1864 G_CALLBACK(src_pad_added_cb), stream); |
| 1813 |
1865 |
| 1814 return TRUE; |
1866 return TRUE; |
| 1815 } |
1867 } |
| 1816 |
1868 |
| |
1869 static void |
| |
1870 free_stream(PurpleMediaBackendFs2Stream *stream) |
| |
1871 { |
| |
1872 /* Remove the connected_cb timeout */ |
| |
1873 if (stream->connected_cb_id != 0) |
| |
1874 purple_timeout_remove(stream->connected_cb_id); |
| |
1875 |
| |
1876 g_free(stream->participant); |
| |
1877 |
| |
1878 if (stream->local_candidates) |
| |
1879 fs_candidate_list_destroy(stream->local_candidates); |
| |
1880 |
| |
1881 if (stream->remote_candidates) |
| |
1882 fs_candidate_list_destroy(stream->remote_candidates); |
| |
1883 |
| |
1884 g_free(stream); |
| |
1885 } |
| |
1886 |
| 1817 static gboolean |
1887 static gboolean |
| 1818 purple_media_backend_fs2_add_stream(PurpleMediaBackend *self, |
1888 purple_media_backend_fs2_add_stream(PurpleMediaBackend *self, |
| 1819 const gchar *sess_id, const gchar *who, |
1889 const gchar *sess_id, const gchar *who, |
| 1820 PurpleMediaSessionType type, gboolean initiator, |
1890 PurpleMediaSessionType type, gboolean initiator, |
| 1821 const gchar *transmitter, |
1891 const gchar *transmitter, |