comparison 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
comparison
equal deleted inserted replaced
25670:42e17cc5b6d2 25671:12a16471f94e
276 g_list_free(values); 276 g_list_free(values);
277 return NULL; 277 return NULL;
278 } 278 }
279 279
280 static GList * 280 static GList *
281 jabber_jingle_get_codecs(const xmlnode *description) 281 jabber_jingle_get_codecs(xmlnode *description)
282 { 282 {
283 GList *codecs = NULL; 283 GList *codecs = NULL;
284 xmlnode *codec_element = NULL; 284 xmlnode *codec_element = NULL;
285 const char *encoding_name,*id, *clock_rate; 285 const char *encoding_name,*id, *clock_rate;
286 FsCodec *codec; 286 FsCodec *codec;
287 287 FsMediaType type = !strcmp(xmlnode_get_namespace(description), JINGLE_VIDEO) ?
288 FS_MEDIA_TYPE_VIDEO : FS_MEDIA_TYPE_AUDIO;
289
288 for (codec_element = xmlnode_get_child(description, "payload-type") ; 290 for (codec_element = xmlnode_get_child(description, "payload-type") ;
289 codec_element ; 291 codec_element ;
290 codec_element = xmlnode_get_next_twin(codec_element)) { 292 codec_element = xmlnode_get_next_twin(codec_element)) {
291 encoding_name = xmlnode_get_attrib(codec_element, "name"); 293 encoding_name = xmlnode_get_attrib(codec_element, "name");
294
292 id = xmlnode_get_attrib(codec_element, "id"); 295 id = xmlnode_get_attrib(codec_element, "id");
293 clock_rate = xmlnode_get_attrib(codec_element, "clockrate"); 296 clock_rate = xmlnode_get_attrib(codec_element, "clockrate");
294 297
295 codec = fs_codec_new(atoi(id), encoding_name, 298 codec = fs_codec_new(atoi(id), encoding_name,
296 FS_MEDIA_TYPE_AUDIO, 299 type,
297 clock_rate ? atoi(clock_rate) : 0); 300 clock_rate ? atoi(clock_rate) : 0);
298 codecs = g_list_append(codecs, codec); 301 purple_debug_info("jingle", "codec: %i, %s, %s, %i\n", codec->id,
302 codec->encoding_name, codec->media_type == FS_MEDIA_TYPE_AUDIO ?
303 "FS_MEDIA_TYPE_AUDIO" : codec->media_type == FS_MEDIA_TYPE_VIDEO ?
304 "FS_MEDIA_TYPE_VIDEO" : "FS_MEDIA_TYPE_NONE", codec->clock_rate);
305 codecs = g_list_append(codecs, codec);
299 } 306 }
300 return codecs; 307 return codecs;
301 } 308 }
302 309
303 static GList * 310 static GList *
395 jabber_jingle_session_add_payload_types(const JingleSessionContent *jsc, 402 jabber_jingle_session_add_payload_types(const JingleSessionContent *jsc,
396 xmlnode *description) 403 xmlnode *description)
397 { 404 {
398 JingleSession *session = jabber_jingle_session_content_get_session(jsc); 405 JingleSession *session = jabber_jingle_session_content_get_session(jsc);
399 PurpleMedia *media = jabber_jingle_session_get_media(session); 406 PurpleMedia *media = jabber_jingle_session_get_media(session);
400 /* change this to the generic function when PurpleMedia supports video */ 407 /* should this be local_codecs or negotiated-codecs? */
401 GList *codecs = purple_media_get_local_audio_codecs(media); 408 GList *codecs = purple_media_get_local_codecs(media,
409 jabber_jingle_session_content_get_name(jsc));
402 410
403 for (; codecs ; codecs = codecs->next) { 411 for (; codecs ; codecs = codecs->next) {
404 FsCodec *codec = (FsCodec*)codecs->data; 412 FsCodec *codec = (FsCodec*)codecs->data;
405 char id[8], clockrate[10], channels[10]; 413 char id[8], clockrate[10], channels[10];
406 xmlnode *payload = xmlnode_new_child(description, "payload-type"); 414 xmlnode *payload = xmlnode_new_child(description, "payload-type");
407 415
408 g_snprintf(id, sizeof(id), "%d", codec->id); 416 g_snprintf(id, sizeof(id), "%d", codec->id);
409 g_snprintf(clockrate, sizeof(clockrate), "%d", codec->clock_rate); 417 g_snprintf(clockrate, sizeof(clockrate), "%d", codec->clock_rate);
410 g_snprintf(channels, sizeof(channels), "%d", 418 g_snprintf(channels, sizeof(channels), "%d", codec->channels);
411 codec->channels == 0 ? 1 : codec->channels);
412 419
413 xmlnode_set_attrib(payload, "name", codec->encoding_name); 420 xmlnode_set_attrib(payload, "name", codec->encoding_name);
414 xmlnode_set_attrib(payload, "id", id); 421 xmlnode_set_attrib(payload, "id", id);
415 xmlnode_set_attrib(payload, "clockrate", clockrate); 422 xmlnode_set_attrib(payload, "clockrate", clockrate);
416 xmlnode_set_attrib(payload, "channels", channels); 423 xmlnode_set_attrib(payload, "channels", channels);
567 g_free(from); 574 g_free(from);
568 xmlnode_set_attrib(result->node, "to", 575 xmlnode_set_attrib(result->node, "to",
569 jabber_jingle_session_get_remote_jid(session)); 576 jabber_jingle_session_get_remote_jid(session));
570 return result; 577 return result;
571 } 578 }
572 579 #if 0
573 static xmlnode *
574 jabber_jingle_session_create_description(const JingleSession *sess)
575 {
576 GList *codecs = purple_media_get_local_audio_codecs(sess->media);
577 xmlnode *description = xmlnode_new("description");
578
579 xmlnode_set_namespace(description, JINGLE_AUDIO);
580
581 /* get codecs */
582 for (; codecs ; codecs = codecs->next) {
583 FsCodec *codec = (FsCodec*)codecs->data;
584 char id[8], clockrate[10], channels[10];
585 xmlnode *payload = xmlnode_new_child(description, "payload-type");
586
587 g_snprintf(id, sizeof(id), "%d", codec->id);
588 g_snprintf(clockrate, sizeof(clockrate), "%d", codec->clock_rate);
589 g_snprintf(channels, sizeof(channels), "%d", codec->channels);
590
591 xmlnode_set_attrib(payload, "name", codec->encoding_name);
592 xmlnode_set_attrib(payload, "id", id);
593 xmlnode_set_attrib(payload, "clockrate", clockrate);
594 xmlnode_set_attrib(payload, "channels", channels);
595 }
596
597 fs_codec_list_destroy(codecs);
598 return description;
599 }
600
601 static xmlnode * 580 static xmlnode *
602 jabber_jingle_session_create_content_accept(const JingleSession *sess) 581 jabber_jingle_session_create_content_accept(const JingleSession *sess)
603 { 582 {
604 xmlnode *jingle = 583 xmlnode *jingle =
605 jabber_jingle_session_add_jingle(sess, NULL, "content-accept"); 584 jabber_jingle_session_add_jingle(sess, NULL, "content-accept");
647 626
648 purple_debug_info("jingle", "End create content modify\n"); 627 purple_debug_info("jingle", "End create content modify\n");
649 628
650 return jingle; 629 return jingle;
651 } 630 }
631 #endif
652 632
653 static JabberIq * 633 static JabberIq *
654 jabber_jingle_session_create_session_accept(const JingleSession *session, 634 jabber_jingle_session_create_session_accept(const JingleSession *session,
655 FsCandidate *local, 635 FsCandidate *local,
656 FsCandidate *remote) 636 FsCandidate *remote)
742 xmlnode *content = jabber_jingle_session_add_content(jsc, jingle); 722 xmlnode *content = jabber_jingle_session_add_content(jsc, jingle);
743 xmlnode *transport = jabber_jingle_session_add_transport(jsc, content); 723 xmlnode *transport = jabber_jingle_session_add_transport(jsc, content);
744 jabber_jingle_session_add_candidate_iceudp(transport, candidate, NULL); 724 jabber_jingle_session_add_candidate_iceudp(transport, candidate, NULL);
745 return request; 725 return request;
746 } 726 }
747 727 #if 0
748 static void 728 static void
749 jabber_jingle_session_send_content_accept(JingleSession *session) 729 jabber_jingle_session_send_content_accept(JingleSession *session)
750 { 730 {
751 JabberIq *result = jabber_iq_new(jabber_jingle_session_get_js(session), 731 JabberIq *result = jabber_iq_new(jabber_jingle_session_get_js(session),
752 JABBER_IQ_SET); 732 JABBER_IQ_SET);
755 jabber_jingle_session_get_remote_jid(session)); 735 jabber_jingle_session_get_remote_jid(session));
756 736
757 xmlnode_insert_child(result->node, jingle); 737 xmlnode_insert_child(result->node, jingle);
758 jabber_iq_send(result); 738 jabber_iq_send(result);
759 } 739 }
760 740 #endif
761 static void 741 static void
762 jabber_jingle_session_send_session_accept(JingleSession *session) 742 jabber_jingle_session_send_session_accept(JingleSession *session)
763 { 743 {
764 /* create transport-info packages */ 744 /* create transport-info packages */
765 PurpleMedia *media = jabber_jingle_session_get_media(session); 745 PurpleMedia *media = jabber_jingle_session_get_media(session);
766 GList *contents = jabber_jingle_session_get_contents(session); 746 GList *contents = jabber_jingle_session_get_contents(session);
767 for (; contents; contents = contents->next) { 747 for (; contents; contents = contents->next) {
768 JingleSessionContent *jsc = contents->data; 748 JingleSessionContent *jsc = contents->data;
769 GList *candidates = purple_media_get_local_audio_candidates( 749 GList *candidates = purple_media_get_local_candidates(
770 jabber_jingle_session_get_media(session)); 750 media,
751 jabber_jingle_session_content_get_name(jsc),
752 jabber_jingle_session_get_remote_jid(session));
771 purple_debug_info("jabber", 753 purple_debug_info("jabber",
772 "jabber_session_candidates_prepared: %d candidates\n", 754 "jabber_session_candidates_prepared: %d candidates\n",
773 g_list_length(candidates)); 755 g_list_length(candidates));
774 for (; candidates; candidates = candidates->next) { 756 for (; candidates; candidates = candidates->next) {
775 FsCandidate *candidate = candidates->data; 757 FsCandidate *candidate = candidates->data;
776 JabberIq *result = jabber_jingle_session_create_transport_info(jsc, 758 JabberIq *result = jabber_jingle_session_create_transport_info(jsc,
777 candidate); 759 candidate);
778 jabber_iq_send(result); 760 jabber_iq_send(result);
779 } 761 }
780 fs_candidate_list_destroy(candidates); 762 fs_candidate_list_destroy(candidates);
781 } 763 purple_debug_info("jingle", "codec intersection: %i\n",
782 764 g_list_length(purple_media_get_negotiated_codecs(media,
783 jabber_iq_send(jabber_jingle_session_create_session_accept(session, 765 jabber_jingle_session_content_get_name(jsc))));
784 purple_media_get_local_candidate(media), 766 jabber_iq_send(jabber_jingle_session_create_session_accept(session,
785 purple_media_get_remote_candidate(media))); 767 purple_media_get_local_candidate(media,
768 jabber_jingle_session_content_get_name(jsc),
769 jabber_jingle_session_get_remote_jid(session)),
770 purple_media_get_remote_candidate(media,
771 jabber_jingle_session_content_get_name(jsc),
772 jabber_jingle_session_get_remote_jid(session))));
773 }
774
786 775
787 purple_debug_info("jabber", "Sent session accept, starting stream\n"); 776 purple_debug_info("jabber", "Sent session accept, starting stream\n");
788 gst_element_set_state(purple_media_get_audio_pipeline(session->media), GST_STATE_PLAYING); 777 gst_element_set_state(purple_media_get_pipeline(session->media), GST_STATE_PLAYING);
789 778
790 session->session_started = TRUE; 779 session->session_started = TRUE;
791 } 780 }
792 781
793 static void 782 static void
820 else 809 else
821 strcpy(sender, "both"); 810 strcpy(sender, "both");
822 jabber_jingle_session_content_create_internal(session, 811 jabber_jingle_session_content_create_internal(session,
823 "audio-content", "initiator", sender, 812 "audio-content", "initiator", sender,
824 TRANSPORT_ICEUDP, JINGLE_AUDIO); 813 TRANSPORT_ICEUDP, JINGLE_AUDIO);
825 } else if (type & PURPLE_MEDIA_VIDEO) { 814 }
815 if (type & PURPLE_MEDIA_VIDEO) {
826 if (type == PURPLE_MEDIA_SEND_VIDEO) 816 if (type == PURPLE_MEDIA_SEND_VIDEO)
827 strcpy(sender, "initiator"); 817 strcpy(sender, "initiator");
828 else if (type == PURPLE_MEDIA_RECV_VIDEO) 818 else if (type == PURPLE_MEDIA_RECV_VIDEO)
829 strcpy(sender, "responder"); 819 strcpy(sender, "responder");
830 else 820 else
835 } 825 }
836 } 826 }
837 827
838 static void 828 static void
839 jabber_jingle_session_content_create_parse(JingleSession *session, 829 jabber_jingle_session_content_create_parse(JingleSession *session,
840 xmlnode *jingle) 830 xmlnode *content)
841 { 831 {
842 xmlnode *content = xmlnode_get_child(jingle, "content");
843 xmlnode *description = xmlnode_get_child(content, "description"); 832 xmlnode *description = xmlnode_get_child(content, "description");
844 xmlnode *transport = xmlnode_get_child(content, "transport"); 833 xmlnode *transport = xmlnode_get_child(content, "transport");
845 834
846 const gchar *creator = xmlnode_get_attrib(content, "creator"); 835 const gchar *creator = xmlnode_get_attrib(content, "creator");
847 const gchar *sender = xmlnode_get_attrib(content, "sender"); 836 const gchar *sender = xmlnode_get_attrib(content, "sender");
905 jabber_jingle_session_initiate_media_internal(JingleSession *session, 894 jabber_jingle_session_initiate_media_internal(JingleSession *session,
906 const char *initiator, 895 const char *initiator,
907 const char *remote_jid) 896 const char *remote_jid)
908 { 897 {
909 PurpleMedia *media = NULL; 898 PurpleMedia *media = NULL;
899 GList *contents = jabber_jingle_session_get_contents(session);
910 900
911 media = purple_media_manager_create_media(purple_media_manager_get(), 901 media = purple_media_manager_create_media(purple_media_manager_get(),
912 session->js->gc, "fsrtpconference", remote_jid); 902 session->js->gc, "fsrtpconference", remote_jid);
913 903
914 if (!media) { 904 if (!media) {
915 purple_debug_error("jabber", "Couldn't create fsrtpconference\n"); 905 purple_debug_error("jabber", "Couldn't create fsrtpconference\n");
916 return FALSE; 906 return FALSE;
917 } 907 }
918 908
919 /* this will need to be changed to "nice" once the libnice transmitter is finished */ 909 for (; contents; contents = contents->next) {
920 if (!purple_media_add_stream(media, remote_jid, PURPLE_MEDIA_AUDIO, "rawudp")) { 910 JingleSessionContent *jsc = contents->data;
921 purple_debug_error("jabber", "Couldn't create audio stream\n"); 911 gboolean result = FALSE;
922 purple_media_reject(media); 912
923 return FALSE; 913 /* these will need to be changed to "nice" once the libnice transmitter is finished */
924 } 914 if (jabber_jingle_session_content_is_type(jsc, JINGLE_AUDIO)) {
915 result = purple_media_add_stream(media, "audio-content", remote_jid,
916 PURPLE_MEDIA_AUDIO, "rawudp");
917 purple_debug_info("jingle", "Created Jingle audio session\n");
918 }
919 else if (jabber_jingle_session_content_is_type(jsc, JINGLE_VIDEO)) {
920 result = purple_media_add_stream(media, "video-content", remote_jid,
921 PURPLE_MEDIA_VIDEO, "rawudp");
922 purple_debug_info("jingle", "Created Jingle video session\n");
923 }
924
925 if (!result) {
926 purple_debug_error("jabber", "Couldn't create stream\n");
927 purple_media_reject(media);
928 return FALSE;
929 }
930 }
931 g_list_free(contents);
925 932
926 jabber_jingle_session_set_remote_jid(session, remote_jid); 933 jabber_jingle_session_set_remote_jid(session, remote_jid);
927 jabber_jingle_session_set_initiator(session, initiator); 934 jabber_jingle_session_set_initiator(session, initiator);
928 jabber_jingle_session_set_media(session, media); 935 jabber_jingle_session_set_media(session, media);
929 936
965 972
966 /* create transport-info packages */ 973 /* create transport-info packages */
967 contents = jabber_jingle_session_get_contents(session); 974 contents = jabber_jingle_session_get_contents(session);
968 for (; contents; contents = contents->next) { 975 for (; contents; contents = contents->next) {
969 JingleSessionContent *jsc = contents->data; 976 JingleSessionContent *jsc = contents->data;
970 GList *candidates = purple_media_get_local_audio_candidates( 977 GList *candidates = purple_media_get_local_candidates(
971 jabber_jingle_session_get_media(session)); 978 jabber_jingle_session_get_media(session),
979 jabber_jingle_session_content_get_name(jsc),
980 jabber_jingle_session_get_remote_jid(session));
972 purple_debug_info("jabber", 981 purple_debug_info("jabber",
973 "jabber_session_candidates_prepared: %d candidates\n", 982 "jabber_session_candidates_prepared: %d candidates\n",
974 g_list_length(candidates)); 983 g_list_length(candidates));
975 for (; candidates; candidates = candidates->next) { 984 for (; candidates; candidates = candidates->next) {
976 FsCandidate *candidate = candidates->data; 985 FsCandidate *candidate = candidates->data;
1010 } else { 1019 } else {
1011 jid = g_strdup(who); 1020 jid = g_strdup(who);
1012 } 1021 }
1013 1022
1014 session = jabber_jingle_session_create(js); 1023 session = jabber_jingle_session_create(js);
1024 jabber_jingle_session_content_create_media(session, type);
1025
1015 /* set ourselves as initiator */ 1026 /* set ourselves as initiator */
1016 me = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain, js->user->resource); 1027 me = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain, js->user->resource);
1017 1028
1018 if (!jabber_jingle_session_initiate_media_internal(session, me, jid)) { 1029 if (!jabber_jingle_session_initiate_media_internal(session, me, jid)) {
1019 g_free(jid); 1030 g_free(jid);
1023 } 1034 }
1024 1035
1025 g_free(jid); 1036 g_free(jid);
1026 g_free(me); 1037 g_free(me);
1027 1038
1028 jabber_jingle_session_content_create_media(session, type);
1029
1030 /* create request */ 1039 /* create request */
1031 request = jabber_jingle_session_create_session_initiate(session); 1040 request = jabber_jingle_session_create_session_initiate(session);
1032 jabber_iq_set_callback(request, jabber_jingle_session_initiate_result_cb, NULL); 1041 jabber_iq_set_callback(request, jabber_jingle_session_initiate_result_cb, NULL);
1033 1042
1034 /* send request to other part */ 1043 /* send request to other part */
1062 } 1071 }
1063 1072
1064 void 1073 void
1065 jabber_jingle_session_handle_content_replace(JabberStream *js, xmlnode *packet) 1074 jabber_jingle_session_handle_content_replace(JabberStream *js, xmlnode *packet)
1066 { 1075 {
1076 #if 0
1067 xmlnode *jingle = xmlnode_get_child(packet, "jingle"); 1077 xmlnode *jingle = xmlnode_get_child(packet, "jingle");
1068 const char *sid = xmlnode_get_attrib(jingle, "sid"); 1078 const char *sid = xmlnode_get_attrib(jingle, "sid");
1069 JingleSession *session = jabber_jingle_session_find_by_id(js, sid); 1079 JingleSession *session = jabber_jingle_session_find_by_id(js, sid);
1070 1080
1071 if (!jabber_jingle_session_is_initiator(session) && session->session_started) { 1081 if (!jabber_jingle_session_is_initiator(session) && session->session_started) {
1084 xmlnode_set_attrib(accept->node, "to", xmlnode_get_attrib(packet, "from")); 1094 xmlnode_set_attrib(accept->node, "to", xmlnode_get_attrib(packet, "from"));
1085 xmlnode_insert_child(accept->node, content_accept); 1095 xmlnode_insert_child(accept->node, content_accept);
1086 1096
1087 jabber_iq_send(accept); 1097 jabber_iq_send(accept);
1088 } 1098 }
1099 #endif
1089 } 1100 }
1090 1101
1091 void 1102 void
1092 jabber_jingle_session_handle_session_accept(JabberStream *js, xmlnode *packet) 1103 jabber_jingle_session_handle_session_accept(JabberStream *js, xmlnode *packet)
1093 { 1104 {
1108 1119
1109 xmlnode_set_attrib(result->node, "to", 1120 xmlnode_set_attrib(result->node, "to",
1110 jabber_jingle_session_get_remote_jid(session)); 1121 jabber_jingle_session_get_remote_jid(session));
1111 jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id")); 1122 jabber_iq_set_id(result, xmlnode_get_attrib(packet, "id"));
1112 1123
1113 description = xmlnode_get_child(content, "description"); 1124 for (content = xmlnode_get_child(jingle, "content"); content;
1114 transport = xmlnode_get_child(content, "transport"); 1125 content = xmlnode_get_next_twin(content)) {
1115 1126 description = xmlnode_get_child(content, "description");
1116 /* fetch codecs from remote party */ 1127 transport = xmlnode_get_child(content, "transport");
1117 purple_debug_info("jabber", "get codecs from session-accept\n"); 1128
1118 remote_codecs = jabber_jingle_get_codecs(description); 1129 /* fetch codecs from remote party */
1119 purple_debug_info("jabber", "get transport candidates from session accept\n"); 1130 purple_debug_info("jabber", "get codecs from session-accept\n");
1120 remote_transports = jabber_jingle_get_candidates(transport); 1131 remote_codecs = jabber_jingle_get_codecs(description);
1121 1132 purple_debug_info("jabber", "get transport candidates from session accept\n");
1122 purple_debug_info("jabber", "Got %d codecs from responder\n", 1133 remote_transports = jabber_jingle_get_candidates(transport);
1123 g_list_length(remote_codecs)); 1134
1124 purple_debug_info("jabber", "Got %d transport candidates from responder\n", 1135 purple_debug_info("jabber", "Got %d codecs from responder\n",
1125 g_list_length(remote_transports)); 1136 g_list_length(remote_codecs));
1126 1137 purple_debug_info("jabber", "Got %d transport candidates from responder\n",
1127 purple_debug_info("jabber", "Setting remote codecs on stream\n"); 1138 g_list_length(remote_transports));
1128 1139
1129 purple_media_set_remote_audio_codecs(session->media, 1140 purple_debug_info("jabber", "Setting remote codecs on stream\n");
1130 jabber_jingle_session_get_remote_jid(session), 1141
1131 remote_codecs); 1142 purple_media_set_remote_codecs(session->media,
1132 1143 xmlnode_get_attrib(content, "name"),
1133 codec_intersection = purple_media_get_negotiated_audio_codecs(session->media); 1144 jabber_jingle_session_get_remote_jid(session),
1134 purple_debug_info("jabber", "codec_intersection contains %d elems\n", 1145 remote_codecs);
1135 g_list_length(codec_intersection)); 1146
1136 /* get the top codec */ 1147 codec_intersection = purple_media_get_negotiated_codecs(session->media,
1137 if (g_list_length(codec_intersection) > 0) { 1148 xmlnode_get_attrib(content, "name"));
1138 top = (FsCodec *) codec_intersection->data; 1149 purple_debug_info("jabber", "codec_intersection contains %d elems\n",
1139 purple_debug_info("jabber", "Found a suitable codec on stream = %d\n", 1150 g_list_length(codec_intersection));
1140 top->id); 1151 /* get the top codec */
1141 1152 if (g_list_length(codec_intersection) > 0) {
1142 /* we have found a suitable codec, but we will not start the stream 1153 top = (FsCodec *) codec_intersection->data;
1143 just yet, wait for transport negotiation to complete... */ 1154 purple_debug_info("jabber", "Found a suitable codec on stream = %d\n",
1144 } 1155 top->id);
1145 /* if we also got transport candidates, add them to our streams 1156
1146 list of known remote candidates */ 1157 /* we have found a suitable codec, but we will not start the stream
1147 if (g_list_length(remote_transports) > 0) { 1158 just yet, wait for transport negotiation to complete... */
1148 purple_media_add_remote_audio_candidates(session->media, 1159 }
1149 jabber_jingle_session_get_remote_jid(session), 1160 /* if we also got transport candidates, add them to our streams
1150 remote_transports); 1161 list of known remote candidates */
1151 fs_candidate_list_destroy(remote_transports); 1162 if (g_list_length(remote_transports) > 0) {
1152 } 1163 purple_media_add_remote_candidates(session->media,
1153 if (g_list_length(codec_intersection) == 0 && 1164 xmlnode_get_attrib(content, "name"),
1154 g_list_length(remote_transports)) { 1165 jabber_jingle_session_get_remote_jid(session),
1155 /* we didn't get any candidates and the codec intersection is empty, 1166 remote_transports);
1156 this means this was not a content-accept message and we couldn't 1167 fs_candidate_list_destroy(remote_transports);
1157 find any suitable codecs, should return error and hang up */ 1168 }
1158 1169 if (g_list_length(codec_intersection) == 0 &&
1159 } 1170 g_list_length(remote_transports)) {
1160 1171 /* we didn't get any candidates and the codec intersection is empty,
1161 g_list_free(codec_intersection); 1172 this means this was not a content-accept message and we couldn't
1173 find any suitable codecs, should return error and hang up */
1174
1175 }
1176
1177 fs_codec_list_destroy(codec_intersection);
1178
1179 }
1162 1180
1163 if (!strcmp(action, "session-accept")) { 1181 if (!strcmp(action, "session-accept")) {
1164 purple_media_got_accept(jabber_jingle_session_get_media(session)); 1182 purple_media_got_accept(jabber_jingle_session_get_media(session));
1165 purple_debug_info("jabber", "Got session-accept, starting stream\n"); 1183 purple_debug_info("jabber", "Got session-accept, starting stream\n");
1166 gst_element_set_state(purple_media_get_audio_pipeline(session->media), 1184 gst_element_set_state(purple_media_get_pipeline(session->media),
1167 GST_STATE_PLAYING); 1185 GST_STATE_PLAYING);
1168 } 1186 }
1169 1187
1170 jabber_iq_send(result); 1188 jabber_iq_send(result);
1171 1189
1202 if (jabber_jingle_session_find_by_id(js, sid)) { 1220 if (jabber_jingle_session_find_by_id(js, sid)) {
1203 /* This should only happen if you start a session with yourself */ 1221 /* This should only happen if you start a session with yourself */
1204 purple_debug_error("jabber", "Jingle session with id={%s} already exists\n", sid); 1222 purple_debug_error("jabber", "Jingle session with id={%s} already exists\n", sid);
1205 return; 1223 return;
1206 } 1224 }
1225
1207 session = jabber_jingle_session_create_by_id(js, sid); 1226 session = jabber_jingle_session_create_by_id(js, sid);
1208 1227
1209 /* init media */ 1228 for (content = xmlnode_get_child(jingle, "content"); content;
1210 content = xmlnode_get_child(jingle, "content"); 1229 content = xmlnode_get_next_twin(content)) {
1211 if (!content) { 1230 /* init media */
1212 purple_debug_error("jabber", "jingle tag must contain content tag\n"); 1231 if (!content) {
1213 /* should send error here */ 1232 purple_debug_error("jabber", "jingle tag must contain content tag\n");
1214 return; 1233 /* should send error here */
1215 } 1234 return;
1216 1235 }
1217 description = xmlnode_get_child(content, "description"); 1236
1218 1237 description = xmlnode_get_child(content, "description");
1219 if (!description) { 1238
1220 purple_debug_error("jabber", "content tag must contain description tag\n"); 1239 if (!description) {
1221 /* we should create an error iq here */ 1240 purple_debug_error("jabber", "content tag must contain description tag\n");
1222 return; 1241 /* we should create an error iq here */
1223 } 1242 return;
1224 1243 }
1225 transport = xmlnode_get_child(content, "transport"); 1244
1226 1245 transport = xmlnode_get_child(content, "transport");
1227 if (!transport) { 1246
1228 purple_debug_error("jingle", "content tag must contain transport tag\n"); 1247 if (!transport) {
1229 /* we should create an error iq here */ 1248 purple_debug_error("jingle", "content tag must contain transport tag\n");
1230 return; 1249 /* we should create an error iq here */
1250 return;
1251 }
1252
1253 jabber_jingle_session_content_create_parse(session, content);
1231 } 1254 }
1232 1255
1233 if (!jabber_jingle_session_initiate_media_internal(session, initiator, initiator)) { 1256 if (!jabber_jingle_session_initiate_media_internal(session, initiator, initiator)) {
1234 purple_debug_error("jabber", "Couldn't start media session with %s\n", initiator); 1257 purple_debug_error("jabber", "Couldn't start media session with %s\n", initiator);
1235 jabber_jingle_session_destroy(session); 1258 jabber_jingle_session_destroy(session);
1236 /* we should create an error iq here */ 1259 /* we should create an error iq here */
1237 return; 1260 return;
1238 } 1261 }
1239 1262
1240 jabber_jingle_session_content_create_parse(session, jingle); 1263 for (content = xmlnode_get_child(jingle, "content"); content;
1241 1264 content = xmlnode_get_next_twin(content)) {
1242 codecs = jabber_jingle_get_codecs(description); 1265 /* init media */
1243 1266 if (!content) {
1244 purple_media_set_remote_audio_codecs(session->media, initiator, codecs); 1267 purple_debug_error("jabber", "jingle tag must contain content tag\n");
1245 1268 /* should send error here */
1269 return;
1270 }
1271
1272 description = xmlnode_get_child(content, "description");
1273
1274 if (!description) {
1275 purple_debug_error("jabber", "content tag must contain description tag\n");
1276 /* we should create an error iq here */
1277 return;
1278 }
1279 codecs = jabber_jingle_get_codecs(description);
1280
1281 purple_media_set_remote_codecs(session->media,
1282 xmlnode_get_attrib(content, "name"),
1283 initiator, codecs);
1284 purple_debug_info("jingle", "codec intersection: %i\n",
1285 g_list_length(purple_media_get_negotiated_codecs(session->media,
1286 xmlnode_get_attrib(content, "name"))));
1287 }
1246 jabber_iq_send(jabber_jingle_session_create_ack(js, packet)); 1288 jabber_iq_send(jabber_jingle_session_create_ack(js, packet));
1247 jabber_iq_send(jabber_jingle_session_create_session_info(session, "ringing")); 1289 jabber_iq_send(jabber_jingle_session_create_session_info(session, "ringing"));
1248 } 1290 }
1249 1291
1250 void 1292 void
1259 return; 1301 return;
1260 } 1302 }
1261 1303
1262 /* maybe we should look at the reasoncode to determine if it was 1304 /* maybe we should look at the reasoncode to determine if it was
1263 a hangup or a reject, and call different callbacks to purple_media */ 1305 a hangup or a reject, and call different callbacks to purple_media */
1264 gst_element_set_state(purple_media_get_audio_pipeline(session->media), GST_STATE_NULL); 1306 gst_element_set_state(purple_media_get_pipeline(session->media), GST_STATE_NULL);
1265 1307
1266 purple_media_got_hangup(jabber_jingle_session_get_media(session)); 1308 purple_media_got_hangup(jabber_jingle_session_get_media(session));
1267 jabber_iq_send(jabber_jingle_session_create_ack(js, packet)); 1309 jabber_iq_send(jabber_jingle_session_create_ack(js, packet));
1268 jabber_jingle_session_destroy(session); 1310 jabber_jingle_session_destroy(session);
1269 } 1311 }
1287 xmlnode_set_attrib(result->node, "to", xmlnode_get_attrib(packet, "from")); 1329 xmlnode_set_attrib(result->node, "to", xmlnode_get_attrib(packet, "from"));
1288 jabber_iq_send(result); 1330 jabber_iq_send(result);
1289 1331
1290 /* add candidates to our list of remote candidates */ 1332 /* add candidates to our list of remote candidates */
1291 if (g_list_length(remote_candidates) > 0) { 1333 if (g_list_length(remote_candidates) > 0) {
1292 purple_media_add_remote_audio_candidates(session->media, 1334 purple_media_add_remote_candidates(session->media,
1293 xmlnode_get_attrib(packet, "from"), 1335 xmlnode_get_attrib(content, "name"),
1294 remote_candidates); 1336 xmlnode_get_attrib(packet, "from"),
1337 remote_candidates);
1295 fs_candidate_list_destroy(remote_candidates); 1338 fs_candidate_list_destroy(remote_candidates);
1296 } 1339 }
1297 } 1340 }
1298 1341
1299 #endif /* USE_VV */ 1342 #endif /* USE_VV */