mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-12-16 08:56:42 -05:00
Use O_APPEND mode with dmix & co plugins
Use O_APPEND mode (only if available) with dmix, dsnoop and dshare plugins. Using this mode, the plugin requires no resource server any more.
This commit is contained in:
parent
194ff97ea6
commit
eafb7ae5d8
7 changed files with 190 additions and 52 deletions
|
|
@ -82,6 +82,8 @@ int snd_pcm_direct_semaphore_create_or_connect(snd_pcm_direct_t *dmix)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SND_PCM_DIRECT_MAGIC 0xa15ad319
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* global shared memory area
|
* global shared memory area
|
||||||
*/
|
*/
|
||||||
|
|
@ -121,7 +123,13 @@ retryget:
|
||||||
buf.shm_perm.gid = dmix->ipc_gid;
|
buf.shm_perm.gid = dmix->ipc_gid;
|
||||||
shmctl(dmix->shmid, IPC_SET, &buf);
|
shmctl(dmix->shmid, IPC_SET, &buf);
|
||||||
}
|
}
|
||||||
|
dmix->shmptr->magic = SND_PCM_DIRECT_MAGIC;
|
||||||
return 1;
|
return 1;
|
||||||
|
} else {
|
||||||
|
if (dmix->shmptr->magic != SND_PCM_DIRECT_MAGIC) {
|
||||||
|
snd_pcm_direct_shm_discard(dmix);
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1028,6 +1036,14 @@ int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, str
|
||||||
dmix->slave_boundary = spcm->boundary;
|
dmix->slave_boundary = spcm->boundary;
|
||||||
|
|
||||||
spcm->donot_close = 1;
|
spcm->donot_close = 1;
|
||||||
|
|
||||||
|
{
|
||||||
|
int ver = 0;
|
||||||
|
ioctl(spcm->poll_fd, SNDRV_PCM_IOCTL_PVERSION, &ver);
|
||||||
|
if (ver < SNDRV_PROTOCOL_VERSION(2, 0, 8))
|
||||||
|
dmix->shmptr->use_server = 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1148,6 +1164,36 @@ int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dm
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open a slave PCM as secondary client (dup'ed fd)
|
||||||
|
*/
|
||||||
|
int snd_pcm_direct_initialize_secondary_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
spcm->donot_close = 1;
|
||||||
|
spcm->setup = 1;
|
||||||
|
/* we copy the slave setting */
|
||||||
|
spcm->buffer_size = dmix->shmptr->s.buffer_size;
|
||||||
|
spcm->sample_bits = dmix->shmptr->s.sample_bits;
|
||||||
|
spcm->channels = dmix->shmptr->s.channels;
|
||||||
|
spcm->format = dmix->shmptr->s.format;
|
||||||
|
spcm->boundary = recalc_boundary_size(dmix->shmptr->s.boundary, spcm->buffer_size);
|
||||||
|
spcm->info = dmix->shmptr->s.info;
|
||||||
|
|
||||||
|
/* Use the slave setting as SPCM, so far */
|
||||||
|
dmix->slave_buffer_size = spcm->buffer_size;
|
||||||
|
dmix->slave_period_size = dmix->shmptr->s.period_size;
|
||||||
|
dmix->slave_boundary = spcm->boundary;
|
||||||
|
|
||||||
|
ret = snd_pcm_mmap(spcm);
|
||||||
|
if (ret < 0) {
|
||||||
|
SNDERR("unable to mmap channels");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix)
|
int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix)
|
||||||
{
|
{
|
||||||
snd_timer_params_t *params;
|
snd_timer_params_t *params;
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,10 @@ struct slave_params {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
unsigned int magic; /* magic number */
|
||||||
char socket_name[256]; /* name of communication socket */
|
char socket_name[256]; /* name of communication socket */
|
||||||
snd_pcm_type_t type; /* PCM type (currently only hw) */
|
snd_pcm_type_t type; /* PCM type (currently only hw) */
|
||||||
|
int use_server;
|
||||||
struct {
|
struct {
|
||||||
unsigned int format;
|
unsigned int format;
|
||||||
snd_interval_t rate;
|
snd_interval_t rate;
|
||||||
|
|
@ -168,6 +170,7 @@ int snd_pcm_direct_server_discard(snd_pcm_direct_t *dmix);
|
||||||
int snd_pcm_direct_client_connect(snd_pcm_direct_t *dmix);
|
int snd_pcm_direct_client_connect(snd_pcm_direct_t *dmix);
|
||||||
int snd_pcm_direct_client_discard(snd_pcm_direct_t *dmix);
|
int snd_pcm_direct_client_discard(snd_pcm_direct_t *dmix);
|
||||||
int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params);
|
int snd_pcm_direct_initialize_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params);
|
||||||
|
int snd_pcm_direct_initialize_secondary_slave(snd_pcm_direct_t *dmix, snd_pcm_t *spcm, struct slave_params *params);
|
||||||
int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix);
|
int snd_pcm_direct_initialize_poll_fd(snd_pcm_direct_t *dmix);
|
||||||
int snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm);
|
int snd_pcm_direct_check_interleave(snd_pcm_direct_t *dmix, snd_pcm_t *pcm);
|
||||||
int snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix,
|
int snd_pcm_direct_parse_bindings(snd_pcm_direct_t *dmix,
|
||||||
|
|
|
||||||
|
|
@ -650,8 +650,10 @@ static int snd_pcm_dmix_close(snd_pcm_t *pcm)
|
||||||
if (dmix->client)
|
if (dmix->client)
|
||||||
snd_pcm_direct_client_discard(dmix);
|
snd_pcm_direct_client_discard(dmix);
|
||||||
shm_sum_discard(dmix);
|
shm_sum_discard(dmix);
|
||||||
snd_pcm_direct_shm_discard(dmix);
|
if (snd_pcm_direct_shm_discard(dmix))
|
||||||
snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
|
snd_pcm_direct_semaphore_discard(dmix);
|
||||||
|
else
|
||||||
|
snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
|
||||||
free(dmix->bindings);
|
free(dmix->bindings);
|
||||||
pcm->private_data = NULL;
|
pcm->private_data = NULL;
|
||||||
free(dmix);
|
free(dmix);
|
||||||
|
|
@ -877,28 +879,54 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name,
|
||||||
|
|
||||||
dmix->spcm = spcm;
|
dmix->spcm = spcm;
|
||||||
|
|
||||||
dmix->server_free = dmix_server_free;
|
if (dmix->shmptr->use_server) {
|
||||||
|
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) {
|
||||||
SNDERR("unable to create server");
|
SNDERR("unable to create server");
|
||||||
goto _err;
|
goto _err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dmix->shmptr->type = spcm->type;
|
dmix->shmptr->type = spcm->type;
|
||||||
} else {
|
} else {
|
||||||
/* up semaphore to avoid deadlock */
|
if (dmix->shmptr->use_server) {
|
||||||
snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
|
/* up semaphore to avoid deadlock */
|
||||||
ret = snd_pcm_direct_client_connect(dmix);
|
snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
|
||||||
if (ret < 0) {
|
ret = snd_pcm_direct_client_connect(dmix);
|
||||||
SNDERR("unable to connect client");
|
if (ret < 0) {
|
||||||
goto _err_nosem;
|
SNDERR("unable to connect client");
|
||||||
}
|
goto _err_nosem;
|
||||||
|
}
|
||||||
|
|
||||||
snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
|
snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
|
||||||
ret = snd_pcm_direct_open_secondary_client(&spcm, dmix, "dmix_client");
|
ret = snd_pcm_direct_open_secondary_client(&spcm, dmix, "dmix_client");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto _err;
|
goto _err;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ret = snd_pcm_open_slave(&spcm, root, sconf, stream,
|
||||||
|
mode | SND_PCM_NONBLOCK |
|
||||||
|
SND_PCM_APPEND,
|
||||||
|
NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
SNDERR("unable to open slave");
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
if (snd_pcm_type(spcm) != SND_PCM_TYPE_HW) {
|
||||||
|
SNDERR("dmix plugin can be only connected to hw plugin");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = snd_pcm_direct_initialize_secondary_slave(dmix, spcm, params);
|
||||||
|
if (ret < 0) {
|
||||||
|
SNDERR("unable to initialize slave");
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dmix->spcm = spcm;
|
dmix->spcm = spcm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -464,8 +464,10 @@ static int snd_pcm_dshare_close(snd_pcm_t *pcm)
|
||||||
snd_pcm_direct_server_discard(dshare);
|
snd_pcm_direct_server_discard(dshare);
|
||||||
if (dshare->client)
|
if (dshare->client)
|
||||||
snd_pcm_direct_client_discard(dshare);
|
snd_pcm_direct_client_discard(dshare);
|
||||||
snd_pcm_direct_shm_discard(dshare);
|
if (snd_pcm_direct_shm_discard(dshare))
|
||||||
snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
|
snd_pcm_direct_semaphore_discard(dshare);
|
||||||
|
else
|
||||||
|
snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
|
||||||
free(dshare->bindings);
|
free(dshare->bindings);
|
||||||
pcm->private_data = NULL;
|
pcm->private_data = NULL;
|
||||||
free(dshare);
|
free(dshare);
|
||||||
|
|
@ -688,26 +690,53 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name,
|
||||||
|
|
||||||
dshare->spcm = spcm;
|
dshare->spcm = spcm;
|
||||||
|
|
||||||
ret = snd_pcm_direct_server_create(dshare);
|
if (dshare->shmptr->use_server) {
|
||||||
if (ret < 0) {
|
ret = snd_pcm_direct_server_create(dshare);
|
||||||
SNDERR("unable to create server");
|
if (ret < 0) {
|
||||||
goto _err;
|
SNDERR("unable to create server");
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dshare->shmptr->type = spcm->type;
|
dshare->shmptr->type = spcm->type;
|
||||||
} else {
|
} else {
|
||||||
/* up semaphore to avoid deadlock */
|
if (dshare->shmptr->use_server) {
|
||||||
snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
|
/* up semaphore to avoid deadlock */
|
||||||
ret = snd_pcm_direct_client_connect(dshare);
|
snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
|
||||||
if (ret < 0) {
|
ret = snd_pcm_direct_client_connect(dshare);
|
||||||
SNDERR("unable to connect client");
|
if (ret < 0) {
|
||||||
goto _err_nosem;
|
SNDERR("unable to connect client");
|
||||||
}
|
goto _err_nosem;
|
||||||
|
}
|
||||||
|
|
||||||
snd_pcm_direct_semaphore_down(dshare, DIRECT_IPC_SEM_CLIENT);
|
snd_pcm_direct_semaphore_down(dshare, DIRECT_IPC_SEM_CLIENT);
|
||||||
ret = snd_pcm_direct_open_secondary_client(&spcm, dshare, "dshare_client");
|
ret = snd_pcm_direct_open_secondary_client(&spcm, dshare, "dshare_client");
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto _err;
|
goto _err;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ret = snd_pcm_open_slave(&spcm, root, sconf, stream,
|
||||||
|
mode | SND_PCM_NONBLOCK |
|
||||||
|
SND_PCM_APPEND,
|
||||||
|
NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
SNDERR("unable to open slave");
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
if (snd_pcm_type(spcm) != SND_PCM_TYPE_HW) {
|
||||||
|
SNDERR("dshare plugin can be only connected to hw plugin");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = snd_pcm_direct_initialize_secondary_slave(dshare, spcm, params);
|
||||||
|
if (ret < 0) {
|
||||||
|
SNDERR("unable to initialize slave");
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dshare->spcm = spcm;
|
dshare->spcm = spcm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -360,8 +360,10 @@ static int snd_pcm_dsnoop_close(snd_pcm_t *pcm)
|
||||||
snd_pcm_direct_server_discard(dsnoop);
|
snd_pcm_direct_server_discard(dsnoop);
|
||||||
if (dsnoop->client)
|
if (dsnoop->client)
|
||||||
snd_pcm_direct_client_discard(dsnoop);
|
snd_pcm_direct_client_discard(dsnoop);
|
||||||
snd_pcm_direct_shm_discard(dsnoop);
|
if (snd_pcm_direct_shm_discard(dsnoop))
|
||||||
snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
|
snd_pcm_direct_semaphore_discard(dsnoop);
|
||||||
|
else
|
||||||
|
snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
|
||||||
free(dsnoop->bindings);
|
free(dsnoop->bindings);
|
||||||
pcm->private_data = NULL;
|
pcm->private_data = NULL;
|
||||||
free(dsnoop);
|
free(dsnoop);
|
||||||
|
|
@ -570,27 +572,53 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name,
|
||||||
|
|
||||||
dsnoop->spcm = spcm;
|
dsnoop->spcm = spcm;
|
||||||
|
|
||||||
ret = snd_pcm_direct_server_create(dsnoop);
|
if (dsnoop->shmptr->use_server) {
|
||||||
if (ret < 0) {
|
ret = snd_pcm_direct_server_create(dsnoop);
|
||||||
SNDERR("unable to create server");
|
if (ret < 0) {
|
||||||
goto _err;
|
SNDERR("unable to create server");
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dsnoop->shmptr->type = spcm->type;
|
dsnoop->shmptr->type = spcm->type;
|
||||||
} else {
|
} else {
|
||||||
/* up semaphore to avoid deadlock */
|
if (dsnoop->shmptr->use_server) {
|
||||||
snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
|
/* up semaphore to avoid deadlock */
|
||||||
ret = snd_pcm_direct_client_connect(dsnoop);
|
snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
|
||||||
if (ret < 0) {
|
ret = snd_pcm_direct_client_connect(dsnoop);
|
||||||
SNDERR("unable to connect client");
|
if (ret < 0) {
|
||||||
goto _err_nosem;
|
SNDERR("unable to connect client");
|
||||||
}
|
goto _err_nosem;
|
||||||
|
}
|
||||||
|
|
||||||
snd_pcm_direct_semaphore_down(dsnoop, DIRECT_IPC_SEM_CLIENT);
|
snd_pcm_direct_semaphore_down(dsnoop, DIRECT_IPC_SEM_CLIENT);
|
||||||
|
|
||||||
|
ret = snd_pcm_direct_open_secondary_client(&spcm, dsnoop, "dsnoop_client");
|
||||||
|
if (ret < 0)
|
||||||
|
goto _err;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ret = snd_pcm_open_slave(&spcm, root, sconf, stream,
|
||||||
|
mode | SND_PCM_NONBLOCK |
|
||||||
|
SND_PCM_APPEND,
|
||||||
|
NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
SNDERR("unable to open slave");
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
if (snd_pcm_type(spcm) != SND_PCM_TYPE_HW) {
|
||||||
|
SNDERR("dsnoop plugin can be only connected to hw plugin");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = snd_pcm_direct_initialize_secondary_slave(dsnoop, spcm, params);
|
||||||
|
if (ret < 0) {
|
||||||
|
SNDERR("unable to initialize slave");
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = snd_pcm_direct_open_secondary_client(&spcm, dsnoop, "dsnoop_client");
|
|
||||||
if (ret < 0)
|
|
||||||
goto _err;
|
|
||||||
dsnoop->spcm = spcm;
|
dsnoop->spcm = spcm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1240,6 +1240,8 @@ int snd_pcm_hw_open(snd_pcm_t **pcmp, const char *name,
|
||||||
fmode |= O_NONBLOCK;
|
fmode |= O_NONBLOCK;
|
||||||
if (mode & SND_PCM_ASYNC)
|
if (mode & SND_PCM_ASYNC)
|
||||||
fmode |= O_ASYNC;
|
fmode |= O_ASYNC;
|
||||||
|
if (mode & SND_PCM_APPEND)
|
||||||
|
fmode |= O_APPEND;
|
||||||
fd = snd_open_device(filename, fmode);
|
fd = snd_open_device(filename, fmode);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
|
|
|
||||||
|
|
@ -746,6 +746,8 @@ int snd_pcm_hw_strategy_simple_choices(snd_pcm_hw_strategy_t *strategy, int orde
|
||||||
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,
|
||||||
snd_config_t **pcm_conf, unsigned int count, ...);
|
snd_config_t **pcm_conf, unsigned int count, ...);
|
||||||
|
|
||||||
|
#define SND_PCM_APPEND (1<<8)
|
||||||
|
|
||||||
int snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root,
|
int snd_pcm_open_slave(snd_pcm_t **pcmp, snd_config_t *root,
|
||||||
snd_config_t *conf, snd_pcm_stream_t stream,
|
snd_config_t *conf, snd_pcm_stream_t stream,
|
||||||
int mode, snd_config_t *parent_conf);
|
int mode, snd_config_t *parent_conf);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue