obs_scripts/source_synchronizer.lua

174 lines
6.7 KiB
Lua
Raw Normal View History

-- "load" OBS bindings
obs = obslua
-- total seconds elapsed since the script has started
total_seconds = 0
-- seconds elapsed in this cycle
cur_seconds = 0
-- names of the sources that are being synced up
master_source_name = ""
slave_source_name = ""
-- seconds between sync attempts
sync_delay = 5
activated = false
-- a hotkey to force synchronisation of a given pair
hotkey_id = obs.OBS_INVALID_HOTKEY_ID
function string.split(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t={}
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
table.insert(t, str)
end
return t
end
function timer_callback()
cur_seconds = cur_seconds - 1
if cur_seconds < 0 then
--print("Source Synchronizer script cycle ended. Delay is " .. total_seconds .. '; Master source is "' .. master_source_name .. '"; Slave source is "' .. slave_source_name ..'".')
-- get both master and slave sources by names set up in the script dialog settings
local master_source = obs.obs_get_source_by_name(master_source_name)
local slave_source = obs.obs_get_source_by_name(slave_source_name)
-- if both were found, we can proceed
if master_source~= nil and slave_source~= nil then
-- obs.obs_get_source_properties always returns nill
-- and obs.obs_source_get_settings is unusable since property_next expects a fucking pointer, not the object itself.
-- Solution? According to the github, using FFI for an already embedded shit. Why, oh, why, mofos?!!
-- Oh, I know why! Because OBS devs don't give a fuck since 2020 :/
-- get settings of a master source
local master_props = obs.obs_source_get_settings(master_source)
-- get the "window" property which will tell what window the master source is captturing
local master_window = obs.obs_data_get_string(master_props, 'window')
-- yes, it uses windows in "game" capture mode (fuck clarity, I guess?)
-- get settings of a slave source
local slave_props = obs.obs_source_get_settings(slave_source)
-- also read the slave props, no need to update anything if there's no need to update anything ;)
local slave_window = obs.obs_data_get_string(slave_props, 'window')
--print("slave " .. (slave_window or "-").. "; master " .. (master_window) or "-")
print(string)
if (slave_window ~= master_window) and not string.match(master_window,"ShaderGlass.exe") then
-- copy/paste the window property from the master to the slave
obs.obs_data_set_string(slave_props, 'window', master_window)
-- the copied source won't update unless...
obs.obs_source_update(slave_source, slave_props)
--obs.obs_frontend_open_source_properties(slave_source_name)
end
-- release master and slave objects
obs.obs_source_release(master_source)
obs.obs_source_release(slave_source)
-- release the new temporary data object
obs.obs_data_release(new_slave_props)
end
-- reset loop timer to the default value, so the cycle can continue
cur_seconds = sync_delay
end
--set_time_text()
end
function activate(activating)
if activated == activating then
return
end
activated = activating
if activating then
cur_seconds = total_seconds
obs.timer_add(timer_callback, 1000)
else
obs.timer_remove(timer_callback)
end
end
----------------------------------------------------------
-- A function named script_properties defines the properties that the user
-- can change for the entire script module itself
function script_properties()
-- create properties dialogue
local props = obs.obs_properties_create()
-- add sync delay settings
obs.obs_properties_add_int(props, "sync_delay", "Sync cycle (seconds)", 1, 3600, 1)
-- add main source combobox
local master = obs.obs_properties_add_list(props, "master_source", "Master source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
-- add the source that will sync up with the main one
local slave = obs.obs_properties_add_list(props, "slave_source", "Slave source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
-- get all the sources
local sources = obs.obs_enum_sources()
if sources ~= nil then
for _, source in ipairs(sources) do
source_id = obs.obs_source_get_unversioned_id(source)
-- if the source is not a group, then ad it to both master and slave lists
if source_id ~= "group"
then
local name = obs.obs_source_get_name(source)
if source_id == "game_capture" then
obs.obs_property_list_add_string(master, name, name)
end
if source_id == "wasapi_process_output_capture" then
obs.obs_property_list_add_string(slave, name, name)
end
end
end
end
-- they say it's important to release sources
obs.source_list_release(sources)
return props
end
-- A function named script_description returns the description shown to
-- the user
function script_description()
return "This script allows one to sync 2 sources'... well, sources.\n\nThe idea is to be able to change *one* source and have the rest of them sync up with that.\n\nThe easiest example to follow: one has a game capture source and an application audio output capture source. With this it's possible to change only the game source and the audio one will reflect the changes automatically after a set time interval.\n\nThere's no explicit limit on what types of sources to use, though. If only because I'm to lazy to check all the types of sources available on different platforms.\n\nMade by 4aiman"
end
-- A function named script_update will be called when settings are changed
function script_update(settings)
total_seconds = obs.obs_data_get_int(settings, "sync_delay")
master_source_name = obs.obs_data_get_string(settings, "master_source")
slave_source_name = obs.obs_data_get_string(settings, "slave_source")
print("Source Synchronizer script upadted. Delay has been set to " .. total_seconds .. '; Master source is now "' .. master_source_name .. '"; Slave source is now "' .. slave_source_name ..'".')
end
-- A function named script_defaults will be called to set the default settings
function script_defaults(settings)
obs.obs_data_set_default_int(settings, "sync_delay", sync_delay)
end
-- A function named script_save will be called when the script is saved
--
-- NOTE: This function is usually used for saving extra data (such as in this
-- case, a hotkey's save data). Settings set via the properties are saved
-- automatically.
function script_save(settings)
local force_sources_sync_hotkey = obs.obs_hotkey_save(hotkey_id)
obs.obs_data_set_array(settings, "force_sources_sync_hotkey", force_sources_sync_hotkey)
obs.obs_data_array_release(force_sources_sync_hotkey)
end
-- a function named script_load will be called on startup
function script_load(settings)
print("Source Synchronizer script loaded")
activate(true)
end