diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-10-02 22:13:12 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-10-02 22:13:12 +0000 |
commit | 3d8c72a1dc1981d866d752a3d3567830fecd0eae (patch) | |
tree | dc3949c8759052bd051e1a8b0df2255e544067a2 /src/conversation/gnunet-helper-audio-playback.c | |
parent | 517263c3f5134e5dba57a25e745cb276937602bc (diff) | |
download | gnunet-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.c | 267 |
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 | */ |
46 | static pa_sample_spec sample_spec = { | 49 | static 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; | |||
96 | static int frame_size; | 99 | static int frame_size; |
97 | 100 | ||
98 | /** | 101 | /** |
99 | * The sampling rate used in Pulseaudio specification | ||
100 | */ | ||
101 | static opus_int32 sampling_rate; | ||
102 | |||
103 | /** | ||
104 | * Audio buffer | 102 | * Audio buffer |
105 | */ | 103 | */ |
106 | static void *buffer; | 104 | static 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 | |||
173 | do_stream_write (size_t length) | 179 | do_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 | */ |
217 | static void | 216 | static void |
218 | stream_write_callback (pa_stream * s, size_t length, void *userdata) | 217 | stream_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 | */ |
253 | static void | 245 | static void |
254 | context_state_callback (pa_context * c, void *userdata) | 246 | context_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); | |
313 | fail: | 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 () | |||
396 | int | 375 | int |
397 | main (int argc, char *argv[]) | 376 | main (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); |