json: add helper function to parse channel positions

Use the helper instead of duplicating the same code.

Also add some helpers to parse a json array of uint32_t

Move some functions to convert between type name and id.
This commit is contained in:
Wim Taymans 2024-09-18 09:54:34 +02:00
parent 911a601b95
commit e2991f6398
34 changed files with 256 additions and 791 deletions

View file

@ -33,6 +33,14 @@ static const struct spa_type_info spa_type_audio_iec958_codec[] = {
{ 0, 0, NULL, NULL },
};
static inline uint32_t spa_type_audio_iec958_codec_from_short_name(const char *name)
{
return spa_type_from_short_name(name, spa_type_audio_iec958_codec, SPA_AUDIO_IEC958_CODEC_UNKNOWN);
}
static inline const char * spa_type_audio_iec958_codec_to_short_name(uint32_t type)
{
return spa_type_to_short_name(type, spa_type_audio_iec958_codec, "UNKNOWN");
}
/**
* \}
*/

View file

@ -0,0 +1,47 @@
/* Simple Plugin API */
/* SPDX-FileCopyrightText: Copyright © 2024 Wim Taymans */
/* SPDX-License-Identifier: MIT */
#ifndef SPA_AUDIO_RAW_JSON_H
#define SPA_AUDIO_RAW_JSON_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup spa_param
* \{
*/
#include <spa/utils/json.h>
#include <spa/param/audio/raw-types.h>
static inline int
spa_audio_parse_position(const char *str, size_t len,
uint32_t *position, uint32_t *n_channels)
{
struct spa_json iter;
char v[256];
uint32_t channels = 0;
if (spa_json_begin_array_relax(&iter, str, len) <= 0)
return 0;
while (spa_json_get_string(&iter, v, sizeof(v)) > 0 &&
channels < SPA_AUDIO_MAX_CHANNELS) {
position[channels++] = spa_type_audio_channel_from_short_name(v);
}
*n_channels = channels;
return channels;
}
/**
* \}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* SPA_AUDIO_RAW_JSON_H */

View file

@ -129,6 +129,15 @@ static const struct spa_type_info spa_type_audio_format[] = {
{ 0, 0, NULL, NULL },
};
static inline uint32_t spa_type_audio_format_from_short_name(const char *name)
{
return spa_type_from_short_name(name, spa_type_audio_format, SPA_AUDIO_FORMAT_UNKNOWN);
}
static inline const char * spa_type_audio_format_to_short_name(uint32_t type)
{
return spa_type_to_short_name(type, spa_type_audio_format, "UNKNOWN");
}
#define SPA_TYPE_INFO_AudioFlags SPA_TYPE_INFO_FLAGS_BASE "AudioFlags"
#define SPA_TYPE_INFO_AUDIO_FLAGS_BASE SPA_TYPE_INFO_AudioFlags ":"
@ -250,12 +259,11 @@ static const struct spa_type_info spa_type_audio_channel[] = {
static inline uint32_t spa_type_audio_channel_from_short_name(const char *name)
{
int i;
for (i = 0; spa_type_audio_channel[i].name; i++) {
if (spa_streq(name, spa_type_short_name(spa_type_audio_channel[i].name)))
return spa_type_audio_channel[i].type;
}
return SPA_AUDIO_CHANNEL_UNKNOWN;
return spa_type_from_short_name(name, spa_type_audio_channel, SPA_AUDIO_CHANNEL_UNKNOWN);
}
static inline const char * spa_type_audio_channel_to_short_name(uint32_t type)
{
return spa_type_to_short_name(type, spa_type_audio_channel, "UNK");
}

View file

@ -20,7 +20,8 @@ extern "C" {
#define SPA_TYPE_INFO_VIDEO_FORMAT_BASE SPA_TYPE_INFO_VideoFormat ":"
static const struct spa_type_info spa_type_video_format[] = {
{ SPA_VIDEO_FORMAT_ENCODED, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "encoded", NULL },
{ SPA_VIDEO_FORMAT_UNKNOWN, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "UNKNOWN", NULL },
{ SPA_VIDEO_FORMAT_ENCODED, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "ENCODED", NULL },
{ SPA_VIDEO_FORMAT_I420, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I420", NULL },
{ SPA_VIDEO_FORMAT_YV12, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YV12", NULL },
{ SPA_VIDEO_FORMAT_YUY2, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YUY2", NULL },
@ -110,6 +111,15 @@ static const struct spa_type_info spa_type_video_format[] = {
{ 0, 0, NULL, NULL },
};
static inline uint32_t spa_type_video_format_from_short_name(const char *name)
{
return spa_type_from_short_name(name, spa_type_video_format, SPA_VIDEO_FORMAT_UNKNOWN);
}
static inline const char * spa_type_video_format_to_short_name(uint32_t type)
{
return spa_type_to_short_name(type, spa_type_video_format, "UNKNOWN");
}
#define SPA_TYPE_INFO_VideoFlags SPA_TYPE_INFO_FLAGS_BASE "VideoFlags"
#define SPA_TYPE_INFO_VIDEO_FLAGS_BASE SPA_TYPE_INFO_VideoFlags ":"

View file

@ -185,6 +185,24 @@ static inline int spa_json_begin_array(struct spa_json * iter, const char *data,
return spa_json_begin_container(iter, data, size, '[', false);
}
#define spa_json_make_str_array_unpack(maxlen,type,conv) \
{ \
struct spa_json iter; \
char v[maxlen]; \
uint32_t count = 0; \
if (spa_json_begin_array_relax(&iter, arr, arr_len) <= 0) \
return -EINVAL; \
while (spa_json_get_string(&iter, v, sizeof(v)) > 0 && count < max) \
values[count++] = conv(v); \
return count; \
}
static inline int spa_json_str_array_uint32(const char *arr, size_t arr_len,
uint32_t *values, size_t max)
{
spa_json_make_str_array_unpack(32,uint32_t, atoi);
}
/**
* \}
*/

View file

@ -10,6 +10,7 @@ extern "C" {
#endif
#include <spa/utils/defs.h>
#include <spa/utils/string.h>
/** \defgroup spa_types Types
* Data type information enumerations
@ -136,6 +137,34 @@ static inline const char *spa_type_short_name(const char *name)
return name;
}
static inline uint32_t spa_type_from_short_name(const char *name,
const struct spa_type_info *info, uint32_t unknown)
{
int i;
for (i = 0; info[i].name; i++) {
if (spa_streq(name, spa_type_short_name(info[i].name)))
return info[i].type;
}
return unknown;
}
static inline const char * spa_type_to_name(uint32_t type,
const struct spa_type_info *info, const char *unknown)
{
int i;
for (i = 0; info[i].name; i++) {
if (info[i].type == type)
return info[i].name;
}
return unknown;
}
static inline const char * spa_type_to_short_name(uint32_t type,
const struct spa_type_info *info, const char *unknown)
{
const char *n = spa_type_to_name(type, info, unknown);
return n ? spa_type_short_name(n) : NULL;
}
/**
* \}
*/

View file

@ -159,7 +159,7 @@ static int alsa_set_param(struct state *state, const char *k, const char *s)
state->default_rate = atoi(s);
fmt_change++;
} else if (spa_streq(k, SPA_KEY_AUDIO_FORMAT)) {
state->default_format = spa_alsa_format_from_name(s, strlen(s));
state->default_format = spa_type_audio_format_from_short_name(s);
fmt_change++;
} else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) {
spa_alsa_parse_position(&state->default_pos, s, strlen(s));
@ -2041,7 +2041,7 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
unsigned aes3;
spa_log_info(state->log, "using IEC958 Codec:%s rate:%d",
spa_debug_type_find_short_name(spa_type_audio_iec958_codec, f->codec),
spa_type_audio_iec958_codec_to_short_name(f->codec),
f->rate);
rformat = SND_PCM_FORMAT_S16_LE;

View file

@ -30,6 +30,7 @@ extern "C" {
#include <spa/param/param.h>
#include <spa/param/latency-utils.h>
#include <spa/param/audio/format-utils.h>
#include <spa/param/audio/raw-json.h>
#include <spa/param/tag-utils.h>
#include "alsa.h"
@ -303,64 +304,19 @@ void spa_alsa_recycle_buffer(struct state *state, uint32_t buffer_id);
void spa_alsa_emit_node_info(struct state *state, bool full);
void spa_alsa_emit_port_info(struct state *state, bool full);
static inline uint32_t spa_alsa_format_from_name(const char *name, size_t len)
{
int i;
for (i = 0; spa_type_audio_format[i].name; i++) {
if (strncmp(name, spa_debug_type_short_name(spa_type_audio_format[i].name), len) == 0)
return spa_type_audio_format[i].type;
}
return SPA_AUDIO_FORMAT_UNKNOWN;
}
static inline uint32_t spa_alsa_channel_from_name(const char *name)
{
int i;
for (i = 0; spa_type_audio_channel[i].name; i++) {
if (strcmp(name, spa_debug_type_short_name(spa_type_audio_channel[i].name)) == 0)
return spa_type_audio_channel[i].type;
}
return SPA_AUDIO_CHANNEL_UNKNOWN;
}
static inline void spa_alsa_parse_position(struct channel_map *map, const char *val, size_t len)
{
struct spa_json it[1];
char v[256];
if (spa_json_begin_array_relax(&it[0], val, len) <= 0)
return;
map->channels = 0;
while (spa_json_get_string(&it[0], v, sizeof(v)) > 0 &&
map->channels < SPA_AUDIO_MAX_CHANNELS) {
map->pos[map->channels++] = spa_alsa_channel_from_name(v);
}
spa_audio_parse_position(val, len, map->pos, &map->channels);
}
static inline uint32_t spa_alsa_parse_rates(uint32_t *rates, uint32_t max, const char *val, size_t len)
{
struct spa_json it[1];
char v[256];
uint32_t count;
if (spa_json_begin_array_relax(&it[0], val, len) <= 0)
return 0;
count = 0;
while (spa_json_get_string(&it[0], v, sizeof(v)) > 0 && count < max)
rates[count++] = atoi(v);
return count;
return spa_json_str_array_uint32(val, len, rates, max);
}
static inline uint32_t spa_alsa_iec958_codec_from_name(const char *name)
{
int i;
for (i = 0; spa_type_audio_iec958_codec[i].name; i++) {
if (strcmp(name, spa_debug_type_short_name(spa_type_audio_iec958_codec[i].name)) == 0)
return spa_type_audio_iec958_codec[i].type;
}
return SPA_AUDIO_IEC958_CODEC_UNKNOWN;
return spa_type_audio_iec958_codec_from_short_name(name);
}
static inline void spa_alsa_parse_iec958_codecs(uint64_t *codecs, const char *val, size_t len)

View file

@ -22,6 +22,7 @@
#include <spa/node/utils.h>
#include <spa/node/keys.h>
#include <spa/param/audio/format-utils.h>
#include <spa/param/audio/raw-json.h>
#include <spa/param/param.h>
#include <spa/param/latency-utils.h>
#include <spa/param/tag-utils.h>
@ -3413,33 +3414,6 @@ impl_get_size(const struct spa_handle_factory *factory,
return sizeof(struct impl);
}
static uint32_t channel_from_name(const char *name)
{
int i;
for (i = 0; spa_type_audio_channel[i].name; i++) {
if (spa_streq(name, spa_debug_type_short_name(spa_type_audio_channel[i].name)))
return spa_type_audio_channel[i].type;
}
return SPA_AUDIO_CHANNEL_UNKNOWN;
}
static inline uint32_t parse_position(uint32_t *pos, const char *val, size_t len)
{
struct spa_json it[1];
char v[256];
uint32_t i = 0;
if (spa_json_begin_array_relax(&it[0], val, len) <= 0)
return 0;
while (spa_json_get_string(&it[0], v, sizeof(v)) > 0 &&
i < SPA_AUDIO_MAX_CHANNELS) {
pos[i++] = channel_from_name(v);
}
return i;
}
static int
impl_init(const struct spa_handle_factory *factory,
struct spa_handle *handle,
@ -3492,7 +3466,8 @@ impl_init(const struct spa_handle_factory *factory,
RESAMPLE_OPTION_PREFILL, spa_atob(s));
else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) {
if (s != NULL)
this->props.n_channels = parse_position(this->props.channel_map, s, strlen(s));
spa_audio_parse_position(s, strlen(s), this->props.channel_map,
&this->props.n_channels);
}
else if (spa_streq(k, SPA_KEY_PORT_IGNORE_LATENCY))
this->port_ignore_latency = spa_atob(s);

View file

@ -37,10 +37,11 @@ static int avb_set_param(struct state *state, const char *k, const char *s)
state->default_rate = atoi(s);
fmt_change++;
} else if (spa_streq(k, SPA_KEY_AUDIO_FORMAT)) {
state->default_format = spa_avb_format_from_name(s, strlen(s));
state->default_format = spa_type_audio_format_from_short_name(s);
fmt_change++;
} else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) {
spa_avb_parse_position(&state->default_pos, s, strlen(s));
spa_audio_parse_position(s, strlen(s), state->default_pos.pos,
&state->default_pos.channels);
fmt_change++;
} else if (spa_streq(k, SPA_KEY_AUDIO_ALLOWED_RATES)) {
state->n_allowed_rates = spa_avb_parse_rates(state->allowed_rates,

View file

@ -33,6 +33,7 @@ extern "C" {
#include <spa/param/param.h>
#include <spa/param/latency-utils.h>
#include <spa/param/audio/format-utils.h>
#include <spa/param/audio/raw-json.h>
#include "avb.h"
@ -264,41 +265,6 @@ int spa_avb_skip(struct state *state);
void spa_avb_recycle_buffer(struct state *state, struct port *port, uint32_t buffer_id);
static inline uint32_t spa_avb_format_from_name(const char *name, size_t len)
{
int i;
for (i = 0; spa_type_audio_format[i].name; i++) {
if (strncmp(name, spa_debug_type_short_name(spa_type_audio_format[i].name), len) == 0)
return spa_type_audio_format[i].type;
}
return SPA_AUDIO_FORMAT_UNKNOWN;
}
static inline uint32_t spa_avb_channel_from_name(const char *name)
{
int i;
for (i = 0; spa_type_audio_channel[i].name; i++) {
if (strcmp(name, spa_debug_type_short_name(spa_type_audio_channel[i].name)) == 0)
return spa_type_audio_channel[i].type;
}
return SPA_AUDIO_CHANNEL_UNKNOWN;
}
static inline void spa_avb_parse_position(struct channel_map *map, const char *val, size_t len)
{
struct spa_json it[1];
char v[256];
if (spa_json_begin_array_relax(&it[0], val, len) <= 0)
return;
map->channels = 0;
while (spa_json_get_string(&it[0], v, sizeof(v)) > 0 &&
map->channels < SPA_AUDIO_MAX_CHANNELS) {
map->pos[map->channels++] = spa_avb_channel_from_name(v);
}
}
static inline uint32_t spa_avb_parse_rates(uint32_t *rates, uint32_t max, const char *val, size_t len)
{
struct spa_json it[1];

View file

@ -502,12 +502,7 @@ static void get_channels(struct spa_bt_transport *t, bool a2dp_duplex, uint32_t
static const char *get_channel_name(uint32_t channel)
{
int i;
for (i = 0; spa_type_audio_channel[i].name; i++) {
if (spa_type_audio_channel[i].type == channel)
return spa_debug_type_short_name(spa_type_audio_channel[i].name);
}
return NULL;
return spa_type_to_short_name(channel, spa_type_audio_channel, NULL);
}
static int channel_position_cmp(const void *pa, const void *pb)

View file

@ -22,6 +22,7 @@
#include <spa/node/io.h>
#include <spa/node/keys.h>
#include <spa/param/audio/format-utils.h>
#include <spa/param/audio/raw-json.h>
#include <spa/debug/types.h>
#include <spa/debug/mem.h>
#include <spa/param/audio/type-info.h>
@ -859,41 +860,6 @@ impl_get_size(const struct spa_handle_factory *factory,
return sizeof(struct impl);
}
static uint32_t format_from_name(const char *name)
{
int i;
for (i = 0; spa_type_audio_format[i].name; i++) {
if (spa_streq(name, spa_debug_type_short_name(spa_type_audio_format[i].name)))
return spa_type_audio_format[i].type;
}
return SPA_AUDIO_FORMAT_UNKNOWN;
}
static uint32_t channel_from_name(const char *name)
{
int i;
for (i = 0; spa_type_audio_channel[i].name; i++) {
if (spa_streq(name, spa_debug_type_short_name(spa_type_audio_channel[i].name)))
return spa_type_audio_channel[i].type;
}
return SPA_AUDIO_CHANNEL_UNKNOWN;
}
static inline void parse_position(struct impl *this, const char *val, size_t len)
{
struct spa_json it[1];
char v[256];
if (spa_json_begin_array_relax(&it[0], val, len) <= 0)
return;
this->props.channels = 0;
while (spa_json_get_string(&it[0], v, sizeof(v)) > 0 &&
this->props.channels < SPA_AUDIO_MAX_CHANNELS) {
this->props.pos[this->props.channels++] = channel_from_name(v);
}
}
static int
impl_init(const struct spa_handle_factory *factory,
struct spa_handle *handle,
@ -975,7 +941,7 @@ impl_init(const struct spa_handle_factory *factory,
if (spa_streq(k, "clock.quantum-limit")) {
spa_atou32(s, &this->quantum_limit, 0);
} else if (spa_streq(k, SPA_KEY_AUDIO_FORMAT)) {
this->props.format = format_from_name(s);
this->props.format = spa_type_audio_format_from_short_name(s);
} else if (spa_streq(k, SPA_KEY_AUDIO_CHANNELS)) {
this->props.channels = atoi(s);
} else if (spa_streq(k, SPA_KEY_AUDIO_RATE)) {
@ -983,7 +949,7 @@ impl_init(const struct spa_handle_factory *factory,
} else if (spa_streq(k, SPA_KEY_NODE_DRIVER)) {
this->props.driver = spa_atob(s);
} else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) {
parse_position(this, s, strlen(s));
spa_audio_parse_position(s, strlen(s), this->props.pos, &this->props.channels);
} else if (spa_streq(k, "clock.name")) {
spa_scnprintf(this->props.clock_name,
sizeof(this->props.clock_name),