[Telepathy-commits] [telepathy-gabble/master] MediaStream code cleanup, support for stream directions

Senko Rasic senko at phyrexia.lan
Tue Dec 2 04:33:58 PST 2008


---
 src/media-stream.c |  753 ++++++++--------------------------------------------
 src/media-stream.h |    2 +
 2 files changed, 111 insertions(+), 644 deletions(-)

diff --git a/src/media-stream.c b/src/media-stream.c
index 4afb65c..93c7d9e 100644
--- a/src/media-stream.c
+++ b/src/media-stream.c
@@ -149,6 +149,10 @@ static void new_remote_candidates_cb (GabbleJingleContent *content,
     GList *clist, GabbleMediaStream *stream);
 static void new_remote_codecs_cb (GabbleJingleContent *content,
     GList *clist, GabbleMediaStream *stream);
+static void content_state_changed_cb (GabbleJingleContent *c,
+     GParamSpec *pspec, GabbleMediaStream *stream);
+static void content_senders_changed_cb (GabbleJingleContent *c,
+     GParamSpec *pspec, GabbleMediaStream *stream);
 
 static void
 gabble_media_stream_init (GabbleMediaStream *self)
@@ -347,10 +351,21 @@ gabble_media_stream_set_property (GObject      *object,
       g_signal_connect (priv->content, "remote-codecs",
           (GCallback) new_remote_codecs_cb, stream);
 
+      g_signal_connect (priv->content, "notify::state",
+          (GCallback) content_state_changed_cb, stream);
+
+      g_signal_connect (priv->content, "notify::senders",
+          (GCallback) content_senders_changed_cb, stream);
+
       /* we can immediately get the codecs if we're responder */
       new_remote_codecs_cb (priv->content,
           gabble_jingle_media_rtp_get_remote_codecs (GABBLE_JINGLE_MEDIA_RTP (priv->content)),
           stream);
+
+      /* if any candidates arrived before idle loop had the chance to excute
+       * us, we don't wan to miss them */
+      new_remote_candidates_cb (priv->content,
+          gabble_jingle_content_get_remote_candidates (priv->content), stream);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -1087,223 +1102,6 @@ gabble_media_stream_supported_codecs (TpSvcMediaStreamHandler *iface,
   tp_svc_media_stream_handler_return_from_supported_codecs (context);
 }
 
-#if 0
-static LmHandlerResult
-candidates_msg_reply_cb (GabbleConnection *conn,
-                         LmMessage *sent_msg,
-                         LmMessage *reply_msg,
-                         GObject *object,
-                         gpointer user_data)
-{
-  GabbleMediaStream *stream = GABBLE_MEDIA_STREAM (object);
-  GabbleMediaStreamPrivate *priv;
-
-  g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
-  priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
-  /* FIXME 
-  MSG_REPLY_CB_END_SESSION_IF_NOT_SUCCESSFUL (priv->session,
-      "candidates failed"); */
-
-  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-#endif
-
-#if 0
-static void
-_add_rtp_candidate_node (GabbleMediaSession *session, LmMessageNode *parent,
-                         GValueArray *candidate)
-{
-  gchar *addr;
-  gchar *user;
-  gchar *pass;
-  gchar *port_str;
-  gchar *pref_str;
-  gchar *xml;
-  const gchar *type_str, *proto_str, *candidate_id;
-  guint port;
-  gdouble pref;
-  TpMediaStreamBaseProto proto;
-  TpMediaStreamTransportType type;
-  const GPtrArray *transports;
-  GValue transport = { 0, };
-  LmMessageNode *cand_node;
-
-  candidate_id = g_value_get_string (g_value_array_get_nth (candidate, 0));
-  transports = g_value_get_boxed (g_value_array_get_nth (candidate, 1));
-
-  /* jingle audio only supports the concept of one transport per candidate */
-  g_assert (transports->len == 1);
-
-  g_value_init (&transport, TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_TRANSPORT);
-  g_value_set_static_boxed (&transport, g_ptr_array_index (transports, 0));
-
-  dbus_g_type_struct_get (&transport,
-      1, &addr,
-      2, &port,
-      3, &proto,
-      6, &pref,
-      7, &type,
-      8, &user,
-      9, &pass,
-      G_MAXUINT);
-
-  port_str = g_strdup_printf ("%d", port);
-  pref_str = g_strdup_printf ("%f", pref);
-
-  switch (type) {
-    case TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL:
-      type_str = "local";
-      break;
-    case TP_MEDIA_STREAM_TRANSPORT_TYPE_DERIVED:
-      type_str = "stun";
-      break;
-    case TP_MEDIA_STREAM_TRANSPORT_TYPE_RELAY:
-      type_str = "relay";
-      break;
-    default:
-      g_warning ("%s: TpMediaStreamTransportType has an invalid value, "
-          "ignoring candidate", G_STRFUNC);
-      goto out;
-  }
-
-  switch (proto)
-    {
-    case TP_MEDIA_STREAM_BASE_PROTO_UDP:
-      proto_str = "udp";
-      break;
-    case TP_MEDIA_STREAM_BASE_PROTO_TCP:
-      if (port == 443 && type == TP_MEDIA_STREAM_TRANSPORT_TYPE_RELAY)
-        proto_str = "ssltcp";
-      else
-        proto_str = "tcp";
-      break;
-    default:
-      g_warning ("%s: TpMediaStreamBaseProto has an invalid value, ignoring "
-          "candidate", G_STRFUNC);
-      goto out;
-    }
-
-  cand_node = lm_message_node_add_child (parent, "candidate", NULL);
-  lm_message_node_set_attributes (cand_node,
-      "name", "rtp",
-      "address", addr,
-      "port", port_str,
-      "username", user,
-      "password", pass,
-      "preference", pref_str,
-      "protocol", proto_str,
-      "type", type_str,
-      "network", "0",
-      "generation", "0",
-      NULL);
-
-  xml = lm_message_node_to_string (cand_node);
-  GMS_DEBUG_DUMP (session,
-    "  from Telepathy D-Bus struct: [%s\"%s\", %s[%s1, \"%s\", %d, %s, "
-    "\"%s\", \"%s\", %f, %s, \"%s\", \"%s\"%s]]",
-    TP_ANSI_BOLD_OFF, candidate_id, TP_ANSI_BOLD_ON, TP_ANSI_BOLD_OFF,
-    addr, port, tp_protocols[proto], "RTP", "AVP", pref, tp_transports[type],
-    user, pass, TP_ANSI_BOLD_ON);
-  GMS_DEBUG_DUMP (session,
-    "  to Jingle XML: [%s%s%s]", TP_ANSI_BOLD_OFF, xml, TP_ANSI_BOLD_ON);
-  g_free (xml);
-
-out:
-  g_free (addr);
-  g_free (user);
-  g_free (pass);
-  g_free (port_str);
-  g_free (pref_str);
-}
-#endif
-
-#if 0
-static LmMessage *
-_gabble_media_stream_message_new (GabbleMediaStream *stream,
-                                  const gchar *action,
-                                  LmMessageNode **content_node)
-{
-  GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-  LmMessage *msg;
-  LmMessageNode *session_node = NULL;
-
-  /* construct a session message */
-  msg = _gabble_media_session_message_new (priv->session, action,
-      &session_node);
-
-  /* add our content node to it if necessary */
-  *content_node = _gabble_media_stream_add_content_node (stream, session_node);
-
-  return msg;
-}
-#endif
-
-#if 0
-static void
-push_candidate (GabbleMediaStream *stream, GValueArray *candidate)
-{
-  GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-  LmMessage *msg;
-  LmMessageNode *content_node, *transport_node;
-  const gchar *action;
-
-  if (priv->mode == MODE_GOOGLE)
-    action = "candidates";
-  else
-    action = "transport-info";
-
-  /* construct a base message */
-  msg = _gabble_media_stream_message_new (stream, action, &content_node);
-
-  /* for jingle, add a transport */
-  transport_node = _gabble_media_stream_content_node_add_transport (stream,
-      content_node);
-
-  /* add transport info to it */
-  _add_rtp_candidate_node (priv->session, transport_node, candidate);
-
-  GMS_DEBUG_INFO (priv->session, "sending jingle session action \"%s\" to "
-      "peer", action);
-
-  /* send it */
-  _gabble_connection_send_with_reply (priv->conn, msg, candidates_msg_reply_cb,
-      G_OBJECT (stream), NULL, NULL);
-
-  /* clean up */
-  lm_message_unref (msg);
-}
-#endif
-
-#if 0
-static void
-push_native_candidates (GabbleMediaStream *stream)
-{
-  GabbleMediaStreamPrivate *priv;
-  GPtrArray *candidates;
-  guint i;
-  GType candidate_list_type =
-      TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CANDIDATE_LIST;
-
-  g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
-  priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
-  if (stream->signalling_state == STREAM_SIG_STATE_NEW ||
-      stream->signalling_state == STREAM_SIG_STATE_REMOVING)
-    return;
-
-  candidates = g_value_get_boxed (&priv->native_candidates);
-
-  for (i = 0; i < candidates->len; i++)
-    push_candidate (stream, g_ptr_array_index (candidates, i));
-
-  g_value_take_boxed (&priv->native_candidates,
-    dbus_g_type_specialized_construct (candidate_list_type));
-}
-#endif
-
 void
 _gabble_media_stream_close (GabbleMediaStream *stream)
 {
@@ -1320,114 +1118,6 @@ _gabble_media_stream_close (GabbleMediaStream *stream)
     }
 }
 
-#if 0
-gboolean
-_gabble_media_stream_post_remote_codecs (GabbleMediaStream *stream,
-                                         LmMessage *message,
-                                         LmMessageNode *desc_node,
-                                         GError **error)
-{
-  GabbleMediaStreamPrivate *priv;
-  LmMessageNode *node;
-  GPtrArray *codecs;
-  GType codec_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CODEC;
-
-  g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
-  priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
-  codecs = g_value_get_boxed (&priv->remote_codecs);
-
-  g_assert (codecs->len == 0);
-
-  for (node = desc_node->children; node; node = node->next)
-    {
-      guchar id;
-      const gchar *name, *str;
-      guint clockrate, channels;
-      GHashTable *params;
-      GValue codec = { 0, };
-
-      if (tp_strdiff (node->name, "payload-type"))
-        continue;
-
-      /* id of codec */
-      str = lm_message_node_get_attribute (node, "id");
-      if (str == NULL)
-        {
-          g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
-              "description has no ID");
-          return FALSE;
-        }
-
-      id = atoi (str);
-
-      /* codec name */
-      name = lm_message_node_get_attribute (node, "name");
-      if (name == NULL)
-        {
-          name = "";
-        }
-
-      /* clock rate: jingle and newer GTalk */
-      str = lm_message_node_get_attribute (node, "clockrate"); /* google */
-      if (str == NULL)
-        str = lm_message_node_get_attribute (node, "rate"); /* jingle */
-
-      if (str != NULL)
-        {
-          clockrate = atoi (str);
-        }
-      else
-        {
-          clockrate = 0;
-        }
-
-      /* number of channels: jingle only */
-      str = lm_message_node_get_attribute (node, "channels");
-      if (str != NULL)
-        {
-          channels = atoi (str);
-        }
-      else
-        {
-          channels = 1;
-        }
-
-      params = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
-
-      /* bitrate: newer GTalk only */
-      str = lm_message_node_get_attribute (node, "bitrate");
-      if (str != NULL)
-        {
-          g_hash_table_insert (params, "bitrate", g_strdup (str));
-        }
-
-      g_value_init (&codec, codec_struct_type);
-      g_value_take_boxed (&codec,
-          dbus_g_type_specialized_construct (codec_struct_type));
-
-      dbus_g_type_struct_set (&codec,
-          0, id,
-          1, name,
-          2, priv->media_type,
-          3, clockrate,
-          4, channels,
-          5, params,
-          G_MAXUINT);
-
-      g_ptr_array_add (codecs, g_value_get_boxed (&codec));
-    }
-
-  GMS_DEBUG_INFO (priv->session, "put %d remote codecs from peer into cache",
-                  codecs->len);
-
-  push_remote_codecs (stream);
-
-  return TRUE;
-}
-#endif
-
 static void
 new_remote_codecs_cb (GabbleJingleContent *content,
     GList *clist, GabbleMediaStream *stream)
@@ -1465,6 +1155,8 @@ new_remote_codecs_cb (GabbleJingleContent *content,
           2, priv->media_type,
           3, c->clockrate,
           4, c->channels,
+            /* FIXME: valgrind shows leak in g_hash_table_new_full - doesn't
+             * dbus-glib free that? */
           5, g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free),
           G_MAXUINT);
 
@@ -1571,218 +1263,28 @@ new_remote_candidates_cb (GabbleJingleContent *content,
     }
 }
 
-#if 0
-gboolean
-_gabble_media_stream_post_remote_candidates (GabbleMediaStream *stream,
-                                             LmMessage *message,
-                                             LmMessageNode *transport_node,
-                                             GError **error)
+static void
+content_state_changed_cb (GabbleJingleContent *c,
+                          GParamSpec *pspec,
+                          GabbleMediaStream *stream)
 {
-  GabbleMediaStreamPrivate *priv;
-  LmMessageNode *node;
-  const gchar *str;
-  GPtrArray *candidates;
-  GType transport_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_TRANSPORT;
-  GType candidate_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CANDIDATE;
-
-  g_assert (GABBLE_IS_MEDIA_STREAM (stream));
+  GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
+  JingleContentState state;
 
-  priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
+  g_object_get (c, "state", &state, NULL);
 
-  candidates = g_value_get_boxed (&priv->remote_candidates);
+  DEBUG ("called");
 
-  for (node = transport_node->children; node; node = node->next)
+  if (state == JINGLE_CONTENT_STATE_ACKNOWLEDGED)
     {
-      gchar *candidate_id;
-      const gchar *name, *addr;
-      guint16 port;
-      TpMediaStreamBaseProto proto;
-      gdouble pref;
-      TpMediaStreamTransportType type;
-      const gchar *user, *pass;
-      guchar net, gen;
-      GValue candidate = { 0, };
-      GPtrArray *transports;
-      GValue transport = { 0, };
-      gchar *xml;
-
-      if (tp_strdiff (node->name, "candidate"))
-        continue;
-
-      /*
-       * Candidate
-       */
-
-      /* stream name */
-      name = lm_message_node_get_attribute (node, "name");
-      if (name == NULL || strcmp (name, "rtp") != 0)
-        goto FAILURE;
-
-
-      /*
-       * Transport
-       */
-
-      /* ip address */
-      addr = lm_message_node_get_attribute (node, "address");
-      if (addr == NULL)
-        goto FAILURE;
-
-      /* port */
-      str = lm_message_node_get_attribute (node, "port");
-      if (str == NULL)
-        goto FAILURE;
-      port = atoi (str);
-
-      /* protocol */
-      str = lm_message_node_get_attribute (node, "protocol");
-      if (str == NULL)
-        goto FAILURE;
-
-      if (strcmp (str, "udp") == 0)
-        {
-          proto = TP_MEDIA_STREAM_BASE_PROTO_UDP;
-        }
-      else if (strcmp (str, "tcp") == 0)
-        {
-          if (port == 443)
-            {
-              GMS_DEBUG_WARNING (priv->session, "%s: tcp candidates on port "
-                  "443 must be ssltcp, ignoring candidate", G_STRFUNC);
-              continue;
-            }
-
-          proto = TP_MEDIA_STREAM_BASE_PROTO_TCP;
-        }
-      else if (strcmp (str, "ssltcp") == 0)
-        {
-          if (port != 443)
-            {
-              GMS_DEBUG_WARNING (priv->session, "%s: ssltcp candidates must "
-                  "be on port 443, ignoring candidate", G_STRFUNC);
-              continue;
-            }
-
-          proto = TP_MEDIA_STREAM_BASE_PROTO_TCP;
-        }
-      else
-        goto FAILURE;
-
-      /* protocol profile: hardcoded to "AVP" for now */
-
-      /* preference */
-      str = lm_message_node_get_attribute (node, "preference");
-      if (str == NULL)
-        goto FAILURE;
-      pref = g_ascii_strtod (str, NULL);
-
-      /* type */
-      str = lm_message_node_get_attribute (node, "type");
-      if (str == NULL)
-        goto FAILURE;
-
-      if (strcmp (str, "local") == 0)
-        {
-          type = TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL;
-        }
-      else if (strcmp (str, "stun") == 0)
-        {
-          type = TP_MEDIA_STREAM_TRANSPORT_TYPE_DERIVED;
-        }
-      else if (strcmp (str, "relay") == 0)
-        {
-          type = TP_MEDIA_STREAM_TRANSPORT_TYPE_RELAY;
-        }
-      else
-        goto FAILURE;
-
-      /* username */
-      user = lm_message_node_get_attribute (node, "username");
-      if (user == NULL)
-        goto FAILURE;
-
-      /* password */
-      pass = lm_message_node_get_attribute (node, "password");
-      if (pass == NULL)
-        goto FAILURE;
-
-      /* unknown */
-      str = lm_message_node_get_attribute (node, "network");
-      if (str == NULL)
-        goto FAILURE;
-      net = atoi (str);
-
-      /* unknown */
-      str = lm_message_node_get_attribute (node, "generation");
-      if (str == NULL)
-        goto FAILURE;
-      gen = atoi (str);
-
-
-      g_value_init (&transport, transport_struct_type);
-      g_value_take_boxed (&transport,
-          dbus_g_type_specialized_construct (transport_struct_type));
-
-      dbus_g_type_struct_set (&transport,
-          0, 1,         /* component number */
-          1, addr,
-          2, port,
-          3, proto,
-          4, "RTP",
-          5, "AVP",
-          6, pref,
-          7, type,
-          8, user,
-          9, pass,
-          G_MAXUINT);
-
-      transports = g_ptr_array_sized_new (1);
-      g_ptr_array_add (transports, g_value_get_boxed (&transport));
-
-
-      g_value_init (&candidate, candidate_struct_type);
-      g_value_take_boxed (&candidate,
-          dbus_g_type_specialized_construct (candidate_struct_type));
-
-      /* FIXME: is this naming scheme sensible? */
-      candidate_id = g_strdup_printf ("R%d", ++priv->remote_candidate_count);
-
-      dbus_g_type_struct_set (&candidate,
-          0, candidate_id,
-          1, transports,
-          G_MAXUINT);
-
-      g_ptr_array_add (candidates, g_value_get_boxed (&candidate));
+      /* FIXME: check direction for these */
+      stream->playing = TRUE;
+      priv->sending = TRUE;
 
-      xml = lm_message_node_to_string (node);
-      GMS_DEBUG_INFO (priv->session,
-          "put 1 remote candidate from peer into cache");
-      GMS_DEBUG_DUMP (priv->session, "  from Jingle XML: [%s%s%s]",
-                      TP_ANSI_BOLD_OFF, xml, TP_ANSI_BOLD_ON);
-      GMS_DEBUG_DUMP (priv->session,
-          "  to Telepathy D-Bus struct: [%s\"%s\", %s[%s1, \"%s\", %d, %s, "
-          "\"%s\", \"%s\", %f, %s, \"%s\", \"%s\"%s]]",
-          TP_ANSI_BOLD_OFF, candidate_id, TP_ANSI_BOLD_ON,
-          TP_ANSI_BOLD_OFF, addr, port, tp_protocols[proto],
-          "RTP", "AVP", pref, tp_transports[type],
-          user, pass, TP_ANSI_BOLD_ON);
-      g_free (xml);
-
-      g_free (candidate_id);
+      push_playing (stream);
+      push_sending (stream);
     }
-
-/*SUCCESS:*/
-  push_remote_candidates (stream);
-
-  return TRUE;
-
-FAILURE:
-  g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_BAD_REQUEST,
-      "unable to parse candidate");
-
-  return FALSE;
 }
-#endif
 
 static void
 push_remote_candidates (GabbleMediaStream *stream)
@@ -1927,139 +1429,102 @@ codec_params_from_tp_foreach (gpointer key, gpointer value, gpointer user_data)
 }
 #endif
 
-#if 0
-LmMessageNode *
-_gabble_media_stream_add_content_node (GabbleMediaStream *stream,
-                                       LmMessageNode *session_node)
+static void
+content_senders_changed_cb (GabbleJingleContent *c,
+                            GParamSpec *pspec,
+                            GabbleMediaStream *stream)
 {
-  GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-  LmMessageNode *node = session_node;
+  // GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
+  JingleContentSenders senders;
 
-  /* add our content node to it if in jingle mode */
-  if (priv->mode == MODE_JINGLE)
-    {
-      node = lm_message_node_add_child (session_node, "content", NULL);
-      lm_message_node_set_attribute (node, "name", stream->name);
-
-      if (priv->session->initiator == stream->initiator)
-        lm_message_node_set_attribute (node, "creator", "initiator");
-      else
-        lm_message_node_set_attribute (node, "creator", "responder");
-    }
-
-  return node;
+  g_object_get (c, "senders", &senders, NULL);
 }
 
-void
-_gabble_media_stream_content_node_add_description (GabbleMediaStream *stream,
-                                                   LmMessageNode *content_node)
+gboolean
+gabble_media_stream_change_direction (GabbleMediaStream *stream,
+    guint requested_dir, GError **error)
 {
-  GabbleMediaStreamPrivate *priv;
-  const GPtrArray *codecs;
-  LmMessageNode *desc_node;
-  guint i;
-  const gchar *xmlns;
-  GType codec_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CODEC;
-
-  g_assert (GABBLE_IS_MEDIA_STREAM (stream));
-
-  priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
-
-  codecs = g_value_get_boxed (&priv->native_codecs);
-
-  desc_node = lm_message_node_add_child (content_node, "description", NULL);
-
-  if (priv->mode == MODE_GOOGLE)
-    xmlns = NS_GOOGLE_SESSION_PHONE;
-  else if (priv->media_type == TP_MEDIA_STREAM_TYPE_VIDEO)
-    xmlns = NS_JINGLE_DESCRIPTION_VIDEO;
-  else
-    xmlns = NS_JINGLE_DESCRIPTION_AUDIO;
-
-  lm_message_node_set_attribute (desc_node, "xmlns", xmlns);
-
-  for (i = 0; i < codecs->len; i++)
+  GabbleMediaStreamPrivate *priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
+  CombinedStreamDirection new_combined_dir;
+  TpMediaStreamDirection current_dir;
+  TpMediaStreamPendingSend pending_send;
+  JingleContentSenders senders;
+  gboolean local_initiator;
+
+  current_dir = COMBINED_DIRECTION_GET_DIRECTION (stream->combined_direction);
+  pending_send = COMBINED_DIRECTION_GET_PENDING_SEND
+    (stream->combined_direction);
+
+  /* if we're awaiting a local decision on sending... */
+  if ((pending_send & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) != 0)
     {
-      GValue codec = { 0, };
-      guint id, clock_rate, channels;
-      gchar *name, buf[16];
-      GHashTable *params;
-      LmMessageNode *pt_node;
-      CodecParamsFromTpContext ctx;
-
-      g_value_init (&codec, codec_struct_type);
-      g_value_set_static_boxed (&codec, g_ptr_array_index (codecs, i));
+      /* clear the flag */
+      pending_send &= ~TP_MEDIA_STREAM_PENDING_LOCAL_SEND;
 
-      dbus_g_type_struct_get (&codec,
-          0, &id,
-          1, &name,
-          3, &clock_rate,
-          4, &channels,
-          5, &params,
-          G_MAXUINT);
-
-      /* create a sub-node called "payload-type" and fill it */
-      pt_node = lm_message_node_add_child (desc_node, "payload-type", NULL);
-
-      /* id: required */
-      sprintf (buf, "%u", id);
-      lm_message_node_set_attribute (pt_node, "id", buf);
-
-      /* name: optional */
-      if (*name != '\0')
-        {
-          lm_message_node_set_attribute (pt_node, "name", name);
-        }
-
-      /* clock rate: optional */
-      if (clock_rate != 0)
-        {
-          sprintf (buf, "%u", clock_rate);
-          lm_message_node_set_attribute (pt_node,
-              (priv->mode == MODE_GOOGLE) ? "clockrate" : "rate", buf);
-        }
-
-      /* number of channels: optional, jingle only */
-      /* FIXME: is it? */
-      if (channels != 0 && priv->mode == MODE_JINGLE)
-        {
-          sprintf (buf, "%u", channels);
-          lm_message_node_set_attribute (pt_node, "channels", buf);
-        }
+      /* make our current_dir match what other end thinks (he thinks we're
+       * bidirectional) so that we send the correct transitions */
+      current_dir ^= TP_MEDIA_STREAM_DIRECTION_SEND;
+    }
 
-      /* parse the optional params */
-      ctx.priv = priv;
-      ctx.pt_node = pt_node;
-      g_hash_table_foreach (params, codec_params_from_tp_foreach, &ctx);
+#if 0
+  /* if we're asking the remote end to start sending, set the pending flag and
+   * don't change our directionality just yet */
+  new_dir = requested_dir;
+  if (((current_dir & TP_MEDIA_STREAM_DIRECTION_RECEIVE) == 0) &&
+      ((new_dir & TP_MEDIA_STREAM_DIRECTION_RECEIVE) != 0))
+    {
+      pending_send ^= TP_MEDIA_STREAM_PENDING_REMOTE_SEND;
+      new_dir &= ~TP_MEDIA_STREAM_DIRECTION_RECEIVE;
+    }
+#endif
 
-      /* clean up */
-      g_free (name);
-      g_hash_table_destroy (params);
+  /* make any necessary changes */
+  new_combined_dir = MAKE_COMBINED_DIRECTION (requested_dir, pending_send);
+  if (new_combined_dir != stream->combined_direction)
+    {
+      g_object_set (stream, "combined-direction", new_combined_dir, NULL);
+      _gabble_media_stream_update_sending (stream, FALSE);
     }
-}
 
-LmMessageNode *
-_gabble_media_stream_content_node_add_transport (GabbleMediaStream *stream,
-                                                 LmMessageNode *content_node)
-{
-  GabbleMediaStreamPrivate *priv;
-  LmMessageNode *node;
+  /* short-circuit sending a request if we're not asking for anything new */
+  if (current_dir == requested_dir)
+    return TRUE;
 
-  g_assert (GABBLE_IS_MEDIA_STREAM (stream));
+  g_object_get (priv->content->session, "local-initiator", &local_initiator, NULL);
 
-  priv = GABBLE_MEDIA_STREAM_GET_PRIVATE (stream);
+  switch (requested_dir)
+    {
+      case TP_MEDIA_STREAM_DIRECTION_SEND:
+        senders = local_initiator ?
+          JINGLE_CONTENT_SENDERS_INITIATOR : JINGLE_CONTENT_SENDERS_RESPONDER;
+        break;
+
+      case TP_MEDIA_STREAM_DIRECTION_RECEIVE:
+        senders = local_initiator ?
+          JINGLE_CONTENT_SENDERS_RESPONDER : JINGLE_CONTENT_SENDERS_INITIATOR;
+        break;
+
+      case TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL:
+        senders = JINGLE_CONTENT_SENDERS_BOTH;
+        break;
+
+      default:
+        g_assert_not_reached ();
+    }
 
-  if (priv->mode != MODE_JINGLE)
-    return content_node;
+  if (!gabble_jingle_content_change_direction (priv->content, senders))
+    {
+      g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+          "stream direction invalid for the Jingle dialect in use");
+      return FALSE;
+    }
 
-  node = lm_message_node_add_child (content_node, "transport", NULL);
+  return TRUE;
+}
 
-  lm_message_node_set_attribute (node, "xmlns", NS_GOOGLE_TRANSPORT_P2P);
 
-  return node;
-}
-#endif
 
+/* FIXME: this doesn't work yet */
 void
 _gabble_media_stream_update_sending (GabbleMediaStream *stream,
                                      gboolean start_sending)
diff --git a/src/media-stream.h b/src/media-stream.h
index c378d90..1369fc7 100644
--- a/src/media-stream.h
+++ b/src/media-stream.h
@@ -107,6 +107,8 @@ void _gabble_media_stream_close (GabbleMediaStream *close);
 void _gabble_media_stream_update_sending (GabbleMediaStream *stream,
     gboolean start_sending);
 void gabble_media_stream_hold (GabbleMediaStream *stream, gboolean hold);
+gboolean gabble_media_stream_change_direction (GabbleMediaStream *stream,
+    guint requested_dir, GError **error);
 
 G_END_DECLS
 
-- 
1.5.6.5




More information about the Telepathy-commits mailing list