
The intention is to make checks for enabled log topics faster. Every topic has its own structure that is statically defined in the file where the logs are printed from. The structure is initialized transparently when it is first used and it contains all the log level flags for the levels that this topic should print messages. It is then checked on the wp_log() macro before printing the message. Topics from SPA/PipeWire are also handled natively, so messages are printed directly without checking if the topic is enabled, since the PipeWire and SPA macros do the checking themselves. Messages coming from GLib are checked inside the handler. An internal WpLogFields object is used to manage the state of each log message, populating all the fields appropriately from the place they are coming from (wp_log, spa_log, glib log), formatting the message and then printing it. For printing to the journald, we still use the glib message handler, converting all the needed fields to GLogField on demand. That message handler does not do any checks for the topic or the level, so we can just call it to send the message.
1238 lines
32 KiB
C
1238 lines
32 KiB
C
/* WirePlumber
|
|
*
|
|
* Copyright © 2021 Collabora Ltd.
|
|
* @author Julian Bouzas <julian.bouzas@collabora.com>
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include <wp/wp.h>
|
|
#include <wplua/wplua.h>
|
|
|
|
#include <spa/utils/type.h>
|
|
|
|
#define WP_LOCAL_LOG_TOPIC log_topic_lua_scripting
|
|
WP_LOG_TOPIC_EXTERN (log_topic_lua_scripting)
|
|
|
|
#define MAX_LUA_TYPES 9
|
|
|
|
/* Builder */
|
|
|
|
typedef gboolean (*primitive_lua_add_func) (WpSpaPodBuilder *, WpSpaIdValue,
|
|
lua_State *, int);
|
|
|
|
struct primitive_lua_type {
|
|
WpSpaType primitive_type;
|
|
primitive_lua_add_func primitive_lua_add_funcs[MAX_LUA_TYPES];
|
|
};
|
|
|
|
static inline gboolean
|
|
builder_add_boolean_lua_boolean (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
wp_spa_pod_builder_add_boolean (b, lua_toboolean (L, idx));
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_boolean_lua_number (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
if (lua_isinteger (L, idx)) {
|
|
wp_spa_pod_builder_add_boolean (b, lua_tointeger (L, idx) > 0);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_boolean_lua_string (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
const gchar *value = lua_tostring (L, idx);
|
|
wp_spa_pod_builder_add_boolean (b,
|
|
g_strcmp0 (value, "true") == 0 || g_strcmp0 (value, "1") == 0);
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_id_lua_number (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
if (lua_isinteger (L, idx)) {
|
|
wp_spa_pod_builder_add_id (b, lua_tointeger (L, idx));
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_id_lua_string (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
const gchar *value = lua_tostring (L, idx);
|
|
WpSpaIdTable id_table = NULL;
|
|
WpSpaIdValue id_val = NULL;
|
|
if (key_id) {
|
|
wp_spa_id_value_get_value_type (key_id, &id_table);
|
|
if (id_table) {
|
|
id_val = wp_spa_id_table_find_value_from_short_name (id_table, value);
|
|
wp_spa_pod_builder_add_id (b, wp_spa_id_value_number (id_val));
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_int_lua_boolean (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
gboolean value = lua_toboolean (L, idx);
|
|
wp_spa_pod_builder_add_int (b, value ? 1 : 0);
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_int_lua_number (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
if (lua_isinteger (L, idx)) {
|
|
wp_spa_pod_builder_add_int (b, lua_tointeger (L, idx));
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_int_lua_string (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
const gchar *value = lua_tostring (L, idx);
|
|
wp_spa_pod_builder_add_int (b, strtol (value, NULL, 10));
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_long_lua_boolean (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
gboolean value = lua_toboolean (L, idx);
|
|
wp_spa_pod_builder_add_long (b, value ? 1 : 0);
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_long_lua_number (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
if (lua_isinteger (L, idx)) {
|
|
wp_spa_pod_builder_add_long (b, lua_tointeger (L, idx));
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_long_lua_string (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
const gchar *value = lua_tostring (L, idx);
|
|
wp_spa_pod_builder_add_long (b, strtol (value, NULL, 10));
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_float_lua_boolean (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
gboolean value = lua_toboolean (L, idx);
|
|
wp_spa_pod_builder_add_float (b, value ? 1.0f : 0.0f);
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_float_lua_number (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
if (lua_isnumber (L, idx) && !lua_isinteger (L, idx)) {
|
|
wp_spa_pod_builder_add_float (b, lua_tonumber (L, idx));
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_double_lua_boolean (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
gboolean value = lua_toboolean (L, idx);
|
|
wp_spa_pod_builder_add_double (b, value ? 1.0f : 0.0f);
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_double_lua_number (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
if (lua_isnumber (L, idx) && !lua_isinteger (L, idx)) {
|
|
wp_spa_pod_builder_add_double (b, lua_tonumber (L, idx));
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_string_lua_boolean (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
gboolean value = lua_toboolean (L, idx);
|
|
wp_spa_pod_builder_add_string (b, value ? "true" : "false");
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_string_lua_number (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
g_autofree gchar *value = NULL;
|
|
value = lua_isinteger (L, idx) ?
|
|
g_strdup_printf ("%lld", lua_tointeger (L, idx)) :
|
|
g_strdup_printf ("%f", lua_tonumber (L, idx));
|
|
wp_spa_pod_builder_add_string (b, value);
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_string_lua_string (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
const gchar *value = lua_tostring (L, idx);
|
|
wp_spa_pod_builder_add_string (b, value);
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_bytes_lua_number (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
if (lua_isinteger (L, idx)) {
|
|
gint64 value = lua_tointeger (L, idx);
|
|
wp_spa_pod_builder_add_bytes (b, (gconstpointer)&value, sizeof (value));
|
|
} else {
|
|
double value = lua_tonumber (L, idx);
|
|
wp_spa_pod_builder_add_bytes (b, (gconstpointer)&value, sizeof (value));
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_bytes_lua_string (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
const gchar *value = lua_tostring (L, idx);
|
|
wp_spa_pod_builder_add_bytes (b, (gconstpointer)value, strlen (value));
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_fd_lua_number (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
if (lua_isinteger (L, idx)) {
|
|
wp_spa_pod_builder_add_fd (b, lua_tointeger (L, idx));
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_fd_lua_string (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
const gchar *value = lua_tostring (L, idx);
|
|
wp_spa_pod_builder_add_fd (b, strtol (value, NULL, 10));
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
is_pod_type_compatible (WpSpaType type, WpSpaPod *pod)
|
|
{
|
|
/* Check if the pod type matches */
|
|
if (type == wp_spa_pod_get_spa_type (pod))
|
|
return TRUE;
|
|
|
|
/* Otherwise, check if the child type of Choice pod matches */
|
|
if (wp_spa_pod_is_choice (pod)) {
|
|
g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (pod);
|
|
WpSpaType child_type = wp_spa_pod_get_spa_type (child);
|
|
if (type == child_type)
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
builder_add_lua_userdata (WpSpaPodBuilder *b, WpSpaIdValue key_id,
|
|
lua_State *L, int idx)
|
|
{
|
|
WpSpaPod *pod = wplua_checkboxed (L, idx, WP_TYPE_SPA_POD);
|
|
if (pod) {
|
|
if (key_id) {
|
|
WpSpaType prop_type = wp_spa_id_value_get_value_type (key_id, NULL);
|
|
if (is_pod_type_compatible (prop_type, pod)) {
|
|
wp_spa_pod_builder_add_pod (b, pod);
|
|
return TRUE;
|
|
}
|
|
} else {
|
|
wp_spa_pod_builder_add_pod (b, pod);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static const struct primitive_lua_type primitive_lua_types[] = {
|
|
{SPA_TYPE_Bool, {
|
|
[LUA_TBOOLEAN] = builder_add_boolean_lua_boolean,
|
|
[LUA_TNUMBER] = builder_add_boolean_lua_number,
|
|
[LUA_TSTRING] = builder_add_boolean_lua_string,
|
|
}},
|
|
{SPA_TYPE_Id, {
|
|
[LUA_TNUMBER] = builder_add_id_lua_number,
|
|
[LUA_TSTRING] = builder_add_id_lua_string,
|
|
}},
|
|
{SPA_TYPE_Int, {
|
|
[LUA_TBOOLEAN] = builder_add_int_lua_boolean,
|
|
[LUA_TNUMBER] = builder_add_int_lua_number,
|
|
[LUA_TSTRING] = builder_add_int_lua_string,
|
|
}},
|
|
{SPA_TYPE_Long, {
|
|
[LUA_TBOOLEAN] = builder_add_long_lua_boolean,
|
|
[LUA_TNUMBER] = builder_add_long_lua_number,
|
|
[LUA_TSTRING] = builder_add_long_lua_string,
|
|
}},
|
|
{SPA_TYPE_Float, {
|
|
[LUA_TBOOLEAN] = builder_add_float_lua_boolean,
|
|
[LUA_TNUMBER] = builder_add_float_lua_number,
|
|
}},
|
|
{SPA_TYPE_Double, {
|
|
[LUA_TBOOLEAN] = builder_add_double_lua_boolean,
|
|
[LUA_TNUMBER] = builder_add_double_lua_number,
|
|
}},
|
|
{SPA_TYPE_String, {
|
|
[LUA_TBOOLEAN] = builder_add_string_lua_boolean,
|
|
[LUA_TNUMBER] = builder_add_string_lua_number,
|
|
[LUA_TSTRING] = builder_add_string_lua_string,
|
|
}},
|
|
{SPA_TYPE_Bytes, {
|
|
[LUA_TNUMBER] = builder_add_bytes_lua_number,
|
|
[LUA_TSTRING] = builder_add_bytes_lua_string,
|
|
}},
|
|
{SPA_TYPE_Fd, {
|
|
[LUA_TNUMBER] = builder_add_fd_lua_number,
|
|
[LUA_TSTRING] = builder_add_fd_lua_string,
|
|
}},
|
|
{0, {}},
|
|
};
|
|
|
|
static gboolean
|
|
builder_add_key (WpSpaPodBuilder *b, WpSpaIdTable table, lua_State *L, int idx)
|
|
{
|
|
/* Number */
|
|
if (lua_type (L, -1) == LUA_TNUMBER) {
|
|
wp_spa_pod_builder_add_id (b, lua_tonumber (L, idx));
|
|
return TRUE;
|
|
}
|
|
|
|
/* String */
|
|
else if (lua_type (L, -1) == LUA_TSTRING) {
|
|
const gchar *key = lua_tostring (L, idx);
|
|
WpSpaIdValue val = wp_spa_id_table_find_value_from_short_name (table, key);
|
|
if (val) {
|
|
wp_spa_pod_builder_add_id (b, wp_spa_id_value_number (val));
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
builder_add_value (WpSpaPodBuilder *b, WpSpaType array_type, lua_State *L,
|
|
int idx)
|
|
{
|
|
int ltype = lua_type (L, idx);
|
|
guint i;
|
|
|
|
if (ltype < 0 || ltype >= MAX_LUA_TYPES)
|
|
return FALSE;
|
|
|
|
for (i = 0; primitive_lua_types[i].primitive_type; i++) {
|
|
const struct primitive_lua_type *t = primitive_lua_types + i;
|
|
if (t->primitive_type == array_type) {
|
|
primitive_lua_add_func f = t->primitive_lua_add_funcs[ltype];
|
|
if (f) {
|
|
return f (b, NULL, L, idx);
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
builder_add_table (lua_State *L, WpSpaPodBuilder *builder)
|
|
{
|
|
const gchar *type_name = NULL;
|
|
WpSpaType type = WP_SPA_TYPE_INVALID;
|
|
WpSpaIdTable table = NULL;
|
|
|
|
luaL_checktype (L, 1, LUA_TTABLE);
|
|
|
|
lua_pushnil (L);
|
|
while (lua_next (L, 1)) {
|
|
/* First filed is always the item type or table */
|
|
if (type == WP_SPA_TYPE_INVALID && !table) {
|
|
if (lua_type (L, -1) == LUA_TSTRING) {
|
|
type_name = lua_tostring (L, -1);
|
|
type = wp_spa_type_from_name (type_name);
|
|
if (type == WP_SPA_TYPE_INVALID) {
|
|
table = wp_spa_id_table_from_name (type_name);
|
|
if (!table)
|
|
luaL_error (L, "Unknown type '%s'", type_name);
|
|
}
|
|
} else {
|
|
luaL_error (L,
|
|
"must have the item type or table on its first field");
|
|
}
|
|
}
|
|
|
|
/* Add remaining table key elements */
|
|
else if (table) {
|
|
if (!builder_add_key (builder, table, L, -1))
|
|
luaL_error (L, "key could not be added");
|
|
}
|
|
|
|
/* Add remaining value elements */
|
|
else if (type != WP_SPA_TYPE_INVALID) {
|
|
if (!builder_add_value (builder, type, L, -1))
|
|
luaL_error (L, "value could not be added");
|
|
}
|
|
|
|
lua_pop (L, 1);
|
|
}
|
|
}
|
|
|
|
/* None */
|
|
|
|
static int
|
|
spa_pod_none_new (lua_State *L)
|
|
{
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_new_none ());
|
|
return 1;
|
|
}
|
|
|
|
/* Boolean */
|
|
|
|
static int
|
|
spa_pod_boolean_new (lua_State *L)
|
|
{
|
|
gboolean value = lua_toboolean (L, 1);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_new_boolean (value));
|
|
return 1;
|
|
}
|
|
|
|
/* Id */
|
|
|
|
static int
|
|
spa_pod_id_new (lua_State *L)
|
|
{
|
|
/* Id number */
|
|
if (lua_type (L, 1) == LUA_TNUMBER) {
|
|
gint64 value = lua_tointeger (L, 1);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_new_id (value));
|
|
return 1;
|
|
}
|
|
|
|
/* Table name and key name */
|
|
else if (lua_type (L, 1) == LUA_TSTRING) {
|
|
const gchar *table_name = lua_tostring (L, 1);
|
|
const gchar *key_name = lua_tostring (L, 2);
|
|
WpSpaIdTable table = NULL;
|
|
WpSpaIdValue value = NULL;
|
|
table = wp_spa_id_table_from_name (table_name);
|
|
if (!table)
|
|
luaL_error (L, "table '%s' does not exist", table_name);
|
|
value = wp_spa_id_table_find_value_from_short_name (table, key_name);
|
|
if (!value)
|
|
luaL_error (L, "key '%s' does not exist in '%s'", key_name, table_name);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD,
|
|
wp_spa_pod_new_id (wp_spa_id_value_number (value)));
|
|
return 1;
|
|
}
|
|
|
|
/* Error */
|
|
luaL_error (L, "Invalid parameters");
|
|
return 0;
|
|
}
|
|
|
|
/* Int */
|
|
|
|
static int
|
|
spa_pod_int_new (lua_State *L)
|
|
{
|
|
gint64 value = lua_tointeger (L, 1);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_new_int (value));
|
|
return 1;
|
|
}
|
|
|
|
/* Long */
|
|
|
|
static int
|
|
spa_pod_long_new (lua_State *L)
|
|
{
|
|
gint64 value = lua_tointeger (L, 1);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_new_long (value));
|
|
return 1;
|
|
}
|
|
|
|
/* Float */
|
|
|
|
static int
|
|
spa_pod_float_new (lua_State *L)
|
|
{
|
|
float value = lua_tonumber (L, 1);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_new_float (value));
|
|
return 1;
|
|
}
|
|
|
|
/* Double */
|
|
|
|
static int
|
|
spa_pod_double_new (lua_State *L)
|
|
{
|
|
double value = lua_tonumber (L, 1);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_new_double (value));
|
|
return 1;
|
|
}
|
|
|
|
/* String */
|
|
|
|
static int
|
|
spa_pod_string_new (lua_State *L)
|
|
{
|
|
const gchar *value = lua_tostring (L, 1);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_new_string (value));
|
|
return 1;
|
|
}
|
|
|
|
/* Bytes */
|
|
|
|
static int
|
|
spa_pod_bytes_new (lua_State *L)
|
|
{
|
|
switch (lua_type (L, 1)) {
|
|
case LUA_TNUMBER: {
|
|
if (lua_isinteger (L, 1)) {
|
|
guint64 value = lua_tointeger (L, 1);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD,
|
|
wp_spa_pod_new_bytes (&value, sizeof (guint64)));
|
|
} else {
|
|
double value = lua_tonumber (L, 1);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD,
|
|
wp_spa_pod_new_bytes (&value, sizeof (double)));
|
|
}
|
|
return 1;
|
|
}
|
|
case LUA_TSTRING: {
|
|
const gchar *str = lua_tostring (L, 1);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD,
|
|
wp_spa_pod_new_bytes (str, strlen (str)));
|
|
return 1;
|
|
}
|
|
default:
|
|
luaL_error (L, "Only number and strings are valid for bytes pod");
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Pointer */
|
|
|
|
static int
|
|
spa_pod_pointer_new (lua_State *L)
|
|
{
|
|
const gchar *type = lua_tostring (L, 1);
|
|
gconstpointer value = lua_touserdata (L, 2);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_new_pointer (type, value));
|
|
return 1;
|
|
}
|
|
|
|
/* Fd */
|
|
|
|
static int
|
|
spa_pod_fd_new (lua_State *L)
|
|
{
|
|
gint64 value = lua_tointeger (L, 1);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_new_fd (value));
|
|
return 1;
|
|
}
|
|
|
|
/* Rectangle */
|
|
|
|
static int
|
|
spa_pod_rectangle_new (lua_State *L)
|
|
{
|
|
gint64 width = lua_tointeger (L, 1);
|
|
gint64 height = lua_tointeger (L, 2);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD,
|
|
wp_spa_pod_new_rectangle (width, height));
|
|
return 1;
|
|
}
|
|
|
|
/* Fraction */
|
|
|
|
static int
|
|
spa_pod_fraction_new (lua_State *L)
|
|
{
|
|
gint64 num = lua_tointeger (L, 1);
|
|
gint64 denom = lua_tointeger (L, 2);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_new_fraction (num, denom));
|
|
return 1;
|
|
}
|
|
|
|
|
|
/* Object */
|
|
|
|
static gboolean
|
|
object_add_property (WpSpaPodBuilder *b, WpSpaIdTable table,
|
|
const gchar *key, lua_State *L, int idx)
|
|
{
|
|
guint i;
|
|
WpSpaIdValue prop_id = NULL;
|
|
int ltype = lua_type (L, idx);
|
|
|
|
if (ltype < 0 || ltype >= MAX_LUA_TYPES)
|
|
return FALSE;
|
|
|
|
/* Check if we can add primitive property directly from LUA type */
|
|
prop_id = wp_spa_id_table_find_value_from_short_name (table, key);
|
|
if (prop_id) {
|
|
WpSpaType prop_type = wp_spa_id_value_get_value_type (prop_id, NULL);
|
|
if (prop_type != WP_SPA_TYPE_INVALID) {
|
|
for (i = 0; primitive_lua_types[i].primitive_type; i++) {
|
|
const struct primitive_lua_type *t = primitive_lua_types + i;
|
|
if (t->primitive_type == prop_type) {
|
|
primitive_lua_add_func f = t->primitive_lua_add_funcs[ltype];
|
|
if (f) {
|
|
wp_spa_pod_builder_add_property (b, key);
|
|
return f (b, prop_id, L, idx);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Otherwise just add pod property */
|
|
if (lua_type (L, idx) == LUA_TUSERDATA) {
|
|
wp_spa_pod_builder_add_property (b, key);
|
|
return builder_add_lua_userdata (b, prop_id, L, idx);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int
|
|
spa_pod_object_new (lua_State *L)
|
|
{
|
|
g_autoptr (WpSpaPodBuilder) builder = NULL;
|
|
const gchar *fields[2] = { NULL, NULL }; // type_name, name_id
|
|
WpSpaType object_type = WP_SPA_TYPE_INVALID;
|
|
WpSpaIdTable table = NULL;
|
|
|
|
luaL_checktype (L, 1, LUA_TTABLE);
|
|
|
|
lua_geti (L, 1, 1);
|
|
fields[0] = lua_tostring (L, -1);
|
|
lua_geti (L, 1, 2);
|
|
fields[1] = lua_tostring (L, -1);
|
|
|
|
object_type = wp_spa_type_from_name (fields[0]);
|
|
if (object_type == WP_SPA_TYPE_INVALID)
|
|
luaL_error (L, "Invalid object type '%s'", fields[0]);
|
|
|
|
table = wp_spa_type_get_values_table (object_type);
|
|
if (!table)
|
|
luaL_error (L, "Object type '%s' has incomplete type information",
|
|
fields[0]);
|
|
|
|
builder = wp_spa_pod_builder_new_object (fields[0], fields[1]);
|
|
if (!builder)
|
|
luaL_error (L, "Could not create pod object");
|
|
|
|
lua_pop (L, 2);
|
|
|
|
lua_pushnil(L);
|
|
while (lua_next (L, -2)) {
|
|
/* Remaining fields with string keys are the object properties */
|
|
if (lua_type (L, -2) == LUA_TSTRING) {
|
|
const gchar *key = lua_tostring (L, -2);
|
|
if (!object_add_property (builder, table, key, L, -1))
|
|
luaL_error (L, "Property '%s' could not be added", key);
|
|
}
|
|
|
|
lua_pop (L, 1);
|
|
}
|
|
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_builder_end (builder));
|
|
return 1;
|
|
}
|
|
|
|
/* Struct */
|
|
|
|
static int
|
|
spa_pod_struct_new (lua_State *L)
|
|
{
|
|
g_autoptr (WpSpaPodBuilder) builder = NULL;
|
|
|
|
luaL_checktype (L, 1, LUA_TTABLE);
|
|
|
|
builder = wp_spa_pod_builder_new_struct ();
|
|
|
|
lua_pushnil (L);
|
|
while (lua_next (L, 1)) {
|
|
switch (lua_type (L, -1)) {
|
|
case LUA_TBOOLEAN:
|
|
wp_spa_pod_builder_add_boolean (builder, lua_toboolean (L, -1));
|
|
break;
|
|
case LUA_TNUMBER:
|
|
if (lua_isinteger (L, -1))
|
|
wp_spa_pod_builder_add_long (builder, lua_tointeger (L, -1));
|
|
else
|
|
wp_spa_pod_builder_add_double (builder, lua_tonumber (L, -1));
|
|
break;
|
|
case LUA_TSTRING:
|
|
wp_spa_pod_builder_add_string (builder, lua_tostring (L, -1));
|
|
break;
|
|
case LUA_TUSERDATA: {
|
|
WpSpaPod *pod = wplua_checkboxed (L, -1, WP_TYPE_SPA_POD);
|
|
wp_spa_pod_builder_add_pod (builder, pod);
|
|
break;
|
|
}
|
|
default:
|
|
luaL_error (L, "Struct does not support lua type ",
|
|
lua_typename(L, lua_type(L, -1)));
|
|
break;
|
|
}
|
|
lua_pop (L, 1);
|
|
}
|
|
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_builder_end (builder));
|
|
return 1;
|
|
}
|
|
|
|
/* Sequence */
|
|
|
|
static int
|
|
spa_pod_sequence_new (lua_State *L)
|
|
{
|
|
g_autoptr (WpSpaPodBuilder) builder = NULL;
|
|
|
|
luaL_checktype (L, 1, LUA_TTABLE);
|
|
|
|
builder = wp_spa_pod_builder_new_sequence (0);
|
|
|
|
lua_pushnil (L);
|
|
while (lua_next (L, -2)) {
|
|
guint32 offset = 0;
|
|
const gchar *type_name = NULL;
|
|
WpSpaPod *value = NULL;
|
|
|
|
/* Read Control */
|
|
if (lua_istable(L, -1)) {
|
|
lua_pushnil (L);
|
|
while (lua_next (L, -2)) {
|
|
const gchar *key = lua_tostring (L, -2);
|
|
if (g_strcmp0 (key, "offset") == 0) {
|
|
offset = lua_tointeger (L, -1);
|
|
} else if (!type_name && g_strcmp0 (key, "typename") == 0) {
|
|
type_name = lua_tostring (L, -1);
|
|
} else if (!value && g_strcmp0 (key, "value") == 0) {
|
|
switch (lua_type (L, -1)) {
|
|
case LUA_TBOOLEAN:
|
|
value = wp_spa_pod_new_boolean (lua_toboolean (L, -1));
|
|
break;
|
|
case LUA_TNUMBER:
|
|
if (lua_isinteger (L, -1))
|
|
value = wp_spa_pod_new_long (lua_tointeger (L, -1));
|
|
else
|
|
value = wp_spa_pod_new_double (lua_tonumber (L, -1));
|
|
break;
|
|
case LUA_TSTRING:
|
|
value = wp_spa_pod_new_string (lua_tostring (L, -1));
|
|
break;
|
|
case LUA_TUSERDATA: {
|
|
value = wplua_checkboxed (L, -1, WP_TYPE_SPA_POD);
|
|
break;
|
|
}
|
|
default: {
|
|
luaL_error (L, "Control value does not support lua type ",
|
|
lua_typename(L, lua_type(L, -1)));
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
lua_pop(L, 1);
|
|
}
|
|
}
|
|
|
|
/* Add control */
|
|
if (type_name && value) {
|
|
wp_spa_pod_builder_add_control (builder, offset, type_name);
|
|
wp_spa_pod_builder_add_pod (builder, value);
|
|
wp_spa_pod_unref (value);
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
}
|
|
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_builder_end (builder));
|
|
return 1;
|
|
}
|
|
|
|
/* Array */
|
|
|
|
static int
|
|
spa_pod_array_new (lua_State *L)
|
|
{
|
|
g_autoptr (WpSpaPodBuilder) builder = wp_spa_pod_builder_new_array ();
|
|
builder_add_table (L, builder);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_builder_end (builder));
|
|
return 1;
|
|
}
|
|
|
|
/* Choice */
|
|
|
|
static int
|
|
spa_pod_choice_none_new (lua_State *L)
|
|
{
|
|
g_autoptr (WpSpaPodBuilder) builder = wp_spa_pod_builder_new_choice ("None");
|
|
builder_add_table (L, builder);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_builder_end (builder));
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
spa_pod_choice_range_new (lua_State *L)
|
|
{
|
|
g_autoptr (WpSpaPodBuilder) builder = wp_spa_pod_builder_new_choice ("Range");
|
|
builder_add_table (L, builder);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_builder_end (builder));
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
spa_pod_choice_step_new (lua_State *L)
|
|
{
|
|
g_autoptr (WpSpaPodBuilder) builder = wp_spa_pod_builder_new_choice ("Step");
|
|
builder_add_table (L, builder);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_builder_end (builder));
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
spa_pod_choice_enum_new (lua_State *L)
|
|
{
|
|
g_autoptr (WpSpaPodBuilder) builder = wp_spa_pod_builder_new_choice ("Enum");
|
|
builder_add_table (L, builder);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_builder_end (builder));
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
spa_pod_choice_flags_new (lua_State *L)
|
|
{
|
|
g_autoptr (WpSpaPodBuilder) builder = wp_spa_pod_builder_new_choice ("Flags");
|
|
builder_add_table (L, builder);
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, wp_spa_pod_builder_end (builder));
|
|
return 1;
|
|
}
|
|
|
|
/* API */
|
|
|
|
static int
|
|
spa_pod_get_type_name (lua_State *L)
|
|
{
|
|
WpSpaPod *pod = wplua_checkboxed (L, 1, WP_TYPE_SPA_POD);
|
|
lua_pushstring (L, wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
|
|
return 1;
|
|
}
|
|
|
|
static void
|
|
push_primitive_values (lua_State *L, WpSpaPod *pod, WpSpaType type,
|
|
guint start_index, WpSpaIdTable idtable)
|
|
{
|
|
g_auto (GValue) item = G_VALUE_INIT;
|
|
g_autoptr (WpIterator) it = wp_spa_pod_new_iterator (pod);
|
|
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
|
|
gpointer p = g_value_get_pointer (&item);
|
|
if (!p)
|
|
continue;
|
|
switch (type) {
|
|
case SPA_TYPE_Bool:
|
|
lua_pushboolean (L, *(gboolean *)p);
|
|
break;
|
|
case SPA_TYPE_Id: {
|
|
WpSpaIdValue idval = NULL;
|
|
if (idtable)
|
|
idval = wp_spa_id_table_find_value (idtable, *(guint32 *)p);
|
|
if (idval)
|
|
lua_pushstring (L, wp_spa_id_value_short_name (idval));
|
|
else
|
|
lua_pushinteger (L, *(guint32 *)p);
|
|
break;
|
|
}
|
|
case SPA_TYPE_Int:
|
|
lua_pushinteger (L, *(gint *)p);
|
|
break;
|
|
case SPA_TYPE_Long:
|
|
lua_pushinteger (L, *(long *)p);
|
|
break;
|
|
case SPA_TYPE_Float:
|
|
lua_pushnumber (L, *(float *)p);
|
|
break;
|
|
case SPA_TYPE_Double:
|
|
lua_pushnumber (L, *(double *)p);
|
|
break;
|
|
case SPA_TYPE_Fd:
|
|
lua_pushnumber (L, *(gint64 *)p);
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
lua_rawseti (L, -2, start_index++);
|
|
}
|
|
}
|
|
|
|
static void
|
|
push_luapod (lua_State *L, WpSpaPod *pod, WpSpaIdValue field_idval)
|
|
{
|
|
/* None */
|
|
if (wp_spa_pod_is_none (pod)) {
|
|
lua_pushnil (L);
|
|
}
|
|
|
|
/* Boolean */
|
|
else if (wp_spa_pod_is_boolean (pod)) {
|
|
gboolean value = FALSE;
|
|
g_warn_if_fail (wp_spa_pod_get_boolean (pod, &value));
|
|
lua_pushboolean (L, value);
|
|
}
|
|
|
|
/* Id */
|
|
else if (wp_spa_pod_is_id (pod)) {
|
|
guint32 value = 0;
|
|
WpSpaIdTable idtable = NULL;
|
|
WpSpaIdValue idval = NULL;
|
|
g_warn_if_fail (wp_spa_pod_get_id (pod, &value));
|
|
if (field_idval && SPA_TYPE_Id ==
|
|
wp_spa_id_value_get_value_type (field_idval, &idtable)) {
|
|
idval = wp_spa_id_table_find_value (idtable, value);
|
|
}
|
|
if (idval)
|
|
lua_pushstring (L, wp_spa_id_value_short_name (idval));
|
|
else
|
|
lua_pushinteger (L, value);
|
|
}
|
|
|
|
/* Int */
|
|
else if (wp_spa_pod_is_int (pod)) {
|
|
gint value = 0;
|
|
g_warn_if_fail (wp_spa_pod_get_int (pod, &value));
|
|
lua_pushinteger (L, value);
|
|
}
|
|
|
|
/* Long */
|
|
else if (wp_spa_pod_is_long (pod)) {
|
|
gint64 value = 0;
|
|
wp_spa_pod_get_long (pod, &value);
|
|
lua_pushinteger (L, value);
|
|
}
|
|
|
|
/* Float */
|
|
else if (wp_spa_pod_is_float (pod)) {
|
|
float value = 0;
|
|
g_warn_if_fail (wp_spa_pod_get_float (pod, &value));
|
|
lua_pushnumber (L, value);
|
|
}
|
|
|
|
/* Double */
|
|
else if (wp_spa_pod_is_double (pod)) {
|
|
double value = 0;
|
|
g_warn_if_fail (wp_spa_pod_get_double (pod, &value));
|
|
lua_pushnumber (L, value);
|
|
}
|
|
|
|
/* String */
|
|
else if (wp_spa_pod_is_string (pod)) {
|
|
const gchar *value = NULL;
|
|
g_warn_if_fail (wp_spa_pod_get_string (pod, &value));
|
|
lua_pushstring (L, value);
|
|
}
|
|
|
|
/* Bytes */
|
|
else if (wp_spa_pod_is_bytes (pod)) {
|
|
gconstpointer value = NULL;
|
|
guint32 size = 0;
|
|
g_warn_if_fail (wp_spa_pod_get_bytes (pod, &value, &size));
|
|
char str[size + 1];
|
|
for (guint i = 0; i < size; i++)
|
|
str[i] = ((const gchar *)value)[i];
|
|
str[size] = '\0';
|
|
lua_pushstring (L, str);
|
|
}
|
|
|
|
/* Pointer */
|
|
else if (wp_spa_pod_is_pointer (pod)) {
|
|
gconstpointer value = NULL;
|
|
g_warn_if_fail (wp_spa_pod_get_pointer (pod, &value));
|
|
if (!value)
|
|
lua_pushnil (L);
|
|
else
|
|
lua_pushlightuserdata (L, (gpointer)value);
|
|
}
|
|
|
|
/* Fd */
|
|
else if (wp_spa_pod_is_fd (pod)) {
|
|
gint64 value = 0;
|
|
g_warn_if_fail (wp_spa_pod_get_fd (pod, &value));
|
|
lua_pushinteger (L, value);
|
|
}
|
|
|
|
/* Rectangle */
|
|
else if (wp_spa_pod_is_rectangle (pod)) {
|
|
guint32 width = 0, height = 0;
|
|
g_warn_if_fail (wp_spa_pod_get_rectangle (pod, &width, &height));
|
|
lua_newtable (L);
|
|
lua_pushstring (L, "Rectangle");
|
|
lua_setfield (L, -2, "pod_type");
|
|
lua_pushinteger (L, width);
|
|
lua_setfield (L, -2, "width");
|
|
lua_pushinteger (L, height);
|
|
lua_setfield (L, -2, "height");
|
|
}
|
|
|
|
/* Fraction */
|
|
else if (wp_spa_pod_is_fraction (pod)) {
|
|
guint32 num = 0, denom = 0;
|
|
g_warn_if_fail (wp_spa_pod_get_fraction (pod, &num, &denom));
|
|
lua_newtable (L);
|
|
lua_pushstring (L, "Fraction");
|
|
lua_setfield (L, -2, "pod_type");
|
|
lua_pushinteger (L, num);
|
|
lua_setfield (L, -2, "num");
|
|
lua_pushinteger (L, denom);
|
|
lua_setfield (L, -2, "denom");
|
|
}
|
|
|
|
/* Object */
|
|
else if (wp_spa_pod_is_object (pod)) {
|
|
WpSpaType type = wp_spa_pod_get_spa_type (pod);
|
|
WpSpaIdTable values_table = wp_spa_type_get_values_table (type);
|
|
const gchar *id_name = NULL;
|
|
g_auto (GValue) item = G_VALUE_INIT;
|
|
g_autoptr (WpIterator) it = NULL;
|
|
g_warn_if_fail (wp_spa_pod_get_object (pod, &id_name, NULL));
|
|
lua_newtable (L);
|
|
lua_pushstring (L, "Object");
|
|
lua_setfield (L, -2, "pod_type");
|
|
lua_pushstring (L, id_name);
|
|
lua_setfield (L, -2, "object_id");
|
|
it = wp_spa_pod_new_iterator (pod);
|
|
lua_newtable (L);
|
|
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
|
|
WpSpaPod *prop = g_value_get_boxed (&item);
|
|
const gchar *key = NULL;
|
|
g_autoptr (WpSpaPod) val = NULL;
|
|
//FIXME: this is suboptimal because _get_property() converts
|
|
// the key to a short name and we convert it back
|
|
g_warn_if_fail (wp_spa_pod_get_property (prop, &key, &val));
|
|
if (key) {
|
|
push_luapod (L, val,
|
|
wp_spa_id_table_find_value_from_short_name (values_table, key));
|
|
lua_setfield (L, -2, key);
|
|
}
|
|
}
|
|
lua_setfield (L, -2, "properties");
|
|
}
|
|
|
|
/* Struct */
|
|
else if (wp_spa_pod_is_struct (pod)) {
|
|
g_auto (GValue) item = G_VALUE_INIT;
|
|
g_autoptr (WpIterator) it = wp_spa_pod_new_iterator (pod);
|
|
guint i = 1;
|
|
lua_newtable (L);
|
|
lua_pushstring (L, "Struct");
|
|
lua_setfield (L, -2, "pod_type");
|
|
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
|
|
WpSpaPod *val = g_value_get_boxed (&item);
|
|
push_luapod (L, val, NULL);
|
|
lua_rawseti (L, -2, i++);
|
|
}
|
|
}
|
|
|
|
/* Sequence */
|
|
else if (wp_spa_pod_is_sequence (pod)) {
|
|
g_auto (GValue) item = G_VALUE_INIT;
|
|
g_autoptr (WpIterator) it = wp_spa_pod_new_iterator (pod);
|
|
guint i = 1;
|
|
lua_newtable (L);
|
|
lua_pushstring (L, "Sequence");
|
|
lua_setfield (L, -2, "pod_type");
|
|
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
|
|
WpSpaPod *control = g_value_get_boxed (&item);
|
|
guint32 offset = 0;
|
|
const char *type_name = NULL;
|
|
g_autoptr (WpSpaPod) val = NULL;
|
|
g_warn_if_fail (wp_spa_pod_get_control (control, &offset, &type_name,
|
|
&val));
|
|
lua_newtable (L);
|
|
lua_pushinteger (L, offset);
|
|
lua_setfield (L, -2, "offset");
|
|
lua_pushstring (L, type_name);
|
|
lua_setfield (L, -2, "typename");
|
|
push_luapod (L, val, NULL);
|
|
lua_setfield (L, -2, "value");
|
|
lua_rawseti (L, -2, i++);
|
|
}
|
|
}
|
|
|
|
/* Array */
|
|
else if (wp_spa_pod_is_array (pod)) {
|
|
g_autoptr (WpSpaPod) child = wp_spa_pod_get_array_child (pod);
|
|
WpSpaType type = wp_spa_pod_get_spa_type (child);
|
|
WpSpaIdTable idtable = NULL;
|
|
if (field_idval && type == SPA_TYPE_Id && SPA_TYPE_Array ==
|
|
wp_spa_id_value_get_value_type (field_idval, &idtable))
|
|
wp_spa_id_value_array_get_item_type (field_idval, &idtable);
|
|
lua_newtable (L);
|
|
lua_pushstring (L, "Array");
|
|
lua_setfield (L, -2, "pod_type");
|
|
lua_pushstring (L, wp_spa_type_name (type));
|
|
lua_setfield (L, -2, "value_type");
|
|
push_primitive_values (L, pod, type, 1, idtable);
|
|
}
|
|
|
|
/* Choice */
|
|
else if (wp_spa_pod_is_choice (pod)) {
|
|
g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (pod);
|
|
WpSpaType type = wp_spa_pod_get_spa_type (child);
|
|
g_autofree const gchar *choice_type = g_strdup_printf ("Choice.%s",
|
|
wp_spa_id_value_short_name (wp_spa_pod_get_choice_type (pod)));
|
|
WpSpaIdTable idtable = NULL;
|
|
if (field_idval && type == SPA_TYPE_Id)
|
|
wp_spa_id_value_get_value_type (field_idval, &idtable);
|
|
lua_newtable (L);
|
|
lua_pushstring (L, choice_type);
|
|
lua_setfield (L, -2, "pod_type");
|
|
lua_pushstring (L, wp_spa_type_name (type));
|
|
lua_setfield (L, -2, "value_type");
|
|
push_primitive_values (L, pod, type, 1, idtable);
|
|
}
|
|
|
|
/* Error */
|
|
else {
|
|
luaL_error (L, "Unsupported pod type ",
|
|
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
|
|
}
|
|
}
|
|
|
|
static int
|
|
spa_pod_parse (lua_State *L)
|
|
{
|
|
WpSpaPod *pod = wplua_checkboxed (L, 1, WP_TYPE_SPA_POD);
|
|
push_luapod (L, pod, NULL);
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
spa_pod_fixate (lua_State *L)
|
|
{
|
|
WpSpaPod *pod = wplua_checkboxed (L, 1, WP_TYPE_SPA_POD);
|
|
gboolean res = wp_spa_pod_fixate (pod);
|
|
lua_pushboolean (L, res);
|
|
return 1;
|
|
}
|
|
|
|
static inline WpSpaPod *
|
|
_checkpod (lua_State *L, int n)
|
|
{
|
|
return wplua_checkboxed (L, n, WP_TYPE_SPA_POD);
|
|
}
|
|
|
|
static int
|
|
spa_pod_filter (lua_State *L)
|
|
{
|
|
WpSpaPod *pod = wplua_checkboxed (L, 1, WP_TYPE_SPA_POD);
|
|
WpSpaPod *filter = luaL_opt (L, _checkpod, 2, NULL);
|
|
WpSpaPod *result = wp_spa_pod_filter (pod, filter);
|
|
if (result) {
|
|
wplua_pushboxed (L, WP_TYPE_SPA_POD, result);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static const luaL_Reg spa_pod_methods[] = {
|
|
{ "get_type_name", spa_pod_get_type_name },
|
|
{ "parse", spa_pod_parse },
|
|
{ "fixate", spa_pod_fixate },
|
|
{ "filter", spa_pod_filter },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
static const luaL_Reg spa_pod_constructors[] = {
|
|
{ "None", spa_pod_none_new },
|
|
{ "Boolean", spa_pod_boolean_new },
|
|
{ "Id", spa_pod_id_new },
|
|
{ "Int", spa_pod_int_new },
|
|
{ "Long", spa_pod_long_new },
|
|
{ "Float", spa_pod_float_new },
|
|
{ "Double", spa_pod_double_new },
|
|
{ "String", spa_pod_string_new },
|
|
{ "Bytes", spa_pod_bytes_new },
|
|
{ "Pointer", spa_pod_pointer_new },
|
|
{ "Fd", spa_pod_fd_new },
|
|
{ "Rectangle", spa_pod_rectangle_new },
|
|
{ "Fraction", spa_pod_fraction_new },
|
|
{ "Object", spa_pod_object_new },
|
|
{ "Struct", spa_pod_struct_new },
|
|
{ "Sequence", spa_pod_sequence_new },
|
|
{ "Array", spa_pod_array_new },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
static const luaL_Reg spa_pod_choice_constructors[] = {
|
|
{ "None", spa_pod_choice_none_new },
|
|
{ "Range", spa_pod_choice_range_new },
|
|
{ "Step", spa_pod_choice_step_new },
|
|
{ "Enum", spa_pod_choice_enum_new },
|
|
{ "Flags", spa_pod_choice_flags_new },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
/* Init */
|
|
|
|
void
|
|
wp_lua_scripting_pod_init (lua_State *L)
|
|
{
|
|
luaL_newlib (L, spa_pod_constructors);
|
|
luaL_newlib (L, spa_pod_choice_constructors);
|
|
lua_setfield (L, -2, "Choice");
|
|
lua_setglobal (L, "WpSpaPod");
|
|
|
|
wplua_register_type_methods (L, WP_TYPE_SPA_POD, NULL, spa_pod_methods);
|
|
}
|