Add new pod parser and builder

Add a new pod builder and parser that is less verbose and
a little more powerful.
This commit is contained in:
Wim Taymans 2017-09-21 18:57:41 +02:00
parent 3e49aec61b
commit 24d80e5c00
54 changed files with 3616 additions and 2817 deletions

View file

@ -50,18 +50,19 @@ spa_type_format_audio_map(struct spa_type_map *map, struct spa_type_format_audio
}
}
static inline bool
static inline int
spa_format_audio_raw_parse(const struct spa_format *format,
struct spa_audio_info_raw *info, struct spa_type_format_audio *type)
{
spa_format_query(format,
type->format, SPA_POD_TYPE_ID, &info->format,
type->flags, SPA_POD_TYPE_INT, &info->flags,
type->layout, SPA_POD_TYPE_INT, &info->layout,
type->rate, SPA_POD_TYPE_INT, &info->rate,
type->channels, SPA_POD_TYPE_INT, &info->channels,
type->channel_mask, SPA_POD_TYPE_INT, &info->channel_mask, 0);
return true;
struct spa_pod_parser prs;
spa_pod_parser_pod(&prs, &format->pod);
return spa_pod_parser_get(&prs,
":",type->format, "I", &info->format,
":",type->rate, "i", &info->rate,
":",type->channels, "i", &info->channels,
":",type->flags, "?i", &info->flags,
":",type->layout, "?i", &info->layout,
":",type->channel_mask, "?i", &info->channel_mask, NULL);
}
#ifdef __cplusplus

View file

@ -71,6 +71,7 @@ enum spa_result {
SPA_RESULT_OUT_OF_BUFFERS = -35,
SPA_RESULT_INCOMPATIBLE_PROPS = -36,
SPA_RESULT_INCOMPATIBLE_VERSION = -37,
SPA_RESULT_NOT_FOUND = -38,
};
#define SPA_ASYNC_BIT (1 << 30)
@ -89,11 +90,14 @@ enum spa_direction {
SPA_DIRECTION_OUTPUT = 1,
};
#define SPA_RECTANGLE(width,height) (struct spa_rectangle){ width, height }
struct spa_rectangle {
uint32_t width;
uint32_t height;
};
#define SPA_FRACTION(num,denom) (struct spa_fraction){ num, denom }
struct spa_fraction {
uint32_t num;
uint32_t denom;

View file

@ -48,11 +48,11 @@ spa_pod_builder_push_format(struct spa_pod_builder *builder,
spa_pod_builder_raw(builder, &p, sizeof(p)));
}
#define spa_pod_builder_format(b,f,format_type,media_type,media_subtype,...) \
spa_pod_builder_object(b, f, 0, format_type, \
SPA_POD_TYPE_ID,media_type, \
SPA_POD_TYPE_ID,media_subtype, \
## __VA_ARGS__)
#define spa_pod_builder_format(b,format_type,media_type,media_subtype,...) \
spa_pod_builder_object(b, 0, format_type, \
"I",media_type, \
"I",media_subtype, \
##__VA_ARGS__)
#ifdef __cplusplus
} /* extern "C" */

View file

@ -27,7 +27,7 @@ extern "C" {
#include <stdarg.h>
#include <spa/format.h>
#include <spa/pod-utils.h>
#include <spa/pod-parser.h>
#include <spa/type-map.h>
struct spa_type_media_type {
@ -149,22 +149,17 @@ spa_type_media_subtype_audio_map(struct spa_type_map *map,
#define SPA_FORMAT_MEDIA_TYPE(f) SPA_POD_VALUE(struct spa_pod_id, &f->body.media_type)
#define SPA_FORMAT_MEDIA_SUBTYPE(f) SPA_POD_VALUE(struct spa_pod_id, &f->body.media_subtype)
static inline struct spa_pod_prop *spa_format_find_prop(const struct spa_format *format,
uint32_t key)
#define spa_format_parse(format,...) \
({ \
struct spa_pod_parser __p; \
const struct spa_format *__format = format; \
spa_pod_parser_pod(&__p, &__format->pod); \
spa_pod_parser_get(&__p, "<", ##__VA_ARGS__, NULL); \
})
static inline struct spa_pod_prop *spa_format_find_prop(const struct spa_format *format, uint32_t key)
{
return spa_pod_contents_find_prop(&format->pod, sizeof(struct spa_format), key);
}
static inline uint32_t spa_format_query(const struct spa_format *format, uint32_t key, ...)
{
uint32_t count;
va_list args;
va_start(args, key);
count = spa_pod_contents_queryv(&format->pod, sizeof(struct spa_format), key, args);
va_end(args);
return count;
return spa_pod_contents_find_prop(&format->pod, sizeof(struct spa_format), key);
}
static inline int spa_format_fixate(struct spa_format *format)

View file

@ -91,7 +91,7 @@ static inline void spa_hook_remove(struct spa_hook *hook)
break; \
} \
} \
});
})
#define spa_hook_list_call(l,t,m,...) spa_hook_list_do_call(l,NULL,t,m,false,##__VA_ARGS__)
#define spa_hook_list_call_once(l,t,m,...) spa_hook_list_do_call(l,NULL,t,m,true,##__VA_ARGS__)

View file

@ -0,0 +1,67 @@
/* Spa
* Copyright (C) 2017 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __SPA_JSON_BUILDER_H__
#define __SPA_JSON_BUILDER_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#include <spa/defs.h>
struct spa_json_builder {
char *data;
int size;
int offset;
int (*printf) (void *user_data, const char *format, va_list args);
void *user_data;
};
static inline int spa_json_builder_printf(struct spa_json_builder *builder,
const char *format, ...)
{
va_list args;
int res;
va_start(args, format);
if (builder->printf)
res = builder->printf(builder->user_data, format, args);
else {
int size = builder->size;
int offset = builder->offset;
int remain = SPA_MAX(0, size - offset);
res = vsnprintf(&builder->data[offset], remain, format, args);
builder->offset += res;
if (builder->offset > size)
res = -1;
}
va_end(args);
return res;
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __SPA_JSON_BUILDER_H__ */

510
spa/include/spa/json.h Normal file
View file

@ -0,0 +1,510 @@
/* Spa
* Copyright (C) 2017 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __SPA_JSON_H__
#define __SPA_JSON_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#include <spa/defs.h>
struct spa_json_iter {
const char *start;
const char *cur;
const char *end;
int state;
int depth;
};
struct spa_json_chunk {
const char *value;
int len;
};
static inline int
spa_json_chunk_extract(struct spa_json_chunk *chunk, const char *template, ...);
enum spa_json_type {
SPA_JSON_TYPE_ANY = '-',
SPA_JSON_TYPE_CHUNK = 'c',
SPA_JSON_TYPE_INT = 'i',
SPA_JSON_TYPE_LONG = 'l',
SPA_JSON_TYPE_FLOAT = 'f',
SPA_JSON_TYPE_DOUBLE = 'd',
SPA_JSON_TYPE_STRING = 's',
SPA_JSON_TYPE_BOOL = 'b',
SPA_JSON_TYPE_RECTANGLE = 'R',
SPA_JSON_TYPE_FRACTION = 'F',
SPA_JSON_TYPE_OBJECT = 'o',
SPA_JSON_TYPE_ARRAY = 'a'
};
static inline bool spa_json_chunk_is_type(struct spa_json_chunk *chunk,
enum spa_json_type type)
{
switch (type) {
case SPA_JSON_TYPE_ANY:
case SPA_JSON_TYPE_CHUNK:
return true;
case SPA_JSON_TYPE_INT:
case SPA_JSON_TYPE_LONG:
case SPA_JSON_TYPE_FLOAT:
case SPA_JSON_TYPE_DOUBLE:
return (chunk->value[0] >= '0' && chunk->value[0] <= '9') ||
chunk->value[0] == '-' ;
case SPA_JSON_TYPE_STRING:
return chunk->value[0] == '\"';
case SPA_JSON_TYPE_BOOL:
return chunk->value[0] == 't' || chunk->value[0] == 'f';
case SPA_JSON_TYPE_RECTANGLE:
case SPA_JSON_TYPE_FRACTION:
case SPA_JSON_TYPE_ARRAY:
return chunk->value[0] == '[';
case SPA_JSON_TYPE_OBJECT:
return chunk->value[0] == '{';
}
return false;
}
static inline int spa_json_chunk_to_int(struct spa_json_chunk *chunk) {
return atoi(chunk->value);
}
static inline int64_t spa_json_chunk_to_long(struct spa_json_chunk *chunk) {
return atol(chunk->value);
}
static inline int64_t spa_json_chunk_to_float(struct spa_json_chunk *chunk) {
return strtof(chunk->value, NULL);
}
static inline int64_t spa_json_chunk_to_double(struct spa_json_chunk *chunk) {
return strtod(chunk->value, NULL);
}
static inline bool spa_json_chunk_to_bool(struct spa_json_chunk *chunk) {
return chunk->value[0] == 't';
}
static inline int spa_json_chunk_to_rectangle(struct spa_json_chunk *chunk,
struct spa_rectangle *rect) {
return spa_json_chunk_extract(chunk, "[ #pi, #pi ]", &rect->width, &rect->height);
}
static inline int spa_json_chunk_to_fraction(struct spa_json_chunk *chunk,
struct spa_fraction *frac) {
return spa_json_chunk_extract(chunk, "[ #pi, #pi ]", &frac->num, &frac->denom);
}
static inline void
spa_json_iter_init (struct spa_json_iter *iter, const char *data, size_t size)
{
iter->start = iter->cur = data;
iter->end = size == -1 ? NULL : data + size;
iter->state = 0;
iter->depth = 0;
}
static inline bool
spa_json_iter_chunk(struct spa_json_iter *iter, struct spa_json_chunk *chunk)
{
if (!spa_json_chunk_is_type(chunk, SPA_JSON_TYPE_OBJECT) &&
!spa_json_chunk_is_type(chunk, SPA_JSON_TYPE_ARRAY))
return false;
spa_json_iter_init (iter, chunk->value, -1);
iter->cur++;
return true;
}
static inline int
spa_json_iter_next_chunk(struct spa_json_iter *iter, struct spa_json_chunk *chunk)
{
int utf8_remain = 0;
for (;iter->end == NULL || iter->cur < iter->end; iter->cur++) {
unsigned char cur = (unsigned char) *iter->cur;
again:
switch (iter->state) {
case 0: /* scanning for objects */
switch (cur) {
case '\t': case ' ': case '\r': case '\n': case ':': case ',':
continue;
case '"':
chunk->value = iter->cur;
iter->state = 2;
continue;
case '[': case '{':
chunk->value = iter->cur;
if (++iter->depth > 1)
continue;
iter->cur++;
return chunk->len = 1;
case '}': case ']':
if (iter->depth == 0)
return 0;
--iter->depth;
continue;
case '-': case 'a' ... 'z': case 'A' ... 'Z': case '0' ... '9': case '#':
chunk->value = iter->cur;
iter->state = 1;
continue;
case '\0':
return 0;
}
return -1;
case 1: /* token */
switch (cur) {
case '\t': case ' ': case '\r': case '\n': case ':': case ',':
case ']': case '}':
iter->state = 0;
if (iter->depth > 0)
goto again;
return chunk->len = iter->cur - chunk->value;
default:
if (cur >= 32 && cur <= 126)
continue;
}
return -1;
case 2: /* string */
switch (cur) {
case '\\':
iter->state = 4;
continue;
case '"':
iter->state = 0;
if (iter->depth > 0)
continue;
iter->cur++;
return chunk->len = iter->cur - chunk->value;
case 240 ... 247:
utf8_remain++;
case 224 ... 239:
utf8_remain++;
case 192 ... 223:
utf8_remain++;
iter->state = 3;
continue;
default:
if (cur >= 32 && cur <= 126)
continue;
}
return -1;
case 3: /* utf chars */
switch (cur) {
case 128 ... 191:
if (--utf8_remain == 0)
iter->state = 2;
continue;
}
return -1;
case 4: /* inside escape chars */
switch (cur) {
case '"': case '\\': case '/': case 'b': case 'f': case 'n': case 'r':
case 't': case 'u':
iter->state = 2;
continue;
}
return -1;
}
}
return iter->depth == 0 ? 0 : -1;
}
static inline void
spa_json_chunk_print(struct spa_json_chunk *chunk, int prefix)
{
struct spa_json_iter iter;
if (spa_json_iter_chunk(&iter, chunk)) {
struct spa_json_chunk chunk2 = { NULL, };
printf ("%-*s%c\n", prefix, "", chunk->value[0]);
while (spa_json_iter_next_chunk(&iter, &chunk2) > 0)
spa_json_chunk_print(&chunk2, prefix + 2);
printf ("%-*s%c\n", prefix, "", iter.cur[0]);
} else {
printf ("%-*s%.*s\n", prefix, "", chunk->len, chunk->value);
}
}
static inline int spa_json_iter_find_key(struct spa_json_iter *iter, const char *key)
{
struct spa_json_chunk ch = { NULL, };
int res;
iter->cur = iter->start + 1;
iter->depth = 0;
iter->state = 0;
while (true) {
/* read key */
if ((res = spa_json_iter_next_chunk(iter, &ch)) <= 0)
return res;
if (spa_json_chunk_is_type(&ch, SPA_JSON_TYPE_STRING) &&
strncmp(key, ch.value, ch.len) == 0)
return 1;
}
return 0;
}
enum spa_json_prop_range {
SPA_JSON_PROP_RANGE_NONE = '-',
SPA_JSON_PROP_RANGE_MIN_MAX = 'r',
SPA_JSON_PROP_RANGE_STEP = 's',
SPA_JSON_PROP_RANGE_ENUM = 'e',
SPA_JSON_PROP_RANGE_FLAGS = 'f'
};
enum spa_json_prop_flags {
SPA_JSON_PROP_FLAG_UNSET = (1 << 0),
SPA_JSON_PROP_FLAG_OPTIONAL = (1 << 1),
SPA_JSON_PROP_FLAG_READONLY = (1 << 2),
SPA_JSON_PROP_FLAG_DEPRECATED = (1 << 3),
};
struct spa_json_prop {
enum spa_json_type type;
enum spa_json_prop_range range;
enum spa_json_prop_flags flags;
struct spa_json_chunk value;
struct spa_json_chunk alternatives;
};
static inline int
spa_json_chunk_parse_prop(struct spa_json_chunk *chunk, char type,
struct spa_json_prop *prop)
{
if (spa_json_chunk_is_type(chunk, SPA_JSON_TYPE_ARRAY)) {
struct spa_json_chunk flags;
int res;
char ch;
/* [<flags>, <default>, [<alternatives>,...]] */
if ((res = spa_json_chunk_extract(chunk,
"[ #&cs, #&c-, #&ca ]",
&flags, &prop->value, &prop->alternatives)) < 3) {
printf("can't parse prop chunk %d\n", res);
return -1;
}
/* skip \" */
flags.value++;
prop->type = *flags.value++;
if (type != SPA_JSON_TYPE_ANY && type != SPA_JSON_TYPE_CHUNK && prop->type != type) {
printf("prop chunk of wrong type %d %d\n", prop->type, type);
return -1;
}
prop->range = *flags.value++;
/* flags */
prop->flags = 0;
while ((ch = *flags.value++) != '\"') {
switch (ch) {
case 'u':
prop->flags |= SPA_JSON_PROP_FLAG_UNSET;
break;
case 'o':
prop->flags |= SPA_JSON_PROP_FLAG_OPTIONAL;
break;
case 'r':
prop->flags |= SPA_JSON_PROP_FLAG_READONLY;
break;
case 'd':
prop->flags |= SPA_JSON_PROP_FLAG_DEPRECATED;
break;
}
}
}
else {
/* <value> */
prop->type = type;
prop->range = SPA_JSON_PROP_RANGE_NONE;
prop->flags = 0;
prop->value = *chunk;
prop->alternatives = *chunk;
}
return 0;
}
/**
* #[*]<asign>
*
* * = skip assignment
* <asign> is:
* &<type> -> pointer to type
* p<type> -> property, fixed value store in pointer to type
* P<type> -> property, stored in pointer to struct spa_json_prop
*
* <type>
* - -> any
* c<type> -> store as chunk if of type
* s -> string
* i -> int
* l -> long
* f -> float
* d -> double
* b -> bool
* R -> rectangle
* F -> fraction
* a -> array
* o -> object
*/
static inline int
spa_json_chunk_extract(struct spa_json_chunk *chunk,
const char *template, ...)
{
struct spa_json_iter templ[16], it[16];
struct spa_json_chunk tch = { NULL, }, ch = { NULL, };
struct spa_json_prop prop;
const char *match;
int collected = 0, res, level = 0;
va_list args;
bool store;
va_start(args, template);
spa_json_iter_init(&it[0], chunk->value, chunk->len);
spa_json_iter_init (&templ[0], template, -1);
while (true) {
res = spa_json_iter_next_chunk(&templ[level], &tch);
if (res == 0) {
if (--level == 0)
break;
continue;
} else if (res < 0) {
return res;
}
switch (tch.value[0]) {
case '[': case '{':
if (spa_json_iter_next_chunk(&it[level], &ch) <= 0 ||
ch.value[0] != tch.value[0])
return -1;
if (++level == 16)
return -2;
spa_json_iter_chunk(&it[level], &ch);
spa_json_iter_chunk(&templ[level], &tch);
break;
case '"':
case '-': case '0' ... '9':
case 't': case 'f':
case 'n':
if (templ[level].start[0] == '{') {
if (spa_json_iter_find_key(&it[level], tch.value) <= 0)
continue;
} else if (spa_json_iter_next_chunk(&it[level], &ch) <= 0 ||
ch.len != tch.len ||
strncmp(ch.value, tch.value, ch.len) != 0)
return -1;
break;
case '#':
match = tch.value + 1;
if (spa_json_iter_next_chunk(&it[level], &ch) <= 0)
return -1;
store = (match[0] != '*');
if (!store)
match++;
switch (match[0]) {
case 'p':
case 'P':
if (spa_json_chunk_parse_prop(&ch, match[1], &prop) < 0)
goto skip;
if (match[0] == 'P') {
if (store)
*va_arg(args, struct spa_json_prop *) = prop;
collected++;
break;
}
else {
if (prop.flags & SPA_JSON_PROP_FLAG_UNSET)
goto skip;
ch = prop.value;
}
/* fallthrough */
case '&':
if (!spa_json_chunk_is_type(&ch, match[1] == SPA_JSON_TYPE_CHUNK ?
match[2] : match[1])) {
skip:
if (store)
va_arg(args, void *);
break;
}
if (!store)
break;
collected++;
switch (match[1]) {
case SPA_JSON_TYPE_CHUNK:
*va_arg(args, struct spa_json_chunk *) = ch;
break;
case SPA_JSON_TYPE_INT:
*va_arg(args, int *) = spa_json_chunk_to_int(&ch);
break;
case SPA_JSON_TYPE_LONG:
*va_arg(args, int64_t *) = spa_json_chunk_to_long(&ch);
break;
case SPA_JSON_TYPE_FLOAT:
*va_arg(args, float *) = spa_json_chunk_to_float(&ch);
break;
case SPA_JSON_TYPE_DOUBLE:
*va_arg(args, double *) = spa_json_chunk_to_double(&ch);
break;
case SPA_JSON_TYPE_BOOL:
*va_arg(args, bool *) = spa_json_chunk_to_bool(&ch);
break;
case SPA_JSON_TYPE_RECTANGLE:
spa_json_chunk_to_rectangle(&ch,
va_arg(args, struct spa_rectangle *));
break;
case SPA_JSON_TYPE_FRACTION:
spa_json_chunk_to_fraction(&ch,
va_arg(args, struct spa_fraction *));
break;
default:
printf("ignoring invalid #p type %c\n", match[1]);
va_arg(args, void *);
collected--;
continue;
}
break;
default:
printf("ignoring unknown match type %c\n", *match);
break;
}
break;
default:
printf("invalid char %c\n", tch.value[0]);
return -2;
}
}
va_end(args);
return collected;
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __SPA_JSON_H__ */

View file

@ -35,18 +35,27 @@ struct spa_param {
struct spa_pod_object object;
};
static inline uint32_t spa_param_query(const struct spa_param *param, uint32_t key, ...)
static inline uint32_t
spa_pod_builder_push_param(struct spa_pod_builder *builder,
struct spa_pod_frame *frame,
uint32_t param_type)
{
uint32_t count;
va_list args;
va_start(args, key);
count = spa_pod_contents_queryv(&param->object.pod, sizeof(struct spa_param), key, args);
va_end(args);
return count;
return spa_pod_builder_push_object(builder, frame, 0, param_type);
}
#define spa_pod_builder_param(b,param_type,...) \
spa_pod_builder_object(b, 0, param_type, \
##__VA_ARGS__)
#define spa_param_parse(param,...) \
({ \
struct spa_pod_parser __p; \
const struct spa_param *__param = param; \
spa_pod_parser_pod(&__p, &__param->object.pod); \
spa_pod_parser_get(&__p, "<", ##__VA_ARGS__, NULL); \
})
#define SPA_PARAM_BODY_FOREACH(body, size, iter) \
for ((iter) = SPA_MEMBER((body), sizeof(struct spa_pod_object_body), struct spa_pod_prop); \
(iter) < SPA_MEMBER((body), (size), struct spa_pod_prop); \

View file

@ -27,6 +27,10 @@ extern "C" {
#include <stdarg.h>
#include <spa/pod-utils.h>
#ifndef SPA_POD_MAX_LEVEL
#define SPA_POD_MAX_LEVEL 16
#endif
struct spa_pod_frame {
struct spa_pod_frame *parent;
struct spa_pod pod;
@ -42,6 +46,8 @@ struct spa_pod_builder {
uint32_t size);
bool in_array;
bool first;
struct spa_pod_frame frame[SPA_POD_MAX_LEVEL];
int depth;
};
#define SPA_POD_BUILDER_INIT(buffer,size) { buffer, size, }
@ -54,6 +60,7 @@ static inline void spa_pod_builder_init(struct spa_pod_builder *builder, void *d
builder->size = size;
builder->offset = 0;
builder->stack = NULL;
builder->depth = 0;
}
static inline uint32_t
@ -144,6 +151,14 @@ spa_pod_builder_primitive(struct spa_pod_builder *builder, const struct spa_pod
return ref;
}
#define SPA_POD_NONE_INIT() { 0, SPA_POD_TYPE_NONE }
static inline uint32_t spa_pod_builder_none(struct spa_pod_builder *builder)
{
const struct spa_pod p = SPA_POD_NONE_INIT();
return spa_pod_builder_primitive(builder, &p);
}
#define SPA_POD_BOOL_INIT(val) { { sizeof(uint32_t), SPA_POD_TYPE_BOOL }, val ? 1 : 0 }
static inline uint32_t spa_pod_builder_bool(struct spa_pod_builder *builder, bool val)
@ -194,12 +209,24 @@ static inline uint32_t spa_pod_builder_double(struct spa_pod_builder *builder, d
#define SPA_POD_STRING_INIT(len) { { len, SPA_POD_TYPE_STRING } }
static inline uint32_t
spa_pod_builder_write_string(struct spa_pod_builder *builder, const char *str, uint32_t len)
{
uint32_t ref = 0;
if (spa_pod_builder_raw(builder, str, len) == -1)
ref = -1;
if (spa_pod_builder_raw(builder, "", 1) == -1)
ref = -1;
spa_pod_builder_pad(builder, builder->offset);
return ref;
}
static inline uint32_t
spa_pod_builder_string_len(struct spa_pod_builder *builder, const char *str, uint32_t len)
{
const struct spa_pod_string p = SPA_POD_STRING_INIT(len);
const struct spa_pod_string p = SPA_POD_STRING_INIT(len+1);
uint32_t ref = spa_pod_builder_raw(builder, &p, sizeof(p));
if (spa_pod_builder_raw_padded(builder, str, len) == -1)
if (spa_pod_builder_write_string(builder, str, len) == -1)
ref = -1;
return ref;
}
@ -207,7 +234,7 @@ spa_pod_builder_string_len(struct spa_pod_builder *builder, const char *str, uin
static inline uint32_t spa_pod_builder_string(struct spa_pod_builder *builder, const char *str)
{
uint32_t len = str ? strlen(str) : 0;
return spa_pod_builder_string_len(builder, str ? str : "", len + 1);
return spa_pod_builder_string_len(builder, str ? str : "", len);
}
#define SPA_POD_BYTES_INIT(len) { { len, SPA_POD_TYPE_BYTES } }
@ -231,6 +258,14 @@ spa_pod_builder_pointer(struct spa_pod_builder *builder, uint32_t type, void *va
return spa_pod_builder_primitive(builder, &p.pod);
}
#define SPA_POD_FD_INIT(fd) { { sizeof(int), SPA_POD_TYPE_FD }, fd }
static inline uint32_t spa_pod_builder_fd(struct spa_pod_builder *builder, int fd)
{
const struct spa_pod_fd p = SPA_POD_FD_INIT(fd);
return spa_pod_builder_primitive(builder, &p.pod);
}
#define SPA_POD_RECTANGLE_INIT(width,height) { { sizeof(struct spa_rectangle), SPA_POD_TYPE_RECTANGLE }, { width, height } }
static inline uint32_t
@ -311,238 +346,227 @@ spa_pod_builder_push_prop(struct spa_pod_builder *builder,
sizeof(p) - sizeof(struct spa_pod)));
}
static inline void
spa_pod_builder_addv(struct spa_pod_builder *builder, uint32_t type, va_list args)
static inline uint32_t spa_pod_range_from_id(char id)
{
uint32_t n_values = 0;
union {
struct spa_pod pod;
struct spa_pod_bool bool_pod;
struct spa_pod_id id_pod;
struct spa_pod_int int_pod;
struct spa_pod_long long_pod;
struct spa_pod_float float_pod;
struct spa_pod_double double_pod;
struct spa_pod_string string_pod;
struct spa_pod_bytes bytes_pod;
struct spa_pod_pointer pointer_pod;
struct spa_pod_rectangle rectangle_pod;
struct spa_pod_fraction fraction_pod;
struct spa_pod_array array_pod;
struct spa_pod_struct struct_pod;
struct spa_pod_object object_pod;
struct spa_pod_prop prop_pod;
} head;
uint32_t head_size;
const void *body;
uint32_t body_size;
static const uint64_t zeroes = 0;
while (type != SPA_POD_TYPE_INVALID) {
struct spa_pod_frame *f = NULL;
const void *data[3];
uint32_t size[3], ref, i, n_sizes = 0;
switch (type) {
case SPA_POD_TYPE_NONE:
break;
case SPA_POD_TYPE_BOOL:
case SPA_POD_TYPE_ID:
case SPA_POD_TYPE_INT:
head.int_pod.pod.type = type;
head.int_pod.pod.size = body_size = sizeof(uint32_t);
head.int_pod.value = va_arg(args, int);
head_size = sizeof(struct spa_pod);
body = &head.int_pod.value;
goto primitive;
case SPA_POD_TYPE_LONG:
head.long_pod.pod.type = SPA_POD_TYPE_LONG;
head.long_pod.pod.size = body_size = sizeof(uint32_t);
head.long_pod.value = va_arg(args, int64_t);
head_size = sizeof(struct spa_pod);
body = &head.long_pod.value;
goto primitive;
case SPA_POD_TYPE_FLOAT:
head.float_pod.pod.type = SPA_POD_TYPE_FLOAT;
head.float_pod.pod.size = body_size = sizeof(float);
head.float_pod.value = va_arg(args, double);
head_size = sizeof(struct spa_pod);
body = &head.float_pod.value;
goto primitive;
case SPA_POD_TYPE_DOUBLE:
head.double_pod.pod.type = SPA_POD_TYPE_DOUBLE;
head.double_pod.pod.size = body_size = sizeof(double);
head.double_pod.value = va_arg(args, double);
head_size = sizeof(struct spa_pod);
body = &head.double_pod.value;
goto primitive;
case SPA_POD_TYPE_STRING:
body = va_arg(args, const char *);
body_size = body ? strlen(body) + 1 : (body = "", 1);
head.string_pod.pod.type = SPA_POD_TYPE_STRING;
head.string_pod.pod.size = body_size;
head_size = sizeof(struct spa_pod);
goto primitive;
case -SPA_POD_TYPE_STRING:
body = va_arg(args, const char *);
body_size = va_arg(args, uint32_t);
head.string_pod.pod.type = SPA_POD_TYPE_STRING;
head.string_pod.pod.size = body_size;
head_size = sizeof(struct spa_pod);
goto primitive;
case SPA_POD_TYPE_BYTES:
body = va_arg(args, void *);
body_size = va_arg(args, uint32_t);
head.bytes_pod.pod.type = SPA_POD_TYPE_BYTES;
head.bytes_pod.pod.size = body_size;
head_size = sizeof(struct spa_pod);
goto primitive;
case SPA_POD_TYPE_POINTER:
head.pointer_pod.pod.type = SPA_POD_TYPE_POINTER;
head.pointer_pod.pod.size = body_size = sizeof(struct spa_pod_pointer_body);
head.pointer_pod.body.type = va_arg(args, uint32_t);
head.pointer_pod.body.value = va_arg(args, void *);
head_size = sizeof(struct spa_pod);
body = &head.pointer_pod.body;
goto primitive;
case SPA_POD_TYPE_RECTANGLE:
head.rectangle_pod.pod.type = SPA_POD_TYPE_RECTANGLE;
head.rectangle_pod.pod.size = body_size = sizeof(struct spa_rectangle);
head.rectangle_pod.value.width = va_arg(args, uint32_t);
head.rectangle_pod.value.height = va_arg(args, uint32_t);
head_size = sizeof(struct spa_pod);
body = &head.rectangle_pod.value;
goto primitive;
case -SPA_POD_TYPE_RECTANGLE:
head.rectangle_pod.pod.type = SPA_POD_TYPE_RECTANGLE;
head.rectangle_pod.pod.size = body_size = sizeof(struct spa_rectangle);
head.rectangle_pod.value = *va_arg(args, struct spa_rectangle *);
head_size = sizeof(struct spa_pod);
body = &head.rectangle_pod.value;
goto primitive;
case SPA_POD_TYPE_FRACTION:
head.fraction_pod.pod.type = SPA_POD_TYPE_FRACTION;
head.fraction_pod.pod.size = body_size = sizeof(struct spa_fraction);
head.fraction_pod.value.num = va_arg(args, uint32_t);
head.fraction_pod.value.denom = va_arg(args, uint32_t);
head_size = sizeof(struct spa_pod);
body = &head.fraction_pod.value;
goto primitive;
case -SPA_POD_TYPE_FRACTION:
head.fraction_pod.pod.type = SPA_POD_TYPE_FRACTION;
head.fraction_pod.pod.size = body_size = sizeof(struct spa_fraction);
head.fraction_pod.value = *va_arg(args, struct spa_fraction *);
head_size = sizeof(struct spa_pod);
body = &head.fraction_pod.value;
goto primitive;
case SPA_POD_TYPE_BITMASK:
break;
case SPA_POD_TYPE_ARRAY:
f = va_arg(args, struct spa_pod_frame *);
type = va_arg(args, uint32_t);
n_values = va_arg(args, uint32_t);
head.array_pod.pod.type = SPA_POD_TYPE_ARRAY;
head.array_pod.pod.size = 0;
head_size = sizeof(struct spa_pod);
body = NULL;
goto primitive;
case SPA_POD_TYPE_STRUCT:
f = va_arg(args, struct spa_pod_frame *);
head.struct_pod.pod.type = SPA_POD_TYPE_STRUCT;
head.struct_pod.pod.size = 0;
head_size = sizeof(struct spa_pod);
body = NULL;
goto primitive;
case SPA_POD_TYPE_OBJECT:
f = va_arg(args, struct spa_pod_frame *);
head.object_pod.pod.type = SPA_POD_TYPE_OBJECT;
head.object_pod.pod.size = sizeof(struct spa_pod_object_body);
head.object_pod.body.id = va_arg(args, uint32_t);
head.object_pod.body.type = va_arg(args, uint32_t);
head_size = sizeof(struct spa_pod_object);
body = NULL;
goto primitive;
case SPA_POD_TYPE_PROP:
f = va_arg(args, struct spa_pod_frame *);
head.prop_pod.pod.type = SPA_POD_TYPE_PROP;
head.prop_pod.pod.size =
sizeof(struct spa_pod_prop_body) - sizeof(struct spa_pod);
head.prop_pod.body.key = va_arg(args, uint32_t);
head.prop_pod.body.flags = va_arg(args, uint32_t);
head_size = sizeof(struct spa_pod_prop) - sizeof(struct spa_pod);
body = NULL;
type = va_arg(args, uint32_t);
n_values = va_arg(args, uint32_t);
goto primitive;
case -SPA_POD_TYPE_ARRAY:
case -SPA_POD_TYPE_STRUCT:
case -SPA_POD_TYPE_OBJECT:
case -SPA_POD_TYPE_PROP:
f = va_arg(args, struct spa_pod_frame *);
spa_pod_builder_pop(builder, f);
break;
case SPA_POD_TYPE_POD:
if ((body = va_arg(args, void *)) == NULL) {
head.pod.type = SPA_POD_TYPE_NONE;
head.pod.size = 0;
body = &head;
}
body_size = SPA_POD_SIZE(body);
goto extra;
}
if (0) {
primitive:
if (!builder->in_array || builder->first) {
data[n_sizes] = &head;
size[n_sizes++] = head_size;
builder->first = false;
}
if (body) {
extra:
data[n_sizes] = body;
size[n_sizes++] = body_size;
if (!builder->in_array) {
data[n_sizes] = &zeroes;
size[n_sizes++] = SPA_ROUND_UP_N(body_size, 8) - body_size;
}
}
for (i = 0; i < n_sizes; i++) {
ref = spa_pod_builder_raw(builder, data[i], size[i]);
if (f && i == 0)
spa_pod_builder_push(builder, f, data[i], ref);
}
}
if (n_values > 0)
n_values--;
else
type = va_arg(args, uint32_t);
switch (id) {
case 'r':
return SPA_POD_PROP_RANGE_MIN_MAX;
case 's':
return SPA_POD_PROP_RANGE_STEP;
case 'e':
return SPA_POD_PROP_RANGE_ENUM;
case 'f':
return SPA_POD_PROP_RANGE_FLAGS;
default:
return SPA_POD_PROP_RANGE_NONE;
}
}
static inline void spa_pod_builder_add(struct spa_pod_builder *builder, uint32_t type, ...)
static inline uint32_t spa_pod_flag_from_id(char id)
{
va_list args;
va_start(args, type);
spa_pod_builder_addv(builder, type, args);
va_end(args);
switch (id) {
case 'u':
return SPA_POD_PROP_FLAG_UNSET;
case 'o':
return SPA_POD_PROP_FLAG_OPTIONAL;
case 'r':
return SPA_POD_PROP_FLAG_READONLY;
case 'd':
return SPA_POD_PROP_FLAG_DEPRECATED;
default:
return 0;
}
}
#define SPA_POD_OBJECT(f,id,type,...) \
SPA_POD_TYPE_OBJECT, f, id, type, __VA_ARGS__, -SPA_POD_TYPE_OBJECT, f
#define SPA_POD_BUILDER_COLLECT(builder,type,args) \
do { \
switch (type) { \
case 'b': \
spa_pod_builder_bool(builder, va_arg(args, int)); \
break; \
case 'I': \
spa_pod_builder_id(builder, va_arg(args, uint32_t)); \
break; \
case 'i': \
spa_pod_builder_int(builder, va_arg(args, int)); \
break; \
case 'l': \
spa_pod_builder_long(builder, va_arg(args, int64_t)); \
break; \
case 'f': \
spa_pod_builder_float(builder, va_arg(args, double)); \
break; \
case 'd': \
spa_pod_builder_double(builder, va_arg(args, double)); \
break; \
case 's': \
{ \
char *strval = va_arg(args, char *) ? : ""; \
size_t len = strlen(strval); \
spa_pod_builder_string_len(builder, strval, len); \
break; \
} \
case 'S': \
{ \
char *strval = va_arg(args, char *); \
size_t len = va_arg(args, int); \
spa_pod_builder_string_len(builder, strval, len); \
break; \
} \
case 'z': \
{ \
void *ptr = va_arg(args, void *); \
int len = va_arg(args, int); \
spa_pod_builder_bytes(builder, ptr, len); \
break; \
} \
case 'R': \
{ \
struct spa_rectangle *rectval = \
va_arg(args, struct spa_rectangle *); \
spa_pod_builder_rectangle(builder, \
rectval->width, rectval->height); \
break; \
} \
case 'F': \
{ \
struct spa_fraction *fracval = \
va_arg(args, struct spa_fraction *); \
spa_pod_builder_fraction(builder, fracval->num, fracval->denom);\
break; \
} \
case 'a': \
{ \
int child_size = va_arg(args, int); \
int child_type = va_arg(args, int); \
int n_elems = va_arg(args, int); \
void *elems = va_arg(args, void *); \
spa_pod_builder_array(builder, child_size, \
child_type, n_elems, elems); \
break; \
} \
case 'p': \
{ \
int t = va_arg(args, uint32_t); \
spa_pod_builder_pointer(builder, t, va_arg(args, void *)); \
break; \
} \
case 'h': \
spa_pod_builder_fd(builder, va_arg(args, int)); \
break; \
case 'P': \
{ \
struct spa_pod *pod = va_arg(args, struct spa_pod *); \
if (pod == NULL) \
spa_pod_builder_none(builder); \
else \
spa_pod_builder_primitive(builder, pod); \
break; \
} \
} \
} while(false)
#define SPA_POD_STRUCT(f,...) \
SPA_POD_TYPE_STRUCT, f, __VA_ARGS__, -SPA_POD_TYPE_STRUCT, f
static inline void *
spa_pod_builder_addv(struct spa_pod_builder *builder,
const char *format, va_list args)
{
while (format) {
switch (*format) {
case '<':
{
uint32_t id = va_arg(args, uint32_t);
uint32_t type = va_arg(args, uint32_t);
spa_pod_builder_push_object(builder, &builder->frame[builder->depth++], id, type);
break;
}
case '[':
spa_pod_builder_push_struct(builder, &builder->frame[builder->depth++]);
break;
case '(':
spa_pod_builder_push_array(builder, &builder->frame[builder->depth++]);
break;
case ':':
{
const char *spec;
char type;
int n_values;
uint32_t key, flags;
#define SPA_POD_PROP(f,key,flags,type,...) \
SPA_POD_TYPE_PROP, f, key, flags, type, __VA_ARGS__, -SPA_POD_TYPE_PROP, f
key = va_arg(args, uint32_t);
format = spec = va_arg(args, const char *);
type = *spec;
if (*spec != '\0')
spec++;
flags = spa_pod_range_from_id(*spec);
if (*spec != '\0')
spec++;
for (;*spec;spec++)
flags |= spa_pod_flag_from_id(*spec);
spa_pod_builder_push_prop(builder, &builder->frame[builder->depth++], key, flags);
#define spa_pod_builder_object(b,f,id,type,...) \
spa_pod_builder_add(b, SPA_POD_OBJECT(f,id,type,__VA_ARGS__), 0)
if (type == '{' || type == '[')
continue;
#define spa_pod_builder_struct(b,f,...) \
spa_pod_builder_add(b, SPA_POD_STRUCT(f,__VA_ARGS__), 0)
n_values = -1;
while (n_values-- != 0) {
SPA_POD_BUILDER_COLLECT(builder, type, args);
if ((flags & SPA_POD_PROP_RANGE_MASK) == 0)
break;
if (n_values == -2)
n_values = va_arg(args, int);
}
spa_pod_builder_pop(builder, &builder->frame[--builder->depth]);
break;
}
case ']': case ')': case '>':
spa_pod_builder_pop(builder, &builder->frame[--builder->depth]);
if (builder->depth > 0 &&
builder->frame[builder->depth-1].pod.type == SPA_POD_TYPE_PROP)
spa_pod_builder_pop(builder, &builder->frame[--builder->depth]);
break;
case ' ': case '\n': case '\t': case '\r':
break;
case '\0':
format = va_arg(args, const char *);
continue;
default:
SPA_POD_BUILDER_COLLECT(builder,*format,args);
break;;
}
format++;
}
return SPA_POD_BUILDER_DEREF(builder, builder->frame[builder->depth].ref, void);
}
static inline void *spa_pod_builder_add(struct spa_pod_builder *builder, const char *format, ...)
{
void *res;
va_list args;
va_start(args, format);
res = spa_pod_builder_addv(builder, format, args);
va_end(args);
return res;
}
#define SPA_POD_OBJECT(id,type,...) \
"<", id, type, ##__VA_ARGS__, ">"
#define SPA_POD_STRUCT(...) \
"[", ##__VA_ARGS__, "]"
#define SPA_POD_PROP(key,spec,type,value,...) \
":", key, spec, value, ##__VA_ARGS__
#define spa_pod_builder_object(b,id,type,...) \
spa_pod_builder_add(b, SPA_POD_OBJECT(id,type,##__VA_ARGS__), NULL)
#define spa_pod_builder_struct(b,...) \
spa_pod_builder_add(b, SPA_POD_STRUCT(__VA_ARGS__), NULL)
#ifdef __cplusplus
} /* extern "C" */

View file

@ -35,102 +35,27 @@ struct spa_pod_iter {
uint32_t offset;
};
static inline void spa_pod_iter_contents(struct spa_pod_iter *iter, const void *data, uint32_t size)
static inline void spa_pod_iter_init(struct spa_pod_iter *iter, const void *data, uint32_t size, uint32_t offset)
{
iter->data = data;
iter->size = size;
iter->offset = 0;
iter->offset = offset;
}
static inline bool spa_pod_iter_struct(struct spa_pod_iter *iter, const void *data, uint32_t size)
static inline struct spa_pod *spa_pod_iter_current(struct spa_pod_iter *iter)
{
if (data == NULL || size < 8 || SPA_POD_SIZE(data) > size
|| SPA_POD_TYPE(data) != SPA_POD_TYPE_STRUCT)
return false;
spa_pod_iter_contents(iter, SPA_POD_CONTENTS(struct spa_pod_struct, data),
SPA_POD_CONTENTS_SIZE(struct spa_pod_struct, data));
return true;
}
static inline bool spa_pod_iter_object(struct spa_pod_iter *iter, const void *data, uint32_t size)
{
if (data == NULL || SPA_POD_SIZE(data) > size || SPA_POD_TYPE(data) != SPA_POD_TYPE_OBJECT)
return false;
spa_pod_iter_contents(iter, SPA_POD_CONTENTS(struct spa_pod_object, data),
SPA_POD_CONTENTS_SIZE(struct spa_pod_object, data));
return true;
}
static inline bool spa_pod_iter_pod(struct spa_pod_iter *iter, struct spa_pod *pod)
{
void *data;
uint32_t size;
switch (SPA_POD_TYPE(pod)) {
case SPA_POD_TYPE_STRUCT:
data = SPA_POD_CONTENTS(struct spa_pod_struct, pod);
size = SPA_POD_CONTENTS_SIZE(struct spa_pod_struct, pod);
break;
case SPA_POD_TYPE_OBJECT:
data = SPA_POD_CONTENTS(struct spa_pod_object, pod);
size = SPA_POD_CONTENTS_SIZE(struct spa_pod_object, pod);
break;
default:
spa_pod_iter_contents(iter, NULL, 0);
return false;
if (iter->offset + 8 <= iter->size) {
struct spa_pod *pod = SPA_MEMBER(iter->data, iter->offset, struct spa_pod);
if (SPA_POD_SIZE(pod) <= iter->size)
return pod;
}
spa_pod_iter_contents(iter, data, size);
return true;
return NULL;
}
static inline bool spa_pod_iter_has_next(struct spa_pod_iter *iter)
static inline void spa_pod_iter_advance(struct spa_pod_iter *iter, struct spa_pod *current)
{
return (iter->offset + 8 <= iter->size &&
SPA_POD_SIZE(SPA_MEMBER(iter->data, iter->offset, struct spa_pod)) <= iter->size);
}
static inline struct spa_pod *spa_pod_iter_next(struct spa_pod_iter *iter)
{
struct spa_pod *res = SPA_MEMBER(iter->data, iter->offset, struct spa_pod);
iter->offset += SPA_ROUND_UP_N(SPA_POD_SIZE(res), 8);
return res;
}
static inline struct spa_pod *spa_pod_iter_first(struct spa_pod_iter *iter, struct spa_pod *pod)
{
if (!spa_pod_iter_pod(iter, pod) || !spa_pod_iter_has_next(iter))
return NULL;
return spa_pod_iter_next(iter);
}
static inline bool spa_pod_iter_getv(struct spa_pod_iter *iter, uint32_t type, va_list args)
{
bool res = true;
while (type && (res = spa_pod_iter_has_next(iter))) {
struct spa_pod *pod = spa_pod_iter_next(iter);
SPA_POD_COLLECT(pod, type, args, error);
type = va_arg(args, uint32_t);
}
return res;
error:
return false;
}
static inline bool spa_pod_iter_get(struct spa_pod_iter *iter, uint32_t type, ...)
{
va_list args;
bool res;
va_start(args, type);
res = spa_pod_iter_getv(iter, type, args);
va_end(args);
return res;
if (current)
iter->offset += SPA_ROUND_UP_N(SPA_POD_SIZE(current), 8);
}
#ifdef __cplusplus

View file

@ -0,0 +1,313 @@
/* Spa
* Copyright (C) 2017 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __SPA_POD_PARSER_H__
#define __SPA_POD_PARSER_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#include <stdio.h>
#include <spa/pod-iter.h>
#ifndef SPA_POD_MAX_LEVEL
#define SPA_POD_MAX_LEVEL 16
#endif
struct spa_pod_parser {
struct spa_pod_iter iter[SPA_POD_MAX_LEVEL];
int depth;
};
static inline void spa_pod_parser_init(struct spa_pod_parser *parser,
const void *data, uint32_t size, uint32_t offset)
{
parser->depth = 0;
spa_pod_iter_init(&parser->iter[0], data, size, offset);
}
static inline void spa_pod_parser_pod(struct spa_pod_parser *parser,
const struct spa_pod *pod)
{
spa_pod_parser_init(parser, pod, SPA_POD_SIZE(pod), 0);
}
static inline bool spa_pod_parser_can_collect(struct spa_pod *pod, char type)
{
if (type == 'P')
return true;
switch (SPA_POD_TYPE(pod)) {
case SPA_POD_TYPE_NONE:
return type == 'T' || type == 'O' || type == 'V';
case SPA_POD_TYPE_BOOL:
return type == 'b';
case SPA_POD_TYPE_ID:
return type == 'I';
case SPA_POD_TYPE_INT:
return type == 'i';
case SPA_POD_TYPE_LONG:
return type == 'l';
case SPA_POD_TYPE_FLOAT:
return type == 'f';
case SPA_POD_TYPE_DOUBLE:
return type == 'd';
case SPA_POD_TYPE_STRING:
return type == 's' || type == 'S';
case SPA_POD_TYPE_BYTES:
return type == 'z';
case SPA_POD_TYPE_RECTANGLE:
return type == 'R';
case SPA_POD_TYPE_FRACTION:
return type == 'F';
case SPA_POD_TYPE_BITMAP:
return type == 'B';
case SPA_POD_TYPE_ARRAY:
return type == 'a';
case SPA_POD_TYPE_STRUCT:
return type == 'T';
case SPA_POD_TYPE_OBJECT:
return type == 'O';
case SPA_POD_TYPE_POINTER:
return type == 'p';
case SPA_POD_TYPE_FD:
return type == 'h';
case SPA_POD_TYPE_PROP:
return type == 'V';
default:
return false;
}
}
#define SPA_POD_PARSER_COLLECT(pod,type,args) \
do { \
switch (type) { \
case 'b': \
*va_arg(args, int*) = SPA_POD_VALUE(struct spa_pod_bool, pod); \
break; \
case 'I': \
case 'i': \
*va_arg(args, int32_t*) = SPA_POD_VALUE(struct spa_pod_int, pod); \
break; \
case 'l': \
*va_arg(args, int64_t*) = SPA_POD_VALUE(struct spa_pod_long, pod); \
break; \
case 'f': \
*va_arg(args, float*) = SPA_POD_VALUE(struct spa_pod_float, pod); \
break; \
case 'd': \
*va_arg(args, double*) = SPA_POD_VALUE(struct spa_pod_double, pod); \
break; \
case 's': \
*va_arg(args, char**) = SPA_POD_CONTENTS(struct spa_pod_string, pod); \
break; \
case 'S': \
{ \
char *dest = va_arg(args, char*); \
uint32_t maxlen = va_arg(args, uint32_t); \
strncpy(dest, SPA_POD_CONTENTS(struct spa_pod_string, pod), maxlen-1); \
break; \
} \
case 'z': \
*(va_arg(args, void **)) = SPA_POD_CONTENTS(struct spa_pod_bytes, pod); \
*(va_arg(args, uint32_t *)) = SPA_POD_BODY_SIZE(pod); \
break; \
case 'R': \
*va_arg(args, struct spa_rectangle*) = \
SPA_POD_VALUE(struct spa_pod_rectangle, pod); \
break; \
case 'F': \
*va_arg(args, struct spa_fraction*) = \
SPA_POD_VALUE(struct spa_pod_fraction, pod); \
break; \
case 'B': \
*va_arg(args, uint32_t **) = \
SPA_POD_CONTENTS(struct spa_pod_bitmap, pod); \
break; \
case 'p': \
{ \
struct spa_pod_pointer_body *b = SPA_POD_BODY(pod); \
*(va_arg(args, void **)) = b->value; \
break; \
} \
case 'h': \
*va_arg(args, int*) = SPA_POD_VALUE(struct spa_pod_fd, pod); \
break; \
case 'V': \
case 'P': \
case 'O': \
case 'T': \
*va_arg(args, struct spa_pod**) = \
(pod == NULL || (SPA_POD_TYPE(pod) == SPA_POD_TYPE_NONE) \
? NULL : pod); \
break; \
default: \
break; \
} \
} while(false)
#define SPA_POD_PARSER_SKIP(type,args) \
do { \
switch (type) { \
case 'S': \
va_arg(args, void*); \
va_arg(args, uint32_t); \
break; \
case 'z': \
va_arg(args, void**); \
case 'b': \
case 'I': \
case 'i': \
case 'l': \
case 'f': \
case 'd': \
case 's': \
case 'R': \
case 'F': \
case 'B': \
case 'p': \
case 'h': \
case 'V': \
case 'P': \
case 'T': \
case 'O': \
va_arg(args, void*); \
break; \
} \
} while(false)
static inline int spa_pod_parser_getv(struct spa_pod_parser *parser,
const char *format, va_list args)
{
struct spa_pod *pod = NULL, *current;
struct spa_pod_prop *prop = NULL;
bool required = true, suppress = false, skip = false;
struct spa_pod_iter *it = &parser->iter[parser->depth];
current = pod = spa_pod_iter_current(it);
while (format) {
switch (*format) {
case '<':
if (pod == NULL || SPA_POD_TYPE(pod) != SPA_POD_TYPE_OBJECT)
return SPA_RESULT_ERROR;
it = &parser->iter[++parser->depth];
spa_pod_iter_init(it, pod, SPA_POD_SIZE(pod), sizeof(struct spa_pod_object));
goto read_pod;
case '[':
if (pod == NULL || SPA_POD_TYPE(pod) != SPA_POD_TYPE_STRUCT)
return SPA_RESULT_ERROR;
it = &parser->iter[++parser->depth];
spa_pod_iter_init(it, pod, SPA_POD_SIZE(pod), sizeof(struct spa_pod_struct));
goto read_pod;
case ']': case '>':
if (current != NULL)
return SPA_RESULT_ERROR;
if (--parser->depth < 0)
return SPA_RESULT_INVALID_ARGUMENTS;
it = &parser->iter[parser->depth];
current = spa_pod_iter_current(it);
spa_pod_iter_advance(it, current);
goto read_pod;
case '\0':
format = va_arg(args, char *);
continue;
case ' ': case '\n': case '\t': case '\r':
break;
case '?':
required = false;
break;
case '*':
suppress = true;
break;
case ':':
{
uint32_t key = va_arg(args, uint32_t);
const struct spa_pod *obj = parser->iter[parser->depth].data;
if (SPA_POD_TYPE(obj) == SPA_POD_TYPE_OBJECT)
prop = spa_pod_object_find_prop((struct spa_pod_object*)obj, key);
else if (SPA_POD_TYPE(obj) == SPA_POD_TYPE_STRUCT)
prop = spa_pod_struct_find_prop((struct spa_pod_struct*)obj, key);
else
prop = NULL;
if (prop != NULL && (prop->body.flags & SPA_POD_PROP_FLAG_UNSET) == 0)
pod = &prop->body.value;
else
pod = NULL;
it->offset = it->size;
current = NULL;
required = true;
break;
}
case 'V':
pod = (struct spa_pod *) prop;
if (pod == NULL && required)
return SPA_RESULT_NOT_FOUND;
goto collect;
default:
if (pod == NULL || !spa_pod_parser_can_collect(pod, *format)) {
if (required)
return SPA_RESULT_NOT_FOUND;
skip = true;
}
collect:
if (suppress)
suppress = false;
else if (skip)
SPA_POD_PARSER_SKIP(*format, args);
else
SPA_POD_PARSER_COLLECT(pod, *format, args);
spa_pod_iter_advance(it, current);
required = true;
skip = false;
read_pod:
pod = current = spa_pod_iter_current(it);
break;
}
format++;
}
return 0;
}
static inline int spa_pod_parser_get(struct spa_pod_parser *parser,
const char *format, ...)
{
int res;
va_list args;
va_start(args, format);
res = spa_pod_parser_getv(parser, format, args);
va_end(args);
return res;
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __SPA_POD_PARSER_H__ */

View file

@ -92,154 +92,19 @@ static inline struct spa_pod_prop *spa_pod_object_find_prop(const struct spa_pod
return spa_pod_contents_find_prop(&obj->pod, sizeof(struct spa_pod_object), key);
}
#define SPA_POD_COLLECT(pod,type,args,error) \
do { \
if (type == SPA_POD_TYPE_POD) { \
*(va_arg(args, struct spa_pod **)) = pod; \
} else if ((pod)->type == SPA_POD_TYPE_NONE) { \
switch (type) { \
case -SPA_POD_TYPE_ARRAY: \
case -SPA_POD_TYPE_STRUCT: \
case -SPA_POD_TYPE_OBJECT: \
case -SPA_POD_TYPE_PROP: \
*(va_arg(args, struct spa_pod **)) = NULL; \
break; \
default: \
goto error; \
} \
} else if ((pod)->type == type || (pod)->type == -type) { \
switch (type) { \
case SPA_POD_TYPE_BOOL: \
case SPA_POD_TYPE_ID: \
case SPA_POD_TYPE_INT: \
*(va_arg(args, int32_t*)) = SPA_POD_VALUE(struct spa_pod_int, pod); \
break; \
case SPA_POD_TYPE_LONG: \
*(va_arg(args, int64_t*)) = SPA_POD_VALUE(struct spa_pod_long, pod); \
break; \
case SPA_POD_TYPE_FLOAT: \
*(va_arg(args, float*)) = SPA_POD_VALUE(struct spa_pod_float, pod); \
break; \
case SPA_POD_TYPE_DOUBLE: \
*(va_arg(args, double*)) = SPA_POD_VALUE(struct spa_pod_double, pod); \
break; \
case SPA_POD_TYPE_STRING: \
*(va_arg(args, char **)) = SPA_POD_CONTENTS(struct spa_pod_string, pod); \
break; \
case -SPA_POD_TYPE_STRING: \
{ \
char *dest = va_arg(args, char *); \
uint32_t maxlen = va_arg(args, uint32_t); \
strncpy(dest, SPA_POD_CONTENTS(struct spa_pod_string, pod), maxlen-1); \
break; \
} \
case SPA_POD_TYPE_BYTES: \
*(va_arg(args, void **)) = SPA_POD_CONTENTS(struct spa_pod_bytes, pod); \
*(va_arg(args, uint32_t *)) = SPA_POD_BODY_SIZE(pod); \
break; \
case SPA_POD_TYPE_POINTER: \
{ \
struct spa_pod_pointer_body *b = SPA_POD_BODY(pod); \
*(va_arg(args, void **)) = b->value; \
break; \
} \
case SPA_POD_TYPE_RECTANGLE: \
*(va_arg(args, struct spa_rectangle *)) = \
SPA_POD_VALUE(struct spa_pod_rectangle, pod); \
break; \
case SPA_POD_TYPE_FRACTION: \
*(va_arg(args, struct spa_fraction *)) = \
SPA_POD_VALUE(struct spa_pod_fraction, pod); \
break; \
case SPA_POD_TYPE_BITMASK: \
*(va_arg(args, uint32_t **)) = SPA_POD_CONTENTS(struct spa_pod, pod); \
break; \
case SPA_POD_TYPE_ARRAY: \
case SPA_POD_TYPE_STRUCT: \
case SPA_POD_TYPE_OBJECT: \
case SPA_POD_TYPE_PROP: \
case -SPA_POD_TYPE_ARRAY: \
case -SPA_POD_TYPE_STRUCT: \
case -SPA_POD_TYPE_OBJECT: \
case -SPA_POD_TYPE_PROP: \
*(va_arg(args, struct spa_pod **)) = pod; \
break; \
default: \
goto error; \
} \
} else \
goto error; \
} while (false);
#define SPA_POD_COLLECT_SKIP(type,args) \
switch (type) { \
case SPA_POD_TYPE_BYTES: \
case SPA_POD_TYPE_POINTER: \
va_arg (args, void*); \
/* fallthrough */ \
case SPA_POD_TYPE_BOOL: \
case SPA_POD_TYPE_ID: \
case SPA_POD_TYPE_INT: \
case SPA_POD_TYPE_LONG: \
case SPA_POD_TYPE_FLOAT: \
case SPA_POD_TYPE_DOUBLE: \
case SPA_POD_TYPE_STRING: \
case -SPA_POD_TYPE_STRING: \
case SPA_POD_TYPE_RECTANGLE: \
case SPA_POD_TYPE_FRACTION: \
case SPA_POD_TYPE_BITMASK: \
case SPA_POD_TYPE_ARRAY: \
case SPA_POD_TYPE_STRUCT: \
case SPA_POD_TYPE_OBJECT: \
case SPA_POD_TYPE_PROP: \
case SPA_POD_TYPE_POD: \
case -SPA_POD_TYPE_ARRAY: \
case -SPA_POD_TYPE_STRUCT: \
case -SPA_POD_TYPE_OBJECT: \
case -SPA_POD_TYPE_PROP: \
va_arg(args, void*); \
default: \
break; \
}
static inline uint32_t
spa_pod_contents_queryv(const struct spa_pod *pod, uint32_t offset, uint32_t key, va_list args)
static inline struct spa_pod_prop *spa_pod_struct_find_prop(const struct spa_pod_struct *obj,
uint32_t key)
{
uint32_t count = 0;
while (key) {
uint32_t type;
struct spa_pod_prop *prop = spa_pod_contents_find_prop(pod, offset, key);
type = va_arg(args, uint32_t);
if (prop && prop->body.key == key && !(prop->body.flags & SPA_POD_PROP_FLAG_UNSET)) {
SPA_POD_COLLECT(&prop->body.value, type, args, next);
count++;
} else {
SPA_POD_COLLECT_SKIP(type, args);
}
next:
key = va_arg(args, uint32_t);
}
return count;
return spa_pod_contents_find_prop(&obj->pod, sizeof(struct spa_pod_struct), key);
}
static inline uint32_t
spa_pod_contents_query(const struct spa_pod *pod, uint32_t offset, uint32_t key, ...)
{
va_list args;
uint32_t count;
va_start(args, key);
count = spa_pod_contents_queryv(pod, offset, key, args);
va_end(args);
return count;
}
#define spa_pod_object_query(object,key, ...) \
spa_pod_contents_query(&(object)->pod, sizeof(struct spa_pod_object), key, __VA_ARGS__)
#define spa_pod_object_parse(object,...) \
({ \
struct spa_pod_parser __p; \
const struct spa_pod_object *__obj = object; \
spa_pod_parser_pod(&__p, &__obj->pod); \
spa_pod_parser_get(&__p, "<", ##__VA_ARGS__, NULL); \
})
#ifdef __cplusplus
} /* extern "C" */

View file

@ -43,23 +43,33 @@ extern "C" {
enum spa_pod_type {
SPA_POD_TYPE_INVALID = 0,
SPA_POD_TYPE_NONE = 1,
SPA_POD_TYPE_BOOL,
SPA_POD_TYPE_ID,
SPA_POD_TYPE_INT,
SPA_POD_TYPE_LONG,
SPA_POD_TYPE_FLOAT,
SPA_POD_TYPE_DOUBLE,
SPA_POD_TYPE_STRING,
SPA_POD_TYPE_BYTES,
SPA_POD_TYPE_POINTER,
SPA_POD_TYPE_RECTANGLE,
SPA_POD_TYPE_FRACTION,
SPA_POD_TYPE_BITMASK,
SPA_POD_TYPE_BITMAP,
SPA_POD_TYPE_ARRAY,
SPA_POD_TYPE_STRUCT,
SPA_POD_TYPE_OBJECT,
SPA_POD_TYPE_POINTER,
SPA_POD_TYPE_FD,
SPA_POD_TYPE_PROP,
SPA_POD_TYPE_POD,
SPA_POD_TYPE_CUSTOM_START = 64,
};
struct spa_pod {
@ -67,12 +77,6 @@ struct spa_pod {
uint32_t type; /* one of spa_pod_type */
};
struct spa_pod_int {
struct spa_pod pod;
int32_t value;
int32_t __padding;
};
struct spa_pod_bool {
struct spa_pod pod;
int32_t value;
@ -85,6 +89,12 @@ struct spa_pod_id {
int32_t __padding;
};
struct spa_pod_int {
struct spa_pod pod;
int32_t value;
int32_t __padding;
};
struct spa_pod_long {
struct spa_pod pod;
int64_t value;
@ -110,16 +120,6 @@ struct spa_pod_bytes {
/* value here */
};
struct spa_pod_pointer_body {
uint32_t type;
void *value;
};
struct spa_pod_pointer {
struct spa_pod pod;
struct spa_pod_pointer_body body;
};
struct spa_pod_rectangle {
struct spa_pod pod;
struct spa_rectangle value;
@ -150,6 +150,32 @@ struct spa_pod_struct {
/* one or more spa_pod follow */
};
struct spa_pod_object_body {
uint32_t id;
uint32_t type;
/* contents follow, series of spa_pod */
};
struct spa_pod_object {
struct spa_pod pod;
struct spa_pod_object_body body;
};
struct spa_pod_pointer_body {
uint32_t type;
void *value;
};
struct spa_pod_pointer {
struct spa_pod pod;
struct spa_pod_pointer_body body;
};
struct spa_pod_fd {
struct spa_pod pod;
int value;
};
struct spa_pod_prop_body {
uint32_t key;
#define SPA_POD_PROP_RANGE_NONE 0
@ -173,17 +199,6 @@ struct spa_pod_prop {
struct spa_pod_prop_body body;
};
struct spa_pod_object_body {
uint32_t id;
uint32_t type;
/* contents follow, series of spa_pod_prop */
};
struct spa_pod_object {
struct spa_pod pod;
struct spa_pod_object_body body;
};
#ifdef __cplusplus
} /* extern "C" */
#endif

View file

@ -26,6 +26,7 @@ extern "C" {
#include <spa/pod.h>
#include <spa/pod-builder.h>
#include <spa/pod-parser.h>
struct spa_props {
struct spa_pod_object object;
@ -58,20 +59,16 @@ spa_pod_builder_push_props(struct spa_pod_builder *builder,
return spa_pod_builder_push_object(builder, frame, 0, props_type);
}
#define spa_pod_builder_props(b,f,props_type,...) \
spa_pod_builder_object(b, f, 0, props_type,__VA_ARGS__)
#define spa_pod_builder_props(b,props_type,...) \
spa_pod_builder_object(b, 0, props_type,##__VA_ARGS__)
static inline uint32_t spa_props_query(const struct spa_props *props, uint32_t key, ...)
{
uint32_t count;
va_list args;
va_start(args, key);
count = spa_pod_contents_queryv(&props->object.pod, sizeof(struct spa_props), key, args);
va_end(args);
return count;
}
#define spa_props_parse(props,...) \
({ \
struct spa_pod_parser __p; \
const struct spa_props *__props = props; \
spa_pod_parser_pod(&__p, &__props->object.pod); \
spa_pod_parser_get(&__p, "<", ##__VA_ARGS__, NULL); \
})
#ifdef __cplusplus
} /* extern "C" */

View file

@ -74,50 +74,53 @@ spa_type_format_video_map(struct spa_type_map *map, struct spa_type_format_video
}
}
static inline bool
static inline int
spa_format_video_raw_parse(const struct spa_format *format,
struct spa_video_info_raw *info, struct spa_type_format_video *type)
{
spa_format_query(format,
type->format, SPA_POD_TYPE_ID, &info->format,
type->size, SPA_POD_TYPE_RECTANGLE, &info->size,
type->framerate, SPA_POD_TYPE_FRACTION, &info->framerate,
type->max_framerate, SPA_POD_TYPE_FRACTION, &info->max_framerate,
type->views, SPA_POD_TYPE_INT, &info->views,
type->interlace_mode, SPA_POD_TYPE_INT, &info->interlace_mode,
type->pixel_aspect_ratio, SPA_POD_TYPE_FRACTION, &info->pixel_aspect_ratio,
type->multiview_mode, SPA_POD_TYPE_INT, &info->multiview_mode,
type->multiview_flags, SPA_POD_TYPE_INT, &info->multiview_flags,
type->chroma_site, SPA_POD_TYPE_INT, &info->chroma_site,
type->color_range, SPA_POD_TYPE_INT, &info->color_range,
type->color_matrix, SPA_POD_TYPE_INT, &info->color_matrix,
type->transfer_function, SPA_POD_TYPE_INT, &info->transfer_function,
type->color_primaries, SPA_POD_TYPE_INT, &info->color_primaries, 0);
return true;
struct spa_pod_parser prs;
spa_pod_parser_pod(&prs, &format->pod);
return spa_pod_parser_get(&prs,
":",type->format, "I", &info->format,
":",type->size, "R", &info->size,
":",type->framerate, "F", &info->framerate,
":",type->max_framerate, "?F", &info->max_framerate,
":",type->views, "?i", &info->views,
":",type->interlace_mode, "?i", &info->interlace_mode,
":",type->pixel_aspect_ratio, "?F", &info->pixel_aspect_ratio,
":",type->multiview_mode, "?i", &info->multiview_mode,
":",type->multiview_flags, "?i", &info->multiview_flags,
":",type->chroma_site, "?i", &info->chroma_site,
":",type->color_range, "?i", &info->color_range,
":",type->color_matrix, "?i", &info->color_matrix,
":",type->transfer_function, "?i", &info->transfer_function,
":",type->color_primaries, "?i", &info->color_primaries, NULL);
}
static inline bool
static inline int
spa_format_video_h264_parse(const struct spa_format *format,
struct spa_video_info_h264 *info, struct spa_type_format_video *type)
{
spa_format_query(format,
type->size, SPA_POD_TYPE_RECTANGLE, &info->size,
type->framerate, SPA_POD_TYPE_FRACTION, &info->framerate,
type->max_framerate, SPA_POD_TYPE_FRACTION, &info->max_framerate,
type->stream_format, SPA_POD_TYPE_INT, &info->stream_format,
type->alignment, SPA_POD_TYPE_INT, &info->alignment, 0);
return true;
struct spa_pod_parser prs;
spa_pod_parser_pod(&prs, &format->pod);
return spa_pod_parser_get(&prs,
":",type->size, "?R", &info->size,
":",type->framerate, "?F", &info->framerate,
":",type->max_framerate, "?F", &info->max_framerate,
":",type->stream_format, "?i", &info->stream_format,
":",type->alignment, "?i", &info->alignment, NULL);
}
static inline bool
static inline int
spa_format_video_mjpg_parse(const struct spa_format *format,
struct spa_video_info_mjpg *info, struct spa_type_format_video *type)
{
spa_format_query(format,
type->size, SPA_POD_TYPE_RECTANGLE, &info->size,
type->framerate, SPA_POD_TYPE_FRACTION, &info->framerate,
type->max_framerate, SPA_POD_TYPE_FRACTION, &info->max_framerate, 0);
return true;
struct spa_pod_parser prs;
spa_pod_parser_pod(&prs, &format->pod);
return spa_pod_parser_get(&prs,
":",type->size, "?R", &info->size,
":",type->framerate, "?F", &info->framerate,
":",type->max_framerate, "?F", &info->max_framerate, NULL);
}
#ifdef __cplusplus

View file

@ -151,25 +151,26 @@ int spa_debug_param(const struct spa_param *param)
}
static const char *pod_type_names[] = {
"invalid",
"none",
"bool",
"id",
"int",
"long",
"float",
"double",
"string",
"bytes",
"pointer",
"rectangle",
"fraction",
"bitmask",
"array",
"struct",
"object",
"prop",
"pod"
[SPA_POD_TYPE_INVALID] = "invalid",
[SPA_POD_TYPE_NONE] = "none",
[SPA_POD_TYPE_BOOL] = "bool",
[SPA_POD_TYPE_ID] = "id",
[SPA_POD_TYPE_INT] = "int",
[SPA_POD_TYPE_LONG] = "long",
[SPA_POD_TYPE_FLOAT] = "float",
[SPA_POD_TYPE_DOUBLE] = "double",
[SPA_POD_TYPE_STRING] = "string",
[SPA_POD_TYPE_BYTES] = "bytes",
[SPA_POD_TYPE_RECTANGLE] = "rectangle",
[SPA_POD_TYPE_FRACTION] = "fraction",
[SPA_POD_TYPE_BITMAP] = "bitmap",
[SPA_POD_TYPE_ARRAY] = "array",
[SPA_POD_TYPE_STRUCT] = "struct",
[SPA_POD_TYPE_OBJECT] = "object",
[SPA_POD_TYPE_POINTER] = "pointer",
[SPA_POD_TYPE_FD] = "fd",
[SPA_POD_TYPE_PROP] = "prop",
[SPA_POD_TYPE_POD] = "pod"
};
static void
@ -198,11 +199,14 @@ print_pod_value(uint32_t size, uint32_t type, void *body, int prefix)
case SPA_POD_TYPE_STRING:
printf("%-*sString \"%s\"\n", prefix, "", (char *) body);
break;
case SPA_POD_TYPE_FD:
printf("%-*sFd %d\n", prefix, "", *(int *) body);
break;
case SPA_POD_TYPE_POINTER:
{
struct spa_pod_pointer_body *b = body;
printf("%-*sPointer %s %p\n", prefix, "",
spa_type_map_get_type(map, b->type), b->value);
map ? spa_type_map_get_type(map, b->type) : "*no map*", b->value);
break;
}
case SPA_POD_TYPE_RECTANGLE:
@ -217,8 +221,8 @@ print_pod_value(uint32_t size, uint32_t type, void *body, int prefix)
printf("%-*sFraction %d/%d\n", prefix, "", f->num, f->denom);
break;
}
case SPA_POD_TYPE_BITMASK:
printf("%-*sBitmask\n", prefix, "");
case SPA_POD_TYPE_BITMAP:
printf("%-*sBitmap\n", prefix, "");
break;
case SPA_POD_TYPE_ARRAY:
{
@ -245,7 +249,7 @@ print_pod_value(uint32_t size, uint32_t type, void *body, int prefix)
struct spa_pod *p;
printf("%-*sObject: size %d, id %d, type %s\n", prefix, "", size, b->id,
spa_type_map_get_type(map, b->type));
map ? spa_type_map_get_type(map, b->type) : "*no map*");
SPA_POD_OBJECT_BODY_FOREACH(b, size, p)
print_pod_value(p->size, p->type, SPA_POD_BODY(p), prefix + 2);
break;
@ -257,7 +261,7 @@ print_pod_value(uint32_t size, uint32_t type, void *body, int prefix)
int i;
printf("%-*sProp: key %s, flags %d\n", prefix, "",
spa_type_map_get_type(map, b->key), b->flags);
map ? spa_type_map_get_type(map, b->key) : "*no map*", b->flags);
if (b->flags & SPA_POD_PROP_FLAG_UNSET)
printf("%-*sUnset (Default):\n", prefix + 2, "");
else
@ -303,7 +307,7 @@ print_format_value(uint32_t size, uint32_t type, void *body)
break;
case SPA_POD_TYPE_ID:
{
const char *str = spa_type_map_get_type(map, *(int32_t *) body);
const char *str = map ? spa_type_map_get_type(map, *(int32_t *) body) : NULL;
if (str) {
const char *h = rindex(str, ':');
if (h)
@ -341,8 +345,8 @@ print_format_value(uint32_t size, uint32_t type, void *body)
fprintf(stderr, "%" PRIu32 "/%" PRIu32, f->num, f->denom);
break;
}
case SPA_POD_TYPE_BITMASK:
fprintf(stderr, "Bitmask");
case SPA_POD_TYPE_BITMAP:
fprintf(stderr, "Bitmap");
break;
case SPA_POD_TYPE_BYTES:
fprintf(stderr, "Bytes");

View file

@ -112,8 +112,8 @@ fill_item(struct impl *this, snd_ctl_card_info_t *card_info, snd_pcm_info_t *dev
const char *str, *name, *klass = NULL;
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(this->item_buffer, sizeof(this->item_buffer));
const struct spa_handle_factory *factory = NULL;
struct spa_pod_frame f[3];
char card_name[64];
struct type *t = &this->type;
switch (snd_pcm_info_get_stream(dev_info)) {
case SND_PCM_STREAM_PLAYBACK:
@ -141,62 +141,56 @@ fill_item(struct impl *this, snd_ctl_card_info_t *card_info, snd_pcm_info_t *dev
snprintf(card_name, 64, "%s,%d", this->card_name, snd_pcm_info_get_device(dev_info));
spa_pod_builder_add(&b,
SPA_POD_TYPE_OBJECT, &f[0], 0, this->type.monitor.MonitorItem,
SPA_POD_PROP(&f[1], this->type.monitor.id, 0, SPA_POD_TYPE_STRING, 1,
name),
SPA_POD_PROP(&f[1], this->type.monitor.flags, 0, SPA_POD_TYPE_INT, 1,
0),
SPA_POD_PROP(&f[1], this->type.monitor.state, 0, SPA_POD_TYPE_INT, 1,
SPA_MONITOR_ITEM_STATE_AVAILABLE),
SPA_POD_PROP(&f[1], this->type.monitor.name, 0, SPA_POD_TYPE_STRING, 1,
name),
SPA_POD_PROP(&f[1], this->type.monitor.klass, 0, SPA_POD_TYPE_STRING, 1,
klass),
SPA_POD_PROP(&f[1], this->type.monitor.factory, 0, SPA_POD_TYPE_POINTER, 1,
this->type.handle_factory, factory), 0);
"<", 0, t->monitor.MonitorItem,
":", t->monitor.id, "s", name,
":", t->monitor.flags, "i", 0,
":", t->monitor.state, "i", SPA_MONITOR_ITEM_STATE_AVAILABLE,
":", t->monitor.name, "s", name,
":", t->monitor.klass, "s", klass,
":", t->monitor.factory, "p", t->handle_factory, factory, NULL);
spa_pod_builder_add(&b,
SPA_POD_TYPE_PROP, &f[1], this->type.monitor.info, 0,
SPA_POD_TYPE_STRUCT, 1, &f[2], 0);
":", t->monitor.info, "[", NULL);
spa_pod_builder_add(&b,
SPA_POD_TYPE_STRING, "alsa.card", SPA_POD_TYPE_STRING, card_name,
SPA_POD_TYPE_STRING, "alsa.card.id", SPA_POD_TYPE_STRING, snd_ctl_card_info_get_id(card_info),
SPA_POD_TYPE_STRING, "alsa.card.components", SPA_POD_TYPE_STRING, snd_ctl_card_info_get_components(card_info),
SPA_POD_TYPE_STRING, "alsa.card.driver", SPA_POD_TYPE_STRING, snd_ctl_card_info_get_driver(card_info),
SPA_POD_TYPE_STRING, "alsa.card.name", SPA_POD_TYPE_STRING, snd_ctl_card_info_get_name(card_info),
SPA_POD_TYPE_STRING, "alsa.card.longname", SPA_POD_TYPE_STRING, snd_ctl_card_info_get_longname(card_info),
SPA_POD_TYPE_STRING, "alsa.card.mixername", SPA_POD_TYPE_STRING, snd_ctl_card_info_get_mixername(card_info),
SPA_POD_TYPE_STRING, "udev-probed", SPA_POD_TYPE_STRING, "1",
SPA_POD_TYPE_STRING, "device.api", SPA_POD_TYPE_STRING, "alsa",
SPA_POD_TYPE_STRING, "alsa.pcm.id", SPA_POD_TYPE_STRING, snd_pcm_info_get_id(dev_info),
SPA_POD_TYPE_STRING, "alsa.pcm.name", SPA_POD_TYPE_STRING, snd_pcm_info_get_name(dev_info),
SPA_POD_TYPE_STRING, "alsa.pcm.subname", SPA_POD_TYPE_STRING, snd_pcm_info_get_subdevice_name(dev_info), 0);
"s", "alsa.card", "s", card_name,
"s", "alsa.card.id", "s", snd_ctl_card_info_get_id(card_info),
"s", "alsa.card.components", "s", snd_ctl_card_info_get_components(card_info),
"s", "alsa.card.driver", "s", snd_ctl_card_info_get_driver(card_info),
"s", "alsa.card.name", "s", snd_ctl_card_info_get_name(card_info),
"s", "alsa.card.longname", "s", snd_ctl_card_info_get_longname(card_info),
"s", "alsa.card.mixername", "s", snd_ctl_card_info_get_mixername(card_info),
"s", "udev-probed", "s", "1",
"s", "device.api", "s", "alsa",
"s", "alsa.pcm.id", "s", snd_pcm_info_get_id(dev_info),
"s", "alsa.pcm.name", "s", snd_pcm_info_get_name(dev_info),
"s", "alsa.pcm.subname", "s", snd_pcm_info_get_subdevice_name(dev_info),
NULL);
if ((str = udev_device_get_property_value(dev, "SOUND_CLASS")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.class", SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.class", "s", str, NULL);
}
str = udev_device_get_property_value(dev, "ID_PATH");
if (!(str && *str))
str = udev_device_get_syspath(dev);
if (str && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.bus_path", SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.bus_path", "s", str, 0);
}
if ((str = udev_device_get_syspath(dev)) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "sysfs.path", SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "sysfs.path", "s", str, 0);
}
if ((str = udev_device_get_property_value(dev, "ID_ID")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "udev.id", SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "udev.id", "s", str, 0);
}
if ((str = udev_device_get_property_value(dev, "ID_BUS")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.bus", SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.bus", "s", str, 0);
}
if ((str = udev_device_get_property_value(dev, "SUBSYSTEM")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.subsystem", SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.subsystem", "s", str, 0);
}
if ((str = udev_device_get_property_value(dev, "ID_VENDOR_ID")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.vendor.id", SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.vendor.id", "s", str, 0);
}
str = udev_device_get_property_value(dev, "ID_VENDOR_FROM_DATABASE");
if (!(str && *str)) {
@ -206,26 +200,20 @@ fill_item(struct impl *this, snd_ctl_card_info_t *card_info, snd_pcm_info_t *dev
}
}
if (str && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.vendor.name", SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.vendor.name", "s", str, 0);
}
if ((str = udev_device_get_property_value(dev, "ID_MODEL_ID")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.product.id", SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.product.id", "s", str, 0);
}
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.product.name", SPA_POD_TYPE_STRING, name, 0);
spa_pod_builder_add(&b, "s", "device.product.name", "s", name, 0);
if ((str = udev_device_get_property_value(dev, "ID_SERIAL")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.serial", SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.serial", "s", str, 0);
}
if ((str = udev_device_get_property_value(dev, "SOUND_FORM_FACTOR")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.form_factor", SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.form_factor", "s", str, 0);
}
spa_pod_builder_add(&b,
-SPA_POD_TYPE_STRUCT, &f[2],
-SPA_POD_TYPE_PROP, &f[1],
-SPA_POD_TYPE_OBJECT, &f[0], 0);
this->item = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_monitor_item);
this->item = spa_pod_builder_add(&b, "]>", NULL);
return 0;
}
@ -342,14 +330,12 @@ static void impl_on_fd_events(struct spa_source *source)
while (true) {
uint8_t buffer[4096];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
struct spa_pod_frame f[1];
struct spa_event *event;
if (get_next_device(this, dev) < 0)
break;
spa_pod_builder_object(&b, &f[0], 0, type, SPA_POD_TYPE_POD, this->item);
event = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_event);
event = spa_pod_builder_object(&b, 0, type, "P", this->item);
this->callbacks->event(this->callbacks_data, event);
}
close_card(this);

View file

@ -44,7 +44,6 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
{
struct state *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS);
@ -53,17 +52,13 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer));
spa_pod_builder_props(&b, &f[0], this->type.props,
PROP(&f[1], this->type.prop_device, -SPA_POD_TYPE_STRING,
this->props.device, sizeof(this->props.device)),
PROP(&f[1], this->type.prop_device_name, -SPA_POD_TYPE_STRING,
this->props.device_name, sizeof(this->props.device_name)),
PROP(&f[1], this->type.prop_card_name, -SPA_POD_TYPE_STRING,
this->props.card_name, sizeof(this->props.card_name)),
PROP_MM(&f[1], this->type.prop_min_latency, SPA_POD_TYPE_INT,
this->props.min_latency,
1, INT32_MAX));
*props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
*props = spa_pod_builder_props(&b,
this->type.props,
":", this->type.prop_device, "S", this->props.device, sizeof(this->props.device),
":", this->type.prop_device_name, "S", this->props.device_name, sizeof(this->props.device_name),
":", this->type.prop_card_name, "S", this->props.card_name, sizeof(this->props.card_name),
":", this->type.prop_min_latency, "ir", this->props.min_latency,
2, 1, INT32_MAX);
return SPA_RESULT_OK;
}
@ -80,10 +75,9 @@ static int impl_node_set_props(struct spa_node *node, const struct spa_props *pr
reset_props(&this->props);
return SPA_RESULT_OK;
} else {
spa_props_query(props,
this->type.prop_device, -SPA_POD_TYPE_STRING,
this->props.device, sizeof(this->props.device),
this->type.prop_min_latency, SPA_POD_TYPE_INT, &this->props.min_latency, 0);
spa_props_parse(props,
":", this->type.prop_device, "?S", this->props.device, sizeof(this->props.device),
":", this->type.prop_min_latency, "?i", &this->props.min_latency, NULL);
}
return SPA_RESULT_OK;
}
@ -273,7 +267,7 @@ impl_node_port_set_format(struct spa_node *node,
info.media_subtype != this->type.media_subtype.raw)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!spa_format_audio_raw_parse(format, &info.info.raw, &this->type.format_audio))
if (spa_format_audio_raw_parse(format, &info.info.raw, &this->type.format_audio) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (spa_alsa_set_format(this, &info, flags) < 0)
@ -299,12 +293,13 @@ impl_node_port_get_format(struct spa_node *node,
{
struct state *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -312,16 +307,12 @@ impl_node_port_get_format(struct spa_node *node,
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
spa_pod_builder_format(&b, &f[0], this->type.format,
this->type.media_type.audio,
this->type.media_subtype.raw,
PROP(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID,
this->current_format.info.raw.format),
PROP(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT,
this->current_format.info.raw.rate),
PROP(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT,
this->current_format.info.raw.channels));
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
*format = spa_pod_builder_format(&b,
t->format,
t->media_type.audio, t->media_subtype.raw,
":", t->format_audio.format, "I", this->current_format.info.raw.format,
":", t->format_audio.rate, "i", this->current_format.info.raw.rate,
":", t->format_audio.channels, "i", this->current_format.info.raw.channels);
return SPA_RESULT_OK;
}
@ -354,12 +345,13 @@ impl_node_port_enum_params(struct spa_node *node,
struct state *this;
struct spa_pod_builder b = { NULL };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -367,48 +359,40 @@ impl_node_port_enum_params(struct spa_node *node,
switch (index) {
case 0:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers,
PROP_U_MM(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
this->props.min_latency * this->frame_size,
this->props.min_latency * this->frame_size, INT32_MAX),
PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT,
0),
PROP_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
2, 2, 32),
PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT,
16));
*param = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "iru", this->props.min_latency * this->frame_size,
2, this->props.min_latency * this->frame_size,
INT32_MAX,
":", t->param_alloc_buffers.stride, "i", 0,
":", t->param_alloc_buffers.buffers, "ir", 2,
2, 2, 32,
":", t->param_alloc_buffers.align, "i", 16);
break;
case 1:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable,
PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
this->type.meta.Header),
PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
*param = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
break;
case 2:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable,
PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
this->type.meta.Ringbuffer),
PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_ringbuffer)),
PROP(&f[1], this->type.param_alloc_meta_enable.ringbufferSize, SPA_POD_TYPE_INT,
this->period_frames * this->frame_size * 32),
PROP(&f[1], this->type.param_alloc_meta_enable.ringbufferStride, SPA_POD_TYPE_INT,
0),
PROP(&f[1], this->type.param_alloc_meta_enable.ringbufferBlocks, SPA_POD_TYPE_INT,
1),
PROP(&f[1], this->type.param_alloc_meta_enable.ringbufferAlign, SPA_POD_TYPE_INT,
16));
*param = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Ringbuffer,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_ringbuffer),
":", t->param_alloc_meta_enable.ringbufferSize, "i", this->period_frames *
this->frame_size * 32,
":", t->param_alloc_meta_enable.ringbufferStride, "i", 0,
":", t->param_alloc_meta_enable.ringbufferBlocks, "i", 1,
":", t->param_alloc_meta_enable.ringbufferAlign, "i", 16);
break;
default:
return SPA_RESULT_NOT_IMPLEMENTED;
}
*param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
return SPA_RESULT_OK;
}

View file

@ -45,7 +45,6 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
{
struct state *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS);
@ -54,17 +53,13 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer));
spa_pod_builder_props(&b, &f[0], this->type.props,
PROP(&f[1], this->type.prop_device, -SPA_POD_TYPE_STRING,
this->props.device, sizeof(this->props.device)),
PROP(&f[1], this->type.prop_device_name, -SPA_POD_TYPE_STRING,
this->props.device_name, sizeof(this->props.device_name)),
PROP(&f[1], this->type. prop_card_name, -SPA_POD_TYPE_STRING,
this->props.card_name, sizeof(this->props.card_name)),
PROP_MM(&f[1], this->type.prop_min_latency, SPA_POD_TYPE_INT,
this->props.min_latency, 1, INT32_MAX));
*props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
*props = spa_pod_builder_props(&b,
this->type.props,
":", this->type.prop_device, "S", this->props.device, sizeof(this->props.device),
":", this->type.prop_device_name, "S", this->props.device_name, sizeof(this->props.device_name),
":", this->type.prop_card_name, "S", this->props.card_name, sizeof(this->props.card_name),
":", this->type.prop_min_latency, "ir", this->props.min_latency,
2, 1, INT32_MAX);
return SPA_RESULT_OK;
}
@ -81,10 +76,9 @@ static int impl_node_set_props(struct spa_node *node, const struct spa_props *pr
reset_props(&this->props);
return SPA_RESULT_OK;
} else {
spa_props_query(props,
this->type.prop_device, -SPA_POD_TYPE_STRING,
this->props.device, sizeof(this->props.device),
this->type.prop_min_latency, SPA_POD_TYPE_INT, &this->props.min_latency, 0);
spa_props_parse(props,
":", this->type.prop_device, "?S", this->props.device, sizeof(this->props.device),
":", this->type.prop_min_latency, "?i", &this->props.min_latency, NULL);
}
return SPA_RESULT_OK;
@ -300,7 +294,7 @@ impl_node_port_set_format(struct spa_node *node,
info.media_subtype != this->type.media_subtype.raw)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!spa_format_audio_raw_parse(format, &info.info.raw, &this->type.format_audio))
if (spa_format_audio_raw_parse(format, &info.info.raw, &this->type.format_audio) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (spa_alsa_set_format(this, &info, flags) < 0)
@ -324,12 +318,13 @@ impl_node_port_get_format(struct spa_node *node,
{
struct state *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -337,16 +332,12 @@ impl_node_port_get_format(struct spa_node *node,
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
spa_pod_builder_format(&b, &f[0], this->type.format,
this->type.media_type.audio,
this->type.media_subtype.raw,
PROP(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID,
this->current_format.info.raw.format),
PROP(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT,
this->current_format.info.raw.rate),
PROP(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT,
this->current_format.info.raw.channels));
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
*format = spa_pod_builder_format(&b,
t->format,
t->media_type.audio, t->media_subtype.raw,
":", t->format_audio.format, "I", this->current_format.info.raw.format,
":", t->format_audio.rate, "i", this->current_format.info.raw.rate,
":", t->format_audio.channels, "i", this->current_format.info.raw.channels);
return SPA_RESULT_OK;
}
@ -375,12 +366,13 @@ impl_node_port_enum_params(struct spa_node *node,
{
struct state *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -388,32 +380,26 @@ impl_node_port_enum_params(struct spa_node *node,
switch (index) {
case 0:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers,
PROP(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT
, this->props.min_latency * this->frame_size),
PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT,
0),
PROP_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
32,
1, 32),
PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT,
16));
*param = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "i", this->props.min_latency * this->frame_size,
":", t->param_alloc_buffers.stride, "i", 0,
":", t->param_alloc_buffers.buffers, "i", 2,
2, 1, 32,
":", t->param_alloc_buffers.align, "i", 16);
break;
case 1:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable,
PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
this->type.meta.Header),
PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
*param = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
break;
default:
return SPA_RESULT_NOT_IMPLEMENTED;
}
*param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
return SPA_RESULT_OK;
}

View file

@ -161,19 +161,6 @@ struct state {
int64_t last_monotonic;
};
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
#define PROP_U_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
int
spa_alsa_enum_format(struct state *state,
struct spa_format **format, const struct spa_format *filter, uint32_t index);

View file

@ -122,19 +122,6 @@ struct impl {
#define GET_OUT_PORT(this,p) (&this->out_ports[p])
#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p))
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
#define PROP_U_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
{
return SPA_RESULT_NOT_IMPLEMENTED;
@ -310,13 +297,14 @@ impl_node_port_enum_formats(struct spa_node *node,
struct spa_format *fmt;
uint8_t buffer[256];
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
uint32_t count, match;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -327,24 +315,20 @@ impl_node_port_enum_formats(struct spa_node *node,
switch (count++) {
case 0:
spa_pod_builder_format(&b, &f[0], this->type.format,
this->type.media_type.audio,
this->type.media_subtype.raw,
PROP_U_EN(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, 3,
this->type.audio_format.S16,
this->type.audio_format.S16,
this->type.audio_format.F32),
PROP_U_MM(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT,
44100,
1, INT32_MAX),
PROP_U_MM(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT,
2,
1, INT32_MAX));
fmt = spa_pod_builder_format(&b,
t->format,
t->media_type.audio, t->media_subtype.raw,
":", t->format_audio.format, "Ieu", t->audio_format.S16,
2, t->audio_format.S16,
t->audio_format.F32,
":", t->format_audio.rate, "iru", 44100,
2, 1, INT32_MAX,
":", t->format_audio.channels, "iru", 2,
2, 1, INT32_MAX);
break;
default:
return SPA_RESULT_ENUM_END;
}
fmt = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
@ -375,10 +359,12 @@ impl_node_port_set_format(struct spa_node *node,
{
struct impl *this;
struct port *port;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -396,11 +382,11 @@ impl_node_port_set_format(struct spa_node *node,
SPA_FORMAT_MEDIA_SUBTYPE(format),
};
if (info.media_type != this->type.media_type.audio ||
info.media_subtype != this->type.media_subtype.raw)
if (info.media_type != t->media_type.audio ||
info.media_subtype != t->media_subtype.raw)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!spa_format_audio_raw_parse(format, &info.info.raw, &this->type.format_audio))
if (spa_format_audio_raw_parse(format, &info.info.raw, &t->format_audio) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (this->have_format) {
@ -409,11 +395,11 @@ impl_node_port_set_format(struct spa_node *node,
} else {
this->have_format = true;
this->format = info;
if (info.info.raw.format == this->type.audio_format.S16) {
if (info.info.raw.format == t->audio_format.S16) {
this->copy = this->ops.copy[CONV_S16_S16];
this->add = this->ops.add[CONV_S16_S16];
}
else if (info.info.raw.format == this->type.audio_format.F32) {
else if (info.info.raw.format == t->audio_format.F32) {
this->copy = this->ops.copy[CONV_F32_F32];
this->add = this->ops.add[CONV_F32_F32];
}
@ -437,12 +423,13 @@ impl_node_port_get_format(struct spa_node *node,
struct impl *this;
struct port *port;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -452,16 +439,12 @@ impl_node_port_get_format(struct spa_node *node,
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
spa_pod_builder_format(&b, &f[0], this->type.format,
this->type.media_type.audio,
this->type.media_subtype.raw,
PROP(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID,
this->format.info.raw.format),
PROP(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT,
this->format.info.raw.rate),
PROP(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT,
this->format.info.raw.channels));
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
*format = spa_pod_builder_format(&b,
t->format,
t->media_type.audio, t->media_subtype.raw,
":", t->format_audio.format, "I", this->format.info.raw.format,
":", t->format_audio.rate, "i", this->format.info.raw.rate,
":", t->format_audio.channels, "i", this->format.info.raw.channels);
return SPA_RESULT_OK;
}
@ -517,10 +500,12 @@ impl_node_port_use_buffers(struct spa_node *node,
struct impl *this;
struct port *port;
uint32_t i;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -537,11 +522,11 @@ impl_node_port_use_buffers(struct spa_node *node,
b = &port->buffers[i];
b->outbuf = buffers[i];
b->outstanding = direction == SPA_DIRECTION_INPUT ? true : false;
b->h = spa_buffer_find_meta(buffers[i], this->type.meta.Header);
b->h = spa_buffer_find_meta(buffers[i], t->meta.Header);
if (!((d[0].type == this->type.data.MemPtr ||
d[0].type == this->type.data.MemFd ||
d[0].type == this->type.data.DmaBuf) && d[0].data != NULL)) {
if (!((d[0].type == t->data.MemPtr ||
d[0].type == t->data.MemFd ||
d[0].type == t->data.DmaBuf) && d[0].data != NULL)) {
spa_log_error(this->log, NAME " %p: invalid memory on buffer %p", this,
buffers[i]);
return SPA_RESULT_ERROR;

View file

@ -169,46 +169,28 @@ static void reset_props(struct impl *this, struct props *props)
props->volume = DEFAULT_VOLUME;
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
#define PROP_U_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer));
spa_pod_builder_props(&b, &f[0], this->type.props,
PROP(&f[1], this->type.prop_live, SPA_POD_TYPE_BOOL,
this->props.live),
PROP_EN(&f[1], this->type.prop_wave, SPA_POD_TYPE_ID, 3,
this->props.wave,
this->type.wave_sine,
this->type.wave_square),
PROP_MM(&f[1], this->type.prop_freq, SPA_POD_TYPE_DOUBLE,
this->props.freq,
0.0, 50000000.0),
PROP_MM(&f[1], this->type.prop_volume, SPA_POD_TYPE_DOUBLE,
this->props.volume,
0.0, 10.0));
*props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
*props = spa_pod_builder_props(&b, t->props,
":", t->prop_live, "b", this->props.live,
":", t->prop_wave, "Ie", this->props.wave,
2, t->wave_sine,
t->wave_square,
":", t->prop_freq, "dr", this->props.freq,
2, 0.0, 50000000.0,
":", t->prop_volume, "dr", this->props.volume,
2, 0.0, 10.0);
return SPA_RESULT_OK;
}
@ -216,20 +198,22 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
{
struct impl *this;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
if (props == NULL) {
reset_props(this, &this->props);
} else {
spa_props_query(props,
this->type.prop_live, SPA_POD_TYPE_BOOL, &this->props.live,
this->type.prop_wave, SPA_POD_TYPE_ID, &this->props.wave,
this->type.prop_freq, SPA_POD_TYPE_DOUBLE, &this->props.freq,
this->type.prop_volume, SPA_POD_TYPE_DOUBLE, &this->props.volume,
0);
spa_props_parse(props,
":",t->prop_live, "?b", &this->props.live,
":",t->prop_wave, "?I", &this->props.wave,
":",t->prop_freq, "?d", &this->props.freq,
":",t->prop_volume, "?d", &this->props.volume,
NULL);
}
if (this->props.live)
@ -483,13 +467,14 @@ impl_node_port_enum_formats(struct spa_node *node,
struct spa_format *fmt;
uint8_t buffer[256];
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
uint32_t count, match;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -500,26 +485,22 @@ impl_node_port_enum_formats(struct spa_node *node,
switch (count++) {
case 0:
spa_pod_builder_format(&b, &f[0], this->type.format,
this->type.media_type.audio,
this->type.media_subtype.raw,
PROP_U_EN(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, 5,
this->type.audio_format.S16,
this->type.audio_format.S16,
this->type.audio_format.S32,
this->type.audio_format.F32,
this->type.audio_format.F64),
PROP_U_MM(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT,
44100,
1, INT32_MAX),
PROP_U_MM(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT,
2,
1, INT32_MAX));
fmt = spa_pod_builder_format(&b, t->format,
t->media_type.audio,
t->media_subtype.raw,
":", t->format_audio.format, "Ieu", t->audio_format.S16,
4, t->audio_format.S16,
t->audio_format.S32,
t->audio_format.F32,
t->audio_format.F64,
":", t->format_audio.rate, "iru", 44100,
2, 1, INT32_MAX,
":", t->format_audio.channels, "iru", 2,
2, 1, INT32_MAX);
break;
default:
return SPA_RESULT_ENUM_END;
}
fmt = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
@ -551,10 +532,12 @@ impl_node_port_set_format(struct spa_node *node,
const struct spa_format *format)
{
struct impl *this;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -568,20 +551,20 @@ impl_node_port_set_format(struct spa_node *node,
int idx;
int sizes[4] = { 2, 4, 4, 8 };
if (info.media_type != this->type.media_type.audio ||
info.media_subtype != this->type.media_subtype.raw)
if (info.media_type != t->media_type.audio ||
info.media_subtype != t->media_subtype.raw)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!spa_format_audio_raw_parse(format, &info.info.raw, &this->type.format_audio))
if (spa_format_audio_raw_parse(format, &info.info.raw, &t->format_audio) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (info.info.raw.format == this->type.audio_format.S16)
if (info.info.raw.format == t->audio_format.S16)
idx = 0;
else if (info.info.raw.format == this->type.audio_format.S32)
else if (info.info.raw.format == t->audio_format.S32)
idx = 1;
else if (info.info.raw.format == this->type.audio_format.F32)
else if (info.info.raw.format == t->audio_format.F32)
idx = 2;
else if (info.info.raw.format == this->type.audio_format.F64)
else if (info.info.raw.format == t->audio_format.F64)
idx = 3;
else
return SPA_RESULT_INVALID_MEDIA_TYPE;
@ -607,12 +590,13 @@ impl_node_port_get_format(struct spa_node *node,
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -620,17 +604,11 @@ impl_node_port_get_format(struct spa_node *node,
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
spa_pod_builder_format(&b, &f[0], this->type.format,
this->type.media_type.audio,
this->type.media_subtype.raw,
PROP(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID,
this->current_format.info.raw.format),
PROP(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT,
this->current_format.info.raw.rate),
PROP(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT,
this->current_format.info.raw.channels));
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
*format = spa_pod_builder_format(&b, t->format,
t->media_type.audio, t->media_subtype.raw,
":", t->format_audio.format, "I", this->current_format.info.raw.format,
":", t->format_audio.rate, "i", this->current_format.info.raw.rate,
":", t->format_audio.channels, "i", this->current_format.info.raw.channels);
return SPA_RESULT_OK;
}
@ -664,12 +642,13 @@ impl_node_port_enum_params(struct spa_node *node,
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -677,30 +656,28 @@ impl_node_port_enum_params(struct spa_node *node,
switch (index) {
case 0:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers,
PROP_U_MM(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
1024 * this->bpf,
16 * this->bpf,
INT32_MAX / this->bpf),
PROP (&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, 0),
PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT, 2, 1, 32),
PROP (&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16));
*param = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "iru", 1024 * this->bpf,
2, 16 * this->bpf,
INT32_MAX / this->bpf,
":", t->param_alloc_buffers.stride, "i", 0,
":", t->param_alloc_buffers.buffers, "iru", 2,
2, 1, 32,
":", t->param_alloc_buffers.align, "i", 16);
break;
case 1:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable,
PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
this->type.meta.Header),
PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
*param = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
break;
default:
return SPA_RESULT_NOT_IMPLEMENTED;
}
*param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
return SPA_RESULT_OK;
}

View file

@ -244,7 +244,7 @@ spa_ffmpeg_dec_node_port_set_format(struct spa_node *node,
info.media_subtype != this->type.media_subtype.raw)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video))
if (spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {

View file

@ -248,7 +248,7 @@ spa_ffmpeg_enc_node_port_set_format(struct spa_node *node,
info.media_subtype != this->type.media_subtype.raw)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video))
if (spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {

View file

@ -125,24 +125,10 @@ static void reset_props(struct impl *this, struct props *props)
props->live = DEFAULT_LIVE;
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key, SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
#define PROP_U_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS);
@ -150,10 +136,9 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer));
spa_pod_builder_props(&b, &f[0], this->type.props,
PROP(&f[1], this->type.prop_live, SPA_POD_TYPE_BOOL,
this->props.live));
*props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
*props = spa_pod_builder_props(&b,
this->type.props,
":", this->type.prop_live, "b", this->props.live);
return SPA_RESULT_OK;
}
@ -169,8 +154,8 @@ static int impl_node_set_props(struct spa_node *node, const struct spa_props *pr
if (props == NULL) {
reset_props(this, &this->props);
} else {
spa_props_query(props,
this->type.prop_live, SPA_POD_TYPE_BOOL, &this->props.live, 0);
spa_props_parse(props,
":", this->type.prop_live, "?b", &this->props.live, NULL);
}
if (this->props.live)
@ -497,12 +482,13 @@ impl_node_port_enum_params(struct spa_node *node,
{
struct impl *this;
struct spa_pod_builder b = { NULL };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -510,30 +496,25 @@ impl_node_port_enum_params(struct spa_node *node,
switch (index) {
case 0:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers,
PROP(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
128),
PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT,
1),
PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
32,
2, 32),
PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT,
16));
*param = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "i", 128,
":", t->param_alloc_buffers.stride, "i", 1,
":", t->param_alloc_buffers.buffers, "ir", 2,
2, 1, 32,
":", t->param_alloc_buffers.align, "i", 16);
break;
case 1:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable,
PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
this->type.meta.Header),
PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
*param = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
break;
default:
return SPA_RESULT_NOT_IMPLEMENTED;
}
*param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
return SPA_RESULT_OK;
}

View file

@ -131,39 +131,24 @@ static void reset_props(struct impl *this, struct props *props)
props->pattern = DEFAULT_PATTERN;
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key, SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
#define PROP_U_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer));
spa_pod_builder_props(&b, &f[0], this->type.props,
PROP(&f[1], this->type.prop_live, SPA_POD_TYPE_BOOL,
this->props.live),
PROP_EN(&f[1], this->type.prop_pattern, SPA_POD_TYPE_ID, 1,
this->props.pattern,
this->props.pattern));
*props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
*props = spa_pod_builder_props(&b,
t->props,
":", t->prop_live, "b", this->props.live,
":", t->prop_pattern, "Ie", this->props.pattern,
1, this->props.pattern);
return SPA_RESULT_OK;
}
@ -171,17 +156,19 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
{
struct impl *this;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
if (props == NULL) {
reset_props(this, &this->props);
} else {
spa_props_query(props,
this->type.prop_live, SPA_POD_TYPE_BOOL, &this->props.live,
this->type.prop_pattern, SPA_POD_TYPE_ID, &this->props.pattern, 0);
spa_props_parse(props,
":", t->prop_live, "?b", &this->props.live,
":", t->prop_pattern, "?I", &this->props.pattern, NULL);
}
if (this->props.live)
@ -514,12 +501,13 @@ impl_node_port_enum_params(struct spa_node *node,
{
struct impl *this;
struct spa_pod_builder b = { NULL };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -527,30 +515,25 @@ impl_node_port_enum_params(struct spa_node *node,
switch (index) {
case 0:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers,
PROP(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
128),
PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT,
1),
PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
32,
2, 32),
PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT,
16));
*param = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "i", 128,
":", t->param_alloc_buffers.stride, "i", 1,
":", t->param_alloc_buffers.buffers, "ir", 32,
2, 2, 32,
":", t->param_alloc_buffers.align, "i", 16);
break;
case 1:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable,
PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
this->type.meta.Header),
PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
*param = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
break;
default:
return SPA_RESULT_NOT_IMPLEMENTED;
}
*param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
return SPA_RESULT_OK;
}

View file

@ -89,7 +89,7 @@ static void fill_item(struct impl *this, struct item *item, struct udev_device *
{
const char *str, *name;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[3];
struct type *t = &this->type;
if (item->udevice)
udev_device_unref(item->udevice);
@ -112,59 +112,43 @@ static void fill_item(struct impl *this, struct item *item, struct udev_device *
spa_pod_builder_init(&b, this->item_buffer, sizeof(this->item_buffer));
spa_pod_builder_push_object(&b, &f[0], 0, this->type.monitor.MonitorItem);
spa_pod_builder_add(&b,
"<", 0, t->monitor.MonitorItem,
":", t->monitor.id, "s", udev_device_get_syspath(item->udevice),
":", t->monitor.flags, "i", 0,
":", t->monitor.state, "i", SPA_MONITOR_ITEM_STATE_AVAILABLE,
":", t->monitor.name, "s", name,
":", t->monitor.klass, "s", "Video/Source",
":", t->monitor.factory, "p", t->handle_factory, &spa_v4l2_source_factory,
":", t->monitor.info, "[",
NULL);
spa_pod_builder_add(&b,
SPA_POD_PROP(&f[1], this->type.monitor.id, 0, SPA_POD_TYPE_STRING, 1,
udev_device_get_syspath(item->udevice)),
SPA_POD_PROP(&f[1], this->type.monitor.flags, 0, SPA_POD_TYPE_INT, 1,
0),
SPA_POD_PROP(&f[1], this->type.monitor.state, 0, SPA_POD_TYPE_INT, 1,
SPA_MONITOR_ITEM_STATE_AVAILABLE),
SPA_POD_PROP(&f[1], this->type.monitor.name, 0, SPA_POD_TYPE_STRING, 1,
name),
SPA_POD_PROP(&f[1], this->type.monitor.klass, 0, SPA_POD_TYPE_STRING, 1,
"Video/Source"),
SPA_POD_PROP(&f[1], this->type.monitor.factory, 0, SPA_POD_TYPE_POINTER, 1,
this->type.handle_factory, &spa_v4l2_source_factory),
0);
spa_pod_builder_add(&b,
SPA_POD_TYPE_PROP, &f[1], this->type.monitor.info, 0,
SPA_POD_TYPE_STRUCT, 1, &f[2], 0);
spa_pod_builder_add(&b,
SPA_POD_TYPE_STRING, "udev-probed", SPA_POD_TYPE_STRING, "1",
SPA_POD_TYPE_STRING, "device.api", SPA_POD_TYPE_STRING, "v4l2",
SPA_POD_TYPE_STRING, "device.path", SPA_POD_TYPE_STRING,
udev_device_get_devnode(item->udevice), 0);
"s", "udev-probed", "s", "1",
"s", "device.api", "s", "v4l2",
"s", "device.path", "s", udev_device_get_devnode(item->udevice),
NULL);
str = udev_device_get_property_value(item->udevice, "ID_PATH");
if (!(str && *str))
str = udev_device_get_syspath(item->udevice);
if (str && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.bus_path", SPA_POD_TYPE_STRING,
str, 0);
spa_pod_builder_add(&b, "s", "device.bus_path", "s", str, 0);
}
if ((str = udev_device_get_syspath(item->udevice)) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "sysfs.path", SPA_POD_TYPE_STRING,
str, 0);
spa_pod_builder_add(&b, "s", "sysfs.path", "s", str, 0);
}
if ((str = udev_device_get_property_value(item->udevice, "ID_ID")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "udev.id", SPA_POD_TYPE_STRING,
str, 0);
spa_pod_builder_add(&b, "s", "udev.id", "s", str, 0);
}
if ((str = udev_device_get_property_value(item->udevice, "ID_BUS")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.bus", SPA_POD_TYPE_STRING,
str, 0);
spa_pod_builder_add(&b, "s", "device.bus", "s", str, 0);
}
if ((str = udev_device_get_property_value(item->udevice, "SUBSYSTEM")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.subsystem",
SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.subsystem", "s", str, 0);
}
if ((str = udev_device_get_property_value(item->udevice, "ID_VENDOR_ID")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.vendor.id",
SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.vendor.id", "s", str, 0);
}
str = udev_device_get_property_value(item->udevice, "ID_VENDOR_FROM_DATABASE");
if (!(str && *str)) {
@ -174,29 +158,20 @@ static void fill_item(struct impl *this, struct item *item, struct udev_device *
}
}
if (str && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.vendor.name",
SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.vendor.name", "s", str, 0);
}
if ((str = udev_device_get_property_value(item->udevice, "ID_MODEL_ID")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.product.id",
SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.product.id", "s", str, 0);
}
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.product.name", SPA_POD_TYPE_STRING,
name, 0);
spa_pod_builder_add(&b, "s", "device.product.name", "s", name, 0);
if ((str = udev_device_get_property_value(item->udevice, "ID_SERIAL")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.serial", SPA_POD_TYPE_STRING,
str, 0);
spa_pod_builder_add(&b, "s", "device.serial", "s", str, 0);
}
if ((str = udev_device_get_property_value(item->udevice, "ID_V4L_CAPABILITIES")) && *str) {
spa_pod_builder_add(&b, SPA_POD_TYPE_STRING, "device.capabilities",
SPA_POD_TYPE_STRING, str, 0);
spa_pod_builder_add(&b, "s", "device.capabilities", "s", str, 0);
}
spa_pod_builder_add(&b, -SPA_POD_TYPE_STRUCT, &f[2], -SPA_POD_TYPE_PROP, &f[1], 0);
spa_pod_builder_pop(&b, &f[0]);
item->item = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_monitor_item);
item->item = spa_pod_builder_add(&b, "]>", NULL);
}
static void impl_on_fd_events(struct spa_source *source)
@ -207,7 +182,6 @@ static void impl_on_fd_events(struct spa_source *source)
const char *action;
uint32_t type;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[1];
uint8_t buffer[4096];
dev = udev_monitor_receive_device(this->umonitor);
@ -228,9 +202,8 @@ static void impl_on_fd_events(struct spa_source *source)
return;
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_object(&b, &f[0], 0, type, SPA_POD_TYPE_POD, this->uitem.item);
event = spa_pod_builder_object(&b, 0, type, "P", this->uitem.item);
event = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_event);
this->callbacks->event(this->callbacks_data, event);
}

View file

@ -166,42 +166,25 @@ struct impl {
#define CHECK_PORT(this,direction,port_id) ((direction) == SPA_DIRECTION_OUTPUT && (port_id) == 0)
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_R(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_READONLY,type,1,__VA_ARGS__)
#define PROP_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
#define PROP_U_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
#include "v4l2-utils.c"
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer));
spa_pod_builder_props(&b, &f[0], this->type.props,
PROP(&f[1], this->type.prop_device, -SPA_POD_TYPE_STRING,
this->props.device, sizeof(this->props.device)),
PROP_R(&f[1], this->type.prop_device_name, -SPA_POD_TYPE_STRING,
this->props.device_name, sizeof(this->props.device_name)),
PROP_R(&f[1], this->type.prop_device_fd, SPA_POD_TYPE_INT,
this->props.device_fd));
*props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
*props = spa_pod_builder_props(&b, t->props,
":", t->prop_device, "S", this->props.device, sizeof(this->props.device),
":", t->prop_device_name, "S-r", this->props.device_name, sizeof(this->props.device_name),
":", t->prop_device_fd, "i-r", this->props.device_fd);
return SPA_RESULT_OK;
}
@ -209,18 +192,20 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
{
struct impl *this;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
if (props == NULL) {
reset_props(&this->props);
return SPA_RESULT_OK;
} else {
spa_props_query(props, this->type.prop_device, -SPA_POD_TYPE_STRING,
this->props.device, sizeof(this->props.device), 0);
}
spa_props_parse(props,
":", t->prop_device, "?S", this->props.device, sizeof(this->props.device), NULL);
return SPA_RESULT_OK;
}
@ -456,10 +441,12 @@ static int impl_node_port_set_format(struct spa_node *node,
struct impl *this;
struct port *state;
struct spa_video_info info;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -475,13 +462,13 @@ static int impl_node_port_set_format(struct spa_node *node,
info.media_type = SPA_FORMAT_MEDIA_TYPE(format);
info.media_subtype = SPA_FORMAT_MEDIA_SUBTYPE(format);
if (info.media_type != this->type.media_type.video) {
if (info.media_type != t->media_type.video) {
spa_log_error(this->log, "media type must be video");
return SPA_RESULT_INVALID_MEDIA_TYPE;
}
if (info.media_subtype == this->type.media_subtype.raw) {
if (!spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video)) {
if (info.media_subtype == t->media_subtype.raw) {
if (spa_format_video_raw_parse(format, &info.info.raw, &t->format_video) < 0) {
spa_log_error(this->log, "can't parse video raw");
return SPA_RESULT_INVALID_MEDIA_TYPE;
}
@ -492,8 +479,8 @@ static int impl_node_port_set_format(struct spa_node *node,
info.info.raw.size.width == state->current_format.info.raw.size.width &&
info.info.raw.size.height == state->current_format.info.raw.size.height)
return SPA_RESULT_OK;
} else if (info.media_subtype == this->type.media_subtype_video.mjpg) {
if (!spa_format_video_mjpg_parse(format, &info.info.mjpg, &this->type.format_video))
} else if (info.media_subtype == t->media_subtype_video.mjpg) {
if (spa_format_video_mjpg_parse(format, &info.info.mjpg, &t->format_video) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (state->have_format && info.media_type == state->current_format.media_type &&
@ -501,8 +488,8 @@ static int impl_node_port_set_format(struct spa_node *node,
info.info.mjpg.size.width == state->current_format.info.mjpg.size.width &&
info.info.mjpg.size.height == state->current_format.info.mjpg.size.height)
return SPA_RESULT_OK;
} else if (info.media_subtype == this->type.media_subtype_video.h264) {
if (!spa_format_video_h264_parse(format, &info.info.h264, &this->type.format_video))
} else if (info.media_subtype == t->media_subtype_video.h264) {
if (spa_format_video_h264_parse(format, &info.info.h264, &t->format_video) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (state->have_format && info.media_type == state->current_format.media_type &&
@ -537,12 +524,14 @@ static int impl_node_port_get_format(struct spa_node *node,
struct impl *this;
struct port *state;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct spa_pod_frame f[1];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -554,36 +543,28 @@ static int impl_node_port_get_format(struct spa_node *node,
b.data = state->format_buffer;
b.size = sizeof(state->format_buffer);
spa_pod_builder_push_format(&b, &f[0], this->type.format,
spa_pod_builder_push_format(&b, &f[0], t->format,
state->current_format.media_type,
state->current_format.media_subtype);
if (state->current_format.media_subtype == this->type.media_subtype.raw) {
if (state->current_format.media_subtype == t->media_subtype.raw) {
spa_pod_builder_add(&b,
PROP(&f[1], this->type.format_video.format, SPA_POD_TYPE_ID,
state->current_format.info.raw.format),
PROP(&f[1], this->type.format_video.size, -SPA_POD_TYPE_RECTANGLE,
&state->current_format.info.raw.size),
PROP(&f[1], this->type.format_video.framerate, -SPA_POD_TYPE_FRACTION,
&state->current_format.info.raw.framerate), 0);
} else if (state->current_format.media_subtype == this->type.media_subtype_video.mjpg ||
state->current_format.media_subtype == this->type.media_subtype_video.jpeg) {
":", t->format_video.format, "I", state->current_format.info.raw.format,
":", t->format_video.size, "R", &state->current_format.info.raw.size,
":", t->format_video.framerate, "F", &state->current_format.info.raw.framerate, 0);
} else if (state->current_format.media_subtype == t->media_subtype_video.mjpg ||
state->current_format.media_subtype == t->media_subtype_video.jpeg) {
spa_pod_builder_add(&b,
PROP(&f[1], this->type.format_video.size, -SPA_POD_TYPE_RECTANGLE,
&state->current_format.info.mjpg.size),
PROP(&f[1], this->type.format_video.framerate, -SPA_POD_TYPE_FRACTION,
&state->current_format.info.mjpg.framerate), 0);
} else if (state->current_format.media_subtype == this->type.media_subtype_video.h264) {
":", t->format_video.size, "R", &state->current_format.info.mjpg.size,
":", t->format_video.framerate, "F", &state->current_format.info.mjpg.framerate, 0);
} else if (state->current_format.media_subtype == t->media_subtype_video.h264) {
spa_pod_builder_add(&b,
PROP(&f[1], this->type.format_video.size, -SPA_POD_TYPE_RECTANGLE,
&state->current_format.info.h264.size),
PROP(&f[1], this->type.format_video.framerate, -SPA_POD_TYPE_FRACTION,
&state->current_format.info.h264.framerate), 0);
":", t->format_video.size, "R", &state->current_format.info.h264.size,
":", t->format_video.framerate, "F", &state->current_format.info.h264.framerate, 0);
} else
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_pop(&b, &f[0]);
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
return SPA_RESULT_OK;
@ -618,12 +599,13 @@ static int impl_node_port_enum_params(struct spa_node *node,
struct impl *this;
struct port *state;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -633,30 +615,23 @@ static int impl_node_port_enum_params(struct spa_node *node,
switch (index) {
case 0:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers,
PROP(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
state->fmt.fmt.pix.sizeimage),
PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT,
state->fmt.fmt.pix.bytesperline),
PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
MAX_BUFFERS, 2, MAX_BUFFERS),
PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16));
*param = spa_pod_builder_param(&b, t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "i", state->fmt.fmt.pix.sizeimage,
":", t->param_alloc_buffers.stride, "i", state->fmt.fmt.pix.bytesperline,
":", t->param_alloc_buffers.buffers, "iru", MAX_BUFFERS,
2, 2, MAX_BUFFERS,
":", t->param_alloc_buffers.align, "i", 16);
break;
case 1:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable,
PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
this->type.meta.Header),
PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
*param = spa_pod_builder_param(&b, t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
break;
default:
return SPA_RESULT_NOT_IMPLEMENTED;
}
*param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
return SPA_RESULT_OK;
}

View file

@ -680,12 +680,11 @@ spa_v4l2_enum_format(struct impl *this,
if (media_subtype == this->type.media_subtype.raw) {
spa_pod_builder_add(&b,
PROP(&f[1], this->type.format_video.format, SPA_POD_TYPE_ID,
video_format), 0);
":", this->type.format_video.format, "I", video_format, 0);
}
spa_pod_builder_add(&b,
PROP(&f[1], this->type.format_video.size, SPA_POD_TYPE_RECTANGLE,
state->frmsize.discrete.width, state->frmsize.discrete.height), 0);
":", this->type.format_video.size, "R", &SPA_RECTANGLE(state->frmsize.discrete.width,
state->frmsize.discrete.height), 0);
spa_pod_builder_push_prop(&b, &f[1], this->type.format_video.framerate,
SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_UNSET);

View file

@ -153,40 +153,25 @@ static void reset_props(struct impl *this, struct props *props)
props->pattern = this->type.DEFAULT_PATTERN;
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
#define PROP_U_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer));
spa_pod_builder_props(&b, &f[0], this->type.props,
PROP(&f[1], this->type.prop_live, SPA_POD_TYPE_BOOL,
this->props.live),
PROP_EN(&f[1], this->type.prop_pattern, SPA_POD_TYPE_ID, 3,
this->props.pattern,
this->type.pattern_smpte_snow,
this->type.pattern_snow));
*props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
*props = spa_pod_builder_props(&b,
t->props,
":", t->prop_live, "b", this->props.live,
":", t->prop_pattern, "Ie", this->props.pattern,
2, t->pattern_smpte_snow,
t->pattern_snow);
return SPA_RESULT_OK;
}
@ -194,18 +179,20 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
{
struct impl *this;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
if (props == NULL) {
reset_props(this, &this->props);
} else {
spa_props_query(props,
this->type.prop_live, SPA_POD_TYPE_BOOL, &this->props.live,
this->type.prop_pattern, SPA_POD_TYPE_ID, &this->props.pattern,
0);
spa_props_parse(props,
":", t->prop_live, "?b", &this->props.live,
":", t->prop_pattern, "?I", &this->props.pattern,
NULL);
}
if (this->props.live)
@ -433,13 +420,14 @@ impl_node_port_enum_formats(struct spa_node *node,
struct spa_format *fmt;
uint8_t buffer[256];
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
uint32_t count, match;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -450,26 +438,22 @@ impl_node_port_enum_formats(struct spa_node *node,
switch (count++) {
case 0:
spa_pod_builder_format(&b, &f[0], this->type.format,
this->type.media_type.video,
this->type.media_subtype.raw,
PROP_U_EN(&f[1], this->type.format_video.format, SPA_POD_TYPE_ID, 3,
this->type.video_format.RGB,
this->type.video_format.RGB,
this->type.video_format.UYVY),
PROP_U_MM(&f[1], this->type.format_video.size, SPA_POD_TYPE_RECTANGLE,
320, 240,
1, 1,
INT32_MAX, INT32_MAX),
PROP_U_MM(&f[1], this->type.format_video.framerate, SPA_POD_TYPE_FRACTION,
25, 1,
0, 1,
INT32_MAX, 1));
fmt = spa_pod_builder_format(&b,
t->format,
t->media_type.video, t->media_subtype.raw,
":", t->format_video.format, "Ieu", t->video_format.RGB,
2, t->video_format.RGB,
t->video_format.UYVY,
":", t->format_video.size, "Rru", &SPA_RECTANGLE(320, 240),
2, &SPA_RECTANGLE(1, 1),
&SPA_RECTANGLE(INT32_MAX, INT32_MAX),
":", t->format_video.framerate, "Fru", &SPA_FRACTION(25,1),
2, &SPA_FRACTION(0, 1),
&SPA_FRACTION(INT32_MAX, 1));
break;
default:
return SPA_RESULT_ENUM_END;
}
fmt = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
@ -520,7 +504,7 @@ impl_node_port_set_format(struct spa_node *node,
info.media_subtype != this->type.media_subtype.raw)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video))
if (spa_format_video_raw_parse(format, &info.info.raw, &this->type.format_video) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (info.info.raw.format == this->type.video_format.RGB)
@ -550,12 +534,13 @@ impl_node_port_get_format(struct spa_node *node,
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -563,17 +548,12 @@ impl_node_port_get_format(struct spa_node *node,
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
spa_pod_builder_format(&b, &f[0], this->type.format,
this->type.media_type.video,
this->type.media_subtype.raw,
PROP(&f[1], this->type.format_video.format, SPA_POD_TYPE_ID,
this->current_format.info.raw.format),
PROP(&f[1], this->type.format_video.size, -SPA_POD_TYPE_RECTANGLE,
&this->current_format.info.raw.size),
PROP(&f[1], this->type.format_video.framerate, -SPA_POD_TYPE_FRACTION,
&this->current_format.info.raw.framerate));
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
*format = spa_pod_builder_format(&b,
t->format,
t->media_type.video, t->media_subtype.raw,
":", t->format_video.format, "I", this->current_format.info.raw.format,
":", t->format_video.size, "R", &this->current_format.info.raw.size,
":", t->format_video.framerate, "F", &this->current_format.info.raw.framerate);
return SPA_RESULT_OK;
}
@ -607,12 +587,13 @@ impl_node_port_enum_params(struct spa_node *node,
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -622,31 +603,26 @@ impl_node_port_enum_params(struct spa_node *node,
case 0: {
struct spa_video_info_raw *raw_info = &this->current_format.info.raw;
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers,
PROP(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
this->stride * raw_info->size.height),
PROP(&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT,
this->stride),
PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
2, 1, 32),
PROP(&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT,
16));
*param = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "i", this->stride * raw_info->size.height,
":", t->param_alloc_buffers.stride, "i", this->stride,
":", t->param_alloc_buffers.buffers, "ir", 2,
2, 1, 32,
":", t->param_alloc_buffers.align, "i", 16);
break;
}
case 1:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable,
PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
this->type.meta.Header),
PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
*param = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
break;
default:
return SPA_RESULT_NOT_IMPLEMENTED;
}
*param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
return SPA_RESULT_OK;
}

View file

@ -135,38 +135,23 @@ static void reset_props(struct props *props)
props->mute = DEFAULT_MUTE;
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_U_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer));
spa_pod_builder_props(&b, &f[0], this->type.props,
PROP_MM(&f[1], this->type.prop_volume, SPA_POD_TYPE_DOUBLE,
this->props.volume,
0.0, 10.0),
PROP(&f[1], this->type.prop_mute, SPA_POD_TYPE_BOOL,
this->props.mute));
*props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
*props = spa_pod_builder_props(&b,
t->props,
":", t->prop_volume, "dr", this->props.volume, 2, 0.0, 10.0,
":", t->prop_mute, "b", this->props.mute);
return SPA_RESULT_OK;
}
@ -174,17 +159,19 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
{
struct impl *this;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
if (props == NULL) {
reset_props(&this->props);
} else {
spa_props_query(props,
this->type.prop_volume, SPA_POD_TYPE_DOUBLE, &this->props.volume,
this->type.prop_mute, SPA_POD_TYPE_BOOL, &this->props.mute, 0);
spa_props_parse(props,
":", t->prop_volume, "?d", &this->props.volume,
":", t->prop_mute, "?b", &this->props.mute, NULL);
}
return SPA_RESULT_OK;
}
@ -288,13 +275,14 @@ impl_node_port_enum_formats(struct spa_node *node,
struct spa_format *fmt;
uint8_t buffer[1024];
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
uint32_t count, match;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -305,25 +293,19 @@ impl_node_port_enum_formats(struct spa_node *node,
switch (count++) {
case 0:
spa_pod_builder_format(&b, &f[0], this->type.format,
this->type.media_type.audio,
this->type.media_subtype.raw,
PROP_U_EN(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, 3,
this->type.audio_format.S16,
this->type.audio_format.S16,
this->type.audio_format.S32),
PROP_U_MM(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT,
44100,
1, INT32_MAX),
PROP_U_MM(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT,
2,
1, INT32_MAX));
fmt = spa_pod_builder_format(&b,
t->format,
t->media_type.audio, t->media_subtype.raw,
":", t->format_audio.format, "Ieu", t->audio_format.S16,
2, t->audio_format.S16,
t->audio_format.S32,
":", t->format_audio.rate, "iru", 44100, 2, 1, INT32_MAX,
":", t->format_audio.channels,"iru", 2, 2, 1, INT32_MAX);
break;
default:
return SPA_RESULT_ENUM_END;
}
fmt = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
if ((res = spa_format_filter(fmt, filter, &b)) != SPA_RESULT_OK || match++ != index)
@ -375,7 +357,7 @@ impl_node_port_set_format(struct spa_node *node,
info.media_subtype != this->type.media_subtype.raw)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!spa_format_audio_raw_parse(format, &info.info.raw, &this->type.format_audio))
if (spa_format_audio_raw_parse(format, &info.info.raw, &this->type.format_audio) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
this->bpf = 2 * info.info.raw.channels;
@ -395,12 +377,13 @@ impl_node_port_get_format(struct spa_node *node,
struct impl *this;
struct port *port;
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -411,16 +394,12 @@ impl_node_port_get_format(struct spa_node *node,
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
spa_pod_builder_format(&b, &f[0], this->type.format,
this->type.media_type.audio,
this->type.media_subtype.raw,
PROP(&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID,
this->current_format.info.raw.format),
PROP(&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT,
this->current_format.info.raw.rate),
PROP(&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT,
this->current_format.info.raw.channels));
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
*format = spa_pod_builder_format(&b,
t->format,
t->media_type.audio, t->media_subtype.raw,
":", t->format_audio.format, "I", this->current_format.info.raw.format,
":", t->format_audio.rate, "i", this->current_format.info.raw.rate,
":", t->format_audio.channels, "i", this->current_format.info.raw.channels);
return SPA_RESULT_OK;
}
@ -456,14 +435,15 @@ impl_node_port_enum_params(struct spa_node *node,
struct spa_param **param)
{
struct spa_pod_builder b = { NULL };
struct spa_pod_frame f[2];
struct impl *this;
struct port *port;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(param != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
@ -474,31 +454,28 @@ impl_node_port_enum_params(struct spa_node *node,
switch (index) {
case 0:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_buffers.Buffers,
PROP_U_MM(&f[1], this->type.param_alloc_buffers.size, SPA_POD_TYPE_INT,
1024 * this->bpf,
16 * this->bpf,
INT32_MAX / this->bpf),
PROP (&f[1], this->type.param_alloc_buffers.stride, SPA_POD_TYPE_INT, 0),
PROP_U_MM(&f[1], this->type.param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
2, 1, MAX_BUFFERS),
PROP (&f[1], this->type.param_alloc_buffers.align, SPA_POD_TYPE_INT, 16));
*param = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "iru", 1024 * this->bpf,
2, 16 * this->bpf,
INT32_MAX / this->bpf,
":", t->param_alloc_buffers.stride, "i", 0,
":", t->param_alloc_buffers.buffers, "iru", 2,
2, 1, MAX_BUFFERS,
":", t->param_alloc_buffers.align, "i", 16);
break;
case 1:
spa_pod_builder_object(&b, &f[0], 0, this->type.param_alloc_meta_enable.MetaEnable,
PROP(&f[1], this->type.param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
this->type.meta.Header),
PROP(&f[1], this->type.param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
*param = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
break;
default:
return SPA_RESULT_NOT_IMPLEMENTED;
}
*param = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
return SPA_RESULT_OK;
}

View file

@ -1,26 +1,32 @@
executable('test-mixer', 'test-mixer.c',
include_directories : [spa_inc ],
dependencies : [dl_lib, pthread_lib],
link_with : spalib,
install : false)
executable('test-ringbuffer', 'test-ringbuffer.c',
include_directories : [spa_inc, spa_libinc ],
dependencies : [dl_lib, pthread_lib],
link_with : spalib,
install : false)
executable('test-graph', 'test-graph.c',
include_directories : [spa_inc ],
dependencies : [dl_lib, pthread_lib],
link_with : spalib,
install : false)
executable('test-graph2', 'test-graph2.c',
include_directories : [spa_inc ],
dependencies : [dl_lib, pthread_lib],
link_with : spalib,
install : false)
executable('test-perf', 'test-perf.c',
include_directories : [spa_inc, spa_libinc ],
dependencies : [dl_lib, pthread_lib],
link_with : spalib,
install : false)
executable('stress-ringbuffer', 'stress-ringbuffer.c',
include_directories : [spa_inc, spa_libinc ],
dependencies : [dl_lib, pthread_lib],
link_with : spalib,
install : false)
if sdl_dep.found()
executable('test-v4l2', 'test-v4l2.c',
@ -44,3 +50,13 @@ executable('test-props3', 'test-props3.c',
dependencies : [],
link_with : spalib,
install : false)
#executable('test-props4', 'test-props4.c',
# include_directories : [spa_inc, spa_libinc ],
# dependencies : [],
# link_with : spalib,
# install : false)
executable('test-props5', 'test-props5.c',
include_directories : [spa_inc, spa_libinc ],
dependencies : [],
link_with : spalib,
install : false)

View file

@ -38,6 +38,8 @@
#include <spa/graph.h>
#include <spa/graph-scheduler1.h>
#include <spa/lib/debug.h>
static SPA_TYPE_MAP_IMPL(default_map, 4096);
static SPA_LOG_IMPL(default_log);
@ -281,7 +283,6 @@ static int make_nodes(struct data *data, const char *device)
int res;
struct spa_props *props;
struct spa_pod_builder b = { 0 };
struct spa_pod_frame f[2];
uint8_t buffer[128];
if ((res = make_node(data, &data->sink,
@ -292,12 +293,12 @@ static int make_nodes(struct data *data, const char *device)
spa_node_set_callbacks(data->sink, &sink_callbacks, data);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_props(&b, &f[0], data->type.props,
SPA_POD_PROP(&f[1], data->type.props_device, 0, SPA_POD_TYPE_STRING, 1,
device ? device : "hw:0"),
SPA_POD_PROP(&f[1], data->type.props_min_latency, 0, SPA_POD_TYPE_INT, 1,
MIN_LATENCY));
props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
props = spa_pod_builder_props(&b,
data->type.props,
":", data->type.props_device, "s", device ? device : "hw:0",
":", data->type.props_min_latency, "i", MIN_LATENCY);
spa_debug_pod(&props->object.pod);
if ((res = spa_node_set_props(data->sink, props)) < 0)
printf("got set_props error %d\n", res);
@ -316,14 +317,11 @@ static int make_nodes(struct data *data, const char *device)
}
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_props(&b, &f[0], data->type.props,
SPA_POD_PROP(&f[1], data->type.props_freq, 0, SPA_POD_TYPE_DOUBLE, 1,
600.0),
SPA_POD_PROP(&f[1], data->type.props_volume, 0, SPA_POD_TYPE_DOUBLE, 1,
0.5),
SPA_POD_PROP(&f[1], data->type.props_live, 0, SPA_POD_TYPE_BOOL, 1,
false));
props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
props = spa_pod_builder_props(&b,
data->type.props,
":", data->type.props_freq, "d", 600.0,
":", data->type.props_volume, "d", 0.5,
":", data->type.props_live, "b", false);
if ((res = spa_node_set_props(data->source, props)) < 0)
printf("got set_props error %d\n", res);
@ -370,22 +368,16 @@ static int negotiate_formats(struct data *data)
struct spa_format *format, *filter;
uint32_t state = 0;
struct spa_pod_builder b = { 0 };
struct spa_pod_frame f[2];
uint8_t buffer[256];
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_format(&b, &f[0], data->type.format,
data->type.media_type.audio,
data->type.media_subtype.raw,
SPA_POD_PROP(&f[1], data->type.format_audio.format, 0, SPA_POD_TYPE_ID, 1,
data->type.audio_format.S16),
SPA_POD_PROP(&f[1], data->type.format_audio.layout, 0, SPA_POD_TYPE_INT, 1,
SPA_AUDIO_LAYOUT_INTERLEAVED),
SPA_POD_PROP(&f[1], data->type.format_audio.rate, 0, SPA_POD_TYPE_INT, 1,
44100),
SPA_POD_PROP(&f[1], data->type.format_audio.channels, 0, SPA_POD_TYPE_INT, 1,
2));
filter = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
filter = spa_pod_builder_format(&b,
data->type.format,
data->type.media_type.audio, data->type.media_subtype.raw,
":", data->type.format_audio.format, "I", data->type.audio_format.S16,
":", data->type.format_audio.layout, "i", SPA_AUDIO_LAYOUT_INTERLEAVED,
":", data->type.format_audio.rate, "i", 44100,
":", data->type.format_audio.channels, "i", 2);
if ((res =
spa_node_port_enum_formats(data->sink, SPA_DIRECTION_INPUT, 0, &format, filter,
@ -527,7 +519,6 @@ int main(int argc, char *argv[])
int res;
const char *str;
spa_graph_init(&data.graph);
spa_graph_data_init(&data.graph_data, &data.graph);
spa_graph_set_callbacks(&data.graph, &spa_graph_impl_default, &data.graph_data);
@ -540,6 +531,8 @@ int main(int argc, char *argv[])
data.data_loop.remove_source = do_remove_source;
data.data_loop.invoke = do_invoke;
spa_debug_set_type_map(data.map);
if ((str = getenv("SPA_DEBUG")))
data.log->level = atoi(str);

View file

@ -325,7 +325,6 @@ static int make_nodes(struct data *data, const char *device)
int res;
struct spa_props *props;
struct spa_pod_builder b = { 0 };
struct spa_pod_frame f[2];
uint8_t buffer[128];
if ((res = make_node(data, &data->sink,
@ -336,12 +335,10 @@ static int make_nodes(struct data *data, const char *device)
spa_node_set_callbacks(data->sink, &sink_callbacks, data);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_props(&b, &f[0], data->type.props,
SPA_POD_PROP(&f[1], data->type.props_device, 0, SPA_POD_TYPE_STRING, 1,
device ? device : "hw:0"),
SPA_POD_PROP(&f[1], data->type.props_min_latency, 0, SPA_POD_TYPE_INT, 1,
MIN_LATENCY));
props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
props = spa_pod_builder_props(&b,
data->type.props,
":", data->type.props_device, "s", device ? device : "hw:0",
":", data->type.props_min_latency, "i", MIN_LATENCY);
if ((res = spa_node_set_props(data->sink, props)) < 0)
printf("got set_props error %d\n", res);
@ -361,14 +358,11 @@ static int make_nodes(struct data *data, const char *device)
}
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_props(&b, &f[0], data->type.props,
SPA_POD_PROP(&f[1], data->type.props_freq, 0, SPA_POD_TYPE_DOUBLE, 1,
600.0),
SPA_POD_PROP(&f[1], data->type.props_volume, 0, SPA_POD_TYPE_DOUBLE, 1,
0.5),
SPA_POD_PROP(&f[1], data->type.props_live, 0, SPA_POD_TYPE_BOOL, 1,
false));
props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
props = spa_pod_builder_props(&b,
data->type.props,
":", data->type.props_freq, "d", 600.0,
":", data->type.props_volume, "d", 0.5,
":", data->type.props_live, "b", false);
if ((res = spa_node_set_props(data->source1, props)) < 0)
printf("got set_props error %d\n", res);
@ -381,14 +375,11 @@ static int make_nodes(struct data *data, const char *device)
}
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_props(&b, &f[0], data->type.props,
SPA_POD_PROP(&f[1], data->type.props_freq, 0, SPA_POD_TYPE_DOUBLE, 1,
440.0),
SPA_POD_PROP(&f[1], data->type.props_volume, 0, SPA_POD_TYPE_DOUBLE, 1,
0.5),
SPA_POD_PROP(&f[1], data->type.props_live, 0, SPA_POD_TYPE_BOOL, 1,
false));
props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
props = spa_pod_builder_props(&b,
data->type.props,
":", data->type.props_freq, "d", 440.0,
":", data->type.props_volume, "d", 0.5,
":", data->type.props_live, "b", false);
if ((res = spa_node_set_props(data->source2, props)) < 0)
printf("got set_props error %d\n", res);
@ -459,22 +450,16 @@ static int negotiate_formats(struct data *data)
struct spa_format *format, *filter;
uint32_t state = 0;
struct spa_pod_builder b = { 0 };
struct spa_pod_frame f[2];
uint8_t buffer[256];
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_format(&b, &f[0], data->type.format,
data->type.media_type.audio,
data->type.media_subtype.raw,
SPA_POD_PROP(&f[1], data->type.format_audio.format, 0, SPA_POD_TYPE_ID, 1,
data->type.audio_format.S16),
SPA_POD_PROP(&f[1], data->type.format_audio.layout, 0, SPA_POD_TYPE_INT, 1,
SPA_AUDIO_LAYOUT_INTERLEAVED),
SPA_POD_PROP(&f[1], data->type.format_audio.rate, 0, SPA_POD_TYPE_INT, 1,
44100),
SPA_POD_PROP(&f[1], data->type.format_audio.channels, 0, SPA_POD_TYPE_INT, 1,
2));
filter = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
filter = spa_pod_builder_format(&b,
data->type.format,
data->type.media_type.audio, data->type.media_subtype.raw,
":", data->type.format_audio.format, "I", data->type.audio_format.S16,
":", data->type.format_audio.layout, "i", SPA_AUDIO_LAYOUT_INTERLEAVED,
":", data->type.format_audio.rate, "i", 44100,
":", data->type.format_audio.channels, "i", 2);
if ((res =
spa_node_port_enum_formats(data->sink, SPA_DIRECTION_INPUT, 0, &format, filter,

View file

@ -387,13 +387,12 @@ static int negotiate_formats(struct data *data)
int res;
struct spa_format *format;
struct spa_pod_builder b = { 0 };
struct spa_pod_frame f[2];
uint8_t buffer[256];
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_format(&b, &f[0], data->type.format,
data->type.media_type.binary, data->type.media_subtype.raw, 0);
format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
format = spa_pod_builder_format(&b,
data->type.format,
data->type.media_type.binary, data->type.media_subtype.raw);
if ((res = spa_node_port_set_format(data->sink, SPA_DIRECTION_INPUT, 0, 0, format)) < 0)
return res;

View file

@ -230,8 +230,8 @@ static void do_static_struct(struct spa_type_map *map)
sizeof(struct spa_rectangle), SPA_POD_TYPE_RECTANGLE),
{
{ 320, 243},
{ 1, 1}, { INT32_MAX, INT32_MAX}
SPA_RECTANGLE(320,243),
SPA_RECTANGLE(1,1), SPA_RECTANGLE(INT32_MAX, INT32_MAX)
},
SPA_POD_PROP_INIT(sizeof(test_format.props.framerate_vals) +
sizeof(struct spa_pod_prop_body),
@ -239,8 +239,8 @@ static void do_static_struct(struct spa_type_map *map)
SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET,
sizeof(struct spa_fraction), SPA_POD_TYPE_FRACTION),
{
{ 25, 1},
{ 0, 1}, { INT32_MAX, 1}
SPA_FRACTION(25,1),
SPA_FRACTION(0,1), SPA_FRACTION(INT32_MAX,1)
}
}
};
@ -249,24 +249,23 @@ static void do_static_struct(struct spa_type_map *map)
spa_debug_format(&test_format.fmt);
{
uint32_t format = 0, match;
struct spa_fraction frac = { 0, 0 };
uint32_t format = -1;
int res;
struct spa_fraction frac = { -1, -1 };
match = spa_pod_contents_query(&test_format.fmt.pod, sizeof(struct spa_format),
type.format_video.format, SPA_POD_TYPE_ID, &format,
type.format_video.framerate, SPA_POD_TYPE_FRACTION,
&frac, 0);
res = spa_format_parse(&test_format.fmt,
":",type.format_video.format, "I", &format,
":",type.format_video.framerate, "F", &frac, NULL);
printf("%d %d %d %d\n", match, format, frac.num, frac.denom);
printf("%d format %d num %d denom %d\n", res, format, frac.num, frac.denom);
spa_format_fixate(&test_format.fmt);
match = spa_pod_contents_query(&test_format.fmt.pod, sizeof(struct spa_format),
type.format_video.format, SPA_POD_TYPE_ID, &format,
type.format_video.framerate, SPA_POD_TYPE_FRACTION,
&frac, 0);
res = spa_format_parse(&test_format.fmt,
":",type.format_video.format, "I", &format,
":",type.format_video.framerate, "F", &frac, NULL);
printf("%d %d %d %d\n", match, format, frac.num, frac.denom);
printf("%d format %d num %d denom %d\n", res, format, frac.num, frac.denom);
}
}
@ -274,7 +273,7 @@ static void do_static_struct(struct spa_type_map *map)
int main(int argc, char *argv[])
{
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame frame[4];
struct spa_pod_frame f[2];
uint8_t buffer[1024];
struct spa_format *fmt;
struct spa_type_map *map = &default_map.map;
@ -284,105 +283,82 @@ int main(int argc, char *argv[])
spa_pod_builder_init(&b, buffer, sizeof(buffer));
fmt = SPA_MEMBER(buffer, spa_pod_builder_push_format(&b, &frame[0], type.format,
fmt = SPA_MEMBER(buffer, spa_pod_builder_push_format(&b, &f[0], type.format,
type.media_type.video,
type.media_subtype.raw),
struct spa_format);
spa_pod_builder_push_prop(&b, &frame[1], type.format_video.format,
spa_pod_builder_push_prop(&b, &f[1], type.format_video.format,
SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_UNSET);
spa_pod_builder_id(&b, type.video_format.I420);
spa_pod_builder_id(&b, type.video_format.I420);
spa_pod_builder_id(&b, type.video_format.YUY2);
spa_pod_builder_pop(&b, &frame[1]);
spa_pod_builder_pop(&b, &f[1]);
struct spa_rectangle size_min_max[] = { {1, 1}, {INT32_MAX, INT32_MAX} };
spa_pod_builder_push_prop(&b, &frame[1],
spa_pod_builder_push_prop(&b, &f[1],
type.format_video.size,
SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET);
spa_pod_builder_rectangle(&b, 320, 240);
spa_pod_builder_raw(&b, size_min_max, sizeof(size_min_max));
spa_pod_builder_pop(&b, &frame[1]);
spa_pod_builder_pop(&b, &f[1]);
struct spa_fraction rate_min_max[] = { {0, 1}, {INT32_MAX, 1} };
spa_pod_builder_push_prop(&b, &frame[1],
spa_pod_builder_push_prop(&b, &f[1],
type.format_video.framerate,
SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET);
spa_pod_builder_fraction(&b, 25, 1);
spa_pod_builder_raw(&b, rate_min_max, sizeof(rate_min_max));
spa_pod_builder_pop(&b, &frame[1]);
spa_pod_builder_pop(&b, &f[1]);
spa_pod_builder_pop(&b, &frame[0]);
spa_pod_builder_pop(&b, &f[0]);
spa_debug_pod(&fmt->pod);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_format(&b, &frame[0], type.format,
type.media_type.video,
type.media_subtype.raw,
SPA_POD_TYPE_PROP, &frame[1],
type.format_video.format,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_RANGE_ENUM,
SPA_POD_TYPE_ID, 3,
type.video_format.I420,
type.video_format.I420,
type.video_format.YUY2,
-SPA_POD_TYPE_PROP, &frame[1],
SPA_POD_TYPE_PROP, &frame[1],
type.format_video.size,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_RANGE_MIN_MAX,
SPA_POD_TYPE_RECTANGLE, 3,
320, 241,
1, 1,
INT32_MAX, INT32_MAX,
-SPA_POD_TYPE_PROP, &frame[1],
SPA_POD_TYPE_PROP, &frame[1],
type.format_video.framerate,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_RANGE_MIN_MAX,
SPA_POD_TYPE_FRACTION, 3,
25, 1,
0, 1,
INT32_MAX, 1,
-SPA_POD_TYPE_PROP, &frame[1]);
fmt = spa_pod_builder_format(&b,
type.format,
type.media_type.video, type.media_subtype.raw,
":", type.format_video.format, "Ieu", type.video_format.I420,
2, type.video_format.I420,
type.video_format.YUY2,
":", type.format_video.size, "Rru", &SPA_RECTANGLE(320,241),
2, &SPA_RECTANGLE(1,1),
&SPA_RECTANGLE(INT32_MAX,INT32_MAX),
":", type.format_video.framerate, "Fru", &SPA_FRACTION(25,1),
2, &SPA_FRACTION(0,1),
&SPA_FRACTION(INT32_MAX,1));
fmt = SPA_MEMBER(buffer, frame[0].ref, struct spa_format);
spa_debug_pod(&fmt->pod);
spa_debug_format(fmt);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_add(&b,
SPA_POD_TYPE_OBJECT, &frame[0], 0, type.format,
SPA_POD_TYPE_ID, type.media_type.video,
SPA_POD_TYPE_ID, type.media_subtype.raw,
SPA_POD_TYPE_PROP, &frame[1],
type.format_video.format,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_RANGE_ENUM,
SPA_POD_TYPE_ID, 3,
type.video_format.I420,
type.video_format.I420,
type.video_format.YUY2,
-SPA_POD_TYPE_PROP, &frame[1],
SPA_POD_TYPE_PROP, &frame[1],
type.format_video.size,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_RANGE_MIN_MAX,
SPA_POD_TYPE_RECTANGLE, 3,
320, 242,
1, 1,
INT32_MAX, INT32_MAX,
-SPA_POD_TYPE_PROP, &frame[1],
SPA_POD_TYPE_PROP, &frame[1],
type.format_video.framerate,
SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_RANGE_MIN_MAX,
SPA_POD_TYPE_FRACTION, 3,
25, 1,
0, 1,
INT32_MAX, 1,
-SPA_POD_TYPE_PROP, &frame[1],
-SPA_POD_TYPE_OBJECT, &frame[0],
0);
/*
* ( "Format",
* ("video", "raw" ),
* {
* "format": ( "seu", "I420", ( "I420","YUY2" ) ),
* "size": ( "Rru", (320, 242), ( (1,1), (MAX, MAX)) ),
* "framerate": ( "Fru", (25, 1), ( (0,1), (MAX, 1)) )
* }
* )
*/
fmt = spa_pod_builder_add(&b,
"<", 0, type.format,
"I", type.media_type.video,
"I", type.media_subtype.raw,
":", type.format_video.format, "Ieu", type.video_format.I420,
2, type.video_format.I420,
type.video_format.YUY2,
":", type.format_video.size, "Rru", &SPA_RECTANGLE(320,242),
2, &SPA_RECTANGLE(1,1),
&SPA_RECTANGLE(INT32_MAX,INT32_MAX),
":", type.format_video.framerate, "Fru", &SPA_FRACTION(25,1),
2, &SPA_FRACTION(0,1),
&SPA_FRACTION(INT32_MAX,1),
">", NULL);
fmt = SPA_MEMBER(buffer, frame[0].ref, struct spa_format);
spa_debug_pod(&fmt->pod);
spa_debug_format(fmt);

View file

@ -26,7 +26,7 @@
#include <spa/pod.h>
#include <spa/pod-builder.h>
#include <spa/pod-iter.h>
#include <spa/pod-parser.h>
#include <spa/type-map-impl.h>
#include <spa/log-impl.h>
@ -42,7 +42,7 @@ int main(int argc, char *argv[])
struct spa_pod_frame frame[4];
uint8_t buffer[1024];
struct spa_pod *obj;
struct spa_pod_iter i;
struct spa_pod_parser prs;
struct spa_type_map *map = &default_map.map;
spa_debug_set_type_map(map);
@ -105,14 +105,17 @@ int main(int argc, char *argv[])
struct spa_rectangle vr;
struct spa_fraction vfr;
struct spa_pod_array *va;
spa_pod_iter_pod(&i, obj);
spa_pod_iter_get(&i, SPA_POD_TYPE_INT, &vi,
SPA_POD_TYPE_LONG, &vl,
SPA_POD_TYPE_FLOAT, &vf,
SPA_POD_TYPE_DOUBLE, &vd,
SPA_POD_TYPE_STRING, &vs,
SPA_POD_TYPE_RECTANGLE, &vr,
SPA_POD_TYPE_FRACTION, &vfr, SPA_POD_TYPE_ARRAY, &va, 0);
spa_pod_parser_pod(&prs, obj);
spa_pod_parser_get(&prs,
"["
"i", &vi,
"l", &vl,
"f", &vf,
"d", &vd,
"s", &vs,
"R", &vr,
"F", &vfr,
"P", &va, 0);
printf("%u %lu %f %g %s %ux%u %u/%u\n", vi, vl, vf, vd, vs, vr.width, vr.height, vfr.num,
vfr.denom);

View file

@ -22,558 +22,10 @@
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <spa/type-map.h>
#include <spa/type-map-impl.h>
#include <spa/log.h>
#include <spa/node.h>
#include <spa/loop.h>
#include <spa/video/format-utils.h>
#include <spa/format-builder.h>
#include <lib/debug.h>
#if 0
/*
* JSON based format description
[ <type>,
[ <media-type>, <media-subtype> ],
{
<key> : <property>,
...
}
]
<property> = [ <flags>, <default>, [ <alternatives>,... ]]
| <value>
<flags> = "123.."
1: s = string : "value"
i = int : <number>
l = long : <number>
f = float : <float>
d = double : <double>
b = bool : true | false
R = rectangle : [ <width>, <height> ]
F = fraction : [ <num>, <denom> ]
2: - = default (only default value present)
e = enum : [ <value>, ... ]
f = flags : [ <number> ]
r = min/max : [ <min>, <max> ]
s = min/max/step : [ <min>, <max>, <step> ]
3: u = unset : value is unset, choose from options or default
o = optional : value does not need to be set
r = readonly : value is read only
d = deprecated : value is deprecated
[ "Format",
[ "video", "raw"],
{
"format" : [ "se", "I420", [ "I420", "YUY2" ] ],
"size" : [ "Rru", [320, 240], [[ 640, 480], [1024,786]]],
"framerate" : [ "Fsu", [25, 1], [[ 0, 1], [65536,1]]]"
}
]
[ "Format",
[ "audio", "raw"],
{
"format" : [ "se", "S16LE", [ "F32LE", "S16LE" ] ],
"rate" : [ "iru", 44100, [8000, 96000]],
"channels" : [ "iru", 1, [1, 4096]]"
"interleaved" : [ "beo", true ]"
}
]
*/
#endif
#include <stddef.h>
#define STRUCT 0
#define BARE 1
#define STRING 2
#define UTF8 3
#define ESC 4
struct spa_json_iter {
const char *start;
const char *cur;
const char *end;
int state;
int depth;
};
struct spa_json_chunk {
const char *value;
int len;
};
static inline int
spa_json_chunk_extract(struct spa_json_chunk *chunk, const char *template, ...);
enum spa_json_type {
SPA_JSON_TYPE_ANY = '-',
SPA_JSON_TYPE_CHUNK = 'c',
SPA_JSON_TYPE_INT = 'i',
SPA_JSON_TYPE_LONG = 'l',
SPA_JSON_TYPE_FLOAT = 'f',
SPA_JSON_TYPE_DOUBLE = 'd',
SPA_JSON_TYPE_STRING = 's',
SPA_JSON_TYPE_BOOL = 'b',
SPA_JSON_TYPE_RECTANGLE = 'R',
SPA_JSON_TYPE_FRACTION = 'F',
SPA_JSON_TYPE_OBJECT = 'o',
SPA_JSON_TYPE_ARRAY = 'a'
};
static inline bool spa_json_chunk_is_type(struct spa_json_chunk *chunk,
enum spa_json_type type)
{
switch (type) {
case SPA_JSON_TYPE_ANY:
case SPA_JSON_TYPE_CHUNK:
return true;
case SPA_JSON_TYPE_INT:
case SPA_JSON_TYPE_LONG:
case SPA_JSON_TYPE_FLOAT:
case SPA_JSON_TYPE_DOUBLE:
return (chunk->value[0] >= '0' && chunk->value[0] <= '9') ||
chunk->value[0] == '-' ;
case SPA_JSON_TYPE_STRING:
return chunk->value[0] == '\"';
case SPA_JSON_TYPE_BOOL:
return chunk->value[0] == 't' || chunk->value[0] == 'f';
case SPA_JSON_TYPE_RECTANGLE:
case SPA_JSON_TYPE_FRACTION:
case SPA_JSON_TYPE_ARRAY:
return chunk->value[0] == '[';
case SPA_JSON_TYPE_OBJECT:
return chunk->value[0] == '{';
}
return false;
}
static inline int spa_json_chunk_to_int(struct spa_json_chunk *chunk) {
return atoi(chunk->value);
}
static inline int64_t spa_json_chunk_to_long(struct spa_json_chunk *chunk) {
return atol(chunk->value);
}
static inline int64_t spa_json_chunk_to_float(struct spa_json_chunk *chunk) {
return strtof(chunk->value, NULL);
}
static inline int64_t spa_json_chunk_to_double(struct spa_json_chunk *chunk) {
return strtod(chunk->value, NULL);
}
static inline bool spa_json_chunk_to_bool(struct spa_json_chunk *chunk) {
return chunk->value[0] == 't';
}
static inline int spa_json_chunk_to_rectangle(struct spa_json_chunk *chunk,
struct spa_rectangle *rect) {
return spa_json_chunk_extract(chunk, "[ #pi, #pi ]", &rect->width, &rect->height);
}
static inline int spa_json_chunk_to_fraction(struct spa_json_chunk *chunk,
struct spa_fraction *frac) {
return spa_json_chunk_extract(chunk, "[ #pi, #pi ]", &frac->num, &frac->denom);
}
static inline void
spa_json_iter_init (struct spa_json_iter *iter, const char *data, size_t size)
{
iter->start = iter->cur = data;
iter->end = size == -1 ? NULL : data + size;
iter->state = STRUCT;
iter->depth = 0;
}
static inline bool
spa_json_iter_chunk(struct spa_json_iter *iter, struct spa_json_chunk *chunk)
{
if (!spa_json_chunk_is_type(chunk, SPA_JSON_TYPE_OBJECT) &&
!spa_json_chunk_is_type(chunk, SPA_JSON_TYPE_ARRAY))
return false;
spa_json_iter_init (iter, chunk->value, -1);
iter->cur++;
return true;
}
static inline int
spa_json_iter_next_chunk(struct spa_json_iter *iter, struct spa_json_chunk *chunk)
{
int utf8_remain = 0;
for (;iter->end == NULL || iter->cur < iter->end; iter->cur++) {
unsigned char cur = (unsigned char) *iter->cur;
again:
switch (iter->state) {
case STRUCT:
switch (cur) {
case '\t': case ' ': case '\r': case '\n': case ':': case ',':
continue;
case '"':
chunk->value = iter->cur;
iter->state = STRING;
continue;
case '[': case '{':
chunk->value = iter->cur;
if (++iter->depth > 1)
continue;
iter->cur++;
return chunk->len = 1;
case '}': case ']':
if (iter->depth == 0)
return 0;
--iter->depth;
continue;
case '-': case 'a' ... 'z': case 'A' ... 'Z': case '0' ... '9': case '#':
chunk->value = iter->cur;
iter->state = BARE;
continue;
case '\0':
return 0;
}
return -1;
case BARE:
switch (cur) {
case '\t': case ' ': case '\r': case '\n': case ':': case ',':
case ']': case '}':
iter->state = STRUCT;
if (iter->depth > 0)
goto again;
return chunk->len = iter->cur - chunk->value;
default:
if (cur >= 32 && cur <= 126)
continue;
}
return -1;
case STRING:
switch (cur) {
case '\\':
iter->state = ESC;
continue;
case '"':
iter->state = STRUCT;
if (iter->depth > 0)
continue;
iter->cur++;
return chunk->len = iter->cur - chunk->value;
case 240 ... 247:
utf8_remain++;
case 224 ... 239:
utf8_remain++;
case 192 ... 223:
utf8_remain++;
iter->state = UTF8;
continue;
default:
if (cur >= 32 && cur <= 126)
continue;
}
return -1;
case UTF8:
switch (cur) {
case 128 ... 191:
if (--utf8_remain == 0)
iter->state = STRING;
continue;
}
return -1;
case ESC:
switch (cur) {
case '"': case '\\': case '/': case 'b': case 'f': case 'n': case 'r':
case 't': case 'u':
iter->state = STRING;
continue;
}
return -1;
}
}
return iter->depth == 0 ? 0 : -1;
}
static inline void
spa_json_chunk_print(struct spa_json_chunk *chunk, int prefix)
{
struct spa_json_iter iter;
if (spa_json_iter_chunk(&iter, chunk)) {
struct spa_json_chunk chunk2 = { NULL, };
printf ("%-*s%c\n", prefix, "", chunk->value[0]);
while (spa_json_iter_next_chunk(&iter, &chunk2) > 0)
spa_json_chunk_print(&chunk2, prefix + 2);
printf ("%-*s%c\n", prefix, "", iter.cur[0]);
} else {
printf ("%-*s%.*s\n", prefix, "", chunk->len, chunk->value);
}
}
static inline int spa_json_iter_find_key(struct spa_json_iter *iter, const char *key)
{
struct spa_json_chunk ch = { NULL, };
int res;
iter->cur = iter->start + 1;
iter->depth = 0;
iter->state = STRUCT;
while (true) {
/* read key */
if ((res = spa_json_iter_next_chunk(iter, &ch)) <= 0)
return res;
if (spa_json_chunk_is_type(&ch, SPA_JSON_TYPE_STRING) &&
strncmp(key, ch.value, ch.len) == 0)
return 1;
}
return 0;
}
enum spa_json_prop_range {
SPA_JSON_PROP_RANGE_NONE = '-',
SPA_JSON_PROP_RANGE_MIN_MAX = 'r',
SPA_JSON_PROP_RANGE_STEP = 's',
SPA_JSON_PROP_RANGE_ENUM = 'e',
SPA_JSON_PROP_RANGE_FLAGS = 'f'
};
enum spa_json_prop_flags {
SPA_JSON_PROP_FLAG_UNSET = (1 << 0),
SPA_JSON_PROP_FLAG_OPTIONAL = (1 << 1),
SPA_JSON_PROP_FLAG_READONLY = (1 << 2),
SPA_JSON_PROP_FLAG_DEPRECATED = (1 << 3),
};
struct spa_json_prop {
enum spa_json_type type;
enum spa_json_prop_range range;
enum spa_json_prop_flags flags;
struct spa_json_chunk value;
struct spa_json_chunk alternatives;
};
static inline int
spa_json_chunk_parse_prop(struct spa_json_chunk *chunk, char type,
struct spa_json_prop *prop)
{
if (spa_json_chunk_is_type(chunk, SPA_JSON_TYPE_ARRAY)) {
struct spa_json_chunk flags;
int res;
char ch;
/* [<flags>, <default>, [<alternatives>,...]] */
if ((res = spa_json_chunk_extract(chunk,
"[ #&cs, #&c-, #&ca ]",
&flags, &prop->value, &prop->alternatives)) < 3) {
printf("can't parse prop chunk %d\n", res);
return -1;
}
/* skip \" */
flags.value++;
prop->type = *flags.value++;
if (type != SPA_JSON_TYPE_ANY && type != SPA_JSON_TYPE_CHUNK && prop->type != type) {
printf("prop chunk of wrong type %d %d\n", prop->type, type);
return -1;
}
prop->range = *flags.value++;
/* flags */
prop->flags = 0;
while ((ch = *flags.value++) != '\"') {
switch (ch) {
case 'u':
prop->flags |= SPA_JSON_PROP_FLAG_UNSET;
break;
case 'o':
prop->flags |= SPA_JSON_PROP_FLAG_OPTIONAL;
break;
case 'r':
prop->flags |= SPA_JSON_PROP_FLAG_READONLY;
break;
case 'd':
prop->flags |= SPA_JSON_PROP_FLAG_DEPRECATED;
break;
}
}
}
else {
/* <value> */
prop->type = type;
prop->range = SPA_JSON_PROP_RANGE_NONE;
prop->flags = 0;
prop->value = *chunk;
prop->alternatives = *chunk;
}
return 0;
}
/**
* #[*]<asign>
*
* * = skip assignment
* <asign> is:
* &<type> -> pointer to type
* p<type> -> property, fixed value store in pointer to type
* P<type> -> property, stored in pointer to struct spa_json_prop
*
* <type>
* - -> any
* c<type> -> store as chunk if of type
* s -> string
* i -> int
* l -> long
* f -> float
* d -> double
* b -> bool
* R -> rectangle
* F -> fraction
* a -> array
* o -> object
*/
static inline int
spa_json_chunk_extract(struct spa_json_chunk *chunk,
const char *template, ...)
{
struct spa_json_iter templ[16], it[16];
struct spa_json_chunk tch = { NULL, }, ch = { NULL, };
struct spa_json_prop prop;
const char *match;
int collected = 0, res, level = 0;
va_list args;
bool store;
va_start(args, template);
spa_json_iter_init(&it[0], chunk->value, chunk->len);
spa_json_iter_init (&templ[0], template, -1);
while (true) {
res = spa_json_iter_next_chunk(&templ[level], &tch);
if (res == 0) {
if (--level == 0)
break;
continue;
} else if (res < 0) {
return res;
}
switch (tch.value[0]) {
case '[': case '{':
if (spa_json_iter_next_chunk(&it[level], &ch) <= 0 ||
ch.value[0] != tch.value[0])
return -1;
if (++level == 16)
return -2;
spa_json_iter_chunk(&it[level], &ch);
spa_json_iter_chunk(&templ[level], &tch);
break;
case '"':
case '-': case '0' ... '9':
case 't': case 'f':
case 'n':
if (templ[level].start[0] == '{') {
if (spa_json_iter_find_key(&it[level], tch.value) <= 0)
continue;
} else if (spa_json_iter_next_chunk(&it[level], &ch) <= 0 ||
ch.len != tch.len ||
strncmp(ch.value, tch.value, ch.len) != 0)
return -1;
break;
case '#':
match = tch.value + 1;
if (spa_json_iter_next_chunk(&it[level], &ch) <= 0)
return -1;
store = (match[0] != '*');
if (!store)
match++;
switch (match[0]) {
case 'p':
case 'P':
if (spa_json_chunk_parse_prop(&ch, match[1], &prop) < 0)
goto skip;
if (match[0] == 'P') {
if (store)
*va_arg(args, struct spa_json_prop *) = prop;
collected++;
break;
}
else {
if (prop.flags & SPA_JSON_PROP_FLAG_UNSET)
goto skip;
ch = prop.value;
}
/* fallthrough */
case '&':
if (!spa_json_chunk_is_type(&ch, match[1] == SPA_JSON_TYPE_CHUNK ?
match[2] : match[1])) {
skip:
if (store)
va_arg(args, void *);
break;
}
if (!store)
break;
collected++;
switch (match[1]) {
case SPA_JSON_TYPE_CHUNK:
*va_arg(args, struct spa_json_chunk *) = ch;
break;
case SPA_JSON_TYPE_INT:
*va_arg(args, int *) = spa_json_chunk_to_int(&ch);
break;
case SPA_JSON_TYPE_LONG:
*va_arg(args, int64_t *) = spa_json_chunk_to_long(&ch);
break;
case SPA_JSON_TYPE_FLOAT:
*va_arg(args, float *) = spa_json_chunk_to_float(&ch);
break;
case SPA_JSON_TYPE_DOUBLE:
*va_arg(args, double *) = spa_json_chunk_to_double(&ch);
break;
case SPA_JSON_TYPE_BOOL:
*va_arg(args, bool *) = spa_json_chunk_to_bool(&ch);
break;
case SPA_JSON_TYPE_RECTANGLE:
spa_json_chunk_to_rectangle(&ch,
va_arg(args, struct spa_rectangle *));
break;
case SPA_JSON_TYPE_FRACTION:
spa_json_chunk_to_fraction(&ch,
va_arg(args, struct spa_fraction *));
break;
default:
printf("ignoring invalid #p type %c\n", match[1]);
va_arg(args, void *);
collected--;
continue;
}
break;
default:
printf("ignoring unknown match type %c\n", *match);
break;
}
break;
default:
printf("invalid char %c\n", tch.value[0]);
return -2;
}
}
va_end(args);
return collected;
}
#include <spa/json.h>
#include <spa/json-builder.h>
static int
spa_json_iter_array(struct spa_json_iter *iter,
@ -749,7 +201,7 @@ static int test_extract3(const char *fmt)
struct spa_json_chunk chunk;
struct spa_json_chunk media_type;
struct spa_json_chunk media_subtype;
struct spa_json_chunk format;
struct spa_json_chunk format = { "*unset*", 7 };
int rate = -1, res;
struct spa_json_prop channels;
@ -781,6 +233,35 @@ static int test_extract3(const char *fmt)
return 0;
}
static int test_builder()
{
struct spa_json_builder builder = { NULL, 0, };
int res;
again:
res = spa_json_builder_printf(&builder,
"[ \"Format\", "
" [ \"audio\", \"raw\"], "
" { "
" \"format\": [ \"seu\", \"S16LE\", [ \"F32LE\", \"S16LE\" ]], "
" \"rate\": %d, "
" \"channels\": %d "
" }"
"]", 48000, 2);
if (res < 0) {
printf("needed %d bytes\n", builder.offset);
builder.data = alloca(builder.offset);
builder.size = builder.offset;
builder.offset = 0;
goto again;
}
printf("have %zd bytes\n", strlen(builder.data));
test_extract3(builder.data);
return 0;
}
int main(int argc, char *argv[])
{
struct spa_json_iter iter;
@ -816,5 +297,7 @@ int main(int argc, char *argv[])
" }"
"]");
test_builder();
return 0;
}

861
spa/tests/test-props4.c Normal file
View file

@ -0,0 +1,861 @@
/* Spa
* Copyright (C) 2017 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <spa/log.h>
#include <lib/debug.h>
#include <spa/pod-iter.h>
#if 0
/*
( "Format",
( "video", "raw" ),
{
"format": ( "seu", "I420", ( "I420", "YUY2" ) ),
"size": ( "Rru", R(320, 242), ( R(1,1), R(MAX, MAX)) ),
"framerate": ( "Fru", F(25, 1), ( F(0,1), F(MAX, 1)) )
}
)
( struct
{ object
[ array
1: s = string : "value"
i = int : <number>
l = long : <number>
f = float : <float>
d = double : <float>
b = bool : true | false
R = rectangle : [ <width>, <height> ]
F = fraction : [ <num>, <denom> ]
2: - = default (only default value present)
e = enum : [ <value>, ... ]
f = flags : [ <number> ]
m = min/max : [ <min>, <max> ]
s = min/max/step : [ <min>, <max>, <step> ]
3: u = unset : value is unset, choose from options or default
o = optional : value does not need to be set
r = readonly : value is read only
d = deprecated : value is deprecated
*/
#endif
#define SPA_POD_MAX_LEVEL 16
struct spa_pod_maker {
struct spa_pod_builder b;
struct spa_pod_frame frame[SPA_POD_MAX_LEVEL];
int depth;
};
static inline void spa_pod_maker_init(struct spa_pod_maker *maker,
char *data, int size)
{
spa_pod_builder_init(&maker->b, data, size);
maker->depth = 0;
}
static const struct {
char *pat;
int len;
int64_t val;
} spa_constants[] = {
{ "#I_MAX#", strlen("#I_MAX#"), INT32_MAX },
{ "#I_MIN#", strlen("#I_MIN#"), INT32_MIN },
{ "#L_MAX#", strlen("#L_MAX#"), INT64_MAX },
{ "#L_MIN#", strlen("#L_MIN#"), INT64_MIN }
};
static inline int64_t spa_parse_int(const char *str, char **endptr)
{
int i;
if (*str != '#')
return strtoll(str, endptr, 10);
for (i = 0; i < SPA_N_ELEMENTS(spa_constants); i++) {
if (strncmp(str, spa_constants[i].pat, spa_constants[i].len) == 0) {
*endptr = (char *) (str + spa_constants[i].len);
return spa_constants[i].val;
}
}
return 0;
}
static inline int spa_parse_string(const char *str, char **endptr)
{
int len;
for (*endptr = (char *)str+1; **endptr != '\"' && **endptr != '\0'; (*endptr)++);
len = (*endptr)++ - (str + 1);
return len;
}
static inline void *
spa_pod_maker_build(struct spa_pod_maker *maker,
const char *format, ...)
{
va_list args;
const char *start, *strval;
int64_t intval;
double doubleval;
char last;
struct spa_rectangle *rectval;
struct spa_fraction *fracval;
int len;
va_start(args, format);
while (*format != '\0') {
switch (*format) {
case '[':
spa_pod_builder_push_struct(&maker->b, &maker->frame[maker->depth++]);
break;
case '(':
spa_pod_builder_push_array(&maker->b, &maker->frame[maker->depth++]);
break;
case '{':
spa_pod_builder_push_map(&maker->b, &maker->frame[maker->depth++]);
break;
case ']': case '}': case ')':
spa_pod_builder_pop(&maker->b, &maker->frame[--maker->depth]);
break;
case '\"':
start = format + 1;
if ((len = spa_parse_string(format, (char **) &format)) < 0)
return NULL;
format += strspn(format, " \t\r\n");
if (*format == ':')
spa_pod_builder_key_len(&maker->b, start, len);
else
spa_pod_builder_string_len(&maker->b, start, len);
continue;
case '@':
case '%':
last = *format;
format++;
switch (*format) {
case 's':
strval = va_arg(args, char *);
spa_pod_builder_string_len(&maker->b, strval, strlen(strval));
break;
case 'i':
spa_pod_builder_int(&maker->b, va_arg(args, int));
break;
case 'I':
spa_pod_builder_id(&maker->b, va_arg(args, int));
break;
case 'l':
spa_pod_builder_long(&maker->b, va_arg(args, int64_t));
break;
case 'f':
spa_pod_builder_float(&maker->b, va_arg(args, double));
break;
case 'd':
spa_pod_builder_double(&maker->b, va_arg(args, double));
break;
case 'b':
spa_pod_builder_bool(&maker->b, va_arg(args, int));
break;
case 'z':
{
void *ptr = va_arg(args, void *);
int len = va_arg(args, int);
spa_pod_builder_bytes(&maker->b, ptr, len);
break;
}
case 'p':
spa_pod_builder_pointer(&maker->b, 0, va_arg(args, void *));
break;
case 'h':
spa_pod_builder_fd(&maker->b, va_arg(args, int));
break;
case 'a':
{
int child_size = va_arg(args, int);
int child_type = va_arg(args, int);
int n_elems = va_arg(args, int);
void *elems = va_arg(args, void *);
spa_pod_builder_array(&maker->b, child_size, child_type, n_elems, elems);
break;
}
case 'P':
spa_pod_builder_primitive(&maker->b, va_arg(args, struct spa_pod *));
break;
case 'R':
rectval = va_arg(args, struct spa_rectangle *);
spa_pod_builder_rectangle(&maker->b, rectval->width, rectval->height);
break;
case 'F':
fracval = va_arg(args, struct spa_fraction *);
spa_pod_builder_fraction(&maker->b, fracval->num, fracval->denom);
break;
}
if (last == '@') {
format = va_arg(args, const char *);
continue;
}
break;
case '0' ... '9': case '-': case '+': case '#':
start = format;
intval = spa_parse_int(start, (char **) &format);
if (*format == '.') {
doubleval = strtod(start, (char **) &format);
if (*format == 'f')
spa_pod_builder_float(&maker->b, doubleval);
else
spa_pod_builder_double(&maker->b, doubleval);
continue;
}
switch (*format) {
case 'x':
spa_pod_builder_rectangle(&maker->b, intval,
spa_parse_int(format+1, (char **) &format));
break;
case '/':
spa_pod_builder_fraction(&maker->b, intval,
spa_parse_int(format+1, (char **) &format));
break;
case 'l':
spa_pod_builder_long(&maker->b, intval);
format++;
break;
default:
spa_pod_builder_int(&maker->b, intval);
break;
}
continue;
}
format++;
}
va_end(args);
return SPA_POD_BUILDER_DEREF(&maker->b, maker->frame[maker->depth].ref, void);
}
static inline int spa_pod_id_to_type(char id)
{
switch (id) {
case 'n':
return SPA_POD_TYPE_NONE;
case 'b':
return SPA_POD_TYPE_BOOL;
case 'I':
return SPA_POD_TYPE_ID;
case 'i':
return SPA_POD_TYPE_INT;
case 'l':
return SPA_POD_TYPE_LONG;
case 'f':
return SPA_POD_TYPE_FLOAT;
case 'd':
return SPA_POD_TYPE_DOUBLE;
case 's':
return SPA_POD_TYPE_STRING;
case 'k':
return SPA_POD_TYPE_KEY;
case 'z':
return SPA_POD_TYPE_BYTES;
case 'R':
return SPA_POD_TYPE_RECTANGLE;
case 'F':
return SPA_POD_TYPE_FRACTION;
case 'B':
return SPA_POD_TYPE_BITMASK;
case 'A':
return SPA_POD_TYPE_ARRAY;
case 'S':
return SPA_POD_TYPE_STRUCT;
case 'O':
return SPA_POD_TYPE_OBJECT;
case 'M':
return SPA_POD_TYPE_MAP;
case 'p':
return SPA_POD_TYPE_POINTER;
case 'h':
return SPA_POD_TYPE_FD;
case 'V': case 'v':
return SPA_POD_TYPE_PROP;
case 'P':
return SPA_POD_TYPE_POD;
default:
return SPA_POD_TYPE_INVALID;
}
}
enum spa_pod_prop_range {
SPA_POD_PROP2_RANGE_NONE = '-',
SPA_POD_PROP2_RANGE_MIN_MAX = 'r',
SPA_POD_PROP2_RANGE_STEP = 's',
SPA_POD_PROP2_RANGE_ENUM = 'e',
SPA_POD_PROP2_RANGE_FLAGS = 'f'
};
enum spa_pod_prop_flags {
SPA_POD_PROP2_FLAG_UNSET = (1 << 0),
SPA_POD_PROP2_FLAG_OPTIONAL = (1 << 1),
SPA_POD_PROP2_FLAG_READONLY = (1 << 2),
SPA_POD_PROP2_FLAG_DEPRECATED = (1 << 3),
};
struct spa_pod_prop2 {
enum spa_pod_type type;
enum spa_pod_prop_range range;
enum spa_pod_prop_flags flags;
struct spa_pod *value;
struct spa_pod *alternatives;
};
static inline int spa_pod_match(struct spa_pod *pod, const char *templ, ...);
static inline int
spa_pod_parse_prop(struct spa_pod *pod, enum spa_pod_type type, struct spa_pod_prop2 *prop)
{
int res;
if (SPA_POD_TYPE(pod) == SPA_POD_TYPE_STRUCT) {
const char *flags;
char ch;
if ((res = spa_pod_match(pod,
"[ %s, %P, %P ]",
&flags,
&prop->value,
&prop->alternatives)) < 0) {
printf("can't parse prop chunk %d\n", res);
return res;
}
prop->type = spa_pod_id_to_type(*flags++);
if (type != SPA_POD_TYPE_POD && type != SPA_POD_TYPE(prop->value)) {
printf("prop chunk of wrong type %d != %d\n", SPA_POD_TYPE(prop->value), type);
return -1;
}
prop->range = *flags++;
/* flags */
prop->flags = 0;
while ((ch = *flags++) != '\0') {
switch (ch) {
case 'u':
prop->flags |= SPA_POD_PROP2_FLAG_UNSET;
break;
case 'o':
prop->flags |= SPA_POD_PROP2_FLAG_OPTIONAL;
break;
case 'r':
prop->flags |= SPA_POD_PROP2_FLAG_READONLY;
break;
case 'd':
prop->flags |= SPA_POD_PROP2_FLAG_DEPRECATED;
break;
}
}
}
else {
/* a single value */
if (type != SPA_POD_TYPE_POD && type != SPA_POD_TYPE(pod)) {
printf("prop chunk of wrong type %d != %d\n", SPA_POD_TYPE(prop->value), type);
return -1;
}
prop->type = SPA_POD_TYPE(pod);
prop->range = SPA_POD_PROP2_RANGE_NONE;
prop->flags = 0;
prop->value = pod;
prop->alternatives = pod;
}
return 0;
}
static inline int
spa_pod_match(struct spa_pod *pod,
const char *templ, ...)
{
struct spa_pod_iter it[SPA_POD_MAX_LEVEL];
int depth = 0, collected = 0;
va_list args;
const char *start;
int64_t intval, int2val;
double doubleval;
char last;
struct spa_rectangle *rectval;
struct spa_fraction *fracval;
int type, len;
struct spa_pod *current = pod;
struct spa_pod_prop2 prop;
bool store, maybe;
va_start(args, templ);
while (*templ != '\0') {
switch (*templ) {
case '[':
depth++;
if (current == NULL ||
!spa_pod_iter_struct(&it[depth], current, SPA_POD_SIZE(current)))
goto done;
break;
case '(':
break;
case '{':
depth++;
if (current == NULL ||
!spa_pod_iter_map(&it[depth], current, SPA_POD_SIZE(current)))
goto done;
break;
case ']': case '}': case ')':
if (depth == 0)
return -1;
if (--depth == 0)
goto done;
break;
case '\"':
start = templ + 1;
if ((len = spa_parse_string(templ, (char **) &templ)) < 0)
return -1;
templ += strspn(templ, " \t\r\n");
if (*templ == ':') {
if (SPA_POD_TYPE(it[depth].data) != SPA_POD_TYPE_MAP)
return -1;
it[depth].offset = sizeof(struct spa_pod_map);
/* move to key */
while (spa_pod_iter_has_next(&it[depth])) {
current = spa_pod_iter_next(&it[depth]);
if (SPA_POD_TYPE(current) == SPA_POD_TYPE_KEY &&
strncmp(SPA_POD_CONTENTS_CONST(struct spa_pod_key, current),
start, len) == 0)
break;
current = NULL;
}
}
else {
if (current == NULL || SPA_POD_TYPE(current) != SPA_POD_TYPE_STRING ||
strncmp(SPA_POD_CONTENTS_CONST(struct spa_pod_string, current),
start, len) != 0)
goto done;
}
break;
case '@':
case '%':
last = *templ;
if (*++templ == '\0')
return -1;
store = *templ != '*';
if (!store)
if (*++templ == '\0')
return -1;
maybe = *templ == '?';
if (maybe)
if (*++templ == '\0')
return -1;
if (*templ == 'V' || *templ == 'v') {
char t = *templ;
templ++;
type = spa_pod_id_to_type(*templ);
if (current == NULL)
goto no_current;
if (spa_pod_parse_prop(current, type, &prop) < 0)
return -1;
if (t == 'v') {
if (prop.flags & SPA_POD_PROP2_FLAG_UNSET) {
if (store)
va_arg(args, void *);
goto skip;
}
else
current = prop.value;
}
else {
collected++;
*va_arg(args, struct spa_pod_prop2 *) = prop;
goto skip;
}
}
no_current:
type = spa_pod_id_to_type(*templ);
if (current == NULL || (type != SPA_POD_TYPE_POD && type != SPA_POD_TYPE(current))) {
if (!maybe)
return -1;
if (store)
va_arg(args, void *);
goto skip;
}
if (!store)
goto skip;
collected++;
switch (*templ) {
case 'n': case 'A': case 'S': case 'O': case 'M': case 'P':
*va_arg(args, struct spa_pod **) = current;
break;
case 'b':
case 'i':
case 'I':
*va_arg(args, int32_t *) = SPA_POD_VALUE(struct spa_pod_int, current);
break;
case 'l':
*va_arg(args, int64_t *) = SPA_POD_VALUE(struct spa_pod_long, current);
break;
case 'f':
*va_arg(args, float *) = SPA_POD_VALUE(struct spa_pod_float, current);
break;
case 'd':
*va_arg(args, double *) = SPA_POD_VALUE(struct spa_pod_double, current);
break;
case 's':
case 'k':
*va_arg(args, char **) = SPA_POD_CONTENTS(struct spa_pod_string, current);
break;
case 'z':
*va_arg(args, void **) = SPA_POD_CONTENTS(struct spa_pod_bytes, current);
*va_arg(args, uint32_t *) = SPA_POD_BODY_SIZE(current);
break;
case 'R':
*va_arg(args, struct spa_rectangle *) =
SPA_POD_VALUE(struct spa_pod_rectangle, current);
break;
case 'F':
*va_arg(args, struct spa_fraction *) =
SPA_POD_VALUE(struct spa_pod_fraction, current);
break;
case 'p':
{
struct spa_pod_pointer_body *b = SPA_POD_BODY(current);
*va_arg(args, void **) = b->value;
break;
}
case 'h':
*va_arg(args, int *) = SPA_POD_VALUE(struct spa_pod_fd, current);
break;
default:
va_arg(args, void *);
break;
}
skip:
if (last == '@') {
templ = va_arg(args, void *);
goto next;
}
break;
case '0' ... '9': case '-': case '+': case '#':
start = templ;
intval = spa_parse_int(start, (char **) &templ);
if (*templ == '.') {
doubleval = strtod(start, (char **) &templ);
if (*templ == 'f') {
if (current == NULL ||
SPA_POD_TYPE(current) != SPA_POD_TYPE_FLOAT ||
doubleval != SPA_POD_VALUE(struct spa_pod_float, current))
goto done;
break;
}
else if (current == NULL ||
SPA_POD_TYPE(current) != SPA_POD_TYPE_DOUBLE ||
doubleval != SPA_POD_VALUE(struct spa_pod_double, current))
goto done;
goto next;
}
switch (*templ) {
case 'x':
if (current == NULL ||
SPA_POD_TYPE(current) != SPA_POD_TYPE_RECTANGLE)
goto done;
rectval = &SPA_POD_VALUE(struct spa_pod_rectangle, current);
int2val = spa_parse_int(templ+1, (char **) &templ);
if (rectval->width != intval || rectval->height != int2val)
goto done;
goto next;
case '/':
if (current == NULL ||
SPA_POD_TYPE(current) != SPA_POD_TYPE_FRACTION)
goto done;
fracval = &SPA_POD_VALUE(struct spa_pod_fraction, current);
int2val = spa_parse_int(templ+1, (char **) &templ);
if (fracval->num != intval || fracval->denom != int2val)
goto done;
goto next;
case 'l':
if (current == NULL ||
SPA_POD_TYPE(current) != SPA_POD_TYPE_LONG ||
SPA_POD_VALUE(struct spa_pod_long, current) != intval)
goto done;
break;
default:
if (current == NULL ||
SPA_POD_TYPE(current) != SPA_POD_TYPE_INT ||
SPA_POD_VALUE(struct spa_pod_int, current) != intval)
goto done;
break;
}
break;
case ' ': case '\n': case '\t': case '\r': case ',':
templ++;
continue;
}
templ++;
next:
if (spa_pod_iter_has_next(&it[depth]))
current = spa_pod_iter_next(&it[depth]);
else
current = NULL;
}
va_end(args);
done:
return collected;
}
static int test_match(const char *fmt)
{
const char *media_type, *media_subtype, *format;
int rate = -1, res;
struct spa_pod_prop2 channels;
struct spa_pod *pod;
struct spa_pod_maker m = { 0, };
char buffer[4096];
spa_pod_maker_init(&m, buffer, sizeof(buffer));
pod = spa_pod_maker_build(&m, fmt);
spa_debug_pod(pod);
res = spa_pod_match(pod,
"[ \"Format\", "
" [ @s",&media_type," @s",&media_subtype," ], "
" { "
" \"rate\": @vi", &rate,
" \"format\": @vs", &format,
" \"channels\": @VP", &channels,
" \"foo\": @?VP", &channels,
" } "
"]");
printf("collected %d\n", res);
printf("media type %s\n", media_type);
printf("media subtype %s\n", media_subtype);
printf("media rate %d\n", rate);
printf("media format %s\n", format);
printf("media channels: %d %c %04x\n",channels.type, channels.range, channels.flags);
spa_debug_pod(channels.value);
spa_debug_pod(channels.alternatives);
return 0;
}
int main(int argc, char *argv[])
{
struct spa_pod_maker m = { 0, };
char buffer[4096];
struct spa_pod *fmt;
spa_pod_maker_init(&m, buffer, sizeof(buffer));
fmt = spa_pod_maker_build(&m,
"[ \"Format\", "
" [\"video\", \"raw\" ], "
" { "
" \"format\": [ \"eu\", \"I420\", [ \"I420\",\"YUY2\" ] ], "
" \"size\": [ \"ru\", 320x242, [ 1x1, #I_MAX#x#I_MAX# ] ], "
" \"framerate\": [ \"ru\", 25/1, [ 0/1, #I_MAX#/1 ] ] "
" } "
"] ");
spa_debug_pod(fmt);
spa_pod_maker_init(&m, buffer, sizeof(buffer));
fmt = spa_pod_maker_build(&m,
"[ \"Format\", "
" [\"video\", %s ], "
" { "
" \"format\": [ \"eu\", \"I420\", [ %s, \"YUY2\" ] ], "
" \"size\": [ \"ru\", 320x242, [ %R, #I_MAX#x#I_MAX# ] ], "
" \"framerate\": [ \"ru\", %F, [ 0/1, #I_MAX#/1 ] ] "
" } "
"] ",
"raw",
"I420",
&(struct spa_rectangle){ 1, 1 },
&(struct spa_fraction){ 25, 1 }
);
spa_debug_pod(fmt);
{
const char *format = "S16";
int rate = 44100, channels = 2;
spa_pod_maker_init(&m, buffer, sizeof(buffer));
fmt = spa_pod_maker_build(&m,
"[ \"Format\", "
" [\"audio\", \"raw\" ], "
" { "
" \"format\": [@s", format, "] "
" \"rate\": [@i", rate, "] "
" \"channels\": [@i", channels, "] "
" \"rect\": [@R", &SPA_RECTANGLE(32, 22), "] "
" } "
"] ");
spa_debug_pod(fmt);
}
{
const char *format = "S16";
int rate = 44100, channels = 2;
struct spa_rectangle rects[3] = { { 1, 1 }, { 2, 2}, {3, 3}};
struct spa_pod_int pod = SPA_POD_INT_INIT(12);
uint8_t bytes[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
spa_pod_maker_init(&m, buffer, sizeof(buffer));
spa_pod_maker_build(&m,
"[ \"Format\", "
" [\"audio\", \"raw\" ], ");
fmt = spa_pod_maker_build(&m,
" { "
" \"format\": [ %s ] "
" \"rate\": [ %i, ( 44100, 48000, 96000 ) ]"
" \"foo\": %i, ( 1.1, 2.2, 3.2 )"
" \"baz\": ( 1.1f, 2.2f, 3.2f )"
" \"bar\": ( 1x1, 2x2, 3x2 )"
" \"faz\": ( 1/1, 2/2, 3/2 )"
" \"wha\": %a, "
" \"fuz\": %P, "
// " \"fur\": ( (1, 2), (7, 8), (7, 5) ) "
// " \"fur\": ( [1, 2], [7, 8], [7, 5] ) "
" \"buz\": %z, "
" \"boo\": %p, "
" \"foz\": %h, "
" } "
"] ", format, rate, channels,
sizeof(struct spa_rectangle), SPA_POD_TYPE_RECTANGLE, 3, rects,
&pod,
bytes, sizeof(bytes),
fmt,
STDOUT_FILENO);
spa_debug_pod(fmt);
}
spa_pod_maker_init(&m, buffer, sizeof(buffer));
fmt = spa_pod_maker_build(&m,
"[ \"Format\", "
" [\"video\", %s ], "
" { "
" \"format\": [ \"eu\", \"I420\", [ %s, \"YUY2\" ] ], "
" \"size\": [ \"ru\", 320x242, [ %R, #I_MAX#x#I_MAX# ] ], "
" \"framerate\": [ \"ru\", %F, [ 0/1, #I_MAX#/1 ] ] "
" } "
"] ",
"raw",
"I420",
&(struct spa_rectangle){ 1, 1 },
&(struct spa_fraction){ 25, 1 }
);
spa_debug_pod(fmt);
{
const char *subtype = NULL, *format = NULL;
struct spa_pod *pod = NULL;
struct spa_rectangle rect = { 0, 0 };
struct spa_fraction frac = { 0, 0 };
int res;
res = spa_pod_match(fmt,
"[ \"Format\", "
" [\"video\", %s ], "
" { "
" \"format\": [ %*s, %*s, [ %s, %*s ] ], "
" \"size\": [ \"ru\", 320x242, [ %R, %P ] ], "
" \"framerate\": [ %*P, %F, %*S ] "
" } "
"] ",
&subtype,
&format,
&rect,
&pod,
&frac);
printf("collected %d\n", res);
printf("media type %s\n", subtype);
printf("media format %s\n", format);
printf("media size %dx%d\n", rect.width, rect.height);
printf("media size pod\n");
spa_debug_pod(pod);
printf("media framerate %d/%d\n", frac.num, frac.denom);
res = spa_pod_match(fmt,
"[ \"Format\", "
" [\"video\", @s", &subtype, " ], "
" { "
" \"format\": [ %*s, %*s, [ @s", &format, ", %*s ] ], "
" \"size\": [ \"ru\", 320x242, [ @R",&rect,", @P",&pod," ] ], "
" \"framerate\": [ %*P, @F",&frac,", %*S ] "
" } "
"] ");
printf("collected %d\n", res);
printf("media type %s\n", subtype);
printf("media format %s\n", format);
printf("media size %dx%d\n", rect.width, rect.height);
printf("media size pod\n");
spa_debug_pod(pod);
printf("media framerate %d/%d\n", frac.num, frac.denom);
res = spa_pod_match(fmt,
"[ \"Format\", "
" [\"video\", @s", &subtype, " ], "
" { "
" \"format\": [ %*s, %*s, [ @s", &format, ", %*s ] ], "
" \"size\": [ \"ru\", 320x242, [ @R",&rect,", @P",&pod," ] ], "
" \"framerate\": [ %*P, @F",&frac,", %*S ] "
" } "
"] ");
}
test_match("[ \"Format\", "
" [\"audio\", \"raw\" ], "
" { "
" \"format\": [ \"se\", \"S16\", [ \"S16\", \"F32\" ] ], "
" \"rate\": [ \"iru\", 44100, [ 1, 192000 ] ], "
" \"channels\": [ \"ir\", 2, [ 1, #I_MAX# ]] "
" } "
"] ");
test_match(
"[ \"Format\", "
" [ \"audio\", \"raw\"], "
" { "
" \"format\": \"S16LE\", "
" \"rate\": 44100, "
" \"channels\": 2 "
" }"
"]");
return 0;
}

92
spa/tests/test-props5.c Normal file
View file

@ -0,0 +1,92 @@
/* Spa
* Copyright (C) 2017 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <spa/log.h>
#include <lib/debug.h>
#include <spa/pod-parser.h>
int main(int argc, char *argv[])
{
char buffer[4096];
struct spa_pod_builder b = { 0, };
struct spa_pod_parser prs;
struct spa_pod *fmt, *pod = NULL, *pod2 = NULL;
uint32_t format = 1, video = 2, raw = 3;
uint32_t size = 4, framerate = 5, I420 = 6, YUY2 = 7;
uint32_t media_type = -1, media_subtype = -1;
uint32_t fmt_value = -1;
int res;
spa_pod_builder_init(&b, buffer, sizeof(buffer));
fmt = spa_pod_builder_add(&b,
"<",0,format,
" [ i", video, "i",raw,"]"
" :", format, "ieu", I420,
2, I420, YUY2,
" :", size, "Rru", &SPA_RECTANGLE(320,240),
2, &SPA_RECTANGLE(1,1),
&SPA_RECTANGLE(INT32_MAX, INT32_MAX),
" :", framerate, "Fru", &SPA_FRACTION(25,1),
2, &SPA_FRACTION(0,1),
&SPA_FRACTION(INT32_MAX, 1),
">", NULL);
spa_debug_pod(fmt);
spa_pod_parser_pod(&prs, fmt);
res = spa_pod_parser_get(&prs,
"<"
" [ i",&media_type,"*i"/*,&media_subtype,*/" ]"
" :", framerate, "V", &pod,
" :", 10, "?V", &pod2,
" :", format, "?i", &fmt_value,
">", NULL);
printf("res :%d\n", res);
printf("media-type:%d media-subtype:%d\n", media_type, media_subtype);
printf("framerate:\n");
if (pod)
spa_debug_pod(pod);
printf("format: %d\n", fmt_value);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
pod = spa_pod_builder_add(&b,
"<",0,format,
" P", NULL,
" [ i", 44, "i",45,"]"
">", NULL);
spa_debug_pod(pod);
spa_pod_parser_pod(&prs, pod);
res = spa_pod_parser_get(&prs,
"<"
" ?[ i",&media_type,"i",&media_subtype," ]"
" [ i", &video, "i",&raw,"]"
">", NULL);
printf("res :%d\n", res);
printf("video:%d raw:%d\n", video, raw);
return 0;
}

View file

@ -277,7 +277,6 @@ static int make_nodes(struct data *data, const char *device)
int res;
struct spa_props *props;
struct spa_pod_builder b = { 0 };
struct spa_pod_frame f[2];
uint8_t buffer[128];
if ((res = make_node(data, &data->sink,
@ -288,12 +287,10 @@ static int make_nodes(struct data *data, const char *device)
spa_node_set_callbacks(data->sink, &sink_callbacks, data);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_props(&b, &f[0], data->type.props,
SPA_POD_PROP(&f[1], data->type.props_device, 0, SPA_POD_TYPE_STRING, 1,
device ? device : "hw:0"),
SPA_POD_PROP(&f[1], data->type.props_min_latency, 0, SPA_POD_TYPE_INT, 1,
64));
props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
props = spa_pod_builder_props(&b,
data->type.props,
":", data->type.props_device, "s", device ? device : "hw:0",
":", data->type.props_min_latency, "i", 64);
if ((res = spa_node_set_props(data->sink, props)) < 0)
printf("got set_props error %d\n", res);
@ -306,10 +303,9 @@ static int make_nodes(struct data *data, const char *device)
}
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_props(&b, &f[0], data->type.props,
SPA_POD_PROP(&f[1], data->type.props_live, 0, SPA_POD_TYPE_BOOL, 1,
false));
props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
props = spa_pod_builder_props(&b,
data->type.props,
":", data->type.props_live, "b", false);
if ((res = spa_node_set_props(data->source, props)) < 0)
printf("got set_props error %d\n", res);
@ -322,22 +318,16 @@ static int negotiate_formats(struct data *data)
struct spa_format *format, *filter;
uint32_t state = 0;
struct spa_pod_builder b = { 0 };
struct spa_pod_frame f[2];
uint8_t buffer[256];
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_format(&b, &f[0], data->type.format,
data->type.media_type.audio,
data->type.media_subtype.raw,
SPA_POD_PROP(&f[1], data->type.format_audio.format, 0, SPA_POD_TYPE_ID, 1,
data->type.audio_format.S16),
SPA_POD_PROP(&f[1], data->type.format_audio.layout, 0, SPA_POD_TYPE_INT, 1,
SPA_AUDIO_LAYOUT_INTERLEAVED),
SPA_POD_PROP(&f[1], data->type.format_audio.rate, 0, SPA_POD_TYPE_INT, 1,
44100),
SPA_POD_PROP(&f[1], data->type.format_audio.channels, 0, SPA_POD_TYPE_INT, 1,
2));
filter = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
filter = spa_pod_builder_format(&b,
data->type.format,
data->type.media_type.audio, data->type.media_subtype.raw,
":", data->type.format_audio.format, "I", data->type.audio_format.S16,
":", data->type.format_audio.layout, "i", SPA_AUDIO_LAYOUT_INTERLEAVED,
":", data->type.format_audio.rate, "i", 44100,
":", data->type.format_audio.channels, "i", 2);
if ((res =
spa_node_port_enum_formats(data->sink, SPA_DIRECTION_INPUT, 0, &format, filter,

View file

@ -299,7 +299,6 @@ static int make_nodes(struct data *data, const char *device)
int res;
struct spa_props *props;
struct spa_pod_builder b = { 0 };
struct spa_pod_frame f[2];
uint8_t buffer[256];
if ((res =
@ -312,10 +311,9 @@ static int make_nodes(struct data *data, const char *device)
spa_node_set_callbacks(data->source, &source_callbacks, data);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_props(&b, &f[0], data->type.props,
SPA_POD_PROP(&f[1], data->type.props_device, 0, SPA_POD_TYPE_STRING, 1,
device ? device : "/dev/video0"));
props = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_props);
props = spa_pod_builder_props(&b,
data->type.props,
":", data->type.props_device, "s", device ? device : "/dev/video0");
if ((res = spa_node_set_props(data->source, props)) < 0)
printf("got set_props error %d\n", res);
@ -389,7 +387,6 @@ static int negotiate_formats(struct data *data)
int res;
const struct spa_port_info *info;
struct spa_format *format;
struct spa_pod_frame f[2];
uint8_t buffer[256];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
@ -407,17 +404,12 @@ static int negotiate_formats(struct data *data)
return res;
#else
spa_pod_builder_format(&b, &f[0], data->type.format,
data->type.media_type.video, data->type.media_subtype.raw,
SPA_POD_PROP(&f[1], data->type.format_video.format, 0,
SPA_POD_TYPE_ID, 1,
data->type.video_format.YUY2),
SPA_POD_PROP(&f[1], data->type.format_video.size, 0,
SPA_POD_TYPE_RECTANGLE, 1,
320, 240),
SPA_POD_PROP(&f[1], data->type.format_video.framerate, 0,
SPA_POD_TYPE_FRACTION, 1, 25, 1));
format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
format = spa_pod_builder_format(&b,
data->type.format,
data->type.media_type.video, data->type.media_subtype.raw,
":", data->type.format_video.format, "I", data->type.video_format.YUY2,
":", data->type.format_video.size, "R", &SPA_RECTANGLE(320, 240),
":", data->type.format_video.framerate, "F", &SPA_FRACTION(25,1));
#endif
if ((res = spa_node_port_set_format(data->source, SPA_DIRECTION_OUTPUT, 0, 0, format)) < 0)

View file

@ -177,12 +177,6 @@ static Uint32 id_to_sdl_format(struct data *data, uint32_t id)
return SDL_PIXELFORMAT_UNKNOWN;
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
static int impl_send_command(struct spa_node *node, const struct spa_command *command)
{
return SPA_RESULT_OK;
@ -233,7 +227,6 @@ static int impl_port_enum_formats(struct spa_node *node, enum spa_direction dire
uint32_t index)
{
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
const struct spa_format *formats[1];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(d->buffer, sizeof(d->buffer));
struct spa_pod_frame f[2];
SDL_RendererInfo info;
@ -268,19 +261,18 @@ static int impl_port_enum_formats(struct spa_node *node, enum spa_direction dire
}
spa_pod_builder_pop(&b, &f[1]);
spa_pod_builder_add(&b,
PROP_U_MM(&f[1], d->type.format_video.size, SPA_POD_TYPE_RECTANGLE,
WIDTH, HEIGHT,
1, 1, info.max_texture_width, info.max_texture_height),
PROP_U_MM(&f[1], d->type.format_video.framerate, SPA_POD_TYPE_FRACTION,
25, 1,
0, 1, 30, 1),
0);
":", d->type.format_video.size, "Rru", &SPA_RECTANGLE(WIDTH, HEIGHT),
2, &SPA_RECTANGLE(1,1),
&SPA_RECTANGLE(info.max_texture_width,
info.max_texture_height),
":", d->type.format_video.framerate, "Fru", &SPA_FRACTION(25,1),
2, &SPA_FRACTION(0,1),
&SPA_FRACTION(30,1),
NULL);
spa_pod_builder_pop(&b, &f[0]);
formats[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
spa_debug_format(formats[0]);
*format = (struct spa_format *)formats[0];
spa_debug_format(*format);
return SPA_RESULT_OK;
}
@ -291,7 +283,6 @@ static int impl_port_set_format(struct spa_node *node, enum spa_direction direct
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
struct pw_type *t = d->t;
struct spa_pod_builder b = { NULL };
struct spa_pod_frame f[2];
Uint32 sdl_format;
void *dest;
@ -315,24 +306,18 @@ static int impl_port_set_format(struct spa_node *node, enum spa_direction direct
SDL_UnlockTexture(d->texture);
spa_pod_builder_init(&b, d->params_buffer, sizeof(d->params_buffer));
spa_pod_builder_object(&b, &f[0], 0, t->param_alloc_buffers.Buffers,
PROP(&f[1], t->param_alloc_buffers.size, SPA_POD_TYPE_INT,
d->stride * d->format.size.height),
PROP(&f[1], t->param_alloc_buffers.stride, SPA_POD_TYPE_INT,
d->stride),
PROP_U_MM(&f[1], t->param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
32,
2, 32),
PROP(&f[1], t->param_alloc_buffers.align, SPA_POD_TYPE_INT,
16));
d->params[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
d->params[0] = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "i", d->stride * d->format.size.height,
":", t->param_alloc_buffers.stride, "i", d->stride,
":", t->param_alloc_buffers.buffers, "iru", 32,
2, 2, 32,
":", t->param_alloc_buffers.align, "i", 16);
spa_pod_builder_object(&b, &f[0], 0, t->param_alloc_meta_enable.MetaEnable,
PROP(&f[1], t->param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
t->meta.Header),
PROP(&f[1], t->param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
d->params[1] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
d->params[1] = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
return SPA_RESULT_OK;
}
@ -342,18 +327,13 @@ static int impl_port_get_format(struct spa_node *node, enum spa_direction direct
{
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(d->buffer, sizeof(d->buffer));
struct spa_pod_frame f[2];
spa_pod_builder_push_format(&b, &f[0], d->type.format,
d->type.media_type.video,
d->type.media_subtype.raw);
spa_pod_builder_add(&b,
PROP(&f[1], d->type.format_video.format, SPA_POD_TYPE_ID, d->format.format),
PROP(&f[1], d->type.format_video.size, SPA_POD_TYPE_RECTANGLE, &d->format.size),
PROP(&f[1], d->type.format_video.framerate, SPA_POD_TYPE_FRACTION, &d->format.framerate),
0);
spa_pod_builder_pop(&b, &f[0]);
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
*format = spa_pod_builder_format(&b, d->type.format,
d->type.media_type.video,
d->type.media_subtype.raw,
":", d->type.format_video.format, "I", d->format.format,
":", d->type.format_video.size, "R", &d->format.size,
":", d->type.format_video.framerate, "F", &d->format.framerate);
return SPA_RESULT_OK;
}

View file

@ -98,12 +98,6 @@ struct data {
double accumulator;
};
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
static int impl_send_command(struct spa_node *node, const struct spa_command *command)
{
return SPA_RESULT_OK;
@ -155,21 +149,15 @@ static int impl_port_enum_formats(struct spa_node *node, enum spa_direction dire
{
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(d->buffer, sizeof(d->buffer));
struct spa_pod_frame f[2];
if (index != 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_push_format(&b, &f[0], d->type.format,
d->type.media_type.audio,
d->type.media_subtype.raw);
spa_pod_builder_add(&b,
PROP(&f[1], d->type.format_audio.format, SPA_POD_TYPE_ID, d->type.audio_format.S16),
PROP(&f[1], d->type.format_audio.channels, SPA_POD_TYPE_INT, 2),
PROP(&f[1], d->type.format_audio.rate, SPA_POD_TYPE_INT, 44100),
0);
spa_pod_builder_pop(&b, &f[0]);
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
*format = spa_pod_builder_format(&b, d->type.format,
d->type.media_type.audio, d->type.media_subtype.raw,
":", d->type.format_audio.format, "I", d->type.audio_format.S16,
":", d->type.format_audio.channels, "i", 2,
":", d->type.format_audio.rate, "i", 44100);
spa_debug_format(*format);
@ -182,31 +170,32 @@ static int impl_port_set_format(struct spa_node *node, enum spa_direction direct
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
struct pw_type *t = d->t;
struct spa_pod_builder b = { NULL };
struct spa_pod_frame f[2];
if (format == NULL)
return SPA_RESULT_OK;
spa_debug_format(format);
spa_format_audio_raw_parse(format, &d->format, &d->type.format_audio);
if (spa_format_audio_raw_parse(format, &d->format, &d->type.format_audio) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (d->format.format != d->type.audio_format.S16)
return SPA_RESULT_ERROR;
spa_pod_builder_init(&b, d->params_buffer, sizeof(d->params_buffer));
spa_pod_builder_object(&b, &f[0], 0, t->param_alloc_buffers.Buffers,
PROP_U_MM(&f[1], t->param_alloc_buffers.size, SPA_POD_TYPE_INT, 1024, 32, 4096),
PROP (&f[1], t->param_alloc_buffers.stride, SPA_POD_TYPE_INT, 0),
PROP_U_MM(&f[1], t->param_alloc_buffers.buffers, SPA_POD_TYPE_INT, 2, 2, 32),
PROP (&f[1], t->param_alloc_buffers.align, SPA_POD_TYPE_INT, 16));
d->params[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
d->params[0] = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "iru", 1024,
2, 32, 4096,
":", t->param_alloc_buffers.stride, "i", 0,
":", t->param_alloc_buffers.buffers, "iru", 2,
2, 2, 32,
":", t->param_alloc_buffers.align, "i", 16);
spa_pod_builder_object(&b, &f[0], 0, t->param_alloc_meta_enable.MetaEnable,
PROP(&f[1], t->param_alloc_meta_enable.type, SPA_POD_TYPE_ID, t->meta.Header),
PROP(&f[1], t->param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
d->params[1] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
d->params[1] = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
return SPA_RESULT_OK;
}
@ -216,18 +205,12 @@ static int impl_port_get_format(struct spa_node *node, enum spa_direction direct
{
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(d->buffer, sizeof(d->buffer));
struct spa_pod_frame f[2];
spa_pod_builder_push_format(&b, &f[0], d->type.format,
d->type.media_type.audio,
d->type.media_subtype.raw);
spa_pod_builder_add(&b,
PROP(&f[1], d->type.format_audio.format, SPA_POD_TYPE_ID, d->format.format),
PROP(&f[1], d->type.format_audio.channels, SPA_POD_TYPE_INT, d->format.channels),
PROP(&f[1], d->type.format_audio.rate, SPA_POD_TYPE_INT, d->format.rate),
0);
spa_pod_builder_pop(&b, &f[0]);
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
*format = spa_pod_builder_format(&b, d->type.format,
d->type.media_type.audio, d->type.media_subtype.raw,
":", d->type.format_audio.format, "I", d->format.format,
":", d->type.format_audio.channels, "i", d->format.channels,
":", d->type.format_audio.rate, "i", d->format.rate);
return SPA_RESULT_OK;
}

View file

@ -177,12 +177,6 @@ static Uint32 id_to_sdl_format(struct data *data, uint32_t id)
return SDL_PIXELFORMAT_UNKNOWN;
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
static int impl_send_command(struct spa_node *node, const struct spa_command *command)
{
return SPA_RESULT_OK;
@ -233,7 +227,6 @@ static int impl_port_enum_formats(struct spa_node *node, enum spa_direction dire
uint32_t index)
{
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
const struct spa_format *formats[1];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(d->buffer, sizeof(d->buffer));
struct spa_pod_frame f[2];
SDL_RendererInfo info;
@ -267,20 +260,20 @@ static int impl_port_enum_formats(struct spa_node *node, enum spa_direction dire
spa_pod_builder_id(&b, id);
}
spa_pod_builder_pop(&b, &f[1]);
spa_pod_builder_add(&b,
PROP_U_MM(&f[1], d->type.format_video.size, SPA_POD_TYPE_RECTANGLE,
WIDTH, HEIGHT,
1, 1, info.max_texture_width, info.max_texture_height),
PROP_U_MM(&f[1], d->type.format_video.framerate, SPA_POD_TYPE_FRACTION,
25, 1,
0, 1, 30, 1),
0);
":", d->type.format_video.size, "Rru", &SPA_RECTANGLE(WIDTH, HEIGHT),
2, &SPA_RECTANGLE(1,1),
&SPA_RECTANGLE(info.max_texture_width,
info.max_texture_height),
":", d->type.format_video.framerate, "Fru", &SPA_FRACTION(25,1),
2, &SPA_FRACTION(0,1),
&SPA_FRACTION(30,1),
NULL);
spa_pod_builder_pop(&b, &f[0]);
formats[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
spa_debug_format(formats[0]);
*format = (struct spa_format *)formats[0];
spa_debug_format(*format);
return SPA_RESULT_OK;
}
@ -291,7 +284,6 @@ static int impl_port_set_format(struct spa_node *node, enum spa_direction direct
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
struct pw_type *t = d->t;
struct spa_pod_builder b = { NULL };
struct spa_pod_frame f[2];
Uint32 sdl_format;
void *dest;
@ -316,24 +308,18 @@ static int impl_port_set_format(struct spa_node *node, enum spa_direction direct
SDL_UnlockTexture(d->texture);
spa_pod_builder_init(&b, d->params_buffer, sizeof(d->params_buffer));
spa_pod_builder_object(&b, &f[0], 0, t->param_alloc_buffers.Buffers,
PROP(&f[1], t->param_alloc_buffers.size, SPA_POD_TYPE_INT,
d->stride * d->format.size.height),
PROP(&f[1], t->param_alloc_buffers.stride, SPA_POD_TYPE_INT,
d->stride),
PROP_U_MM(&f[1], t->param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
32,
2, 32),
PROP(&f[1], t->param_alloc_buffers.align, SPA_POD_TYPE_INT,
16));
d->params[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
d->params[0] = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "i", d->stride * d->format.size.height,
":", t->param_alloc_buffers.stride, "i", d->stride,
":", t->param_alloc_buffers.buffers, "iru", 2,
2, 1, 32,
":", t->param_alloc_buffers.align, "i", 16);
spa_pod_builder_object(&b, &f[0], 0, t->param_alloc_meta_enable.MetaEnable,
PROP(&f[1], t->param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
t->meta.Header),
PROP(&f[1], t->param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
d->params[1] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
d->params[1] = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
return SPA_RESULT_OK;
}

View file

@ -223,12 +223,6 @@ static Uint32 id_to_sdl_format(struct data *data, uint32_t id)
return SDL_PIXELFORMAT_UNKNOWN;
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
static void
on_stream_format_changed(void *_data, struct spa_format *format)
{
@ -236,7 +230,6 @@ on_stream_format_changed(void *_data, struct spa_format *format)
struct pw_stream *stream = data->stream;
struct pw_type *t = data->t;
struct spa_pod_builder b = { NULL };
struct spa_pod_frame f[2];
struct spa_param *params[2];
Uint32 sdl_format;
void *d;
@ -265,24 +258,18 @@ on_stream_format_changed(void *_data, struct spa_format *format)
SDL_UnlockTexture(data->texture);
spa_pod_builder_init(&b, data->params_buffer, sizeof(data->params_buffer));
spa_pod_builder_object(&b, &f[0], 0, t->param_alloc_buffers.Buffers,
PROP(&f[1], t->param_alloc_buffers.size, SPA_POD_TYPE_INT,
data->stride * data->format.size.height),
PROP(&f[1], t->param_alloc_buffers.stride, SPA_POD_TYPE_INT,
data->stride),
PROP_U_MM(&f[1], t->param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
32,
2, 32),
PROP(&f[1], t->param_alloc_buffers.align, SPA_POD_TYPE_INT,
16));
params[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
params[0] = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "i", data->stride * data->format.size.height,
":", t->param_alloc_buffers.stride, "i", data->stride,
":", t->param_alloc_buffers.buffers, "iru", 32,
2, 2, 32,
":", t->param_alloc_buffers.align, "i", 16);
spa_pod_builder_object(&b, &f[0], 0, t->param_alloc_meta_enable.MetaEnable,
PROP(&f[1], t->param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
t->meta.Header),
PROP(&f[1], t->param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
params[1] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
params[1] = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
pw_stream_finish_format(stream, SPA_RESULT_OK, params, 2);
}
@ -344,13 +331,14 @@ static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remo
}
spa_pod_builder_pop(&b, &f[1]);
spa_pod_builder_add(&b,
PROP_U_MM(&f[1], data->type.format_video.size, SPA_POD_TYPE_RECTANGLE,
WIDTH, HEIGHT,
1, 1, info.max_texture_width, info.max_texture_height),
PROP_U_MM(&f[1], data->type.format_video.framerate, SPA_POD_TYPE_FRACTION,
25, 1,
0, 1, 30, 1),
0);
":", data->type.format_video.size, "Rru", &SPA_RECTANGLE(WIDTH, HEIGHT),
2, &SPA_RECTANGLE(1,1),
&SPA_RECTANGLE(info.max_texture_width,
info.max_texture_height),
":", data->type.format_video.framerate, "Fru", &SPA_FRACTION(25,1),
2, &SPA_RECTANGLE(0,1),
&SPA_RECTANGLE(30,1),
NULL);
spa_pod_builder_pop(&b, &f[0]);
formats[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);

View file

@ -165,12 +165,6 @@ static void on_stream_state_changed(void *_data, enum pw_stream_state old, enum
}
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
static void
on_stream_format_changed(void *_data, struct spa_format *format)
{
@ -178,7 +172,6 @@ on_stream_format_changed(void *_data, struct spa_format *format)
struct pw_stream *stream = data->stream;
struct pw_type *t = data->t;
struct spa_pod_builder b = { NULL };
struct spa_pod_frame f[2];
struct spa_param *params[2];
if (format == NULL) {
@ -190,24 +183,18 @@ on_stream_format_changed(void *_data, struct spa_format *format)
data->stride = SPA_ROUND_UP_N(data->format.size.width * BPP, 4);
spa_pod_builder_init(&b, data->params_buffer, sizeof(data->params_buffer));
spa_pod_builder_object(&b, &f[0], 0, t->param_alloc_buffers.Buffers,
PROP(&f[1], t->param_alloc_buffers.size, SPA_POD_TYPE_INT,
data->stride * data->format.size.height),
PROP(&f[1], t->param_alloc_buffers.stride, SPA_POD_TYPE_INT,
data->stride),
PROP_U_MM(&f[1], t->param_alloc_buffers.buffers, SPA_POD_TYPE_INT,
32,
2, 32),
PROP(&f[1], t->param_alloc_buffers.align, SPA_POD_TYPE_INT,
16));
params[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
params[0] = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "i", data->stride * data->format.size.height,
":", t->param_alloc_buffers.stride, "i", data->stride,
":", t->param_alloc_buffers.buffers, "iru", 2,
2, 1, 32,
":", t->param_alloc_buffers.align, "i", 16);
spa_pod_builder_object(&b, &f[0], 0, t->param_alloc_meta_enable.MetaEnable,
PROP(&f[1], t->param_alloc_meta_enable.type, SPA_POD_TYPE_ID,
t->meta.Header),
PROP(&f[1], t->param_alloc_meta_enable.size, SPA_POD_TYPE_INT,
sizeof(struct spa_meta_header)));
params[1] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_param);
params[1] = spa_pod_builder_param(&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof(struct spa_meta_header));
pw_stream_finish_format(stream, SPA_RESULT_OK, params, 2);
}
@ -234,24 +221,19 @@ static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remo
const struct spa_format *formats[1];
uint8_t buffer[1024];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
struct spa_pod_frame f[2];
printf("remote state: \"%s\"\n",
pw_remote_state_as_string(state));
data->stream = pw_stream_new(remote, "video-src", NULL);
spa_pod_builder_format(&b, &f[0], data->type.format,
data->type.media_type.video,
data->type.media_subtype.raw,
PROP(&f[1], data->type.format_video.format, SPA_POD_TYPE_ID,
data->type.video_format.RGB),
PROP_U_MM(&f[1], data->type.format_video.size, SPA_POD_TYPE_RECTANGLE,
320, 240,
1, 1, 4096, 4096),
PROP(&f[1], data->type.format_video.framerate, SPA_POD_TYPE_FRACTION,
25, 1));
formats[0] = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
formats[0] = spa_pod_builder_format(&b, data->type.format,
data->type.media_type.video, data->type.media_subtype.raw,
":", data->type.format_video.format, "I", data->type.video_format.RGB,
":", data->type.format_video.size, "Rru", &SPA_RECTANGLE(320, 240),
2, &SPA_RECTANGLE(1, 1),
&SPA_RECTANGLE(4096, 4096),
":", data->type.format_video.framerate, "F", &SPA_FRACTION(25, 1));
pw_stream_add_listener(data->stream,
&data->stream_listener,

View file

@ -217,21 +217,8 @@ gst_pipewire_sink_class_init (GstPipeWireSinkClass * klass)
process_mem_data_quark = g_quark_from_static_string ("GstPipeWireSinkProcessMemQuark");
}
#define SPA_PROP_RANGE(min,max) 2,min,max
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_R(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_READONLY,type,1,__VA_ARGS__)
#define PROP_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
#define PROP_U_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
static void
pool_activated (GstPipeWirePool *pool, GstPipeWireSink *sink)
{
@ -244,43 +231,44 @@ pool_activated (GstPipeWirePool *pool, GstPipeWireSink *sink)
struct spa_param *port_params[3];
struct spa_pod_builder b = { NULL };
uint8_t buffer[1024];
struct spa_pod_frame f[2];
struct spa_pod_frame f[1];
config = gst_buffer_pool_get_config (GST_BUFFER_POOL (pool));
gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers);
spa_pod_builder_init (&b, buffer, sizeof (buffer));
spa_pod_builder_push_object (&b, &f[0], 0, t->param_alloc_buffers.Buffers);
spa_pod_builder_push_param (&b, &f[0], t->param_alloc_buffers.Buffers);
if (size == 0)
spa_pod_builder_add (&b,
PROP_U_MM (&f[1], t->param_alloc_buffers.size, SPA_POD_TYPE_INT, 0, 0, INT32_MAX), 0);
":", t->param_alloc_buffers.size, "iru", 0, SPA_PROP_RANGE(0, INT32_MAX), NULL);
else
spa_pod_builder_add (&b,
PROP_MM (&f[1], t->param_alloc_buffers.size, SPA_POD_TYPE_INT, size, size, INT32_MAX), 0);
":", t->param_alloc_buffers.size, "ir", size, SPA_PROP_RANGE(size, INT32_MAX), NULL);
spa_pod_builder_add (&b,
PROP_MM (&f[1], t->param_alloc_buffers.stride, SPA_POD_TYPE_INT, 0, 0, INT32_MAX),
PROP_U_MM (&f[1], t->param_alloc_buffers.buffers, SPA_POD_TYPE_INT, min_buffers, min_buffers, max_buffers ? max_buffers : INT32_MAX),
PROP (&f[1], t->param_alloc_buffers.align, SPA_POD_TYPE_INT, 16),
0);
":", t->param_alloc_buffers.stride, "ir", 0, SPA_PROP_RANGE(0, INT32_MAX),
":", t->param_alloc_buffers.buffers, "iru", min_buffers,
SPA_PROP_RANGE(min_buffers,
max_buffers ? max_buffers : INT32_MAX),
":", t->param_alloc_buffers.align, "i", 16,
NULL);
spa_pod_builder_pop (&b, &f[0]);
port_params[0] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param);
spa_pod_builder_object (&b, &f[0], 0, t->param_alloc_meta_enable.MetaEnable,
PROP (&f[1], t->param_alloc_meta_enable.type, SPA_POD_TYPE_ID, t->meta.Header),
PROP (&f[1], t->param_alloc_meta_enable.size, SPA_POD_TYPE_INT, sizeof (struct spa_meta_header)));
port_params[1] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param);
port_params[1] = spa_pod_builder_param (&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof (struct spa_meta_header));
spa_pod_builder_object (&b, &f[0], 0, t->param_alloc_meta_enable.MetaEnable,
PROP (&f[1], t->param_alloc_meta_enable.type, SPA_POD_TYPE_ID, t->meta.Ringbuffer),
PROP (&f[1], t->param_alloc_meta_enable.size, SPA_POD_TYPE_INT, sizeof (struct spa_meta_ringbuffer)),
PROP (&f[1], t->param_alloc_meta_enable.ringbufferSize, SPA_POD_TYPE_INT,
size * SPA_MAX (4,
SPA_MAX (min_buffers, max_buffers))),
PROP (&f[1], t->param_alloc_meta_enable.ringbufferStride, SPA_POD_TYPE_INT, 0),
PROP (&f[1], t->param_alloc_meta_enable.ringbufferBlocks, SPA_POD_TYPE_INT, 1),
PROP (&f[1], t->param_alloc_meta_enable.ringbufferAlign, SPA_POD_TYPE_INT, 16));
port_params[2] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param);
port_params[2] = spa_pod_builder_param (&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Ringbuffer,
":", t->param_alloc_meta_enable.size, "i", sizeof (struct spa_meta_ringbuffer),
":", t->param_alloc_meta_enable.ringbufferSize, "i", size * SPA_MAX (4,
SPA_MAX (min_buffers, max_buffers)),
":", t->param_alloc_meta_enable.ringbufferStride, "i", 0,
":", t->param_alloc_meta_enable.ringbufferBlocks, "i", 1,
":", t->param_alloc_meta_enable.ringbufferAlign, "i", 16);
pw_thread_loop_lock (sink->main_loop);
pw_stream_finish_format (sink->stream, SPA_RESULT_OK, port_params, 2);

View file

@ -726,11 +726,7 @@ connect_error:
}
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define SPA_PROP_RANGE(min,max) 2,min,max
static void
on_format_changed (void *data,
@ -757,20 +753,19 @@ on_format_changed (void *data,
struct spa_param *params[2];
struct spa_pod_builder b = { NULL };
uint8_t buffer[512];
struct spa_pod_frame f[2];
spa_pod_builder_init (&b, buffer, sizeof (buffer));
spa_pod_builder_object (&b, &f[0], 0, t->param_alloc_buffers.Buffers,
PROP_U_MM (&f[1], t->param_alloc_buffers.size, SPA_POD_TYPE_INT, 0, 0, INT32_MAX),
PROP_U_MM (&f[1], t->param_alloc_buffers.stride, SPA_POD_TYPE_INT, 0, 0, INT32_MAX),
PROP_U_MM (&f[1], t->param_alloc_buffers.buffers, SPA_POD_TYPE_INT, 16, 0, INT32_MAX),
PROP (&f[1], t->param_alloc_buffers.align, SPA_POD_TYPE_INT, 16));
params[0] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param);
params[0] = spa_pod_builder_param (&b,
t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "ir", 0, SPA_PROP_RANGE(0, INT32_MAX),
":", t->param_alloc_buffers.stride, "ir", 0, SPA_PROP_RANGE(0, INT32_MAX),
":", t->param_alloc_buffers.buffers, "ir", 16, SPA_PROP_RANGE(1, INT32_MAX),
":", t->param_alloc_buffers.align, "i", 16);
spa_pod_builder_object (&b, &f[0], 0, t->param_alloc_meta_enable.MetaEnable,
PROP (&f[1], t->param_alloc_meta_enable.type, SPA_POD_TYPE_ID, t->meta.Header),
PROP (&f[1], t->param_alloc_meta_enable.size, SPA_POD_TYPE_INT, sizeof (struct spa_meta_header)));
params[1] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, struct spa_param);
params[1] = spa_pod_builder_param (&b,
t->param_alloc_meta_enable.MetaEnable,
":", t->param_alloc_meta_enable.type, "I", t->meta.Header,
":", t->param_alloc_meta_enable.size, "i", sizeof (struct spa_meta_header));
GST_DEBUG_OBJECT (pwsrc, "doing finish format");
pw_stream_finish_format (pwsrc->stream, SPA_RESULT_OK, params, 2);

View file

@ -19,7 +19,7 @@
#include <errno.h>
#include "spa/pod-iter.h"
#include "spa/pod-parser.h"
#include "pipewire/pipewire.h"
#include "pipewire/interfaces.h"
@ -36,13 +36,12 @@ client_node_marshal_done(void *object, int seq, int res)
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_DONE);
spa_pod_builder_struct(b, &f,
SPA_POD_TYPE_INT, seq,
SPA_POD_TYPE_INT, res);
spa_pod_builder_struct(b,
"i", seq,
"i", res);
pw_protocol_native_end_proxy(proxy, b);
}
@ -56,14 +55,14 @@ client_node_marshal_update(void *object,
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_UPDATE);
spa_pod_builder_struct(b, &f,
SPA_POD_TYPE_INT, change_mask,
SPA_POD_TYPE_INT, max_input_ports,
SPA_POD_TYPE_INT, max_output_ports, SPA_POD_TYPE_POD, props);
spa_pod_builder_struct(b,
"i", change_mask,
"i", max_input_ports,
"i", max_output_ports,
"P", props);
pw_protocol_native_end_proxy(proxy, b);
}
@ -81,36 +80,35 @@ client_node_marshal_port_update(void *object,
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
struct spa_pod_frame f[2];
int i;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_PORT_UPDATE);
spa_pod_builder_add(b,
SPA_POD_TYPE_STRUCT, &f[0],
SPA_POD_TYPE_INT, direction,
SPA_POD_TYPE_INT, port_id,
SPA_POD_TYPE_INT, change_mask, SPA_POD_TYPE_INT, n_possible_formats, 0);
"[",
"i", direction,
"i", port_id,
"i", change_mask,
"i", n_possible_formats, NULL);
for (i = 0; i < n_possible_formats; i++)
spa_pod_builder_add(b, SPA_POD_TYPE_POD, possible_formats[i], 0);
spa_pod_builder_add(b, "P", possible_formats[i], NULL);
spa_pod_builder_add(b, SPA_POD_TYPE_POD, format, SPA_POD_TYPE_INT, n_params, 0);
spa_pod_builder_add(b,
"P", format,
"i", n_params, NULL);
for (i = 0; i < n_params; i++) {
const struct spa_param *p = params[i];
spa_pod_builder_add(b, SPA_POD_TYPE_POD, p, 0);
}
for (i = 0; i < n_params; i++)
spa_pod_builder_add(b, "P", params[i], NULL);
if (info) {
spa_pod_builder_add(b,
SPA_POD_TYPE_STRUCT, &f[1],
SPA_POD_TYPE_INT, info->flags, SPA_POD_TYPE_INT, info->rate, 0);
spa_pod_builder_add(b, -SPA_POD_TYPE_STRUCT, &f[1], 0);
spa_pod_builder_struct(b,
"i", info->flags,
"i", info->rate);
} else {
spa_pod_builder_add(b, SPA_POD_TYPE_POD, NULL, 0);
spa_pod_builder_add(b, "P", NULL, NULL);
}
spa_pod_builder_add(b, -SPA_POD_TYPE_STRUCT, &f[0], 0);
spa_pod_builder_add(b, "]", NULL);
pw_protocol_native_end_proxy(proxy, b);
}
@ -119,11 +117,10 @@ static void client_node_marshal_event_method(void *object, struct spa_event *eve
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_EVENT);
spa_pod_builder_struct(b, &f, SPA_POD_TYPE_POD, event);
spa_pod_builder_struct(b, "P", event);
pw_protocol_native_end_proxy(proxy, b);
}
@ -132,11 +129,10 @@ static void client_node_marshal_destroy(void *object)
{
struct pw_proxy *proxy = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_DESTROY);
spa_pod_builder_struct(b, &f, 0);
spa_pod_builder_struct(b);
pw_protocol_native_end_proxy(proxy, b);
}
@ -144,14 +140,15 @@ static void client_node_marshal_destroy(void *object)
static bool client_node_demarshal_set_props(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
uint32_t seq;
const struct spa_props *props = NULL;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &seq,
-SPA_POD_TYPE_OBJECT, &props, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &seq,
"O", &props, NULL) < 0)
return false;
pw_proxy_notify(proxy, struct pw_client_node_proxy_events, set_props, seq, props);
@ -161,11 +158,11 @@ static bool client_node_demarshal_set_props(void *object, void *data, size_t siz
static bool client_node_demarshal_event_event(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
const struct spa_event *event;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it, SPA_POD_TYPE_OBJECT, &event, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs, "[ O", &event, NULL) < 0)
return false;
pw_proxy_notify(proxy, struct pw_client_node_proxy_events, event, event);
@ -175,13 +172,15 @@ static bool client_node_demarshal_event_event(void *object, void *data, size_t s
static bool client_node_demarshal_add_port(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
int32_t seq, direction, port_id;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &seq,
SPA_POD_TYPE_INT, &direction, SPA_POD_TYPE_INT, &port_id, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &seq,
"i", &direction,
"i", &port_id, NULL) < 0)
return false;
pw_proxy_notify(proxy, struct pw_client_node_proxy_events, add_port, seq, direction, port_id);
@ -191,13 +190,15 @@ static bool client_node_demarshal_add_port(void *object, void *data, size_t size
static bool client_node_demarshal_remove_port(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
int32_t seq, direction, port_id;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &seq,
SPA_POD_TYPE_INT, &direction, SPA_POD_TYPE_INT, &port_id, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &seq,
"i", &direction,
"i", &port_id, NULL) < 0)
return false;
pw_proxy_notify(proxy, struct pw_client_node_proxy_events, remove_port, seq, direction, port_id);
@ -207,17 +208,18 @@ static bool client_node_demarshal_remove_port(void *object, void *data, size_t s
static bool client_node_demarshal_set_format(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
uint32_t seq, direction, port_id, flags;
const struct spa_format *format = NULL;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &seq,
SPA_POD_TYPE_INT, &direction,
SPA_POD_TYPE_INT, &port_id,
SPA_POD_TYPE_INT, &flags,
-SPA_POD_TYPE_OBJECT, &format, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &seq,
"i", &direction,
"i", &port_id,
"i", &flags,
"O", &format, NULL) < 0)
return false;
pw_proxy_notify(proxy, struct pw_client_node_proxy_events, set_format, seq, direction, port_id,
@ -228,16 +230,17 @@ static bool client_node_demarshal_set_format(void *object, void *data, size_t si
static bool client_node_demarshal_set_param(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
uint32_t seq, direction, port_id;
const struct spa_param *param = NULL;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &seq,
SPA_POD_TYPE_INT, &direction,
SPA_POD_TYPE_INT, &port_id,
-SPA_POD_TYPE_OBJECT, &param, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &seq,
"i", &direction,
"i", &port_id,
"O", &param, NULL) < 0)
return false;
pw_proxy_notify(proxy, struct pw_client_node_proxy_events, set_param, seq, direction, port_id, param);
@ -247,19 +250,21 @@ static bool client_node_demarshal_set_param(void *object, void *data, size_t siz
static bool client_node_demarshal_add_mem(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
uint32_t direction, port_id, mem_id, type, memfd_idx, flags, offset, sz;
int memfd;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &direction,
SPA_POD_TYPE_INT, &port_id,
SPA_POD_TYPE_INT, &mem_id,
SPA_POD_TYPE_ID, &type,
SPA_POD_TYPE_INT, &memfd_idx,
SPA_POD_TYPE_INT, &flags,
SPA_POD_TYPE_INT, &offset, SPA_POD_TYPE_INT, &sz, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &direction,
"i", &port_id,
"i", &mem_id,
"I", &type,
"i", &memfd_idx,
"i", &flags,
"i", &offset,
"i", &sz, NULL) < 0)
return false;
memfd = pw_protocol_native_get_proxy_fd(proxy, memfd_idx);
@ -275,52 +280,54 @@ static bool client_node_demarshal_add_mem(void *object, void *data, size_t size)
static bool client_node_demarshal_use_buffers(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
uint32_t seq, direction, port_id, n_buffers, data_id;
struct pw_client_node_buffer *buffers;
int i, j;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &seq,
SPA_POD_TYPE_INT, &direction,
SPA_POD_TYPE_INT, &port_id, SPA_POD_TYPE_INT, &n_buffers, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &seq,
"i", &direction,
"i", &port_id,
"i", &n_buffers, NULL) < 0)
return false;
buffers = alloca(sizeof(struct pw_client_node_buffer) * n_buffers);
for (i = 0; i < n_buffers; i++) {
struct spa_buffer *buf = buffers[i].buffer = alloca(sizeof(struct spa_buffer));
if (!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &buffers[i].mem_id,
SPA_POD_TYPE_INT, &buffers[i].offset,
SPA_POD_TYPE_INT, &buffers[i].size,
SPA_POD_TYPE_INT, &buf->id,
SPA_POD_TYPE_INT, &buf->n_metas, 0))
if (spa_pod_parser_get(&prs,
"i", &buffers[i].mem_id,
"i", &buffers[i].offset,
"i", &buffers[i].size,
"i", &buf->id,
"i", &buf->n_metas, NULL) < 0)
return false;
buf->metas = alloca(sizeof(struct spa_meta) * buf->n_metas);
for (j = 0; j < buf->n_metas; j++) {
struct spa_meta *m = &buf->metas[j];
if (!spa_pod_iter_get(&it,
SPA_POD_TYPE_ID, &m->type,
SPA_POD_TYPE_INT, &m->size, 0))
if (spa_pod_parser_get(&prs,
"I", &m->type,
"i", &m->size, NULL) < 0)
return false;
}
if (!spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &buf->n_datas, 0))
if (spa_pod_parser_get(&prs, "i", &buf->n_datas, NULL) < 0)
return false;
buf->datas = alloca(sizeof(struct spa_data) * buf->n_datas);
for (j = 0; j < buf->n_datas; j++) {
struct spa_data *d = &buf->datas[j];
if (!spa_pod_iter_get(&it,
SPA_POD_TYPE_ID, &d->type,
SPA_POD_TYPE_INT, &data_id,
SPA_POD_TYPE_INT, &d->flags,
SPA_POD_TYPE_INT, &d->mapoffset,
SPA_POD_TYPE_INT, &d->maxsize, 0))
if (spa_pod_parser_get(&prs,
"I", &d->type,
"i", &data_id,
"i", &d->flags,
"i", &d->mapoffset,
"i", &d->maxsize, NULL) < 0)
return false;
d->data = SPA_UINT32_TO_PTR(data_id);
@ -336,12 +343,15 @@ static bool client_node_demarshal_use_buffers(void *object, void *data, size_t s
static bool client_node_demarshal_node_command(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
const struct spa_command *command;
uint32_t seq;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &seq, SPA_POD_TYPE_OBJECT, &command, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &seq,
"O", &command, NULL) < 0)
return false;
pw_proxy_notify(proxy, struct pw_client_node_proxy_events, node_command, seq, command);
@ -351,15 +361,16 @@ static bool client_node_demarshal_node_command(void *object, void *data, size_t
static bool client_node_demarshal_port_command(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
const struct spa_command *command;
uint32_t direction, port_id;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &direction,
SPA_POD_TYPE_INT, &port_id,
SPA_POD_TYPE_OBJECT, &command, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &direction,
"i", &port_id,
"O", &command, NULL) < 0)
return false;
pw_proxy_notify(proxy, struct pw_client_node_proxy_events, port_command, direction,
@ -371,20 +382,21 @@ static bool client_node_demarshal_port_command(void *object, void *data, size_t
static bool client_node_demarshal_transport(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
uint32_t node_id, ridx, widx, memfd_idx;
int readfd, writefd;
struct pw_client_node_transport_info info;
struct pw_client_node_transport *transport;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &node_id,
SPA_POD_TYPE_INT, &ridx,
SPA_POD_TYPE_INT, &widx,
SPA_POD_TYPE_INT, &memfd_idx,
SPA_POD_TYPE_INT, &info.offset,
SPA_POD_TYPE_INT, &info.size, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &node_id,
"i", &ridx,
"i", &widx,
"i", &memfd_idx,
"i", &info.offset,
"i", &info.size, NULL) < 0)
return false;
readfd = pw_protocol_native_get_proxy_fd(proxy, ridx);
@ -406,13 +418,12 @@ client_node_marshal_set_props(void *object, uint32_t seq, const struct spa_props
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_SET_PROPS);
spa_pod_builder_struct(b, &f,
SPA_POD_TYPE_INT, seq,
SPA_POD_TYPE_POD, props);
spa_pod_builder_struct(b,
"i", seq,
"P", props);
pw_protocol_native_end_resource(resource, b);
}
@ -421,11 +432,10 @@ static void client_node_marshal_event_event(void *object, const struct spa_event
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_EVENT);
spa_pod_builder_struct(b, &f, SPA_POD_TYPE_POD, event);
spa_pod_builder_struct(b, "P", event);
pw_protocol_native_end_resource(resource, b);
}
@ -436,13 +446,13 @@ client_node_marshal_add_port(void *object,
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_ADD_PORT);
spa_pod_builder_struct(b, &f,
SPA_POD_TYPE_INT, seq,
SPA_POD_TYPE_INT, direction, SPA_POD_TYPE_INT, port_id);
spa_pod_builder_struct(b,
"i", seq,
"i", direction,
"i", port_id);
pw_protocol_native_end_resource(resource, b);
}
@ -453,13 +463,13 @@ client_node_marshal_remove_port(void *object,
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_REMOVE_PORT);
spa_pod_builder_struct(b, &f,
SPA_POD_TYPE_INT, seq,
SPA_POD_TYPE_INT, direction, SPA_POD_TYPE_INT, port_id);
spa_pod_builder_struct(b,
"i", seq,
"i", direction,
"i", port_id);
pw_protocol_native_end_resource(resource, b);
}
@ -474,16 +484,15 @@ client_node_marshal_set_format(void *object,
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_SET_FORMAT);
spa_pod_builder_struct(b, &f,
SPA_POD_TYPE_INT, seq,
SPA_POD_TYPE_INT, direction,
SPA_POD_TYPE_INT, port_id,
SPA_POD_TYPE_INT, flags,
SPA_POD_TYPE_POD, format);
spa_pod_builder_struct(b,
"i", seq,
"i", direction,
"i", port_id,
"i", flags,
"P", format);
pw_protocol_native_end_resource(resource, b);
}
@ -497,15 +506,14 @@ client_node_marshal_set_param(void *object,
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_SET_PARAM);
spa_pod_builder_struct(b, &f,
SPA_POD_TYPE_INT, seq,
SPA_POD_TYPE_INT, direction,
SPA_POD_TYPE_INT, port_id,
SPA_POD_TYPE_POD, param);
spa_pod_builder_struct(b,
"i", seq,
"i", direction,
"i", port_id,
"P", param);
pw_protocol_native_end_resource(resource, b);
}
@ -520,18 +528,18 @@ client_node_marshal_add_mem(void *object,
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_ADD_MEM);
spa_pod_builder_struct(b, &f,
SPA_POD_TYPE_INT, direction,
SPA_POD_TYPE_INT, port_id,
SPA_POD_TYPE_INT, mem_id,
SPA_POD_TYPE_ID, type,
SPA_POD_TYPE_INT, pw_protocol_native_add_resource_fd(resource, memfd),
SPA_POD_TYPE_INT, flags,
SPA_POD_TYPE_INT, offset, SPA_POD_TYPE_INT, size);
spa_pod_builder_struct(b,
"i", direction,
"i", port_id,
"i", mem_id,
"I", type,
"i", pw_protocol_native_add_resource_fd(resource, memfd),
"i", flags,
"i", offset,
"i", size);
pw_protocol_native_end_resource(resource, b);
}
@ -545,43 +553,45 @@ client_node_marshal_use_buffers(void *object,
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
uint32_t i, j;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_USE_BUFFERS);
spa_pod_builder_add(b,
SPA_POD_TYPE_STRUCT, &f,
SPA_POD_TYPE_INT, seq,
SPA_POD_TYPE_INT, direction,
SPA_POD_TYPE_INT, port_id, SPA_POD_TYPE_INT, n_buffers, 0);
"[",
"i", seq,
"i", direction,
"i", port_id,
"i", n_buffers, NULL);
for (i = 0; i < n_buffers; i++) {
struct spa_buffer *buf = buffers[i].buffer;
spa_pod_builder_add(b,
SPA_POD_TYPE_INT, buffers[i].mem_id,
SPA_POD_TYPE_INT, buffers[i].offset,
SPA_POD_TYPE_INT, buffers[i].size,
SPA_POD_TYPE_INT, buf->id, SPA_POD_TYPE_INT, buf->n_metas, 0);
"i", buffers[i].mem_id,
"i", buffers[i].offset,
"i", buffers[i].size,
"i", buf->id,
"i", buf->n_metas, NULL);
for (j = 0; j < buf->n_metas; j++) {
struct spa_meta *m = &buf->metas[j];
spa_pod_builder_add(b,
SPA_POD_TYPE_ID, m->type, SPA_POD_TYPE_INT, m->size, 0);
"I", m->type,
"i", m->size, NULL);
}
spa_pod_builder_add(b, SPA_POD_TYPE_INT, buf->n_datas, 0);
spa_pod_builder_add(b, "i", buf->n_datas, NULL);
for (j = 0; j < buf->n_datas; j++) {
struct spa_data *d = &buf->datas[j];
spa_pod_builder_add(b,
SPA_POD_TYPE_ID, d->type,
SPA_POD_TYPE_INT, SPA_PTR_TO_UINT32(d->data),
SPA_POD_TYPE_INT, d->flags,
SPA_POD_TYPE_INT, d->mapoffset,
SPA_POD_TYPE_INT, d->maxsize, 0);
"I", d->type,
"i", SPA_PTR_TO_UINT32(d->data),
"i", d->flags,
"i", d->mapoffset,
"i", d->maxsize, NULL);
}
}
spa_pod_builder_add(b, -SPA_POD_TYPE_STRUCT, &f, 0);
spa_pod_builder_add(b, "]", NULL);
pw_protocol_native_end_resource(resource, b);
}
@ -591,11 +601,10 @@ client_node_marshal_node_command(void *object, uint32_t seq, const struct spa_co
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_NODE_COMMAND);
spa_pod_builder_struct(b, &f, SPA_POD_TYPE_INT, seq, SPA_POD_TYPE_POD, command);
spa_pod_builder_struct(b, "i", seq, "P", command);
pw_protocol_native_end_resource(resource, b);
}
@ -608,14 +617,13 @@ client_node_marshal_port_command(void *object,
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_PORT_COMMAND);
spa_pod_builder_struct(b, &f,
SPA_POD_TYPE_INT, direction,
SPA_POD_TYPE_INT, port_id,
SPA_POD_TYPE_POD, command);
spa_pod_builder_struct(b,
"i", direction,
"i", port_id,
"P", command);
pw_protocol_native_end_resource(resource, b);
}
@ -625,20 +633,19 @@ static void client_node_marshal_transport(void *object, uint32_t node_id, int re
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
struct pw_client_node_transport_info info;
pw_client_node_transport_get_info(transport, &info);
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE_PROXY_EVENT_TRANSPORT);
spa_pod_builder_struct(b, &f,
SPA_POD_TYPE_INT, node_id,
SPA_POD_TYPE_INT, pw_protocol_native_add_resource_fd(resource, readfd),
SPA_POD_TYPE_INT, pw_protocol_native_add_resource_fd(resource, writefd),
SPA_POD_TYPE_INT, pw_protocol_native_add_resource_fd(resource, info.memfd),
SPA_POD_TYPE_INT, info.offset,
SPA_POD_TYPE_INT, info.size);
spa_pod_builder_struct(b,
"i", node_id,
"i", pw_protocol_native_add_resource_fd(resource, readfd),
"i", pw_protocol_native_add_resource_fd(resource, writefd),
"i", pw_protocol_native_add_resource_fd(resource, info.memfd),
"i", info.offset,
"i", info.size);
pw_protocol_native_end_resource(resource, b);
}
@ -647,13 +654,14 @@ static void client_node_marshal_transport(void *object, uint32_t node_id, int re
static bool client_node_demarshal_done(void *object, void *data, size_t size)
{
struct pw_resource *resource = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
uint32_t seq, res;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &seq,
SPA_POD_TYPE_INT, &res, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &seq,
"i", &res, NULL) < 0)
return false;
pw_resource_do(resource, struct pw_client_node_proxy_methods, done, seq, res);
@ -663,15 +671,17 @@ static bool client_node_demarshal_done(void *object, void *data, size_t size)
static bool client_node_demarshal_update(void *object, void *data, size_t size)
{
struct pw_resource *resource = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
uint32_t change_mask, max_input_ports, max_output_ports;
const struct spa_props *props;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &change_mask,
SPA_POD_TYPE_INT, &max_input_ports,
SPA_POD_TYPE_INT, &max_output_ports, -SPA_POD_TYPE_OBJECT, &props, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &change_mask,
"i", &max_input_ports,
"i", &max_output_ports,
"O", &props, NULL) < 0)
return false;
pw_resource_do(resource, struct pw_client_node_proxy_methods, update, change_mask,
@ -684,45 +694,47 @@ static bool client_node_demarshal_update(void *object, void *data, size_t size)
static bool client_node_demarshal_port_update(void *object, void *data, size_t size)
{
struct pw_resource *resource = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
uint32_t i, direction, port_id, change_mask, n_possible_formats, n_params;
const struct spa_param **params = NULL;
const struct spa_format **possible_formats = NULL, *format = NULL;
struct spa_port_info info, *infop = NULL;
struct spa_pod *ipod;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &direction,
SPA_POD_TYPE_INT, &port_id,
SPA_POD_TYPE_INT, &change_mask,
SPA_POD_TYPE_INT, &n_possible_formats, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"i", &direction,
"i", &port_id,
"i", &change_mask,
"i", &n_possible_formats, NULL) < 0)
return false;
possible_formats = alloca(n_possible_formats * sizeof(struct spa_format *));
for (i = 0; i < n_possible_formats; i++)
if (!spa_pod_iter_get(&it, SPA_POD_TYPE_OBJECT, &possible_formats[i], 0))
if (spa_pod_parser_get(&prs, "O", &possible_formats[i], NULL) < 0)
return false;
if (!spa_pod_iter_get(&it, -SPA_POD_TYPE_OBJECT, &format, SPA_POD_TYPE_INT, &n_params, 0))
if (spa_pod_parser_get(&prs, "O", &format, "i", &n_params, NULL) < 0)
return false;
params = alloca(n_params * sizeof(struct spa_param *));
for (i = 0; i < n_params; i++)
if (!spa_pod_iter_get(&it, SPA_POD_TYPE_OBJECT, &params[i], 0))
if (spa_pod_parser_get(&prs, "O", &params[i], NULL) < 0)
return false;
if (!spa_pod_iter_get(&it, -SPA_POD_TYPE_STRUCT, &ipod, 0))
if (spa_pod_parser_get(&prs, "T", &ipod, NULL) < 0)
return false;
if (ipod) {
struct spa_pod_iter it2;
struct spa_pod_parser p2;
infop = &info;
if (!spa_pod_iter_pod(&it2, ipod) ||
!spa_pod_iter_get(&it2,
SPA_POD_TYPE_INT, &info.flags,
SPA_POD_TYPE_INT, &info.rate, 0))
spa_pod_parser_pod(&p2, ipod);
if (spa_pod_parser_get(&p2,
"["
"i", &info.flags,
"i", &info.rate, NULL) < 0)
return false;
}
@ -740,11 +752,13 @@ static bool client_node_demarshal_port_update(void *object, void *data, size_t s
static bool client_node_demarshal_event_method(void *object, void *data, size_t size)
{
struct pw_resource *resource = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
struct spa_event *event;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it, SPA_POD_TYPE_OBJECT, &event, 0))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs,
"["
"O", &event, NULL) < 0)
return false;
pw_resource_do(resource, struct pw_client_node_proxy_methods, event, event);
@ -754,9 +768,10 @@ static bool client_node_demarshal_event_method(void *object, void *data, size_t
static bool client_node_demarshal_destroy(void *object, void *data, size_t size)
{
struct pw_resource *resource = object;
struct spa_pod_iter it;
struct spa_pod_parser prs;
if (!spa_pod_iter_struct(&it, data, size))
spa_pod_parser_init(&prs, data, size, 0);
if (spa_pod_parser_get(&prs, "[", NULL) < 0)
return false;
pw_resource_do(resource, struct pw_client_node_proxy_methods, destroy);

View file

@ -368,9 +368,6 @@ static int port_set_io(struct spa_node *node, enum spa_direction direction, uint
return SPA_RESULT_OK;
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
static int port_enum_formats(struct spa_node *node, enum spa_direction direction, uint32_t port_id,
struct spa_format **format,
const struct spa_format *filter,
@ -383,8 +380,6 @@ static int port_enum_formats(struct spa_node *node, enum spa_direction direction
struct spa_format *fmt;
uint8_t buffer[4096];
int res;
struct spa_pod_frame f[2];
struct jack_engine_control *ctrl = pd->node->node.server->engine_control;
if (index > 0)
@ -394,27 +389,29 @@ static int port_enum_formats(struct spa_node *node, enum spa_direction direction
if (pd->port.jack_port) {
if (pd->port.jack_port->type_id == 0) {
spa_pod_builder_format(&b, &f[0], t->format,
fmt = spa_pod_builder_format(&b,
t->format,
t->media_type.audio, t->media_subtype.raw,
PROP(&f[1], t->format_audio.format, SPA_POD_TYPE_ID, t->audio_format.F32),
PROP(&f[1], t->format_audio.rate, SPA_POD_TYPE_INT, ctrl->sample_rate),
PROP(&f[1], t->format_audio.channels, SPA_POD_TYPE_INT, 1));
":", t->format_audio.format, "I", t->audio_format.F32,
":", t->format_audio.rate, "i", ctrl->sample_rate,
":", t->format_audio.channels, "i", 1);
}
else if (pd->port.jack_port->type_id == 1) {
spa_pod_builder_format(&b, &f[0], t->format,
fmt = spa_pod_builder_format(&b,
t->format,
t->media_type.audio, t->media_subtype_audio.midi);
}
else
return SPA_RESULT_ENUM_END;
}
else {
spa_pod_builder_format(&b, &f[0], t->format,
fmt = spa_pod_builder_format(&b,
t->format,
t->media_type.audio, t->media_subtype.raw,
PROP(&f[1], t->format_audio.format, SPA_POD_TYPE_ID, t->audio_format.S16),
PROP(&f[1], t->format_audio.rate, SPA_POD_TYPE_INT, ctrl->sample_rate),
PROP(&f[1], t->format_audio.channels, SPA_POD_TYPE_INT, 2));
":", t->format_audio.format, "I", t->audio_format.S16,
":", t->format_audio.rate, "i", ctrl->sample_rate,
":", t->format_audio.channels, "i", 2);
}
fmt = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
spa_pod_builder_init(&b, pd->buffer, sizeof(pd->buffer));
if ((res = spa_format_filter(fmt, filter, &b)) < 0)

File diff suppressed because it is too large Load diff

View file

@ -29,7 +29,7 @@
#include <spa/node.h>
#include <spa/monitor.h>
#include <spa/pod-iter.h>
#include <spa/pod-parser.h>
#include <pipewire/log.h>
#include <pipewire/type.h>
@ -73,27 +73,29 @@ static void add_item(struct pw_spa_monitor *this, struct spa_monitor_item *item)
const struct spa_support *support;
uint32_t n_support;
spa_pod_object_query(&item->object,
t->monitor.name, SPA_POD_TYPE_STRING, &name,
t->monitor.id, SPA_POD_TYPE_STRING, &id,
t->monitor.klass, SPA_POD_TYPE_STRING, &klass,
t->monitor.factory, SPA_POD_TYPE_POINTER, &factory,
t->monitor.info, SPA_POD_TYPE_STRUCT, &info, 0);
if (spa_pod_object_parse(&item->object,
":",t->monitor.name, "s", &name,
":",t->monitor.id, "s", &id,
":",t->monitor.klass, "s", &klass,
":",t->monitor.factory, "p", &factory,
":",t->monitor.info, "T", &info, NULL) < 0)
return;
pw_log_debug("monitor %p: add: \"%s\" (%s)", this, name, id);
props = pw_properties_new(NULL, NULL);
if (info) {
struct spa_pod_iter it;
struct spa_pod_parser prs;
spa_pod_iter_pod(&it, info);
while (true) {
const char *key, *val;
if (!spa_pod_iter_get
(&it, SPA_POD_TYPE_STRING, &key, SPA_POD_TYPE_STRING, &val, 0))
break;
pw_properties_set(props, key, val);
spa_pod_parser_pod(&prs, info);
if (spa_pod_parser_get(&prs, "[", NULL) == 0) {
while (true) {
const char *key, *val;
if (spa_pod_parser_get(&prs, "ss", &key, &val, NULL) < 0)
break;
pw_properties_set(props, key, val);
}
}
}
@ -157,9 +159,10 @@ static void remove_item(struct pw_spa_monitor *this, struct spa_monitor_item *it
const char *name, *id;
struct pw_type *t = pw_core_get_type(impl->core);
spa_pod_object_query(&item->object,
t->monitor.name, SPA_POD_TYPE_STRING, &name,
t->monitor.id, SPA_POD_TYPE_STRING, &id, 0);
if (spa_pod_object_parse(&item->object,
":",t->monitor.name, "s", &name,
":",t->monitor.id, "s", &id, NULL) < 0)
return;
pw_log_debug("monitor %p: remove: \"%s\" (%s)", this, name, id);
mitem = find_item(this, id);
@ -183,8 +186,9 @@ static void on_monitor_event(void *data, struct spa_event *event)
struct spa_monitor_item *item = SPA_POD_CONTENTS(struct spa_event, event);
const char *name;
spa_pod_object_query(&item->object,
t->monitor.name, SPA_POD_TYPE_STRING, &name, 0);
if (spa_pod_object_parse(&item->object,
":",t->monitor.name, "s", &name, NULL) < 0)
return;
pw_log_debug("monitor %p: changed: \"%s\"", this, name);
}

View file

@ -236,9 +236,8 @@ static struct spa_param *find_meta_enable(struct pw_core *core, struct spa_param
(&params[i]->object.pod, core->type.param_alloc_meta_enable.MetaEnable)) {
uint32_t qtype;
if (spa_param_query(params[i],
core->type.param_alloc_meta_enable.type,
SPA_POD_TYPE_ID, &qtype, 0) != 1)
if (spa_param_parse(params[i],
":", core->type.param_alloc_meta_enable.type, "I", &qtype, NULL) < 0)
continue;
if (qtype == type)
@ -285,11 +284,9 @@ static struct spa_buffer **alloc_buffers(struct pw_link *this,
(&params[i]->object.pod, this->core->type.param_alloc_meta_enable.MetaEnable)) {
uint32_t type, size;
if (spa_param_query(params[i],
this->core->type.param_alloc_meta_enable.type,
SPA_POD_TYPE_ID, &type,
this->core->type.param_alloc_meta_enable.size,
SPA_POD_TYPE_INT, &size, 0) != 2)
if (spa_param_parse(params[i],
":", this->core->type.param_alloc_meta_enable.type, "I", &type,
":", this->core->type.param_alloc_meta_enable.size, "i", &size, NULL) < 0)
continue;
pw_log_debug("link %p: enable meta %d %d", this, type, size);
@ -534,11 +531,9 @@ static int do_allocation(struct pw_link *this, uint32_t in_state, uint32_t out_s
uint32_t ms, s;
max_buffers = 1;
if (spa_param_query(param,
this->core->type.param_alloc_meta_enable.ringbufferSize,
SPA_POD_TYPE_INT, &ms,
this->core->type.param_alloc_meta_enable.
ringbufferStride, SPA_POD_TYPE_INT, &s, 0) == 2) {
if (spa_param_parse(param,
":", this->core->type.param_alloc_meta_enable.ringbufferSize, "i", &ms,
":", this->core->type.param_alloc_meta_enable.ringbufferStride, "i", &s, NULL) >= 0) {
minsize = ms;
stride = s;
}
@ -551,13 +546,10 @@ static int do_allocation(struct pw_link *this, uint32_t in_state, uint32_t out_s
uint32_t qmax_buffers = max_buffers,
qminsize = minsize, qstride = stride;
spa_param_query(param,
this->core->type.param_alloc_buffers.size,
SPA_POD_TYPE_INT, &qminsize,
this->core->type.param_alloc_buffers.stride,
SPA_POD_TYPE_INT, &qstride,
this->core->type.param_alloc_buffers.buffers,
SPA_POD_TYPE_INT, &qmax_buffers, 0);
spa_param_parse(param,
":", this->core->type.param_alloc_buffers.size, "i", &qminsize,
":", this->core->type.param_alloc_buffers.stride, "i", &qstride,
":", this->core->type.param_alloc_buffers.buffers, "i", &qmax_buffers, NULL);
max_buffers =
qmax_buffers == 0 ? max_buffers : SPA_MIN(qmax_buffers,