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);
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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, ¶ms.format,
|
||||
SND_PCM_HW_PARAM_RATE, 0, ¶ms.rate,
|
||||
SND_PCM_HW_PARAM_CHANNELS, 0, ¶ms.channels,
|
||||
SND_PCM_HW_PARAM_PERIOD_TIME, 0, ¶ms.period_time,
|
||||
SND_PCM_HW_PARAM_BUFFER_TIME, 0, ¶ms.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, ¶ms.periods);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
params.period_size = psize;
|
||||
params.buffer_size = bsize;
|
||||
|
||||
err = snd_pcm_dmix_open(pcmp, name, ipc_key, ¶ms, bindings, root, sconf, stream, mode);
|
||||
if (err < 0)
|
||||
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_PERIOD_TIME, 0, ¶ms.period_time,
|
||||
SND_PCM_HW_PARAM_BUFFER_TIME, 0, ¶ms.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, ¶ms.periods);
|
||||
if (err < 0)
|
||||
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_PERIOD_TIME, 0, ¶ms.period_time,
|
||||
SND_PCM_HW_PARAM_BUFFER_TIME, 0, ¶ms.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, ¶ms.periods);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue