changeset 26474:8399b545925c

propagate from branch 'im.pidgin.pidgin' (head 58b2ba106e563fcd0984b9438aa427f1d61e25e9) to branch 'im.pidgin.cpw.darkrain42.xmpp.iq-handlers' (head a7d6ab07b988776e830ffb6befb18179ff46e24e)
author Paul Aurich <paul@darkrain42.org>
date Sat, 04 Apr 2009 07:08:33 +0000
parents c08719989149 (diff) 50ff0162fe26 (current diff)
children bf9438ea308d
files libpurple/protocols/jabber/jabber.c libpurple/protocols/jabber/jingle/rtp.c
diffstat 6 files changed, 290 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog.API	Sat Apr 04 07:05:23 2009 +0000
+++ b/ChangeLog.API	Sat Apr 04 07:08:33 2009 +0000
@@ -22,6 +22,10 @@
 		* purple_global_proxy_set_info
 		* purple_log_get_activity_score
 		* purple_network_force_online
+		* purple_network_set_stun_server
+		* purple_network_set_turn_server
+		* purple_network_get_stun_ip
+		* purple_network_get_turn_ip
 		* purple_prpl_get_media_caps
 		* purple_prpl_initiate_media
 		* purple_request_field_get_group
--- a/libpurple/media.c	Sat Apr 04 07:05:23 2009 +0000
+++ b/libpurple/media.c	Sat Apr 04 07:08:33 2009 +0000
@@ -655,6 +655,7 @@
 	GObject parent;
 };
 
+#ifdef USE_VV
 struct _PurpleMediaCandidatePrivate
 {
 	gchar *foundation;
@@ -929,6 +930,13 @@
 
 G_DEFINE_TYPE(PurpleMediaCandidate,
 		purple_media_candidate, G_TYPE_OBJECT);
+#else
+GType
+purple_media_candidate_get_type()
+{
+	return G_TYPE_NONE;
+}
+#endif
 
 PurpleMediaCandidate *
 purple_media_candidate_new(const gchar *foundation, guint component_id,
@@ -948,6 +956,7 @@
 static PurpleMediaCandidate *
 purple_media_candidate_copy(PurpleMediaCandidate *candidate)
 {
+#ifdef USE_VV
 	PurpleMediaCandidatePrivate *priv;
 	PurpleMediaCandidate *new_candidate;
 
@@ -967,6 +976,9 @@
 			"password", priv->password,
 			"ttl", priv->ttl, NULL);
 	return new_candidate;
+#else
+	return NULL;
+#endif
 }
 
 #ifdef USE_VV
@@ -1240,6 +1252,7 @@
 	GObject parent;
 };
 
+#ifdef USE_VV
 struct _PurpleMediaCodecPrivate
 {
 	gint id;
@@ -1408,6 +1421,13 @@
 
 G_DEFINE_TYPE(PurpleMediaCodec,
 		purple_media_codec, G_TYPE_OBJECT);
+#else
+GType
+purple_media_codec_get_type()
+{
+	return G_TYPE_NONE;
+}
+#endif
 
 guint
 purple_media_codec_get_id(PurpleMediaCodec *codec)
@@ -1458,6 +1478,7 @@
 purple_media_codec_add_optional_parameter(PurpleMediaCodec *codec,
 		const gchar *name, const gchar *value)
 {
+#ifdef USE_VV
 	PurpleMediaCodecPrivate *priv;
 	PurpleKeyValuePair *new_param;
 
@@ -1471,12 +1492,14 @@
 	new_param->value = g_strdup(value);
 	priv->optional_params = g_list_append(
 			priv->optional_params, new_param);
+#endif
 }
 
 void
 purple_media_codec_remove_optional_parameter(PurpleMediaCodec *codec,
 		PurpleKeyValuePair *param)
 {
+#ifdef USE_VV
 	PurpleMediaCodecPrivate *priv;
 
 	g_return_if_fail(codec != NULL && param != NULL);
@@ -1489,12 +1512,14 @@
 
 	priv->optional_params =
 			g_list_remove(priv->optional_params, param);
+#endif
 }
 
 PurpleKeyValuePair *
 purple_media_codec_get_optional_parameter(PurpleMediaCodec *codec,
 		const gchar *name, const gchar *value)
 {
+#ifdef USE_VV
 	PurpleMediaCodecPrivate *priv;
 	GList *iter;
 
@@ -1510,6 +1535,7 @@
 				!g_ascii_strcasecmp(param->value, value)))
 			return param;
 	}
+#endif
 
 	return NULL;
 }
@@ -1530,6 +1556,7 @@
 static PurpleMediaCodec *
 purple_media_codec_copy(PurpleMediaCodec *codec)
 {
+#ifdef USE_VV
 	PurpleMediaCodecPrivate *priv;
 	PurpleMediaCodec *new_codec;
 	GList *iter;
@@ -1551,6 +1578,9 @@
 	}
 
 	return new_codec;
+#else
+	return NULL;
+#endif
 }
 
 #ifdef USE_VV
--- a/libpurple/mediamanager.c	Sat Apr 04 07:05:23 2009 +0000
+++ b/libpurple/mediamanager.c	Sat Apr 04 07:08:33 2009 +0000
@@ -67,7 +67,6 @@
 	gulong window_id;
 	GstElement *sink;
 };
-#endif
 
 struct _PurpleMediaManagerPrivate
 {
@@ -100,10 +99,12 @@
 	LAST_SIGNAL
 };
 static guint purple_media_manager_signals[LAST_SIGNAL] = {0};
+#endif
 
 GType
 purple_media_manager_get_type()
 {
+#ifdef USE_VV
 	static GType type = 0;
 
 	if (type == 0) {
@@ -122,9 +123,12 @@
 		type = g_type_register_static(G_TYPE_OBJECT, "PurpleMediaManager", &info, 0);
 	}
 	return type;
+#else
+	return G_TYPE_NONE;
+#endif
 }
 
-
+#ifdef USE_VV
 static void
 purple_media_manager_class_init (PurpleMediaManagerClass *klass)
 {
@@ -165,6 +169,7 @@
 	}
 	parent_class->finalize(media);
 }
+#endif
 
 PurpleMediaManager *
 purple_media_manager_get()
@@ -837,7 +842,7 @@
 			PURPLE_MEDIA_CAPS_NONE);
 	return manager->priv->ui_caps;
 #else
-	return PURPLE_CAPS_NONE;
+	return PURPLE_MEDIA_CAPS_NONE;
 #endif
 }
 
@@ -909,6 +914,7 @@
 	GObject parent;
 };
 
+#ifdef USE_VV
 struct _PurpleMediaElementInfoPrivate
 {
 	gchar *id;
@@ -1048,6 +1054,13 @@
 
 G_DEFINE_TYPE(PurpleMediaElementInfo,
 		purple_media_element_info, G_TYPE_OBJECT);
+#else
+GType
+purple_media_element_info_get_type()
+{
+	return G_TYPE_NONE;
+}
+#endif
 
 gchar *
 purple_media_element_info_get_id(PurpleMediaElementInfo *info)
--- a/libpurple/network.h	Sat Apr 04 07:05:23 2009 +0000
+++ b/libpurple/network.h	Sat Apr 04 07:08:33 2009 +0000
@@ -230,6 +230,7 @@
  * Will result in a DNS query being executed asynchronous
  * 
  * @param stun_server The host name of the STUN server to set
+ * @since 2.6.0
  */
 void purple_network_set_stun_server(const gchar *stun_server);
 	
@@ -237,6 +238,7 @@
  * Get the IP address of the STUN server as a string representation
  *
  * @return the IP address
+ * @since 2.6.0
  */
 const gchar *purple_network_get_stun_ip(void);
 	
@@ -245,6 +247,7 @@
  * Will result in a DNS query being executed asynchronous
  * 
  * @param stun_server The host name of the STUN server to set
+ * @since 2.6.0
  */
 void purple_network_set_turn_server(const gchar *stun_server);
 	
@@ -252,6 +255,7 @@
  * Get the IP address of the STUN server as a string representation
  *
  * @return the IP address
+ * @since 2.6.0
  */
 const gchar *purple_network_get_turn_ip(void);
 		
--- a/libpurple/protocols/jabber/jabber.c	Sat Apr 04 07:05:23 2009 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Sat Apr 04 07:08:33 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
--- a/libpurple/protocols/jabber/jingle/rtp.c	Sat Apr 04 07:05:23 2009 +0000
+++ b/libpurple/protocols/jabber/jingle/rtp.c	Sat Apr 04 07:08:33 2009 +0000
@@ -835,7 +835,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);
@@ -843,7 +843,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");
 	}
@@ -858,17 +862,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);
 
 
@@ -889,7 +887,6 @@
 		jingle_rtp_init_media(content);
 	}
 
-	g_free(jid);
 	g_free(me);
 
 	if (jingle_rtp_get_media(session) == NULL) {