Unify props, params and formats

Make enum_params and set_param to configure properties, format
and other parameters. This allows us to remove some duplicate
code and make the properties and parameters much more extensible.
Use the object id to mark the id of the parameter.
Remove the spa_format and spa_props.
We can now make the client-node easier by merging the various
format methods into the params.
Make the stream API more powerful now that we can pass params
around.
This commit is contained in:
Wim Taymans 2017-11-07 17:39:31 +01:00
parent b6ee67905d
commit f3bca48398
87 changed files with 3773 additions and 3580 deletions

View file

@ -51,7 +51,7 @@ spa_type_format_audio_map(struct spa_type_map *map, struct spa_type_format_audio
}
static inline int
spa_format_audio_raw_parse(const struct spa_format *format,
spa_format_audio_raw_parse(const struct spa_pod_object *format,
struct spa_audio_info_raw *info, struct spa_type_format_audio *type)
{
struct spa_pod_parser prs;

View file

@ -41,7 +41,7 @@ enum spa_clock_state {
#include <spa/defs.h>
#include <spa/plugin.h>
#include <spa/props.h>
#include <spa/pod-builder.h>
/**
* spa_clock:
@ -64,9 +64,8 @@ struct spa_clock {
/**
* spa_clock::get_props:
* @clock: a #spa_clock
* @props: a location for a #struct spa_props pointer
*
* Get the configurable properties of @clock.
* Get the parameters of @clock.
*
* The returned @props is a snapshot of the current configuration and
* can be modified. The modifications will take effect after a call
@ -77,8 +76,9 @@ struct spa_clock {
* #SPA_RESULT_NOT_IMPLEMENTED when there are no properties
* implemented on @clock
*/
int (*get_props) (struct spa_clock *clock,
struct spa_props **props);
int (*enum_params) (struct spa_clock *clock,
uint32_t id, uint32_t *index,
struct spa_pod_builder *builder);
/**
* spa_clock::set_props:
* @clock: a #spa_clock
@ -101,8 +101,9 @@ struct spa_clock {
* #SPA_RESULT_WRONG_PROPERTY_TYPE when a property has the wrong
* type.
*/
int (*set_props) (struct spa_clock *clock,
const struct spa_props *props);
int (*set_param) (struct spa_clock *clock,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param);
int (*get_time) (struct spa_clock *clock,
int32_t *rate,
@ -110,8 +111,8 @@ struct spa_clock {
int64_t *monotonic_time);
};
#define spa_clock_get_props(n,...) (n)->get_props((n),__VA_ARGS__)
#define spa_clock_set_props(n,...) (n)->set_props((n),__VA_ARGS__)
#define spa_clock_enum_params(n,...) (n)->enum_params((n),__VA_ARGS__)
#define spa_clock_set_param(n,...) (n)->set_param((n),__VA_ARGS__)
#define spa_clock_get_time(n,...) (n)->get_time((n),__VA_ARGS__)
#ifdef __cplusplus

View file

@ -73,6 +73,8 @@ enum spa_result {
SPA_RESULT_INCOMPATIBLE_VERSION = -37,
SPA_RESULT_NOT_FOUND = -38,
SPA_RESULT_BUSY = -39,
SPA_RESULT_UNKNOWN_PARAM = -40,
SPA_RESULT_PARAM_INCOMPLETE = -41,
};
#define SPA_ASYNC_BIT (1 << 30)

View file

@ -1,61 +0,0 @@
/* Simple Plugin API
* Copyright (C) 2016 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_FORMAT_BUILDER_H__
#define __SPA_FORMAT_BUILDER_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
#include <spa/format.h>
#include <spa/pod-builder.h>
#define SPA_FORMAT_INIT(size,type,media_type,media_subtype) \
{ { size, SPA_POD_TYPE_OBJECT }, \
{ { 0, type }, \
SPA_POD_ID_INIT(media_type), \
SPA_POD_ID_INIT(media_subtype) } }
static inline uint32_t
spa_pod_builder_push_format(struct spa_pod_builder *builder,
struct spa_pod_frame *frame,
uint32_t format_type,
uint32_t media_type,
uint32_t media_subtype)
{
const struct spa_format p = SPA_FORMAT_INIT(sizeof(struct spa_format_body),
format_type, media_type, media_subtype);
return spa_pod_builder_push(builder, frame, &p.pod,
spa_pod_builder_raw(builder, &p, sizeof(p)));
}
#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" */
#endif
#endif /* __SPA_FORMAT_BUILDER_H__ */

View file

@ -138,40 +138,6 @@ spa_type_media_subtype_audio_map(struct spa_type_map *map,
}
}
#define SPA_FORMAT_BODY_FOREACH(body, size, iter) \
for ((iter) = SPA_MEMBER((body), sizeof(struct spa_format_body), struct spa_pod_prop); \
(iter) < SPA_MEMBER((body), (size), struct spa_pod_prop); \
(iter) = SPA_MEMBER((iter), SPA_ROUND_UP_N(SPA_POD_SIZE(iter), 8), struct spa_pod_prop))
#define SPA_FORMAT_FOREACH(format, iter) \
SPA_FORMAT_BODY_FOREACH(&format->body, SPA_POD_BODY_SIZE(format), iter)
#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)
#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 int spa_format_fixate(struct spa_format *format)
{
struct spa_pod_prop *prop;
SPA_FORMAT_FOREACH(format, prop)
prop->body.flags &= ~SPA_POD_PROP_FLAG_UNSET;
return SPA_RESULT_OK;
}
#ifdef __cplusplus
} /* extern "C" */
#endif

View file

@ -24,7 +24,6 @@
extern "C" {
#endif
struct spa_format;
#define SPA_TYPE__Format SPA_TYPE_POD_OBJECT_BASE "Format"
#define SPA_TYPE_FORMAT_BASE SPA_TYPE__Format ":"
@ -77,24 +76,6 @@ struct spa_format;
#define SPA_TYPE_MEDIA_SUBTYPE__gsm SPA_TYPE_MEDIA_SUBTYPE_BASE "gsm"
#define SPA_TYPE_MEDIA_SUBTYPE__midi SPA_TYPE_MEDIA_SUBTYPE_BASE "midi"
struct spa_format_body {
struct spa_pod_object_body obj_body;
struct spa_pod_id media_type SPA_ALIGNED(8);
struct spa_pod_id media_subtype SPA_ALIGNED(8);
/* contents follow, series of spa_pod_prop */
};
/**
* spa_format:
* @media_type: media type
* @media_subtype: subtype
* @pod: POD object with properties
*/
struct spa_format {
struct spa_pod pod;
struct spa_format_body body;
};
#ifdef __cplusplus
} /* extern "C" */
#endif

View file

@ -8,7 +8,6 @@ spa_headers = [
'event.h',
'event-node.h',
'format.h',
'format-builder.h',
'format-utils.h',
'hook.h',
'list.h',

View file

@ -32,6 +32,7 @@ struct spa_node;
#include <spa/defs.h>
#include <spa/plugin.h>
#include <spa/props.h>
#include <spa/pod-builder.h>
#include <spa/param.h>
#include <spa/event-node.h>
#include <spa/command-node.h>
@ -134,6 +135,10 @@ struct spa_node_callbacks {
};
#define SPA_NODE_PARAM_FLAG_TEST_ONLY (1 << 0) /* just check if the param is accepted */
#define SPA_NODE_PARAM_FLAG_FIXATE (1 << 1) /* fixate the non-optional unset fields */
#define SPA_NODE_PARAM_FLAG_NEAREST (1 << 2) /* allow set fields to be rounded to the
* nearest allowed field value. */
/**
* struct spa_node:
*
@ -154,49 +159,61 @@ struct spa_node {
*/
const struct spa_dict *info;
/**
* spa_node::get_props:
* @node: a #spa_node
* @props: a location for a #struct spa_props pointer
* Enumerate the parameters of a node.
*
* Get the configurable properties of @node.
* Parameters are identified with an \a id. Some parameters can have
* multiple values, see the documentation of the parameter id.
*
* The returned @props is a snapshot of the current configuration and
* can be modified. The modifications will take effect after a call
* to spa_node::set_props.
* Parameters can be filtered by passing a non-NULL \a filter.
*
* This function must be called from the main thread.
*
* Returns: #SPA_RESULT_OK on success
* #SPA_RESULT_INVALID_ARGUMENTS when node or props are %NULL
* #SPA_RESULT_NOT_IMPLEMENTED when there are no properties
* implemented on @node
* \param node a \ref spa_node
* \param id the param id to enumerate
* \param index the index of enumeration, pass 0 for the first item and the
* index is updated to retrieve the next item.
* \param filter and optional filter to use
* \param param builder for the result object.
*
* \return #SPA_RESULT_OK on success
* #SPA_RESULT_INVALID_ARGUMENTS when node or builder are %NULL
* #SPA_RESULT_UNKNOWN_PARAM the parameter \a id is unknown
* #SPA_RESULT_ENUM_END when there are no more parameters to enumerate
* #SPA_RESULT_NOT_IMPLEMENTED when there are no parameters
* implemented on \a node
*/
int (*get_props) (struct spa_node *node, struct spa_props **props);
int (*enum_params) (struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder);
/**
* struct spa_node::set_props:
* @node: a #struct spa_node
* @props: a #struct spa_props
* Set the configurable parameter in \a node.
*
* Set the configurable properties in @node.
* Usually, \a param will be obtained from enum_params and then
* modified but it is also possible to set another spa_pod_object
* as long as its keys and types match a supported object.
*
* Usually, @props will be obtained from struct spa_node::get_props and then
* modified but it is also possible to set another #struct spa_props object
* as long as its keys and types match those of struct spa_props::get_props.
*
* Properties with keys that are not known are ignored.
*
* If @props is NULL, all the properties are reset to their defaults.
* Objects with property keys that are not known are ignored.
*
* This function must be called from the main thread.
*
* Returns: #SPA_RESULT_OK on success
* #SPA_RESULT_INVALID_ARGUMENTS when node is %NULL
* #SPA_RESULT_NOT_IMPLEMENTED when no properties can be
* modified on @node.
* #SPA_RESULT_WRONG_PROPERTY_TYPE when a property has the wrong
* \param node a \ref spa_node
* \param id the parameter id to configure
* \param flags additional flags
* \param param the parameter to configure
*
* \return #SPA_RESULT_OK on success
* #SPA_RESULT_INVALID_ARGUMENTS when node is %NULL
* #SPA_RESULT_NOT_IMPLEMENTED when there are no parameters
* implemented on \a node
* #SPA_RESULT_WRONG_PROPERTY_TYPE when a property has the wrong
* type.
* #SPA_RESULT_UNKNOWN_PARAM the parameter is unknown
*/
int (*set_props) (struct spa_node *node, const struct spa_props *props);
int (*set_param) (struct spa_node *node,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param);
/**
* struct spa_node::send_command:
* @node: a #struct spa_node
@ -292,117 +309,72 @@ struct spa_node {
int (*add_port) (struct spa_node *node, enum spa_direction direction, uint32_t port_id);
int (*remove_port) (struct spa_node *node, enum spa_direction direction, uint32_t port_id);
/**
* struct spa_node::port_enum_formats:
* @node: a #struct spa_node
* @direction: a #enum spa_direction
* @port_id: the port to query
* @format: pointer to a format
* @filter: a format filter
* @index: an index variable, 0 to get the first item
*
* Enumerate all possible formats on @port_id of @node that are compatible
* with @filter. When @port_id is #SPA_ID_INVALID, the enumeration will
* list all the formats possible on a port that would be added with
* add_port().
*
* Use @index to retrieve the formats one by one until the function
* returns #SPA_RESULT_ENUM_END.
*
* The result format can be queried and modified and ultimately be used
* to call struct spa_node::port_set_format.
*
* This function must be called from the main thread.
*
* Returns: #SPA_RESULT_OK on success
* #SPA_RESULT_INVALID_ARGUMENTS when node or format is %NULL
* #SPA_RESULT_INVALID_PORT when port_id is not valid
* #SPA_RESULT_ENUM_END when no format exists
*/
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,
uint32_t index);
/**
* struct spa_node::port_set_format:
* @node: a #struct spa_node
* @direction: a #enum spa_direction
* @port_id: the port to configure
* @flags: flags
* @format: a #struct spa_format with the format
*
* Set a format on @port_id of @node.
*
* When @format is %NULL, the current format will be removed.
*
* This function takes a copy of the format.
*
* Upon completion, this function might change the state of a node to
* the READY state or to CONFIGURE when @format is NULL.
*
* This function must be called from the main thread.
*
* Returns: #SPA_RESULT_OK on success
* #SPA_RESULT_OK_RECHECK on success, the value of @format might have been
* changed depending on @flags and the final value can be found by
* doing struct spa_node::get_format.
* #SPA_RESULT_INVALID_ARGUMENTS when node is %NULL
* #SPA_RESULT_INVALID_PORT when port_id is not valid
* #SPA_RESULT_INVALID_MEDIA_TYPE when the media type is not valid
* #SPA_RESULT_INVALID_FORMAT_PROPERTIES when one of the mandatory format
* properties is not specified and #SPA_PORT_FORMAT_FLAG_FIXATE was
* not set in @flags.
* #SPA_RESULT_WRONG_PROPERTY_TYPE when the type or size of a property
* is not correct.
* #SPA_RESULT_ASYNC the function is executed asynchronously
*/
#define SPA_PORT_FORMAT_FLAG_TEST_ONLY (1 << 0) /* just check if the format is accepted */
#define SPA_PORT_FORMAT_FLAG_FIXATE (1 << 1) /* fixate the non-optional unset fields */
#define SPA_PORT_FORMAT_FLAG_NEAREST (1 << 2) /* allow set fields to be rounded to the
* nearest allowed field value. */
int (*port_set_format) (struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags,
const struct spa_format *format);
/**
* struct spa_node::port_get_format:
* @node: a #struct spa_node
* @direction: a #enum spa_direction
* @port_id: the port to query
* @format: a pointer to a location to hold the #struct spa_format
*
* Get the format on @port_id of @node. The result #struct spa_format can
* not be modified.
*
* This function must be called from the main thread.
*
* Returns: #SPA_RESULT_OK on success
* #SPA_RESULT_INVALID_ARGUMENTS when @node or @format is %NULL
* #SPA_RESULT_INVALID_PORT when @port_id is not valid
* #SPA_RESULT_INVALID_NO_FORMAT when no format was set
*/
int (*port_get_format) (struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_format **format);
int (*port_get_info) (struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_port_info **info);
/**
* Enumerate all possible parameters of \a id on \a port_id of \a node
* that are compatible with \a filter.
*
* Use \a index to retrieve the parameters one by one until the function
* returns #SPA_RESULT_ENUM_END.
*
* The result parameters can be queried and modified and ultimately be used
* to call struct spa_node::port_set_param.
*
* This function must be called from the main thread.
*
* \param node a #struct spa_node
* \param direction a #enum spa_direction
* \param port_id the port to query
* \param id the parameter id to query
* \param index an index state variable, 0 to get the first item
* \param filter a parameter filter or NULL for no filter
* \param builder a builder for the result parameter object
* \return #SPA_RESULT_OK on success
* #SPA_RESULT_INVALID_ARGUMENTS when node or index or builder is %NULL
* #SPA_RESULT_INVALID_PORT when port_id is not valid
* #SPA_RESULT_ENUM_END when no more parameters exists
* #SPA_RESULT_UNKNOWN_PARAM when \a id is unknown
*/
int (*port_enum_params) (struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t index,
struct spa_param **param);
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder);
/**
* Set a parameter on \a port_id of \a node.
*
* When \a param is %NULL, the parameter will be unset.
*
* This function must be called from the main thread.
*
* \param node a #struct spa_node
* \param direction a #enum spa_direction
* \param port_id the port to configure
* \param flags optional flags
* \param param a #struct spa_pod_object with the parameter to set
* \return #SPA_RESULT_OK on success
* #SPA_RESULT_OK_RECHECK on success, the value of \a param might have been
* changed depending on \a flags and the final value can be found by
* doing struct spa_node::enum_params.
* #SPA_RESULT_INVALID_ARGUMENTS when node is %NULL
* #SPA_RESULT_INVALID_PORT when port_id is not valid
* #SPA_RESULT_INVALID_PARAM_INCOMPLETE when one of the mandatory param
* properties is not specified and #SPA_NODE_PARAM_FLAG_FIXATE was
* not set in \a flags.
* #SPA_RESULT_WRONG_PROPERTY_TYPE when the type or size of a property
* is not correct.
* #SPA_RESULT_ASYNC the function is executed asynchronously
*/
int (*port_set_param) (struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_param *param);
uint32_t id, uint32_t flags,
const struct spa_pod_object *param);
/**
* struct spa_node::port_use_buffers:
@ -477,7 +449,7 @@ struct spa_node {
int (*port_alloc_buffers) (struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers);
@ -595,17 +567,14 @@ struct spa_node {
int (*process_output) (struct spa_node *node);
};
#define spa_node_get_props(n,...) (n)->get_props((n),__VA_ARGS__)
#define spa_node_set_props(n,...) (n)->set_props((n),__VA_ARGS__)
#define spa_node_enum_params(n,...) (n)->enum_params((n),__VA_ARGS__)
#define spa_node_set_param(n,...) (n)->set_param((n),__VA_ARGS__)
#define spa_node_send_command(n,...) (n)->send_command((n),__VA_ARGS__)
#define spa_node_set_callbacks(n,...) (n)->set_callbacks((n),__VA_ARGS__)
#define spa_node_get_n_ports(n,...) (n)->get_n_ports((n),__VA_ARGS__)
#define spa_node_get_port_ids(n,...) (n)->get_port_ids((n),__VA_ARGS__)
#define spa_node_add_port(n,...) (n)->add_port((n),__VA_ARGS__)
#define spa_node_remove_port(n,...) (n)->remove_port((n),__VA_ARGS__)
#define spa_node_port_enum_formats(n,...) (n)->port_enum_formats((n),__VA_ARGS__)
#define spa_node_port_set_format(n,...) (n)->port_set_format((n),__VA_ARGS__)
#define spa_node_port_get_format(n,...) (n)->port_get_format((n),__VA_ARGS__)
#define spa_node_port_get_info(n,...) (n)->port_get_info((n),__VA_ARGS__)
#define spa_node_port_enum_params(n,...) (n)->port_enum_params((n),__VA_ARGS__)
#define spa_node_port_set_param(n,...) (n)->port_set_param((n),__VA_ARGS__)

View file

@ -66,6 +66,7 @@ spa_type_param_alloc_buffers_map(struct spa_type_map *map,
#define SPA_TYPE_PARAM_ALLOC_META_ENABLE__size SPA_TYPE_PARAM_ALLOC_META_ENABLE_BASE "size"
#define SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferSize SPA_TYPE_PARAM_ALLOC_META_ENABLE_BASE "ringbufferSize"
#define SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferMinAvail SPA_TYPE_PARAM_ALLOC_META_ENABLE_BASE "ringbufferMinAvail"
#define SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferStride SPA_TYPE_PARAM_ALLOC_META_ENABLE_BASE "ringbufferStride"
#define SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferBlocks SPA_TYPE_PARAM_ALLOC_META_ENABLE_BASE "ringbufferBlocks"
#define SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferAlign SPA_TYPE_PARAM_ALLOC_META_ENABLE_BASE "ringbufferAlign"
@ -75,6 +76,7 @@ struct spa_type_param_alloc_meta_enable {
uint32_t type;
uint32_t size;
uint32_t ringbufferSize;
uint32_t ringbufferMinAvail;
uint32_t ringbufferStride;
uint32_t ringbufferBlocks;
uint32_t ringbufferAlign;
@ -85,13 +87,21 @@ spa_type_param_alloc_meta_enable_map(struct spa_type_map *map,
struct spa_type_param_alloc_meta_enable *type)
{
if (type->MetaEnable == 0) {
type->MetaEnable = spa_type_map_get_id(map, SPA_TYPE_PARAM_ALLOC__MetaEnable);
type->type = spa_type_map_get_id(map, SPA_TYPE_PARAM_ALLOC_META_ENABLE__type);
type->size = spa_type_map_get_id(map, SPA_TYPE_PARAM_ALLOC_META_ENABLE__size);
type->ringbufferSize = spa_type_map_get_id(map, SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferSize);
type->ringbufferStride = spa_type_map_get_id(map, SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferStride);
type->ringbufferBlocks = spa_type_map_get_id(map, SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferBlocks);
type->ringbufferAlign = spa_type_map_get_id(map, SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferAlign);
int i;
#define OFF(n) offsetof(struct spa_type_param_alloc_meta_enable, n)
static struct { off_t offset; const char *type; } tab[] = {
{ OFF(MetaEnable), SPA_TYPE_PARAM_ALLOC__MetaEnable },
{ OFF(type), SPA_TYPE_PARAM_ALLOC_META_ENABLE__type },
{ OFF(size), SPA_TYPE_PARAM_ALLOC_META_ENABLE__size },
{ OFF(ringbufferSize), SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferSize },
{ OFF(ringbufferMinAvail), SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferMinAvail },
{ OFF(ringbufferStride), SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferStride },
{ OFF(ringbufferBlocks), SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferBlocks },
{ OFF(ringbufferAlign), SPA_TYPE_PARAM_ALLOC_META_ENABLE__ringbufferAlign },
};
#undef OFF
for (i = 0; i < SPA_N_ELEMENTS(tab); i++)
*SPA_MEMBER(type, tab[i].offset, uint32_t) = spa_type_map_get_id(map, tab[i].type);
}
}

View file

@ -26,52 +26,64 @@ extern "C" {
#include <spa/defs.h>
#include <spa/pod-utils.h>
#include <spa/type-map.h>
struct spa_param;
#define SPA_TYPE__Param SPA_TYPE_POD_OBJECT_BASE "Param"
#define SPA_TYPE_PARAM_BASE SPA_TYPE__Param ":"
/* base for parameter objects */
#define SPA_TYPE__Param SPA_TYPE_POD_OBJECT_BASE "Param"
#define SPA_TYPE_PARAM_BASE SPA_TYPE__Param ":"
struct spa_param {
struct spa_pod_object object;
/* base for parameter object enumerations */
#define SPA_TYPE__ParamId SPA_TYPE_ENUM_BASE "ParamId"
#define SPA_TYPE_PARAM_ID_BASE SPA_TYPE__ParamId ":"
/** List of supported parameters */
#define SPA_TYPE_PARAM_ID__List SPA_TYPE_PARAM_ID_BASE "List"
/* object with supported parameter id */
#define SPA_TYPE_PARAM__List SPA_TYPE_PARAM_BASE "List"
#define SPA_TYPE_PARAM_LIST_BASE SPA_TYPE_PARAM__List ":"
#define SPA_TYPE_PARAM_LIST__id SPA_TYPE_PARAM_LIST_BASE "id"
/** Property parameter id, deals with SPA_TYPE__Props */
#define SPA_TYPE_PARAM_ID__Props SPA_TYPE_PARAM_ID_BASE "Props"
/** The available formats */
#define SPA_TYPE_PARAM_ID__EnumFormat SPA_TYPE_PARAM_ID_BASE "EnumFormat"
/** The current format */
#define SPA_TYPE_PARAM_ID__Format SPA_TYPE_PARAM_ID_BASE "Format"
/** The supported buffer sizes */
#define SPA_TYPE_PARAM_ID__Buffers SPA_TYPE_PARAM_ID_BASE "Buffers"
/** The supported metadata */
#define SPA_TYPE_PARAM_ID__Meta SPA_TYPE_PARAM_ID_BASE "Meta"
struct spa_type_param {
uint32_t idList; /**< id of the list param */
uint32_t List; /**< list object type */
uint32_t listId; /**< id in the list object */
uint32_t idProps; /**< id to enumerate properties */
uint32_t idEnumFormat; /**< id to enumerate formats */
uint32_t idFormat; /**< id to get/set format parameter */
uint32_t idBuffers; /**< id to enumerate buffer requirements */
uint32_t idMeta; /**< id to enumerate supported metadata */
};
static inline uint32_t
spa_pod_builder_push_param(struct spa_pod_builder *builder,
struct spa_pod_frame *frame,
uint32_t param_type)
static inline void
spa_type_param_map(struct spa_type_map *map,
struct spa_type_param *type)
{
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); \
(iter) = SPA_MEMBER((iter), SPA_ROUND_UP_N(SPA_POD_SIZE(iter), 8), struct spa_pod_prop))
#define SPA_PARAM_FOREACH(param, iter) \
SPA_PARAM_BODY_FOREACH(&param->object.body, SPA_POD_BODY_SIZE(param), iter)
static inline int spa_param_fixate(struct spa_param *param)
{
struct spa_pod_prop *prop;
SPA_PARAM_FOREACH(param, prop)
prop->body.flags &= ~SPA_POD_PROP_FLAG_UNSET;
return SPA_RESULT_OK;
if (type->idList == 0) {
type->idList = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__List);
type->List = spa_type_map_get_id(map, SPA_TYPE_PARAM__List);
type->listId = spa_type_map_get_id(map, SPA_TYPE_PARAM_LIST__id);
type->idProps = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__Props);
type->idEnumFormat = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__EnumFormat);
type->idFormat = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__Format);
type->idBuffers = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__Buffers);
type->idMeta = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID__Meta);
}
}
#ifdef __cplusplus

View file

@ -98,6 +98,8 @@ static inline struct spa_pod_prop *spa_pod_struct_find_prop(const struct spa_pod
return spa_pod_contents_find_prop(&obj->pod, sizeof(struct spa_pod_struct), key);
}
#include <spa/pod-parser.h>
#define spa_pod_object_parse(object,...) \
({ \
struct spa_pod_parser __p; \
@ -106,6 +108,16 @@ static inline struct spa_pod_prop *spa_pod_struct_find_prop(const struct spa_pod
spa_pod_parser_get(&__p, "<", ##__VA_ARGS__, NULL); \
})
static inline int spa_pod_object_fixate(struct spa_pod_object *obj)
{
struct spa_pod *res;
SPA_POD_OBJECT_FOREACH(obj, res) {
if (res->type == SPA_POD_TYPE_PROP)
((struct spa_pod_prop *) res)->body.flags &= ~SPA_POD_PROP_FLAG_UNSET;
}
return SPA_RESULT_OK;
}
#ifdef __cplusplus
} /* extern "C" */
#endif

View file

@ -25,16 +25,12 @@ extern "C" {
#endif
#include <spa/pod.h>
#include <spa/pod-builder.h>
#include <spa/pod-parser.h>
#include <spa/param.h>
struct spa_props {
struct spa_pod_object object;
};
#define SPA_TYPE__Props SPA_TYPE_POD_OBJECT_BASE "Props"
#define SPA_TYPE_PROPS_BASE SPA_TYPE__Props ":"
#define SPA_TYPE__Props SPA_TYPE_POD_OBJECT_BASE "Props"
#define SPA_TYPE_PROPS_BASE SPA_TYPE__Props ":"
/** Common property ids */
#define SPA_TYPE_PROPS__device SPA_TYPE_PROPS_BASE "device"
#define SPA_TYPE_PROPS__deviceName SPA_TYPE_PROPS_BASE "deviceName"
#define SPA_TYPE_PROPS__deviceFd SPA_TYPE_PROPS_BASE "deviceFd"
@ -52,25 +48,6 @@ struct spa_props {
#define SPA_TYPE_PROPS__mute SPA_TYPE_PROPS_BASE "mute"
#define SPA_TYPE_PROPS__patternType SPA_TYPE_PROPS_BASE "patternType"
static inline uint32_t
spa_pod_builder_push_props(struct spa_pod_builder *builder,
struct spa_pod_frame *frame,
uint32_t props_type)
{
return spa_pod_builder_push_object(builder, frame, 0, props_type);
}
#define spa_pod_builder_props(b,props_type,...) \
spa_pod_builder_object(b, 0, props_type,##__VA_ARGS__)
#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" */
#endif

View file

@ -75,7 +75,7 @@ spa_type_format_video_map(struct spa_type_map *map, struct spa_type_format_video
}
static inline int
spa_format_video_raw_parse(const struct spa_format *format,
spa_format_video_raw_parse(const struct spa_pod_object *format,
struct spa_video_info_raw *info, struct spa_type_format_video *type)
{
struct spa_pod_parser prs;
@ -98,7 +98,7 @@ spa_format_video_raw_parse(const struct spa_format *format,
}
static inline int
spa_format_video_h264_parse(const struct spa_format *format,
spa_format_video_h264_parse(const struct spa_pod_object *format,
struct spa_video_info_h264 *info, struct spa_type_format_video *type)
{
struct spa_pod_parser prs;
@ -112,7 +112,7 @@ spa_format_video_h264_parse(const struct spa_format *format,
}
static inline int
spa_format_video_mjpg_parse(const struct spa_format *format,
spa_format_video_mjpg_parse(const struct spa_pod_object *format,
struct spa_video_info_mjpg *info, struct spa_type_format_video *type)
{
struct spa_pod_parser prs;

View file

@ -138,18 +138,6 @@ int spa_debug_dump_mem(const void *mem, size_t size)
return SPA_RESULT_OK;
}
int spa_debug_props(const struct spa_props *props)
{
spa_debug_pod(&props->object.pod);
return SPA_RESULT_OK;
}
int spa_debug_param(const struct spa_param *param)
{
spa_debug_pod(&param->object.pod);
return SPA_RESULT_OK;
}
static const char *pod_type_names[] = {
[SPA_POD_TYPE_INVALID] = "invalid",
[SPA_POD_TYPE_NONE] = "none",
@ -248,7 +236,8 @@ print_pod_value(uint32_t size, uint32_t type, void *body, int prefix)
struct spa_pod_object_body *b = body;
struct spa_pod *p;
printf("%-*sObject: size %d, id %d, type %s\n", prefix, "", size, b->id,
printf("%-*sObject: size %d, id %s, type %s\n", prefix, "", size,
map ? spa_type_map_get_type(map, b->id) : "*no map*",
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);
@ -292,12 +281,6 @@ print_pod_value(uint32_t size, uint32_t type, void *body, int prefix)
}
}
int spa_debug_pod(const struct spa_pod *pod)
{
print_pod_value(pod->size, pod->type, SPA_POD_BODY(pod), 0);
return SPA_RESULT_OK;
}
static void
print_format_value(uint32_t size, uint32_t type, void *body)
{
@ -356,19 +339,20 @@ print_format_value(uint32_t size, uint32_t type, void *body)
}
}
int spa_debug_format(const struct spa_format *format)
static int spa_debug_format(const struct spa_pod_object *format)
{
int i;
const char *media_type;
const char *media_subtype;
struct spa_pod_prop *prop;
struct spa_pod *pod;
uint32_t mtype, mstype;
if (format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
mtype = format->body.media_type.value;
mstype = format->body.media_subtype.value;
if (spa_pod_object_parse(format, "I", &mtype,
"I", &mstype) < 0)
return SPA_RESULT_INVALID_ARGUMENTS;
media_type = spa_type_map_get_type(map, mtype);
media_subtype = spa_type_map_get_type(map, mstype);
@ -376,9 +360,15 @@ int spa_debug_format(const struct spa_format *format)
fprintf(stderr, "%-6s %s/%s\n", "", rindex(media_type, ':') + 1,
rindex(media_subtype, ':') + 1);
SPA_FORMAT_FOREACH(format, prop) {
SPA_POD_OBJECT_FOREACH(format, pod) {
struct spa_pod_prop *prop;
const char *key;
if (pod->type != SPA_POD_TYPE_PROP)
continue;
prop = (struct spa_pod_prop *)pod;
if ((prop->body.flags & SPA_POD_PROP_FLAG_UNSET) &&
(prop->body.flags & SPA_POD_PROP_FLAG_OPTIONAL))
continue;
@ -428,6 +418,19 @@ int spa_debug_format(const struct spa_format *format)
return SPA_RESULT_OK;
}
int spa_debug_pod(const struct spa_pod *pod, uint32_t flags)
{
int res = SPA_RESULT_OK;
if (flags & SPA_DEBUG_FLAG_FORMAT)
res = spa_debug_format((struct spa_pod_object*)pod);
else
print_pod_value(pod->size, pod->type, SPA_POD_BODY(pod), 0);
return res;
}
int spa_debug_dict(const struct spa_dict *dict)
{
unsigned int i;

View file

@ -37,10 +37,8 @@ void spa_debug_set_type_map(const struct spa_type_map *map);
int spa_debug_port_info(const struct spa_port_info *info);
int spa_debug_buffer(const struct spa_buffer *buffer);
int spa_debug_props(const struct spa_props *props);
int spa_debug_param(const struct spa_param *param);
int spa_debug_pod(const struct spa_pod *pod);
int spa_debug_format(const struct spa_format *format);
#define SPA_DEBUG_FLAG_FORMAT (1 << 0)
int spa_debug_pod(const struct spa_pod *pod, uint32_t flags);
int spa_debug_dump_mem(const void *data, size_t size);
int spa_debug_dict(const struct spa_dict *dict);

View file

@ -22,57 +22,44 @@
#include <stdio.h>
#include <string.h>
#include <spa/format-builder.h>
#include <spa/video/format-utils.h>
#include <lib/props.h>
int
spa_format_filter(const struct spa_format *format,
const struct spa_format *filter,
struct spa_pod_builder *result)
spa_pod_object_filter(const struct spa_pod_object *obj,
struct spa_pod_object *filter,
struct spa_pod_builder *result)
{
struct spa_pod_frame f;
int res;
if (format == NULL || result == NULL)
if (obj == NULL || result == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
if (filter == NULL) {
spa_pod_builder_raw_padded(result, format, SPA_POD_SIZE(format));
spa_pod_builder_raw_padded(result, obj, SPA_POD_SIZE(obj));
return SPA_RESULT_OK;
}
if (SPA_FORMAT_MEDIA_TYPE(filter) != SPA_FORMAT_MEDIA_TYPE(format) ||
SPA_FORMAT_MEDIA_SUBTYPE(filter) != SPA_FORMAT_MEDIA_SUBTYPE(format))
return SPA_RESULT_INVALID_MEDIA_TYPE;
spa_pod_builder_push_format(result, &f, filter->body.obj_body.type,
SPA_FORMAT_MEDIA_TYPE(filter),
SPA_FORMAT_MEDIA_SUBTYPE(filter));
spa_pod_builder_push_object(result, &f, obj->body.id, obj->body.type);
res = spa_props_filter(result,
SPA_POD_CONTENTS(struct spa_format, format),
SPA_POD_CONTENTS_SIZE(struct spa_format, format),
SPA_POD_CONTENTS(struct spa_format, filter),
SPA_POD_CONTENTS_SIZE(struct spa_format, filter));
SPA_POD_CONTENTS(struct spa_pod_object, obj),
SPA_POD_CONTENTS_SIZE(struct spa_pod_object, obj),
SPA_POD_CONTENTS(struct spa_pod_object, filter),
SPA_POD_CONTENTS_SIZE(struct spa_pod_object, filter));
spa_pod_builder_pop(result, &f);
return res;
}
int
spa_format_compare(const struct spa_format *format1,
const struct spa_format *format2)
spa_pod_object_compare(const struct spa_pod_object *obj1,
const struct spa_pod_object *obj2)
{
if (format1 == NULL || format2 == NULL)
if (obj1 == NULL || obj2 == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
if (SPA_FORMAT_MEDIA_TYPE(format1) != SPA_FORMAT_MEDIA_TYPE(format2) ||
SPA_FORMAT_MEDIA_SUBTYPE(format1) != SPA_FORMAT_MEDIA_SUBTYPE(format2))
return SPA_RESULT_INVALID_MEDIA_TYPE;
return spa_props_compare(SPA_POD_CONTENTS(struct spa_format, format1),
SPA_POD_CONTENTS_SIZE(struct spa_format, format1),
SPA_POD_CONTENTS(struct spa_format, format2),
SPA_POD_CONTENTS_SIZE(struct spa_format, format2));
return spa_props_compare(SPA_POD_CONTENTS(struct spa_pod_object, obj1),
SPA_POD_CONTENTS_SIZE(struct spa_pod_object, obj1),
SPA_POD_CONTENTS(struct spa_pod_object, obj2),
SPA_POD_CONTENTS_SIZE(struct spa_pod_object, obj2));
}

View file

@ -26,12 +26,12 @@ extern "C" {
#include <spa/props.h>
int spa_format_filter(const struct spa_format *format,
const struct spa_format *filter,
struct spa_pod_builder *result);
int spa_pod_object_filter(const struct spa_pod_object *obj,
const struct spa_pod_object *filter,
struct spa_pod_builder *result);
int spa_format_compare(const struct spa_format *format1,
const struct spa_format *format2);
int spa_pod_object_compare(const struct spa_pod_object *obj1,
const struct spa_pod_object *obj2);
#ifdef __cplusplus
} /* extern "C" */

View file

@ -23,6 +23,7 @@
#include <string.h>
#include <spa/props.h>
#include <spa/pod-builder.h>
static int compare_value(enum spa_pod_type type, const void *r1, const void *r2)
{

View file

@ -25,6 +25,7 @@ extern "C" {
#endif
#include <spa/props.h>
#include <spa/pod-builder.h>
int spa_props_filter(struct spa_pod_builder *b,
const struct spa_pod *props,

View file

@ -42,20 +42,22 @@ static void reset_props(struct props *props)
props->max_latency = default_max_latency;
}
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_enum_params(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct state *this;
struct spa_pod_builder b = { NULL, };
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer));
*props = spa_pod_builder_props(&b,
this->type.props,
if (id == this->type.param.idProps) {
spa_pod_builder_object(builder,
id, 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),
@ -63,11 +65,15 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
2, 1, INT32_MAX,
":", this->type.prop_max_latency, "ir", this->props.max_latency,
2, 1, INT32_MAX);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
struct state *this;
@ -75,14 +81,18 @@ static int impl_node_set_props(struct spa_node *node, const struct spa_props *pr
this = SPA_CONTAINER_OF(node, struct state, node);
if (props == NULL) {
reset_props(&this->props);
return SPA_RESULT_OK;
} else {
spa_props_parse(props,
if (id == this->type.param.idProps) {
if (param == NULL) {
reset_props(&this->props);
return SPA_RESULT_OK;
}
spa_pod_object_parse(param,
":", this->type.prop_device, "?S", this->props.device, sizeof(this->props.device),
":", this->type.prop_min_latency, "?i", &this->props.min_latency, NULL);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
@ -213,23 +223,130 @@ static int impl_node_remove_port(struct spa_node *node, enum spa_direction direc
}
static int
impl_node_port_enum_formats(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_format **format,
const struct spa_format *filter,
uint32_t index)
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction, uint32_t port_id, const struct spa_port_info **info)
{
struct state *this;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
return spa_alsa_enum_format(this, format, filter, index);
*info = &this->info;
return SPA_RESULT_OK;
}
static int port_enum_formats(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct state *this = SPA_CONTAINER_OF(node, struct state, node);
return spa_alsa_enum_format(this, index, filter, builder);
}
static int port_get_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct state *this = SPA_CONTAINER_OF(node, struct state, node);
struct type *t = &this->type;
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if(*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_object(builder,
t->param.idFormat, t->format,
"I", t->media_type.audio,
"I", 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;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct state *this;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != 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);
if (id == t->param.idEnumFormat) {
return port_enum_formats(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idFormat) {
return port_get_format(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idBuffers) {
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_object(builder,
id, 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, MAX_BUFFERS,
":", t->param_alloc_buffers.align, "i", 16);
}
else if (id == t->param.idMeta) {
switch (*index) {
case 0:
spa_pod_builder_object(builder,
id, 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 1:
spa_pod_builder_object(builder,
id, 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, "iru",
this->props.max_latency * this->frame_size,
2, this->props.min_latency * this->frame_size,
this->period_frames * this->frame_size,
":", 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_ENUM_END;
}
}
else
return SPA_RESULT_UNKNOWN_PARAM;
(*index)++;
return SPA_RESULT_OK;
}
static int clear_buffers(struct state *this)
@ -241,22 +358,14 @@ static int clear_buffers(struct state *this)
return SPA_RESULT_OK;
}
static int
impl_node_port_set_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags,
const struct spa_format *format)
static int port_set_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t flags,
const struct spa_pod_object *format)
{
struct state *this;
struct state *this = SPA_CONTAINER_OF(node, struct state, node);
int err;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
if (format == NULL) {
spa_log_info(this->log, "clear format");
spa_alsa_pause(this, false);
@ -264,9 +373,11 @@ impl_node_port_set_format(struct spa_node *node,
spa_alsa_close(this);
this->have_format = false;
} else {
struct spa_audio_info info = { SPA_FORMAT_MEDIA_TYPE(format),
SPA_FORMAT_MEDIA_SUBTYPE(format),
};
struct spa_audio_info info = { 0 };
spa_pod_object_parse(format,
"I", &info.media_type,
"I", &info.media_subtype);
if (info.media_type != this->type.media_type.audio ||
info.media_subtype != this->type.media_subtype.raw)
@ -290,124 +401,27 @@ impl_node_port_set_format(struct spa_node *node,
return SPA_RESULT_OK;
}
static int
impl_node_port_get_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_format **format)
{
struct state *this;
struct spa_pod_builder b = { NULL, };
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);
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
*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;
}
static int
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction, uint32_t port_id, const struct spa_port_info **info)
{
struct state *this;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
*info = &this->info;
return SPA_RESULT_OK;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t index,
struct spa_param **param)
{
struct state *this;
struct spa_pod_builder b = { NULL };
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);
spa_pod_builder_init(&b, this->params_buffer, sizeof(this->params_buffer));
switch (index) {
case 0:
*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, MAX_BUFFERS,
":", t->param_alloc_buffers.align, "i", 16);
break;
case 1:
*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:
*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, "iru",
this->props.max_latency * this->frame_size,
2, this->props.min_latency * this->frame_size,
this->period_frames * this->frame_size,
":", 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_ENUM_END;
}
return SPA_RESULT_OK;
}
static int
impl_node_port_set_param(struct spa_node *node,
enum spa_direction direction, uint32_t port_id, const struct spa_param *param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
struct state *this;
struct type *t;
spa_return_val_if_fail(node != 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);
if (id == t->param.idFormat) {
return port_set_format(node, direction, port_id, flags, param);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
}
static int
@ -462,7 +476,7 @@ static int
impl_node_port_alloc_buffers(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@ -573,17 +587,14 @@ static const struct spa_dict node_info = {
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
&node_info,
impl_node_get_props,
impl_node_set_props,
impl_node_enum_params,
impl_node_set_param,
impl_node_send_command,
impl_node_set_callbacks,
impl_node_get_n_ports,
impl_node_get_port_ids,
impl_node_add_port,
impl_node_remove_port,
impl_node_port_enum_formats,
impl_node_port_set_format,
impl_node_port_get_format,
impl_node_port_get_info,
impl_node_port_enum_params,
impl_node_port_set_param,

View file

@ -41,20 +41,21 @@ static void reset_props(struct props *props)
props->min_latency = default_min_latency;
}
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_enum_params(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct state *this;
struct spa_pod_builder b = { NULL, };
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(props != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_pod_builder_init(&b, this->props_buffer, sizeof(this->props_buffer));
*props = spa_pod_builder_props(&b,
this->type.props,
spa_pod_builder_object(builder,
id, 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),
@ -64,7 +65,8 @@ static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
return SPA_RESULT_OK;
}
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
struct state *this;
@ -72,14 +74,9 @@ static int impl_node_set_props(struct spa_node *node, const struct spa_props *pr
this = SPA_CONTAINER_OF(node, struct state, node);
if (props == NULL) {
reset_props(&this->props);
return SPA_RESULT_OK;
} else {
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);
}
spa_pod_object_parse(param,
":", 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;
}
@ -227,21 +224,21 @@ static int impl_node_remove_port(struct spa_node *node, enum spa_direction direc
}
static int
impl_node_port_enum_formats(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_format **format, const struct spa_format *filter, uint32_t index)
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction, uint32_t port_id, const struct spa_port_info **info)
{
struct state *this;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
return spa_alsa_enum_format(this, format, filter, index);
*info = &this->info;
return SPA_RESULT_OK;
}
static void recycle_buffer(struct state *this, uint32_t buffer_id)
@ -257,6 +254,97 @@ static void recycle_buffer(struct state *this, uint32_t buffer_id)
spa_list_append(&this->free, &b->link);
}
static int port_enum_formats(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct state *this = SPA_CONTAINER_OF(node, struct state, node);
return spa_alsa_enum_format(this, index, filter, builder);
}
static int port_get_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct state *this = SPA_CONTAINER_OF(node, struct state, node);
struct type *t = &this->type;
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_object(builder,
t->param.idFormat, t->format,
"I", t->media_type.audio,
"I", 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;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct state *this;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != 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);
if (id == t->param.idEnumFormat) {
return port_enum_formats(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idFormat) {
return port_get_format(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idBuffers) {
spa_pod_builder_object(builder,
id, 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, "ir", 2,
2, 1, 32,
":", t->param_alloc_buffers.align, "i", 16);
}
else if (id == t->param.idMeta) {
switch (*index) {
case 0:
spa_pod_builder_object(builder,
id, 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_ENUM_END;
}
}
else
return SPA_RESULT_UNKNOWN_PARAM;
(*index)++;
return SPA_RESULT_OK;
}
static int clear_buffers(struct state *this)
{
if (this->n_buffers > 0) {
@ -267,29 +355,24 @@ static int clear_buffers(struct state *this)
return SPA_RESULT_OK;
}
static int
impl_node_port_set_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id, uint32_t flags, const struct spa_format *format)
static int port_set_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t flags, const struct spa_pod_object *format)
{
struct state *this;
struct state *this = SPA_CONTAINER_OF(node, struct state, node);
int err;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
if (format == NULL) {
spa_alsa_pause(this, false);
clear_buffers(this);
spa_alsa_close(this);
this->have_format = false;
} else {
struct spa_audio_info info = { SPA_FORMAT_MEDIA_TYPE(format),
SPA_FORMAT_MEDIA_SUBTYPE(format),
};
struct spa_audio_info info = { 0 };
spa_pod_object_parse(format,
"I", &info.media_type,
"I", &info.media_subtype);
if (info.media_type != this->type.media_type.audio ||
info.media_subtype != this->type.media_subtype.raw)
@ -313,102 +396,27 @@ impl_node_port_set_format(struct spa_node *node,
return SPA_RESULT_OK;
}
static int
impl_node_port_get_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id, const struct spa_format **format)
{
struct state *this;
struct spa_pod_builder b = { NULL, };
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);
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
*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;
}
static int
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction, uint32_t port_id, const struct spa_port_info **info)
{
struct state *this;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
*info = &this->info;
return SPA_RESULT_OK;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction, uint32_t port_id, uint32_t index, struct spa_param **param)
{
struct state *this;
struct spa_pod_builder b = { NULL, };
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);
spa_pod_builder_init(&b, this->params_buffer, sizeof(this->params_buffer));
switch (index) {
case 0:
*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, "ir", 2,
2, 1, 32,
":", t->param_alloc_buffers.align, "i", 16);
break;
case 1:
*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;
}
return SPA_RESULT_OK;
}
static int
impl_node_port_set_param(struct spa_node *node,
enum spa_direction direction, uint32_t port_id, const struct spa_param *param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
struct state *this;
struct type *t;
spa_return_val_if_fail(node != 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);
if (id == t->param.idFormat) {
return port_set_format(node, direction, port_id, flags, param);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
}
static int
@ -461,7 +469,7 @@ static int
impl_node_port_alloc_buffers(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@ -579,17 +587,14 @@ static const struct spa_dict node_info = {
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
&node_info,
impl_node_get_props,
impl_node_set_props,
impl_node_enum_params,
impl_node_set_param,
impl_node_send_command,
impl_node_set_callbacks,
impl_node_get_n_ports,
impl_node_get_port_ids,
impl_node_add_port,
impl_node_remove_port,
impl_node_port_enum_formats,
impl_node_port_set_format,
impl_node_port_get_format,
impl_node_port_get_info,
impl_node_port_enum_params,
impl_node_port_set_param,
@ -602,12 +607,15 @@ static const struct spa_node impl_node = {
impl_node_process_output,
};
static int impl_clock_get_props(struct spa_clock *clock, struct spa_props **props)
static int impl_clock_enum_params(struct spa_clock *clock, uint32_t id, uint32_t *index,
struct spa_pod_builder *builder)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int impl_clock_set_props(struct spa_clock *clock, const struct spa_props *props)
static int impl_clock_set_param(struct spa_clock *clock,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
@ -637,8 +645,8 @@ static const struct spa_clock impl_clock = {
SPA_VERSION_CLOCK,
NULL,
SPA_CLOCK_STATE_STOPPED,
impl_clock_get_props,
impl_clock_set_props,
impl_clock_enum_params,
impl_clock_set_param,
impl_clock_get_time,
};

View file

@ -117,7 +117,9 @@ static snd_pcm_format_t spa_alsa_format_to_alsa(struct type *map, uint32_t forma
}
int
spa_alsa_enum_format(struct state *state, struct spa_format **format, const struct spa_format *filter, uint32_t index)
spa_alsa_enum_format(struct state *state, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
snd_pcm_t *hndl;
snd_pcm_hw_params_t *params;
@ -128,11 +130,11 @@ spa_alsa_enum_format(struct state *state, struct spa_format **format, const stru
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
struct spa_pod_frame f[2];
struct spa_pod_prop *prop;
struct spa_format *fmt;
struct spa_pod_object *fmt;
int res;
bool opened;
if (index == 1)
if (*index > 0)
return SPA_RESULT_ENUM_END;
opened = state->opened;
@ -143,8 +145,11 @@ spa_alsa_enum_format(struct state *state, struct spa_format **format, const stru
snd_pcm_hw_params_alloca(&params);
CHECK(snd_pcm_hw_params_any(hndl, params), "Broken configuration: no configurations available");
spa_pod_builder_push_format(&b, &f[0], state->type.format,
state->type.media_type.audio, state->type.media_subtype.raw);
spa_pod_builder_push_object(&b, &f[0],
state->type.param.idEnumFormat, state->type.format);
spa_pod_builder_add(&b,
"I", state->type.media_type.audio,
"I", state->type.media_subtype.raw, 0);
snd_pcm_format_mask_alloca(&fmask);
snd_pcm_hw_params_get_format_mask(params, fmask);
@ -195,13 +200,13 @@ spa_alsa_enum_format(struct state *state, struct spa_format **format, const stru
spa_pod_builder_pop(&b, &f[1]);
spa_pod_builder_pop(&b, &f[0]);
fmt = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
fmt = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_pod_object);
spa_pod_builder_init(&b, state->format_buffer, sizeof(state->format_buffer));
if ((res = spa_format_filter(fmt, filter, &b)) < 0)
(*index)++;
if ((res = spa_pod_object_filter(fmt, filter, builder)) < 0)
return res;
*format = SPA_POD_BUILDER_DEREF(&b, 0, struct spa_format);
if (!opened)
spa_alsa_close(state);
@ -251,7 +256,7 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
CHECK(snd_pcm_hw_params_set_channels_near(hndl, params, &rchannels), "set_channels");
if (rchannels != info->channels) {
spa_log_info(state->log, "Channels doesn't match (requested %u, get %u", info->channels, rchannels);
if (flags & SPA_PORT_FORMAT_FLAG_NEAREST)
if (flags & SPA_NODE_PARAM_FLAG_NEAREST)
info->channels = rchannels;
else
return -EINVAL;
@ -262,7 +267,7 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
CHECK(snd_pcm_hw_params_set_rate_near(hndl, params, &rrate, 0), "set_rate_near");
if (rrate != info->rate) {
spa_log_info(state->log, "Rate doesn't match (requested %iHz, get %iHz)", info->rate, rrate);
if (flags & SPA_PORT_FORMAT_FLAG_NEAREST)
if (flags & SPA_NODE_PARAM_FLAG_NEAREST)
info->rate = rrate;
else
return -EINVAL;

View file

@ -37,7 +37,6 @@ extern "C" {
#include <spa/loop.h>
#include <spa/ringbuffer.h>
#include <spa/audio/format-utils.h>
#include <spa/format-builder.h>
struct props {
char device[64];
@ -67,6 +66,7 @@ struct type {
uint32_t prop_card_name;
uint32_t prop_min_latency;
uint32_t prop_max_latency;
struct spa_type_param param;
struct spa_type_meta meta;
struct spa_type_data data;
struct spa_type_media_type media_type;
@ -92,6 +92,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
type->prop_min_latency = spa_type_map_get_id(map, SPA_TYPE_PROPS__minLatency);
type->prop_max_latency = spa_type_map_get_id(map, SPA_TYPE_PROPS__maxLatency);
spa_type_param_map(map, &type->param);
spa_type_meta_map(map, &type->meta);
spa_type_data_map(map, &type->data);
spa_type_media_type_map(map, &type->media_type);
@ -124,7 +125,6 @@ struct state {
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
uint8_t props_buffer[1024];
struct props props;
bool opened;
@ -169,7 +169,9 @@ struct state {
int
spa_alsa_enum_format(struct state *state,
struct spa_format **format, const struct spa_format *filter, uint32_t index);
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder);
int spa_alsa_set_format(struct state *state, struct spa_audio_info *info, uint32_t flags);

View file

@ -25,7 +25,6 @@
#include <spa/type-map.h>
#include <spa/node.h>
#include <spa/audio/format-utils.h>
#include <spa/format-builder.h>
#include <lib/format.h>
#include <lib/props.h>
#include <spa/param-alloc.h>
@ -69,6 +68,7 @@ struct port {
struct type {
uint32_t node;
uint32_t format;
struct spa_type_param param;
struct spa_type_media_type media_type;
struct spa_type_media_subtype media_subtype;
struct spa_type_format_audio format_audio;
@ -84,6 +84,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
{
type->node = spa_type_map_get_id(map, SPA_TYPE__Node);
type->format = spa_type_map_get_id(map, SPA_TYPE__Format);
spa_type_param_map(map, &type->param);
spa_type_media_type_map(map, &type->media_type);
spa_type_media_subtype_map(map, &type->media_subtype);
spa_type_format_audio_map(map, &type->format_audio);
@ -133,12 +134,16 @@ 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))
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_enum_params(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
@ -294,41 +299,50 @@ impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint3
return SPA_RESULT_OK;
}
static int
impl_node_port_enum_formats(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_format **format,
const struct spa_format *filter,
uint32_t index)
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_port_info **info)
{
struct impl *this;
int res;
struct spa_format *fmt;
uint8_t buffer[256];
struct spa_pod_builder b = { NULL, };
uint32_t count, match;
struct type *t;
struct port *port;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(info != 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);
count = match = filter ? 0 : index;
port = GET_PORT(this, direction, port_id);
*info = &port->info;
return SPA_RESULT_OK;
}
static int port_enum_formats(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct spa_pod_object *fmt;
uint8_t buffer[256];
struct spa_pod_builder b = { NULL, };
struct type *t = &this->type;
int res;
next:
spa_pod_builder_init(&b, buffer, sizeof(buffer));
switch (count++) {
switch (*index) {
case 0:
fmt = spa_pod_builder_format(&b,
t->format,
t->media_type.audio, t->media_subtype.raw,
fmt = spa_pod_builder_object(&b,
t->param.idEnumFormat, t->format,
"I", t->media_type.audio,
"I", t->media_subtype.raw,
":", t->format_audio.format, "Ieu", t->audio_format.S16,
2, t->audio_format.S16,
t->audio_format.F32,
@ -341,12 +355,109 @@ impl_node_port_enum_formats(struct spa_node *node,
return SPA_RESULT_ENUM_END;
}
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
(*index)++;
if ((res = spa_format_filter(fmt, filter, &b)) != SPA_RESULT_OK || match++ != index)
if ((res = spa_pod_object_filter(fmt, filter, builder)) != SPA_RESULT_OK)
goto next;
*format = SPA_POD_BUILDER_DEREF(&b, 0, struct spa_format);
return SPA_RESULT_OK;
}
static int port_get_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct port *port;
struct type *t = &this->type;
port = GET_PORT(this, direction, port_id);
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_object(builder,
t->param.idFormat, t->format,
"I", t->media_type.audio,
"I", 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;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != 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);
if (id == t->param.idEnumFormat) {
return port_enum_formats(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idFormat) {
return port_get_format(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idBuffers) {
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_object(builder,
id, 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, 2, MAX_BUFFERS,
":", t->param_alloc_buffers.align, "i", 16);
}
else if (id == t->param.idMeta) {
switch (*index) {
case 0:
spa_pod_builder_object(builder,
id, 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 1:
spa_pod_builder_object(builder,
id, 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, "iru", 1024 * this->bpf,
2, 16 * this->bpf, INT32_MAX / this->bpf,
":", 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_ENUM_END;
}
}
else
return SPA_RESULT_UNKNOWN_PARAM;
(*index)++;
return SPA_RESULT_OK;
}
@ -361,23 +472,15 @@ static int clear_buffers(struct impl *this, struct port *port)
return SPA_RESULT_OK;
}
static int
impl_node_port_set_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags,
const struct spa_format *format)
static int port_set_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags,
const struct spa_pod_object *format)
{
struct impl *this;
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
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);
struct type *t = &this->type;
port = GET_PORT(this, direction, port_id);
@ -389,9 +492,11 @@ impl_node_port_set_format(struct spa_node *node,
clear_buffers(this, port);
}
} else {
struct spa_audio_info info = { SPA_FORMAT_MEDIA_TYPE(format),
SPA_FORMAT_MEDIA_SUBTYPE(format),
};
struct spa_audio_info info = { 0 };
spa_pod_object_parse(format,
"I", &info.media_type,
"I", &info.media_subtype);
if (info.media_type != t->media_type.audio ||
info.media_subtype != t->media_subtype.raw)
@ -430,129 +535,28 @@ impl_node_port_set_format(struct spa_node *node,
return SPA_RESULT_OK;
}
static int
impl_node_port_get_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_format **format)
{
struct impl *this;
struct port *port;
struct spa_pod_builder b = { NULL, };
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);
port = GET_PORT(this, direction, port_id);
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
*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;
}
static int
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_port_info **info)
{
struct impl *this;
struct port *port;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
port = GET_PORT(this, direction, port_id);
*info = &port->info;
return SPA_RESULT_OK;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t index,
struct spa_param **param)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
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);
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
switch (index) {
case 0:
*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, 2, MAX_BUFFERS,
":", t->param_alloc_buffers.align, "i", 16);
break;
case 1:
*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:
*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, "iru", 1024 * this->bpf,
2, 16 * this->bpf, INT32_MAX / this->bpf,
":", 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_ENUM_END;
}
return SPA_RESULT_OK;
}
static int
impl_node_port_set_param(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_param *param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
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);
if (id == t->param.idFormat) {
return port_set_format(node, direction, port_id, flags, param);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
}
static int
@ -620,7 +624,7 @@ static int
impl_node_port_alloc_buffers(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@ -933,17 +937,14 @@ static int impl_node_process_output(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
NULL,
impl_node_get_props,
impl_node_set_props,
impl_node_enum_params,
impl_node_set_param,
impl_node_send_command,
impl_node_set_callbacks,
impl_node_get_n_ports,
impl_node_get_port_ids,
impl_node_add_port,
impl_node_remove_port,
impl_node_port_enum_formats,
impl_node_port_set_format,
impl_node_port_get_format,
impl_node_port_get_info,
impl_node_port_enum_params,
impl_node_port_set_param,

View file

@ -31,7 +31,6 @@
#include <spa/param-alloc.h>
#include <spa/list.h>
#include <spa/audio/format-utils.h>
#include <spa/format-builder.h>
#include <lib/format.h>
#include <lib/props.h>
@ -53,6 +52,7 @@ struct type {
uint32_t prop_volume;
uint32_t wave_sine;
uint32_t wave_square;
struct spa_type_param param;
struct spa_type_meta meta;
struct spa_type_data data;
struct spa_type_media_type media_type;
@ -77,6 +77,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
type->prop_volume = spa_type_map_get_id(map, SPA_TYPE_PROPS__volume);
type->wave_sine = spa_type_map_get_id(map, SPA_TYPE_PROPS__waveType ":sine");
type->wave_square = spa_type_map_get_id(map, SPA_TYPE_PROPS__waveType ":square");
spa_type_param_map(map, &type->param);
spa_type_meta_map(map, &type->meta);
spa_type_data_map(map, &type->data);
spa_type_media_type_map(map, &type->media_type);
@ -132,7 +133,6 @@ struct impl {
struct itimerspec timerspec;
struct spa_port_info info;
uint8_t params_buffer[1024];
struct spa_port_io *io;
bool have_format;
@ -169,33 +169,41 @@ static void reset_props(struct impl *this, struct props *props)
props->volume = DEFAULT_VOLUME;
}
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_enum_params(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
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);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != 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));
*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);
if (id == t->param.idProps) {
spa_pod_builder_object(builder,
id, 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);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
struct impl *this;
struct type *t;
@ -205,21 +213,25 @@ static int impl_node_set_props(struct spa_node *node, const struct spa_props *pr
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
if (props == NULL) {
reset_props(this, &this->props);
} else {
spa_props_parse(props,
if (id == t->param.idProps) {
if (param == NULL) {
reset_props(this, &this->props);
return SPA_RESULT_OK;
}
spa_pod_object_parse(param,
":",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)
this->info.flags |= SPA_PORT_INFO_FLAG_LIVE;
if (this->props.live)
this->info.flags |= SPA_PORT_INFO_FLAG_LIVE;
else
this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE;
}
else
this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE;
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
@ -458,39 +470,47 @@ impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint3
}
static int
impl_node_port_enum_formats(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_format **format,
const struct spa_format *filter,
uint32_t index)
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_port_info **info)
{
struct impl *this;
int res;
struct spa_format *fmt;
uint8_t buffer[256];
struct spa_pod_builder b = { NULL, };
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);
spa_return_val_if_fail(info != 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);
count = match = filter ? 0 : index;
*info = &this->info;
return SPA_RESULT_OK;
}
static int
port_enum_formats(struct impl *this,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct spa_pod_object *fmt;
struct type *t = &this->type;
uint8_t buffer[1024];
struct spa_pod_builder b = { 0 };
int res;
next:
spa_pod_builder_init(&b, buffer, sizeof(buffer));
switch (count++) {
switch (*index) {
case 0:
fmt = spa_pod_builder_format(&b, t->format,
t->media_type.audio,
t->media_subtype.raw,
fmt = spa_pod_builder_object(&b,
t->param.idEnumFormat, t->format,
"I", t->media_type.audio,
"I", t->media_subtype.raw,
":", t->format_audio.format, "Ieu", t->audio_format.S16,
4, t->audio_format.S16,
t->audio_format.S32,
@ -505,12 +525,107 @@ impl_node_port_enum_formats(struct spa_node *node,
return SPA_RESULT_ENUM_END;
}
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
(*index)++;
if ((res = spa_format_filter(fmt, filter, &b)) != SPA_RESULT_OK || match++ != index)
if ((res = spa_pod_object_filter(fmt, filter, builder)) != SPA_RESULT_OK)
goto next;
*format = SPA_POD_BUILDER_DEREF(&b, 0, struct spa_format);
return SPA_RESULT_OK;
}
static int
port_get_format(struct impl *this,
enum spa_direction direction,
uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct type *t = &this->type;
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_object(builder,
t->param.idFormat, t->format,
"I", t->media_type.audio,
"I", 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;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != 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);
if (id == t->param.idEnumFormat) {
return port_enum_formats(this, direction, port_id, index, filter, builder);
}
else if (id == t->param.idFormat) {
return port_get_format(this, direction, port_id, index, filter, builder);
}
else if (id == t->param.idBuffers) {
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_object(builder,
id, 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);
}
else if (id == t->param.idMeta) {
switch (*index) {
case 0:
spa_pod_builder_object(builder,
id, 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 1:
spa_pod_builder_object(builder,
id, 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, "ir", 5512 * this->bpf,
2, 16 * this->bpf, INT32_MAX / this->bpf,
":", 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_ENUM_END;
}
}
else
return SPA_RESULT_UNKNOWN_PARAM;
(*index)++;
return SPA_RESULT_OK;
}
@ -528,32 +643,26 @@ static int clear_buffers(struct impl *this)
}
static int
impl_node_port_set_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags,
const struct spa_format *format)
port_set_format(struct impl *this,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags,
const struct spa_pod_object *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);
struct type *t = &this->type;
if (format == NULL) {
this->have_format = false;
clear_buffers(this);
} else {
struct spa_audio_info info = { SPA_FORMAT_MEDIA_TYPE(format),
SPA_FORMAT_MEDIA_SUBTYPE(format),
};
struct spa_audio_info info = { 0 };
int idx;
int sizes[4] = { 2, 4, 4, 8 };
spa_pod_object_parse(format,
"I", &info.media_type,
"I", &info.media_subtype);
if (info.media_type != t->media_type.audio ||
info.media_subtype != t->media_subtype.raw)
return SPA_RESULT_INVALID_MEDIA_TYPE;
@ -581,128 +690,29 @@ impl_node_port_set_format(struct spa_node *node,
if (this->have_format) {
this->info.rate = this->current_format.info.raw.rate;
}
return SPA_RESULT_OK;
}
static int
impl_node_port_get_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_format **format)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
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);
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
*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;
}
static int
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_port_info **info)
{
struct impl *this;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
*info = &this->info;
return SPA_RESULT_OK;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t index,
struct spa_param **param)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
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);
spa_pod_builder_init(&b, this->params_buffer, sizeof(this->params_buffer));
switch (index) {
case 0:
*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:
*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:
*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, "ir", 5512 * this->bpf,
2, 16 * this->bpf, INT32_MAX / this->bpf,
":", 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_ENUM_END;
}
return SPA_RESULT_OK;
}
static int
impl_node_port_set_param(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_param *param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
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);
if (id == t->param.idFormat)
return port_set_format(this, direction, port_id, flags, param);
return SPA_RESULT_UNKNOWN_PARAM;
}
static int
@ -754,7 +764,7 @@ static int
impl_node_port_alloc_buffers(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@ -874,17 +884,14 @@ static const struct spa_dict node_info = {
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
&node_info,
impl_node_get_props,
impl_node_set_props,
impl_node_enum_params,
impl_node_set_param,
impl_node_send_command,
impl_node_set_callbacks,
impl_node_get_n_ports,
impl_node_get_port_ids,
impl_node_add_port,
impl_node_remove_port,
impl_node_port_enum_formats,
impl_node_port_set_format,
impl_node_port_get_format,
impl_node_port_get_info,
impl_node_port_enum_params,
impl_node_port_set_param,
@ -897,12 +904,14 @@ static const struct spa_node impl_node = {
impl_node_process_output,
};
static int impl_clock_get_props(struct spa_clock *clock, struct spa_props **props)
static int impl_clock_enum_params(struct spa_clock *clock, uint32_t id, uint32_t *index,
struct spa_pod_builder *builder)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int impl_clock_set_props(struct spa_clock *clock, const struct spa_props *props)
static int impl_clock_set_param(struct spa_clock *clock, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
@ -936,8 +945,8 @@ static const struct spa_clock impl_clock = {
SPA_VERSION_CLOCK,
NULL,
SPA_CLOCK_STATE_STOPPED,
impl_clock_get_props,
impl_clock_set_props,
impl_clock_enum_params,
impl_clock_set_param,
impl_clock_get_time,
};

View file

@ -48,6 +48,7 @@ struct port {
struct type {
uint32_t node;
struct spa_type_param param;
struct spa_type_media_type media_type;
struct spa_type_media_subtype media_subtype;
struct spa_type_format_video format_video;
@ -57,6 +58,7 @@ struct type {
static inline void init_type(struct type *type, struct spa_type_map *map)
{
type->node = spa_type_map_get_id(map, SPA_TYPE__Node);
spa_type_param_map(map, &type->param);
spa_type_media_type_map(map, &type->media_type);
spa_type_media_subtype_map(map, &type->media_subtype);
spa_type_format_video_map(map, &type->format_video);
@ -80,12 +82,17 @@ struct impl {
bool started;
};
static int spa_ffmpeg_dec_node_get_props(struct spa_node *node, struct spa_props **props)
static int spa_ffmpeg_dec_node_enum_params(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int spa_ffmpeg_dec_node_set_props(struct spa_node *node, const struct spa_props *props)
static int spa_ffmpeg_dec_node_set_param(struct spa_node *node,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
@ -182,17 +189,15 @@ spa_ffmpeg_dec_node_remove_port(struct spa_node *node,
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int
spa_ffmpeg_dec_node_port_enum_formats(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_format **format,
const struct spa_format *filter,
uint32_t index)
static int port_enum_formats(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
//struct impl *this;
if (node == NULL || format == NULL)
if (node == NULL || index == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
//this = SPA_CONTAINER_OF (node, struct impl, node);
@ -200,23 +205,20 @@ spa_ffmpeg_dec_node_port_enum_formats(struct spa_node *node,
if (!IS_VALID_PORT(this, direction, port_id))
return SPA_RESULT_INVALID_PORT;
switch (index) {
switch (*index) {
case 0:
break;
default:
return SPA_RESULT_ENUM_END;
}
*format = NULL;
return SPA_RESULT_OK;
}
static int
spa_ffmpeg_dec_node_port_set_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags,
const struct spa_format *format)
static int port_set_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t flags,
const struct spa_pod_object *format)
{
struct impl *this;
struct port *port;
@ -236,9 +238,11 @@ spa_ffmpeg_dec_node_port_set_format(struct spa_node *node,
port->have_format = false;
return SPA_RESULT_OK;
} else {
struct spa_video_info info = { SPA_FORMAT_MEDIA_TYPE(format),
SPA_FORMAT_MEDIA_SUBTYPE(format),
};
struct spa_video_info info = { 0 };
spa_pod_object_parse(format,
"I", &info.media_type,
"I", &info.media_subtype);
if (info.media_type != this->type.media_type.video &&
info.media_subtype != this->type.media_subtype.raw)
@ -247,7 +251,7 @@ spa_ffmpeg_dec_node_port_set_format(struct spa_node *node,
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)) {
if (!(flags & SPA_NODE_PARAM_FLAG_TEST_ONLY)) {
port->current_format = info;
port->have_format = true;
}
@ -255,30 +259,23 @@ spa_ffmpeg_dec_node_port_set_format(struct spa_node *node,
return SPA_RESULT_OK;
}
static int
spa_ffmpeg_dec_node_port_get_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_format **format)
static int port_get_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct port *port;
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
this = SPA_CONTAINER_OF(node, struct impl, node);
if (!IS_VALID_PORT(this, direction, port_id))
return SPA_RESULT_INVALID_PORT;
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
*format = NULL;
if (*index > 0)
return SPA_RESULT_ENUM_END;
return SPA_RESULT_OK;
}
@ -309,21 +306,38 @@ spa_ffmpeg_dec_node_port_get_info(struct spa_node *node,
static int
spa_ffmpeg_dec_node_port_enum_params(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t index,
struct spa_param **param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
return SPA_RESULT_NOT_IMPLEMENTED;
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct type *t = &this->type;
if (id == t->param.idEnumFormat) {
return port_enum_formats(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idFormat) {
return port_get_format(node, direction, port_id, index, filter, builder);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
}
static int
spa_ffmpeg_dec_node_port_set_param(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_param *param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct type *t = &this->type;
if (id == t->param.idFormat) {
return port_set_format(node, direction, port_id, flags, param);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
}
static int
@ -346,7 +360,7 @@ static int
spa_ffmpeg_dec_node_port_alloc_buffers(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@ -433,17 +447,14 @@ spa_ffmpeg_dec_node_port_send_command(struct spa_node *node,
static const struct spa_node ffmpeg_dec_node = {
SPA_VERSION_NODE,
NULL,
spa_ffmpeg_dec_node_get_props,
spa_ffmpeg_dec_node_set_props,
spa_ffmpeg_dec_node_enum_params,
spa_ffmpeg_dec_node_set_param,
spa_ffmpeg_dec_node_send_command,
spa_ffmpeg_dec_node_set_callbacks,
spa_ffmpeg_dec_node_get_n_ports,
spa_ffmpeg_dec_node_get_port_ids,
spa_ffmpeg_dec_node_add_port,
spa_ffmpeg_dec_node_remove_port,
spa_ffmpeg_dec_node_port_enum_formats,
spa_ffmpeg_dec_node_port_set_format,
spa_ffmpeg_dec_node_port_get_format,
spa_ffmpeg_dec_node_port_get_info,
spa_ffmpeg_dec_node_port_enum_params,
spa_ffmpeg_dec_node_port_set_param,

View file

@ -52,6 +52,7 @@ struct port {
struct type {
uint32_t node;
struct spa_type_param param;
struct spa_type_media_type media_type;
struct spa_type_media_subtype media_subtype;
struct spa_type_format_video format_video;
@ -61,6 +62,7 @@ struct type {
static inline void init_type(struct type *type, struct spa_type_map *map)
{
type->node = spa_type_map_get_id(map, SPA_TYPE__Node);
spa_type_param_map(map, &type->param);
spa_type_media_type_map(map, &type->media_type);
spa_type_media_subtype_map(map, &type->media_subtype);
spa_type_format_video_map(map, &type->format_video);
@ -84,12 +86,16 @@ struct impl {
bool started;
};
static int spa_ffmpeg_enc_node_get_props(struct spa_node *node, struct spa_props **props)
static int spa_ffmpeg_enc_node_enum_params(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int spa_ffmpeg_enc_node_set_props(struct spa_node *node, const struct spa_props *props)
static int spa_ffmpeg_enc_node_set_param(struct spa_node *node, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
@ -185,107 +191,6 @@ spa_ffmpeg_enc_node_remove_port(struct spa_node *node,
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int
spa_ffmpeg_enc_node_port_enum_formats(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_format **format,
const struct spa_format *filter, uint32_t index)
{
//struct impl *this;
//struct port *port;
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
//this = SPA_CONTAINER_OF (node, struct impl, node);
if (!IS_VALID_PORT(this, direction, port_id))
return SPA_RESULT_INVALID_PORT;
//port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
switch (index) {
case 0:
break;
default:
return SPA_RESULT_ENUM_END;
}
*format = NULL;
return SPA_RESULT_OK;
}
static int
spa_ffmpeg_enc_node_port_set_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags, const struct spa_format *format)
{
struct impl *this;
struct port *port;
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
this = SPA_CONTAINER_OF(node, struct impl, node);
if (!IS_VALID_PORT(this, direction, port_id))
return SPA_RESULT_INVALID_PORT;
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
if (format == NULL) {
port->have_format = false;
return SPA_RESULT_OK;
} else {
struct spa_video_info info = { SPA_FORMAT_MEDIA_TYPE(format),
SPA_FORMAT_MEDIA_SUBTYPE(format),
};
if (info.media_type != this->type.media_type.video &&
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) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
port->current_format = info;
port->have_format = true;
}
}
return SPA_RESULT_OK;
}
static int
spa_ffmpeg_enc_node_port_get_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id, const struct spa_format **format)
{
struct impl *this;
struct port *port;
if (node == NULL || format == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
this = SPA_CONTAINER_OF(node, struct impl, node);
if (!IS_VALID_PORT(this, direction, port_id))
return SPA_RESULT_INVALID_PORT;
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
*format = NULL;
return SPA_RESULT_OK;
}
static int
spa_ffmpeg_enc_node_port_get_info(struct spa_node *node,
enum spa_direction direction,
@ -309,20 +214,116 @@ spa_ffmpeg_enc_node_port_get_info(struct spa_node *node,
return SPA_RESULT_OK;
}
static int port_enum_formats(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
//struct impl *this = SPA_CONTAINER_OF (node, struct impl, node);
//struct port *port;
//port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
switch (*index) {
case 0:
break;
default:
return SPA_RESULT_ENUM_END;
}
return SPA_RESULT_OK;
}
static int port_get_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct port *port;
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
if (*index > 0)
return SPA_RESULT_ENUM_END;
return SPA_RESULT_OK;
}
static int
spa_ffmpeg_enc_node_port_enum_params(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id, uint32_t index, struct spa_param **param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
return SPA_RESULT_NOT_IMPLEMENTED;
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct type *t = &this->type;
if (id == t->param.idEnumFormat) {
return port_enum_formats(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idFormat) {
return port_get_format(node, direction, port_id, index, filter, builder);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
}
static int port_set_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t flags, const struct spa_pod_object *format)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct port *port;
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
if (format == NULL) {
port->have_format = false;
return SPA_RESULT_OK;
} else {
struct spa_video_info info = { 0 };
spa_pod_object_parse(format,
"I", &info.media_type,
"I", &info.media_subtype);
if (info.media_type != this->type.media_type.video &&
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) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!(flags & SPA_NODE_PARAM_FLAG_TEST_ONLY)) {
port->current_format = info;
port->have_format = true;
}
}
return SPA_RESULT_OK;
}
static int
spa_ffmpeg_enc_node_port_set_param(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id, const struct spa_param *param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct type *t = &this->type;
if (id == t->param.idFormat) {
return port_set_format(node, direction, port_id, flags, param);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
}
static int
@ -344,7 +345,7 @@ static int
spa_ffmpeg_enc_node_port_alloc_buffers(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@ -428,17 +429,14 @@ static int spa_ffmpeg_enc_node_process_output(struct spa_node *node)
static const struct spa_node ffmpeg_enc_node = {
SPA_VERSION_NODE,
NULL,
spa_ffmpeg_enc_node_get_props,
spa_ffmpeg_enc_node_set_props,
spa_ffmpeg_enc_node_enum_params,
spa_ffmpeg_enc_node_set_param,
spa_ffmpeg_enc_node_send_command,
spa_ffmpeg_enc_node_set_callbacks,
spa_ffmpeg_enc_node_get_n_ports,
spa_ffmpeg_enc_node_get_port_ids,
spa_ffmpeg_enc_node_add_port,
spa_ffmpeg_enc_node_remove_port,
spa_ffmpeg_enc_node_port_enum_formats,
spa_ffmpeg_enc_node_port_set_format,
spa_ffmpeg_enc_node_port_get_format,
spa_ffmpeg_enc_node_port_get_info,
spa_ffmpeg_enc_node_port_enum_params,
spa_ffmpeg_enc_node_port_set_param,

View file

@ -31,7 +31,6 @@
#include <spa/node.h>
#include <spa/param-alloc.h>
#include <spa/list.h>
#include <spa/format-builder.h>
#include <lib/props.h>
#define NAME "logger"

View file

@ -31,7 +31,6 @@
#include <spa/node.h>
#include <spa/param-alloc.h>
#include <spa/list.h>
#include <spa/format-builder.h>
#include <lib/props.h>
#define NAME "mapper"

View file

@ -30,7 +30,6 @@
#include <spa/node.h>
#include <spa/param-alloc.h>
#include <spa/list.h>
#include <spa/format-builder.h>
#include <lib/props.h>
#define NAME "fakesink"
@ -41,6 +40,7 @@ struct type {
uint32_t format;
uint32_t props;
uint32_t prop_live;
struct spa_type_param param;
struct spa_type_meta meta;
struct spa_type_data data;
struct spa_type_event_node event_node;
@ -56,6 +56,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
type->format = spa_type_map_get_id(map, SPA_TYPE__Format);
type->props = spa_type_map_get_id(map, SPA_TYPE__Props);
type->prop_live = spa_type_map_get_id(map, SPA_TYPE_PROPS__live);
spa_type_param_map(map, &type->param);
spa_type_meta_map(map, &type->meta);
spa_type_data_map(map, &type->data);
spa_type_event_node_map(map, &type->event_node);
@ -88,7 +89,6 @@ struct impl {
struct spa_log *log;
struct spa_loop *data_loop;
uint8_t props_buffer[512];
struct props props;
const struct spa_node_callbacks *callbacks;
@ -98,7 +98,6 @@ struct impl {
struct itimerspec timerspec;
struct spa_port_info info;
uint8_t params_buffer[1024];
struct spa_port_io *io;
bool have_format;
@ -125,43 +124,57 @@ static void reset_props(struct impl *this, struct props *props)
props->live = DEFAULT_LIVE;
}
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_enum_params(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
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);
spa_return_val_if_fail(builder != 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));
*props = spa_pod_builder_props(&b,
this->type.props,
":", this->type.prop_live, "b", this->props.live);
if (id == t->param.idProps) {
spa_pod_builder_object(builder,
id, t->props,
":", t->prop_live, "b", this->props.live);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
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_parse(props,
":", this->type.prop_live, "?b", &this->props.live, NULL);
if (id == t->param.idProps) {
if (param == NULL) {
reset_props(this, &this->props);
return SPA_RESULT_OK;
}
spa_pod_object_parse(param,
":", t->prop_live, "?b", &this->props.live, NULL);
if (this->props.live)
this->info.flags |= SPA_PORT_INFO_FLAG_LIVE;
else
this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE;
}
if (this->props.live)
this->info.flags |= SPA_PORT_INFO_FLAG_LIVE;
else
this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE;
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
@ -372,87 +385,6 @@ impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint3
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int
impl_node_port_enum_formats(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_format **format,
const struct spa_format *filter, uint32_t index)
{
struct impl *this;
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);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
return SPA_RESULT_ENUM_END;
}
static int clear_buffers(struct impl *this)
{
if (this->n_buffers > 0) {
spa_log_info(this->log, NAME " %p: clear buffers", this);
this->n_buffers = 0;
spa_list_init(&this->ready);
this->started = false;
set_timer(this, false);
}
return SPA_RESULT_OK;
}
static int
impl_node_port_set_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags,
const struct spa_format *format)
{
struct impl *this;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
if (format == NULL) {
this->have_format = false;
clear_buffers(this);
} else {
if (SPA_POD_SIZE(format) > sizeof(this->format_buffer))
return SPA_RESULT_ERROR;
memcpy(this->format_buffer, format, SPA_POD_SIZE(format));
this->have_format = true;
}
return SPA_RESULT_OK;
}
static int
impl_node_port_get_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_format **format)
{
struct impl *this;
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);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
*format = (const struct spa_format *) this->format_buffer;
return SPA_RESULT_OK;
}
static int
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction,
@ -473,59 +405,143 @@ impl_node_port_get_info(struct spa_node *node,
return SPA_RESULT_OK;
}
static int port_enum_formats(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
return SPA_RESULT_ENUM_END;
}
static int port_get_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_primitive(builder, SPA_MEMBER(this->format_buffer, 0, struct spa_pod));
return SPA_RESULT_OK;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t index,
struct spa_param **param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct spa_pod_builder b = { NULL };
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);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != 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);
spa_pod_builder_init(&b, this->params_buffer, sizeof(this->params_buffer));
if (id == t->param.idEnumFormat) {
return port_enum_formats(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idFormat) {
return port_get_format(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idBuffers) {
if (*index > 0)
return SPA_RESULT_ENUM_END;
switch (index) {
case 0:
*param = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
spa_pod_builder_object(builder,
id, 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:
*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;
}
else if (id == t->param.idMeta) {
switch (*index) {
case 0:
spa_pod_builder_object(builder,
id, 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_ENUM_END;
}
}
else
return SPA_RESULT_UNKNOWN_PARAM;
(*index)++;
return SPA_RESULT_OK;
}
static int clear_buffers(struct impl *this)
{
if (this->n_buffers > 0) {
spa_log_info(this->log, NAME " %p: clear buffers", this);
this->n_buffers = 0;
spa_list_init(&this->ready);
this->started = false;
set_timer(this, false);
}
return SPA_RESULT_OK;
}
static int port_set_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t flags,
const struct spa_pod_object *format)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
if (format == NULL) {
this->have_format = false;
clear_buffers(this);
} else {
if (SPA_POD_SIZE(format) > sizeof(this->format_buffer))
return SPA_RESULT_ERROR;
memcpy(this->format_buffer, format, SPA_POD_SIZE(format));
this->have_format = true;
}
return SPA_RESULT_OK;
}
static int
impl_node_port_set_param(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_param *param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
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);
if (id == t->param.idFormat) {
return port_set_format(node, direction, port_id, flags, param);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
}
static int
@ -574,7 +590,7 @@ static int
impl_node_port_alloc_buffers(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@ -669,17 +685,14 @@ static int impl_node_process_output(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
NULL,
impl_node_get_props,
impl_node_set_props,
impl_node_enum_params,
impl_node_set_param,
impl_node_send_command,
impl_node_set_callbacks,
impl_node_get_n_ports,
impl_node_get_port_ids,
impl_node_add_port,
impl_node_remove_port,
impl_node_port_enum_formats,
impl_node_port_set_format,
impl_node_port_get_format,
impl_node_port_get_info,
impl_node_port_enum_params,
impl_node_port_set_param,
@ -692,12 +705,14 @@ static const struct spa_node impl_node = {
impl_node_process_output,
};
static int impl_clock_get_props(struct spa_clock *clock, struct spa_props **props)
static int impl_clock_enum_params(struct spa_clock *clock, uint32_t id, uint32_t *index,
struct spa_pod_builder *builder)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int impl_clock_set_props(struct spa_clock *clock, const struct spa_props *props)
static int impl_clock_set_param(struct spa_clock *clock, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
@ -731,8 +746,8 @@ static const struct spa_clock impl_clock = {
SPA_VERSION_CLOCK,
NULL,
SPA_CLOCK_STATE_STOPPED,
impl_clock_get_props,
impl_clock_set_props,
impl_clock_enum_params,
impl_clock_set_param,
impl_clock_get_time,
};

View file

@ -30,7 +30,6 @@
#include <spa/node.h>
#include <spa/param-alloc.h>
#include <spa/list.h>
#include <spa/format-builder.h>
#include <lib/props.h>
#define NAME "fakesrc"
@ -42,6 +41,7 @@ struct type {
uint32_t props;
uint32_t prop_live;
uint32_t prop_pattern;
struct spa_type_param param;
struct spa_type_meta meta;
struct spa_type_data data;
struct spa_type_event_node event_node;
@ -58,6 +58,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
type->props = spa_type_map_get_id(map, SPA_TYPE__Props);
type->prop_live = spa_type_map_get_id(map, SPA_TYPE_PROPS__live);
type->prop_pattern = spa_type_map_get_id(map, SPA_TYPE_PROPS__patternType);
spa_type_param_map(map, &type->param);
spa_type_meta_map(map, &type->meta);
spa_type_data_map(map, &type->data);
spa_type_event_node_map(map, &type->event_node);
@ -91,7 +92,6 @@ struct impl {
struct spa_log *log;
struct spa_loop *data_loop;
uint8_t props_buffer[512];
struct props props;
const struct spa_node_callbacks *callbacks;
@ -101,7 +101,6 @@ struct impl {
struct itimerspec timerspec;
struct spa_port_info info;
uint8_t params_buffer[1024];
struct spa_port_io *io;
bool have_format;
@ -131,29 +130,36 @@ static void reset_props(struct impl *this, struct props *props)
props->pattern = DEFAULT_PATTERN;
}
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_enum_params(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
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);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != 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));
*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);
if (id == t->param.idProps) {
spa_pod_builder_object(builder,
id, t->props,
":", t->prop_live, "b", this->props.live,
":", t->prop_pattern, "Ie", this->props.pattern,
1, this->props.pattern);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
struct impl *this;
struct type *t;
@ -163,18 +169,22 @@ static int impl_node_set_props(struct spa_node *node, const struct spa_props *pr
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
if (props == NULL) {
reset_props(this, &this->props);
} else {
spa_props_parse(props,
":", t->prop_live, "?b", &this->props.live,
":", t->prop_pattern, "?I", &this->props.pattern, NULL);
}
if (id == t->param.idProps) {
if (param == NULL) {
reset_props(this, &this->props);
return SPA_RESULT_OK;
}
spa_pod_object_parse(param,
":", t->prop_live, "?b", &this->props.live,
":", t->prop_pattern, "?I", &this->props.pattern, NULL);
if (this->props.live)
this->info.flags |= SPA_PORT_INFO_FLAG_LIVE;
if (this->props.live)
this->info.flags |= SPA_PORT_INFO_FLAG_LIVE;
else
this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE;
}
else
this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE;
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
@ -386,92 +396,6 @@ impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint3
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int
impl_node_port_enum_formats(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_format **format,
const struct spa_format *filter,
uint32_t index)
{
struct impl *this;
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);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
return SPA_RESULT_ENUM_END;
}
static int clear_buffers(struct impl *this)
{
if (this->n_buffers > 0) {
spa_log_info(this->log, NAME " %p: clear buffers", this);
this->n_buffers = 0;
spa_list_init(&this->empty);
this->started = false;
set_timer(this, false);
}
return SPA_RESULT_OK;
}
static int
impl_node_port_set_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags,
const struct spa_format *format)
{
struct impl *this;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
if (format == NULL) {
this->have_format = false;
clear_buffers(this);
} else {
if (SPA_POD_SIZE(format) > sizeof(this->format_buffer))
return SPA_RESULT_ERROR;
memcpy(this->format_buffer, format, SPA_POD_SIZE(format));
this->have_format = true;
}
if (this->have_format) {
}
return SPA_RESULT_OK;
}
static int
impl_node_port_get_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_format **format)
{
struct impl *this;
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);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
*format = (const struct spa_format *) this->format_buffer;
return SPA_RESULT_OK;
}
static int
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction,
@ -492,59 +416,140 @@ impl_node_port_get_info(struct spa_node *node,
return SPA_RESULT_OK;
}
static int port_enum_formats(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
return SPA_RESULT_ENUM_END;
}
static int port_get_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_primitive(builder, SPA_MEMBER(this->format_buffer, 0, struct spa_pod));
return SPA_RESULT_OK;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t index,
struct spa_param **param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct spa_pod_builder b = { NULL };
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);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != 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);
spa_pod_builder_init(&b, this->params_buffer, sizeof(this->params_buffer));
switch (index) {
case 0:
*param = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
if (id == t->param.idEnumFormat) {
return port_enum_formats(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idFormat) {
return port_get_format(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idBuffers) {
spa_pod_builder_object(builder,
id, 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:
*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;
}
else if (id == t->param.idMeta) {
switch (*index) {
case 0:
spa_pod_builder_object(builder,
id, 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_ENUM_END;
}
}
else
return SPA_RESULT_UNKNOWN_PARAM;
(*index)++;
return SPA_RESULT_OK;
}
static int clear_buffers(struct impl *this)
{
if (this->n_buffers > 0) {
spa_log_info(this->log, NAME " %p: clear buffers", this);
this->n_buffers = 0;
spa_list_init(&this->empty);
this->started = false;
set_timer(this, false);
}
return SPA_RESULT_OK;
}
static int port_set_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t flags,
const struct spa_pod_object *format)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
if (format == NULL) {
this->have_format = false;
clear_buffers(this);
} else {
if (SPA_POD_SIZE(format) > sizeof(this->format_buffer))
return SPA_RESULT_ERROR;
memcpy(this->format_buffer, format, SPA_POD_SIZE(format));
this->have_format = true;
}
return SPA_RESULT_OK;
}
static int
impl_node_port_set_param(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_param *param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
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);
if (id == t->param.idFormat) {
return port_set_format(node, direction, port_id, flags, param);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
}
static int
@ -595,7 +600,7 @@ static int
impl_node_port_alloc_buffers(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@ -709,17 +714,14 @@ static int impl_node_process_output(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
NULL,
impl_node_get_props,
impl_node_set_props,
impl_node_enum_params,
impl_node_set_param,
impl_node_send_command,
impl_node_set_callbacks,
impl_node_get_n_ports,
impl_node_get_port_ids,
impl_node_add_port,
impl_node_remove_port,
impl_node_port_enum_formats,
impl_node_port_set_format,
impl_node_port_get_format,
impl_node_port_get_info,
impl_node_port_enum_params,
impl_node_port_set_param,
@ -732,12 +734,14 @@ static const struct spa_node impl_node = {
impl_node_process_output,
};
static int impl_clock_get_props(struct spa_clock *clock, struct spa_props **props)
static int impl_clock_enum_params(struct spa_clock *clock, uint32_t id, uint32_t *index,
struct spa_pod_builder *builder)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int impl_clock_set_props(struct spa_clock *clock, const struct spa_props *props)
static int impl_clock_set_param(struct spa_clock *clock, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
@ -771,8 +775,8 @@ static const struct spa_clock impl_clock = {
SPA_VERSION_CLOCK,
NULL,
SPA_CLOCK_STATE_STOPPED,
impl_clock_get_props,
impl_clock_set_props,
impl_clock_enum_params,
impl_clock_set_param,
impl_clock_get_time,
};

View file

@ -32,7 +32,6 @@
#include <spa/loop.h>
#include <spa/param-alloc.h>
#include <spa/type-map.h>
#include <spa/format-builder.h>
#include <lib/debug.h>
#include <lib/props.h>
@ -69,6 +68,7 @@ struct type {
uint32_t prop_device;
uint32_t prop_device_name;
uint32_t prop_device_fd;
struct spa_type_param param;
struct spa_type_media_type media_type;
struct spa_type_media_subtype media_subtype;
struct spa_type_media_subtype_video media_subtype_video;
@ -91,6 +91,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
type->prop_device = spa_type_map_get_id(map, SPA_TYPE_PROPS__device);
type->prop_device_name = spa_type_map_get_id(map, SPA_TYPE_PROPS__deviceName);
type->prop_device_fd = spa_type_map_get_id(map, SPA_TYPE_PROPS__deviceFd);
spa_type_param_map(map, &type->param);
spa_type_media_type_map(map, &type->media_type);
spa_type_media_subtype_map(map, &type->media_subtype);
spa_type_media_subtype_video_map(map, &type->media_subtype_video);
@ -136,7 +137,6 @@ struct port {
struct spa_source source;
struct spa_port_info info;
uint8_t params_buffer[1024];
struct spa_port_io *io;
int64_t last_ticks;
@ -168,28 +168,51 @@ struct impl {
#include "v4l2-utils.c"
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int get_props(struct impl *this, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
struct type *t;
struct type *t = &this->type;
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));
*props = spa_pod_builder_props(&b, t->props,
switch (*index) {
case 0:
spa_pod_builder_object(builder, t->param.idProps, 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);
break;
default:
return SPA_RESULT_ENUM_END;
}
(*index)++;
return SPA_RESULT_OK;
}
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
static int impl_node_enum_params(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
if (id == t->param.idProps)
return get_props(this, index, filter, builder);
return SPA_RESULT_UNKNOWN_PARAM;
}
static int impl_node_set_param(struct spa_node *node,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
struct impl *this;
struct type *t;
@ -199,12 +222,16 @@ static int impl_node_set_props(struct spa_node *node, const struct spa_props *pr
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
if (props == NULL) {
reset_props(&this->props);
return SPA_RESULT_OK;
if (id == t->param.idProps) {
if (param == NULL) {
reset_props(&this->props);
return SPA_RESULT_OK;
}
spa_pod_object_parse(param,
":", t->prop_device, "?S", this->props.device, sizeof(this->props.device), NULL);
}
spa_props_parse(props,
":", t->prop_device, "?S", this->props.device, sizeof(this->props.device), NULL);
else
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
@ -409,41 +436,96 @@ static int impl_node_remove_port(struct spa_node *node,
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int
impl_node_port_enum_formats(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_format **format,
const struct spa_format *filter,
uint32_t index)
static int impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_port_info **info)
{
struct impl *this;
int res;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
res = spa_v4l2_enum_format(this, format, filter, index);
*info = &this->out_ports[port_id].info;
return res;
return SPA_RESULT_OK;
}
static int impl_node_port_set_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags,
const struct spa_format *format)
static int port_enum_formats(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
return spa_v4l2_enum_format(this, index, filter, builder);
}
static int port_get_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct spa_pod_frame f[1];
struct type *t = &this->type;
struct port *port = &this->out_ports[port_id];
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_push_object(builder, &f[0],
t->param.idFormat, t->format);
spa_pod_builder_add(builder,
"I", port->current_format.media_type,
"I", port->current_format.media_subtype, 0);
if (port->current_format.media_subtype == t->media_subtype.raw) {
spa_pod_builder_add(builder,
":", t->format_video.format, "I", port->current_format.info.raw.format,
":", t->format_video.size, "R", &port->current_format.info.raw.size,
":", t->format_video.framerate, "F", &port->current_format.info.raw.framerate, 0);
} else if (port->current_format.media_subtype == t->media_subtype_video.mjpg ||
port->current_format.media_subtype == t->media_subtype_video.jpeg) {
spa_pod_builder_add(builder,
":", t->format_video.size, "R", &port->current_format.info.mjpg.size,
":", t->format_video.framerate, "F", &port->current_format.info.mjpg.framerate, 0);
} else if (port->current_format.media_subtype == t->media_subtype_video.h264) {
spa_pod_builder_add(builder,
":", t->format_video.size, "R", &port->current_format.info.h264.size,
":", t->format_video.framerate, "F", &port->current_format.info.h264.framerate, 0);
} else
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_pop(builder, &f[0]);
return SPA_RESULT_OK;
}
static int impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct port *port;
struct spa_video_info info;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
@ -452,6 +534,66 @@ static int impl_node_port_set_format(struct spa_node *node,
port = &this->out_ports[port_id];
if (id == t->param.idList) {
uint32_t list[] = { t->param.idEnumFormat,
t->param.idFormat,
t->param.idBuffers,
t->param.idMeta };
if (*index < SPA_N_ELEMENTS(list))
spa_pod_builder_object(builder, id, t->param.List,
":", t->param.listId, "I", list[*index]);
else
return SPA_RESULT_ENUM_END;
}
else if (id == t->param.idEnumFormat) {
return port_enum_formats(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idFormat) {
return port_get_format(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idBuffers) {
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_object(builder,
id, t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "i", port->fmt.fmt.pix.sizeimage,
":", t->param_alloc_buffers.stride, "i", port->fmt.fmt.pix.bytesperline,
":", t->param_alloc_buffers.buffers, "iru", MAX_BUFFERS,
2, 2, MAX_BUFFERS,
":", t->param_alloc_buffers.align, "i", 16);
}
else if (id == t->param.idMeta) {
switch (*index) {
case 0:
spa_pod_builder_object(builder,
id, 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_ENUM_END;
}
}
else
return SPA_RESULT_UNKNOWN_PARAM;
(*index)++;
return SPA_RESULT_OK;
}
static int port_set_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t flags,
const struct spa_pod_object *format)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct spa_video_info info;
struct type *t = &this->type;
struct port *port = &this->out_ports[port_id];
if (format == NULL) {
spa_v4l2_stream_off(this);
spa_v4l2_clear_buffers(this);
@ -459,8 +601,9 @@ static int impl_node_port_set_format(struct spa_node *node,
port->have_format = false;
return SPA_RESULT_OK;
} else {
info.media_type = SPA_FORMAT_MEDIA_TYPE(format);
info.media_subtype = SPA_FORMAT_MEDIA_SUBTYPE(format);
spa_pod_object_parse(format,
"I", &info.media_type,
"I", &info.media_subtype);
if (info.media_type != t->media_type.video) {
spa_log_error(this->log, "media type must be video");
@ -500,15 +643,15 @@ static int impl_node_port_set_format(struct spa_node *node,
}
}
if (port->have_format && !(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
if (port->have_format && !(flags & SPA_NODE_PARAM_FLAG_TEST_ONLY)) {
spa_v4l2_use_buffers(this, NULL, 0);
port->have_format = false;
}
if (spa_v4l2_set_format(this, &info, flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY) < 0)
if (spa_v4l2_set_format(this, &info, flags & SPA_NODE_PARAM_FLAG_TEST_ONLY) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
if (!(flags & SPA_NODE_PARAM_FLAG_TEST_ONLY)) {
port->current_format = info;
port->have_format = true;
}
@ -516,131 +659,26 @@ static int impl_node_port_set_format(struct spa_node *node,
return SPA_RESULT_OK;
}
static int impl_node_port_get_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_format **format)
{
struct impl *this;
struct port *port;
struct spa_pod_builder b = { NULL, };
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);
port = &this->out_ports[port_id];
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
b.data = port->format_buffer;
b.size = sizeof(port->format_buffer);
spa_pod_builder_push_format(&b, &f[0], t->format,
port->current_format.media_type,
port->current_format.media_subtype);
if (port->current_format.media_subtype == t->media_subtype.raw) {
spa_pod_builder_add(&b,
":", t->format_video.format, "I", port->current_format.info.raw.format,
":", t->format_video.size, "R", &port->current_format.info.raw.size,
":", t->format_video.framerate, "F", &port->current_format.info.raw.framerate, 0);
} else if (port->current_format.media_subtype == t->media_subtype_video.mjpg ||
port->current_format.media_subtype == t->media_subtype_video.jpeg) {
spa_pod_builder_add(&b,
":", t->format_video.size, "R", &port->current_format.info.mjpg.size,
":", t->format_video.framerate, "F", &port->current_format.info.mjpg.framerate, 0);
} else if (port->current_format.media_subtype == t->media_subtype_video.h264) {
spa_pod_builder_add(&b,
":", t->format_video.size, "R", &port->current_format.info.h264.size,
":", t->format_video.framerate, "F", &port->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;
}
static int impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_port_info **info)
{
struct impl *this;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
*info = &this->out_ports[port_id].info;
return SPA_RESULT_OK;
}
static int impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t index,
struct spa_param **param)
{
struct impl *this;
struct port *port;
struct spa_pod_builder b = { NULL, };
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);
port = &this->out_ports[port_id];
spa_pod_builder_init(&b, port->params_buffer, sizeof(port->params_buffer));
switch (index) {
case 0:
*param = spa_pod_builder_param(&b, t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "i", port->fmt.fmt.pix.sizeimage,
":", t->param_alloc_buffers.stride, "i", port->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:
*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;
}
return SPA_RESULT_OK;
}
static int impl_node_port_set_param(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_param *param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
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);
if (id == t->param.idFormat) {
return port_set_format(node, direction, port_id, flags, param);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
}
static int impl_node_port_use_buffers(struct spa_node *node,
@ -680,7 +718,7 @@ static int
impl_node_port_alloc_buffers(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@ -812,17 +850,14 @@ static const struct spa_dict info = {
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
&info,
impl_node_get_props,
impl_node_set_props,
impl_node_enum_params,
impl_node_set_param,
impl_node_send_command,
impl_node_set_callbacks,
impl_node_get_n_ports,
impl_node_get_port_ids,
impl_node_add_port,
impl_node_remove_port,
impl_node_port_enum_formats,
impl_node_port_set_format,
impl_node_port_get_format,
impl_node_port_get_info,
impl_node_port_enum_params,
impl_node_port_set_param,
@ -835,12 +870,15 @@ static const struct spa_node impl_node = {
impl_node_process_output,
};
static int impl_clock_get_props(struct spa_clock *clock, struct spa_props **props)
static int impl_clock_enum_params(struct spa_clock *clock, uint32_t id, uint32_t *index,
struct spa_pod_builder *builder)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int impl_clock_set_props(struct spa_clock *clock, const struct spa_props *props)
static int impl_clock_set_param(struct spa_clock *clock,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
@ -872,8 +910,8 @@ static const struct spa_clock impl_clock = {
SPA_VERSION_CLOCK,
NULL,
SPA_CLOCK_STATE_STOPPED,
impl_clock_get_props,
impl_clock_set_props,
impl_clock_enum_params,
impl_clock_set_param,
impl_clock_get_time,
};

View file

@ -398,18 +398,19 @@ static const struct format_info *find_format_info_by_media_type(struct type *typ
}
static uint32_t
enum_filter_format(struct type *type, const struct spa_format *filter, uint32_t index)
enum_filter_format(struct type *type, uint32_t media_type, int32_t media_subtype,
const struct spa_pod_object *filter, uint32_t index)
{
uint32_t video_format = 0;
if ((filter->body.media_type.value == type->media_type.video ||
filter->body.media_type.value == type->media_type.image)) {
if (filter->body.media_subtype.value == type->media_subtype.raw) {
if ((media_type == type->media_type.video ||
media_type == type->media_type.image)) {
if (media_subtype == type->media_subtype.raw) {
struct spa_pod_prop *p;
uint32_t n_values;
const uint32_t *values;
if (!(p = spa_format_find_prop(filter, type->format_video.format)))
if (!(p = spa_pod_object_find_prop(filter, type->format_video.format)))
return type->video_format.UNKNOWN;
if (p->body.value.type != SPA_POD_TYPE_ID)
@ -522,24 +523,22 @@ filter_framerate(struct v4l2_frmivalenum *frmival,
static int
spa_v4l2_enum_format(struct impl *this,
struct spa_format **format,
const struct spa_format *filter,
uint32_t index)
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct port *port = &this->out_ports[0];
int res, n_fractions;
const struct format_info *info;
struct spa_pod_frame f[2];
struct spa_pod_prop *prop;
struct spa_pod_builder b = { NULL, };
uint32_t media_type, media_subtype, video_format;
uint32_t filter_media_type, filter_media_subtype;
if (spa_v4l2_open(this) < 0)
return SPA_RESULT_ERROR;
*format = NULL;
if (index == 0) {
if (*index == 0) {
spa_zero(port->fmtdesc);
port->fmtdesc.index = 0;
port->fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@ -549,6 +548,12 @@ spa_v4l2_enum_format(struct impl *this,
spa_zero(port->frmival);
}
if (filter) {
spa_pod_object_parse(filter,
"I", &filter_media_type,
"I", &filter_media_subtype);
}
if (false) {
next_fmtdesc:
port->fmtdesc.index++;
@ -557,14 +562,17 @@ spa_v4l2_enum_format(struct impl *this,
while (port->next_fmtdesc) {
if (filter) {
video_format =
enum_filter_format(&this->type, filter, port->fmtdesc.index);
video_format = enum_filter_format(&this->type,
filter_media_type,
filter_media_subtype,
filter, port->fmtdesc.index);
if (video_format == this->type.video_format.UNKNOWN)
return SPA_RESULT_ENUM_END;
info = find_format_info_by_media_type(&this->type,
filter->body.media_type.value,
filter->body.media_subtype.value,
filter_media_type,
filter_media_subtype,
video_format, 0);
if (info == NULL)
goto next_fmtdesc;
@ -591,7 +599,7 @@ spa_v4l2_enum_format(struct impl *this,
struct spa_pod_prop *p;
/* check if we have a fixed frame size */
if (!(p = spa_format_find_prop(filter, this->type.format_video.size)))
if (!(p = spa_pod_object_find_prop(filter, this->type.format_video.size)))
goto do_frmsize;
if (p->body.value.type != SPA_POD_TYPE_RECTANGLE)
@ -625,7 +633,7 @@ spa_v4l2_enum_format(struct impl *this,
uint32_t i, n_values;
/* check if we have a fixed frame size */
if (!(p = spa_format_find_prop(filter, this->type.format_video.size)))
if (!(p = spa_pod_object_find_prop(filter, this->type.format_video.size)))
goto have_size;
range = p->body.flags & SPA_POD_PROP_RANGE_MASK;
@ -675,21 +683,25 @@ spa_v4l2_enum_format(struct impl *this,
media_subtype = *SPA_MEMBER(&this->type, info->media_subtype_offset, uint32_t);
video_format = *SPA_MEMBER(&this->type, info->format_offset, uint32_t);
spa_pod_builder_init(&b, port->format_buffer, sizeof(port->format_buffer));
spa_pod_builder_push_format(&b, &f[0], this->type.format, media_type, media_subtype);
spa_pod_builder_init(builder, port->format_buffer, sizeof(port->format_buffer));
spa_pod_builder_push_object(builder, &f[0],
this->type.param.idEnumFormat, this->type.format);
spa_pod_builder_add(builder,
"I", media_type,
"I", media_subtype, 0);
if (media_subtype == this->type.media_subtype.raw) {
spa_pod_builder_add(&b,
":", this->type.format_video.format, "I", video_format, 0);
spa_pod_builder_add(builder,
":", this->type.format_video.format, "I", video_format, 0);
}
spa_pod_builder_add(&b,
spa_pod_builder_add(builder,
":", this->type.format_video.size, "R", &SPA_RECTANGLE(port->frmsize.discrete.width,
port->frmsize.discrete.height), 0);
spa_pod_builder_push_prop(&b, &f[1], this->type.format_video.framerate,
spa_pod_builder_push_prop(builder, &f[1], this->type.format_video.framerate,
SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_UNSET);
prop = SPA_POD_BUILDER_DEREF(&b, f[1].ref, struct spa_pod_prop);
prop = SPA_POD_BUILDER_DEREF(builder, f[1].ref, struct spa_pod_prop);
n_fractions = 0;
port->frmival.index = 0;
@ -712,7 +724,7 @@ spa_v4l2_enum_format(struct impl *this,
uint32_t i, n_values;
const struct spa_fraction step = { 1, 1 }, *values;
if (!(p = spa_format_find_prop(filter, this->type.format_video.framerate)))
if (!(p = spa_pod_object_find_prop(filter, this->type.format_video.framerate)))
goto have_framerate;
if (p->body.value.type != SPA_POD_TYPE_FRACTION)
@ -746,21 +758,21 @@ spa_v4l2_enum_format(struct impl *this,
if (port->frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
prop->body.flags |= SPA_POD_PROP_RANGE_ENUM;
if (n_fractions == 0)
spa_pod_builder_fraction(&b,
spa_pod_builder_fraction(builder,
port->frmival.discrete.denominator,
port->frmival.discrete.numerator);
spa_pod_builder_fraction(&b,
spa_pod_builder_fraction(builder,
port->frmival.discrete.denominator,
port->frmival.discrete.numerator);
port->frmival.index++;
} else if (port->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
port->frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
if (n_fractions == 0)
spa_pod_builder_fraction(&b, 25, 1);
spa_pod_builder_fraction(&b,
spa_pod_builder_fraction(builder, 25, 1);
spa_pod_builder_fraction(builder,
port->frmival.stepwise.min.denominator,
port->frmival.stepwise.min.numerator);
spa_pod_builder_fraction(&b,
spa_pod_builder_fraction(builder,
port->frmival.stepwise.max.denominator,
port->frmival.stepwise.max.numerator);
@ -768,7 +780,7 @@ spa_v4l2_enum_format(struct impl *this,
prop->body.flags |= SPA_POD_PROP_RANGE_MIN_MAX;
} else {
prop->body.flags |= SPA_POD_PROP_RANGE_STEP;
spa_pod_builder_fraction(&b,
spa_pod_builder_fraction(builder,
port->frmival.stepwise.step.denominator,
port->frmival.stepwise.step.numerator);
}
@ -779,10 +791,10 @@ spa_v4l2_enum_format(struct impl *this,
if (n_fractions <= 1) {
prop->body.flags &= ~(SPA_POD_PROP_RANGE_MASK | SPA_POD_PROP_FLAG_UNSET);
}
spa_pod_builder_pop(&b, &f[1]);
spa_pod_builder_pop(&b, &f[0]);
spa_pod_builder_pop(builder, &f[1]);
spa_pod_builder_pop(builder, &f[0]);
*format = SPA_POD_BUILDER_DEREF(&b, f[0].ref, struct spa_format);
(*index)++;
return SPA_RESULT_OK;
}
@ -1028,7 +1040,7 @@ static int spa_v4l2_use_buffers(struct impl *this, struct spa_buffer **buffers,
static int
mmap_init(struct impl *this,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@ -1137,7 +1149,7 @@ static int read_init(struct impl *this)
static int
spa_v4l2_alloc_buffers(struct impl *this,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)

View file

@ -32,7 +32,6 @@
#include <spa/param-alloc.h>
#include <spa/list.h>
#include <spa/video/format-utils.h>
#include <spa/format-builder.h>
#include <lib/format.h>
#include <lib/props.h>
@ -51,6 +50,7 @@ struct type {
uint32_t prop_pattern;
uint32_t pattern_smpte_snow;
uint32_t pattern_snow;
struct spa_type_param param;
struct spa_type_meta meta;
struct spa_type_data data;
struct spa_type_media_type media_type;
@ -73,6 +73,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
type->prop_pattern = spa_type_map_get_id(map, SPA_TYPE_PROPS__patternType);
type->pattern_smpte_snow = spa_type_map_get_id(map, SPA_TYPE_PROPS__patternType ":smpte-snow");
type->pattern_snow = spa_type_map_get_id(map, SPA_TYPE_PROPS__patternType ":snow");
spa_type_param_map(map, &type->param);
spa_type_meta_map(map, &type->meta);
spa_type_data_map(map, &type->data);
spa_type_media_type_map(map, &type->media_type);
@ -121,7 +122,6 @@ struct impl {
struct itimerspec timerspec;
struct spa_port_info info;
uint8_t params_buffer[1024];
struct spa_port_io *io;
bool have_format;
@ -153,30 +153,39 @@ static void reset_props(struct impl *this, struct props *props)
props->pattern = this->type.DEFAULT_PATTERN;
}
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_enum_params(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
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);
spa_return_val_if_fail(builder != 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));
*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);
if (id == t->param.idProps) {
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_object(builder,
id, t->props,
":", t->prop_live, "b", this->props.live,
":", t->prop_pattern, "Ie", this->props.pattern,
2, t->pattern_smpte_snow,
t->pattern_snow);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
struct impl *this;
struct type *t;
@ -186,19 +195,19 @@ static int impl_node_set_props(struct spa_node *node, const struct spa_props *pr
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
if (props == NULL) {
reset_props(this, &this->props);
} else {
spa_props_parse(props,
if (id == t->param.idProps) {
spa_pod_object_parse(param,
":", t->prop_live, "?b", &this->props.live,
":", t->prop_pattern, "?I", &this->props.pattern,
NULL);
}
if (this->props.live)
this->info.flags |= SPA_PORT_INFO_FLAG_LIVE;
if (this->props.live)
this->info.flags |= SPA_PORT_INFO_FLAG_LIVE;
else
this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE;
}
else
this->info.flags &= ~SPA_PORT_INFO_FLAG_LIVE;
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
@ -408,39 +417,47 @@ impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint3
}
static int
impl_node_port_enum_formats(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_format **format,
const struct spa_format *filter,
uint32_t index)
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_port_info **info)
{
struct impl *this;
int res;
struct spa_format *fmt;
uint8_t buffer[256];
struct spa_pod_builder b = { NULL, };
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);
spa_return_val_if_fail(info != 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);
count = match = filter ? 0 : index;
*info = &this->info;
return SPA_RESULT_OK;
}
static int port_enum_formats(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct spa_pod_object *fmt;
uint8_t buffer[256];
struct spa_pod_builder b = { NULL, };
struct type *t = &this->type;
int res;
next:
spa_pod_builder_init(&b, buffer, sizeof(buffer));
switch (count++) {
switch (*index) {
case 0:
fmt = spa_pod_builder_format(&b,
t->format,
t->media_type.video, t->media_subtype.raw,
fmt = spa_pod_builder_object(&b,
t->param.idEnumFormat, t->format,
"I", t->media_type.video,
"I", t->media_subtype.raw,
":", t->format_video.format, "Ieu", t->video_format.RGB,
2, t->video_format.RGB,
t->video_format.UYVY,
@ -454,13 +471,93 @@ impl_node_port_enum_formats(struct spa_node *node,
default:
return SPA_RESULT_ENUM_END;
}
(*index)++;
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)
if ((res = spa_pod_object_filter(fmt, filter, builder)) != SPA_RESULT_OK)
goto next;
*format = SPA_POD_BUILDER_DEREF(&b, 0, struct spa_format);
return SPA_RESULT_OK;
}
static int port_get_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct type *t = &this->type;
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_object(builder,
t->param.idFormat, t->format,
"I", t->media_type.video,
"I", 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;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct type *t;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != 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);
if (id == t->param.idEnumFormat) {
return port_enum_formats(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idFormat) {
return port_get_format(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idBuffers) {
struct spa_video_info_raw *raw_info = &this->current_format.info.raw;
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_object(builder,
id, 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);
}
else if (id == t->param.idMeta) {
switch (*index) {
case 0:
spa_pod_builder_object(builder,
id, 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_ENUM_END;
}
}
(*index)++;
return SPA_RESULT_OK;
}
@ -477,28 +574,22 @@ static int clear_buffers(struct impl *this)
return SPA_RESULT_OK;
}
static int
impl_node_port_set_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags,
const struct spa_format *format)
static int port_set_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t flags,
const struct spa_pod_object *format)
{
struct impl *this;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
if (format == NULL) {
this->have_format = false;
clear_buffers(this);
} else {
struct spa_video_info info = { SPA_FORMAT_MEDIA_TYPE(format),
SPA_FORMAT_MEDIA_SUBTYPE(format),
};
struct spa_video_info info = { 0 };
spa_pod_object_parse(format,
"I", &info.media_type,
"I", &info.media_subtype);
if (info.media_type != this->type.media_type.video &&
info.media_subtype != this->type.media_subtype.raw)
@ -526,113 +617,27 @@ impl_node_port_set_format(struct spa_node *node,
return SPA_RESULT_OK;
}
static int
impl_node_port_get_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_format **format)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
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);
if (!this->have_format)
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
*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;
}
static int
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_port_info **info)
{
struct impl *this;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(info != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
*info = &this->info;
return SPA_RESULT_OK;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t index,
struct spa_param **param)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
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);
spa_pod_builder_init(&b, this->params_buffer, sizeof(this->params_buffer));
switch (index) {
case 0: {
struct spa_video_info_raw *raw_info = &this->current_format.info.raw;
*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:
*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;
}
return SPA_RESULT_OK;
}
static int
impl_node_port_set_param(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_param *param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
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);
if (id == t->param.idFormat) {
return port_set_format(node, direction, port_id, flags, param);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
}
static int
@ -683,7 +688,7 @@ static int
impl_node_port_alloc_buffers(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@ -803,17 +808,14 @@ static const struct spa_dict node_info = {
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
&node_info,
impl_node_get_props,
impl_node_set_props,
impl_node_enum_params,
impl_node_set_param,
impl_node_send_command,
impl_node_set_callbacks,
impl_node_get_n_ports,
impl_node_get_port_ids,
impl_node_add_port,
impl_node_remove_port,
impl_node_port_enum_formats,
impl_node_port_set_format,
impl_node_port_get_format,
impl_node_port_get_info,
impl_node_port_enum_params,
impl_node_port_set_param,
@ -826,12 +828,14 @@ static const struct spa_node impl_node = {
impl_node_process_output,
};
static int impl_clock_get_props(struct spa_clock *clock, struct spa_props **props)
static int impl_clock_enum_params(struct spa_clock *clock, uint32_t id, uint32_t *index,
struct spa_pod_builder *builder)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int impl_clock_set_props(struct spa_clock *clock, const struct spa_props *props)
static int impl_clock_set_param(struct spa_clock *clock, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
@ -865,8 +869,8 @@ static const struct spa_clock impl_clock = {
SPA_VERSION_CLOCK,
NULL,
SPA_CLOCK_STATE_STOPPED,
impl_clock_get_props,
impl_clock_set_props,
impl_clock_enum_params,
impl_clock_set_param,
impl_clock_get_time,
};

View file

@ -25,7 +25,6 @@
#include <spa/node.h>
#include <spa/list.h>
#include <spa/audio/format-utils.h>
#include <spa/format-builder.h>
#include <spa/param-alloc.h>
#include <lib/props.h>
#include <lib/format.h>
@ -67,6 +66,7 @@ struct type {
uint32_t props;
uint32_t prop_volume;
uint32_t prop_mute;
struct spa_type_param param;
struct spa_type_meta meta;
struct spa_type_data data;
struct spa_type_media_type media_type;
@ -86,6 +86,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
type->props = spa_type_map_get_id(map, SPA_TYPE__Props);
type->prop_volume = spa_type_map_get_id(map, SPA_TYPE_PROPS__volume);
type->prop_mute = spa_type_map_get_id(map, SPA_TYPE_PROPS__mute);
spa_type_param_map(map, &type->param);
spa_type_meta_map(map, &type->meta);
spa_type_data_map(map, &type->data);
spa_type_media_type_map(map, &type->media_type);
@ -106,7 +107,6 @@ struct impl {
struct spa_type_map *map;
struct spa_log *log;
uint8_t props_buffer[512];
struct props props;
const struct spa_node_callbacks *callbacks;
@ -135,28 +135,35 @@ static void reset_props(struct props *props)
props->mute = DEFAULT_MUTE;
}
static int impl_node_get_props(struct spa_node *node, struct spa_props **props)
static int impl_node_enum_params(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this;
struct spa_pod_builder b = { NULL, };
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);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != 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));
*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);
if (id == t->param.idProps) {
spa_pod_builder_object(builder,
id, t->props,
":", t->prop_volume, "dr", this->props.volume, 2, 0.0, 10.0,
":", t->prop_mute, "b", this->props.mute);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
static int impl_node_set_props(struct spa_node *node, const struct spa_props *props)
static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
struct impl *this;
struct type *t;
@ -166,13 +173,18 @@ static int impl_node_set_props(struct spa_node *node, const struct spa_props *pr
this = SPA_CONTAINER_OF(node, struct impl, node);
t = &this->type;
if (props == NULL) {
reset_props(&this->props);
} else {
spa_props_parse(props,
if (id == t->param.idProps) {
if (param == NULL) {
reset_props(&this->props);
return SPA_RESULT_OK;
}
spa_pod_object_parse(param,
":", t->prop_volume, "?d", &this->props.volume,
":", t->prop_mute, "?b", &this->props.mute, NULL);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
return SPA_RESULT_OK;
}
@ -262,148 +274,6 @@ impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint3
return SPA_RESULT_NOT_IMPLEMENTED;
}
static int
impl_node_port_enum_formats(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_format **format,
const struct spa_format *filter,
uint32_t index)
{
struct impl *this;
int res;
struct spa_format *fmt;
uint8_t buffer[1024];
struct spa_pod_builder b = { NULL, };
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);
count = match = filter ? 0 : index;
next:
spa_pod_builder_init(&b, buffer, sizeof(buffer));
switch (count++) {
case 0:
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;
}
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)
goto next;
*format = SPA_POD_BUILDER_DEREF(&b, 0, struct spa_format);
return SPA_RESULT_OK;
}
static int clear_buffers(struct impl *this, struct port *port)
{
if (port->n_buffers > 0) {
spa_log_info(this->log, NAME " %p: clear buffers", this);
port->n_buffers = 0;
spa_list_init(&port->empty);
}
return SPA_RESULT_OK;
}
static int
impl_node_port_set_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t flags,
const struct spa_format *format)
{
struct impl *this;
struct port *port;
spa_return_val_if_fail(node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), SPA_RESULT_INVALID_PORT);
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
if (format == NULL) {
port->have_format = false;
clear_buffers(this, port);
} else {
struct spa_audio_info info = { SPA_FORMAT_MEDIA_TYPE(format),
SPA_FORMAT_MEDIA_SUBTYPE(format),
};
if (info.media_type != this->type.media_type.audio ||
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) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
this->bpf = 2 * info.info.raw.channels;
this->current_format = info;
port->have_format = true;
}
return SPA_RESULT_OK;
}
static int
impl_node_port_get_format(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_format **format)
{
struct impl *this;
struct port *port;
struct spa_pod_builder b = { NULL, };
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);
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
spa_pod_builder_init(&b, this->format_buffer, sizeof(this->format_buffer));
*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;
}
static int
impl_node_port_get_info(struct spa_node *node,
enum spa_direction direction,
@ -427,35 +297,103 @@ impl_node_port_get_info(struct spa_node *node,
return SPA_RESULT_OK;
}
static int port_enum_formats(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
int res;
struct spa_pod_object *fmt;
uint8_t buffer[1024];
struct spa_pod_builder b = { NULL, };
struct type *t = &this->type;
next:
spa_pod_builder_init(&b, buffer, sizeof(buffer));
switch (*index) {
case 0:
fmt = spa_pod_builder_object(&b,
t->param.idEnumFormat, t->format,
"I", t->media_type.audio,
"I", 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;
}
(*index)++;
if ((res = spa_pod_object_filter(fmt, filter, builder)) != SPA_RESULT_OK)
goto next;
return SPA_RESULT_OK;
}
static int port_get_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct port *port;
struct type *t = &this->type;
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
if (*index > 0)
return SPA_RESULT_ENUM_END;
spa_pod_builder_object(builder,
t->param.idFormat, t->format,
"I", t->media_type.audio,
"I", 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;
}
static int
impl_node_port_enum_params(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
uint32_t index,
struct spa_param **param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t *index,
const struct spa_pod_object *filter,
struct spa_pod_builder *builder)
{
struct spa_pod_builder b = { NULL };
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);
spa_return_val_if_fail(index != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail(builder != 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);
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
spa_pod_builder_init(&b, port->params_buffer, sizeof(port->params_buffer));
switch (index) {
case 0:
*param = spa_pod_builder_param(&b,
t->param_alloc_buffers.Buffers,
if (id == t->param.idEnumFormat) {
return port_enum_formats(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idFormat) {
return port_get_format(node, direction, port_id, index, filter, builder);
}
else if (id == t->param.idBuffers) {
spa_pod_builder_object(builder,
id, t->param_alloc_buffers.Buffers,
":", t->param_alloc_buffers.size, "iru", 1024 * this->bpf,
2, 16 * this->bpf,
INT32_MAX / this->bpf,
@ -463,17 +401,68 @@ impl_node_port_enum_params(struct spa_node *node,
":", t->param_alloc_buffers.buffers, "iru", 2,
2, 1, MAX_BUFFERS,
":", t->param_alloc_buffers.align, "i", 16);
break;
}
else if (id == t->param.idMeta) {
switch (*index) {
case 0:
spa_pod_builder_object(builder,
id, 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_ENUM_END;
}
}
else
return SPA_RESULT_UNKNOWN_PARAM;
case 1:
*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;
(*index)++;
default:
return SPA_RESULT_NOT_IMPLEMENTED;
return SPA_RESULT_OK;
}
static int clear_buffers(struct impl *this, struct port *port)
{
if (port->n_buffers > 0) {
spa_log_info(this->log, NAME " %p: clear buffers", this);
port->n_buffers = 0;
spa_list_init(&port->empty);
}
return SPA_RESULT_OK;
}
static int port_set_format(struct spa_node *node,
enum spa_direction direction, uint32_t port_id,
uint32_t flags,
const struct spa_pod_object *format)
{
struct impl *this = SPA_CONTAINER_OF(node, struct impl, node);
struct port *port;
port =
direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
if (format == NULL) {
port->have_format = false;
clear_buffers(this, port);
} else {
struct spa_audio_info info = { 0 };
spa_pod_object_parse(format,
"I", &info.media_type,
"I", &info.media_subtype);
if (info.media_type != this->type.media_type.audio ||
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) < 0)
return SPA_RESULT_INVALID_MEDIA_TYPE;
this->bpf = 2 * info.info.raw.channels;
this->current_format = info;
port->have_format = true;
}
return SPA_RESULT_OK;
@ -481,11 +470,25 @@ impl_node_port_enum_params(struct spa_node *node,
static int
impl_node_port_set_param(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
const struct spa_param *param)
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t flags,
const struct spa_pod_object *param)
{
return SPA_RESULT_NOT_IMPLEMENTED;
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);
if (id == t->param.idFormat) {
return port_set_format(node, direction, port_id, flags, param);
}
else
return SPA_RESULT_UNKNOWN_PARAM;
}
static int
@ -544,7 +547,7 @@ static int
impl_node_port_alloc_buffers(struct spa_node *node,
enum spa_direction direction,
uint32_t port_id,
struct spa_param **params,
struct spa_pod_object **params,
uint32_t n_params,
struct spa_buffer **buffers,
uint32_t *n_buffers)
@ -762,17 +765,14 @@ static int impl_node_process_output(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
NULL,
impl_node_get_props,
impl_node_set_props,
impl_node_enum_params,
impl_node_set_param,
impl_node_send_command,
impl_node_set_callbacks,
impl_node_get_n_ports,
impl_node_get_port_ids,
impl_node_add_port,
impl_node_remove_port,
impl_node_port_enum_formats,
impl_node_port_set_format,
impl_node_port_get_format,
impl_node_port_get_info,
impl_node_port_enum_params,
impl_node_port_set_param,

View file

@ -34,7 +34,6 @@
#include <spa/type-map-impl.h>
#include <spa/audio/format-utils.h>
#include <spa/format-utils.h>
#include <spa/format-builder.h>
static SPA_TYPE_MAP_IMPL(default_map, 4096);
static SPA_LOG_IMPL(default_log);
@ -55,6 +54,7 @@ struct type {
uint32_t props_volume;
uint32_t props_min_latency;
uint32_t props_live;
struct spa_type_param param;
struct spa_type_meta meta;
struct spa_type_data data;
struct spa_type_media_type media_type;
@ -75,6 +75,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
type->props_volume = spa_type_map_get_id(map, SPA_TYPE_PROPS__volume);
type->props_min_latency = spa_type_map_get_id(map, SPA_TYPE_PROPS__minLatency);
type->props_live = spa_type_map_get_id(map, SPA_TYPE_PROPS__live);
spa_type_param_map(map, &type->param);
spa_type_meta_map(map, &type->meta);
spa_type_data_map(map, &type->data);
spa_type_media_type_map(map, &type->media_type);
@ -284,7 +285,7 @@ do_invoke(struct spa_loop *loop,
static int make_nodes(struct data *data, const char *device)
{
int res;
struct spa_props *props;
struct spa_pod_object *props;
struct spa_pod_builder b = { 0 };
uint8_t buffer[128];
@ -296,14 +297,14 @@ 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));
props = spa_pod_builder_props(&b,
data->type.props,
props = spa_pod_builder_object(&b,
0, 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);
spa_debug_pod(&props->pod, 0);
if ((res = spa_node_set_props(data->sink, props)) < 0)
if ((res = spa_node_set_param(data->sink, data->type.param.idProps, 0, props)) < 0)
printf("got set_props error %d\n", res);
if ((res = make_node(data, &data->volume,
@ -320,13 +321,13 @@ static int make_nodes(struct data *data, const char *device)
}
spa_pod_builder_init(&b, buffer, sizeof(buffer));
props = spa_pod_builder_props(&b,
data->type.props,
props = spa_pod_builder_object(&b,
0, 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)
if ((res = spa_node_set_param(data->source, data->type.param.idProps, 0, props)) < 0)
printf("got set_props error %d\n", res);
data->source_volume_io[0] = SPA_PORT_IO_INIT;
@ -367,31 +368,41 @@ static int make_nodes(struct data *data, const char *device)
static int negotiate_formats(struct data *data)
{
int res;
struct spa_format *format, *filter;
int res, ref;
struct spa_pod_object *format, *filter;
uint32_t state = 0;
struct spa_pod_builder b = { 0 };
uint8_t buffer[256];
uint8_t buffer[4096];
spa_pod_builder_init(&b, buffer, sizeof(buffer));
filter = spa_pod_builder_format(&b,
data->type.format,
data->type.media_type.audio, data->type.media_subtype.raw,
filter = spa_pod_builder_object(&b,
0, data->type.format,
"I", data->type.media_type.audio,
"I", 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,
state)) < 0)
ref = b.offset;
if ((res = spa_node_port_enum_params(data->sink,
SPA_DIRECTION_INPUT, 0,
data->type.param.idEnumFormat, &state,
filter, &b)) < 0)
return res;
format = SPA_POD_BUILDER_DEREF(&b, ref, struct spa_pod_object);
if ((res = spa_node_port_set_format(data->sink, SPA_DIRECTION_INPUT, 0, 0, format)) < 0)
if ((res = spa_node_port_set_param(data->sink,
SPA_DIRECTION_INPUT, 0,
data->type.param.idFormat, 0, format)) < 0)
return res;
if ((res = spa_node_port_set_format(data->volume, SPA_DIRECTION_OUTPUT, 0, 0, format)) < 0)
if ((res = spa_node_port_set_param(data->volume,
SPA_DIRECTION_OUTPUT, 0,
data->type.param.idFormat, 0, format)) < 0)
return res;
init_buffer(data, data->volume_buffers, data->volume_buffer, 1, BUFFER_SIZE);
@ -404,9 +415,13 @@ static int negotiate_formats(struct data *data)
1)) < 0)
return res;
if ((res = spa_node_port_set_format(data->volume, SPA_DIRECTION_INPUT, 0, 0, format)) < 0)
if ((res = spa_node_port_set_param(data->volume,
SPA_DIRECTION_INPUT, 0,
data->type.param.idFormat, 0, format)) < 0)
return res;
if ((res = spa_node_port_set_format(data->source, SPA_DIRECTION_OUTPUT, 0, 0, format)) < 0)
if ((res = spa_node_port_set_param(data->source,
SPA_DIRECTION_OUTPUT, 0,
data->type.param.idFormat, 0, format)) < 0)
return res;
init_buffer(data, data->source_buffers, data->source_buffer, 1, BUFFER_SIZE);

View file

@ -34,7 +34,6 @@
#include <spa/type-map-impl.h>
#include <spa/audio/format-utils.h>
#include <spa/format-utils.h>
#include <spa/format-builder.h>
#include <spa/graph.h>
#include <spa/graph-scheduler1.h>

View file

@ -34,7 +34,6 @@
#include <spa/type-map-impl.h>
#include <spa/audio/format-utils.h>
#include <spa/format-utils.h>
#include <spa/format-builder.h>
#define USE_GRAPH
@ -55,6 +54,7 @@ struct type {
uint32_t props_volume;
uint32_t props_min_latency;
uint32_t props_live;
struct spa_type_param param;
struct spa_type_meta meta;
struct spa_type_data data;
struct spa_type_media_type media_type;
@ -75,6 +75,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
type->props_volume = spa_type_map_get_id(map, SPA_TYPE_PROPS__volume);
type->props_min_latency = spa_type_map_get_id(map, SPA_TYPE_PROPS__minLatency);
type->props_live = spa_type_map_get_id(map, SPA_TYPE_PROPS__live);
spa_type_param_map(map, &type->param);
spa_type_meta_map(map, &type->meta);
spa_type_data_map(map, &type->data);
spa_type_media_type_map(map, &type->media_type);
@ -326,7 +327,7 @@ do_invoke(struct spa_loop *loop,
static int make_nodes(struct data *data, const char *device)
{
int res;
struct spa_props *props;
struct spa_pod_object *props;
struct spa_pod_builder b = { 0 };
uint8_t buffer[128];
@ -338,12 +339,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));
props = spa_pod_builder_props(&b,
data->type.props,
props = spa_pod_builder_object(&b,
0, 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)
if ((res = spa_node_set_param(data->sink, data->type.param.idProps, 0, props)) < 0)
printf("got set_props error %d\n", res);
if ((res = make_node(data, &data->mix,
@ -361,13 +362,13 @@ static int make_nodes(struct data *data, const char *device)
}
spa_pod_builder_init(&b, buffer, sizeof(buffer));
props = spa_pod_builder_props(&b,
data->type.props,
props = spa_pod_builder_object(&b,
0, 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)
if ((res = spa_node_set_param(data->source1, data->type.param.idProps, 0, props)) < 0)
printf("got set_props error %d\n", res);
if ((res = make_node(data, &data->source2,
@ -378,13 +379,13 @@ static int make_nodes(struct data *data, const char *device)
}
spa_pod_builder_init(&b, buffer, sizeof(buffer));
props = spa_pod_builder_props(&b,
data->type.props,
props = spa_pod_builder_object(&b,
0, 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)
if ((res = spa_node_set_param(data->source2, data->type.param.idProps, 0, props)) < 0)
printf("got set_props error %d\n", res);
data->mix_ports[0] = 0;
@ -450,29 +451,42 @@ static int make_nodes(struct data *data, const char *device)
static int negotiate_formats(struct data *data)
{
int res;
struct spa_format *format, *filter;
uint32_t state = 0;
struct spa_pod_object *format, *filter;
uint32_t state = 0, ref;
struct spa_pod_builder b = { 0 };
uint8_t buffer[256];
uint8_t buffer[2048];
spa_pod_builder_init(&b, buffer, sizeof(buffer));
filter = spa_pod_builder_format(&b,
data->type.format,
data->type.media_type.audio, data->type.media_subtype.raw,
filter = spa_pod_builder_object(&b,
0, data->type.format,
"I", data->type.media_type.audio,
"I", 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);
ref = b.offset;
if ((res =
spa_node_port_enum_formats(data->sink, SPA_DIRECTION_INPUT, 0, &format, filter,
state)) < 0)
spa_node_port_enum_params(data->sink,
SPA_DIRECTION_INPUT, 0,
data->type.param.idEnumFormat, &state,
filter, &b)) < 0)
return res;
if ((res = spa_node_port_set_format(data->sink, SPA_DIRECTION_INPUT, 0, 0, format)) < 0)
format = SPA_POD_BUILDER_DEREF(&b, ref, struct spa_pod_object);
if ((res = spa_node_port_set_param(data->sink,
SPA_DIRECTION_INPUT, 0,
data->type.param.idFormat, 0,
format)) < 0)
return res;
if ((res = spa_node_port_set_format(data->mix, SPA_DIRECTION_OUTPUT, 0, 0, format)) < 0)
if ((res = spa_node_port_set_param(data->mix,
SPA_DIRECTION_OUTPUT, 0,
data->type.param.idFormat, 0,
format)) < 0)
return res;
init_buffer(data, data->mix_buffers, data->mix_buffer, 1, BUFFER_SIZE2);
@ -486,11 +500,16 @@ static int negotiate_formats(struct data *data)
return res;
if ((res =
spa_node_port_set_format(data->mix, SPA_DIRECTION_INPUT, data->mix_ports[0], 0,
format)) < 0)
spa_node_port_set_param(data->mix,
SPA_DIRECTION_INPUT, data->mix_ports[0],
data->type.param.idFormat, 0,
format)) < 0)
return res;
if ((res = spa_node_port_set_format(data->source1, SPA_DIRECTION_OUTPUT, 0, 0, format)) < 0)
if ((res = spa_node_port_set_param(data->source1,
SPA_DIRECTION_OUTPUT, 0,
data->type.param.idFormat, 0,
format)) < 0)
return res;
init_buffer(data, data->source1_buffers, data->source1_buffer, 2, BUFFER_SIZE1);
@ -504,11 +523,16 @@ static int negotiate_formats(struct data *data)
return res;
if ((res =
spa_node_port_set_format(data->mix, SPA_DIRECTION_INPUT, data->mix_ports[1], 0,
format)) < 0)
spa_node_port_set_param(data->mix,
SPA_DIRECTION_INPUT, data->mix_ports[1],
data->type.param.idFormat, 0,
format)) < 0)
return res;
if ((res = spa_node_port_set_format(data->source2, SPA_DIRECTION_OUTPUT, 0, 0, format)) < 0)
if ((res = spa_node_port_set_param(data->source2,
SPA_DIRECTION_OUTPUT, 0,
data->type.param.idFormat, 0,
format)) < 0)
return res;
init_buffer(data, data->source2_buffers, data->source2_buffer, 2, BUFFER_SIZE2);

View file

@ -32,7 +32,6 @@
#include <spa/type-map-impl.h>
#include <spa/audio/format-utils.h>
#include <spa/format-utils.h>
#include <spa/format-builder.h>
#include <spa/graph.h>
#include <spa/graph-scheduler1.h>
@ -55,6 +54,7 @@ struct type {
uint32_t props_volume;
uint32_t props_min_latency;
uint32_t props_live;
struct spa_type_param param;
struct spa_type_meta meta;
struct spa_type_data data;
struct spa_type_media_type media_type;
@ -73,6 +73,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
type->props_volume = spa_type_map_get_id(map, SPA_TYPE_PROPS__volume);
type->props_min_latency = spa_type_map_get_id(map, SPA_TYPE_PROPS__minLatency);
type->props_live = spa_type_map_get_id(map, SPA_TYPE_PROPS__live);
spa_type_param_map(map, &type->param);
spa_type_meta_map(map, &type->meta);
spa_type_data_map(map, &type->data);
spa_type_media_type_map(map, &type->media_type);
@ -385,19 +386,26 @@ static int make_nodes(struct data *data)
static int negotiate_formats(struct data *data)
{
int res;
struct spa_format *format;
struct spa_pod_object *format;
struct spa_pod_builder b = { 0 };
uint8_t buffer[256];
spa_pod_builder_init(&b, buffer, sizeof(buffer));
format = spa_pod_builder_format(&b,
data->type.format,
data->type.media_type.binary, data->type.media_subtype.raw);
format = spa_pod_builder_object(&b,
0, data->type.format,
"I", data->type.media_type.binary,
"I", data->type.media_subtype.raw);
if ((res = spa_node_port_set_format(data->sink, SPA_DIRECTION_INPUT, 0, 0, format)) < 0)
if ((res = spa_node_port_set_param(data->sink,
SPA_DIRECTION_INPUT, 0,
data->type.param.idFormat, 0,
format)) < 0)
return res;
if ((res = spa_node_port_set_format(data->source, SPA_DIRECTION_OUTPUT, 0, 0, format)) < 0)
if ((res = spa_node_port_set_param(data->source,
SPA_DIRECTION_OUTPUT, 0,
data->type.param.idFormat, 0,
format)) < 0)
return res;
init_buffer(data, data->source_buffers, data->source_buffer, 1, BUFFER_SIZE);

View file

@ -29,7 +29,6 @@
#include <spa/node.h>
#include <spa/loop.h>
#include <spa/video/format-utils.h>
#include <spa/format-builder.h>
#include <lib/debug.h>
@ -187,9 +186,12 @@ static inline void type_init(struct spa_type_map *map)
static void do_static_struct(struct spa_type_map *map)
{
struct _test_format {
struct spa_format fmt;
struct spa_pod_object fmt;
struct {
struct spa_pod_id media_type SPA_ALIGNED(8);
struct spa_pod_id media_subtype SPA_ALIGNED(8);
struct spa_pod_prop prop_format SPA_ALIGNED(8);
struct {
uint32_t def_format;
@ -211,9 +213,12 @@ static void do_static_struct(struct spa_type_map *map)
} framerate_vals;
} props;
} test_format = {
SPA_FORMAT_INIT(sizeof(test_format.props) + sizeof(struct spa_format_body),
type.format, type.media_type.video, type.media_subtype.raw),
SPA_POD_OBJECT_INIT(sizeof(test_format.props) + sizeof(struct spa_pod_object_body),
0, type.format),
{
SPA_POD_ID_INIT(type.media_type.video),
SPA_POD_ID_INIT(type.media_subtype.raw),
SPA_POD_PROP_INIT(sizeof(test_format.props.format_vals) +
sizeof(struct spa_pod_prop_body),
type.format_video.format,
@ -245,23 +250,23 @@ static void do_static_struct(struct spa_type_map *map)
}
};
spa_debug_pod(&test_format.fmt.pod);
spa_debug_format(&test_format.fmt);
spa_debug_pod(&test_format.fmt.pod, 0);
spa_debug_pod(&test_format.fmt.pod, SPA_DEBUG_FLAG_FORMAT);
{
uint32_t format = -1;
int res;
struct spa_fraction frac = { -1, -1 };
res = spa_format_parse(&test_format.fmt,
res = spa_pod_object_parse(&test_format.fmt,
":",type.format_video.format, "I", &format,
":",type.format_video.framerate, "F", &frac, NULL);
printf("%d format %d num %d denom %d\n", res, format, frac.num, frac.denom);
spa_format_fixate(&test_format.fmt);
spa_pod_object_fixate(&test_format.fmt);
res = spa_format_parse(&test_format.fmt,
res = spa_pod_object_parse(&test_format.fmt,
":",type.format_video.format, "I", &format,
":",type.format_video.framerate, "F", &frac, NULL);
@ -275,7 +280,7 @@ int main(int argc, char *argv[])
struct spa_pod_builder b = { NULL, };
struct spa_pod_frame f[2];
uint8_t buffer[1024];
struct spa_format *fmt;
struct spa_pod_object *fmt;
struct spa_type_map *map = &default_map.map;
type_init(map);
@ -283,10 +288,12 @@ int main(int argc, char *argv[])
spa_pod_builder_init(&b, buffer, sizeof(buffer));
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);
fmt = SPA_MEMBER(buffer, spa_pod_builder_push_object(&b, &f[0], 0, type.format),
struct spa_pod_object);
spa_pod_builder_id(&b, type.media_type.video);
spa_pod_builder_id(&b, type.media_subtype.raw);
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);
@ -312,13 +319,14 @@ int main(int argc, char *argv[])
spa_pod_builder_pop(&b, &f[0]);
spa_debug_pod(&fmt->pod);
spa_debug_pod(&fmt->pod, 0);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
fmt = spa_pod_builder_format(&b,
type.format,
type.media_type.video, type.media_subtype.raw,
fmt = spa_pod_builder_object(&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,
@ -329,8 +337,8 @@ int main(int argc, char *argv[])
2, &SPA_FRACTION(0,1),
&SPA_FRACTION(INT32_MAX,1));
spa_debug_pod(&fmt->pod);
spa_debug_format(fmt);
spa_debug_pod(&fmt->pod, 0);
spa_debug_pod(&fmt->pod, SPA_DEBUG_FLAG_FORMAT);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
@ -359,8 +367,8 @@ int main(int argc, char *argv[])
&SPA_FRACTION(INT32_MAX,1),
">", NULL);
spa_debug_pod(&fmt->pod);
spa_debug_format(fmt);
spa_debug_pod(&fmt->pod, 0);
spa_debug_pod(&fmt->pod, SPA_DEBUG_FLAG_FORMAT);
do_static_struct(map);

View file

@ -89,11 +89,11 @@ int main(int argc, char *argv[])
spa_pod_builder_pop(&b, &frame[0]);
obj = SPA_POD_BUILDER_DEREF(&b, frame[0].ref, struct spa_pod);
spa_debug_pod(obj);
spa_debug_pod(obj, 0);
struct spa_pod_prop *p = spa_pod_object_find_prop((struct spa_pod_object *) obj, 4);
printf("%d %d\n", p->body.key, p->body.flags);
spa_debug_pod(&p->body.value);
spa_debug_pod(&p->body.value, 0);
obj = SPA_POD_BUILDER_DEREF(&b, frame[2].ref, struct spa_pod);

View file

@ -53,7 +53,7 @@ int main(int argc, char *argv[])
2, &SPA_FRACTION(0,1),
&SPA_FRACTION(INT32_MAX, 1),
">", NULL);
spa_debug_pod(fmt);
spa_debug_pod(fmt, 0);
spa_pod_parser_pod(&prs, fmt);
res = spa_pod_parser_get(&prs,
@ -68,7 +68,7 @@ int main(int argc, char *argv[])
printf("media-type:%d media-subtype:%d\n", media_type, media_subtype);
printf("framerate:\n");
if (pod)
spa_debug_pod(pod);
spa_debug_pod(pod, 0);
printf("format: %d\n", fmt_value);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
@ -77,7 +77,7 @@ int main(int argc, char *argv[])
" P", NULL,
" [ i", 44, "i",45,"]"
">", NULL);
spa_debug_pod(pod);
spa_debug_pod(pod, 0);
spa_pod_parser_pod(&prs, pod);
res = spa_pod_parser_get(&prs,

View file

@ -32,7 +32,6 @@
#include <spa/type-map-impl.h>
#include <spa/audio/format-utils.h>
#include <spa/format-utils.h>
#include <spa/format-builder.h>
#include <lib/debug.h>
#include <lib/props.h>
@ -49,6 +48,7 @@ struct type {
uint32_t props_volume;
uint32_t props_min_latency;
uint32_t props_live;
struct spa_type_param param;
struct spa_type_meta meta;
struct spa_type_data data;
struct spa_type_media_type media_type;
@ -69,6 +69,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
type->props_volume = spa_type_map_get_id(map, SPA_TYPE_PROPS__volume);
type->props_min_latency = spa_type_map_get_id(map, SPA_TYPE_PROPS__minLatency);
type->props_live = spa_type_map_get_id(map, SPA_TYPE_PROPS__live);
spa_type_param_map(map, &type->param);
spa_type_meta_map(map, &type->meta);
spa_type_data_map(map, &type->data);
spa_type_media_type_map(map, &type->media_type);
@ -275,7 +276,7 @@ do_invoke(struct spa_loop *loop,
static int make_nodes(struct data *data, const char *device)
{
int res;
struct spa_props *props;
struct spa_pod_object *props;
struct spa_pod_builder b = { 0 };
uint8_t buffer[128];
@ -287,12 +288,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));
props = spa_pod_builder_props(&b,
data->type.props,
props = spa_pod_builder_object(&b,
0, 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)
if ((res = spa_node_set_param(data->sink, data->type.param.idProps, 0, props)) < 0)
printf("got set_props error %d\n", res);
if ((res = make_node(data, &data->source,
@ -303,11 +304,11 @@ static int make_nodes(struct data *data, const char *device)
}
spa_pod_builder_init(&b, buffer, sizeof(buffer));
props = spa_pod_builder_props(&b,
data->type.props,
props = spa_pod_builder_object(&b,
0, data->type.props,
":", data->type.props_live, "b", false);
if ((res = spa_node_set_props(data->source, props)) < 0)
if ((res = spa_node_set_param(data->source, data->type.param.idProps, 0, props)) < 0)
printf("got set_props error %d\n", res);
return res;
}
@ -315,27 +316,36 @@ static int make_nodes(struct data *data, const char *device)
static int negotiate_formats(struct data *data)
{
int res;
struct spa_format *format, *filter;
uint32_t state = 0;
struct spa_pod_object *format, *filter;
uint32_t state = 0, ref;
struct spa_pod_builder b = { 0 };
uint8_t buffer[256];
uint8_t buffer[4096];
spa_pod_builder_init(&b, buffer, sizeof(buffer));
filter = spa_pod_builder_format(&b,
data->type.format,
data->type.media_type.audio, data->type.media_subtype.raw,
filter = spa_pod_builder_object(&b,
0, data->type.format,
"I", data->type.media_type.audio,
"I", 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,
state)) < 0)
ref = b.offset;
if ((res = spa_node_port_enum_params(data->sink,
SPA_DIRECTION_INPUT, 0,
data->type.param.idEnumFormat, &state,
filter, &b)) < 0)
return res;
format = SPA_POD_BUILDER_DEREF(&b, ref, struct spa_pod_object);
if ((res = spa_node_port_set_format(data->sink, SPA_DIRECTION_INPUT, 0, 0, format)) < 0)
if ((res = spa_node_port_set_param(data->sink,
SPA_DIRECTION_INPUT, 0,
data->type.param.idFormat, 0,
format)) < 0)
return res;
data->source_sink_io[0] = SPA_PORT_IO_INIT;
@ -343,7 +353,10 @@ static int negotiate_formats(struct data *data)
spa_node_port_set_io(data->source, SPA_DIRECTION_OUTPUT, 0, &data->source_sink_io[0]);
spa_node_port_set_io(data->sink, SPA_DIRECTION_INPUT, 0, &data->source_sink_io[0]);
if ((res = spa_node_port_set_format(data->source, SPA_DIRECTION_OUTPUT, 0, 0, format)) < 0)
if ((res = spa_node_port_set_param(data->source,
SPA_DIRECTION_OUTPUT, 0,
data->type.param.idFormat, 0,
format)) < 0)
return res;
init_buffer(data, data->source_buffers, data->source_buffer, 1, BUFFER_SIZE);

View file

@ -33,7 +33,6 @@
#include <spa/node.h>
#include <spa/loop.h>
#include <spa/video/format-utils.h>
#include <spa/format-builder.h>
#include <lib/debug.h>
#include <lib/props.h>
@ -46,6 +45,7 @@ struct type {
uint32_t format;
uint32_t props_device;
uint32_t SDL_Texture;
struct spa_type_param param;
struct spa_type_meta meta;
struct spa_type_data data;
struct spa_type_media_type media_type;
@ -63,6 +63,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
type->format = spa_type_map_get_id(map, SPA_TYPE__Format);
type->props_device = spa_type_map_get_id(map, SPA_TYPE_PROPS__device);
type->SDL_Texture = spa_type_map_get_id(map, SPA_TYPE_POINTER_BASE "SDL_Texture");
spa_type_param_map(map, &type->param);
spa_type_meta_map(map, &type->meta);
spa_type_data_map(map, &type->data);
spa_type_media_type_map(map, &type->media_type);
@ -297,7 +298,7 @@ do_invoke(struct spa_loop *loop,
static int make_nodes(struct data *data, const char *device)
{
int res;
struct spa_props *props;
struct spa_pod_object *props;
struct spa_pod_builder b = { 0 };
uint8_t buffer[256];
@ -311,11 +312,11 @@ 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));
props = spa_pod_builder_props(&b,
data->type.props,
props = spa_pod_builder_object(&b,
0, data->type.props,
":", data->type.props_device, "s", device ? device : "/dev/video0");
if ((res = spa_node_set_props(data->source, props)) < 0)
if ((res = spa_node_set_param(data->source, data->type.param.idProps, 0, props)) < 0)
printf("got set_props error %d\n", res);
return res;
@ -386,7 +387,7 @@ static int negotiate_formats(struct data *data)
{
int res;
const struct spa_port_info *info;
struct spa_format *format;
struct spa_pod_object *format;
uint8_t buffer[256];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
@ -404,15 +405,19 @@ static int negotiate_formats(struct data *data)
return res;
#else
format = spa_pod_builder_format(&b,
data->type.format,
data->type.media_type.video, data->type.media_subtype.raw,
format = spa_pod_builder_object(&b,
0, data->type.format,
"I", data->type.media_type.video,
"I", data->type.media_subtype.raw,
":", data->type.format_video.format, "I", data->type.video_format.YUY2,
":", data->type.format_video.size, "R", &SPA_RECTANGLE(320, 240),
":", data->type.format_video.framerate, "F", &SPA_FRACTION(25,1));
#endif
if ((res = spa_node_port_set_format(data->source, SPA_DIRECTION_OUTPUT, 0, 0, format)) < 0)
if ((res = spa_node_port_set_param(data->source,
SPA_DIRECTION_OUTPUT, 0,
data->type.param.idFormat, 0,
(struct spa_pod_object*)format)) < 0)
return res;
if ((res = spa_node_port_get_info(data->source, SPA_DIRECTION_OUTPUT, 0, &info)) < 0)

View file

@ -37,6 +37,7 @@ static SPA_LOG_IMPL(default_log);
struct type {
uint32_t node;
uint32_t clock;
struct spa_type_param param;
};
struct data {
@ -54,40 +55,51 @@ inspect_port(struct data *data, struct spa_node *node, enum spa_direction direct
uint32_t port_id)
{
int res;
struct spa_format *format;
uint32_t index;
uint32_t idx1, idx2;
uint32_t buffer[4096];
struct spa_pod_builder b = { 0 };
for (index = 0;; index++) {
if ((res =
spa_node_port_enum_formats(node, direction, port_id, &format, NULL,
index)) < 0) {
for (idx1 = 0;;) {
struct spa_pod_object *param;
uint32_t id;
spa_pod_builder_init(&b, buffer, sizeof(buffer));
if ((res = spa_node_port_enum_params(node,
direction, port_id,
data->type.param.idList, &idx1,
NULL, &b)) < 0) {
if (res != SPA_RESULT_ENUM_END)
printf("got error %d\n", res);
break;
}
if (format)
spa_debug_format(format);
}
param = SPA_POD_BUILDER_DEREF(&b, 0, struct spa_pod_object);
spa_debug_pod(&param->pod, 0);
spa_pod_object_parse(param,
":", data->type.param.listId, "I", &id,
NULL);
for (index = 0;; index++) {
struct spa_param *param;
if ((res = spa_node_port_enum_params(node, direction, port_id, index, &param)) < 0) {
if (res != SPA_RESULT_ENUM_END)
printf("port_enum_params error: %d\n", res);
break;
for (idx2 = 0;;) {
spa_pod_builder_init(&b, buffer, sizeof(buffer));
if ((res = spa_node_port_enum_params(node,
direction, port_id,
id, &idx2,
NULL, &b)) < 0) {
if (res != SPA_RESULT_ENUM_END)
printf("got error %d\n", res);
break;
}
param = SPA_POD_BUILDER_DEREF(&b, 0, struct spa_pod_object);
spa_debug_pod(&param->pod, 0);
}
spa_debug_param(param);
}
}
static void inspect_node(struct data *data, struct spa_node *node)
{
int res;
uint32_t i, n_input, max_input, n_output, max_output;
uint32_t i, n_input, max_input, n_output, max_output, index = 0;
uint32_t *in_ports, *out_ports;
struct spa_props *props;
printf("node info:\n");
if (node->info)
@ -95,10 +107,19 @@ static void inspect_node(struct data *data, struct spa_node *node)
else
printf(" none\n");
if ((res = spa_node_get_props(node, &props)) < 0)
printf("can't get properties: %d\n", res);
else
spa_debug_props(props);
for (index = 0;;) {
uint8_t buf[2048];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
struct spa_pod_object *param;
if ((res = spa_node_enum_params(node, SPA_ID_INVALID, &index, NULL, &b)) < 0) {
if (res != SPA_RESULT_ENUM_END)
printf("enum_params error: %d\n", res);
break;
}
param = SPA_POD_BUILDER_DEREF(&b, 0, struct spa_pod_object);
spa_debug_pod(&param->pod, 0);
}
if ((res = spa_node_get_n_ports(node, &n_input, &max_input, &n_output, &max_output)) < 0) {
printf("can't get n_ports: %d\n", res);
@ -224,6 +245,7 @@ int main(int argc, char *argv[])
data.type.node = spa_type_map_get_id(data.map, SPA_TYPE__Node);
data.type.clock = spa_type_map_get_id(data.map, SPA_TYPE__Clock);
spa_type_param_map(data.map, &data.type.param);
if ((handle = dlopen(argv[1], RTLD_NOW)) == NULL) {
printf("can't load %s\n", argv[1]);

View file

@ -60,7 +60,7 @@ struct data {
static void inspect_item(struct data *data, struct spa_monitor_item *item)
{
spa_debug_pod(&item->object.pod);
spa_debug_pod(&item->object.pod, 0);
}
static void on_monitor_event(void *_data, struct spa_event *event)