maiku.vv: 33c389f2: Wait for Farsight 2's codecs-ready prope...
maiku at soc.pidgin.im
maiku at soc.pidgin.im
Thu Sep 4 23:31:27 EDT 2008
-----------------------------------------------------------------
Revision: 33c389f28f8fbefb95f7cf1bc22730ffd1d92bcb
Ancestor: 1423c95edd2cc48f194d3574fc0798cd8249869e
Author: maiku at soc.pidgin.im
Date: 2008-09-05T02:18:15
Branch: im.pidgin.maiku.vv
URL: http://d.pidgin.im/viewmtn/revision/info/33c389f28f8fbefb95f7cf1bc22730ffd1d92bcb
Modified files:
libpurple/media.c libpurple/media.h
libpurple/protocols/jabber/jingle.c pidgin/gtkmedia.c
ChangeLog:
Wait for Farsight 2's codecs-ready property to be TRUE before using codecs.
This will make codecs that need extra configuration, such as THEORA and
H264, work consistently.
-------------- next part --------------
============================================================
--- libpurple/media.c 941cd561f2aa4fe43bbe9dd8cb0df1ac4d7d56e8
+++ libpurple/media.c 5c6fb6e8b18c47210149f378ad13362893ebd872
@@ -106,6 +106,7 @@ enum {
NEW_CANDIDATE,
CANDIDATES_PREPARED,
CANDIDATE_PAIR,
+ CODECS_READY,
LAST_SIGNAL
};
static guint purple_media_signals[LAST_SIGNAL] = {0};
@@ -215,6 +216,10 @@ purple_media_class_init (PurpleMediaClas
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
purple_smarshal_VOID__BOXED_BOXED,
G_TYPE_NONE, 2, FS_TYPE_CANDIDATE, FS_TYPE_CANDIDATE);
+ purple_media_signals[CODECS_READY] = g_signal_new("codecs-ready", G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
g_type_class_add_private(klass, sizeof(PurpleMediaPrivate));
}
@@ -663,6 +668,18 @@ media_bus_call(GstBus *bus, GstMessage *
} else if (gst_structure_has_name(msg->structure,
"farsight-codecs-changed")) {
+ GList *sessions = g_hash_table_get_values(PURPLE_MEDIA(media)->priv->sessions);
+ FsSession *fssession = g_value_get_object(gst_structure_get_value(msg->structure, "session"));
+ for (; sessions; sessions = g_list_delete_link(sessions, sessions)) {
+ PurpleMediaSession *session = sessions->data;
+ if (session->session == fssession) {
+ g_signal_emit(session->media,
+ purple_media_signals[CODECS_READY],
+ 0, &session->id);
+ g_list_free(sessions);
+ break;
+ }
+ }
}
break;
}
@@ -880,7 +897,7 @@ purple_media_video_init_src(GstElement *
src = gst_element_factory_make(video_plugin, "purplevideosource");
gst_bin_add(GST_BIN(*sendbin), src);
- tee = gst_element_factory_make("tee", NULL);
+ tee = gst_element_factory_make("tee", "purplevideosrctee");
gst_bin_add(GST_BIN(*sendbin), tee);
gst_element_link(src, tee);
@@ -893,13 +910,14 @@ purple_media_video_init_src(GstElement *
g_object_set (G_OBJECT(src), "is-live", TRUE, NULL);
}
- pad = gst_element_get_pad(queue, "src");
+ pad = gst_element_get_static_pad(queue, "src");
ghost = gst_ghost_pad_new("ghostsrc", pad);
+ gst_object_unref(pad);
gst_element_add_pad(*sendbin, ghost);
- queue = gst_element_factory_make("queue", NULL);
+ queue = gst_element_factory_make("queue", "purplelocalvideoqueue");
gst_bin_add(GST_BIN(*sendbin), queue);
- gst_element_link(tee, queue);
+ /* The queue is linked later, when the local video is ready to be shown */
local_sink = gst_element_factory_make("autovideosink", "purplelocalvideosink");
gst_bin_add(GST_BIN(*sendbin), local_sink);
@@ -1316,6 +1334,15 @@ purple_media_set_send_codec(PurpleMedia
return TRUE;
}
+gboolean
+purple_media_codecs_ready(PurpleMedia *media, const gchar *sess_id)
+{
+ PurpleMediaSession *session = purple_media_get_session(media, sess_id);
+ gboolean ret;
+ g_object_get(session->session, "codecs-ready", &ret, NULL);
+ return ret;
+}
+
void purple_media_mute(PurpleMedia *media, gboolean active)
{
GList *sessions = g_hash_table_get_values(media->priv->sessions);
============================================================
--- libpurple/media.h 359360edf6edcbcd4d69e7da23e83f2565a76870
+++ libpurple/media.h 6f2ed391b1ff575ec8d6be06c724c9f607c8ffa6
@@ -472,6 +472,16 @@ gboolean purple_media_set_send_codec(Pur
gboolean purple_media_set_send_codec(PurpleMedia *media, const gchar *sess_id, FsCodec *codec);
/**
+ * Gets whether a session's codecs are ready to be used.
+ *
+ * @param media The media object to find the session in.
+ * @param sess_id The session id of the session to check.
+ *
+ * @return @c TRUE The codecs are ready, or @c FALSE otherwise.
+ */
+gboolean purple_media_codecs_ready(PurpleMedia *media, const gchar *sess_id);
+
+/**
* Mutes or unmutes all the audio local audio sources.
*
* @param media The media object to mute or unmute
============================================================
--- libpurple/protocols/jabber/jingle.c c341efe0614b9574529bd2bc864ceb9d386923e8
+++ libpurple/protocols/jabber/jingle.c 670d4292cd432fdf0bbee6dae2a1b999a3868915
@@ -814,7 +814,22 @@ jabber_jingle_session_send_content_accep
jabber_iq_send(result);
}
#endif
+
static void
+jabber_jingle_session_accept(JingleSession *session)
+{
+ if (jabber_jingle_session_get_state(session) == ACCEPTED &&
+ purple_media_candidates_prepared(
+ jabber_jingle_session_get_media(session),
+ jabber_jingle_session_get_remote_jid(session))) {
+ jabber_iq_send(jabber_jingle_session_create_session_accept(session));
+
+ purple_debug_info("jingle", "Sent session accept.\n");
+ jabber_jingle_session_set_state(session, ACTIVE);
+ }
+}
+
+static void
jabber_jingle_session_send_session_accept(JingleSession *session)
{
/* create transport-info packages */
@@ -843,13 +858,8 @@ jabber_jingle_session_send_session_accep
jabber_jingle_session_content_get_name(jsc))));
}
- if (purple_media_candidates_prepared(media, remote_jid)) {
- jabber_iq_send(jabber_jingle_session_create_session_accept(session));
-
- purple_debug_info("jingle", "Sent session accept.\n");
- jabber_jingle_session_set_state(session, ACTIVE);
- } else
- jabber_jingle_session_set_state(session, ACCEPTED);
+ jabber_jingle_session_set_state(session, ACCEPTED);
+ jabber_jingle_session_accept(session);
}
static void
@@ -942,17 +952,93 @@ jabber_jingle_session_candidate_pair_est
FsCandidate *remote_candidate,
JingleSession *session)
{
- if (!jabber_jingle_session_is_initiator(session) &&
- jabber_jingle_session_get_state(session) == ACCEPTED &&
- purple_media_candidates_prepared(media,
- jabber_jingle_session_get_remote_jid(session))) {
- jabber_iq_send(jabber_jingle_session_create_session_accept(session));
-
- purple_debug_info("jingle", "Sent session accept.\n");
- jabber_jingle_session_set_state(session, ACTIVE);
+ if (!jabber_jingle_session_is_initiator(session)) {
+ jabber_jingle_session_accept(session);
}
}
+static void
+jabber_jingle_session_initiate_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
+{
+ const char *from = xmlnode_get_attrib(packet, "from");
+ JingleSession *session = jabber_jingle_session_find_by_jid(js, from);
+ PurpleMedia *media;
+ GList *contents;
+
+ if (!session) {
+ /* respond with an error here */
+ purple_debug_error("jingle", "Received session-initiate ack"
+ " to nonexistent session\n");
+ return;
+ }
+
+ media = session->media;
+
+ if (!strcmp(xmlnode_get_attrib(packet, "type"), "error")) {
+ purple_media_got_hangup(media);
+ return;
+ }
+
+ /* catch errors */
+ if (xmlnode_get_child(packet, "error")) {
+ purple_media_got_hangup(media);
+ return;
+ }
+
+ /* create transport-info packages */
+ contents = jabber_jingle_session_get_contents(session);
+ for (; contents; contents = contents->next) {
+ JingleSessionContent *jsc = contents->data;
+ GList *candidates = purple_media_get_local_candidates(
+ jabber_jingle_session_get_media(session),
+ jabber_jingle_session_content_get_name(jsc),
+ jabber_jingle_session_get_remote_jid(session));
+ purple_debug_info("jingle",
+ "jabber_session_candidates_prepared: %d candidates\n",
+ g_list_length(candidates));
+ for (; candidates; candidates = candidates->next) {
+ FsCandidate *candidate = candidates->data;
+ JabberIq *result = jabber_jingle_session_create_transport_info(jsc,
+ candidate);
+ jabber_iq_send(result);
+ }
+ fs_candidate_list_destroy(candidates);
+ }
+
+ jabber_jingle_session_set_state(session, GOT_ACK);
+}
+
+static void
+jabber_jingle_session_codecs_ready_cb(PurpleMedia *media,
+ const gchar *sess_id,
+ JingleSession *session)
+{
+ GList *contents = jabber_jingle_session_get_contents(session);
+ for (; contents; contents = g_list_delete_link(contents, contents)) {
+ JingleSessionContent *jsc = contents->data;
+ if (!purple_media_codecs_ready(media,
+ jabber_jingle_session_content_get_name(jsc))) {
+ break;
+ }
+ }
+
+ if (contents != NULL)
+ g_list_free(contents);
+ else if (jabber_jingle_session_is_initiator(session)
+ && jabber_jingle_session_get_state(session) == PENDING) {
+ JabberIq *request;
+
+ /* create request */
+ request = jabber_jingle_session_create_session_initiate(session);
+ jabber_iq_set_callback(request, jabber_jingle_session_initiate_result_cb, NULL);
+
+ /* send request to other part */
+ jabber_iq_send(request);
+ } else {
+ jabber_jingle_session_accept(session);
+ }
+}
+
static gboolean
jabber_jingle_session_initiate_media_internal(JingleSession *session,
const char *initiator,
@@ -1027,69 +1113,19 @@ jabber_jingle_session_initiate_media_int
G_CALLBACK(jabber_jingle_session_new_candidate_cb), session);
g_signal_connect(G_OBJECT(media), "candidate-pair",
G_CALLBACK(jabber_jingle_session_candidate_pair_established_cb), session);
+ g_signal_connect(G_OBJECT(media), "codecs-ready",
+ G_CALLBACK(jabber_jingle_session_codecs_ready_cb), session);
purple_media_ready(media);
return TRUE;
}
-static void
-jabber_jingle_session_initiate_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
-{
- const char *from = xmlnode_get_attrib(packet, "from");
- JingleSession *session = jabber_jingle_session_find_by_jid(js, from);
- PurpleMedia *media;
- GList *contents;
-
- if (!session) {
- /* respond with an error here */
- purple_debug_error("jingle", "Received session-initiate ack"
- " to nonexistent session\n");
- return;
- }
-
- media = session->media;
-
- if (!strcmp(xmlnode_get_attrib(packet, "type"), "error")) {
- purple_media_got_hangup(media);
- return;
- }
-
- /* catch errors */
- if (xmlnode_get_child(packet, "error")) {
- purple_media_got_hangup(media);
- return;
- }
-
- /* create transport-info packages */
- contents = jabber_jingle_session_get_contents(session);
- for (; contents; contents = contents->next) {
- JingleSessionContent *jsc = contents->data;
- GList *candidates = purple_media_get_local_candidates(
- jabber_jingle_session_get_media(session),
- jabber_jingle_session_content_get_name(jsc),
- jabber_jingle_session_get_remote_jid(session));
- purple_debug_info("jingle",
- "jabber_session_candidates_prepared: %d candidates\n",
- g_list_length(candidates));
- for (; candidates; candidates = candidates->next) {
- FsCandidate *candidate = candidates->data;
- JabberIq *result = jabber_jingle_session_create_transport_info(jsc,
- candidate);
- jabber_iq_send(result);
- }
- fs_candidate_list_destroy(candidates);
- }
-
- jabber_jingle_session_set_state(session, GOT_ACK);
-}
-
PurpleMedia *
jabber_jingle_session_initiate_media(JabberStream *js, const char *who,
PurpleMediaSessionType type)
{
/* create content negotiation */
- JabberIq *request;
JingleSession *session;
JabberBuddy *jb;
JabberBuddyResource *jbr;
@@ -1129,13 +1165,6 @@ jabber_jingle_session_initiate_media(Jab
g_free(jid);
g_free(me);
- /* create request */
- request = jabber_jingle_session_create_session_initiate(session);
- jabber_iq_set_callback(request, jabber_jingle_session_initiate_result_cb, NULL);
-
- /* send request to other part */
- jabber_iq_send(request);
-
return session->media;
}
============================================================
--- pidgin/gtkmedia.c fc5dafd0e42a74ca0411894d4cc2b2029a4d2619
+++ pidgin/gtkmedia.c e6bdc85a826b2957d8bffc0e428f9e3f20b442a6
@@ -314,18 +314,18 @@ pidgin_media_ready_cb(PurpleMedia *media
if (!audiosendbin && (type & PURPLE_MEDIA_SEND_AUDIO)) {
purple_media_audio_init_src(&audiosendbin, &audiosendlevel);
purple_media_set_src(media, sessions->data, audiosendbin);
- gst_element_set_state(audiosendbin, GST_STATE_READY);
+ gst_element_set_state(audiosendbin, GST_STATE_PLAYING);
}
if (!audiorecvbin && (type & PURPLE_MEDIA_RECV_AUDIO)) {
purple_media_audio_init_recv(&audiorecvbin, &audiorecvlevel);
purple_media_set_sink(media, sessions->data, audiorecvbin);
gst_element_set_state(audiorecvbin, GST_STATE_READY);
}
- } else if (purple_media_get_session_type(media, sessions->data) & PURPLE_MEDIA_VIDEO) {
+ } else if (type & PURPLE_MEDIA_VIDEO) {
if (!videosendbin && (type & PURPLE_MEDIA_SEND_VIDEO)) {
purple_media_video_init_src(&videosendbin);
purple_media_set_src(media, sessions->data, videosendbin);
- gst_element_set_state(videosendbin, GST_STATE_READY);
+ gst_element_set_state(videosendbin, GST_STATE_PLAYING);
}
if (!videorecvbin && (type & PURPLE_MEDIA_RECV_VIDEO)) {
purple_media_video_init_recv(&videorecvbin);
@@ -401,6 +401,7 @@ pidgin_media_accept_cb(PurpleMedia *medi
if (videosendbin) {
GtkWidget *aspect;
GtkWidget *local_video;
+ GstElement *tee, *queue;
aspect = gtk_aspect_frame_new(NULL, 0.5, 0.5, 4.0/3.0, FALSE);
gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN);
@@ -414,7 +415,11 @@ pidgin_media_accept_cb(PurpleMedia *medi
gtkmedia->priv->local_video = local_video;
- gst_element_set_state(videosendbin, GST_STATE_PLAYING);
+ tee = gst_bin_get_by_name(GST_BIN(videosendbin), "purplevideosrctee");
+ queue = gst_bin_get_by_name(GST_BIN(videosendbin), "purplelocalvideoqueue");
+ gst_element_link(tee, queue);
+ gst_object_unref(tee);
+ gst_object_unref(queue);
}
if (audiorecvbin) {
@@ -435,7 +440,6 @@ pidgin_media_accept_cb(PurpleMedia *medi
gtk_box_pack_end(GTK_BOX(send_widget),
gtkmedia->priv->send_progress, FALSE, FALSE, 0);
gtk_widget_show(gtkmedia->priv->send_progress);
- gst_element_set_state(audiosendbin, GST_STATE_PLAYING);
gtk_widget_show(gtkmedia->priv->mute);
}
More information about the Commits
mailing list