]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Fixed file plugin - mmap access was broken and revents were not handled correctly
authorJaroslav Kysela <perex@perex.cz>
Sun, 8 Feb 2004 10:19:52 +0000 (10:19 +0000)
committerJaroslav Kysela <perex@perex.cz>
Sun, 8 Feb 2004 10:19:52 +0000 (10:19 +0000)
src/pcm/pcm.c
src/pcm/pcm_file.c
src/pcm/pcm_local.h
src/pcm/pcm_mmap.c
src/pcm/pcm_plug.c

index 272c9541ca27a35d26b8211b82e60bfdfccc3463..9ddfbd8addc78bf683c350c5de7907607d5683e8 100644 (file)
@@ -2257,6 +2257,8 @@ int snd_pcm_area_copy(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t
        char *dst;
        int width;
        int src_step, dst_step;
+       if (dst_area == src_area && dst_offset == src_offset)
+               return 0;
        if (!src_area->addr)
                return snd_pcm_area_silence(dst_area, dst_offset, samples, format);
        src = snd_pcm_channel_area_addr(src_area, src_offset);
index 4dfa11405c2504762cead9b06a6b0a9570a6a048..81b2704d250311d6d479124b01253fbe5f5dc138 100644 (file)
@@ -138,6 +138,12 @@ static int snd_pcm_file_async(snd_pcm_t *pcm, int sig, pid_t pid)
        return snd_pcm_async(file->slave, sig, pid);
 }
 
+static int snd_pcm_file_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
+{
+       snd_pcm_file_t *file = pcm->private_data;
+       return snd_pcm_poll_descriptors_revents(file->slave, pfds, nfds, revents);
+}
+
 static int snd_pcm_file_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
 {
        snd_pcm_file_t *file = pcm->private_data;
@@ -345,6 +351,19 @@ static int snd_pcm_file_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
        return snd_pcm_hw_refine(file->slave, params);
 }
 
+static int snd_pcm_file_hw_free(snd_pcm_t *pcm)
+{
+       snd_pcm_file_t *file = pcm->private_data;
+       if (file->wbuf) {
+               free(file->wbuf);
+               if (file->wbuf_areas)
+                       free(file->wbuf_areas);
+               file->wbuf = 0;
+               file->wbuf_areas = 0;
+       }
+       return snd_pcm_hw_free(file->slave);
+}
+
 static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
 {
        snd_pcm_file_t *file = pcm->private_data;
@@ -358,7 +377,15 @@ static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
        file->wbuf_size_bytes = snd_pcm_frames_to_bytes(slave, file->wbuf_size);
        assert(!file->wbuf);
        file->wbuf = malloc(file->wbuf_size_bytes);
+       if (file->wbuf == NULL) {
+               snd_pcm_file_hw_free(pcm);
+               return -ENOMEM;
+       }
        file->wbuf_areas = malloc(sizeof(*file->wbuf_areas) * slave->channels);
+       if (file->wbuf_areas == NULL) {
+               snd_pcm_file_hw_free(pcm);
+               return -ENOMEM;
+       }
        file->appl_ptr = file->file_ptr_bytes = 0;
        for (channel = 0; channel < slave->channels; ++channel) {
                snd_pcm_channel_area_t *a = &file->wbuf_areas[channel];
@@ -369,18 +396,6 @@ static int snd_pcm_file_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
        return 0;
 }
 
-static int snd_pcm_file_hw_free(snd_pcm_t *pcm)
-{
-       snd_pcm_file_t *file = pcm->private_data;
-       if (file->wbuf) {
-               free(file->wbuf);
-               free(file->wbuf_areas);
-               file->wbuf = 0;
-               file->wbuf_areas = 0;
-       }
-       return snd_pcm_hw_free(file->slave);
-}
-
 static int snd_pcm_file_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
 {
        snd_pcm_file_t *file = pcm->private_data;
@@ -389,11 +404,23 @@ static int snd_pcm_file_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
 
 static int snd_pcm_file_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
 {
+       snd_pcm_file_t *file = pcm->private_data;
+       snd_pcm_t *slave = file->slave;
+       pcm->running_areas = slave->running_areas;
+       pcm->stopped_areas = slave->stopped_areas;
+       pcm->mmap_channels = slave->mmap_channels;
+       pcm->mmap_shadow = 1;
        return 0;
 }
 
 static int snd_pcm_file_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
 {
+       snd_pcm_file_t *file = pcm->private_data;
+       snd_pcm_t *slave = file->slave;
+       pcm->mmap_channels = NULL;
+       pcm->running_areas = NULL;
+       pcm->stopped_areas = NULL;
+       pcm->mmap_shadow = 0;
        return 0;
 }
 
@@ -423,6 +450,7 @@ static snd_pcm_ops_t snd_pcm_file_ops = {
        .dump = snd_pcm_file_dump,
        .nonblock = snd_pcm_file_nonblock,
        .async = snd_pcm_file_async,
+       .poll_revents = snd_pcm_file_poll_revents,
        .mmap = snd_pcm_file_mmap,
        .munmap = snd_pcm_file_munmap,
 };
@@ -512,6 +540,7 @@ int snd_pcm_file_open(snd_pcm_t **pcmp, const char *name,
        pcm->private_data = file;
        pcm->poll_fd = slave->poll_fd;
        pcm->poll_events = slave->poll_events;
+       pcm->mmap_shadow = 1;
        snd_pcm_link_hw_ptr(pcm, slave);
        snd_pcm_link_appl_ptr(pcm, slave);
        *pcmp = pcm;
index e5ecb90cd7c5a3234a4877b892ae58034ea3a569..f01f7a00bc890684a06cb7067a2ac6f7c318689e 100644 (file)
@@ -200,9 +200,9 @@ struct _snd_pcm {
        snd_pcm_rbptr_t appl;
        snd_pcm_rbptr_t hw;
        snd_pcm_uframes_t min_align;
-       int mmap_rw;
-       int shadow_mmap;
-       int donot_close;
+       int mmap_rw: 1,
+           mmap_shadow: 1,
+           donot_close: 1;
        snd_pcm_channel_info_t *mmap_channels;
        snd_pcm_channel_area_t *running_areas;
        snd_pcm_channel_area_t *stopped_areas;
index dd30f5c77647c98066526fbd1780419d00240bc1..6cf1ff1aa610301dd4f22f2fc773924bc3cd4487 100644 (file)
@@ -295,7 +295,7 @@ int snd_pcm_mmap(snd_pcm_t *pcm)
        err = pcm->ops->mmap(pcm);
        if (err < 0)
                return err;
-       if (pcm->shadow_mmap)
+       if (pcm->mmap_shadow)
                return 0;
        pcm->mmap_channels = calloc(pcm->channels, sizeof(pcm->mmap_channels[0]));
        if (!pcm->mmap_channels)
@@ -434,7 +434,7 @@ int snd_pcm_munmap(snd_pcm_t *pcm)
        unsigned int c;
        assert(pcm);
        assert(pcm->mmap_channels);
-       if (pcm->shadow_mmap)
+       if (pcm->mmap_shadow)
                return pcm->ops->munmap(pcm);
        for (c = 0; c < pcm->channels; ++c) {
                snd_pcm_channel_info_t *i = &pcm->mmap_channels[c];
index b3f43b9d7891496bb75ec27a0277d217dfc3b97a..bfca32bb99d5e211df341800c1849855de482c4d 100644 (file)
@@ -943,7 +943,7 @@ static int snd_pcm_plug_mmap(snd_pcm_t *pcm)
        pcm->mmap_channels = plug->slave->mmap_channels;
        pcm->running_areas = plug->slave->running_areas;
        pcm->stopped_areas = plug->slave->stopped_areas;
-       pcm->shadow_mmap = 1;
+       pcm->mmap_shadow = 1;
        return 0;
 }
 
@@ -953,7 +953,7 @@ static int snd_pcm_plug_munmap(snd_pcm_t *pcm)
        pcm->mmap_channels = NULL;
        pcm->running_areas = NULL;
        pcm->stopped_areas = NULL;
-       pcm->shadow_mmap = 0;
+       pcm->mmap_shadow = 0;
        return 0;
 }