From 4bb5a9397366f6c773f221f31966ba7cfaffd8a3 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Sat, 3 Nov 2018 06:13:28 +0200 Subject: simulate mmap access --- src/pcm.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- src/stubs.h | 2 -- src/util/util.h | 1 + 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/pcm.c b/src/pcm.c index 014f35a..0acd77d 100644 --- a/src/pcm.c +++ b/src/pcm.c @@ -6,6 +6,11 @@ #include "util/dsp.h" #include "util/util.h" +static const snd_pcm_access_t SUPPORTED_ACCESS[] = { + SND_PCM_ACCESS_MMAP_INTERLEAVED, + SND_PCM_ACCESS_RW_INTERLEAVED +}; + static const struct format_info { const char *name; snd_pcm_format_t fmt; @@ -116,6 +121,10 @@ struct _snd_pcm { struct _snd_pcm_hw_params hw; struct _snd_pcm_sw_params sw; struct timespec start_time; + struct { + snd_pcm_channel_area_t areas[NCHAN_MAX]; + unsigned char *data; + } mmap; struct sio_hdl *hdl; const char *name; snd_pcm_uframes_t position, written, avail; @@ -260,6 +269,7 @@ int snd_pcm_close(snd_pcm_t *pcm) { sio_close(pcm->hdl); + free(pcm->mmap.data); free(pcm); return 0; } @@ -499,12 +509,48 @@ snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) ret = snd_pcm_bytes_to_frames(pcm, io.read(buffer, snd_pcm_frames_to_bytes(pcm, size), &state)); } + static size_t old_ret; + if (ret != old_ret) { + WARNX("%lu %lu %lu", pcm->avail, size, ret); + old_ret = ret; + } + assert(pcm->avail >= ret); pcm->written += ret; pcm->avail -= ret; return ret; } +int +snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames) +{ + snd_pcm_uframes_t todo_frames = pcm->avail; + if (frames) todo_frames = MIN(todo_frames, *frames); + + if (pcm->hw.stream == SND_PCM_STREAM_CAPTURE) + todo_frames = snd_pcm_readi(pcm, pcm->mmap.data, todo_frames); + + if (offset) *offset = 0; + if (frames) *frames = todo_frames; + if (areas) { + const unsigned int chans = (pcm->hw.stream == SND_PCM_STREAM_PLAYBACK ? pcm->hw.par.pchan : pcm->hw.par.rchan); + for (unsigned int i = 0; i < chans; ++i) + pcm->mmap.areas[i].addr = pcm->mmap.data + snd_pcm_format_size(pcm->hw.format, todo_frames) * i; + *areas = pcm->mmap.areas; + } + + return 0; +} + +snd_pcm_sframes_t +snd_pcm_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t frames) +{ + if (pcm->hw.stream == SND_PCM_STREAM_PLAYBACK) + return snd_pcm_writei(pcm, pcm->mmap.data, frames); + + return frames; +} + static uint64_t get_time_ns(void) { @@ -692,6 +738,22 @@ out: return ret; } +static bool +is_mmap_access(const snd_pcm_access_t access) +{ + return (access == SND_PCM_ACCESS_MMAP_INTERLEAVED || access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED || access == SND_PCM_ACCESS_MMAP_COMPLEX); +} + +static void +ensure_mmap_buffer(snd_pcm_t *pcm) +{ + free(pcm->mmap.data); + pcm->mmap.data = NULL; + + if (is_mmap_access(pcm->hw.access) && !(pcm->mmap.data = calloc(1, snd_pcm_frames_to_bytes(pcm, pcm->hw.par.bufsz)))) + ERR1(EXIT_FAILURE, "realloc"); +} + int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) { @@ -704,6 +766,7 @@ snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) WARNX("set: rate: %u, round: %u, appbufsz: %u chan: %u", params->par.rate, params->par.round, params->par.appbufsz, (params->stream == SND_PCM_STREAM_PLAYBACK ? params->par.pchan : params->par.rchan)); pcm->hw = *params; + ensure_mmap_buffer(pcm); } return snd_pcm_prepare(pcm); @@ -726,17 +789,20 @@ snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) int snd_pcm_hw_params_test_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t _access) { - if (_access != SND_PCM_ACCESS_RW_INTERLEAVED) { - WARNX("access mode `0x%x` not supported yet", _access); - return -1; + for (size_t i = 0; i < ARRAY_SIZE(SUPPORTED_ACCESS); ++i) { + if (SUPPORTED_ACCESS[i] == _access) + return 0; } - return 0; + WARNX("access mode `0x%x` not supported yet", _access); + return -1; } int snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t _access) { + WARNX("0x%x", _access); + if (snd_pcm_hw_params_test_access(pcm, params, _access) != 0) return -1; diff --git a/src/stubs.h b/src/stubs.h index 4eafb06..d7c4174 100644 --- a/src/stubs.h +++ b/src/stubs.h @@ -645,8 +645,6 @@ int snd_pcm_dump_setup(snd_pcm_t *pcm, snd_output_t *out) { WARNX1("stub"); retu int snd_pcm_hw_params_dump(snd_pcm_hw_params_t *params, snd_output_t *out) { WARNX1("stub"); return 0; } int snd_pcm_sw_params_dump(snd_pcm_sw_params_t *params, snd_output_t *out) { WARNX1("stub"); return 0; } int snd_pcm_status_dump(snd_pcm_status_t *status, snd_output_t *out) { WARNX1("stub"); return 0; } -int snd_pcm_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames) { WARNX1("stub"); return 0; } -snd_pcm_sframes_t snd_pcm_mmap_commit(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t frames) { WARNX1("stub"); return 0; } snd_pcm_sframes_t snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size) { WARNX1("stub"); return 0; } snd_pcm_sframes_t snd_pcm_mmap_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size) { WARNX1("stub"); return 0; } snd_pcm_sframes_t snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size) { WARNX1("stub"); return 0; } diff --git a/src/util/util.h b/src/util/util.h index fe3f50c..a6defc3 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -22,6 +22,7 @@ do_debug(void) #define WARNX(x, ...) do { if (do_debug()) warnx("asound: %s " x, __func__, ##__VA_ARGS__); } while (0) #define ERRX1(x, y) do { errx(x, "asound: %s %s", __func__, y); } while (0) #define ERRX(x, y, ...) do { errx(x, "asound: %s " y, __func__, ##__VA_ARGS__); } while (0) +#define ERR1(x, y) do { err(x, "asound: %s %s", __func__, y); } while (0) #define ERR(x, y, ...) do { err(x, "asound: %s " y, __func__, ##__VA_ARGS__); } while (0) #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) -- cgit v1.2.3