uncrustify as demanded.
[oweals/gnunet.git] / src / conversation / gnunet_gst.c
1 /*
2    This file is part of GNUnet.
3    Copyright (C) 2016 GNUnet e.V.
4
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.
9
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.
14
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/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 /**
21  * @file conversation/gnunet_gst.c
22  * @brief FIXME
23  * @author Hark
24  */
25 #include "gnunet_gst_def.h"
26
27 /**
28  * Our configuration.
29  */
30 static struct GNUNET_CONFIGURATION_Handle *cfg;
31
32
33 void
34 dump_buffer(unsigned n, const unsigned char* buf)
35 {
36   const unsigned char *p, *end;
37   unsigned i, j;
38
39   end = buf + n;
40
41   for (i = 0; ; i += 16)
42     {
43       p = buf + i;
44       for (j = 0; j < 16; j++)
45         {
46           fprintf(stderr, "%02X ", p[j]);
47           if (p + j >= end)
48             goto BREAKOUT;
49         }
50       fprintf(stderr, " ");
51       p = buf + i;
52       for (j = 0; j < 16; j++)
53         {
54           fprintf(stderr, "%c", isprint(p[j]) ? p[j] :
55                   '.');
56           if (p + j >= end)
57             goto BREAKOUT;
58         }
59       fprintf(stderr, "\n");
60     }
61 BREAKOUT:
62   return;
63 }
64
65 /***
66  * load gnunet configuration
67  */
68 void
69 gg_load_configuration(GNUNET_gstData * d)
70 {
71   char *audiobackend_string;
72
73   cfg = GNUNET_CONFIGURATION_create();
74   GNUNET_CONFIGURATION_load(cfg, "mediahelper.conf");
75
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);
78
79   GNUNET_CONFIGURATION_get_value_string(cfg, "MEDIAHELPER", "AUDIOBACKEND", &audiobackend_string);
80
81   // printf("abstring: %s \n", audiobackend_string);
82
83   if (0 == strcasecmp(audiobackend_string, "AUTO"))
84     {
85       d->audiobackend = AUTO;
86     }
87   else if (0 == strcasecmp(audiobackend_string, "JACK"))
88     {
89       d->audiobackend = JACK;
90     }
91   else if (0 == strcasecmp(audiobackend_string, "ALSA"))
92     {
93       d->audiobackend = ALSA;
94     }
95   else if (0 == strcasecmp(audiobackend_string, "FAKE"))
96     {
97       d->audiobackend = FAKE;
98     }
99   else if (0 == strcasecmp(audiobackend_string, "TEST"))
100     {
101       d->audiobackend = TEST;
102     }
103   else
104     {
105       d->audiobackend = AUTO;
106     }
107
108   if (GNUNET_CONFIGURATION_get_value_yesno(cfg, "MEDIAHELPER", "REMOVESILENCE") == GNUNET_YES)
109     {
110       d->dropsilence = TRUE;
111     }
112   else
113     {
114       d->dropsilence = FALSE;
115     }
116
117   if (GNUNET_CONFIGURATION_get_value_yesno(cfg, "MEDIAHELPER", "NO_GN_HEADERS") == GNUNET_YES)
118     {
119       d->pure_ogg = TRUE;
120     }
121   else
122     {
123       d->pure_ogg = FALSE;
124     }
125
126
127   if (GNUNET_CONFIGURATION_get_value_yesno(cfg, "MEDIAHELPER", "USERTP") == GNUNET_YES)
128     {
129       d->usertp = TRUE;
130     }
131   else
132     {
133       d->usertp = FALSE;
134     }
135
136 //  GNUNET_CONFIGURATION_write(cfg, "mediahelper.conf");
137 }
138
139 static void
140 write_data(const char *ptr, size_t msg_size)
141 {
142   ssize_t ret;
143   size_t off;
144
145   off = 0;
146   while (off < msg_size)
147     {
148       ret = write(1, &ptr[off], msg_size - off);
149       if (0 >= ret)
150         {
151           if (-1 == ret)
152             GNUNET_log_strerror(GNUNET_ERROR_TYPE_ERROR, "write");
153 //      quit (2);
154         }
155       off += ret;
156     }
157 }
158
159
160
161 extern GstFlowReturn
162 on_appsink_new_sample(GstElement * element, GNUNET_gstData * d)
163 {
164   //size of message including gnunet header
165   size_t msg_size;
166
167   GstSample *s;
168   GstBuffer *b;
169   GstMapInfo map;
170
171 /*
172    const GstStructure *si;
173    char *si_str;
174    GstCaps *s_caps;
175    char *caps_str;
176  */
177
178   if (gst_app_sink_is_eos(GST_APP_SINK(element)))
179     return GST_FLOW_OK;
180
181   //pull sample from appsink
182   s = gst_app_sink_pull_sample(GST_APP_SINK(element));
183
184   if (s == NULL)
185     return GST_FLOW_OK;
186
187   if (!GST_IS_SAMPLE(s))
188     return GST_FLOW_OK;
189
190   b = gst_sample_get_buffer(s);
191
192   GST_WARNING("caps are %" GST_PTR_FORMAT, gst_sample_get_caps(s));
193
194
195
196   gst_buffer_map(b, &map, GST_MAP_READ);
197
198   size_t len;
199   len = map.size;
200   if (len > UINT16_MAX - sizeof(struct AudioMessage))
201     {
202       // this should never happen?
203       printf("GSTREAMER sample too big! \n");
204       exit(20);
205       len = UINT16_MAX - sizeof(struct AudioMessage);
206     }
207
208   msg_size = sizeof(struct AudioMessage) + len;
209
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);
213   if (d->pure_ogg)
214     // write the audio_message without the gnunet headers
215     write_data((const char *)&(d->audio_message)[1], len);
216   else
217     write_data((const char *)d->audio_message, msg_size);
218
219   gst_sample_unref(s);
220   return GST_FLOW_OK;
221 }
222
223 /***
224  * Dump a pipeline graph
225  */
226 extern void
227 pl_graph(GstElement * pipeline)
228 {
229 #ifdef IS_SPEAKER
230   gst_debug_bin_to_dot_file_with_ts(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "playback_helper.dot");
231 #endif
232 #ifdef IS_MIC
233   gst_debug_bin_to_dot_file_with_ts(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "record_helper.dot");
234 #endif
235
236
237   //  load_configuration();
238 }
239
240
241
242 extern gboolean
243 gnunet_gst_bus_call(GstBus *bus, GstMessage *msg, gpointer data)
244 {
245   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
246              "Bus message\n");
247   switch (GST_MESSAGE_TYPE(msg))
248     {
249     case GST_MESSAGE_EOS:
250       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
251                  "End of stream\n");
252       exit(10);
253       break;
254
255     case GST_MESSAGE_ERROR:
256     {
257       gchar  *debug;
258       GError *error;
259
260       gst_message_parse_error(msg, &error, &debug);
261       g_free(debug);
262
263       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
264                  "Error: %s\n",
265                  error->message);
266       g_error_free(error);
267
268       exit(10);
269       break;
270     }
271
272     default:
273       break;
274     }
275
276   return TRUE;
277 }
278
279 /* called when pipeline changes state */
280 extern void
281 state_changed_cb(GstBus * bus, GstMessage * msg, GNUNET_gstData * d)
282 {
283   GstState old_state, new_state, pending_state;
284
285   gst_message_parse_state_changed(msg, &old_state, &new_state,
286                                   &pending_state);
287   switch (new_state)
288     {
289     case GST_STATE_READY:
290 //      printf("ready.... \n");
291       //pl_graph(GST_ELEMENT(d->pipeline));
292       break;
293
294     case GST_STATE_PLAYING:
295
296       //GST_LOG ("caps are %" GST_PTR_FORMAT, caps);
297
298       //     printf("Playing.... \n");
299       pl_graph(GST_ELEMENT(d->pipeline));
300       break;
301
302     case GST_STATE_VOID_PENDING:
303       //   printf("void_pending.... \n");
304       //pl_graph(GST_ELEMENT(d->pipeline));
305       break;
306
307     case GST_STATE_NULL:
308       //  printf("null.... \n");
309       //pl_graph(GST_ELEMENT(d->pipeline));
310       break;
311
312     case GST_STATE_PAUSED:
313       //     printf("paused.... \n");
314       //pl_graph(GST_ELEMENT(d->pipeline));
315       break;
316     }
317 }
318
319 static void
320 application_cb(GstBus * bus, GstMessage * msg, GNUNET_gstData * data)
321 {
322   // printf("application cb");
323   return;
324 }
325
326 static void
327 error_cb(GstBus * bus, GstMessage * msg, GNUNET_gstData * data)
328 {
329   // printf("error cb");
330   return;
331 }
332
333 static void
334 eos_cb(GstBus * bus, GstMessage * msg, GNUNET_gstData * data)
335 {
336   // printf("eos cb");
337   return;
338 }
339
340 extern void
341 gg_setup_gst_bus(GNUNET_gstData * d)
342 {
343   GstBus *bus;
344
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,
348                    d);
349   g_signal_connect(G_OBJECT(bus), "message::eos", (GCallback)eos_cb,
350                    d);
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);
358 }
359
360 /*
361  * take buffer from gstreamer and feed it to gnunet
362  */
363 /*
364    extern int
365    feed_buffer_to_gnunet (GNUNET_gstData * d)
366    {
367    GstSample *s;
368    GstBuffer *b;
369    GstMapInfo m;
370    size_t len, msg_size;
371    const char *ptr;
372    int phase;
373
374    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pulling...\n");
375    s = gst_app_sink_pull_sample (GST_APP_SINK(d->appsink));
376    if (NULL == s)
377    {
378     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pulled NULL\n");
379     return OK;
380    }
381    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "...pulled!\n");
382
383     const GstStructure *si;
384     char *si_str;
385     GstCaps *s_caps;
386     char *caps_str;
387     si = gst_sample_get_info (s);
388     if (si)
389     {
390       si_str = gst_structure_to_string (si);
391       if (si_str)
392       {
393         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample %s\n", si_str);
394         g_free (si_str);
395       }
396     }
397     else
398       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with no info\n");
399     s_caps = gst_sample_get_caps (s);
400     if (s_caps)
401     {
402       caps_str = gst_caps_to_string (s_caps);
403       if (caps_str)
404       {
405         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with caps %s\n", caps_str);
406         g_free (caps_str);
407       }
408     }
409     else
410       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with no caps\n");
411
412    b = gst_sample_get_buffer (s);
413    if (NULL == b || !gst_buffer_map (b, &m, GST_MAP_READ))
414    {
415     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got NULL buffer %p or failed to map the buffer\n", b);
416     gst_sample_unref (s);
417     return FAIL;
418    }
419
420    len = m.size;
421    if (len > UINT16_MAX - sizeof (struct AudioMessage))
422    {
423     GNUNET_break (0);
424     len = UINT16_MAX - sizeof (struct AudioMessage);
425    }
426    msg_size = sizeof (struct AudioMessage) + len;
427    audio_message.header.size = htons ((uint16_t) msg_size);
428
429
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++)
433    {
434     size_t offset;
435     size_t to_send;
436     ssize_t ret;
437     if (0 == phase && !d->pure_ogg)
438     {
439    //#ifdef DEBUG_RECORD_PURE_OGG
440
441    //      if (d->pure_ogg)
442    //        break;
443
444    //#endif
445       ptr = (const char *) &audio_message;
446       to_send = sizeof (audio_message);
447     }
448     else
449     {
450       ptr = (const char *) m.data;
451       to_send = len;
452     }
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)
456     {
457       ret = write (1, &ptr[offset], to_send - offset);
458       if (0 >= ret)
459       {
460         if (-1 == ret)
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));
465      //   abort_send = 1;
466         return FAIL;
467       }
468     }
469
470    //   if (abort_send)
471    //   break;
472
473    }
474    gst_buffer_unmap (b, &m);
475    gst_sample_unref (s);
476    }
477  */
478
479
480 extern int
481 feed_buffer_to_gst(const char *audio, size_t b_len, GNUNET_gstData * d)
482 {
483   GstBuffer *b;
484   gchar *bufspace;
485   GstFlowReturn flow;
486
487   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
488              "Feeding %u bytes to GStreamer\n",
489              (unsigned int)b_len);
490
491   bufspace = g_memdup(audio, b_len);
492   b = gst_buffer_new_wrapped(bufspace, b_len);
493   if (NULL == b)
494     {
495       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
496                  "Failed to wrap a buffer\n");
497       g_free(bufspace);
498       return GNUNET_SYSERR;
499     }
500   if (GST_APP_SRC(d->appsrc) == NULL)
501     exit(10);
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.
506    */
507   switch (flow)
508     {
509     case GST_FLOW_OK:
510       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
511                  "Fed %u bytes to the pipeline\n",
512                  (unsigned int)b_len);
513       break;
514
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");
519       break;
520
521     case GST_FLOW_EOS:
522       /* end of stream */
523       GNUNET_log(GNUNET_ERROR_TYPE_INFO,
524                  "EOS\n");
525       break;
526
527     default:
528       GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
529                  "Unexpected push result\n");
530       break;
531     }
532   return GNUNET_OK;
533 }
534
535
536
537 /**
538  * debug making elements
539  */
540 extern GstElement *
541 gst_element_factory_make_debug(gchar *factoryname, gchar *name)
542 {
543   GstElement *element;
544
545   element = gst_element_factory_make(factoryname, name);
546
547   if (element == NULL)
548     {
549       printf("\n Failed to create element - type: %s name: %s \n", factoryname, name);
550       exit(10);
551       return element;
552     }
553   else
554     {
555       return element;
556     }
557 }
558
559 /*
560    static gboolean
561    gst_element_link_many_debug(...)
562    {
563    va_list arguments;
564    gst_element_link_many(argptr);
565    }
566
567  #define gst_element_link_many(...) \
568            gst_element_link_many_debug(__VA_ARGS__)
569  */
570 extern void
571 lf(char * msg)
572 {
573   printf("linking elements failed: %s", msg);
574   exit(10);
575 }
576
577 /***
578  * used to set properties on autoaudiosink's chosen sink
579  */
580 static void
581 autoaudiosink_child_added(GstChildProxy *child_proxy,
582                           GObject *object,
583                           gchar *name,
584                           gpointer user_data)
585 {
586   if (GST_IS_AUDIO_BASE_SRC(object))
587     g_object_set(object,
588                  "buffer-time", (gint64)BUFFER_TIME,
589                  "latency-time", (gint64)LATENCY_TIME,
590                  NULL);
591 }
592
593 /***
594  * used to set properties on autoaudiosource's chosen sink
595  */
596 static void
597 autoaudiosource_child_added(GstChildProxy *child_proxy, GObject *object, gchar *name, gpointer user_data)
598 {
599   if (GST_IS_AUDIO_BASE_SRC(object))
600     g_object_set(object, "buffer-time", (gint64)BUFFER_TIME, "latency-time", (gint64)LATENCY_TIME, NULL);
601 }
602
603
604 GstElement *
605 get_pipeline(GstElement *element)
606 {
607   GstPipeline *p;
608
609   p = GST_PIPELINE(gst_object_get_parent(GST_OBJECT(element)));
610
611   return GST_ELEMENT(p);
612 }
613
614 static void
615 decoder_ogg_pad_added(GstElement *element,
616                       GstPad *pad,
617                       gpointer data)
618 {
619   GstPad *sinkpad;
620   GstElement *decoder = (GstElement *)data;
621
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");
626
627   gst_pad_link(pad, sinkpad);
628   gst_element_link_many(element, decoder, NULL);
629   gst_object_unref(sinkpad);
630 }
631
632
633 int
634 gnunet_read(GNUNET_gstData * d)
635 {
636   char readbuf[MAXLINE];
637   int ret;
638
639   printf("read \n");
640   ret = read(0, readbuf, sizeof(readbuf));
641   if (0 > ret)
642     {
643       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
644                  _("Read error from STDIN: %d %s\n"),
645                  ret, strerror(errno));
646       return FAIL;
647     }
648   //toff += ret;
649   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
650              "Received %d bytes of audio data\n",
651              (int)ret);
652   if (0 == ret)
653     return FAIL;
654   //#ifdef DEBUG_READ_PURE_OGG
655
656   if (d->pure_ogg)
657     {
658       feed_buffer_to_gst(readbuf, ret, d);
659     }
660   else
661     {
662       //#endif
663       GNUNET_MST_from_buffer(d->stdin_mst,
664                              readbuf,
665                              ret,
666                              GNUNET_NO,
667                              GNUNET_NO);
668     }
669   return 0;
670 }
671
672 /**
673  * Message callback
674  *
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
679  */
680 static int
681 stdin_receiver(void *cls,
682                const struct GNUNET_MessageHeader *msg)
683 {
684   struct AudioMessage *audio;
685   size_t b_len;
686
687   printf("stdin receiver \n ");
688   dump_buffer(sizeof(msg),
689               (const unsigned char *)msg);
690
691   switch (ntohs(msg->type))
692     {
693     case GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO:
694       audio = (struct AudioMessage *)msg;
695
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);
699       break;
700
701     default:
702       printf("No audio message: %u \n ", ntohs(msg->type));
703       break;
704     }
705   return GNUNET_OK;
706 }
707
708
709 GstBin *
710 get_app(GNUNET_gstData *d, int type)
711 {
712   GstBin *bin;
713   GstPad *pad, *ghostpad;
714
715   if (type == SOURCE)
716     {
717       bin = GST_BIN(gst_bin_new("Gnunet appsrc"));
718
719
720       GNUNET_assert(GNUNET_OK ==
721                     GNUNET_log_setup("gnunet-helper-audio-playback",
722                                      "WARNING",
723                                      NULL));
724
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);
729
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));
733
734
735       //d->audio_message.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
736
737
738       d->stdin_mst = GNUNET_MST_create(&stdin_receiver, d);
739
740       if (d->stdin_mst == NULL)
741         printf("stdin_mst = NULL");
742
743       d->appsrc = gst_element_factory_make("appsrc", "appsrc");
744
745       gst_bin_add_many(bin, d->appsrc, NULL);
746 //    gst_element_link_many ( encoder, muxer, NULL);
747
748       pad = gst_element_get_static_pad(d->appsrc, "src");
749       ghostpad = gst_ghost_pad_new("src", pad);
750     }
751   if (type == SINK)
752     {
753       bin = GST_BIN(gst_bin_new("Gnunet appsink"));
754
755
756       GNUNET_assert(GNUNET_OK ==
757                     GNUNET_log_setup("gnunet-helper-audio-record",
758                                      "WARNING",
759                                      NULL));
760
761       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
762                  "Audio source starts\n");
763
764       d->appsink = gst_element_factory_make("appsink", "appsink");
765
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);
770
771       g_signal_connect(d->appsink, "new-sample",
772                        G_CALLBACK(on_appsink_new_sample), &d);
773
774       gst_bin_add_many(bin, d->appsink, NULL);
775 //    gst_element_link_many ( encoder, muxer, NULL);
776
777       pad = gst_element_get_static_pad(d->appsink, "sink");
778       ghostpad = gst_ghost_pad_new("sink", pad);
779     }
780
781   /* set the bin pads */
782   gst_pad_set_active(ghostpad, TRUE);
783   gst_element_add_pad(GST_ELEMENT(bin), ghostpad);
784
785   gst_object_unref(pad);
786
787   return bin;
788 }
789
790 extern GstBin *
791 get_coder(GNUNET_gstData *d, int type)
792 {
793   GstBin *bin;
794   GstPad *srcpad, *sinkpad, *srcghostpad, *sinkghostpad;
795   GstCaps *rtpcaps;
796   GstElement *encoder, *muxer, *decoder, *demuxer, *jitterbuffer, *rtpcapsfilter;
797
798   if (d->usertp == TRUE)
799     {
800       /*
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 */
802 /*
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",
810           NULL);
811  */
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",
819                                     NULL);
820
821
822       rtpcapsfilter = gst_element_factory_make("capsfilter", "rtpcapsfilter");
823
824       g_object_set(G_OBJECT(rtpcapsfilter),
825                    "caps", rtpcaps,
826                    NULL);
827       gst_caps_unref(rtpcaps);
828     }
829
830
831   if (type == ENCODER)
832     {
833       bin = GST_BIN(gst_bin_new("Gnunet audioencoder"));
834
835       encoder = gst_element_factory_make("opusenc", "opus-encoder");
836       if (d->usertp == TRUE)
837         {
838           muxer = gst_element_factory_make("rtpopuspay", "rtp-payloader");
839         }
840       else
841         {
842           muxer = gst_element_factory_make("oggmux", "ogg-muxer");
843         }
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,
852                    NULL);
853
854       if (d->usertp != TRUE)
855         {
856           g_object_set(G_OBJECT(muxer),
857                        "max-delay", OGG_MAX_DELAY,
858                        "max-page-delay", OGG_MAX_PAGE_DELAY,
859                        NULL);
860         }
861
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);
866
867       srcpad = gst_element_get_static_pad(muxer, "src");
868       srcghostpad = gst_ghost_pad_new("src", srcpad);
869     }
870   if (type == DECODER)
871     {
872       bin = GST_BIN(gst_bin_new("Gnunet audiodecoder"));
873
874       // decoder
875       if (d->usertp == TRUE)
876         {
877           demuxer = gst_element_factory_make("rtpopusdepay", "ogg-demuxer");
878           jitterbuffer = gst_element_factory_make("rtpjitterbuffer", "rtpjitterbuffer");
879         }
880       else
881         {
882           demuxer = gst_element_factory_make("oggdemux", "ogg-demuxer");
883         }
884       decoder = gst_element_factory_make("opusdec", "opus-decoder");
885
886       if (d->usertp == TRUE)
887         {
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");
891         }
892       else
893         {
894           gst_bin_add_many(bin, demuxer, decoder, NULL);
895
896           g_signal_connect(demuxer,
897                            "pad-added",
898                            G_CALLBACK(decoder_ogg_pad_added),
899                            decoder);
900
901           sinkpad = gst_element_get_static_pad(demuxer, "sink");
902         }
903       sinkghostpad = gst_ghost_pad_new("sink", sinkpad);
904
905       srcpad = gst_element_get_static_pad(decoder, "src");
906       srcghostpad = gst_ghost_pad_new("src", srcpad);
907     }
908
909   // add pads to the bin
910   gst_pad_set_active(sinkghostpad, TRUE);
911   gst_element_add_pad(GST_ELEMENT(bin), sinkghostpad);
912
913   gst_pad_set_active(srcghostpad, TRUE);
914   gst_element_add_pad(GST_ELEMENT(bin), srcghostpad);
915
916
917   return bin;
918 }
919
920
921 extern GstBin *
922 get_audiobin(GNUNET_gstData *d, int type)
923 {
924   GstBin *bin;
925   GstElement *sink, *source, *queue, *conv, *resampler, *removesilence, *filter;
926   GstPad *pad, *ghostpad;
927   GstCaps *caps;
928
929   if (type == SINK)
930     {
931       bin = GST_BIN(gst_bin_new("Gnunet audiosink"));
932
933       /* Create all the elements */
934       if (d->dropsilence == TRUE)
935         {
936           queue = gst_element_factory_make("queue", "queue");
937           removesilence = gst_element_factory_make("removesilence", "removesilence");
938         }
939
940       conv = gst_element_factory_make("audioconvert", "converter");
941       resampler = gst_element_factory_make("audioresample", "resampler");
942
943       if (d->audiobackend == AUTO)
944         {
945           sink = gst_element_factory_make("autoaudiosink", "audiosink");
946           g_signal_connect(sink, "child-added", G_CALLBACK(autoaudiosink_child_added), NULL);
947         }
948
949       if (d->audiobackend == ALSA)
950         {
951           sink = gst_element_factory_make("alsaaudiosink", "audiosink");
952         }
953
954       if (d->audiobackend == JACK)
955         {
956           sink = gst_element_factory_make("jackaudiosink", "audiosink");
957
958           g_object_set(G_OBJECT(sink), "client-name", "gnunet", NULL);
959
960           if (g_object_class_find_property
961                 (G_OBJECT_GET_CLASS(sink), "port-pattern"))
962             {
963 //        char *portpattern = "system";
964
965               g_object_set(G_OBJECT(sink), "port-pattern", d->jack_pp_out,
966                            NULL);
967             }
968         }
969
970       if (d->audiobackend == FAKE)
971         {
972           sink = gst_element_factory_make("fakesink", "audiosink");
973         }
974
975       g_object_set(sink,
976                    "buffer-time", (gint64)BUFFER_TIME,
977                    "latency-time", (gint64)LATENCY_TIME,
978                    NULL);
979
980       if (d->dropsilence == TRUE)
981         {
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);
985           /*
986              g_signal_connect (source,
987              "need-data",
988              G_CALLBACK(appsrc_need_data),
989              NULL);
990
991              g_signal_connect (source,
992              "enough-data",
993              G_CALLBACK(appsrc_enough_data),
994              NULL);
995            */
996 /*
997       g_signal_connect (queue,
998           "notify::current-level-bytes",
999           G_CALLBACK(queue_current_level),
1000           NULL);
1001
1002       g_signal_connect (queue,
1003           "underrun",
1004           G_CALLBACK(queue_underrun),
1005           NULL);
1006
1007       g_signal_connect (queue,
1008           "running",
1009           G_CALLBACK(queue_running),
1010           NULL);
1011
1012       g_signal_connect (queue,
1013           "overrun",
1014           G_CALLBACK(queue_overrun),
1015           NULL);
1016
1017       g_signal_connect (queue,
1018           "pushing",
1019           G_CALLBACK(queue_pushing),
1020           NULL);
1021  */
1022         }
1023
1024
1025
1026
1027
1028       gst_bin_add_many(bin, conv, resampler, sink, NULL);
1029       gst_element_link_many(conv, resampler, sink, NULL);
1030
1031       if (d->dropsilence == TRUE)
1032         {
1033           gst_bin_add_many(bin, queue, removesilence, NULL);
1034
1035           if (!gst_element_link_many(queue, removesilence, conv, NULL))
1036             lf("queue, removesilence, conv ");
1037
1038           pad = gst_element_get_static_pad(queue, "sink");
1039         }
1040       else
1041         {
1042           pad = gst_element_get_static_pad(conv, "sink");
1043         }
1044
1045       ghostpad = gst_ghost_pad_new("sink", pad);
1046     }
1047   else
1048     {
1049       // SOURCE
1050
1051       bin = GST_BIN(gst_bin_new("Gnunet audiosource"));
1052
1053       //    source = gst_element_factory_make("audiotestsrc", "audiotestsrcbla");
1054
1055       if (d->audiobackend == AUTO)
1056         {
1057           source = gst_element_factory_make("autoaudiosrc", "audiosource");
1058         }
1059       if (d->audiobackend == ALSA)
1060         {
1061           source = gst_element_factory_make("alsasrc", "audiosource");
1062         }
1063       if (d->audiobackend == JACK)
1064         {
1065           source = gst_element_factory_make("jackaudiosrc", "audiosource");
1066         }
1067       if (d->audiobackend == TEST)
1068         {
1069           source = gst_element_factory_make("audiotestsrc", "audiosource");
1070         }
1071
1072       filter = gst_element_factory_make("capsfilter", "filter");
1073       conv = gst_element_factory_make("audioconvert", "converter");
1074       resampler = gst_element_factory_make("audioresample", "resampler");
1075
1076       if (d->audiobackend == AUTO)
1077         {
1078           g_signal_connect(source, "child-added", G_CALLBACK(autoaudiosource_child_added), NULL);
1079         }
1080       else
1081         {
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)
1085             {
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"))
1089                 {
1090                   char *portpattern = "moc";
1091
1092                   g_object_set(G_OBJECT(source), "port-pattern", portpattern,
1093                                NULL);
1094                 }
1095             }
1096         }
1097
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",*/
1103                                  NULL);
1104
1105       g_object_set(G_OBJECT(filter),
1106                    "caps", caps,
1107                    NULL);
1108       gst_caps_unref(caps);
1109
1110       gst_bin_add_many(bin, source, filter, conv, resampler, NULL);
1111       gst_element_link_many(source, filter, conv, resampler, NULL);
1112
1113       pad = gst_element_get_static_pad(resampler, "src");
1114
1115
1116       /* pads */
1117       ghostpad = gst_ghost_pad_new("src", pad);
1118     }
1119
1120   /* set the bin pads */
1121   gst_pad_set_active(ghostpad, TRUE);
1122   gst_element_add_pad(GST_ELEMENT(bin), ghostpad);
1123
1124   gst_object_unref(pad);
1125
1126   return bin;
1127 }