[Telepathy-commits] [telepathy-gabble/master] MediaChannel: delay RequestStreams if caps discover for contact is in progress
Senko Rasic
senko.rasic at collabora.co.uk
Thu Dec 4 06:11:28 PST 2008
---
src/media-channel.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 99 insertions(+), 8 deletions(-)
diff --git a/src/media-channel.c b/src/media-channel.c
index 387950d..8909d9c 100644
--- a/src/media-channel.c
+++ b/src/media-channel.c
@@ -183,7 +183,8 @@ static void session_new_content_cb (GabbleJingleSession *session,
GabbleJingleContent *c, gpointer user_data);
static GabbleMediaStream *
create_stream_from_content (GabbleMediaChannel *chan, GabbleJingleContent *c);
-static gboolean contact_is_media_capable (GabbleMediaChannel *chan, TpHandle peer);
+static gboolean contact_is_media_capable (GabbleMediaChannel *chan, TpHandle peer,
+ gboolean *wait);
static gboolean
_create_streams (GabbleMediaChannel *chan)
@@ -1300,7 +1301,7 @@ _gabble_media_channel_request_streams (GabbleMediaChannel *chan,
g_object_get (priv->session, "peer", &peer,
"peer-resource", &peer_resource, NULL);
- if (!contact_is_media_capable (chan, peer))
+ if (!contact_is_media_capable (chan, peer, NULL))
{
DEBUG ("peer has no a/v capabilities");
g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
@@ -1443,6 +1444,61 @@ _gabble_media_channel_request_streams (GabbleMediaChannel *chan,
return TRUE;
}
+struct _delayed_request_streams_ctx {
+ gulong caps_updated_id;
+ TpSvcChannelTypeStreamedMedia *iface;
+ guint contact_handle;
+ GArray *types;
+ DBusGMethodInvocation *context;
+};
+
+static void gabble_media_channel_request_streams (TpSvcChannelTypeStreamedMedia *iface,
+ guint contact_handle, const GArray *types, DBusGMethodInvocation *context);
+
+static void
+capabilities_discovered_cb (GabblePresenceCache *cache,
+ TpHandle handle,
+ gpointer user_data)
+{
+ struct _delayed_request_streams_ctx *ctx = user_data;
+
+ g_assert (handle == ctx->contact_handle);
+
+ /* If there are more cache caps pending, wait for them. */
+ if (gabble_presence_cache_caps_pending (cache, handle))
+ return;
+
+ g_signal_handler_disconnect (cache, ctx->caps_updated_id);
+
+ DEBUG ("Contact caps arrived, completing RequestStreams");
+
+ gabble_media_channel_request_streams (ctx->iface, handle,
+ ctx->types, ctx->context);
+
+ g_array_free (ctx->types, TRUE);
+ g_slice_free (struct _delayed_request_streams_ctx, ctx);
+}
+
+static void
+delay_stream_request (GabbleMediaChannel *chan,
+ TpSvcChannelTypeStreamedMedia *iface,
+ guint contact_handle,
+ const GArray *types,
+ DBusGMethodInvocation *context)
+{
+ GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan);
+ struct _delayed_request_streams_ctx *ctx =
+ g_slice_new0 (struct _delayed_request_streams_ctx);
+
+ ctx->iface = iface;
+ ctx->contact_handle = contact_handle;
+ ctx->context = context;
+ ctx->types = g_array_sized_new (FALSE, FALSE, sizeof(guint), types->len);
+ g_array_append_vals (ctx->types, types->data, types->len);
+
+ ctx->caps_updated_id = g_signal_connect (priv->conn-> presence_cache,
+ "capabilities-discovered", G_CALLBACK (capabilities_discovered_cb), ctx);
+}
/**
* gabble_media_channel_request_streams
@@ -1463,6 +1519,7 @@ gabble_media_channel_request_streams (TpSvcChannelTypeStreamedMedia *iface,
GError *error = NULL;
GPtrArray *ret;
TpHandleRepoIface *contact_handles;
+ gboolean wait;
g_assert (GABBLE_IS_MEDIA_CHANNEL (self));
@@ -1476,6 +1533,19 @@ gabble_media_channel_request_streams (TpSvcChannelTypeStreamedMedia *iface,
if (!tp_handle_is_valid (contact_handles, contact_handle, &error))
goto error;
+ /* If we know the caps haven't arrived yet, delay stream creation
+ * and check again later */
+ if (!contact_is_media_capable (self, contact_handle, &wait))
+ {
+ if (wait)
+ {
+ DEBUG ("delaying RequestStreams until we get all caps from contact");
+ delay_stream_request (self, iface, contact_handle, types, context);
+ return;
+ }
+ }
+
+
if (priv->session == NULL)
{
create_session (self, contact_handle);
@@ -1516,7 +1586,7 @@ error:
static gboolean
-contact_is_media_capable (GabbleMediaChannel *chan, TpHandle peer)
+contact_is_media_capable (GabbleMediaChannel *chan, TpHandle peer, gboolean *wait)
{
GabbleMediaChannelPrivate *priv = GABBLE_MEDIA_CHANNEL_GET_PRIVATE (chan);
GabblePresence *presence;
@@ -1527,6 +1597,16 @@ contact_is_media_capable (GabbleMediaChannel *chan, TpHandle peer)
conn, TP_HANDLE_TYPE_CONTACT);
#endif
+ if (wait != NULL)
+ *wait = FALSE;
+
+ if (gabble_presence_cache_caps_pending (priv->conn->presence_cache, peer))
+ {
+ DEBUG ("caps are pending for peer %u", peer);
+ if (wait != NULL)
+ *wait = TRUE;
+ }
+
caps = PRESENCE_CAP_GOOGLE_VOICE | PRESENCE_CAP_JINGLE_RTP |
PRESENCE_CAP_JINGLE_DESCRIPTION_AUDIO | PRESENCE_CAP_JINGLE_DESCRIPTION_VIDEO;
@@ -1563,6 +1643,7 @@ _gabble_media_channel_add_member (GObject *obj,
if (priv->creator == mixin->self_handle)
{
TpIntSet *set;
+ gboolean wait;
/* yes: check we don't have a peer already, invite this onis one */
@@ -1581,12 +1662,22 @@ _gabble_media_channel_add_member (GObject *obj,
}
}
- if (!contact_is_media_capable (chan, handle))
+ /* We can't delay the request at this time, but if there's a chance
+ * the caps might be available later, we'll add the contact and
+ * hope for the best. */
+ if (!contact_is_media_capable (chan, handle, &wait))
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "handle %u cannot be added: has no media capabilities",
- handle);
- return FALSE;
+ if (wait)
+ {
+ DEBUG ("contact %u caps still pending, adding anyways", handle);
+ }
+ else
+ {
+ g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "handle %u cannot be added: has no media capabilities",
+ handle);
+ return FALSE;
+ }
}
/* make the peer remote pending */
--
1.5.6.5
More information about the Telepathy-commits
mailing list