[telepathy-gabble/master] Support name="" on <active/> and <mute/>

Will Thompson will.thompson at collabora.co.uk
Thu Apr 2 07:49:24 PDT 2009


---
 src/jingle-media-rtp.c              |   23 +++++++--
 tests/twisted/jingle/call-state.py  |  102 ++++++++++++++++++++++++++++++++---
 tests/twisted/jingle/jingletest2.py |   25 +++++++++
 3 files changed, 139 insertions(+), 11 deletions(-)

diff --git a/src/jingle-media-rtp.c b/src/jingle-media-rtp.c
index bccf926..92cae40 100644
--- a/src/jingle-media-rtp.c
+++ b/src/jingle-media-rtp.c
@@ -821,6 +821,8 @@ gabble_jingle_media_rtp_handle_info (GabbleJingleContent *content,
   GabbleJingleMediaRtp *self = GABBLE_JINGLE_MEDIA_RTP (content);
   const gchar *ns = lm_message_node_get_namespace (payload);
   const gchar *elt = lm_message_node_get_name (payload);
+  const gchar *name_attr = lm_message_node_get_attribute (payload, "name");
+  const gchar *content_name = gabble_jingle_content_get_name (content);
   JingleRtpRemoteState new_state;
 
   if (tp_strdiff (ns, NS_JINGLE_RTP_INFO))
@@ -831,14 +833,27 @@ gabble_jingle_media_rtp_handle_info (GabbleJingleContent *content,
 
   *handled = TRUE;
 
+  /* The XEP only says active and mute can have name="". */
   if (!tp_strdiff (elt, "active"))
-    new_state = JINGLE_RTP_REMOTE_STATE_ACTIVE;
+    {
+      if (name_attr != NULL && tp_strdiff (name_attr, content_name))
+        return TRUE;
+      new_state = JINGLE_RTP_REMOTE_STATE_ACTIVE;
+    }
   else if (!tp_strdiff (elt, "ringing"))
-    new_state = JINGLE_RTP_REMOTE_STATE_RINGING;
+    {
+      new_state = JINGLE_RTP_REMOTE_STATE_RINGING;
+    }
   else if (!tp_strdiff (elt, "hold"))
-    new_state = JINGLE_RTP_REMOTE_STATE_HOLD;
+    {
+      new_state = JINGLE_RTP_REMOTE_STATE_HOLD;
+    }
   else if (!tp_strdiff (elt, "mute"))
-    new_state = JINGLE_RTP_REMOTE_STATE_MUTE;
+    {
+      if (name_attr != NULL && tp_strdiff (name_attr, content_name))
+        return TRUE;
+      new_state = JINGLE_RTP_REMOTE_STATE_MUTE;
+    }
   else
     {
       g_set_error (error, GABBLE_XMPP_ERROR, XMPP_ERROR_JINGLE_UNSUPPORTED_INFO,
diff --git a/tests/twisted/jingle/call-state.py b/tests/twisted/jingle/call-state.py
index 39640a2..5e0690e 100644
--- a/tests/twisted/jingle/call-state.py
+++ b/tests/twisted/jingle/call-state.py
@@ -7,7 +7,7 @@ from twisted.words.xish import xpath
 
 from gabbletest import make_result_iq, sync_stream
 from servicetest import wrap_channel, make_channel_proxy, call_async, \
-    EventPattern
+    EventPattern, tp_path_prefix
 import ns
 import constants as cs
 
@@ -47,8 +47,9 @@ def test(jp, q, bus, conn, stream):
     session_handler.Ready()
 
     e = q.expect('dbus-signal', signal='NewStreamHandler')
-
-    stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler')
+    audio_path = e.args[0]
+    audio_path_suffix = audio_path[len(tp_path_prefix):]
+    stream_handler = make_channel_proxy(conn, audio_path, 'Media.StreamHandler')
 
     stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus())
     stream_handler.Ready(jt.get_audio_codecs_dbus())
@@ -76,7 +77,8 @@ def test(jp, q, bus, conn, stream):
 
     # Various misc happens; among other things, Gabble tells s-e to start
     # sending.
-    q.expect('dbus-signal', signal='SetStreamSending', args=[True])
+    q.expect('dbus-signal', signal='SetStreamSending', args=[True],
+        path=audio_path_suffix)
 
     # Plus, the other person's client decides it's not ringing any more
     node = jp.SetIq(jt.peer, jt.jid, [
@@ -98,7 +100,8 @@ def test(jp, q, bus, conn, stream):
 
     q.expect_many(
         EventPattern('stream-iq', iq_type='result', iq_id=node[2]['id']),
-        EventPattern('dbus-signal', signal='SetStreamSending', args=[False]),
+        EventPattern('dbus-signal', signal='SetStreamSending', args=[False],
+            path=audio_path_suffix),
         EventPattern('dbus-signal', signal='CallStateChanged',
             args=[handle, cs.CALL_STATE_HELD]),
         )
@@ -138,7 +141,8 @@ def test(jp, q, bus, conn, stream):
 
     q.expect_many(
         EventPattern('stream-iq', iq_type='result', iq_id=node[2]['id']),
-        EventPattern('dbus-signal', signal='SetStreamSending', args=[True]),
+        EventPattern('dbus-signal', signal='SetStreamSending', args=[True],
+            path=audio_path_suffix),
         EventPattern('dbus-signal', signal='CallStateChanged',
             args=[handle, 0]),
         )
@@ -146,7 +150,91 @@ def test(jp, q, bus, conn, stream):
     call_states = chan.CallState.GetCallStates()
     assert call_states == { handle: 0 } or call_states == {}, call_states
 
-    # Test completed, close the connection
+    # Okay, let's get a second stream involved!
+
+    chan.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_VIDEO])
+
+    e = q.expect('dbus-signal', signal='NewStreamHandler')
+    video_path = e.args[0]
+    video_path_suffix = video_path[len(tp_path_prefix):]
+    stream_handler2 = make_channel_proxy(conn, video_path, 'Media.StreamHandler')
+
+    stream_handler2.NewNativeCandidate("fake", jt.get_remote_transports_dbus())
+    stream_handler2.Ready(jt.get_video_codecs_dbus())
+    stream_handler2.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED)
+
+    e = q.expect('stream-iq', predicate=lambda e:
+            jp.match_jingle_action(e.query, 'content-add'))
+    stream.send(make_result_iq(stream, e.stanza))
+
+    jt.content_accept(e.query, 'video')
+
+    q.expect('dbus-signal', signal='SetStreamSending', args=[True],
+        path=video_path_suffix)
+
+    call_states = chan.CallState.GetCallStates()
+    assert call_states == { handle: 0 } or call_states == {}, call_states
+
+    # The other person puts us on hold.  Gabble should ack the session-info IQ,
+    # tell s-e to stop sending on both streams, and set the call state.
+    node = jp.SetIq(jt.peer, jt.jid, [
+        jp.Jingle(jt.sid, jt.jid, 'session-info', [
+            ('hold', ns.JINGLE_RTP_INFO_1, {}, []) ]) ])
+    stream.send(jp.xml(node))
+
+    q.expect_many(
+        EventPattern('stream-iq', iq_type='result', iq_id=node[2]['id']),
+        EventPattern('dbus-signal', signal='SetStreamSending', args=[False],
+            path=audio_path_suffix),
+        EventPattern('dbus-signal', signal='SetStreamSending', args=[False],
+            path=video_path_suffix),
+        EventPattern('dbus-signal', signal='CallStateChanged',
+            args=[handle, cs.CALL_STATE_HELD]),
+        )
+
+    call_states = chan.CallState.GetCallStates()
+    assert call_states == { handle: cs.CALL_STATE_HELD }, call_states
+
+    # The other person sets the video stream back to <active/>. (XEP-0167
+    # says that <active/> and <mute/> can have name='', but <hold/> can't.
+    # Gabble should expose this as "start sending video again, but the call's
+    # still held."
+    # FIXME: hardcoded stream id
+    node = jp.SetIq(jt.peer, jt.jid, [
+        jp.Jingle(jt.sid, jt.jid, 'session-info', [
+            ('active', ns.JINGLE_RTP_INFO_1, {'name': 'stream2'}, []) ]) ])
+    stream.send(jp.xml(node))
+
+    q.expect_many(
+        EventPattern('stream-iq', iq_type='result', iq_id=node[2]['id']),
+        EventPattern('dbus-signal', signal='SetStreamSending', args=[True],
+            path=video_path_suffix),
+        )
+
+    call_states = chan.CallState.GetCallStates()
+    assert call_states == { handle: cs.CALL_STATE_HELD }, call_states
+
+    # Now the other person sets the audio stream to mute. Gabble should expose
+    # this as the call being active again (since we can't represent mute yet!)
+    # and tell s-e to start sending audio again.
+    # FIXME: hardcoded stream id
+    node = jp.SetIq(jt.peer, jt.jid, [
+        jp.Jingle(jt.sid, jt.jid, 'session-info', [
+            ('mute', ns.JINGLE_RTP_INFO_1, {'name': 'stream1'}, []) ]) ])
+    stream.send(jp.xml(node))
+
+    q.expect_many(
+        EventPattern('stream-iq', iq_type='result', iq_id=node[2]['id']),
+        EventPattern('dbus-signal', signal='SetStreamSending', args=[True],
+            path=audio_path_suffix),
+        EventPattern('dbus-signal', signal='CallStateChanged',
+            args=[ handle, 0 ]),
+        )
+
+    call_states = chan.CallState.GetCallStates()
+    assert call_states == { handle: 0 } or call_states == {}, call_states
+
+    # That'll do, pig.
 
     chan.Group.RemoveMembers([self_handle], 'closed')
     e = q.expect('dbus-signal', signal='Close') #XXX - match against the path
diff --git a/tests/twisted/jingle/jingletest2.py b/tests/twisted/jingle/jingletest2.py
index f42ee71..b1482c8 100644
--- a/tests/twisted/jingle/jingletest2.py
+++ b/tests/twisted/jingle/jingletest2.py
@@ -393,6 +393,31 @@ class JingleTest2:
                 audio + video) ])
         self.stream.send(jp.xml(node))
 
+    def content_accept(self, query, media):
+        """
+        Accepts a content-add stanza containing a single <content> of the given
+        media type.
+        """
+        jp = self.jp
+        c = query.firstChildElement()
+
+        if media == 'audio':
+            codecs = self.audio_codecs
+        elif media == 'video':
+            codecs = self.video_codecs
+        else:
+            assert False
+
+        # Remote end finally accepts
+        node = jp.SetIq(self.peer, self.jid, [
+            jp.Jingle(self.sid, self.peer, 'content-accept', [
+                jp.Content(c['name'], c['creator'], c['senders'], [
+                    jp.Description(media, [
+                        jp.PayloadType(name, str(rate), str(id)) for
+                            (name, id, rate) in codecs ]),
+                jp.TransportGoogleP2P() ]) ]) ])
+        self.stream.send(jp.xml(node))
+
     def terminate(self, reason=None):
         jp = self.jp
 
-- 
1.5.6.5




More information about the telepathy-commits mailing list