uecp testing

This commit is contained in:
2026-04-22 17:14:50 +02:00
parent 35bbb2aa99
commit c62b7fde36
11 changed files with 322 additions and 158 deletions
+7
View File
@@ -28,11 +28,18 @@ function dp.reset_rds() end
---@return nil ---@return nil
function dp.force_save() end function dp.force_save() end
---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_program(program_idx) end
---@return integer ---@return integer
function dp.get_program() end function dp.get_program() end
---Sets the program all of the set/get functions affect
---@param program_idx integer 0 to (max_programs - 1)
function dp.set_writing_program(program_idx) end
---@return integer
function dp.get_writing_program() end
---This function is called by the C core after we reset data, or have no data in general ---This function is called by the C core after we reset data, or have no data in general
---It should be defined by the user in the script. ---It should be defined by the user in the script.
---@return nil ---@return nil
+110 -5
View File
@@ -1,4 +1,113 @@
local mec_handlers = {}
local function dsn_helper(dsn, write)
if dsn == 0 then write()
elseif dsn == 254 then
local start = dp.get_writing_program()
for i = 1, dp.max_programs do
local p = i - 1
if p ~= start then
dp.set_writing_program(p)
write()
end
end
elseif dsn == 255 then
for i = 1, dp.max_programs do
dp.set_writing_program(i - 1)
write()
end
else
dp.set_writing_program(dsn - 1)
write()
end
end
mec_handlers[1] = function (data)
-- PI
local dsn = string.byte(data, 2)
local psn = string.byte(data, 3)
local pi_msb = string.byte(data, 4)
local pi_lsb = string.byte(data, 5)
dsn_helper(dsn, function ()
rds.set_pi((pi_msb << 8) | pi_lsb)
end)
end
mec_handlers[2] = function (data)
-- PS
local dsn = string.byte(data, 2)
local psn = string.byte(data, 3)
local ps = string.sub(data, 4, 11)
dsn_helper(dsn, function ()
rds.set_ps(ps)
end)
end
mec_handlers[3] = function (data)
-- TP/TA
local dsn = string.byte(data, 2)
local psn = string.byte(data, 3)
local data = string.byte(data, 4)
dsn_helper(dsn, function ()
rds.set_ta((data & 1) ~= 0)
rds.set_ta((data & 2) ~= 0)
end)
end
---@param data string
local function undo_byte_stuff(data)
local output = {}
local i = 1
while i <= #data do
local d0 = string.byte(data, i)
if d0 == 0xFD then
local d1 = string.byte(data, i + 1)
output[#output + 1] = string.char(0xFD + d1)
i = i + 2
else
output[#output + 1] = string.char(d0)
i = i + 1
end
end
return table.concat(output)
end
---@param packet string
local function parse_uecp(packet)
local end_i = string.find(packet, "\xff", 1, true)
if not end_i then return end
local unstuffed = undo_byte_stuff(string.sub(packet, 2, end_i - 1))
local addr1 = string.byte(unstuffed, 1)
local addr2 = string.byte(unstuffed, 2)
local site_addr = (addr1 << 2) | (addr2 >> 6)
local encoder_addr = addr2 & 0x3F
local sequence_count = string.byte(unstuffed, 3)
local mfl = string.byte(unstuffed, 4)
local data = string.sub(unstuffed, 5, 4 + mfl)
if mfl ~= #data then return end
local crc_calculated = dp.crc16(string.sub(unstuffed, 1, 4 + mfl))
local crc_hi = string.byte(unstuffed, 4 + mfl + 1)
local crc_lo = string.byte(unstuffed, 4 + mfl + 2)
local crc_stored = (crc_hi << 8) | crc_lo
if crc_calculated ~= crc_stored then return end
local mec = string.byte(data, 1)
local handler = mec_handlers[mec]
if handler then
handler(data)
dp.set_writing_program(dp.get_program())
end
end
function data_handle(data) function data_handle(data)
-- UECP
if string.byte(data, 1) == 0xfe then return parse_uecp(data) end
if string.sub(data, 1, 4):lower() == "lua=" then if string.sub(data, 1, 4):lower() == "lua=" then
local chunk, err = load("return " .. string.sub(data, 5), "udp_chunk") -- skip "lua=" local chunk, err = load("return " .. string.sub(data, 5), "udp_chunk") -- skip "lua="
if not chunk then return string.format("-\r\n%s\r\n", err) end if not chunk then return string.format("-\r\n%s\r\n", err) end
@@ -212,11 +321,6 @@ function data_handle(data)
if not pty then return "-\r\n" end if not pty then return "-\r\n" end
rds.set_pty(pty) rds.set_pty(pty)
return "+\r\n" return "+\r\n"
elseif cmd == "slcd" then
local slc_data = tonumber(value, 16)
if not slc_data then return "-\r\n" end
rds.set_slc_data(slc_data)
return "+\r\n"
elseif cmd == "ct" then elseif cmd == "ct" then
local ct = tonumber(value) local ct = tonumber(value)
if not ct then return "-\r\n" end if not ct then return "-\r\n" end
@@ -303,6 +407,7 @@ function data_handle(data)
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_program(program-1)
dp.set_writing_program(program-1)
rds.set_ta(false) rds.set_ta(false)
return "+\r\n" return "+\r\n"
elseif cmd == "dttmout" then elseif cmd == "dttmout" then
+73 -57
View File
@@ -6,24 +6,25 @@ 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]; extern uint8_t unload_refs[33];
static int writing_program = 0;
int lua_get_userdata(lua_State *localL) { int lua_get_userdata(lua_State *localL) {
lua_pushlstring(localL, (const char*)&enc->data[enc->program].lua_data, LUA_USER_DATA); lua_pushlstring(localL, (const char*)&enc->data[writing_program].lua_data, LUA_USER_DATA);
return 1; return 1;
} }
int lua_get_userdata_offset(lua_State *localL) { int lua_get_userdata_offset(lua_State *localL) {
uint16_t offset = luaL_checkinteger(localL, 1); uint16_t offset = luaL_checkinteger(localL, 1);
uint16_t size = luaL_checkinteger(localL, 2); uint16_t size = luaL_checkinteger(localL, 2);
if((offset+size) > LUA_USER_DATA) return luaL_error(localL, "data exceeds limit"); if((offset+size) > LUA_USER_DATA) return luaL_error(localL, "data exceeds limit");
lua_pushlstring(localL, (const char*)&enc->data[enc->program].lua_data[offset], size); lua_pushlstring(localL, (const char*)&enc->data[writing_program].lua_data[offset], size);
return 1; return 1;
} }
int lua_set_userdata(lua_State *localL) { int lua_set_userdata(lua_State *localL) {
size_t len; size_t len;
const char *data = luaL_checklstring(localL, 1, &len); const char *data = luaL_checklstring(localL, 1, &len);
if(len > LUA_USER_DATA) return luaL_error(localL, "data exceeds limit"); if(len > LUA_USER_DATA) return luaL_error(localL, "data exceeds limit");
memset(enc->data[enc->program].lua_data, 0, LUA_USER_DATA); memset(enc->data[writing_program].lua_data, 0, LUA_USER_DATA);
memcpy(enc->data[enc->program].lua_data, data, len); memcpy(enc->data[writing_program].lua_data, data, len);
return 0; return 0;
} }
@@ -34,8 +35,8 @@ int lua_set_userdata_offset(lua_State *localL) {
size_t len; size_t len;
const char *data = luaL_checklstring(localL, 3, &len); const char *data = luaL_checklstring(localL, 3, &len);
if(len > size || (offset + size) > LUA_USER_DATA) return luaL_error(localL, "data exceeds limit"); if(len > size || (offset + size) > LUA_USER_DATA) return luaL_error(localL, "data exceeds limit");
memset(enc->data[enc->program].lua_data + offset, 0, size); memset(enc->data[writing_program].lua_data + offset, 0, size);
memcpy(enc->data[enc->program].lua_data + offset, data, len); memcpy(enc->data[writing_program].lua_data + offset, data, len);
return 0; return 0;
} }
@@ -55,7 +56,7 @@ int lua_set_rds_program_defaults(lua_State *localL) {
in_set_defaults = 1; in_set_defaults = 1;
for (int i = 1; i < *unload_refs; i++) luaL_unref(L, LUA_REGISTRYINDEX, unload_refs[i]); for (int i = 1; i < *unload_refs; i++) luaL_unref(L, LUA_REGISTRYINDEX, unload_refs[i]);
unload_refs[0] = 1; unload_refs[0] = 1;
set_rds_defaults(enc, enc->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");
in_set_defaults = 0; in_set_defaults = 0;
@@ -77,24 +78,24 @@ int lua_reset_rds(lua_State *localL) {
#define BOOL_SETTER(name) \ #define BOOL_SETTER(name) \
int lua_set_rds_##name(lua_State *localL) { \ int lua_set_rds_##name(lua_State *localL) { \
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1)); \ if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1)); \
enc->data[enc->program].name = lua_toboolean(localL, 1); \ enc->data[writing_program].name = lua_toboolean(localL, 1); \
return 0; \ return 0; \
} }
#define INT_SETTER(name) \ #define INT_SETTER(name) \
int lua_set_rds_##name(lua_State *localL) { \ int lua_set_rds_##name(lua_State *localL) { \
enc->data[enc->program].name = luaL_checkinteger(localL, 1); \ enc->data[writing_program].name = luaL_checkinteger(localL, 1); \
return 0; \ return 0; \
} }
#define STR_SETTER(name, function) \ #define STR_SETTER(name, function) \
int lua_set_rds_##name(lua_State *localL) { \ int lua_set_rds_##name(lua_State *localL) { \
const char* str = luaL_checklstring(localL, 1, NULL); \ const char* str = luaL_checklstring(localL, 1, NULL); \
function(enc, convert_to_rdscharset(str)); \ function(enc, convert_to_rdscharset(str), writing_program); \
return 0; \ return 0; \
} }
#define STR_RAW_SETTER(name, function) \ #define STR_RAW_SETTER(name, function) \
int lua_set_rds_##name(lua_State *localL) { \ int lua_set_rds_##name(lua_State *localL) { \
const char* str = luaL_checklstring(localL, 1, NULL); \ const char* str = luaL_checklstring(localL, 1, NULL); \
function(enc, str); \ function(enc, str, writing_program); \
return 0; \ return 0; \
} }
#define AF_SETTER(name, af_field, af_struct, add_func) \ #define AF_SETTER(name, af_field, af_struct, add_func) \
@@ -103,7 +104,7 @@ int lua_set_rds_##name(lua_State *localL) { \
\ \
int n = lua_rawlen(localL, 1); \ int n = lua_rawlen(localL, 1); \
if (n == 0) { \ if (n == 0) { \
memset(&(enc->data[enc->program].af_field), 0, sizeof(af_struct)); \ memset(&(enc->data[writing_program].af_field), 0, sizeof(af_struct)); \
return 0; \ return 0; \
} \ } \
if(n > 25) return luaL_error(localL, "table length over 25"); \ if(n > 25) return luaL_error(localL, "table length over 25"); \
@@ -117,24 +118,24 @@ int lua_set_rds_##name(lua_State *localL) { \
else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1)); \ else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1)); \
lua_pop(localL, 1); \ lua_pop(localL, 1); \
} \ } \
memcpy(&(enc->data[enc->program].af_field), &new_af, sizeof(new_af)); \ memcpy(&(enc->data[writing_program].af_field), &new_af, sizeof(new_af)); \
\ \
return 0; \ return 0; \
} }
#define INT_GETTER(name) \ #define INT_GETTER(name) \
int lua_get_rds_##name(lua_State *localL) { \ int lua_get_rds_##name(lua_State *localL) { \
lua_pushinteger(localL, enc->data[enc->program].name); \ lua_pushinteger(localL, enc->data[writing_program].name); \
return 1; \ return 1; \
} }
#define BOOL_GETTER(name) \ #define BOOL_GETTER(name) \
int lua_get_rds_##name(lua_State *localL) { \ int lua_get_rds_##name(lua_State *localL) { \
lua_pushboolean(localL, enc->data[enc->program].name); \ lua_pushboolean(localL, enc->data[writing_program].name); \
return 1; \ return 1; \
} }
#define STR_RAW_GETTER(name, length) \ #define STR_RAW_GETTER(name, length) \
int lua_get_rds_##name(lua_State *localL) { \ int lua_get_rds_##name(lua_State *localL) { \
lua_pushlstring(localL, enc->data[enc->program].name, length); \ lua_pushlstring(localL, enc->data[writing_program].name, length); \
return 1; \ return 1; \
} }
INT_SETTER(pi) INT_SETTER(pi)
@@ -195,12 +196,12 @@ int lua_get_rds_streams(lua_State *localL) {
int lua_set_rds_link(lua_State *localL) { int lua_set_rds_link(lua_State *localL) {
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1)); if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
enc->state[enc->program].eon_linkage = lua_toboolean(localL, 1); enc->state[writing_program].eon_linkage = lua_toboolean(localL, 1);
return 0; return 0;
} }
int lua_get_rds_link(lua_State *localL) { int lua_get_rds_link(lua_State *localL) {
lua_pushboolean(localL, enc->state[enc->program].eon_linkage); lua_pushboolean(localL, enc->state[writing_program].eon_linkage);
return 1; return 1;
} }
@@ -214,6 +215,7 @@ int lua_set_rds_program(lua_State *localL) {
enc->data[enc->program].ta = 0; enc->data[enc->program].ta = 0;
enc->data[(uint8_t)program].ta = 0; enc->data[(uint8_t)program].ta = 0;
enc->program = (uint8_t)program; enc->program = (uint8_t)program;
writing_program = program;
return 0; return 0;
} }
@@ -222,34 +224,48 @@ int lua_get_rds_program(lua_State *localL) {
return 1; return 1;
} }
int lua_set_rds_writing_program(lua_State *localL) {
int program = luaL_checkinteger(localL, 1);
if(program >= PROGRAMS) program = (PROGRAMS-1);
if(program < 0) program = 0;
writing_program = program;
return 0;
}
int lua_get_rds_writing_program(lua_State *localL) {
lua_pushinteger(localL, writing_program);
return 1;
}
int lua_set_rds_rt_switching_period(lua_State *localL) { int lua_set_rds_rt_switching_period(lua_State *localL) {
enc->data[enc->program].rt_switching_period = luaL_checkinteger(localL, 1); enc->data[writing_program].rt_switching_period = luaL_checkinteger(localL, 1);
enc->state[enc->program].rt_switching_period_state = enc->data[enc->program].rt_switching_period; enc->state[writing_program].rt_switching_period_state = enc->data[writing_program].rt_switching_period;
return 0; return 0;
} }
INT_GETTER(rt_switching_period) INT_GETTER(rt_switching_period)
int lua_set_rds_rt_text_timeout(lua_State *localL) { int lua_set_rds_rt_text_timeout(lua_State *localL) {
enc->data[enc->program].rt_text_timeout = luaL_checkinteger(localL, 1); enc->data[writing_program].rt_text_timeout = luaL_checkinteger(localL, 1);
enc->state[enc->program].rt_text_timeout_state = enc->data[enc->program].rt_text_timeout; enc->state[writing_program].rt_text_timeout_state = enc->data[writing_program].rt_text_timeout;
return 0; return 0;
} }
INT_GETTER(rt_text_timeout) INT_GETTER(rt_text_timeout)
int lua_put_rds_custom_group(lua_State *localL) { int lua_put_rds_custom_group(lua_State *localL) {
enc->state[enc->program].custom_group[0] = 1; enc->state[writing_program].custom_group[0] = 1;
enc->state[enc->program].custom_group[1] = luaL_checkinteger(localL, 1); enc->state[writing_program].custom_group[1] = luaL_checkinteger(localL, 1);
enc->state[enc->program].custom_group[2] = luaL_checkinteger(localL, 2); enc->state[writing_program].custom_group[2] = luaL_checkinteger(localL, 2);
enc->state[enc->program].custom_group[3] = luaL_checkinteger(localL, 3); enc->state[writing_program].custom_group[3] = luaL_checkinteger(localL, 3);
return 0; return 0;
} }
int lua_put_rds2_custom_group(lua_State *localL) { int lua_put_rds2_custom_group(lua_State *localL) {
enc->state[enc->program].custom_group2[0] = 1; enc->state[writing_program].custom_group2[0] = 1;
enc->state[enc->program].custom_group2[1] = luaL_checkinteger(localL, 1); enc->state[writing_program].custom_group2[1] = luaL_checkinteger(localL, 1);
enc->state[enc->program].custom_group2[2] = luaL_checkinteger(localL, 2); enc->state[writing_program].custom_group2[2] = luaL_checkinteger(localL, 2);
enc->state[enc->program].custom_group2[3] = luaL_checkinteger(localL, 3); enc->state[writing_program].custom_group2[3] = luaL_checkinteger(localL, 3);
enc->state[enc->program].custom_group2[4] = luaL_checkinteger(localL, 4); enc->state[writing_program].custom_group2[4] = luaL_checkinteger(localL, 4);
return 0; return 0;
} }
@@ -268,8 +284,8 @@ STR_RAW_GETTER(grp_sqc_rds2, 32)
int lua_set_rds_grp_sqc(lua_State *localL) { int lua_set_rds_grp_sqc(lua_State *localL) {
const char* str = luaL_checklstring(localL, 1, NULL); const char* str = luaL_checklstring(localL, 1, NULL);
if(_strnlen(str, 2) < 1) set_rds_grpseq(enc, DEFAULT_GRPSQC); if(_strnlen(str, 2) < 1) set_rds_grpseq(enc, DEFAULT_GRPSQC, writing_program);
else set_rds_grpseq(enc, str); else set_rds_grpseq(enc, str, writing_program);
return 0; return 0;
} }
@@ -284,16 +300,16 @@ int lua_set_rds_eon(lua_State *localL) {
if (!lua_isboolean(localL, 4)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 4)); 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)); if (!lua_isboolean(localL, 5)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 5));
luaL_checktype(localL, 8, LUA_TTABLE); luaL_checktype(localL, 8, LUA_TTABLE);
enc->data[enc->program].eon[eon].enabled = lua_toboolean(localL, 2); enc->data[writing_program].eon[eon].enabled = lua_toboolean(localL, 2);
enc->data[enc->program].eon[eon].pi = luaL_checkinteger(localL, 3); enc->data[writing_program].eon[eon].pi = luaL_checkinteger(localL, 3);
enc->data[enc->program].eon[eon].tp = lua_toboolean(localL, 4); enc->data[writing_program].eon[eon].tp = lua_toboolean(localL, 4);
enc->data[enc->program].eon[eon].ta = lua_toboolean(localL, 5); enc->data[writing_program].eon[eon].ta = lua_toboolean(localL, 5);
enc->data[enc->program].eon[eon].pty = luaL_checkinteger(localL, 6); enc->data[writing_program].eon[eon].pty = luaL_checkinteger(localL, 6);
_strncpy(enc->data[enc->program].eon[eon].ps, luaL_checklstring(localL, 7, NULL), 8); _strncpy(enc->data[writing_program].eon[eon].ps, luaL_checklstring(localL, 7, NULL), 8);
int n = lua_rawlen(localL, 8); int n = lua_rawlen(localL, 8);
if (n == 0) { if (n == 0) {
memset(&(enc->data[enc->program].eon[eon].af), 0, sizeof(RDSAFs)); memset(&(enc->data[writing_program].eon[eon].af), 0, sizeof(RDSAFs));
return 0; return 0;
} }
if(n > 25) return luaL_error(localL, "table length over 25"); if(n > 25) return luaL_error(localL, "table length over 25");
@@ -307,23 +323,23 @@ int lua_set_rds_eon(lua_State *localL) {
else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1)); else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1));
lua_pop(localL, 1); lua_pop(localL, 1);
} }
memcpy(&(enc->data[enc->program].eon[eon].af), &new_af, sizeof(new_af)); memcpy(&(enc->data[writing_program].eon[eon].af), &new_af, sizeof(new_af));
enc->data[enc->program].eon[eon].data = luaL_checkinteger(localL, 9); 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_pushboolean(localL, enc->data[enc->program].eon[eon].enabled); lua_pushboolean(localL, enc->data[writing_program].eon[eon].enabled);
lua_pushinteger(localL, enc->data[enc->program].eon[eon].pi); lua_pushinteger(localL, enc->data[writing_program].eon[eon].pi);
lua_pushboolean(localL, enc->data[enc->program].eon[eon].tp); lua_pushboolean(localL, enc->data[writing_program].eon[eon].tp);
lua_pushboolean(localL, enc->data[enc->program].eon[eon].ta); lua_pushboolean(localL, enc->data[writing_program].eon[eon].ta);
lua_pushinteger(localL, enc->data[enc->program].eon[eon].pty); lua_pushinteger(localL, enc->data[writing_program].eon[eon].pty);
lua_pushlstring(localL, enc->data[enc->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_createtable(localL, 0, 0); // don't have decoding for AF, so just return empty table
lua_pushinteger(localL, enc->data[enc->program].eon[eon].data); lua_pushinteger(localL, enc->data[writing_program].eon[eon].data);
return 8; return 8;
} }
@@ -353,11 +369,11 @@ int lua_set_rds_udg(lua_State *localL) {
} }
if(xy) { if(xy) {
memcpy(&(enc->data[enc->program].udg2), blocks, n * sizeof(uint16_t[3])); memcpy(&(enc->data[writing_program].udg2), blocks, n * sizeof(uint16_t[3]));
enc->data[enc->program].udg2_len = n; enc->data[writing_program].udg2_len = n;
} else { } else {
memcpy(&(enc->data[enc->program].udg1), blocks, n * sizeof(uint16_t[3])); memcpy(&(enc->data[writing_program].udg1), blocks, n * sizeof(uint16_t[3]));
enc->data[enc->program].udg1_len = n; enc->data[writing_program].udg1_len = n;
} }
return 0; return 0;
@@ -389,11 +405,11 @@ int lua_set_rds_udg2(lua_State *localL) {
} }
if(xy) { if(xy) {
memcpy(&(enc->data[enc->program].udg2_rds2), blocks, n * sizeof(uint16_t[4])); memcpy(&(enc->data[writing_program].udg2_rds2), blocks, n * sizeof(uint16_t[4]));
enc->data[enc->program].udg2_len_rds2 = n; enc->data[writing_program].udg2_len_rds2 = n;
} else { } else {
memcpy(&(enc->data[enc->program].udg1_rds2), blocks, n * sizeof(uint16_t[4])); memcpy(&(enc->data[writing_program].udg1_rds2), blocks, n * sizeof(uint16_t[4]));
enc->data[enc->program].udg1_len_rds2 = n; enc->data[writing_program].udg1_len_rds2 = n;
} }
return 0; return 0;
+3
View File
@@ -68,6 +68,9 @@ int lua_get_rds_link(lua_State *localL);
int lua_set_rds_program(lua_State *localL); int lua_set_rds_program(lua_State *localL);
int lua_get_rds_program(lua_State *localL); int lua_get_rds_program(lua_State *localL);
int lua_set_rds_writing_program(lua_State *localL);
int lua_get_rds_writing_program(lua_State *localL);
int lua_set_rds_rt_switching_period(lua_State *localL); int lua_set_rds_rt_switching_period(lua_State *localL);
int lua_get_rds_rt_switching_period(lua_State *localL); int lua_get_rds_rt_switching_period(lua_State *localL);
+13 -4
View File
@@ -56,6 +56,8 @@ void init_lua(RDSEncoder* _enc) {
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_program", lua_set_rds_program);
lua_registertotable(L, "get_program", lua_get_rds_program); lua_registertotable(L, "get_program", lua_get_rds_program);
lua_registertotable(L, "set_writing_program", lua_set_rds_writing_program);
lua_registertotable(L, "get_writing_program", lua_get_rds_writing_program);
lua_setglobal(L, "dp"); lua_setglobal(L, "dp");
lua_newtable(L); lua_newtable(L);
@@ -163,16 +165,23 @@ void init_lua(RDSEncoder* _enc) {
} }
} }
void run_lua(char *str, char *cmd_output, size_t* out_len) { void run_lua(char *str, size_t str_len, char *cmd_output, size_t *out_len) {
pthread_mutex_lock(&lua_mutex); pthread_mutex_lock(&lua_mutex);
lua_getglobal(L, "data_handle"); lua_getglobal(L, "data_handle");
if (lua_isfunction(L, -1)) { if (lua_isfunction(L, -1)) {
lua_pushstring(L, str); lua_pushlstring(L, str, str_len);
if (lua_pcall(L, 1, 1, 0) == LUA_OK) { if (lua_pcall(L, 1, 1, 0) == LUA_OK) {
if (lua_isstring(L, -1) && cmd_output) _strncpy(cmd_output, lua_tolstring(L, -1, out_len), 254); if (lua_isstring(L, -1) && cmd_output) {
const char *lua_str = lua_tolstring(L, -1, out_len);
if (*out_len > 254) *out_len = 254;
memcpy(cmd_output, lua_str, *out_len);
}
} else fprintf(stderr, "Lua error: %s at 'data_handle'\n", lua_tostring(L, -1)); } else fprintf(stderr, "Lua error: %s at 'data_handle'\n", lua_tostring(L, -1));
} else if (lua_isstring(L, -1) && cmd_output) _strncpy(cmd_output, lua_tolstring(L, -1, out_len), 254); } else fprintf(stderr, "'data_handle' is not a function\n");
lua_pop(L, 1); lua_pop(L, 1);
pthread_mutex_unlock(&lua_mutex); pthread_mutex_unlock(&lua_mutex);
} }
+1 -1
View File
@@ -6,7 +6,7 @@
#include <lauxlib.h> #include <lauxlib.h>
void init_lua(RDSEncoder* _enc); void init_lua(RDSEncoder* _enc);
void run_lua(char *str, 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_nolock(const char* function);
+8 -8
View File
@@ -329,14 +329,14 @@ void reset_rds_state(RDSEncoder* enc, uint8_t program) {
tempCoder.state[program].rt_ab = 1; tempCoder.state[program].rt_ab = 1;
tempCoder.state[program].ptyn_ab = 1; tempCoder.state[program].ptyn_ab = 1;
set_rds_rt1(&tempCoder, enc->data[program].rt1); set_rds_rt1(&tempCoder, enc->data[program].rt1, program);
set_rds_rt2(&tempCoder, enc->data[program].rt2); set_rds_rt2(&tempCoder, enc->data[program].rt2, program);
set_rds_ps(&tempCoder, enc->data[program].ps); set_rds_ps(&tempCoder, enc->data[program].ps), program;
set_rds_tps(&tempCoder, enc->data[program].tps); set_rds_tps(&tempCoder, enc->data[program].tps, program);
set_rds_ptyn(&tempCoder, enc->data[program].ptyn); set_rds_lps(&tempCoder, enc->data[program].lps, program);
set_rds_lps(&tempCoder, enc->data[program].lps); set_rds_ptyn(&tempCoder, enc->data[program].ptyn, program);
set_rds_grpseq(&tempCoder, enc->data[program].grp_sqc); set_rds_grpseq(&tempCoder, enc->data[program].grp_sqc, program);
set_rds_grpseq2(&tempCoder, enc->data[program].grp_sqc_rds2); set_rds_grpseq2(&tempCoder, enc->data[program].grp_sqc_rds2, program);
struct tm *utc; struct tm *utc;
time_t now; time_t now;
+9 -9
View File
@@ -195,12 +195,12 @@ void add_checkwords(RDSGroup *group, uint8_t *bits);
void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream); void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream);
void get_rds_bits(RDSEncoder* enc, uint8_t *bits, uint8_t stream); void get_rds_bits(RDSEncoder* enc, uint8_t *bits, uint8_t stream);
void set_rds_rt1(RDSEncoder* enc, const char *rt1); void set_rds_rt1(RDSEncoder* enc, const char *rt1, uint8_t program);
void set_rds_rt2(RDSEncoder* enc, const char *rt2); void set_rds_rt2(RDSEncoder* enc, const char *rt2, uint8_t program);
void set_rds_default_rt(RDSEncoder* enc, const char *rt); void set_rds_default_rt(RDSEncoder* enc, const char *rt, uint8_t program);
void set_rds_ps(RDSEncoder* enc, const char *ps); void set_rds_ps(RDSEncoder* enc, const char *ps, uint8_t program);
void set_rds_tps(RDSEncoder* enc, const char *tps); void set_rds_tps(RDSEncoder* enc, const char *tps, uint8_t program);
void set_rds_lps(RDSEncoder* enc, const char *lps); void set_rds_lps(RDSEncoder* enc, const char *lps, uint8_t program);
void set_rds_ptyn(RDSEncoder *enc, const char *ptyn); void set_rds_ptyn(RDSEncoder *enc, const char *ptyn, uint8_t program);
void set_rds_grpseq(RDSEncoder* enc, const char *grpseq); void set_rds_grpseq(RDSEncoder* enc, const char *grpseq, uint8_t program);
void set_rds_grpseq2(RDSEncoder* enc, const char *grpseq2); void set_rds_grpseq2(RDSEncoder* enc, const char *grpseq2, uint8_t program);
+63 -63
View File
@@ -1,148 +1,148 @@
#include "rds.h" #include "rds.h"
void set_rds_rt1(RDSEncoder* enc, const char *rt1) { void set_rds_rt1(RDSEncoder* enc, const char *rt1, uint8_t program) {
uint8_t i = 0, len = 0; uint8_t i = 0, len = 0;
enc->state[enc->program].rt_text_timeout_state = enc->data[enc->program].rt_text_timeout; enc->state[program].rt_text_timeout_state = enc->data[program].rt_text_timeout;
enc->state[enc->program].rt_update = 1; enc->state[program].rt_update = 1;
memset(enc->data[enc->program].rt1, ' ', RT_LENGTH); memset(enc->data[program].rt1, ' ', RT_LENGTH);
while (*rt1 != 0 && len < RT_LENGTH) enc->data[enc->program].rt1[len++] = *rt1++; while (*rt1 != 0 && len < RT_LENGTH) enc->data[program].rt1[len++] = *rt1++;
while (len > 0 && enc->data[enc->program].rt1[len - 1] == ' ') len--; while (len > 0 && enc->data[program].rt1[len - 1] == ' ') len--;
if (len < RT_LENGTH) { if (len < RT_LENGTH) {
enc->state[enc->program].rt_segments = 0; enc->state[program].rt_segments = 0;
enc->data[enc->program].rt1[len++] = '\r'; enc->data[program].rt1[len++] = '\r';
while (i < len) { while (i < len) {
i += 4; i += 4;
enc->state[enc->program].rt_segments++; enc->state[program].rt_segments++;
} }
} else enc->state[enc->program].rt_segments = 16; } else enc->state[program].rt_segments = 16;
if(enc->state[enc->program].rt_segments > 16) enc->state[enc->program].rt_segments = 16; //make sure if(enc->state[program].rt_segments > 16) enc->state[program].rt_segments = 16; //make sure
} }
void set_rds_default_rt(RDSEncoder* enc, const char *rt) { void set_rds_default_rt(RDSEncoder* enc, const char *rt, uint8_t program) {
uint8_t i = 0, len = 0; uint8_t i = 0, len = 0;
memset(enc->data[enc->program].default_rt, ' ', RT_LENGTH); memset(enc->data[program].default_rt, ' ', RT_LENGTH);
while (*rt != 0 && len < RT_LENGTH) enc->data[enc->program].default_rt[len++] = *rt++; while (*rt != 0 && len < RT_LENGTH) enc->data[program].default_rt[len++] = *rt++;
while (len > 0 && enc->data[enc->program].default_rt[len - 1] == ' ') len--; while (len > 0 && enc->data[program].default_rt[len - 1] == ' ') len--;
if (len < RT_LENGTH) { if (len < RT_LENGTH) {
enc->state[enc->program].default_rt_segments = 0; enc->state[program].default_rt_segments = 0;
enc->data[enc->program].default_rt[len++] = '\r'; enc->data[program].default_rt[len++] = '\r';
while (i < len) { while (i < len) {
i += 4; i += 4;
enc->state[enc->program].default_rt_segments++; enc->state[program].default_rt_segments++;
} }
} else enc->state[enc->program].default_rt_segments = 16; } else enc->state[program].default_rt_segments = 16;
if(enc->state[enc->program].default_rt_segments > 16) enc->state[enc->program].default_rt_segments = 16; //make sure if(enc->state[program].default_rt_segments > 16) enc->state[program].default_rt_segments = 16; //make sure
} }
void set_rds_rt2(RDSEncoder* enc, const char *rt2) { void set_rds_rt2(RDSEncoder* enc, const char *rt2, uint8_t program) {
uint8_t i = 0, len = 0; uint8_t i = 0, len = 0;
enc->state[enc->program].rt2_update = 1; enc->state[program].rt2_update = 1;
memset(enc->data[enc->program].rt2, ' ', RT_LENGTH); memset(enc->data[program].rt2, ' ', RT_LENGTH);
while (*rt2 != 0 && len < RT_LENGTH) enc->data[enc->program].rt2[len++] = *rt2++; while (*rt2 != 0 && len < RT_LENGTH) enc->data[program].rt2[len++] = *rt2++;
while (len > 0 && enc->data[enc->program].rt2[len - 1] == ' ') len--; while (len > 0 && enc->data[program].rt2[len - 1] == ' ') len--;
if (len < RT_LENGTH) { if (len < RT_LENGTH) {
enc->state[enc->program].rt2_segments = 0; enc->state[program].rt2_segments = 0;
enc->data[enc->program].rt2[len++] = '\r'; enc->data[program].rt2[len++] = '\r';
while (i < len) { while (i < len) {
i += 4; i += 4;
enc->state[enc->program].rt2_segments++; enc->state[program].rt2_segments++;
} }
} else enc->state[enc->program].rt2_segments = 16; } else enc->state[program].rt2_segments = 16;
if(enc->state[enc->program].rt2_segments > 16) enc->state[enc->program].rt2_segments = 16; //make sure if(enc->state[program].rt2_segments > 16) enc->state[program].rt2_segments = 16; //make sure
} }
void set_rds_ps(RDSEncoder* enc, const char *ps) { void set_rds_ps(RDSEncoder* enc, const char *ps, uint8_t program) {
uint8_t len = 0; uint8_t len = 0;
enc->state[enc->program].ps_update = 1; enc->state[program].ps_update = 1;
memset(enc->data[enc->program].ps, ' ', PS_LENGTH); memset(enc->data[program].ps, ' ', PS_LENGTH);
while (*ps != 0 && len < PS_LENGTH) enc->data[enc->program].ps[len++] = *ps++; while (*ps != 0 && len < PS_LENGTH) enc->data[program].ps[len++] = *ps++;
} }
void set_rds_tps(RDSEncoder* enc, const char *tps) { void set_rds_tps(RDSEncoder* enc, const char *tps, uint8_t program) {
uint8_t len = 0; uint8_t len = 0;
enc->state[enc->program].tps_update = 1; enc->state[program].tps_update = 1;
if(tps[0] == '\0') { if(tps[0] == '\0') {
memset(enc->data[enc->program].tps, 0, PS_LENGTH); memset(enc->data[program].tps, 0, PS_LENGTH);
return; return;
} }
memset(enc->data[enc->program].tps, ' ', PS_LENGTH); memset(enc->data[program].tps, ' ', PS_LENGTH);
while (*tps != 0 && len < PS_LENGTH) enc->data[enc->program].tps[len++] = *tps++; while (*tps != 0 && len < PS_LENGTH) enc->data[program].tps[len++] = *tps++;
} }
void set_rds_lps(RDSEncoder* enc, const char *lps) { void set_rds_lps(RDSEncoder* enc, const char *lps, uint8_t program) {
uint8_t i = 0, len = 0; uint8_t i = 0, len = 0;
enc->state[enc->program].lps_update = 1; enc->state[program].lps_update = 1;
if(lps[0] == '\0') { if(lps[0] == '\0') {
memset(enc->data[enc->program].lps, 0, LPS_LENGTH); memset(enc->data[program].lps, 0, LPS_LENGTH);
return; return;
} }
memset(enc->data[enc->program].lps, ' ', LPS_LENGTH); memset(enc->data[program].lps, ' ', LPS_LENGTH);
while (*lps != 0 && len < LPS_LENGTH) enc->data[enc->program].lps[len++] = *lps++; while (*lps != 0 && len < LPS_LENGTH) enc->data[program].lps[len++] = *lps++;
if (len < LPS_LENGTH) { if (len < LPS_LENGTH) {
enc->state[enc->program].lps_segments = 0; enc->state[program].lps_segments = 0;
enc->data[enc->program].lps[len++] = '\r'; enc->data[program].lps[len++] = '\r';
while (i < len) { while (i < len) {
i += 4; i += 4;
enc->state[enc->program].lps_segments++; enc->state[program].lps_segments++;
} }
} else enc->state[enc->program].lps_segments = 8; } else enc->state[program].lps_segments = 8;
if(enc->state[enc->program].lps_segments > 8) enc->state[enc->program].lps_segments = 8; //make sure if(enc->state[program].lps_segments > 8) enc->state[program].lps_segments = 8; //make sure
} }
void set_rds_ptyn(RDSEncoder* enc, const char *ptyn) { void set_rds_ptyn(RDSEncoder* enc, const char *ptyn, uint8_t program) {
uint8_t len = 0; uint8_t len = 0;
enc->state[enc->program].ptyn_update = 1; enc->state[program].ptyn_update = 1;
if(ptyn[0] == '\0') { if(ptyn[0] == '\0') {
memset(enc->data[enc->program].ptyn, 0, PTYN_LENGTH); memset(enc->data[program].ptyn, 0, PTYN_LENGTH);
return; return;
} }
memset(enc->data[enc->program].ptyn, ' ', PTYN_LENGTH); memset(enc->data[program].ptyn, ' ', PTYN_LENGTH);
while (*ptyn != 0 && len < PTYN_LENGTH) enc->data[enc->program].ptyn[len++] = *ptyn++; while (*ptyn != 0 && len < PTYN_LENGTH) enc->data[program].ptyn[len++] = *ptyn++;
} }
void set_rds_grpseq(RDSEncoder* enc, const char *grpseq) { void set_rds_grpseq(RDSEncoder* enc, const char *grpseq, uint8_t program) {
uint8_t len = 0; uint8_t len = 0;
if(grpseq[0] == '\0') { if(grpseq[0] == '\0') {
while (DEFAULT_GRPSQC[len] != 0 && len < 32) { while (DEFAULT_GRPSQC[len] != 0 && len < 32) {
enc->data[enc->program].grp_sqc[len] = DEFAULT_GRPSQC[len]; enc->data[program].grp_sqc[len] = DEFAULT_GRPSQC[len];
len++; len++;
} }
return; return;
} }
memset(enc->data[enc->program].grp_sqc, 0, 32); memset(enc->data[program].grp_sqc, 0, 32);
while (*grpseq != 0 && len < 32) enc->data[enc->program].grp_sqc[len++] = *grpseq++; while (*grpseq != 0 && len < 32) enc->data[program].grp_sqc[len++] = *grpseq++;
} }
void set_rds_grpseq2(RDSEncoder* enc, const char *grpseq2) { void set_rds_grpseq2(RDSEncoder* enc, const char *grpseq2, uint8_t program) {
uint8_t len = 0; uint8_t len = 0;
if(grpseq2[0] == '\0') { if(grpseq2[0] == '\0') {
memset(enc->data[enc->program].grp_sqc_rds2, 0, 32); memset(enc->data[program].grp_sqc_rds2, 0, 32);
memcpy(enc->data[enc->program].grp_sqc_rds2, enc->data[enc->program].grp_sqc, 32); memcpy(enc->data[program].grp_sqc_rds2, enc->data[program].grp_sqc, 32);
return; return;
} }
memset(enc->data[enc->program].grp_sqc_rds2, 0, 32); memset(enc->data[program].grp_sqc_rds2, 0, 32);
while (*grpseq2 != 0 && len < 32) enc->data[enc->program].grp_sqc_rds2[len++] = *grpseq2++; while (*grpseq2 != 0 && len < 32) enc->data[program].grp_sqc_rds2[len++] = *grpseq2++;
} }
+35 -11
View File
@@ -44,22 +44,46 @@ void poll_udp_server() {
ssize_t bytes_read = recvfrom(sockfd, buf, BUF_SIZE - 1, 0, (struct sockaddr *)&client_addr, &client_len); ssize_t bytes_read = recvfrom(sockfd, buf, BUF_SIZE - 1, 0, (struct sockaddr *)&client_addr, &client_len);
if (bytes_read <= 0) return; if (bytes_read <= 0) return;
buf[bytes_read] = '\0'; size_t start = 0;
for (ssize_t i = 0; i < bytes_read; i++) {
if (buf[i] == '\n' || (unsigned char)buf[i] == 0xFF) {
size_t len = i - start;
if (len > 0 && len < BUF_SIZE) {
memset(cmd_buf, 0, BUF_SIZE);
memcpy(cmd_buf, buf + start, len);
memset(cmd_output, 0, BUF_SIZE);
size_t out_len = 0;
run_lua(cmd_buf, len, cmd_output, &out_len);
if (out_len > 0 &&
sendto(sockfd, cmd_output, out_len, 0,
(struct sockaddr *)&client_addr, client_len) == -1) {
perror("sendto");
}
}
start = i + 1;
}
}
if (start < bytes_read) {
size_t len = bytes_read - start;
char *token = strtok(buf, "\r\n");
while (token != NULL) {
size_t len = strlen(token);
if (len > 0 && len < BUF_SIZE) { if (len > 0 && len < BUF_SIZE) {
memset(cmd_buf, 0, BUF_SIZE); memcpy(cmd_buf, buf + start, len);
strncpy(cmd_buf, token, BUF_SIZE - 1);
memset(cmd_output, 0, BUF_SIZE);
size_t out_len = 0; size_t out_len = 0;
run_lua(cmd_buf, cmd_output, &out_len); run_lua(cmd_buf, len, cmd_output, &out_len);
if (out_len > 0 && sendto(sockfd, cmd_output, out_len, 0, (struct sockaddr *)&client_addr, client_len) == -1) perror("sendto"); // no walrus
if (out_len > 0 &&
sendto(sockfd, cmd_output, out_len, 0,
(struct sockaddr *)&client_addr, client_len) == -1) {
perror("sendto");
}
} }
token = strtok(NULL, "\r\n");
} }
} }
Binary file not shown.