OSDN Git Service

- added shm area manager code
authorJaroslav Kysela <perex@perex.cz>
Wed, 23 Apr 2003 12:41:55 +0000 (12:41 +0000)
committerJaroslav Kysela <perex@perex.cz>
Wed, 23 Apr 2003 12:41:55 +0000 (12:41 +0000)
- fixed parsing of period_size/buffer_size options for dmix, dsnoop and
  dshare plugins

include/global.h
src/Makefile.am
src/pcm/pcm.c
src/pcm/pcm_direct.c
src/pcm/pcm_direct.h
src/pcm/pcm_dmix.c
src/pcm/pcm_dshare.c
src/pcm/pcm_dsnoop.c
src/pcm/pcm_hw.c
src/pcm/pcm_local.h
src/pcm/pcm_mmap.c

index 8e59f07..2969949 100644 (file)
@@ -114,6 +114,13 @@ int snd_async_handler_get_fd(snd_async_handler_t *handler);
 int snd_async_handler_get_signo(snd_async_handler_t *handler);
 void *snd_async_handler_get_callback_private(snd_async_handler_t *handler);
 
+/**
+ * \brief Internal structure for an IPC shm area manager.
+ */
+struct snd_shm_area *snd_shm_area_create(int shmid, void *ptr);
+struct snd_shm_area *snd_shm_area_share(struct snd_shm_area *area);
+int snd_shm_area_destroy(struct snd_shm_area *area);
+
 /** Timestamp */
 typedef struct timeval snd_timestamp_t;
 /** Hi-res timestamp */
index afe7d59..feeec57 100644 (file)
@@ -9,7 +9,7 @@ VSYMS =
 endif
 
 lib_LTLIBRARIES = libasound.la
-libasound_la_SOURCES = conf.c confmisc.c input.c output.c async.c error.c dlmisc.c socket.c
+libasound_la_SOURCES = conf.c confmisc.c input.c output.c async.c error.c dlmisc.c socket.c shmarea.c
 libasound_la_LIBADD = control/libcontrol.la mixer/libmixer.la pcm/libpcm.la \
                       rawmidi/librawmidi.la timer/libtimer.la \
                      hwdep/libhwdep.la seq/libseq.la instr/libinstr.la \
index b7ec267..36fb018 100644 (file)
@@ -6246,7 +6246,10 @@ static const char *names[SND_PCM_HW_PARAM_LAST_INTERVAL + 1] = {
        [SND_PCM_HW_PARAM_CHANNELS] = "channels",
        [SND_PCM_HW_PARAM_RATE] = "rate",
        [SND_PCM_HW_PARAM_PERIOD_TIME] = "period_time",
-       [SND_PCM_HW_PARAM_BUFFER_TIME] = "buffer_time"
+       [SND_PCM_HW_PARAM_PERIOD_SIZE] = "period_size",
+       [SND_PCM_HW_PARAM_BUFFER_TIME] = "buffer_time",
+       [SND_PCM_HW_PARAM_BUFFER_SIZE] = "buffer_size",
+       [SND_PCM_HW_PARAM_PERIODS] = "periods"
 };
 
 int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
index 5a0f146..dded984 100644 (file)
@@ -278,6 +278,8 @@ static void server_job(snd_pcm_direct_t *dmix)
        }
        close(dmix->server_fd);
        close(dmix->hw_fd);
+       if (dmix->server_free)
+               dmix->server_free(dmix);
        snd_pcm_direct_shm_discard(dmix);
        snd_pcm_direct_semaphore_discard(dmix);
        server_printf("DIRECT SERVER EXIT\n");
index fd9e1c1..bb60b9f 100644 (file)
@@ -72,7 +72,9 @@ typedef struct {
        } u;
 } snd_pcm_direct_share_t;
 
-typedef struct {
+typedef struct snd_pcm_direct snd_pcm_direct_t;
+
+struct snd_pcm_direct {
        snd_pcm_type_t type;            /* type (dmix, dsnoop, dshare) */
        key_t ipc_key;                  /* IPC key for semaphore and memory */
        int semid;                      /* IPC global semaphore identification */
@@ -109,7 +111,8 @@ typedef struct {
                        unsigned long long chn_mask;
                } dshare;
        } u;
-} snd_pcm_direct_t;
+       void (*server_free)(snd_pcm_direct_t *direct);
+};
 
 int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix);
 int snd_pcm_direct_semaphore_discard(snd_pcm_direct_t *dmix);
index 3d381e2..0361c74 100644 (file)
@@ -96,6 +96,13 @@ static int shm_sum_discard(snd_pcm_direct_t *dmix)
        return ret;
 }
 
+static void dmix_server_free(snd_pcm_direct_t *dmix)
+{
+       /* remove the memory region */
+       shm_sum_create_or_connect(dmix);
+       shm_sum_discard(dmix);
+}
+
 /*
  *  the main function of this plugin: mixing
  *  FIXME: optimize it for different architectures
@@ -954,6 +961,8 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
                }
 
                dmix->spcm = spcm;
+
+               dmix->server_free = dmix_server_free;
                
                ret = snd_pcm_direct_server_create(dmix);
                if (ret < 0) {
@@ -992,7 +1001,7 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
 
        ret = shm_sum_create_or_connect(dmix);
        if (ret < 0) {
-               SNDERR("unabel to initialize sum ring buffer");
+               SNDERR("unable to initialize sum ring buffer");
                goto _err;
        }
 
@@ -1177,20 +1186,22 @@ int _snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
        params.buffer_time = -1;
        bsize = psize = -1;
        params.periods = 3;
+
        err = snd_pcm_slave_conf(root, slave, &sconf, 8,
                                 SND_PCM_HW_PARAM_FORMAT, 0, &params.format,
                                 SND_PCM_HW_PARAM_RATE, 0, &params.rate,
                                 SND_PCM_HW_PARAM_CHANNELS, 0, &params.channels,
                                 SND_PCM_HW_PARAM_PERIOD_TIME, 0, &params.period_time,
                                 SND_PCM_HW_PARAM_BUFFER_TIME, 0, &params.buffer_time,
-                                SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &bsize,
-                                SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &psize,
+                                SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &psize,
+                                SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &bsize,
                                 SND_PCM_HW_PARAM_PERIODS, 0, &params.periods);
        if (err < 0)
                return err;
 
        params.period_size = psize;
        params.buffer_size = bsize;
+
        err = snd_pcm_dmix_open(pcmp, name, ipc_key, &params, bindings, root, sconf, stream, mode);
        if (err < 0)
                snd_config_delete(sconf);
index 54752ce..ec018dc 100644 (file)
@@ -984,8 +984,8 @@ int _snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
                                 SND_PCM_HW_PARAM_CHANNELS, 0, &params.channels,
                                 SND_PCM_HW_PARAM_PERIOD_TIME, 0, &params.period_time,
                                 SND_PCM_HW_PARAM_BUFFER_TIME, 0, &params.buffer_time,
-                                SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &bsize,
-                                SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &psize,
+                                SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &psize,
+                                SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &bsize,
                                 SND_PCM_HW_PARAM_PERIODS, 0, &params.periods);
        if (err < 0)
                return err;
index cc4403f..6158cae 100644 (file)
@@ -936,8 +936,8 @@ int _snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
                                 SND_PCM_HW_PARAM_CHANNELS, 0, &params.channels,
                                 SND_PCM_HW_PARAM_PERIOD_TIME, 0, &params.period_time,
                                 SND_PCM_HW_PARAM_BUFFER_TIME, 0, &params.buffer_time,
-                                SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &bsize,
-                                SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &psize,
+                                SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &psize,
+                                SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &bsize,
                                 SND_PCM_HW_PARAM_PERIODS, 0, &params.periods);
        if (err < 0)
                return err;
index e086943..e64faaf 100644 (file)
@@ -95,7 +95,6 @@ typedef struct {
            avail_update_flag: 1,
            mmap_shm: 1;
        snd_pcm_uframes_t appl_ptr;
-       int shmid;
 } snd_pcm_hw_t;
 
 #define SNDRV_FILE_PCM_STREAM_PLAYBACK         "/dev/snd/pcmC%iD%ip"
@@ -395,7 +394,7 @@ static int snd_pcm_hw_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info
                info->u.mmap.offset = i.offset;
                return 0;
        }
-       return snd_pcm_channel_info_shm(pcm, info, hw->shmid);
+       return snd_pcm_channel_info_shm(pcm, info, -1);
 }
 
 static int snd_pcm_hw_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
@@ -733,35 +732,13 @@ static int snd_pcm_hw_munmap_control(snd_pcm_t *pcm)
        return 0;
 }
 
-static int snd_pcm_hw_mmap(snd_pcm_t *pcm)
+static int snd_pcm_hw_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
 {
-       snd_pcm_hw_t *hw = pcm->private_data;
-       int err;
-       if (hw->mmap_shm) {
-               snd_pcm_uframes_t size = snd_pcm_frames_to_bytes(pcm, (snd_pcm_sframes_t) pcm->buffer_size);
-               int id = shmget(IPC_PRIVATE, size, 0666);
-               hw->mmap_shm = 1;
-               if (id < 0) {
-                       err = -errno;
-                       SYSERR("shmget failed");
-                       return err;
-               }
-               hw->shmid = id;
-       }
        return 0;
 }
 
-static int snd_pcm_hw_munmap(snd_pcm_t *pcm)
+static int snd_pcm_hw_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
 {
-       snd_pcm_hw_t *hw = pcm->private_data;
-       int err;
-       if (hw->mmap_shm) {
-               if (shmctl(hw->shmid, IPC_RMID, 0) < 0) {
-                       err = -errno;
-                       SYSERR("shmctl IPC_RMID failed");
-                       return err;
-               }
-       }
        return 0;
 }
 
index 5873b1b..48ba437 100644 (file)
@@ -110,8 +110,8 @@ typedef struct _snd_pcm_channel_info {
        enum { SND_PCM_AREA_SHM, SND_PCM_AREA_MMAP } type;
        union {
                struct {
+                       struct snd_shm_area *area;
                        int shmid;
-                       int remove;
                } shm;
                struct {
                        int fd;
index 9232094..31ebec7 100644 (file)
@@ -261,8 +261,7 @@ int snd_pcm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info)
        return pcm->ops->channel_info(pcm, info);
 }
 
-int snd_pcm_channel_info_shm(snd_pcm_t *pcm, snd_pcm_channel_info_t *info,
-                            int shmid)
+int snd_pcm_channel_info_shm(snd_pcm_t *pcm, snd_pcm_channel_info_t *info, int shmid)
 {
        switch (pcm->access) {
        case SND_PCM_ACCESS_MMAP_INTERLEAVED:
@@ -282,7 +281,7 @@ int snd_pcm_channel_info_shm(snd_pcm_t *pcm, snd_pcm_channel_info_t *info,
        info->addr = 0;
        info->type = SND_PCM_AREA_SHM;
        info->u.shm.shmid = shmid;
-       info->u.shm.remove = 0;
+       info->u.shm.area = NULL;
        return 0;
 }      
 
@@ -362,7 +361,16 @@ int snd_pcm_mmap(snd_pcm_t *pcm)
                                                return -errno;
                                        }
                                        i->u.shm.shmid = id;
-                                       i->u.shm.remove = 1;
+                                       ptr = shmat(i->u.shm.shmid, 0, 0);
+                                       if (ptr == (void *) -1) {
+                                               SYSERR("shmat 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;
@@ -370,15 +378,16 @@ int snd_pcm_mmap(snd_pcm_t *pcm)
                                                        snd_pcm_channel_info_t *i1 = &pcm->mmap_channels[c1];
                                                        if (i1->u.shm.shmid < 0) {
                                                                i1->u.shm.shmid = id;
-                                                               i1->u.shm.remove = 1;
+                                                               i1->u.shm.area = snd_shm_area_share(i->u.shm.area);
                                                        }
                                                }
                                        }
-                               }
-                               ptr = shmat(i->u.shm.shmid, 0, 0);
-                               if (ptr == (void*) -1) {
-                                       SYSERR("shmat failed");
-                                       return -errno;
+                               } else {
+                                       ptr = shmat(i->u.shm.shmid, 0, 0);
+                                       if (ptr == (void*) -1) {
+                                               SYSERR("shmat failed");
+                                               return -errno;
+                                       }
                                }
                                i->addr = ptr;
                                break;
@@ -446,18 +455,15 @@ int snd_pcm_munmap(snd_pcm_t *pcm)
                        errno = 0;
                        break;
                case SND_PCM_AREA_SHM:
-                       err = shmdt(i->addr);
-                       if (err < 0) {
-                               SYSERR("shmdt failed");
-                               return -errno;
-                       }
-                       if (i->u.shm.remove) {
-                               if (shmctl(i->u.shm.shmid, IPC_RMID, 0) < 0) {
-                                       SYSERR("shmctl IPC_RMID failed");
+                       if (i->u.shm.area) {
+                               snd_shm_area_destroy(i->u.shm.area);
+                               i->u.shm.area = NULL;
+                       } else {
+                               err = shmdt(i->addr);
+                               if (err < 0) {
+                                       SYSERR("shmdt failed");
                                        return -errno;
                                }
-                               i->u.shm.shmid = -1;
-                               i->u.shm.remove = 0;
                        }
                        break;
                default: