From 4d7c53d2800945f22f218dbe6b7a9ce5bdd12cca Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 19 May 2005 16:59:04 +0000 Subject: [PATCH] Add snd_pcm_hw_params_get/set_export_buffer() Add snd_pcm_hw_params_get/set_export_buffer() API functions. They control to ensure the buffer export to other processes. If this flag is set, the local buffer of a plugin is exported over IPC shm. Otherwise the buffer can be handled only locally (no shm). Also fixed Version file for 1.0.9. --- include/pcm.h | 2 ++ include/sound/asound.h | 1 + src/Versions | 4 +++- src/pcm/pcm.c | 30 ++++++++++++++++++++++++++++++ src/pcm/pcm_local.h | 13 +++++-------- src/pcm/pcm_mmap.c | 26 +++++++++++++++++++++++--- src/pcm/pcm_shm.c | 1 + 7 files changed, 65 insertions(+), 12 deletions(-) diff --git a/include/pcm.h b/include/pcm.h index fe0a4ca0..d814a43e 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -585,6 +585,8 @@ int snd_pcm_hw_params_set_rate_first(snd_pcm_t *pcm, snd_pcm_hw_params_t *params int snd_pcm_hw_params_set_rate_last(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir); int snd_pcm_hw_params_set_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val); int snd_pcm_hw_params_get_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val); +int snd_pcm_hw_params_set_export_buffer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val); +int snd_pcm_hw_params_get_export_buffer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val); int snd_pcm_hw_params_get_period_time(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir); int snd_pcm_hw_params_get_period_time_min(const snd_pcm_hw_params_t *params, unsigned int *val, int *dir); diff --git a/include/sound/asound.h b/include/sound/asound.h index 9f7cef87..443d4982 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h @@ -344,6 +344,7 @@ enum sndrv_pcm_hw_param { }; #define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */ +#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1) /* export buffer */ struct sndrv_interval { unsigned int min, max; diff --git a/src/Versions b/src/Versions index 793025f8..37aecaf9 100644 --- a/src/Versions +++ b/src/Versions @@ -179,6 +179,8 @@ ALSA_1.0.9 { snd_pcm_hw_params_set_rate_resample; snd_pcm_hw_params_get_rate_resample; + snd_pcm_hw_params_set_export_buffer; + snd_pcm_hw_params_get_export_buffer; snd_pcm_ioplug_create; snd_pcm_ioplug_delete; @@ -215,4 +217,4 @@ ALSA_1.0.9 { snd_timer_ginfo_get_resolution_max; snd_timer_ginfo_get_clients; -} ALSA_1.0.5; +} ALSA_1.0.8; diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 69e7a530..39c8f008 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -3959,6 +3959,36 @@ int snd_pcm_hw_params_get_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *par return 0; } +/** + * \brief Restrict a configuration space to allow the buffer accessible from outside + * \param pcm PCM handle + * \param params Configuration space + * \param val 0 = disable, 1 = enable (default) exporting buffer + * \return 0 otherwise a negative error code + */ +int snd_pcm_hw_params_set_export_buffer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val) +{ + assert(pcm && params); + if (val) + params->flags |= SND_PCM_HW_PARAMS_EXPORT_BUFFER; + else + params->flags &= ~SND_PCM_HW_PARAMS_EXPORT_BUFFER; + return snd_pcm_hw_refine(pcm, params); +} + +/** + * \brief Extract buffer accessibility from a configuration space + * \param pcm PCM handle + * \param *val 0 = disable, 1 = enable exporting buffer + * \return 0 otherwise a negative error code + */ +int snd_pcm_hw_params_get_export_buffer(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val) +{ + assert(pcm && params && val); + *val = params->flags & SND_PCM_HW_PARAMS_EXPORT_BUFFER ? 1 : 0; + return 0; +} + /** * \brief Extract period time from a configuration space * \param params Configuration space diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index d174ca92..15464a63 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -92,11 +92,8 @@ typedef enum sndrv_pcm_hw_param snd_pcm_hw_param_t; /** device can do a kind of synchronized start */ #define SND_PCM_INFO_SYNC_START SNDRV_PCM_INFO_SYNC_START -#ifndef SNDRV_PCM_HW_PARAMS_NORESAMPLE -#define SND_PCM_HW_PARAMS_NORESAMPLE (1<<0) -#else #define SND_PCM_HW_PARAMS_NORESAMPLE SNDRV_PCM_HW_PARAMS_NORESAMPLE -#endif +#define SND_PCM_HW_PARAMS_EXPORT_BUFFER SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER typedef struct _snd_pcm_rbptr { snd_pcm_t *master; @@ -114,7 +111,7 @@ typedef struct _snd_pcm_channel_info { void *addr; /* base address of channel samples */ unsigned int first; /* offset to first sample in bits */ unsigned int step; /* samples distance in bits */ - enum { SND_PCM_AREA_SHM, SND_PCM_AREA_MMAP } type; + enum { SND_PCM_AREA_SHM, SND_PCM_AREA_MMAP, SND_PCM_AREA_LOCAL } type; union { struct { struct snd_shm_area *area; @@ -214,9 +211,9 @@ struct _snd_pcm { snd_pcm_rbptr_t appl; snd_pcm_rbptr_t hw; snd_pcm_uframes_t min_align; - int mmap_rw: 1, - mmap_shadow: 1, - donot_close: 1; + unsigned int mmap_rw: 1; + unsigned int mmap_shadow: 1; + unsigned int donot_close: 1; snd_pcm_channel_info_t *mmap_channels; snd_pcm_channel_area_t *running_areas; snd_pcm_channel_area_t *stopped_areas; diff --git a/src/pcm/pcm_mmap.c b/src/pcm/pcm_mmap.c index e67ade73..adea7fb7 100644 --- a/src/pcm/pcm_mmap.c +++ b/src/pcm/pcm_mmap.c @@ -285,9 +285,12 @@ int snd_pcm_channel_info_shm(snd_pcm_t *pcm, snd_pcm_channel_info_t *info, int s return -EINVAL; } info->addr = 0; - info->type = SND_PCM_AREA_SHM; - info->u.shm.shmid = shmid; - info->u.shm.area = NULL; + if (pcm->hw_flags & SND_PCM_HW_PARAMS_EXPORT_BUFFER) { + info->type = SND_PCM_AREA_SHM; + info->u.shm.shmid = shmid; + info->u.shm.area = NULL; + } else + info->type = SND_PCM_AREA_LOCAL; return 0; } @@ -347,6 +350,8 @@ int snd_pcm_mmap(snd_pcm_t *pcm) if (i1->u.shm.shmid != i->u.shm.shmid) continue; break; + case SND_PCM_AREA_LOCAL: + break; default: assert(0); } @@ -368,6 +373,7 @@ int snd_pcm_mmap(snd_pcm_t *pcm) 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"); @@ -409,6 +415,14 @@ int snd_pcm_mmap(snd_pcm_t *pcm) } 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); } @@ -427,6 +441,8 @@ int snd_pcm_mmap(snd_pcm_t *pcm) if (i1->u.shm.shmid != i->u.shm.shmid) continue; break; + case SND_PCM_AREA_LOCAL: + break; default: assert(0); } @@ -494,6 +510,10 @@ int snd_pcm_munmap(snd_pcm_t *pcm) } } break; + case SND_PCM_AREA_LOCAL: + free(i->addr); + i->addr = NULL; + break; default: assert(0); } diff --git a/src/pcm/pcm_shm.c b/src/pcm/pcm_shm.c index 1c963aff..f2968a5a 100644 --- a/src/pcm/pcm_shm.c +++ b/src/pcm/pcm_shm.c @@ -288,6 +288,7 @@ static int snd_pcm_shm_hw_params_slave(snd_pcm_t *pcm, snd_pcm_shm_t *shm = pcm->private_data; volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl; int err; + params->flags |= SND_PCM_HW_PARAMS_EXPORT_BUFFER; ctrl->cmd = SNDRV_PCM_IOCTL_HW_PARAMS; ctrl->u.hw_params = *params; err = snd_pcm_shm_action(pcm); -- 2.47.1