diff options
author | Olivier CrĂȘte <olivier.crete@collabora.com> | 2012-02-22 16:15:45 -0500 |
---|---|---|
committer | Olivier CrĂȘte <olivier.crete@collabora.com> | 2012-02-22 16:15:45 -0500 |
commit | 92a846c32180c0ce51a4862b80b5159261d45b98 (patch) | |
tree | a10c63cb04c0c019f9626af5ea862268b3b26bd2 | |
parent | 7dc9846458c8598793b6f42f839d256367ece9f8 (diff) |
Make it possible to add a content to a connected call
-rw-r--r-- | rakia/call-content.c | 3 | ||||
-rw-r--r-- | rakia/call-stream.c | 17 | ||||
-rw-r--r-- | rakia/sip-media.c | 86 | ||||
-rw-r--r-- | rakia/sip-media.h | 2 | ||||
-rw-r--r-- | rakia/sip-session.c | 4 | ||||
-rw-r--r-- | tests/twisted/Makefile.am | 1 | ||||
-rw-r--r-- | tests/twisted/voip/add-remove-content.py | 61 | ||||
-rw-r--r-- | tests/twisted/voip/calltest.py | 26 |
8 files changed, 178 insertions, 22 deletions
diff --git a/rakia/call-content.c b/rakia/call-content.c index 7f0463e..20a18ec 100644 --- a/rakia/call-content.c +++ b/rakia/call-content.c @@ -397,6 +397,9 @@ rakia_call_content_add_stream (RakiaCallContent *self) TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", ""); tp_base_call_content_add_stream (bcc, TP_BASE_CALL_STREAM (priv->stream)); + + tp_base_media_call_stream_update_receiving_state ( + TP_BASE_MEDIA_CALL_STREAM (priv->stream)); } static void diff --git a/rakia/call-stream.c b/rakia/call-stream.c index c727ca4..f2db669 100644 --- a/rakia/call-stream.c +++ b/rakia/call-stream.c @@ -63,6 +63,8 @@ static void media_remote_candidates_updated_cb (RakiaSipMedia *media, RakiaCallStream *self); static void media_direction_changed_cb (RakiaSipMedia *media, RakiaCallStream *self); +static void receiving_updated_cb (RakiaCallStream *self); + G_DEFINE_TYPE (RakiaCallStream, rakia_call_stream, TP_TYPE_BASE_MEDIA_CALL_STREAM) @@ -200,6 +202,10 @@ rakia_call_stream_constructed (GObject *object) tp_base_media_call_stream_set_relay_info (bmcs, relay_array); g_ptr_array_unref (relay_array); + g_signal_connect (self, "notify::receiving-state", + G_CALLBACK (receiving_updated_cb), NULL); + receiving_updated_cb (self); + G_OBJECT_CLASS (rakia_call_stream_parent_class)->constructed (object); } @@ -523,3 +529,14 @@ media_direction_changed_cb (RakiaSipMedia *media, RakiaCallStream *self) TP_SENDING_STATE_NONE, 0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", ""); } + +static void +receiving_updated_cb (RakiaCallStream *self) +{ + RakiaCallStreamPrivate *priv = self->priv; + TpBaseMediaCallStream *bmcs = TP_BASE_MEDIA_CALL_STREAM (self); + + rakia_sip_media_set_can_receive (priv->media, + tp_base_media_call_stream_get_receiving_state (bmcs) == + TP_STREAM_FLOW_STATE_STARTED); +} diff --git a/rakia/sip-media.c b/rakia/sip-media.c index f3a967b..37cb0ad 100644 --- a/rakia/sip-media.c +++ b/rakia/sip-media.c @@ -113,6 +113,8 @@ struct _RakiaSipMediaPrivate GPtrArray *remote_codec_offer; GPtrArray *remote_candidates; + + gboolean can_receive; }; @@ -856,9 +858,6 @@ rakia_sip_media_set_remote_media (RakiaSipMedia *media, /* Check if there was any media update at all */ - if (old_media) - g_debug ("old m %d new m %d", old_media->m_mode, new_media->m_mode); - new_direction = rakia_direction_from_remote_media (new_media); @@ -954,7 +953,14 @@ rakia_sip_media_is_codec_intersect_pending (RakiaSipMedia *self) gboolean rakia_sip_media_is_ready (RakiaSipMedia *self) { - return (self->priv->local_candidates_prepared && self->priv->local_codecs); + RakiaSipMediaPrivate *priv = RAKIA_SIP_MEDIA_GET_PRIVATE (self); + + if (priv->requested_direction & RAKIA_DIRECTION_RECEIVE && !priv->can_receive) + return FALSE; + + return (self->priv->local_candidates_prepared && + self->priv->local_codecs && + !priv->codec_intersect_pending); } void @@ -966,18 +972,38 @@ rakia_sip_media_take_local_codecs (RakiaSipMedia *self, GPtrArray *local_codecs) g_ptr_array_unref (priv->local_codecs); priv->local_codecs = local_codecs; - if (priv->codec_intersect_pending) + MEDIA_DEBUG (self, "New local codecs intersect_pending: %d " + "push_candidates: %d candidates_prepared: %d", + priv->codec_intersect_pending, priv->push_candidates_on_new_codecs, + priv->local_candidates_prepared); + + + if (priv->push_remote_codecs_pending) + { + priv->push_remote_codecs_pending = FALSE; + push_remote_codecs (self); + } + else if (priv->codec_intersect_pending) { if (priv->push_candidates_on_new_codecs) { /* Push the new candidates now that we have new codecs */ + priv->push_candidates_on_new_codecs = FALSE; push_remote_candidates (self); } - priv->codec_intersect_pending = FALSE; - if (priv->local_candidates_prepared) - g_signal_emit (self, signals[SIG_LOCAL_NEGOTIATION_COMPLETE], 0, + priv->codec_intersect_pending = FALSE; + if (rakia_sip_media_is_ready (self)) + { + g_signal_emit (self, signals[SIG_LOCAL_NEGOTIATION_COMPLETE], 0, TRUE); + g_ptr_array_unref (priv->remote_codec_offer); + priv->remote_codec_offer = NULL; + } + } + else + { + rakia_sip_media_local_updated (self); } } @@ -1013,9 +1039,11 @@ rakia_sip_media_local_candidates_prepared (RakiaSipMedia *self) self->priv->local_candidates_prepared = TRUE; - if (self->priv->local_codecs) - g_signal_emit (self, signals[SIG_LOCAL_NEGOTIATION_COMPLETE], 0, - TRUE); + if (rakia_sip_media_is_ready (self)) + { + g_signal_emit (self, signals[SIG_LOCAL_NEGOTIATION_COMPLETE], 0, + TRUE); + } return TRUE; } @@ -1090,7 +1118,20 @@ rakia_sip_media_get_session (RakiaSipMedia *media) void rakia_sip_media_codecs_rejected (RakiaSipMedia *media) { - g_signal_emit (media, signals[SIG_LOCAL_NEGOTIATION_COMPLETE], 0, FALSE); + RakiaSipMediaPrivate *priv = RAKIA_SIP_MEDIA_GET_PRIVATE (media); + + if (priv->push_remote_codecs_pending) + { + priv->push_remote_codecs_pending = FALSE; + push_remote_codecs (media); + } + else + { + priv->codec_intersect_pending = FALSE; + g_signal_emit (media, signals[SIG_LOCAL_NEGOTIATION_COMPLETE], 0, FALSE); + g_ptr_array_unref (priv->remote_codec_offer); + priv->remote_codec_offer = NULL; + } } RakiaDirection @@ -1118,3 +1159,24 @@ rakia_sip_media_is_held (RakiaSipMedia *media) { return !(media->priv->direction & RAKIA_DIRECTION_SEND); } + +void +rakia_sip_media_set_can_receive (RakiaSipMedia *media, gboolean can_receive) +{ + RakiaSipMediaPrivate *priv = RAKIA_SIP_MEDIA_GET_PRIVATE (media); + + if (priv->can_receive == can_receive) + return; + + priv->can_receive = can_receive; + + if (rakia_sip_media_is_ready (media)) + { + g_signal_emit (media, signals[SIG_LOCAL_NEGOTIATION_COMPLETE], 0, TRUE); + if (priv->remote_codec_offer) + { + g_ptr_array_unref (priv->remote_codec_offer); + priv->remote_codec_offer = NULL; + } + } +} diff --git a/rakia/sip-media.h b/rakia/sip-media.h index 571ca3d..4275312 100644 --- a/rakia/sip-media.h +++ b/rakia/sip-media.h @@ -168,6 +168,8 @@ RakiaDirection rakia_sip_media_get_remote_direction (RakiaSipMedia *media); RakiaDirection rakia_sip_media_get_requested_direction ( RakiaSipMedia *self); +void rakia_sip_media_set_can_receive (RakiaSipMedia *media, + gboolean can_receive); G_END_DECLS diff --git a/rakia/sip-session.c b/rakia/sip-session.c index be999b4..57d0045 100644 --- a/rakia/sip-session.c +++ b/rakia/sip-session.c @@ -750,6 +750,8 @@ priv_media_local_negotiation_complete_cb (RakiaSipMedia *media, { RakiaSipSessionPrivate *priv = RAKIA_SIP_SESSION_GET_PRIVATE (self); + SESSION_DEBUG (self, "negotiation complete %d", success); + if (!success) { /* This remote media description got no codec intersection. */ @@ -805,6 +807,8 @@ rakia_sip_session_media_changed (RakiaSipSession *self) { RakiaSipSessionPrivate *priv = RAKIA_SIP_SESSION_GET_PRIVATE (self); + SESSION_DEBUG (self, "media changed"); + switch (priv->state) { case RAKIA_SIP_SESSION_STATE_CREATED: diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am index a61b69c..870e1b3 100644 --- a/tests/twisted/Makefile.am +++ b/tests/twisted/Makefile.am @@ -14,6 +14,7 @@ TWISTED_TESTS = \ voip/ringing-queued.py \ voip/requestable-classes.py \ voip/direction-change.py + voip/add-remote-content.py \ $(NULL) TESTS = diff --git a/tests/twisted/voip/add-remove-content.py b/tests/twisted/voip/add-remove-content.py new file mode 100644 index 0000000..6921997 --- /dev/null +++ b/tests/twisted/voip/add-remove-content.py @@ -0,0 +1,61 @@ +import calltest +import constants as cs +from servicetest import ( + EventPattern, call_async, + assertEquals, assertNotEquals, assertContains, assertLength, + assertDoesNotContain + ) + +class AddRemoveContent(calltest.CallTest): + + def __init__(self, *params): + calltest.CallTest.__init__(self, *params) + + + + def during_call(self): + content = self.contents[0] + + o = self.chan.Call1.AddContent("new audio", cs.MEDIA_STREAM_TYPE_AUDIO, + cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL) + + + self.q.expect('dbus-signal', signal='ContentAdded', + args=[o], path=self.chan.__dbus_object_path__) + + content = self.add_content(o, initial=False, incoming=False) + + self.add_candidates(content.stream) + + md_path, _ = content.Get(cs.CALL_CONTENT_IFACE_MEDIA, + 'MediaDescriptionOffer') + md = self.bus.get_object (self.conn.bus_name, md_path) + md.Accept(self.context.get_audio_md_dbus(self.remote_handle)) + self.q.expect_many( + EventPattern('dbus-signal', signal='MediaDescriptionOfferDone'), + EventPattern('dbus-signal', signal='LocalMediaDescriptionChanged'), + EventPattern('dbus-signal', signal='RemoteMediaDescriptionsChanged')) + + content.stream.Media.CompleteReceivingStateChange( + cs.CALL_STREAM_FLOW_STATE_STARTED) + + reinvite_event, _ = self.q.expect_many( + EventPattern('sip-invite'), + EventPattern('dbus-signal', signal='ReceivingStateChanged', + args=[cs.CALL_STREAM_FLOW_STATE_STARTED], + path=content.stream.__dbus_object_path__)) + + medias = self.medias + [('audio', None)] + + self.context.check_call_sdp(reinvite_event.sip_message.body, + medias) + self.context.accept(reinvite_event.sip_message) + + return calltest.CallTest.during_call(self) + + + + +if __name__ == '__main__': + calltest.run(klass=AddRemoveContent) + diff --git a/tests/twisted/voip/calltest.py b/tests/twisted/voip/calltest.py index 14b9fc8..1d130d2 100644 --- a/tests/twisted/voip/calltest.py +++ b/tests/twisted/voip/calltest.py @@ -118,8 +118,12 @@ class CallTest: smedia_props = content.stream.Properties.GetAll( cs.CALL_STREAM_IFACE_MEDIA) assertEquals(cs.CALL_SENDING_STATE_NONE, smedia_props['SendingState']) - assertEquals(cs.CALL_SENDING_STATE_NONE, - smedia_props['ReceivingState']) + if initial: + assertEquals(cs.CALL_SENDING_STATE_NONE, + smedia_props['ReceivingState']) + else: + assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, + smedia_props['ReceivingState']) assertEquals(cs.CALL_STREAM_TRANSPORT_RAW_UDP, smedia_props['Transport']) assertEquals([], smedia_props['LocalCandidates']) @@ -138,7 +142,12 @@ class CallTest: else: assert False - def __add_content(self, content_path, initial): + def add_content(self, content_path, initial, incoming = None): + + if initial: + incoming = self.incoming + else: + assert incoming is not None content = self.bus.get_object (self.conn.bus_name, content_path) @@ -164,7 +173,7 @@ class CallTest: cmedia_props = content.GetAll(cs.CALL_CONTENT_IFACE_MEDIA) assertLength(0, cmedia_props['RemoteMediaDescriptions']) assertLength(0, cmedia_props['LocalMediaDescriptions']) - if self.incoming: + if incoming: assertNotEquals('/', cmedia_props['MediaDescriptionOffer'][0]) else: assertNotEquals('/', cmedia_props['MediaDescriptionOffer'][0]) @@ -176,7 +185,7 @@ class CallTest: self.__add_stream(content, content_props['Streams'][0], initial) - if self.incoming: + if incoming: md = self.bus.get_object (self.conn.bus_name, cmedia_props['MediaDescriptionOffer'][0]) md.Accept(self.context.get_audio_md_dbus(self.remote_handle)) @@ -189,10 +198,7 @@ class CallTest: assertEquals([], o[0].args[1]) self.connect_endpoint(content, o[0].args[0][0]) - - - - + return content def check_call_properties(self, call_props): if self.incoming: @@ -247,7 +253,7 @@ class CallTest: call_props = self.chan.Properties.GetAll(cs.CHANNEL_TYPE_CALL) self.check_call_properties(call_props) for c in call_props['Contents']: - self.__add_content(c, True) + self.add_content(c, True) if self.incoming: o = self.q.expect('dbus-signal', signal='CallStateChanged') |