From b83a96d88961f34028b0cd7d7c07dc78c743495b Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Wed, 24 Dec 2025 16:26:00 +0100 Subject: [PATCH] thread safety and register oda --- plugin.lua | 10 +++++- src/lua_rds.c | 85 ++++++++++++++++++++---------------------------- src/rds.c | 8 ++++- src/rds.h | 17 ++++++++++ src/rds_groups.c | 12 +++++++ 5 files changed, 80 insertions(+), 52 deletions(-) diff --git a/plugin.lua b/plugin.lua index 2f35949..561099b 100644 --- a/plugin.lua +++ b/plugin.lua @@ -255,4 +255,12 @@ function set_rds_udg(xy, groups) end ---Sets the X/Y of the UDG for RDS2 ---@param xy boolean ---@param groups table Table of tables, this should be up to 8 tables containing 4 integers -function set_rds_udg2(xy, groups) end \ No newline at end of file +function set_rds_udg2(xy, groups) end + +---Registers an ODA to be used in the O of the group sequence. ODAs are stored as state data, thus running reset_rds will clear it +---@param group integer +---@param group_version boolean +---@param id integer +---@param id_data integer +---@return integer oda_id +function register_oda(group, group_version, id, id_data) end \ No newline at end of file diff --git a/src/lua_rds.c b/src/lua_rds.c index 20cbd77..f2db75a 100644 --- a/src/lua_rds.c +++ b/src/lua_rds.c @@ -1,7 +1,9 @@ #include "lua_rds.h" +#include static RDSModulator* mod = NULL; static lua_State *L = NULL; +static pthread_mutex_t lua_mutex; int lua_set_rds_program_defaults(lua_State *localL) { (void)localL; @@ -397,6 +399,19 @@ int lua_set_rds_udg2(lua_State *localL) { return 0; } +int lua_register_oda(lua_State *localL) { + if (!lua_isboolean(localL, 2)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 2)); + uint8_t id = mod->enc->state[mod->enc->program].user_oda.oda_len++; + if(mod->enc->state[mod->enc->program].user_oda.oda_len >= 32) return luaL_error(localL, "There can't be more than 32 registered ODAs"); + mod->enc->state[mod->enc->program].user_oda.odas[id].enabled = 1; + mod->enc->state[mod->enc->program].user_oda.odas[id].group = luaL_checkinteger(localL, 1); + mod->enc->state[mod->enc->program].user_oda.odas[id].group_version = lua_toboolean(localL, 2); + mod->enc->state[mod->enc->program].user_oda.odas[id].id = luaL_checkinteger(localL, 3); + mod->enc->state[mod->enc->program].user_oda.odas[id].id_data = luaL_checkinteger(localL, 4); + lua_pushinteger(localL, id); + return 1; +} + void init_lua(RDSModulator* rds_mod) { mod = rds_mod; L = luaL_newstate(); @@ -512,9 +527,9 @@ void init_lua(RDSModulator* rds_mod) { lua_register(L, "set_rds_udg", lua_set_rds_udg); lua_register(L, "set_rds_udg2", lua_set_rds_udg2); -} -void run_lua(char *str, char *cmd_output) { + lua_register(L, "register_oda", lua_register_oda); + char path[128]; const char *home = getenv("HOME"); if (!home) return; @@ -524,48 +539,31 @@ void run_lua(char *str, char *cmd_output) { fprintf(stderr, "Lua error loading file: %s\n", lua_tostring(L, -1)); lua_pop(L, 1); return; + } else { + if (lua_pcall(L, 0, 0, 0) != LUA_OK) { + printf("Init error: %s\n", lua_tostring(L, -1)); + lua_pop(L, 1); + } } - if (lua_pcall(L, 0, 0, 0) != LUA_OK) { - fprintf(stderr, "Lua error running script: %s\n", lua_tostring(L, -1)); - lua_pop(L, 1); - return; - } + pthread_mutex_init(&lua_mutex, NULL); +} +void run_lua(char *str, char *cmd_output) { + pthread_mutex_lock(&lua_mutex); lua_getglobal(L, "data_handle"); if (lua_isfunction(L, -1)) { lua_pushstring(L, str); if (lua_pcall(L, 1, 1, 0) == LUA_OK) { - if (lua_isstring(L, -1) && cmd_output) { - const char *res = lua_tostring(L, -1); - strcpy(cmd_output, res); - } - } else { - fprintf(stderr, "Lua error: %s\n", lua_tostring(L, -1)); - } - } else if (lua_isstring(L, -1)) { - if (cmd_output) strcpy(cmd_output, lua_tostring(L, -1)); - } + if (lua_isstring(L, -1) && cmd_output) strcpy(cmd_output, lua_tostring(L, -1)); + } else fprintf(stderr, "Lua error: %s\n", lua_tostring(L, -1)); + } else if (lua_isstring(L, -1) && cmd_output) strcpy(cmd_output, lua_tostring(L, -1)); lua_pop(L, 1); + pthread_mutex_unlock(&lua_mutex); } void lua_group(RDSGroup* group) { - char path[128]; - const char *home = getenv("HOME"); - if (!home) return; - snprintf(path, sizeof(path), "%s/.rds95.command.lua", home); - - if (luaL_loadfile(L, path) != LUA_OK) { - fprintf(stderr, "Lua error loading file: %s\n", lua_tostring(L, -1)); - lua_pop(L, 1); - return; - } - if (lua_pcall(L, 0, 0, 0) != LUA_OK) { - fprintf(stderr, "Lua error running script: %s\n", lua_tostring(L, -1)); - lua_pop(L, 1); - return; - } - + pthread_mutex_lock(&lua_mutex); lua_getglobal(L, "group"); if (lua_isfunction(L, -1)) { @@ -584,26 +582,11 @@ void lua_group(RDSGroup* group) { } else { lua_pop(L, 1); } + pthread_mutex_unlock(&lua_mutex); } void lua_call_function(const char* function) { - char path[128]; - snprintf(path, sizeof(path), "%s/.rds95.command.lua", getenv("HOME")); - - if (luaL_loadfilex(L, path, NULL) != LUA_OK) { - const char *err = lua_tostring(L, -1); - fprintf(stderr, "Lua error loading file: %s\n", err); - lua_pop(L, 1); - return; - } - - if (lua_pcall(L, 0, 0, 0) != LUA_OK) { - const char *err = lua_tostring(L, -1); - fprintf(stderr, "Lua error running script: %s\n", err); - lua_pop(L, 1); - return; - } - + pthread_mutex_lock(&lua_mutex); lua_getglobal(L, function); if (lua_isfunction(L, -1)) { @@ -612,6 +595,7 @@ void lua_call_function(const char* function) { lua_pop(L, 1); } } else lua_pop(L, 1); + pthread_mutex_unlock(&lua_mutex); } void destroy_lua(void) { @@ -620,4 +604,5 @@ void destroy_lua(void) { L = NULL; } mod = NULL; + pthread_mutex_destroy(&lua_mutex); } diff --git a/src/rds.c b/src/rds.c index baab26a..767be2f 100644 --- a/src/rds.c +++ b/src/rds.c @@ -29,6 +29,7 @@ void get_rds_ert_group(RDSEncoder* enc, RDSGroup *group); uint8_t get_rds_custom_groups(RDSEncoder* enc, RDSGroup *group); uint8_t get_rds_custom_groups2(RDSEncoder* enc, RDSGroup *group); void get_rdsp_lua_group(RDSGroup *group); +void get_rds_user_oda_group(RDSEncoder* enc, RDSGroup *group); #define HANDLE_UDG_STREAM(chan_idx, udg_prefix) \ do { \ @@ -112,6 +113,9 @@ static void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, char* grp, case 'L': get_rdsp_lua_group(group); break; + case 'O': + get_rds_user_oda_group(enc, group); + break; case 'U': if(enc->state[enc->program].af_oda == 0) get_rds_oda_af_group(enc, group); else get_rdsp_oda_af_oda_group(group); @@ -142,6 +146,7 @@ static uint8_t check_rds_good_group(RDSEncoder* enc, char* grp) { if(*grp == 'F' && enc->data[enc->program].lps[0] != '\0') good_group = 1; if(*grp == 'T') good_group = 1; if(*grp == 'L') good_group = 1; + if(*grp == 'O' && enc->state[enc->program].user_oda.oda_len != 0) good_group = 1; if(*grp == 'U' && enc->data[enc->program].af_oda.num_afs) good_group = 1; return good_group; } @@ -151,6 +156,7 @@ static void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream) { group->b = 0; group->c = 0; group->d = 0; + group->is_type_b = 0; struct tm *utc; time_t now; @@ -394,7 +400,7 @@ void init_rds_encoder(RDSEncoder* enc) { printf("Encoder file will be reinitialized.\n"); lua_call_function("on_init"); } - encoder_saveToFile(enc); for(int i = 0; i < PROGRAMS; i++) reset_rds_state(enc, i); lua_call_function("on_start"); + encoder_saveToFile(enc); } \ No newline at end of file diff --git a/src/rds.h b/src/rds.h index 143a0ba..e4ca5ab 100644 --- a/src/rds.h +++ b/src/rds.h @@ -111,6 +111,21 @@ typedef struct { typedef struct { uint8_t af_state : 6; } RDSEONState; + +typedef struct { + uint8_t enabled : 1; + uint8_t group : 4; + uint8_t group_version : 1; + uint16_t id; + uint16_t id_data; + int lua_handler; +} RDSODA; +typedef struct { + uint8_t oda_len; + uint8_t oda_pointer; + RDSODA odas[32]; +} RDSODAState; + typedef struct { uint8_t ps_update : 1; uint8_t tps_update : 1; @@ -175,6 +190,8 @@ typedef struct { uint16_t last_stream0_group[3]; uint8_t last_stream0_group_type_b : 1; + + RDSODAState user_oda; } RDSState; typedef struct { diff --git a/src/rds_groups.c b/src/rds_groups.c index 4fb2fdb..c89cfaa 100644 --- a/src/rds_groups.c +++ b/src/rds_groups.c @@ -369,4 +369,16 @@ uint8_t get_rds_custom_groups2(RDSEncoder* enc, RDSGroup *group) { void get_rdsp_lua_group(RDSGroup *group) { lua_group(group); group->is_type_b = (IS_TYPE_B(group->b) != 0); +} + +void get_rds_user_oda_group(RDSEncoder* enc, RDSGroup *group) { + uint8_t pointer = enc->state[enc->program].user_oda.oda_pointer++; + if(enc->state[enc->program].user_oda.oda_pointer >= enc->state[enc->program].user_oda.oda_len) enc->state[enc->program].user_oda.oda_pointer = 0; + RDSODA oda = enc->state[enc->program].user_oda.odas[pointer]; + + group->b |= 3 << 12; + group->b |= oda.group << 1; + group->b |= oda.group_version; + group->c = oda.id_data; + group->d = oda.id; } \ No newline at end of file