mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-01 22:58:49 -04:00
Added route_policy option for the plug plugin.
Some fixes in the route and hooks plugin.
This commit is contained in:
parent
0d9a5d0e59
commit
b81a1dd79f
4 changed files with 83 additions and 30 deletions
|
|
@ -128,6 +128,11 @@ pcm.NAME {
|
||||||
[channels INT] # Slave channels (default nearest) or "unchanged"
|
[channels INT] # Slave channels (default nearest) or "unchanged"
|
||||||
[rate INT] # Slave rate (default nearest) or "unchanged"
|
[rate INT] # Slave rate (default nearest) or "unchanged"
|
||||||
}
|
}
|
||||||
|
route_policy STR # route policy for automatic ttable generation
|
||||||
|
# STR can be 'sum', 'copy', 'duplicate'
|
||||||
|
# sum: result is sum of input channels
|
||||||
|
# copy: only first channels are copied to destination
|
||||||
|
# duplicate: duplicate first set of channels
|
||||||
ttable { # Transfer table (bidimensional compound of
|
ttable { # Transfer table (bidimensional compound of
|
||||||
# cchannels * schannels numbers)
|
# cchannels * schannels numbers)
|
||||||
CCHANNEL {
|
CCHANNEL {
|
||||||
|
|
|
||||||
|
|
@ -319,7 +319,7 @@ int snd_pcm_hooks_open(snd_pcm_t **pcmp, const char *name, snd_pcm_t *slave, int
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_t *conf)
|
static int snd_pcm_hook_add_conf(snd_pcm_t *pcm, snd_config_t *root, snd_config_t *conf)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,13 @@
|
||||||
#include "pcm_local.h"
|
#include "pcm_local.h"
|
||||||
#include "pcm_plugin.h"
|
#include "pcm_plugin.h"
|
||||||
|
|
||||||
|
enum snd_pcm_plug_route_policy {
|
||||||
|
PLUG_ROUTE_POLICY_NONE,
|
||||||
|
PLUG_ROUTE_POLICY_COPY,
|
||||||
|
PLUG_ROUTE_POLICY_SUM,
|
||||||
|
PLUG_ROUTE_POLICY_DUP,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
snd_pcm_t *req_slave;
|
snd_pcm_t *req_slave;
|
||||||
int close_slave;
|
int close_slave;
|
||||||
|
|
@ -29,6 +36,7 @@ typedef struct {
|
||||||
snd_pcm_format_t sformat;
|
snd_pcm_format_t sformat;
|
||||||
int schannels;
|
int schannels;
|
||||||
int srate;
|
int srate;
|
||||||
|
enum snd_pcm_plug_route_policy route_policy;
|
||||||
snd_pcm_route_ttable_entry_t *ttable;
|
snd_pcm_route_ttable_entry_t *ttable;
|
||||||
unsigned int tt_ssize, tt_cused, tt_sused;
|
unsigned int tt_ssize, tt_cused, tt_sused;
|
||||||
} snd_pcm_plug_t;
|
} snd_pcm_plug_t;
|
||||||
|
|
@ -249,6 +257,9 @@ static int snd_pcm_plug_change_channels(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm
|
||||||
ttable = alloca(tt_cused * tt_sused * sizeof(*ttable));
|
ttable = alloca(tt_cused * tt_sused * sizeof(*ttable));
|
||||||
for (k = 0; k < tt_cused * tt_sused; ++k)
|
for (k = 0; k < tt_cused * tt_sused; ++k)
|
||||||
ttable[k] = 0;
|
ttable[k] = 0;
|
||||||
|
switch (plug->route_policy) {
|
||||||
|
case PLUG_ROUTE_POLICY_SUM:
|
||||||
|
case PLUG_ROUTE_POLICY_DUP:
|
||||||
if (clt->channels > slv->channels) {
|
if (clt->channels > slv->channels) {
|
||||||
n = clt->channels;
|
n = clt->channels;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -256,6 +267,7 @@ static int snd_pcm_plug_change_channels(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm
|
||||||
}
|
}
|
||||||
while (n-- > 0) {
|
while (n-- > 0) {
|
||||||
snd_pcm_route_ttable_entry_t v = FULL;
|
snd_pcm_route_ttable_entry_t v = FULL;
|
||||||
|
if (plug->route_policy == PLUG_ROUTE_POLICY_SUM) {
|
||||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK &&
|
if (pcm->stream == SND_PCM_STREAM_PLAYBACK &&
|
||||||
clt->channels > slv->channels) {
|
clt->channels > slv->channels) {
|
||||||
int srcs = clt->channels / slv->channels;
|
int srcs = clt->channels / slv->channels;
|
||||||
|
|
@ -269,12 +281,27 @@ static int snd_pcm_plug_change_channels(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm
|
||||||
srcs++;
|
srcs++;
|
||||||
v /= srcs;
|
v /= srcs;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ttable[c * tt_ssize + s] = v;
|
ttable[c * tt_ssize + s] = v;
|
||||||
if (++c == clt->channels)
|
if (++c == clt->channels)
|
||||||
c = 0;
|
c = 0;
|
||||||
if (++s == slv->channels)
|
if (++s == slv->channels)
|
||||||
s = 0;
|
s = 0;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case PLUG_ROUTE_POLICY_COPY:
|
||||||
|
if (clt->channels < slv->channels) {
|
||||||
|
n = clt->channels;
|
||||||
|
} else {
|
||||||
|
n = slv->channels;
|
||||||
|
}
|
||||||
|
for (c = 0; (int)c < n; c++)
|
||||||
|
ttable[c * tt_ssize + c] = FULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SNDERR("Invalid route policy");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
err = snd_pcm_route_open(new, NULL, slv->format, (int) slv->channels, ttable, tt_ssize, tt_cused, tt_sused, plug->slave, plug->slave != plug->req_slave);
|
err = snd_pcm_route_open(new, NULL, slv->format, (int) slv->channels, ttable, tt_ssize, tt_cused, tt_sused, plug->slave, plug->slave != plug->req_slave);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
@ -701,6 +728,7 @@ snd_pcm_ops_t snd_pcm_plug_ops = {
|
||||||
int snd_pcm_plug_open(snd_pcm_t **pcmp,
|
int snd_pcm_plug_open(snd_pcm_t **pcmp,
|
||||||
const char *name,
|
const char *name,
|
||||||
snd_pcm_format_t sformat, int schannels, int srate,
|
snd_pcm_format_t sformat, int schannels, int srate,
|
||||||
|
enum snd_pcm_plug_route_policy route_policy,
|
||||||
snd_pcm_route_ttable_entry_t *ttable,
|
snd_pcm_route_ttable_entry_t *ttable,
|
||||||
unsigned int tt_ssize,
|
unsigned int tt_ssize,
|
||||||
unsigned int tt_cused, unsigned int tt_sused,
|
unsigned int tt_cused, unsigned int tt_sused,
|
||||||
|
|
@ -718,6 +746,7 @@ int snd_pcm_plug_open(snd_pcm_t **pcmp,
|
||||||
plug->srate = srate;
|
plug->srate = srate;
|
||||||
plug->slave = plug->req_slave = slave;
|
plug->slave = plug->req_slave = slave;
|
||||||
plug->close_slave = close_slave;
|
plug->close_slave = close_slave;
|
||||||
|
plug->route_policy = route_policy;
|
||||||
plug->ttable = ttable;
|
plug->ttable = ttable;
|
||||||
plug->tt_ssize = tt_ssize;
|
plug->tt_ssize = tt_ssize;
|
||||||
plug->tt_cused = tt_cused;
|
plug->tt_cused = tt_cused;
|
||||||
|
|
@ -751,6 +780,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
|
||||||
snd_pcm_t *spcm;
|
snd_pcm_t *spcm;
|
||||||
snd_config_t *slave = NULL, *sconf;
|
snd_config_t *slave = NULL, *sconf;
|
||||||
snd_config_t *tt = NULL;
|
snd_config_t *tt = NULL;
|
||||||
|
enum snd_pcm_plug_route_policy route_policy = PLUG_ROUTE_POLICY_SUM;
|
||||||
snd_pcm_route_ttable_entry_t *ttable = NULL;
|
snd_pcm_route_ttable_entry_t *ttable = NULL;
|
||||||
unsigned int cused, sused;
|
unsigned int cused, sused;
|
||||||
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
|
snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
|
||||||
|
|
@ -765,6 +795,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strcmp(id, "ttable") == 0) {
|
if (strcmp(id, "ttable") == 0) {
|
||||||
|
route_policy = PLUG_ROUTE_POLICY_NONE;
|
||||||
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
|
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
|
||||||
SNDERR("Invalid type for %s", id);
|
SNDERR("Invalid type for %s", id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -772,6 +803,19 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
|
||||||
tt = n;
|
tt = n;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (strcmp(id, "route_policy") == 0) {
|
||||||
|
const char *str;
|
||||||
|
if ((err = snd_config_get_string(n, &str)) < 0) {
|
||||||
|
SNDERR("Invalid type for %s", id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (!strcmp(str, "sum"))
|
||||||
|
route_policy = PLUG_ROUTE_POLICY_SUM;
|
||||||
|
else if (!strcmp(str, "copy"))
|
||||||
|
route_policy = PLUG_ROUTE_POLICY_COPY;
|
||||||
|
else if (!strcmp(str, "duplicate"))
|
||||||
|
route_policy = PLUG_ROUTE_POLICY_DUP;
|
||||||
|
}
|
||||||
SNDERR("Unknown field %s", id);
|
SNDERR("Unknown field %s", id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
@ -800,7 +844,7 @@ int _snd_pcm_plug_open(snd_pcm_t **pcmp, const char *name,
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = snd_pcm_plug_open(pcmp, name, sformat, schannels, srate,
|
err = snd_pcm_plug_open(pcmp, name, sformat, schannels, srate,
|
||||||
ttable, MAX_CHANNELS, cused, sused, spcm, 1);
|
route_policy, ttable, MAX_CHANNELS, cused, sused, spcm, 1);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
snd_pcm_close(spcm);
|
snd_pcm_close(spcm);
|
||||||
return err;
|
return err;
|
||||||
|
|
|
||||||
|
|
@ -617,7 +617,11 @@ static void snd_pcm_route_dump(snd_pcm_t *pcm, snd_output_t *out)
|
||||||
while (1) {
|
while (1) {
|
||||||
snd_pcm_route_ttable_src_t *s = &d->srcs[src];
|
snd_pcm_route_ttable_src_t *s = &d->srcs[src];
|
||||||
if (d->att)
|
if (d->att)
|
||||||
|
#if ROUTE_PLUGIN_FLOAT
|
||||||
snd_output_printf(out, "%d*%g", s->channel, s->as_float);
|
snd_output_printf(out, "%d*%g", s->channel, s->as_float);
|
||||||
|
#else
|
||||||
|
snd_output_printf(out, "%d*%g", s->channel, (double)s->as_int / (double)ROUTE_PLUGIN_RESOLUTION);
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
snd_output_printf(out, "%d", s->channel);
|
snd_output_printf(out, "%d", s->channel);
|
||||||
src++;
|
src++;
|
||||||
|
|
@ -768,7 +772,7 @@ int snd_pcm_route_open(snd_pcm_t **pcmp, const char *name,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_route_load_ttable(snd_config_t *tt, snd_pcm_route_ttable_entry_t *ttable,
|
static int snd_pcm_route_load_ttable(snd_config_t *tt, snd_pcm_route_ttable_entry_t *ttable,
|
||||||
unsigned int tt_csize, unsigned int tt_ssize,
|
unsigned int tt_csize, unsigned int tt_ssize,
|
||||||
unsigned int *tt_cused, unsigned int *tt_sused,
|
unsigned int *tt_cused, unsigned int *tt_sused,
|
||||||
int schannels)
|
int schannels)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue