[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