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