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