move some scripts as modules and also change rds1 group hook

This commit is contained in:
2026-06-20 14:42:10 +02:00
parent a189c56cdf
commit 90d082a845
9 changed files with 107 additions and 102 deletions
+3 -1
View File
@@ -4,10 +4,12 @@
"os": "disable", "os": "disable",
"jit": "disable", "jit": "disable",
"ffi":"disable", "ffi":"disable",
"package": "disable"
}, },
"workspace.library": ["context.lua"], "workspace.library": ["context.lua"],
"diagnostics.disable": [ "diagnostics.disable": [
"duplicate-set-field" "duplicate-set-field"
],
"runtime.path": [
"modules/?.lua"
] ]
} }
+12 -33
View File
@@ -93,16 +93,21 @@ hooks.ps_transmission = {}
---@return string ---@return string
function hooks.data_handle(data) end function hooks.data_handle(data) end
---This function is called an unknown group is seen in the group sequence. See set_grpseq ---@alias group_handler fun(group: string): boolean, integer, integer, integer
---This will be also called on recognized groups - if they can't be properly encoded by the core
---Please remember that the core always fills in PTY and TP and PI in C if this is an B group ---Called when an unknown group is seen in the group sequence. See set_grpseq.
---It should be defined by the user in the script. ---This is also called on recognized groups if they can't be properly encoded by the core.
---@param group string group this was called in from the group sequence ---The core always fills in PTY, TP, and PI in C if this is a B group.
---Should be defined by the user in the script.
---@param group string
---@return boolean generated ---@return boolean generated
---@return integer b ---@return integer b
---@return integer c ---@return integer c
---@return integer d ---@return integer d
function hooks.group(group) end local function group_handler(group) end
---@type group_handler[]
hooks.group = {}
---This function is called when an RDS2 group. Full control of every RDS2 subcarrier is under this function ---This function is called when an RDS2 group. Full control of every RDS2 subcarrier is under this function
---If a was returned 0, PTY and TP will be filled in, along with the PI code in C if needed ---If a was returned 0, PTY and TP will be filled in, along with the PI code in C if needed
@@ -339,33 +344,7 @@ function ext.set_oda_id_data(oda_id, data) end
---@param fun ODAHandler ---@param fun ODAHandler
function ext.set_oda_handler(oda_id, fun) end function ext.set_oda_handler(oda_id, fun) end
---The callback function for an ODA handler
---@alias RDS2_ODAHandler fun(integer): (boolean, integer, integer, integer, integer)
---You are asked to not fill in the channel id in block A, however you are asked to fill in the function number (if you do not know what is that, just OR block A with (1 << 14))
---@param oda_id integer
---@param func RDS2_ODAHandler
function ext.set_oda_handler_rds2(oda_id, func) end
---@param oda_id integer
---@param data integer
function ext.set_oda_id_data_rds2(oda_id, data) end
---@param aid integer
---@param data integer
---@param file_related boolean
---@return integer oda_id
function ext.register_oda_rds2(aid, data, file_related) end
---Unregisters an RDS 2 ODA, this stops the handler or AID being called/sent
---@param oda_id integer
function ext.unregister_oda_rds2(oda_id) end
---@param ert string ---@param ert string
function RDS.ext.set_ert(ert) end function RDS.ext.set_ert(ert) end
---@return string ---@return string
function RDS.ext.get_ert() end function RDS.ext.get_ert() end
---@param designator string
---@param handler function
function RDS.ext.register_group(designator, handler) end
+25
View File
@@ -0,0 +1,25 @@
local md = {}
md.registered_groups = {}
hooks.group[#hooks.group+1] = function (group)
if md.registered_groups[group] then
local ok, generated, b, c, d = pcall(md.registered_groups[group], group)
if ok then return generated, b, c, d
else
print(generated)
return false, 0, 0, 0
end
end
return false, 0, 0, 0
end
---@param designator string
---@param handler function
function md.register_group(designator, handler)
for i = 1, #designator do
local char = designator:sub(i, i)
md.registered_groups[char] = handler
end
end
return md
+21 -12
View File
@@ -1,5 +1,7 @@
_RDS2_ODA = { aid = 0, data = 0, handler = false, file_related = false, channel = 0 } local rds2_oda = {}
_RDS2_next_channel = { normal = 16, file = 0 }
local _RDS2_ODA = { aid = 0, data = 0, handler = false, file_related = false, channel = 0 }
local _RDS2_next_channel = { normal = 16, file = 0 }
function _RDS2_ODA.new(aid, data, handler, file_related, channel) function _RDS2_ODA.new(aid, data, handler, file_related, channel)
local instance = { aid = aid or 0, data = data or 0, handler = handler or false, file_related = file_related or false, channel = channel or 0 } local instance = { aid = aid or 0, data = data or 0, handler = handler or false, file_related = file_related or false, channel = channel or 0 }
@@ -7,15 +9,15 @@ function _RDS2_ODA.new(aid, data, handler, file_related, channel)
return instance return instance
end end
_RDS2_ODAs = {} local _RDS2_ODAs = {}
_RDS2_ODA_aid = 0 local _RDS2_ODA_aid = 0
_RDS2_ODA_pointer = 1 local _RDS2_ODA_pointer = 1
---@param aid integer ---@param aid integer
---@param data integer ---@param data integer
---@param file_related boolean ---@param file_related boolean
---@return integer oda_id ---@return integer oda_id
function ext.register_oda_rds2(aid, data, file_related) function rds2_oda.register_oda_rds2(aid, data, file_related)
local channel local channel
if file_related then if file_related then
channel = _RDS2_next_channel.file channel = _RDS2_next_channel.file
@@ -38,7 +40,7 @@ end
---Unregisters an RDS 2 ODA, this stops the handler or AID being called/sent ---Unregisters an RDS 2 ODA, this stops the handler or AID being called/sent
---@param oda_id integer ---@param oda_id integer
function ext.unregister_oda_rds2(oda_id) function rds2_oda.unregister_oda_rds2(oda_id)
if oda_id < 1 or oda_id > #_RDS2_ODAs or _RDS2_ODAs[oda_id] == false then error("Invalid ODA ID: " .. tostring(oda_id), 2) end if oda_id < 1 or oda_id > #_RDS2_ODAs or _RDS2_ODAs[oda_id] == false then error("Invalid ODA ID: " .. tostring(oda_id), 2) end
_RDS2_ODAs[oda_id] = false _RDS2_ODAs[oda_id] = false
@@ -49,19 +51,23 @@ end
---@param oda_id integer ---@param oda_id integer
---@param data integer ---@param data integer
function ext.set_oda_id_data_rds2(oda_id, data) function rds2_oda.set_oda_id_data_rds2(oda_id, data)
if oda_id < 1 or oda_id > #_RDS2_ODAs or _RDS2_ODAs[oda_id] == false then error("Invalid ODA ID: " .. tostring(oda_id), 2) end if oda_id < 1 or oda_id > #_RDS2_ODAs or _RDS2_ODAs[oda_id] == false then error("Invalid ODA ID: " .. tostring(oda_id), 2) end
_RDS2_ODAs[oda_id].data = data _RDS2_ODAs[oda_id].data = data
end end
---The callback function for an ODA handler
---@alias RDS2_ODAHandler fun(integer): (boolean, integer, integer, integer, integer)
---You are asked to not fill in the channel id in block A, however you are asked to fill in the function number (if you do not know what is that, just OR block A with (1 << 14))
---@param oda_id integer ---@param oda_id integer
---@param func RDS2_ODAHandler ---@param func RDS2_ODAHandler
function ext.set_oda_handler_rds2(oda_id, func) function rds2_oda.set_oda_handler_rds2(oda_id, func)
if oda_id < 1 or oda_id > #_RDS2_ODAs or _RDS2_ODAs[oda_id] == false then error("Invalid ODA ID: " .. tostring(oda_id), 2) end if oda_id < 1 or oda_id > #_RDS2_ODAs or _RDS2_ODAs[oda_id] == false then error("Invalid ODA ID: " .. tostring(oda_id), 2) end
_RDS2_ODAs[oda_id].handler = func _RDS2_ODAs[oda_id].handler = func
end end
function hooks.rds2_group(stream) function rds2_oda.rds2_group(stream)
if #_RDS2_ODAs == 0 then return false, 0, 0, 0, 0 end if #_RDS2_ODAs == 0 then return false, 0, 0, 0, 0 end
if _RDS2_ODA_pointer > #_RDS2_ODAs then _RDS2_ODA_pointer = 1 end if _RDS2_ODA_pointer > #_RDS2_ODAs then _RDS2_ODA_pointer = 1 end
@@ -106,9 +112,10 @@ function hooks.rds2_group(stream)
_RDS2_ODA_aid = _RDS2_ODA_aid + 1 _RDS2_ODA_aid = _RDS2_ODA_aid + 1
if _RDS2_ODA_aid > 8 then _RDS2_ODA_aid = 0 end if _RDS2_ODA_aid > 8 then _RDS2_ODA_aid = 0 end
if oda.handler then if oda.handler then
generated = false local generated = false
checked = 0 checked = 0
while generated == false and checked < #_RDS2_ODAs do while generated == false and checked < #_RDS2_ODAs do
local ok, a, b, c, d
ok, generated, a, b, c, d = pcall(oda.handler, stream) ok, generated, a, b, c, d = pcall(oda.handler, stream)
if not (generated and ok) then if not (generated and ok) then
_RDS2_ODA_pointer = _RDS2_ODA_pointer + 1 _RDS2_ODA_pointer = _RDS2_ODA_pointer + 1
@@ -138,4 +145,6 @@ table.insert(hooks.on_state, function ()
_RDS2_ODAs = {} _RDS2_ODAs = {}
_RDS2_ODA_aid = 0 _RDS2_ODA_aid = 0
_RDS2_ODA_pointer = 1 _RDS2_ODA_pointer = 1
end) end)
return rds2_oda
+9 -5
View File
@@ -1,3 +1,5 @@
local scheduler = require("rds2_oda")
---@class RftInstance ---@class RftInstance
---@field oda_id integer|nil The internal ODA registration ID ---@field oda_id integer|nil The internal ODA registration ID
---@field file_data string The raw binary content of the file ---@field file_data string The raw binary content of the file
@@ -43,7 +45,7 @@ end
function RftInstance:stop() function RftInstance:stop()
if self.oda_id ~= nil and self.aid ~= 0 then if self.oda_id ~= nil and self.aid ~= 0 then
ext.unregister_oda_rds2(self.oda_id) scheduler.unregister_oda_rds2(self.oda_id)
self.oda_id = nil self.oda_id = nil
end end
@@ -59,9 +61,9 @@ end
---@private ---@private
function RftInstance:start() function RftInstance:start()
if self.oda_id == nil and self.aid ~= 0 then if self.oda_id == nil and self.aid ~= 0 then
self.oda_id = ext.register_oda_rds2(self.aid, 0, true) self.oda_id = scheduler.register_oda_rds2(self.aid, 0, true)
ext.set_oda_handler_rds2(self.oda_id, function(stream) scheduler.set_oda_handler_rds2(self.oda_id, function(stream)
if #self.file_data == 0 or self.paused then if #self.file_data == 0 or self.paused then
return false, 0, 0, 0, 0 return false, 0, 0, 0, 0
end end
@@ -161,8 +163,10 @@ function RftInstance:sendFile(aid, path, id, crc, once)
if f_size > (0x3ffff * 5) then error("File too large") end if f_size > (0x3ffff * 5) then error("File too large") end
if self.oda_id == nil then self:start() end if self.oda_id == nil then self:start() end
ext.set_oda_id_data_rds2(self.oda_id, f_size | (id & 63) << 18 | (self.version & 7) << 24 | (self.crc_enabled and 1 or 0) << 27) scheduler.set_oda_id_data_rds2(self.oda_id, f_size | (id & 63) << 18 | (self.version & 7) << 24 | (self.crc_enabled and 1 or 0) << 27)
self.last_id = id self.last_id = id
self.paused = false self.paused = false
return interrupted return interrupted
end end
return RftInstance
-22
View File
@@ -1,22 +0,0 @@
hooks.registered_groups = {}
function hooks.group(group)
if hooks.registered_groups[group] then
local ok, generated, b, c, d = pcall(hooks.registered_groups[group], group)
if ok then return generated, b, c, d
else
print(generated)
return false, 0, 0, 0
end
end
return false, 0, 0, 0
end
---@param designator string
---@param handler function
function RDS.ext.register_group(designator, handler)
for i = 1, #designator do
local char = designator:sub(i, i)
hooks.registered_groups[char] = handler
end
end
+1 -1
View File
@@ -119,7 +119,7 @@ local function group_handler(group_type)
elseif group_type == "\xff" then return get_data() elseif group_type == "\xff" then return get_data()
else return false, 0, 0, 0 end else return false, 0, 0, 0 end
end end
RDS.ext.register_group("\x06\xff", group_handler) require("group").register_group("\x06\xff", group_handler)
table.insert(hooks.on_state, function () table.insert(hooks.on_state, function ()
_RDS_ODAs = {} _RDS_ODAs = {}
+36 -27
View File
@@ -204,35 +204,47 @@ void run_lua(char *str, size_t str_len, char *cmd_output, size_t *out_len) {
} }
int lua_group(RDSGroup* group, const char grp) { int lua_group(RDSGroup* group, const char grp) {
int success = 0;
pthread_mutex_lock(&lua_mutex); pthread_mutex_lock(&lua_mutex);
lua_rawgeti(globalL, LUA_REGISTRYINDEX, hooks_ref); lua_rawgeti(globalL, LUA_REGISTRYINDEX, hooks_ref);
lua_getfield(globalL, -1, "group"); lua_getfield(globalL, -1, "group");
if (!lua_isfunction(globalL, -1)) { if (!lua_istable(globalL, -1)) {
lua_pop(globalL, 2); lua_pop(globalL, 2);
pthread_mutex_unlock(&lua_mutex); pthread_mutex_unlock(&lua_mutex);
return 0; return 0;
} }
lua_pushlstring(globalL, &grp, 1); lua_Integer len = lua_rawlen(globalL, -1);
for (lua_Integer i = 1; i <= len; i++) {
lua_rawgeti(globalL, -1, i);
if (lua_pcall(globalL, 1, 4, 0) != LUA_OK) { if (!lua_isfunction(globalL, -1)) {
fprintf(stderr, "Lua error: %s\n", lua_tostring(globalL, -1)); lua_pop(globalL, 1);
lua_pop(globalL, 2); continue;
pthread_mutex_unlock(&lua_mutex); }
return 0;
lua_pushlstring(globalL, &grp, 1);
if (lua_pcall(globalL, 1, 4, 0) != LUA_OK) {
fprintf(stderr, "Lua error: %s at 'group[%lld]'\n",
lua_tostring(globalL, -1), (long long)i);
lua_pop(globalL, 1);
continue;
}
if (lua_isboolean(globalL, -4) && lua_toboolean(globalL, -4) &&
lua_isinteger(globalL, -3) && lua_isinteger(globalL, -2) && lua_isinteger(globalL, -1)) {
group->b = (uint16_t)lua_tointeger(globalL, -3);
group->c = (uint16_t)lua_tointeger(globalL, -2);
group->d = (uint16_t)lua_tointeger(globalL, -1);
success = 1;
}
lua_pop(globalL, 4);
if (success) break;
} }
lua_pop(globalL, 2);
int success = 0;
if (lua_isboolean(globalL, -4) && lua_toboolean(globalL, -4) &&
lua_isinteger(globalL, -3) && lua_isinteger(globalL, -2) && lua_isinteger(globalL, -1)) {
group->b = (uint16_t)lua_tointeger(globalL, -3);
group->c = (uint16_t)lua_tointeger(globalL, -2);
group->d = (uint16_t)lua_tointeger(globalL, -1);
success = 1;
}
lua_pop(globalL, 5);
pthread_mutex_unlock(&lua_mutex); pthread_mutex_unlock(&lua_mutex);
return success; return success;
} }
@@ -292,7 +304,12 @@ int lua_rds2_group(RDSGroup* group, int stream) {
return 1; return 1;
} }
void lua_call_function_nolock(const char* function) { oid lua_call_function(const char* function) {
int need_lock = (pthread_mutex_trylock(&lua_mutex) == 0);
if (!need_lock) {
fprintf(stderr, "Warning: lua_mutex already locked when calling %s\n", function);
return;
}
lua_getglobal(globalL, function); lua_getglobal(globalL, function);
if (lua_isfunction(globalL, -1)) { if (lua_isfunction(globalL, -1)) {
@@ -301,14 +318,6 @@ void lua_call_function_nolock(const char* function) {
lua_pop(globalL, 1); lua_pop(globalL, 1);
} }
} else lua_pop(globalL, 1); } else lua_pop(globalL, 1);
}
void lua_call_function(const char* function) {
int need_lock = (pthread_mutex_trylock(&lua_mutex) == 0);
if (!need_lock) {
fprintf(stderr, "Warning: lua_mutex already locked when calling %s\n", function);
return;
}
lua_call_function_nolock(function);
pthread_mutex_unlock(&lua_mutex); pthread_mutex_unlock(&lua_mutex);
} }
-1
View File
@@ -9,7 +9,6 @@ uint8_t init_lua(RDSEncoder* _enc);
void run_lua(char *str, size_t str_len, char *cmd_output, size_t* out_len); void run_lua(char *str, size_t str_len, char *cmd_output, size_t* out_len);
int lua_group(RDSGroup* group, const char grp); 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(const char* function); void lua_call_function(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);