diff --git a/src/dcall.c b/src/dcall.c index c719be1..ade1a1c 100644 --- a/src/dcall.c +++ b/src/dcall.c @@ -15,6 +15,7 @@ struct dcall_elements { char *remote_host, *audio_tap, *audio_sink, *audio_file, *gstreamer_log_path; int remote_port, latency; guint64 grtppktlost; + GMainLoop *loop; }; int create_rx_chain(struct dcall_elements* de) { @@ -65,9 +66,56 @@ int create_rx_chain(struct dcall_elements* de) { return 0; } +static void uridecodebin_newpad (GstElement *src, GstPad *new_pad, gpointer data) { + struct dcall_elements *de = data; + GstPad *sink_pad = gst_element_get_static_pad (de->tx_audioconvert, "sink"); + GstPadLinkReturn ret; + GstCaps *new_pad_caps = NULL; + GstStructure *new_pad_struct = NULL; + const gchar *new_pad_type = NULL; + + g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (new_pad), GST_ELEMENT_NAME (src)); + + /* If our converter is already linked, we have nothing to do here */ + if (gst_pad_is_linked (sink_pad)) { + g_print ("We are already linked. Ignoring.\n"); + goto exit; + } + + /* Check the new pad's type */ + new_pad_caps = gst_pad_get_current_caps (new_pad); + new_pad_struct = gst_caps_get_structure (new_pad_caps, 0); + new_pad_type = gst_structure_get_name (new_pad_struct); + if (!g_str_has_prefix (new_pad_type, "audio/x-raw")) { + g_print ("It has type '%s' which is not raw audio. Ignoring.\n", new_pad_type); + goto exit; + } + + /* Attempt the link */ + ret = gst_pad_link (new_pad, sink_pad); + if (GST_PAD_LINK_FAILED (ret)) { + g_print ("Type is '%s' but link failed.\n", new_pad_type); + } else { + g_print ("Link succeeded (type '%s').\n", new_pad_type); + } + +exit: + /* Unreference the new pad's caps, if we got them */ + if (new_pad_caps != NULL) + gst_caps_unref (new_pad_caps); + + /* Unreference the sink pad */ + gst_object_unref (sink_pad); +} + +static void uridecodebin_drained (GstElement *src, gpointer data) { + struct dcall_elements *de = data; + g_main_loop_quit (de->loop); +} + int create_tx_chain(struct dcall_elements* de) { de->tx_pulse = gst_element_factory_make("pulsesrc", "tx-pulse"); - de->tx_filesrc = gst_element_factory_make("filesrc", "tx-filesrc"); + de->tx_filesrc = gst_element_factory_make("uridecodebin", "tx-filesrc"); de->tx_mpegaudioparse = gst_element_factory_make("mpegaudioparse", "tx-mpegaudioparse"); de->tx_mpgaudiodec = gst_element_factory_make("mpg123audiodec", "tx-mpgaudiodec"); de->tx_audioconvert = gst_element_factory_make("audioconvert", "tx-audioconvert"); @@ -107,14 +155,16 @@ int create_tx_chain(struct dcall_elements* de) { g_object_set (de->tx_pulse, "stream-properties", props, NULL); gst_structure_free (props); - g_object_set(de->tx_filesrc, "location", de->audio_file, NULL); + g_object_set(de->tx_filesrc, "uri", de->audio_file, NULL); if (strcmp(de->audio_tap, "pulsesrc") == 0) { gst_bin_add_many(GST_BIN(de->pipeline), de->tx_pulse, de->tx_echocancel, de->tx_queue, de->tx_resample, de->tx_opusenc, de->tx_pay, de->tx_sink, NULL); gst_element_link_many(de->tx_pulse, de->tx_resample, de->tx_echocancel, de->tx_queue, de->tx_opusenc, de->tx_pay, de->tx_sink, NULL); } else if (strcmp(de->audio_tap, "filesrc") == 0) { gst_bin_add_many(GST_BIN(de->pipeline), de->tx_filesrc, de->tx_mpegaudioparse, de->tx_mpgaudiodec, de->tx_audioconvert, de->tx_queue, de->tx_resample, de->tx_opusenc, de->tx_pay, de->tx_sink, NULL); - gst_element_link_many(de->tx_filesrc, de->tx_mpegaudioparse, de->tx_mpgaudiodec, de->tx_audioconvert, de->tx_resample, de->tx_queue, de->tx_opusenc, de->tx_pay, de->tx_sink, NULL); + gst_element_link_many(de->tx_audioconvert, de->tx_resample, de->tx_queue, de->tx_opusenc, de->tx_pay, de->tx_sink, NULL); + g_signal_connect (de->tx_filesrc, "pad-added", G_CALLBACK (uridecodebin_newpad), de); + g_signal_connect (de->tx_filesrc, "drained", G_CALLBACK(uridecodebin_drained), de); } else { fprintf(stderr, "Wrong audio tap %s, exiting...\n", de->audio_tap); exit(EXIT_FAILURE); @@ -165,7 +215,8 @@ gboolean stop_handler(gpointer user_data) { } int main(int argc, char *argv[]) { - GMainLoop *loop; + + GstBus *bus; struct dcall_elements de = { .audio_file = "voice.mp3", .gstreamer_log_path = "dcall.log", @@ -213,7 +264,7 @@ int main(int argc, char *argv[]) { setenv("GST_DEBUG", "3,opusdec:5", 0); gst_init (&argc, &argv); - loop = g_main_loop_new (NULL, FALSE); + de.loop = g_main_loop_new (NULL, FALSE); de.pipeline = gst_pipeline_new ("pipeline"); if (!de.pipeline) { @@ -226,11 +277,11 @@ int main(int argc, char *argv[]) { gst_element_set_state (de.pipeline, GST_STATE_PLAYING); - g_unix_signal_add (SIGTERM, stop_handler, loop); - g_unix_signal_add (SIGINT, stop_handler, loop); + g_unix_signal_add (SIGTERM, stop_handler, de.loop); + g_unix_signal_add (SIGINT, stop_handler, de.loop); g_print ("Running...\n"); - g_main_loop_run (loop); + g_main_loop_run (de.loop); g_print ("Main loop stopped...\n"); @@ -247,7 +298,7 @@ int main(int argc, char *argv[]) { gst_element_set_state (de.pipeline, GST_STATE_NULL); gst_object_unref (GST_OBJECT (de.pipeline)); - g_main_loop_unref (loop); + g_main_loop_unref (de.loop); return 0; }