[telepathy-gabble/master] Emit CallStateChanged when "most held" state changes

Will Thompson will.thompson at collabora.co.uk
Wed Apr 1 11:09:39 PDT 2009


---
 src/media-channel.c |   93 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/media-stream.c  |    9 +++++
 src/media-stream.h  |    2 +
 3 files changed, 104 insertions(+), 0 deletions(-)

diff --git a/src/media-channel.c b/src/media-channel.c
index 153d921..492abcb 100644
--- a/src/media-channel.c
+++ b/src/media-channel.c
@@ -160,6 +160,11 @@ struct _GabbleMediaChannelPrivate
   TpLocalHoldState hold_state;
   TpLocalHoldStateReason hold_state_reason;
 
+  /* The "most held" of all associated contents' current states, which is what
+   * we present on CallState.
+   */
+  JingleRtpRemoteState remote_state;
+
   GPtrArray *delayed_request_streams;
 
   /* These are really booleans, but gboolean is signed. Thanks, GLib */
@@ -2429,6 +2434,86 @@ stream_direction_changed_cb (GabbleMediaStream *stream,
       chan, id, direction, pending_send);
 }
 
+static TpChannelCallStateFlags
+jingle_remote_state_to_csf (JingleRtpRemoteState state)
+{
+  switch (state)
+    {
+    case JINGLE_RTP_REMOTE_STATE_ACTIVE:
+    /* FIXME: we should be able to expose <mute/> through CallState */
+    case JINGLE_RTP_REMOTE_STATE_MUTE:
+      return 0;
+    case JINGLE_RTP_REMOTE_STATE_RINGING:
+      return TP_CHANNEL_CALL_STATE_RINGING;
+    case JINGLE_RTP_REMOTE_STATE_HOLD:
+      return TP_CHANNEL_CALL_STATE_HELD;
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+remote_state_changed_cb (GabbleJingleMediaRtp *rtp,
+    GParamSpec *pspec G_GNUC_UNUSED,
+    GabbleMediaChannel *self)
+{
+  GabbleMediaChannelPrivate *priv = self->priv;
+  JingleRtpRemoteState state = gabble_jingle_media_rtp_get_remote_state (rtp);
+  TpChannelCallStateFlags csf = 0;
+
+  DEBUG ("Content %p's state changed to %u (current channel state: %u)", rtp,
+      state, priv->remote_state);
+
+  if (state == priv->remote_state)
+    {
+      DEBUG ("already in that state");
+      return;
+    }
+
+  if (state > priv->remote_state)
+    {
+      /* If this content's state is "more held" than the current aggregated level,
+       * move up to it.
+       */
+      DEBUG ("%u is more held than %u, moving up", state, priv->remote_state);
+      priv->remote_state = state;
+    }
+  else
+    {
+      /* This content is now less held than the current aggregated level; we
+       * need to recalculate the highest hold level and see if it's changed.
+       */
+      guint i = 0;
+
+      DEBUG ("%u less held than %u; recalculating", state, priv->remote_state);
+      state = JINGLE_RTP_REMOTE_STATE_ACTIVE;
+
+      for (i = 0; i < priv->streams->len; i++)
+        {
+          GabbleJingleMediaRtp *c = gabble_media_stream_get_content (
+                g_ptr_array_index (priv->streams, i));
+          JingleRtpRemoteState s = gabble_jingle_media_rtp_get_remote_state (c);
+
+          state = MAX (state, s);
+          DEBUG ("%p in state %u; high water mark %u", c, s, state);
+        }
+
+      if (priv->remote_state == state)
+        {
+          DEBUG ("no change");
+          return;
+        }
+
+      priv->remote_state = state;
+    }
+
+  csf = jingle_remote_state_to_csf (priv->remote_state);
+  DEBUG ("emitting CallStateChanged(%u, %u) (JingleRtpRemoteState %u)",
+      priv->session->peer, csf, priv->remote_state);
+  tp_svc_channel_interface_call_state_emit_call_state_changed (self,
+      priv->session->peer, csf);
+}
+
 #define GTALK_CAPS \
   ( PRESENCE_CAP_GOOGLE_VOICE )
 
@@ -2529,6 +2614,14 @@ construct_stream (GabbleMediaChannel *chan,
   gabble_signal_connect_weak (stream, "notify::local-hold",
       (GCallback) stream_hold_state_changed, chan_o);
 
+  /* While we're here, watch the active/mute/held state of the corresponding
+   * content so we can keep the call state up to date, and call the callback
+   * once to pick up the current state of this content.
+   */
+  gabble_signal_connect_weak (c, "notify::remote-state",
+      (GCallback) remote_state_changed_cb, chan_o);
+  remote_state_changed_cb (GABBLE_JINGLE_MEDIA_RTP (c), NULL, chan);
+
   /* emit StreamAdded */
   mtype = gabble_media_stream_get_media_type (stream);
 
diff --git a/src/media-stream.c b/src/media-stream.c
index d0b94c5..ad82a39 100644
--- a/src/media-stream.c
+++ b/src/media-stream.c
@@ -1928,3 +1928,12 @@ dbus_properties_iface_init (gpointer g_iface,
   /* set not implemented in this class */
 #undef IMPLEMENT
 }
+
+GabbleJingleMediaRtp *
+gabble_media_stream_get_content (GabbleMediaStream *self)
+{
+  /* FIXME: we should fix this whole class up. It relies throughout on
+   *        self->priv->content actually secretly being a GabbleJingleMediaRtp.
+   */
+  return GABBLE_JINGLE_MEDIA_RTP (self->priv->content);
+}
diff --git a/src/media-stream.h b/src/media-stream.h
index bb7b309..d7e090e 100644
--- a/src/media-stream.h
+++ b/src/media-stream.h
@@ -99,6 +99,8 @@ GabbleMediaStream *gabble_media_stream_new (const gchar *object_path,
     const gchar *nat_traversal, const GPtrArray *relays);
 TpMediaStreamType gabble_media_stream_get_media_type (GabbleMediaStream *self);
 
+GabbleJingleMediaRtp *gabble_media_stream_get_content (GabbleMediaStream *self);
+
 G_END_DECLS
 
 #endif /* #ifndef __GABBLE_MEDIA_STREAM_H__*/
-- 
1.5.6.5




More information about the telepathy-commits mailing list