2 e26da60a 2023-03-23 op * Copyright (c) 2023 Omar Polo <op@omarpolo.com>
4 e26da60a 2023-03-23 op * Permission to use, copy, modify, and distribute this software for any
5 e26da60a 2023-03-23 op * purpose with or without fee is hereby granted, provided that the above
6 e26da60a 2023-03-23 op * copyright notice and this permission notice appear in all copies.
8 e26da60a 2023-03-23 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 e26da60a 2023-03-23 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 e26da60a 2023-03-23 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 e26da60a 2023-03-23 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 e26da60a 2023-03-23 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 e26da60a 2023-03-23 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 e26da60a 2023-03-23 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 e26da60a 2023-03-23 op #include "config.h"
19 e26da60a 2023-03-23 op #include <alsa/asoundlib.h>
21 e26da60a 2023-03-23 op #include <limits.h>
23 e26da60a 2023-03-23 op #include "amused.h"
24 e26da60a 2023-03-23 op #include "log.h"
26 e26da60a 2023-03-23 op static snd_pcm_t *pcm;
29 e26da60a 2023-03-23 op audio_open(void (*onmove_cb)(void *, int))
31 e26da60a 2023-03-23 op const char *device = "default";
34 e26da60a 2023-03-23 op err = snd_pcm_open(&pcm, device, SND_PCM_STREAM_PLAYBACK,
35 e26da60a 2023-03-23 op SND_PCM_NONBLOCK);
36 e26da60a 2023-03-23 op if (err < 0) {
37 e26da60a 2023-03-23 op log_warnx("playback open error: %s", snd_strerror(err));
41 e26da60a 2023-03-23 op /* TODO: set up onmove callback? */
46 e26da60a 2023-03-23 op audio_setup(unsigned int bits, unsigned int rate, unsigned int channels,
47 e26da60a 2023-03-23 op struct pollfd *pfds)
50 e26da60a 2023-03-23 op snd_pcm_format_t fmt;
52 e26da60a 2023-03-23 op if (bits == 8)
53 e26da60a 2023-03-23 op fmt = SND_PCM_FORMAT_S8;
54 e26da60a 2023-03-23 op else if (bits == 16)
55 e26da60a 2023-03-23 op fmt = SND_PCM_FORMAT_S16;
56 e26da60a 2023-03-23 op else if (bits == 24)
57 e26da60a 2023-03-23 op fmt = SND_PCM_FORMAT_S24;
58 e26da60a 2023-03-23 op else if (bits == 32)
59 e26da60a 2023-03-23 op fmt = SND_PCM_FORMAT_S32;
61 e26da60a 2023-03-23 op log_warnx("can't handle %d bits", bits);
65 e26da60a 2023-03-23 op err = snd_pcm_set_params(pcm, fmt, SND_PCM_ACCESS_RW_INTERLEAVED,
66 e26da60a 2023-03-23 op channels, rate, 1, 500000 /* 0.5s */);
67 e26da60a 2023-03-23 op if (err < 0) {
68 e26da60a 2023-03-23 op log_warnx("invalid params: %s", snd_strerror(err));
72 e26da60a 2023-03-23 op err = snd_pcm_prepare(pcm);
73 e26da60a 2023-03-23 op if (err < 0) {
74 e26da60a 2023-03-23 op log_warnx("snd_pcm_prepare failed: %s", snd_strerror(err));
82 e26da60a 2023-03-23 op audio_nfds(void)
84 e26da60a 2023-03-23 op return snd_pcm_poll_descriptors_count(pcm);
88 e26da60a 2023-03-23 op audio_pollfd(struct pollfd *pfds, int events)
90 e26da60a 2023-03-23 op return snd_pcm_poll_descriptors(pcm, pfds, audio_nfds());
94 e26da60a 2023-03-23 op audio_revents(struct pollfd *pfds)
97 e26da60a 2023-03-23 op unsigned short revents;
99 e26da60a 2023-03-23 op err = snd_pcm_poll_descriptors_revents(pcm, pfds, audio_nfds(),
101 e26da60a 2023-03-23 op if (err < 0) {
102 e26da60a 2023-03-23 op log_warnx("snd revents failure: %s", snd_strerror(err));
106 e26da60a 2023-03-23 op return revents;
110 e26da60a 2023-03-23 op audio_write(const void *buf, size_t len)
112 e26da60a 2023-03-23 op snd_pcm_sframes_t ret;
114 e26da60a 2023-03-23 op ret = snd_pcm_writei(pcm, buf, len);
115 e26da60a 2023-03-23 op if (ret < 0) {
116 e26da60a 2023-03-23 op log_warnx("snd_pcm_writei failed: %s", snd_strerror(ret));
123 e26da60a 2023-03-23 op audio_flush(void)
127 e26da60a 2023-03-23 op err = snd_pcm_drop(pcm);
128 e26da60a 2023-03-23 op if (err < 0) {
129 e26da60a 2023-03-23 op log_warnx("snd_pcm_drop: %s", snd_strerror(err));
137 e26da60a 2023-03-23 op audio_stop(void)
141 e26da60a 2023-03-23 op err = snd_pcm_drain(pcm);
142 e26da60a 2023-03-23 op if (err < 0) {
143 e26da60a 2023-03-23 op log_warnx("snd_pcm_drain: %s", snd_strerror(err));