From 77e281dbfc8e48e39615698a587532cebd8359d5 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Wed, 24 Dec 2025 19:40:53 +0100 Subject: [PATCH] oda_handler --- plugin.lua | 6 +++- src/lua_rds.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++-- src/lua_rds.h | 1 + src/rds.c | 5 ++++ src/rds.h | 2 +- src/rds_groups.c | 17 +++++++++++ 6 files changed, 100 insertions(+), 5 deletions(-) diff --git a/plugin.lua b/plugin.lua index 561099b..29de1b9 100644 --- a/plugin.lua +++ b/plugin.lua @@ -263,4 +263,8 @@ function set_rds_udg2(xy, groups) end ---@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 +function register_oda(group, group_version, id, id_data) end +---Sets a function to handle the ODA for the oda id we have specified when we get to group "" TODO: which one +---@param oda_id integer +---@param fun function +function set_oda_handler(oda_id, fun) end \ No newline at end of file diff --git a/src/lua_rds.c b/src/lua_rds.c index f2db75a..f4de20f 100644 --- a/src/lua_rds.c +++ b/src/lua_rds.c @@ -4,9 +4,12 @@ static RDSModulator* mod = NULL; static lua_State *L = NULL; static pthread_mutex_t lua_mutex; +static uint8_t unload_refs[33] = {LUA_REFNIL}; int lua_set_rds_program_defaults(lua_State *localL) { (void)localL; + for (int i = 1; i < *unload_refs; i++) luaL_unref(L, LUA_REGISTRYINDEX, unload_refs[i]); + unload_refs[0] = 0; set_rds_defaults(mod->enc, mod->enc->program); lua_call_function("on_init"); return 0; @@ -14,6 +17,8 @@ int lua_set_rds_program_defaults(lua_State *localL) { int lua_reset_rds(lua_State *localL) { (void)localL; + for (int i = 1; i < *unload_refs; i++) luaL_unref(L, LUA_REGISTRYINDEX, unload_refs[i]); + unload_refs[0] = 0; encoder_saveToFile(mod->enc); Modulator_saveToFile(&mod->params); @@ -403,8 +408,9 @@ 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; + if(mod->enc->state[mod->enc->program].user_oda.odas[id].group != 0) return luaL_error(localL, "internal error"); mod->enc->state[mod->enc->program].user_oda.odas[id].group = luaL_checkinteger(localL, 1); + if(mod->enc->state[mod->enc->program].user_oda.odas[id].group == 0) return luaL_error(localL, "Invalid group") 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); @@ -412,6 +418,20 @@ int lua_register_oda(lua_State *localL) { return 1; } +int lua_set_oda_handler(lua_State *localL) { + uint8_t idx = luaL_checkinteger(localL, 1); + if(idx >= 32) return luaL_error(localL, "There can't be more than 32 registered ODAs"); + if(mod->enc->state[mod->enc->program].user_oda.odas[idx].group == 0) return luaL_error(localL, "this oda is not registered"); + luaL_checktype(localL, 2, LUA_TFUNCTION); + lua_pushvalue(localL, 2); + if(mod->enc->state[mod->enc->program].user_oda.odas[idx].lua_handler != 0) luaL_unref(localL, LUA_REGISTRYINDEX, mod->enc->state[mod->enc->program].user_oda.odas[idx].lua_handler); + mod->enc->state[mod->enc->program].user_oda.odas[idx].lua_handler = luaL_ref(localL, LUA_REGISTRYINDEX); + int index = *unload_refs; + unload_refs[index] = mod->enc->state[mod->enc->program].user_oda.odas[idx].lua_handler; + (*unload_refs)++; + return 0; +} + void init_lua(RDSModulator* rds_mod) { mod = rds_mod; L = luaL_newstate(); @@ -529,6 +549,7 @@ void init_lua(RDSModulator* rds_mod) { lua_register(L, "set_rds_udg2", lua_set_rds_udg2); lua_register(L, "register_oda", lua_register_oda); + lua_register(L, "set_oda_handler", lua_set_oda_handler); char path[128]; const char *home = getenv("HOME"); @@ -545,6 +566,7 @@ void init_lua(RDSModulator* rds_mod) { lua_pop(L, 1); } } + lua_pushvalue(L, 1); pthread_mutex_init(&lua_mutex, NULL); } @@ -555,9 +577,9 @@ void run_lua(char *str, char *cmd_output) { 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) strcpy(cmd_output, lua_tostring(L, -1)); + if (lua_isstring(L, -1) && cmd_output) _strncpy(cmd_output, lua_tostring(L, -1), 254); } 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)); + } else if (lua_isstring(L, -1) && cmd_output) _strncpy(cmd_output, lua_tostring(L, -1), 254); lua_pop(L, 1); pthread_mutex_unlock(&lua_mutex); } @@ -571,6 +593,18 @@ void lua_group(RDSGroup* group) { lua_pushinteger(L, group->c); lua_pushinteger(L, group->d); if (lua_pcall(L, 3, 3, 0) == LUA_OK) { + if (!lua_isinteger(localL, -1)) { + pthread_mutex_unlock(&lua_mutex); + return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -1)); + } + if (!lua_isinteger(localL, -2)) { + pthread_mutex_unlock(&lua_mutex); + return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -2)); + } + if (!lua_isinteger(localL, -3)) { + pthread_mutex_unlock(&lua_mutex); + return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -3)); + } group->d = luaL_checkinteger(L, -1); group->c = luaL_checkinteger(L, -2); group->b = luaL_checkinteger(L, -3); @@ -585,6 +619,39 @@ void lua_group(RDSGroup* group) { pthread_mutex_unlock(&lua_mutex); } +void lua_group_ref(RDSGroup* group, int ref) { + pthread_mutex_lock(&lua_mutex); + lua_rawgeti(L, LUA_REGISTRYINDEX, ref); + + if (lua_isfunction(L, -1)) { + lua_pushinteger(L, group->b); + lua_pushinteger(L, group->c); + lua_pushinteger(L, group->d); + if (lua_pcall(L, 3, 3, 0) == LUA_OK) { + if (!lua_isinteger(localL, -1)) { + pthread_mutex_unlock(&lua_mutex); + return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -1)); + } + if (!lua_isinteger(localL, -2)) { + pthread_mutex_unlock(&lua_mutex); + return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -2)); + } + if (!lua_isinteger(localL, -3)) { + pthread_mutex_unlock(&lua_mutex); + return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -3)); + } + group->d = luaL_checkinteger(L, -1); + group->c = luaL_checkinteger(L, -2); + group->b = luaL_checkinteger(L, -3); + lua_pop(L, 3); + } else { + fprintf(stderr, "Lua error: %s\n", lua_tostring(L, -1)); + lua_pop(L, 1); + } + } else lua_pop(L, 1); + pthread_mutex_unlock(&lua_mutex); +} + void lua_call_function(const char* function) { pthread_mutex_lock(&lua_mutex); lua_getglobal(L, function); @@ -600,6 +667,7 @@ void lua_call_function(const char* function) { void destroy_lua(void) { if (L) { + for (int i = 1; i < *unload_refs; i++) luaL_unref(L, LUA_REGISTRYINDEX, unload_refs[i]); lua_close(L); L = NULL; } diff --git a/src/lua_rds.h b/src/lua_rds.h index f518419..c2ef2ba 100644 --- a/src/lua_rds.h +++ b/src/lua_rds.h @@ -10,4 +10,5 @@ void init_lua(RDSModulator* rds_mod); void run_lua(char *str, char *cmd_output); void lua_group(RDSGroup* group); void lua_call_function(const char* function); +void lua_group_ref(RDSGroup* group, int ref); void destroy_lua(); \ No newline at end of file diff --git a/src/rds.c b/src/rds.c index 767be2f..76bbdcc 100644 --- a/src/rds.c +++ b/src/rds.c @@ -30,6 +30,7 @@ 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); +int get_rds_user_oda_group_content(RDSEncoder* enc, RDSGroup *group); #define HANDLE_UDG_STREAM(chan_idx, udg_prefix) \ do { \ @@ -116,6 +117,9 @@ static void get_rds_sequence_group(RDSEncoder* enc, RDSGroup *group, char* grp, case 'O': get_rds_user_oda_group(enc, group); break; + case 'K': + if(get_rds_user_oda_group_content(enc, group) == 0) get_rds_ps_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); @@ -147,6 +151,7 @@ static uint8_t check_rds_good_group(RDSEncoder* enc, char* grp) { 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 == 'K') good_group = 1; if(*grp == 'U' && enc->data[enc->program].af_oda.num_afs) good_group = 1; return good_group; } diff --git a/src/rds.h b/src/rds.h index e4ca5ab..7c9ca8e 100644 --- a/src/rds.h +++ b/src/rds.h @@ -113,7 +113,6 @@ typedef struct { } RDSEONState; typedef struct { - uint8_t enabled : 1; uint8_t group : 4; uint8_t group_version : 1; uint16_t id; @@ -123,6 +122,7 @@ typedef struct { typedef struct { uint8_t oda_len; uint8_t oda_pointer; + uint8_t oda_runner_pointer; RDSODA odas[32]; } RDSODAState; diff --git a/src/rds_groups.c b/src/rds_groups.c index c89cfaa..01d915b 100644 --- a/src/rds_groups.c +++ b/src/rds_groups.c @@ -381,4 +381,21 @@ void get_rds_user_oda_group(RDSEncoder* enc, RDSGroup *group) { group->b |= oda.group_version; group->c = oda.id_data; group->d = oda.id; +} +int get_rds_user_oda_group_content(RDSEncoder* enc, RDSGroup *group) { + RDSODAState *oda_state = &enc->state[enc->program].user_oda; + + if (oda_state->oda_len == 0) return 0; + for (uint8_t i = 0; i < oda_state->oda_len; i++) { + uint8_t current_idx = oda_state->oda_runner_pointer; + + oda_state->oda_runner_pointer = (oda_state->oda_runner_pointer + 1) % oda_state->oda_len; + + if (oda_state->odas[current_idx].lua_handler != 0) { + lua_group_ref(group, oda_state->odas[current_idx].lua_handler); + return 1; + } + } + + return 0; } \ No newline at end of file