mirror of
https://github.com/radio95-rnt/rds95.git
synced 2026-07-29 08:19:17 +02:00
uecp testing
This commit is contained in:
@@ -28,11 +28,18 @@ function dp.reset_rds() end
|
||||
---@return nil
|
||||
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)
|
||||
function dp.set_program(program_idx) end
|
||||
---@return integer
|
||||
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
|
||||
---It should be defined by the user in the script.
|
||||
---@return nil
|
||||
|
||||
+110
-5
@@ -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)
|
||||
-- UECP
|
||||
if string.byte(data, 1) == 0xfe then return parse_uecp(data) end
|
||||
|
||||
if string.sub(data, 1, 4):lower() == "lua=" then
|
||||
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
|
||||
@@ -212,11 +321,6 @@ function data_handle(data)
|
||||
if not pty then return "-\r\n" end
|
||||
rds.set_pty(pty)
|
||||
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
|
||||
local ct = tonumber(value)
|
||||
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 program < 1 or program > dp.max_programs then return "-\r\n" end
|
||||
dp.set_program(program-1)
|
||||
dp.set_writing_program(program-1)
|
||||
rds.set_ta(false)
|
||||
return "+\r\n"
|
||||
elseif cmd == "dttmout" then
|
||||
|
||||
+73
-57
@@ -6,24 +6,25 @@ static int in_set_defaults = 0;
|
||||
extern lua_State *L;
|
||||
extern RDSEncoder* enc;
|
||||
extern uint8_t unload_refs[33];
|
||||
static int writing_program = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
int lua_get_userdata_offset(lua_State *localL) {
|
||||
uint16_t offset = luaL_checkinteger(localL, 1);
|
||||
uint16_t size = luaL_checkinteger(localL, 2);
|
||||
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;
|
||||
}
|
||||
int lua_set_userdata(lua_State *localL) {
|
||||
size_t len;
|
||||
const char *data = luaL_checklstring(localL, 1, &len);
|
||||
if(len > LUA_USER_DATA) return luaL_error(localL, "data exceeds limit");
|
||||
memset(enc->data[enc->program].lua_data, 0, LUA_USER_DATA);
|
||||
memcpy(enc->data[enc->program].lua_data, data, len);
|
||||
memset(enc->data[writing_program].lua_data, 0, LUA_USER_DATA);
|
||||
memcpy(enc->data[writing_program].lua_data, data, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -34,8 +35,8 @@ int lua_set_userdata_offset(lua_State *localL) {
|
||||
size_t len;
|
||||
const char *data = luaL_checklstring(localL, 3, &len);
|
||||
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);
|
||||
memcpy(enc->data[enc->program].lua_data + offset, data, len);
|
||||
memset(enc->data[writing_program].lua_data + offset, 0, size);
|
||||
memcpy(enc->data[writing_program].lua_data + offset, data, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -55,7 +56,7 @@ int lua_set_rds_program_defaults(lua_State *localL) {
|
||||
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, enc->program);
|
||||
set_rds_defaults(enc, writing_program);
|
||||
lua_call_tfunction_nolock("on_init");
|
||||
lua_call_tfunction_nolock("on_state");
|
||||
in_set_defaults = 0;
|
||||
@@ -77,24 +78,24 @@ int lua_reset_rds(lua_State *localL) {
|
||||
#define BOOL_SETTER(name) \
|
||||
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)); \
|
||||
enc->data[enc->program].name = lua_toboolean(localL, 1); \
|
||||
enc->data[writing_program].name = lua_toboolean(localL, 1); \
|
||||
return 0; \
|
||||
}
|
||||
#define INT_SETTER(name) \
|
||||
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; \
|
||||
}
|
||||
#define STR_SETTER(name, function) \
|
||||
int lua_set_rds_##name(lua_State *localL) { \
|
||||
const char* str = luaL_checklstring(localL, 1, NULL); \
|
||||
function(enc, convert_to_rdscharset(str)); \
|
||||
function(enc, convert_to_rdscharset(str), writing_program); \
|
||||
return 0; \
|
||||
}
|
||||
#define STR_RAW_SETTER(name, function) \
|
||||
int lua_set_rds_##name(lua_State *localL) { \
|
||||
const char* str = luaL_checklstring(localL, 1, NULL); \
|
||||
function(enc, str); \
|
||||
function(enc, str, writing_program); \
|
||||
return 0; \
|
||||
}
|
||||
#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); \
|
||||
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; \
|
||||
} \
|
||||
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)); \
|
||||
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; \
|
||||
}
|
||||
|
||||
#define INT_GETTER(name) \
|
||||
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; \
|
||||
}
|
||||
#define BOOL_GETTER(name) \
|
||||
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; \
|
||||
}
|
||||
#define STR_RAW_GETTER(name, length) \
|
||||
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; \
|
||||
}
|
||||
INT_SETTER(pi)
|
||||
@@ -195,12 +196,12 @@ int lua_get_rds_streams(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));
|
||||
enc->state[enc->program].eon_linkage = lua_toboolean(localL, 1);
|
||||
enc->state[writing_program].eon_linkage = lua_toboolean(localL, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -214,6 +215,7 @@ int lua_set_rds_program(lua_State *localL) {
|
||||
enc->data[enc->program].ta = 0;
|
||||
enc->data[(uint8_t)program].ta = 0;
|
||||
enc->program = (uint8_t)program;
|
||||
writing_program = program;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -222,34 +224,48 @@ int lua_get_rds_program(lua_State *localL) {
|
||||
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) {
|
||||
enc->data[enc->program].rt_switching_period = luaL_checkinteger(localL, 1);
|
||||
enc->state[enc->program].rt_switching_period_state = enc->data[enc->program].rt_switching_period;
|
||||
enc->data[writing_program].rt_switching_period = luaL_checkinteger(localL, 1);
|
||||
enc->state[writing_program].rt_switching_period_state = enc->data[writing_program].rt_switching_period;
|
||||
return 0;
|
||||
}
|
||||
INT_GETTER(rt_switching_period)
|
||||
|
||||
int lua_set_rds_rt_text_timeout(lua_State *localL) {
|
||||
enc->data[enc->program].rt_text_timeout = luaL_checkinteger(localL, 1);
|
||||
enc->state[enc->program].rt_text_timeout_state = enc->data[enc->program].rt_text_timeout;
|
||||
enc->data[writing_program].rt_text_timeout = luaL_checkinteger(localL, 1);
|
||||
enc->state[writing_program].rt_text_timeout_state = enc->data[writing_program].rt_text_timeout;
|
||||
return 0;
|
||||
}
|
||||
INT_GETTER(rt_text_timeout)
|
||||
|
||||
int lua_put_rds_custom_group(lua_State *localL) {
|
||||
enc->state[enc->program].custom_group[0] = 1;
|
||||
enc->state[enc->program].custom_group[1] = luaL_checkinteger(localL, 1);
|
||||
enc->state[enc->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[0] = 1;
|
||||
enc->state[writing_program].custom_group[1] = luaL_checkinteger(localL, 1);
|
||||
enc->state[writing_program].custom_group[2] = luaL_checkinteger(localL, 2);
|
||||
enc->state[writing_program].custom_group[3] = luaL_checkinteger(localL, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_put_rds2_custom_group(lua_State *localL) {
|
||||
enc->state[enc->program].custom_group2[0] = 1;
|
||||
enc->state[enc->program].custom_group2[1] = luaL_checkinteger(localL, 1);
|
||||
enc->state[enc->program].custom_group2[2] = luaL_checkinteger(localL, 2);
|
||||
enc->state[enc->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[0] = 1;
|
||||
enc->state[writing_program].custom_group2[1] = luaL_checkinteger(localL, 1);
|
||||
enc->state[writing_program].custom_group2[2] = luaL_checkinteger(localL, 2);
|
||||
enc->state[writing_program].custom_group2[3] = luaL_checkinteger(localL, 3);
|
||||
enc->state[writing_program].custom_group2[4] = luaL_checkinteger(localL, 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -268,8 +284,8 @@ STR_RAW_GETTER(grp_sqc_rds2, 32)
|
||||
|
||||
int lua_set_rds_grp_sqc(lua_State *localL) {
|
||||
const char* str = luaL_checklstring(localL, 1, NULL);
|
||||
if(_strnlen(str, 2) < 1) set_rds_grpseq(enc, DEFAULT_GRPSQC);
|
||||
else set_rds_grpseq(enc, str);
|
||||
if(_strnlen(str, 2) < 1) set_rds_grpseq(enc, DEFAULT_GRPSQC, writing_program);
|
||||
else set_rds_grpseq(enc, str, writing_program);
|
||||
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, 5)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 5));
|
||||
luaL_checktype(localL, 8, LUA_TTABLE);
|
||||
enc->data[enc->program].eon[eon].enabled = lua_toboolean(localL, 2);
|
||||
enc->data[enc->program].eon[eon].pi = luaL_checkinteger(localL, 3);
|
||||
enc->data[enc->program].eon[eon].tp = lua_toboolean(localL, 4);
|
||||
enc->data[enc->program].eon[eon].ta = lua_toboolean(localL, 5);
|
||||
enc->data[enc->program].eon[eon].pty = luaL_checkinteger(localL, 6);
|
||||
_strncpy(enc->data[enc->program].eon[eon].ps, luaL_checklstring(localL, 7, NULL), 8);
|
||||
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 (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;
|
||||
}
|
||||
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));
|
||||
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;
|
||||
}
|
||||
|
||||
int lua_get_rds_eon(lua_State *localL) {
|
||||
int eon = luaL_checkinteger(localL, 1);
|
||||
if(eon >= EONs) return luaL_error(localL, "eon index exceeded");
|
||||
lua_pushboolean(localL, enc->data[enc->program].eon[eon].enabled);
|
||||
lua_pushinteger(localL, enc->data[enc->program].eon[eon].pi);
|
||||
lua_pushboolean(localL, enc->data[enc->program].eon[eon].tp);
|
||||
lua_pushboolean(localL, enc->data[enc->program].eon[eon].ta);
|
||||
lua_pushinteger(localL, enc->data[enc->program].eon[eon].pty);
|
||||
lua_pushlstring(localL, enc->data[enc->program].eon[eon].ps, 8);
|
||||
lua_pushboolean(localL, enc->data[writing_program].eon[eon].enabled);
|
||||
lua_pushinteger(localL, enc->data[writing_program].eon[eon].pi);
|
||||
lua_pushboolean(localL, enc->data[writing_program].eon[eon].tp);
|
||||
lua_pushboolean(localL, enc->data[writing_program].eon[eon].ta);
|
||||
lua_pushinteger(localL, enc->data[writing_program].eon[eon].pty);
|
||||
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_pushinteger(localL, enc->data[enc->program].eon[eon].data);
|
||||
lua_pushinteger(localL, enc->data[writing_program].eon[eon].data);
|
||||
return 8;
|
||||
}
|
||||
|
||||
@@ -353,11 +369,11 @@ int lua_set_rds_udg(lua_State *localL) {
|
||||
}
|
||||
|
||||
if(xy) {
|
||||
memcpy(&(enc->data[enc->program].udg2), blocks, n * sizeof(uint16_t[3]));
|
||||
enc->data[enc->program].udg2_len = n;
|
||||
memcpy(&(enc->data[writing_program].udg2), blocks, n * sizeof(uint16_t[3]));
|
||||
enc->data[writing_program].udg2_len = n;
|
||||
} else {
|
||||
memcpy(&(enc->data[enc->program].udg1), blocks, n * sizeof(uint16_t[3]));
|
||||
enc->data[enc->program].udg1_len = n;
|
||||
memcpy(&(enc->data[writing_program].udg1), blocks, n * sizeof(uint16_t[3]));
|
||||
enc->data[writing_program].udg1_len = n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -389,11 +405,11 @@ int lua_set_rds_udg2(lua_State *localL) {
|
||||
}
|
||||
|
||||
if(xy) {
|
||||
memcpy(&(enc->data[enc->program].udg2_rds2), blocks, n * sizeof(uint16_t[4]));
|
||||
enc->data[enc->program].udg2_len_rds2 = n;
|
||||
memcpy(&(enc->data[writing_program].udg2_rds2), blocks, n * sizeof(uint16_t[4]));
|
||||
enc->data[writing_program].udg2_len_rds2 = n;
|
||||
} else {
|
||||
memcpy(&(enc->data[enc->program].udg1_rds2), blocks, n * sizeof(uint16_t[4]));
|
||||
enc->data[enc->program].udg1_len_rds2 = n;
|
||||
memcpy(&(enc->data[writing_program].udg1_rds2), blocks, n * sizeof(uint16_t[4]));
|
||||
enc->data[writing_program].udg1_len_rds2 = n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -68,6 +68,9 @@ int lua_get_rds_link(lua_State *localL);
|
||||
int lua_set_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_get_rds_rt_switching_period(lua_State *localL);
|
||||
|
||||
|
||||
+13
-4
@@ -56,6 +56,8 @@ void init_lua(RDSEncoder* _enc) {
|
||||
lua_setfield(L, -2, "max_programs");
|
||||
lua_registertotable(L, "set_program", lua_set_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_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);
|
||||
|
||||
lua_getglobal(L, "data_handle");
|
||||
|
||||
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_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 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);
|
||||
pthread_mutex_unlock(&lua_mutex);
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
#include <lauxlib.h>
|
||||
|
||||
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_rds2_group(RDSGroup* group, int stream);
|
||||
void lua_call_function_nolock(const char* function);
|
||||
|
||||
@@ -329,14 +329,14 @@ void reset_rds_state(RDSEncoder* enc, uint8_t program) {
|
||||
|
||||
tempCoder.state[program].rt_ab = 1;
|
||||
tempCoder.state[program].ptyn_ab = 1;
|
||||
set_rds_rt1(&tempCoder, enc->data[program].rt1);
|
||||
set_rds_rt2(&tempCoder, enc->data[program].rt2);
|
||||
set_rds_ps(&tempCoder, enc->data[program].ps);
|
||||
set_rds_tps(&tempCoder, enc->data[program].tps);
|
||||
set_rds_ptyn(&tempCoder, enc->data[program].ptyn);
|
||||
set_rds_lps(&tempCoder, enc->data[program].lps);
|
||||
set_rds_grpseq(&tempCoder, enc->data[program].grp_sqc);
|
||||
set_rds_grpseq2(&tempCoder, enc->data[program].grp_sqc_rds2);
|
||||
set_rds_rt1(&tempCoder, enc->data[program].rt1, program);
|
||||
set_rds_rt2(&tempCoder, enc->data[program].rt2, program);
|
||||
set_rds_ps(&tempCoder, enc->data[program].ps), program;
|
||||
set_rds_tps(&tempCoder, enc->data[program].tps, program);
|
||||
set_rds_lps(&tempCoder, enc->data[program].lps, program);
|
||||
set_rds_ptyn(&tempCoder, enc->data[program].ptyn, program);
|
||||
set_rds_grpseq(&tempCoder, enc->data[program].grp_sqc, program);
|
||||
set_rds_grpseq2(&tempCoder, enc->data[program].grp_sqc_rds2, program);
|
||||
|
||||
struct tm *utc;
|
||||
time_t now;
|
||||
|
||||
@@ -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_bits(RDSEncoder* enc, uint8_t *bits, uint8_t stream);
|
||||
|
||||
void set_rds_rt1(RDSEncoder* enc, const char *rt1);
|
||||
void set_rds_rt2(RDSEncoder* enc, const char *rt2);
|
||||
void set_rds_default_rt(RDSEncoder* enc, const char *rt);
|
||||
void set_rds_ps(RDSEncoder* enc, const char *ps);
|
||||
void set_rds_tps(RDSEncoder* enc, const char *tps);
|
||||
void set_rds_lps(RDSEncoder* enc, const char *lps);
|
||||
void set_rds_ptyn(RDSEncoder *enc, const char *ptyn);
|
||||
void set_rds_grpseq(RDSEncoder* enc, const char *grpseq);
|
||||
void set_rds_grpseq2(RDSEncoder* enc, const char *grpseq2);
|
||||
void set_rds_rt1(RDSEncoder* enc, const char *rt1, uint8_t program);
|
||||
void set_rds_rt2(RDSEncoder* enc, const char *rt2, uint8_t program);
|
||||
void set_rds_default_rt(RDSEncoder* enc, const char *rt, uint8_t program);
|
||||
void set_rds_ps(RDSEncoder* enc, const char *ps, uint8_t program);
|
||||
void set_rds_tps(RDSEncoder* enc, const char *tps, uint8_t program);
|
||||
void set_rds_lps(RDSEncoder* enc, const char *lps, uint8_t program);
|
||||
void set_rds_ptyn(RDSEncoder *enc, const char *ptyn, uint8_t program);
|
||||
void set_rds_grpseq(RDSEncoder* enc, const char *grpseq, uint8_t program);
|
||||
void set_rds_grpseq2(RDSEncoder* enc, const char *grpseq2, uint8_t program);
|
||||
+63
-63
@@ -1,148 +1,148 @@
|
||||
#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;
|
||||
|
||||
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);
|
||||
while (*rt1 != 0 && len < RT_LENGTH) enc->data[enc->program].rt1[len++] = *rt1++;
|
||||
memset(enc->data[program].rt1, ' ', RT_LENGTH);
|
||||
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) {
|
||||
enc->state[enc->program].rt_segments = 0;
|
||||
enc->data[enc->program].rt1[len++] = '\r';
|
||||
enc->state[program].rt_segments = 0;
|
||||
enc->data[program].rt1[len++] = '\r';
|
||||
while (i < len) {
|
||||
i += 4;
|
||||
enc->state[enc->program].rt_segments++;
|
||||
enc->state[program].rt_segments++;
|
||||
}
|
||||
} else enc->state[enc->program].rt_segments = 16;
|
||||
if(enc->state[enc->program].rt_segments > 16) enc->state[enc->program].rt_segments = 16; //make sure
|
||||
} else enc->state[program].rt_segments = 16;
|
||||
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;
|
||||
|
||||
memset(enc->data[enc->program].default_rt, ' ', RT_LENGTH);
|
||||
while (*rt != 0 && len < RT_LENGTH) enc->data[enc->program].default_rt[len++] = *rt++;
|
||||
memset(enc->data[program].default_rt, ' ', RT_LENGTH);
|
||||
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) {
|
||||
enc->state[enc->program].default_rt_segments = 0;
|
||||
enc->data[enc->program].default_rt[len++] = '\r';
|
||||
enc->state[program].default_rt_segments = 0;
|
||||
enc->data[program].default_rt[len++] = '\r';
|
||||
while (i < len) {
|
||||
i += 4;
|
||||
enc->state[enc->program].default_rt_segments++;
|
||||
enc->state[program].default_rt_segments++;
|
||||
}
|
||||
} else enc->state[enc->program].default_rt_segments = 16;
|
||||
if(enc->state[enc->program].default_rt_segments > 16) enc->state[enc->program].default_rt_segments = 16; //make sure
|
||||
} else enc->state[program].default_rt_segments = 16;
|
||||
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;
|
||||
|
||||
enc->state[enc->program].rt2_update = 1;
|
||||
enc->state[program].rt2_update = 1;
|
||||
|
||||
memset(enc->data[enc->program].rt2, ' ', RT_LENGTH);
|
||||
while (*rt2 != 0 && len < RT_LENGTH) enc->data[enc->program].rt2[len++] = *rt2++;
|
||||
memset(enc->data[program].rt2, ' ', RT_LENGTH);
|
||||
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) {
|
||||
enc->state[enc->program].rt2_segments = 0;
|
||||
enc->data[enc->program].rt2[len++] = '\r';
|
||||
enc->state[program].rt2_segments = 0;
|
||||
enc->data[program].rt2[len++] = '\r';
|
||||
while (i < len) {
|
||||
i += 4;
|
||||
enc->state[enc->program].rt2_segments++;
|
||||
enc->state[program].rt2_segments++;
|
||||
}
|
||||
} else enc->state[enc->program].rt2_segments = 16;
|
||||
if(enc->state[enc->program].rt2_segments > 16) enc->state[enc->program].rt2_segments = 16; //make sure
|
||||
} else enc->state[program].rt2_segments = 16;
|
||||
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;
|
||||
|
||||
enc->state[enc->program].ps_update = 1;
|
||||
memset(enc->data[enc->program].ps, ' ', PS_LENGTH);
|
||||
while (*ps != 0 && len < PS_LENGTH) enc->data[enc->program].ps[len++] = *ps++;
|
||||
enc->state[program].ps_update = 1;
|
||||
memset(enc->data[program].ps, ' ', PS_LENGTH);
|
||||
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;
|
||||
|
||||
enc->state[enc->program].tps_update = 1;
|
||||
enc->state[program].tps_update = 1;
|
||||
if(tps[0] == '\0') {
|
||||
memset(enc->data[enc->program].tps, 0, PS_LENGTH);
|
||||
memset(enc->data[program].tps, 0, PS_LENGTH);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(enc->data[enc->program].tps, ' ', PS_LENGTH);
|
||||
while (*tps != 0 && len < PS_LENGTH) enc->data[enc->program].tps[len++] = *tps++;
|
||||
memset(enc->data[program].tps, ' ', PS_LENGTH);
|
||||
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;
|
||||
|
||||
enc->state[enc->program].lps_update = 1;
|
||||
enc->state[program].lps_update = 1;
|
||||
if(lps[0] == '\0') {
|
||||
memset(enc->data[enc->program].lps, 0, LPS_LENGTH);
|
||||
memset(enc->data[program].lps, 0, LPS_LENGTH);
|
||||
return;
|
||||
}
|
||||
memset(enc->data[enc->program].lps, ' ', LPS_LENGTH);
|
||||
while (*lps != 0 && len < LPS_LENGTH) enc->data[enc->program].lps[len++] = *lps++;
|
||||
memset(enc->data[program].lps, ' ', LPS_LENGTH);
|
||||
while (*lps != 0 && len < LPS_LENGTH) enc->data[program].lps[len++] = *lps++;
|
||||
|
||||
if (len < LPS_LENGTH) {
|
||||
enc->state[enc->program].lps_segments = 0;
|
||||
enc->data[enc->program].lps[len++] = '\r';
|
||||
enc->state[program].lps_segments = 0;
|
||||
enc->data[program].lps[len++] = '\r';
|
||||
while (i < len) {
|
||||
i += 4;
|
||||
enc->state[enc->program].lps_segments++;
|
||||
enc->state[program].lps_segments++;
|
||||
}
|
||||
} else enc->state[enc->program].lps_segments = 8;
|
||||
if(enc->state[enc->program].lps_segments > 8) enc->state[enc->program].lps_segments = 8; //make sure
|
||||
} else enc->state[program].lps_segments = 8;
|
||||
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;
|
||||
|
||||
enc->state[enc->program].ptyn_update = 1;
|
||||
enc->state[program].ptyn_update = 1;
|
||||
|
||||
if(ptyn[0] == '\0') {
|
||||
memset(enc->data[enc->program].ptyn, 0, PTYN_LENGTH);
|
||||
memset(enc->data[program].ptyn, 0, PTYN_LENGTH);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(enc->data[enc->program].ptyn, ' ', PTYN_LENGTH);
|
||||
while (*ptyn != 0 && len < PTYN_LENGTH) enc->data[enc->program].ptyn[len++] = *ptyn++;
|
||||
memset(enc->data[program].ptyn, ' ', PTYN_LENGTH);
|
||||
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;
|
||||
|
||||
if(grpseq[0] == '\0') {
|
||||
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++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
memset(enc->data[enc->program].grp_sqc, 0, 32);
|
||||
while (*grpseq != 0 && len < 32) enc->data[enc->program].grp_sqc[len++] = *grpseq++;
|
||||
memset(enc->data[program].grp_sqc, 0, 32);
|
||||
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;
|
||||
|
||||
if(grpseq2[0] == '\0') {
|
||||
memset(enc->data[enc->program].grp_sqc_rds2, 0, 32);
|
||||
memcpy(enc->data[enc->program].grp_sqc_rds2, enc->data[enc->program].grp_sqc, 32);
|
||||
memset(enc->data[program].grp_sqc_rds2, 0, 32);
|
||||
memcpy(enc->data[program].grp_sqc_rds2, enc->data[program].grp_sqc, 32);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(enc->data[enc->program].grp_sqc_rds2, 0, 32);
|
||||
while (*grpseq2 != 0 && len < 32) enc->data[enc->program].grp_sqc_rds2[len++] = *grpseq2++;
|
||||
memset(enc->data[program].grp_sqc_rds2, 0, 32);
|
||||
while (*grpseq2 != 0 && len < 32) enc->data[program].grp_sqc_rds2[len++] = *grpseq2++;
|
||||
}
|
||||
+35
-11
@@ -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);
|
||||
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) {
|
||||
memset(cmd_buf, 0, BUF_SIZE);
|
||||
strncpy(cmd_buf, token, BUF_SIZE - 1);
|
||||
|
||||
memset(cmd_output, 0, BUF_SIZE);
|
||||
memcpy(cmd_buf, buf + start, len);
|
||||
|
||||
size_t out_len = 0;
|
||||
run_lua(cmd_buf, 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
|
||||
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");
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, "\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user