static int outstream_start_pa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { SoundIoOutStream *outstream = &os->pub; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio; pa_threaded_mainloop_lock(sipa->main_loop); ospa->write_byte_count = pa_stream_writable_size(ospa->stream); int frame_count = ospa->write_byte_count / outstream->bytes_per_frame; outstream->write_callback(outstream, 0, frame_count); pa_operation *op = pa_stream_cork(ospa->stream, false, nullptr, nullptr); if (!op) { pa_threaded_mainloop_unlock(sipa->main_loop); return SoundIoErrorStreaming; } pa_operation_unref(op); pa_stream_set_write_callback(ospa->stream, playback_stream_write_callback, os); pa_stream_set_underflow_callback(ospa->stream, playback_stream_underflow_callback, outstream); pa_stream_set_overflow_callback(ospa->stream, playback_stream_underflow_callback, outstream); pa_threaded_mainloop_unlock(sipa->main_loop); return 0; }
static int outstream_sample_rate_callback(jack_nframes_t nframes, void *arg) { SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg; SoundIoOutStream *outstream = &os->pub; if (nframes == (jack_nframes_t)outstream->sample_rate) { return 0; } else { outstream->error_callback(outstream, SoundIoErrorStreaming); return -1; } }
static int outstream_buffer_size_callback(jack_nframes_t nframes, void *arg) { SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg; SoundIoOutStreamJack *osj = &os->backend_data.jack; SoundIoOutStream *outstream = &os->pub; if ((jack_nframes_t)osj->period_size == nframes) { return 0; } else { outstream->error_callback(outstream, SoundIoErrorStreaming); return -1; } }
static int outstream_process_callback(jack_nframes_t nframes, void *arg) { SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg; SoundIoOutStreamJack *osj = &os->backend_data.jack; SoundIoOutStream *outstream = &os->pub; osj->frames_left = nframes; for (int ch = 0; ch < outstream->layout.channel_count; ch += 1) { SoundIoOutStreamJackPort *osjp = &osj->ports[ch]; osj->areas[ch].ptr = (char*)jack_port_get_buffer(osjp->source_port, nframes); osj->areas[ch].step = outstream->bytes_per_sample; } outstream->write_callback(outstream, osj->frames_left, osj->frames_left); return 0; }
static void playback_stream_state_callback(pa_stream *stream, void *userdata) { SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate*) userdata; SoundIoOutStream *outstream = &os->pub; SoundIo *soundio = outstream->device->soundio; SoundIoPrivate *si = (SoundIoPrivate *)soundio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; SoundIoOutStreamPulseAudio *ospa = &os->backend_data.pulseaudio; switch (pa_stream_get_state(stream)) { case PA_STREAM_UNCONNECTED: case PA_STREAM_CREATING: case PA_STREAM_TERMINATED: break; case PA_STREAM_READY: ospa->stream_ready = true; pa_threaded_mainloop_signal(sipa->main_loop, 0); break; case PA_STREAM_FAILED: outstream->error_callback(outstream, SoundIoErrorStreaming); break; } }
static void outstream_shutdown_callback(void *arg) { SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg; SoundIoOutStream *outstream = &os->pub; outstream->error_callback(outstream, SoundIoErrorStreaming); }
static int outstream_xrun_callback(void *arg) { SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg; SoundIoOutStream *outstream = &os->pub; outstream->underflow_callback(outstream); return 0; }
static void playback_stream_write_callback(pa_stream *stream, size_t nbytes, void *userdata) { SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate*)(userdata); SoundIoOutStream *outstream = &os->pub; int frame_count = nbytes / outstream->bytes_per_frame; outstream->write_callback(outstream, 0, frame_count); }
static void playback_stream_underflow_callback(pa_stream *stream, void *userdata) { SoundIoOutStream *outstream = (SoundIoOutStream*)userdata; outstream->underflow_callback(outstream); }