obs = obslua source_name = "" total_seconds = 0 last_seconds = 0 starttime = "" tenths = 9 curr_time = 0 --fade_duration = 0 --fade_duration = 0 last_text = "" stop_text = "" top_text = "" switch_scene_name = "" activated = false dateTable = nil always_active = false show_tenths = false hotkey_id = obs.OBS_INVALID_HOTKEY_ID -- Helper stuff function calctimeoffset(s) local hour local min local sec local p ="(%d+):(%d+):(%d+)" hour,min,sec=s:match(p) dateTable = os.date("*t", os.time()) dateTable.hour = hour dateTable.min = min dateTable.sec = sec return os.time(dateTable) end function calctimetogo() return os.difftime(calctimeoffset(starttime), os.time ()) end -- Functions to activate a scene function find_source_by_name_in_list(source_list, name) for i, source in pairs(source_list) do source_name = obs.obs_source_get_name(source) if source_name == name then return source end end return nil end function activate_scene(switch_scene_name) local scenes = obs.obs_frontend_get_scenes() local switch_scene = find_source_by_name_in_list(scenes, switch_scene_name) obs.obs_frontend_set_current_scene(switch_scene) obs.source_list_release(scenes) end -- Function to set the time text function set_time_text() local seconds = math.floor((curr_time / 10) % 60) local minutes = math.floor((curr_time /600) % 60) local hours = math.floor(curr_time / 36000) if last_second == seconds then if tenths > 0 then tenths = tenths - 1 end else tenths = 9 end last_second = seconds local text if show_tenths == true then text = string.format("%02d:%02d:%02d.%01d", hours, minutes, seconds, tenths) else text = string.format("%02d:%02d:%02d", hours, minutes, seconds) end if top_text ~= "" then text = top_text .. "\n" .. text end if curr_time < 1 then text = stop_text if switch_scene ~= "" then activate_scene(switch_scene) end end if text ~= last_text then local source = obs.obs_get_source_by_name(source_name) if source ~= nil then local settings = obs.obs_data_create() obs.obs_data_set_string(settings, "text", text) obs.obs_source_update(source, settings) obs.obs_data_release(settings) obs.obs_source_release(source) end -- obs.script_log(obs.LOG_WARNING, text..":"..switch_scene) -- obs.script_log(obs.LOG_WARNING, text..":"..starttime) end last_text = text end function timer_callback() if starttime == nil then curr_time = curr_time - 1 else curr_time = calctimetogo() * 10 end if curr_time < 0 then obs.remove_current_callback() curr_time = 0 end set_time_text() end function activate(activating) if activated == activating then return end activated = activating if activating then curr_time = total_seconds set_time_text() obs.timer_remove(timer_callback) obs.timer_add(timer_callback, 100) else if always_active then obs.timer_remove(timer_callback) obs.timer_add(timer_callback, 100) else obs.timer_remove(timer_callback) end end end -- Called when a source is activated/deactivated function activate_signal(cd, activating) local source = obs.calldata_source(cd, "source") if source ~= nil then local name = obs.obs_source_get_name(source) if (name == source_name) then activate(activating) end end end function source_activated(cd) activate_signal(cd, true) end function source_deactivated(cd) activate_signal(cd, false) end function reset(pressed) if not pressed then return end activate(false) local source = obs.obs_get_source_by_name(source_name) if source ~= nil then local active = obs.obs_source_active(source) obs.obs_source_release(source) activate(active) end end function reset_button_clicked(props, p) reset(true) return false end function start_stop_button_clicked(props, p) reset(true) return false end ---------------------------------------------------------- -- A function named script_properties defines the properties that the user -- can change for the entire script module itself function script_properties() local props = obs.obs_properties_create() obs.obs_properties_add_text(props, "top_text", "Top Text", obs.OBS_TEXT_DEFAULT) obs.obs_properties_add_int(props, "duration", "Duration (minutes)", 1, 100000, 1) obs.obs_properties_add_text(props, "starttime", "Start time (hh:mm:ss)", obs.OBS_TEXT_DEFAULT) local p = obs.obs_properties_add_list(props, "source", "Text Source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING) local sources = obs.obs_enum_sources() if sources ~= nil then for _, source in ipairs(sources) do source_id = obs.obs_source_get_id(source) if source_id == "text_gdiplus" or source_id == "text_ft2_source" then local name = obs.obs_source_get_name(source) obs.obs_property_list_add_string(p, name, name) end end end obs.source_list_release(sources) local scenechoice = obs.obs_properties_add_list(props, "scenechoice", "Switch to scene", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING) obs.obs_property_set_long_description(scenechoice, "NOTE: The [current scene] option can behave incorrectly if the\nscene is switched while the trigger is active") obs.obs_property_list_add_string(scenechoice, CURRENT_SCENE_OPTION, CURRENT_SCENE_OPTION) local sceneSources = obs.obs_frontend_get_scenes() for _, sceneSource in ipairs(sceneSources) do local name = obs.obs_source_get_name(sceneSource) obs.obs_property_list_add_string(scenechoice, name, name) end obs.source_list_release(sceneSources) -- obs.obs_properties_add_int(props, "fade_duration", "Fade duration (ms)", 0, 10000, 200) obs.obs_properties_add_bool(props, "always_active", "Timer always active") obs.obs_properties_add_bool(props, "tenths", "Show tenths") obs.obs_properties_add_text(props, "stop_text", "Final Text", obs.OBS_TEXT_DEFAULT) obs.obs_properties_add_button(props, "reset_button", "Reset Timer", reset_button_clicked) obs.obs_properties_add_button(props, "statstop_button", "Start/Stop Timer", start_stop_button_clicked) return props end -- A function named script_description returns the description shown to -- the user function script_description() return "A modification of the original countdown.lua made by Jim" .. "A couple of extra settings make it possible to:\n" .. " 1. Activate a given Scene at the end of the countdown\n" .. " If this is not set the Final Text is activated\n" .. " 2. Count down to a given time in the form hh:mm:ss\n" .. " If this is not set the Duration is used as time\n" .. " 3. Set a text on a line above the count down timer\n\n" .. "Made by SiR" end -- A function named script_update will be called when settings are changed function script_update(settings) activate(false) top_text = obs.obs_data_get_string(settings,"top_text") starttime = obs.obs_data_get_string(settings,"starttime") total_seconds = obs.obs_data_get_int(settings,"duration") * 60 * 10 source_name = obs.obs_data_get_string(settings,"source") stop_text = obs.obs_data_get_string(settings,"stop_text") switch_scene = obs.obs_data_get_string(settings,"scenechoice") always_active = obs.obs_data_get_bool(settings, "always_active") show_tenths = obs.obs_data_get_bool(settings, "tenths") -- fade_duration = obs.obs_data_get_string(settings,"fade_duration") if starttime ~= "" then -- obs.script_log(obs.LOG_WARNING, "Starts "..starttime) total_seconds = os.difftime(calctimeoffset(starttime), os.time ()) * 10 -- obs.script_log(obs.LOG_WARNING, "Starts "..total_seconds) end reset(true) 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, "duration", 5) obs.obs_data_set_default_string(settings, "stop_text", "Starting soon (tm)") 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 hotkey_save_array = obs.obs_hotkey_save(hotkey_id) obs.obs_data_set_array(settings, "reset_hotkey", hotkey_save_array) obs.obs_data_array_release(hotkey_save_array) end -- a function named script_load will be called on startup function script_load(settings) -- Connect hotkey and activation/deactivation signal callbacks -- -- NOTE: These particular script callbacks do not necessarily have to -- be disconnected, as callbacks will automatically destroy themselves -- if the script is unloaded. So there's no real need to manually -- disconnect callbacks that are intended to last until the script is -- unloaded. local sh = obs.obs_get_signal_handler() obs.signal_handler_connect(sh, "source_activate", source_activated) obs.signal_handler_connect(sh, "source_deactivate", source_deactivated) hotkey_id = obs.obs_hotkey_register_frontend("reset_timer_thingy", "Reset Timer", reset) local hotkey_save_array = obs.obs_data_get_array(settings, "reset_hotkey") obs.obs_hotkey_load(hotkey_id, hotkey_save_array) obs.obs_data_array_release(hotkey_save_array) end