spa: add spa_audio_parse_position_n

Add a function that accepts the size of the position array when reading
the audio positions. This makes it possible to decouple the position
array size from SPA_AUDIO_MAX_CHANNELS.

Also use SPA_N_ELEMENTS to pass the number of array elements to
functions instead of a fixed constant. This makes it easier to change
the array size later to a different constant without having to patch up
all the places where the size is used.
This commit is contained in:
Wim Taymans 2025-10-20 15:16:54 +02:00
parent 9e7cae13df
commit 8bbca3b8f3
27 changed files with 84 additions and 63 deletions

View file

@ -856,7 +856,7 @@ static void parse_props(struct global *g, const struct spa_pod *param, bool devi
uint32_t n_volumes, i; uint32_t n_volumes, i;
n_volumes = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, n_volumes = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
volumes, SPA_AUDIO_MAX_CHANNELS); volumes, SPA_N_ELEMENTS(volumes));
g->node.channel_volume.channels = n_volumes; g->node.channel_volume.channels = n_volumes;
for (i = 0; i < n_volumes; i++) for (i = 0; i < n_volumes; i++)

View file

@ -42,7 +42,7 @@ spa_format_audio_dsd_parse(const struct spa_pod *format, struct spa_audio_info_d
SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels), SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels),
SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position)); SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position));
if (position == NULL || if (position == NULL ||
!spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS)) !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_N_ELEMENTS(info->position)))
SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
return res; return res;

View file

@ -28,8 +28,8 @@ extern "C" {
#endif #endif
SPA_API_AUDIO_RAW_JSON int SPA_API_AUDIO_RAW_JSON int
spa_audio_parse_position(const char *str, size_t len, spa_audio_parse_position_n(const char *str, size_t len,
uint32_t *position, uint32_t *n_channels) uint32_t *position, uint32_t max_channels, uint32_t *n_channels)
{ {
struct spa_json iter; struct spa_json iter;
char v[256]; char v[256];
@ -39,12 +39,18 @@ spa_audio_parse_position(const char *str, size_t len,
return 0; return 0;
while (spa_json_get_string(&iter, v, sizeof(v)) > 0 && while (spa_json_get_string(&iter, v, sizeof(v)) > 0 &&
channels < SPA_AUDIO_MAX_CHANNELS) { channels < max_channels) {
position[channels++] = spa_type_audio_channel_from_short_name(v); position[channels++] = spa_type_audio_channel_from_short_name(v);
} }
*n_channels = channels; *n_channels = channels;
return channels; return channels;
} }
SPA_API_AUDIO_RAW_JSON int
spa_audio_parse_position(const char *str, size_t len,
uint32_t *position, uint32_t *n_channels)
{
return spa_audio_parse_position_n(str, len, position, SPA_AUDIO_MAX_CHANNELS, n_channels);
}
SPA_API_AUDIO_RAW_JSON int SPA_API_AUDIO_RAW_JSON int
spa_audio_info_raw_update(struct spa_audio_info_raw *info, const char *key, const char *val, bool force) spa_audio_info_raw_update(struct spa_audio_info_raw *info, const char *key, const char *val, bool force)
@ -58,10 +64,11 @@ spa_audio_info_raw_update(struct spa_audio_info_raw *info, const char *key, cons
info->rate = v; info->rate = v;
} else if (spa_streq(key, SPA_KEY_AUDIO_CHANNELS)) { } else if (spa_streq(key, SPA_KEY_AUDIO_CHANNELS)) {
if (spa_atou32(val, &v, 0) && (force || info->channels == 0)) if (spa_atou32(val, &v, 0) && (force || info->channels == 0))
info->channels = SPA_MIN(v, SPA_AUDIO_MAX_CHANNELS); info->channels = SPA_MIN(v, SPA_N_ELEMENTS(info->position));
} else if (spa_streq(key, SPA_KEY_AUDIO_POSITION)) { } else if (spa_streq(key, SPA_KEY_AUDIO_POSITION)) {
if (force || info->channels == 0) { if (force || info->channels == 0) {
if (spa_audio_parse_position(val, strlen(val), info->position, &info->channels) > 0) if (spa_audio_parse_position_n(val, strlen(val), info->position,
SPA_N_ELEMENTS(info->position), &info->channels) > 0)
SPA_FLAG_CLEAR(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); SPA_FLAG_CLEAR(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
} }
} }

View file

@ -55,7 +55,7 @@ spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_r
SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels), SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels),
SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position)); SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position));
if (position == NULL || if (position == NULL ||
!spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS)) !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_N_ELEMENTS(info->position)))
SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
return res; return res;

View file

@ -697,13 +697,13 @@ static int apply_device_props(struct impl *this, struct acp_device *dev, struct
break; break;
case SPA_PROP_channelVolumes: case SPA_PROP_channelVolumes:
if ((n_volumes = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, if ((n_volumes = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
volumes, SPA_AUDIO_MAX_CHANNELS)) > 0) { volumes, SPA_N_ELEMENTS(volumes))) > 0) {
changed++; changed++;
} }
break; break;
case SPA_PROP_channelMap: case SPA_PROP_channelMap:
if (spa_pod_copy_array(&prop->value, SPA_TYPE_Id, if (spa_pod_copy_array(&prop->value, SPA_TYPE_Id,
channels, SPA_AUDIO_MAX_CHANNELS) > 0) { channels, SPA_N_ELEMENTS(channels)) > 0) {
changed++; changed++;
} }
break; break;

View file

@ -315,7 +315,7 @@ void spa_alsa_emit_port_info(struct state *state, bool full);
static inline void spa_alsa_parse_position(struct channel_map *map, const char *val, size_t len) static inline void spa_alsa_parse_position(struct channel_map *map, const char *val, size_t len)
{ {
spa_audio_parse_position(val, len, map->pos, &map->channels); spa_audio_parse_position_n(val, len, map->pos, SPA_N_ELEMENTS(map->pos), &map->channels);
} }
static inline uint32_t spa_alsa_parse_rates(uint32_t *rates, uint32_t max, const char *val, size_t len) static inline uint32_t spa_alsa_parse_rates(uint32_t *rates, uint32_t max, const char *val, size_t len)

View file

@ -1104,11 +1104,11 @@ static void graph_info(void *object, const struct spa_filter_graph_info *info)
else if (spa_streq(k, "n_outputs")) else if (spa_streq(k, "n_outputs"))
spa_atou32(s, &g->n_outputs, 0); spa_atou32(s, &g->n_outputs, 0);
else if (spa_streq(k, "inputs.audio.position")) else if (spa_streq(k, "inputs.audio.position"))
spa_audio_parse_position(s, strlen(s), spa_audio_parse_position_n(s, strlen(s), g->inputs_position,
g->inputs_position, &g->n_inputs); SPA_N_ELEMENTS(g->inputs_position), &g->n_inputs);
else if (spa_streq(k, "outputs.audio.position")) else if (spa_streq(k, "outputs.audio.position"))
spa_audio_parse_position(s, strlen(s), spa_audio_parse_position_n(s, strlen(s), g->outputs_position,
g->outputs_position, &g->n_outputs); SPA_N_ELEMENTS(g->outputs_position), &g->n_outputs);
else if (spa_streq(k, "latency")) { else if (spa_streq(k, "latency")) {
double latency; double latency;
if (spa_atod(s, &latency)) if (spa_atod(s, &latency))
@ -1749,7 +1749,7 @@ static int apply_props(struct impl *this, const struct spa_pod *param)
case SPA_PROP_channelVolumes: case SPA_PROP_channelVolumes:
if (!p->lock_volumes && if (!p->lock_volumes &&
(n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, (n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
p->channel.volumes, SPA_AUDIO_MAX_CHANNELS)) > 0) { p->channel.volumes, SPA_N_ELEMENTS(p->channel.volumes))) > 0) {
have_channel_volume = true; have_channel_volume = true;
p->channel.n_volumes = n; p->channel.n_volumes = n;
changed++; changed++;
@ -1757,7 +1757,7 @@ static int apply_props(struct impl *this, const struct spa_pod *param)
break; break;
case SPA_PROP_channelMap: case SPA_PROP_channelMap:
if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Id, if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Id,
p->channel_map, SPA_AUDIO_MAX_CHANNELS)) > 0) { p->channel_map, SPA_N_ELEMENTS(p->channel_map))) > 0) {
p->n_channels = n; p->n_channels = n;
changed++; changed++;
} }
@ -1772,7 +1772,7 @@ static int apply_props(struct impl *this, const struct spa_pod *param)
case SPA_PROP_softVolumes: case SPA_PROP_softVolumes:
if (!p->lock_volumes && if (!p->lock_volumes &&
(n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, (n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
p->soft.volumes, SPA_AUDIO_MAX_CHANNELS)) > 0) { p->soft.volumes, SPA_N_ELEMENTS(p->soft.volumes))) > 0) {
have_soft_volume = true; have_soft_volume = true;
p->soft.n_volumes = n; p->soft.n_volumes = n;
changed++; changed++;
@ -1784,7 +1784,7 @@ static int apply_props(struct impl *this, const struct spa_pod *param)
break; break;
case SPA_PROP_monitorVolumes: case SPA_PROP_monitorVolumes:
if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
p->monitor.volumes, SPA_AUDIO_MAX_CHANNELS)) > 0) { p->monitor.volumes, SPA_N_ELEMENTS(p->monitor.volumes))) > 0) {
p->monitor.n_volumes = n; p->monitor.n_volumes = n;
changed++; changed++;
} }
@ -4297,8 +4297,9 @@ impl_init(const struct spa_handle_factory *factory,
} }
else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) { else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) {
if (s != NULL) if (s != NULL)
spa_audio_parse_position(s, strlen(s), this->props.channel_map, spa_audio_parse_position_n(s, strlen(s),
&this->props.n_channels); this->props.channel_map, SPA_N_ELEMENTS(this->props.channel_map),
&this->props.n_channels);
} }
else if (spa_streq(k, SPA_KEY_PORT_IGNORE_LATENCY)) else if (spa_streq(k, SPA_KEY_PORT_IGNORE_LATENCY))
this->port_ignore_latency = spa_atob(s); this->port_ignore_latency = spa_atob(s);

View file

@ -40,7 +40,8 @@ static int avb_set_param(struct state *state, const char *k, const char *s)
state->default_format = spa_type_audio_format_from_short_name(s); state->default_format = spa_type_audio_format_from_short_name(s);
fmt_change++; fmt_change++;
} else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) { } else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) {
spa_audio_parse_position(s, strlen(s), state->default_pos.pos, spa_audio_parse_position_n(s, strlen(s), state->default_pos.pos,
SPA_N_ELEMENTS(state->default_pos.pos),
&state->default_pos.channels); &state->default_pos.channels);
fmt_change++; fmt_change++;
} else if (spa_streq(k, SPA_KEY_AUDIO_ALLOWED_RATES)) { } else if (spa_streq(k, SPA_KEY_AUDIO_ALLOWED_RATES)) {

View file

@ -6861,7 +6861,8 @@ static void parse_bap_locations(struct spa_bt_monitor *this, const struct spa_di
if (spa_atou32(str, value, 0)) if (spa_atou32(str, value, 0))
return; return;
if (!spa_audio_parse_position(str, strlen(str), position, &n_channels)) { if (!spa_audio_parse_position_n(str, strlen(str), position,
SPA_N_ELEMENTS(position), &n_channels)) {
spa_log_error(this->log, "property %s '%s' is not valid position array", key, str); spa_log_error(this->log, "property %s '%s' is not valid position array", key, str);
return; return;
} }

View file

@ -2972,11 +2972,11 @@ static int apply_device_props(struct impl *this, struct node *node, struct spa_p
break; break;
case SPA_PROP_channelVolumes: case SPA_PROP_channelVolumes:
n_volumes = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, n_volumes = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
volumes, SPA_AUDIO_MAX_CHANNELS); volumes, SPA_N_ELEMENTS(volumes));
break; break;
case SPA_PROP_channelMap: case SPA_PROP_channelMap:
n_channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Id, n_channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Id,
channels, SPA_AUDIO_MAX_CHANNELS); channels, SPA_N_ELEMENTS(channels));
break; break;
case SPA_PROP_latencyOffsetNsec: case SPA_PROP_latencyOffsetNsec:
if (spa_pod_get_long(&prop->value, &latency_offset) == 0) { if (spa_pod_get_long(&prop->value, &latency_offset) == 0) {

View file

@ -749,7 +749,7 @@ static int impl_set_props(void *object, enum spa_direction direction, const stru
float vols[MAX_CHANNELS]; float vols[MAX_CHANNELS];
if ((n_vols = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, vols, if ((n_vols = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, vols,
SPA_AUDIO_MAX_CHANNELS)) > 0) { SPA_N_ELEMENTS(vols))) > 0) {
if (vol->n_volumes != n_vols) if (vol->n_volumes != n_vols)
do_volume = true; do_volume = true;
vol->n_volumes = n_vols; vol->n_volumes = n_vols;
@ -2119,8 +2119,9 @@ static int load_graph(struct graph *graph, const struct spa_dict *props)
spa_log_error(impl->log, "%s expects an array", key); spa_log_error(impl->log, "%s expects an array", key);
return -EINVAL; return -EINVAL;
} }
spa_audio_parse_position(val, len, graph->inputs_position, spa_audio_parse_position_n(val, len, graph->inputs_position,
&graph->n_inputs_position); SPA_N_ELEMENTS(graph->inputs_position),
&graph->n_inputs_position);
impl->info.n_inputs = graph->n_inputs_position; impl->info.n_inputs = graph->n_inputs_position;
} }
else if (spa_streq("outputs.audio.position", key)) { else if (spa_streq("outputs.audio.position", key)) {
@ -2129,8 +2130,9 @@ static int load_graph(struct graph *graph, const struct spa_dict *props)
spa_log_error(impl->log, "%s expects an array", key); spa_log_error(impl->log, "%s expects an array", key);
return -EINVAL; return -EINVAL;
} }
spa_audio_parse_position(val, len, graph->outputs_position, spa_audio_parse_position_n(val, len, graph->outputs_position,
&graph->n_outputs_position); SPA_N_ELEMENTS(graph->outputs_position),
&graph->n_outputs_position);
impl->info.n_outputs = graph->n_outputs_position; impl->info.n_outputs = graph->n_outputs_position;
} }
else if (spa_streq("nodes", key)) { else if (spa_streq("nodes", key)) {

View file

@ -637,7 +637,7 @@ port_set_format(struct impl *this,
if (info.info.raw.rate == 0 || if (info.info.raw.rate == 0 ||
info.info.raw.channels == 0 || info.info.raw.channels == 0 ||
info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) info.info.raw.channels > SPA_N_ELEMENTS(info.info.raw.position))
return -EINVAL; return -EINVAL;
if (this->props.format != 0) { if (this->props.format != 0) {
@ -950,7 +950,8 @@ impl_init(const struct spa_handle_factory *factory,
} else if (spa_streq(k, SPA_KEY_NODE_DRIVER)) { } else if (spa_streq(k, SPA_KEY_NODE_DRIVER)) {
this->props.driver = spa_atob(s); this->props.driver = spa_atob(s);
} else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) { } else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) {
spa_audio_parse_position(s, strlen(s), this->props.pos, &this->props.channels); spa_audio_parse_position_n(s, strlen(s), this->props.pos,
SPA_N_ELEMENTS(this->props.pos), &this->props.channels);
} else if (spa_streq(k, "clock.name")) { } else if (spa_streq(k, "clock.name")) {
spa_scnprintf(this->props.clock_name, spa_scnprintf(this->props.clock_name,
sizeof(this->props.clock_name), sizeof(this->props.clock_name),

View file

@ -455,7 +455,7 @@ static int port_set_format(void *object,
if (info.info.raw.format != SPA_AUDIO_FORMAT_S16 || if (info.info.raw.format != SPA_AUDIO_FORMAT_S16 ||
info.info.raw.channels == 0 || info.info.raw.channels == 0 ||
info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) info.info.raw.channels > SPA_N_ELEMENTS(info.info.raw.position))
return -EINVAL; return -EINVAL;
this->bpf = 2 * info.info.raw.channels; this->bpf = 2 * info.info.raw.channels;

View file

@ -269,7 +269,7 @@ static int port_set_format(void *object,
return -EINVAL; return -EINVAL;
if (d->format.rate == 0 || if (d->format.rate == 0 ||
d->format.channels == 0 || d->format.channels == 0 ||
d->format.channels > SPA_AUDIO_MAX_CHANNELS) d->format.channels > SPA_N_ELEMENTS(d->format.position))
return -EINVAL; return -EINVAL;
} }

View file

@ -866,13 +866,15 @@ static int create_stream(struct stream_info *info)
s->info = impl->info; s->info = impl->info;
if ((str = pw_properties_get(info->stream_props, SPA_KEY_AUDIO_POSITION)) != NULL) if ((str = pw_properties_get(info->stream_props, SPA_KEY_AUDIO_POSITION)) != NULL)
spa_audio_parse_position(str, strlen(str), s->info.position, &s->info.channels); spa_audio_parse_position_n(str, strlen(str), s->info.position,
SPA_N_ELEMENTS(s->info.position), &s->info.channels);
if (s->info.channels == 0) if (s->info.channels == 0)
s->info = impl->info; s->info = impl->info;
spa_zero(remap_info); spa_zero(remap_info);
if ((str = pw_properties_get(info->stream_props, "combine.audio.position")) != NULL) if ((str = pw_properties_get(info->stream_props, "combine.audio.position")) != NULL)
spa_audio_parse_position(str, strlen(str), remap_info.position, &remap_info.channels); spa_audio_parse_position_n(str, strlen(str), remap_info.position,
SPA_N_ELEMENTS(remap_info.position), &remap_info.channels);
if (remap_info.channels == 0) if (remap_info.channels == 0)
remap_info = s->info; remap_info = s->info;

View file

@ -1371,21 +1371,21 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
} }
if ((str = pw_properties_get(impl->capture_props, SPA_KEY_AUDIO_POSITION)) != NULL) { if ((str = pw_properties_get(impl->capture_props, SPA_KEY_AUDIO_POSITION)) != NULL) {
spa_audio_parse_position(str, strlen(str), spa_audio_parse_position_n(str, strlen(str), impl->capture_info.position,
impl->capture_info.position, &impl->capture_info.channels); SPA_N_ELEMENTS(impl->capture_info.position), &impl->capture_info.channels);
} }
if ((str = pw_properties_get(impl->source_props, SPA_KEY_AUDIO_POSITION)) != NULL) { if ((str = pw_properties_get(impl->source_props, SPA_KEY_AUDIO_POSITION)) != NULL) {
spa_audio_parse_position(str, strlen(str), spa_audio_parse_position_n(str, strlen(str), impl->source_info.position,
impl->source_info.position, &impl->source_info.channels); SPA_N_ELEMENTS(impl->source_info.position), &impl->source_info.channels);
} }
if ((str = pw_properties_get(impl->sink_props, SPA_KEY_AUDIO_POSITION)) != NULL) { if ((str = pw_properties_get(impl->sink_props, SPA_KEY_AUDIO_POSITION)) != NULL) {
spa_audio_parse_position(str, strlen(str), spa_audio_parse_position_n(str, strlen(str), impl->sink_info.position,
impl->sink_info.position, &impl->sink_info.channels); SPA_N_ELEMENTS(impl->sink_info.position), &impl->sink_info.channels);
impl->playback_info = impl->sink_info; impl->playback_info = impl->sink_info;
} }
if ((str = pw_properties_get(impl->playback_props, SPA_KEY_AUDIO_POSITION)) != NULL) { if ((str = pw_properties_get(impl->playback_props, SPA_KEY_AUDIO_POSITION)) != NULL) {
spa_audio_parse_position(str, strlen(str), spa_audio_parse_position_n(str, strlen(str), impl->playback_info.position,
impl->playback_info.position, &impl->playback_info.channels); SPA_N_ELEMENTS(impl->playback_info.position), &impl->playback_info.channels);
if (impl->playback_info.channels != impl->sink_info.channels) if (impl->playback_info.channels != impl->sink_info.channels)
impl->playback_info = impl->sink_info; impl->playback_info = impl->sink_info;
} }

View file

@ -299,7 +299,7 @@ static void capture_param_changed(void *data, uint32_t id, const struct spa_pod
return; return;
if (info.rate == 0 || if (info.rate == 0 ||
info.channels == 0 || info.channels == 0 ||
info.channels > SPA_AUDIO_MAX_CHANNELS) info.channels > SPA_N_ELEMENTS(info.position))
return; return;
break; break;
} }

View file

@ -876,7 +876,7 @@ static void parse_props(struct stream *s, const struct spa_pod *param)
uint32_t n; uint32_t n;
float vols[MAX_CHANNELS]; float vols[MAX_CHANNELS];
if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
vols, SPA_AUDIO_MAX_CHANNELS)) > 0) { vols, SPA_N_ELEMENTS(vols))) > 0) {
s->volume.n_volumes = n; s->volume.n_volumes = n;
for (n = 0; n < s->volume.n_volumes; n++) for (n = 0; n < s->volume.n_volumes; n++)
s->volume.volumes[n] = vols[n]; s->volume.volumes[n] = vols[n];

View file

@ -627,7 +627,7 @@ static void parse_props(struct stream *s, const struct spa_pod *param)
uint32_t n; uint32_t n;
float vols[MAX_CHANNELS]; float vols[MAX_CHANNELS];
if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
vols, SPA_AUDIO_MAX_CHANNELS)) > 0) { vols, SPA_N_ELEMENTS(vols))) > 0) {
s->volume.n_volumes = n; s->volume.n_volumes = n;
for (n = 0; n < s->volume.n_volumes; n++) for (n = 0; n < s->volume.n_volumes; n++)
s->volume.volumes[n] = vols[n]; s->volume.volumes[n] = vols[n];

View file

@ -539,7 +539,7 @@ static void param_format_changed(struct impl *impl, const struct spa_pod *param,
if (param != NULL) { if (param != NULL) {
if (spa_format_audio_raw_parse(param, &info) < 0 || if (spa_format_audio_raw_parse(param, &info) < 0 ||
info.channels == 0 || info.channels == 0 ||
info.channels > SPA_AUDIO_MAX_CHANNELS) info.channels > SPA_N_ELEMENTS(info.position))
return; return;
if ((impl->info.format != 0 && impl->info.format != info.format) || if ((impl->info.format != 0 && impl->info.format != info.format) ||

View file

@ -442,7 +442,7 @@ 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_debug_type_find_short_name(spa_type_audio_channel,
s->info.position[i % SPA_AUDIO_MAX_CHANNELS]); s->info.position[i % SPA_N_ELEMENTS(s->info.position)]);
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 ? str : "UNK",
@ -514,7 +514,7 @@ static void parse_props(struct stream *s, const struct spa_pod *param)
uint32_t n; uint32_t n;
float vols[MAX_CHANNELS]; float vols[MAX_CHANNELS];
if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
vols, SPA_AUDIO_MAX_CHANNELS)) > 0) { vols, SPA_N_ELEMENTS(vols))) > 0) {
s->volume.n_volumes = n; s->volume.n_volumes = n;
for (n = 0; n < s->volume.n_volumes; n++) for (n = 0; n < s->volume.n_volumes; n++)
s->volume.volumes[n] = vols[n]; s->volume.volumes[n] = vols[n];
@ -863,7 +863,8 @@ static int handle_follower_setup(struct impl *impl, struct nj2_session_params *p
} }
impl->sink.info.rate = peer->params.sample_rate; impl->sink.info.rate = peer->params.sample_rate;
if ((uint32_t)peer->params.send_audio_channels != impl->sink.info.channels) { if ((uint32_t)peer->params.send_audio_channels != impl->sink.info.channels) {
impl->sink.info.channels = SPA_MIN(peer->params.send_audio_channels, (int)SPA_AUDIO_MAX_CHANNELS); impl->sink.info.channels = SPA_MIN(peer->params.send_audio_channels,
(int)SPA_N_ELEMENTS(impl->sink.info.position));
for (i = 0; i < impl->sink.info.channels; i++) for (i = 0; i < impl->sink.info.channels; i++)
impl->sink.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i; impl->sink.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
} }
@ -874,7 +875,8 @@ static int handle_follower_setup(struct impl *impl, struct nj2_session_params *p
} }
impl->source.info.rate = peer->params.sample_rate; impl->source.info.rate = peer->params.sample_rate;
if ((uint32_t)peer->params.recv_audio_channels != impl->source.info.channels) { if ((uint32_t)peer->params.recv_audio_channels != impl->source.info.channels) {
impl->source.info.channels = SPA_MIN(peer->params.recv_audio_channels, (int)SPA_AUDIO_MAX_CHANNELS); impl->source.info.channels = SPA_MIN(peer->params.recv_audio_channels,
(int)SPA_N_ELEMENTS(impl->source.info.position));
for (i = 0; i < impl->source.info.channels; i++) for (i = 0; i < impl->source.info.channels; i++)
impl->source.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i; impl->source.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
} }

View file

@ -679,7 +679,7 @@ static void parse_props(struct stream *s, const struct spa_pod *param)
uint32_t n; uint32_t n;
float vols[MAX_CHANNELS]; float vols[MAX_CHANNELS];
if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
vols, SPA_AUDIO_MAX_CHANNELS)) > 0) { vols, SPA_N_ELEMENTS(vols))) > 0) {
s->volume.n_volumes = n; s->volume.n_volumes = n;
for (n = 0; n < s->volume.n_volumes; n++) for (n = 0; n < s->volume.n_volumes; n++)
s->volume.volumes[n] = vols[n]; s->volume.volumes[n] = vols[n];
@ -1026,14 +1026,16 @@ static int handle_follower_available(struct impl *impl, struct nj2_session_param
follower->source.n_ports = peer->params.recv_audio_channels + peer->params.recv_midi_channels; follower->source.n_ports = peer->params.recv_audio_channels + peer->params.recv_midi_channels;
follower->source.info.rate = peer->params.sample_rate; follower->source.info.rate = peer->params.sample_rate;
if ((uint32_t)peer->params.recv_audio_channels != follower->source.info.channels) { if ((uint32_t)peer->params.recv_audio_channels != follower->source.info.channels) {
follower->source.info.channels = SPA_MIN(peer->params.recv_audio_channels, (int)SPA_AUDIO_MAX_CHANNELS); follower->source.info.channels = SPA_MIN(peer->params.recv_audio_channels,
(int)SPA_N_ELEMENTS(follower->source.info.position));
for (i = 0; i < follower->source.info.channels; i++) for (i = 0; i < follower->source.info.channels; i++)
follower->source.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i; follower->source.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
} }
follower->sink.n_ports = peer->params.send_audio_channels + peer->params.send_midi_channels; follower->sink.n_ports = peer->params.send_audio_channels + peer->params.send_midi_channels;
follower->sink.info.rate = peer->params.sample_rate; follower->sink.info.rate = peer->params.sample_rate;
if ((uint32_t)peer->params.send_audio_channels != follower->sink.info.channels) { if ((uint32_t)peer->params.send_audio_channels != follower->sink.info.channels) {
follower->sink.info.channels = SPA_MIN(peer->params.send_audio_channels, (int)SPA_AUDIO_MAX_CHANNELS); follower->sink.info.channels = SPA_MIN(peer->params.send_audio_channels,
(int)SPA_N_ELEMENTS(follower->sink.info.position));
for (i = 0; i < follower->sink.info.channels; i++) for (i = 0; i < follower->sink.info.channels; i++)
follower->sink.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i; follower->sink.info.position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
} }

View file

@ -451,7 +451,8 @@ void channel_map_parse(const char *str, struct channel_map *map)
void channel_map_parse_position(const char *str, struct channel_map *map) void channel_map_parse_position(const char *str, struct channel_map *map)
{ {
uint32_t channels = 0, position[SPA_AUDIO_MAX_CHANNELS]; uint32_t channels = 0, position[SPA_AUDIO_MAX_CHANNELS];
spa_audio_parse_position(str, strlen(str), position, &channels); spa_audio_parse_position_n(str, strlen(str), position,
SPA_N_ELEMENTS(position), &channels);
positions_to_channel_map(position, channels, map); positions_to_channel_map(position, channels, map);
} }
@ -535,7 +536,7 @@ int format_parse_param(const struct spa_pod *param, bool collect,
if (info.info.raw.format == 0 || if (info.info.raw.format == 0 ||
info.info.raw.rate == 0 || info.info.raw.rate == 0 ||
info.info.raw.channels == 0 || info.info.raw.channels == 0 ||
info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) info.info.raw.channels > SPA_N_ELEMENTS(info.info.raw.position))
return -ENOTSUP; return -ENOTSUP;
} }
break; break;

View file

@ -53,7 +53,7 @@ int volume_parse_param(const struct spa_pod *param, struct volume_info *info, bo
if (monitor) if (monitor)
continue; continue;
info->volume.channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, info->volume.channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
info->volume.values, CHANNELS_MAX); info->volume.values, SPA_N_ELEMENTS(info->volume.values));
SPA_FLAG_UPDATE(info->flags, VOLUME_HW_VOLUME, SPA_FLAG_UPDATE(info->flags, VOLUME_HW_VOLUME,
prop->flags & SPA_POD_PROP_FLAG_HARDWARE); prop->flags & SPA_POD_PROP_FLAG_HARDWARE);
break; break;
@ -68,7 +68,7 @@ int volume_parse_param(const struct spa_pod *param, struct volume_info *info, bo
if (!monitor) if (!monitor)
continue; continue;
info->volume.channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, info->volume.channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
info->volume.values, CHANNELS_MAX); info->volume.values, SPA_N_ELEMENTS(info->volume.values));
SPA_FLAG_CLEAR(info->flags, VOLUME_HW_VOLUME); SPA_FLAG_CLEAR(info->flags, VOLUME_HW_VOLUME);
break; break;
case SPA_PROP_volumeBase: case SPA_PROP_volumeBase:
@ -84,7 +84,7 @@ int volume_parse_param(const struct spa_pod *param, struct volume_info *info, bo
} }
case SPA_PROP_channelMap: case SPA_PROP_channelMap:
info->map.channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Id, info->map.channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Id,
info->map.map, CHANNELS_MAX); info->map.map, SPA_N_ELEMENTS(info->map.map));
break; break;
default: default:
break; break;

View file

@ -300,7 +300,7 @@ static void stream_param_changed(void *d, uint32_t id, const struct spa_pod *par
float vols[MAX_CHANNELS]; float vols[MAX_CHANNELS];
if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
vols, SPA_AUDIO_MAX_CHANNELS)) > 0) { vols, SPA_N_ELEMENTS(vols))) > 0) {
volume.channels = SPA_MIN(PA_CHANNELS_MAX, n); volume.channels = SPA_MIN(PA_CHANNELS_MAX, n);
for (n = 0; n < volume.channels; n++) for (n = 0; n < volume.channels; n++)
volume.values[n] = pa_sw_volume_from_linear(vols[n]); volume.values[n] = pa_sw_volume_from_linear(vols[n]);

View file

@ -1617,7 +1617,7 @@ static void stream_props_changed(struct impl *impl, uint32_t id, const struct sp
float soft_vols[MAX_CHANNELS]; float soft_vols[MAX_CHANNELS];
if ((n_vols = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, if ((n_vols = spa_pod_copy_array(&prop->value, SPA_TYPE_Float,
vols, SPA_AUDIO_MAX_CHANNELS)) > 0) { vols, SPA_N_ELEMENTS(vols))) > 0) {
volume = 0.0f; volume = 0.0f;
for (i = 0; i < n_vols; i++) { for (i = 0; i < n_vols; i++) {
volume += vols[i]; volume += vols[i];

View file

@ -704,7 +704,8 @@ static int parse_channelmap(const char *channel_map, struct channelmap *map)
} }
} }
spa_audio_parse_position(channel_map, strlen(channel_map), map->channels, &map->n_channels); spa_audio_parse_position_n(channel_map, strlen(channel_map),
map->channels, SPA_N_ELEMENTS(map->channels), &map->n_channels);
return 0; return 0;
} }