Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Julian Bouzas
WirePlumber
Commits
ce3883c1
Commit
ce3883c1
authored
Dec 03, 2019
by
George Kiagiadakis
Browse files
lib: add WpSpaProps, a helper to deal with SPA_PARAM_Props & SPA_PARAM_PropInfo
parent
44e498ca
Changes
5
Hide whitespace changes
Inline
Side-by-side
lib/wp/meson.build
View file @
ce3883c1
...
...
@@ -14,6 +14,7 @@ wp_lib_sources = [
'proxy-link.c',
'proxy-node.c',
'proxy-port.c',
'spa-props.c',
]
wp_lib_headers = [
...
...
lib/wp/private.h
View file @
ce3883c1
...
...
@@ -93,6 +93,64 @@ void wp_proxy_augment_error (WpProxy * self, GError * error);
void
wp_proxy_register_async_task
(
WpProxy
*
self
,
int
seq
,
GTask
*
task
);
GTask
*
wp_proxy_find_async_task
(
WpProxy
*
self
,
int
seq
,
gboolean
steal
);
/* spa props */
struct
spa_pod
;
struct
spa_pod_builder
;
typedef
struct
_WpSpaProps
WpSpaProps
;
struct
_WpSpaProps
{
GList
*
entries
;
};
void
wp_spa_props_clear
(
WpSpaProps
*
self
);
void
wp_spa_props_register_pod
(
WpSpaProps
*
self
,
guint32
id
,
const
gchar
*
name
,
const
struct
spa_pod
*
type
);
gint
wp_spa_props_register_from_prop_info
(
WpSpaProps
*
self
,
const
struct
spa_pod
*
prop_info
);
const
struct
spa_pod
*
wp_spa_props_get_stored
(
WpSpaProps
*
self
,
guint32
id
);
gint
wp_spa_props_store_pod
(
WpSpaProps
*
self
,
guint32
id
,
const
struct
spa_pod
*
value
);
gint
wp_spa_props_store_from_props
(
WpSpaProps
*
self
,
const
struct
spa_pod
*
props
,
GArray
*
changed_ids
);
GPtrArray
*
wp_spa_props_build_all_pods
(
WpSpaProps
*
self
,
struct
spa_pod_builder
*
b
);
struct
spa_pod
*
wp_spa_props_build_update
(
WpSpaProps
*
self
,
guint32
id
,
const
struct
spa_pod
*
value
,
struct
spa_pod_builder
*
b
);
const
struct
spa_pod
*
wp_spa_props_build_pod_valist
(
gchar
*
buffer
,
gsize
size
,
va_list
args
);
static
inline
const
struct
spa_pod
*
wp_spa_props_build_pod
(
gchar
*
buffer
,
gsize
size
,
...)
{
const
struct
spa_pod
*
ret
;
va_list
args
;
va_start
(
args
,
size
);
ret
=
wp_spa_props_build_pod_valist
(
buffer
,
size
,
args
);
va_end
(
args
);
return
ret
;
}
#define wp_spa_props_register(self, id, name, ...) \
({ \
gchar b[512]; \
wp_spa_props_register_pod (self, id, name, \
wp_spa_props_build_pod (b, sizeof (b), ##__VA_ARGS__, NULL)); \
})
#define wp_spa_props_store(self, id, ...) \
({ \
gchar b[512]; \
wp_spa_props_store_pod (self, id, \
wp_spa_props_build_pod (b, sizeof (b), ##__VA_ARGS__, NULL)); \
})
G_END_DECLS
#endif
lib/wp/spa-props.c
0 → 100644
View file @
ce3883c1
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include
"private.h"
#include
<spa/pod/pod.h>
#include
<spa/pod/builder.h>
#include
<spa/pod/parser.h>
#include
<spa/param/props.h>
#include
<spa/utils/defs.h>
#include
<spa/utils/result.h>
struct
entry
{
guint32
id
;
gchar
*
name
;
struct
spa_pod
*
type
;
struct
spa_pod
*
value
;
};
struct
entry
*
entry_new
(
void
)
{
struct
entry
*
e
=
g_slice_new0
(
struct
entry
);
return
e
;
}
static
void
entry_free
(
struct
entry
*
e
)
{
g_free
(
e
->
name
);
free
(
e
->
type
);
free
(
e
->
value
);
g_slice_free
(
struct
entry
,
e
);
}
void
wp_spa_props_clear
(
WpSpaProps
*
self
)
{
g_list_free_full
(
self
->
entries
,
(
GDestroyNotify
)
entry_free
);
self
->
entries
=
NULL
;
}
void
wp_spa_props_register_pod
(
WpSpaProps
*
self
,
guint32
id
,
const
gchar
*
name
,
const
struct
spa_pod
*
type
)
{
struct
entry
*
e
=
entry_new
();
e
->
id
=
id
;
e
->
name
=
g_strdup
(
name
);
e
->
type
=
spa_pod_copy
(
type
);
if
(
!
spa_pod_is_choice
(
type
))
e
->
value
=
spa_pod_copy
(
type
);
else
e
->
value
=
spa_pod_copy
(
SPA_POD_CHOICE_CHILD
(
type
));
self
->
entries
=
g_list_append
(
self
->
entries
,
e
);
}
gint
wp_spa_props_register_from_prop_info
(
WpSpaProps
*
self
,
const
struct
spa_pod
*
prop_info
)
{
guint32
id
;
gchar
*
name
;
const
struct
spa_pod
*
type
;
int
res
;
res
=
spa_pod_parse_object
(
prop_info
,
SPA_TYPE_OBJECT_PropInfo
,
NULL
,
SPA_PROP_INFO_id
,
SPA_POD_Id
(
&
id
),
SPA_PROP_INFO_name
,
SPA_POD_String
(
&
name
),
SPA_PROP_INFO_type
,
SPA_POD_Pod
(
&
type
));
if
(
res
<
0
)
{
g_debug
(
"Bad prop info object"
);
return
res
;
}
wp_spa_props_register_pod
(
self
,
id
,
name
,
type
);
return
0
;
}
// get <-- cached
const
struct
spa_pod
*
wp_spa_props_get_stored
(
WpSpaProps
*
self
,
guint32
id
)
{
GList
*
l
=
self
->
entries
;
while
(
l
&&
((
struct
entry
*
)
l
->
data
)
->
id
!=
id
)
l
=
g_list_next
(
l
);
return
l
?
((
struct
entry
*
)
l
->
data
)
->
value
:
NULL
;
}
// exported set --> cache + update(variant to pod -> push)
gint
wp_spa_props_store_pod
(
WpSpaProps
*
self
,
guint32
id
,
const
struct
spa_pod
*
value
)
{
GList
*
l
=
self
->
entries
;
struct
entry
*
e
;
uint32_t
expected_type
;
while
(
l
&&
((
struct
entry
*
)
l
->
data
)
->
id
!=
id
)
l
=
g_list_next
(
l
);
if
(
!
l
)
return
-
ESRCH
;
e
=
(
struct
entry
*
)
l
->
data
;
expected_type
=
spa_pod_is_choice
(
e
->
type
)
?
SPA_POD_CHOICE_VALUE_TYPE
(
e
->
type
)
:
SPA_POD_TYPE
(
e
->
type
);
if
(
SPA_POD_TYPE
(
value
)
!=
expected_type
)
return
-
EINVAL
;
#define GET_VAL(pod, type) ((struct spa_pod_##type *) pod)->value
switch
(
SPA_POD_TYPE
(
value
))
{
//TODO bounds checking on integer types
case
SPA_TYPE_Id
:
if
(
GET_VAL
(
e
->
value
,
id
)
!=
GET_VAL
(
value
,
id
))
{
GET_VAL
(
e
->
value
,
id
)
=
GET_VAL
(
value
,
id
);
return
1
;
}
break
;
case
SPA_TYPE_Bool
:
if
(
GET_VAL
(
e
->
value
,
bool
)
!=
GET_VAL
(
value
,
bool
))
{
GET_VAL
(
e
->
value
,
bool
)
=
GET_VAL
(
value
,
bool
);
return
1
;
}
break
;
case
SPA_TYPE_Int
:
if
(
GET_VAL
(
e
->
value
,
int
)
!=
GET_VAL
(
value
,
int
))
{
GET_VAL
(
e
->
value
,
int
)
=
GET_VAL
(
value
,
int
);
return
1
;
}
break
;
case
SPA_TYPE_Long
:
if
(
GET_VAL
(
e
->
value
,
long
)
!=
GET_VAL
(
value
,
long
))
{
GET_VAL
(
e
->
value
,
long
)
=
GET_VAL
(
value
,
long
);
return
1
;
}
break
;
case
SPA_TYPE_Fd
:
if
(
GET_VAL
(
e
->
value
,
fd
)
!=
GET_VAL
(
value
,
fd
))
{
GET_VAL
(
e
->
value
,
fd
)
=
GET_VAL
(
value
,
fd
);
return
1
;
}
break
;
case
SPA_TYPE_Float
:
if
(
GET_VAL
(
e
->
value
,
float
)
!=
GET_VAL
(
value
,
float
))
{
GET_VAL
(
e
->
value
,
float
)
=
GET_VAL
(
value
,
float
);
return
1
;
}
break
;
case
SPA_TYPE_Double
:
if
(
GET_VAL
(
e
->
value
,
double
)
!=
GET_VAL
(
value
,
double
))
{
GET_VAL
(
e
->
value
,
double
)
=
GET_VAL
(
value
,
double
);
return
1
;
}
break
;
case
SPA_TYPE_Rectangle
:
if
(
GET_VAL
(
e
->
value
,
rectangle
).
width
!=
GET_VAL
(
value
,
rectangle
).
width
||
GET_VAL
(
e
->
value
,
rectangle
).
height
!=
GET_VAL
(
value
,
rectangle
).
height
)
{
GET_VAL
(
e
->
value
,
rectangle
)
=
GET_VAL
(
value
,
rectangle
);
return
1
;
}
break
;
case
SPA_TYPE_Fraction
:
if
(
GET_VAL
(
e
->
value
,
fraction
).
num
!=
GET_VAL
(
value
,
fraction
).
num
||
GET_VAL
(
e
->
value
,
fraction
).
denom
!=
GET_VAL
(
value
,
fraction
).
denom
)
{
GET_VAL
(
e
->
value
,
fraction
)
=
GET_VAL
(
value
,
fraction
);
return
1
;
}
break
;
default:
g_clear_pointer
(
&
e
->
value
,
free
);
e
->
value
=
spa_pod_copy
(
value
);
return
1
;
}
#undef GET_VAL
return
0
;
}
// exported event set --> pod to variant -> cache
// proxy event param --> pod to variant -> cache
gint
wp_spa_props_store_from_props
(
WpSpaProps
*
self
,
const
struct
spa_pod
*
props
,
GArray
*
changed_ids
)
{
const
struct
spa_pod_object
*
obj
;
const
struct
spa_pod_prop
*
iter
;
gint
ret
,
count
=
0
;
g_return_val_if_fail
(
!
changed_ids
||
g_array_get_element_size
(
changed_ids
)
==
sizeof
(
uint32_t
),
-
EINVAL
);
if
(
!
spa_pod_is_object_type
(
props
,
SPA_TYPE_OBJECT_Props
))
return
-
EINVAL
;
obj
=
(
const
struct
spa_pod_object
*
)
props
;
iter
=
spa_pod_prop_first
(
&
obj
->
body
);
for
(
iter
=
spa_pod_prop_first
(
&
obj
->
body
);
spa_pod_prop_is_inside
(
&
obj
->
body
,
obj
->
pod
.
size
,
iter
);
iter
=
spa_pod_prop_next
(
iter
))
{
if
((
ret
=
wp_spa_props_store_pod
(
self
,
iter
->
key
,
&
iter
->
value
))
<
0
)
{
g_debug
(
"error storing property 0x%x: %s"
,
iter
->
key
,
spa_strerror
(
ret
));
}
else
if
(
ret
==
1
&&
changed_ids
)
{
g_array_append_val
(
changed_ids
,
iter
->
key
);
count
++
;
}
}
return
count
;
}
// for exported update / prop_info + props
GPtrArray
*
wp_spa_props_build_all_pods
(
WpSpaProps
*
self
,
struct
spa_pod_builder
*
b
)
{
GPtrArray
*
res
=
g_ptr_array_new
();
GList
*
l
;
struct
spa_pod_frame
f
;
struct
spa_pod
*
pod
;
/* Props */
spa_pod_builder_push_object
(
b
,
&
f
,
SPA_TYPE_OBJECT_Props
,
SPA_PARAM_Props
);
for
(
l
=
self
->
entries
;
l
!=
NULL
;
l
=
g_list_next
(
l
))
{
struct
entry
*
e
=
(
struct
entry
*
)
l
->
data
;
if
(
e
->
value
)
{
spa_pod_builder_prop
(
b
,
e
->
id
,
0
);
spa_pod_builder_primitive
(
b
,
e
->
value
);
}
}
pod
=
spa_pod_builder_pop
(
b
,
&
f
);
g_ptr_array_add
(
res
,
pod
);
/* PropInfo */
for
(
l
=
self
->
entries
;
l
!=
NULL
;
l
=
g_list_next
(
l
))
{
struct
entry
*
e
=
(
struct
entry
*
)
l
->
data
;
pod
=
spa_pod_builder_add_object
(
b
,
SPA_TYPE_OBJECT_PropInfo
,
SPA_PARAM_PropInfo
,
SPA_PROP_INFO_id
,
SPA_POD_Id
(
e
->
id
),
SPA_PROP_INFO_name
,
SPA_POD_String
(
e
->
name
),
SPA_PROP_INFO_type
,
SPA_POD_Pod
(
e
->
type
));
g_ptr_array_add
(
res
,
pod
);
}
return
res
;
}
// proxy set --> value to props object -> push
struct
spa_pod
*
wp_spa_props_build_update
(
WpSpaProps
*
self
,
guint32
id
,
const
struct
spa_pod
*
value
,
struct
spa_pod_builder
*
b
)
{
struct
spa_pod_frame
f
;
spa_pod_builder_push_object
(
b
,
&
f
,
SPA_TYPE_OBJECT_Props
,
SPA_PARAM_Props
);
spa_pod_builder_prop
(
b
,
id
,
0
);
spa_pod_builder_primitive
(
b
,
value
);
return
spa_pod_builder_pop
(
b
,
&
f
);
}
const
struct
spa_pod
*
wp_spa_props_build_pod_valist
(
gchar
*
buffer
,
gsize
size
,
va_list
args
)
{
struct
spa_pod_builder
b
=
SPA_POD_BUILDER_INIT
(
buffer
,
size
);
struct
spa_pod_frame
f
;
void
*
pod
;
spa_pod_builder_push_struct
(
&
b
,
&
f
);
spa_pod_builder_addv
(
&
b
,
args
);
pod
=
spa_pod_builder_pop
(
&
b
,
&
f
);
return
SPA_POD_CONTENTS
(
struct
spa_pod_struct
,
pod
);
}
tests/wp/meson.build
View file @
ce3883c1
...
...
@@ -15,3 +15,9 @@ test(
executable('test-proxy', 'proxy.c', dependencies: common_deps),
env: common_env,
)
test(
'test-spa-props',
executable('test-spa-props', 'spa-props.c', dependencies: common_deps),
env: common_env,
)
tests/wp/spa-props.c
0 → 100644
View file @
ce3883c1
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
/* private functions, they should be hidden in the shared library */
#include
"wp/spa-props.c"
#include
<spa/pod/iter.h>
static
void
test_spa_props_set_get
(
void
)
{
WpSpaProps
props
=
{
0
};
const
struct
spa_pod
*
pod
;
float
float_value
=
0
.
0
;
const
gchar
*
string_value
=
NULL
;
wp_spa_props_register
(
&
props
,
SPA_PROP_volume
,
"Volume"
,
SPA_POD_CHOICE_RANGE_Float
(
1
.
0
,
0
.
0
,
10
.
0
));
wp_spa_props_register
(
&
props
,
SPA_PROP_START_CUSTOM
+
1
,
"Test property"
,
SPA_POD_String
(
"default value"
));
g_assert_nonnull
(
pod
=
wp_spa_props_get_stored
(
&
props
,
SPA_PROP_volume
));
g_assert_cmpint
(
spa_pod_get_float
(
pod
,
&
float_value
),
==
,
0
);
g_assert_cmpfloat_with_epsilon
(
float_value
,
1
.
0
,
0
.
001
);
g_assert_nonnull
(
pod
=
wp_spa_props_get_stored
(
&
props
,
SPA_PROP_START_CUSTOM
+
1
));
g_assert_cmpint
(
spa_pod_get_string
(
pod
,
&
string_value
),
==
,
0
);
g_assert_cmpstr
(
string_value
,
==
,
"default value"
);
g_assert_cmpint
(
wp_spa_props_store
(
&
props
,
SPA_PROP_volume
,
SPA_POD_Float
(
0
.
8
)),
==
,
1
);
g_assert_cmpint
(
wp_spa_props_store
(
&
props
,
SPA_PROP_START_CUSTOM
+
1
,
SPA_POD_String
(
"test value"
)),
==
,
1
);
g_assert_nonnull
(
pod
=
wp_spa_props_get_stored
(
&
props
,
SPA_PROP_volume
));
g_assert_cmpint
(
spa_pod_get_float
(
pod
,
&
float_value
),
==
,
0
);
g_assert_cmpfloat_with_epsilon
(
float_value
,
0
.
8
,
0
.
001
);
g_assert_nonnull
(
pod
=
wp_spa_props_get_stored
(
&
props
,
SPA_PROP_START_CUSTOM
+
1
));
g_assert_cmpint
(
spa_pod_get_string
(
pod
,
&
string_value
),
==
,
0
);
g_assert_cmpstr
(
string_value
,
==
,
"test value"
);
wp_spa_props_clear
(
&
props
);
}
static
void
test_spa_props_build_all
(
void
)
{
WpSpaProps
props
=
{
0
};
gchar
buffer
[
512
];
struct
spa_pod_builder
b
=
SPA_POD_BUILDER_INIT
(
buffer
,
sizeof
(
buffer
));
struct
spa_pod
*
pod
;
float
float_value
=
0
.
0
;
const
gchar
*
string_value
=
NULL
;
guint32
id
;
g_autoptr
(
GPtrArray
)
arr
=
NULL
;
wp_spa_props_register
(
&
props
,
SPA_PROP_volume
,
"Volume"
,
SPA_POD_CHOICE_RANGE_Float
(
1
.
0
,
0
.
0
,
10
.
0
));
wp_spa_props_register
(
&
props
,
SPA_PROP_START_CUSTOM
+
1
,
"Test property"
,
SPA_POD_String
(
"default value"
));
g_assert_cmpint
(
wp_spa_props_store
(
&
props
,
SPA_PROP_volume
,
SPA_POD_Float
(
0
.
8
)),
==
,
1
);
g_assert_cmpint
(
wp_spa_props_store
(
&
props
,
SPA_PROP_START_CUSTOM
+
1
,
SPA_POD_String
(
"test value"
)),
==
,
1
);
arr
=
wp_spa_props_build_all_pods
(
&
props
,
&
b
);
g_assert_nonnull
(
arr
);
g_assert_cmpint
(
arr
->
len
,
==
,
3
);
pod
=
g_ptr_array_index
(
arr
,
0
);
g_assert_nonnull
(
pod
);
g_assert_true
(
spa_pod_is_object_type
(
pod
,
SPA_TYPE_OBJECT_Props
));
g_assert_true
(
spa_pod_is_object_id
(
pod
,
SPA_PARAM_Props
));
g_assert_cmpint
(
spa_pod_parse_object
(
pod
,
SPA_TYPE_OBJECT_Props
,
NULL
,
SPA_PROP_volume
,
SPA_POD_Float
(
&
float_value
),
SPA_PROP_START_CUSTOM
+
1
,
SPA_POD_String
(
&
string_value
)),
==
,
2
);
g_assert_cmpfloat_with_epsilon
(
float_value
,
0
.
8
,
0
.
001
);
g_assert_cmpstr
(
string_value
,
==
,
"test value"
);
pod
=
g_ptr_array_index
(
arr
,
1
);
g_assert_nonnull
(
pod
);
g_assert_true
(
spa_pod_is_object_type
(
pod
,
SPA_TYPE_OBJECT_PropInfo
));
g_assert_true
(
spa_pod_is_object_id
(
pod
,
SPA_PARAM_PropInfo
));
g_assert_cmpint
(
spa_pod_parse_object
(
pod
,
SPA_TYPE_OBJECT_PropInfo
,
NULL
,
SPA_PROP_INFO_id
,
SPA_POD_Id
(
&
id
),
SPA_PROP_INFO_name
,
SPA_POD_String
(
&
string_value
),
SPA_PROP_INFO_type
,
SPA_POD_Pod
(
&
pod
)),
==
,
3
);
g_assert_cmpuint
(
id
,
==
,
SPA_PROP_volume
);
g_assert_cmpstr
(
string_value
,
==
,
"Volume"
);
g_assert_nonnull
(
pod
);
/* https://gitlab.freedesktop.org/pipewire/pipewire/issues/196
g_assert_true (spa_pod_is_choice (pod));
g_assert_true (SPA_POD_CHOICE_VALUE_TYPE (pod) == SPA_TYPE_Float); */
g_assert_true
(
SPA_POD_TYPE
(
pod
)
==
SPA_TYPE_Float
);
pod
=
g_ptr_array_index
(
arr
,
2
);
g_assert_nonnull
(
pod
);
g_assert_true
(
spa_pod_is_object_type
(
pod
,
SPA_TYPE_OBJECT_PropInfo
));
g_assert_true
(
spa_pod_is_object_id
(
pod
,
SPA_PARAM_PropInfo
));
g_assert_cmpint
(
spa_pod_parse_object
(
pod
,
SPA_TYPE_OBJECT_PropInfo
,
NULL
,
SPA_PROP_INFO_id
,
SPA_POD_Id
(
&
id
),
SPA_PROP_INFO_name
,
SPA_POD_String
(
&
string_value
),
SPA_PROP_INFO_type
,
SPA_POD_Pod
(
&
pod
)),
==
,
3
);
g_assert_cmpuint
(
id
,
==
,
SPA_PROP_START_CUSTOM
+
1
);
g_assert_cmpstr
(
string_value
,
==
,
"Test property"
);
g_assert_nonnull
(
pod
);
g_assert_true
(
spa_pod_is_string
(
pod
));
wp_spa_props_clear
(
&
props
);
}
static
void
test_spa_props_store_from_props
(
void
)
{
WpSpaProps
props
=
{
0
};
gchar
buffer
[
512
];
struct
spa_pod_builder
b
=
SPA_POD_BUILDER_INIT
(
buffer
,
sizeof
(
buffer
));
const
struct
spa_pod
*
pod
;
float
float_value
=
0
.
0
;
const
gchar
*
string_value
=
NULL
;
g_autoptr
(
GArray
)
arr
=
g_array_new
(
FALSE
,
FALSE
,
sizeof
(
guint32
));
wp_spa_props_register
(
&
props
,
SPA_PROP_volume
,
"Volume"
,
SPA_POD_CHOICE_RANGE_Float
(
1
.
0
,
0
.
0
,
10
.
0
));
wp_spa_props_register
(
&
props
,
SPA_PROP_START_CUSTOM
+
1
,
"Test property"
,
SPA_POD_String
(
"default value"
));
pod
=
spa_pod_builder_add_object
(
&
b
,
SPA_TYPE_OBJECT_Props
,
SPA_PARAM_Props
,
SPA_PROP_volume
,
SPA_POD_Float
(
0
.
8
),
SPA_PROP_START_CUSTOM
+
1
,
SPA_POD_String
(
"test value"
));
g_assert_cmpint
(
wp_spa_props_store_from_props
(
&
props
,
pod
,
arr
),
==
,
2
);
g_assert_cmpint
(
arr
->
len
,
==
,
2
);
g_assert_cmpint
(((
guint32
*
)
arr
->
data
)[
0
],
==
,
SPA_PROP_volume
);
g_assert_cmpint
(((
guint32
*
)
arr
->
data
)[
1
],
==
,
SPA_PROP_START_CUSTOM
+
1
);
g_assert_nonnull
(
pod
=
wp_spa_props_get_stored
(
&
props
,
SPA_PROP_volume
));
g_assert_cmpint
(
spa_pod_get_float
(
pod
,
&
float_value
),
==
,
0
);
g_assert_cmpfloat_with_epsilon
(
float_value
,
0
.
8
,
0
.
001
);
g_assert_nonnull
(
pod
=
wp_spa_props_get_stored
(
&
props
,
SPA_PROP_START_CUSTOM
+
1
));
g_assert_cmpint
(
spa_pod_get_string
(
pod
,
&
string_value
),
==
,
0
);
g_assert_cmpstr
(
string_value
,
==
,
"test value"
);
wp_spa_props_clear
(
&
props
);
}
static
void
test_spa_props_register_from_prop_info
(
void
)
{
WpSpaProps
props
=
{
0
};
gchar
buffer
[
512
];
struct
spa_pod_builder
b
=
SPA_POD_BUILDER_INIT
(
buffer
,
sizeof
(
buffer
));
const
struct
spa_pod
*
pod
;
float
float_value
=
0
.
0
;
const
gchar
*
string_value
=
NULL
;
g_autoptr
(
GPtrArray
)
arr
=
NULL
;
guint32
id
;
pod
=
spa_pod_builder_add_object
(
&
b
,
SPA_TYPE_OBJECT_PropInfo
,
SPA_PARAM_PropInfo
,
SPA_PROP_INFO_id
,
SPA_POD_Id
(
SPA_PROP_volume
),
SPA_PROP_INFO_name
,
SPA_POD_String
(
"Volume"
),
SPA_PROP_INFO_type
,
SPA_POD_CHOICE_RANGE_Float
(
1
.
0
,
0
.
0
,
10
.
0
));
g_assert_cmpint
(
wp_spa_props_register_from_prop_info
(
&
props
,
pod
),
==
,
0
);
pod
=
spa_pod_builder_add_object
(
&
b
,
SPA_TYPE_OBJECT_PropInfo
,
SPA_PARAM_PropInfo
,
SPA_PROP_INFO_id
,
SPA_POD_Id
(
SPA_PROP_START_CUSTOM
+
1
),
SPA_PROP_INFO_name
,
SPA_POD_String
(
"Test property"
),
SPA_PROP_INFO_type
,
SPA_POD_String
(
"default value"
));
g_assert_cmpint
(
wp_spa_props_register_from_prop_info
(
&
props
,
pod
),
==
,
0
);
g_assert_cmpint
(
wp_spa_props_store
(
&
props
,
SPA_PROP_volume
,
SPA_POD_Float
(
0
.
8
)),
==
,
1
);
g_assert_cmpint
(
wp_spa_props_store
(
&
props
,
SPA_PROP_START_CUSTOM
+
1
,
SPA_POD_String
(
"test value"
)),
==
,
1
);
arr
=
wp_spa_props_build_all_pods
(
&
props
,
&
b
);
g_assert_nonnull
(
arr
);
g_assert_cmpint
(
arr
->
len
,
==
,
3
);
pod
=
g_ptr_array_index
(
arr
,
0
);
g_assert_nonnull
(
pod
);
g_assert_true
(
spa_pod_is_object_type
(
pod
,
SPA_TYPE_OBJECT_Props
));
g_assert_true
(
spa_pod_is_object_id
(
pod
,
SPA_PARAM_Props
));
g_assert_cmpint
(
spa_pod_parse_object
(
pod
,
SPA_TYPE_OBJECT_Props
,
NULL
,
SPA_PROP_volume
,
SPA_POD_Float
(
&
float_value
),
SPA_PROP_START_CUSTOM
+
1
,
SPA_POD_String
(
&
string_value
)),
==
,
2
);
g_assert_cmpfloat_with_epsilon
(
float_value
,
0
.
8
,
0
.
001
);
g_assert_cmpstr
(
string_value
,
==
,
"test value"
);
pod
=
g_ptr_array_index
(
arr
,
1
);
g_assert_nonnull
(
pod
);
g_assert_true
(
spa_pod_is_object_type
(
pod
,
SPA_TYPE_OBJECT_PropInfo
));
g_assert_true
(
spa_pod_is_object_id
(
pod
,
SPA_PARAM_PropInfo
));
g_assert_cmpint
(
spa_pod_parse_object
(
pod
,
SPA_TYPE_OBJECT_PropInfo
,
NULL
,
SPA_PROP_INFO_id
,
SPA_POD_Id
(
&
id
),
SPA_PROP_INFO_name
,
SPA_POD_String
(
&
string_value
),
SPA_PROP_INFO_type
,
SPA_POD_Pod
(
&
pod
)),
==
,
3
);
g_assert_cmpuint
(
id
,
==
,
SPA_PROP_volume
);
g_assert_cmpstr
(
string_value
,
==
,
"Volume"
);
g_assert_nonnull
(
pod
);
/* https://gitlab.freedesktop.org/pipewire/pipewire/issues/196
g_assert_true (spa_pod_is_choice (pod));
g_assert_true (SPA_POD_CHOICE_VALUE_TYPE (pod) == SPA_TYPE_Float); */
g_assert_true
(
SPA_POD_TYPE
(
pod
)
==
SPA_TYPE_Float
);
pod
=
g_ptr_array_index
(
arr
,
2
);
g_assert_nonnull
(
pod
);
g_assert_true
(
spa_pod_is_object_type
(
pod
,
SPA_TYPE_OBJECT_PropInfo
));
g_assert_true
(
spa_pod_is_object_id
(
pod
,
SPA_PARAM_PropInfo
));
g_assert_cmpint
(
spa_pod_parse_object
(
pod
,
SPA_TYPE_OBJECT_PropInfo
,
NULL
,
SPA_PROP_INFO_id
,
SPA_POD_Id
(
&
id
),
SPA_PROP_INFO_name
,
SPA_POD_String
(
&
string_value
),
SPA_PROP_INFO_type
,
SPA_POD_Pod
(
&
pod
)),
==
,
3
);