spa: make a function to make a channel short name

Make a function that can generate and parse a short name for
the positions that are not in the type list, like the AUX channels.
This commit is contained in:
Wim Taymans 2025-10-22 13:04:53 +02:00
parent 7177f8269d
commit 11f1298f53
16 changed files with 74 additions and 38 deletions

View file

@ -925,11 +925,12 @@ static int snd_pcm_pipewire_set_chmap(snd_pcm_ioplug_t * io,
} }
for (i = 0; i < map->channels; i++) { for (i = 0; i < map->channels; i++) {
uint32_t pos = chmap_to_channel(map->pos[i]); uint32_t pos = chmap_to_channel(map->pos[i]);
char buf[8];
if (i < max_position) if (i < max_position)
position[i] = pos; position[i] = pos;
pw_log_debug("map %d: %s / %s", i, pw_log_debug("map %d: %s / %s", i,
snd_pcm_chmap_name(map->pos[i]), snd_pcm_chmap_name(map->pos[i]),
spa_debug_type_find_short_name(spa_type_audio_channel, pos)); spa_type_audio_channel_make_short_name(pos, buf, sizeof(buf), "UNK"));
} }
return 1; return 1;
} }

View file

@ -267,12 +267,34 @@ static const struct spa_type_info spa_type_audio_channel[] = {
SPA_API_AUDIO_RAW_TYPES uint32_t spa_type_audio_channel_from_short_name(const char *name) SPA_API_AUDIO_RAW_TYPES uint32_t spa_type_audio_channel_from_short_name(const char *name)
{ {
return spa_type_from_short_name(name, spa_type_audio_channel, SPA_AUDIO_CHANNEL_UNKNOWN); uint32_t res;
if (spa_strstartswith(name, "AUX")) {
if (spa_atou32(name+3, &res, 10) && res < 0x1000)
res = SPA_AUDIO_CHANNEL_AUX0 + res;
else
res = SPA_AUDIO_CHANNEL_UNKNOWN;
} else {
res = spa_type_from_short_name(name, spa_type_audio_channel, SPA_AUDIO_CHANNEL_UNKNOWN);
}
return res;
} }
SPA_API_AUDIO_RAW_TYPES const char * spa_type_audio_channel_to_short_name(uint32_t type) SPA_API_AUDIO_RAW_TYPES const char * spa_type_audio_channel_to_short_name(uint32_t type)
{ {
return spa_type_to_short_name(type, spa_type_audio_channel, "UNK"); return spa_type_to_short_name(type, spa_type_audio_channel, "UNK");
} }
SPA_API_AUDIO_RAW_TYPES const char * spa_type_audio_channel_make_short_name(uint32_t type,
char *buf, size_t size, const char *unknown)
{
if (SPA_AUDIO_CHANNEL_IS_AUX(type)) {
snprintf(buf, size, "AUX%u", type - SPA_AUDIO_CHANNEL_AUX0);
} else {
const char *str = spa_type_to_short_name(type, spa_type_audio_channel, NULL);
if (str == NULL)
return unknown;
snprintf(buf, size, "%.7s", str);
}
return buf;
}
#define SPA_TYPE_INFO_AudioVolumeRampScale SPA_TYPE_INFO_ENUM_BASE "AudioVolumeRampScale" #define SPA_TYPE_INFO_AudioVolumeRampScale SPA_TYPE_INFO_ENUM_BASE "AudioVolumeRampScale"
#define SPA_TYPE_INFO_AUDIO_VOLUME_RAMP_SCALE_BASE SPA_TYPE_INFO_AudioVolumeRampScale ":" #define SPA_TYPE_INFO_AUDIO_VOLUME_RAMP_SCALE_BASE SPA_TYPE_INFO_AudioVolumeRampScale ":"

View file

@ -241,12 +241,13 @@ static int alsa_set_param(struct state *state, const char *k, const char *s)
static int position_to_string(struct channel_map *map, char *val, size_t len) static int position_to_string(struct channel_map *map, char *val, size_t len)
{ {
uint32_t i, o = 0; uint32_t i, o = 0;
char pos[8];
int r; int r;
o += snprintf(val, len, "[ "); o += snprintf(val, len, "[ ");
for (i = 0; i < map->n_pos; i++) { for (i = 0; i < map->n_pos; i++) {
r = snprintf(val+o, len-o, "%s%s", i == 0 ? "" : ", ", r = snprintf(val+o, len-o, "%s%s", i == 0 ? "" : ", ",
spa_debug_type_find_short_name(spa_type_audio_channel, spa_type_audio_channel_make_short_name(map->pos[i],
map->pos[i])); pos, sizeof(pos), "UNK"));
if (r < 0 || o + r >= len) if (r < 0 || o + r >= len)
return -ENOSPC; return -ENOSPC;
o += r; o += r;

View file

@ -424,7 +424,6 @@ static int init_port(struct impl *this, enum spa_direction direction, uint32_t p
uint32_t position, bool is_dsp, bool is_monitor, bool is_control) uint32_t position, bool is_dsp, bool is_monitor, bool is_control)
{ {
struct port *port = GET_PORT(this, direction, port_id); struct port *port = GET_PORT(this, direction, port_id);
const char *name;
spa_assert(port_id < MAX_PORTS); spa_assert(port_id < MAX_PORTS);
@ -439,8 +438,7 @@ static int init_port(struct impl *this, enum spa_direction direction, uint32_t p
port->latency[SPA_DIRECTION_INPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT); port->latency[SPA_DIRECTION_INPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT);
port->latency[SPA_DIRECTION_OUTPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_OUTPUT); port->latency[SPA_DIRECTION_OUTPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_OUTPUT);
name = spa_debug_type_find_short_name(spa_type_audio_channel, position); spa_type_audio_channel_make_short_name(position, port->position, sizeof(port->position), "UNK");
snprintf(port->position, sizeof(port->position), "%s", name ? name : "UNK");
port->info = SPA_PORT_INFO_INIT(); port->info = SPA_PORT_INFO_INIT();
port->info.change_mask = port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | port->info.change_mask = port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
@ -2067,6 +2065,7 @@ static int setup_in_convert(struct impl *this)
for (i = 0; i < src_info.info.raw.channels; i++) { for (i = 0; i < src_info.info.raw.channels; i++) {
for (j = 0; j < dst_info.info.raw.channels; j++) { for (j = 0; j < dst_info.info.raw.channels; j++) {
uint32_t pi, pj; uint32_t pi, pj;
char b1[8], b2[8];
pi = spa_format_audio_raw_get_position(&src_info.info.raw, i); pi = spa_format_audio_raw_get_position(&src_info.info.raw, i);
pj = spa_format_audio_raw_get_position(&dst_info.info.raw, j); pj = spa_format_audio_raw_get_position(&dst_info.info.raw, j);
@ -2077,8 +2076,8 @@ static int setup_in_convert(struct impl *this)
remap = true; remap = true;
spa_log_debug(this->log, "%p: channel %d (%d) -> %d (%s -> %s)", this, spa_log_debug(this->log, "%p: channel %d (%d) -> %d (%s -> %s)", this,
i, in->remap[i], j, i, in->remap[i], j,
spa_debug_type_find_short_name(spa_type_audio_channel, pi), spa_type_audio_channel_make_short_name(pi, b1, 8, "UNK"),
spa_debug_type_find_short_name(spa_type_audio_channel, pj)); spa_type_audio_channel_make_short_name(pj, b2, 8, "UNK"));
spa_format_audio_raw_set_position(&dst_info.info.raw, j, -1); spa_format_audio_raw_set_position(&dst_info.info.raw, j, -1);
break; break;
} }
@ -2192,10 +2191,11 @@ static void set_volume(struct impl *this)
static char *format_position(char *str, size_t len, uint32_t channels, uint32_t *position, uint32_t max_position) static char *format_position(char *str, size_t len, uint32_t channels, uint32_t *position, uint32_t max_position)
{ {
uint32_t i, idx = 0; uint32_t i, idx = 0;
char buf[8];
for (i = 0; i < channels; i++) for (i = 0; i < channels; i++)
idx += snprintf(str + idx, len - idx, "%s%s", i == 0 ? "" : " ", idx += snprintf(str + idx, len - idx, "%s%s", i == 0 ? "" : " ",
spa_debug_type_find_short_name(spa_type_audio_channel, spa_type_audio_channel_make_short_name(position[i % max_position],
position[i % max_position])); buf, sizeof(buf), "UNK"));
return str; return str;
} }
@ -2359,6 +2359,7 @@ static int setup_out_convert(struct impl *this)
for (i = 0; i < src_info.info.raw.channels; i++) { for (i = 0; i < src_info.info.raw.channels; i++) {
for (j = 0; j < dst_info.info.raw.channels; j++) { for (j = 0; j < dst_info.info.raw.channels; j++) {
uint32_t pi, pj; uint32_t pi, pj;
char b1[8], b2[8];
pi = spa_format_audio_raw_get_position(&src_info.info.raw, i); pi = spa_format_audio_raw_get_position(&src_info.info.raw, i);
pj = spa_format_audio_raw_get_position(&dst_info.info.raw, j); pj = spa_format_audio_raw_get_position(&dst_info.info.raw, j);
@ -2370,8 +2371,8 @@ static int setup_out_convert(struct impl *this)
spa_log_debug(this->log, "%p: channel %d (%d) -> %d (%s -> %s)", this, spa_log_debug(this->log, "%p: channel %d (%d) -> %d (%s -> %s)", this,
i, out->remap[i], j, i, out->remap[i], j,
spa_debug_type_find_short_name(spa_type_audio_channel, pi), spa_type_audio_channel_make_short_name(pi, b1, 8, "UNK"),
spa_debug_type_find_short_name(spa_type_audio_channel, pj)); spa_type_audio_channel_make_short_name(pj, b2, 8, "UNK"));
spa_format_audio_raw_set_position(&dst_info.info.raw, j, -1); spa_format_audio_raw_set_position(&dst_info.info.raw, j, -1);
break; break;

View file

@ -86,11 +86,12 @@ static int position_to_string(struct channel_map *map, char *val, size_t len)
{ {
uint32_t i, o = 0; uint32_t i, o = 0;
int r; int r;
char pos[8];
o += snprintf(val, len, "[ "); o += snprintf(val, len, "[ ");
for (i = 0; i < map->channels; i++) { for (i = 0; i < map->channels; i++) {
r = snprintf(val+o, len-o, "%s%s", i == 0 ? "" : ", ", r = snprintf(val+o, len-o, "%s%s", i == 0 ? "" : ", ",
spa_debug_type_find_short_name(spa_type_audio_channel, spa_type_audio_channel_make_short_name(map->pos[i],
map->pos[i])); pos, sizeof(pos), "UNK"));
if (r < 0 || o + r >= len) if (r < 0 || o + r >= len)
return -ENOSPC; return -ENOSPC;
o += r; o += r;

View file

@ -236,13 +236,14 @@ static inline void print_channels(char *buffer, size_t max_size, uint32_t n_posi
{ {
uint32_t i; uint32_t i;
struct spa_strbuf buf; struct spa_strbuf buf;
char pos[8];
spa_strbuf_init(&buf, buffer, max_size); spa_strbuf_init(&buf, buffer, max_size);
spa_strbuf_append(&buf, "["); spa_strbuf_append(&buf, "[");
for (i = 0; i < n_positions; i++) { for (i = 0; i < n_positions; i++) {
spa_strbuf_append(&buf, "%s%s", i ? "," : "", spa_strbuf_append(&buf, "%s%s", i ? "," : "",
spa_type_audio_channel_to_short_name(positions[i])); spa_type_audio_channel_make_short_name(positions[i],
pos, sizeof(pos), "UNK"));
} }
spa_strbuf_append(&buf, "]"); spa_strbuf_append(&buf, "]");
} }

View file

@ -514,6 +514,7 @@ static void make_stream_ports(struct stream *s)
for (i = 0; i < s->n_ports; i++) { for (i = 0; i < s->n_ports; i++) {
struct port *port = s->ports[i]; struct port *port = s->ports[i];
char *link_port = NULL; char *link_port = NULL;
char pos[8];
if (port != NULL) { if (port != NULL) {
s->ports[i] = NULL; s->ports[i] = NULL;
@ -523,8 +524,9 @@ static void make_stream_ports(struct stream *s)
} }
if (i < s->info.channels) { if (i < s->info.channels) {
str = spa_debug_type_find_short_name(spa_type_audio_channel, str = spa_type_audio_channel_make_short_name(
spa_format_audio_raw_get_position(&s->info, i)); spa_format_audio_raw_get_position(&s->info, i),
pos, sizeof(pos), NULL);
if (str) if (str)
snprintf(name, sizeof(name), "%s_%s", prefix, str); snprintf(name, sizeof(name), "%s_%s", prefix, str);
else else

View file

@ -441,11 +441,12 @@ static void make_stream_ports(struct stream *s)
} }
if (i < s->info.channels) { if (i < s->info.channels) {
str = spa_debug_type_find_short_name(spa_type_audio_channel, str = spa_type_audio_channel_make_short_name(
spa_format_audio_raw_get_position(&s->info, i)); spa_format_audio_raw_get_position(&s->info, i),
name, sizeof(name), "UNK");
props = pw_properties_new( props = pw_properties_new(
PW_KEY_FORMAT_DSP, "32 bit float mono audio", PW_KEY_FORMAT_DSP, "32 bit float mono audio",
PW_KEY_AUDIO_CHANNEL, str ? str : "UNK", PW_KEY_AUDIO_CHANNEL, str,
PW_KEY_PORT_PHYSICAL, "true", PW_KEY_PORT_PHYSICAL, "true",
NULL); NULL);

View file

@ -601,12 +601,12 @@ static void make_stream_ports(struct stream *s)
} }
if (i < s->info.channels) { if (i < s->info.channels) {
str = spa_debug_type_find_short_name(spa_type_audio_channel, str = spa_type_audio_channel_make_short_name(
spa_format_audio_raw_get_position(&s->info, i)); spa_format_audio_raw_get_position(&s->info, i),
name, sizeof(name), "UNK");
props = pw_properties_new( props = pw_properties_new(
PW_KEY_FORMAT_DSP, "32 bit float mono audio", PW_KEY_FORMAT_DSP, "32 bit float mono audio",
PW_KEY_AUDIO_CHANNEL, str ? str : "UNK", PW_KEY_AUDIO_CHANNEL, str,
PW_KEY_PORT_PHYSICAL, "true", PW_KEY_PORT_PHYSICAL, "true",
NULL); NULL);

View file

@ -298,9 +298,9 @@ uint32_t channel_pa2id(enum channel_position channel)
return audio_channels[channel].channel; return audio_channels[channel].channel;
} }
const char *channel_id2name(uint32_t channel) const char *channel_id2name(uint32_t channel, char *buf, size_t size)
{ {
return spa_type_audio_channel_to_short_name(channel); return spa_type_audio_channel_make_short_name(channel, buf, size, "UNK");
} }
uint32_t channel_name2id(const char *name) uint32_t channel_name2id(const char *name)

View file

@ -190,7 +190,7 @@ void sample_spec_fix(struct sample_spec *ss, struct channel_map *map,
struct spa_dict *props); struct spa_dict *props);
uint32_t channel_pa2id(enum channel_position channel); uint32_t channel_pa2id(enum channel_position channel);
const char *channel_id2name(uint32_t channel); const char *channel_id2name(uint32_t channel, char *buf, size_t size);
uint32_t channel_name2id(const char *name); uint32_t channel_name2id(const char *name);
enum channel_position channel_id2pa(uint32_t id, uint32_t *aux); enum channel_position channel_id2pa(uint32_t id, uint32_t *aux);
const char *channel_id2paname(uint32_t id, uint32_t *aux); const char *channel_id2paname(uint32_t id, uint32_t *aux);

View file

@ -761,11 +761,13 @@ int message_dump(enum spa_log_level level, const char *prefix, struct message *m
case TAG_CHANNEL_MAP: case TAG_CHANNEL_MAP:
{ {
struct channel_map map; struct channel_map map;
char pos[8];
if ((res = read_channel_map(m, &map)) < 0) if ((res = read_channel_map(m, &map)) < 0)
return res; return res;
pw_log(level, "%s %u: channelmap: channels:%u", prefix, o, map.channels); pw_log(level, "%s %u: channelmap: channels:%u", prefix, o, map.channels);
for (i = 0; i < map.channels; i++) for (i = 0; i < map.channels; i++)
pw_log(level, "%s %d: %s", prefix, i, channel_id2name(map.map[i])); pw_log(level, "%s %d: %s", prefix, i,
channel_id2name(map.map[i], pos, sizeof(pos)));
break; break;
} }
case TAG_CVOLUME: case TAG_CVOLUME:

View file

@ -283,14 +283,15 @@ void audioinfo_to_properties(struct spa_audio_info_raw *info, struct pw_properti
if (info->rate) if (info->rate)
pw_properties_setf(props, SPA_KEY_AUDIO_RATE, "%u", info->rate); pw_properties_setf(props, SPA_KEY_AUDIO_RATE, "%u", info->rate);
if (info->channels) { if (info->channels) {
char *s, *p; char *s, *p, pos[8];
pw_properties_setf(props, SPA_KEY_AUDIO_CHANNELS, "%u", info->channels); pw_properties_setf(props, SPA_KEY_AUDIO_CHANNELS, "%u", info->channels);
p = s = alloca(info->channels * 8); p = s = alloca(info->channels * 8);
for (i = 0; i < info->channels; i++) for (i = 0; i < info->channels; i++)
p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ", ", p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ", ",
channel_id2name(spa_format_audio_raw_get_position(info, i))); channel_id2name(spa_format_audio_raw_get_position(info, i),
pos, sizeof(pos)));
pw_properties_setf(props, SPA_KEY_AUDIO_POSITION, "[ %s ]", s); pw_properties_setf(props, SPA_KEY_AUDIO_POSITION, "[ %s ]", s);
} }
} }

View file

@ -295,9 +295,11 @@ static int do_extension_stream_restore_write(struct module *module, struct clien
fprintf(f, " ]"); fprintf(f, " ]");
} }
if (map.channels > 0) { if (map.channels > 0) {
char pos[8];
fprintf(f, ", \"channels\": ["); fprintf(f, ", \"channels\": [");
for (i = 0; i < map.channels; i++) for (i = 0; i < map.channels; i++)
fprintf(f, "%s\"%s\"", (i == 0 ? " ":", "), channel_id2name(map.map[i])); fprintf(f, "%s\"%s\"", (i == 0 ? " ":", "),
channel_id2name(map.map[i], pos, sizeof(pos)));
fprintf(f, " ]"); fprintf(f, " ]");
} }
if (device_name != NULL && device_name[0] && if (device_name != NULL && device_name[0] &&

View file

@ -188,7 +188,7 @@ static void pw_properties_from_avahi_string(const char *key, const char *value,
else if (spa_streq(key, "channel_map")) { else if (spa_streq(key, "channel_map")) {
struct channel_map channel_map; struct channel_map channel_map;
uint32_t i, pos[CHANNELS_MAX]; uint32_t i, pos[CHANNELS_MAX];
char *p, *s; char *p, *s, buf[8];
spa_zero(channel_map); spa_zero(channel_map);
channel_map_parse(value, &channel_map); channel_map_parse(value, &channel_map);
@ -198,7 +198,7 @@ static void pw_properties_from_avahi_string(const char *key, const char *value,
p += spa_scnprintf(p, 2, "["); p += spa_scnprintf(p, 2, "[");
for (i = 0; i < channel_map.channels; i++) for (i = 0; i < channel_map.channels; i++)
p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ",", p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ",",
channel_id2name(pos[i])); channel_id2name(pos[i], buf, sizeof(buf)));
p += spa_scnprintf(p, 2, "]"); p += spa_scnprintf(p, 2, "]");
pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s); pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s);
} }

View file

@ -747,10 +747,11 @@ static int channelmap_default(struct channelmap *map, int n_channels)
static void channelmap_print(struct channelmap *map) static void channelmap_print(struct channelmap *map)
{ {
uint32_t i; uint32_t i;
char pos[8];
for (i = 0; i < map->n_channels; i++) { for (i = 0; i < map->n_channels; i++) {
const char *name = spa_type_audio_channel_to_short_name(map->channels[i]); fprintf(stderr, "%s%s", i ? "," : "",
fprintf(stderr, "%s%s", name, i + 1 < map->n_channels ? "," : ""); spa_type_audio_channel_make_short_name(map->channels[i],
pos, sizeof(pos), "UNK"));
} }
} }