diff --git a/spa/plugins/alsa/alsa-pcm-sink.c b/spa/plugins/alsa/alsa-pcm-sink.c index d84f1ee33..9182653df 100644 --- a/spa/plugins/alsa/alsa-pcm-sink.c +++ b/spa/plugins/alsa/alsa-pcm-sink.c @@ -797,6 +797,8 @@ impl_init(const struct spa_handle_factory *factory, this->default_period_size = atoi(info->items[i].value); } else if (!strcmp(info->items[i].key, "api.alsa.headroom")) { this->default_headroom = atoi(info->items[i].value); + } else if (!strcmp(info->items[i].key, "api.alsa.disable-mmap")) { + this->disable_mmap = atoi(info->items[i].value); } } return 0; diff --git a/spa/plugins/alsa/alsa-pcm-source.c b/spa/plugins/alsa/alsa-pcm-source.c index 81f03f8f4..22b4a3069 100644 --- a/spa/plugins/alsa/alsa-pcm-source.c +++ b/spa/plugins/alsa/alsa-pcm-source.c @@ -818,6 +818,8 @@ impl_init(const struct spa_handle_factory *factory, this->default_period_size = atoi(info->items[i].value); } else if (!strcmp(info->items[i].key, "api.alsa.headroom")) { this->default_headroom = atoi(info->items[i].value); + } else if (!strcmp(info->items[i].key, "api.alsa.disable-mmap")) { + this->disable_mmap = atoi(info->items[i].value); } } return 0; diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c index 3fda9f195..17c041323 100644 --- a/spa/plugins/alsa/alsa-pcm.c +++ b/spa/plugins/alsa/alsa-pcm.c @@ -516,11 +516,17 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_ snd_pcm_access_mask_alloca(&amask); snd_pcm_hw_params_get_access_mask(params, amask); - if ((err = snd_pcm_hw_params_set_access(hndl, params, - planar ? SND_PCM_ACCESS_MMAP_NONINTERLEAVED - : SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0) { - spa_log_debug(state->log, NAME" %p: MMAP not possible: %s", state, - snd_strerror(err)); + state->use_mmap = !state->disable_mmap; + if (state->use_mmap) { + if ((err = snd_pcm_hw_params_set_access(hndl, params, + planar ? SND_PCM_ACCESS_MMAP_NONINTERLEAVED + : SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0) { + spa_log_debug(state->log, NAME" %p: MMAP not possible: %s", state, + snd_strerror(err)); + state->use_mmap = false; + } + } + if (!state->use_mmap) { if ((err = snd_pcm_hw_params_set_access(hndl, params, planar ? SND_PCM_ACCESS_RW_NONINTERLEAVED : SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { @@ -528,9 +534,6 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_ snd_strerror(err)); return err; } - state->use_mmap = false; - } else { - state->use_mmap = true; } /* disable ALSA wakeups, we use a timer */ diff --git a/spa/plugins/alsa/alsa-pcm.h b/spa/plugins/alsa/alsa-pcm.h index 35d266ca4..69ab6f690 100644 --- a/spa/plugins/alsa/alsa-pcm.h +++ b/spa/plugins/alsa/alsa-pcm.h @@ -116,6 +116,7 @@ struct state { unsigned int default_channels; unsigned int default_rate; struct channel_map default_pos; + unsigned int disable_mmap; snd_pcm_uframes_t buffer_frames; snd_pcm_uframes_t period_frames; diff --git a/src/daemon/media-session.d/alsa-monitor.conf b/src/daemon/media-session.d/alsa-monitor.conf index da5f7a2a6..01cde4e6d 100644 --- a/src/daemon/media-session.d/alsa-monitor.conf +++ b/src/daemon/media-session.d/alsa-monitor.conf @@ -56,6 +56,7 @@ rules = [ #audio.position = "FL,FR" #api.alsa.period-size = 1024 #api.alsa.headroom = 0 + #api.alsa.disable-mmap = false } } }