You've already forked rdsspy-lua-host
mirror of
https://github.com/KubaPro010/rdsspy-lua-host.git
synced 2026-02-27 10:55:04 +01:00
Compare commits
15 Commits
d8b152a2ba
...
ebfb628ab3
| Author | SHA1 | Date | |
|---|---|---|---|
|
ebfb628ab3
|
|||
|
db4794dd38
|
|||
|
c43f2f33c7
|
|||
|
b2479a7f42
|
|||
|
c496d2cfd6
|
|||
|
62e012e867
|
|||
|
1c33dd63da
|
|||
|
b67634ef41
|
|||
|
31ba79e74c
|
|||
|
c444a854c8
|
|||
|
0a7917a751
|
|||
|
9ea35829ac
|
|||
|
c5224d5a53
|
|||
|
3da022a4c2
|
|||
|
0066252626
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
*.dll
|
||||
liblua
|
||||
liblua
|
||||
liblua.native
|
||||
13
Makefile
13
Makefile
@@ -2,11 +2,20 @@ liblua:
|
||||
gcc -c lua/*.c
|
||||
ar rcs liblua *.o
|
||||
rm *.o
|
||||
liblua-native:
|
||||
gcc -c lua/*.c -march=native
|
||||
ar rcs liblua.native *.o
|
||||
rm *.o
|
||||
|
||||
build: liblua
|
||||
gcc -O2 -shared -static -o luahost.dll plugin.c liblua -lgdi32 -luser32 -lshell32 \
|
||||
gcc -O2 -shared -static -o luahost-x86.dll plugin.c liblua -lgdi32 -luser32 -lshell32 \
|
||||
-Wl,--add-stdcall-alias \
|
||||
-ffunction-sections -fdata-sections
|
||||
|
||||
install: build
|
||||
build-native: liblua
|
||||
gcc -O2 -shared -static -o luahost.dll plugin.c liblua.native -lgdi32 -luser32 -lshell32 -march=native \
|
||||
-Wl,--add-stdcall-alias \
|
||||
-ffunction-sections -fdata-sections
|
||||
|
||||
install: build-native
|
||||
cp luahost.dll "/c/Program Files (x86)/RDS Spy/plugins"
|
||||
@@ -9,4 +9,11 @@ Aside from all that, this it loads and executes the script at "%LOCALAPPDATA%\RD
|
||||
|
||||
## Why?
|
||||
|
||||
Ask Jan Kolar why his funny little rds decoder doesn't have Enchanced RT (excluding the 0x6552 to ERT mapping of course)
|
||||
Ask Jan Kolar why his funny little rds decoder doesn't have Enchanced RT (excluding the 0x6552 to ERT mapping of course)
|
||||
|
||||
# Scripts
|
||||
Inside of the examples folder you have `basic.lua` which mostly replaced the `basic.dll` plugin in RDS Spy
|
||||
|
||||
Note that you can double click on the buttons, if you try it
|
||||
|
||||
Another note is that on menu 0 you have the PI and PS in a large font, why? democracy? or something like that ([forum post](https://pira.cz/forum/index.php?topic=1124.0))
|
||||
@@ -1,8 +1,5 @@
|
||||
set_console_mode(true)
|
||||
|
||||
local last_pi = 0
|
||||
local last_super_pi = 0
|
||||
|
||||
local ert_string = string.rep("_", 128)
|
||||
local rt_a = string.rep("_", 64)
|
||||
local rt_b = string.rep("_", 64)
|
||||
@@ -19,8 +16,8 @@ local rta_display = ""
|
||||
local rtb_display = ""
|
||||
local lps_display = ""
|
||||
|
||||
|
||||
local current_menu = 1
|
||||
local menu_extended = false
|
||||
|
||||
local pty_rds = {
|
||||
"None", "News", "Current Affairs",
|
||||
@@ -458,57 +455,103 @@ local pi_ecc_to_country = {
|
||||
}
|
||||
|
||||
local pi_coverage = {
|
||||
"Local",
|
||||
"International",
|
||||
"National",
|
||||
"Supra-regional",
|
||||
"Regional 4",
|
||||
"Regional 5",
|
||||
"Regional 5",
|
||||
"Regional 7",
|
||||
"Regional 8",
|
||||
"Regional 9",
|
||||
"Regional A",
|
||||
"Regional B",
|
||||
"Regional C",
|
||||
"Regional D",
|
||||
"Regional E",
|
||||
"Local", "International", "National",
|
||||
"Supra-regional", "Regional 4", "Regional 5",
|
||||
"Regional 5", "Regional 7", "Regional 8",
|
||||
"Regional 9", "Regional A", "Regional B",
|
||||
"Regional C", "Regional D", "Regional E",
|
||||
"Regional F",
|
||||
}
|
||||
|
||||
local time_display_utc = "-"
|
||||
local time_display_local = "-"
|
||||
local time_display_offset = 0
|
||||
|
||||
local rtp_len1 = 0
|
||||
local rtp_len2 = 0
|
||||
local rtp_type1 = 0
|
||||
local rtp_type2 = 0
|
||||
local rtp_start1 = 0
|
||||
local rtp_start2 = 0
|
||||
local rtp_toggle = false
|
||||
local rtp_running = false
|
||||
|
||||
local rtp_types = {
|
||||
"DUMMY_CLASS",
|
||||
"Item.Title", "Item.Album", "Item.Tracknumber",
|
||||
"Item.Artist", "Item.Composition", "Item.Movement",
|
||||
"Item.Conductor", "Item.Composer", "Item.Band",
|
||||
"Item.Comment", "Item.Genre", "Info.News",
|
||||
"Info.News.Local", "Info.Stockmarket", "Info.Sport",
|
||||
"Info.Lottery", "Info.Horoscope", "Info.Daily_Diversion",
|
||||
"Info.Health", "Info.Event", "Info.Scene",
|
||||
"Info.Cinema", "Info.Tv", "Info.Date_time",
|
||||
"Info.Weather", "Info.Traffic", "Info.Alarm",
|
||||
"Info.Advertisement", "Info.URL", "Info.Other",
|
||||
"Stationame.Short", "Stationname.Long", "Program.Now",
|
||||
"Program.Next", "Program.Part", "Program.Host",
|
||||
"Program.Editorial_Staff", "Program.Frequency", "Program.Homepage",
|
||||
"Program.Subchannel", "Phone.Hotline", "Phone.Studio",
|
||||
"Phone.Other", "SMS.Studio", "SMS.Other",
|
||||
"Email.Hotline", "Email.Studio", "Email.Other",
|
||||
"MMS.Other", "Chat", "Chat.Center",
|
||||
"Vote.Question", "Vote.Center", "Rfu_1",
|
||||
"Rfu_2", "Private_1", "Private_2",
|
||||
"Private_3", "Place", "Appointment",
|
||||
"Identifier", "Purchase", "GET_DATA"
|
||||
}
|
||||
|
||||
local expected_afs = 0
|
||||
local afs = {}
|
||||
local state_af_am_follows = false
|
||||
|
||||
local last_render_hash = 0
|
||||
local function crc(data)
|
||||
local crc = 0xFF
|
||||
local sum = 0xFF
|
||||
|
||||
for i = 1, #data do
|
||||
crc = crc ~ data:byte(i)
|
||||
|
||||
sum = sum ~ data:byte(i)
|
||||
for _ = 1, 8 do
|
||||
if (crc & 0x80) ~= 0 then crc = (crc << 1) ~ 0x7
|
||||
else crc = crc << 1 end
|
||||
crc = crc & 0xFF
|
||||
if (sum & 0x80) ~= 0 then sum = (sum << 1) ~ 0x7
|
||||
else sum = sum << 1 end
|
||||
sum = sum & 0xFF
|
||||
end
|
||||
end
|
||||
|
||||
return crc
|
||||
return sum
|
||||
end
|
||||
|
||||
function render_menu()
|
||||
out = string.format("Menu %d\r\n------\r\n", current_menu)
|
||||
local function render_menu()
|
||||
local out = string.format("Menu %d%s\r\n------\r\n", current_menu, menu_extended and " (extended)" or "")
|
||||
set_font_size(26)
|
||||
if current_menu == 1 then
|
||||
if current_menu == 1 and not menu_extended then
|
||||
set_font_size(72) -- largest as i can do, this is directly from the public's wants (https://pira.cz/forum/index.php?topic=1124.0)
|
||||
out = out .. string.format("PI: %X (SPI: %X)\r\n", last_pi, last_super_pi)
|
||||
out = out .. string.format("PI: %s\r\n", db.read_value("PI") or "----")
|
||||
out = out .. string.format("PS: %s", db.read_value("PS") or "--------")
|
||||
elseif current_menu == 2 then
|
||||
elseif current_menu == 1 and menu_extended then
|
||||
out = out .. string.format("AF: (%d)\r\n\t", expected_afs)
|
||||
for _, freq in ipairs(afs) do
|
||||
out = out .. string.format("%.1f\r\n\t", freq)
|
||||
end
|
||||
elseif current_menu == 2 and not menu_extended then
|
||||
out = out .. string.format("PTY: %d (%s / %s)\r\n", pty, pty_rds[pty+1], pty_rbds[pty+1])
|
||||
out = out .. string.format("TP %s | TA %s | DPTY %s\r\n", tp and "+" or "-", ta and "+" or "-", dpty and "+" or "-")
|
||||
out = out .. string.format("PTYN: %s\r\n\r\n", ptyn)
|
||||
out = out .. string.format("RT[A]: %s%s\r\n", last_rt and ">" or " ", rta_display)
|
||||
out = out .. string.format("RT[B]: %s%s\r\n\r\n", (not last_rt) and ">" or " ", rtb_display)
|
||||
elseif current_menu == 2 and menu_extended then
|
||||
local current_rt = rta_display
|
||||
if not last_rt then current_rt = rtb_display end
|
||||
out = out .. string.format("RTP\r\n\tRUNNING %s | TOGGLE %s\r\n\t", rtp_running and "+" or "-", rtp_toggle and "+" or "-")
|
||||
if rtp_running then
|
||||
out = out .. string.format("%s - %s\r\n\t", rtp_types[rtp_type1+1], current_rt:sub(rtp_start1+1, rtp_start1+rtp_len1+1))
|
||||
out = out .. string.format("%s - %s\r\n\t", rtp_types[rtp_type2+1], current_rt:sub(rtp_start2+1, rtp_start2+rtp_len2+1))
|
||||
else out = out .. "-\r\n\t-\r\n\t" end
|
||||
out = out .. string.format("RAW %d,%d,%d,%d,%d,%d\r\n", rtp_type1, rtp_start1, rtp_len1, rtp_type2, rtp_start2, rtp_len2)
|
||||
elseif current_menu == 3 then
|
||||
local country_id = (last_pi & 0xF000) >> 12
|
||||
local coverage_id = (last_pi & 0xF00) >> 8
|
||||
local pi_code = tonumber(db.read_value("PI") or "0000", 16)
|
||||
local country_id = (pi_code & 0xF000) >> 12
|
||||
local coverage_id = (pi_code & 0xF00) >> 8
|
||||
|
||||
out = out .. string.format("LPS: %s\r\n\r\n", lps_display)
|
||||
|
||||
@@ -528,6 +571,13 @@ function render_menu()
|
||||
oda_string = oda_string .. string.format("%d%s - %04X | ", grp, ver_char, data.aid)
|
||||
end
|
||||
out = out .. string.format("ODA: %s\r\n", oda_string:sub(1, #oda_string-2))
|
||||
elseif current_menu == 4 then
|
||||
if time_display_offset > 2 then out = out .. string.format("RDS-System time offset: %d seconds\r\n", time_display_offset)
|
||||
else out = out .. string.format("RDS-System time offset: ~0\r\n") end
|
||||
out = out .. string.format("Local time: %s\r\n", time_display_local)
|
||||
out = out .. string.format("UTC time: %s\r\n", time_display_utc)
|
||||
elseif current_menu == event_count and menu_extended then
|
||||
out = out .. "Toggled windows stickness"
|
||||
end
|
||||
|
||||
local hash = crc(out)
|
||||
@@ -538,7 +588,13 @@ function render_menu()
|
||||
end
|
||||
|
||||
function event(event)
|
||||
current_menu = event
|
||||
if event > event_count then
|
||||
menu_extended = true
|
||||
if event-event_count == event_count then set_window_stick(not get_window_stick()) end
|
||||
else
|
||||
menu_extended = false
|
||||
current_menu = event
|
||||
end
|
||||
render_menu()
|
||||
end
|
||||
|
||||
@@ -560,13 +616,22 @@ function command(cmd, param)
|
||||
db.add_value("PTY.Name", string.format("%s / %s", pty_rds[pty+1], pty_rbds[pty+1]))
|
||||
db.add_value("ECC", string.format("%X", ecc))
|
||||
db.add_value("LPS", lps_display)
|
||||
db.add_value("LocalTime", time_display_local)
|
||||
db.add_value("UTCTime", time_display_utc)
|
||||
-- TODO time error
|
||||
db.add_value("RTP.RawData", string.format("%d,%d,%d,%d,%d,%d\r\n", rtp_type1, rtp_start1, rtp_len1, rtp_type2, rtp_start2, rtp_len2))
|
||||
|
||||
local current_rt = rta_display
|
||||
if not last_rt then current_rt = rtb_display end
|
||||
db.add_value("RTP.Tag1", current_rt:sub(rtp_start1+1, rtp_start1+rtp_len1+1))
|
||||
db.add_value("RTP.Tag2", current_rt:sub(rtp_start2+1, rtp_start2+rtp_len2+1))
|
||||
db.add_value("RTP.Tag1Type", rtp_types[rtp_type1+1])
|
||||
db.add_value("RTP.Tag2Type", rtp_types[rtp_type2+1])
|
||||
elseif cmd:lower() == "resetdata" then
|
||||
ert_string = string.rep("_", 128)
|
||||
rt_a = string.rep("_", 64)
|
||||
rt_b = string.rep("_", 64)
|
||||
odas = {}
|
||||
last_pi = 0
|
||||
last_super_pi = 0
|
||||
pty = 0
|
||||
tp = false
|
||||
ta = false
|
||||
@@ -575,8 +640,20 @@ function command(cmd, param)
|
||||
ptyn_toggle = false
|
||||
ecc = 0
|
||||
lps = string.rep("_", 32)
|
||||
elseif cmd:lower() == "superpi" then
|
||||
if #param <= 4 then last_super_pi = tonumber(param, 16) end
|
||||
time_display_utc = "-"
|
||||
time_display_local = "-"
|
||||
time_display_offset = 0
|
||||
rtp_running = false
|
||||
rtp_toggle = false
|
||||
rtp_type1 = 0
|
||||
rtp_start1 = 0
|
||||
rtp_len1 = 0
|
||||
rtp_type2 = 0
|
||||
rtp_start2 = 0
|
||||
rtp_len2 = 0
|
||||
expected_afs = 0
|
||||
afs = {}
|
||||
state_af_am_follows = false
|
||||
end
|
||||
end
|
||||
|
||||
@@ -587,12 +664,89 @@ local function findODAByAID(t, targetAID)
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
function group(stream, b_corr, a, b, c, d)
|
||||
local function dateToEpoch(year, month, day)
|
||||
local daysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
|
||||
local function isLeapYear(y)
|
||||
return (y % 4 == 0 and y % 100 ~= 0) or (y % 400 == 0)
|
||||
end
|
||||
|
||||
if year < 2025 or month < 1 or month > 12 or day < 1 or day > 31 then error(string.format("%d %d %d", year, month, day), 2) end
|
||||
|
||||
local totalDays = 0
|
||||
for y = 2025, year - 1 do
|
||||
totalDays = totalDays + (isLeapYear(y) and 366 or 365)
|
||||
end
|
||||
|
||||
for m = 1, month - 1 do
|
||||
local days = daysInMonth[m]
|
||||
if m == 2 and isLeapYear(year) then days = 29 end
|
||||
totalDays = totalDays + days
|
||||
end
|
||||
|
||||
totalDays = totalDays + (day - 1)
|
||||
|
||||
return totalDays * 86400
|
||||
end
|
||||
|
||||
local function epochToDate(epochSeconds)
|
||||
local totalDays = math.floor(epochSeconds / 86400)
|
||||
|
||||
local remainingSeconds = epochSeconds % 86400
|
||||
local hour = math.floor(remainingSeconds / 3600)
|
||||
local minute = math.floor((remainingSeconds % 3600) / 60)
|
||||
|
||||
local year = 2025
|
||||
|
||||
local function isLeapYear(y)
|
||||
return (y % 4 == 0 and y % 100 ~= 0) or (y % 400 == 0)
|
||||
end
|
||||
|
||||
while true do
|
||||
local daysInYear = isLeapYear(year) and 366 or 365
|
||||
if totalDays < daysInYear then break end
|
||||
totalDays = totalDays - daysInYear
|
||||
year = year + 1
|
||||
end
|
||||
|
||||
local daysInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
if isLeapYear(year) then daysInMonth[2] = 29 end
|
||||
|
||||
local month = 1
|
||||
for m = 1, 12 do
|
||||
if totalDays < daysInMonth[m] then break end
|
||||
totalDays = totalDays - daysInMonth[m]
|
||||
month = month + 1
|
||||
end
|
||||
|
||||
return year, month, totalDays + 1, hour, minute
|
||||
end
|
||||
|
||||
local function getDayOfWeek(year, month, day)
|
||||
if month < 3 then
|
||||
month = month + 12
|
||||
year = year - 1
|
||||
end
|
||||
|
||||
local K = year % 100
|
||||
local J = math.floor(year / 100)
|
||||
|
||||
local h = (day + math.floor(13 * (month + 1) / 5) + K + math.floor(K / 4) + math.floor(J / 4) - 2 * J) % 7
|
||||
|
||||
return ((h + 5) % 7) + 1
|
||||
end
|
||||
|
||||
---@param stream integer
|
||||
---@param b_corr boolean
|
||||
---@param a integer
|
||||
---@param b integer
|
||||
---@param c integer
|
||||
---@param d integer
|
||||
---@param time timetable
|
||||
function group(stream, b_corr, a, b, c, d, time)
|
||||
if stream ~= 0 and a ~= 0 then return
|
||||
elseif stream ~= 0 and not db.load_boolean("rdsspy.ini", "General", "Tunnelling", false) then return end
|
||||
|
||||
if a > 0 then last_pi = a end
|
||||
|
||||
render_menu()
|
||||
|
||||
if b_corr or b < 0 then return end
|
||||
@@ -610,8 +764,10 @@ function group(stream, b_corr, a, b, c, d)
|
||||
if odas[target_group] == nil then odas[target_group] = { aid = d, version = (b & 1) } end
|
||||
else
|
||||
local ert_grp, ert_ver = findODAByAID(odas, 0x6552)
|
||||
local rtp_grp, rtp_ver = findODAByAID(odas, 0x4BD7)
|
||||
|
||||
if ert_grp and group_type == ert_grp and group_version == ert_ver then
|
||||
if d < 0 or c < 0 then return end
|
||||
local ert_state = b & 0x1f
|
||||
local new_chars = string.char((c >> 8) & 0xff) .. string.char(c & 0xff) .. string.char((d >> 8) & 0xff) .. string.char(d & 0xff)
|
||||
local start_pos = (ert_state * 4) + 1
|
||||
@@ -620,6 +776,16 @@ function group(stream, b_corr, a, b, c, d)
|
||||
local carriage = ert_string:find("\r", 1, true)
|
||||
if carriage then ert_display = ert_string:sub(1, carriage - 1)
|
||||
else ert_display = ert_string:gsub("%s+$", "") end
|
||||
elseif rtp_grp and group_type == rtp_grp and group_version == rtp_ver then
|
||||
if d < 0 or c < 0 then return end
|
||||
rtp_toggle = ((b & 0x10) >> 4) ~= 0
|
||||
rtp_running = ((b & 8) >> 3) ~= 0
|
||||
rtp_type1 = (b & 7) << 3 | (c & 0xe000) >> 13
|
||||
rtp_start1 = (c & 0x1f80) >> 7
|
||||
rtp_len1 = (c >> 1) & 63
|
||||
rtp_type2 = ((c & 1) << 6) | (d >> 11) & 63
|
||||
rtp_start2 = (d >> 5) & 63
|
||||
rtp_len2 = d & 0x1f
|
||||
else
|
||||
if group_type == 0 then
|
||||
ta = ((b & 0x10) >> 4) ~= 0
|
||||
@@ -627,6 +793,45 @@ function group(stream, b_corr, a, b, c, d)
|
||||
local segment = b & 0x3
|
||||
if di_bit and segment == 0 then dpty = true
|
||||
elseif segment == 0 then dpty = false end
|
||||
if c < 0 or group_version == 1 then return end
|
||||
local af_high = c >> 8
|
||||
local af_low = c & 0xff
|
||||
if af_high >= 224 and af_high <= (224+25) then
|
||||
local run_new = false
|
||||
expected_afs = af_high - 224
|
||||
if af_low ~= 205 and af_low ~= 250 and #afs ~= 0 and afs[1] ~= (af_low+875)/10 then run_new = true end
|
||||
if #afs ~= expected_afs or run_new then
|
||||
afs = {}
|
||||
state_af_am_follows = false
|
||||
if af_low ~= 205 and af_low ~= 250 then table.insert(afs, (af_low+875)/10)
|
||||
elseif af_low == 250 then state_af_am_follows = true end
|
||||
end
|
||||
elseif #afs ~= expected_afs then
|
||||
if not (af_high == 250 or state_af_am_follows) then
|
||||
local freq = (af_high+875)/10
|
||||
local found
|
||||
for _, value in ipairs(afs) do
|
||||
if value == freq then
|
||||
found = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not found then table.insert(afs, freq) end
|
||||
end
|
||||
if state_af_am_follows then state_af_am_follows = false end
|
||||
if not (af_high == 250 or af_low == 205 or af_low == 250) then
|
||||
local freq = (af_low+875)/10
|
||||
local found
|
||||
for _, value in ipairs(afs) do
|
||||
if value == freq then
|
||||
found = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not found then table.insert(afs, freq) end
|
||||
end
|
||||
if af_low == 250 then state_af_am_follows = true end
|
||||
end
|
||||
elseif group_type == 1 and group_version == 0 then
|
||||
if d < 0 then return end
|
||||
local variant = (c & 0x7000) >> 12
|
||||
@@ -696,6 +901,35 @@ function group(stream, b_corr, a, b, c, d)
|
||||
local carriage = lps:find("\r", 1, true)
|
||||
if carriage then lps_display = lps:sub(1, carriage - 1)
|
||||
else lps_display = lps:gsub("%s+$", "") end
|
||||
elseif group_type == 4 and group_version == 0 then
|
||||
if d < 0 or c < 0 then return end
|
||||
local mjd = ((b & 7) << 15) | c >> 1
|
||||
local year = math.floor((mjd - 15078.2) / 365.25)
|
||||
local month = math.floor((mjd - 14956.1 - math.floor(year * 365.25)) / 30.6001)
|
||||
local day = mjd - 14956 - math.floor(year * 365.25) - math.floor(month * 30.6001)
|
||||
local k = 0
|
||||
if month == 14 or month == 15 then k = 1 end
|
||||
year = year + 1900 + k
|
||||
month = month - 1 - k * 12
|
||||
|
||||
local hour = (c & 1) << 4 | (d & 0xf000) >> 12
|
||||
local minute = (d & 0xfc0) >> 6
|
||||
local offset_sign = (d & 32) >> 5 -- 0 = +, i have no clue why
|
||||
local offset = d & 31 -- 2 = hour, meaning one means 30 minutes of offset
|
||||
|
||||
local epoch = dateToEpoch(year, month, day) + (hour * 3600) + (minute * 60)
|
||||
local utc_year, utc_month, utc_day, utc_hour, utc_minute = epochToDate(epoch)
|
||||
local weekday_table = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}
|
||||
time_display_utc = string.format("%d/%02d/%02d (%s) - %02d:%02d", utc_year, utc_month, utc_day, weekday_table[getDayOfWeek(utc_year, utc_month, utc_day)], utc_hour, utc_minute)
|
||||
|
||||
if offset_sign == 0 then epoch = epoch + (offset*1800)
|
||||
else epoch = epoch - (offset*1800) end
|
||||
|
||||
local systemepoch = dateToEpoch(time.year, time.month, time.day) + (time.hour * 3600) + (time.minute * 60) + time.second + (time.centisecond * 0.01)
|
||||
time_display_offset = math.floor(math.abs(epoch - systemepoch))
|
||||
|
||||
local local_year, local_month, local_day, local_hour, local_minute = epochToDate(epoch)
|
||||
time_display_local = string.format("%d/%02d/%02d (%s) - %02d:%02d", local_year, local_month, local_day, weekday_table[getDayOfWeek(local_year, local_month, local_day)], local_hour, local_minute)
|
||||
end
|
||||
end
|
||||
end
|
||||
208
plugin.c
208
plugin.c
@@ -12,7 +12,7 @@ typedef struct {
|
||||
uint8_t Month;
|
||||
uint8_t Day;
|
||||
uint8_t Hour;
|
||||
uint8_t Minutes;
|
||||
uint8_t Minute;
|
||||
uint8_t Second;
|
||||
uint8_t Centisecond;
|
||||
uint16_t RFU;
|
||||
@@ -80,7 +80,10 @@ static const unsigned char EBU[127] = {
|
||||
0x00, 0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE6, 0x9C, 0x9F, 0x00
|
||||
};
|
||||
|
||||
static unsigned int console_mode = 0;
|
||||
static unsigned short console_mode = 0;
|
||||
static unsigned short stop_execution = 0;
|
||||
static unsigned short sticky = 0;
|
||||
static unsigned char workspaceFile[MAX_PATH] = "";
|
||||
|
||||
const char* int_to_string(int value) {
|
||||
static char buffer[16];
|
||||
@@ -113,7 +116,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
int offset = 0;
|
||||
if(HIWORD(wParam) == BN_DOUBLECLICKED) offset = BUTTON_COUNT;
|
||||
|
||||
if (controlId == IDC_MAIN_BUTTON) InitLua();
|
||||
if (controlId == IDC_MAIN_BUTTON && HIWORD(wParam) == BN_DOUBLECLICKED) InitLua();
|
||||
else if (controlId > IDC_MAIN_BUTTON && controlId <= IDC_MAIN_BUTTON + BUTTON_COUNT) lua_event((controlId - IDC_MAIN_BUTTON) + offset);
|
||||
}
|
||||
break;
|
||||
@@ -156,7 +159,7 @@ void CreatePluginWindow(HWND hOwner) {
|
||||
|
||||
HWND hButton = CreateWindowEx(
|
||||
0, "BUTTON", "Reload",
|
||||
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
|
||||
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON | BS_NOTIFY,
|
||||
10, WINDOW_HEIGHT-62,
|
||||
70, 30, hWnd,
|
||||
(HMENU)IDC_MAIN_BUTTON, hInst, NULL
|
||||
@@ -226,6 +229,17 @@ int lua_set_console_mode(lua_State* localL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_set_window_stick(lua_State* localL) {
|
||||
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
|
||||
sticky = lua_toboolean(localL, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_get_window_stick(lua_State* localL) {
|
||||
lua_pushboolean(localL, sticky);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_set_font_size(lua_State* localL) {
|
||||
int size = luaL_checkinteger(localL, 1);
|
||||
|
||||
@@ -363,106 +377,50 @@ int lua_CharConv(lua_State* localL) {
|
||||
}
|
||||
|
||||
int lua_SaveString(lua_State* localL) {
|
||||
const char* filename = luaL_checkstring(localL, 1);
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
const char* value = luaL_checkstring(localL, 4);
|
||||
if (lua_isstring(localL, 1)) {
|
||||
const char* filename = luaL_checkstring(localL, 1);
|
||||
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
WritePrivateProfileStringA(section, key, value, fullPath);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_SaveInteger(lua_State* localL) {
|
||||
const char* filename = luaL_checkstring(localL, 1);
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
int value = luaL_checkinteger(localL, 4);
|
||||
|
||||
char valueStr[32];
|
||||
snprintf(valueStr, 32, "%d", value);
|
||||
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
WritePrivateProfileStringA(section, key, valueStr, fullPath);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_SaveBoolean(lua_State* localL) {
|
||||
const char* filename = luaL_checkstring(localL, 1);
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
int value = lua_toboolean(localL, 4);
|
||||
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
WritePrivateProfileStringA(section, key, value ? "1" : "0", fullPath);
|
||||
}
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
WritePrivateProfileStringA(section, key, value, fullPath);
|
||||
}
|
||||
} else if(lua_isnil(localL, 1)) WritePrivateProfileStringA(section, key, value, workspaceFile);
|
||||
else luaL_typeerror(L, 1, lua_typename(L, LUA_TSTRING));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_LoadString(lua_State* localL) {
|
||||
const char* filename = luaL_checkstring(localL, 1);
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
const char* defaultValue = luaL_optstring(localL, 4, "");
|
||||
|
||||
char buffer[1024];
|
||||
char path[MAX_PATH];
|
||||
if (lua_isstring(localL, 1)) {
|
||||
const char* filename = luaL_checkstring(localL, 1);
|
||||
char path[MAX_PATH];
|
||||
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
GetPrivateProfileStringA(section, key, defaultValue, buffer, 1024, fullPath);
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
GetPrivateProfileStringA(section, key, defaultValue, buffer, 1024, fullPath);
|
||||
lua_pushstring(localL, buffer);
|
||||
} else lua_pushstring(localL, defaultValue);
|
||||
return 1;
|
||||
} else if(lua_isnil(localL, 1)) {
|
||||
GetPrivateProfileStringA(section, key, defaultValue, buffer, 1024, workspaceFile);
|
||||
lua_pushstring(localL, buffer);
|
||||
} else lua_pushstring(localL, defaultValue);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_LoadInteger(lua_State* localL) {
|
||||
const char* filename = luaL_checkstring(localL, 1);
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
int defaultValue = luaL_optinteger(localL, 4, 0);
|
||||
|
||||
char path[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
int value = GetPrivateProfileIntA(section, key, defaultValue, fullPath);
|
||||
lua_pushinteger(localL, value);
|
||||
} else lua_pushinteger(localL, defaultValue);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_LoadBoolean(lua_State* localL) {
|
||||
const char* filename = luaL_checkstring(localL, 1);
|
||||
const char* section = luaL_checkstring(localL, 2);
|
||||
const char* key = luaL_checkstring(localL, 3);
|
||||
int defaultValue = lua_toboolean(localL, 4);
|
||||
|
||||
char buffer[16];
|
||||
char path[MAX_PATH];
|
||||
|
||||
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path))) {
|
||||
char fullPath[MAX_PATH];
|
||||
snprintf(fullPath, MAX_PATH, "%s\\RDS Spy\\%s", path, filename);
|
||||
GetPrivateProfileStringA(section, key, defaultValue ? "1" : "0", buffer, 16, fullPath);
|
||||
lua_pushboolean(localL, atoi(buffer) != 0);
|
||||
} else lua_pushboolean(localL, defaultValue);
|
||||
return 1;
|
||||
return 1;
|
||||
} else luaL_typeerror(L, 1, lua_typename(L, LUA_TSTRING));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lua_call_command(const char* Cmd, const char* Param) {
|
||||
if(stop_execution != 0) return;
|
||||
lua_getglobal(L, "command");
|
||||
|
||||
if (lua_isfunction(L, -1)) {
|
||||
@@ -473,11 +431,13 @@ void lua_call_command(const char* Cmd, const char* Param) {
|
||||
snprintf(msg_buffer, sizeof(msg_buffer), "Lua error: %s at '%s'\n", lua_tostring(L, -1), "command");
|
||||
AppendText(msg_buffer);
|
||||
lua_pop(L, 1);
|
||||
stop_execution = 1;
|
||||
}
|
||||
} else lua_pop(L, 1);
|
||||
}
|
||||
|
||||
void lua_call_group() {
|
||||
if(stop_execution != 0) return;
|
||||
lua_getglobal(L, "group");
|
||||
|
||||
if (lua_isfunction(L, -1)) {
|
||||
@@ -487,16 +447,35 @@ void lua_call_group() {
|
||||
lua_pushinteger(L, Group.Blk2);
|
||||
lua_pushinteger(L, Group.Blk3);
|
||||
lua_pushinteger(L, Group.Blk4);
|
||||
if (lua_pcall(L, 6, 0, 0) != LUA_OK) {
|
||||
|
||||
lua_newtable(L);
|
||||
lua_pushinteger(L, Group.Year);
|
||||
lua_setfield(L, -2, "year");
|
||||
lua_pushinteger(L, Group.Month);
|
||||
lua_setfield(L, -2, "month");
|
||||
lua_pushinteger(L, Group.Day);
|
||||
lua_setfield(L, -2, "day");
|
||||
lua_pushinteger(L, Group.Hour);
|
||||
lua_setfield(L, -2, "hour");
|
||||
lua_pushinteger(L, Group.Minute);
|
||||
lua_setfield(L, -2, "minute");
|
||||
lua_pushinteger(L, Group.Second);
|
||||
lua_setfield(L, -2, "second");
|
||||
lua_pushinteger(L, Group.Centisecond);
|
||||
lua_setfield(L, -2, "centisecond");
|
||||
|
||||
if (lua_pcall(L, 7, 0, 0) != LUA_OK) {
|
||||
char msg_buffer[255];
|
||||
snprintf(msg_buffer, sizeof(msg_buffer), "Lua error: %s at '%s'\r\n", lua_tostring(L, -1), "group");
|
||||
AppendText(msg_buffer);
|
||||
lua_pop(L, 1);
|
||||
stop_execution = 1;
|
||||
}
|
||||
} else lua_pop(L, 1);
|
||||
}
|
||||
|
||||
void lua_event(int event) {
|
||||
if(stop_execution != 0) return;
|
||||
lua_getglobal(L, "event");
|
||||
|
||||
if (lua_isfunction(L, -1)) {
|
||||
@@ -506,18 +485,19 @@ void lua_event(int event) {
|
||||
snprintf(msg_buffer, sizeof(msg_buffer), "Lua error: %s at '%s'\r\n", lua_tostring(L, -1), "event");
|
||||
AppendText(msg_buffer);
|
||||
lua_pop(L, 1);
|
||||
stop_execution = 1;
|
||||
}
|
||||
} else lua_pop(L, 1);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void __stdcall RDSGroup(TRDSGroup* PRDSGroup) {
|
||||
__declspec(dllexport) void WINAPI RDSGroup(TRDSGroup* PRDSGroup) {
|
||||
if (PRDSGroup == NULL) return;
|
||||
|
||||
Group = *PRDSGroup;
|
||||
lua_call_group();
|
||||
}
|
||||
|
||||
__declspec(dllexport) void __stdcall Command(const char* Cmd, const char* Param) {
|
||||
__declspec(dllexport) void WINAPI Command(const char* Cmd, const char* Param) {
|
||||
if (Cmd == NULL) return;
|
||||
if (_stricmp(Cmd, "EXIT") == 0) {
|
||||
if (hWnd != NULL) {
|
||||
@@ -528,10 +508,12 @@ __declspec(dllexport) void __stdcall Command(const char* Cmd, const char* Param)
|
||||
lua_close(L);
|
||||
L = NULL;
|
||||
}
|
||||
} else if (_stricmp(Cmd, "CONFIGURE") == 0) ShowWindow(hWnd, SW_SHOW);
|
||||
else if (_stricmp(Cmd, "SHOW") == 0) ShowWindow(hWnd, SW_SHOW);
|
||||
else if (_stricmp(Cmd, "MINIMIZE") == 0) ShowWindow(hWnd, SW_MINIMIZE);
|
||||
else if (_stricmp(Cmd, "RESTORE") == 0) ShowWindow(hWnd, SW_RESTORE);
|
||||
} else if (_stricmp(Cmd, "CONFIGURE") == 0 || _stricmp(Cmd, "SHOW") == 0 || _stricmp(Cmd, "RESTORE") == 0) ShowWindow(hWnd, SW_SHOW);
|
||||
else if (_stricmp(Cmd, "MINIMIZE") == 0) ShowWindow(hWnd, SW_HIDE);
|
||||
else if (_stricmp(Cmd, "SHOWHIDE") == 0) {
|
||||
if(IsWindowVisible(hWnd)) ShowWindow(hWnd, SW_HIDE);
|
||||
else ShowWindow(hWnd, SW_SHOW);
|
||||
}
|
||||
else if (_stricmp(Cmd, "OPENWORKSPACE") == 0) {
|
||||
if(hWnd != NULL) {
|
||||
int value = GetPrivateProfileIntA("luahost", "Visible", 0, Param);
|
||||
@@ -541,6 +523,7 @@ __declspec(dllexport) void __stdcall Command(const char* Cmd, const char* Param)
|
||||
int y = GetPrivateProfileIntA("luahost", "Top", 240, Param);
|
||||
SetWindowPos(hWnd, NULL, x, y, 0, 0, SWP_NOSIZE);
|
||||
}
|
||||
sticky = GetPrivateProfileIntA("luahost", "Stick", 0, Param);
|
||||
lua_call_command(Cmd, Param); // still call
|
||||
} else if (_stricmp(Cmd, "SAVEWORKSPACE") == 0) {
|
||||
if(hWnd != NULL) {
|
||||
@@ -549,8 +532,11 @@ __declspec(dllexport) void __stdcall Command(const char* Cmd, const char* Param)
|
||||
WritePrivateProfileStringA("luahost", "Left", int_to_string(rect.left), Param);
|
||||
WritePrivateProfileStringA("luahost", "Top", int_to_string(rect.top), Param);
|
||||
}
|
||||
WritePrivateProfileStringA("luahost", "Stick", (sticky != 0) ? "1" : "0", Param);
|
||||
WritePrivateProfileStringA("luahost", "Visible", IsWindowVisible(hWnd) ? "1" : "0", Param);
|
||||
}
|
||||
memcpy(workspaceFile, Param, MAX_PATH);
|
||||
workspaceFile[MAX_PATH-1] = 0;
|
||||
lua_call_command(Cmd, Param); // still call
|
||||
} else if (_stricmp(Cmd, "LUASCRIPT") == 0) { // custom
|
||||
char msg_buffer[255];
|
||||
@@ -558,17 +544,29 @@ __declspec(dllexport) void __stdcall Command(const char* Cmd, const char* Param)
|
||||
snprintf(msg_buffer, sizeof(msg_buffer), "Lua error loading file: %s\r\n", lua_tostring(L, -1));
|
||||
AppendText(msg_buffer);
|
||||
lua_pop(L, 1);
|
||||
stop_execution = 1;
|
||||
} else {
|
||||
if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
|
||||
snprintf(msg_buffer, sizeof(msg_buffer), "Init error: %s\r\n", lua_tostring(L, -1));
|
||||
AppendText(msg_buffer);
|
||||
lua_pop(L, 1);
|
||||
stop_execution = 1;
|
||||
}
|
||||
}
|
||||
} else if(_stricmp(Cmd, "MOVEX") == 0) {
|
||||
if(sticky != 0) {
|
||||
RECT rect; // get rect
|
||||
if (GetWindowRect(hWnd, &rect)) SetWindowPos(hWnd, NULL, rect.left+atoi(Param), rect.top, 0, 0, SWP_NOSIZE);
|
||||
}
|
||||
} else if(_stricmp(Cmd, "MOVEY") == 0) {
|
||||
if(sticky != 0) {
|
||||
RECT rect; // get rect
|
||||
if (GetWindowRect(hWnd, &rect)) SetWindowPos(hWnd, NULL, rect.left, rect.top+atoi(Param), 0, 0, SWP_NOSIZE);
|
||||
}
|
||||
} else lua_call_command(Cmd, Param);
|
||||
}
|
||||
|
||||
__declspec(dllexport) const char* __stdcall PluginName(void) { return "Lua Host"; }
|
||||
__declspec(dllexport) const char* WINAPI PluginName(void) { return "Lua Host"; }
|
||||
|
||||
void InitLua() {
|
||||
if(L != NULL) {
|
||||
@@ -582,6 +580,11 @@ void InitLua() {
|
||||
lua_register(L, "log", lua_log);
|
||||
lua_register(L, "set_console", lua_set_console);
|
||||
lua_register(L, "set_console_mode", lua_set_console_mode);
|
||||
lua_register(L, "set_window_stick", lua_set_window_stick);
|
||||
lua_register(L, "get_window_stick", lua_get_window_stick);
|
||||
|
||||
lua_pushinteger(L, BUTTON_COUNT);
|
||||
lua_setglobal(L, "event_count");
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
@@ -606,24 +609,13 @@ void InitLua() {
|
||||
lua_pushcfunction(L, lua_SaveString);
|
||||
lua_setfield(L, -2, "save_string");
|
||||
|
||||
lua_pushcfunction(L, lua_SaveInteger);
|
||||
lua_setfield(L, -2, "save_integer");
|
||||
|
||||
lua_pushcfunction(L, lua_SaveBoolean);
|
||||
lua_setfield(L, -2, "save_boolean");
|
||||
|
||||
lua_pushcfunction(L, lua_LoadString);
|
||||
lua_setfield(L, -2, "load_string");
|
||||
|
||||
lua_pushcfunction(L, lua_LoadInteger);
|
||||
lua_setfield(L, -2, "load_integer");
|
||||
|
||||
lua_pushcfunction(L, lua_LoadBoolean);
|
||||
lua_setfield(L, -2, "load_boolean");
|
||||
|
||||
lua_setglobal(L, "db");
|
||||
|
||||
console_mode = 0;
|
||||
stop_execution = 0;
|
||||
|
||||
char path[MAX_PATH];
|
||||
char fullPath[MAX_PATH];
|
||||
@@ -640,16 +632,18 @@ void InitLua() {
|
||||
snprintf(msg_buffer, sizeof(msg_buffer), "Lua error loading file: %s\r\n", lua_tostring(L, -1));
|
||||
AppendText(msg_buffer);
|
||||
lua_pop(L, 1);
|
||||
stop_execution = 1;
|
||||
} else {
|
||||
if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
|
||||
snprintf(msg_buffer, sizeof(msg_buffer), "Lua error: %s\r\n", lua_tostring(L, -1));
|
||||
AppendText(msg_buffer);
|
||||
lua_pop(L, 1);
|
||||
stop_execution = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__declspec(dllexport) int __stdcall Initialize(HANDLE hHandle, TDB* DBPointer) {
|
||||
__declspec(dllexport) int WINAPI Initialize(HANDLE hHandle, TDB* DBPointer) {
|
||||
CreatePluginWindow(hHandle);
|
||||
AppendText(LUA_COPYRIGHT);
|
||||
AppendText("\r\n");
|
||||
|
||||
55
plugin.lua
55
plugin.lua
@@ -1,11 +1,23 @@
|
||||
---@meta
|
||||
|
||||
---@type integer
|
||||
event_count = 0
|
||||
|
||||
---This function should be defined by the user in the script
|
||||
---EXIT, CONFIGURE, SHOW, MINIMIZE, RESTORE commands are not sent to the script
|
||||
---EXIT, CONFIGURE, SHOW, MINIMIZE, RESTORE, MOVEX, MOVEY commands are not sent to the script
|
||||
---@param cmd string
|
||||
---@param param string
|
||||
function command(cmd, param) end
|
||||
|
||||
---@class timetable
|
||||
---@field year integer
|
||||
---@field month integer
|
||||
---@field day integer
|
||||
---@field hour integer
|
||||
---@field minute integer
|
||||
---@field second integer
|
||||
---@field centisecond integer
|
||||
|
||||
---This function should be defined by the user in the script
|
||||
---@param stream integer
|
||||
---@param block_b_correction boolean
|
||||
@@ -13,7 +25,8 @@ function command(cmd, param) end
|
||||
---@param b integer
|
||||
---@param c integer
|
||||
---@param d integer
|
||||
function group(stream, block_b_correction, a, b, c, d) end
|
||||
---@param time timetable
|
||||
function group(stream, block_b_correction, a, b, c, d, time) end
|
||||
|
||||
---This function should be defined by the user in the script
|
||||
---@param event integer
|
||||
@@ -38,6 +51,12 @@ function set_console(data) end
|
||||
---@param mode boolean
|
||||
function set_console_mode(mode) end
|
||||
|
||||
---Settings this on makes the window move with the main RDS Spy window regardless the console is
|
||||
---@param stick boolean
|
||||
function set_window_stick(stick) end
|
||||
---@return boolean
|
||||
function get_window_stick() end
|
||||
|
||||
db = {}
|
||||
|
||||
---@param key string
|
||||
@@ -61,41 +80,15 @@ function db.count_records(key, value) end
|
||||
---@return integer
|
||||
function db.char_conv(ch) end
|
||||
|
||||
---@param filename string
|
||||
---@param filename string|nil nil means workspace file
|
||||
---@param section string
|
||||
---@param key string
|
||||
---@param value string
|
||||
function db.save_string(filename, section, key, value) end
|
||||
|
||||
---@param filename string
|
||||
---@param section string
|
||||
---@param key string
|
||||
---@param value integer
|
||||
function db.save_integer(filename, section, key, value) end
|
||||
|
||||
---@param filename string
|
||||
---@param section string
|
||||
---@param key string
|
||||
---@param value boolean
|
||||
function db.save_boolean(filename, section, key, value) end
|
||||
|
||||
---@param filename string
|
||||
---@param filename string|nil nil means workspace file
|
||||
---@param section string
|
||||
---@param key string
|
||||
---@param defaultValue string
|
||||
---@return string
|
||||
function db.load_string(filename, section, key, defaultValue) end
|
||||
|
||||
---@param filename string
|
||||
---@param section string
|
||||
---@param key string
|
||||
---@param defaultValue integer|nil optional
|
||||
---@return integer
|
||||
function db.load_integer(filename, section, key, defaultValue) end
|
||||
|
||||
---@param filename string
|
||||
---@param section string
|
||||
---@param key string
|
||||
---@param defaultValue boolean|nil optional
|
||||
---@return boolean
|
||||
function db.load_boolean(filename, section, key, defaultValue) end
|
||||
function db.load_string(filename, section, key, defaultValue) end
|
||||
Reference in New Issue
Block a user