X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/42f738c244c06450e25775631b73ac2fa0878da5..bfdadcc93fcb88261478c1b04d32e619fd961a13:/lib/uaudio-alsa.c?ds=sidebyside diff --git a/lib/uaudio-alsa.c b/lib/uaudio-alsa.c index 2236c91..3cec315 100644 --- a/lib/uaudio-alsa.c +++ b/lib/uaudio-alsa.c @@ -26,6 +26,7 @@ #include "mem.h" #include "log.h" #include "uaudio.h" +#include "configuration.h" /** @brief The current PCM handle */ static snd_pcm_t *alsa_pcm; @@ -56,7 +57,24 @@ static long alsa_mixer_min; static long alsa_mixer_max; /** @brief Actually play sound via ALSA */ -static size_t alsa_play(void *buffer, size_t samples) { +static size_t alsa_play(void *buffer, size_t samples, unsigned flags) { + /* If we're paused we just pretend. We rely on snd_pcm_writei() blocking so + * we have to fake up a sleep here. However it doesn't have to be all that + * accurate - in particular it's quite acceptable to greatly underestimate + * the required wait time. For 'lengthy' waits we do this by the blunt + * instrument of halving it. */ + if(flags & UAUDIO_PAUSED) { + if(samples > 64) + samples /= 2; + const uint64_t ns = ((uint64_t)samples * 1000000000 + / (uaudio_rate * uaudio_channels)); + struct timespec ts[1]; + ts->tv_sec = ns / 1000000000; + ts->tv_nsec = ns % 1000000000; + while(nanosleep(ts, ts) < 0 && errno == EINTR) + ; + return samples; + } int err; /* ALSA wants 'frames', where frame = several concurrently played samples */ const snd_pcm_uframes_t frames = samples / uaudio_channels; @@ -116,14 +134,6 @@ static void alsa_open(void) { } -static void alsa_activate(void) { - uaudio_thread_activate(); -} - -static void alsa_deactivate(void) { - uaudio_thread_deactivate(); -} - static void alsa_start(uaudio_callback *callback, void *userdata) { if(uaudio_channels != 1 && uaudio_channels != 2) @@ -135,7 +145,8 @@ static void alsa_start(uaudio_callback *callback, alsa_open(); uaudio_thread_start(callback, userdata, alsa_play, 32 / uaudio_sample_size, - 4096 / uaudio_sample_size); + 4096 / uaudio_sample_size, + 0); } static void alsa_stop(void) { @@ -245,17 +256,24 @@ static void alsa_set_volume(int *left, int *right) { *right = to_percent(r); } +static void alsa_configure(void) { + uaudio_set("device", config->device); + uaudio_set("mixer-control", config->mixer); + uaudio_set("mixer-channel", config->channel); +} + const struct uaudio uaudio_alsa = { .name = "alsa", .options = alsa_options, .start = alsa_start, .stop = alsa_stop, - .activate = alsa_activate, - .deactivate = alsa_deactivate, + .activate = uaudio_thread_activate, + .deactivate = uaudio_thread_deactivate, .open_mixer = alsa_open_mixer, .close_mixer = alsa_close_mixer, .get_volume = alsa_get_volume, .set_volume = alsa_set_volume, + .configure = alsa_configure }; #endif