spa: make events and commands as objects

So we can serialize and introspect them more easily
This commit is contained in:
Wim Taymans 2017-03-15 16:21:05 +01:00
parent 4c4c0f2a7f
commit c951264fff
26 changed files with 423 additions and 327 deletions

View file

@ -130,8 +130,10 @@ typedef void (*SpaNotify) (void *data);
#ifdef __GNUC__
# define SPA_PRINTF_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
# define SPA_ALIGNED(align) __attribute__ ((aligned (align)))
#else
# define SPA_PRINTF_FUNC(fmt, arg1)
# define SPA_ALIGNED(align)
#endif
#define SPA_ROUND_UP_N(num,align) ((((num) + ((align) - 1)) & ~((align) - 1)))

View file

@ -49,11 +49,25 @@ typedef enum {
SPA_NODE_COMMAND_CLOCK_UPDATE
} SpaNodeCommandType;
#define SPA_NODE_COMMAND_TYPE(cmd) ((cmd)->body.body.type)
typedef struct {
SpaPODObjectBody body;
} SpaNodeCommandBody;
struct _SpaNodeCommand {
SpaNodeCommandType type;
uint32_t size;
SpaPOD pod;
SpaNodeCommandBody body;
};
#define SPA_NODE_COMMAND_INIT(type) \
{ { sizeof (SpaNodeCommandBody), SPA_POD_TYPE_OBJECT }, \
{ { 0, type } } } \
#define SPA_NODE_COMMAND_INIT_COMPLEX(size,type,...) \
{ { size, SPA_POD_TYPE_OBJECT }, \
{ { 0, type }, __VA_ARGS__ } } \
/**
* SpaNodeCommandClockUpdate:
* @change_mask: marks which fields are updated
@ -67,23 +81,41 @@ struct _SpaNodeCommand {
* @state: the new clock state, when @change_mask = 1<<2
*/
typedef struct {
SpaNodeCommand command;
SpaPODObjectBody body;
#define SPA_NODE_COMMAND_CLOCK_UPDATE_TIME (1 << 0)
#define SPA_NODE_COMMAND_CLOCK_UPDATE_SCALE (1 << 1)
#define SPA_NODE_COMMAND_CLOCK_UPDATE_STATE (1 << 2)
#define SPA_NODE_COMMAND_CLOCK_UPDATE_LATENCY (1 << 3)
uint32_t change_mask;
int32_t rate;
int64_t ticks;
int64_t monotonic_time;
int64_t offset;
int32_t scale;
SpaClockState state;
SpaPODInt change_mask SPA_ALIGNED (8);
SpaPODInt rate SPA_ALIGNED (8);
SpaPODLong ticks SPA_ALIGNED (8);
SpaPODLong monotonic_time SPA_ALIGNED (8);
SpaPODLong offset SPA_ALIGNED (8);
SpaPODInt scale SPA_ALIGNED (8);
SpaPODInt state SPA_ALIGNED (8);
#define SPA_NODE_COMMAND_CLOCK_UPDATE_FLAG_LIVE (1 << 0)
uint32_t flags;
int64_t latency;
SpaPODInt flags SPA_ALIGNED (8);
SpaPODLong latency SPA_ALIGNED (8);
} SpaNodeCommandClockUpdateBody;
typedef struct {
SpaPOD pod;
SpaNodeCommandClockUpdateBody body;
} SpaNodeCommandClockUpdate;
#define SPA_NODE_COMMAND_CLOCK_UPDATE_INIT(change_mask,rate,ticks,monotonic_time,offset,scale,state,flags,latency) \
SPA_NODE_COMMAND_INIT_COMPLEX (sizeof (SpaNodeCommandClockUpdateBody), \
SPA_NODE_COMMAND_CLOCK_UPDATE, \
SPA_POD_INT_INIT (change_mask), \
SPA_POD_INT_INIT (rate), \
SPA_POD_LONG_INIT (ticks), \
SPA_POD_LONG_INIT (monotonic_time), \
SPA_POD_LONG_INIT (offset), \
SPA_POD_INT_INIT (scale), \
SPA_POD_INT_INIT (state), \
SPA_POD_INT_INIT (flags), \
SPA_POD_LONG_INIT (latency))
#ifdef __cplusplus
} /* extern "C" */
#endif

View file

@ -43,55 +43,103 @@ typedef struct _SpaNodeEvent SpaNodeEvent;
/**
* SpaEventType:
* @SPA_NODE_EVENT_TYPE_INVALID: invalid event, should be ignored
* @SPA_NODE_EVENT_TYPE_ASYNC_COMPLETE: an async operation completed
* @SPA_NODE_EVENT_TYPE_HAVE_OUTPUT: emited when an async node has output that can be pulled
* @SPA_NODE_EVENT_TYPE_NEED_INPUT: emited when more data can be pushed to an async node
* @SPA_NODE_EVENT_TYPE_REUSE_BUFFER: emited when a buffer can be reused
* @SPA_NODE_EVENT_TYPE_ERROR: emited when error occured
* @SPA_NODE_EVENT_TYPE_BUFFERING: emited when buffering is in progress
* @SPA_NODE_EVENT_TYPE_REQUEST_REFRESH: emited when a keyframe refresh is needed
* @SPA_NODE_EVENT_TYPE_REQUEST_CLOCK_UPDATE: the element asks for a clock update
* @SPA_NODE_EVENT_INVALID: invalid event, should be ignored
* @SPA_NODE_EVENT_ASYNC_COMPLETE: an async operation completed
* @SPA_NODE_EVENT_HAVE_OUTPUT: emited when an async node has output that can be pulled
* @SPA_NODE_EVENT_NEED_INPUT: emited when more data can be pushed to an async node
* @SPA_NODE_EVENT_REUSE_BUFFER: emited when a buffer can be reused
* @SPA_NODE_EVENT_ERROR: emited when error occured
* @SPA_NODE_EVENT_BUFFERING: emited when buffering is in progress
* @SPA_NODE_EVENT_REQUEST_REFRESH: emited when a keyframe refresh is needed
* @SPA_NODE_EVENT_REQUEST_CLOCK_UPDATE: the element asks for a clock update
*/
typedef enum {
SPA_NODE_EVENT_TYPE_INVALID = 0,
SPA_NODE_EVENT_TYPE_ASYNC_COMPLETE,
SPA_NODE_EVENT_TYPE_HAVE_OUTPUT,
SPA_NODE_EVENT_TYPE_NEED_INPUT,
SPA_NODE_EVENT_TYPE_REUSE_BUFFER,
SPA_NODE_EVENT_TYPE_ERROR,
SPA_NODE_EVENT_TYPE_BUFFERING,
SPA_NODE_EVENT_TYPE_REQUEST_REFRESH,
SPA_NODE_EVENT_TYPE_REQUEST_CLOCK_UPDATE,
SPA_NODE_EVENT_INVALID = 0,
SPA_NODE_EVENT_ASYNC_COMPLETE,
SPA_NODE_EVENT_HAVE_OUTPUT,
SPA_NODE_EVENT_NEED_INPUT,
SPA_NODE_EVENT_REUSE_BUFFER,
SPA_NODE_EVENT_ERROR,
SPA_NODE_EVENT_BUFFERING,
SPA_NODE_EVENT_REQUEST_REFRESH,
SPA_NODE_EVENT_REQUEST_CLOCK_UPDATE,
} SpaNodeEventType;
#define SPA_NODE_EVENT_TYPE(ev) ((ev)->body.body.type)
typedef struct {
SpaPODObjectBody body;
} SpaNodeEventBody;
struct _SpaNodeEvent {
SpaNodeEventType type;
uint32_t size;
SpaPOD pod;
SpaNodeEventBody body;
};
#define SPA_NODE_EVENT_INIT(type) \
{ { sizeof (SpaNodeEventBody), SPA_POD_TYPE_OBJECT }, \
{ { 0, type } } } \
#define SPA_NODE_EVENT_INIT_COMPLEX(size,type,...) \
{ { size, SPA_POD_TYPE_OBJECT }, \
{ { 0, type }, __VA_ARGS__ } } \
typedef struct {
SpaNodeEvent event;
uint32_t seq;
SpaResult res;
SpaPODObjectBody body;
SpaPODInt seq SPA_ALIGNED (8);
SpaPODInt res SPA_ALIGNED (8);
} SpaNodeEventAsyncCompleteBody;
typedef struct {
SpaPOD pod;
SpaNodeEventAsyncCompleteBody body;
} SpaNodeEventAsyncComplete;
typedef struct {
SpaNodeEvent event;
uint32_t port_id;
uint32_t buffer_id;
} SpaNodeEventReuseBuffer;
#define SPA_NODE_EVENT_ASYNC_COMPLETE_INIT(seq,res) \
SPA_NODE_EVENT_INIT_COMPLEX (sizeof (SpaNodeEventAsyncCompleteBody), \
SPA_NODE_EVENT_ASYNC_COMPLETE, \
SPA_POD_INT_INIT (seq), \
SPA_POD_INT_INIT (res))
typedef struct {
SpaNodeEvent event;
SpaPODObjectBody body;
SpaPODInt port_id;
SpaPODInt buffer_id;
} SpaNodeEventReuseBufferBody;
typedef struct {
SpaPOD pod;
SpaNodeEventReuseBufferBody body;
} SpaNodeEventReuseBuffer;
#define SPA_NODE_EVENT_REUSE_BUFFER_INIT(port_id,buffer_id) \
SPA_NODE_EVENT_INIT_COMPLEX (sizeof (SpaNodeEventReuseBufferBody), \
SPA_NODE_EVENT_REUSE_BUFFER, \
SPA_POD_INT_INIT (port_id), \
SPA_POD_INT_INIT (buffer_id))
typedef struct {
SpaPODObjectBody body;
#define SPA_NODE_EVENT_REQUEST_CLOCK_UPDATE_TIME (1 << 0)
#define SPA_NODE_EVENT_REQUEST_CLOCK_UPDATE_SCALE (1 << 1)
#define SPA_NODE_EVENT_REQUEST_CLOCK_UPDATE_STATE (1 << 2)
uint32_t update_mask;
int64_t timestamp;
int64_t offset;
SpaPODInt update_mask SPA_ALIGNED (8);
SpaPODLong timestamp SPA_ALIGNED (8);
SpaPODLong offset SPA_ALIGNED (8);
} SpaNodeEventRequestClockUpdateBody;
typedef struct {
SpaPOD pod;
SpaNodeEventRequestClockUpdateBody body;
} SpaNodeEventRequestClockUpdate;
#define SPA_NODE_EVENT_REQUEST_CLOCK_UPDATE_INIT(update_mask,timestamp,offset) \
SPA_NODE_EVENT_INIT_COMPLEX (sizeof (SpaNodeEventRequestClockUpdateBody), \
SPA_NODE_EVENT_REQUEST_CLOCK_UPDATE, \
SPA_POD_INT_INIT (update_mask), \
SPA_POD_LONG_INIT (timestamp), \
SPA_POD_LONG_INIT (offset))
#ifdef __cplusplus
} /* extern "C" */
#endif

View file

@ -147,52 +147,66 @@ spa_pod_builder_primitive (SpaPODBuilder *builder, const SpaPOD *p)
return ref;
}
#define SPA_POD_BOOL_INIT(val) { { sizeof (uint32_t), SPA_POD_TYPE_BOOL }, val ? 1 : 0 }
static inline uint32_t
spa_pod_builder_bool (SpaPODBuilder *builder, bool val)
{
const SpaPODBool p = { { sizeof (uint32_t), SPA_POD_TYPE_BOOL }, val ? 1 : 0 };
const SpaPODBool p = SPA_POD_BOOL_INIT (val);
return spa_pod_builder_primitive (builder, &p.pod);
}
#define SPA_POD_URI_INIT(val) { { sizeof (uint32_t), SPA_POD_TYPE_URI }, val }
static inline uint32_t
spa_pod_builder_uri (SpaPODBuilder *builder, uint32_t val)
{
const SpaPODURI p = { { sizeof (uint32_t), SPA_POD_TYPE_URI }, val };
const SpaPODURI p = SPA_POD_URI_INIT (val);
return spa_pod_builder_primitive (builder, &p.pod);
}
#define SPA_POD_INT_INIT(val) { { sizeof (uint32_t), SPA_POD_TYPE_INT }, val }
static inline uint32_t
spa_pod_builder_int (SpaPODBuilder *builder, int32_t val)
{
const SpaPODInt p = { { sizeof (uint32_t), SPA_POD_TYPE_INT }, val };
const SpaPODInt p = SPA_POD_INT_INIT (val);
return spa_pod_builder_primitive (builder, &p.pod);
}
#define SPA_POD_LONG_INIT(val) { { sizeof (uint64_t), SPA_POD_TYPE_LONG }, val }
static inline uint32_t
spa_pod_builder_long (SpaPODBuilder *builder, int64_t val)
{
const SpaPODLong p = { { sizeof (val), SPA_POD_TYPE_LONG }, val };
const SpaPODLong p = SPA_POD_LONG_INIT (val);
return spa_pod_builder_primitive (builder, &p.pod);
}
#define SPA_POD_FLOAT_INIT(val) { { sizeof (float), SPA_POD_TYPE_FLOAT }, val }
static inline uint32_t
spa_pod_builder_float (SpaPODBuilder *builder, float val)
{
const SpaPODFloat p = { { sizeof (val), SPA_POD_TYPE_FLOAT }, val };
const SpaPODFloat p = SPA_POD_FLOAT_INIT (val);
return spa_pod_builder_primitive (builder, &p.pod);
}
#define SPA_POD_DOUBLE_INIT(val) { { sizeof (double), SPA_POD_TYPE_DOUBLE }, val }
static inline uint32_t
spa_pod_builder_double (SpaPODBuilder *builder, double val)
{
const SpaPODDouble p = { { sizeof (val), SPA_POD_TYPE_DOUBLE }, val };
const SpaPODDouble p = SPA_POD_DOUBLE_INIT (val);
return spa_pod_builder_primitive (builder, &p.pod);
}
#define SPA_POD_STRING_INIT(len) { { len, SPA_POD_TYPE_STRING } }
static inline uint32_t
spa_pod_builder_string_len (SpaPODBuilder *builder, const char *str, uint32_t len)
{
const SpaPODString p = { { len, SPA_POD_TYPE_STRING } };
const SpaPODString p = SPA_POD_STRING_INIT (len);
uint32_t ref = spa_pod_builder_raw (builder, &p, sizeof (p));
if (spa_pod_builder_raw_padded (builder, str, len) == -1)
ref = -1;
@ -206,27 +220,33 @@ spa_pod_builder_string (SpaPODBuilder *builder, const char *str)
return spa_pod_builder_string_len (builder, str ? str : "", len + 1);
}
#define SPA_POD_BYTES_INIT(len) { { len, SPA_POD_TYPE_BYTES } }
static inline uint32_t
spa_pod_builder_bytes (SpaPODBuilder *builder, const void *bytes, uint32_t len)
{
const SpaPODBytes p = { { len, SPA_POD_TYPE_BYTES } };
const SpaPODBytes p = SPA_POD_BYTES_INIT (len);
uint32_t ref = spa_pod_builder_raw (builder, &p, sizeof (p));
if (spa_pod_builder_raw_padded (builder, bytes, len) == -1)
ref = -1;
return ref;
}
#define SPA_POD_RECTANGLE_INIT(width,height) { { sizeof (SpaRectangle), SPA_POD_TYPE_RECTANGLE }, { width, height } }
static inline uint32_t
spa_pod_builder_rectangle (SpaPODBuilder *builder, uint32_t width, uint32_t height)
{
const SpaPODRectangle p = { { sizeof (SpaRectangle), SPA_POD_TYPE_RECTANGLE }, { width, height } };
const SpaPODRectangle p = SPA_POD_RECTANGLE_INIT (width, height);
return spa_pod_builder_primitive (builder, &p.pod);
}
#define SPA_POD_FRACTION_INIT(num,denom) { { sizeof (SpaFraction), SPA_POD_TYPE_FRACTION }, { num, denom } }
static inline uint32_t
spa_pod_builder_fraction (SpaPODBuilder *builder, uint32_t num, uint32_t denom)
{
const SpaPODFraction p = { { sizeof (SpaFraction), SPA_POD_TYPE_FRACTION }, { num, denom } };
const SpaPODFraction p = SPA_POD_FRACTION_INIT (num, denom);
return spa_pod_builder_primitive (builder, &p.pod);
}
@ -247,31 +267,35 @@ spa_pod_builder_array (SpaPODBuilder *builder,
const void *elems)
{
const SpaPODArray p = {
{ (uint32_t)(sizeof (SpaPODArrayBody) + n_elems * child_size), SPA_POD_TYPE_ARRAY },
{ sizeof (SpaPODArrayBody) + n_elems * child_size, SPA_POD_TYPE_ARRAY },
{ { child_size, child_type } }
};
uint32_t ref = spa_pod_builder_raw_padded (builder, &p, sizeof(p));
uint32_t ref = spa_pod_builder_raw (builder, &p, sizeof(p));
if (spa_pod_builder_raw_padded (builder, elems, child_size * n_elems) == -1)
ref = -1;
return ref;
}
#define SPA_POD_STRUCT_INIT(size) { { size, SPA_POD_TYPE_STRUCT } }
static inline uint32_t
spa_pod_builder_push_struct (SpaPODBuilder *builder,
SpaPODFrame *frame)
{
const SpaPODStruct p = { { 0, SPA_POD_TYPE_STRUCT } };
const SpaPODStruct p = SPA_POD_STRUCT_INIT (0);
return spa_pod_builder_push (builder, frame, &p.pod,
spa_pod_builder_raw (builder, &p, sizeof(p)));
}
#define SPA_POD_OBJECT_INIT(size,id,type) { { size, SPA_POD_TYPE_OBJECT }, { id, type } }
static inline uint32_t
spa_pod_builder_push_object (SpaPODBuilder *builder,
SpaPODFrame *frame,
uint32_t id,
uint32_t type)
{
const SpaPODObject p = { { sizeof (SpaPODObjectBody), SPA_POD_TYPE_OBJECT }, { id, type } };
const SpaPODObject p = SPA_POD_OBJECT_INIT (sizeof (SpaPODObjectBody), id, type);
return spa_pod_builder_push (builder, frame, &p.pod,
spa_pod_builder_raw (builder, &p, sizeof(p)));
}

View file

@ -80,6 +80,7 @@ spa_pod_iter_pod (SpaPODIter *iter, SpaPOD *pod)
size = SPA_POD_CONTENTS_SIZE (SpaPODObject, pod);
break;
default:
spa_pod_iter_contents (iter, NULL, 0);
return false;
}
spa_pod_iter_contents (iter, data, size);
@ -101,6 +102,15 @@ spa_pod_iter_next (SpaPODIter *iter)
return res;
}
static inline SpaPOD *
spa_pod_iter_first (SpaPODIter *iter, SpaPOD *pod)
{
if (!spa_pod_iter_pod (iter, pod) ||
!spa_pod_iter_has_next (iter))
return false;
return spa_pod_iter_next (iter);
}
static inline bool
spa_pod_iter_getv (SpaPODIter *iter,
uint32_t type,

View file

@ -112,7 +112,7 @@ typedef struct {
typedef struct {
SpaPOD pod;
/* array of uint32_t follows with the bitmap */
/* array of uint8_t follows with the bitmap */
} SpaPODBitmap;
typedef struct {
@ -182,9 +182,9 @@ typedef struct {
SPA_POD_FOREACH(SPA_MEMBER ((pod), (offset), SpaPOD),SPA_POD_SIZE (pod),iter)
#define SPA_POD_OBJECT_BODY_FOREACH(body, size, iter) \
for ((iter) = SPA_MEMBER ((body), sizeof (SpaPODObjectBody), SpaPODProp); \
(iter) < SPA_MEMBER ((body), (size), SpaPODProp); \
(iter) = SPA_MEMBER ((iter), SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), SpaPODProp))
for ((iter) = SPA_MEMBER ((body), sizeof (SpaPODObjectBody), SpaPOD); \
(iter) < SPA_MEMBER ((body), (size), SpaPOD); \
(iter) = SPA_MEMBER ((iter), SPA_ROUND_UP_N (SPA_POD_SIZE (iter), 8), SpaPOD))
#define SPA_POD_OBJECT_FOREACH(obj, iter) \
SPA_POD_OBJECT_BODY_FOREACH(&obj->body, SPA_POD_BODY_SIZE(obj), iter)