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.
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);
};
#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;
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;
snd_timer_ginfo_get_resolution_max;
snd_timer_ginfo_get_clients;
-} ALSA_1.0.5;
+} ALSA_1.0.8;
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
/** 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;
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;
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;
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;
}
if (i1->u.shm.shmid != i->u.shm.shmid)
continue;
break;
+ case SND_PCM_AREA_LOCAL:
+ break;
default:
assert(0);
}
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");
}
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);
}
if (i1->u.shm.shmid != i->u.shm.shmid)
continue;
break;
+ case SND_PCM_AREA_LOCAL:
+ break;
default:
assert(0);
}
}
}
break;
+ case SND_PCM_AREA_LOCAL:
+ free(i->addr);
+ i->addr = NULL;
+ break;
default:
assert(0);
}
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);