From: Takashi Iwai Date: Fri, 23 Nov 2007 14:46:48 +0000 (+0100) Subject: Fix mmap with multi plugin X-Git-Tag: v1.0.16rc1~44 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=0b66de95a9733dfbe0292bc41324582edc13550c;p=alsa-lib.git Fix mmap with multi plugin The mmap of multi plugin seems broken (for a long time!) due to its creation of local buffer via snd_pcm_mmap(). Since the multi plugin just needs to shadow the mmap buffer of each slave, it now has mmap_shadow=1 and its own mmap/unmap method to do shadowing. --- diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c index e15038cc..dfd679cc 100644 --- a/src/pcm/pcm_multi.c +++ b/src/pcm/pcm_multi.c @@ -690,13 +690,44 @@ static snd_pcm_sframes_t snd_pcm_multi_mmap_commit(snd_pcm_t *pcm, return size; } -static int snd_pcm_multi_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) +static int snd_pcm_multi_munmap(snd_pcm_t *pcm) { + free(pcm->mmap_channels); + free(pcm->running_areas); + pcm->mmap_channels = NULL; + pcm->running_areas = NULL; return 0; } -static int snd_pcm_multi_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) +static int snd_pcm_multi_mmap(snd_pcm_t *pcm) { + snd_pcm_multi_t *multi = pcm->private_data; + unsigned int c; + + pcm->mmap_channels = calloc(pcm->channels, + sizeof(pcm->mmap_channels[0])); + pcm->running_areas = calloc(pcm->channels, + sizeof(pcm->running_areas[0])); + if (!pcm->mmap_channels || !pcm->running_areas) { + snd_pcm_multi_munmap(pcm); + return -ENOMEM; + } + + /* Copy the slave mmapped buffer data */ + for (c = 0; c < pcm->channels; c++) { + snd_pcm_multi_channel_t *chan = &multi->channels[c]; + snd_pcm_t *slave; + if (chan->slave_idx < 0) { + snd_pcm_multi_munmap(pcm); + return -ENXIO; + } + slave = multi->slaves[chan->slave_idx].pcm; + pcm->mmap_channels[c] = + slave->mmap_channels[chan->slave_channel]; + pcm->mmap_channels[c].channel = c; + pcm->running_areas[c] = + slave->running_areas[chan->slave_channel]; + } return 0; } @@ -850,6 +881,7 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, return err; } pcm->mmap_rw = 1; + pcm->mmap_shadow = 1; /* has own mmap method */ pcm->ops = &snd_pcm_multi_ops; pcm->fast_ops = &snd_pcm_multi_fast_ops; pcm->private_data = multi;