--[[ OBS Studio datetime script
This script transforms a text source into a digital clock. The datetime format
is configurable and uses the same syntax than the Lua os.date() call.
https://www.lua.org/pil/22.1.html
v1 - Created by Albin Kauffmann (albinou) https://gitlab.com/albinou/obs-scripts/-/blob/master/datetime.lua
v2 - Revisions by Richard Gagnon
added %dx day of month with st,rd,th,nd (01st) [01-31]\
noted %z
noted %Z
fixed ability to choose Text Source
v3 - Revisions by Scott Hardwick
added %dn day of the month as a decimal number [1-31]
added %mn month as a decimal number [1-12]
added %In hour, using a 12-hour clock as a decimal number [1-12]
noted %n
v4 - Revisions by Suslik V
removed %dx Reason: No localization.
added %ms Month as a custom string (12 values)
added %ws Weekday as a custom string (7 values)
added %Hn Hour, in 24h format as a decimal number (0-23)
]]
local obs = obslua
local source_name = ""
local datetime_format = ""
local activated = false
local week = {}
local month = {}
-- Function to set the time text
function set_datetime_text(source, format)
local x = 0
local d = ""
if string.find(format, "%%dn") ~= nil then
d = os.date("%d")
x = tonumber(d) -- make the day string a number
format = format.gsub(format, "%%dn", tostring(x))
end
if string.find(format, "%%mn") ~= nil then
d = os.date("%m")
x = tonumber(d) -- make the month string a number
format = format.gsub(format, "%%mn", tostring(x))
end
if string.find(format, "%%Hn") ~= nil then
d = os.date("%H")
x = tonumber(d) -- make the hour (24 hour clock) string a number
format = format.gsub(format, "%%Hn", tostring(x))
end
if string.find(format, "%%In") ~= nil then
d = os.date("%I")
x = tonumber(d) -- make the hour (12 hour clock) string a number
format = format.gsub(format, "%%In", tostring(x))
end
if string.find(format, "%%ws") ~= nil then
d = os.date("%w")
x = tonumber(d) -- make the week string a number
format = format.gsub(format, "%%ws", week[x + 1])
end
if string.find(format, "%%ms") ~= nil then
d = os.date("%m")
x = tonumber(d) -- make the month string a number
format = format.gsub(format, "%%ms", month[x])
end
local text = os.date(format)
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)
end
function timer_callback()
local source = obs.obs_get_source_by_name(source_name)
if source ~= nil then
set_datetime_text(source, datetime_format)
obs.obs_source_release(source)
end
end
function activate(activating)
if activated == activating then
return
end
activated = activating
if activating then
obs.timer_add(timer_callback, 1000)
else
obs.timer_remove(timer_callback)
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()
activate(false)
local source = obs.obs_get_source_by_name(source_name)
if source ~= nil then
local active = obs.obs_source_showing(source)
obs.obs_source_release(source)
activate(active)
end
end
----------------------------------------------------------
function script_description()
return "Sets a text source to act as a clock when the source is active."
end
function script_properties()
local props = obs.obs_properties_create()
obs.obs_properties_add_text(props, "sunday_0", "Sunday", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "monday_1", "Monday", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "tuesday_2", "Tuesday", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "wednesday_3", "Wednesday", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "thursday_4", "Thursday", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "friday_5", "Friday", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "saturday_6", "Saturday", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "month_1", "Jun", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "month_2", "Feb", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "month_3", "Mar", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "month_4", "Apr", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "month_5", "May", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "month_6", "Jun", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "month_7", "Jul", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "month_8", "Aug", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "month_9", "Sep", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "month_10", "Oct", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "month_11", "Nov", obs.OBS_TEXT_DEFAULT)
obs.obs_properties_add_text(props, "month_12", "Dec", obs.OBS_TEXT_DEFAULT)
p = obs.obs_properties_add_text(props, "format", "Datetime format", obs.OBS_TEXT_DEFAULT)
local desc = "Specifier Replaced by [Example]\
%a Abbreviated weekday name [Thu]\
%A Full weekday name [Thursday]\
%b Abbreviated month name [Aug]\
%B Full month name [August]\
%c Date and time representation [Thu Aug 23 14:55:02 2001]\
%C Year divided by 100 and truncated to integer (00-99) [20]\
%d Day of the month, zero-padded (01-31) [04]\
%dn Day of the month (1-31) [4]\
%D Short MM/DD/YY date, equivalent to %m/%d/%y [08/23/01]\
%e Day of the month, space-padded ( 1-31) [ 3]\
%F Short YYYY-MM-DD date, equivalent to %Y-%m-%d [2001-08-23]\
%g Week-based year, last two digits (00-99) [01]\
%G Week-based year [2001]\
%h Abbreviated month name (same as %b) [Aug]\
%H Hour in 24h format, zero-padded (00-23) [14]\
%I Hour in 12h format, zero padded (01-12) [02]\
%Hn Hour, in 24h format as a decimal number [0-23] [21]\
%In Hour, in 12h format as a decimal number [1-12] [9]\
%j Day of the year (001-366) [235]\
%m Month as a decimal number, zero padded (01-12) [08]\
%mn Month as a decimal number (1-12) [8]\
%ms Month as a custom string (12 values) [Winter]\
%M Minute (00-59) [55]\
%n New-line character ('\\n')\
%p AM or PM designation [PM]\
%r 12-hour clock time [02:55:02 pm]\
%R 24-hour HH:MM time, equivalent to %H:%M [14:55]\
%S Second (00-61) [02]\
%t Horizontal-tab character ('\\t')\
%T ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S [14:55:02]\
%u ISO 8601 weekday as number with Monday as 1 (1-7) [4]\
%U Week number with the first Sunday as the first day of week one (00-53) [33]\
%V ISO 8601 week number (01-53) [34]\
%w Weekday as a decimal number with Sunday as 0 (0-6) [4]\
%ws Weekday as a custom string (7 values) [Middle day]\
%W Week number with the first Monday as the first day of week one (00-53) [34]\
%x Date representation [08/23/01]\
%X Time representation [14:55:02]\
%y Year, last two digits (00-99) [01]\
%Y Year [2001]\
%z ISO 8601 offset from UTC in timezone (1 minute=1, 1 hour=100)\
If timezone cannot be determined, no characters [+0200]\
%Z Timezone name or abbreviation\
If timezone cannot be determined, no characters [CDT]\
%% A % sign"
obs.obs_property_set_long_description(p, desc)
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_unversioned_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)
return props
end
function script_defaults(settings)
obs.obs_data_set_default_string(settings, "format", "%X")
obs.obs_data_set_default_string(settings, "sunday_0", "First day of week")
obs.obs_data_set_default_string(settings, "monday_1", "Second day of week")
obs.obs_data_set_default_string(settings, "tuesday_2", "Third day of week")
obs.obs_data_set_default_string(settings, "wednesday_3", "Middle day of week")
obs.obs_data_set_default_string(settings, "thursday_4", "Fifth day of week")
obs.obs_data_set_default_string(settings, "friday_5", "Sixth day of week")
obs.obs_data_set_default_string(settings, "saturday_6", "Last day of week")
obs.obs_data_set_default_string(settings, "month_1", "I")
obs.obs_data_set_default_string(settings, "month_2", "II")
obs.obs_data_set_default_string(settings, "month_3", "III")
obs.obs_data_set_default_string(settings, "month_4", "IV")
obs.obs_data_set_default_string(settings, "month_5", "V")
obs.obs_data_set_default_string(settings, "month_6", "VI")
obs.obs_data_set_default_string(settings, "month_7", "VII")
obs.obs_data_set_default_string(settings, "month_8", "VIII")
obs.obs_data_set_default_string(settings, "month_9", "IX")
obs.obs_data_set_default_string(settings, "month_10", "X")
obs.obs_data_set_default_string(settings, "month_11", "XI")
obs.obs_data_set_default_string(settings, "month_12", "XII")
end
function script_update(settings)
activate(false)
week[1] = obs.obs_data_get_string(settings, "sunday_0")
week[2] = obs.obs_data_get_string(settings, "monday_1")
week[3] = obs.obs_data_get_string(settings, "tuesday_2")
week[4] = obs.obs_data_get_string(settings, "wednesday_3")
week[5] = obs.obs_data_get_string(settings, "thursday_4")
week[6] = obs.obs_data_get_string(settings, "friday_5")
week[7] = obs.obs_data_get_string(settings, "saturday_6")
month[1] = obs.obs_data_get_string(settings, "month_1")
month[2] = obs.obs_data_get_string(settings, "month_2")
month[3] = obs.obs_data_get_string(settings, "month_3")
month[4] = obs.obs_data_get_string(settings, "month_4")
month[5] = obs.obs_data_get_string(settings, "month_5")
month[6] = obs.obs_data_get_string(settings, "month_6")
month[7] = obs.obs_data_get_string(settings, "month_7")
month[8] = obs.obs_data_get_string(settings, "month_8")
month[9] = obs.obs_data_get_string(settings, "month_9")
month[10] = obs.obs_data_get_string(settings, "month_10")
month[11] = obs.obs_data_get_string(settings, "month_11")
month[12] = obs.obs_data_get_string(settings, "month_12")
source_name = obs.obs_data_get_string(settings, "source")
datetime_format = obs.obs_data_get_string(settings, "format")
reset()
end
function script_load(settings)
local sh = obs.obs_get_signal_handler()
obs.signal_handler_connect(sh, "source_show", source_activated)
obs.signal_handler_connect(sh, "source_hide", source_deactivated)
end