mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	Add POD helper objects
POD (plain old data) objects are similar to LV2 Atoms and allows storage and construction of datastructures in memory or on the stack. They can be copied with a simple memcpy. The idea is to use this to construct the network messages and to replace the structures used for describing formats and properties.
This commit is contained in:
		
							parent
							
								
									922997175d
								
							
						
					
					
						commit
						7fc73953cd
					
				
					 8 changed files with 657 additions and 11 deletions
				
			
		| 
						 | 
				
			
			@ -88,6 +88,16 @@ typedef enum {
 | 
			
		|||
  SPA_DIRECTION_OUTPUT,
 | 
			
		||||
} SpaDirection;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  uint32_t width;
 | 
			
		||||
  uint32_t height;
 | 
			
		||||
} SpaRectangle;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  uint32_t num;
 | 
			
		||||
  uint32_t denom;
 | 
			
		||||
} SpaFraction;
 | 
			
		||||
 | 
			
		||||
typedef void (*SpaNotify) (void *data);
 | 
			
		||||
 | 
			
		||||
#define SPA_N_ELEMENTS(arr)  (sizeof (arr) / sizeof ((arr)[0]))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -98,6 +98,8 @@ typedef enum {
 | 
			
		|||
} SpaFormatProps;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static inline SpaResult
 | 
			
		||||
spa_format_fixate (SpaFormat *format)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,8 @@ spa_headers = [
 | 
			
		|||
  'node-event.h',
 | 
			
		||||
  'node.h',
 | 
			
		||||
  'plugin.h',
 | 
			
		||||
  'pod.h',
 | 
			
		||||
  'pod-builder.h',
 | 
			
		||||
  'port.h',
 | 
			
		||||
  'props.h',
 | 
			
		||||
  'ringbuffer.h'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										264
									
								
								spa/include/spa/pod-builder.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								spa/include/spa/pod-builder.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,264 @@
 | 
			
		|||
/* Simple Plugin API
 | 
			
		||||
 * Copyright (C) 2017 Wim Taymans <wim.taymans@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Library General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Library General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Library General Public
 | 
			
		||||
 * License along with this library; if not, write to the
 | 
			
		||||
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 | 
			
		||||
 * Boston, MA 02110-1301, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SPA_POD_BUILDER_H__
 | 
			
		||||
#define __SPA_POD_BUILDER_H__
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct _SpaPodFrame {
 | 
			
		||||
  struct _SpaPodFrame *parent;
 | 
			
		||||
  off_t                offset;
 | 
			
		||||
} SpaPODFrame;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  void        *data;
 | 
			
		||||
  size_t       size;
 | 
			
		||||
  off_t        offset;
 | 
			
		||||
  SpaPODFrame *stack;
 | 
			
		||||
} SpaPODBuilder;
 | 
			
		||||
 | 
			
		||||
static inline uint32_t
 | 
			
		||||
spa_pod_builder_top (SpaPODBuilder *builder)
 | 
			
		||||
{
 | 
			
		||||
  if (builder->stack && builder->stack->offset != -1)
 | 
			
		||||
    return SPA_MEMBER(builder->data, builder->stack->offset, SpaPOD)->type;
 | 
			
		||||
  return SPA_POD_TYPE_INVALID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool
 | 
			
		||||
spa_pod_builder_in_array (SpaPODBuilder *builder)
 | 
			
		||||
{
 | 
			
		||||
  if (builder->stack && builder->stack->offset != -1) {
 | 
			
		||||
    SpaPOD *p = SPA_MEMBER(builder->data, builder->stack->offset, SpaPOD);
 | 
			
		||||
    if (p->type == SPA_POD_TYPE_ARRAY && p->size > 0)
 | 
			
		||||
      return true;
 | 
			
		||||
    if (p->type == SPA_POD_TYPE_PROP && p->size > (sizeof (SpaPODPropBody) - sizeof(SpaPOD)))
 | 
			
		||||
      return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_push (SpaPODBuilder *builder,
 | 
			
		||||
                      SpaPODFrame   *frame,
 | 
			
		||||
                      off_t          offset)
 | 
			
		||||
{
 | 
			
		||||
  frame->parent = builder->stack;
 | 
			
		||||
  frame->offset = offset;
 | 
			
		||||
  builder->stack = frame;
 | 
			
		||||
  return offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
spa_pod_builder_advance (SpaPODBuilder *builder, uint32_t size, bool pad)
 | 
			
		||||
{
 | 
			
		||||
  SpaPODFrame *f;
 | 
			
		||||
 | 
			
		||||
  if (pad) {
 | 
			
		||||
    size += SPA_ROUND_UP_N (builder->offset, 8) - builder->offset;
 | 
			
		||||
  }
 | 
			
		||||
  builder->offset += size;
 | 
			
		||||
 | 
			
		||||
  for (f = builder->stack; f; f = f->parent) {
 | 
			
		||||
    if (f->offset != -1)
 | 
			
		||||
      SPA_MEMBER (builder->data, f->offset, SpaPOD)->size += size;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
spa_pod_builder_pop (SpaPODBuilder *builder,
 | 
			
		||||
                     SpaPODFrame   *frame)
 | 
			
		||||
{
 | 
			
		||||
  builder->stack = frame->parent;
 | 
			
		||||
  spa_pod_builder_advance (builder, 0, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_raw (SpaPODBuilder *builder, const void *data, uint32_t size, bool pad)
 | 
			
		||||
{
 | 
			
		||||
  off_t offset = builder->offset;
 | 
			
		||||
 | 
			
		||||
  if (offset + size <= builder->size)
 | 
			
		||||
    memcpy (builder->data + offset, data, size);
 | 
			
		||||
  else
 | 
			
		||||
    offset = -1;
 | 
			
		||||
 | 
			
		||||
  spa_pod_builder_advance (builder, size, pad);
 | 
			
		||||
 | 
			
		||||
  return offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_string_body (SpaPODBuilder *builder,
 | 
			
		||||
                             const char    *str,
 | 
			
		||||
                             uint32_t       len)
 | 
			
		||||
{
 | 
			
		||||
  off_t out = spa_pod_builder_raw (builder, str, len + 1 , true);
 | 
			
		||||
  if (out != -1)
 | 
			
		||||
    *SPA_MEMBER (builder->data, out + len, char) = '\0';
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_pod (SpaPODBuilder *builder, uint32_t size, uint32_t type)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPOD p = { size, type };
 | 
			
		||||
  return spa_pod_builder_raw (builder, &p, sizeof (p), false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_primitive (SpaPODBuilder *builder, const SpaPOD *p)
 | 
			
		||||
{
 | 
			
		||||
  const void *data;
 | 
			
		||||
  size_t size;
 | 
			
		||||
  bool pad;
 | 
			
		||||
 | 
			
		||||
  if (spa_pod_builder_in_array (builder)) {
 | 
			
		||||
    data = SPA_POD_BODY_CONST (p);
 | 
			
		||||
    size = SPA_POD_BODY_SIZE (p);
 | 
			
		||||
    pad = false;
 | 
			
		||||
  } else {
 | 
			
		||||
    data = p;
 | 
			
		||||
    size = SPA_POD_SIZE (p);
 | 
			
		||||
    pad = true;
 | 
			
		||||
  }
 | 
			
		||||
  return spa_pod_builder_raw (builder, data, size, pad);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_bool (SpaPODBuilder *builder, bool val)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPODBool p = { { sizeof (uint32_t), SPA_POD_TYPE_BOOL }, val ? 1 : 0 };
 | 
			
		||||
  return spa_pod_builder_primitive (builder, &p.pod);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_int (SpaPODBuilder *builder, int32_t val)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPODInt p = { { sizeof (val), SPA_POD_TYPE_INT }, val };
 | 
			
		||||
  return spa_pod_builder_primitive (builder, &p.pod);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_long (SpaPODBuilder *builder, int64_t val)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPODLong p = { { sizeof (val), SPA_POD_TYPE_LONG }, val };
 | 
			
		||||
  return spa_pod_builder_primitive (builder, &p.pod);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_float (SpaPODBuilder *builder, float val)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPODFloat p = { { sizeof (val), SPA_POD_TYPE_FLOAT }, val };
 | 
			
		||||
  return spa_pod_builder_primitive (builder, &p.pod);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_double (SpaPODBuilder *builder, double val)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPODDouble p = { { sizeof (val), SPA_POD_TYPE_DOUBLE }, val };
 | 
			
		||||
  return spa_pod_builder_primitive (builder, &p.pod);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_string (SpaPODBuilder *builder, const char *str, uint32_t len)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPODString p = { { len + 1, SPA_POD_TYPE_STRING } };
 | 
			
		||||
  off_t out = spa_pod_builder_raw (builder, &p, sizeof (p) , false);
 | 
			
		||||
  if (spa_pod_builder_string_body (builder, str, len) == -1)
 | 
			
		||||
    out = -1;
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_rectangle (SpaPODBuilder *builder, SpaRectangle *val)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPODRectangle p = { { sizeof (val), SPA_POD_TYPE_RECTANGLE }, *val };
 | 
			
		||||
  return spa_pod_builder_primitive (builder, &p.pod);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_fraction (SpaPODBuilder *builder, SpaFraction *val)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPODFraction p = { { sizeof (val), SPA_POD_TYPE_FRACTION }, *val };
 | 
			
		||||
  return spa_pod_builder_primitive (builder, &p.pod);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_push_array (SpaPODBuilder  *builder,
 | 
			
		||||
                            SpaPODFrame    *frame)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPODArray p = { { sizeof (SpaPODArrayBody) - sizeof (SpaPOD), SPA_POD_TYPE_ARRAY }, { { 0, 0 } } };
 | 
			
		||||
  return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p) - sizeof(SpaPOD), false));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_array (SpaPODBuilder *builder,
 | 
			
		||||
                       uint32_t       child_size,
 | 
			
		||||
                       uint32_t       child_type,
 | 
			
		||||
                       uint32_t       n_elems,
 | 
			
		||||
                       const void*    elems)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPODArray p = {
 | 
			
		||||
    { (uint32_t)(sizeof (SpaPODArrayBody) + n_elems * child_size), SPA_POD_TYPE_ARRAY },
 | 
			
		||||
    { { child_size, child_type } }
 | 
			
		||||
  };
 | 
			
		||||
  off_t out = spa_pod_builder_raw (builder, &p, sizeof(p), true);
 | 
			
		||||
  if (spa_pod_builder_raw (builder, elems, child_size * n_elems, true) == -1)
 | 
			
		||||
    out = -1;
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_push_struct (SpaPODBuilder  *builder,
 | 
			
		||||
                             SpaPODFrame    *frame)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPODStruct p = { { 0, SPA_POD_TYPE_STRUCT } };
 | 
			
		||||
  return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p), false));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_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 } };
 | 
			
		||||
  return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p), false));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline off_t
 | 
			
		||||
spa_pod_builder_push_prop (SpaPODBuilder *builder,
 | 
			
		||||
                           SpaPODFrame   *frame,
 | 
			
		||||
                           uint32_t       key,
 | 
			
		||||
                           uint32_t       flags)
 | 
			
		||||
{
 | 
			
		||||
  const SpaPODProp p = { { sizeof (SpaPODPropBody) - sizeof(SpaPOD), SPA_POD_TYPE_PROP},
 | 
			
		||||
                         { key, flags | SPA_POD_PROP_RANGE_NONE, { 0, 0 } } };
 | 
			
		||||
  return spa_pod_builder_push (builder, frame, spa_pod_builder_raw (builder, &p, sizeof(p) - sizeof(SpaPOD), false));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __SPA_POD_BUILDER_H__ */
 | 
			
		||||
							
								
								
									
										194
									
								
								spa/include/spa/pod.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								spa/include/spa/pod.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,194 @@
 | 
			
		|||
/* Simple Plugin API
 | 
			
		||||
 * Copyright (C) 2017 Wim Taymans <wim.taymans@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Library General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Library General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Library General Public
 | 
			
		||||
 * License along with this library; if not, write to the
 | 
			
		||||
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 | 
			
		||||
 * Boston, MA 02110-1301, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __SPA_POD_H__
 | 
			
		||||
#define __SPA_POD_H__
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define SPA_POD_URI             "http://spaplug.in/ns/pod"
 | 
			
		||||
#define SPA_POD_PREFIX          SPA_POD_URI "#"
 | 
			
		||||
 | 
			
		||||
#include <spa/defs.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SpaPODType:
 | 
			
		||||
 */
 | 
			
		||||
typedef enum {
 | 
			
		||||
  SPA_POD_TYPE_INVALID         = 0,
 | 
			
		||||
  SPA_POD_TYPE_BOOL,
 | 
			
		||||
  SPA_POD_TYPE_INT,
 | 
			
		||||
  SPA_POD_TYPE_LONG,
 | 
			
		||||
  SPA_POD_TYPE_FLOAT,
 | 
			
		||||
  SPA_POD_TYPE_DOUBLE,
 | 
			
		||||
  SPA_POD_TYPE_STRING,
 | 
			
		||||
  SPA_POD_TYPE_RECTANGLE,
 | 
			
		||||
  SPA_POD_TYPE_FRACTION,
 | 
			
		||||
  SPA_POD_TYPE_BITMASK,
 | 
			
		||||
  SPA_POD_TYPE_ARRAY,
 | 
			
		||||
  SPA_POD_TYPE_STRUCT,
 | 
			
		||||
  SPA_POD_TYPE_OBJECT,
 | 
			
		||||
  SPA_POD_TYPE_PROP
 | 
			
		||||
} SpaPODType;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  uint32_t     size;
 | 
			
		||||
  uint32_t     type;
 | 
			
		||||
} SpaPOD;
 | 
			
		||||
 | 
			
		||||
#define SPA_POD_BODY_SIZE(pod)           ((pod)->size)
 | 
			
		||||
#define SPA_POD_SIZE(pod)                (sizeof(SpaPOD) + SPA_POD_BODY_SIZE(pod))
 | 
			
		||||
 | 
			
		||||
#define SPA_POD_CONTENTS(type,pod)       SPA_MEMBER((pod),sizeof(type),void)
 | 
			
		||||
#define SPA_POD_CONTENTS_CONST(type,pod) SPA_MEMBER((pod),sizeof(type),const void)
 | 
			
		||||
#define SPA_POD_BODY(pod)                SPA_MEMBER((pod),sizeof(SpaPOD),void)
 | 
			
		||||
#define SPA_POD_BODY_CONST(pod)          SPA_MEMBER((pod),sizeof(SpaPOD),const void)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD       pod;
 | 
			
		||||
  int32_t      value;
 | 
			
		||||
} SpaPODInt;
 | 
			
		||||
 | 
			
		||||
typedef SpaPODInt SpaPODBool;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD       pod;
 | 
			
		||||
  int64_t      value;
 | 
			
		||||
} SpaPODLong;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD       pod;
 | 
			
		||||
  float        value;
 | 
			
		||||
} SpaPODFloat;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD       pod;
 | 
			
		||||
  double       value;
 | 
			
		||||
} SpaPODDouble;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD       pod;
 | 
			
		||||
  /* value here */
 | 
			
		||||
} SpaPODString;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD       pod;
 | 
			
		||||
  SpaRectangle value;
 | 
			
		||||
} SpaPODRectangle;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD       pod;
 | 
			
		||||
  SpaFraction  value;
 | 
			
		||||
} SpaPODFraction;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD       pod;
 | 
			
		||||
  /* array of uint32_t follows with the bitmap */
 | 
			
		||||
} SpaPODBitmap;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD    child;
 | 
			
		||||
  /* array with elements of child.size follows */
 | 
			
		||||
} SpaPODArrayBody;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD           pod;
 | 
			
		||||
  SpaPODArrayBody  body;
 | 
			
		||||
} SpaPODArray;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD           pod;
 | 
			
		||||
  /* one or more SpaPOD follow */
 | 
			
		||||
} SpaPODStruct;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  uint32_t         key;
 | 
			
		||||
#define SPA_POD_PROP_FLAG_UNSET         (1 << 4)
 | 
			
		||||
#define SPA_POD_PROP_FLAG_OPTIONAL      (1 << 5)
 | 
			
		||||
#define SPA_POD_PROP_FLAG_READABLE      (1 << 6)
 | 
			
		||||
#define SPA_POD_PROP_FLAG_WRITABLE      (1 << 7)
 | 
			
		||||
#define SPA_POD_PROP_FLAG_READWRITE     (SPA_POD_PROP_FLAG_READABLE | SPA_POD_PROP_FLAG_WRITABLE)
 | 
			
		||||
#define SPA_POD_PROP_FLAG_DEPRECATED    (1 << 8)
 | 
			
		||||
#define SPA_POD_PROP_RANGE_NONE         0
 | 
			
		||||
#define SPA_POD_PROP_RANGE_MIN_MAX      1
 | 
			
		||||
#define SPA_POD_PROP_RANGE_STEP         2
 | 
			
		||||
#define SPA_POD_PROP_RANGE_ENUM         3
 | 
			
		||||
#define SPA_POD_PROP_RANGE_FLAGS        4
 | 
			
		||||
  uint32_t         flags;
 | 
			
		||||
  SpaPOD           value;
 | 
			
		||||
  /* array with elements of value.size follows,
 | 
			
		||||
   * first element is value/default, rest are alternatives */
 | 
			
		||||
} SpaPODPropBody;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD         pod;
 | 
			
		||||
  SpaPODPropBody body;
 | 
			
		||||
} SpaPODProp;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  uint32_t         id;
 | 
			
		||||
  uint32_t         type;
 | 
			
		||||
  /* contents follow, series of SpaPODProp */
 | 
			
		||||
} SpaPODObjectBody;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  SpaPOD           pod;
 | 
			
		||||
  SpaPODObjectBody body;
 | 
			
		||||
} SpaPODObject;
 | 
			
		||||
 | 
			
		||||
#define SPA_POD_ARRAY_BODY_FOREACH(body, size, iter) \
 | 
			
		||||
  for ((iter) = SPA_MEMBER (body, sizeof(SpaPODArrayBody), __typeof__(*iter)); \
 | 
			
		||||
       (iter) < SPA_MEMBER (body, (size), __typeof__(*iter)); \
 | 
			
		||||
       (iter) = SPA_MEMBER ((iter), (body)->child.size, __typeof__(*iter)))
 | 
			
		||||
 | 
			
		||||
#define SPA_POD_STRUCT_BODY_FOREACH(body, size, iter) \
 | 
			
		||||
  for ((iter) = SPA_MEMBER ((body), 0, 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_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)->pod), 8), SpaPODProp))
 | 
			
		||||
 | 
			
		||||
#define SPA_POD_PROP_ALTERNATIVE_FOREACH(body, _size, iter) \
 | 
			
		||||
  for ((iter) = SPA_MEMBER ((body), (body)->value.size + sizeof (SpaPODPropBody), __typeof__(*iter)); \
 | 
			
		||||
       (iter) < SPA_MEMBER ((body), (_size), __typeof__(*iter)); \
 | 
			
		||||
       (iter) = SPA_MEMBER ((iter), (body)->value.size, __typeof__(*iter)))
 | 
			
		||||
 | 
			
		||||
static inline SpaPODProp *
 | 
			
		||||
spa_pod_object_body_find_prop (SpaPODObjectBody *body, uint32_t size, uint32_t key)
 | 
			
		||||
{
 | 
			
		||||
  SpaPODProp *res;
 | 
			
		||||
  SPA_POD_OBJECT_BODY_FOREACH (body, size, res) {
 | 
			
		||||
    if (res->body.key == key)
 | 
			
		||||
      return res;
 | 
			
		||||
  }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}  /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __SPA_POD_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -58,16 +58,6 @@ typedef enum {
 | 
			
		|||
  SPA_PROP_TYPE_POINTER
 | 
			
		||||
} SpaPropType;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  uint32_t width;
 | 
			
		||||
  uint32_t height;
 | 
			
		||||
} SpaRectangle;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  uint32_t num;
 | 
			
		||||
  uint32_t denom;
 | 
			
		||||
} SpaFraction;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SpaPropFlags:
 | 
			
		||||
 * @SPA_PROP_FLAG_NONE: no flags
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,11 @@
 | 
			
		|||
#           install : false)
 | 
			
		||||
executable('test-props', 'test-props.c',
 | 
			
		||||
           include_directories : [spa_inc, spa_libinc ],
 | 
			
		||||
           dependencies : [dl_lib, sdl_dep, pthread_lib],
 | 
			
		||||
           dependencies : [],
 | 
			
		||||
           link_with : spalib,
 | 
			
		||||
           install : false)
 | 
			
		||||
executable('test-props2', 'test-props2.c',
 | 
			
		||||
           include_directories : [spa_inc, spa_libinc ],
 | 
			
		||||
           dependencies : [],
 | 
			
		||||
           link_with : spalib,
 | 
			
		||||
           install : false)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										179
									
								
								spa/tests/test-props2.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								spa/tests/test-props2.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,179 @@
 | 
			
		|||
/* Spa
 | 
			
		||||
 * Copyright (C) 2017 Wim Taymans <wim.taymans@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Library General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Library General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Library General Public
 | 
			
		||||
 * License along with this library; if not, write to the
 | 
			
		||||
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 | 
			
		||||
 * Boston, MA 02110-1301, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <spa/pod.h>
 | 
			
		||||
#include <spa/pod-builder.h>
 | 
			
		||||
 | 
			
		||||
#include <spa/id-map.h>
 | 
			
		||||
#include <spa/log.h>
 | 
			
		||||
#include <spa/video/format.h>
 | 
			
		||||
#include <lib/debug.h>
 | 
			
		||||
#include <lib/mapper.h>
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
print_value (uint32_t size, uint32_t type, void *body, int prefix, uint32_t flags)
 | 
			
		||||
{
 | 
			
		||||
  switch (type) {
 | 
			
		||||
    case SPA_POD_TYPE_BOOL:
 | 
			
		||||
      printf ("%-*sBool %d\n", prefix, "", *(int32_t *) body);
 | 
			
		||||
      break;
 | 
			
		||||
    case SPA_POD_TYPE_INT:
 | 
			
		||||
      printf ("%-*sInt %d\n", prefix, "", *(int32_t *) body);
 | 
			
		||||
      break;
 | 
			
		||||
    case SPA_POD_TYPE_LONG:
 | 
			
		||||
      printf ("%-*sLong %"PRIi64"\n", prefix, "", *(int64_t *) body);
 | 
			
		||||
      break;
 | 
			
		||||
    case SPA_POD_TYPE_FLOAT:
 | 
			
		||||
      printf ("%-*sFloat %f\n", prefix, "", *(float *) body);
 | 
			
		||||
      break;
 | 
			
		||||
    case SPA_POD_TYPE_DOUBLE:
 | 
			
		||||
      printf ("%-*sDouble %g\n", prefix, "", *(double *) body);
 | 
			
		||||
      break;
 | 
			
		||||
    case SPA_POD_TYPE_STRING:
 | 
			
		||||
      printf ("%-*sString %s\n", prefix, "", (char *) body);
 | 
			
		||||
      break;
 | 
			
		||||
    case SPA_POD_TYPE_RECTANGLE:
 | 
			
		||||
    {
 | 
			
		||||
      SpaRectangle *r = body;
 | 
			
		||||
      printf ("%-*sRectangle %dx%d\n", prefix, "", r->width, r->height);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case SPA_POD_TYPE_FRACTION:
 | 
			
		||||
    {
 | 
			
		||||
      SpaFraction *f = body;
 | 
			
		||||
      printf ("%-*sFraction %d/%d\n", prefix, "", f->num, f->denom);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case SPA_POD_TYPE_BITMASK:
 | 
			
		||||
      printf ("%-*sBitmask\n", prefix, "");
 | 
			
		||||
      break;
 | 
			
		||||
    case SPA_POD_TYPE_ARRAY:
 | 
			
		||||
    {
 | 
			
		||||
      SpaPODArrayBody *b = body;
 | 
			
		||||
      void *p;
 | 
			
		||||
      printf ("%-*sArray: child.size %d, child.type %d\n", prefix, "", b->child.size, b->child.type);
 | 
			
		||||
 | 
			
		||||
      SPA_POD_ARRAY_BODY_FOREACH (b, size, p)
 | 
			
		||||
        print_value (b->child.size, b->child.type, p, prefix + 2, flags);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case SPA_POD_TYPE_STRUCT:
 | 
			
		||||
    {
 | 
			
		||||
      SpaPOD *b = body, *p;
 | 
			
		||||
      printf ("%-*sStruct: size %d\n", prefix, "", size);
 | 
			
		||||
      SPA_POD_STRUCT_BODY_FOREACH (b, size, p)
 | 
			
		||||
        print_value (p->size, p->type, SPA_POD_BODY (p), prefix + 2, flags);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case SPA_POD_TYPE_OBJECT:
 | 
			
		||||
    {
 | 
			
		||||
      SpaPODObjectBody *b = body;
 | 
			
		||||
      SpaPODProp *p;
 | 
			
		||||
      void *alt;
 | 
			
		||||
      int i;
 | 
			
		||||
 | 
			
		||||
      printf ("%-*sObject: size %d\n", prefix, "", size);
 | 
			
		||||
      SPA_POD_OBJECT_BODY_FOREACH (b, size, p) {
 | 
			
		||||
        printf ("%-*sProp: key %d, flags %d\n", prefix + 2, "", p->body.key, p->body.flags);
 | 
			
		||||
        if (p->body.flags & SPA_POD_PROP_FLAG_UNSET)
 | 
			
		||||
          printf ("%-*sUnset (Default):\n", prefix + 4, "");
 | 
			
		||||
        else
 | 
			
		||||
          printf ("%-*sValue:\n", prefix + 4, "");
 | 
			
		||||
        print_value (p->body.value.size, p->body.value.type, SPA_POD_BODY (&p->body.value), prefix + 6, p->body.flags);
 | 
			
		||||
 | 
			
		||||
        i = 0;
 | 
			
		||||
        SPA_POD_PROP_ALTERNATIVE_FOREACH (&p->body, p->pod.size, alt) {
 | 
			
		||||
          if (i == 0)
 | 
			
		||||
            printf ("%-*sAlternatives:\n", prefix + 4, "");
 | 
			
		||||
          print_value (p->body.value.size, p->body.value.type, alt, prefix + 6, p->body.flags);
 | 
			
		||||
          i++;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main (int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  SpaPODBuilder b = { NULL, };
 | 
			
		||||
  SpaPODFrame frame[4];
 | 
			
		||||
  uint8_t buffer[1024];
 | 
			
		||||
  SpaPOD *obj;
 | 
			
		||||
 | 
			
		||||
  b.data = buffer;
 | 
			
		||||
  b.size = 1024;
 | 
			
		||||
 | 
			
		||||
  obj = SPA_MEMBER (buffer, spa_pod_builder_push_object (&b, &frame[0], 0, 0), SpaPOD);
 | 
			
		||||
 | 
			
		||||
  uint32_t formats[] = { 1, 2 };
 | 
			
		||||
  spa_pod_builder_push_prop (&b, &frame[1],
 | 
			
		||||
                             1, SPA_POD_PROP_RANGE_ENUM | SPA_POD_PROP_FLAG_READWRITE);
 | 
			
		||||
  spa_pod_builder_int (&b, 1);
 | 
			
		||||
  spa_pod_builder_int (&b, formats[0]);
 | 
			
		||||
  spa_pod_builder_int (&b, formats[1]);
 | 
			
		||||
  spa_pod_builder_pop (&b, &frame[1]);
 | 
			
		||||
 | 
			
		||||
  spa_pod_builder_push_prop (&b, &frame[1],
 | 
			
		||||
                             2, SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_READWRITE);
 | 
			
		||||
  spa_pod_builder_int (&b, 42);
 | 
			
		||||
  spa_pod_builder_pop (&b, &frame[1]);
 | 
			
		||||
 | 
			
		||||
  SpaRectangle def = { 320, 240 }, sizes[] = { { 0, 0 }, { 1024, 1024} };
 | 
			
		||||
  spa_pod_builder_push_prop (&b, &frame[1],
 | 
			
		||||
                             3, SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET | SPA_POD_PROP_FLAG_READWRITE);
 | 
			
		||||
  spa_pod_builder_rectangle (&b, &def);
 | 
			
		||||
  spa_pod_builder_raw (&b, sizes, sizeof (sizes), false);
 | 
			
		||||
  spa_pod_builder_pop (&b, &frame[1]);
 | 
			
		||||
 | 
			
		||||
  spa_pod_builder_push_prop (&b, &frame[1], 4, SPA_POD_PROP_RANGE_NONE | SPA_POD_PROP_FLAG_READABLE);
 | 
			
		||||
  spa_pod_builder_push_struct (&b, &frame[2]);
 | 
			
		||||
  spa_pod_builder_int (&b, 4);
 | 
			
		||||
  spa_pod_builder_long (&b, 6000);
 | 
			
		||||
  spa_pod_builder_float (&b, 4.0);
 | 
			
		||||
  spa_pod_builder_double (&b, 3.14);
 | 
			
		||||
  spa_pod_builder_string (&b, "test123", strlen ("test123"));
 | 
			
		||||
  spa_pod_builder_rectangle (&b, &def);
 | 
			
		||||
  SpaFraction f = { 25, 1 };
 | 
			
		||||
  spa_pod_builder_fraction (&b, &f);
 | 
			
		||||
  spa_pod_builder_push_array (&b, &frame[3]);
 | 
			
		||||
  spa_pod_builder_int (&b, 4);
 | 
			
		||||
  spa_pod_builder_int (&b, 5);
 | 
			
		||||
  spa_pod_builder_int (&b, 6);
 | 
			
		||||
  spa_pod_builder_pop (&b, &frame[3]);
 | 
			
		||||
  spa_pod_builder_pop (&b, &frame[2]);
 | 
			
		||||
  spa_pod_builder_pop (&b, &frame[1]);
 | 
			
		||||
  spa_pod_builder_pop (&b, &frame[0]);
 | 
			
		||||
 | 
			
		||||
  print_value (obj->size, obj->type, SPA_POD_BODY (obj), 0, 0);
 | 
			
		||||
 | 
			
		||||
  SpaPODProp *p = spa_pod_object_body_find_prop (SPA_POD_BODY (obj), obj->size, 4);
 | 
			
		||||
  printf ("%d %d\n", p->body.key, p->body.flags);
 | 
			
		||||
  print_value (p->body.value.size, p->body.value.type, SPA_POD_BODY (&p->body.value), 0, 0);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue