libpurple/media/backend-fs2.c

changeset 31618
5a2acc3fb58c
parent 31566
fa37798387fa
child 31687
4877d06f3234
equal deleted inserted replaced
31617:cde45e08dbfd 31618:5a2acc3fb58c
84 GList *codecs); 84 GList *codecs);
85 static gboolean purple_media_backend_fs2_set_send_codec( 85 static gboolean purple_media_backend_fs2_set_send_codec(
86 PurpleMediaBackend *self, const gchar *sess_id, 86 PurpleMediaBackend *self, const gchar *sess_id,
87 PurpleMediaCodec *codec); 87 PurpleMediaCodec *codec);
88 88
89 static void free_stream(PurpleMediaBackendFs2Stream *stream);
90 static void free_session(PurpleMediaBackendFs2Session *session);
91
89 struct _PurpleMediaBackendFs2Class 92 struct _PurpleMediaBackendFs2Class
90 { 93 {
91 GObjectClass parent_class; 94 GObjectClass parent_class;
92 }; 95 };
93 96
108 111
109 GstElement *src; 112 GstElement *src;
110 GstElement *tee; 113 GstElement *tee;
111 GstElement *volume; 114 GstElement *volume;
112 GstElement *level; 115 GstElement *level;
116 GstElement *fakesink;
117 GstElement *queue;
113 118
114 GList *local_candidates; 119 GList *local_candidates;
115 GList *remote_candidates; 120 GList *remote_candidates;
116 121
117 guint connected_cb_id; 122 guint connected_cb_id;
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);
1534 } 1579 }
1535 1580
1536 return TRUE; 1581 return TRUE;
1537 } 1582 }
1538 1583
1584 static void
1585 free_session(PurpleMediaBackendFs2Session *session)
1586 {
1587 g_free(session->id);
1588 g_free(session);
1589 }
1590
1539 static gboolean 1591 static gboolean
1540 create_participant(PurpleMediaBackendFs2 *self, const gchar *name) 1592 create_participant(PurpleMediaBackendFs2 *self, const gchar *name)
1541 { 1593 {
1542 PurpleMediaBackendFs2Private *priv = 1594 PurpleMediaBackendFs2Private *priv =
1543 PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self); 1595 PURPLE_MEDIA_BACKEND_FS2_GET_PRIVATE(self);
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,

mercurial