On Mon, 2 Jan 2006, Jaroslav Kysela wrote:

> > Running "speaker-test -c2 -Dplug:test" only plays the "front right"
> > audio out of both front speakers.
> 
> Confirmed. It seems that the problem has nothing with the ALSA LADSPA 
> plugin code but with the latest mmap code optimizations. I'm still 
> figuring where the real bug is.

The attached patch fixes this bug.

                                                Jaroslav

-----
Jaroslav Kysela <[EMAIL PROTECTED]>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs
? out.txt
Index: pcm_mmap.c
===================================================================
RCS file: /cvsroot/alsa/alsa-lib/src/pcm/pcm_mmap.c,v
retrieving revision 1.76
diff -u -r1.76 pcm_mmap.c
--- pcm_mmap.c  30 Nov 2005 11:39:21 -0000      1.76
+++ pcm_mmap.c  2 Jan 2006 12:11:10 -0000
@@ -326,122 +326,130 @@
        for (c = 0; c < pcm->channels; ++c) {
                snd_pcm_channel_info_t *i = &pcm->mmap_channels[c];
                snd_pcm_channel_area_t *a = &pcm->running_areas[c];
+               char *ptr;
+               size_t size;
                unsigned int c1;
-               if (!i->addr) {
-                       char *ptr;
-                       size_t size = i->first + i->step * (pcm->buffer_size - 
1) + pcm->sample_bits;
-                       for (c1 = c + 1; c1 < pcm->channels; ++c1) {
-                               snd_pcm_channel_info_t *i1 = 
&pcm->mmap_channels[c1];
-                               size_t s;
-                               if (i1->type != i->type)
+               if (i->addr) {
+                       a->addr = i->addr;
+                       a->first = i->first;
+                       a->step = i->step;
+                       continue;
+                }
+                size = i->first + i->step * (pcm->buffer_size - 1) + 
pcm->sample_bits;
+               for (c1 = c + 1; c1 < pcm->channels; ++c1) {
+                       snd_pcm_channel_info_t *i1 = &pcm->mmap_channels[c1];
+                       size_t s;
+                       if (i1->type != i->type)
+                               continue;
+                       switch (i1->type) {
+                       case SND_PCM_AREA_MMAP:
+                               if (i1->u.mmap.fd != i->u.mmap.fd ||
+                                   i1->u.mmap.offset != i->u.mmap.offset)
                                        continue;
-                               switch (i1->type) {
-                               case SND_PCM_AREA_MMAP:
-                                       if (i1->u.mmap.fd != i->u.mmap.fd ||
-                                           i1->u.mmap.offset != 
i->u.mmap.offset)
-                                               continue;
-                                       break;
-                               case SND_PCM_AREA_SHM:
-                                       if (i1->u.shm.shmid != i->u.shm.shmid)
-                                               continue;
-                                       break;
-                               case SND_PCM_AREA_LOCAL:
-                                       break;
-                               default:
-                                       assert(0);
-                               }
-                               s = i1->first + i1->step * (pcm->buffer_size - 
1) + pcm->sample_bits;
-                               if (s > size)
-                                       size = s;
+                               break;
+                       case SND_PCM_AREA_SHM:
+                               if (i1->u.shm.shmid != i->u.shm.shmid)
+                                       continue;
+                               break;
+                       case SND_PCM_AREA_LOCAL:
+                               break;
+                       default:
+                               assert(0);
                        }
-                       size = (size + 7) / 8;
-                       size = page_align(size);
-                       switch (i->type) {
-                       case SND_PCM_AREA_MMAP:
-                               ptr = mmap(NULL, size, PROT_READ|PROT_WRITE, 
MAP_FILE|MAP_SHARED, i->u.mmap.fd, i->u.mmap.offset);
-                               if (ptr == MAP_FAILED) {
-                                       SYSERR("mmap failed");
+                       s = i1->first + i1->step * (pcm->buffer_size - 1) + 
pcm->sample_bits;
+                       if (s > size)
+                               size = s;
+               }
+               size = (size + 7) / 8;
+               size = page_align(size);
+               switch (i->type) {
+               case SND_PCM_AREA_MMAP:
+                       ptr = mmap(NULL, size, PROT_READ|PROT_WRITE, 
MAP_FILE|MAP_SHARED, i->u.mmap.fd, i->u.mmap.offset);
+                       if (ptr == MAP_FAILED) {
+                               SYSERR("mmap failed");
+                               return -errno;
+                       }
+                       i->addr = ptr;
+                       break;
+               case SND_PCM_AREA_SHM:
+                       if (i->u.shm.shmid < 0) {
+                               int id;
+                               /* FIXME: safer permission? */
+                               id = shmget(IPC_PRIVATE, size, 0666);
+                               if (id < 0) {
+                                       SYSERR("shmget failed");
                                        return -errno;
                                }
-                               i->addr = ptr;
-                               break;
-                       case SND_PCM_AREA_SHM:
-                               if (i->u.shm.shmid < 0) {
-                                       int id;
-                                       /* FIXME: safer permission? */
-                                       id = shmget(IPC_PRIVATE, size, 0666);
-                                       if (id < 0) {
-                                               SYSERR("shmget failed");
-                                               return -errno;
-                                       }
-                                       i->u.shm.shmid = id;
-                                       ptr = shmat(i->u.shm.shmid, 0, 0);
-                                       if (ptr == (void *) -1) {
-                                               SYSERR("shmat failed");
-                                               return -errno;
-                                       }
-                                       /* automatically remove segment if not 
used */
-                                       if (shmctl(id, IPC_RMID, NULL) < 0){
-                                               SYSERR("shmctl mark remove 
failed");
-                                               return -errno;
-                                       }
-                                       i->u.shm.area = snd_shm_area_create(id, 
ptr);
-                                       if (i->u.shm.area == NULL) {
-                                               SYSERR("snd_shm_area_create 
failed");
-                                               return -ENOMEM;
-                                       }
-                                       if (pcm->access == 
SND_PCM_ACCESS_MMAP_INTERLEAVED ||
-                                           pcm->access == 
SND_PCM_ACCESS_RW_INTERLEAVED) {
-                                               unsigned int c1;
-                                               for (c1 = c + 1; c1 < 
pcm->channels; c1++) {
-                                                       snd_pcm_channel_info_t 
*i1 = &pcm->mmap_channels[c1];
-                                                       if (i1->u.shm.shmid < 
0) {
-                                                               i1->u.shm.shmid 
= id;
-                                                               i1->u.shm.area 
= snd_shm_area_share(i->u.shm.area);
-                                                       }
+                               i->u.shm.shmid = id;
+                               ptr = shmat(i->u.shm.shmid, 0, 0);
+                               if (ptr == (void *) -1) {
+                                       SYSERR("shmat failed");
+                                       return -errno;
+                               }
+                               /* automatically remove segment if not used */
+                               if (shmctl(id, IPC_RMID, NULL) < 0){
+                                       SYSERR("shmctl mark remove failed");
+                                       return -errno;
+                               }
+                               i->u.shm.area = snd_shm_area_create(id, ptr);
+                               if (i->u.shm.area == NULL) {
+                                       SYSERR("snd_shm_area_create failed");
+                                       return -ENOMEM;
+                               }
+                               if (pcm->access == 
SND_PCM_ACCESS_MMAP_INTERLEAVED ||
+                                   pcm->access == 
SND_PCM_ACCESS_RW_INTERLEAVED) {
+                                       unsigned int c1;
+                                       for (c1 = c + 1; c1 < pcm->channels; 
c1++) {
+                                               snd_pcm_channel_info_t *i1 = 
&pcm->mmap_channels[c1];
+                                               if (i1->u.shm.shmid < 0) {
+                                                       i1->u.shm.shmid = id;
+                                                       i1->u.shm.area = 
snd_shm_area_share(i->u.shm.area);
                                                }
                                        }
-                               } else {
-                                       ptr = shmat(i->u.shm.shmid, 0, 0);
-                                       if (ptr == (void*) -1) {
-                                               SYSERR("shmat failed");
-                                               return -errno;
-                                       }
                                }
-                               i->addr = ptr;
-                               break;
-                       case SND_PCM_AREA_LOCAL:
-                               ptr = malloc(size);
-                               if (ptr == NULL) {
-                                       SYSERR("malloc failed");
+                       } else {
+                               ptr = shmat(i->u.shm.shmid, 0, 0);
+                               if (ptr == (void*) -1) {
+                                       SYSERR("shmat failed");
                                        return -errno;
                                }
-                               i->addr = ptr;
+                       }
+                       i->addr = ptr;
+                       break;
+               case SND_PCM_AREA_LOCAL:
+                       ptr = malloc(size);
+                       if (ptr == NULL) {
+                               SYSERR("malloc failed");
+                               return -errno;
+                       }
+                       i->addr = ptr;
+                       break;
+               default:
+                       assert(0);
+               }
+               for (c1 = c + 1; c1 < pcm->channels; ++c1) {
+                       snd_pcm_channel_info_t *i1 = &pcm->mmap_channels[c1];
+                       if (i1->type != i->type)
+                               continue;
+                       switch (i1->type) {
+                       case SND_PCM_AREA_MMAP:
+                               if (i1->u.mmap.fd != i->u.mmap.fd ||
+                                    i1->u.mmap.offset != i->u.mmap.offset)
+                                       continue;
+                               break;
+                       case SND_PCM_AREA_SHM:
+                               if (i1->u.shm.shmid != i->u.shm.shmid)
+                                       continue;
+                               /* follow thru */
+                       case SND_PCM_AREA_LOCAL:
+                               if (pcm->access != 
SND_PCM_ACCESS_MMAP_INTERLEAVED &&
+                                   pcm->access != 
SND_PCM_ACCESS_RW_INTERLEAVED)
+                                       continue;
                                break;
                        default:
                                assert(0);
                        }
-                       for (c1 = c + 1; c1 < pcm->channels; ++c1) {
-                               snd_pcm_channel_info_t *i1 = 
&pcm->mmap_channels[c1];
-                               if (i1->type != i->type)
-                                       continue;
-                               switch (i1->type) {
-                               case SND_PCM_AREA_MMAP:
-                                       if (i1->u.mmap.fd != i->u.mmap.fd ||
-                                           i1->u.mmap.offset != 
i->u.mmap.offset)
-                                               continue;
-                                       break;
-                               case SND_PCM_AREA_SHM:
-                                       if (i1->u.shm.shmid != i->u.shm.shmid)
-                                               continue;
-                                       break;
-                               case SND_PCM_AREA_LOCAL:
-                                       break;
-                               default:
-                                       assert(0);
-                               }
-                               i1->addr = i->addr;
-                       }
+                       i1->addr = i->addr;
                }
                a->addr = i->addr;
                a->first = i->first;

Reply via email to