aboutsummaryrefslogtreecommitdiff
path: root/gtk/soundout/alsaout.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/soundout/alsaout.c')
-rw-r--r--gtk/soundout/alsaout.c152
1 files changed, 0 insertions, 152 deletions
diff --git a/gtk/soundout/alsaout.c b/gtk/soundout/alsaout.c
deleted file mode 100644
index 5c5e667..0000000
--- a/gtk/soundout/alsaout.c
+++ /dev/null
@@ -1,152 +0,0 @@
-#include "alsaout.h"
-#include <stdbool.h>
-#include <stdatomic.h>
-#include <stdlib.h>
-#include <sys/eventfd.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <poll.h>
-#include <asoundlib.h>
-
-enum {
- BUF_FRAMES = 1024,
-};
-
-struct alsaout_state {
- struct sound_state ss;
- sound_callback cbfunc;
- void *userptr;
- snd_pcm_t *apcm;
- int fd_event;
- int fds_space;
- struct pollfd *fds;
- bool paused;
- bool terminate;
- atomic_flag cb_flag;
- bool thread_valid;
- pthread_t alsa_thread;
- int16_t buf[BUF_FRAMES*2];
-};
-
-static void *alsaout_thread(void *ptr) {
- struct alsaout_state *as = ptr;
- for (;;) {
- as->fds[0] = (struct pollfd) {
- .fd = as->fd_event,
- .events = POLLIN,
- };
- int fd_cnt = 1;
- fd_cnt += snd_pcm_poll_descriptors(
- as->apcm, as->fds + 1, as->fds_space - 1
- );
- int err = poll(as->fds, fd_cnt, -1);
- if (err <= 0) {
- continue;
- }
- if (as->terminate) return 0;
- if (as->fds[0].revents) {
- uint64_t eventdata;
- read(as->fd_event, &eventdata, sizeof(eventdata));
- }
- unsigned short event;
- if (snd_pcm_poll_descriptors_revents(
- as->apcm, as->fds + 1, fd_cnt - 1, &event) < 0) continue;
- if (!event) continue;
- snd_pcm_sframes_t frames = snd_pcm_avail_update(as->apcm);
- if (frames <= 0) continue;
- while (frames) {
- snd_pcm_sframes_t genframes = frames;
- if (genframes > BUF_FRAMES) genframes = BUF_FRAMES;
- while (atomic_flag_test_and_set_explicit(
- &as->cb_flag, memory_order_acquire));
- if (as->paused) {
- atomic_flag_clear_explicit(&as->cb_flag, memory_order_release);
- break;
- }
- as->cbfunc(as->userptr, as->buf, genframes);
- atomic_flag_clear_explicit(&as->cb_flag, memory_order_release);
- frames -= genframes;
- if (snd_pcm_state(as->apcm) == SND_PCM_STATE_XRUN) {
- err = snd_pcm_prepare(as->apcm);
- }
- snd_pcm_sframes_t written = snd_pcm_writei(as->apcm, as->buf, genframes);
- if (written < 0) {
- snd_pcm_prepare(as->apcm);
- }
- }
- }
-}
-
-static void alsaout_pause(struct sound_state *ss, int pause, int flush) {
- struct alsaout_state *as = (struct alsaout_state *)ss;
-
- while (atomic_flag_test_and_set_explicit(
- &as->cb_flag, memory_order_acquire));
- as->paused = pause;
- snd_pcm_pause(as->apcm, pause);
- atomic_flag_clear_explicit(&as->cb_flag, memory_order_release);
- uint64_t event = 1;
- write(as->fd_event, &event, sizeof(event));
-}
-
-static void alsaout_free(struct sound_state *ss) {
- if (!ss) return;
- struct alsaout_state *as = (struct alsaout_state *)ss;
- if (as->thread_valid) {
- as->terminate = true;
- uint64_t event = 1;
- write(as->fd_event, &event, sizeof(event));
- pthread_join(as->alsa_thread, 0);
- }
- if (as->fd_event != -1) {
- close(as->fd_event);
- }
- if (as->fds) free(as->fds);
- if (as->apcm) {
- snd_pcm_close(as->apcm);
- }
- free(as);
-}
-
-struct sound_state *alsaout_init(
- const char *clientname, unsigned srate,
- sound_callback cbfunc, void *userptr) {
- (void)clientname;
- struct alsaout_state *as = malloc(sizeof(*as));
- if (!as) goto err;
- *as = (struct alsaout_state) {
- .ss = {
- .pause = alsaout_pause,
- .free = alsaout_free,
- .apiname = "ALSA",
- },
- .cbfunc = cbfunc,
- .userptr = userptr,
- .fd_event = -1,
- .cb_flag = ATOMIC_FLAG_INIT,
- .paused = true,
- };
- if (snd_pcm_open(&as->apcm, "default", SND_PCM_STREAM_PLAYBACK, 0)) {
- goto err;
- }
- as->fd_event = eventfd(0, EFD_CLOEXEC);
- if (as->fd_event < 0) goto err;
- as->fds_space = snd_pcm_poll_descriptors_count(as->apcm) + 1;
- as->fds = malloc(sizeof(*as->fds) * as->fds_space);
- if (!as->fds) goto err;
- if (snd_pcm_set_params(
- as->apcm,
- SND_PCM_FORMAT_S16, SND_PCM_ACCESS_RW_INTERLEAVED, 2, srate, 1,
- 1000*1000/60)) {
- goto err;
- }
- if (pthread_create(&as->alsa_thread, 0, alsaout_thread, as)) {
- goto err;
- }
- as->thread_valid = true;
- return as;
-
-err:
- alsaout_free(&as->ss);
- return 0;
-}