aboutsummaryrefslogtreecommitdiff
path: root/src/conversation/gnunet-helper-audio-playback.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-10-02 22:13:12 +0000
committerChristian Grothoff <christian@grothoff.org>2013-10-02 22:13:12 +0000
commit3d8c72a1dc1981d866d752a3d3567830fecd0eae (patch)
treedc3949c8759052bd051e1a8b0df2255e544067a2 /src/conversation/gnunet-helper-audio-playback.c
parent517263c3f5134e5dba57a25e745cb276937602bc (diff)
downloadgnunet-3d8c72a1dc1981d866d752a3d3567830fecd0eae.tar.gz
gnunet-3d8c72a1dc1981d866d752a3d3567830fecd0eae.zip
-debugging logic
Diffstat (limited to 'src/conversation/gnunet-helper-audio-playback.c')
-rw-r--r--src/conversation/gnunet-helper-audio-playback.c267
1 files changed, 127 insertions, 140 deletions
diff --git a/src/conversation/gnunet-helper-audio-playback.c b/src/conversation/gnunet-helper-audio-playback.c
index 5fdc217f2..74571e538 100644
--- a/src/conversation/gnunet-helper-audio-playback.c
+++ b/src/conversation/gnunet-helper-audio-playback.c
@@ -22,6 +22,7 @@
22 * @brief constants for network protocols 22 * @brief constants for network protocols
23 * @author Siomon Dieterle 23 * @author Siomon Dieterle
24 * @author Andreas Fuchs 24 * @author Andreas Fuchs
25 * @author Christian Grothoff
25 */ 26 */
26#include "platform.h" 27#include "platform.h"
27#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
@@ -40,12 +41,14 @@
40 41
41#define MAXLINE 4096 42#define MAXLINE 4096
42 43
44#define SAMPLING_RATE 48000
45
43/** 46/**
44 * Pulseaudio specification. May change in the future. 47 * Pulseaudio specification. May change in the future.
45 */ 48 */
46static pa_sample_spec sample_spec = { 49static pa_sample_spec sample_spec = {
47 .format = PA_SAMPLE_FLOAT32LE, 50 .format = PA_SAMPLE_FLOAT32LE,
48 .rate = 48000, 51 .rate = SAMPLING_RATE,
49 .channels = 1 52 .channels = 1
50}; 53};
51 54
@@ -96,11 +99,6 @@ static int pcm_length;
96static int frame_size; 99static int frame_size;
97 100
98/** 101/**
99 * The sampling rate used in Pulseaudio specification
100 */
101static opus_int32 sampling_rate;
102
103/**
104 * Audio buffer 102 * Audio buffer
105 */ 103 */
106static void *buffer; 104static void *buffer;
@@ -125,19 +123,27 @@ stdin_receiver (void *cls,
125 const struct GNUNET_MessageHeader *msg) 123 const struct GNUNET_MessageHeader *msg)
126{ 124{
127 struct AudioMessage *audio; 125 struct AudioMessage *audio;
126 int ret;
128 127
129 switch (ntohs (msg->type)) 128 switch (ntohs (msg->type))
130 { 129 {
131 case GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO: 130 case GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO:
132 audio = (struct AudioMessage *) msg; 131 audio = (struct AudioMessage *) msg;
133 132
134 int len = 133 ret = opus_decode_float (dec,
135 opus_decode_float (dec, 134 (const unsigned char *) &audio[1],
136 (const unsigned char *) &audio[1], 135 ntohs (audio->header.size) - sizeof (struct AudioMessage),
137 ntohs (audio->header.size) - sizeof (struct AudioMessage), 136 pcm_buffer,
138 pcm_buffer, 137 frame_size, 0);
139 frame_size, 0); 138 if (ret < 0)
140 // FIXME: pcm_length != len??? 139 {
140 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
141 "Opus decoding failed: %d\n",
142 ret);
143 return GNUNET_OK;
144 }
145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
146 "Decoded frame\n");
141 if (pa_stream_write 147 if (pa_stream_write
142 (stream_out, (uint8_t *) pcm_buffer, pcm_length, NULL, 0, 148 (stream_out, (uint8_t *) pcm_buffer, pcm_length, NULL, 0,
143 PA_SEEK_RELATIVE) < 0) 149 PA_SEEK_RELATIVE) < 0)
@@ -173,41 +179,34 @@ static void
173do_stream_write (size_t length) 179do_stream_write (size_t length)
174{ 180{
175 size_t l; 181 size_t l;
176 GNUNET_assert (length);
177
178 if (!buffer || !buffer_length)
179 {
180 return;
181 }
182 182
183 GNUNET_assert (0 != length);
184 if ( (! buffer) || (! buffer_length) )
185 return;
183 186
184 l = length; 187 l = length;
185 if (l > buffer_length) 188 if (l > buffer_length)
186 { 189 l = buffer_length;
187 l = buffer_length; 190 if (0 > pa_stream_write (stream_out,
188 191 (uint8_t *) buffer + buffer_index,
189 } 192 l,
190 193 NULL, 0,
191 if (pa_stream_write 194 PA_SEEK_RELATIVE))
192 (stream_out, (uint8_t *) buffer + buffer_index, l, NULL, 0, 195 {
193 PA_SEEK_RELATIVE) < 0) 196 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
194 { 197 _("pa_stream_write() failed: %s\n"),
195 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 198 pa_strerror (pa_context_errno (context)));
196 _("pa_stream_write() failed: %s\n"), 199 quit (1);
197 pa_strerror (pa_context_errno (context))); 200 return;
198 quit (1); 201 }
199 return;
200 }
201
202 buffer_length -= l; 202 buffer_length -= l;
203 buffer_index += l; 203 buffer_index += l;
204 204 if (! buffer_length)
205 if (!buffer_length) 205 {
206 { 206 pa_xfree (buffer);
207 pa_xfree (buffer); 207 buffer = NULL;
208 buffer = NULL; 208 buffer_index = buffer_length = 0;
209 buffer_index = buffer_length = 0; 209 }
210 }
211} 210}
212 211
213 212
@@ -215,21 +214,14 @@ do_stream_write (size_t length)
215 * Callback when data is there for playback 214 * Callback when data is there for playback
216 */ 215 */
217static void 216static void
218stream_write_callback (pa_stream * s, size_t length, void *userdata) 217stream_write_callback (pa_stream * s,
218 size_t length,
219 void *userdata)
219{ 220{
220
221 if (stdio_event) 221 if (stdio_event)
222 { 222 mainloop_api->io_enable (stdio_event, PA_IO_EVENT_INPUT);
223 mainloop_api->io_enable (stdio_event, PA_IO_EVENT_INPUT);
224 }
225
226
227 if (!buffer) 223 if (!buffer)
228 { 224 return;
229 return;
230 }
231
232
233 do_stream_write (length); 225 do_stream_write (length);
234} 226}
235 227
@@ -251,66 +243,58 @@ exit_signal_callback (pa_mainloop_api * m, pa_signal_event * e, int sig,
251 * Pulseaudio stream state callback 243 * Pulseaudio stream state callback
252 */ 244 */
253static void 245static void
254context_state_callback (pa_context * c, void *userdata) 246context_state_callback (pa_context * c,
247 void *userdata)
255{ 248{
256 int p; 249 int p;
257 GNUNET_assert (c);
258 250
251 GNUNET_assert (NULL != c);
259 switch (pa_context_get_state (c)) 252 switch (pa_context_get_state (c))
253 {
254 case PA_CONTEXT_CONNECTING:
255 case PA_CONTEXT_AUTHORIZING:
256 case PA_CONTEXT_SETTING_NAME:
257 break;
258 case PA_CONTEXT_READY:
259 {
260 GNUNET_assert (!stream_out);
261 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
262 _("Connection established.\n"));
263 if (!(stream_out =
264 pa_stream_new (c, "GNUNET VoIP playback", &sample_spec, NULL)))
260 { 265 {
261 case PA_CONTEXT_CONNECTING: 266 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
262 case PA_CONTEXT_AUTHORIZING: 267 _("pa_stream_new() failed: %s\n"),
263 case PA_CONTEXT_SETTING_NAME:
264 break;
265
266 case PA_CONTEXT_READY:
267 {
268 GNUNET_assert (c);
269 GNUNET_assert (!stream_out);
270
271 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connection established.\n"));
272
273
274 if (!
275 (stream_out =
276 pa_stream_new (c, "GNUNET VoIP playback", &sample_spec, NULL)))
277 {
278 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
279 _("pa_stream_new() failed: %s\n"),
280 pa_strerror (pa_context_errno (c)));
281 goto fail;
282 }
283
284 pa_stream_set_write_callback (stream_out, stream_write_callback,
285 NULL);
286
287 if ((p =
288 pa_stream_connect_playback (stream_out, NULL, NULL, 0, NULL,
289 NULL)) < 0)
290 {
291 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
292 _("pa_stream_connect_playback() failed: %s\n"),
293 pa_strerror (pa_context_errno (c)));
294 goto fail;
295 }
296
297 break;
298 }
299
300 case PA_CONTEXT_TERMINATED:
301 quit (0);
302 break;
303
304 case PA_CONTEXT_FAILED:
305 default:
306 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Connection failure: %s\n"),
307 pa_strerror (pa_context_errno (c))); 268 pa_strerror (pa_context_errno (c)));
308 goto fail; 269 goto fail;
309 } 270 }
310 271 pa_stream_set_write_callback (stream_out,
311 return; 272 stream_write_callback,
312 273 NULL);
313fail: 274 if ((p =
275 pa_stream_connect_playback (stream_out, NULL, NULL, 0, NULL,
276 NULL)) < 0)
277 {
278 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
279 _("pa_stream_connect_playback() failed: %s\n"),
280 pa_strerror (pa_context_errno (c)));
281 goto fail;
282 }
283 break;
284 }
285 case PA_CONTEXT_TERMINATED:
286 quit (0);
287 break;
288
289 case PA_CONTEXT_FAILED:
290 default:
291 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
292 _("Connection failure: %s\n"),
293 pa_strerror (pa_context_errno (c)));
294 goto fail;
295 }
296 return;
297 fail:
314 quit (1); 298 quit (1);
315} 299}
316 300
@@ -324,22 +308,18 @@ pa_init ()
324 int r; 308 int r;
325 309
326 if (!pa_sample_spec_valid (&sample_spec)) 310 if (!pa_sample_spec_valid (&sample_spec))
327 { 311 {
328 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Wrong Spec\n")); 312 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
329 } 313 _("Wrong Spec\n"));
330 314 }
331 /* set up threaded playback mainloop */ 315 /* set up threaded playback mainloop */
332
333 if (!(m = pa_threaded_mainloop_new ())) 316 if (!(m = pa_threaded_mainloop_new ()))
334 { 317 {
335 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_mainloop_new() failed.\n")); 318 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
336 } 319 _("pa_mainloop_new() failed.\n"));
337 320 }
338 mainloop_api = pa_threaded_mainloop_get_api (m); 321 mainloop_api = pa_threaded_mainloop_get_api (m);
339
340
341 /* listen to signals */ 322 /* listen to signals */
342
343 r = pa_signal_init (mainloop_api); 323 r = pa_signal_init (mainloop_api);
344 GNUNET_assert (r == 0); 324 GNUNET_assert (r == 0);
345 pa_signal_new (SIGINT, exit_signal_callback, NULL); 325 pa_signal_new (SIGINT, exit_signal_callback, NULL);
@@ -347,25 +327,24 @@ pa_init ()
347 327
348 328
349 /* connect to the main pulseaudio context */ 329 /* connect to the main pulseaudio context */
350
351 if (!(context = pa_context_new (mainloop_api, "GNUnet VoIP"))) 330 if (!(context = pa_context_new (mainloop_api, "GNUnet VoIP")))
352 { 331 {
353 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_context_new() failed.\n")); 332 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
354 } 333 _("pa_context_new() failed.\n"));
355 334 }
356 pa_context_set_state_callback (context, context_state_callback, NULL); 335 pa_context_set_state_callback (context, context_state_callback, NULL);
357 336
358 if (pa_context_connect (context, NULL, 0, NULL) < 0) 337 if (pa_context_connect (context, NULL, 0, NULL) < 0)
359 { 338 {
360 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 339 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
361 _("pa_context_connect() failed: %s\n"), 340 _("pa_context_connect() failed: %s\n"),
362 pa_strerror (pa_context_errno (context))); 341 pa_strerror (pa_context_errno (context)));
363 } 342 }
364
365 if (pa_threaded_mainloop_start (m) < 0) 343 if (pa_threaded_mainloop_start (m) < 0)
366 { 344 {
367 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_mainloop_run() failed.\n")); 345 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
368 } 346 _("pa_mainloop_run() failed.\n"));
347 }
369} 348}
370 349
371 350
@@ -377,11 +356,11 @@ opus_init ()
377{ 356{
378 int err; 357 int err;
379 int channels = 1; 358 int channels = 1;
380 sampling_rate = 48000; 359
381 frame_size = sampling_rate / 50; 360 frame_size = SAMPLING_RATE / 50;
382 pcm_length = frame_size * channels * sizeof (float); 361 pcm_length = frame_size * channels * sizeof (float);
383 362
384 dec = opus_decoder_create (sampling_rate, channels, &err); 363 dec = opus_decoder_create (SAMPLING_RATE, channels, &err);
385 pcm_buffer = (float *) pa_xmalloc (frame_size * channels * sizeof (float)); 364 pcm_buffer = (float *) pa_xmalloc (frame_size * channels * sizeof (float));
386} 365}
387 366
@@ -396,20 +375,26 @@ opus_init ()
396int 375int
397main (int argc, char *argv[]) 376main (int argc, char *argv[])
398{ 377{
378 static unsigned long long toff;
379
399 char readbuf[MAXLINE]; 380 char readbuf[MAXLINE];
400 struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst; 381 struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst;
401 382
402 fprintf (stderr, "HERE!\n");
403 GNUNET_assert (GNUNET_OK == 383 GNUNET_assert (GNUNET_OK ==
404 GNUNET_log_setup ("gnunet-helper-audio-playback", 384 GNUNET_log_setup ("gnunet-helper-audio-playback",
405 "WARNING", 385 "DEBUG",
406 NULL)); 386 "/tmp/helper-audio-playback"));
407 stdin_mst = GNUNET_SERVER_mst_create (&stdin_receiver, NULL); 387 stdin_mst = GNUNET_SERVER_mst_create (&stdin_receiver, NULL);
408 opus_init (); 388 opus_init ();
409 pa_init (); 389 pa_init ();
410 while (1) 390 while (1)
411 { 391 {
412 ssize_t ret = read (0, readbuf, sizeof (readbuf)); 392 ssize_t ret = read (0, readbuf, sizeof (readbuf));
393 toff += ret;
394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
395 "Received %d bytes of audio data (total: %llu)\n",
396 (int) ret,
397 toff);
413 if (0 > ret) 398 if (0 > ret)
414 { 399 {
415 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 400 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -417,6 +402,8 @@ main (int argc, char *argv[])
417 strerror (errno)); 402 strerror (errno));
418 break; 403 break;
419 } 404 }
405 if (0 == ret)
406 break;
420 GNUNET_SERVER_mst_receive (stdin_mst, NULL, 407 GNUNET_SERVER_mst_receive (stdin_mst, NULL,
421 readbuf, ret, 408 readbuf, ret,
422 GNUNET_NO, GNUNET_NO); 409 GNUNET_NO, GNUNET_NO);