summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier CrĂȘte <olivier.crete@collabora.com>2012-03-02 19:48:01 -0500
committerOlivier CrĂȘte <olivier.crete@collabora.com>2012-03-02 19:48:01 -0500
commit20dbc5534e6e4df88717d83a3c070f1377885560 (patch)
tree355c25d5607ea45178daf8f71e645f87508aaaaa
parentaa458fd5de4857e6b6d6995916295f56b2d10855 (diff)
Fix the cases when a media is removed and then re-added
Also simplify the add_media function a bit
-rw-r--r--rakia/call-channel.c6
-rw-r--r--rakia/sip-session.c111
-rw-r--r--rakia/sip-session.h3
3 files changed, 89 insertions, 31 deletions
diff --git a/rakia/call-channel.c b/rakia/call-channel.c
index 5caecb2..23de0cf 100644
--- a/rakia/call-channel.c
+++ b/rakia/call-channel.c
@@ -227,12 +227,12 @@ rakia_call_channel_constructed (GObject *obj)
if (tp_base_call_channel_has_initial_audio (bcc, &initial_audio_name))
rakia_sip_session_add_media (self->priv->session,
TP_MEDIA_STREAM_TYPE_AUDIO, initial_audio_name,
- RAKIA_DIRECTION_BIDIRECTIONAL, TRUE);
+ RAKIA_DIRECTION_BIDIRECTIONAL);
if (tp_base_call_channel_has_initial_video (bcc, &initial_video_name))
rakia_sip_session_add_media (self->priv->session,
TP_MEDIA_STREAM_TYPE_VIDEO, initial_video_name,
- RAKIA_DIRECTION_BIDIRECTIONAL, TRUE);
+ RAKIA_DIRECTION_BIDIRECTIONAL);
actor = tp_base_channel_get_self_handle (bc);
reason = TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED;
@@ -379,7 +379,7 @@ rakia_call_channel_add_content (
RakiaSipMedia *media;
media = rakia_sip_session_add_media (priv->session,
- type, name, initial_direction, TRUE);
+ type, name, initial_direction);
content = rakia_call_channel_get_content_by_media (self, media);
diff --git a/rakia/sip-session.c b/rakia/sip-session.c
index 84e1d14..7284625 100644
--- a/rakia/sip-session.c
+++ b/rakia/sip-session.c
@@ -870,19 +870,23 @@ rakia_sip_session_media_changed (RakiaSipSession *self)
}
-RakiaSipMedia*
-rakia_sip_session_add_media (RakiaSipSession *self,
+static RakiaSipMedia *
+rakia_sip_session_add_media_internal (RakiaSipSession *self,
TpMediaStreamType media_type,
const gchar *name,
RakiaDirection direction,
- gboolean created_locally)
+ const sdp_media_t *sdp_media,
+ gboolean authoritative,
+ gint slot)
{
RakiaSipSessionPrivate *priv = RAKIA_SIP_SESSION_GET_PRIVATE (self);
RakiaSipMedia *media = NULL;
+ gboolean created_locally = (sdp_media == NULL);
SESSION_DEBUG (self, "enter");
- if (rakia_sip_session_supports_media_type (media_type)) {
+ if ((!sdp_media || !sdp_media->m_rejected) &&
+ rakia_sip_session_supports_media_type (media_type)) {
media = rakia_sip_media_new (self, media_type, name, direction,
created_locally, priv->hold_requested);
@@ -892,17 +896,53 @@ rakia_sip_session_add_media (RakiaSipSession *self,
G_CALLBACK (rakia_sip_session_media_changed), self,
G_CONNECT_SWAPPED);
- g_signal_emit (self, signals[SIG_MEDIA_ADDED], 0, media);
+ if (sdp_media == NULL ||
+ rakia_sip_media_set_remote_media (media, sdp_media, authoritative))
+ {
+ g_signal_emit (self, signals[SIG_MEDIA_ADDED], 0, media);
+ }
+ else
+ {
+ rakia_sip_session_remove_media (self, media, 488,
+ "Can not process this SDP");
+ media = NULL;
+ }
}
/* note: we add an entry even for unsupported media types */
- g_ptr_array_add (priv->medias, media);
+ if (slot >= 0)
+ {
+ if (slot < priv->medias->len)
+ {
+ g_assert (g_ptr_array_index (priv->medias, slot) == NULL);
+ g_ptr_array_index (priv->medias, slot) = media;
+ }
+ else
+ {
+ g_assert (slot == priv->medias->len);
+ g_ptr_array_add (priv->medias, media);
+ }
+ }
+ else
+ {
+ g_ptr_array_add (priv->medias, media);
+ }
SESSION_DEBUG (self, "exit");
return media;
}
+RakiaSipMedia *
+rakia_sip_session_add_media (RakiaSipSession *self,
+ TpMediaStreamType media_type,
+ const gchar *name,
+ RakiaDirection direction)
+{
+ return rakia_sip_session_add_media_internal (self, media_type, name,
+ direction, NULL, TRUE, -1);
+}
+
static void
priv_update_remote_hold (RakiaSipSession *self)
@@ -984,42 +1024,61 @@ priv_update_remote_media (RakiaSipSession *self, gboolean authoritative)
media_type = rakia_media_type (sdp_media->m_type);
- if (i >= priv->medias->len)
- media = rakia_sip_session_add_media (
- self,
- media_type,
- NULL,
- /* Don't start sending unless requested by the user */
- rakia_direction_from_remote_media (sdp_media),
- FALSE);
- else
+ if (i < priv->medias->len)
media = g_ptr_array_index(priv->medias, i);
+ /* Check if the media type has changed, if it has
+ * just replace the media with the new one.
+ */
+ if (media != NULL && rakia_sip_media_get_media_type (media) != media_type)
+ {
+ g_object_ref (media);
+ g_ptr_array_index (self->priv->medias, i) = NULL;
+ g_signal_emit (self, signals[SIG_MEDIA_REMOVED], 0, media);
+ g_object_unref (media);
+ media = NULL;
+ }
+
+ /* Add the new media if it hasn't been rejected */
+ if (media == NULL && !sdp_media->m_rejected)
+ {
+ media = rakia_sip_session_add_media_internal (
+ self,
+ media_type,
+ NULL,
+ /* Don't start sending unless requested by the user */
+ rakia_direction_from_remote_media (sdp_media) &
+ RAKIA_DIRECTION_RECEIVE,
+ sdp_media, authoritative, i);
+
+ if (media != NULL)
+ has_supported_media = TRUE;
+ continue;
+ }
+
/* note: it is ok for the media to be NULL (unsupported media type) */
if (media == NULL)
continue;
SESSION_DEBUG (self, "setting remote SDP for media %u", i);
+ /* Remove rejected medias */
if (sdp_media->m_rejected)
{
SESSION_DEBUG (self, "the media has been rejected, closing");
+ rakia_sip_session_remove_media (self, media, 488,
+ "Can not process this media type");
+ continue;
}
- else if (rakia_sip_media_get_media_type (media) != media_type)
- {
- /* XXX: close this media and create a new one in its place? */
- WARNING ("The peer has changed the media type, don't know what to do");
- }
- else if (rakia_sip_media_set_remote_media (media, sdp_media,
+
+ if (!rakia_sip_media_set_remote_media (media, sdp_media,
authoritative))
{
- has_supported_media = TRUE;
+ rakia_sip_session_remove_media (self, media, 488,
+ "Can not process this media type");
continue;
}
-
- /* There have been problems with the media update, kill the media */
- rakia_sip_session_remove_media (self, media, 488,
- "Can not process this media type");
+ has_supported_media = TRUE;
}
g_assert(sdp_media == NULL);
g_assert(i <= priv->medias->len);
diff --git a/rakia/sip-session.h b/rakia/sip-session.h
index 7ab4cb0..c56ccad 100644
--- a/rakia/sip-session.h
+++ b/rakia/sip-session.h
@@ -96,8 +96,7 @@ RakiaSipSessionState rakia_sip_session_get_state (RakiaSipSession *session);
RakiaSipMedia* rakia_sip_session_add_media (RakiaSipSession *self,
TpMediaStreamType media_type,
const gchar *name,
- RakiaDirection direction,
- gboolean created_locally);
+ RakiaDirection direction);
gboolean rakia_sip_session_remove_media (RakiaSipSession *self,
RakiaSipMedia *media,