obs = obslua source_name = "" lyrics_file = "" lyrics = {} num_lines = 1 cur_line = 1 visible = true hotkey_n_id = obs.OBS_INVALID_HOTKEY_ID hotkey_sf_id = obs.OBS_INVALID_HOTKEY_ID hotkey_p_id = obs.OBS_INVALID_HOTKEY_ID hotkey_sb_id = obs.OBS_INVALID_HOTKEY_ID hotkey_c_id = obs.OBS_INVALID_HOTKEY_ID -- Function to set the lyric text function set_lyric_text() local text = "" if visible then for i=1,num_lines do if #lyrics >= cur_line + i + 1 then text = text .. lyrics[cur_line + i - 1] .. "\n" end end end 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 end -- see if the file exists function file_exists(file) local f = io.open(file, "rb") if f then f:close() end return f ~= nil end -- load all lyrics from a file into lyrics list function load_lyrics(file) if not file_exists(file) then lyrics = {} return end lyrics = {} for line in io.lines(file) do lyrics[#lyrics + 1] = line end lyrics[#lyrics + 1] = "" end function next_lyric(pressed) if not pressed then return end print("Pressed NEXT lyric - cur_line = " .. cur_line .. " of " .. #lyrics) if cur_line < #lyrics - num_lines then cur_line = cur_line + 1 set_lyric_text() end end function skip_forward_lyric(pressed) if not pressed then return end if cur_line < #lyrics - num_lines then cur_line = cur_line + num_lines if cur_line > #lyrics - num_lines then cur_line = #lyrics - num_lines end set_lyric_text() end end function prev_lyric(pressed) if not pressed then return end print("Pressed PREV lyric - cur_line = " .. cur_line) if cur_line > 1 then cur_line = cur_line - 1 set_lyric_text() end end function skip_backward_lyric(pressed) if not pressed then return end if cur_line > 1 then cur_line = cur_line - num_lines if cur_line < 1 then cur_line = 1 end set_lyric_text() end end function clear_lyric(pressed) if not pressed then return end print("Pressed CLEAR lyric") visible = not visible set_lyric_text() end function next_button_clicked(props, p) next_lyric(true) return false end function prev_button_clicked(props, p) prev_lyric(true) return false end function clear_button_clicked(props, p) clear_lyric(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_path(props, "lyric_file", "Lyrics File", obs.OBS_PATH_FILE, "Text File (*.txt)", "") obs.obs_properties_add_int(props, "lyric_num_lines", "Lines Displayed", 1, 100, 1) 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) obs.obs_properties_add_button(props, "next_lyric_button", "Next Lyric", next_button_clicked) obs.obs_properties_add_button(props, "prev_lyric_button", "Previous Lyric", prev_button_clicked) obs.obs_properties_add_button(props, "clear_lyric_button", "Toggle Lyrics", clear_button_clicked) return props end -- A function named script_description returns the description shown to -- the user function script_description() return "Displays and updates song lyrics (or other text) from lines in a text file. Set the hotkeys used to trigger lyric changes in the settings.\n\nWritten by JStark" end -- A function named script_update will be called when settings are changed function script_update(settings) lyrics_file = obs.obs_data_get_string(settings, "lyric_file") num_lines = obs.obs_data_get_int(settings, "lyric_num_lines") source_name = obs.obs_data_get_string(settings, "source") load_lyrics(lyrics_file) set_lyric_text() 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, "lyric_num_lines", 2) obs.obs_data_set_default_string(settings, "lyric_file", "") 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_n_id) obs.obs_data_set_array(settings, "lyric_next_hotkey", hotkey_save_array) hotkey_save_array = obs.obs_hotkey_save(hotkey_n_id) obs.obs_data_array_release(hotkey_save_array) hotkey_save_array = obs.obs_hotkey_save(hotkey_sf_id) obs.obs_data_set_array(settings, "lyric_sf_hotkey", hotkey_save_array) hotkey_save_array = obs.obs_hotkey_save(hotkey_sf_id) obs.obs_data_array_release(hotkey_save_array) hotkey_save_array = obs.obs_hotkey_save(hotkey_p_id) obs.obs_data_set_array(settings, "lyric_prev_hotkey", hotkey_save_array) hotkey_save_array = obs.obs_hotkey_save(hotkey_p_id) obs.obs_data_array_release(hotkey_save_array) hotkey_save_array = obs.obs_hotkey_save(hotkey_sb_id) obs.obs_data_set_array(settings, "lyric_sb_hotkey", hotkey_save_array) hotkey_save_array = obs.obs_hotkey_save(hotkey_sb_id) obs.obs_data_array_release(hotkey_save_array) hotkey_save_array = obs.obs_hotkey_save(hotkey_c_id) obs.obs_data_set_array(settings, "lyric_clear_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. hotkey_n_id = obs.obs_hotkey_register_frontend("lyric_next_hotkey_thing", "Next Lyric", next_lyric) hotkey_p_id = obs.obs_hotkey_register_frontend("lyric_prev_hotkey_thing", "Previous Lyric", prev_lyric) hotkey_sf_id = obs.obs_hotkey_register_frontend("lyric_sf_hotkey_thing", "Skip Forward Lyric", skip_forward_lyric) hotkey_sb_id = obs.obs_hotkey_register_frontend("lyric_prev_hotkey_thing", "Skip Backward Lyric", skip_backward_lyric) hotkey_c_id = obs.obs_hotkey_register_frontend("lyric_clear_hotkey_thing", "Toggle Lyrics", clear_lyric) local hotkey_save_array = obs.obs_data_get_array(settings, "lyric_next_hotkey") obs.obs_hotkey_load(hotkey_n_id, hotkey_save_array) obs.obs_data_array_release(hotkey_save_array) hotkey_save_array = obs.obs_data_get_array(settings, "lyric_sf_hotkey") obs.obs_hotkey_load(hotkey_sf_id, hotkey_save_array) obs.obs_data_array_release(hotkey_save_array) hotkey_save_array = obs.obs_data_get_array(settings, "lyric_prev_hotkey") obs.obs_hotkey_load(hotkey_p_id, hotkey_save_array) obs.obs_data_array_release(hotkey_save_array) hotkey_save_array = obs.obs_data_get_array(settings, "lyric_sb_hotkey") obs.obs_hotkey_load(hotkey_sb_id, hotkey_save_array) obs.obs_data_array_release(hotkey_save_array) hotkey_save_array = obs.obs_data_get_array(settings, "lyric_clear_hotkey") obs.obs_hotkey_load(hotkey_c_id, hotkey_save_array) obs.obs_data_array_release(hotkey_save_array) end