# HG changeset patch # User Mike Ruprecht # Date 1238813739 0 # Node ID c08719989149ff17cc0e03dc079365a957c6c2bf # Parent f171707b7d54052006e2fdad29ff0c7c95f95139# Parent 0adf41b3de79d6aa825a5d49971dcd3023a8413d merge of '1890ad1259c93f5ad18ceb3365717ebc43b30198' and 'b28028a0f1c19eaf4ee7d941c83b587980320568' diff -r f171707b7d54 -r c08719989149 libpurple/protocols/jabber/jabber.c --- a/libpurple/protocols/jabber/jabber.c Fri Apr 03 20:46:31 2009 +0000 +++ b/libpurple/protocols/jabber/jabber.c Sat Apr 04 02:55:39 2009 +0000 @@ -2612,6 +2612,39 @@ return TRUE; } +#ifdef USE_VV +typedef struct { + PurpleConnection *pc; + gchar *who; + PurpleMediaSessionType type; + +} JabberMediaRequest; + +static void +jabber_media_cancel_cb(JabberMediaRequest *request, + PurpleRequestFields *fields) +{ + g_free(request->who); + g_free(request); +} + +static void +jabber_media_ok_cb(JabberMediaRequest *request, PurpleRequestFields *fields) +{ + PurpleRequestField *field = + purple_request_fields_get_field(fields, "resource"); + int selected_id = purple_request_field_choice_get_value(field); + GList *labels = purple_request_field_choice_get_labels(field); + gchar *who = g_strdup_printf("%s/%s", request->who, + (gchar*)g_list_nth_data(labels, selected_id)); + jabber_initiate_media(request->pc, who, request->type); + + g_free(who); + g_free(request->who); + g_free(request); +} +#endif + gboolean jabber_initiate_media(PurpleConnection *gc, const char *who, PurpleMediaSessionType type) @@ -2619,6 +2652,8 @@ #ifdef USE_VV JabberStream *js = (JabberStream *) gc->proto_data; JabberBuddy *jb; + JabberBuddyResource *jbr = NULL; + char *resource; if (!js) { purple_debug_error("jabber", @@ -2626,23 +2661,135 @@ return FALSE; } - jb = jabber_buddy_find(js, who, FALSE); - - if (!jb) { - purple_debug_error("jabber", "Could not find buddy\n"); - return FALSE; + + if((resource = jabber_get_resource(who)) != NULL) { + /* they've specified a resource, no need to ask or + * default or anything, just do it */ + + jb = jabber_buddy_find(js, who, FALSE); + jbr = jabber_buddy_find_resource(jb, resource); + g_free(resource); + + if (type & PURPLE_MEDIA_AUDIO && + !jabber_resource_has_capability(jbr, + JINGLE_APP_RTP_SUPPORT_AUDIO) && + jabber_resource_has_capability(jbr, + GOOGLE_VOICE_CAP)) + return jabber_google_session_initiate( + gc->proto_data, who, type); + else + return jingle_rtp_initiate_media( + gc->proto_data, who, type); } - if (type & PURPLE_MEDIA_AUDIO && - !jabber_buddy_has_capability(jb, - JINGLE_APP_RTP_SUPPORT_AUDIO) && - jabber_buddy_has_capability(jb, GOOGLE_VOICE_CAP)) - return jabber_google_session_initiate(gc->proto_data, who, type); - else - return jingle_rtp_initiate_media(gc->proto_data, who, type); -#else + jb = jabber_buddy_find(js, who, FALSE); + + if(!jb || !jb->resources) { + /* no resources online, we're trying to initiate with someone + * whose presence we're not subscribed to, or + * someone who is offline. Let's inform the user */ + char *msg; + + if(!jb) { + msg = g_strdup_printf(_("Unable to initiate media with %s, invalid JID"), who); + } else if(jb->subscription & JABBER_SUB_TO) { + msg = g_strdup_printf(_("Unable to initiate media with %s, user is not online"), who); + } else { + msg = g_strdup_printf(_("Unable to initiate media with %s, not subscribed to user presence"), who); + } + + purple_notify_error(js->gc, _("Media Initiation Failed"), + _("Media Initiation Failed"), msg); + g_free(msg); + return FALSE; + } else if(!jb->resources->next) { + /* only 1 resource online (probably our most common case) + * so no need to ask who to initiate with */ + gchar *name; + gboolean result; + jbr = jb->resources->data; + name = g_strdup_printf("%s/%s", who, jbr->name); + result = jabber_initiate_media(gc, name, type); + g_free(name); + return result; + } else { + /* we've got multiple resources, + * we need to pick one to initiate with */ + GList *l; + char *msg; + PurpleRequestFields *fields; + PurpleRequestField *field = purple_request_field_choice_new( + "resource", _("Resource"), 0); + PurpleRequestFieldGroup *group; + JabberMediaRequest *request; + + for(l = jb->resources; l; l = l->next) + { + JabberBuddyResource *ljbr = l->data; + PurpleMediaCaps caps; + gchar *name; + name = g_strdup_printf("%s/%s", who, ljbr->name); + caps = jabber_get_media_caps(gc, name); + g_free(name); + + if ((type & PURPLE_MEDIA_AUDIO) && + (type & PURPLE_MEDIA_VIDEO)) { + if (caps & PURPLE_MEDIA_CAPS_AUDIO_VIDEO) { + jbr = ljbr; + purple_request_field_choice_add( + field, jbr->name); + } + } else if (type & (PURPLE_MEDIA_AUDIO) && + (caps & PURPLE_MEDIA_CAPS_AUDIO)) { + jbr = ljbr; + purple_request_field_choice_add( + field, jbr->name); + }else if (type & (PURPLE_MEDIA_VIDEO) && + (caps & PURPLE_MEDIA_CAPS_VIDEO)) { + jbr = ljbr; + purple_request_field_choice_add( + field, jbr->name); + } + } + + if (jbr == NULL) { + purple_debug_error("jabber", + "No resources available\n"); + return FALSE; + } + + if (g_list_length(purple_request_field_choice_get_labels( + field)) <= 1) { + gchar *name; + gboolean result; + purple_request_field_destroy(field); + name = g_strdup_printf("%s/%s", who, jbr->name); + result = jabber_initiate_media(gc, name, type); + g_free(name); + return result; + } + + msg = g_strdup_printf(_("Please select the resource of %s to which you would like to start a media session with."), who); + fields = purple_request_fields_new(); + group = purple_request_field_group_new(NULL); + request = g_new0(JabberMediaRequest, 1); + request->pc = gc; + request->who = g_strdup(who); + request->type = type; + + purple_request_field_group_add_field(group, field); + purple_request_fields_add_group(fields, group); + purple_request_fields(gc, _("Select a Resource"), msg, NULL, + fields, _("Initiate Media"), + G_CALLBACK(jabber_media_ok_cb), _("Cancel"), + G_CALLBACK(jabber_media_cancel_cb), + gc->account, who, NULL, request); + + g_free(msg); + return TRUE; + } +#endif return FALSE; -#endif } PurpleMediaCaps jabber_get_media_caps(PurpleConnection *gc, const char *who) @@ -2650,7 +2797,9 @@ #ifdef USE_VV JabberStream *js = (JabberStream *) gc->proto_data; JabberBuddy *jb; + JabberBuddyResource *jbr; PurpleMediaCaps caps = PURPLE_MEDIA_CAPS_NONE; + gchar *resource; if (!js) { purple_debug_info("jabber", @@ -2658,35 +2807,75 @@ return FALSE; } - jb = jabber_buddy_find(js, who, FALSE); - - if (!jb) { - purple_debug_error("jabber", "Could not find buddy\n"); - return FALSE; + if ((resource = jabber_get_resource(who)) != NULL) { + /* they've specified a resource, no need to ask or + * default or anything, just do it */ + + jb = jabber_buddy_find(js, who, FALSE); + jbr = jabber_buddy_find_resource(jb, resource); + g_free(resource); + + if (!jbr) { + purple_debug_error("jabber", "jabber_get_media_caps:" + " Can't find resource %s\n", who); + return caps; + } + + if (jabber_resource_has_capability(jbr, + JINGLE_APP_RTP_SUPPORT_AUDIO)) + caps |= PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION | + PURPLE_MEDIA_CAPS_AUDIO; + if (jabber_resource_has_capability(jbr, + JINGLE_APP_RTP_SUPPORT_VIDEO)) + caps |= PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION | + PURPLE_MEDIA_CAPS_VIDEO; + if (caps & PURPLE_MEDIA_CAPS_AUDIO && caps & + PURPLE_MEDIA_CAPS_VIDEO) + caps |= PURPLE_MEDIA_CAPS_AUDIO_VIDEO; + if (caps != PURPLE_MEDIA_CAPS_NONE) { + if (!jabber_resource_has_capability(jbr, + JINGLE_TRANSPORT_ICEUDP) && + !jabber_resource_has_capability(jbr, + JINGLE_TRANSPORT_RAWUDP)) { + purple_debug_info("jingle-rtp", "Buddy doesn't " + "support the same transport types\n"); + caps = PURPLE_MEDIA_CAPS_NONE; + } else + caps |= PURPLE_MEDIA_CAPS_MODIFY_SESSION | + PURPLE_MEDIA_CAPS_CHANGE_DIRECTION; + } + if (jabber_resource_has_capability(jbr, GOOGLE_VOICE_CAP)) + caps |= PURPLE_MEDIA_CAPS_AUDIO; + return caps; } - if (jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_AUDIO)) - caps |= PURPLE_MEDIA_CAPS_AUDIO | - PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION; - if (jabber_buddy_has_capability(jb, JINGLE_APP_RTP_SUPPORT_VIDEO)) - caps |= PURPLE_MEDIA_CAPS_VIDEO | - PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION; - if (caps & PURPLE_MEDIA_CAPS_AUDIO && caps & PURPLE_MEDIA_CAPS_VIDEO) - caps |= PURPLE_MEDIA_CAPS_AUDIO_VIDEO; - if (caps != PURPLE_MEDIA_CAPS_NONE) { - if (!jabber_buddy_has_capability(jb, - JINGLE_TRANSPORT_ICEUDP) && - !jabber_buddy_has_capability(jb, - JINGLE_TRANSPORT_RAWUDP)) { - purple_debug_info("jingle-rtp", "Buddy doesn't " - "support the same transport types\n"); - caps = PURPLE_MEDIA_CAPS_NONE; - } else - caps |= PURPLE_MEDIA_CAPS_MODIFY_SESSION | - PURPLE_MEDIA_CAPS_CHANGE_DIRECTION; + jb = jabber_buddy_find(js, who, FALSE); + + if(!jb || !jb->resources) { + /* no resources online, we're trying to get caps for someone + * whose presence we're not subscribed to, or + * someone who is offline. */ + return caps; + } else if(!jb->resources->next) { + /* only 1 resource online (probably our most common case) */ + gchar *name; + jbr = jb->resources->data; + name = g_strdup_printf("%s/%s", who, jbr->name); + caps = jabber_get_media_caps(gc, name); + g_free(name); + } else { + /* we've got multiple resources, combine their caps */ + GList *l; + + for(l = jb->resources; l; l = l->next) + { + gchar *name; + jbr = l->data; + name = g_strdup_printf("%s/%s", who, jbr->name); + caps |= jabber_get_media_caps(gc, name); + g_free(name); + } } - if (jabber_buddy_has_capability(jb, GOOGLE_VOICE_CAP)) - caps |= PURPLE_MEDIA_CAPS_AUDIO; return caps; #else diff -r f171707b7d54 -r c08719989149 libpurple/protocols/jabber/jingle/rtp.c --- a/libpurple/protocols/jabber/jingle/rtp.c Fri Apr 03 20:46:31 2009 +0000 +++ b/libpurple/protocols/jabber/jingle/rtp.c Sat Apr 04 02:55:39 2009 +0000 @@ -834,7 +834,7 @@ JabberBuddyResource *jbr; const gchar *transport_type; - gchar *jid = NULL, *me = NULL, *sid = NULL; + gchar *resource = NULL, *me = NULL, *sid = NULL; /* construct JID to send to */ jb = jabber_buddy_find(js, who, FALSE); @@ -842,7 +842,11 @@ purple_debug_error("jingle-rtp", "Could not find Jabber buddy\n"); return FALSE; } - jbr = jabber_buddy_find_resource(jb, NULL); + + resource = jabber_get_resource(who); + jbr = jabber_buddy_find_resource(jb, resource); + g_free(resource); + if (!jbr) { purple_debug_error("jingle-rtp", "Could not find buddy's resource\n"); } @@ -857,17 +861,11 @@ return FALSE; } - if ((strchr(who, '/') == NULL) && jbr && (jbr->name != NULL)) { - jid = g_strdup_printf("%s/%s", who, jbr->name); - } else { - jid = g_strdup(who); - } - /* set ourselves as initiator */ me = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain, js->user->resource); sid = jabber_get_next_id(js); - session = jingle_session_create(js, sid, me, jid, TRUE); + session = jingle_session_create(js, sid, me, who, TRUE); g_free(sid); @@ -888,7 +886,6 @@ jingle_rtp_init_media(content); } - g_free(jid); g_free(me); if (jingle_rtp_get_media(session) == NULL) {