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 | |
parent | 517263c3f5134e5dba57a25e745cb276937602bc (diff) | |
download | gnunet-3d8c72a1dc1981d866d752a3d3567830fecd0eae.tar.gz gnunet-3d8c72a1dc1981d866d752a3d3567830fecd0eae.zip |
-debugging logic
Diffstat (limited to 'src/conversation')
-rw-r--r-- | src/conversation/gnunet-helper-audio-playback.c | 267 | ||||
-rw-r--r-- | src/conversation/gnunet-helper-audio-record.c | 358 |
2 files changed, 310 insertions, 315 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); |
diff --git a/src/conversation/gnunet-helper-audio-record.c b/src/conversation/gnunet-helper-audio-record.c index 2267c764b..c14b35fe6 100644 --- a/src/conversation/gnunet-helper-audio-record.c +++ b/src/conversation/gnunet-helper-audio-record.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" |
@@ -38,13 +39,15 @@ | |||
38 | #include <opus/opus.h> | 39 | #include <opus/opus.h> |
39 | #include <opus/opus_types.h> | 40 | #include <opus/opus_types.h> |
40 | 41 | ||
42 | #define SAMPLING_RATE 48000 | ||
43 | |||
41 | 44 | ||
42 | /** | 45 | /** |
43 | * Specification for recording. May change in the future to spec negotiation. | 46 | * Specification for recording. May change in the future to spec negotiation. |
44 | */ | 47 | */ |
45 | static pa_sample_spec sample_spec = { | 48 | static pa_sample_spec sample_spec = { |
46 | .format = PA_SAMPLE_FLOAT32LE, | 49 | .format = PA_SAMPLE_FLOAT32LE, |
47 | .rate = 48000, | 50 | .rate = SAMPLING_RATE, |
48 | .channels = 1 | 51 | .channels = 1 |
49 | }; | 52 | }; |
50 | 53 | ||
@@ -106,7 +109,7 @@ static int max_payload_bytes = 1500; | |||
106 | /** | 109 | /** |
107 | * Audio buffer | 110 | * Audio buffer |
108 | */ | 111 | */ |
109 | static void *transmit_buffer; | 112 | static char *transmit_buffer; |
110 | 113 | ||
111 | /** | 114 | /** |
112 | * Length of audio buffer | 115 | * Length of audio buffer |
@@ -141,15 +144,21 @@ quit (int ret) | |||
141 | static void | 144 | static void |
142 | packetizer () | 145 | packetizer () |
143 | { | 146 | { |
147 | static unsigned long long toff; | ||
148 | char *nbuf; | ||
149 | size_t new_size; | ||
150 | const char *ptr; | ||
151 | size_t off; | ||
152 | ssize_t ret; | ||
153 | int len; // FIXME: int? | ||
154 | size_t msg_size; | ||
155 | |||
144 | while (transmit_buffer_length >= transmit_buffer_index + pcm_length) | 156 | while (transmit_buffer_length >= transmit_buffer_index + pcm_length) |
145 | { | 157 | { |
146 | ssize_t ret; | ||
147 | int len; // FIXME: int? | ||
148 | size_t msg_size; | ||
149 | |||
150 | memcpy (pcm_buffer, | 158 | memcpy (pcm_buffer, |
151 | (float *) transmit_buffer + | 159 | &transmit_buffer[transmit_buffer_index], |
152 | (transmit_buffer_index / sizeof (float)), pcm_length); | 160 | pcm_length); |
161 | transmit_buffer_index += pcm_length; | ||
153 | len = | 162 | len = |
154 | opus_encode_float (enc, pcm_buffer, frame_size, opus_data, | 163 | opus_encode_float (enc, pcm_buffer, frame_size, opus_data, |
155 | max_payload_bytes); | 164 | max_payload_bytes); |
@@ -162,25 +171,43 @@ packetizer () | |||
162 | audio_message->header.size = htons ((uint16_t) msg_size); | 171 | audio_message->header.size = htons ((uint16_t) msg_size); |
163 | memcpy (&audio_message[1], opus_data, len); | 172 | memcpy (&audio_message[1], opus_data, len); |
164 | 173 | ||
165 | // FIXME: handle partial writes better... | 174 | toff += msg_size; |
166 | if ((ret = write (1, audio_message, msg_size)) != msg_size) | 175 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
176 | "Sending %u bytes of audio data (total: %llu)\n", | ||
177 | (unsigned int) msg_size, | ||
178 | toff); | ||
179 | ptr = (const char *) audio_message; | ||
180 | off = 0; | ||
181 | while (off < msg_size) | ||
167 | { | 182 | { |
168 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("write")); | 183 | ret = write (1, &ptr[off], msg_size - off); |
169 | return; | 184 | if (0 >= ret) |
170 | } | 185 | { |
171 | transmit_buffer_index += pcm_length; | 186 | if (-1 == ret) |
187 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "write"); | ||
188 | quit (2); | ||
189 | } | ||
190 | off += ret; | ||
191 | } | ||
172 | } | 192 | } |
173 | 193 | ||
174 | int new_size = transmit_buffer_length - transmit_buffer_index; | 194 | new_size = transmit_buffer_length - transmit_buffer_index; |
175 | if (0 != new_size) | 195 | if (0 != new_size) |
176 | { | 196 | { |
177 | transmit_buffer = pa_xrealloc (transmit_buffer, new_size); | 197 | nbuf = pa_xmalloc (new_size); |
178 | memcpy (transmit_buffer, transmit_buffer + transmit_buffer_index, | 198 | memmove (nbuf, |
179 | new_size); | 199 | &transmit_buffer[transmit_buffer_index], |
180 | 200 | new_size); | |
181 | transmit_buffer_index = 0; | 201 | pa_xfree (transmit_buffer); |
182 | transmit_buffer_length = new_size; | 202 | transmit_buffer = nbuf; |
183 | } | 203 | } |
204 | else | ||
205 | { | ||
206 | pa_xfree (transmit_buffer); | ||
207 | transmit_buffer = NULL; | ||
208 | } | ||
209 | transmit_buffer_index = 0; | ||
210 | transmit_buffer_length = new_size; | ||
184 | } | 211 | } |
185 | 212 | ||
186 | 213 | ||
@@ -188,31 +215,33 @@ packetizer () | |||
188 | * Pulseaudio callback when new data is available. | 215 | * Pulseaudio callback when new data is available. |
189 | */ | 216 | */ |
190 | static void | 217 | static void |
191 | stream_read_callback (pa_stream * s, size_t length, void *userdata) | 218 | stream_read_callback (pa_stream * s, |
219 | size_t length, | ||
220 | void *userdata) | ||
192 | { | 221 | { |
193 | const void *data; | 222 | const void *data; |
194 | 223 | ||
195 | GNUNET_assert (s); | 224 | GNUNET_assert (NULL != s); |
196 | GNUNET_assert (length > 0); | 225 | GNUNET_assert (length > 0); |
197 | if (stdio_event) | 226 | if (stdio_event) |
198 | mainloop_api->io_enable (stdio_event, PA_IO_EVENT_OUTPUT); | 227 | mainloop_api->io_enable (stdio_event, PA_IO_EVENT_OUTPUT); |
199 | 228 | ||
200 | if (pa_stream_peek (s, (const void **) &data, &length) < 0) | 229 | if (pa_stream_peek (s, (const void **) &data, &length) < 0) |
201 | { | 230 | { |
202 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_stream_peek() failed: %s\n"), | 231 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
203 | pa_strerror (pa_context_errno (context))); | 232 | _("pa_stream_peek() failed: %s\n"), |
204 | quit (1); | 233 | pa_strerror (pa_context_errno (context))); |
205 | return; | 234 | quit (1); |
206 | } | 235 | return; |
207 | 236 | } | |
208 | GNUNET_assert (data); | 237 | GNUNET_assert (NULL != data); |
209 | GNUNET_assert (length > 0); | 238 | GNUNET_assert (length > 0); |
210 | 239 | if (NULL != transmit_buffer) | |
211 | if (transmit_buffer) | ||
212 | { | 240 | { |
213 | transmit_buffer = | 241 | transmit_buffer = pa_xrealloc (transmit_buffer, |
214 | pa_xrealloc (transmit_buffer, transmit_buffer_length + length); | 242 | transmit_buffer_length + length); |
215 | memcpy ((uint8_t *) transmit_buffer + transmit_buffer_length, data, | 243 | memcpy (&transmit_buffer[transmit_buffer_length], |
244 | data, | ||
216 | length); | 245 | length); |
217 | transmit_buffer_length += length; | 246 | transmit_buffer_length += length; |
218 | } | 247 | } |
@@ -249,61 +278,57 @@ exit_signal_callback (pa_mainloop_api * m, | |||
249 | static void | 278 | static void |
250 | stream_state_callback (pa_stream * s, void *userdata) | 279 | stream_state_callback (pa_stream * s, void *userdata) |
251 | { | 280 | { |
252 | GNUNET_assert (s); | 281 | GNUNET_assert (NULL != s); |
253 | 282 | ||
254 | switch (pa_stream_get_state (s)) | 283 | switch (pa_stream_get_state (s)) |
284 | { | ||
285 | case PA_STREAM_CREATING: | ||
286 | case PA_STREAM_TERMINATED: | ||
287 | break; | ||
288 | case PA_STREAM_READY: | ||
255 | { | 289 | { |
256 | case PA_STREAM_CREATING: | 290 | const pa_buffer_attr *a; |
257 | case PA_STREAM_TERMINATED: | 291 | char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], |
258 | break; | 292 | sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; |
259 | 293 | ||
260 | case PA_STREAM_READY: | 294 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
261 | if (1) | 295 | _("Stream successfully created.\n")); |
262 | { | 296 | |
263 | const pa_buffer_attr *a; | 297 | if (!(a = pa_stream_get_buffer_attr (s))) |
264 | char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], | 298 | { |
265 | sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; | 299 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
266 | 300 | _("pa_stream_get_buffer_attr() failed: %s\n"), | |
267 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 301 | pa_strerror (pa_context_errno |
268 | _("Stream successfully created.\n")); | 302 | (pa_stream_get_context (s)))); |
269 | 303 | ||
270 | if (!(a = pa_stream_get_buffer_attr (s))) | 304 | } |
271 | { | 305 | else |
272 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 306 | { |
273 | _("pa_stream_get_buffer_attr() failed: %s\n"), | 307 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
274 | pa_strerror (pa_context_errno | 308 | _("Buffer metrics: maxlength=%u, fragsize=%u\n"), |
275 | (pa_stream_get_context (s)))); | 309 | a->maxlength, a->fragsize); |
276 | 310 | } | |
277 | } | 311 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
278 | else | 312 | _("Using sample spec '%s', channel map '%s'.\n"), |
279 | { | 313 | pa_sample_spec_snprint (sst, sizeof (sst), |
280 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 314 | pa_stream_get_sample_spec (s)), |
281 | _("Buffer metrics: maxlength=%u, fragsize=%u\n"), | 315 | pa_channel_map_snprint (cmt, sizeof (cmt), |
282 | a->maxlength, a->fragsize); | 316 | pa_stream_get_channel_map (s))); |
283 | } | 317 | |
284 | 318 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | |
285 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 319 | _("Connected to device %s (%u, %ssuspended).\n"), |
286 | _("Using sample spec '%s', channel map '%s'.\n"), | 320 | pa_stream_get_device_name (s), |
287 | pa_sample_spec_snprint (sst, sizeof (sst), | 321 | pa_stream_get_device_index (s), |
288 | pa_stream_get_sample_spec (s)), | 322 | pa_stream_is_suspended (s) ? "" : "not "); |
289 | pa_channel_map_snprint (cmt, sizeof (cmt), | 323 | } |
290 | pa_stream_get_channel_map (s))); | 324 | break; |
291 | 325 | case PA_STREAM_FAILED: | |
292 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 326 | default: |
293 | _("Connected to device %s (%u, %ssuspended).\n"), | 327 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
294 | pa_stream_get_device_name (s), | 328 | _("Stream error: %s\n"), |
295 | pa_stream_get_device_index (s), | 329 | pa_strerror (pa_context_errno (pa_stream_get_context (s)))); |
296 | pa_stream_is_suspended (s) ? "" : "not "); | 330 | quit (1); |
297 | } | 331 | } |
298 | |||
299 | break; | ||
300 | |||
301 | case PA_STREAM_FAILED: | ||
302 | default: | ||
303 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Stream error: %s\n"), | ||
304 | pa_strerror (pa_context_errno (pa_stream_get_context (s)))); | ||
305 | quit (1); | ||
306 | } | ||
307 | } | 332 | } |
308 | 333 | ||
309 | 334 | ||
@@ -317,58 +342,48 @@ context_state_callback (pa_context * c, | |||
317 | GNUNET_assert (c); | 342 | GNUNET_assert (c); |
318 | 343 | ||
319 | switch (pa_context_get_state (c)) | 344 | switch (pa_context_get_state (c)) |
345 | { | ||
346 | case PA_CONTEXT_CONNECTING: | ||
347 | case PA_CONTEXT_AUTHORIZING: | ||
348 | case PA_CONTEXT_SETTING_NAME: | ||
349 | break; | ||
350 | case PA_CONTEXT_READY: | ||
351 | { | ||
352 | int r; | ||
353 | |||
354 | GNUNET_assert (!stream_in); | ||
355 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
356 | _("Connection established.\n")); | ||
357 | if (! (stream_in = | ||
358 | pa_stream_new (c, "GNUNET_VoIP recorder", &sample_spec, NULL))) | ||
320 | { | 359 | { |
321 | case PA_CONTEXT_CONNECTING: | 360 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
322 | case PA_CONTEXT_AUTHORIZING: | 361 | _("pa_stream_new() failed: %s\n"), |
323 | case PA_CONTEXT_SETTING_NAME: | ||
324 | break; | ||
325 | |||
326 | case PA_CONTEXT_READY: | ||
327 | { | ||
328 | int r; | ||
329 | |||
330 | GNUNET_assert (c); | ||
331 | GNUNET_assert (!stream_in); | ||
332 | |||
333 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connection established.\n")); | ||
334 | |||
335 | if (! | ||
336 | (stream_in = | ||
337 | pa_stream_new (c, "GNUNET_VoIP recorder", &sample_spec, NULL))) | ||
338 | { | ||
339 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
340 | _("pa_stream_new() failed: %s\n"), | ||
341 | pa_strerror (pa_context_errno (c))); | ||
342 | goto fail; | ||
343 | } | ||
344 | |||
345 | |||
346 | pa_stream_set_state_callback (stream_in, stream_state_callback, NULL); | ||
347 | pa_stream_set_read_callback (stream_in, stream_read_callback, NULL); | ||
348 | |||
349 | |||
350 | if ((r = pa_stream_connect_record (stream_in, NULL, NULL, 0)) < 0) | ||
351 | { | ||
352 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
353 | _("pa_stream_connect_record() failed: %s\n"), | ||
354 | pa_strerror (pa_context_errno (c))); | ||
355 | goto fail; | ||
356 | } | ||
357 | |||
358 | break; | ||
359 | } | ||
360 | |||
361 | case PA_CONTEXT_TERMINATED: | ||
362 | quit (0); | ||
363 | break; | ||
364 | |||
365 | case PA_CONTEXT_FAILED: | ||
366 | default: | ||
367 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Connection failure: %s\n"), | ||
368 | pa_strerror (pa_context_errno (c))); | 362 | pa_strerror (pa_context_errno (c))); |
369 | goto fail; | 363 | goto fail; |
370 | } | 364 | } |
371 | 365 | pa_stream_set_state_callback (stream_in, stream_state_callback, NULL); | |
366 | pa_stream_set_read_callback (stream_in, stream_read_callback, NULL); | ||
367 | if ((r = pa_stream_connect_record (stream_in, NULL, NULL, 0)) < 0) | ||
368 | { | ||
369 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
370 | _("pa_stream_connect_record() failed: %s\n"), | ||
371 | pa_strerror (pa_context_errno (c))); | ||
372 | goto fail; | ||
373 | } | ||
374 | |||
375 | break; | ||
376 | } | ||
377 | case PA_CONTEXT_TERMINATED: | ||
378 | quit (0); | ||
379 | break; | ||
380 | case PA_CONTEXT_FAILED: | ||
381 | default: | ||
382 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
383 | _("Connection failure: %s\n"), | ||
384 | pa_strerror (pa_context_errno (c))); | ||
385 | goto fail; | ||
386 | } | ||
372 | return; | 387 | return; |
373 | 388 | ||
374 | fail: | 389 | fail: |
@@ -386,21 +401,19 @@ pa_init () | |||
386 | int i; | 401 | int i; |
387 | 402 | ||
388 | if (!pa_sample_spec_valid (&sample_spec)) | 403 | if (!pa_sample_spec_valid (&sample_spec)) |
389 | { | 404 | { |
390 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong Spec\n")); | 405 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
391 | } | 406 | _("Wrong Spec\n")); |
392 | 407 | } | |
393 | /* set up main record loop */ | 408 | /* set up main record loop */ |
394 | |||
395 | if (!(m = pa_mainloop_new ())) | 409 | if (!(m = pa_mainloop_new ())) |
396 | { | 410 | { |
397 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_mainloop_new() failed.\n")); | 411 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
398 | } | 412 | _("pa_mainloop_new() failed.\n")); |
399 | 413 | } | |
400 | mainloop_api = pa_mainloop_get_api (m); | 414 | mainloop_api = pa_mainloop_get_api (m); |
401 | 415 | ||
402 | /* listen to signals */ | 416 | /* listen to signals */ |
403 | |||
404 | r = pa_signal_init (mainloop_api); | 417 | r = pa_signal_init (mainloop_api); |
405 | GNUNET_assert (r == 0); | 418 | GNUNET_assert (r == 0); |
406 | pa_signal_new (SIGINT, exit_signal_callback, NULL); | 419 | pa_signal_new (SIGINT, exit_signal_callback, NULL); |
@@ -409,23 +422,22 @@ pa_init () | |||
409 | /* connect to the main pulseaudio context */ | 422 | /* connect to the main pulseaudio context */ |
410 | 423 | ||
411 | if (!(context = pa_context_new (mainloop_api, "GNUNET VoIP"))) | 424 | if (!(context = pa_context_new (mainloop_api, "GNUNET VoIP"))) |
412 | { | 425 | { |
413 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_context_new() failed.\n")); | 426 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
414 | } | 427 | _("pa_context_new() failed.\n")); |
415 | 428 | } | |
416 | pa_context_set_state_callback (context, context_state_callback, NULL); | 429 | pa_context_set_state_callback (context, context_state_callback, NULL); |
417 | |||
418 | if (pa_context_connect (context, NULL, 0, NULL) < 0) | 430 | if (pa_context_connect (context, NULL, 0, NULL) < 0) |
419 | { | 431 | { |
420 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 432 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
421 | _("pa_context_connect() failed: %s\n"), | 433 | _("pa_context_connect() failed: %s\n"), |
422 | pa_strerror (pa_context_errno (context))); | 434 | pa_strerror (pa_context_errno (context))); |
423 | } | 435 | } |
424 | |||
425 | if (pa_mainloop_run (m, &i) < 0) | 436 | if (pa_mainloop_run (m, &i) < 0) |
426 | { | 437 | { |
427 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_mainloop_run() failed.\n")); | 438 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
428 | } | 439 | _("pa_mainloop_run() failed.\n")); |
440 | } | ||
429 | } | 441 | } |
430 | 442 | ||
431 | 443 | ||
@@ -435,20 +447,17 @@ pa_init () | |||
435 | static void | 447 | static void |
436 | opus_init () | 448 | opus_init () |
437 | { | 449 | { |
438 | opus_int32 sampling_rate = 48000; | ||
439 | int channels = 1; | 450 | int channels = 1; |
440 | int err; | 451 | int err; |
441 | 452 | ||
442 | frame_size = sampling_rate / 50; | 453 | frame_size = SAMPLING_RATE / 50; |
443 | pcm_length = frame_size * channels * sizeof (float); | 454 | pcm_length = frame_size * channels * sizeof (float); |
444 | enc = | 455 | pcm_buffer = pa_xmalloc (pcm_length); |
445 | opus_encoder_create (sampling_rate, channels, OPUS_APPLICATION_VOIP, | 456 | opus_data = GNUNET_malloc (max_payload_bytes); |
446 | &err); | 457 | enc = opus_encoder_create (SAMPLING_RATE, |
447 | pcm_buffer = (float *) pa_xmalloc (pcm_length); | 458 | channels, |
448 | opus_data = (unsigned char *) calloc (max_payload_bytes, sizeof (char)); | 459 | OPUS_APPLICATION_VOIP, |
449 | 460 | &err); | |
450 | audio_message = pa_xmalloc (UINT16_MAX); | ||
451 | audio_message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO); | ||
452 | } | 461 | } |
453 | 462 | ||
454 | 463 | ||
@@ -462,14 +471,13 @@ opus_init () | |||
462 | int | 471 | int |
463 | main (int argc, char *argv[]) | 472 | main (int argc, char *argv[]) |
464 | { | 473 | { |
465 | fprintf (stderr, "HERE2!\n"); | ||
466 | |||
467 | GNUNET_assert (GNUNET_OK == | 474 | GNUNET_assert (GNUNET_OK == |
468 | GNUNET_log_setup ("gnunet-helper-audio-record", | 475 | GNUNET_log_setup ("gnunet-helper-audio-record", |
469 | "WARNING", | 476 | "DEBUG", |
470 | NULL)); | 477 | "/tmp/helper-audio-record")); |
478 | audio_message = GNUNET_malloc (UINT16_MAX); | ||
479 | audio_message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO); | ||
471 | opus_init (); | 480 | opus_init (); |
472 | pa_init (); | 481 | pa_init (); |
473 | |||
474 | return 0; | 482 | return 0; |
475 | } | 483 | } |