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