mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
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:
parent
3e49aec61b
commit
24d80e5c00
54 changed files with 3616 additions and 2817 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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" */
|
||||
|
|
|
|||
|
|
@ -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,24 +149,19 @@ 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;
|
||||
}
|
||||
|
||||
static inline int spa_format_fixate(struct spa_format *format)
|
||||
{
|
||||
struct spa_pod_prop *prop;
|
||||
|
|
|
|||
|
|
@ -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__)
|
||||
|
|
|
|||
67
spa/include/spa/json-builder.h
Normal file
67
spa/include/spa/json-builder.h
Normal 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
510
spa/include/spa/json.h
Normal 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__ */
|
||||
|
|
@ -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(¶m->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); \
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
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_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)
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
if (type == '{' || type == '[')
|
||||
continue;
|
||||
|
||||
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, type);
|
||||
spa_pod_builder_addv(builder, type, args);
|
||||
va_start(args, format);
|
||||
res = spa_pod_builder_addv(builder, format, args);
|
||||
va_end(args);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define SPA_POD_OBJECT(f,id,type,...) \
|
||||
SPA_POD_TYPE_OBJECT, f, id, type, __VA_ARGS__, -SPA_POD_TYPE_OBJECT, f
|
||||
#define SPA_POD_OBJECT(id,type,...) \
|
||||
"<", id, type, ##__VA_ARGS__, ">"
|
||||
|
||||
#define SPA_POD_STRUCT(f,...) \
|
||||
SPA_POD_TYPE_STRUCT, f, __VA_ARGS__, -SPA_POD_TYPE_STRUCT, f
|
||||
#define SPA_POD_STRUCT(...) \
|
||||
"[", ##__VA_ARGS__, "]"
|
||||
|
||||
#define SPA_POD_PROP(f,key,flags,type,...) \
|
||||
SPA_POD_TYPE_PROP, f, key, flags, type, __VA_ARGS__, -SPA_POD_TYPE_PROP, f
|
||||
#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_object(b,f,id,type,...) \
|
||||
spa_pod_builder_add(b, SPA_POD_OBJECT(f,id,type,__VA_ARGS__), 0)
|
||||
|
||||
#define spa_pod_builder_struct(b,f,...) \
|
||||
spa_pod_builder_add(b, SPA_POD_STRUCT(f,__VA_ARGS__), 0)
|
||||
#define spa_pod_builder_struct(b,...) \
|
||||
spa_pod_builder_add(b, SPA_POD_STRUCT(__VA_ARGS__), NULL)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
static inline bool spa_pod_iter_has_next(struct spa_pod_iter *iter)
|
||||
{
|
||||
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)
|
||||
static inline void spa_pod_iter_advance(struct spa_pod_iter *iter, struct spa_pod *current)
|
||||
{
|
||||
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
|
||||
|
|
|
|||
313
spa/include/spa/pod-parser.h
Normal file
313
spa/include/spa/pod-parser.h
Normal 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__ */
|
||||
|
|
@ -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" */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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" */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
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,
|
||||
-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]);
|
||||
":", 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,
|
||||
/*
|
||||
* ( "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,
|
||||
-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);
|
||||
":", 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
861
spa/tests/test-props4.c
Normal 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
92
spa/tests/test-props5.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
format = spa_pod_builder_format(&b,
|
||||
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);
|
||||
":", 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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
*format = spa_pod_builder_format(&b, 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);
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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, ¶m, 0))
|
||||
spa_pod_parser_init(&prs, data, size, 0);
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"["
|
||||
"i", &seq,
|
||||
"i", &direction,
|
||||
"i", &port_id,
|
||||
"O", ¶m, 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, ¶ms[i], 0))
|
||||
if (spa_pod_parser_get(&prs, "O", ¶ms[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);
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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,29 +73,31 @@ 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);
|
||||
spa_pod_parser_pod(&prs, info);
|
||||
if (spa_pod_parser_get(&prs, "[", NULL) == 0) {
|
||||
while (true) {
|
||||
const char *key, *val;
|
||||
if (!spa_pod_iter_get
|
||||
(&it, SPA_POD_TYPE_STRING, &key, SPA_POD_TYPE_STRING, &val, 0))
|
||||
if (spa_pod_parser_get(&prs, "ss", &key, &val, NULL) < 0)
|
||||
break;
|
||||
pw_properties_set(props, key, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
support = pw_core_get_support(impl->core, &n_support);
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -236,9 +236,8 @@ static struct spa_param *find_meta_enable(struct pw_core *core, struct spa_param
|
|||
(¶ms[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,
|
|||
(¶ms[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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue