commit 35a334b
hovercats
·
2026-01-22 02:58:24 +0000 UTC
parent 994ffce
sndio: import
10 files changed,
+1464,
-0
+4,
-0
1@@ -338,3 +338,7 @@
2 path = pkg/hevel/src
3 url = https://git.sr.ht/~dlm/hevel
4 ignore = all
5+[submodule "pkg/sndio/src"]
6+ path = pkg/sndio/src
7+ url = https://caoua.org/git/sndio
8+ ignore = all
+1,
-0
1@@ -93,6 +93,7 @@ subgen 'scdoc'
2 subgen 'sdhcp'
3 subgen 'skeleton'
4 subgen 'smu'
5+subgen 'sndio'
6 subgen 'squashfs-tools-ng'
7 subgen 'st'
8 subgen 'strace'
+5,
-0
1@@ -0,0 +1,5 @@
2+#define HAVE_ISSETUGID 1
3+#define HAVE_STRLCAT 1
4+#define HAVE_STRLCPY 1
5+#define HAVE_CLOCK_GETTIME 1
6+#define HAVE_SOCK_CLOEXEC 1
+56,
-0
1@@ -0,0 +1,56 @@
2+cflags{
3+ '-std=c99', '-Wall', '-Wpedantic',
4+ '-Wno-format-truncation', '-Wno-maybe-uninitialized',
5+ '-D _GNU_SOURCE',
6+ '-I $srcdir/libsndio',
7+ '-I $srcdir/bsd-compat',
8+ '-isystem $builddir/pkg/tinyalsa/include',
9+ '-include $dir/config.h',
10+}
11+
12+pkg.deps = {
13+ 'pkg/tinyalsa/headers',
14+}
15+pkg.hdrs = copy('$outdir/include', '$srcdir/libsndio', {'sndio.h'})
16+
17+-- everything but mio.c and sio.c
18+local objs = objects[[
19+ libsndio/(
20+ debug.c aucat.c
21+ mio.c mio_aucat.c
22+ sio_aucat.c
23+ sioctl.c sioctl_aucat.c
24+ )
25+ bsd-compat/(getpeereid.c issetugid.c strlcat.c strlcpy.c strtonum.c clock_gettime.c)
26+ $builddir/pkg/tinyalsa/libtinyalsa.a
27+]]
28+
29+-- build mio.c and sio.c for sndiod with alsa support
30+for _, src in ipairs{'sio.c', 'sio_alsa.c'} do
31+ build('cc', '$outdir/sndiod/'..src..'.o', {'$srcdir/libsndio/'..src, '||', '$gendir/deps'}, {
32+ cflags='$cflags -D USE_ALSA',
33+ })
34+end
35+lib('libsndio.a', {objs, 'libsndio/sio.c'})
36+
37+exe('bin/sndiod', {objs, paths[[
38+ sndiod/(
39+ abuf.c utils.c dev.c dev_sioctl.c dsp.c file.c listen.c midi.c miofile.c
40+ opt.c siofile.c sndiod.c sock.c
41+
42+ sio.c.o sio_alsa.c.o
43+ )
44+ $builddir/pkg/tinyalsa/libtinyalsa.a
45+]]})
46+file('bin/sndiod', '755', '$outdir/bin/sndiod')
47+man{'sndiod/sndiod.8'}
48+
49+exe('bin/sndioctl', 'sndioctl/sndioctl.c libsndio.a')
50+file('bin/sndioctl', '755', '$outdir/bin/sndioctl')
51+man{'sndioctl/sndioctl.1'}
52+
53+exe('bin/aucat', 'aucat/(abuf.c afile.c aucat.c dsp.c utils.c) libsndio.a')
54+file('bin/aucat', '755', '$outdir/bin/aucat')
55+man{'aucat/aucat.1'}
56+
57+fetch 'git'
1@@ -0,0 +1,58 @@
2+From 4ee56f07ef8be718bb1f24f5b73c440527c93bc9 Mon Sep 17 00:00:00 2001
3+From: Michael Forney <mforney@mforney.org>
4+Date: Thu, 5 Nov 2020 00:28:06 -0800
5+Subject: [PATCH] sndiod: Fix build without DEBUG
6+
7+---
8+ aucat/afile.c | 4 ++--
9+ sndiod/listen.c | 4 ++++
10+ 2 files changed, 6 insertions(+), 2 deletions(-)
11+
12+diff --git a/aucat/afile.c b/aucat/afile.c
13+index b880878..3e400ce 100644
14+--- a/aucat/afile.c
15++++ b/aucat/afile.c
16+@@ -743,13 +743,13 @@ afile_au_writehdr(struct afile *f)
17+ case 32:
18+ fmt = AU_FMT_PCM32;
19+ break;
20+-#ifdef DEBUG
21+ default:
22++#ifdef DEBUG
23+ log_puts(f->path);
24+ log_puts(": wrong precision\n");
25+ panic();
26+- return 0;
27+ #endif
28++ return 0;
29+ }
30+ be32_set(&hdr.fmt, fmt);
31+ be32_set(&hdr.rate, f->rate);
32+diff --git a/sndiod/listen.c b/sndiod/listen.c
33+index 54c9684..c87f600 100644
34+--- a/sndiod/listen.c
35++++ b/sndiod/listen.c
36+@@ -254,16 +254,20 @@ listen_in(void *arg)
37+ return;
38+ }
39+ if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
40++#ifdef DEBUG
41+ file_log(f->file);
42+ log_puts(": failed to set non-blocking mode\n");
43++#endif
44+ goto bad_close;
45+ }
46+ if (f->path == NULL) {
47+ opt = 1;
48+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
49+ &opt, sizeof(int)) == -1) {
50++#ifdef DEBUG
51+ file_log(f->file);
52+ log_puts(": failed to set TCP_NODELAY flag\n");
53++#endif
54+ goto bad_close;
55+ }
56+ }
57+--
58+2.29.2
59+
1@@ -0,0 +1,26 @@
2+From 7c55a1db6eb0334e3e5902cb52272abd668019df Mon Sep 17 00:00:00 2001
3+From: Michael Forney <mforney@mforney.org>
4+Date: Thu, 5 Nov 2020 00:58:34 -0800
5+Subject: [PATCH] aucat: Use unsigned char for wav_guid to prevent overflow
6+
7+0x80 is not representable as char.
8+---
9+ aucat/afile.c | 2 +-
10+ 1 file changed, 1 insertion(+), 1 deletion(-)
11+
12+diff --git a/aucat/afile.c b/aucat/afile.c
13+index fce69f3..1a37463 100644
14+--- a/aucat/afile.c
15++++ b/aucat/afile.c
16+@@ -135,7 +135,7 @@ const char wav_id_riff[4] = {'R', 'I', 'F', 'F'};
17+ const char wav_id_wave[4] = {'W', 'A', 'V', 'E'};
18+ const char wav_id_data[4] = {'d', 'a', 't', 'a'};
19+ const char wav_id_fmt[4] = {'f', 'm', 't', ' '};
20+-const char wav_guid[14] = {
21++const unsigned char wav_guid[14] = {
22+ 0x00, 0x00, 0x00, 0x00,
23+ 0x10, 0x00, 0x80, 0x00,
24+ 0x00, 0xAA, 0x00, 0x38,
25+--
26+2.30.0
27+
+1171,
-0
1@@ -0,0 +1,1171 @@
2+From 39ec20119841c84500e589fee15c10e9fe6c0c97 Mon Sep 17 00:00:00 2001
3+From: Michael Forney <mforney@mforney.org>
4+Date: Tue, 31 Aug 2021 14:30:07 -0700
5+Subject: [PATCH] alsa: Port to tinyalsa
6+
7+---
8+ libsndio/debug.c | 2 +-
9+ libsndio/sio_alsa.c | 747 +++++++++++++++-----------------------------
10+ 2 files changed, 247 insertions(+), 502 deletions(-)
11+
12+diff --git a/libsndio/debug.c b/libsndio/debug.c
13+index 304975a..40fdc92 100644
14+--- a/libsndio/debug.c
15++++ b/libsndio/debug.c
16+@@ -35,7 +35,7 @@ _sndio_debug_init(void)
17+
18+ if (_sndio_debug < 0) {
19+ dbg = issetugid() ? NULL : getenv("SNDIO_DEBUG");
20+- if (!dbg || sscanf(dbg, "%u", &_sndio_debug) != 1)
21++ if (!dbg || sscanf(dbg, "%d", &_sndio_debug) != 1)
22+ _sndio_debug = 0;
23+ }
24+ }
25+diff --git a/libsndio/sio_alsa.c b/libsndio/sio_alsa.c
26+index 6107617..e460bf6 100644
27+--- a/libsndio/sio_alsa.c
28++++ b/libsndio/sio_alsa.c
29+@@ -29,31 +29,28 @@
30+ #include <string.h>
31+ #include <unistd.h>
32+ #include <values.h>
33+-#include <alsa/asoundlib.h>
34++#include <tinyalsa/asoundlib.h>
35+
36+ #include "debug.h"
37+ #include "sio_priv.h"
38+ #include "bsd-compat.h"
39+
40+-#define DEVNAME_PREFIX "hw:"
41+-
42+ #ifdef DEBUG
43+-static snd_output_t *output = NULL;
44+-#define DALSA(str, err) fprintf(stderr, "%s: %s\n", str, snd_strerror(err))
45++#define DALSA(str, pcm) fprintf(stderr, "%s: %s\n", str, pcm_get_error(pcm))
46+ #else
47+-#define DALSA(str, err) do {} while (0)
48++#define DALSA(str, pcm) do {} while (0)
49+ #endif
50+
51+ struct sio_alsa_hdl {
52+ struct sio_hdl sio;
53+ struct sio_par par;
54+- char *devname;
55+- snd_pcm_t *opcm;
56+- snd_pcm_t *ipcm;
57++ struct pcm_params *opar;
58++ struct pcm_params *ipar;
59++ struct pcm *opcm;
60++ struct pcm *ipcm;
61+ unsigned ibpf, obpf; /* bytes per frame */
62+ int iused, oused; /* frames used in hardware fifos */
63+ int idelta, odelta; /* position reported to client */
64+- int nfds, infds, onfds;
65+ int running;
66+ int events;
67+ int ipartial, opartial;
68+@@ -102,90 +99,56 @@ static unsigned int cap_rates[] = {
69+ 8000, 11025, 12000, 16000, 22050, 24000,
70+ 32000, 44100, 48000, 64000, 88200, 96000
71+ };
72+-static snd_pcm_format_t cap_fmts[] = {
73++static enum pcm_format cap_fmts[] = {
74+ /* XXX add s24le3 and s24be3 */
75+- SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_BE,
76+- SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_BE,
77+- SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE,
78+- SND_PCM_FORMAT_U8
79++ PCM_FORMAT_S32_LE, PCM_FORMAT_S32_BE,
80++ PCM_FORMAT_S24_LE, PCM_FORMAT_S24_BE,
81++ PCM_FORMAT_S16_LE, PCM_FORMAT_S16_BE,
82++ PCM_FORMAT_S8
83+ };
84+
85+ /*
86+ * convert ALSA format to sio_par encoding
87+ */
88+ static int
89+-sio_alsa_fmttopar(struct sio_alsa_hdl *hdl, snd_pcm_format_t fmt,
90++sio_alsa_fmttopar(struct sio_alsa_hdl *hdl, enum pcm_format fmt,
91+ unsigned int *bits, unsigned int *sig, unsigned int *le)
92+ {
93+ switch (fmt) {
94+- case SND_PCM_FORMAT_U8:
95+- *bits = 8;
96+- *sig = 0;
97+- break;
98+- case SND_PCM_FORMAT_S8:
99++ case PCM_FORMAT_S8:
100+ *bits = 8;
101+ *sig = 1;
102+ break;
103+- case SND_PCM_FORMAT_S16_LE:
104++ case PCM_FORMAT_S16_LE:
105+ *bits = 16;
106+ *sig = 1;
107+ *le = 1;
108+ break;
109+- case SND_PCM_FORMAT_S16_BE:
110++ case PCM_FORMAT_S16_BE:
111+ *bits = 16;
112+ *sig = 1;
113+ *le = 0;
114+ break;
115+- case SND_PCM_FORMAT_U16_LE:
116+- *bits = 16;
117+- *sig = 0;
118+- *le = 1;
119+- break;
120+- case SND_PCM_FORMAT_U16_BE:
121+- *bits = 16;
122+- *sig = 0;
123+- *le = 0;
124+- break;
125+- case SND_PCM_FORMAT_S24_LE:
126++ case PCM_FORMAT_S24_LE:
127+ *bits = 24;
128+ *sig = 1;
129+ *le = 1;
130+ break;
131+- case SND_PCM_FORMAT_S24_BE:
132++ case PCM_FORMAT_S24_BE:
133+ *bits = 24;
134+ *sig = 1;
135+ *le = 0;
136+ break;
137+- case SND_PCM_FORMAT_U24_LE:
138+- *bits = 24;
139+- *sig = 0;
140+- *le = 1;
141+- break;
142+- case SND_PCM_FORMAT_U24_BE:
143+- *bits = 24;
144+- *sig = 0;
145+- *le = 0;
146+- break;
147+- case SND_PCM_FORMAT_S32_LE:
148++ case PCM_FORMAT_S32_LE:
149+ *bits = 32;
150+ *sig = 1;
151+ *le = 1;
152+ break;
153+- case SND_PCM_FORMAT_S32_BE:
154++ case PCM_FORMAT_S32_BE:
155+ *bits = 32;
156+ *sig = 1;
157+ *le = 0;
158+ break;
159+- case SND_PCM_FORMAT_U32_LE:
160+- *bits = 32;
161+- *sig = 0;
162+- *le = 1;
163+- break;
164+- case SND_PCM_FORMAT_U32_BE:
165+- *bits = 32;
166+- *sig = 0;
167+- *le = 0;
168+- break;
169+ default:
170+ DPRINTF("sio_alsa_fmttopar: 0x%x: unsupported format\n", fmt);
171+ hdl->sio.eof = 1;
172+@@ -199,78 +162,19 @@ sio_alsa_fmttopar(struct sio_alsa_hdl *hdl, snd_pcm_format_t fmt,
173+ * convert sio_par encoding to ALSA format
174+ */
175+ static void
176+-sio_alsa_enctofmt(struct sio_alsa_hdl *hdl, snd_pcm_format_t *rfmt,
177++sio_alsa_enctofmt(struct sio_alsa_hdl *hdl, enum pcm_format *rfmt,
178+ unsigned int bits, unsigned int sig, unsigned int le)
179+ {
180+- if (bits == 8) {
181+- if (sig == ~0U || !sig)
182+- *rfmt = SND_PCM_FORMAT_U8;
183+- else
184+- *rfmt = SND_PCM_FORMAT_S8;
185+- } else if (bits == 16) {
186+- if (sig == ~0U || sig) {
187+- if (le == ~0U) {
188+- *rfmt = SIO_LE_NATIVE ?
189+- SND_PCM_FORMAT_S16_LE :
190+- SND_PCM_FORMAT_S16_BE;
191+- } else if (le)
192+- *rfmt = SND_PCM_FORMAT_S16_LE;
193+- else
194+- *rfmt = SND_PCM_FORMAT_S16_BE;
195+- } else {
196+- if (le == ~0U) {
197+- *rfmt = SIO_LE_NATIVE ?
198+- SND_PCM_FORMAT_U16_LE :
199+- SND_PCM_FORMAT_U16_BE;
200+- } else if (le)
201+- *rfmt = SND_PCM_FORMAT_U16_LE;
202+- else
203+- *rfmt = SND_PCM_FORMAT_U16_BE;
204+- }
205+- } else if (bits == 24) {
206+- if (sig == ~0U || sig) {
207+- if (le == ~0U) {
208+- *rfmt = SIO_LE_NATIVE ?
209+- SND_PCM_FORMAT_S24_LE :
210+- SND_PCM_FORMAT_S24_BE;
211+- } else if (le)
212+- *rfmt = SND_PCM_FORMAT_S24_LE;
213+- else
214+- *rfmt = SND_PCM_FORMAT_S24_BE;
215+- } else {
216+- if (le == ~0U) {
217+- *rfmt = SIO_LE_NATIVE ?
218+- SND_PCM_FORMAT_U24_LE :
219+- SND_PCM_FORMAT_U24_BE;
220+- } else if (le)
221+- *rfmt = SND_PCM_FORMAT_U24_LE;
222+- else
223+- *rfmt = SND_PCM_FORMAT_U24_BE;
224+- }
225+- } else if (bits == 32) {
226+- if (sig == ~0U || sig) {
227+- if (le == ~0U) {
228+- *rfmt = SIO_LE_NATIVE ?
229+- SND_PCM_FORMAT_S32_LE :
230+- SND_PCM_FORMAT_S32_BE;
231+- } else if (le)
232+- *rfmt = SND_PCM_FORMAT_S32_LE;
233+- else
234+- *rfmt = SND_PCM_FORMAT_S32_BE;
235+- } else {
236+- if (le == ~0U) {
237+- *rfmt = SIO_LE_NATIVE ?
238+- SND_PCM_FORMAT_U32_LE :
239+- SND_PCM_FORMAT_U32_BE;
240+- } else if (le)
241+- *rfmt = SND_PCM_FORMAT_U32_LE;
242+- else
243+- *rfmt = SND_PCM_FORMAT_U32_BE;
244+- }
245+- } else {
246+- *rfmt = SIO_LE_NATIVE ?
247+- SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_S16_BE;
248+- }
249++ if (le == ~0U)
250++ le = SIO_LE_NATIVE;
251++ if (bits == 8)
252++ *rfmt = PCM_FORMAT_S8;
253++ else if (bits == 24)
254++ *rfmt = le ? PCM_FORMAT_S24_LE : PCM_FORMAT_S24_BE;
255++ else if (bits == 32)
256++ *rfmt = le ? PCM_FORMAT_S32_LE : PCM_FORMAT_S32_BE;
257++ else
258++ *rfmt = le ? PCM_FORMAT_S16_LE : PCM_FORMAT_S16_BE;
259+ }
260+
261+ struct sio_hdl *
262+@@ -279,8 +183,7 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio)
263+ const char *p;
264+ struct sio_alsa_hdl *hdl;
265+ struct sio_par par;
266+- size_t len;
267+- int err;
268++ unsigned card, dev;
269+
270+ p = _sndio_parsetype(str, "rsnd");
271+ if (p == NULL) {
272+@@ -300,42 +203,45 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio)
273+ return NULL;
274+ _sio_create(&hdl->sio, &sio_alsa_ops, mode, nbio);
275+
276+-#ifdef DEBUG
277+- err = snd_output_stdio_attach(&output, stderr, 0);
278+- if (err < 0)
279+- DALSA("couldn't attach to stderr", err);
280+-#endif
281+- if (strcmp(p, "default") == 0)
282+- p = "0";
283+- len = strlen(p);
284+- hdl->devname = malloc(len + sizeof(DEVNAME_PREFIX));
285+- if (hdl->devname == NULL)
286+- goto bad_free_hdl;
287+- memcpy(hdl->devname, DEVNAME_PREFIX, sizeof(DEVNAME_PREFIX) - 1);
288+- memcpy(hdl->devname + sizeof(DEVNAME_PREFIX) - 1, p, len + 1);
289++ if (strcmp(p, "default") == 0) {
290++ card = 0;
291++ dev = 0;
292++ } else {
293++ switch (sscanf(p, "%u,%u", &card, &dev)) {
294++ case 1:
295++ dev = 0;
296++ break;
297++ case 2:
298++ break;
299++ default:
300++ DPRINTF("invalid device name\n");
301++ }
302++ }
303+ if (mode & SIO_PLAY) {
304+- err = snd_pcm_open(&hdl->opcm, hdl->devname,
305+- SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
306+- if (err < 0) {
307+- DALSA("couldn't open play stream", err);
308+- goto bad_free;
309++ hdl->opar = pcm_params_get(card, dev, PCM_OUT);
310++ if (hdl->opar == NULL) {
311++ DPRINTF("couldn't get play params\n");
312++ goto bad_free_hdl;
313++ }
314++ hdl->opcm = pcm_open(card, dev, PCM_OUT | PCM_NONBLOCK, NULL);
315++ if (!pcm_is_ready(hdl->opcm)) {
316++ DALSA("couldn't open play stream", hdl->opcm);
317++ goto bad_free_opar;
318+ }
319+ }
320+ if (mode & SIO_REC) {
321+- err = snd_pcm_open(&hdl->ipcm, hdl->devname,
322+- SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
323+- if (err < 0) {
324+- DALSA("couldn't open rec stream", err);
325++ hdl->ipar = pcm_params_get(card, dev, PCM_IN);
326++ if (hdl->ipar == NULL) {
327++ DPRINTF("couldn't get rec params\n");
328+ goto bad_free_opcm;
329+ }
330++ hdl->ipcm = pcm_open(card, dev, PCM_IN | PCM_NONBLOCK, NULL);
331++ if (!pcm_is_ready(hdl->ipcm)) {
332++ DALSA("couldn't open rec stream", hdl->ipcm);
333++ goto bad_free_ipar;
334++ }
335+ }
336+
337+- /*
338+- * snd_pcm_poll_descriptors_count returns a small value
339+- * that grows later, after the stream is started
340+- */
341+- hdl->nfds = SIO_MAXNFDS;
342+-
343+ /*
344+ * Default parameters may not be compatible with libsndio (eg. mulaw
345+ * encodings, different playback and recording parameters, etc...), so
346+@@ -356,12 +262,16 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio)
347+ return (struct sio_hdl *)hdl;
348+ bad_free_ipcm:
349+ if (mode & SIO_REC)
350+- snd_pcm_close(hdl->ipcm);
351++ pcm_close(hdl->ipcm);
352++bad_free_ipar:
353++ if (mode & SIO_REC)
354++ free(hdl->ipar);
355+ bad_free_opcm:
356+ if (mode & SIO_PLAY)
357+- snd_pcm_close(hdl->opcm);
358+-bad_free:
359+- free(hdl->devname);
360++ pcm_close(hdl->opcm);
361++bad_free_opar:
362++ if (mode & SIO_PLAY)
363++ free(hdl->opar);
364+ bad_free_hdl:
365+ free(hdl);
366+ return NULL;
367+@@ -372,11 +282,14 @@ sio_alsa_close(struct sio_hdl *sh)
368+ {
369+ struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
370+
371+- if (hdl->sio.mode & SIO_PLAY)
372+- snd_pcm_close(hdl->opcm);
373+- if (hdl->sio.mode & SIO_REC)
374+- snd_pcm_close(hdl->ipcm);
375+- free(hdl->devname);
376++ if (hdl->sio.mode & SIO_PLAY) {
377++ free(hdl->opar);
378++ pcm_close(hdl->opcm);
379++ }
380++ if (hdl->sio.mode & SIO_REC) {
381++ free(hdl->ipar);
382++ pcm_close(hdl->ipcm);
383++ }
384+ free(hdl);
385+ }
386+
387+@@ -394,14 +307,12 @@ sio_alsa_start(struct sio_hdl *sh)
388+ hdl->oused = 0;
389+ hdl->idelta = 0;
390+ hdl->odelta = 0;
391+- hdl->infds = 0;
392+- hdl->onfds = 0;
393+ hdl->running = 0;
394+
395+ if (hdl->sio.mode & SIO_PLAY) {
396+- err = snd_pcm_prepare(hdl->opcm);
397++ err = pcm_prepare(hdl->opcm);
398+ if (err < 0) {
399+- DALSA("couldn't prepare play stream", err);
400++ DALSA("couldn't prepare play stream", hdl->opcm);
401+ hdl->sio.eof = 1;
402+ return 0;
403+ }
404+@@ -413,9 +324,9 @@ sio_alsa_start(struct sio_hdl *sh)
405+ hdl->opartial = 0;
406+ }
407+ if (hdl->sio.mode & SIO_REC) {
408+- err = snd_pcm_prepare(hdl->ipcm);
409++ err = pcm_prepare(hdl->ipcm);
410+ if (err < 0) {
411+- DALSA("couldn't prepare rec stream", err);
412++ DALSA("couldn't prepare rec stream", hdl->ipcm);
413+ hdl->sio.eof = 1;
414+ return 0;
415+ }
416+@@ -427,17 +338,17 @@ sio_alsa_start(struct sio_hdl *sh)
417+ hdl->ipartial = 0;
418+ }
419+ if ((hdl->sio.mode & SIO_PLAY) && (hdl->sio.mode & SIO_REC)) {
420+- err = snd_pcm_link(hdl->ipcm, hdl->opcm);
421++ err = pcm_link(hdl->ipcm, hdl->opcm);
422+ if (err < 0) {
423+- DALSA("couldn't link streams", err);
424++ DALSA("couldn't link streams", hdl->ipcm);
425+ hdl->sio.eof = 1;
426+ return 0;
427+ }
428+ }
429+ if (!(hdl->sio.mode & SIO_PLAY)) {
430+- err = snd_pcm_start(hdl->ipcm);
431++ err = pcm_start(hdl->ipcm);
432+ if (err < 0) {
433+- DALSA("couldn't start rec stream", err);
434++ DALSA("couldn't start rec stream", hdl->ipcm);
435+ hdl->sio.eof = 1;
436+ return 0;
437+ }
438+@@ -449,30 +360,26 @@ static int
439+ sio_alsa_flush(struct sio_hdl *sh)
440+ {
441+ struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
442+- int err;
443+
444+ if (hdl->sio.mode & SIO_PLAY) {
445+- err = snd_pcm_drop(hdl->opcm);
446+- if (err < 0) {
447+- DALSA("couldn't stop play stream", err);
448++ if (pcm_stop(hdl->opcm) != 0) {
449++ DALSA("couldn't stop play stream", hdl->opcm);
450+ hdl->sio.eof = 1;
451+ return 0;
452+ }
453+ free(hdl->otmpbuf);
454+ }
455+ if (hdl->sio.mode & SIO_REC) {
456+- err = snd_pcm_drop(hdl->ipcm);
457+- if (err < 0) {
458+- DALSA("couldn't stop rec stream", err);
459++ if (pcm_stop(hdl->ipcm) != 0) {
460++ DALSA("couldn't stop rec stream", hdl->ipcm);
461+ hdl->sio.eof = 1;
462+ return 0;
463+ }
464+ free(hdl->itmpbuf);
465+ }
466+ if ((hdl->sio.mode & SIO_PLAY) && (hdl->sio.mode & SIO_REC)) {
467+- err = snd_pcm_unlink(hdl->ipcm);
468+- if (err < 0) {
469+- DALSA("couldn't unlink streams", err);
470++ if (pcm_unlink(hdl->ipcm) != 0) {
471++ DALSA("couldn't unlink streams", hdl->ipcm);
472+ hdl->sio.eof = 1;
473+ return 0;
474+ }
475+@@ -537,143 +444,110 @@ sio_alsa_xrun(struct sio_alsa_hdl *hdl)
476+ }
477+
478+ static int
479+-sio_alsa_setpar_hw(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwp,
480+- snd_pcm_format_t *reqfmt, unsigned int *rate, unsigned int *chans,
481+- snd_pcm_uframes_t *round, unsigned int *periods)
482++sio_alsa_setpar_hw(struct pcm *pcm, struct pcm_params *par,
483++ struct pcm_config *cfg)
484+ {
485+- static snd_pcm_format_t fmts[] = {
486+- SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_BE,
487+- SND_PCM_FORMAT_U32_LE, SND_PCM_FORMAT_U32_BE,
488+- SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_BE,
489+- SND_PCM_FORMAT_U24_LE, SND_PCM_FORMAT_U24_BE,
490+- SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE,
491+- SND_PCM_FORMAT_U16_LE, SND_PCM_FORMAT_U16_BE,
492+- SND_PCM_FORMAT_U8, SND_PCM_FORMAT_S8
493++ static enum pcm_format fmts[] = {
494++ PCM_FORMAT_S32_LE, PCM_FORMAT_S32_BE,
495++ PCM_FORMAT_S24_LE, PCM_FORMAT_S24_BE,
496++ PCM_FORMAT_S16_LE, PCM_FORMAT_S16_BE,
497++ PCM_FORMAT_S8
498+ };
499+- int i, err, dir = 0;
500+- unsigned req_rate, min_periods = 2;
501++ int i, err;
502++ unsigned req_rate;
503++ unsigned min, max;
504+
505+- req_rate = *rate;
506++ /* XXX: HW_FREE */
507+
508+- err = snd_pcm_hw_free(pcm);
509+- if (err < 0) {
510+- DALSA("couldn't reset hw configuration", err);
511+- return 0;
512+- }
513+- err = snd_pcm_hw_params_any(pcm, hwp);
514+- if (err < 0) {
515+- DALSA("couldn't init pars", err);
516+- return 0;
517+- }
518+- err = snd_pcm_hw_params_set_access(pcm, hwp,
519+- SND_PCM_ACCESS_RW_INTERLEAVED);
520+- if (err < 0) {
521+- DALSA("couldn't set interleaved access", err);
522+- return 0;
523+- }
524+- err = snd_pcm_hw_params_test_format(pcm, hwp, *reqfmt);
525+- if (err < 0) {
526++ if (pcm_params_format_test(par, cfg->format) == 0) {
527+ for (i = 0; ; i++) {
528+- if (i == sizeof(fmts) / sizeof(snd_pcm_format_t)) {
529++ if (i == sizeof(fmts) / sizeof(fmts[0])) {
530+ DPRINTF("no known format found\n");
531+ return 0;
532+ }
533+- err = snd_pcm_hw_params_test_format(pcm, hwp, fmts[i]);
534+- if (err)
535++ if (pcm_params_format_test(par, fmts[i]) == 0)
536+ continue;
537+- *reqfmt = fmts[i];
538++ cfg->format = fmts[i];
539+ break;
540+ }
541+ }
542+- err = snd_pcm_hw_params_set_format(pcm, hwp, *reqfmt);
543+- if (err < 0) {
544+- DALSA("couldn't set fmt", err);
545+- return 0;
546+- }
547+- err = snd_pcm_hw_params_set_rate_resample(pcm, hwp, 0);
548+- if (err < 0) {
549+- DALSA("couldn't turn resampling off", err);
550+- return 0;
551+- }
552+- err = snd_pcm_hw_params_set_rate_near(pcm, hwp, rate, 0);
553+- if (err < 0) {
554+- DALSA("couldn't set rate", err);
555+- return 0;
556+- }
557+- err = snd_pcm_hw_params_set_channels_near(pcm, hwp, chans);
558+- if (err < 0) {
559+- DALSA("couldn't set channel count", err);
560+- return 0;
561+- }
562+- err = snd_pcm_hw_params_set_periods_integer(pcm, hwp);
563+- if (err < 0) {
564+- DALSA("couldn't set periods to integer", err);
565+- return 0;
566+- }
567+- err = snd_pcm_hw_params_set_periods_min(pcm, hwp, &min_periods, NULL);
568+- if (err < 0) {
569+- DALSA("couldn't set minimum periods", err);
570+- return 0;
571+- }
572+- err = snd_pcm_hw_params_set_period_size_integer(pcm, hwp);
573+- if (err < 0) {
574+- DALSA("couldn't set period to integer", err);
575+- return 0;
576+- }
577+-
578+- *round = *round * *rate / req_rate;
579+- *round = (*round + 31) & ~31;
580+
581+- err = snd_pcm_hw_params_set_period_size_near(pcm, hwp, round, &dir);
582+- if (err < 0) {
583+- DALSA("couldn't set period size failed", err);
584+- return 0;
585+- }
586+- err = snd_pcm_hw_params_set_periods_near(pcm, hwp, periods, &dir);
587+- if (err < 0) {
588+- DALSA("couldn't set period count", err);
589+- return 0;
590+- }
591+- err = snd_pcm_hw_params(pcm, hwp);
592++ req_rate = cfg->rate;
593++ min = pcm_params_get_min(par, PCM_PARAM_RATE);
594++ if (cfg->rate < min)
595++ cfg->rate = min;
596++ max = pcm_params_get_max(par, PCM_PARAM_RATE);
597++ if (cfg->rate > max)
598++ cfg->rate = max;
599++
600++ min = pcm_params_get_min(par, PCM_PARAM_CHANNELS);
601++ if (cfg->channels < min)
602++ cfg->channels = min;
603++ max = pcm_params_get_max(par, PCM_PARAM_CHANNELS);
604++ if (cfg->channels > max)
605++ cfg->channels = max;
606++
607++ cfg->period_size = cfg->period_size * cfg->rate / req_rate;
608++ cfg->period_size = (cfg->period_size + 31) & ~31;
609++
610++ min = pcm_params_get_min(par, PCM_PARAM_PERIOD_SIZE);
611++ if (min < 2)
612++ min = 2;
613++ if (cfg->period_size < min)
614++ cfg->period_size = min;
615++ max = pcm_params_get_max(par, PCM_PARAM_PERIOD_SIZE);
616++ if (cfg->period_size > max)
617++ cfg->period_size = max;
618++
619++ min = pcm_params_get_min(par, PCM_PARAM_PERIODS);
620++ if (cfg->period_count < min)
621++ cfg->period_count = min;
622++ max = pcm_params_get_max(par, PCM_PARAM_PERIODS);
623++ if (cfg->period_count > max)
624++ cfg->period_count = max;
625++
626++ cfg->start_threshold = 0;
627++ cfg->stop_threshold = cfg->period_count * cfg->period_size;
628++ cfg->avail_min = 1;
629++ cfg->silence_size = 0;
630++ cfg->silence_threshold = 0;
631++
632++ /* XXX: period_event=1, silence?, silence_threshold? */
633++
634++ err = pcm_set_config(pcm, cfg);
635+ if (err < 0) {
636+- DALSA("couldn't commit params", err);
637++ DALSA("couldn't set config", pcm);
638+ return 0;
639+ }
640+ return 1;
641+ }
642+
643+ static int
644+-sio_alsa_getcap_hw(snd_pcm_t *pcm, int *rates, int *fmts, int *chans)
645++sio_alsa_getcap_hw(struct pcm_params *par, int *rates, int *fmts, int *chans)
646+ {
647+ int i, err;
648+- snd_pcm_hw_params_t *hwp;
649+-
650+- snd_pcm_hw_params_alloca(&hwp);
651+-
652+- err = snd_pcm_hw_params_any(pcm, hwp);
653+- if (err < 0) {
654+- DALSA("sio_alsa_trypar: couldn't init pars", err);
655+- return 0;
656+- }
657++ unsigned min, max;
658+
659+ *fmts = 0;
660+ for (i = 0; i < CAP_NFMTS; i++) {
661+- err = snd_pcm_hw_params_test_format(pcm, hwp, cap_fmts[i]);
662++ err = pcm_params_format_test(par, cap_fmts[i]);
663+ if (err == 0) {
664+ *fmts |= 1 << i;
665+ }
666+ }
667+ *rates = 0;
668++ min = pcm_params_get_min(par, PCM_PARAM_RATE);
669++ max = pcm_params_get_max(par, PCM_PARAM_RATE);
670+ for (i = 0; i < CAP_NRATES; i++) {
671+- err = snd_pcm_hw_params_test_rate(pcm, hwp, cap_rates[i], 0);
672+- if (err == 0) {
673++ if (min <= cap_rates[i] && cap_rates[i] <= max) {
674+ *rates |= 1 << i;
675+ }
676+ }
677+ *chans = 0;
678++ min = pcm_params_get_min(par, PCM_PARAM_CHANNELS);
679++ max = pcm_params_get_max(par, PCM_PARAM_CHANNELS);
680+ for (i = 0; i < CAP_NCHANS; i++) {
681+- err = snd_pcm_hw_params_test_channels(pcm, hwp, cap_chans[i]);
682+- if (err == 0) {
683++ if (min <= cap_chans[i] && cap_chans[i] <= max) {
684+ *chans |= 1 << i;
685+ }
686+ }
687+@@ -693,13 +567,13 @@ sio_alsa_getcap(struct sio_hdl *sh, struct sio_cap *cap)
688+ irates = orates = ifmts = ofmts = ichans = ochans = 0;
689+
690+ if (hdl->sio.mode & SIO_PLAY) {
691+- if (!sio_alsa_getcap_hw(hdl->opcm,
692++ if (!sio_alsa_getcap_hw(hdl->opar,
693+ &orates, &ofmts, &ochans)) {
694+ return 0;
695+ }
696+ }
697+ if (hdl->sio.mode & SIO_REC) {
698+- if (!sio_alsa_getcap_hw(hdl->ipcm,
699++ if (!sio_alsa_getcap_hw(hdl->ipar,
700+ &irates, &ifmts, &ichans)) {
701+ return 0;
702+ }
703+@@ -711,7 +585,7 @@ sio_alsa_getcap(struct sio_hdl *sh, struct sio_cap *cap)
704+ &cap->enc[i].sig,
705+ &cap->enc[i].le);
706+ cap->enc[i].bps = SIO_BPS(cap->enc[0].bits);
707+- cap->enc[i].msb = 1;
708++ cap->enc[i].msb = 0;
709+ }
710+ for (i = 0; i < CAP_NRATES; i++) {
711+ cap->rate[i] = cap_rates[i];
712+@@ -744,186 +618,72 @@ static int
713+ sio_alsa_setpar(struct sio_hdl *sh, struct sio_par *par)
714+ {
715+ struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
716+- snd_pcm_hw_params_t *ohwp, *ihwp;
717+- snd_pcm_sw_params_t *oswp, *iswp;
718+- snd_pcm_uframes_t iround, oround;
719+- snd_pcm_format_t ifmt, ofmt;
720+- unsigned int iperiods, operiods;
721+- unsigned irate, orate;
722+- int err;
723+-
724+- snd_pcm_hw_params_alloca(&ohwp);
725+- snd_pcm_sw_params_alloca(&oswp);
726+- snd_pcm_hw_params_alloca(&ihwp);
727+- snd_pcm_sw_params_alloca(&iswp);
728++ struct pcm_config icfg, ocfg;
729+
730+- sio_alsa_enctofmt(hdl, &ifmt, par->bits, par->sig, par->le);
731+- irate = (par->rate == ~0U) ? 48000 : par->rate;
732++ sio_alsa_enctofmt(hdl, &icfg.format, par->bits, par->sig, par->le);
733++ icfg.rate = (par->rate == ~0U) ? 48000 : par->rate;
734+ if (par->appbufsz != ~0U) {
735+- iround = (par->round != ~0U) ?
736++ icfg.period_size = (par->round != ~0U) ?
737+ par->round : (par->appbufsz + 1) / 2;
738+- iperiods = par->appbufsz / iround;
739+- if (iperiods < 2)
740+- iperiods = 2;
741++ icfg.period_count = par->appbufsz / icfg.period_size;
742++ if (icfg.period_count < 2)
743++ icfg.period_count = 2;
744+ } else if (par->round != ~0U) {
745+- iround = par->round;
746+- iperiods = 2;
747++ icfg.period_size = par->round;
748++ icfg.period_count = 2;
749+ } else {
750+- iperiods = 2;
751+- iround = irate / 100;
752++ icfg.period_count = 2;
753++ icfg.period_size = icfg.rate / 100;
754+ }
755+
756+ if (hdl->sio.mode & SIO_REC) {
757+ hdl->par.rchan = par->rchan;
758+- if (!sio_alsa_setpar_hw(hdl->ipcm, ihwp,
759+- &ifmt, &irate, &hdl->par.rchan,
760+- &iround, &iperiods)) {
761++ if (!sio_alsa_setpar_hw(hdl->ipcm, hdl->ipar, &icfg)) {
762+ hdl->sio.eof = 1;
763+ return 0;
764+ }
765+ }
766+- ofmt = ifmt;
767+- orate = irate;
768+- oround = iround;
769+- operiods = iperiods;
770++ ocfg = icfg;
771+ if (hdl->sio.mode & SIO_PLAY) {
772+ hdl->par.pchan = par->pchan;
773+- if (!sio_alsa_setpar_hw(hdl->opcm, ohwp,
774+- &ofmt, &orate, &hdl->par.pchan,
775+- &oround, &operiods)) {
776++ if (!sio_alsa_setpar_hw(hdl->opcm, hdl->opar, &ocfg)) {
777+ hdl->sio.eof = 1;
778+ return 0;
779+ }
780+- if (!(hdl->sio.mode & SIO_REC)) {
781+- ifmt = ofmt;
782+- irate = orate;
783+- iround = oround;
784+- iperiods = operiods;
785+- }
786++ if (!(hdl->sio.mode & SIO_REC))
787++ icfg = ocfg;
788+ }
789+
790+ DPRINTFN(2, "ofmt = %u, orate = %u, oround = %u, operiods = %u\n",
791+- ofmt, orate, (unsigned int)oround, operiods);
792++ ocfg.format, ocfg.rate, ocfg.period_size, ocfg.period_count);
793+ DPRINTFN(2, "ifmt = %u, irate = %u, iround = %u, iperiods = %u\n",
794+- ifmt, irate, (unsigned int)iround, iperiods);
795++ icfg.format, icfg.rate, icfg.period_size, icfg.period_count);
796+
797+- if (ifmt != ofmt) {
798++ if (icfg.format != ocfg.format) {
799+ DPRINTF("play and rec formats differ\n");
800+ hdl->sio.eof = 1;
801+ return 0;
802+ }
803+- if (irate != orate) {
804++ if (icfg.rate != ocfg.rate) {
805+ DPRINTF("play and rec rates differ\n");
806+ hdl->sio.eof = 1;
807+ return 0;
808+ }
809+- if (iround != oround) {
810++ if (icfg.period_size != ocfg.period_size) {
811+ DPRINTF("play and rec block sizes differ\n");
812+ hdl->sio.eof = 1;
813+ return 0;
814+ }
815+- if (!sio_alsa_fmttopar(hdl, ifmt,
816++ if (!sio_alsa_fmttopar(hdl, icfg.format,
817+ &hdl->par.bits, &hdl->par.sig, &hdl->par.le))
818+ return 0;
819+- hdl->par.msb = 1;
820++ hdl->par.msb = 0;
821+ hdl->par.bps = SIO_BPS(hdl->par.bits);
822+- hdl->par.rate = orate;
823+- hdl->par.round = oround;
824+- hdl->par.bufsz = oround * operiods;
825++ hdl->par.rate = ocfg.rate;
826++ hdl->par.round = ocfg.period_size;
827++ hdl->par.bufsz = ocfg.period_size * ocfg.period_count;
828+ hdl->par.appbufsz = hdl->par.bufsz;
829+
830+- /* software params */
831+-
832+- if (hdl->sio.mode & SIO_REC) {
833+- err = snd_pcm_sw_params_current(hdl->ipcm, iswp);
834+- if (err < 0) {
835+- DALSA("couldn't get current rec params", err);
836+- hdl->sio.eof = 1;
837+- return 0;
838+- }
839+- err = snd_pcm_sw_params_set_start_threshold(hdl->ipcm,
840+- iswp, 0);
841+- if (err < 0) {
842+- DALSA("couldn't set rec start threshold", err);
843+- hdl->sio.eof = 1;
844+- return 0;
845+- }
846+- err = snd_pcm_sw_params_set_stop_threshold(hdl->ipcm,
847+- iswp, hdl->par.bufsz);
848+- if (err < 0) {
849+- DALSA("couldn't set rec stop threshold", err);
850+- hdl->sio.eof = 1;
851+- return 0;
852+- }
853+- err = snd_pcm_sw_params_set_avail_min(hdl->ipcm,
854+- iswp, 1);
855+- if (err < 0) {
856+- DALSA("couldn't set rec avail min", err);
857+- hdl->sio.eof = 1;
858+- return 0;
859+- }
860+- err = snd_pcm_sw_params_set_period_event(hdl->ipcm, iswp, 1);
861+- if (err < 0) {
862+- DALSA("couldn't set rec period event", err);
863+- hdl->sio.eof = 1;
864+- return 0;
865+- }
866+- err = snd_pcm_sw_params(hdl->ipcm, iswp);
867+- if (err < 0) {
868+- DALSA("couldn't commit rec sw params", err);
869+- hdl->sio.eof = 1;
870+- return 0;
871+- }
872+- }
873+- if (hdl->sio.mode & SIO_PLAY) {
874+- err = snd_pcm_sw_params_current(hdl->opcm, oswp);
875+- if (err < 0) {
876+- DALSA("couldn't get current play params", err);
877+- hdl->sio.eof = 1;
878+- return 0;
879+- }
880+- err = snd_pcm_sw_params_set_start_threshold(hdl->opcm,
881+- oswp, hdl->par.bufsz - hdl->par.round);
882+- if (err < 0) {
883+- DALSA("couldn't set play start threshold", err);
884+- hdl->sio.eof = 1;
885+- return 0;
886+- }
887+- err = snd_pcm_sw_params_set_stop_threshold(hdl->opcm,
888+- oswp, hdl->par.bufsz);
889+- if (err < 0) {
890+- DALSA("couldn't set play stop threshold", err);
891+- hdl->sio.eof = 1;
892+- return 0;
893+- }
894+- err = snd_pcm_sw_params_set_avail_min(hdl->opcm,
895+- oswp, 1);
896+- if (err < 0) {
897+- DALSA("couldn't set play avail min", err);
898+- hdl->sio.eof = 1;
899+- return 0;
900+- }
901+- err = snd_pcm_sw_params_set_period_event(hdl->opcm, oswp, 1);
902+- if (err < 0) {
903+- DALSA("couldn't set play period event", err);
904+- hdl->sio.eof = 1;
905+- return 0;
906+- }
907+- err = snd_pcm_sw_params(hdl->opcm, oswp);
908+- if (err < 0) {
909+- DALSA("couldn't commit play sw params", err);
910+- hdl->sio.eof = 1;
911+- return 0;
912+- }
913+- }
914+-#ifdef DEBUG
915+- if (_sndio_debug >= 2) {
916+- if (hdl->sio.mode & SIO_REC)
917+- snd_pcm_dump(hdl->ipcm, output);
918+- if (hdl->sio.mode & SIO_PLAY)
919+- snd_pcm_dump(hdl->opcm, output);
920+- }
921+-#endif
922+ return 1;
923+ }
924+
925+@@ -940,7 +700,7 @@ static size_t
926+ sio_alsa_read(struct sio_hdl *sh, void *buf, size_t len)
927+ {
928+ struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
929+- snd_pcm_sframes_t n;
930++ int n;
931+ size_t todo;
932+
933+ if (hdl->ipartial > 0) {
934+@@ -959,7 +719,7 @@ sio_alsa_read(struct sio_hdl *sh, void *buf, size_t len)
935+ todo = len / hdl->ibpf;
936+ if (todo == 0)
937+ return 0;
938+- while ((n = snd_pcm_readi(hdl->ipcm, buf, todo)) < 0) {
939++ while ((n = pcm_readi(hdl->ipcm, buf, todo)) < 0) {
940+ if (n == -EINTR)
941+ continue;
942+ if (n == -EPIPE || n == -ESTRPIPE) {
943+@@ -967,7 +727,7 @@ sio_alsa_read(struct sio_hdl *sh, void *buf, size_t len)
944+ return 0;
945+ }
946+ if (n != -EAGAIN) {
947+- DALSA("couldn't read data", n);
948++ DALSA("couldn't read data", hdl->ipcm);
949+ hdl->sio.eof = 1;
950+ }
951+ return 0;
952+@@ -989,7 +749,7 @@ static size_t
953+ sio_alsa_write(struct sio_hdl *sh, const void *buf, size_t len)
954+ {
955+ struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
956+- snd_pcm_sframes_t n;
957++ int n;
958+ size_t todo;
959+
960+ if (len < hdl->obpf || hdl->opartial > 0) {
961+@@ -1007,7 +767,7 @@ sio_alsa_write(struct sio_hdl *sh, const void *buf, size_t len)
962+ todo = len / hdl->obpf;
963+ if (todo == 0)
964+ return 0;
965+- while ((n = snd_pcm_writei(hdl->opcm, buf, todo)) < 0) {
966++ while ((n = pcm_writei(hdl->opcm, buf, todo)) < 0) {
967+ if (n == -EINTR)
968+ continue;
969+ if (n == -ESTRPIPE || n == -EPIPE) {
970+@@ -1015,7 +775,7 @@ sio_alsa_write(struct sio_hdl *sh, const void *buf, size_t len)
971+ return 0;
972+ }
973+ if (n != -EAGAIN) {
974+- DALSA("couldn't write data", n);
975++ DALSA("couldn't write data", hdl->opcm);
976+ hdl->sio.eof = 1;
977+ }
978+ return 0;
979+@@ -1062,16 +822,14 @@ sio_alsa_onmove(struct sio_alsa_hdl *hdl)
980+ static int
981+ sio_alsa_nfds(struct sio_hdl *sh)
982+ {
983+- struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
984+-
985+- return hdl->nfds;
986++ return 2;
987+ }
988+
989+ static int
990+ sio_alsa_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events)
991+ {
992+ struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
993+- int i;
994++ int i, nfds;
995+
996+ if (hdl->sio.eof)
997+ return 0;
998+@@ -1083,100 +841,86 @@ sio_alsa_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events)
999+ hdl->events &= ~POLLIN;
1000+ if (!hdl->sio.started)
1001+ hdl->events = 0;
1002+- memset(pfd, 0, sizeof(struct pollfd) * hdl->nfds);
1003+- hdl->onfds = hdl->infds = 0;
1004++ memset(pfd, 0, sizeof(struct pollfd) * 2);
1005++ nfds = 0;
1006+ if (hdl->events & POLLOUT) {
1007+ if (!hdl->running &&
1008+- snd_pcm_state(hdl->opcm) == SND_PCM_STATE_RUNNING)
1009++ pcm_state(hdl->opcm) == PCM_STATE_RUNNING)
1010+ sio_alsa_onmove(hdl);
1011+- hdl->onfds = snd_pcm_poll_descriptors(hdl->opcm,
1012+- pfd, hdl->nfds);
1013+- if (hdl->onfds < 0) {
1014+- DALSA("couldn't poll play descriptors",
1015+- hdl->onfds);
1016+- hdl->sio.eof = 1;
1017+- return 0;
1018+- }
1019++
1020++ pfd[0].fd = pcm_get_poll_fd(hdl->opcm);
1021++ pfd[0].events = POLLOUT;
1022++ nfds++;
1023+ }
1024+ if (hdl->events & POLLIN) {
1025+ if (!hdl->running &&
1026+- snd_pcm_state(hdl->ipcm) == SND_PCM_STATE_RUNNING)
1027++ pcm_state(hdl->ipcm) == PCM_STATE_RUNNING)
1028+ sio_alsa_onmove(hdl);
1029+- hdl->infds = snd_pcm_poll_descriptors(hdl->ipcm,
1030+- pfd + hdl->onfds, hdl->nfds - hdl->onfds);
1031+- if (hdl->infds < 0) {
1032+- DALSA("couldn't poll rec descriptors",
1033+- hdl->infds);
1034+- hdl->sio.eof = 1;
1035+- return 0;
1036+- }
1037++
1038++ pfd[nfds].fd = pcm_get_poll_fd(hdl->ipcm);
1039++ pfd[nfds].events = POLLIN;
1040++ nfds++;
1041+ }
1042+- DPRINTFN(4, "sio_alsa_pollfd: events = %x, nfds = %d + %d\n",
1043+- events, hdl->onfds, hdl->infds);
1044++ DPRINTFN(4, "sio_alsa_pollfd: events = %x, nfds = %d\n",
1045++ events, nfds);
1046+
1047+- for (i = 0; i < hdl->onfds + hdl->infds; i++) {
1048++ for (i = 0; i < nfds; i++) {
1049+ DPRINTFN(4, "sio_alsa_pollfd: pfds[%d].events = %x\n",
1050+ i, pfd[i].events);
1051+ }
1052+- return hdl->onfds + hdl->infds;
1053++ return nfds;
1054+ }
1055+
1056+ int
1057+ sio_alsa_revents(struct sio_hdl *sh, struct pollfd *pfd)
1058+ {
1059+ struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
1060+- snd_pcm_sframes_t iused, oavail, oused;
1061+- snd_pcm_state_t istate, ostate;
1062+- unsigned short revents, r;
1063+- int nfds, err, i;
1064++ struct timespec ts;
1065++ unsigned iused, oavail, oused;
1066++ int istate, ostate;
1067++ unsigned short revents;
1068++ int nfds, i;
1069+
1070+ if (hdl->sio.eof)
1071+ return POLLHUP;
1072+
1073+- for (i = 0; i < hdl->onfds + hdl->infds; i++) {
1074++ nfds = 0;
1075++ if (hdl->events & POLLOUT)
1076++ nfds++;
1077++ if (hdl->events & POLLIN)
1078++ nfds++;
1079++
1080++ for (i = 0; i < nfds; i++) {
1081+ DPRINTFN(4, "sio_alsa_revents: pfds[%d].revents = %x\n",
1082+ i, pfd[i].revents);
1083+ }
1084+ revents = nfds = 0;
1085+ if (hdl->events & POLLOUT) {
1086+- err = snd_pcm_poll_descriptors_revents(hdl->opcm,
1087+- pfd, hdl->onfds, &r);
1088+- if (err < 0) {
1089+- DALSA("couldn't get play events", err);
1090+- hdl->sio.eof = 1;
1091+- return POLLHUP;
1092+- }
1093+- revents |= r;
1094+- nfds += hdl->onfds;
1095++ revents |= pfd[0].revents;
1096++ ++nfds;
1097+ }
1098+ if (hdl->events & POLLIN) {
1099+- err = snd_pcm_poll_descriptors_revents(hdl->ipcm,
1100+- pfd + nfds, hdl->infds, &r);
1101+- if (err < 0) {
1102+- DALSA("couldn't get rec events", err);
1103+- hdl->sio.eof = 1;
1104+- return POLLHUP;
1105+- }
1106+- revents |= r;
1107+- nfds += hdl->infds;
1108++ revents |= pfd[nfds].revents;
1109++ ++nfds;
1110+ }
1111+ if (hdl->sio.mode & SIO_PLAY) {
1112+- ostate = snd_pcm_state(hdl->opcm);
1113+- if (ostate == SND_PCM_STATE_XRUN) {
1114++ ostate = pcm_state(hdl->opcm);
1115++ if (ostate == PCM_STATE_XRUN) {
1116+ if (!sio_alsa_xrun(hdl))
1117+ return POLLHUP;
1118+ return 0;
1119+ }
1120+- if (ostate == SND_PCM_STATE_RUNNING ||
1121+- ostate == SND_PCM_STATE_PREPARED) {
1122+- oavail = snd_pcm_avail_update(hdl->opcm);
1123+- if (oavail < 0) {
1124++ if (ostate == PCM_STATE_RUNNING ||
1125++ ostate == PCM_STATE_PREPARED) {
1126++ if (pcm_get_htimestamp(hdl->opcm, &oavail, &ts) != 0) {
1127++ /*
1128+ if (oavail == -EPIPE || oavail == -ESTRPIPE) {
1129+ if (!sio_alsa_xrun(hdl))
1130+ return POLLHUP;
1131+ return 0;
1132+ }
1133+- DALSA("couldn't get play buffer ptr", oavail);
1134++ */
1135++ DPRINTF("couldn't get play buffer ptr\n");
1136+ hdl->sio.eof = 1;
1137+ return POLLHUP;
1138+ }
1139+@@ -1186,22 +930,23 @@ sio_alsa_revents(struct sio_hdl *sh, struct pollfd *pfd)
1140+ }
1141+ }
1142+ if (hdl->sio.mode & SIO_REC) {
1143+- istate = snd_pcm_state(hdl->ipcm);
1144+- if (istate == SND_PCM_STATE_XRUN) {
1145++ istate = pcm_state(hdl->ipcm);
1146++ if (istate == PCM_STATE_XRUN) {
1147+ if (!sio_alsa_xrun(hdl))
1148+ return POLLHUP;
1149+ return 0;
1150+ }
1151+- if (istate == SND_PCM_STATE_RUNNING ||
1152+- istate == SND_PCM_STATE_PREPARED) {
1153+- iused = snd_pcm_avail_update(hdl->ipcm);
1154+- if (iused < 0) {
1155++ if (istate == PCM_STATE_RUNNING ||
1156++ istate == PCM_STATE_PREPARED) {
1157++ if (pcm_get_htimestamp(hdl->ipcm, &iused, &ts) != 0) {
1158++ /*
1159+ if (iused == -EPIPE || iused == -ESTRPIPE) {
1160+ if (!sio_alsa_xrun(hdl))
1161+ return POLLHUP;
1162+ return 0;
1163+ }
1164+- DALSA("couldn't get rec buffer ptr", iused);
1165++ */
1166++ DPRINTF("couldn't get rec buffer ptr\n");
1167+ hdl->sio.eof = 1;
1168+ return POLLHUP;
1169+ }
1170+--
1171+2.37.3
1172+
1@@ -0,0 +1,141 @@
2+From 7472a43ccf2f5bae14cd736102daab8b4be0df31 Mon Sep 17 00:00:00 2001
3+From: Michael Forney <mforney@mforney.org>
4+Date: Mon, 31 Oct 2022 03:47:44 -0700
5+Subject: [PATCH] alsa: Add support for s24le3/s24be3
6+
7+---
8+ libsndio/sio_alsa.c | 41 +++++++++++++++++++++++++++++++++--------
9+ 1 file changed, 33 insertions(+), 8 deletions(-)
10+
11+diff --git a/libsndio/sio_alsa.c b/libsndio/sio_alsa.c
12+index e460bf6..9a65288 100644
13+--- a/libsndio/sio_alsa.c
14++++ b/libsndio/sio_alsa.c
15+@@ -112,40 +112,60 @@ static enum pcm_format cap_fmts[] = {
16+ */
17+ static int
18+ sio_alsa_fmttopar(struct sio_alsa_hdl *hdl, enum pcm_format fmt,
19+- unsigned int *bits, unsigned int *sig, unsigned int *le)
20++ unsigned int *bits, unsigned int *bps, unsigned int *sig, unsigned int *le)
21+ {
22+ switch (fmt) {
23+ case PCM_FORMAT_S8:
24+ *bits = 8;
25++ *bps = 1;
26+ *sig = 1;
27++ *le = 1;
28+ break;
29+ case PCM_FORMAT_S16_LE:
30+ *bits = 16;
31++ *bps = 2;
32+ *sig = 1;
33+ *le = 1;
34+ break;
35+ case PCM_FORMAT_S16_BE:
36+ *bits = 16;
37++ *bps = 2;
38++ *sig = 1;
39++ *le = 0;
40++ break;
41++ case PCM_FORMAT_S24_3LE:
42++ *bits = 24;
43++ *bps = 3;
44++ *sig = 1;
45++ *le = 1;
46++ break;
47++ case PCM_FORMAT_S24_3BE:
48++ *bits = 24;
49++ *bps = 3;
50+ *sig = 1;
51+ *le = 0;
52+ break;
53+ case PCM_FORMAT_S24_LE:
54+ *bits = 24;
55++ *bps = 4;
56+ *sig = 1;
57+ *le = 1;
58+ break;
59+ case PCM_FORMAT_S24_BE:
60+ *bits = 24;
61++ *bps = 4;
62+ *sig = 1;
63+ *le = 0;
64+ break;
65+ case PCM_FORMAT_S32_LE:
66+ *bits = 32;
67++ *bps = 4;
68+ *sig = 1;
69+ *le = 1;
70+ break;
71+ case PCM_FORMAT_S32_BE:
72+ *bits = 32;
73++ *bps = 4;
74+ *sig = 1;
75+ *le = 0;
76+ break;
77+@@ -163,13 +183,17 @@ sio_alsa_fmttopar(struct sio_alsa_hdl *hdl, enum pcm_format fmt,
78+ */
79+ static void
80+ sio_alsa_enctofmt(struct sio_alsa_hdl *hdl, enum pcm_format *rfmt,
81+- unsigned int bits, unsigned int sig, unsigned int le)
82++ unsigned int bits, unsigned int bps, unsigned int sig, unsigned int le)
83+ {
84++ if (bps == ~0U)
85++ bps = SIO_BPS(bits);
86+ if (le == ~0U)
87+ le = SIO_LE_NATIVE;
88+ if (bits == 8)
89+ *rfmt = PCM_FORMAT_S8;
90+- else if (bits == 24)
91++ else if (bits == 24 && bps == 3)
92++ *rfmt = le ? PCM_FORMAT_S24_3LE : PCM_FORMAT_S24_3BE;
93++ else if (bits == 24 && bps == 4)
94+ *rfmt = le ? PCM_FORMAT_S24_LE : PCM_FORMAT_S24_BE;
95+ else if (bits == 32)
96+ *rfmt = le ? PCM_FORMAT_S32_LE : PCM_FORMAT_S32_BE;
97+@@ -450,6 +474,7 @@ sio_alsa_setpar_hw(struct pcm *pcm, struct pcm_params *par,
98+ static enum pcm_format fmts[] = {
99+ PCM_FORMAT_S32_LE, PCM_FORMAT_S32_BE,
100+ PCM_FORMAT_S24_LE, PCM_FORMAT_S24_BE,
101++ PCM_FORMAT_S24_3LE, PCM_FORMAT_S24_3BE,
102+ PCM_FORMAT_S16_LE, PCM_FORMAT_S16_BE,
103+ PCM_FORMAT_S8
104+ };
105+@@ -582,9 +607,9 @@ sio_alsa_getcap(struct sio_hdl *sh, struct sio_cap *cap)
106+ for (i = 0; i < CAP_NFMTS; i++) {
107+ sio_alsa_fmttopar(hdl, cap_fmts[i],
108+ &cap->enc[i].bits,
109++ &cap->enc[i].bps,
110+ &cap->enc[i].sig,
111+ &cap->enc[i].le);
112+- cap->enc[i].bps = SIO_BPS(cap->enc[0].bits);
113+ cap->enc[i].msb = 0;
114+ }
115+ for (i = 0; i < CAP_NRATES; i++) {
116+@@ -620,7 +645,8 @@ sio_alsa_setpar(struct sio_hdl *sh, struct sio_par *par)
117+ struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
118+ struct pcm_config icfg, ocfg;
119+
120+- sio_alsa_enctofmt(hdl, &icfg.format, par->bits, par->sig, par->le);
121++ sio_alsa_enctofmt(hdl, &icfg.format, par->bits, par->bps, par->sig,
122++ par->le);
123+ icfg.rate = (par->rate == ~0U) ? 48000 : par->rate;
124+ if (par->appbufsz != ~0U) {
125+ icfg.period_size = (par->round != ~0U) ?
126+@@ -674,11 +700,10 @@ sio_alsa_setpar(struct sio_hdl *sh, struct sio_par *par)
127+ hdl->sio.eof = 1;
128+ return 0;
129+ }
130+- if (!sio_alsa_fmttopar(hdl, icfg.format,
131+- &hdl->par.bits, &hdl->par.sig, &hdl->par.le))
132++ if (!sio_alsa_fmttopar(hdl, icfg.format, &hdl->par.bits, &hdl->par.bps,
133++ &hdl->par.sig, &hdl->par.le))
134+ return 0;
135+ hdl->par.msb = 0;
136+- hdl->par.bps = SIO_BPS(hdl->par.bits);
137+ hdl->par.rate = ocfg.rate;
138+ hdl->par.round = ocfg.period_size;
139+ hdl->par.bufsz = ocfg.period_size * ocfg.period_count;
140+--
141+2.37.3
142+
+1,
-0
1@@ -0,0 +1 @@
2+Subproject commit 584d41515a981818f6f60e9d9dca97af3657a640
+1,
-0
1@@ -0,0 +1 @@
2+1.9.0 r0