2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @file conversation/gnunet_gst.c
25 #include "gnunet_gst_def.h"
30 static struct GNUNET_CONFIGURATION_Handle *cfg;
34 dump_buffer(unsigned n, const unsigned char* buf)
36 const unsigned char *p, *end;
41 for (i = 0; ; i += 16)
44 for (j = 0; j < 16; j++)
46 fprintf(stderr, "%02X ", p[j]);
52 for (j = 0; j < 16; j++)
54 fprintf(stderr, "%c", isprint(p[j]) ? p[j] :
59 fprintf(stderr, "\n");
66 * load gnunet configuration
69 gg_load_configuration(GNUNET_gstData * d)
71 char *audiobackend_string;
73 cfg = GNUNET_CONFIGURATION_create();
74 GNUNET_CONFIGURATION_load(cfg, "mediahelper.conf");
76 GNUNET_CONFIGURATION_get_value_string(cfg, "MEDIAHELPER", "JACK_PP_IN", &d->jack_pp_in);
77 GNUNET_CONFIGURATION_get_value_string(cfg, "MEDIAHELPER", "JACK_PP_OUT", &d->jack_pp_out);
79 GNUNET_CONFIGURATION_get_value_string(cfg, "MEDIAHELPER", "AUDIOBACKEND", &audiobackend_string);
81 // printf("abstring: %s \n", audiobackend_string);
83 if (0 == strcasecmp(audiobackend_string, "AUTO"))
85 d->audiobackend = AUTO;
87 else if (0 == strcasecmp(audiobackend_string, "JACK"))
89 d->audiobackend = JACK;
91 else if (0 == strcasecmp(audiobackend_string, "ALSA"))
93 d->audiobackend = ALSA;
95 else if (0 == strcasecmp(audiobackend_string, "FAKE"))
97 d->audiobackend = FAKE;
99 else if (0 == strcasecmp(audiobackend_string, "TEST"))
101 d->audiobackend = TEST;
105 d->audiobackend = AUTO;
108 if (GNUNET_CONFIGURATION_get_value_yesno(cfg, "MEDIAHELPER", "REMOVESILENCE") == GNUNET_YES)
110 d->dropsilence = TRUE;
114 d->dropsilence = FALSE;
117 if (GNUNET_CONFIGURATION_get_value_yesno(cfg, "MEDIAHELPER", "NO_GN_HEADERS") == GNUNET_YES)
127 if (GNUNET_CONFIGURATION_get_value_yesno(cfg, "MEDIAHELPER", "USERTP") == GNUNET_YES)
136 // GNUNET_CONFIGURATION_write(cfg, "mediahelper.conf");
140 write_data(const char *ptr, size_t msg_size)
146 while (off < msg_size)
148 ret = write(1, &ptr[off], msg_size - off);
152 GNUNET_log_strerror(GNUNET_ERROR_TYPE_ERROR, "write");
162 on_appsink_new_sample(GstElement * element, GNUNET_gstData * d)
164 //size of message including gnunet header
172 const GstStructure *si;
178 if (gst_app_sink_is_eos(GST_APP_SINK(element)))
181 //pull sample from appsink
182 s = gst_app_sink_pull_sample(GST_APP_SINK(element));
187 if (!GST_IS_SAMPLE(s))
190 b = gst_sample_get_buffer(s);
192 GST_WARNING("caps are %" GST_PTR_FORMAT, gst_sample_get_caps(s));
196 gst_buffer_map(b, &map, GST_MAP_READ);
200 if (len > UINT16_MAX - sizeof(struct AudioMessage))
202 // this should never happen?
203 printf("GSTREAMER sample too big! \n");
205 len = UINT16_MAX - sizeof(struct AudioMessage);
208 msg_size = sizeof(struct AudioMessage) + len;
210 // copy the data into audio_message
211 GNUNET_memcpy(((char *)&(d->audio_message)[1]), map.data, len);
212 (d->audio_message)->header.size = htons((uint16_t)msg_size);
214 // write the audio_message without the gnunet headers
215 write_data((const char *)&(d->audio_message)[1], len);
217 write_data((const char *)d->audio_message, msg_size);
224 * Dump a pipeline graph
227 pl_graph(GstElement * pipeline)
230 gst_debug_bin_to_dot_file_with_ts(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "playback_helper.dot");
233 gst_debug_bin_to_dot_file_with_ts(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "record_helper.dot");
237 // load_configuration();
243 gnunet_gst_bus_call(GstBus *bus, GstMessage *msg, gpointer data)
245 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
247 switch (GST_MESSAGE_TYPE(msg))
249 case GST_MESSAGE_EOS:
250 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
255 case GST_MESSAGE_ERROR:
260 gst_message_parse_error(msg, &error, &debug);
263 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
279 /* called when pipeline changes state */
281 state_changed_cb(GstBus * bus, GstMessage * msg, GNUNET_gstData * d)
283 GstState old_state, new_state, pending_state;
285 gst_message_parse_state_changed(msg, &old_state, &new_state,
289 case GST_STATE_READY:
290 // printf("ready.... \n");
291 //pl_graph(GST_ELEMENT(d->pipeline));
294 case GST_STATE_PLAYING:
296 //GST_LOG ("caps are %" GST_PTR_FORMAT, caps);
298 // printf("Playing.... \n");
299 pl_graph(GST_ELEMENT(d->pipeline));
302 case GST_STATE_VOID_PENDING:
303 // printf("void_pending.... \n");
304 //pl_graph(GST_ELEMENT(d->pipeline));
308 // printf("null.... \n");
309 //pl_graph(GST_ELEMENT(d->pipeline));
312 case GST_STATE_PAUSED:
313 // printf("paused.... \n");
314 //pl_graph(GST_ELEMENT(d->pipeline));
320 application_cb(GstBus * bus, GstMessage * msg, GNUNET_gstData * data)
322 // printf("application cb");
327 error_cb(GstBus * bus, GstMessage * msg, GNUNET_gstData * data)
329 // printf("error cb");
334 eos_cb(GstBus * bus, GstMessage * msg, GNUNET_gstData * data)
341 gg_setup_gst_bus(GNUNET_gstData * d)
345 bus = gst_element_get_bus(GST_ELEMENT(d->pipeline));
346 gst_bus_add_signal_watch(bus);
347 g_signal_connect(G_OBJECT(bus), "message::error", (GCallback)error_cb,
349 g_signal_connect(G_OBJECT(bus), "message::eos", (GCallback)eos_cb,
351 g_signal_connect(G_OBJECT(bus), "message::state-changed",
352 (GCallback)state_changed_cb, d);
353 g_signal_connect(G_OBJECT(bus), "message::application",
354 (GCallback)application_cb, d);
355 g_signal_connect(G_OBJECT(bus), "message::about-to-finish",
356 (GCallback)application_cb, d);
357 gst_object_unref(bus);
361 * take buffer from gstreamer and feed it to gnunet
365 feed_buffer_to_gnunet (GNUNET_gstData * d)
370 size_t len, msg_size;
374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pulling...\n");
375 s = gst_app_sink_pull_sample (GST_APP_SINK(d->appsink));
378 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pulled NULL\n");
381 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "...pulled!\n");
383 const GstStructure *si;
387 si = gst_sample_get_info (s);
390 si_str = gst_structure_to_string (si);
393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample %s\n", si_str);
398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with no info\n");
399 s_caps = gst_sample_get_caps (s);
402 caps_str = gst_caps_to_string (s_caps);
405 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with caps %s\n", caps_str);
410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with no caps\n");
412 b = gst_sample_get_buffer (s);
413 if (NULL == b || !gst_buffer_map (b, &m, GST_MAP_READ))
415 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got NULL buffer %p or failed to map the buffer\n", b);
416 gst_sample_unref (s);
421 if (len > UINT16_MAX - sizeof (struct AudioMessage))
424 len = UINT16_MAX - sizeof (struct AudioMessage);
426 msg_size = sizeof (struct AudioMessage) + len;
427 audio_message.header.size = htons ((uint16_t) msg_size);
430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
431 "Sending %u bytes of audio data\n", (unsigned int) msg_size);
432 for (phase = 0; phase < 2; phase++)
437 if (0 == phase && !d->pure_ogg)
439 //#ifdef DEBUG_RECORD_PURE_OGG
445 ptr = (const char *) &audio_message;
446 to_send = sizeof (audio_message);
450 ptr = (const char *) m.data;
453 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
454 "Sending %u bytes on phase %d\n", (unsigned int) to_send, phase);
455 for (offset = 0; offset < to_send; offset += ret)
457 ret = write (1, &ptr[offset], to_send - offset);
461 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
462 "Failed to write %u bytes at offset %u (total %u) in phase %d: %s\n",
463 (unsigned int) to_send - offset, (unsigned int) offset,
464 (unsigned int) (to_send + offset), phase, strerror (errno));
474 gst_buffer_unmap (b, &m);
475 gst_sample_unref (s);
481 feed_buffer_to_gst(const char *audio, size_t b_len, GNUNET_gstData * d)
487 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
488 "Feeding %u bytes to GStreamer\n",
489 (unsigned int)b_len);
491 bufspace = g_memdup(audio, b_len);
492 b = gst_buffer_new_wrapped(bufspace, b_len);
495 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
496 "Failed to wrap a buffer\n");
498 return GNUNET_SYSERR;
500 if (GST_APP_SRC(d->appsrc) == NULL)
502 flow = gst_app_src_push_buffer(GST_APP_SRC(d->appsrc), b);
503 /* They all return GNUNET_OK, because currently player stops when
504 * data stops coming. This might need to be changed for the player
505 * to also stop when pipeline breaks.
510 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
511 "Fed %u bytes to the pipeline\n",
512 (unsigned int)b_len);
515 case GST_FLOW_FLUSHING:
516 /* buffer was dropped, because pipeline state is not PAUSED or PLAYING */
517 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
518 "Dropped a buffer\n");
523 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
528 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
529 "Unexpected push result\n");
538 * debug making elements
541 gst_element_factory_make_debug(gchar *factoryname, gchar *name)
545 element = gst_element_factory_make(factoryname, name);
549 printf("\n Failed to create element - type: %s name: %s \n", factoryname, name);
561 gst_element_link_many_debug(...)
564 gst_element_link_many(argptr);
567 #define gst_element_link_many(...) \
568 gst_element_link_many_debug(__VA_ARGS__)
573 printf("linking elements failed: %s", msg);
578 * used to set properties on autoaudiosink's chosen sink
581 autoaudiosink_child_added(GstChildProxy *child_proxy,
586 if (GST_IS_AUDIO_BASE_SRC(object))
588 "buffer-time", (gint64)BUFFER_TIME,
589 "latency-time", (gint64)LATENCY_TIME,
594 * used to set properties on autoaudiosource's chosen sink
597 autoaudiosource_child_added(GstChildProxy *child_proxy, GObject *object, gchar *name, gpointer user_data)
599 if (GST_IS_AUDIO_BASE_SRC(object))
600 g_object_set(object, "buffer-time", (gint64)BUFFER_TIME, "latency-time", (gint64)LATENCY_TIME, NULL);
605 get_pipeline(GstElement *element)
609 p = GST_PIPELINE(gst_object_get_parent(GST_OBJECT(element)));
611 return GST_ELEMENT(p);
615 decoder_ogg_pad_added(GstElement *element,
620 GstElement *decoder = (GstElement *)data;
622 printf("==== ogg pad added callback \n");
623 /* We can now link this pad with the opus-decoder sink pad */
624 // pl_graph(get_pipeline(element));
625 sinkpad = gst_element_get_static_pad(decoder, "sink");
627 gst_pad_link(pad, sinkpad);
628 gst_element_link_many(element, decoder, NULL);
629 gst_object_unref(sinkpad);
634 gnunet_read(GNUNET_gstData * d)
636 char readbuf[MAXLINE];
640 ret = read(0, readbuf, sizeof(readbuf));
643 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
644 _("Read error from STDIN: %d %s\n"),
645 ret, strerror(errno));
649 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
650 "Received %d bytes of audio data\n",
654 //#ifdef DEBUG_READ_PURE_OGG
658 feed_buffer_to_gst(readbuf, ret, d);
663 GNUNET_MST_from_buffer(d->stdin_mst,
675 * @param msg message we received.
676 * @return #GNUNET_OK on success,
677 * #GNUNET_NO to stop further processing due to disconnect (no error)
678 * #GNUNET_SYSERR to stop further processing due to error
681 stdin_receiver(void *cls,
682 const struct GNUNET_MessageHeader *msg)
684 struct AudioMessage *audio;
687 printf("stdin receiver \n ");
688 dump_buffer(sizeof(msg),
689 (const unsigned char *)msg);
691 switch (ntohs(msg->type))
693 case GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO:
694 audio = (struct AudioMessage *)msg;
696 b_len = ntohs(audio->header.size) - sizeof(struct AudioMessage);
697 printf("feeding buffer to gst \n ");
698 feed_buffer_to_gst((const char *)&audio[1], b_len, cls);
702 printf("No audio message: %u \n ", ntohs(msg->type));
710 get_app(GNUNET_gstData *d, int type)
713 GstPad *pad, *ghostpad;
717 bin = GST_BIN(gst_bin_new("Gnunet appsrc"));
720 GNUNET_assert(GNUNET_OK ==
721 GNUNET_log_setup("gnunet-helper-audio-playback",
725 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
726 "Audio playback starts\n");
727 printf(" creating appsrc \n ");
728 //d->audio_message.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
730 // d->audio_message = GNUNET_malloc (UINT16_MAX);
731 // d->audio_message = (AudioMessage*)malloc(sizeof(struct AudioMessage));
732 // d->audio_message = GNUNET_malloc(sizeof(struct AudioMessage));
735 //d->audio_message.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
738 d->stdin_mst = GNUNET_MST_create(&stdin_receiver, d);
740 if (d->stdin_mst == NULL)
741 printf("stdin_mst = NULL");
743 d->appsrc = gst_element_factory_make("appsrc", "appsrc");
745 gst_bin_add_many(bin, d->appsrc, NULL);
746 // gst_element_link_many ( encoder, muxer, NULL);
748 pad = gst_element_get_static_pad(d->appsrc, "src");
749 ghostpad = gst_ghost_pad_new("src", pad);
753 bin = GST_BIN(gst_bin_new("Gnunet appsink"));
756 GNUNET_assert(GNUNET_OK ==
757 GNUNET_log_setup("gnunet-helper-audio-record",
761 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
762 "Audio source starts\n");
764 d->appsink = gst_element_factory_make("appsink", "appsink");
766 // Move this out of here!
767 d->audio_message = GNUNET_malloc(UINT16_MAX);
768 (d->audio_message)->header.type = htons(GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
769 g_object_set(G_OBJECT(d->appsink), "emit-signals", TRUE, "sync", TRUE, NULL);
771 g_signal_connect(d->appsink, "new-sample",
772 G_CALLBACK(on_appsink_new_sample), &d);
774 gst_bin_add_many(bin, d->appsink, NULL);
775 // gst_element_link_many ( encoder, muxer, NULL);
777 pad = gst_element_get_static_pad(d->appsink, "sink");
778 ghostpad = gst_ghost_pad_new("sink", pad);
781 /* set the bin pads */
782 gst_pad_set_active(ghostpad, TRUE);
783 gst_element_add_pad(GST_ELEMENT(bin), ghostpad);
785 gst_object_unref(pad);
791 get_coder(GNUNET_gstData *d, int type)
794 GstPad *srcpad, *sinkpad, *srcghostpad, *sinkghostpad;
796 GstElement *encoder, *muxer, *decoder, *demuxer, *jitterbuffer, *rtpcapsfilter;
798 if (d->usertp == TRUE)
801 * application/x-rtp, media=(string)audio, clock-rate=(int)48000, encoding-name=(string)OPUS, sprop-maxcapturerate=(string)48000, sprop-stereo=(string)0, payload=(int)96, encoding-params=(string)2, ssrc=(uint)630297634, timestamp-offset=(uint)678334141, seqnum-offset=(uint)16938 */
803 rtpcaps = gst_caps_new_simple ("application/x-rtp",
804 "media", G_TYPE_STRING, "audio",
805 "clock-rate", G_TYPE_INT, SAMPLING_RATE,
806 "encoding-name", G_TYPE_STRING, "OPUS",
807 "payload", G_TYPE_INT, 96,
808 "sprop-stereo", G_TYPE_STRING, "0",
809 "encoding-params", G_TYPE_STRING, "2",
812 rtpcaps = gst_caps_new_simple("application/x-rtp",
813 "media", G_TYPE_STRING, "audio",
814 "clock-rate", G_TYPE_INT, SAMPLING_RATE,
815 "encoding-name", G_TYPE_STRING, "OPUS",
816 "payload", G_TYPE_INT, 96,
817 "sprop-stereo", G_TYPE_STRING, "0",
818 "encoding-params", G_TYPE_STRING, "2",
822 rtpcapsfilter = gst_element_factory_make("capsfilter", "rtpcapsfilter");
824 g_object_set(G_OBJECT(rtpcapsfilter),
827 gst_caps_unref(rtpcaps);
833 bin = GST_BIN(gst_bin_new("Gnunet audioencoder"));
835 encoder = gst_element_factory_make("opusenc", "opus-encoder");
836 if (d->usertp == TRUE)
838 muxer = gst_element_factory_make("rtpopuspay", "rtp-payloader");
842 muxer = gst_element_factory_make("oggmux", "ogg-muxer");
844 g_object_set(G_OBJECT(encoder),
845 /* "bitrate", 64000, */
846 /* "bandwidth", OPUS_BANDWIDTH_FULLBAND, */
847 "inband-fec", INBAND_FEC_MODE,
848 "packet-loss-percentage", PACKET_LOSS_PERCENTAGE,
849 "max-payload-size", MAX_PAYLOAD_SIZE,
850 "audio", TRUE, /* VoIP, not audio */
851 "frame-size", OPUS_FRAME_SIZE,
854 if (d->usertp != TRUE)
856 g_object_set(G_OBJECT(muxer),
857 "max-delay", OGG_MAX_DELAY,
858 "max-page-delay", OGG_MAX_PAGE_DELAY,
862 gst_bin_add_many(bin, encoder, muxer, NULL);
863 gst_element_link_many(encoder, muxer, NULL);
864 sinkpad = gst_element_get_static_pad(encoder, "sink");
865 sinkghostpad = gst_ghost_pad_new("sink", sinkpad);
867 srcpad = gst_element_get_static_pad(muxer, "src");
868 srcghostpad = gst_ghost_pad_new("src", srcpad);
872 bin = GST_BIN(gst_bin_new("Gnunet audiodecoder"));
875 if (d->usertp == TRUE)
877 demuxer = gst_element_factory_make("rtpopusdepay", "ogg-demuxer");
878 jitterbuffer = gst_element_factory_make("rtpjitterbuffer", "rtpjitterbuffer");
882 demuxer = gst_element_factory_make("oggdemux", "ogg-demuxer");
884 decoder = gst_element_factory_make("opusdec", "opus-decoder");
886 if (d->usertp == TRUE)
888 gst_bin_add_many(bin, rtpcapsfilter, jitterbuffer, demuxer, decoder, NULL);
889 gst_element_link_many(rtpcapsfilter, jitterbuffer, demuxer, decoder, NULL);
890 sinkpad = gst_element_get_static_pad(rtpcapsfilter, "sink");
894 gst_bin_add_many(bin, demuxer, decoder, NULL);
896 g_signal_connect(demuxer,
898 G_CALLBACK(decoder_ogg_pad_added),
901 sinkpad = gst_element_get_static_pad(demuxer, "sink");
903 sinkghostpad = gst_ghost_pad_new("sink", sinkpad);
905 srcpad = gst_element_get_static_pad(decoder, "src");
906 srcghostpad = gst_ghost_pad_new("src", srcpad);
909 // add pads to the bin
910 gst_pad_set_active(sinkghostpad, TRUE);
911 gst_element_add_pad(GST_ELEMENT(bin), sinkghostpad);
913 gst_pad_set_active(srcghostpad, TRUE);
914 gst_element_add_pad(GST_ELEMENT(bin), srcghostpad);
922 get_audiobin(GNUNET_gstData *d, int type)
925 GstElement *sink, *source, *queue, *conv, *resampler, *removesilence, *filter;
926 GstPad *pad, *ghostpad;
931 bin = GST_BIN(gst_bin_new("Gnunet audiosink"));
933 /* Create all the elements */
934 if (d->dropsilence == TRUE)
936 queue = gst_element_factory_make("queue", "queue");
937 removesilence = gst_element_factory_make("removesilence", "removesilence");
940 conv = gst_element_factory_make("audioconvert", "converter");
941 resampler = gst_element_factory_make("audioresample", "resampler");
943 if (d->audiobackend == AUTO)
945 sink = gst_element_factory_make("autoaudiosink", "audiosink");
946 g_signal_connect(sink, "child-added", G_CALLBACK(autoaudiosink_child_added), NULL);
949 if (d->audiobackend == ALSA)
951 sink = gst_element_factory_make("alsaaudiosink", "audiosink");
954 if (d->audiobackend == JACK)
956 sink = gst_element_factory_make("jackaudiosink", "audiosink");
958 g_object_set(G_OBJECT(sink), "client-name", "gnunet", NULL);
960 if (g_object_class_find_property
961 (G_OBJECT_GET_CLASS(sink), "port-pattern"))
963 // char *portpattern = "system";
965 g_object_set(G_OBJECT(sink), "port-pattern", d->jack_pp_out,
970 if (d->audiobackend == FAKE)
972 sink = gst_element_factory_make("fakesink", "audiosink");
976 "buffer-time", (gint64)BUFFER_TIME,
977 "latency-time", (gint64)LATENCY_TIME,
980 if (d->dropsilence == TRUE)
982 // Do not remove silence by default
983 g_object_set(removesilence, "remove", FALSE, NULL);
984 g_object_set(queue, "max-size-buffers", 12, NULL);
986 g_signal_connect (source,
988 G_CALLBACK(appsrc_need_data),
991 g_signal_connect (source,
993 G_CALLBACK(appsrc_enough_data),
997 g_signal_connect (queue,
998 "notify::current-level-bytes",
999 G_CALLBACK(queue_current_level),
1002 g_signal_connect (queue,
1004 G_CALLBACK(queue_underrun),
1007 g_signal_connect (queue,
1009 G_CALLBACK(queue_running),
1012 g_signal_connect (queue,
1014 G_CALLBACK(queue_overrun),
1017 g_signal_connect (queue,
1019 G_CALLBACK(queue_pushing),
1028 gst_bin_add_many(bin, conv, resampler, sink, NULL);
1029 gst_element_link_many(conv, resampler, sink, NULL);
1031 if (d->dropsilence == TRUE)
1033 gst_bin_add_many(bin, queue, removesilence, NULL);
1035 if (!gst_element_link_many(queue, removesilence, conv, NULL))
1036 lf("queue, removesilence, conv ");
1038 pad = gst_element_get_static_pad(queue, "sink");
1042 pad = gst_element_get_static_pad(conv, "sink");
1045 ghostpad = gst_ghost_pad_new("sink", pad);
1051 bin = GST_BIN(gst_bin_new("Gnunet audiosource"));
1053 // source = gst_element_factory_make("audiotestsrc", "audiotestsrcbla");
1055 if (d->audiobackend == AUTO)
1057 source = gst_element_factory_make("autoaudiosrc", "audiosource");
1059 if (d->audiobackend == ALSA)
1061 source = gst_element_factory_make("alsasrc", "audiosource");
1063 if (d->audiobackend == JACK)
1065 source = gst_element_factory_make("jackaudiosrc", "audiosource");
1067 if (d->audiobackend == TEST)
1069 source = gst_element_factory_make("audiotestsrc", "audiosource");
1072 filter = gst_element_factory_make("capsfilter", "filter");
1073 conv = gst_element_factory_make("audioconvert", "converter");
1074 resampler = gst_element_factory_make("audioresample", "resampler");
1076 if (d->audiobackend == AUTO)
1078 g_signal_connect(source, "child-added", G_CALLBACK(autoaudiosource_child_added), NULL);
1082 if (GST_IS_AUDIO_BASE_SRC(source))
1083 g_object_set(source, "buffer-time", (gint64)BUFFER_TIME, "latency-time", (gint64)LATENCY_TIME, NULL);
1084 if (d->audiobackend == JACK)
1086 g_object_set(G_OBJECT(source), "client-name", "gnunet", NULL);
1087 if (g_object_class_find_property
1088 (G_OBJECT_GET_CLASS(source), "port-pattern"))
1090 char *portpattern = "moc";
1092 g_object_set(G_OBJECT(source), "port-pattern", portpattern,
1098 caps = gst_caps_new_simple("audio/x-raw",
1099 /* "format", G_TYPE_STRING, "S16LE", */
1100 /* "rate", G_TYPE_INT, SAMPLING_RATE,*/
1101 "channels", G_TYPE_INT, OPUS_CHANNELS,
1102 /* "layout", G_TYPE_STRING, "interleaved",*/
1105 g_object_set(G_OBJECT(filter),
1108 gst_caps_unref(caps);
1110 gst_bin_add_many(bin, source, filter, conv, resampler, NULL);
1111 gst_element_link_many(source, filter, conv, resampler, NULL);
1113 pad = gst_element_get_static_pad(resampler, "src");
1117 ghostpad = gst_ghost_pad_new("src", pad);
1120 /* set the bin pads */
1121 gst_pad_set_active(ghostpad, TRUE);
1122 gst_element_add_pad(GST_ELEMENT(bin), ghostpad);
1124 gst_object_unref(pad);