mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
- added shm area manager code
- fixed parsing of period_size/buffer_size options for dmix, dsnoop and dshare plugins
This commit is contained in:
parent
7340d20729
commit
573f85dc1d
11 changed files with 67 additions and 58 deletions
|
|
@ -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);
|
int snd_async_handler_get_signo(snd_async_handler_t *handler);
|
||||||
void *snd_async_handler_get_callback_private(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 */
|
/** Timestamp */
|
||||||
typedef struct timeval snd_timestamp_t;
|
typedef struct timeval snd_timestamp_t;
|
||||||
/** Hi-res timestamp */
|
/** Hi-res timestamp */
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ VSYMS =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
lib_LTLIBRARIES = libasound.la
|
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 \
|
libasound_la_LIBADD = control/libcontrol.la mixer/libmixer.la pcm/libpcm.la \
|
||||||
rawmidi/librawmidi.la timer/libtimer.la \
|
rawmidi/librawmidi.la timer/libtimer.la \
|
||||||
hwdep/libhwdep.la seq/libseq.la instr/libinstr.la \
|
hwdep/libhwdep.la seq/libseq.la instr/libinstr.la \
|
||||||
|
|
|
||||||
|
|
@ -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_CHANNELS] = "channels",
|
||||||
[SND_PCM_HW_PARAM_RATE] = "rate",
|
[SND_PCM_HW_PARAM_RATE] = "rate",
|
||||||
[SND_PCM_HW_PARAM_PERIOD_TIME] = "period_time",
|
[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,
|
int snd_pcm_slave_conf(snd_config_t *root, snd_config_t *conf,
|
||||||
|
|
|
||||||
|
|
@ -278,6 +278,8 @@ static void server_job(snd_pcm_direct_t *dmix)
|
||||||
}
|
}
|
||||||
close(dmix->server_fd);
|
close(dmix->server_fd);
|
||||||
close(dmix->hw_fd);
|
close(dmix->hw_fd);
|
||||||
|
if (dmix->server_free)
|
||||||
|
dmix->server_free(dmix);
|
||||||
snd_pcm_direct_shm_discard(dmix);
|
snd_pcm_direct_shm_discard(dmix);
|
||||||
snd_pcm_direct_semaphore_discard(dmix);
|
snd_pcm_direct_semaphore_discard(dmix);
|
||||||
server_printf("DIRECT SERVER EXIT\n");
|
server_printf("DIRECT SERVER EXIT\n");
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,9 @@ typedef struct {
|
||||||
} u;
|
} u;
|
||||||
} snd_pcm_direct_share_t;
|
} 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) */
|
snd_pcm_type_t type; /* type (dmix, dsnoop, dshare) */
|
||||||
key_t ipc_key; /* IPC key for semaphore and memory */
|
key_t ipc_key; /* IPC key for semaphore and memory */
|
||||||
int semid; /* IPC global semaphore identification */
|
int semid; /* IPC global semaphore identification */
|
||||||
|
|
@ -109,7 +111,8 @@ typedef struct {
|
||||||
unsigned long long chn_mask;
|
unsigned long long chn_mask;
|
||||||
} dshare;
|
} dshare;
|
||||||
} u;
|
} 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_create_or_connect(snd_pcm_direct_t *dmix);
|
||||||
int snd_pcm_direct_semaphore_discard(snd_pcm_direct_t *dmix);
|
int snd_pcm_direct_semaphore_discard(snd_pcm_direct_t *dmix);
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,13 @@ static int shm_sum_discard(snd_pcm_direct_t *dmix)
|
||||||
return ret;
|
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
|
* the main function of this plugin: mixing
|
||||||
* FIXME: optimize it for different architectures
|
* 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->spcm = spcm;
|
||||||
|
|
||||||
|
dmix->server_free = dmix_server_free;
|
||||||
|
|
||||||
ret = snd_pcm_direct_server_create(dmix);
|
ret = snd_pcm_direct_server_create(dmix);
|
||||||
if (ret < 0) {
|
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);
|
ret = shm_sum_create_or_connect(dmix);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
SNDERR("unabel to initialize sum ring buffer");
|
SNDERR("unable to initialize sum ring buffer");
|
||||||
goto _err;
|
goto _err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1177,20 +1186,22 @@ int _snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
|
||||||
params.buffer_time = -1;
|
params.buffer_time = -1;
|
||||||
bsize = psize = -1;
|
bsize = psize = -1;
|
||||||
params.periods = 3;
|
params.periods = 3;
|
||||||
|
|
||||||
err = snd_pcm_slave_conf(root, slave, &sconf, 8,
|
err = snd_pcm_slave_conf(root, slave, &sconf, 8,
|
||||||
SND_PCM_HW_PARAM_FORMAT, 0, ¶ms.format,
|
SND_PCM_HW_PARAM_FORMAT, 0, ¶ms.format,
|
||||||
SND_PCM_HW_PARAM_RATE, 0, ¶ms.rate,
|
SND_PCM_HW_PARAM_RATE, 0, ¶ms.rate,
|
||||||
SND_PCM_HW_PARAM_CHANNELS, 0, ¶ms.channels,
|
SND_PCM_HW_PARAM_CHANNELS, 0, ¶ms.channels,
|
||||||
SND_PCM_HW_PARAM_PERIOD_TIME, 0, ¶ms.period_time,
|
SND_PCM_HW_PARAM_PERIOD_TIME, 0, ¶ms.period_time,
|
||||||
SND_PCM_HW_PARAM_BUFFER_TIME, 0, ¶ms.buffer_time,
|
SND_PCM_HW_PARAM_BUFFER_TIME, 0, ¶ms.buffer_time,
|
||||||
SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &bsize,
|
SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &psize,
|
||||||
SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &psize,
|
SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &bsize,
|
||||||
SND_PCM_HW_PARAM_PERIODS, 0, ¶ms.periods);
|
SND_PCM_HW_PARAM_PERIODS, 0, ¶ms.periods);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
params.period_size = psize;
|
params.period_size = psize;
|
||||||
params.buffer_size = bsize;
|
params.buffer_size = bsize;
|
||||||
|
|
||||||
err = snd_pcm_dmix_open(pcmp, name, ipc_key, ¶ms, bindings, root, sconf, stream, mode);
|
err = snd_pcm_dmix_open(pcmp, name, ipc_key, ¶ms, bindings, root, sconf, stream, mode);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
snd_config_delete(sconf);
|
snd_config_delete(sconf);
|
||||||
|
|
|
||||||
|
|
@ -984,8 +984,8 @@ int _snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
|
||||||
SND_PCM_HW_PARAM_CHANNELS, 0, ¶ms.channels,
|
SND_PCM_HW_PARAM_CHANNELS, 0, ¶ms.channels,
|
||||||
SND_PCM_HW_PARAM_PERIOD_TIME, 0, ¶ms.period_time,
|
SND_PCM_HW_PARAM_PERIOD_TIME, 0, ¶ms.period_time,
|
||||||
SND_PCM_HW_PARAM_BUFFER_TIME, 0, ¶ms.buffer_time,
|
SND_PCM_HW_PARAM_BUFFER_TIME, 0, ¶ms.buffer_time,
|
||||||
SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &bsize,
|
SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &psize,
|
||||||
SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &psize,
|
SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &bsize,
|
||||||
SND_PCM_HW_PARAM_PERIODS, 0, ¶ms.periods);
|
SND_PCM_HW_PARAM_PERIODS, 0, ¶ms.periods);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
|
||||||
|
|
@ -936,8 +936,8 @@ int _snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
|
||||||
SND_PCM_HW_PARAM_CHANNELS, 0, ¶ms.channels,
|
SND_PCM_HW_PARAM_CHANNELS, 0, ¶ms.channels,
|
||||||
SND_PCM_HW_PARAM_PERIOD_TIME, 0, ¶ms.period_time,
|
SND_PCM_HW_PARAM_PERIOD_TIME, 0, ¶ms.period_time,
|
||||||
SND_PCM_HW_PARAM_BUFFER_TIME, 0, ¶ms.buffer_time,
|
SND_PCM_HW_PARAM_BUFFER_TIME, 0, ¶ms.buffer_time,
|
||||||
SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &bsize,
|
SND_PCM_HW_PARAM_PERIOD_SIZE, 0, &psize,
|
||||||
SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &psize,
|
SND_PCM_HW_PARAM_BUFFER_SIZE, 0, &bsize,
|
||||||
SND_PCM_HW_PARAM_PERIODS, 0, ¶ms.periods);
|
SND_PCM_HW_PARAM_PERIODS, 0, ¶ms.periods);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,6 @@ typedef struct {
|
||||||
avail_update_flag: 1,
|
avail_update_flag: 1,
|
||||||
mmap_shm: 1;
|
mmap_shm: 1;
|
||||||
snd_pcm_uframes_t appl_ptr;
|
snd_pcm_uframes_t appl_ptr;
|
||||||
int shmid;
|
|
||||||
} snd_pcm_hw_t;
|
} snd_pcm_hw_t;
|
||||||
|
|
||||||
#define SNDRV_FILE_PCM_STREAM_PLAYBACK "/dev/snd/pcmC%iD%ip"
|
#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;
|
info->u.mmap.offset = i.offset;
|
||||||
return 0;
|
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)
|
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;
|
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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,8 +110,8 @@ typedef struct _snd_pcm_channel_info {
|
||||||
enum { SND_PCM_AREA_SHM, SND_PCM_AREA_MMAP } type;
|
enum { SND_PCM_AREA_SHM, SND_PCM_AREA_MMAP } type;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
|
struct snd_shm_area *area;
|
||||||
int shmid;
|
int shmid;
|
||||||
int remove;
|
|
||||||
} shm;
|
} shm;
|
||||||
struct {
|
struct {
|
||||||
int fd;
|
int fd;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
return pcm->ops->channel_info(pcm, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_channel_info_shm(snd_pcm_t *pcm, snd_pcm_channel_info_t *info,
|
int snd_pcm_channel_info_shm(snd_pcm_t *pcm, snd_pcm_channel_info_t *info, int shmid)
|
||||||
int shmid)
|
|
||||||
{
|
{
|
||||||
switch (pcm->access) {
|
switch (pcm->access) {
|
||||||
case SND_PCM_ACCESS_MMAP_INTERLEAVED:
|
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->addr = 0;
|
||||||
info->type = SND_PCM_AREA_SHM;
|
info->type = SND_PCM_AREA_SHM;
|
||||||
info->u.shm.shmid = shmid;
|
info->u.shm.shmid = shmid;
|
||||||
info->u.shm.remove = 0;
|
info->u.shm.area = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -362,7 +361,16 @@ int snd_pcm_mmap(snd_pcm_t *pcm)
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
i->u.shm.shmid = id;
|
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 ||
|
if (pcm->access == SND_PCM_ACCESS_MMAP_INTERLEAVED ||
|
||||||
pcm->access == SND_PCM_ACCESS_RW_INTERLEAVED) {
|
pcm->access == SND_PCM_ACCESS_RW_INTERLEAVED) {
|
||||||
unsigned int c1;
|
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];
|
snd_pcm_channel_info_t *i1 = &pcm->mmap_channels[c1];
|
||||||
if (i1->u.shm.shmid < 0) {
|
if (i1->u.shm.shmid < 0) {
|
||||||
i1->u.shm.shmid = id;
|
i1->u.shm.shmid = id;
|
||||||
i1->u.shm.remove = 1;
|
i1->u.shm.area = snd_shm_area_share(i->u.shm.area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
ptr = shmat(i->u.shm.shmid, 0, 0);
|
ptr = shmat(i->u.shm.shmid, 0, 0);
|
||||||
if (ptr == (void*) -1) {
|
if (ptr == (void*) -1) {
|
||||||
SYSERR("shmat failed");
|
SYSERR("shmat failed");
|
||||||
return -errno;
|
return -errno;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i->addr = ptr;
|
i->addr = ptr;
|
||||||
break;
|
break;
|
||||||
|
|
@ -446,18 +455,15 @@ int snd_pcm_munmap(snd_pcm_t *pcm)
|
||||||
errno = 0;
|
errno = 0;
|
||||||
break;
|
break;
|
||||||
case SND_PCM_AREA_SHM:
|
case SND_PCM_AREA_SHM:
|
||||||
err = shmdt(i->addr);
|
if (i->u.shm.area) {
|
||||||
if (err < 0) {
|
snd_shm_area_destroy(i->u.shm.area);
|
||||||
SYSERR("shmdt failed");
|
i->u.shm.area = NULL;
|
||||||
return -errno;
|
} else {
|
||||||
}
|
err = shmdt(i->addr);
|
||||||
if (i->u.shm.remove) {
|
if (err < 0) {
|
||||||
if (shmctl(i->u.shm.shmid, IPC_RMID, 0) < 0) {
|
SYSERR("shmdt failed");
|
||||||
SYSERR("shmctl IPC_RMID failed");
|
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
i->u.shm.shmid = -1;
|
|
||||||
i->u.shm.remove = 0;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue