change the api and extend lua user data len

This commit is contained in:
2026-04-23 21:19:33 +02:00
parent 865ac5b979
commit d79c238924
7 changed files with 212 additions and 164 deletions
+20 -26
View File
@@ -1,11 +1,8 @@
---@meta ---@meta
-- Global Variables
---@type string ---@type string
core_version = "" core_version = ""
--#region Functions implemented or used in C
dp = {} dp = {}
---@type integer ---@type integer
@@ -30,9 +27,9 @@ function dp.force_save() end
---Set the program which is actually being modulated. Setting this does not affect the writing program ---Set the program which is actually being modulated. Setting this does not affect the writing program
---@param program_idx integer 0 to (max_programs - 1) ---@param program_idx integer 0 to (max_programs - 1)
function dp.set_program(program_idx) end function dp.set_output_program(program_idx) end
---@return integer ---@return integer
function dp.get_program() end function dp.get_output_program() end
---Sets the program all of the set/get functions affect ---Sets the program all of the set/get functions affect
---@param program_idx integer 0 to (max_programs - 1) ---@param program_idx integer 0 to (max_programs - 1)
@@ -179,6 +176,7 @@ function rds.set_tps(tps) end
---@param rt string Radio Text (max 64 chars) ---@param rt string Radio Text (max 64 chars)
function rds.set_rt(rt) end function rds.set_rt(rt) end
---@return nil
function rds.toggle_rt_ab() end function rds.toggle_rt_ab() end
---@param lps string ---@param lps string
@@ -213,28 +211,24 @@ function rds.put_rds2_custom_group(a, b, c, d) end
---@param afs table ---@param afs table
function rds.set_af(afs) end function rds.set_af(afs) end
---@class EON_Data
---@field enabled? boolean
---@field pi? integer
---@field tp? boolean
---@field ta? boolean
---@field pty? integer
---@field ps? string
---@field afs? table Empty on the getter - empty table does not mean the same thing as nil
---@field data? integer
---Sets data about the EON ---Sets data about the EON
---@param eon integer Index of the EON we are setting ---@param eon integer Index of the EON we are setting
---@param enabled boolean ---@param data EON_Data
---@param pi integer function rds.set_eon(eon, data) end
---@param tp boolean
---@param ta boolean
---@param pty integer
---@param ps string
---@param afs table
---@param data integer
function rds.set_eon(eon, enabled, pi, tp, ta, pty, ps, afs, data) end
---Gets the same data set_rds_eon sets, yes this returns 8 arguments ---Gets the same data set_rds_eon sets
---@param eon integer ---@param eon integer
---@return boolean enabled ---@return EON_Data
---@return integer pi
---@return boolean tp
---@return boolean ta
---@return integer pty
---@return string ps
---@return table _ this is empty, getting afs is not supported yet
---@return integer data
function rds.get_eon(eon) end function rds.get_eon(eon) end
---Sets the X/Y of the UDG ---Sets the X/Y of the UDG
@@ -256,9 +250,9 @@ userdata.len = 0
function userdata.set(data) end function userdata.set(data) end
---Writes to the userdata at the offset, size does not have to match the length of the string, if the string is less than size then the rest of the string will be padded with zeroes until it is size ---Writes to the userdata at the offset, size does not have to match the length of the string, if the string is less than size then the rest of the string will be padded with zeroes until it is size
---@param offset integer ---@param offset integer
---@param size integer ---@param padded_size integer
---@param data string ---@param data string
function userdata.set_offset(offset, size, data) end function userdata.set_offset(offset, padded_size, data) end
---Returns all of the data saved as user data ---Returns all of the data saved as user data
---@return string ---@return string
@@ -314,7 +308,7 @@ function rds.ext.set_af_oda(afs) end
---@param group_version boolean ---@param group_version boolean
---@param aid integer ---@param aid integer
---@param data integer ---@param data integer
---@param temp boolean ---@param temp boolean Send AID once (no data) and destroy
---@return integer oda_id ---@return integer oda_id
function ext.register_oda(group, group_version, aid, data, temp) end function ext.register_oda(group, group_version, aid, data, temp) end
+94 -9
View File
@@ -1,4 +1,6 @@
uecp = {} uecp = {}
uecp.site_addreses = {}
uecp.encoder_addreses = {}
uecp.rt_buffer = {} uecp.rt_buffer = {}
uecp.rt_buffer_index = 1 uecp.rt_buffer_index = 1
uecp.rt_tx_remaining = 0 uecp.rt_tx_remaining = 0
@@ -21,7 +23,6 @@ hooks.rt_transmission[#hooks.rt_transmission + 1] = function ()
if entry.toggle_ab then rds.toggle_rt_ab() end if entry.toggle_ab then rds.toggle_rt_ab() end
end end
local mec_handlers = {}
local function dsn_helper(dsn, write) local function dsn_helper(dsn, write)
if dsn == 0 then write() if dsn == 0 then write()
@@ -45,6 +46,7 @@ local function dsn_helper(dsn, write)
end end
end end
local mec_handlers = {}
mec_handlers[1] = function(data) mec_handlers[1] = function(data)
-- PI -- PI
local dsn = string.byte(data, 2) local dsn = string.byte(data, 2)
@@ -99,7 +101,7 @@ mec_handlers[3] = function(data)
local data = string.byte(data, 4) local data = string.byte(data, 4)
dsn_helper(dsn, function () dsn_helper(dsn, function ()
rds.set_ta((data & 1) ~= 0) rds.set_ta((data & 1) ~= 0)
rds.set_ta((data & 2) ~= 0) rds.set_tp((data & 2) ~= 0)
end) end)
return 4 return 4
end end
@@ -181,7 +183,17 @@ mec_handlers[0x13] = function (data)
local psn = string.byte(data, 3) local psn = string.byte(data, 3)
local mel = string.sub(data, 4) local mel = string.sub(data, 4)
-- TODO: decode -- TODO: decode - i have zero clue what the hell is the meaning of the docs, it might as well be in chinese (traditional)
return 4+mel
end
mec_handlers[0x14] = function (data)
-- EON-AF
local dsn = string.byte(data, 2)
local psn = string.byte(data, 3)
local mel = string.sub(data, 4)
-- TODO: decode - haven't read this one
return 4+mel return 4+mel
end end
@@ -195,6 +207,7 @@ mec_handlers[0x1A] = function (data)
local full_data = ((data & 15) << 8) | data_lsb local full_data = ((data & 15) << 8) | data_lsb
local variant = (data >> 4) & 3 local variant = (data >> 4) & 3
if variant == 0 then if variant == 0 then
-- TODO: maybe make it more than just ecc? idk why but would be cool
dsn_helper(dsn, function () dsn_helper(dsn, function ()
rds.set_ecc(full_data) rds.set_ecc(full_data)
end) end)
@@ -202,20 +215,59 @@ mec_handlers[0x1A] = function (data)
return 4 return 4
end end
mec_handlers[0x2E] = function (data)
-- Linkage Information
-- What? What is the main PSN? Does the server tell me that or am i to fucking guess?
return 5
end
mec_handlers[0x24] = function (data)
-- Free-format data in type A or B group
-- TODO: figure out the docs
return 7
end
-- Fuck you mean, i have to implement some fucking "spinning wHELLs"? may the lord have mercy
-- Also no time setting via UECP - this is linux, just install fucking chrony
mec_handlers[0x19] = function (data) mec_handlers[0x19] = function (data)
-- CT -- CT
local data = string.byte(data, 2) local data = string.byte(data, 2)
dsn_helper(255, function ()
rds.set_ct(data ~= 0) rds.set_ct(data ~= 0)
end)
return 2 return 2
end end
mec_handlers[0x23] = function (data)
-- Site address
local control_bits = string.byte(data, 2)
local high = string.byte(data, 3)
local low = string.byte(data, 4)
local data = high << 8 | low
if control_bits == 0 then
for i, v in ipairs(uecp.site_addreses) do
if v == data then table.remove(uecp.site_addreses, i) end
end
elseif control_bits == 1 then uecp.site_addreses[#uecp.site_addreses+1] = data
elseif control_bits == 2 then uecp.site_addreses = {} end
return 4
end
mec_handlers[0x27] = function (data)
-- Encoder address
local control_bits = string.byte(data, 2)
local data = string.byte(data, 3)
if control_bits == 0 then
for i, v in ipairs(uecp.encoder_addreses) do
if v == data then table.remove(uecp.encoder_addreses, i) end
end
elseif control_bits == 1 then uecp.encoder_addreses[#uecp.encoder_addreses+1] = data
elseif control_bits == 2 then uecp.encoder_addreses = {} end
return 3
end
mec_handlers[0x1C] = function (data) mec_handlers[0x1C] = function (data)
-- DS select -- DS select
local dsn = string.byte(data, 2) local dsn = string.byte(data, 2)
dp.set_program(dsn) dp.set_output_program(dsn)
dp.set_writing_program(dsn) dp.set_writing_program(dsn)
return 2 return 2
end end
mec_handlers[0x2D] = function (data) mec_handlers[0x2D] = function (data)
-- Manufacturer -- Manufacturer
local mel = string.byte(data, 2) local mel = string.byte(data, 2)
@@ -246,14 +298,48 @@ local function undo_byte_stuff(data)
return table.concat(output) return table.concat(output)
end end
---@param site integer
---@param encoder integer
---@return boolean
local function check_address(site, encoder)
if site == 0 and encoder == 0 then return true end
local site_allowed = false
if site ~= 0 then
for i, v in ipairs(uecp.site_addreses) do
if v == site then
site_allowed = true
break
end
end
else site_allowed = true end
local encoder_allowed = false
if encoder ~= 0 then
for i, v in ipairs(uecp.encoder_addreses) do
if v == encoder then
encoder_allowed = true
break
end
end
else encoder_allowed = true end
return site_allowed and encoder_allowed
end
---@param packet string ---@param packet string
function uecp.parse_uecp(packet) function uecp.parse_uecp(packet)
if not packet or #packet == 0 then return end
if string.byte(packet, 1) ~= 0xfe or string.byte(packet, #packet) ~= 0xff then return end
local unstuffed = undo_byte_stuff(string.sub(packet, 2, #packet - 1)) local unstuffed = undo_byte_stuff(string.sub(packet, 2, #packet - 1))
local addr1 = string.byte(unstuffed, 1) local addr1 = string.byte(unstuffed, 1)
local addr2 = string.byte(unstuffed, 2) local addr2 = string.byte(unstuffed, 2)
local site_addr = (addr1 << 2) | (addr2 >> 6) local site_addr = (addr1 << 2) | (addr2 >> 6)
local encoder_addr = addr2 & 0x3F
if not check_address(site_addr, addr2 & 0x3F) then return end
local sequence_count = string.byte(unstuffed, 3) local sequence_count = string.byte(unstuffed, 3)
local mfl = string.byte(unstuffed, 4) local mfl = string.byte(unstuffed, 4)
@@ -266,8 +352,7 @@ function uecp.parse_uecp(packet)
local crc_calculated = dp.crc16(string.sub(unstuffed, 1, 4 + mfl)) local crc_calculated = dp.crc16(string.sub(unstuffed, 1, 4 + mfl))
local crc_hi = string.byte(unstuffed, 4 + mfl + 1) local crc_hi = string.byte(unstuffed, 4 + mfl + 1)
local crc_lo = string.byte(unstuffed, 4 + mfl + 2) local crc_stored = (crc_hi << 8) | string.byte(unstuffed, 4 + mfl + 2)
local crc_stored = (crc_hi << 8) | crc_lo
if crc_calculated ~= crc_stored then if crc_calculated ~= crc_stored then
print("bad crc") print("bad crc")
@@ -284,6 +369,6 @@ function uecp.parse_uecp(packet)
end end
local advance = handler(string.sub(data, consumed)) local advance = handler(string.sub(data, consumed))
consumed = consumed + advance consumed = consumed + advance
dp.set_writing_program(dp.get_program()) dp.set_writing_program(dp.get_output_program())
end end
end end
+22 -23
View File
@@ -1,3 +1,4 @@
---@param data string
function data_handle(data) function data_handle(data)
-- UECP -- UECP
if uecp.parse_uecp and string.byte(data, 1) == 0xfe then return uecp.parse_uecp(data) end if uecp.parse_uecp and string.byte(data, 1) == 0xfe then return uecp.parse_uecp(data) end
@@ -85,15 +86,15 @@ function data_handle(data)
local eon_idx = tonumber(eon_cmd) local eon_idx = tonumber(eon_cmd)
if not eon_idx or eon_idx < 1 or eon_idx > rds.eon_count then return "?\r\n" end if not eon_idx or eon_idx < 1 or eon_idx > rds.eon_count then return "?\r\n" end
eon_idx = eon_idx - 1 eon_idx = eon_idx - 1
local enabled, pi, tp, ta, pty, ps, afs, data_val = rds.get_eon(eon_idx) local eon_data = rds.get_eon(eon_idx)
if eon_num == "en" then return string.format("EON%dEN=%d\r\n", eon_idx + 1, enabled and 1 or 0) if eon_num == "en" then return string.format("EON%dEN=%d\r\n", eon_idx + 1, eon_data.enabled and 1 or 0)
elseif eon_num == "pi" then return string.format("EON%dPI=%x\r\n", eon_idx + 1, pi) elseif eon_num == "pi" then return string.format("EON%dPI=%x\r\n", eon_idx + 1, eon_data.pi)
elseif eon_num == "ps" then return string.format("EON%dPS=%s\r\n", eon_idx + 1, ps) elseif eon_num == "ps" then return string.format("EON%dPS=%s\r\n", eon_idx + 1, eon_data.ps)
elseif eon_num == "pty" then return string.format("EON%dPTY=%d\r\n", eon_idx + 1, pty) elseif eon_num == "pty" then return string.format("EON%dPTY=%d\r\n", eon_idx + 1, eon_data.pty)
elseif eon_num == "ta" then return string.format("EON%dTA=%d\r\n", eon_idx + 1, ta and 1 or 0) elseif eon_num == "ta" then return string.format("EON%dTA=%d\r\n", eon_idx + 1, eon_data.ta and 1 or 0)
elseif eon_num == "tp" then return string.format("EON%dTP=%d\r\n", eon_idx + 1, tp and 1 or 0) elseif eon_num == "tp" then return string.format("EON%dTP=%d\r\n", eon_idx + 1, eon_data.tp and 1 or 0)
elseif eon_num == "dt" then return string.format("EON%dDT=%x\r\n", eon_idx + 1, data_val) elseif eon_num == "dt" then return string.format("EON%dDT=%x\r\n", eon_idx + 1, eon_data.data)
end end
end end
return "?\r\n" return "?\r\n"
@@ -109,45 +110,43 @@ function data_handle(data)
if not eon_idx or eon_idx < 1 or eon_idx > rds.eon_count then return "?\r\n" end if not eon_idx or eon_idx < 1 or eon_idx > rds.eon_count then return "?\r\n" end
eon_idx = eon_idx - 1 eon_idx = eon_idx - 1
local enabled, pi, tp, ta, pty, ps, afs, data_val = rds.get_eon(eon_idx)
if eon_type == "en" then if eon_type == "en" then
local en_val = tonumber(value) local en_val = tonumber(value)
if not en_val then return "-\r\n" end if not en_val then return "-\r\n" end
enabled = (en_val ~= 0) local enabled = (en_val ~= 0)
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val) rds.set_eon(eon_idx, { enabled = enabled })
return "+\r\n" return "+\r\n"
elseif eon_type == "pi" then elseif eon_type == "pi" then
local pi_val = tonumber(value, 16) local pi_val = tonumber(value, 16)
if not pi_val then return "-\r\n" end if not pi_val then return "-\r\n" end
rds.set_eon(eon_idx, enabled, pi_val, tp, ta, pty, ps, afs, data_val) rds.set_eon(eon_idx, { pi = pi_val })
return "+\r\n" return "+\r\n"
elseif eon_type == "ps" then elseif eon_type == "ps" then
local ps_val = value:sub(1, 24) local ps_val = value:sub(1, 24)
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps_val, afs, data_val) rds.set_eon(eon_idx, { ps = ps_val })
return "+\r\n" return "+\r\n"
elseif eon_type == "pty" then elseif eon_type == "pty" then
local pty_val = tonumber(value) local pty_val = tonumber(value)
if not pty_val then return "-\r\n" end if not pty_val then return "-\r\n" end
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty_val, ps, afs, data_val) rds.set_eon(eon_idx, { pty = pty_val })
return "+\r\n" return "+\r\n"
elseif eon_type == "ta" then elseif eon_type == "ta" then
if not enabled or not tp then return "-\r\n" end
local ta_val = tonumber(value) local ta_val = tonumber(value)
if not ta_val then return "-\r\n" end if not ta_val then return "-\r\n" end
ta = (ta_val ~= 0) local ta = (ta_val ~= 0)
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val) rds.set_eon(eon_idx, { ta = ta })
if ta then rds.set_ta(true) end if ta then rds.set_ta(true) end
return "+\r\n" return "+\r\n"
elseif eon_type == "tp" then elseif eon_type == "tp" then
local tp_val = tonumber(value) local tp_val = tonumber(value)
if not tp_val then return "-\r\n" end if not tp_val then return "-\r\n" end
tp = (tp_val ~= 0) local tp = (tp_val ~= 0)
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val) rds.set_eon(eon_idx, { tp = tp })
return "+\r\n" return "+\r\n"
elseif eon_type == "af" then elseif eon_type == "af" then
local af_table = {} local af_table = {}
if value == "" or value == "0" then if value == "" or value == "0" then
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps, {}, data_val) rds.set_eon(eon_idx, { afs = {} })
return "+\r\n" return "+\r\n"
end end
for freq_str in value:gmatch("([^,]+)") do for freq_str in value:gmatch("([^,]+)") do
@@ -156,12 +155,12 @@ function data_handle(data)
else return "-\r\n" end else return "-\r\n" end
end end
if #af_table > 25 then return "-\r\n" end if #af_table > 25 then return "-\r\n" end
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps, af_table, data_val) rds.set_eon(eon_idx, { afs = af_table })
return "+\r\n" return "+\r\n"
elseif eon_type == "dt" then elseif eon_type == "dt" then
local dt_val = tonumber(value, 16) local dt_val = tonumber(value, 16)
if not dt_val then return "-\r\n" end if not dt_val then return "-\r\n" end
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, dt_val) rds.set_eon(eon_idx, { data = dt_val })
return "+\r\n" return "+\r\n"
else return "?\r\n" end else return "?\r\n" end
end end
@@ -286,7 +285,7 @@ function data_handle(data)
local program = tonumber(value) local program = tonumber(value)
if not program then return "-\r\n" end if not program then return "-\r\n" end
if program < 1 or program > dp.max_programs then return "-\r\n" end if program < 1 or program > dp.max_programs then return "-\r\n" end
dp.set_program(program-1) dp.set_output_program(program-1)
dp.set_writing_program(program-1) dp.set_writing_program(program-1)
rds.set_ta(false) rds.set_ta(false)
return "+\r\n" return "+\r\n"
+70 -23
View File
@@ -5,7 +5,6 @@ static int in_set_defaults = 0;
extern lua_State *L; extern lua_State *L;
extern RDSEncoder* enc; extern RDSEncoder* enc;
extern uint8_t unload_refs[33];
static int writing_program = 0; static int writing_program = 0;
int lua_get_userdata(lua_State *localL) { int lua_get_userdata(lua_State *localL) {
@@ -54,8 +53,6 @@ int lua_set_rds_program_defaults(lua_State *localL) {
return 0; return 0;
} }
in_set_defaults = 1; in_set_defaults = 1;
for (int i = 1; i < *unload_refs; i++) luaL_unref(L, LUA_REGISTRYINDEX, unload_refs[i]);
unload_refs[0] = 1;
set_rds_defaults(enc, writing_program); set_rds_defaults(enc, writing_program);
lua_call_tfunction_nolock("on_init"); lua_call_tfunction_nolock("on_init");
lua_call_tfunction_nolock("on_state"); lua_call_tfunction_nolock("on_state");
@@ -65,8 +62,6 @@ int lua_set_rds_program_defaults(lua_State *localL) {
int lua_reset_rds(lua_State *localL) { int lua_reset_rds(lua_State *localL) {
(void)localL; (void)localL;
for (int i = 1; i < *unload_refs; i++) luaL_unref(L, LUA_REGISTRYINDEX, unload_refs[i]);
unload_refs[0] = 1;
encoder_saveToFile(enc); encoder_saveToFile(enc);
encoder_loadFromFile(enc); encoder_loadFromFile(enc);
@@ -280,19 +275,58 @@ int lua_toggle_rt_ab(lua_State *localL) {
int lua_set_rds_eon(lua_State *localL) { int lua_set_rds_eon(lua_State *localL) {
int eon = luaL_checkinteger(localL, 1); int eon = luaL_checkinteger(localL, 1);
if(eon >= EONs) return luaL_error(localL, "eon index exceeded"); if(eon >= EONs) return luaL_error(localL, "eon index exceeded");
if (!lua_isboolean(localL, 2)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 2));
if (!lua_isboolean(localL, 4)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 4));
if (!lua_isboolean(localL, 5)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 5));
luaL_checktype(localL, 8, LUA_TTABLE);
enc->data[writing_program].eon[eon].enabled = lua_toboolean(localL, 2);
enc->data[writing_program].eon[eon].pi = luaL_checkinteger(localL, 3);
enc->data[writing_program].eon[eon].tp = lua_toboolean(localL, 4);
enc->data[writing_program].eon[eon].ta = lua_toboolean(localL, 5);
enc->data[writing_program].eon[eon].pty = luaL_checkinteger(localL, 6);
_strncpy(enc->data[writing_program].eon[eon].ps, luaL_checklstring(localL, 7, NULL), 8);
int n = lua_rawlen(localL, 8); if(!lua_istable(localL, 2)) return luaL_error(localL, "table expected, got %s", luaL_typename(localL, 2));
lua_getfield(localL, 2, "enabled");
if(!lua_isnil(localL, -1)) {
luaL_checktype(localL, -1, LUA_TBOOLEAN);
enc->data[writing_program].eon[eon].enabled = lua_toboolean(localL, -1);
} lua_pop(localL, 1);
lua_getfield(localL, 2, "tp");
if(!lua_isnil(localL, -1)) {
luaL_checktype(localL, -1, LUA_TBOOLEAN);
enc->data[writing_program].eon[eon].tp = lua_toboolean(localL, -1);
} lua_pop(localL, 1);
lua_getfield(localL, 2, "ta");
if(!lua_isnil(localL, -1)) {
luaL_checktype(localL, -1, LUA_TBOOLEAN);
enc->data[writing_program].eon[eon].ta = lua_toboolean(localL, -1);
} lua_pop(localL, 1);
lua_getfield(localL, 2, "pi");
if(!lua_isnil(localL, -1)) {
lua_Integer pi = luaL_checkinteger(localL, -1);
lua_pop(localL, 1);
enc->data[writing_program].eon[eon].pi = pi;
} else lua_pop(localL, 1);
lua_getfield(localL, 2, "pty");
if(!lua_isnil(localL, -1)) {
lua_Integer pty = luaL_checkinteger(localL, -1);
lua_pop(localL, 1);
enc->data[writing_program].eon[eon].pty = pty;
} else lua_pop(localL, 1);
lua_getfield(localL, 2, "data");
if(!lua_isnil(localL, -1)) {
lua_Integer data = luaL_checkinteger(localL, -1);
lua_pop(localL, 1);
enc->data[writing_program].eon[eon].data = data;
} else lua_pop(localL, 1);
lua_getfield(localL, 2, "ps");
if(!lua_isnil(localL, -1)) _strncpy(enc->data[writing_program].eon[eon].ps, luaL_checklstring(localL, -1, NULL), 8);
lua_pop(localL, 1);
lua_getfield(localL, 2, "afs");
luaL_checktype(localL, -1, LUA_TTABLE);
int n = lua_rawlen(localL, -1);
if (n == 0) { if (n == 0) {
lua_pop(localL, 1);
memset(&(enc->data[writing_program].eon[eon].af), 0, sizeof(RDSAFs)); memset(&(enc->data[writing_program].eon[eon].af), 0, sizeof(RDSAFs));
return 0; return 0;
} }
@@ -302,29 +336,42 @@ int lua_set_rds_eon(lua_State *localL) {
memset(&new_af, 0, sizeof(RDSAFs)); memset(&new_af, 0, sizeof(RDSAFs));
for (int i = 1; i <= n; i++) { for (int i = 1; i <= n; i++) {
lua_rawgeti(localL, 8, i); lua_rawgeti(localL, -1, i);
if (lua_isnumber(localL, -1)) add_rds_af(&new_af, lua_tonumber(localL, -1)); if (!lua_isnumber(localL, -1)) {
else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1)); const char *type = luaL_typename(localL, -1);
lua_pop(localL, 1);
return luaL_error(localL, "number expected, got %s", type);
}
add_rds_af(&new_af, lua_tonumber(localL, -1));
lua_pop(localL, 1); lua_pop(localL, 1);
} }
memcpy(&(enc->data[writing_program].eon[eon].af), &new_af, sizeof(new_af)); memcpy(&(enc->data[writing_program].eon[eon].af), &new_af, sizeof(new_af));
lua_pop(localL, 1);
enc->data[writing_program].eon[eon].data = luaL_checkinteger(localL, 9);
return 0; return 0;
} }
int lua_get_rds_eon(lua_State *localL) { int lua_get_rds_eon(lua_State *localL) {
int eon = luaL_checkinteger(localL, 1); int eon = luaL_checkinteger(localL, 1);
if(eon >= EONs) return luaL_error(localL, "eon index exceeded"); if(eon >= EONs) return luaL_error(localL, "eon index exceeded");
lua_newtable(localL);
lua_pushboolean(localL, enc->data[writing_program].eon[eon].enabled); lua_pushboolean(localL, enc->data[writing_program].eon[eon].enabled);
lua_setfield(L, -2, "enabled");
lua_pushinteger(localL, enc->data[writing_program].eon[eon].pi); lua_pushinteger(localL, enc->data[writing_program].eon[eon].pi);
lua_setfield(L, -2, "pi");
lua_pushboolean(localL, enc->data[writing_program].eon[eon].tp); lua_pushboolean(localL, enc->data[writing_program].eon[eon].tp);
lua_setfield(L, -2, "tp");
lua_pushboolean(localL, enc->data[writing_program].eon[eon].ta); lua_pushboolean(localL, enc->data[writing_program].eon[eon].ta);
lua_setfield(L, -2, "ta");
lua_pushinteger(localL, enc->data[writing_program].eon[eon].pty); lua_pushinteger(localL, enc->data[writing_program].eon[eon].pty);
lua_setfield(L, -2, "pty");
lua_pushlstring(localL, enc->data[writing_program].eon[eon].ps, 8); lua_pushlstring(localL, enc->data[writing_program].eon[eon].ps, 8);
lua_createtable(localL, 0, 0); // don't have decoding for AF, so just return empty table lua_setfield(L, -2, "ps");
lua_newtable(localL); // don't have decoding for AF, so just return empty table
lua_setfield(L, -2, "afs");
lua_pushinteger(localL, enc->data[writing_program].eon[eon].data); lua_pushinteger(localL, enc->data[writing_program].eon[eon].data);
return 8; lua_setfield(L, -2, "data");
return 1;
} }
int lua_set_rds_udg(lua_State *localL) { int lua_set_rds_udg(lua_State *localL) {
+4 -78
View File
@@ -5,7 +5,6 @@
RDSEncoder* enc = NULL; RDSEncoder* enc = NULL;
lua_State *L = NULL; lua_State *L = NULL;
static pthread_mutex_t lua_mutex; static pthread_mutex_t lua_mutex;
uint8_t unload_refs[33] = {LUA_REFNIL};
#define lua_registertotable(L,n,f) (lua_pushcfunction(L, (f)), lua_setfield(L, -2, (n))) #define lua_registertotable(L,n,f) (lua_pushcfunction(L, (f)), lua_setfield(L, -2, (n)))
void init_lua(RDSEncoder* _enc) { void init_lua(RDSEncoder* _enc) {
@@ -54,8 +53,8 @@ void init_lua(RDSEncoder* _enc) {
lua_registertotable(L, "set_program_defaults", lua_set_rds_program_defaults); lua_registertotable(L, "set_program_defaults", lua_set_rds_program_defaults);
lua_pushinteger(L, PROGRAMS); lua_pushinteger(L, PROGRAMS);
lua_setfield(L, -2, "max_programs"); lua_setfield(L, -2, "max_programs");
lua_registertotable(L, "set_program", lua_set_rds_program); lua_registertotable(L, "set_output_program", lua_set_rds_program);
lua_registertotable(L, "get_program", lua_get_rds_program); lua_registertotable(L, "get_output_program", lua_get_rds_program);
lua_registertotable(L, "set_writing_program", lua_set_rds_writing_program); lua_registertotable(L, "set_writing_program", lua_set_rds_writing_program);
lua_registertotable(L, "get_writing_program", lua_get_rds_writing_program); lua_registertotable(L, "get_writing_program", lua_get_rds_writing_program);
lua_setglobal(L, "dp"); lua_setglobal(L, "dp");
@@ -148,7 +147,6 @@ void init_lua(RDSEncoder* _enc) {
lua_setglobal(L, "rds"); lua_setglobal(L, "rds");
if (luaL_loadfile(L, "/etc/rds95.lua") != LUA_OK) { if (luaL_loadfile(L, "/etc/rds95.lua") != LUA_OK) {
fprintf(stderr, "Lua error loading file: %s\n", lua_tostring(L, -1)); fprintf(stderr, "Lua error loading file: %s\n", lua_tostring(L, -1));
lua_pop(L, 1); lua_pop(L, 1);
@@ -274,39 +272,6 @@ int lua_rds2_group(RDSGroup* group, int stream) {
return 1; return 1;
} }
void lua_group_ref(RDSGroup* group, int ref) {
pthread_mutex_lock(&lua_mutex);
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
if (lua_isfunction(L, -1)) {
if (lua_pcall(L, 0, 3, 0) == LUA_OK) {
if (!lua_isinteger(L, -1)) {
pthread_mutex_unlock(&lua_mutex);
lua_pop(L, 1);
return;
}
if (!lua_isinteger(L, -2)) {
pthread_mutex_unlock(&lua_mutex);
lua_pop(L, 1);
return;
}
if (!lua_isinteger(L, -3)) {
pthread_mutex_unlock(&lua_mutex);
lua_pop(L, 1);
return;
}
group->d = luaL_checkinteger(L, -1);
group->c = luaL_checkinteger(L, -2);
group->b = luaL_checkinteger(L, -3);
lua_pop(L, 3);
} else {
fprintf(stderr, "Lua error: %s at ref %d\n", lua_tostring(L, -1), ref);
lua_pop(L, 1);
}
} else lua_pop(L, 1);
pthread_mutex_unlock(&lua_mutex);
}
void lua_call_function_nolock(const char* function) { void lua_call_function_nolock(const char* function) {
lua_getglobal(L, function); lua_getglobal(L, function);
@@ -327,40 +292,6 @@ void lua_call_function(const char* function) {
pthread_mutex_unlock(&lua_mutex); pthread_mutex_unlock(&lua_mutex);
} }
void lua_call_table_nolock(const char *table_name) {
lua_getglobal(L, table_name);
if (!lua_istable(L, -1)) {
lua_pop(L, 1);
return;
}
lua_Integer len = lua_rawlen(L, -1);
for (lua_Integer i = 1; i <= len; i++) {
lua_rawgeti(L, -1, i);
if (lua_isfunction(L, -1)) {
if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
fprintf(stderr,
"Lua error: %s at '%s[%lld]'\n",
lua_tostring(L, -1),
table_name,
(long long)i);
lua_pop(L, 1);
}
} else lua_pop(L, 1);
}
lua_pop(L, 1); // pop table
}
void lua_call_table(const char* function) {
int need_lock = (pthread_mutex_trylock(&lua_mutex) == 0);
if (!need_lock) {
fprintf(stderr, "Warning: lua_mutex already locked when table calling %s\n", function);
return;
}
lua_call_table_nolock(function);
pthread_mutex_unlock(&lua_mutex);
}
void lua_call_tfunction_nolock(const char* name) { void lua_call_tfunction_nolock(const char* name) {
lua_getglobal(L, "hooks"); lua_getglobal(L, "hooks");
if (!lua_istable(L, -1)) { if (!lua_istable(L, -1)) {
@@ -380,11 +311,8 @@ void lua_call_tfunction_nolock(const char* name) {
lua_rawgeti(L, -1, i); lua_rawgeti(L, -1, i);
if (lua_isfunction(L, -1)) { if (lua_isfunction(L, -1)) {
if (lua_pcall(L, 0, 0, 0) != LUA_OK) { if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
fprintf(stderr, fprintf(stderr, "Lua error: %s at '%s[%lld]'\n",
"Lua error: %s at '%s[%lld]'\n", lua_tostring(L, -1), name, (long long)i);
lua_tostring(L, -1),
name,
(long long)i);
lua_pop(L, 1); lua_pop(L, 1);
} }
} else lua_pop(L, 1); } else lua_pop(L, 1);
@@ -404,8 +332,6 @@ void lua_call_tfunction(const char* name) {
void destroy_lua() { void destroy_lua() {
if (L) { if (L) {
for (int i = 1; i < *unload_refs; i++) luaL_unref(L, LUA_REGISTRYINDEX, unload_refs[i]);
*unload_refs = 1;
lua_close(L); lua_close(L);
L = NULL; L = NULL;
} }
-3
View File
@@ -11,9 +11,6 @@ int lua_group(RDSGroup* group, const char grp);
int lua_rds2_group(RDSGroup* group, int stream); int lua_rds2_group(RDSGroup* group, int stream);
void lua_call_function_nolock(const char* function); void lua_call_function_nolock(const char* function);
void lua_call_function(const char* function); void lua_call_function(const char* function);
void lua_call_table_nolock(const char *table_name);
void lua_call_table(const char* function);
void lua_call_tfunction_nolock(const char* name); void lua_call_tfunction_nolock(const char* name);
void lua_call_tfunction(const char* name); void lua_call_tfunction(const char* name);
void lua_group_ref(RDSGroup* group, int ref);
void destroy_lua(); void destroy_lua();
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "common.h" #include "common.h"
#define LUA_USER_DATA 1152 #define LUA_USER_DATA 1280
/* The RDS error-detection code generator polynomial is /* The RDS error-detection code generator polynomial is
* x^10 + x^8 + x^7 + x^5 + x^4 + x^3 + x^0 * x^10 + x^8 + x^7 + x^5 + x^4 + x^3 + x^0