mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2026-03-12 05:33:44 -04:00
PCM: Add string conversion helper functions for chmap
Added a few helper functions between chmap and string. snd_pcm_chmap_type_name() -- a string of the given chmap type snd_pcm_chmap_name() -- a string of the given channel position snd_pcm_chmap_print() -- print channel map on the given buffer snd_pcm_chmap_from_string() -- get a channel position from string snd_pcm_parse_string() -- parse the whole channel map from string Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
6950a1030c
commit
b4c64e815a
3 changed files with 160 additions and 57 deletions
|
|
@ -534,6 +534,12 @@ void snd_pcm_free_chmaps(snd_pcm_chmap_query_t **maps);
|
||||||
snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm);
|
snd_pcm_chmap_t *snd_pcm_get_chmap(snd_pcm_t *pcm);
|
||||||
int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
|
int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map);
|
||||||
|
|
||||||
|
const char *snd_pcm_chmap_type_name(enum snd_pcm_chmap_type val);
|
||||||
|
const char *snd_pcm_chmap_name(enum snd_pcm_chmap_position val);
|
||||||
|
int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf);
|
||||||
|
unsigned int snd_pcm_chmap_from_string(const char *str);
|
||||||
|
snd_pcm_chmap_t *snd_pcm_chmap_parse_string(const char *str);
|
||||||
|
|
||||||
//int snd_pcm_mixer_element(snd_pcm_t *pcm, snd_mixer_t *mixer, snd_mixer_elem_t **elem);
|
//int snd_pcm_mixer_element(snd_pcm_t *pcm, snd_mixer_t *mixer, snd_mixer_elem_t **elem);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
142
src/pcm/pcm.c
142
src/pcm/pcm.c
|
|
@ -633,6 +633,7 @@ playback devices.
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
@ -7356,6 +7357,147 @@ int snd_pcm_set_chmap(snd_pcm_t *pcm, const snd_pcm_chmap_t *map)
|
||||||
return pcm->ops->set_chmap(pcm, map);
|
return pcm->ops->set_chmap(pcm, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
#define _NAME(n) [SND_CHMAP_TYPE_##n] = #n
|
||||||
|
static const char *chmap_type_names[SND_CHMAP_TYPE_LAST + 1] = {
|
||||||
|
_NAME(NONE), _NAME(FIXED), _NAME(VAR), _NAME(PAIRED),
|
||||||
|
};
|
||||||
|
#undef _NAME
|
||||||
|
|
||||||
|
const char *snd_pcm_chmap_type_name(enum snd_pcm_chmap_type val)
|
||||||
|
{
|
||||||
|
if (val <= SND_CHMAP_TYPE_LAST)
|
||||||
|
return chmap_type_names[val];
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _NAME(n) [SND_CHMAP_##n] = #n
|
||||||
|
static const char *chmap_names[SND_CHMAP_LAST + 1] = {
|
||||||
|
_NAME(UNKNOWN),
|
||||||
|
_NAME(FL), _NAME(FR),
|
||||||
|
_NAME(RL), _NAME(RR),
|
||||||
|
_NAME(FC), _NAME(LFE),
|
||||||
|
_NAME(SL), _NAME(SR),
|
||||||
|
_NAME(RC), _NAME(FLC), _NAME(FRC), _NAME(RLC), _NAME(RRC),
|
||||||
|
_NAME(FLW), _NAME(FRW),
|
||||||
|
_NAME(FLH), _NAME(FCH), _NAME(FRH), _NAME(TC),
|
||||||
|
_NAME(NA),
|
||||||
|
};
|
||||||
|
#undef _NAME
|
||||||
|
|
||||||
|
const char *snd_pcm_chmap_name(enum snd_pcm_chmap_position val)
|
||||||
|
{
|
||||||
|
if (val <= SND_CHMAP_LAST)
|
||||||
|
return chmap_names[val];
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int snd_pcm_chmap_print(const snd_pcm_chmap_t *map, size_t maxlen, char *buf)
|
||||||
|
{
|
||||||
|
unsigned int i, len = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < map->channels; i++) {
|
||||||
|
unsigned int p = map->pos[i] & SND_CHMAP_POSITION_MASK;
|
||||||
|
if (i > 0) {
|
||||||
|
len += snprintf(buf + len, maxlen - len, " ");
|
||||||
|
if (len >= maxlen)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
if (map->pos[i] & SND_CHMAP_DRIVER_SPEC)
|
||||||
|
len += snprintf(buf + len, maxlen, "%d", p);
|
||||||
|
else {
|
||||||
|
const char *name = chmap_names[p];
|
||||||
|
if (name)
|
||||||
|
len += snprintf(buf + len, maxlen - len,
|
||||||
|
"%s", name);
|
||||||
|
else
|
||||||
|
len += snprintf(buf + len, maxlen - len,
|
||||||
|
"Ch%d", p);
|
||||||
|
}
|
||||||
|
if (len >= maxlen)
|
||||||
|
return -ENOMEM;
|
||||||
|
if (map->pos[i] & SND_CHMAP_PHASE_INVERSE) {
|
||||||
|
len += snprintf(buf + len, maxlen - len, "[INV]");
|
||||||
|
if (len >= maxlen)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int str_to_chmap(const char *str, int len)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (isdigit(*str)) {
|
||||||
|
val = atoi(str);
|
||||||
|
if (val < 0)
|
||||||
|
return -1;
|
||||||
|
return val | SND_CHMAP_DRIVER_SPEC;
|
||||||
|
} else if (str[0] == 'C' && str[1] == 'h') {
|
||||||
|
val = atoi(str + 2);
|
||||||
|
if (val < 0)
|
||||||
|
return -1;
|
||||||
|
return val;
|
||||||
|
} else {
|
||||||
|
for (val = 0; val <= SND_CHMAP_LAST; val++) {
|
||||||
|
if (!strncmp(str, chmap_names[val], len))
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int snd_pcm_chmap_from_string(const char *str)
|
||||||
|
{
|
||||||
|
return str_to_chmap(str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_pcm_chmap_t *snd_pcm_chmap_parse_string(const char *str)
|
||||||
|
{
|
||||||
|
int i, ch = 0;
|
||||||
|
int tmp_map[64];
|
||||||
|
snd_pcm_chmap_t *map;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
const char *p;
|
||||||
|
int len, val;
|
||||||
|
|
||||||
|
if (ch >= (int)(sizeof(tmp_map) / sizeof(tmp_map[0])))
|
||||||
|
return NULL;
|
||||||
|
for (p = str; *p && isalnum(*p); p++)
|
||||||
|
;
|
||||||
|
len = p - str;
|
||||||
|
if (!len)
|
||||||
|
return NULL;
|
||||||
|
val = str_to_chmap(str, len);
|
||||||
|
if (val < 0)
|
||||||
|
return NULL;
|
||||||
|
str += len;
|
||||||
|
if (*str == '[') {
|
||||||
|
if (!strncmp(str, "[INV]", 5)) {
|
||||||
|
val |= SND_CHMAP_PHASE_INVERSE;
|
||||||
|
str += 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmp_map[ch] = val;
|
||||||
|
ch++;
|
||||||
|
for (; *str && !isalnum(*str); str++)
|
||||||
|
;
|
||||||
|
if (!*str)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
map = malloc(sizeof(*map) + ch * sizeof(int));
|
||||||
|
if (!map)
|
||||||
|
return NULL;
|
||||||
|
map->channels = ch;
|
||||||
|
for (i = 0; i < ch; i++)
|
||||||
|
map->pos[i] = tmp_map[i];
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* basic helpers
|
* basic helpers
|
||||||
|
|
|
||||||
69
test/chmap.c
69
test/chmap.c
|
|
@ -21,62 +21,11 @@ static void usage(void)
|
||||||
" -r rate Sample rate\n");
|
" -r rate Sample rate\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * const chname[] = {
|
|
||||||
"Unknown",
|
|
||||||
"FL", "FR", "RL", "RR", "FC", "LFE", "SL", "SR", "RC",
|
|
||||||
"FLC", "FRC", "RLC", "RRC", "FLW", "FRW", "FLH",
|
|
||||||
"FCH", "FRH", "TC",
|
|
||||||
"N/A",
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
|
||||||
|
|
||||||
static void print_channels(const snd_pcm_chmap_t *map)
|
static void print_channels(const snd_pcm_chmap_t *map)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
char tmp[128];
|
||||||
|
if (snd_pcm_chmap_print(map, sizeof(tmp), tmp) > 0)
|
||||||
printf(" ");
|
printf(" %s\n", tmp);
|
||||||
for (i = 0; i < map->channels; i++) {
|
|
||||||
unsigned int c = map->pos[i];
|
|
||||||
unsigned int p = c & SND_CHMAP_POSITION_MASK;
|
|
||||||
if (c & SND_CHMAP_DRIVER_SPEC)
|
|
||||||
printf(" %d", p);
|
|
||||||
else if (p >= ARRAY_SIZE(chname))
|
|
||||||
printf(" Ch%d", p);
|
|
||||||
else
|
|
||||||
printf(" %s", chname[p]);
|
|
||||||
if (c & SND_CHMAP_PHASE_INVERSE)
|
|
||||||
printf("[INV]");
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int to_channel(const char *name)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (isdigit(*name))
|
|
||||||
return atoi(name);
|
|
||||||
for (i = 0; i < ARRAY_SIZE(chname); i++)
|
|
||||||
if (!strcmp(chname[i], name))
|
|
||||||
return i;
|
|
||||||
return SND_CHMAP_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *chmap_type(int type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case SND_CHMAP_NONE:
|
|
||||||
return "None";
|
|
||||||
case SND_CHMAP_FIXED:
|
|
||||||
return "Fixed";
|
|
||||||
case SND_CHMAP_VAR:
|
|
||||||
return "Variable";
|
|
||||||
case SND_CHMAP_PAIRED:
|
|
||||||
return "Paired";
|
|
||||||
default:
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int query_chmaps(snd_pcm_t *pcm)
|
static int query_chmaps(snd_pcm_t *pcm)
|
||||||
|
|
@ -89,7 +38,9 @@ static int query_chmaps(snd_pcm_t *pcm)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
for (p = maps; (v = *p) != NULL; p++) {
|
for (p = maps; (v = *p) != NULL; p++) {
|
||||||
printf("Type = %s, Channels = %d\n", chmap_type(v->type), v->map.channels);
|
printf("Type = %s, Channels = %d\n",
|
||||||
|
snd_pcm_chmap_type_name(v->type),
|
||||||
|
v->map.channels);
|
||||||
print_channels(&v->map);
|
print_channels(&v->map);
|
||||||
}
|
}
|
||||||
snd_pcm_free_chmaps(maps);
|
snd_pcm_free_chmaps(maps);
|
||||||
|
|
@ -173,8 +124,12 @@ static int set_chmap(snd_pcm_t *pcm, int format, int channels, int rate,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
map->channels = channels;
|
map->channels = channels;
|
||||||
for (i = 0; i < channels; i++)
|
for (i = 0; i < channels; i++) {
|
||||||
map->pos[i] = to_channel(arg[i]);
|
int val = snd_pcm_chmap_from_string(arg[i]);
|
||||||
|
if (val < 0)
|
||||||
|
val = SND_CHMAP_UNKNOWN;
|
||||||
|
map->pos[i] = val;
|
||||||
|
}
|
||||||
if (snd_pcm_set_chmap(pcm, map) < 0) {
|
if (snd_pcm_set_chmap(pcm, map) < 0) {
|
||||||
printf("Cannot set chmap\n");
|
printf("Cannot set chmap\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue