summaryrefslogtreecommitdiff
path: root/rakia/media-session.c
diff options
context:
space:
mode:
authorMikhail Zabaluev <mikhail.zabaluev@nokia.com>2011-09-05 11:01:37 +0300
committerMikhail Zabaluev <mikhail.zabaluev@nokia.com>2011-09-05 11:01:37 +0300
commit6acdc05cf49cd03a1ec8058eae5a4f2d043323e9 (patch)
treec50d90b0d852fd3686fe0944d20bef9dd338fbab /rakia/media-session.c
parentcf94024c49bc64ca31961cb5895249ce0dc57048 (diff)
parentcb9453be492f28cf7b12c53f10b639ee9c56ed0f (diff)
Merge branch 'master' into debug-lite
Diffstat (limited to 'rakia/media-session.c')
-rw-r--r--rakia/media-session.c214
1 files changed, 125 insertions, 89 deletions
diff --git a/rakia/media-session.c b/rakia/media-session.c
index 10e5e44..a78b3da 100644
--- a/rakia/media-session.c
+++ b/rakia/media-session.c
@@ -70,6 +70,7 @@ G_DEFINE_TYPE_WITH_CODE(RakiaMediaSession,
enum
{
SIG_STATE_CHANGED,
+ SIG_DTMF_READY,
SIG_LAST_SIGNAL
};
@@ -154,10 +155,12 @@ struct _RakiaMediaSessionPrivate
su_home_t *backup_home; /* Sofia memory home for previous generation remote SDP session*/
sdp_session_t *remote_sdp; /* last received remote session */
sdp_session_t *backup_remote_sdp; /* previous remote session */
+ gchar *local_sdp; /* local session as SDP string */
GPtrArray *streams;
gboolean remote_initiated; /*< session is remotely intiated */
gboolean accepted; /*< session has been locally accepted for use */
gboolean se_ready; /*< connection established with stream-engine */
+ gboolean audio_connected; /*< an audio stream has reached connected state */
gboolean pending_offer; /*< local media have been changed, but a re-INVITE is pending */
gboolean dispose_has_run;
};
@@ -188,7 +191,7 @@ static void priv_zap_event (RakiaMediaSession *self);
static void rakia_media_session_init (RakiaMediaSession *self)
{
- RakiaMediaSessionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE ((self),
+ RakiaMediaSessionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
RAKIA_TYPE_MEDIA_SESSION, RakiaMediaSessionPrivate);
self->priv = priv;
@@ -453,6 +456,14 @@ rakia_media_session_class_init (RakiaMediaSessionClass *klass)
NULL, NULL,
_rakia_marshal_VOID__UINT_UINT,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+
+ signals[SIG_DTMF_READY] =
+ g_signal_new ("dtmf-ready",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
}
static void
@@ -508,6 +519,7 @@ rakia_media_session_finalize (GObject *object)
if (priv->backup_home != NULL)
su_home_unref (priv->backup_home);
+ g_free (priv->local_sdp);
g_free (priv->remote_ptime);
g_free (priv->remote_max_ptime);
g_free (priv->local_ip_address);
@@ -1105,6 +1117,10 @@ rakia_media_session_accept (RakiaMediaSession *self)
/* Will change session state to active when streams are ready */
priv_request_response_step (self);
+
+ /* Can play the DTMF dialstring if an audio stream is connected */
+ if (priv->audio_connected)
+ g_signal_emit (self, signals[SIG_DTMF_READY], 0);
}
void
@@ -1367,54 +1383,68 @@ rakia_media_session_request_hold (RakiaMediaSession *self,
}
gboolean
-rakia_media_session_start_telephony_event (RakiaMediaSession *self,
- guint stream_id,
- guchar event,
- GError **error)
+rakia_media_session_has_media (RakiaMediaSession *self,
+ TpMediaStreamType type)
{
+ RakiaMediaSessionPrivate *priv = RAKIA_MEDIA_SESSION_GET_PRIVATE (self);
RakiaMediaStream *stream;
+ guint i;
- stream = rakia_media_session_get_stream (self, stream_id, error);
- if (stream == NULL)
- return FALSE;
-
- if (rakia_media_stream_get_media_type (stream) != TP_MEDIA_STREAM_TYPE_AUDIO)
+ for (i = 0; i < priv->streams->len; i++)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "non-audio stream %u does not support telephony events", stream_id);
- return FALSE;
+ stream = g_ptr_array_index(priv->streams, i);
+ if (stream == NULL)
+ continue;
+ if (rakia_media_stream_get_media_type (stream) == type)
+ return TRUE;
}
- DEBUG("starting telephony event %u on stream %u", (guint) event, stream_id);
-
- rakia_media_stream_start_telephony_event (stream, event);
-
- return TRUE;
+ return FALSE;
}
-gboolean
-rakia_media_session_stop_telephony_event (RakiaMediaSession *self,
- guint stream_id,
- GError **error)
+void
+rakia_media_session_start_telephony_event (RakiaMediaSession *self,
+ guchar event)
{
+ RakiaMediaSessionPrivate *priv = RAKIA_MEDIA_SESSION_GET_PRIVATE (self);
RakiaMediaStream *stream;
+ guint i;
- stream = rakia_media_session_get_stream (self, stream_id, error);
- if (stream == NULL)
- return FALSE;
-
- if (rakia_media_stream_get_media_type (stream) != TP_MEDIA_STREAM_TYPE_AUDIO)
+ for (i = 0; i < priv->streams->len; i++)
{
- g_set_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
- "non-audio stream %u does not support telephony events; spurious use of the stop event?", stream_id);
- return FALSE;
+ stream = g_ptr_array_index(priv->streams, i);
+ if (stream == NULL)
+ continue;
+ if (rakia_media_stream_get_media_type (stream)
+ != TP_MEDIA_STREAM_TYPE_AUDIO)
+ continue;
+
+ DEBUG("starting telephony event %u on stream %u", (guint) event, i);
+
+ rakia_media_stream_start_telephony_event (stream, event);
}
+}
- DEBUG("stopping the telephony event on stream %u", stream_id);
+void
+rakia_media_session_stop_telephony_event (RakiaMediaSession *self)
+{
+ RakiaMediaSessionPrivate *priv = RAKIA_MEDIA_SESSION_GET_PRIVATE (self);
+ RakiaMediaStream *stream;
+ guint i;
+
+ for (i = 0; i < priv->streams->len; i++)
+ {
+ stream = g_ptr_array_index(priv->streams, i);
+ if (stream == NULL)
+ continue;
+ if (rakia_media_stream_get_media_type (stream)
+ != TP_MEDIA_STREAM_TYPE_AUDIO)
+ continue;
- rakia_media_stream_stop_telephony_event (stream);
+ DEBUG("stopping the telephony event on stream %u", i);
- return TRUE;
+ rakia_media_stream_stop_telephony_event (stream);
+ }
}
gint
@@ -1742,17 +1772,18 @@ priv_session_rollback (RakiaMediaSession *session)
rakia_media_session_change_state (session, RAKIA_MEDIA_SESSION_STATE_ACTIVE);
}
-static gboolean
-priv_session_local_sdp (RakiaMediaSession *session,
- GString *user_sdp,
- gboolean authoritative)
+static GString *
+priv_session_generate_sdp (RakiaMediaSession *session,
+ gboolean authoritative)
{
RakiaMediaSessionPrivate *priv = RAKIA_MEDIA_SESSION_GET_PRIVATE (session);
- gboolean has_supported_media = FALSE;
+ GString *user_sdp;
guint len;
guint i;
- g_return_val_if_fail (priv->local_non_ready == 0, FALSE);
+ g_return_val_if_fail (priv->local_non_ready == 0, NULL);
+
+ user_sdp = g_string_new ("v=0\r\n");
len = priv->streams->len;
if (!authoritative && len > priv->remote_stream_count)
@@ -1761,24 +1792,16 @@ priv_session_local_sdp (RakiaMediaSession *session,
DEBUG("clamped response to %u streams seen in the offer", len);
}
- g_string_append (user_sdp, "v=0\r\n");
-
for (i = 0; i < len; i++)
{
RakiaMediaStream *stream = g_ptr_array_index (priv->streams, i);
if (stream)
- {
- user_sdp = g_string_append (user_sdp,
- rakia_media_stream_local_sdp (stream));
- has_supported_media = TRUE;
- }
+ rakia_media_stream_generate_sdp (stream, user_sdp);
else
- {
- user_sdp = g_string_append (user_sdp, "m=audio 0 RTP/AVP 0\r\n");
- }
+ g_string_append (user_sdp, "m=audio 0 RTP/AVP 0\r\n");
}
- return has_supported_media;
+ return user_sdp;
}
static void
@@ -1791,16 +1814,23 @@ priv_session_invite (RakiaMediaSession *session, gboolean reinvite)
g_return_if_fail (priv->nua_op != NULL);
- user_sdp = g_string_new (NULL);
+ user_sdp = priv_session_generate_sdp (session, TRUE);
+
+ g_return_if_fail (user_sdp != NULL);
- if (priv_session_local_sdp (session, user_sdp, TRUE))
+ if (!reinvite
+ || priv->state == RAKIA_MEDIA_SESSION_STATE_REINVITE_PENDING
+ || tp_strdiff (priv->local_sdp, user_sdp->str))
{
+ g_free (priv->local_sdp);
+ priv->local_sdp = g_string_free (user_sdp, FALSE);
+
/* We need to be prepared to receive media right after the
* offer is sent, so we must set the streams to playing */
priv_session_set_streams_playing (session, TRUE);
nua_invite (priv->nua_op,
- SOATAG_USER_SDP_STR(user_sdp->str),
+ SOATAG_USER_SDP_STR(priv->local_sdp),
SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE),
SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL),
NUTAG_AUTOANSWER(0),
@@ -1815,53 +1845,46 @@ priv_session_invite (RakiaMediaSession *session, gboolean reinvite)
: RAKIA_MEDIA_SESSION_STATE_INVITE_SENT);
}
else
- WARNING ("cannot send a valid SDP offer, are there no streams?");
-
- g_string_free (user_sdp, TRUE);
+ {
+ DEBUG("SDP unchanged, not sending a re-INVITE");
+ g_string_free (user_sdp, TRUE);
+ }
}
static void
priv_session_respond (RakiaMediaSession *session)
{
RakiaMediaSessionPrivate *priv = RAKIA_MEDIA_SESSION_GET_PRIVATE (session);
- GString *user_sdp;
+ msg_t *msg;
g_return_if_fail (priv->nua_op != NULL);
- user_sdp = g_string_new (NULL);
-
- if (priv_session_local_sdp (session, user_sdp, FALSE))
- {
- msg_t *msg;
+ {
+ GString *user_sdp = priv_session_generate_sdp (session, FALSE);
- /* We need to be prepared to receive media right after the
- * answer is sent, so we must set the streams to playing */
- priv_session_set_streams_playing (session, TRUE);
+ g_free (priv->local_sdp);
+ priv->local_sdp = g_string_free (user_sdp, FALSE);
+ }
- msg = (priv->saved_event[0])
- ? nua_saved_event_request (priv->saved_event) : NULL;
+ /* We need to be prepared to receive media right after the
+ * answer is sent, so we must set the streams to playing */
+ priv_session_set_streams_playing (session, TRUE);
- nua_respond (priv->nua_op, SIP_200_OK,
- TAG_IF(msg, NUTAG_WITH(msg)),
- SOATAG_USER_SDP_STR (user_sdp->str),
- SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE),
- SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL),
- NUTAG_AUTOANSWER(0),
- TAG_END());
+ msg = (priv->saved_event[0])
+ ? nua_saved_event_request (priv->saved_event) : NULL;
- if (priv->saved_event[0])
- nua_destroy_event (priv->saved_event);
+ nua_respond (priv->nua_op, SIP_200_OK,
+ TAG_IF(msg, NUTAG_WITH(msg)),
+ SOATAG_USER_SDP_STR(priv->local_sdp),
+ SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE),
+ SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL),
+ NUTAG_AUTOANSWER(0),
+ TAG_END());
- rakia_media_session_change_state (session, RAKIA_MEDIA_SESSION_STATE_ACTIVE);
- }
- else
- {
- WARNING ("cannot respond with a valid SDP answer, were all streams closed?");
-
- priv_session_rollback (session);
- }
+ if (priv->saved_event[0])
+ nua_destroy_event (priv->saved_event);
- g_string_free (user_sdp, TRUE);
+ rakia_media_session_change_state (session, RAKIA_MEDIA_SESSION_STATE_ACTIVE);
}
static gboolean
@@ -2021,12 +2044,25 @@ static void priv_stream_supported_codecs_cb (RakiaMediaStream *stream,
static void
priv_stream_state_changed_cb (RakiaMediaStream *stream,
guint state,
- RakiaMediaChannel *channel)
+ RakiaMediaSession *session)
{
- g_assert (RAKIA_IS_MEDIA_CHANNEL (channel));
+ RakiaMediaSessionPrivate *priv = session->priv;
+
tp_svc_channel_type_streamed_media_emit_stream_state_changed(
- channel,
+ priv->channel,
rakia_media_stream_get_id (stream), state);
+
+ /* Check if DTMF can now be played */
+ if (!priv->audio_connected
+ && state == TP_MEDIA_STREAM_STATE_CONNECTED
+ && rakia_media_stream_get_media_type (stream)
+ == TP_MEDIA_STREAM_TYPE_AUDIO)
+ {
+ priv->audio_connected = TRUE;
+
+ if (priv->accepted)
+ g_signal_emit (session, signals[SIG_DTMF_READY], 0);
+ }
}
static void
@@ -2149,7 +2185,7 @@ rakia_media_session_add_stream (RakiaMediaSession *self,
self);
g_signal_connect (stream, "state-changed",
G_CALLBACK (priv_stream_state_changed_cb),
- priv->channel);
+ self);
g_signal_connect (stream, "direction-changed",
G_CALLBACK (priv_stream_direction_changed_cb),
priv->channel);