obs = obslua
ffi = require("ffi")

-- Global variables
local G = {
    lock = false,
    start_delay = 3,
    duration = 0,
    noise = 999,
    tick = 16,
    tick_mili = 16 * 0.001,
    interval_sec = 0.05,
    tick_acc = 0,
    source_name = "Audio",  -- Changed from "Mic" to "Audio"
    speach_source_name = "speach",
    volmeter = nil,
    threshold = -50,  -- Adjust this value to set the dB threshold
    is_speach_visible = false
}

-- FFI declarations
ffi.cdef[[
    typedef struct obs_source obs_source_t;
    typedef struct obs_volmeter obs_volmeter_t;
  
    obs_source_t *obs_get_source_by_name(const char *name);
    void obs_source_release(obs_source_t *source);
    obs_volmeter_t *obs_volmeter_create(int fader_type);
    void obs_volmeter_destroy(obs_volmeter_t *volmeter);
    bool obs_volmeter_attach_source(obs_volmeter_t *volmeter, obs_source_t *source);
    typedef void (*obs_volmeter_callback_t)(void *param, const float magnitude[4], const float peak[4], const float input_peak[4]);
    void obs_volmeter_add_callback(obs_volmeter_t *volmeter, obs_volmeter_callback_t callback, void *param);
    void obs_volmeter_remove_callback(obs_volmeter_t *volmeter, obs_volmeter_callback_t callback, void *param);
]]

local obsffi = ffi.load("obs")

-- Volmeter callback
local function volmeter_callback(param, magnitude, peak, input_peak)
    G.noise = tonumber(peak[0])
end

-- Function to show/hide the "speach" source
local function toggle_speach_source(should_show)
    local current_scene = obs.obs_frontend_get_current_scene()
    local scene = obs.obs_scene_from_source(current_scene)
    local scene_item = obs.obs_scene_find_source(scene, G.speach_source_name)
  
    if scene_item ~= nil then
        obs.obs_sceneitem_set_visible(scene_item, should_show)
        G.is_speach_visible = should_show
    end
  
    obs.obs_source_release(current_scene)
end

-- Event loop
local function event_loop()
    G.duration = G.duration + G.tick_mili
  
    if G.duration > G.start_delay then
        if not G.lock then
            local source = obsffi.obs_get_source_by_name(G.source_name)
            G.volmeter = obsffi.obs_volmeter_create(2)  -- OBS_FADER_LOG
            obsffi.obs_volmeter_add_callback(G.volmeter, volmeter_callback, nil)
            if obsffi.obs_volmeter_attach_source(G.volmeter, source) then
                obsffi.obs_source_release(source)
                G.lock = true
            end
        else
            G.tick_acc = G.tick_acc + G.tick_mili
            if G.tick_acc > G.interval_sec then
                if G.noise > G.threshold and not G.is_speach_visible then
                    toggle_speach_source(true)
                elseif G.noise <= G.threshold and G.is_speach_visible then
                    toggle_speach_source(false)
                end
                G.tick_acc = 0
            end
        end
    end
end

-- Script description
function script_description()
    return "Script to show/hide 'speach' source based on audio levels."
end

-- Script load function
function script_load(settings)
    obs.timer_add(event_loop, G.tick)
end

-- Script unload function
function script_unload()
    if G.volmeter then
        obsffi.obs_volmeter_remove_callback(G.volmeter, volmeter_callback, nil)
        obsffi.obs_volmeter_destroy(G.volmeter)
    end
end