diff options
Diffstat (limited to 'gtk/soundout/pulseout.c')
-rw-r--r-- | gtk/soundout/pulseout.c | 133 |
1 files changed, 0 insertions, 133 deletions
diff --git a/gtk/soundout/pulseout.c b/gtk/soundout/pulseout.c deleted file mode 100644 index 9dbcd6c..0000000 --- a/gtk/soundout/pulseout.c +++ /dev/null @@ -1,133 +0,0 @@ -#include "pulseout.h" - -#include <stdbool.h> -#include <stdlib.h> -#include <pulse/thread-mainloop.h> -#include <pulse/stream.h> - -struct pulseout_state { - struct sound_state ss; - bool paused; - bool flush; - unsigned srate; - sound_callback cbfunc; - void *userptr; - pa_threaded_mainloop *pa_tm; - pa_context *pa_c; - pa_stream *pa_s; - bool pa_status_changed; -}; - -static void pulseout_pause(struct sound_state *ss, int pause, int flush) { - //return; - struct pulseout_state *ps = (struct pulseout_state *)ss; - if (ps->paused != !!pause) { - if (pause) { - pa_threaded_mainloop_lock(ps->pa_tm); - } - ps->paused = pause; - if (!pause) { - if (flush) ps->flush = true; - pa_threaded_mainloop_unlock(ps->pa_tm); - } - } -} - -static void pulseout_free(struct sound_state *ss) { - struct pulseout_state *ps = (struct pulseout_state *)ss; - if (ps) { - if (ps->pa_tm) { - if (ps->paused) pa_threaded_mainloop_unlock(ps->pa_tm); - pa_threaded_mainloop_stop(ps->pa_tm); - if (ps->pa_s) { - pa_stream_disconnect(ps->pa_s); - pa_stream_unref(ps->pa_s); - } - if (ps->pa_c) pa_context_unref(ps->pa_c); - pa_threaded_mainloop_free(ps->pa_tm); - } - free(ps); - } -} - -static void pulseout_cb(pa_stream *p, size_t bytes, void *userdata) { - struct pulseout_state *ps = userdata; - int16_t *buf; - pa_stream_begin_write(p, (void **)&buf, &bytes); - size_t nframes = bytes / (2 * sizeof(int16_t)); - if (!ps->paused) { - ps->cbfunc(ps->userptr, buf, nframes); - } else { - for (size_t i = 0; i < nframes; i++) { - buf[i*2+0] = 0; - buf[i*2+1] = 0; - } - } - pa_seek_mode_t smode = - ps->flush ? PA_SEEK_RELATIVE_ON_READ : PA_SEEK_RELATIVE; - pa_stream_write(p, buf, nframes * 2 * sizeof(int16_t), 0, 0, smode); - ps->flush = false; -} - -static void pa_c_cb(pa_context *pa_c, void *userdata) { - struct pulseout_state *ps = userdata; - ps->pa_status_changed = true; - pa_threaded_mainloop_signal(ps->pa_tm, 0); -} - -struct sound_state *pulseout_init( - const char *clientname, unsigned srate, - sound_callback cbfunc, void *userptr) { - struct pulseout_state *ps = malloc(sizeof(*ps)); - if (!ps) goto err; - *ps = (struct pulseout_state){ - .ss = { - .pause = pulseout_pause, - .free = pulseout_free, - .apiname = "PulseAudio", - }, - .cbfunc = cbfunc, - .userptr = userptr, - .paused = false, - .srate = srate, - }; - ps->pa_tm = pa_threaded_mainloop_new(); - if (!ps->pa_tm) goto err; - ps->pa_c = pa_context_new( - pa_threaded_mainloop_get_api(ps->pa_tm), clientname - ); - if (!ps->pa_c) goto err; - if (pa_context_connect(ps->pa_c, 0, 0, 0) < 0) goto err; - pa_context_set_state_callback(ps->pa_c, pa_c_cb, ps); - if (pa_threaded_mainloop_start(ps->pa_tm) < 0) goto err; - pa_threaded_mainloop_lock(ps->pa_tm); - ps->paused = true; - for (;;) { - while (!ps->pa_status_changed) { - pa_threaded_mainloop_wait(ps->pa_tm); - } - ps->pa_status_changed = false; - pa_context_state_t state = pa_context_get_state(ps->pa_c); - if (state == PA_CONTEXT_CONNECTING || - state == PA_CONTEXT_AUTHORIZING || - state == PA_CONTEXT_SETTING_NAME) continue; - else if (state == PA_CONTEXT_READY) break; - else goto err; - } - pa_sample_spec ss = { - .format = PA_SAMPLE_S16NE, - .rate = ps->srate, - .channels = 2, - }; - ps->pa_s = pa_stream_new( - ps->pa_c, - "stereoout", &ss, 0 - ); - if (!ps->pa_s) goto err; - pa_stream_set_write_callback(ps->pa_s, pulseout_cb, ps); - if (pa_stream_connect_playback(ps->pa_s, 0, 0, 0, 0, 0) < 0) goto err; - return &ps->ss; -err: - pulseout_free(&ps->ss); - return 0; -} |