diff options
Diffstat (limited to 'src/conversation/gnunet-helper-audio-playback.c')
-rw-r--r-- | src/conversation/gnunet-helper-audio-playback.c | 1025 |
1 files changed, 522 insertions, 503 deletions
diff --git a/src/conversation/gnunet-helper-audio-playback.c b/src/conversation/gnunet-helper-audio-playback.c index 34e61c100..d7e1cd036 100644 --- a/src/conversation/gnunet-helper-audio-playback.c +++ b/src/conversation/gnunet-helper-audio-playback.c | |||
@@ -124,7 +124,8 @@ static float gain; | |||
124 | GNUNET_NETWORK_STRUCT_BEGIN | 124 | GNUNET_NETWORK_STRUCT_BEGIN |
125 | 125 | ||
126 | /* OggOpus spec says the numbers must be in little-endian order */ | 126 | /* OggOpus spec says the numbers must be in little-endian order */ |
127 | struct OpusHeadPacket { | 127 | struct OpusHeadPacket |
128 | { | ||
128 | uint8_t magic[8]; | 129 | uint8_t magic[8]; |
129 | uint8_t version; | 130 | uint8_t version; |
130 | uint8_t channels; | 131 | uint8_t channels; |
@@ -142,71 +143,71 @@ GNUNET_NETWORK_STRUCT_END | |||
142 | * elsewhere in the code. | 143 | * elsewhere in the code. |
143 | */ | 144 | */ |
144 | static OpusDecoder * | 145 | static OpusDecoder * |
145 | process_header(ogg_packet *op) | 146 | process_header (ogg_packet *op) |
146 | { | 147 | { |
147 | int err; | 148 | int err; |
148 | OpusDecoder *dec; | 149 | OpusDecoder *dec; |
149 | struct OpusHeadPacket header; | 150 | struct OpusHeadPacket header; |
150 | 151 | ||
151 | if (((unsigned int)op->bytes) < sizeof(header)) | 152 | if (((unsigned int) op->bytes) < sizeof(header)) |
152 | return NULL; | 153 | return NULL; |
153 | GNUNET_memcpy(&header, | 154 | GNUNET_memcpy (&header, |
154 | op->packet, | 155 | op->packet, |
155 | sizeof(header)); | 156 | sizeof(header)); |
156 | header.preskip = GNUNET_le16toh(header.preskip); | 157 | header.preskip = GNUNET_le16toh (header.preskip); |
157 | header.sampling_rate = GNUNET_le32toh(header.sampling_rate); | 158 | header.sampling_rate = GNUNET_le32toh (header.sampling_rate); |
158 | header.gain = GNUNET_le16toh(header.gain); | 159 | header.gain = GNUNET_le16toh (header.gain); |
159 | 160 | ||
160 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | 161 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
161 | "Header: v%u, %u-ch, skip %u, %uHz, %u gain\n", | 162 | "Header: v%u, %u-ch, skip %u, %uHz, %u gain\n", |
162 | header.version, | 163 | header.version, |
163 | header.channels, | 164 | header.channels, |
164 | header.preskip, | 165 | header.preskip, |
165 | header.sampling_rate, | 166 | header.sampling_rate, |
166 | header.gain); | 167 | header.gain); |
167 | channels = header.channels; | 168 | channels = header.channels; |
168 | preskip = header.preskip; | 169 | preskip = header.preskip; |
169 | 170 | ||
170 | if (header.channel_mapping != 0) | 171 | if (header.channel_mapping != 0) |
171 | { | 172 | { |
172 | fprintf(stderr, | 173 | fprintf (stderr, |
173 | "This implementation does not support non-mono streams\n"); | 174 | "This implementation does not support non-mono streams\n"); |
174 | return NULL; | 175 | return NULL; |
175 | } | 176 | } |
176 | 177 | ||
177 | dec = opus_decoder_create(SAMPLING_RATE, channels, &err); | 178 | dec = opus_decoder_create (SAMPLING_RATE, channels, &err); |
178 | if (OPUS_OK != err) | 179 | if (OPUS_OK != err) |
180 | { | ||
181 | fprintf (stderr, | ||
182 | "Cannot create encoder: %s\n", | ||
183 | opus_strerror (err)); | ||
184 | return NULL; | ||
185 | } | ||
186 | if (! dec) | ||
187 | { | ||
188 | fprintf (stderr, | ||
189 | "Decoder initialization failed: %s\n", | ||
190 | opus_strerror (err)); | ||
191 | return NULL; | ||
192 | } | ||
193 | |||
194 | if (0 != header.gain) | ||
195 | { | ||
196 | /*Gain API added in a newer libopus version, if we don't have it | ||
197 | we apply the gain ourselves. We also add in a user provided | ||
198 | manual gain at the same time.*/ | ||
199 | int gainadj = (int) header.gain; | ||
200 | err = opus_decoder_ctl (dec, OPUS_SET_GAIN (gainadj)); | ||
201 | if (OPUS_UNIMPLEMENTED == err) | ||
179 | { | 202 | { |
180 | fprintf(stderr, | 203 | gain = pow (10.0, gainadj / 5120.0); |
181 | "Cannot create encoder: %s\n", | ||
182 | opus_strerror(err)); | ||
183 | return NULL; | ||
184 | } | 204 | } |
185 | if (!dec) | 205 | else if (OPUS_OK != err) |
186 | { | 206 | { |
187 | fprintf(stderr, | 207 | fprintf (stderr, "Error setting gain: %s\n", opus_strerror (err)); |
188 | "Decoder initialization failed: %s\n", | ||
189 | opus_strerror(err)); | ||
190 | return NULL; | 208 | return NULL; |
191 | } | 209 | } |
192 | 210 | } | |
193 | if (0 != header.gain) | ||
194 | { | ||
195 | /*Gain API added in a newer libopus version, if we don't have it | ||
196 | we apply the gain ourselves. We also add in a user provided | ||
197 | manual gain at the same time.*/ | ||
198 | int gainadj = (int)header.gain; | ||
199 | err = opus_decoder_ctl(dec, OPUS_SET_GAIN(gainadj)); | ||
200 | if (OPUS_UNIMPLEMENTED == err) | ||
201 | { | ||
202 | gain = pow(10.0, gainadj / 5120.0); | ||
203 | } | ||
204 | else if (OPUS_OK != err) | ||
205 | { | ||
206 | fprintf(stderr, "Error setting gain: %s\n", opus_strerror(err)); | ||
207 | return NULL; | ||
208 | } | ||
209 | } | ||
210 | 211 | ||
211 | return dec; | 212 | return dec; |
212 | } | 213 | } |
@@ -214,58 +215,58 @@ process_header(ogg_packet *op) | |||
214 | 215 | ||
215 | #ifdef DEBUG_DUMP_DECODED_OGG | 216 | #ifdef DEBUG_DUMP_DECODED_OGG |
216 | static size_t | 217 | static size_t |
217 | fwrite_le32(opus_int32 i32, FILE *file) | 218 | fwrite_le32 (opus_int32 i32, FILE *file) |
218 | { | 219 | { |
219 | unsigned char buf[4]; | 220 | unsigned char buf[4]; |
220 | 221 | ||
221 | buf[0] = (unsigned char)(i32 & 0xFF); | 222 | buf[0] = (unsigned char) (i32 & 0xFF); |
222 | buf[1] = (unsigned char)(i32 >> 8 & 0xFF); | 223 | buf[1] = (unsigned char) (i32 >> 8 & 0xFF); |
223 | buf[2] = (unsigned char)(i32 >> 16 & 0xFF); | 224 | buf[2] = (unsigned char) (i32 >> 16 & 0xFF); |
224 | buf[3] = (unsigned char)(i32 >> 24 & 0xFF); | 225 | buf[3] = (unsigned char) (i32 >> 24 & 0xFF); |
225 | return fwrite(buf, 4, 1, file); | 226 | return fwrite (buf, 4, 1, file); |
226 | } | 227 | } |
227 | 228 | ||
228 | 229 | ||
229 | static size_t | 230 | static size_t |
230 | fwrite_le16(int i16, FILE *file) | 231 | fwrite_le16 (int i16, FILE *file) |
231 | { | 232 | { |
232 | unsigned char buf[2]; | 233 | unsigned char buf[2]; |
233 | 234 | ||
234 | buf[0] = (unsigned char)(i16 & 0xFF); | 235 | buf[0] = (unsigned char) (i16 & 0xFF); |
235 | buf[1] = (unsigned char)(i16 >> 8 & 0xFF); | 236 | buf[1] = (unsigned char) (i16 >> 8 & 0xFF); |
236 | return fwrite(buf, 2, 1, file); | 237 | return fwrite (buf, 2, 1, file); |
237 | } | 238 | } |
238 | 239 | ||
239 | 240 | ||
240 | static int | 241 | static int |
241 | write_wav_header() | 242 | write_wav_header () |
242 | { | 243 | { |
243 | int ret; | 244 | int ret; |
244 | FILE *file = stdout; | 245 | FILE *file = stdout; |
245 | 246 | ||
246 | ret = fprintf(file, "RIFF") >= 0; | 247 | ret = fprintf (file, "RIFF") >= 0; |
247 | ret &= fwrite_le32(0x7fffffff, file); | 248 | ret &= fwrite_le32 (0x7fffffff, file); |
248 | 249 | ||
249 | ret &= fprintf(file, "WAVEfmt ") >= 0; | 250 | ret &= fprintf (file, "WAVEfmt ") >= 0; |
250 | ret &= fwrite_le32(16, file); | 251 | ret &= fwrite_le32 (16, file); |
251 | ret &= fwrite_le16(1, file); | 252 | ret &= fwrite_le16 (1, file); |
252 | ret &= fwrite_le16(channels, file); | 253 | ret &= fwrite_le16 (channels, file); |
253 | ret &= fwrite_le32(SAMPLING_RATE, file); | 254 | ret &= fwrite_le32 (SAMPLING_RATE, file); |
254 | ret &= fwrite_le32(2 * channels * SAMPLING_RATE, file); | 255 | ret &= fwrite_le32 (2 * channels * SAMPLING_RATE, file); |
255 | ret &= fwrite_le16(2 * channels, file); | 256 | ret &= fwrite_le16 (2 * channels, file); |
256 | ret &= fwrite_le16(16, file); | 257 | ret &= fwrite_le16 (16, file); |
257 | 258 | ||
258 | ret &= fprintf(file, "data") >= 0; | 259 | ret &= fprintf (file, "data") >= 0; |
259 | ret &= fwrite_le32(0x7fffffff, file); | 260 | ret &= fwrite_le32 (0x7fffffff, file); |
260 | 261 | ||
261 | return !ret ? -1 : 16; | 262 | return ! ret ? -1 : 16; |
262 | } | 263 | } |
263 | 264 | ||
264 | #endif | 265 | #endif |
265 | 266 | ||
266 | 267 | ||
267 | static int64_t | 268 | static int64_t |
268 | audio_write(int64_t maxout) | 269 | audio_write (int64_t maxout) |
269 | { | 270 | { |
270 | int64_t sampout = 0; | 271 | int64_t sampout = 0; |
271 | int tmp_skip; | 272 | int tmp_skip; |
@@ -276,66 +277,67 @@ audio_write(int64_t maxout) | |||
276 | #ifdef DEBUG_DUMP_DECODED_OGG | 277 | #ifdef DEBUG_DUMP_DECODED_OGG |
277 | static int wrote_wav_header; | 278 | static int wrote_wav_header; |
278 | 279 | ||
279 | if (dump_to_stdout && !wrote_wav_header) | 280 | if (dump_to_stdout && ! wrote_wav_header) |
280 | { | 281 | { |
281 | write_wav_header(); | 282 | write_wav_header (); |
282 | wrote_wav_header = 1; | 283 | wrote_wav_header = 1; |
283 | } | 284 | } |
284 | #endif | 285 | #endif |
285 | maxout = 0 > maxout ? 0 : maxout; | 286 | maxout = 0 > maxout ? 0 : maxout; |
286 | do | 287 | do |
288 | { | ||
289 | tmp_skip = (preskip > frame_size) ? (int) frame_size : preskip; | ||
290 | preskip -= tmp_skip; | ||
291 | output = pcm_buffer + channels * tmp_skip; | ||
292 | out_len = frame_size - tmp_skip; | ||
293 | if (out_len > MAX_FRAME_SIZE) | ||
294 | exit (6); | ||
295 | frame_size = 0; | ||
296 | |||
297 | to_write = out_len < maxout ? out_len : (unsigned) maxout; | ||
298 | if (0 < maxout) | ||
287 | { | 299 | { |
288 | tmp_skip = (preskip > frame_size) ? (int)frame_size : preskip; | 300 | int64_t wrote = 0; |
289 | preskip -= tmp_skip; | 301 | wrote = to_write; |
290 | output = pcm_buffer + channels * tmp_skip; | 302 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
291 | out_len = frame_size - tmp_skip; | 303 | "Writing %u * %u * %u = %llu bytes into PA\n", |
292 | if (out_len > MAX_FRAME_SIZE) | 304 | to_write, |
293 | exit(6); | 305 | channels, |
294 | frame_size = 0; | 306 | (unsigned int) sizeof(float), |
295 | 307 | (unsigned long long) (to_write * channels * sizeof(float))); | |
296 | to_write = out_len < maxout ? out_len : (unsigned)maxout; | ||
297 | if (0 < maxout) | ||
298 | { | ||
299 | int64_t wrote = 0; | ||
300 | wrote = to_write; | ||
301 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
302 | "Writing %u * %u * %u = %llu bytes into PA\n", | ||
303 | to_write, | ||
304 | channels, | ||
305 | (unsigned int)sizeof(float), | ||
306 | (unsigned long long)(to_write * channels * sizeof(float))); | ||
307 | #ifdef DEBUG_DUMP_DECODED_OGG | 308 | #ifdef DEBUG_DUMP_DECODED_OGG |
308 | if (dump_to_stdout) | 309 | if (dump_to_stdout) |
309 | { | 310 | { |
310 | # define fminf(_x, _y) ((_x) < (_y) ? (_x) : (_y)) | 311 | # define fminf(_x, _y) ((_x) < (_y) ? (_x) : (_y)) |
311 | # define fmaxf(_x, _y) ((_x) > (_y) ? (_x) : (_y)) | 312 | # define fmaxf(_x, _y) ((_x) > (_y) ? (_x) : (_y)) |
312 | # define float2int(flt) ((int)(floor(.5 + flt))) | 313 | # define float2int(flt) ((int) (floor (.5 + flt))) |
313 | int i; | 314 | int i; |
314 | int16_t *out = alloca(sizeof(short) * MAX_FRAME_SIZE * channels); | 315 | int16_t *out = alloca (sizeof(short) * MAX_FRAME_SIZE * channels); |
315 | for (i = 0; i < (int)out_len * channels; i++) | 316 | for (i = 0; i < (int) out_len * channels; i++) |
316 | out[i] = (short)float2int(fmaxf(-32768, fminf(output[i] * 32768.f, 32767))); | 317 | out[i] = (short) float2int (fmaxf (-32768, fminf (output[i] * 32768.f, |
317 | 318 | 32767))); | |
318 | fwrite(out, 2 * channels, out_len < maxout ? out_len : maxout, stdout); | 319 | |
319 | } | 320 | fwrite (out, 2 * channels, out_len < maxout ? out_len : maxout, stdout); |
320 | else | 321 | } |
322 | else | ||
321 | #endif | 323 | #endif |
322 | if (pa_stream_write | 324 | if (pa_stream_write |
323 | (stream_out, output, to_write * channels * sizeof(float), NULL, 0, | 325 | (stream_out, output, to_write * channels * sizeof(float), NULL, 0, |
324 | PA_SEEK_RELATIVE) < 0) | 326 | PA_SEEK_RELATIVE) < 0) |
325 | { | 327 | { |
326 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | 328 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
327 | _("pa_stream_write() failed: %s\n"), | 329 | _ ("pa_stream_write() failed: %s\n"), |
328 | pa_strerror(pa_context_errno(context))); | 330 | pa_strerror (pa_context_errno (context))); |
329 | } | 331 | } |
330 | sampout += wrote; | 332 | sampout += wrote; |
331 | maxout -= wrote; | 333 | maxout -= wrote; |
332 | } | ||
333 | } | 334 | } |
335 | } | ||
334 | while (0 < frame_size && 0 < maxout); | 336 | while (0 < frame_size && 0 < maxout); |
335 | 337 | ||
336 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | 338 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
337 | "Wrote %" PRId64 " samples\n", | 339 | "Wrote %" PRId64 " samples\n", |
338 | sampout); | 340 | sampout); |
339 | return sampout; | 341 | return sampout; |
340 | } | 342 | } |
341 | 343 | ||
@@ -344,16 +346,16 @@ audio_write(int64_t maxout) | |||
344 | * Pulseaudio shutdown task | 346 | * Pulseaudio shutdown task |
345 | */ | 347 | */ |
346 | static void | 348 | static void |
347 | quit(int ret) | 349 | quit (int ret) |
348 | { | 350 | { |
349 | mainloop_api->quit(mainloop_api, | 351 | mainloop_api->quit (mainloop_api, |
350 | ret); | 352 | ret); |
351 | exit(ret); | 353 | exit (ret); |
352 | } | 354 | } |
353 | 355 | ||
354 | 356 | ||
355 | static void | 357 | static void |
356 | ogg_demux_and_decode() | 358 | ogg_demux_and_decode () |
357 | { | 359 | { |
358 | ogg_page og; | 360 | ogg_page og; |
359 | static int stream_init; | 361 | static int stream_init; |
@@ -368,189 +370,204 @@ ogg_demux_and_decode() | |||
368 | static int total_links; | 370 | static int total_links; |
369 | static int gran_offset; | 371 | static int gran_offset; |
370 | 372 | ||
371 | while (1 == ogg_sync_pageout(&oy, &og)) | 373 | while (1 == ogg_sync_pageout (&oy, &og)) |
374 | { | ||
375 | if (0 == stream_init) | ||
376 | { | ||
377 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
378 | "Initialized the stream\n"); | ||
379 | ogg_stream_init (&os, ogg_page_serialno (&og)); | ||
380 | stream_init = 1; | ||
381 | } | ||
382 | if (ogg_page_serialno (&og) != os.serialno) | ||
383 | { | ||
384 | /* so all streams are read. */ | ||
385 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
386 | "Re-set serial number\n"); | ||
387 | ogg_stream_reset_serialno (&os, ogg_page_serialno (&og)); | ||
388 | } | ||
389 | /*Add page to the bitstream*/ | ||
390 | ogg_stream_pagein (&os, &og); | ||
391 | page_granule = ogg_page_granulepos (&og); | ||
392 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
393 | "Reading page that ends at %" PRId64 "\n", | ||
394 | page_granule); | ||
395 | /*Extract all available packets*/ | ||
396 | while (1 == ogg_stream_packetout (&os, &op)) | ||
372 | { | 397 | { |
373 | if (0 == stream_init) | 398 | /*OggOpus streams are identified by a magic string in the initial |
399 | stream header.*/ | ||
400 | if (op.b_o_s &&(op.bytes >= 8) && ! memcmp (op.packet, "OpusHead", 8)) | ||
401 | { | ||
402 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
403 | "Got Opus Header\n"); | ||
404 | if (has_opus_stream && has_tags_packet) | ||
374 | { | 405 | { |
375 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | 406 | /*If we're seeing another BOS OpusHead now it means |
376 | "Initialized the stream\n"); | 407 | the stream is chained without an EOS. |
377 | ogg_stream_init(&os, ogg_page_serialno(&og)); | 408 | This can easily happen if record helper is terminated unexpectedly. |
378 | stream_init = 1; | 409 | */ |
410 | has_opus_stream = 0; | ||
411 | if (dec) | ||
412 | opus_decoder_destroy (dec); | ||
413 | dec = NULL; | ||
414 | fprintf (stderr, | ||
415 | "\nWarning: stream %" PRId64 | ||
416 | " ended without EOS and a new stream began.\n", | ||
417 | (int64_t) os.serialno); | ||
379 | } | 418 | } |
380 | if (ogg_page_serialno(&og) != os.serialno) | 419 | if (! has_opus_stream) |
381 | { | 420 | { |
382 | /* so all streams are read. */ | 421 | if ((packet_count > 0) &&(opus_serialno == os.serialno) ) |
383 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | 422 | { |
384 | "Re-set serial number\n"); | 423 | fprintf (stderr, |
385 | ogg_stream_reset_serialno(&os, ogg_page_serialno(&og)); | 424 | "\nError: Apparent chaining without changing serial number (%" |
425 | PRId64 "==%" PRId64 ").\n", | ||
426 | (int64_t) opus_serialno, (int64_t) os.serialno); | ||
427 | quit (1); | ||
428 | } | ||
429 | opus_serialno = os.serialno; | ||
430 | has_opus_stream = 1; | ||
431 | has_tags_packet = 0; | ||
432 | link_out = 0; | ||
433 | packet_count = 0; | ||
434 | eos = 0; | ||
435 | total_links++; | ||
436 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
437 | "Got header for stream %" PRId64 ", this is %dth link\n", | ||
438 | (int64_t) opus_serialno, total_links); | ||
386 | } | 439 | } |
387 | /*Add page to the bitstream*/ | 440 | else |
388 | ogg_stream_pagein(&os, &og); | ||
389 | page_granule = ogg_page_granulepos(&og); | ||
390 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
391 | "Reading page that ends at %" PRId64 "\n", | ||
392 | page_granule); | ||
393 | /*Extract all available packets*/ | ||
394 | while (1 == ogg_stream_packetout(&os, &op)) | ||
395 | { | 441 | { |
396 | /*OggOpus streams are identified by a magic string in the initial | 442 | fprintf (stderr, "\nWarning: ignoring opus stream %" PRId64 "\n", |
397 | stream header.*/ | 443 | (int64_t) os.serialno); |
398 | if (op.b_o_s && op.bytes >= 8 && !memcmp(op.packet, "OpusHead", 8)) | ||
399 | { | ||
400 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
401 | "Got Opus Header\n"); | ||
402 | if (has_opus_stream && has_tags_packet) | ||
403 | { | ||
404 | /*If we're seeing another BOS OpusHead now it means | ||
405 | the stream is chained without an EOS. | ||
406 | This can easily happen if record helper is terminated unexpectedly. | ||
407 | */ | ||
408 | has_opus_stream = 0; | ||
409 | if (dec) | ||
410 | opus_decoder_destroy(dec); | ||
411 | dec = NULL; | ||
412 | fprintf(stderr, "\nWarning: stream %" PRId64 " ended without EOS and a new stream began.\n", (int64_t)os.serialno); | ||
413 | } | ||
414 | if (!has_opus_stream) | ||
415 | { | ||
416 | if (packet_count > 0 && opus_serialno == os.serialno) | ||
417 | { | ||
418 | fprintf(stderr, "\nError: Apparent chaining without changing serial number (%" PRId64 "==%" PRId64 ").\n", | ||
419 | (int64_t)opus_serialno, (int64_t)os.serialno); | ||
420 | quit(1); | ||
421 | } | ||
422 | opus_serialno = os.serialno; | ||
423 | has_opus_stream = 1; | ||
424 | has_tags_packet = 0; | ||
425 | link_out = 0; | ||
426 | packet_count = 0; | ||
427 | eos = 0; | ||
428 | total_links++; | ||
429 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
430 | "Got header for stream %" PRId64 ", this is %dth link\n", | ||
431 | (int64_t)opus_serialno, total_links); | ||
432 | } | ||
433 | else | ||
434 | { | ||
435 | fprintf(stderr, "\nWarning: ignoring opus stream %" PRId64 "\n", (int64_t)os.serialno); | ||
436 | } | ||
437 | } | ||
438 | if (!has_opus_stream || os.serialno != opus_serialno) | ||
439 | { | ||
440 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
441 | "breaking out\n"); | ||
442 | break; | ||
443 | } | ||
444 | /*If first packet in a logical stream, process the Opus header*/ | ||
445 | if (0 == packet_count) | ||
446 | { | ||
447 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
448 | "Decoding header\n"); | ||
449 | dec = process_header(&op); | ||
450 | if (!dec) | ||
451 | quit(1); | ||
452 | |||
453 | if (0 != ogg_stream_packetout(&os, &op) || 255 == og.header[og.header_len - 1]) | ||
454 | { | ||
455 | /*The format specifies that the initial header and tags packets are on their | ||
456 | own pages. To aid implementors in discovering that their files are wrong | ||
457 | we reject them explicitly here. In some player designs files like this would | ||
458 | fail even without an explicit test.*/ | ||
459 | fprintf(stderr, "Extra packets on initial header page. Invalid stream.\n"); | ||
460 | quit(1); | ||
461 | } | ||
462 | |||
463 | /*Remember how many samples at the front we were told to skip | ||
464 | so that we can adjust the timestamp counting.*/ | ||
465 | gran_offset = preskip; | ||
466 | |||
467 | if (!pcm_buffer) | ||
468 | { | ||
469 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
470 | "Allocating %u * %u * %u = %llu bytes of buffer space\n", | ||
471 | MAX_FRAME_SIZE, | ||
472 | channels, | ||
473 | (unsigned int)sizeof(float), | ||
474 | (unsigned long long)(MAX_FRAME_SIZE * channels * sizeof(float))); | ||
475 | pcm_buffer = pa_xmalloc(sizeof(float) * MAX_FRAME_SIZE * channels); | ||
476 | } | ||
477 | } | ||
478 | else if (1 == packet_count) | ||
479 | { | ||
480 | has_tags_packet = 1; | ||
481 | if (0 != ogg_stream_packetout(&os, &op) || 255 == og.header[og.header_len - 1]) | ||
482 | { | ||
483 | fprintf(stderr, "Extra packets on initial tags page. Invalid stream.\n"); | ||
484 | quit(1); | ||
485 | } | ||
486 | } | ||
487 | else | ||
488 | { | ||
489 | int ret; | ||
490 | int64_t maxout; | ||
491 | int64_t outsamp; | ||
492 | |||
493 | /*End of stream condition*/ | ||
494 | if (op.e_o_s && os.serialno == opus_serialno) | ||
495 | { | ||
496 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
497 | "Got EOS\n"); | ||
498 | eos = 1; /* don't care for anything except opus eos */ | ||
499 | } | ||
500 | |||
501 | /*Decode Opus packet*/ | ||
502 | ret = opus_decode_float(dec, | ||
503 | (const unsigned char *)op.packet, | ||
504 | op.bytes, | ||
505 | pcm_buffer, | ||
506 | MAX_FRAME_SIZE, 0); | ||
507 | |||
508 | /*If the decoder returned less than zero, we have an error.*/ | ||
509 | if (0 > ret) | ||
510 | { | ||
511 | fprintf(stderr, "Decoding error: %s\n", opus_strerror(ret)); | ||
512 | break; | ||
513 | } | ||
514 | frame_size = ret; | ||
515 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
516 | "Decoded %d bytes/channel (%d bytes) from %u compressed bytes\n", | ||
517 | ret, | ||
518 | ret * channels, | ||
519 | (unsigned int)op.bytes); | ||
520 | |||
521 | /*Apply header gain, if we're not using an opus library new | ||
522 | enough to do this internally.*/ | ||
523 | if (0 != gain) | ||
524 | { | ||
525 | int i; | ||
526 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
527 | "Applying gain %f\n", | ||
528 | gain); | ||
529 | for (i = 0; i < frame_size * channels; i++) | ||
530 | pcm_buffer[i] *= gain; | ||
531 | } | ||
532 | |||
533 | /*This handles making sure that our output duration respects | ||
534 | the final end-trim by not letting the output sample count | ||
535 | get ahead of the granpos indicated value.*/ | ||
536 | maxout = ((page_granule - gran_offset) * SAMPLING_RATE / 48000) - link_out; | ||
537 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
538 | "Writing audio packet %" PRId64 ", at most %" PRId64 " samples\n", | ||
539 | packet_count, maxout); | ||
540 | |||
541 | outsamp = audio_write(0 > maxout ? 0 : maxout); | ||
542 | link_out += outsamp; | ||
543 | } | ||
544 | packet_count++; | ||
545 | } | 444 | } |
546 | if (eos) | 445 | } |
446 | if (! has_opus_stream ||(os.serialno != opus_serialno) ) | ||
447 | { | ||
448 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
449 | "breaking out\n"); | ||
450 | break; | ||
451 | } | ||
452 | /*If first packet in a logical stream, process the Opus header*/ | ||
453 | if (0 == packet_count) | ||
454 | { | ||
455 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
456 | "Decoding header\n"); | ||
457 | dec = process_header (&op); | ||
458 | if (! dec) | ||
459 | quit (1); | ||
460 | |||
461 | if ((0 != ogg_stream_packetout (&os, &op)) ||(255 == | ||
462 | og.header[og.header_len | ||
463 | - 1]) ) | ||
547 | { | 464 | { |
548 | has_opus_stream = 0; | 465 | /*The format specifies that the initial header and tags packets are on their |
549 | if (dec) | 466 | own pages. To aid implementors in discovering that their files are wrong |
550 | opus_decoder_destroy(dec); | 467 | we reject them explicitly here. In some player designs files like this would |
551 | dec = NULL; | 468 | fail even without an explicit test.*/ |
469 | fprintf (stderr, | ||
470 | "Extra packets on initial header page. Invalid stream.\n"); | ||
471 | quit (1); | ||
472 | } | ||
473 | |||
474 | /*Remember how many samples at the front we were told to skip | ||
475 | so that we can adjust the timestamp counting.*/ | ||
476 | gran_offset = preskip; | ||
477 | |||
478 | if (! pcm_buffer) | ||
479 | { | ||
480 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
481 | "Allocating %u * %u * %u = %llu bytes of buffer space\n", | ||
482 | MAX_FRAME_SIZE, | ||
483 | channels, | ||
484 | (unsigned int) sizeof(float), | ||
485 | (unsigned long long) (MAX_FRAME_SIZE * channels | ||
486 | * sizeof(float))); | ||
487 | pcm_buffer = pa_xmalloc (sizeof(float) * MAX_FRAME_SIZE * channels); | ||
488 | } | ||
489 | } | ||
490 | else if (1 == packet_count) | ||
491 | { | ||
492 | has_tags_packet = 1; | ||
493 | if ((0 != ogg_stream_packetout (&os, &op)) ||(255 == | ||
494 | og.header[og.header_len | ||
495 | - 1]) ) | ||
496 | { | ||
497 | fprintf (stderr, | ||
498 | "Extra packets on initial tags page. Invalid stream.\n"); | ||
499 | quit (1); | ||
552 | } | 500 | } |
501 | } | ||
502 | else | ||
503 | { | ||
504 | int ret; | ||
505 | int64_t maxout; | ||
506 | int64_t outsamp; | ||
507 | |||
508 | /*End of stream condition*/ | ||
509 | if (op.e_o_s &&(os.serialno == opus_serialno) ) | ||
510 | { | ||
511 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
512 | "Got EOS\n"); | ||
513 | eos = 1; /* don't care for anything except opus eos */ | ||
514 | } | ||
515 | |||
516 | /*Decode Opus packet*/ | ||
517 | ret = opus_decode_float (dec, | ||
518 | (const unsigned char *) op.packet, | ||
519 | op.bytes, | ||
520 | pcm_buffer, | ||
521 | MAX_FRAME_SIZE, 0); | ||
522 | |||
523 | /*If the decoder returned less than zero, we have an error.*/ | ||
524 | if (0 > ret) | ||
525 | { | ||
526 | fprintf (stderr, "Decoding error: %s\n", opus_strerror (ret)); | ||
527 | break; | ||
528 | } | ||
529 | frame_size = ret; | ||
530 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
531 | "Decoded %d bytes/channel (%d bytes) from %u compressed bytes\n", | ||
532 | ret, | ||
533 | ret * channels, | ||
534 | (unsigned int) op.bytes); | ||
535 | |||
536 | /*Apply header gain, if we're not using an opus library new | ||
537 | enough to do this internally.*/ | ||
538 | if (0 != gain) | ||
539 | { | ||
540 | int i; | ||
541 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
542 | "Applying gain %f\n", | ||
543 | gain); | ||
544 | for (i = 0; i < frame_size * channels; i++) | ||
545 | pcm_buffer[i] *= gain; | ||
546 | } | ||
547 | |||
548 | /*This handles making sure that our output duration respects | ||
549 | the final end-trim by not letting the output sample count | ||
550 | get ahead of the granpos indicated value.*/ | ||
551 | maxout = ((page_granule - gran_offset) * SAMPLING_RATE / 48000) | ||
552 | - link_out; | ||
553 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
554 | "Writing audio packet %" PRId64 ", at most %" PRId64 | ||
555 | " samples\n", | ||
556 | packet_count, maxout); | ||
557 | |||
558 | outsamp = audio_write (0 > maxout ? 0 : maxout); | ||
559 | link_out += outsamp; | ||
560 | } | ||
561 | packet_count++; | ||
553 | } | 562 | } |
563 | if (eos) | ||
564 | { | ||
565 | has_opus_stream = 0; | ||
566 | if (dec) | ||
567 | opus_decoder_destroy (dec); | ||
568 | dec = NULL; | ||
569 | } | ||
570 | } | ||
554 | } | 571 | } |
555 | 572 | ||
556 | 573 | ||
@@ -563,32 +580,32 @@ ogg_demux_and_decode() | |||
563 | * #GNUNET_SYSERR to stop further processing due to error | 580 | * #GNUNET_SYSERR to stop further processing due to error |
564 | */ | 581 | */ |
565 | static int | 582 | static int |
566 | stdin_receiver(void *cls, | 583 | stdin_receiver (void *cls, |
567 | const struct GNUNET_MessageHeader *msg) | 584 | const struct GNUNET_MessageHeader *msg) |
568 | { | 585 | { |
569 | struct AudioMessage *audio; | 586 | struct AudioMessage *audio; |
570 | char *data; | 587 | char *data; |
571 | size_t payload_len; | 588 | size_t payload_len; |
572 | 589 | ||
573 | (void)cls; | 590 | (void) cls; |
574 | switch (ntohs(msg->type)) | 591 | switch (ntohs (msg->type)) |
575 | { | 592 | { |
576 | case GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO: | 593 | case GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO: |
577 | audio = (struct AudioMessage *)msg; | 594 | audio = (struct AudioMessage *) msg; |
578 | payload_len = ntohs(audio->header.size) - sizeof(struct AudioMessage); | 595 | payload_len = ntohs (audio->header.size) - sizeof(struct AudioMessage); |
579 | 596 | ||
580 | /*Get the ogg buffer for writing*/ | 597 | /*Get the ogg buffer for writing*/ |
581 | data = ogg_sync_buffer(&oy, payload_len); | 598 | data = ogg_sync_buffer (&oy, payload_len); |
582 | /*Read bitstream from input file*/ | 599 | /*Read bitstream from input file*/ |
583 | GNUNET_memcpy(data, (const unsigned char *)&audio[1], payload_len); | 600 | GNUNET_memcpy (data, (const unsigned char *) &audio[1], payload_len); |
584 | ogg_sync_wrote(&oy, payload_len); | 601 | ogg_sync_wrote (&oy, payload_len); |
585 | 602 | ||
586 | ogg_demux_and_decode(); | 603 | ogg_demux_and_decode (); |
587 | break; | 604 | break; |
588 | 605 | ||
589 | default: | 606 | default: |
590 | break; | 607 | break; |
591 | } | 608 | } |
592 | return GNUNET_OK; | 609 | return GNUNET_OK; |
593 | } | 610 | } |
594 | 611 | ||
@@ -597,20 +614,20 @@ stdin_receiver(void *cls, | |||
597 | * Callback when data is there for playback | 614 | * Callback when data is there for playback |
598 | */ | 615 | */ |
599 | static void | 616 | static void |
600 | stream_write_callback(pa_stream *s, | 617 | stream_write_callback (pa_stream *s, |
601 | size_t length, | 618 | size_t length, |
602 | void *userdata) | 619 | void *userdata) |
603 | { | 620 | { |
604 | /* unblock 'main' */ | 621 | /* unblock 'main' */ |
605 | (void)userdata; | 622 | (void) userdata; |
606 | (void)length; | 623 | (void) length; |
607 | (void)s; | 624 | (void) s; |
608 | if (-1 != ready_pipe[1]) | 625 | if (-1 != ready_pipe[1]) |
609 | { | 626 | { |
610 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | 627 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
611 | "Unblocking main loop!\n"); | 628 | "Unblocking main loop!\n"); |
612 | (void)write(ready_pipe[1], "r", 1); | 629 | (void) write (ready_pipe[1], "r", 1); |
613 | } | 630 | } |
614 | } | 631 | } |
615 | 632 | ||
616 | 633 | ||
@@ -618,18 +635,18 @@ stream_write_callback(pa_stream *s, | |||
618 | * Exit callback for SIGTERM and SIGINT | 635 | * Exit callback for SIGTERM and SIGINT |
619 | */ | 636 | */ |
620 | static void | 637 | static void |
621 | exit_signal_callback(pa_mainloop_api *m, | 638 | exit_signal_callback (pa_mainloop_api *m, |
622 | pa_signal_event *e, | 639 | pa_signal_event *e, |
623 | int sig, | 640 | int sig, |
624 | void *userdata) | 641 | void *userdata) |
625 | { | 642 | { |
626 | (void)m; | 643 | (void) m; |
627 | (void)e; | 644 | (void) e; |
628 | (void)sig; | 645 | (void) sig; |
629 | (void)userdata; | 646 | (void) userdata; |
630 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, | 647 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
631 | _("gnunet-helper-audio-playback - Got signal, exiting\n")); | 648 | _ ("gnunet-helper-audio-playback - Got signal, exiting\n")); |
632 | quit(1); | 649 | quit (1); |
633 | } | 650 | } |
634 | 651 | ||
635 | 652 | ||
@@ -637,64 +654,66 @@ exit_signal_callback(pa_mainloop_api *m, | |||
637 | * Pulseaudio stream state callback | 654 | * Pulseaudio stream state callback |
638 | */ | 655 | */ |
639 | static void | 656 | static void |
640 | context_state_callback(pa_context *c, | 657 | context_state_callback (pa_context *c, |
641 | void *userdata) | 658 | void *userdata) |
642 | { | 659 | { |
643 | int p; | 660 | int p; |
644 | 661 | ||
645 | (void)userdata; | 662 | (void) userdata; |
646 | GNUNET_assert(NULL != c); | 663 | GNUNET_assert (NULL != c); |
647 | switch (pa_context_get_state(c)) | 664 | switch (pa_context_get_state (c)) |
648 | { | 665 | { |
649 | case PA_CONTEXT_CONNECTING: | 666 | case PA_CONTEXT_CONNECTING: |
650 | case PA_CONTEXT_AUTHORIZING: | 667 | case PA_CONTEXT_AUTHORIZING: |
651 | case PA_CONTEXT_SETTING_NAME: | 668 | case PA_CONTEXT_SETTING_NAME: |
652 | break; | 669 | break; |
653 | 670 | ||
654 | case PA_CONTEXT_READY: | 671 | case PA_CONTEXT_READY: |
655 | { | 672 | { |
656 | GNUNET_assert(!stream_out); | 673 | GNUNET_assert (! stream_out); |
657 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, | 674 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
658 | _("Connection established.\n")); | 675 | _ ("Connection established.\n")); |
659 | if (!(stream_out = | 676 | if (! (stream_out = |
660 | pa_stream_new(c, "GNUNET VoIP playback", &sample_spec, NULL))) | 677 | pa_stream_new (c, "GNUNET VoIP playback", &sample_spec, NULL))) |
661 | { | 678 | { |
662 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | 679 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
663 | _("pa_stream_new() failed: %s\n"), | 680 | _ ("pa_stream_new() failed: %s\n"), |
664 | pa_strerror(pa_context_errno(c))); | 681 | pa_strerror (pa_context_errno (c))); |
665 | goto fail; | 682 | goto fail; |
666 | } | 683 | } |
667 | pa_stream_set_write_callback(stream_out, | 684 | pa_stream_set_write_callback (stream_out, |
668 | &stream_write_callback, | 685 | &stream_write_callback, |
669 | NULL); | 686 | NULL); |
670 | if ((p = | 687 | if ((p = |
671 | pa_stream_connect_playback(stream_out, NULL, | 688 | pa_stream_connect_playback (stream_out, NULL, |
672 | NULL, | 689 | NULL, |
673 | PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE, | 690 | PA_STREAM_ADJUST_LATENCY |
674 | NULL, NULL)) < 0) | 691 | | PA_STREAM_INTERPOLATE_TIMING |
675 | { | 692 | | PA_STREAM_AUTO_TIMING_UPDATE, |
676 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | 693 | NULL, NULL)) < 0) |
677 | _("pa_stream_connect_playback() failed: %s\n"), | 694 | { |
678 | pa_strerror(pa_context_errno(c))); | 695 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
679 | goto fail; | 696 | _ ("pa_stream_connect_playback() failed: %s\n"), |
680 | } | 697 | pa_strerror (pa_context_errno (c))); |
698 | goto fail; | ||
699 | } | ||
681 | break; | 700 | break; |
682 | } | 701 | } |
683 | 702 | ||
684 | case PA_CONTEXT_TERMINATED: | 703 | case PA_CONTEXT_TERMINATED: |
685 | quit(0); | 704 | quit (0); |
686 | break; | 705 | break; |
687 | 706 | ||
688 | case PA_CONTEXT_FAILED: | 707 | case PA_CONTEXT_FAILED: |
689 | default: | 708 | default: |
690 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | 709 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
691 | _("Connection failure: %s\n"), | 710 | _ ("Connection failure: %s\n"), |
692 | pa_strerror(pa_context_errno(c))); | 711 | pa_strerror (pa_context_errno (c))); |
693 | goto fail; | 712 | goto fail; |
694 | } | 713 | } |
695 | return; | 714 | return; |
696 | fail: | 715 | fail: |
697 | quit(1); | 716 | quit (1); |
698 | } | 717 | } |
699 | 718 | ||
700 | 719 | ||
@@ -702,66 +721,66 @@ fail: | |||
702 | * Pulseaudio initialization | 721 | * Pulseaudio initialization |
703 | */ | 722 | */ |
704 | static void | 723 | static void |
705 | pa_init() | 724 | pa_init () |
706 | { | 725 | { |
707 | int r; | 726 | int r; |
708 | 727 | ||
709 | if (!pa_sample_spec_valid(&sample_spec)) | 728 | if (! pa_sample_spec_valid (&sample_spec)) |
710 | { | 729 | { |
711 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, | 730 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
712 | _("Wrong Spec\n")); | 731 | _ ("Wrong Spec\n")); |
713 | } | 732 | } |
714 | /* set up threaded playback mainloop */ | 733 | /* set up threaded playback mainloop */ |
715 | if (!(m = pa_threaded_mainloop_new())) | 734 | if (! (m = pa_threaded_mainloop_new ())) |
716 | { | 735 | { |
717 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | 736 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
718 | _("pa_mainloop_new() failed.\n")); | 737 | _ ("pa_mainloop_new() failed.\n")); |
719 | } | 738 | } |
720 | mainloop_api = pa_threaded_mainloop_get_api(m); | 739 | mainloop_api = pa_threaded_mainloop_get_api (m); |
721 | /* listen to signals */ | 740 | /* listen to signals */ |
722 | r = pa_signal_init(mainloop_api); | 741 | r = pa_signal_init (mainloop_api); |
723 | GNUNET_assert(r == 0); | 742 | GNUNET_assert (r == 0); |
724 | pa_signal_new(SIGINT, exit_signal_callback, NULL); | 743 | pa_signal_new (SIGINT, exit_signal_callback, NULL); |
725 | pa_signal_new(SIGTERM, exit_signal_callback, NULL); | 744 | pa_signal_new (SIGTERM, exit_signal_callback, NULL); |
726 | 745 | ||
727 | 746 | ||
728 | /* connect to the main pulseaudio context */ | 747 | /* connect to the main pulseaudio context */ |
729 | if (!(context = pa_context_new(mainloop_api, "GNUnet VoIP"))) | 748 | if (! (context = pa_context_new (mainloop_api, "GNUnet VoIP"))) |
730 | { | 749 | { |
731 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | 750 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
732 | _("pa_context_new() failed.\n")); | 751 | _ ("pa_context_new() failed.\n")); |
733 | } | 752 | } |
734 | pa_context_set_state_callback(context, context_state_callback, NULL); | 753 | pa_context_set_state_callback (context, context_state_callback, NULL); |
735 | 754 | ||
736 | if (pa_context_connect(context, NULL, 0, NULL) < 0) | 755 | if (pa_context_connect (context, NULL, 0, NULL) < 0) |
737 | { | 756 | { |
738 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | 757 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
739 | _("pa_context_connect() failed: %s\n"), | 758 | _ ("pa_context_connect() failed: %s\n"), |
740 | pa_strerror(pa_context_errno(context))); | 759 | pa_strerror (pa_context_errno (context))); |
741 | } | 760 | } |
742 | if (pa_threaded_mainloop_start(m) < 0) | 761 | if (pa_threaded_mainloop_start (m) < 0) |
743 | { | 762 | { |
744 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | 763 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
745 | _("pa_mainloop_run() failed.\n")); | 764 | _ ("pa_mainloop_run() failed.\n")); |
746 | } | 765 | } |
747 | } | 766 | } |
748 | 767 | ||
749 | 768 | ||
750 | static void | 769 | static void |
751 | ogg_init() | 770 | ogg_init () |
752 | { | 771 | { |
753 | ogg_sync_init(&oy); | 772 | ogg_sync_init (&oy); |
754 | } | 773 | } |
755 | 774 | ||
756 | 775 | ||
757 | static void | 776 | static void |
758 | drain_callback(pa_stream*s, int success, void *userdata) | 777 | drain_callback (pa_stream*s, int success, void *userdata) |
759 | { | 778 | { |
760 | (void)s; | 779 | (void) s; |
761 | (void)success; | 780 | (void) success; |
762 | (void)userdata; | 781 | (void) userdata; |
763 | pa_threaded_mainloop_signal(m, | 782 | pa_threaded_mainloop_signal (m, |
764 | 0); | 783 | 0); |
765 | } | 784 | } |
766 | 785 | ||
767 | 786 | ||
@@ -773,7 +792,7 @@ drain_callback(pa_stream*s, int success, void *userdata) | |||
773 | * @return 0 ok, 1 on error | 792 | * @return 0 ok, 1 on error |
774 | */ | 793 | */ |
775 | int | 794 | int |
776 | main(int argc, char *argv[]) | 795 | main (int argc, char *argv[]) |
777 | { | 796 | { |
778 | static unsigned long long toff; | 797 | static unsigned long long toff; |
779 | char readbuf[MAXLINE]; | 798 | char readbuf[MAXLINE]; |
@@ -782,87 +801,87 @@ main(int argc, char *argv[]) | |||
782 | ssize_t ret; | 801 | ssize_t ret; |
783 | 802 | ||
784 | #ifdef DEBUG_READ_PURE_OGG | 803 | #ifdef DEBUG_READ_PURE_OGG |
785 | int read_pure_ogg = getenv("GNUNET_READ_PURE_OGG") ? 1 : 0; | 804 | int read_pure_ogg = getenv ("GNUNET_READ_PURE_OGG") ? 1 : 0; |
786 | #endif | 805 | #endif |
787 | 806 | ||
788 | (void)argc; | 807 | (void) argc; |
789 | (void)argv; | 808 | (void) argv; |
790 | GNUNET_assert(GNUNET_OK == | 809 | GNUNET_assert (GNUNET_OK == |
791 | GNUNET_log_setup("gnunet-helper-audio-playback", | 810 | GNUNET_log_setup ("gnunet-helper-audio-playback", |
792 | "WARNING", | 811 | "WARNING", |
793 | NULL)); | 812 | NULL)); |
794 | if (0 != pipe(ready_pipe)) | 813 | if (0 != pipe (ready_pipe)) |
795 | { | 814 | { |
796 | GNUNET_log_strerror(GNUNET_ERROR_TYPE_ERROR, "pipe"); | 815 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "pipe"); |
797 | return 1; | 816 | return 1; |
798 | } | 817 | } |
799 | stdin_mst = GNUNET_MST_create(&stdin_receiver, NULL); | 818 | stdin_mst = GNUNET_MST_create (&stdin_receiver, NULL); |
800 | ogg_init(); | 819 | ogg_init (); |
801 | pa_init(); | 820 | pa_init (); |
802 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | 821 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
803 | "Waiting for PulseAudio to be ready.\n"); | 822 | "Waiting for PulseAudio to be ready.\n"); |
804 | GNUNET_assert(1 == read(ready_pipe[0], &c, 1)); | 823 | GNUNET_assert (1 == read (ready_pipe[0], &c, 1)); |
805 | close(ready_pipe[0]); | 824 | close (ready_pipe[0]); |
806 | close(ready_pipe[1]); | 825 | close (ready_pipe[1]); |
807 | ready_pipe[0] = -1; | 826 | ready_pipe[0] = -1; |
808 | ready_pipe[1] = -1; | 827 | ready_pipe[1] = -1; |
809 | #ifdef DEBUG_DUMP_DECODED_OGG | 828 | #ifdef DEBUG_DUMP_DECODED_OGG |
810 | dump_to_stdout = getenv("GNUNET_DUMP_DECODED_OGG") ? 1 : 0; | 829 | dump_to_stdout = getenv ("GNUNET_DUMP_DECODED_OGG") ? 1 : 0; |
811 | #endif | 830 | #endif |
812 | while (1) | 831 | while (1) |
832 | { | ||
833 | ret = read (STDIN_FILENO, | ||
834 | readbuf, | ||
835 | sizeof(readbuf)); | ||
836 | toff += ret; | ||
837 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
838 | "Received %d bytes of audio data (total: %llu)\n", | ||
839 | (int) ret, | ||
840 | toff); | ||
841 | if (0 > ret) | ||
813 | { | 842 | { |
814 | ret = read(STDIN_FILENO, | 843 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
815 | readbuf, | 844 | _ ("Read error from STDIN: %s\n"), |
816 | sizeof(readbuf)); | 845 | strerror (errno)); |
817 | toff += ret; | 846 | break; |
818 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | 847 | } |
819 | "Received %d bytes of audio data (total: %llu)\n", | 848 | if (0 == ret) |
820 | (int)ret, | 849 | break; |
821 | toff); | ||
822 | if (0 > ret) | ||
823 | { | ||
824 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
825 | _("Read error from STDIN: %s\n"), | ||
826 | strerror(errno)); | ||
827 | break; | ||
828 | } | ||
829 | if (0 == ret) | ||
830 | break; | ||
831 | #ifdef DEBUG_READ_PURE_OGG | 850 | #ifdef DEBUG_READ_PURE_OGG |
832 | if (read_pure_ogg) | 851 | if (read_pure_ogg) |
833 | { | 852 | { |
834 | char *data = ogg_sync_buffer(&oy, ret); | 853 | char *data = ogg_sync_buffer (&oy, ret); |
835 | GNUNET_memcpy(data, readbuf, ret); | 854 | GNUNET_memcpy (data, readbuf, ret); |
836 | ogg_sync_wrote(&oy, ret); | 855 | ogg_sync_wrote (&oy, ret); |
837 | ogg_demux_and_decode(); | 856 | ogg_demux_and_decode (); |
838 | } | ||
839 | else | ||
840 | #endif | ||
841 | GNUNET_MST_from_buffer(stdin_mst, | ||
842 | readbuf, ret, | ||
843 | GNUNET_NO, GNUNET_NO); | ||
844 | } | 857 | } |
845 | GNUNET_MST_destroy(stdin_mst); | 858 | else |
859 | #endif | ||
860 | GNUNET_MST_from_buffer (stdin_mst, | ||
861 | readbuf, ret, | ||
862 | GNUNET_NO, GNUNET_NO); | ||
863 | } | ||
864 | GNUNET_MST_destroy (stdin_mst); | ||
846 | if (stream_out) | 865 | if (stream_out) |
866 | { | ||
867 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
868 | "Locking\n"); | ||
869 | pa_threaded_mainloop_lock (m); | ||
870 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
871 | "Draining\n"); | ||
872 | pa_operation *o = pa_stream_drain (stream_out, drain_callback, NULL); | ||
873 | while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) | ||
847 | { | 874 | { |
848 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | 875 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
849 | "Locking\n"); | 876 | "Waiting\n"); |
850 | pa_threaded_mainloop_lock(m); | 877 | pa_threaded_mainloop_wait (m); |
851 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
852 | "Draining\n"); | ||
853 | pa_operation *o = pa_stream_drain(stream_out, drain_callback, NULL); | ||
854 | while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) | ||
855 | { | ||
856 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
857 | "Waiting\n"); | ||
858 | pa_threaded_mainloop_wait(m); | ||
859 | } | ||
860 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
861 | "Unreffing\n"); | ||
862 | pa_operation_unref(o); | ||
863 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
864 | "Unlocking\n"); | ||
865 | pa_threaded_mainloop_unlock(m); | ||
866 | } | 878 | } |
879 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
880 | "Unreffing\n"); | ||
881 | pa_operation_unref (o); | ||
882 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
883 | "Unlocking\n"); | ||
884 | pa_threaded_mainloop_unlock (m); | ||
885 | } | ||
867 | return 0; | 886 | return 0; |
868 | } | 887 | } |