/* This is called whenever new data may is available */ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { pa_assert(s); pa_assert(length > 0); if (raw) { pa_assert(!sndfile); if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); while (pa_stream_readable_size(s) > 0) { const void *data; if (pa_stream_peek(s, &data, &length) < 0) { pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } pa_assert(data); pa_assert(length > 0); if (buffer) { buffer = pa_xrealloc(buffer, buffer_length + length); memcpy((uint8_t*) buffer + buffer_length, data, length); buffer_length += length; } else { buffer = pa_xmalloc(length); memcpy(buffer, data, length); buffer_length = length; buffer_index = 0; } pa_stream_drop(s); } } else { pa_assert(sndfile); while (pa_stream_readable_size(s) > 0) { sf_count_t bytes; const void *data; if (pa_stream_peek(s, &data, &length) < 0) { pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } pa_assert(data); pa_assert(length > 0); if (writef_function) { size_t k = pa_frame_size(&sample_spec); if ((bytes = writef_function(sndfile, data, (sf_count_t) (length/k))) > 0) bytes *= (sf_count_t) k; } else bytes = sf_write_raw(sndfile, data, (sf_count_t) length); if (bytes < (sf_count_t) length) quit(1); pa_stream_drop(s); } } }
/* This is called whenever new data may is available */ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { pa_assert(s); pa_assert(length > 0); if (raw) { pa_assert(!sndfile); if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); while (pa_stream_readable_size(s) > 0) { const void *data; if (pa_stream_peek(s, &data, &length) < 0) { pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } pa_assert(length > 0); /* If there is a hole in the stream, we generate silence, except * if it's a passthrough stream in which case we skip the hole. */ if (data || !(flags & PA_STREAM_PASSTHROUGH)) { buffer = pa_xrealloc(buffer, buffer_length + length); if (data) memcpy((uint8_t *) buffer + buffer_length, data, length); else pa_silence_memory((uint8_t *) buffer + buffer_length, length, &sample_spec); buffer_length += length; } pa_stream_drop(s); } } else { pa_assert(sndfile); while (pa_stream_readable_size(s) > 0) { sf_count_t bytes; const void *data; if (pa_stream_peek(s, &data, &length) < 0) { pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } pa_assert(length > 0); if (!data && (flags & PA_STREAM_PASSTHROUGH)) { pa_stream_drop(s); continue; } if (!data && length > silence_buffer_length) { silence_buffer = pa_xrealloc(silence_buffer, length); pa_silence_memory((uint8_t *) silence_buffer + silence_buffer_length, length - silence_buffer_length, &sample_spec); silence_buffer_length = length; } if (writef_function) { size_t k = pa_frame_size(&sample_spec); if ((bytes = writef_function(sndfile, data ? data : silence_buffer, (sf_count_t) (length/k))) > 0) bytes *= (sf_count_t) k; } else bytes = sf_write_raw(sndfile, data ? data : silence_buffer, (sf_count_t) length); if (bytes < (sf_count_t) length) quit(1); pa_stream_drop(s); } } }