Mercurial > pidgin.yaz
diff libpurple/protocols/jabber/jingle.c @ 25671:12a16471f94e
Refactored PurpleMedia to make creating audio or video sessions virtually identical. Audio, video, and audio/video sessions now work. Also added videotestsrc to the video plugin preference.
author | Mike Ruprecht <maiku@soc.pidgin.im> |
---|---|
date | Fri, 06 Jun 2008 07:43:03 +0000 |
parents | 42e17cc5b6d2 |
children | 9983353706b8 |
line wrap: on
line diff
--- a/libpurple/protocols/jabber/jingle.c Wed Jun 04 19:21:49 2008 +0000 +++ b/libpurple/protocols/jabber/jingle.c Fri Jun 06 07:43:03 2008 +0000 @@ -278,24 +278,31 @@ } static GList * -jabber_jingle_get_codecs(const xmlnode *description) +jabber_jingle_get_codecs(xmlnode *description) { GList *codecs = NULL; xmlnode *codec_element = NULL; const char *encoding_name,*id, *clock_rate; FsCodec *codec; - + FsMediaType type = !strcmp(xmlnode_get_namespace(description), JINGLE_VIDEO) ? + FS_MEDIA_TYPE_VIDEO : FS_MEDIA_TYPE_AUDIO; + for (codec_element = xmlnode_get_child(description, "payload-type") ; codec_element ; codec_element = xmlnode_get_next_twin(codec_element)) { encoding_name = xmlnode_get_attrib(codec_element, "name"); + id = xmlnode_get_attrib(codec_element, "id"); clock_rate = xmlnode_get_attrib(codec_element, "clockrate"); codec = fs_codec_new(atoi(id), encoding_name, - FS_MEDIA_TYPE_AUDIO, + type, clock_rate ? atoi(clock_rate) : 0); - codecs = g_list_append(codecs, codec); + purple_debug_info("jingle", "codec: %i, %s, %s, %i\n", codec->id, + codec->encoding_name, codec->media_type == FS_MEDIA_TYPE_AUDIO ? + "FS_MEDIA_TYPE_AUDIO" : codec->media_type == FS_MEDIA_TYPE_VIDEO ? + "FS_MEDIA_TYPE_VIDEO" : "FS_MEDIA_TYPE_NONE", codec->clock_rate); + codecs = g_list_append(codecs, codec); } return codecs; } @@ -397,8 +404,9 @@ { JingleSession *session = jabber_jingle_session_content_get_session(jsc); PurpleMedia *media = jabber_jingle_session_get_media(session); - /* change this to the generic function when PurpleMedia supports video */ - GList *codecs = purple_media_get_local_audio_codecs(media); + /* should this be local_codecs or negotiated-codecs? */ + GList *codecs = purple_media_get_local_codecs(media, + jabber_jingle_session_content_get_name(jsc)); for (; codecs ; codecs = codecs->next) { FsCodec *codec = (FsCodec*)codecs->data; @@ -407,8 +415,7 @@ g_snprintf(id, sizeof(id), "%d", codec->id); g_snprintf(clockrate, sizeof(clockrate), "%d", codec->clock_rate); - g_snprintf(channels, sizeof(channels), "%d", - codec->channels == 0 ? 1 : codec->channels); + g_snprintf(channels, sizeof(channels), "%d", codec->channels); xmlnode_set_attrib(payload, "name", codec->encoding_name); xmlnode_set_attrib(payload, "id", id); @@ -569,35 +576,7 @@ jabber_jingle_session_get_remote_jid(session)); return result; } - -static xmlnode * -jabber_jingle_session_create_description(const JingleSession *sess) -{ - GList *codecs = purple_media_get_local_audio_codecs(sess->media); - xmlnode *description = xmlnode_new("description"); - - xmlnode_set_namespace(description, JINGLE_AUDIO); - - /* get codecs */ - for (; codecs ; codecs = codecs->next) { - FsCodec *codec = (FsCodec*)codecs->data; - char id[8], clockrate[10], channels[10]; - xmlnode *payload = xmlnode_new_child(description, "payload-type"); - - g_snprintf(id, sizeof(id), "%d", codec->id); - g_snprintf(clockrate, sizeof(clockrate), "%d", codec->clock_rate); - g_snprintf(channels, sizeof(channels), "%d", codec->channels); - - xmlnode_set_attrib(payload, "name", codec->encoding_name); - xmlnode_set_attrib(payload, "id", id); - xmlnode_set_attrib(payload, "clockrate", clockrate); - xmlnode_set_attrib(payload, "channels", channels); - } - - fs_codec_list_destroy(codecs); - return description; -} - +#if 0 static xmlnode * jabber_jingle_session_create_content_accept(const JingleSession *sess) { @@ -649,6 +628,7 @@ return jingle; } +#endif static JabberIq * jabber_jingle_session_create_session_accept(const JingleSession *session, @@ -744,7 +724,7 @@ jabber_jingle_session_add_candidate_iceudp(transport, candidate, NULL); return request; } - +#if 0 static void jabber_jingle_session_send_content_accept(JingleSession *session) { @@ -757,7 +737,7 @@ xmlnode_insert_child(result->node, jingle); jabber_iq_send(result); } - +#endif static void jabber_jingle_session_send_session_accept(JingleSession *session) { @@ -766,8 +746,10 @@ GList *contents = jabber_jingle_session_get_contents(session); for (; contents; contents = contents->next) { JingleSessionContent *jsc = contents->data; - GList *candidates = purple_media_get_local_audio_candidates( - jabber_jingle_session_get_media(session)); + GList *candidates = purple_media_get_local_candidates( + media, + jabber_jingle_session_content_get_name(jsc), + jabber_jingle_session_get_remote_jid(session)); purple_debug_info("jabber", "jabber_session_candidates_prepared: %d candidates\n", g_list_length(candidates)); @@ -778,14 +760,21 @@ jabber_iq_send(result); } fs_candidate_list_destroy(candidates); + purple_debug_info("jingle", "codec intersection: %i\n", + g_list_length(purple_media_get_negotiated_codecs(media, + jabber_jingle_session_content_get_name(jsc)))); + jabber_iq_send(jabber_jingle_session_create_session_accept(session, + purple_media_get_local_candidate(media, + jabber_jingle_session_content_get_name(jsc), + jabber_jingle_session_get_remote_jid(session)), + purple_media_get_remote_candidate(media, + jabber_jingle_session_content_get_name(jsc), + jabber_jingle_session_get_remote_jid(session)))); } - jabber_iq_send(jabber_jingle_session_create_session_accept(session, - purple_media_get_local_candidate(media), - purple_media_get_remote_candidate(media))); purple_debug_info("jabber", "Sent session accept, starting stream\n"); - gst_element_set_state(purple_media_get_audio_pipeline(session->media), GST_STATE_PLAYING); + gst_element_set_state(purple_media_get_pipeline(session->media), GST_STATE_PLAYING); session->session_started = TRUE; } @@ -822,7 +811,8 @@ jabber_jingle_session_content_create_internal(session, "audio-content", "initiator", sender, TRANSPORT_ICEUDP, JINGLE_AUDIO); - } else if (type & PURPLE_MEDIA_VIDEO) { + } + if (type & PURPLE_MEDIA_VIDEO) { if (type == PURPLE_MEDIA_SEND_VIDEO) strcpy(sender, "initiator"); else if (type == PURPLE_MEDIA_RECV_VIDEO) @@ -837,9 +827,8 @@ static void jabber_jingle_session_content_create_parse(JingleSession *session, - xmlnode *jingle) + xmlnode *content) { - xmlnode *content = xmlnode_get_child(jingle, "content"); xmlnode *description = xmlnode_get_child(content, "description"); xmlnode *transport = xmlnode_get_child(content, "transport"); @@ -907,6 +896,7 @@ const char *remote_jid) { PurpleMedia *media = NULL; + GList *contents = jabber_jingle_session_get_contents(session); media = purple_media_manager_create_media(purple_media_manager_get(), session->js->gc, "fsrtpconference", remote_jid); @@ -916,12 +906,29 @@ return FALSE; } - /* this will need to be changed to "nice" once the libnice transmitter is finished */ - if (!purple_media_add_stream(media, remote_jid, PURPLE_MEDIA_AUDIO, "rawudp")) { - purple_debug_error("jabber", "Couldn't create audio stream\n"); - purple_media_reject(media); - return FALSE; + for (; contents; contents = contents->next) { + JingleSessionContent *jsc = contents->data; + gboolean result = FALSE; + + /* these will need to be changed to "nice" once the libnice transmitter is finished */ + if (jabber_jingle_session_content_is_type(jsc, JINGLE_AUDIO)) { + result = purple_media_add_stream(media, "audio-content", remote_jid, + PURPLE_MEDIA_AUDIO, "rawudp"); + purple_debug_info("jingle", "Created Jingle audio session\n"); + } + else if (jabber_jingle_session_content_is_type(jsc, JINGLE_VIDEO)) { + result = purple_media_add_stream(media, "video-content", remote_jid, + PURPLE_MEDIA_VIDEO, "rawudp"); + purple_debug_info("jingle", "Created Jingle video session\n"); + } + + if (!result) { + purple_debug_error("jabber", "Couldn't create stream\n"); + purple_media_reject(media); + return FALSE; + } } + g_list_free(contents); jabber_jingle_session_set_remote_jid(session, remote_jid); jabber_jingle_session_set_initiator(session, initiator); @@ -967,8 +974,10 @@ contents = jabber_jingle_session_get_contents(session); for (; contents; contents = contents->next) { JingleSessionContent *jsc = contents->data; - GList *candidates = purple_media_get_local_audio_candidates( - jabber_jingle_session_get_media(session)); + 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("jabber", "jabber_session_candidates_prepared: %d candidates\n", g_list_length(candidates)); @@ -1012,6 +1021,8 @@ } session = jabber_jingle_session_create(js); + jabber_jingle_session_content_create_media(session, type); + /* set ourselves as initiator */ me = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain, js->user->resource); @@ -1025,8 +1036,6 @@ g_free(jid); g_free(me); - jabber_jingle_session_content_create_media(session, type); - /* create request */ request = jabber_jingle_session_create_session_initiate(session); jabber_iq_set_callback(request, jabber_jingle_session_initiate_result_cb, NULL); @@ -1064,6 +1073,7 @@ void jabber_jingle_session_handle_content_replace(JabberStream *js, xmlnode *packet) { +#if 0 xmlnode *jingle = xmlnode_get_child(packet, "jingle"); const char *sid = xmlnode_get_attrib(jingle, "sid"); JingleSession *session = jabber_jingle_session_find_by_id(js, sid); @@ -1086,6 +1096,7 @@ jabber_iq_send(accept); } +#endif } void @@ -1110,60 +1121,67 @@ jabber_jingle_session_get_remote_jid(session)); jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id")); - description = xmlnode_get_child(content, "description"); - transport = xmlnode_get_child(content, "transport"); + for (content = xmlnode_get_child(jingle, "content"); content; + content = xmlnode_get_next_twin(content)) { + description = xmlnode_get_child(content, "description"); + transport = xmlnode_get_child(content, "transport"); - /* fetch codecs from remote party */ - purple_debug_info("jabber", "get codecs from session-accept\n"); - remote_codecs = jabber_jingle_get_codecs(description); - purple_debug_info("jabber", "get transport candidates from session accept\n"); - remote_transports = jabber_jingle_get_candidates(transport); + /* fetch codecs from remote party */ + purple_debug_info("jabber", "get codecs from session-accept\n"); + remote_codecs = jabber_jingle_get_codecs(description); + purple_debug_info("jabber", "get transport candidates from session accept\n"); + remote_transports = jabber_jingle_get_candidates(transport); - purple_debug_info("jabber", "Got %d codecs from responder\n", - g_list_length(remote_codecs)); - purple_debug_info("jabber", "Got %d transport candidates from responder\n", - g_list_length(remote_transports)); + purple_debug_info("jabber", "Got %d codecs from responder\n", + g_list_length(remote_codecs)); + purple_debug_info("jabber", "Got %d transport candidates from responder\n", + g_list_length(remote_transports)); - purple_debug_info("jabber", "Setting remote codecs on stream\n"); + purple_debug_info("jabber", "Setting remote codecs on stream\n"); - purple_media_set_remote_audio_codecs(session->media, - jabber_jingle_session_get_remote_jid(session), - remote_codecs); + purple_media_set_remote_codecs(session->media, + xmlnode_get_attrib(content, "name"), + jabber_jingle_session_get_remote_jid(session), + remote_codecs); - codec_intersection = purple_media_get_negotiated_audio_codecs(session->media); - purple_debug_info("jabber", "codec_intersection contains %d elems\n", - g_list_length(codec_intersection)); - /* get the top codec */ - if (g_list_length(codec_intersection) > 0) { - top = (FsCodec *) codec_intersection->data; - purple_debug_info("jabber", "Found a suitable codec on stream = %d\n", - top->id); + codec_intersection = purple_media_get_negotiated_codecs(session->media, + xmlnode_get_attrib(content, "name")); + purple_debug_info("jabber", "codec_intersection contains %d elems\n", + g_list_length(codec_intersection)); + /* get the top codec */ + if (g_list_length(codec_intersection) > 0) { + top = (FsCodec *) codec_intersection->data; + purple_debug_info("jabber", "Found a suitable codec on stream = %d\n", + top->id); - /* we have found a suitable codec, but we will not start the stream - just yet, wait for transport negotiation to complete... */ - } - /* if we also got transport candidates, add them to our streams - list of known remote candidates */ - if (g_list_length(remote_transports) > 0) { - purple_media_add_remote_audio_candidates(session->media, - jabber_jingle_session_get_remote_jid(session), - remote_transports); - fs_candidate_list_destroy(remote_transports); - } - if (g_list_length(codec_intersection) == 0 && - g_list_length(remote_transports)) { - /* we didn't get any candidates and the codec intersection is empty, - this means this was not a content-accept message and we couldn't - find any suitable codecs, should return error and hang up */ + /* we have found a suitable codec, but we will not start the stream + just yet, wait for transport negotiation to complete... */ + } + /* if we also got transport candidates, add them to our streams + list of known remote candidates */ + if (g_list_length(remote_transports) > 0) { + purple_media_add_remote_candidates(session->media, + xmlnode_get_attrib(content, "name"), + jabber_jingle_session_get_remote_jid(session), + remote_transports); + fs_candidate_list_destroy(remote_transports); + } + if (g_list_length(codec_intersection) == 0 && + g_list_length(remote_transports)) { + /* we didn't get any candidates and the codec intersection is empty, + this means this was not a content-accept message and we couldn't + find any suitable codecs, should return error and hang up */ + + } + + fs_codec_list_destroy(codec_intersection); } - g_list_free(codec_intersection); - if (!strcmp(action, "session-accept")) { purple_media_got_accept(jabber_jingle_session_get_media(session)); purple_debug_info("jabber", "Got session-accept, starting stream\n"); - gst_element_set_state(purple_media_get_audio_pipeline(session->media), + gst_element_set_state(purple_media_get_pipeline(session->media), GST_STATE_PLAYING); } @@ -1204,30 +1222,35 @@ purple_debug_error("jabber", "Jingle session with id={%s} already exists\n", sid); return; } + session = jabber_jingle_session_create_by_id(js, sid); - /* init media */ - content = xmlnode_get_child(jingle, "content"); - if (!content) { - purple_debug_error("jabber", "jingle tag must contain content tag\n"); - /* should send error here */ - return; - } + for (content = xmlnode_get_child(jingle, "content"); content; + content = xmlnode_get_next_twin(content)) { + /* init media */ + if (!content) { + purple_debug_error("jabber", "jingle tag must contain content tag\n"); + /* should send error here */ + return; + } - description = xmlnode_get_child(content, "description"); + description = xmlnode_get_child(content, "description"); - if (!description) { - purple_debug_error("jabber", "content tag must contain description tag\n"); - /* we should create an error iq here */ - return; - } + if (!description) { + purple_debug_error("jabber", "content tag must contain description tag\n"); + /* we should create an error iq here */ + return; + } + + transport = xmlnode_get_child(content, "transport"); - transport = xmlnode_get_child(content, "transport"); + if (!transport) { + purple_debug_error("jingle", "content tag must contain transport tag\n"); + /* we should create an error iq here */ + return; + } - if (!transport) { - purple_debug_error("jingle", "content tag must contain transport tag\n"); - /* we should create an error iq here */ - return; + jabber_jingle_session_content_create_parse(session, content); } if (!jabber_jingle_session_initiate_media_internal(session, initiator, initiator)) { @@ -1237,12 +1260,31 @@ return; } - jabber_jingle_session_content_create_parse(session, jingle); + for (content = xmlnode_get_child(jingle, "content"); content; + content = xmlnode_get_next_twin(content)) { + /* init media */ + if (!content) { + purple_debug_error("jabber", "jingle tag must contain content tag\n"); + /* should send error here */ + return; + } + + description = xmlnode_get_child(content, "description"); - codecs = jabber_jingle_get_codecs(description); + if (!description) { + purple_debug_error("jabber", "content tag must contain description tag\n"); + /* we should create an error iq here */ + return; + } + codecs = jabber_jingle_get_codecs(description); - purple_media_set_remote_audio_codecs(session->media, initiator, codecs); - + purple_media_set_remote_codecs(session->media, + xmlnode_get_attrib(content, "name"), + initiator, codecs); + purple_debug_info("jingle", "codec intersection: %i\n", + g_list_length(purple_media_get_negotiated_codecs(session->media, + xmlnode_get_attrib(content, "name")))); + } jabber_iq_send(jabber_jingle_session_create_ack(js, packet)); jabber_iq_send(jabber_jingle_session_create_session_info(session, "ringing")); } @@ -1261,7 +1303,7 @@ /* maybe we should look at the reasoncode to determine if it was a hangup or a reject, and call different callbacks to purple_media */ - gst_element_set_state(purple_media_get_audio_pipeline(session->media), GST_STATE_NULL); + gst_element_set_state(purple_media_get_pipeline(session->media), GST_STATE_NULL); purple_media_got_hangup(jabber_jingle_session_get_media(session)); jabber_iq_send(jabber_jingle_session_create_ack(js, packet)); @@ -1289,9 +1331,10 @@ /* add candidates to our list of remote candidates */ if (g_list_length(remote_candidates) > 0) { - purple_media_add_remote_audio_candidates(session->media, - xmlnode_get_attrib(packet, "from"), - remote_candidates); + purple_media_add_remote_candidates(session->media, + xmlnode_get_attrib(content, "name"), + xmlnode_get_attrib(packet, "from"), + remote_candidates); fs_candidate_list_destroy(remote_candidates); } }