pidgin: b28028a0: Add a resource selector when initiating ...
maiku at soc.pidgin.im
maiku at soc.pidgin.im
Fri Apr 3 22:30:57 EDT 2009
-----------------------------------------------------------------
Revision: b28028a0f1c19eaf4ee7d941c83b587980320568
Ancestor: 030ca835c7587163eaabbe46fcca8596be10594b
Author: maiku at soc.pidgin.im
Date: 2009-04-04T02:26:49
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/b28028a0f1c19eaf4ee7d941c83b587980320568
Modified files:
libpurple/protocols/jabber/jabber.c
libpurple/protocols/jabber/jingle/rtp.c
ChangeLog:
Add a resource selector when initiating media.
-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/jabber.c ba869893c637d7f553e39b685f9e9148e3e646b4
+++ libpurple/protocols/jabber/jabber.c c8de69e0a6f1dbf009ebd5d4c31a78d2b7b1d990
@@ -2612,6 +2612,39 @@ gboolean jabber_offline_message(const Pu
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 @@ jabber_initiate_media(PurpleConnection *
#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 @@ jabber_initiate_media(PurpleConnection *
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);
+ }
+
jb = jabber_buddy_find(js, who, FALSE);
- if (!jb) {
- purple_debug_error("jabber", "Could not find buddy\n");
+ 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;
- 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
- return FALSE;
+ 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;
}
PurpleMediaCaps jabber_get_media_caps(PurpleConnection *gc, const char *who)
@@ -2650,7 +2797,9 @@ PurpleMediaCaps jabber_get_media_caps(Pu
#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 @@ PurpleMediaCaps jabber_get_media_caps(Pu
return FALSE;
}
- jb = jabber_buddy_find(js, who, FALSE);
+ if ((resource = jabber_get_resource(who)) != NULL) {
+ /* they've specified a resource, no need to ask or
+ * default or anything, just do it */
- if (!jb) {
- purple_debug_error("jabber", "Could not find buddy\n");
- return FALSE;
+ 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
============================================================
--- libpurple/protocols/jabber/jingle/rtp.c 00ade75579a2b54c158ccc8346748449ededc5bb
+++ libpurple/protocols/jabber/jingle/rtp.c 2ac3cc9cad689b329ad384a909fd312a8fd8a82e
@@ -834,7 +834,7 @@ jingle_rtp_initiate_media(JabberStream *
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 @@ jingle_rtp_initiate_media(JabberStream *
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 @@ jingle_rtp_initiate_media(JabberStream *
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_initiate_media(JabberStream *
jingle_rtp_init_media(content);
}
- g_free(jid);
g_free(me);
if (jingle_rtp_get_media(session) == NULL) {
More information about the Commits
mailing list