- added shm area manager code

- fixed parsing of period_size/buffer_size options for dmix, dsnoop and
  dshare plugins
This commit is contained in:
Jaroslav Kysela 2003-04-23 12:41:55 +00:00
parent 7340d20729
commit 573f85dc1d
11 changed files with 67 additions and 58 deletions

View 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 */

View 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 \

View 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,

View 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");

View 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);

View 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);

View 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;

View 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;

View 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;
}

View 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;

View 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: