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