static gboolean start_stop_sending_dtmf (gpointer data) { GstState state; GstStateChangeReturn ret; if (!dat || !dat->pipeline || !dat->session) return TRUE; ret = gst_element_get_state (dat->pipeline, &state, NULL, 0); ts_fail_if (ret == GST_STATE_CHANGE_FAILURE); if (ret != GST_STATE_CHANGE_SUCCESS || state != GST_STATE_PLAYING) return TRUE; if (!ready_to_send) return TRUE; if (sending) { ts_fail_unless (fs_session_stop_telephony_event (dat->session, method), "Could not stop telephony event"); sending = FALSE; ts_fail_unless (received == TRUE, "Did not receive any buffer for digit %d", digit); if (digit >= FS_DTMF_EVENT_D && !change_codec) { g_main_loop_quit (loop); return FALSE; } } else { if (digit >= FS_DTMF_EVENT_D) { digit = 0; dtmf_id++; ready_to_send = FALSE; change_codec = FALSE; set_codecs (dat, stream); return TRUE; } digit++; received = FALSE; ts_fail_unless (fs_session_start_telephony_event (dat->session, digit, digit, method), "Could not start telephony event"); sending = TRUE; } return TRUE; }
gboolean skype_audio_stream_send_dtmf (SkypeAudioStream *self, int event, int type) { SkypeAudioStreamPrivate *priv = self->priv; FsuSession *session; FsSession *fssession; FsDTMFMethod method; gboolean ret = TRUE; GstStructure *structure; GstEvent *gstevent; g_debug ("Sending telephony event: %d, type: %d", event, type); structure = gst_structure_new ("dtmf-event", "type", G_TYPE_INT, 1, "number", G_TYPE_INT, event, "volume", G_TYPE_INT, 8, "start", G_TYPE_BOOLEAN, TRUE, NULL); gstevent = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure); if (!gst_element_send_event (priv->dtmfsrc, gstevent)) g_warning ("DTMF start event wasn't applied"); structure = gst_structure_new ("dtmf-event", "type", G_TYPE_INT, 1, "number", G_TYPE_INT, event, "volume", G_TYPE_INT, 8, "start", G_TYPE_BOOLEAN, FALSE, NULL); gstevent = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, structure); if (!gst_element_send_event (priv->dtmfsrc, gstevent)) g_warning ("DTMF start event wasn't applied"); if (g_queue_is_empty (priv->event_queue)) { /* The type argument doubles as both the type of event * (RTP or in-band) as well as the PT to use if it's RTP */ if (type == SKYPE_DTMF_EVENT_TYPE_IN_BAND) { method = FS_DTMF_METHOD_IN_BAND; } else if (type == priv->last_telephony_pt) { /* Play now only if the current PT matches the desired one */ method = FS_DTMF_METHOD_RTP_RFC4733; } else { FsCodec *codec; /* Can't play the DTMF event now, queue the event and update codecs */ DTMFQueueEvent *dtmf_event = g_slice_new0 (DTMFQueueEvent); dtmf_event->event_nr = event; dtmf_event->rtp_type = type; g_queue_push_tail (priv->event_queue, dtmf_event); priv->pending_telephony_pt = type; /* Trigger a codec update */ g_object_get (self, "codec", &codec, NULL); g_object_set (self, "codec", codec, NULL); fs_codec_destroy (codec); return ret; } } else { /* Other events are pending, queue this one */ DTMFQueueEvent *dtmf_event = g_slice_new0 (DTMFQueueEvent); dtmf_event->event_nr = event; dtmf_event->rtp_type = type; g_queue_push_tail (priv->event_queue, dtmf_event); return ret; } g_object_get (priv->stream, "fsu-session", &session, NULL); if (session == NULL) { g_warning ("SendDTMF: session == NULL"); return FALSE; } g_object_get (session, "fs-session", &fssession, NULL); g_object_unref (session); if (fssession == NULL) { g_warning ("SendDTMF: fssession == NULL"); return FALSE; } /* Play the event */ if (!fs_session_start_telephony_event (fssession, event, 0, method)) { g_warning ("Telephony event type not supported"); ret = FALSE; } else { fs_session_stop_telephony_event (fssession, method); } g_object_unref (fssession); return ret; }
gboolean skype_audio_stream_handle_message (SkypeBaseStream *self, GstMessage *message) { SkypeAudioStreamPrivate *priv = SKYPE_AUDIO_STREAM (self)->priv; GstStructure *structure; FsSession *session = NULL; GList *secondary_codecs = NULL; GList *iter; if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) return FALSE; structure = (GstStructure *)gst_message_get_structure (message); if (!gst_structure_has_name (structure, "farsight-send-codec-changed")) return FALSE; gst_structure_get (structure, "session", FS_TYPE_SESSION, &session, "secondary-codecs", FS_TYPE_CODEC_LIST, &secondary_codecs, NULL); /* Update the current telephony PT */ for (iter = secondary_codecs; iter != NULL; iter = g_list_next (iter)) { FsCodec *codec = (FsCodec *)iter->data; if (codec != NULL && !g_strcmp0 (codec->encoding_name, "telephone-event")) { priv->last_telephony_pt = codec->id; if (priv->pending_telephony_pt != FS_CODEC_ID_DISABLE && priv->pending_telephony_pt == priv->last_telephony_pt) priv->pending_telephony_pt = FS_CODEC_ID_DISABLE; break; } } while (!g_queue_is_empty (priv->event_queue)) { DTMFQueueEvent *event = (DTMFQueueEvent *) g_queue_pop_head (priv->event_queue); FsDTMFMethod method = FS_DTMF_METHOD_AUTO; if (event->rtp_type == SKYPE_DTMF_EVENT_TYPE_IN_BAND) { method = FS_DTMF_METHOD_IN_BAND; } else if (event->rtp_type == priv->last_telephony_pt) { method = FS_DTMF_METHOD_RTP_RFC4733; } else { /* New PT needed. Update codecs */ FsCodec *codec; g_queue_push_head (priv->event_queue, event); priv->pending_telephony_pt = event->rtp_type; /* Trigger a codec update */ g_object_get (self, "codec", &codec, NULL); g_object_set (self, "codec", codec, NULL); fs_codec_destroy (codec); break; } if (!fs_session_start_telephony_event (session, event->event_nr, 0, method)) { g_warning ("Telephony event type not supported"); g_queue_push_head (priv->event_queue, event); } else { fs_session_stop_telephony_event (session, method); } g_slice_free (DTMFQueueEvent, event); } g_object_unref (session); fs_codec_list_destroy (secondary_codecs); return TRUE; }