Files
oasis-linux-mirror/pkg/sndio/patch/0003-alsa-Port-to-tinyalsa.patch

1172 lines
31 KiB
Diff

From 39ec20119841c84500e589fee15c10e9fe6c0c97 Mon Sep 17 00:00:00 2001
From: Michael Forney <mforney@mforney.org>
Date: Tue, 31 Aug 2021 14:30:07 -0700
Subject: [PATCH] alsa: Port to tinyalsa
---
libsndio/debug.c | 2 +-
libsndio/sio_alsa.c | 747 +++++++++++++++-----------------------------
2 files changed, 247 insertions(+), 502 deletions(-)
diff --git a/libsndio/debug.c b/libsndio/debug.c
index 304975a..40fdc92 100644
--- a/libsndio/debug.c
+++ b/libsndio/debug.c
@@ -35,7 +35,7 @@ _sndio_debug_init(void)
if (_sndio_debug < 0) {
dbg = issetugid() ? NULL : getenv("SNDIO_DEBUG");
- if (!dbg || sscanf(dbg, "%u", &_sndio_debug) != 1)
+ if (!dbg || sscanf(dbg, "%d", &_sndio_debug) != 1)
_sndio_debug = 0;
}
}
diff --git a/libsndio/sio_alsa.c b/libsndio/sio_alsa.c
index 6107617..e460bf6 100644
--- a/libsndio/sio_alsa.c
+++ b/libsndio/sio_alsa.c
@@ -29,31 +29,28 @@
#include <string.h>
#include <unistd.h>
#include <values.h>
-#include <alsa/asoundlib.h>
+#include <tinyalsa/asoundlib.h>
#include "debug.h"
#include "sio_priv.h"
#include "bsd-compat.h"
-#define DEVNAME_PREFIX "hw:"
-
#ifdef DEBUG
-static snd_output_t *output = NULL;
-#define DALSA(str, err) fprintf(stderr, "%s: %s\n", str, snd_strerror(err))
+#define DALSA(str, pcm) fprintf(stderr, "%s: %s\n", str, pcm_get_error(pcm))
#else
-#define DALSA(str, err) do {} while (0)
+#define DALSA(str, pcm) do {} while (0)
#endif
struct sio_alsa_hdl {
struct sio_hdl sio;
struct sio_par par;
- char *devname;
- snd_pcm_t *opcm;
- snd_pcm_t *ipcm;
+ struct pcm_params *opar;
+ struct pcm_params *ipar;
+ struct pcm *opcm;
+ struct pcm *ipcm;
unsigned ibpf, obpf; /* bytes per frame */
int iused, oused; /* frames used in hardware fifos */
int idelta, odelta; /* position reported to client */
- int nfds, infds, onfds;
int running;
int events;
int ipartial, opartial;
@@ -102,90 +99,56 @@ static unsigned int cap_rates[] = {
8000, 11025, 12000, 16000, 22050, 24000,
32000, 44100, 48000, 64000, 88200, 96000
};
-static snd_pcm_format_t cap_fmts[] = {
+static enum pcm_format cap_fmts[] = {
/* XXX add s24le3 and s24be3 */
- SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_BE,
- SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_BE,
- SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE,
- SND_PCM_FORMAT_U8
+ PCM_FORMAT_S32_LE, PCM_FORMAT_S32_BE,
+ PCM_FORMAT_S24_LE, PCM_FORMAT_S24_BE,
+ PCM_FORMAT_S16_LE, PCM_FORMAT_S16_BE,
+ PCM_FORMAT_S8
};
/*
* convert ALSA format to sio_par encoding
*/
static int
-sio_alsa_fmttopar(struct sio_alsa_hdl *hdl, snd_pcm_format_t fmt,
+sio_alsa_fmttopar(struct sio_alsa_hdl *hdl, enum pcm_format fmt,
unsigned int *bits, unsigned int *sig, unsigned int *le)
{
switch (fmt) {
- case SND_PCM_FORMAT_U8:
- *bits = 8;
- *sig = 0;
- break;
- case SND_PCM_FORMAT_S8:
+ case PCM_FORMAT_S8:
*bits = 8;
*sig = 1;
break;
- case SND_PCM_FORMAT_S16_LE:
+ case PCM_FORMAT_S16_LE:
*bits = 16;
*sig = 1;
*le = 1;
break;
- case SND_PCM_FORMAT_S16_BE:
+ case PCM_FORMAT_S16_BE:
*bits = 16;
*sig = 1;
*le = 0;
break;
- case SND_PCM_FORMAT_U16_LE:
- *bits = 16;
- *sig = 0;
- *le = 1;
- break;
- case SND_PCM_FORMAT_U16_BE:
- *bits = 16;
- *sig = 0;
- *le = 0;
- break;
- case SND_PCM_FORMAT_S24_LE:
+ case PCM_FORMAT_S24_LE:
*bits = 24;
*sig = 1;
*le = 1;
break;
- case SND_PCM_FORMAT_S24_BE:
+ case PCM_FORMAT_S24_BE:
*bits = 24;
*sig = 1;
*le = 0;
break;
- case SND_PCM_FORMAT_U24_LE:
- *bits = 24;
- *sig = 0;
- *le = 1;
- break;
- case SND_PCM_FORMAT_U24_BE:
- *bits = 24;
- *sig = 0;
- *le = 0;
- break;
- case SND_PCM_FORMAT_S32_LE:
+ case PCM_FORMAT_S32_LE:
*bits = 32;
*sig = 1;
*le = 1;
break;
- case SND_PCM_FORMAT_S32_BE:
+ case PCM_FORMAT_S32_BE:
*bits = 32;
*sig = 1;
*le = 0;
break;
- case SND_PCM_FORMAT_U32_LE:
- *bits = 32;
- *sig = 0;
- *le = 1;
- break;
- case SND_PCM_FORMAT_U32_BE:
- *bits = 32;
- *sig = 0;
- *le = 0;
- break;
default:
DPRINTF("sio_alsa_fmttopar: 0x%x: unsupported format\n", fmt);
hdl->sio.eof = 1;
@@ -199,78 +162,19 @@ sio_alsa_fmttopar(struct sio_alsa_hdl *hdl, snd_pcm_format_t fmt,
* convert sio_par encoding to ALSA format
*/
static void
-sio_alsa_enctofmt(struct sio_alsa_hdl *hdl, snd_pcm_format_t *rfmt,
+sio_alsa_enctofmt(struct sio_alsa_hdl *hdl, enum pcm_format *rfmt,
unsigned int bits, unsigned int sig, unsigned int le)
{
- if (bits == 8) {
- if (sig == ~0U || !sig)
- *rfmt = SND_PCM_FORMAT_U8;
- else
- *rfmt = SND_PCM_FORMAT_S8;
- } else if (bits == 16) {
- if (sig == ~0U || sig) {
- if (le == ~0U) {
- *rfmt = SIO_LE_NATIVE ?
- SND_PCM_FORMAT_S16_LE :
- SND_PCM_FORMAT_S16_BE;
- } else if (le)
- *rfmt = SND_PCM_FORMAT_S16_LE;
- else
- *rfmt = SND_PCM_FORMAT_S16_BE;
- } else {
- if (le == ~0U) {
- *rfmt = SIO_LE_NATIVE ?
- SND_PCM_FORMAT_U16_LE :
- SND_PCM_FORMAT_U16_BE;
- } else if (le)
- *rfmt = SND_PCM_FORMAT_U16_LE;
- else
- *rfmt = SND_PCM_FORMAT_U16_BE;
- }
- } else if (bits == 24) {
- if (sig == ~0U || sig) {
- if (le == ~0U) {
- *rfmt = SIO_LE_NATIVE ?
- SND_PCM_FORMAT_S24_LE :
- SND_PCM_FORMAT_S24_BE;
- } else if (le)
- *rfmt = SND_PCM_FORMAT_S24_LE;
- else
- *rfmt = SND_PCM_FORMAT_S24_BE;
- } else {
- if (le == ~0U) {
- *rfmt = SIO_LE_NATIVE ?
- SND_PCM_FORMAT_U24_LE :
- SND_PCM_FORMAT_U24_BE;
- } else if (le)
- *rfmt = SND_PCM_FORMAT_U24_LE;
- else
- *rfmt = SND_PCM_FORMAT_U24_BE;
- }
- } else if (bits == 32) {
- if (sig == ~0U || sig) {
- if (le == ~0U) {
- *rfmt = SIO_LE_NATIVE ?
- SND_PCM_FORMAT_S32_LE :
- SND_PCM_FORMAT_S32_BE;
- } else if (le)
- *rfmt = SND_PCM_FORMAT_S32_LE;
- else
- *rfmt = SND_PCM_FORMAT_S32_BE;
- } else {
- if (le == ~0U) {
- *rfmt = SIO_LE_NATIVE ?
- SND_PCM_FORMAT_U32_LE :
- SND_PCM_FORMAT_U32_BE;
- } else if (le)
- *rfmt = SND_PCM_FORMAT_U32_LE;
- else
- *rfmt = SND_PCM_FORMAT_U32_BE;
- }
- } else {
- *rfmt = SIO_LE_NATIVE ?
- SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_S16_BE;
- }
+ if (le == ~0U)
+ le = SIO_LE_NATIVE;
+ if (bits == 8)
+ *rfmt = PCM_FORMAT_S8;
+ else if (bits == 24)
+ *rfmt = le ? PCM_FORMAT_S24_LE : PCM_FORMAT_S24_BE;
+ else if (bits == 32)
+ *rfmt = le ? PCM_FORMAT_S32_LE : PCM_FORMAT_S32_BE;
+ else
+ *rfmt = le ? PCM_FORMAT_S16_LE : PCM_FORMAT_S16_BE;
}
struct sio_hdl *
@@ -279,8 +183,7 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio)
const char *p;
struct sio_alsa_hdl *hdl;
struct sio_par par;
- size_t len;
- int err;
+ unsigned card, dev;
p = _sndio_parsetype(str, "rsnd");
if (p == NULL) {
@@ -300,42 +203,45 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio)
return NULL;
_sio_create(&hdl->sio, &sio_alsa_ops, mode, nbio);
-#ifdef DEBUG
- err = snd_output_stdio_attach(&output, stderr, 0);
- if (err < 0)
- DALSA("couldn't attach to stderr", err);
-#endif
- if (strcmp(p, "default") == 0)
- p = "0";
- len = strlen(p);
- hdl->devname = malloc(len + sizeof(DEVNAME_PREFIX));
- if (hdl->devname == NULL)
- goto bad_free_hdl;
- memcpy(hdl->devname, DEVNAME_PREFIX, sizeof(DEVNAME_PREFIX) - 1);
- memcpy(hdl->devname + sizeof(DEVNAME_PREFIX) - 1, p, len + 1);
+ if (strcmp(p, "default") == 0) {
+ card = 0;
+ dev = 0;
+ } else {
+ switch (sscanf(p, "%u,%u", &card, &dev)) {
+ case 1:
+ dev = 0;
+ break;
+ case 2:
+ break;
+ default:
+ DPRINTF("invalid device name\n");
+ }
+ }
if (mode & SIO_PLAY) {
- err = snd_pcm_open(&hdl->opcm, hdl->devname,
- SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
- if (err < 0) {
- DALSA("couldn't open play stream", err);
- goto bad_free;
+ hdl->opar = pcm_params_get(card, dev, PCM_OUT);
+ if (hdl->opar == NULL) {
+ DPRINTF("couldn't get play params\n");
+ goto bad_free_hdl;
+ }
+ hdl->opcm = pcm_open(card, dev, PCM_OUT | PCM_NONBLOCK, NULL);
+ if (!pcm_is_ready(hdl->opcm)) {
+ DALSA("couldn't open play stream", hdl->opcm);
+ goto bad_free_opar;
}
}
if (mode & SIO_REC) {
- err = snd_pcm_open(&hdl->ipcm, hdl->devname,
- SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
- if (err < 0) {
- DALSA("couldn't open rec stream", err);
+ hdl->ipar = pcm_params_get(card, dev, PCM_IN);
+ if (hdl->ipar == NULL) {
+ DPRINTF("couldn't get rec params\n");
goto bad_free_opcm;
}
+ hdl->ipcm = pcm_open(card, dev, PCM_IN | PCM_NONBLOCK, NULL);
+ if (!pcm_is_ready(hdl->ipcm)) {
+ DALSA("couldn't open rec stream", hdl->ipcm);
+ goto bad_free_ipar;
+ }
}
- /*
- * snd_pcm_poll_descriptors_count returns a small value
- * that grows later, after the stream is started
- */
- hdl->nfds = SIO_MAXNFDS;
-
/*
* Default parameters may not be compatible with libsndio (eg. mulaw
* encodings, different playback and recording parameters, etc...), so
@@ -356,12 +262,16 @@ _sio_alsa_open(const char *str, unsigned mode, int nbio)
return (struct sio_hdl *)hdl;
bad_free_ipcm:
if (mode & SIO_REC)
- snd_pcm_close(hdl->ipcm);
+ pcm_close(hdl->ipcm);
+bad_free_ipar:
+ if (mode & SIO_REC)
+ free(hdl->ipar);
bad_free_opcm:
if (mode & SIO_PLAY)
- snd_pcm_close(hdl->opcm);
-bad_free:
- free(hdl->devname);
+ pcm_close(hdl->opcm);
+bad_free_opar:
+ if (mode & SIO_PLAY)
+ free(hdl->opar);
bad_free_hdl:
free(hdl);
return NULL;
@@ -372,11 +282,14 @@ sio_alsa_close(struct sio_hdl *sh)
{
struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
- if (hdl->sio.mode & SIO_PLAY)
- snd_pcm_close(hdl->opcm);
- if (hdl->sio.mode & SIO_REC)
- snd_pcm_close(hdl->ipcm);
- free(hdl->devname);
+ if (hdl->sio.mode & SIO_PLAY) {
+ free(hdl->opar);
+ pcm_close(hdl->opcm);
+ }
+ if (hdl->sio.mode & SIO_REC) {
+ free(hdl->ipar);
+ pcm_close(hdl->ipcm);
+ }
free(hdl);
}
@@ -394,14 +307,12 @@ sio_alsa_start(struct sio_hdl *sh)
hdl->oused = 0;
hdl->idelta = 0;
hdl->odelta = 0;
- hdl->infds = 0;
- hdl->onfds = 0;
hdl->running = 0;
if (hdl->sio.mode & SIO_PLAY) {
- err = snd_pcm_prepare(hdl->opcm);
+ err = pcm_prepare(hdl->opcm);
if (err < 0) {
- DALSA("couldn't prepare play stream", err);
+ DALSA("couldn't prepare play stream", hdl->opcm);
hdl->sio.eof = 1;
return 0;
}
@@ -413,9 +324,9 @@ sio_alsa_start(struct sio_hdl *sh)
hdl->opartial = 0;
}
if (hdl->sio.mode & SIO_REC) {
- err = snd_pcm_prepare(hdl->ipcm);
+ err = pcm_prepare(hdl->ipcm);
if (err < 0) {
- DALSA("couldn't prepare rec stream", err);
+ DALSA("couldn't prepare rec stream", hdl->ipcm);
hdl->sio.eof = 1;
return 0;
}
@@ -427,17 +338,17 @@ sio_alsa_start(struct sio_hdl *sh)
hdl->ipartial = 0;
}
if ((hdl->sio.mode & SIO_PLAY) && (hdl->sio.mode & SIO_REC)) {
- err = snd_pcm_link(hdl->ipcm, hdl->opcm);
+ err = pcm_link(hdl->ipcm, hdl->opcm);
if (err < 0) {
- DALSA("couldn't link streams", err);
+ DALSA("couldn't link streams", hdl->ipcm);
hdl->sio.eof = 1;
return 0;
}
}
if (!(hdl->sio.mode & SIO_PLAY)) {
- err = snd_pcm_start(hdl->ipcm);
+ err = pcm_start(hdl->ipcm);
if (err < 0) {
- DALSA("couldn't start rec stream", err);
+ DALSA("couldn't start rec stream", hdl->ipcm);
hdl->sio.eof = 1;
return 0;
}
@@ -449,30 +360,26 @@ static int
sio_alsa_flush(struct sio_hdl *sh)
{
struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
- int err;
if (hdl->sio.mode & SIO_PLAY) {
- err = snd_pcm_drop(hdl->opcm);
- if (err < 0) {
- DALSA("couldn't stop play stream", err);
+ if (pcm_stop(hdl->opcm) != 0) {
+ DALSA("couldn't stop play stream", hdl->opcm);
hdl->sio.eof = 1;
return 0;
}
free(hdl->otmpbuf);
}
if (hdl->sio.mode & SIO_REC) {
- err = snd_pcm_drop(hdl->ipcm);
- if (err < 0) {
- DALSA("couldn't stop rec stream", err);
+ if (pcm_stop(hdl->ipcm) != 0) {
+ DALSA("couldn't stop rec stream", hdl->ipcm);
hdl->sio.eof = 1;
return 0;
}
free(hdl->itmpbuf);
}
if ((hdl->sio.mode & SIO_PLAY) && (hdl->sio.mode & SIO_REC)) {
- err = snd_pcm_unlink(hdl->ipcm);
- if (err < 0) {
- DALSA("couldn't unlink streams", err);
+ if (pcm_unlink(hdl->ipcm) != 0) {
+ DALSA("couldn't unlink streams", hdl->ipcm);
hdl->sio.eof = 1;
return 0;
}
@@ -537,143 +444,110 @@ sio_alsa_xrun(struct sio_alsa_hdl *hdl)
}
static int
-sio_alsa_setpar_hw(snd_pcm_t *pcm, snd_pcm_hw_params_t *hwp,
- snd_pcm_format_t *reqfmt, unsigned int *rate, unsigned int *chans,
- snd_pcm_uframes_t *round, unsigned int *periods)
+sio_alsa_setpar_hw(struct pcm *pcm, struct pcm_params *par,
+ struct pcm_config *cfg)
{
- static snd_pcm_format_t fmts[] = {
- SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_S32_BE,
- SND_PCM_FORMAT_U32_LE, SND_PCM_FORMAT_U32_BE,
- SND_PCM_FORMAT_S24_LE, SND_PCM_FORMAT_S24_BE,
- SND_PCM_FORMAT_U24_LE, SND_PCM_FORMAT_U24_BE,
- SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE,
- SND_PCM_FORMAT_U16_LE, SND_PCM_FORMAT_U16_BE,
- SND_PCM_FORMAT_U8, SND_PCM_FORMAT_S8
+ static enum pcm_format fmts[] = {
+ PCM_FORMAT_S32_LE, PCM_FORMAT_S32_BE,
+ PCM_FORMAT_S24_LE, PCM_FORMAT_S24_BE,
+ PCM_FORMAT_S16_LE, PCM_FORMAT_S16_BE,
+ PCM_FORMAT_S8
};
- int i, err, dir = 0;
- unsigned req_rate, min_periods = 2;
+ int i, err;
+ unsigned req_rate;
+ unsigned min, max;
- req_rate = *rate;
+ /* XXX: HW_FREE */
- err = snd_pcm_hw_free(pcm);
- if (err < 0) {
- DALSA("couldn't reset hw configuration", err);
- return 0;
- }
- err = snd_pcm_hw_params_any(pcm, hwp);
- if (err < 0) {
- DALSA("couldn't init pars", err);
- return 0;
- }
- err = snd_pcm_hw_params_set_access(pcm, hwp,
- SND_PCM_ACCESS_RW_INTERLEAVED);
- if (err < 0) {
- DALSA("couldn't set interleaved access", err);
- return 0;
- }
- err = snd_pcm_hw_params_test_format(pcm, hwp, *reqfmt);
- if (err < 0) {
+ if (pcm_params_format_test(par, cfg->format) == 0) {
for (i = 0; ; i++) {
- if (i == sizeof(fmts) / sizeof(snd_pcm_format_t)) {
+ if (i == sizeof(fmts) / sizeof(fmts[0])) {
DPRINTF("no known format found\n");
return 0;
}
- err = snd_pcm_hw_params_test_format(pcm, hwp, fmts[i]);
- if (err)
+ if (pcm_params_format_test(par, fmts[i]) == 0)
continue;
- *reqfmt = fmts[i];
+ cfg->format = fmts[i];
break;
}
}
- err = snd_pcm_hw_params_set_format(pcm, hwp, *reqfmt);
- if (err < 0) {
- DALSA("couldn't set fmt", err);
- return 0;
- }
- err = snd_pcm_hw_params_set_rate_resample(pcm, hwp, 0);
- if (err < 0) {
- DALSA("couldn't turn resampling off", err);
- return 0;
- }
- err = snd_pcm_hw_params_set_rate_near(pcm, hwp, rate, 0);
- if (err < 0) {
- DALSA("couldn't set rate", err);
- return 0;
- }
- err = snd_pcm_hw_params_set_channels_near(pcm, hwp, chans);
- if (err < 0) {
- DALSA("couldn't set channel count", err);
- return 0;
- }
- err = snd_pcm_hw_params_set_periods_integer(pcm, hwp);
- if (err < 0) {
- DALSA("couldn't set periods to integer", err);
- return 0;
- }
- err = snd_pcm_hw_params_set_periods_min(pcm, hwp, &min_periods, NULL);
- if (err < 0) {
- DALSA("couldn't set minimum periods", err);
- return 0;
- }
- err = snd_pcm_hw_params_set_period_size_integer(pcm, hwp);
- if (err < 0) {
- DALSA("couldn't set period to integer", err);
- return 0;
- }
-
- *round = *round * *rate / req_rate;
- *round = (*round + 31) & ~31;
- err = snd_pcm_hw_params_set_period_size_near(pcm, hwp, round, &dir);
- if (err < 0) {
- DALSA("couldn't set period size failed", err);
- return 0;
- }
- err = snd_pcm_hw_params_set_periods_near(pcm, hwp, periods, &dir);
- if (err < 0) {
- DALSA("couldn't set period count", err);
- return 0;
- }
- err = snd_pcm_hw_params(pcm, hwp);
+ req_rate = cfg->rate;
+ min = pcm_params_get_min(par, PCM_PARAM_RATE);
+ if (cfg->rate < min)
+ cfg->rate = min;
+ max = pcm_params_get_max(par, PCM_PARAM_RATE);
+ if (cfg->rate > max)
+ cfg->rate = max;
+
+ min = pcm_params_get_min(par, PCM_PARAM_CHANNELS);
+ if (cfg->channels < min)
+ cfg->channels = min;
+ max = pcm_params_get_max(par, PCM_PARAM_CHANNELS);
+ if (cfg->channels > max)
+ cfg->channels = max;
+
+ cfg->period_size = cfg->period_size * cfg->rate / req_rate;
+ cfg->period_size = (cfg->period_size + 31) & ~31;
+
+ min = pcm_params_get_min(par, PCM_PARAM_PERIOD_SIZE);
+ if (min < 2)
+ min = 2;
+ if (cfg->period_size < min)
+ cfg->period_size = min;
+ max = pcm_params_get_max(par, PCM_PARAM_PERIOD_SIZE);
+ if (cfg->period_size > max)
+ cfg->period_size = max;
+
+ min = pcm_params_get_min(par, PCM_PARAM_PERIODS);
+ if (cfg->period_count < min)
+ cfg->period_count = min;
+ max = pcm_params_get_max(par, PCM_PARAM_PERIODS);
+ if (cfg->period_count > max)
+ cfg->period_count = max;
+
+ cfg->start_threshold = 0;
+ cfg->stop_threshold = cfg->period_count * cfg->period_size;
+ cfg->avail_min = 1;
+ cfg->silence_size = 0;
+ cfg->silence_threshold = 0;
+
+ /* XXX: period_event=1, silence?, silence_threshold? */
+
+ err = pcm_set_config(pcm, cfg);
if (err < 0) {
- DALSA("couldn't commit params", err);
+ DALSA("couldn't set config", pcm);
return 0;
}
return 1;
}
static int
-sio_alsa_getcap_hw(snd_pcm_t *pcm, int *rates, int *fmts, int *chans)
+sio_alsa_getcap_hw(struct pcm_params *par, int *rates, int *fmts, int *chans)
{
int i, err;
- snd_pcm_hw_params_t *hwp;
-
- snd_pcm_hw_params_alloca(&hwp);
-
- err = snd_pcm_hw_params_any(pcm, hwp);
- if (err < 0) {
- DALSA("sio_alsa_trypar: couldn't init pars", err);
- return 0;
- }
+ unsigned min, max;
*fmts = 0;
for (i = 0; i < CAP_NFMTS; i++) {
- err = snd_pcm_hw_params_test_format(pcm, hwp, cap_fmts[i]);
+ err = pcm_params_format_test(par, cap_fmts[i]);
if (err == 0) {
*fmts |= 1 << i;
}
}
*rates = 0;
+ min = pcm_params_get_min(par, PCM_PARAM_RATE);
+ max = pcm_params_get_max(par, PCM_PARAM_RATE);
for (i = 0; i < CAP_NRATES; i++) {
- err = snd_pcm_hw_params_test_rate(pcm, hwp, cap_rates[i], 0);
- if (err == 0) {
+ if (min <= cap_rates[i] && cap_rates[i] <= max) {
*rates |= 1 << i;
}
}
*chans = 0;
+ min = pcm_params_get_min(par, PCM_PARAM_CHANNELS);
+ max = pcm_params_get_max(par, PCM_PARAM_CHANNELS);
for (i = 0; i < CAP_NCHANS; i++) {
- err = snd_pcm_hw_params_test_channels(pcm, hwp, cap_chans[i]);
- if (err == 0) {
+ if (min <= cap_chans[i] && cap_chans[i] <= max) {
*chans |= 1 << i;
}
}
@@ -693,13 +567,13 @@ sio_alsa_getcap(struct sio_hdl *sh, struct sio_cap *cap)
irates = orates = ifmts = ofmts = ichans = ochans = 0;
if (hdl->sio.mode & SIO_PLAY) {
- if (!sio_alsa_getcap_hw(hdl->opcm,
+ if (!sio_alsa_getcap_hw(hdl->opar,
&orates, &ofmts, &ochans)) {
return 0;
}
}
if (hdl->sio.mode & SIO_REC) {
- if (!sio_alsa_getcap_hw(hdl->ipcm,
+ if (!sio_alsa_getcap_hw(hdl->ipar,
&irates, &ifmts, &ichans)) {
return 0;
}
@@ -711,7 +585,7 @@ sio_alsa_getcap(struct sio_hdl *sh, struct sio_cap *cap)
&cap->enc[i].sig,
&cap->enc[i].le);
cap->enc[i].bps = SIO_BPS(cap->enc[0].bits);
- cap->enc[i].msb = 1;
+ cap->enc[i].msb = 0;
}
for (i = 0; i < CAP_NRATES; i++) {
cap->rate[i] = cap_rates[i];
@@ -744,186 +618,72 @@ static int
sio_alsa_setpar(struct sio_hdl *sh, struct sio_par *par)
{
struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
- snd_pcm_hw_params_t *ohwp, *ihwp;
- snd_pcm_sw_params_t *oswp, *iswp;
- snd_pcm_uframes_t iround, oround;
- snd_pcm_format_t ifmt, ofmt;
- unsigned int iperiods, operiods;
- unsigned irate, orate;
- int err;
-
- snd_pcm_hw_params_alloca(&ohwp);
- snd_pcm_sw_params_alloca(&oswp);
- snd_pcm_hw_params_alloca(&ihwp);
- snd_pcm_sw_params_alloca(&iswp);
+ struct pcm_config icfg, ocfg;
- sio_alsa_enctofmt(hdl, &ifmt, par->bits, par->sig, par->le);
- irate = (par->rate == ~0U) ? 48000 : par->rate;
+ sio_alsa_enctofmt(hdl, &icfg.format, par->bits, par->sig, par->le);
+ icfg.rate = (par->rate == ~0U) ? 48000 : par->rate;
if (par->appbufsz != ~0U) {
- iround = (par->round != ~0U) ?
+ icfg.period_size = (par->round != ~0U) ?
par->round : (par->appbufsz + 1) / 2;
- iperiods = par->appbufsz / iround;
- if (iperiods < 2)
- iperiods = 2;
+ icfg.period_count = par->appbufsz / icfg.period_size;
+ if (icfg.period_count < 2)
+ icfg.period_count = 2;
} else if (par->round != ~0U) {
- iround = par->round;
- iperiods = 2;
+ icfg.period_size = par->round;
+ icfg.period_count = 2;
} else {
- iperiods = 2;
- iround = irate / 100;
+ icfg.period_count = 2;
+ icfg.period_size = icfg.rate / 100;
}
if (hdl->sio.mode & SIO_REC) {
hdl->par.rchan = par->rchan;
- if (!sio_alsa_setpar_hw(hdl->ipcm, ihwp,
- &ifmt, &irate, &hdl->par.rchan,
- &iround, &iperiods)) {
+ if (!sio_alsa_setpar_hw(hdl->ipcm, hdl->ipar, &icfg)) {
hdl->sio.eof = 1;
return 0;
}
}
- ofmt = ifmt;
- orate = irate;
- oround = iround;
- operiods = iperiods;
+ ocfg = icfg;
if (hdl->sio.mode & SIO_PLAY) {
hdl->par.pchan = par->pchan;
- if (!sio_alsa_setpar_hw(hdl->opcm, ohwp,
- &ofmt, &orate, &hdl->par.pchan,
- &oround, &operiods)) {
+ if (!sio_alsa_setpar_hw(hdl->opcm, hdl->opar, &ocfg)) {
hdl->sio.eof = 1;
return 0;
}
- if (!(hdl->sio.mode & SIO_REC)) {
- ifmt = ofmt;
- irate = orate;
- iround = oround;
- iperiods = operiods;
- }
+ if (!(hdl->sio.mode & SIO_REC))
+ icfg = ocfg;
}
DPRINTFN(2, "ofmt = %u, orate = %u, oround = %u, operiods = %u\n",
- ofmt, orate, (unsigned int)oround, operiods);
+ ocfg.format, ocfg.rate, ocfg.period_size, ocfg.period_count);
DPRINTFN(2, "ifmt = %u, irate = %u, iround = %u, iperiods = %u\n",
- ifmt, irate, (unsigned int)iround, iperiods);
+ icfg.format, icfg.rate, icfg.period_size, icfg.period_count);
- if (ifmt != ofmt) {
+ if (icfg.format != ocfg.format) {
DPRINTF("play and rec formats differ\n");
hdl->sio.eof = 1;
return 0;
}
- if (irate != orate) {
+ if (icfg.rate != ocfg.rate) {
DPRINTF("play and rec rates differ\n");
hdl->sio.eof = 1;
return 0;
}
- if (iround != oround) {
+ if (icfg.period_size != ocfg.period_size) {
DPRINTF("play and rec block sizes differ\n");
hdl->sio.eof = 1;
return 0;
}
- if (!sio_alsa_fmttopar(hdl, ifmt,
+ if (!sio_alsa_fmttopar(hdl, icfg.format,
&hdl->par.bits, &hdl->par.sig, &hdl->par.le))
return 0;
- hdl->par.msb = 1;
+ hdl->par.msb = 0;
hdl->par.bps = SIO_BPS(hdl->par.bits);
- hdl->par.rate = orate;
- hdl->par.round = oround;
- hdl->par.bufsz = oround * operiods;
+ hdl->par.rate = ocfg.rate;
+ hdl->par.round = ocfg.period_size;
+ hdl->par.bufsz = ocfg.period_size * ocfg.period_count;
hdl->par.appbufsz = hdl->par.bufsz;
- /* software params */
-
- if (hdl->sio.mode & SIO_REC) {
- err = snd_pcm_sw_params_current(hdl->ipcm, iswp);
- if (err < 0) {
- DALSA("couldn't get current rec params", err);
- hdl->sio.eof = 1;
- return 0;
- }
- err = snd_pcm_sw_params_set_start_threshold(hdl->ipcm,
- iswp, 0);
- if (err < 0) {
- DALSA("couldn't set rec start threshold", err);
- hdl->sio.eof = 1;
- return 0;
- }
- err = snd_pcm_sw_params_set_stop_threshold(hdl->ipcm,
- iswp, hdl->par.bufsz);
- if (err < 0) {
- DALSA("couldn't set rec stop threshold", err);
- hdl->sio.eof = 1;
- return 0;
- }
- err = snd_pcm_sw_params_set_avail_min(hdl->ipcm,
- iswp, 1);
- if (err < 0) {
- DALSA("couldn't set rec avail min", err);
- hdl->sio.eof = 1;
- return 0;
- }
- err = snd_pcm_sw_params_set_period_event(hdl->ipcm, iswp, 1);
- if (err < 0) {
- DALSA("couldn't set rec period event", err);
- hdl->sio.eof = 1;
- return 0;
- }
- err = snd_pcm_sw_params(hdl->ipcm, iswp);
- if (err < 0) {
- DALSA("couldn't commit rec sw params", err);
- hdl->sio.eof = 1;
- return 0;
- }
- }
- if (hdl->sio.mode & SIO_PLAY) {
- err = snd_pcm_sw_params_current(hdl->opcm, oswp);
- if (err < 0) {
- DALSA("couldn't get current play params", err);
- hdl->sio.eof = 1;
- return 0;
- }
- err = snd_pcm_sw_params_set_start_threshold(hdl->opcm,
- oswp, hdl->par.bufsz - hdl->par.round);
- if (err < 0) {
- DALSA("couldn't set play start threshold", err);
- hdl->sio.eof = 1;
- return 0;
- }
- err = snd_pcm_sw_params_set_stop_threshold(hdl->opcm,
- oswp, hdl->par.bufsz);
- if (err < 0) {
- DALSA("couldn't set play stop threshold", err);
- hdl->sio.eof = 1;
- return 0;
- }
- err = snd_pcm_sw_params_set_avail_min(hdl->opcm,
- oswp, 1);
- if (err < 0) {
- DALSA("couldn't set play avail min", err);
- hdl->sio.eof = 1;
- return 0;
- }
- err = snd_pcm_sw_params_set_period_event(hdl->opcm, oswp, 1);
- if (err < 0) {
- DALSA("couldn't set play period event", err);
- hdl->sio.eof = 1;
- return 0;
- }
- err = snd_pcm_sw_params(hdl->opcm, oswp);
- if (err < 0) {
- DALSA("couldn't commit play sw params", err);
- hdl->sio.eof = 1;
- return 0;
- }
- }
-#ifdef DEBUG
- if (_sndio_debug >= 2) {
- if (hdl->sio.mode & SIO_REC)
- snd_pcm_dump(hdl->ipcm, output);
- if (hdl->sio.mode & SIO_PLAY)
- snd_pcm_dump(hdl->opcm, output);
- }
-#endif
return 1;
}
@@ -940,7 +700,7 @@ static size_t
sio_alsa_read(struct sio_hdl *sh, void *buf, size_t len)
{
struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
- snd_pcm_sframes_t n;
+ int n;
size_t todo;
if (hdl->ipartial > 0) {
@@ -959,7 +719,7 @@ sio_alsa_read(struct sio_hdl *sh, void *buf, size_t len)
todo = len / hdl->ibpf;
if (todo == 0)
return 0;
- while ((n = snd_pcm_readi(hdl->ipcm, buf, todo)) < 0) {
+ while ((n = pcm_readi(hdl->ipcm, buf, todo)) < 0) {
if (n == -EINTR)
continue;
if (n == -EPIPE || n == -ESTRPIPE) {
@@ -967,7 +727,7 @@ sio_alsa_read(struct sio_hdl *sh, void *buf, size_t len)
return 0;
}
if (n != -EAGAIN) {
- DALSA("couldn't read data", n);
+ DALSA("couldn't read data", hdl->ipcm);
hdl->sio.eof = 1;
}
return 0;
@@ -989,7 +749,7 @@ static size_t
sio_alsa_write(struct sio_hdl *sh, const void *buf, size_t len)
{
struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
- snd_pcm_sframes_t n;
+ int n;
size_t todo;
if (len < hdl->obpf || hdl->opartial > 0) {
@@ -1007,7 +767,7 @@ sio_alsa_write(struct sio_hdl *sh, const void *buf, size_t len)
todo = len / hdl->obpf;
if (todo == 0)
return 0;
- while ((n = snd_pcm_writei(hdl->opcm, buf, todo)) < 0) {
+ while ((n = pcm_writei(hdl->opcm, buf, todo)) < 0) {
if (n == -EINTR)
continue;
if (n == -ESTRPIPE || n == -EPIPE) {
@@ -1015,7 +775,7 @@ sio_alsa_write(struct sio_hdl *sh, const void *buf, size_t len)
return 0;
}
if (n != -EAGAIN) {
- DALSA("couldn't write data", n);
+ DALSA("couldn't write data", hdl->opcm);
hdl->sio.eof = 1;
}
return 0;
@@ -1062,16 +822,14 @@ sio_alsa_onmove(struct sio_alsa_hdl *hdl)
static int
sio_alsa_nfds(struct sio_hdl *sh)
{
- struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
-
- return hdl->nfds;
+ return 2;
}
static int
sio_alsa_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events)
{
struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
- int i;
+ int i, nfds;
if (hdl->sio.eof)
return 0;
@@ -1083,100 +841,86 @@ sio_alsa_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events)
hdl->events &= ~POLLIN;
if (!hdl->sio.started)
hdl->events = 0;
- memset(pfd, 0, sizeof(struct pollfd) * hdl->nfds);
- hdl->onfds = hdl->infds = 0;
+ memset(pfd, 0, sizeof(struct pollfd) * 2);
+ nfds = 0;
if (hdl->events & POLLOUT) {
if (!hdl->running &&
- snd_pcm_state(hdl->opcm) == SND_PCM_STATE_RUNNING)
+ pcm_state(hdl->opcm) == PCM_STATE_RUNNING)
sio_alsa_onmove(hdl);
- hdl->onfds = snd_pcm_poll_descriptors(hdl->opcm,
- pfd, hdl->nfds);
- if (hdl->onfds < 0) {
- DALSA("couldn't poll play descriptors",
- hdl->onfds);
- hdl->sio.eof = 1;
- return 0;
- }
+
+ pfd[0].fd = pcm_get_poll_fd(hdl->opcm);
+ pfd[0].events = POLLOUT;
+ nfds++;
}
if (hdl->events & POLLIN) {
if (!hdl->running &&
- snd_pcm_state(hdl->ipcm) == SND_PCM_STATE_RUNNING)
+ pcm_state(hdl->ipcm) == PCM_STATE_RUNNING)
sio_alsa_onmove(hdl);
- hdl->infds = snd_pcm_poll_descriptors(hdl->ipcm,
- pfd + hdl->onfds, hdl->nfds - hdl->onfds);
- if (hdl->infds < 0) {
- DALSA("couldn't poll rec descriptors",
- hdl->infds);
- hdl->sio.eof = 1;
- return 0;
- }
+
+ pfd[nfds].fd = pcm_get_poll_fd(hdl->ipcm);
+ pfd[nfds].events = POLLIN;
+ nfds++;
}
- DPRINTFN(4, "sio_alsa_pollfd: events = %x, nfds = %d + %d\n",
- events, hdl->onfds, hdl->infds);
+ DPRINTFN(4, "sio_alsa_pollfd: events = %x, nfds = %d\n",
+ events, nfds);
- for (i = 0; i < hdl->onfds + hdl->infds; i++) {
+ for (i = 0; i < nfds; i++) {
DPRINTFN(4, "sio_alsa_pollfd: pfds[%d].events = %x\n",
i, pfd[i].events);
}
- return hdl->onfds + hdl->infds;
+ return nfds;
}
int
sio_alsa_revents(struct sio_hdl *sh, struct pollfd *pfd)
{
struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
- snd_pcm_sframes_t iused, oavail, oused;
- snd_pcm_state_t istate, ostate;
- unsigned short revents, r;
- int nfds, err, i;
+ struct timespec ts;
+ unsigned iused, oavail, oused;
+ int istate, ostate;
+ unsigned short revents;
+ int nfds, i;
if (hdl->sio.eof)
return POLLHUP;
- for (i = 0; i < hdl->onfds + hdl->infds; i++) {
+ nfds = 0;
+ if (hdl->events & POLLOUT)
+ nfds++;
+ if (hdl->events & POLLIN)
+ nfds++;
+
+ for (i = 0; i < nfds; i++) {
DPRINTFN(4, "sio_alsa_revents: pfds[%d].revents = %x\n",
i, pfd[i].revents);
}
revents = nfds = 0;
if (hdl->events & POLLOUT) {
- err = snd_pcm_poll_descriptors_revents(hdl->opcm,
- pfd, hdl->onfds, &r);
- if (err < 0) {
- DALSA("couldn't get play events", err);
- hdl->sio.eof = 1;
- return POLLHUP;
- }
- revents |= r;
- nfds += hdl->onfds;
+ revents |= pfd[0].revents;
+ ++nfds;
}
if (hdl->events & POLLIN) {
- err = snd_pcm_poll_descriptors_revents(hdl->ipcm,
- pfd + nfds, hdl->infds, &r);
- if (err < 0) {
- DALSA("couldn't get rec events", err);
- hdl->sio.eof = 1;
- return POLLHUP;
- }
- revents |= r;
- nfds += hdl->infds;
+ revents |= pfd[nfds].revents;
+ ++nfds;
}
if (hdl->sio.mode & SIO_PLAY) {
- ostate = snd_pcm_state(hdl->opcm);
- if (ostate == SND_PCM_STATE_XRUN) {
+ ostate = pcm_state(hdl->opcm);
+ if (ostate == PCM_STATE_XRUN) {
if (!sio_alsa_xrun(hdl))
return POLLHUP;
return 0;
}
- if (ostate == SND_PCM_STATE_RUNNING ||
- ostate == SND_PCM_STATE_PREPARED) {
- oavail = snd_pcm_avail_update(hdl->opcm);
- if (oavail < 0) {
+ if (ostate == PCM_STATE_RUNNING ||
+ ostate == PCM_STATE_PREPARED) {
+ if (pcm_get_htimestamp(hdl->opcm, &oavail, &ts) != 0) {
+ /*
if (oavail == -EPIPE || oavail == -ESTRPIPE) {
if (!sio_alsa_xrun(hdl))
return POLLHUP;
return 0;
}
- DALSA("couldn't get play buffer ptr", oavail);
+ */
+ DPRINTF("couldn't get play buffer ptr\n");
hdl->sio.eof = 1;
return POLLHUP;
}
@@ -1186,22 +930,23 @@ sio_alsa_revents(struct sio_hdl *sh, struct pollfd *pfd)
}
}
if (hdl->sio.mode & SIO_REC) {
- istate = snd_pcm_state(hdl->ipcm);
- if (istate == SND_PCM_STATE_XRUN) {
+ istate = pcm_state(hdl->ipcm);
+ if (istate == PCM_STATE_XRUN) {
if (!sio_alsa_xrun(hdl))
return POLLHUP;
return 0;
}
- if (istate == SND_PCM_STATE_RUNNING ||
- istate == SND_PCM_STATE_PREPARED) {
- iused = snd_pcm_avail_update(hdl->ipcm);
- if (iused < 0) {
+ if (istate == PCM_STATE_RUNNING ||
+ istate == PCM_STATE_PREPARED) {
+ if (pcm_get_htimestamp(hdl->ipcm, &iused, &ts) != 0) {
+ /*
if (iused == -EPIPE || iused == -ESTRPIPE) {
if (!sio_alsa_xrun(hdl))
return POLLHUP;
return 0;
}
- DALSA("couldn't get rec buffer ptr", iused);
+ */
+ DPRINTF("couldn't get rec buffer ptr\n");
hdl->sio.eof = 1;
return POLLHUP;
}
--
2.37.3