summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier CrĂȘte <olivier.crete@collabora.com>2012-02-22 16:15:45 -0500
committerOlivier CrĂȘte <olivier.crete@collabora.com>2012-02-22 16:15:45 -0500
commit92a846c32180c0ce51a4862b80b5159261d45b98 (patch)
treea10c63cb04c0c019f9626af5ea862268b3b26bd2
parent7dc9846458c8598793b6f42f839d256367ece9f8 (diff)
Make it possible to add a content to a connected call
-rw-r--r--rakia/call-content.c3
-rw-r--r--rakia/call-stream.c17
-rw-r--r--rakia/sip-media.c86
-rw-r--r--rakia/sip-media.h2
-rw-r--r--rakia/sip-session.c4
-rw-r--r--tests/twisted/Makefile.am1
-rw-r--r--tests/twisted/voip/add-remove-content.py61
-rw-r--r--tests/twisted/voip/calltest.py26
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')