How to enumerate script properties in LUA

Bobby©

New Member
Hi all,
I'm trying to update script properties in runtime depending on other property values, In order to do it I attempt to enumerate properties using obs_properties_first/obs_property_next. Call to the second function produces the following error:

Error in obs_property_next (arg 1), expected 'obs_property_t **|struct obs_property **' got 'obs_property_t *|struct obs_property *'

Is it possible to pass pointer-to-pointer objects in lua scripting? Or maybe is there a different way to enumerate all properties in a bundle?

Thanks in advance
 

MacTartan

Member
Did you ever get a solution? I recently came across the same problem with obs_property_next. Using ffi, the following code snippet works to retrieve a list of filter properties of a source called 'tmp' with a color filter named 'color';

OUTPUT...
[Test.lua] Property 1 = key_color_type
[Test.lua] Property 2 = key_color
[Test.lua] Property 3 = similarity
[Test.lua] Property 4 = smoothness
[Test.lua] Property 5 = opacity
[Test.lua] Property 6 = contrast
[Test.lua] Property 7 = brightness
[Test.lua] Property 8 = gamma


Code:
local obs = obslua
local ffi = require("ffi")
local obsffi


ffi.cdef[[

struct obs_source;
struct obs_properties;
struct obs_property;
typedef struct obs_source obs_source_t;
typedef struct obs_properties obs_properties_t;
typedef struct obs_property obs_property_t;

obs_source_t *obs_get_source_by_name(const char *name);
obs_source_t *obs_source_get_filter_by_name(obs_source_t *source, const char *name);
obs_properties_t *obs_source_properties(const obs_source_t *source);
obs_property_t *obs_properties_first(obs_properties_t *props);
bool obs_property_next(obs_property_t **p);
const char *obs_property_name(obs_property_t *p);
void obs_properties_destroy(obs_properties_t *props);
void obs_source_release(obs_source_t *source);

]]


if ffi.os == "OSX" then
    obsffi = ffi.load("obs.0.dylib")
else
    obsffi = ffi.load("obs")
end


local function filterTest()
    local source = obsffi.obs_get_source_by_name("tmp")
    if source then
        local fSource = obsffi.obs_source_get_filter_by_name(source, "color")
        if fSource then
            local props = obsffi.obs_source_properties(fSource)
            if props then
                local prop = obsffi.obs_properties_first(props)
                local name = obsffi.obs_property_name(prop)
                if name then
                    local propCount = 1
                    obs.script_log(obs.LOG_INFO, string.format("Property 1 = %s", ffi.string(name)))
                    local _p = ffi.new("obs_property_t *[1]", prop)
                    local foundProp = obsffi.obs_property_next(_p)
                    prop = ffi.new("obs_property_t *", _p[0])
                    while foundProp do
                        propCount = propCount + 1
                        name = obsffi.obs_property_name(prop)
                        obs.script_log(obs.LOG_INFO, string.format("Property %d = %s", propCount, ffi.string(name)))
                        _p = ffi.new("obs_property_t *[1]", prop)
                        foundProp = obsffi.obs_property_next(_p)
                        prop = ffi.new("obs_property_t *", _p[0])
                    end
                end
                obsffi.obs_properties_destroy(props)
            end
            obsffi.obs_source_release(fSource)
        end
        obsffi.obs_source_release(source)
    end
end
.....
.....
.....
 

uuoocl

Member
Thanks for sharing this script.
I'm trying to automate clicking the "Get Value" button in the Move Transition plug-in's Move Video Capture Device filter, but can't figure it out.
Using your script, I can see the property is named "value_get"
I've modified your script to include the "obs_property_button_clicked" function, but it returns an error.

52: Error in obs_property_button_clicked (arg 1), expected 'obs_property_t *' got 'cdata'

Would you know how to get the variables into the format for the "obs_property_button_clicked" function?

Here is the script

Lua:
local obs = obslua
local ffi = require("ffi")
local obsffi

ffi.cdef[[

struct obs_source;
struct obs_properties;
struct obs_property;
typedef struct obs_source obs_source_t;
typedef struct obs_properties obs_properties_t;
typedef struct obs_property obs_property_t;

obs_source_t *obs_get_source_by_name(const char *name);
obs_source_t *obs_source_get_filter_by_name(obs_source_t *source, const char *name);
obs_properties_t *obs_source_properties(const obs_source_t *source);
obs_property_t *obs_properties_first(obs_properties_t *props);
bool obs_property_next(obs_property_t **p);
const char *obs_property_name(obs_property_t *p);
void obs_properties_destroy(obs_properties_t *props);
void obs_source_release(obs_source_t *source);

]]

if ffi.os == "OSX" then
    obsffi = ffi.load("obs.0.dylib")
else
    obsffi = ffi.load("obs")
end

local function filterTest()
    local source = obsffi.obs_get_source_by_name("Video Capture Device 2")
    if source then
        local fSource = obsffi.obs_source_get_filter_by_name(source, "mVideo")
        if fSource then
            local props = obsffi.obs_source_properties(fSource)
            if props then
                local prop = obsffi.obs_properties_first(props)
                local name = obsffi.obs_property_name(prop)
                if name then
                    local propCount = 1
                    obs.script_log(obs.LOG_INFO, string.format("Property 1 = %s", ffi.string(name)))
                    local _p = ffi.new("obs_property_t *[1]", prop)
                    local foundProp = obsffi.obs_property_next(_p)
                    prop = ffi.new("obs_property_t *", _p[0])
                    while foundProp do
                        propCount = propCount + 1
                        name = obsffi.obs_property_name(prop)

                        if ffi.string(name) == "value_get" then
                            obs.script_log(obs.LOG_INFO, string.format("Property %d = %s", propCount, ffi.string(name)))
                            obs.obs_property_button_clicked(prop, fSource)
                        end   
                        
                        _p = ffi.new("obs_property_t *[1]", prop)
                        foundProp = obsffi.obs_property_next(_p)
                        prop = ffi.new("obs_property_t *", _p[0])
                    end
                end
                obsffi.obs_properties_destroy(props)
            end
            obsffi.obs_source_release(fSource)
        end
        obsffi.obs_source_release(source)
    end
end

filterTest()
 
Top