mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2025-12-20 04:10:03 +01:00
m-lua-scripting: Add WpProperties API
Similar to Pod and Json, this API allows handling WpProperties references.
This commit is contained in:
parent
2712cbb5a9
commit
a35e40c1d2
5 changed files with 301 additions and 1 deletions
|
|
@ -2039,6 +2039,108 @@ static const luaL_Reg proc_utils_funcs[] = {
|
|||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* Properties */
|
||||
|
||||
static int
|
||||
properties_new (lua_State *L)
|
||||
{
|
||||
WpProperties *props;
|
||||
|
||||
if (lua_type (L, 1) != LUA_TNONE && lua_type (L, 1) != LUA_TNIL) {
|
||||
luaL_checktype (L, 1, LUA_TTABLE);
|
||||
props = wplua_table_to_properties (L, 1);
|
||||
} else {
|
||||
props = wp_properties_new_empty ();
|
||||
}
|
||||
|
||||
wplua_pushboxed (L, WP_TYPE_PROPERTIES, props);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
properties_get_boolean (lua_State *L)
|
||||
{
|
||||
WpProperties *props = wplua_checkboxed (L, 1, WP_TYPE_PROPERTIES);
|
||||
const char *key = luaL_checkstring (L, 2);
|
||||
const char *val = wp_properties_get (props, key);
|
||||
if (val)
|
||||
lua_pushboolean (L, spa_atob (val));
|
||||
else
|
||||
lua_pushnil (L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
properties_get_int (lua_State *L)
|
||||
{
|
||||
WpProperties *props = wplua_checkboxed (L, 1, WP_TYPE_PROPERTIES);
|
||||
const char *key = luaL_checkstring (L, 2);
|
||||
const char *val = wp_properties_get (props, key);
|
||||
if (val) {
|
||||
gint64 int_val = 0;
|
||||
if (spa_atoi64 (val, &int_val, 10))
|
||||
lua_pushinteger (L, int_val);
|
||||
else
|
||||
lua_pushnil (L);
|
||||
} else {
|
||||
lua_pushnil (L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
properties_get_float (lua_State *L)
|
||||
{
|
||||
WpProperties *props = wplua_checkboxed (L, 1, WP_TYPE_PROPERTIES);
|
||||
const char *key = luaL_checkstring (L, 2);
|
||||
const char *val = wp_properties_get (props, key);
|
||||
if (val) {
|
||||
double d_val = 0;
|
||||
if (spa_atod (val, &d_val))
|
||||
lua_pushnumber (L, d_val);
|
||||
else
|
||||
lua_pushnil (L);
|
||||
} else {
|
||||
lua_pushnil (L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
properties_get_count (lua_State *L)
|
||||
{
|
||||
WpProperties *props = wplua_checkboxed (L, 1, WP_TYPE_PROPERTIES);
|
||||
lua_pushinteger (L, wp_properties_get_count (props));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
properties_copy (lua_State *L)
|
||||
{
|
||||
WpProperties *props = wplua_checkboxed (L, 1, WP_TYPE_PROPERTIES);
|
||||
WpProperties *copy = wp_properties_copy (props);
|
||||
wplua_pushboxed (L, WP_TYPE_PROPERTIES, copy);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
properties_parse (lua_State *L)
|
||||
{
|
||||
WpProperties *props = wplua_checkboxed (L, 1, WP_TYPE_PROPERTIES);
|
||||
wplua_properties_to_table (L, props);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg properties_funcs[] = {
|
||||
{ "get_boolean", properties_get_boolean },
|
||||
{ "get_int", properties_get_int },
|
||||
{ "get_float", properties_get_float },
|
||||
{ "get_count", properties_get_count },
|
||||
{ "copy", properties_copy },
|
||||
{ "parse", properties_parse },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* WpSettings */
|
||||
|
||||
static int
|
||||
|
|
@ -3013,6 +3115,8 @@ wp_lua_scripting_api_init (lua_State *L)
|
|||
NULL, proc_info_funcs);
|
||||
wplua_register_type_methods (L, WP_TYPE_ITERATOR,
|
||||
NULL, iterator_funcs);
|
||||
wplua_register_type_methods (L, WP_TYPE_PROPERTIES,
|
||||
properties_new, properties_funcs);
|
||||
|
||||
if (!wplua_load_uri (L, URI_API, &error) ||
|
||||
!wplua_pcall (L, 0, 0, &error)) {
|
||||
|
|
|
|||
|
|
@ -217,6 +217,7 @@ SANDBOX_EXPORT = {
|
|||
Conf = WpConf,
|
||||
JsonUtils = JsonUtils,
|
||||
ProcUtils = ProcUtils,
|
||||
Properties = WpProperties_new,
|
||||
SimpleEventHook = WpSimpleEventHook_new,
|
||||
AsyncEventHook = WpAsyncEventHook_new,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,8 +29,9 @@ _wplua_gboxed___index (lua_State *L)
|
|||
GValue *obj_v = _wplua_togvalue_userdata_named (L, 1, G_TYPE_BOXED, "GBoxed");
|
||||
luaL_argcheck (L, obj_v != NULL, 1,
|
||||
"expected userdata storing GValue<GBoxed>");
|
||||
const gchar *key = luaL_checkstring (L, 2);
|
||||
const gchar *key = luaL_tolstring (L, 2, NULL);
|
||||
GType type = G_VALUE_TYPE (obj_v);
|
||||
GType boxed_type = type;
|
||||
lua_CFunction func = NULL;
|
||||
GHashTable *vtables;
|
||||
|
||||
|
|
@ -53,6 +54,99 @@ _wplua_gboxed___index (lua_State *L)
|
|||
lua_pushcfunction (L, func);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If WpProperties type, just return the property value for that key */
|
||||
if (boxed_type == WP_TYPE_PROPERTIES) {
|
||||
WpProperties * props = g_value_get_boxed (obj_v);
|
||||
const gchar *val = wp_properties_get (props, key);
|
||||
lua_pushstring (L, val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_wplua_gboxed___newindex (lua_State *L)
|
||||
{
|
||||
GValue *obj_v = _wplua_togvalue_userdata_named (L, 1, G_TYPE_BOXED, "GBoxed");
|
||||
luaL_argcheck (L, obj_v != NULL, 1,
|
||||
"expected userdata storing GValue<GBoxed>");
|
||||
const gchar *key = luaL_tolstring (L, 2, NULL);
|
||||
GType type = G_VALUE_TYPE (obj_v);
|
||||
|
||||
/* Set property value */
|
||||
if (type == WP_TYPE_PROPERTIES) {
|
||||
WpProperties * props = g_value_dup_boxed (obj_v);
|
||||
g_autofree gchar *val = NULL;
|
||||
luaL_checkany (L, 3);
|
||||
|
||||
switch (lua_type (L, 3)) {
|
||||
case LUA_TNIL:
|
||||
break;
|
||||
case LUA_TUSERDATA: {
|
||||
GValue *v = lua_touserdata (L, 3);
|
||||
gpointer p = g_value_peek_pointer (v);
|
||||
val = g_strdup_printf ("%p", p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
val = g_strdup (luaL_tolstring (L, 3, NULL));
|
||||
break;
|
||||
}
|
||||
|
||||
props = wp_properties_ensure_unique_owner (props);
|
||||
wp_properties_set (props, key, val);
|
||||
g_value_take_boxed (obj_v, props);
|
||||
} else {
|
||||
luaL_error (L, "cannot assign property '%s' to boxed type %s",
|
||||
key, g_type_name (type));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
properties_iterator_next (lua_State *L)
|
||||
{
|
||||
WpIterator *it = wplua_checkboxed (L, 1, WP_TYPE_ITERATOR);
|
||||
g_auto (GValue) item = G_VALUE_INIT;
|
||||
if (wp_iterator_next (it, &item)) {
|
||||
WpPropertiesItem *si = g_value_get_boxed (&item);
|
||||
const gchar *k = wp_properties_item_get_key (si);
|
||||
const gchar *v = wp_properties_item_get_value (si);
|
||||
lua_pushstring (L, k);
|
||||
lua_pushstring (L, v);
|
||||
return 2;
|
||||
} else {
|
||||
lua_pushnil (L);
|
||||
lua_pushnil (L);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
push_properties_wpiterator (lua_State *L, WpIterator *it)
|
||||
{
|
||||
lua_pushcfunction (L, properties_iterator_next);
|
||||
wplua_pushboxed (L, WP_TYPE_ITERATOR, it);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int
|
||||
_wplua_gboxed___pairs (lua_State *L)
|
||||
{
|
||||
GValue *obj_v = _wplua_togvalue_userdata_named (L, 1, G_TYPE_BOXED, "GBoxed");
|
||||
luaL_argcheck (L, obj_v != NULL, 1,
|
||||
"expected userdata storing GValue<GBoxed>");
|
||||
GType type = G_VALUE_TYPE (obj_v);
|
||||
|
||||
if (type == WP_TYPE_PROPERTIES) {
|
||||
WpProperties * props = g_value_get_boxed (obj_v);
|
||||
WpIterator *it = wp_properties_new_iterator (props);
|
||||
return push_properties_wpiterator (L, it);
|
||||
} else {
|
||||
luaL_error (L, "cannot do pairs of boxed type %s", g_type_name (type));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -69,6 +163,8 @@ _wplua_init_gboxed (lua_State *L)
|
|||
{ "__gc", _wplua_gvalue_userdata___gc },
|
||||
{ "__eq", _wplua_gboxed___eq },
|
||||
{ "__index", _wplua_gboxed___index },
|
||||
{ "__newindex", _wplua_gboxed___newindex },
|
||||
{ "__pairs", _wplua_gboxed___pairs },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -64,3 +64,9 @@ test(
|
|||
args: ['lua-api-tests', 'event-hooks.lua'],
|
||||
env: common_env,
|
||||
)
|
||||
test(
|
||||
'test-lua-properties',
|
||||
script_tester,
|
||||
args: ['lua-api-tests', 'properties.lua'],
|
||||
env: common_env,
|
||||
)
|
||||
|
|
|
|||
93
tests/wplua/scripts/properties.lua
Normal file
93
tests/wplua/scripts/properties.lua
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
-- create empty properties
|
||||
props = Properties ()
|
||||
|
||||
-- set nil
|
||||
props["key-nil"] = nil
|
||||
assert (props["key-nil"] == nil)
|
||||
|
||||
-- set bool
|
||||
props["key-bool"] = false
|
||||
assert (props["key-bool"] == "false")
|
||||
assert (props:get_boolean ("key-bool") == false)
|
||||
props["key-bool"] = true
|
||||
assert (props["key-bool"] == "true")
|
||||
assert (props:get_boolean ("key-bool") == true)
|
||||
|
||||
-- set int
|
||||
props["key-int"] = 4
|
||||
assert (props["key-int"] == "4")
|
||||
assert (props:get_int ("key-int") == 4)
|
||||
|
||||
-- set float
|
||||
props["key-float"] = 3.14
|
||||
val = props:get_float ("key-float")
|
||||
assert (val > 3.13 and val < 3.15)
|
||||
|
||||
-- set string
|
||||
props["key-string"] = "value"
|
||||
assert (props["key-string"] == "value")
|
||||
assert (props:get_boolean ("key-string") == false)
|
||||
assert (props:get_int ("key-string") == nil)
|
||||
assert (props:get_float ("key-string") == nil)
|
||||
|
||||
-- copy
|
||||
copy = props:copy ()
|
||||
assert (copy["key-nil"] == nil)
|
||||
assert (copy:get_boolean ("key-bool") == true)
|
||||
assert (copy:get_int ("key-int") == 4)
|
||||
val = copy:get_float ("key-float")
|
||||
assert (val > 3.13 and val < 3.15)
|
||||
assert (copy["key-string"] == "value")
|
||||
|
||||
-- remove int property
|
||||
props["key-int"] = nil
|
||||
assert (props["key-int"] == nil)
|
||||
assert (copy:get_int ("key-int") == 4)
|
||||
|
||||
-- create properties from table
|
||||
props = Properties {
|
||||
["key0"] = nil,
|
||||
["key1"] = false,
|
||||
["key2"] = 64,
|
||||
["key3"] = 2.71,
|
||||
["key4"] = "string",
|
||||
}
|
||||
assert (props["key0"] == nil)
|
||||
assert (props:get_boolean ("key1") == false)
|
||||
assert (props:get_int ("key2") == 64)
|
||||
val = props:get_float ("key3")
|
||||
assert (val > 2.70 and val < 2.72)
|
||||
assert (props["key4"] == "string")
|
||||
|
||||
-- count
|
||||
assert (props:get_count () == 4)
|
||||
|
||||
-- parse
|
||||
parsed = props:parse ()
|
||||
assert (parsed["key0"] == nil)
|
||||
assert (parsed["key1"] == "false")
|
||||
assert (tonumber (parsed["key2"]) == 64)
|
||||
val = tonumber (parsed["key3"])
|
||||
assert (val > 2.70 and val < 2.72)
|
||||
assert (parsed["key4"] == "string")
|
||||
|
||||
-- pairs
|
||||
values = {}
|
||||
for k, v in pairs (props) do
|
||||
values [k] = v
|
||||
end
|
||||
assert (values["key0"] == nil)
|
||||
assert (values["key1"] == "false")
|
||||
assert (tonumber (values["key2"]) == 64)
|
||||
val = tonumber (values["key3"])
|
||||
assert (val > 2.70 and val < 2.72)
|
||||
assert (values["key4"] == "string")
|
||||
|
||||
-- Make sure the reference changes are also updated
|
||||
local properties = Properties ()
|
||||
properties["key"] = "value"
|
||||
assert (properties["key"] == "value")
|
||||
local properties2 = properties
|
||||
properties2["key"] = "another-value"
|
||||
assert (properties2["key"] == "another-value")
|
||||
assert (properties["key"] == "another-value")
|
||||
Loading…
Add table
Reference in a new issue