diff options
author | Olivier CrĂȘte <olivier.crete@collabora.co.uk> | 2010-10-29 18:27:11 +0100 |
---|---|---|
committer | Olivier CrĂȘte <olivier.crete@collabora.co.uk> | 2011-04-07 13:59:37 -0400 |
commit | 9e6e83dc0e9cf3954db0058cc23251766299cf7c (patch) | |
tree | b5176d4924d4bd5cc0f65139f9f9bddce62dd892 | |
parent | 9caaf79d76252c1988036e8cef1f52494d86b254 (diff) |
Implement StartNamedTelephoneEvent
-rw-r--r-- | telepathy-farsight/stream.c | 179 |
1 files changed, 172 insertions, 7 deletions
diff --git a/telepathy-farsight/stream.c b/telepathy-farsight/stream.c index 4c067e6..1032601 100644 --- a/telepathy-farsight/stream.c +++ b/telepathy-farsight/stream.c @@ -73,6 +73,11 @@ G_DEFINE_TYPE (TfStream, tf_stream, G_TYPE_OBJECT); static TpMediaStreamError fserrorno_to_tperrorno (FsError fserror); +struct DtmfEvent { + gint codec_id; + guint event_id; +}; + struct _TfStreamPrivate { TfChannel *channel; @@ -107,6 +112,8 @@ struct _TfStreamPrivate TpMediaStreamState current_state; NewStreamCreatedCb *new_stream_created_cb; + + GQueue events_to_send; }; enum @@ -231,6 +238,8 @@ tf_stream_init (TfStream *self) g_static_mutex_init (&priv->mutex); priv->has_resource = TP_MEDIA_STREAM_DIRECTION_NONE; priv->current_state = TP_MEDIA_STREAM_STATE_DISCONNECTED; + + g_queue_init (&priv->events_to_send); } static void @@ -379,6 +388,7 @@ tf_stream_dispose (GObject *object) { TfStream *stream = TF_STREAM (object); TfStreamPrivate *priv = stream->priv; + gpointer data; TF_STREAM_LOCK (stream); if (stream->priv->idle_connected_id) @@ -443,6 +453,9 @@ tf_stream_dispose (GObject *object) priv->last_sent_codecs = NULL; } + while ((data = g_queue_pop_head (&priv->events_to_send))) + g_slice_free (struct DtmfEvent, data); + fs_candidate_list_destroy (priv->local_candidates); priv->local_candidates = NULL; @@ -1840,6 +1853,59 @@ start_telephony_event (TpMediaStreamHandler *proxy G_GNUC_UNUSED, WARNING (self, "sending event %u failed", event); } +static gboolean +check_codecs_for_telephone_event (TfStream *self, GList **codecs, + FsCodec *send_codec, guint codecid) +{ + GList *item = NULL; + gboolean found = FALSE; + GError *error = NULL; + + again: + + for (item = *codecs; item; item = item->next) + { + FsCodec *codec = item->data; + + if (!g_ascii_strcasecmp (codec->encoding_name, "telephone-event") && + send_codec->clock_rate == codec->clock_rate) + { + if (found) + { + *codecs = g_list_delete_link (*codecs, item); + goto again; + } + else if (codecid == (guint) codec->id) + { + return TRUE; } + else + { + codec->id = codecid; + } + } + } + + if (!found) + { + FsCodec *codec = fs_codec_new (codecid, "telephone-event", + FS_MEDIA_TYPE_AUDIO, send_codec->clock_rate); + + *codecs = g_list_append (*codecs, codec); + } + + if (!fs_stream_set_remote_codecs (self->priv->fs_stream, *codecs, &error)) + { + /* + * Call the error method with the proper thing here + */ + g_prefix_error (&error, "Codec negotiation failed for DTMF: "); + tf_stream_error (self, fserror_to_tperror (error), error->message); + g_clear_error (&error); + } + + return FALSE; +} + static void start_named_telephony_event (TpMediaStreamHandler *proxy, guchar event, @@ -1848,8 +1914,36 @@ start_named_telephony_event (TpMediaStreamHandler *proxy, GObject *object) { TfStream *self = TF_STREAM (object); + FsCodec *send_codec = NULL; + GList *codecs = NULL; + struct DtmfEvent *dtmfevent; + + g_object_get (self->priv->fs_session, + "current-send-codec", &send_codec, + "codecs", &codecs, + NULL); - WARNING (self, "Named Telephony Events not implemented"); + + if (check_codecs_for_telephone_event (self, &codecs, send_codec, codecid)) + { + DEBUG (self, "Sending named telephony event %d with pt %d", + event, codecid); + if (!fs_session_start_telephony_event (self->priv->fs_session, + event, 8, FS_DTMF_METHOD_RTP_RFC4733)) + WARNING (self, "sending event %u failed", event); + } + else + { + DEBUG (self, "Queing named telephony event %d with pt %d", + event, codecid); + dtmfevent = g_slice_new (struct DtmfEvent); + dtmfevent->codec_id = codecid; + dtmfevent->event_id = event; + g_queue_push_tail (&self->priv->events_to_send, dtmfevent); + } + + fs_codec_destroy (send_codec); + fs_codec_list_destroy (codecs); } static void @@ -2012,6 +2106,60 @@ invalidated_cb (TpMediaStreamHandler *proxy G_GNUC_UNUSED, tf_stream_shutdown (stream); } +static void +cb_fs_send_codec_changed (TfStream *self, + FsCodec *send_codec, + GList *secondary_codecs) +{ + GList *item; + gint last_event_id = -1; + struct DtmfEvent *dtmfevent; + + while ((dtmfevent = g_queue_peek_head (&self->priv->events_to_send))) + { + if (dtmfevent->codec_id != last_event_id) + { + last_event_id = -1; + for (item = secondary_codecs; item; item = item->next) + { + FsCodec *codec = item->data; + + if (!g_ascii_strcasecmp (codec->encoding_name, "telephone-event") + && codec->id == dtmfevent->codec_id) + { + last_event_id = codec->id; + goto have_id; + } + } + if (dtmfevent->codec_id != last_event_id) + { + GList *codecs = NULL; + + g_object_get (self->priv->fs_session, "codecs", &codecs, NULL); + + DEBUG (self, "Still do not have the right PT for telephony" + " events, trying to force it again"); + if (check_codecs_for_telephone_event (self, &codecs, send_codec, + dtmfevent->codec_id)) + WARNING (self, "Did not have the right pt in the secondary" + " codecs, but it was in the codec list. Ignoring for now"); + fs_codec_list_destroy (codecs); + return; + } + } + + have_id: + DEBUG (self, "Sending queued event %d with pt %d", dtmfevent->event_id, + dtmfevent->codec_id); + dtmfevent = g_queue_pop_head (&self->priv->events_to_send); + if (!fs_session_start_telephony_event (self->priv->fs_session, + dtmfevent->event_id, 8, FS_DTMF_METHOD_RTP_RFC4733)) + WARNING (self, "sending event %u failed", dtmfevent->event_id); + + g_slice_free (struct DtmfEvent, dtmfevent); + } +} + /** * tf_stream_error: * @self: a #TfStream @@ -2194,6 +2342,8 @@ _tf_stream_bus_message (TfStream *stream, FsSession *fssession; const GValue *value; FsCodec *codec = NULL; + GList *secondary_codecs = NULL; + FsCodec *objcodec = NULL; value = gst_structure_get_value (s, "session"); fssession = g_value_get_object (value); @@ -2201,15 +2351,30 @@ _tf_stream_bus_message (TfStream *stream, if (fssession != stream->priv->fs_session) return FALSE; - g_object_get (fssession, "current-send-codec", &codec, NULL); + value = gst_structure_get_value (s, "codec"); + codec = g_value_get_boxed (value); + g_object_get (fssession, "current-send-codec", &objcodec, NULL); - if (codec) + if (!fs_codec_are_equal (objcodec, codec)) { - DEBUG (stream, "Send codec changed: " FS_CODEC_FORMAT, - FS_CODEC_ARGS (codec)); - - fs_codec_destroy (codec); + fs_codec_destroy (objcodec); + return TRUE; } + + value = gst_structure_get_value (s, "secondary-codecs"); + secondary_codecs = g_value_get_boxed (value); + + + if (codec) + DEBUG (stream, "Send codec changed: " FS_CODEC_FORMAT, + FS_CODEC_ARGS (codec)); + + cb_fs_send_codec_changed (stream, codec, secondary_codecs); + + if (codec) + fs_codec_destroy (codec); + fs_codec_list_destroy (secondary_codecs); + return TRUE; } else if (gst_structure_has_name (s, "farsight-component-state-changed")) { |