mirror of
https://github.com/radio95-rnt/rds95.git
synced 2026-02-26 12:32:05 +01:00
massive lua api refactor
This commit is contained in:
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -30,5 +30,8 @@
|
||||
"ffi": "disable",
|
||||
"package": "disable"
|
||||
},
|
||||
"C_Cpp.dimInactiveRegions": false
|
||||
"C_Cpp.dimInactiveRegions": false,
|
||||
"Lua.diagnostics.disable": [
|
||||
"duplicate-set-field"
|
||||
]
|
||||
}
|
||||
196
plugin.lua
196
plugin.lua
@@ -3,48 +3,62 @@
|
||||
-- Global Variables
|
||||
---@type string
|
||||
core_version = ""
|
||||
---@type integer
|
||||
eon_count = 0
|
||||
---@type integer
|
||||
max_programs = 0
|
||||
---@type integer
|
||||
user_data_len = 0
|
||||
|
||||
--#region Functions implemented or used in C
|
||||
|
||||
---Executes a CRC-16 CCIIT
|
||||
dp = {}
|
||||
|
||||
---@type integer
|
||||
dp.max_programs = 0
|
||||
|
||||
---Executes a CRC-16 CCIIT on given data
|
||||
---@param data string
|
||||
---@return integer
|
||||
function crc16(data) end
|
||||
function dp.crc16(data) end
|
||||
|
||||
---Starts the initialization sequence, also calls the on_init function
|
||||
---@return nil
|
||||
function set_rds_program_defaults() end
|
||||
function dp.set_rds_program_defaults() end
|
||||
|
||||
---Saves, loads and resets the state of the data, you might as well restart the whole program
|
||||
---@return nil
|
||||
function reset_rds() end
|
||||
function dp.reset_rds() end
|
||||
|
||||
---Forces encoder and modulator data to be saved to disc
|
||||
---@return nil
|
||||
function force_save() end
|
||||
function dp.force_save() end
|
||||
|
||||
---@param program_idx integer 0 to (max_programs - 1)
|
||||
function dp.set_rds_program(program_idx) end
|
||||
---@return integer
|
||||
function dp.get_rds_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
|
||||
function on_init() end
|
||||
on_inits = {}
|
||||
|
||||
---This function is called by the C core after we initialize the encoder (always, every start)
|
||||
---It should be defined by the user in the script.
|
||||
---@return nil
|
||||
function on_start() end
|
||||
on_starts = {}
|
||||
|
||||
---This function is called every time when the state resets, register your odas here
|
||||
---It should be defined by the user in the script.
|
||||
---@return nil
|
||||
function on_state() end
|
||||
on_states = {}
|
||||
|
||||
---This function is called every second
|
||||
---It should be defined by the user in the script.
|
||||
---@return nil
|
||||
function tick() end
|
||||
ticks = {}
|
||||
|
||||
-- Every function with with the s suffixed table means that other versions of that function can be in that list-table, and each one will be called
|
||||
|
||||
---This function is called in order to handle UDP data
|
||||
---It should be defined by the user in the script.
|
||||
---@param data string
|
||||
@@ -70,72 +84,77 @@ function group(group) end
|
||||
---@return integer d
|
||||
function rds2_group(stream) end
|
||||
|
||||
rds = {}
|
||||
|
||||
---@type integer
|
||||
rds.eon_count = 0
|
||||
|
||||
---@param pi integer
|
||||
function set_rds_pi(pi) end
|
||||
function rds.set_pi(pi) end
|
||||
---@return integer
|
||||
function get_rds_pi() end
|
||||
function rds.get_pi() end
|
||||
|
||||
---@param pty integer
|
||||
function set_rds_pty(pty) end
|
||||
function rds.set_pty(pty) end
|
||||
---@return integer
|
||||
function get_rds_pty() end
|
||||
function rds.get_pty() end
|
||||
|
||||
---@param ecc integer
|
||||
function set_rds_ecc(ecc) end
|
||||
function rds.set_ecc(ecc) end
|
||||
---@return integer
|
||||
function get_rds_ecc() end
|
||||
function rds.get_ecc() end
|
||||
|
||||
---@param slc_data integer
|
||||
function set_rds_slc_data(slc_data) end
|
||||
function rds.set_slc_data(slc_data) end
|
||||
---@return integer
|
||||
function get_rds_slc_data() end
|
||||
function rds.get_slc_data() end
|
||||
|
||||
---@param ct boolean
|
||||
function set_rds_ct(ct) end
|
||||
function rds.set_ct(ct) end
|
||||
---@return boolean
|
||||
function get_rds_ct() end
|
||||
function rds.get_ct() end
|
||||
|
||||
---@param dpty boolean
|
||||
function set_rds_dpty(dpty) end
|
||||
function rds.set_dpty(dpty) end
|
||||
---@return boolean
|
||||
function get_rds_dpty() end
|
||||
function rds.get_dpty() end
|
||||
|
||||
---@param tp boolean
|
||||
function set_rds_tp(tp) end
|
||||
function rds.set_tp(tp) end
|
||||
---@return boolean
|
||||
function get_rds_tp() end
|
||||
function rds.get_tp() end
|
||||
|
||||
---@param ta boolean
|
||||
function set_rds_ta(ta) end
|
||||
function rds.set_ta(ta) end
|
||||
---@return boolean
|
||||
function get_rds_ta() end
|
||||
function rds.get_ta() end
|
||||
|
||||
-- Feature Flags
|
||||
---@param enabled boolean
|
||||
function set_rds_rt1_enabled(enabled) end
|
||||
function rds.set_rt1_enabled(enabled) end
|
||||
---@return boolean
|
||||
function get_rds_rt1_enabled() end
|
||||
function rds.get_rt1_enabled() end
|
||||
|
||||
---@param enabled boolean
|
||||
function set_rds_rt2_enabled(enabled) end
|
||||
function rds.set_rt2_enabled(enabled) end
|
||||
---@return boolean
|
||||
function get_rds_rt2_enabled() end
|
||||
function rds.get_rt2_enabled() end
|
||||
|
||||
---@param enabled boolean
|
||||
function set_rds_ptyn_enabled(enabled) end
|
||||
function rds.set_ptyn_enabled(enabled) end
|
||||
---@return boolean
|
||||
function get_rds_ptyn_enabled() end
|
||||
function rds.get_ptyn_enabled() end
|
||||
|
||||
---@param rt_type integer
|
||||
function set_rds_rt_type(rt_type) end
|
||||
function rds.set_rt_type(rt_type) end
|
||||
---@return integer
|
||||
function get_rds_rt_type() end
|
||||
function rds.get_rt_type() end
|
||||
|
||||
-- Modulation & Generation
|
||||
---@param mode integer
|
||||
function set_rds2_mode(mode) end
|
||||
function rds.set_rds2_mode(mode) end
|
||||
---@return integer
|
||||
function get_rds2_mode() end
|
||||
function rds.get_rds2_mode() end
|
||||
|
||||
---@param streams integer
|
||||
function set_rds_streams(streams) end
|
||||
@@ -152,72 +171,67 @@ function get_rds_level() end
|
||||
|
||||
-- Program & Linking
|
||||
---@param linkage boolean
|
||||
function set_rds_link(linkage) end
|
||||
function rds.set_link(linkage) end
|
||||
---@return boolean
|
||||
function get_rds_link() end
|
||||
|
||||
---@param program_idx integer 0 to (max_programs - 1)
|
||||
function set_rds_program(program_idx) end
|
||||
---@return integer
|
||||
function get_rds_program() end
|
||||
function rds.get_link() end
|
||||
|
||||
-- Timeouts and Periods
|
||||
---@param period integer in seconds
|
||||
function set_rds_rt_switching_period(period) end
|
||||
function rds.set_rt_switching_period(period) end
|
||||
---@return integer
|
||||
function get_rds_rt_switching_period() end
|
||||
function rds.get_rt_switching_period() end
|
||||
|
||||
---For a RT1, this sets the timeout period before setting RT1 into "Default RT" (not literally)
|
||||
---@param timeout integer in seconds
|
||||
function set_rds_rt_text_timeout(timeout) end
|
||||
function rds.set_rt_text_timeout(timeout) end
|
||||
---@return integer
|
||||
function get_rds_rt_text_timeout() end
|
||||
function rds.get_rt_text_timeout() end
|
||||
|
||||
-- String Setters (Charset converted)
|
||||
---@param ptyn string Program Type Name (max 8 chars)
|
||||
function set_rds_ptyn(ptyn) end
|
||||
function rds.set_ptyn(ptyn) end
|
||||
---@param ps string Program Service (8 chars)
|
||||
function set_rds_ps(ps) end
|
||||
function rds.set_ps(ps) end
|
||||
---@param tps string Traffic PS
|
||||
function set_rds_tps(tps) end
|
||||
function rds.set_tps(tps) end
|
||||
---@param rt1 string Radio Text 1 (max 64 chars)
|
||||
function set_rds_rt1(rt1) end
|
||||
function rds.set_rt1(rt1) end
|
||||
---@param rt2 string Radio Text 2 (max 64 chars)
|
||||
function set_rds_rt2(rt2) end
|
||||
function rds.set_rt2(rt2) end
|
||||
---@param rt string Default radio text - max 64 characters
|
||||
function set_rds_default_rt(rt) end
|
||||
function rds.set_default_rt(rt) end
|
||||
|
||||
---@param lps string
|
||||
function set_rds_lps(lps) end
|
||||
function rds.set_lps(lps) end
|
||||
---@return string
|
||||
function get_rds_lps() end
|
||||
function rds.get_lps() end
|
||||
|
||||
---@param grpseq string
|
||||
function set_rds_grpseq(grpseq) end
|
||||
function rds.set_grpseq(grpseq) end
|
||||
---@return string
|
||||
function get_rds_grpseq() end
|
||||
function rds.get_grpseq() end
|
||||
|
||||
---@param grpseq2 string
|
||||
function set_rds_grpseq2(grpseq2) end
|
||||
function rds.set_grpseq2(grpseq2) end
|
||||
---@return string
|
||||
function get_rds_grpseq2() end
|
||||
function rds.get_grpseq2() end
|
||||
|
||||
---Puts in a RDS1 group in the buffer, note that block A is filled in always
|
||||
---@param b integer
|
||||
---@param c integer
|
||||
---@param d integer
|
||||
function put_rds_custom_group(b, c, d) end
|
||||
function rds.put_custom_group(b, c, d) end
|
||||
|
||||
---Puts in a RDS2 group in the buffer
|
||||
---@param a integer
|
||||
---@param b integer
|
||||
---@param c integer
|
||||
---@param d integer
|
||||
function put_rds2_custom_group(a, b, c, d) end
|
||||
function rds.put_rds2_custom_group(a, b, c, d) end
|
||||
|
||||
---Sets the AFs included in group 0
|
||||
---@param afs table
|
||||
function set_rds_af_group0(afs) end
|
||||
function rds.set_af(afs) end
|
||||
|
||||
---Sets data about the EON
|
||||
---@param eon integer Index of the EON we are setting
|
||||
@@ -229,7 +243,7 @@ function set_rds_af_group0(afs) end
|
||||
---@param ps string
|
||||
---@param afs table
|
||||
---@param data integer
|
||||
function set_rds_eon(eon, enabled, pi, tp, ta, pty, ps, afs, data) end
|
||||
function rds.set_eon(eon, enabled, pi, tp, ta, pty, ps, afs, data) end
|
||||
|
||||
---Gets the same data set_rds_eon sets, yes this returns 8 arguments
|
||||
---@param eon integer
|
||||
@@ -241,37 +255,45 @@ function set_rds_eon(eon, enabled, pi, tp, ta, pty, ps, afs, data) end
|
||||
---@return string ps
|
||||
---@return table _ this is empty, getting afs is not supported yet
|
||||
---@return integer data
|
||||
function get_rds_eon(eon) end
|
||||
function rds.get_eon(eon) end
|
||||
|
||||
---Sets the X/Y of the UDG
|
||||
---@param xy boolean
|
||||
---@param groups table Table of tables, this should be up to 8 tables containing 3 integers
|
||||
function set_rds_udg(xy, groups) end
|
||||
function rds.set_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
|
||||
function rds.set_udg2(xy, groups) end
|
||||
|
||||
userdata = {}
|
||||
|
||||
---@type integer
|
||||
userdata.len = 0
|
||||
|
||||
---Data is allocated in each program's data for lua data (per program, diffrent program, diffrent data), note that this overwrites existing data over the whole userdata string
|
||||
---@param data string
|
||||
function set_userdata(data) end
|
||||
function userdata.set(data) end
|
||||
---Writes to the userdata at the offset, size does not have to match the length of the string, if the string is less than size then the rest of the string will be padded with zeroes until it is size
|
||||
---@param offset integer
|
||||
---@param size integer
|
||||
---@param data string
|
||||
function set_userdata_offset(offset, size, data) end
|
||||
function userdata.set_offset(offset, size, data) end
|
||||
|
||||
---Returns all of the data saved as user data
|
||||
---@return string
|
||||
function get_userdata() end
|
||||
function userdata.get() end
|
||||
---Gets data from userdata but at the specified offset
|
||||
---@param offset integer
|
||||
---@param size integer
|
||||
---@return string
|
||||
function get_userdata_offset(offset, size) end
|
||||
function userdata.get_offset(offset, size) end
|
||||
|
||||
--#endregion
|
||||
|
||||
ext = {}
|
||||
rds.ext = {}
|
||||
|
||||
-- RT Plus Tags
|
||||
---Sets RT+ tags: type1, start1, len1, type2, start2, len2
|
||||
---@param ertp boolean
|
||||
@@ -281,29 +303,29 @@ function get_userdata_offset(offset, size) end
|
||||
---@param t2 integer
|
||||
---@param s2 integer
|
||||
---@param l2 integer
|
||||
function set_rds_rtplus_tags(ertp, t1, s1, l1, t2, s2, l2) end
|
||||
function rds.ext.set_rtplus_tags(ertp, t1, s1, l1, t2, s2, l2) end
|
||||
|
||||
---Gets RT+ tags: type1, start1, len1, type2, start2, len2
|
||||
---@param ertp boolean
|
||||
---@return integer type1, integer start1, integer len1, integer type2, integer start2, integer len2
|
||||
function get_rds_rtplus_tags(ertp) end
|
||||
function rds.ext.get_rtplus_tags(ertp) end
|
||||
|
||||
---Toggles RTP or ERTP's toggle switch
|
||||
---@param ertp boolean
|
||||
function toggle_rds_rtp(ertp) end
|
||||
function rds.ext.toggle_rtp(ertp) end
|
||||
|
||||
---Sets the metadata of RTP or ERTP
|
||||
---@param ertp boolean
|
||||
---@param running boolean
|
||||
function set_rds_rtp_meta(ertp, running) end
|
||||
function rds.ext.set_rtp_meta(ertp, running) end
|
||||
---Gets the metadata of RTP and ERTP
|
||||
---@param ertp boolean
|
||||
---@return boolean running
|
||||
function get_rds_rtp_meta(ertp) end
|
||||
function rds.ext.get_rtp_meta(ertp) end
|
||||
|
||||
---Sets the AFs included in the ODA
|
||||
---@param afs table
|
||||
function set_rds_af_oda(afs) end
|
||||
function rds.ext.set_af_oda(afs) 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
|
||||
---Groups 14, 15, 2, 0 cannot be registered either version, groups 10, 4, 1 can be only registered as B, any other is free to take
|
||||
@@ -313,16 +335,16 @@ function set_rds_af_oda(afs) end
|
||||
---@param aid integer
|
||||
---@param data integer
|
||||
---@return integer oda_id
|
||||
function register_oda(group, group_version, aid, data) end
|
||||
function ext.register_oda(group, group_version, aid, data) end
|
||||
|
||||
---Unregisters an ODA, this stops the handler or AID being called/sent
|
||||
---@param oda_id integer
|
||||
function unregister_oda(oda_id) end
|
||||
function ext.unregister_oda(oda_id) end
|
||||
|
||||
---Sets the data for a existing ODA group
|
||||
---@param oda_id integer
|
||||
---@param data integer
|
||||
function set_oda_id_data(oda_id, data) end
|
||||
function ext.set_oda_id_data(oda_id, data) end
|
||||
|
||||
---The callback function for an ODA handler
|
||||
---@alias ODAHandler fun(): (boolean, integer, integer, integer)
|
||||
@@ -334,7 +356,7 @@ function set_oda_id_data(oda_id, data) end
|
||||
---You are asked to set groups B last 5 bits, leave rest 0
|
||||
---@param oda_id integer The ID returned by register_oda
|
||||
---@param fun ODAHandler
|
||||
function set_oda_handler(oda_id, fun) end
|
||||
function ext.set_oda_handler(oda_id, fun) end
|
||||
|
||||
---The callback function for an ODA handler
|
||||
---@alias RDS2_ODAHandler fun(integer): (boolean, integer, integer, integer, integer)
|
||||
@@ -342,23 +364,23 @@ function set_oda_handler(oda_id, fun) end
|
||||
---You are asked to not fill in the channel id in block A, however you are asked to fill in the function number (if you do not know what is that, just OR block A with (1 << 14))
|
||||
---@param oda_id integer
|
||||
---@param func RDS2_ODAHandler
|
||||
function set_oda_handler_rds2(oda_id, func) end
|
||||
function ext.set_oda_handler_rds2(oda_id, func) end
|
||||
|
||||
---@param oda_id integer
|
||||
---@param data integer
|
||||
function set_oda_id_data_rds2(oda_id, data) end
|
||||
function ext.set_oda_id_data_rds2(oda_id, data) end
|
||||
|
||||
---@param aid integer
|
||||
---@param data integer
|
||||
---@param file_related boolean
|
||||
---@return integer oda_id
|
||||
function register_oda_rds2(aid, data, file_related) end
|
||||
function ext.register_oda_rds2(aid, data, file_related) end
|
||||
|
||||
---Unregisters an RDS 2 ODA, this stops the handler or AID being called/sent
|
||||
---@param oda_id integer
|
||||
function unregister_oda_rds2(oda_id) end
|
||||
function ext.unregister_oda_rds2(oda_id) end
|
||||
|
||||
---@param ert string
|
||||
function set_rds_ert(ert) end
|
||||
function rds.ext.set_ert(ert) end
|
||||
---@return string
|
||||
function get_rds_ert() end
|
||||
function rds.ext.get_ert() end
|
||||
@@ -17,7 +17,7 @@ local _RDS_ODA_pointer = 1
|
||||
---@param aid integer
|
||||
---@param data integer
|
||||
---@return integer oda_id
|
||||
function register_oda(group, group_version, aid, data)
|
||||
function ext.register_oda(group, group_version, aid, data)
|
||||
if group == 14 or group == 15 or group == 2 or group == 0 then error("Group is incorrect", 2) end
|
||||
if (group == 10 or group == 4 or group == 1) and group_version then error("Group is incorrect", 2) end
|
||||
local oda = _ODA.new(group, group_version, aid, data, false)
|
||||
@@ -33,7 +33,7 @@ end
|
||||
|
||||
---Unregisters an ODA, this stops the handler or AID being called/sent
|
||||
---@param oda_id integer
|
||||
function unregister_oda(oda_id)
|
||||
function ext.unregister_oda(oda_id)
|
||||
if oda_id < 1 or oda_id > #_RDS_ODAs or _RDS_ODAs[oda_id] == false then error("Invalid ODA ID: " .. tostring(oda_id), 2) end
|
||||
|
||||
_RDS_ODAs[oda_id] = false
|
||||
@@ -45,7 +45,7 @@ end
|
||||
---Sets the id_data for a existing ODA group
|
||||
---@param oda_id integer
|
||||
---@param data integer
|
||||
function set_oda_id_data(oda_id, data)
|
||||
function ext.set_oda_id_data(oda_id, data)
|
||||
if oda_id < 1 or oda_id > #_RDS_ODAs or _RDS_ODAs[oda_id] == false then error("Invalid ODA ID: " .. tostring(oda_id), 2) end
|
||||
_RDS_ODAs[oda_id].data = data
|
||||
end
|
||||
@@ -57,7 +57,7 @@ end
|
||||
---You are asked to set groups B last 5 bits, leave rest 0
|
||||
---@param oda_id integer The ID returned by register_oda
|
||||
---@param fun ODAHandler
|
||||
function set_oda_handler(oda_id, fun)
|
||||
function ext.set_oda_handler(oda_id, fun)
|
||||
if oda_id < 1 or oda_id > #_RDS_ODAs or _RDS_ODAs[oda_id] == false then error("Invalid ODA ID: " .. tostring(oda_id), 2) end
|
||||
if _RDS_ODAs[oda_id].group == 3 then error("3A ODAs cannot have handlers.", 2) end
|
||||
_RDS_ODAs[oda_id].handler = fun
|
||||
@@ -113,18 +113,13 @@ function group(group_type)
|
||||
if #_RDS_ODAs == 0 then return false, 0, 0, 0 end
|
||||
if _RDS_ODA_pointer > #_RDS_ODAs or _RDS_ODA_pointer < 1 then _RDS_ODA_pointer = 1 end
|
||||
|
||||
if group_type == "O" then
|
||||
return get_aid()
|
||||
elseif group_type == "K" then
|
||||
return get_data()
|
||||
end
|
||||
if group_type == "O" then return get_aid()
|
||||
elseif group_type == "K" then return get_data() end
|
||||
end
|
||||
return false, 0, 0, 0
|
||||
end
|
||||
|
||||
local _old_on_state_oda = on_state
|
||||
function on_state()
|
||||
table.insert(on_states, function ()
|
||||
_RDS_ODAs = {}
|
||||
_RDS_ODA_pointer = 1
|
||||
if type(_old_on_state_oda) == "function" then _old_on_state_oda() end
|
||||
end
|
||||
end)
|
||||
@@ -14,7 +14,7 @@ _RDS2_ODA_pointer = 1
|
||||
---@param data integer
|
||||
---@param file_related boolean
|
||||
---@return integer oda_id
|
||||
function register_oda_rds2(aid, data, file_related)
|
||||
function ext.register_oda_rds2(aid, data, file_related)
|
||||
local oda = _RDS2_ODA.new(aid, data, false, file_related)
|
||||
for i = 1, #_RDS2_ODAs do
|
||||
if _RDS2_ODAs[i] == false then
|
||||
@@ -28,7 +28,7 @@ end
|
||||
|
||||
---Unregisters an RDS 2 ODA, this stops the handler or AID being called/sent
|
||||
---@param oda_id integer
|
||||
function unregister_oda_rds2(oda_id)
|
||||
function ext.unregister_oda_rds2(oda_id)
|
||||
if oda_id < 1 or oda_id > #_RDS2_ODAs or _RDS2_ODAs[oda_id] == false then error("Invalid ODA ID: " .. tostring(oda_id), 2) end
|
||||
|
||||
_RDS2_ODAs[oda_id] = false
|
||||
@@ -39,14 +39,14 @@ end
|
||||
|
||||
---@param oda_id integer
|
||||
---@param data integer
|
||||
function set_oda_id_data_rds2(oda_id, data)
|
||||
function ext.set_oda_id_data_rds2(oda_id, data)
|
||||
if oda_id < 1 or oda_id > #_RDS2_ODAs or _RDS2_ODAs[oda_id] == false then error("Invalid ODA ID: " .. tostring(oda_id), 2) end
|
||||
_RDS2_ODAs[oda_id].data = data
|
||||
end
|
||||
|
||||
---@param oda_id integer
|
||||
---@param func RDS2_ODAHandler
|
||||
function set_oda_handler_rds2(oda_id, func)
|
||||
function ext.set_oda_handler_rds2(oda_id, func)
|
||||
if oda_id < 1 or oda_id > #_RDS2_ODAs or _RDS2_ODAs[oda_id] == false then error("Invalid ODA ID: " .. tostring(oda_id), 2) end
|
||||
_RDS2_ODAs[oda_id].handler = func
|
||||
end
|
||||
@@ -125,10 +125,8 @@ function rds2_group(stream)
|
||||
end
|
||||
end
|
||||
|
||||
local _old_on_state_oda_rds2 = on_state
|
||||
function on_state()
|
||||
table.insert(on_states, function ()
|
||||
_RDS2_ODAs = {}
|
||||
_RDS2_ODA_aid = 0
|
||||
_RDS2_ODA_pointer = 1
|
||||
if type(_old_on_state_oda_rds2) == "function" then _old_on_state_oda_rds2() end
|
||||
end
|
||||
end)
|
||||
@@ -55,8 +55,8 @@ end
|
||||
|
||||
local function init_af_oda()
|
||||
if _Af_Oda_id == nil then
|
||||
_Af_Oda_id = register_oda(7, false, 0x6365, 0)
|
||||
set_oda_handler(_Af_Oda_id, function()
|
||||
_Af_Oda_id = ext.register_oda(7, false, 0x6365, 0)
|
||||
ext.set_oda_handler(_Af_Oda_id, function()
|
||||
local b, c, d = get_next_af_oda_group()
|
||||
return true, b, c, d
|
||||
end)
|
||||
@@ -69,7 +69,7 @@ local function save_af_to_userdata(afs)
|
||||
|
||||
local payload = string.pack("B", count)
|
||||
for i = 1, count do payload = payload .. string.pack("f", afs[i]) end
|
||||
set_userdata_offset(USERDATA_ODA_OFFSET, #payload, payload)
|
||||
userdata.set_offset(USERDATA_ODA_OFFSET, #payload, payload)
|
||||
end
|
||||
|
||||
local function _process_af_list(afs)
|
||||
@@ -86,13 +86,13 @@ local function _process_af_list(afs)
|
||||
end
|
||||
|
||||
local function load_af_from_userdata()
|
||||
local header = get_userdata_offset(USERDATA_ODA_OFFSET, 1)
|
||||
local header = userdata.get_offset(USERDATA_ODA_OFFSET, 1)
|
||||
if header == "" or header == nil then return end
|
||||
|
||||
local count = string.unpack("B", header)
|
||||
if count == 0 or count > 25 then return end
|
||||
|
||||
local data = get_userdata_offset(USERDATA_ODA_OFFSET + 1, count * 4)
|
||||
local data = userdata.get_offset(USERDATA_ODA_OFFSET + 1, count * 4)
|
||||
if #data < (count * 4) then return end
|
||||
|
||||
local afs = {}
|
||||
@@ -106,14 +106,12 @@ end
|
||||
|
||||
---Sets the AFs included in the ODA and saves them
|
||||
---@param afs table List of numbers (e.g., {98.1, 102.5})
|
||||
function set_rds_af_oda(afs)
|
||||
function rds.ext.set_af_oda(afs)
|
||||
_process_af_list(afs)
|
||||
save_af_to_userdata(afs)
|
||||
end
|
||||
|
||||
local _old_on_state_af = on_state
|
||||
function on_state()
|
||||
table.insert(on_states, function ()
|
||||
load_af_from_userdata()
|
||||
if _Af_Oda_len ~= 0 then init_af_oda() end
|
||||
if type(_old_on_state_af) == "function" then _old_on_state_af() end
|
||||
end
|
||||
end)
|
||||
@@ -6,25 +6,25 @@ local USERDATA_ERT_OFFSET = 0
|
||||
|
||||
local function init_ert()
|
||||
if _Ert_oda_id == nil then
|
||||
_Ert_oda_id = register_oda(13, false, 0x6552, 1)
|
||||
set_oda_handler(_Ert_oda_id, function ()
|
||||
if string.byte(get_userdata_offset(USERDATA_ERT_OFFSET+258, 1)) == 1 then
|
||||
local new_data = get_userdata_offset(USERDATA_ERT_OFFSET, 128)
|
||||
local new_segments = string.byte(get_userdata_offset(USERDATA_ERT_OFFSET+128, 1))
|
||||
set_userdata_offset(USERDATA_ERT_OFFSET+129, 128, new_data)
|
||||
set_userdata_offset(USERDATA_ERT_OFFSET+257, 1, string.char(new_segments))
|
||||
set_userdata_offset(USERDATA_ERT_OFFSET+258, 1, string.char(0))
|
||||
_Ert_oda_id = ext.register_oda(13, false, 0x6552, 1)
|
||||
ext.set_oda_handler(_Ert_oda_id, function ()
|
||||
if string.byte(userdata.get_offset(USERDATA_ERT_OFFSET+258, 1)) == 1 then
|
||||
local new_data = userdata.get_offset(USERDATA_ERT_OFFSET, 128)
|
||||
local new_segments = string.byte(userdata.get_offset(USERDATA_ERT_OFFSET+128, 1))
|
||||
userdata.set_offset(USERDATA_ERT_OFFSET+129, 128, new_data)
|
||||
userdata.set_offset(USERDATA_ERT_OFFSET+257, 1, string.char(new_segments))
|
||||
userdata.set_offset(USERDATA_ERT_OFFSET+258, 1, string.char(0))
|
||||
_Ert_state = 0
|
||||
end
|
||||
|
||||
local segments = string.byte(get_userdata_offset(USERDATA_ERT_OFFSET+257, 1))
|
||||
local segments = string.byte(userdata.get_offset(USERDATA_ERT_OFFSET+257, 1))
|
||||
|
||||
if segments == 0 then return false, 0, 0, 0 end
|
||||
|
||||
if _Ert_state >= segments then _Ert_state = 0 end
|
||||
|
||||
local b = _Ert_state & 31
|
||||
local chunk = get_userdata_offset(USERDATA_ERT_OFFSET + 129 + _Ert_state * 4, 4)
|
||||
local chunk = userdata.get_offset(USERDATA_ERT_OFFSET + 129 + _Ert_state * 4, 4)
|
||||
local c = (string.byte(chunk, 1) << 8) | string.byte(chunk, 2)
|
||||
local d = (string.byte(chunk, 3) << 8) | string.byte(chunk, 4)
|
||||
|
||||
@@ -36,16 +36,16 @@ end
|
||||
|
||||
function unregister_ert()
|
||||
if _Ert_oda_id ~= nil then
|
||||
unregister_oda(_Ert_oda_id)
|
||||
ext.unregister_oda(_Ert_oda_id)
|
||||
_Ert_oda_id = nil
|
||||
end
|
||||
end
|
||||
|
||||
function set_rds_ert(ert)
|
||||
function rds.ext.set_ert(ert)
|
||||
if #ert == 0 then
|
||||
set_userdata_offset(USERDATA_ERT_OFFSET, 128, "")
|
||||
set_userdata_offset(USERDATA_ERT_OFFSET+128, 1, string.char(0))
|
||||
set_userdata_offset(USERDATA_ERT_OFFSET+258, 1, string.char(1))
|
||||
userdata.set_offset(USERDATA_ERT_OFFSET, 128, "")
|
||||
userdata.set_offset(USERDATA_ERT_OFFSET+128, 1, string.char(0))
|
||||
userdata.set_offset(USERDATA_ERT_OFFSET+258, 1, string.char(1))
|
||||
return
|
||||
end
|
||||
|
||||
@@ -55,33 +55,31 @@ function set_rds_ert(ert)
|
||||
local padding = (4 - (#data % 4)) % 4
|
||||
data = data .. string.rep("\0", padding)
|
||||
|
||||
set_userdata_offset(USERDATA_ERT_OFFSET, 128, data)
|
||||
userdata.set_offset(USERDATA_ERT_OFFSET, 128, data)
|
||||
|
||||
local segments = #data // 4
|
||||
if segments > 32 then segments = 32 end
|
||||
|
||||
set_userdata_offset(USERDATA_ERT_OFFSET+128, 1, string.char(segments))
|
||||
userdata.set_offset(USERDATA_ERT_OFFSET+128, 1, string.char(segments))
|
||||
|
||||
if string.byte(get_userdata_offset(USERDATA_ERT_OFFSET+257, 1)) == 0 then
|
||||
if string.byte(userdata.get_offset(USERDATA_ERT_OFFSET+257, 1)) == 0 then
|
||||
init_ert()
|
||||
set_userdata_offset(USERDATA_ERT_OFFSET+129, 128, data)
|
||||
set_userdata_offset(USERDATA_ERT_OFFSET+257, 1, string.char(segments))
|
||||
userdata.set_offset(USERDATA_ERT_OFFSET+129, 128, data)
|
||||
userdata.set_offset(USERDATA_ERT_OFFSET+257, 1, string.char(segments))
|
||||
_Ert_state = 0
|
||||
else set_userdata_offset(USERDATA_ERT_OFFSET+258, 1, string.char(1)) end
|
||||
else userdata.set_offset(USERDATA_ERT_OFFSET+258, 1, string.char(1)) end
|
||||
|
||||
if _Ert_oda_id == nil then init_ert() end
|
||||
end
|
||||
|
||||
function get_rds_ert()
|
||||
local segments = string.byte(get_userdata_offset(USERDATA_ERT_OFFSET+128, 1))
|
||||
function rds.ext.get_ert()
|
||||
local segments = string.byte(userdata.get_offset(USERDATA_ERT_OFFSET+128, 1))
|
||||
if segments == 0 then return "" end
|
||||
|
||||
local data = get_userdata_offset(USERDATA_ERT_OFFSET, 128)
|
||||
local data = userdata.get_offset(USERDATA_ERT_OFFSET, 128)
|
||||
return data:match("^(.-)[\r%z]*") or ""
|
||||
end
|
||||
|
||||
local _old_on_state_ert = on_state
|
||||
function on_state()
|
||||
if string.byte(get_userdata_offset(USERDATA_ERT_OFFSET+257, 1)) ~= 0 then init_ert() end
|
||||
if type(_old_on_state_ert) == "function" then _old_on_state_ert() end
|
||||
end
|
||||
table.insert(on_states, function ()
|
||||
if string.byte(userdata.get_offset(USERDATA_ERT_OFFSET+257, 1)) ~= 0 then init_ert() end
|
||||
end)
|
||||
@@ -43,7 +43,7 @@ end
|
||||
|
||||
function RftInstance:stop()
|
||||
if self.oda_id ~= nil and self.aid ~= 0 then
|
||||
unregister_oda_rds2(self.oda_id)
|
||||
ext.unregister_oda_rds2(self.oda_id)
|
||||
self.oda_id = nil
|
||||
end
|
||||
|
||||
@@ -59,9 +59,9 @@ end
|
||||
---@private
|
||||
function RftInstance:start()
|
||||
if self.oda_id == nil and self.aid ~= 0 then
|
||||
self.oda_id = register_oda_rds2(self.aid, 0, true)
|
||||
self.oda_id = ext.register_oda_rds2(self.aid, 0, true)
|
||||
|
||||
set_oda_handler_rds2(self.oda_id, function(stream)
|
||||
ext.set_oda_handler_rds2(self.oda_id, function(stream)
|
||||
if #self.file_data == 0 or self.paused then
|
||||
return false, 0, 0, 0, 0
|
||||
end
|
||||
@@ -138,7 +138,7 @@ function RftInstance:sendFile(aid, path, id, crc, once)
|
||||
local f_size = #self.file_data
|
||||
if crc == 0 then
|
||||
self.crc_mode = 0
|
||||
self.crc_full_file = crc16(self.file_data)
|
||||
self.crc_full_file = dp.crc16(self.file_data)
|
||||
elseif crc == true or crc == 7 then
|
||||
if f_size <= 40960 then self.crc_mode = 1
|
||||
elseif f_size > 40960 and f_size <= 81920 then self.crc_mode = 2
|
||||
@@ -153,7 +153,7 @@ function RftInstance:sendFile(aid, path, id, crc, once)
|
||||
local chunk_size = 5 * multiplier
|
||||
for i = 1, f_size, chunk_size do
|
||||
local chunk = string.sub(self.file_data, i, i + chunk_size - 1)
|
||||
local v = crc16(chunk)
|
||||
local v = dp.crc16(chunk)
|
||||
self.crc_data = self.crc_data .. string.char(v >> 8, v & 0xff)
|
||||
end
|
||||
end
|
||||
@@ -161,7 +161,7 @@ function RftInstance:sendFile(aid, path, id, crc, once)
|
||||
if f_size > (0x3ffff * 5) then error("File too large") end
|
||||
if self.oda_id == nil then self:start() end
|
||||
|
||||
set_oda_id_data_rds2(self.oda_id, f_size | (id & 63) << 18 | (self.version & 7) << 24 | (self.crc_enabled and 1 or 0) << 27)
|
||||
ext.set_oda_id_data_rds2(self.oda_id, f_size | (id & 63) << 18 | (self.version & 7) << 24 | (self.crc_enabled and 1 or 0) << 27)
|
||||
self.last_id = id
|
||||
self.paused = false
|
||||
return interrupted
|
||||
|
||||
@@ -8,11 +8,11 @@ local USERDATA_RTP_OFFSET = 259
|
||||
|
||||
local function init_rtp()
|
||||
if _Rtp_oda_id == nil then
|
||||
_Rtp_oda_id = register_oda(11, false, 0x4BD7, 0)
|
||||
set_oda_handler(_Rtp_oda_id, function ()
|
||||
local b = (_Rtp_toggle and 1 or 0) << 4 | string.byte(get_userdata_offset(USERDATA_RTP_OFFSET, 1)) << 3
|
||||
local data_0 = get_userdata_offset(USERDATA_RTP_OFFSET+1, 3)
|
||||
local data_1 = get_userdata_offset(USERDATA_RTP_OFFSET+4, 3)
|
||||
_Rtp_oda_id = ext.register_oda(11, false, 0x4BD7, 0)
|
||||
ext.set_oda_handler(_Rtp_oda_id, function ()
|
||||
local b = (_Rtp_toggle and 1 or 0) << 4 | string.byte(userdata.get_offset(USERDATA_RTP_OFFSET, 1)) << 3
|
||||
local data_0 = userdata.get_offset(USERDATA_RTP_OFFSET+1, 3)
|
||||
local data_1 = userdata.get_offset(USERDATA_RTP_OFFSET+4, 3)
|
||||
b = b | (string.byte(data_0, 1) & 0xf8) >> 3
|
||||
|
||||
local c = (string.byte(data_0, 1) & 0x7) << 13
|
||||
@@ -31,11 +31,11 @@ end
|
||||
|
||||
local function init_ertp()
|
||||
if _Ertp_oda_id == nil then
|
||||
_Ertp_oda_id = register_oda(12, false, 0x4BD8, 0)
|
||||
set_oda_handler(_Ertp_oda_id, function ()
|
||||
local b = (_Ertp_toggle and 1 or 0) << 4 | string.byte(get_userdata_offset(USERDATA_RTP_OFFSET+7, 1)) << 3
|
||||
local data_0 = get_userdata_offset(USERDATA_RTP_OFFSET+8, 3)
|
||||
local data_1 = get_userdata_offset(USERDATA_RTP_OFFSET+11, 3)
|
||||
_Ertp_oda_id = ext.register_oda(12, false, 0x4BD8, 0)
|
||||
ext.set_oda_handler(_Ertp_oda_id, function ()
|
||||
local b = (_Ertp_toggle and 1 or 0) << 4 | string.byte(userdata.get_offset(USERDATA_RTP_OFFSET+7, 1)) << 3
|
||||
local data_0 = userdata.get_offset(USERDATA_RTP_OFFSET+8, 3)
|
||||
local data_1 = userdata.get_offset(USERDATA_RTP_OFFSET+11, 3)
|
||||
b = b | (string.byte(data_0, 1) & 0xf8) >> 3
|
||||
|
||||
local c = (string.byte(data_0, 1) & 0x7) << 13
|
||||
@@ -52,46 +52,44 @@ local function init_ertp()
|
||||
end
|
||||
end
|
||||
|
||||
function set_rds_rtp_meta(ertp, running)
|
||||
function rds.ext.set_rtp_meta(ertp, running)
|
||||
if ertp then
|
||||
if running and _Ertp_oda_id == nil then init_ertp() end
|
||||
set_userdata_offset(USERDATA_RTP_OFFSET+7, 1, string.char(running and 1 or 0))
|
||||
userdata.set_offset(USERDATA_RTP_OFFSET+7, 1, string.char(running and 1 or 0))
|
||||
else
|
||||
if running and _Rtp_oda_id == nil then init_rtp() end
|
||||
set_userdata_offset(USERDATA_RTP_OFFSET, 1, string.char(running and 1 or 0))
|
||||
userdata.set_offset(USERDATA_RTP_OFFSET, 1, string.char(running and 1 or 0))
|
||||
end
|
||||
end
|
||||
function get_rds_rtp_meta(ertp)
|
||||
function rds.ext.get_rtp_meta(ertp)
|
||||
local offset = ertp and (USERDATA_RTP_OFFSET+7) or USERDATA_RTP_OFFSET
|
||||
return string.byte(get_userdata_offset(offset, 1)) ~= 0
|
||||
return string.byte(userdata.get_offset(offset, 1)) ~= 0
|
||||
end
|
||||
function toggle_rds_rtp(ertp)
|
||||
function rds.ext.toggle_rtp(ertp)
|
||||
if ertp then _Ertp_toggle = not _Ertp_toggle
|
||||
else _Rtp_toggle = not _Rtp_toggle end
|
||||
end
|
||||
|
||||
function set_rds_rtplus_tags(ertp, t1, s1, l1, t2, s2, l2)
|
||||
set_rds_rtp_meta(ertp, true)
|
||||
toggle_rds_rtp(ertp)
|
||||
set_userdata_offset(ertp and (USERDATA_RTP_OFFSET+8) or (USERDATA_RTP_OFFSET+1), 6, string.char(t1, s1, l1, t2, s2, l2))
|
||||
function rds.ext.set_rtplus_tags(ertp, t1, s1, l1, t2, s2, l2)
|
||||
rds.ext.set_rds_rtp_meta(ertp, true)
|
||||
rds.ext.toggle_rds_rtp(ertp)
|
||||
userdata.set_offset(ertp and (USERDATA_RTP_OFFSET+8) or (USERDATA_RTP_OFFSET+1), 6, string.char(t1, s1, l1, t2, s2, l2))
|
||||
end
|
||||
function get_rds_rtplus_tags(ertp)
|
||||
return string.byte(get_userdata_offset(ertp and (USERDATA_RTP_OFFSET+8) or (USERDATA_RTP_OFFSET+1), 6), 1, 6)
|
||||
function rds.ext.get_rtplus_tags(ertp)
|
||||
return string.byte(userdata.get_offset(ertp and (USERDATA_RTP_OFFSET+8) or (USERDATA_RTP_OFFSET+1), 6), 1, 6)
|
||||
end
|
||||
|
||||
function unregister_rtp(ertp)
|
||||
if ertp and _Ertp_oda_id ~= nil then
|
||||
unregister_oda(_Ertp_oda_id)
|
||||
ext.unregister_oda(_Ertp_oda_id)
|
||||
_Ertp_oda_id = nil
|
||||
elseif _Rtp_oda_id ~= nil then
|
||||
unregister_oda(_Rtp_oda_id)
|
||||
ext.unregister_oda(_Rtp_oda_id)
|
||||
_Rtp_oda_id = nil
|
||||
end
|
||||
end
|
||||
|
||||
local _old_on_state_rtp = on_state
|
||||
function on_state()
|
||||
if get_rds_rtp_meta(false) then init_rtp() end
|
||||
if get_rds_rtp_meta(true) then init_ertp() end
|
||||
if type(_old_on_state_rtp) == "function" then _old_on_state_rtp() end
|
||||
end
|
||||
table.insert(on_states, function ()
|
||||
if rds.ext.get_rtp_meta(false) then init_rtp() end
|
||||
if rds.ext.get_rtp_meta(true) then init_ertp() end
|
||||
end)
|
||||
@@ -40,52 +40,52 @@ function data_handle(data)
|
||||
data = data:lower()
|
||||
if data == "ver" then return string.format("rds95 core v. %s - (C) 2025 radio95 - lua parser\r\n", core_version)
|
||||
elseif data == "init" then
|
||||
set_rds_program_defaults()
|
||||
dp.set_rds_program_defaults()
|
||||
return "+\r\n"
|
||||
elseif data == "reset" then
|
||||
reset_rds()
|
||||
dp.reset_rds()
|
||||
return "+\r\n"
|
||||
elseif data == "pi" then return string.format("PI=%s\r\n", string.format("%x", get_rds_pi()))
|
||||
elseif data == "pty" then return string.format("PTY=%s\r\n", string.format("%d", get_rds_pty()))
|
||||
elseif data == "ecc" then return string.format("ECC=%s\r\n", string.format("%x", get_rds_ecc()))
|
||||
elseif data == "slcd" then return string.format("SLCD=%s\r\n", string.format("%x", get_rds_slc_data()))
|
||||
elseif data == "ct" then return string.format("CT=%s\r\n", string.format("%d", (get_rds_ct() and 1 or 0)))
|
||||
elseif data == "dpty" then return string.format("DPTY=%s\r\n", string.format("%d", (get_rds_dpty() and 1 or 0)))
|
||||
elseif data == "tp" then return string.format("TP=%s\r\n", string.format("%d", (get_rds_tp() and 1 or 0)))
|
||||
elseif data == "ta" then return string.format("TA=%s\r\n", string.format("%d", (get_rds_ta() and 1 or 0)))
|
||||
elseif data == "rt1en" then return string.format("RT1EN=%s\r\n", string.format("%d", (get_rds_rt1_enabled() and 1 or 0)))
|
||||
elseif data == "rt2en" then return string.format("RT2EN=%s\r\n", string.format("%d", (get_rds_rt2_enabled() and 1 or 0)))
|
||||
elseif data == "ptynen" then return string.format("PTYNEN=%s\r\n", string.format("%d", (get_rds_ptyn_enabled() and 1 or 0)))
|
||||
elseif data == "rttype" then return string.format("RTTYPE=%s\r\n", string.format("%d", get_rds_rt_type()))
|
||||
elseif data == "rds2mod" then return string.format("RDS2MOD=%s\r\n", string.format("%d", get_rds2_mode()))
|
||||
elseif data == "pi" then return string.format("PI=%s\r\n", string.format("%x", rds.get_pi()))
|
||||
elseif data == "pty" then return string.format("PTY=%s\r\n", string.format("%d", rds.get_pty()))
|
||||
elseif data == "ecc" then return string.format("ECC=%s\r\n", string.format("%x", rds.get_ecc()))
|
||||
elseif data == "slcd" then return string.format("SLCD=%s\r\n", string.format("%x", rds.get_slc_data()))
|
||||
elseif data == "ct" then return string.format("CT=%s\r\n", string.format("%d", (rds.get_ct() and 1 or 0)))
|
||||
elseif data == "dpty" then return string.format("DPTY=%s\r\n", string.format("%d", (rds.get_dpty() and 1 or 0)))
|
||||
elseif data == "tp" then return string.format("TP=%s\r\n", string.format("%d", (rds.get_tp() and 1 or 0)))
|
||||
elseif data == "ta" then return string.format("TA=%s\r\n", string.format("%d", (rds.get_ta() and 1 or 0)))
|
||||
elseif data == "rt1en" then return string.format("RT1EN=%s\r\n", string.format("%d", (rds.get_rt1_enabled() and 1 or 0)))
|
||||
elseif data == "rt2en" then return string.format("RT2EN=%s\r\n", string.format("%d", (rds.get_rt2_enabled() and 1 or 0)))
|
||||
elseif data == "ptynen" then return string.format("PTYNEN=%s\r\n", string.format("%d", (rds.get_ptyn_enabled() and 1 or 0)))
|
||||
elseif data == "rttype" then return string.format("RTTYPE=%s\r\n", string.format("%d", rds.get_rt_type()))
|
||||
elseif data == "rds2mod" then return string.format("RDS2MOD=%s\r\n", string.format("%d", rds.get_rds2_mode()))
|
||||
elseif data == "rdsgen" then return string.format("RDSGEN=%s\r\n", string.format("%d", get_rds_streams()))
|
||||
elseif data == "level" then return string.format("LEVEL=%s\r\n", string.format("%d", get_rds_level() * 255))
|
||||
elseif data == "link" then return string.format("LINK=%s\r\n", string.format("%d", (get_rds_link() and 1 or 0)))
|
||||
elseif data == "link" then return string.format("LINK=%s\r\n", string.format("%d", (rds.get_link() and 1 or 0)))
|
||||
elseif data == "rtp" then
|
||||
local t1, s1, l1, t2, s2, l2 = get_rds_rtplus_tags(false)
|
||||
local t1, s1, l1, t2, s2, l2 = rds.ext.get_rtplus_tags(false)
|
||||
return string.format("RTP=%d,%d,%d,%d,%d,%d\r\n", t1, s1, l1, t2, s2, l2)
|
||||
elseif data == "ertp" then
|
||||
local t1, s1, l1, t2, s2, l2 = get_rds_rtplus_tags(true)
|
||||
local t1, s1, l1, t2, s2, l2 = rds.ext.get_rtplus_tags(true)
|
||||
return string.format("ERTP=%d,%d,%d,%d,%d,%d\r\n", t1, s1, l1, t2, s2, l2)
|
||||
elseif data == "rtprun" then
|
||||
local running = get_rds_rtp_meta(false)
|
||||
local running = rds.ext.get_rtp_meta(false)
|
||||
local f1 = 2 or (running and 1 or 0)
|
||||
return string.format("RTPRUN=%d\r\n", f1)
|
||||
elseif data == "ertprun" then
|
||||
local running = get_rds_rtp_meta(true)
|
||||
local running = rds.ext.get_rtp_meta(true)
|
||||
local f1 = 2 or (running and 1 or 0)
|
||||
return string.format("ERTPRUN=%d\r\n", f1)
|
||||
elseif data == "lps" then return string.format("LPS=%s\r\n", get_rds_lps())
|
||||
elseif data == "ert" then return string.format("ERT=%s\r\n", get_rds_ert())
|
||||
elseif data == "grpseq" then return string.format("GRPSEQ=%s\r\n", get_rds_grpseq())
|
||||
elseif data == "grpseq2" then return string.format("GRPSEQ2=%s\r\n", get_rds_grpseq2())
|
||||
elseif data == "lps" then return string.format("LPS=%s\r\n", rds.get_lps())
|
||||
elseif data == "ert" then return string.format("ERT=%s\r\n", rds.ext.get_ert())
|
||||
elseif data == "grpseq" then return string.format("GRPSEQ=%s\r\n", rds.get_grpseq())
|
||||
elseif data == "grpseq2" then return string.format("GRPSEQ2=%s\r\n", rds.get_grpseq2())
|
||||
else
|
||||
local eon_cmd, eon_num = data:match("^eon(%d+)([a-z]+)$")
|
||||
if eon_cmd then
|
||||
local eon_idx = tonumber(eon_cmd)
|
||||
if not eon_idx or eon_idx < 1 or eon_idx > eon_count then return "?\r\n" end
|
||||
if not eon_idx or eon_idx < 1 or eon_idx > rds.eon_count then return "?\r\n" end
|
||||
eon_idx = eon_idx - 1
|
||||
local enabled, pi, tp, ta, pty, ps, afs, data_val = get_rds_eon(eon_idx)
|
||||
local enabled, pi, tp, ta, pty, ps, afs, data_val = rds.get_eon(eon_idx)
|
||||
|
||||
if eon_num == "en" then return string.format("EON%dEN=%d\r\n", eon_idx + 1, enabled and 1 or 0)
|
||||
elseif eon_num == "pi" then return string.format("EON%dPI=%x\r\n", eon_idx + 1, pi)
|
||||
@@ -106,48 +106,48 @@ function data_handle(data)
|
||||
local eon_num, eon_type = cmd:match("^eon(%d+)([a-z]+)$")
|
||||
if eon_num then
|
||||
local eon_idx = tonumber(eon_num)
|
||||
if not eon_idx or eon_idx < 1 or eon_idx > eon_count then return "?\r\n" end
|
||||
if not eon_idx or eon_idx < 1 or eon_idx > rds.eon_count then return "?\r\n" end
|
||||
eon_idx = eon_idx - 1
|
||||
|
||||
local enabled, pi, tp, ta, pty, ps, afs, data_val = get_rds_eon(eon_idx)
|
||||
local enabled, pi, tp, ta, pty, ps, afs, data_val = rds.get_eon(eon_idx)
|
||||
if eon_type == "en" then
|
||||
local en_val = tonumber(value)
|
||||
if not en_val then return "-\r\n" end
|
||||
enabled = (en_val ~= 0)
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val)
|
||||
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val)
|
||||
return "+\r\n"
|
||||
elseif eon_type == "pi" then
|
||||
local pi_val = tonumber(value, 16)
|
||||
if not pi_val then return "-\r\n" end
|
||||
set_rds_eon(eon_idx, enabled, pi_val, tp, ta, pty, ps, afs, data_val)
|
||||
rds.set_eon(eon_idx, enabled, pi_val, tp, ta, pty, ps, afs, data_val)
|
||||
return "+\r\n"
|
||||
elseif eon_type == "ps" then
|
||||
local ps_val = value:sub(1, 24)
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps_val, afs, data_val)
|
||||
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps_val, afs, data_val)
|
||||
return "+\r\n"
|
||||
elseif eon_type == "pty" then
|
||||
local pty_val = tonumber(value)
|
||||
if not pty_val then return "-\r\n" end
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty_val, ps, afs, data_val)
|
||||
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty_val, ps, afs, data_val)
|
||||
return "+\r\n"
|
||||
elseif eon_type == "ta" then
|
||||
if not enabled or not tp then return "-\r\n" end
|
||||
local ta_val = tonumber(value)
|
||||
if not ta_val then return "-\r\n" end
|
||||
ta = (ta_val ~= 0)
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val)
|
||||
if ta then set_rds_ta(true) end
|
||||
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val)
|
||||
if ta then rds.set_ta(true) end
|
||||
return "+\r\n"
|
||||
elseif eon_type == "tp" then
|
||||
local tp_val = tonumber(value)
|
||||
if not tp_val then return "-\r\n" end
|
||||
tp = (tp_val ~= 0)
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val)
|
||||
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val)
|
||||
return "+\r\n"
|
||||
elseif eon_type == "af" then
|
||||
local af_table = {}
|
||||
if value == "" or value == "0" then
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, {}, data_val)
|
||||
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps, {}, data_val)
|
||||
return "+\r\n"
|
||||
end
|
||||
for freq_str in value:gmatch("([^,]+)") do
|
||||
@@ -156,12 +156,12 @@ function data_handle(data)
|
||||
else return "-\r\n" end
|
||||
end
|
||||
if #af_table > 25 then return "-\r\n" end
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, af_table, data_val)
|
||||
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps, af_table, data_val)
|
||||
return "+\r\n"
|
||||
elseif eon_type == "dt" then
|
||||
local dt_val = tonumber(value, 16)
|
||||
if not dt_val then return "-\r\n" end
|
||||
set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, dt_val)
|
||||
rds.set_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, dt_val)
|
||||
return "+\r\n"
|
||||
else return "?\r\n" end
|
||||
end
|
||||
@@ -179,7 +179,7 @@ function data_handle(data)
|
||||
end
|
||||
|
||||
if #groups > 8 or #groups == 0 then return "-\r\n" end
|
||||
set_rds_udg(xy, groups)
|
||||
rds.set_udg(xy, groups)
|
||||
return "+\r\n"
|
||||
end
|
||||
if udg2_num then
|
||||
@@ -193,7 +193,7 @@ function data_handle(data)
|
||||
end
|
||||
|
||||
if #groups > 8 or #groups == 0 then return "-" end
|
||||
set_rds_udg2(xy, groups)
|
||||
rds.set_udg2(xy, groups)
|
||||
return "+\r\n"
|
||||
end
|
||||
|
||||
@@ -201,67 +201,67 @@ function data_handle(data)
|
||||
local pi = tonumber(value, 16)
|
||||
if not pi then return "-\r\n" end
|
||||
if (pi & 0xF000) == 0 then return "-\r\n" end
|
||||
set_rds_pi(pi)
|
||||
rds.set_pi(pi)
|
||||
return "+\r\n"
|
||||
elseif cmd == "ecc" then
|
||||
local ecc = tonumber(value, 16)
|
||||
if not ecc then return "-\r\n" end
|
||||
set_rds_ecc(ecc)
|
||||
rds.set_ecc(ecc)
|
||||
return "+\r\n"
|
||||
elseif cmd == "pty" then
|
||||
local pty = tonumber(value)
|
||||
if not pty then return "-\r\n" end
|
||||
set_rds_pty(pty)
|
||||
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
|
||||
set_rds_slc_data(slc_data)
|
||||
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
|
||||
set_rds_ct(ct ~= 0)
|
||||
rds.set_ct(ct ~= 0)
|
||||
return "+\r\n"
|
||||
elseif cmd == "dpty" then
|
||||
local dpty = tonumber(value)
|
||||
if not dpty then return "-\r\n" end
|
||||
set_rds_dpty(dpty ~= 0)
|
||||
rds.set_dpty(dpty ~= 0)
|
||||
return "+\r\n"
|
||||
elseif cmd == "tp" then
|
||||
local tp = tonumber(value)
|
||||
if not tp then return "-\r\n" end
|
||||
set_rds_tp(tp ~= 0)
|
||||
rds.set_tp(tp ~= 0)
|
||||
return "+\r\n"
|
||||
elseif cmd == "ta" then
|
||||
local ta = tonumber(value)
|
||||
if not ta then return "-\r\n" end
|
||||
set_rds_ta(ta ~= 0)
|
||||
rds.set_ta(ta ~= 0)
|
||||
return "+\r\n"
|
||||
elseif cmd == "rt1en" then
|
||||
local en = tonumber(value)
|
||||
if not en then return "-\r\n" end
|
||||
set_rds_rt1_enabled(en ~= 0)
|
||||
rds.set_rt1_enabled(en ~= 0)
|
||||
return "+\r\n"
|
||||
elseif cmd == "rt2en" then
|
||||
local en = tonumber(value)
|
||||
if not en then return "-\r\n" end
|
||||
set_rds_rt2_enabled(en ~= 0)
|
||||
rds.set_rt2_enabled(en ~= 0)
|
||||
return "+\r\n"
|
||||
elseif cmd == "ptynen" then
|
||||
local en = tonumber(value)
|
||||
if not en then return "-\r\n" end
|
||||
set_rds_ptyn_enabled(en ~= 0)
|
||||
rds.set_ptyn_enabled(en ~= 0)
|
||||
return "+\r\n"
|
||||
elseif cmd == "rttype" then
|
||||
local type = tonumber(value)
|
||||
if not type then return "-\r\n" end
|
||||
set_rds_rt_type(type)
|
||||
rds.set_rt_type(type)
|
||||
return "+\r\n"
|
||||
elseif cmd == "rds2mod" then
|
||||
local type = tonumber(value)
|
||||
if not type then return "-\r\n" end
|
||||
set_rds2_mode(type)
|
||||
rds.set_rds2_mode(type)
|
||||
return "+\r\n"
|
||||
elseif cmd == "rdsgen" then
|
||||
local type = tonumber(value)
|
||||
@@ -269,42 +269,42 @@ function data_handle(data)
|
||||
set_rds_streams(type)
|
||||
return "+\r\n"
|
||||
elseif cmd == "ptyn" then
|
||||
set_rds_ptyn(value)
|
||||
rds.set_ptyn(value)
|
||||
return "+\r\n"
|
||||
elseif cmd == "ps" then
|
||||
set_rds_ps(value)
|
||||
rds.set_ps(value)
|
||||
return "+\r\n"
|
||||
elseif cmd == "tps" then
|
||||
set_rds_tps(value)
|
||||
rds.set_tps(value)
|
||||
return "+\r\n"
|
||||
elseif cmd == "rt1" or cmd == "text" then
|
||||
set_rds_rt1(value)
|
||||
rds.set_rt1(value)
|
||||
return "+\r\n"
|
||||
elseif cmd == "rt2" then
|
||||
set_rds_rt2(value)
|
||||
rds.set_rt2(value)
|
||||
return "+\r\n"
|
||||
elseif cmd == "lps" then
|
||||
set_rds_lps(value)
|
||||
rds.set_lps(value)
|
||||
return "+\r\n"
|
||||
elseif cmd == "ert" then
|
||||
set_rds_ert(value)
|
||||
rds.ext.set_ert(value)
|
||||
return "+\r\n"
|
||||
elseif cmd == "link" then
|
||||
local link = tonumber(value)
|
||||
if not link then return "-\r\n" end
|
||||
set_rds_link(link ~= 0)
|
||||
rds.set_link(link ~= 0)
|
||||
return "+\r\n"
|
||||
elseif cmd == "rtper" then
|
||||
local period = tonumber(value)
|
||||
if not period then return "-\r\n" end
|
||||
set_rds_rt_switching_period(period*60)
|
||||
rds.set_rt_switching_period(period*60)
|
||||
return "+\r\n"
|
||||
elseif cmd == "program" then
|
||||
local program = tonumber(value)
|
||||
if not program then return "-\r\n" end
|
||||
if program < 1 or program > max_programs then return "-\r\n" end
|
||||
set_rds_program(program-1)
|
||||
set_rds_ta(false)
|
||||
if program < 1 or program > dp.max_programs then return "-\r\n" end
|
||||
dp.set_rds_program(program-1)
|
||||
rds.set_ta(false)
|
||||
return "+\r\n"
|
||||
elseif cmd == "level" then
|
||||
local level = tonumber(value)
|
||||
@@ -314,20 +314,20 @@ function data_handle(data)
|
||||
elseif cmd == "dttmout" then
|
||||
local timeout = tonumber(value)
|
||||
if not timeout then return "-\r\n" end
|
||||
set_rds_rt_text_timeout(timeout*60)
|
||||
rds.set_rt_text_timeout(timeout*60)
|
||||
return "+\r\n"
|
||||
elseif cmd == "grpseq" then
|
||||
set_rds_grpseq(value)
|
||||
rds.set_grpseq(value)
|
||||
return "+\r\n"
|
||||
elseif cmd == "grpseq2" then
|
||||
set_rds_grpseq2(value)
|
||||
rds.set_grpseq2(value)
|
||||
return "+\r\n"
|
||||
elseif cmd == "rtp" or cmd == "ertp" then
|
||||
local is_ertp = (cmd == "ertp")
|
||||
local t1, s1, l1, t2, s2, l2 = value:match("(%d+),(%d+),(%d+),(%d+),(%d+),(%d+)")
|
||||
|
||||
if not l2 then return "-\r\n" end
|
||||
set_rds_rtplus_tags(
|
||||
rds.ext.set_rtplus_tags(
|
||||
is_ertp,
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
tonumber(t1), tonumber(s1), tonumber(l1), tonumber(t2), tonumber(s2), tonumber(l2)
|
||||
@@ -336,13 +336,13 @@ function data_handle(data)
|
||||
elseif cmd == "g" then
|
||||
local a, b, c, d = value:match("^(%x%x%x%x)(%x%x%x%x)(%x%x%x%x)(%x%x%x%x)$")
|
||||
if a and b and c and d then
|
||||
put_rds2_custom_group(tonumber(a, 16), tonumber(b, 16), tonumber(c, 16), tonumber(d, 16))
|
||||
rds.put_rds2_custom_group(tonumber(a, 16), tonumber(b, 16), tonumber(c, 16), tonumber(d, 16))
|
||||
return "+\r\n"
|
||||
end
|
||||
|
||||
local b1, c1, d1 = value:match("^(%x%x%x%x)(%x%x%x%x)(%x%x%x%x)$")
|
||||
if b1 and c1 and d1 then
|
||||
put_rds_custom_group(tonumber(b1, 16), tonumber(c1, 16), tonumber(d1, 16))
|
||||
rds.put_custom_group(tonumber(b1, 16), tonumber(c1, 16), tonumber(d1, 16))
|
||||
return "+\r\n"
|
||||
end
|
||||
|
||||
@@ -357,14 +357,14 @@ function data_handle(data)
|
||||
local f2 = tonumber(f2_str) or 0
|
||||
local running = (f1 & 1) ~= 0
|
||||
|
||||
set_rds_rtp_meta(is_ertp, running)
|
||||
if f2 ~= 0 then toggle_rds_rtp(is_ertp) end
|
||||
rds.ext.set_rtp_meta(is_ertp, running)
|
||||
if f2 ~= 0 then rds.ext.toggle_rtp(is_ertp) end
|
||||
return "+\r\n"
|
||||
elseif cmd == "af" then
|
||||
local af_table = {}
|
||||
|
||||
if value == "" or value == "0" then
|
||||
set_rds_af_group0({})
|
||||
rds.set_af({})
|
||||
return "+\r\n"
|
||||
end
|
||||
|
||||
@@ -376,13 +376,13 @@ function data_handle(data)
|
||||
|
||||
if #af_table > 25 then return "-\r\n" end
|
||||
|
||||
set_rds_af_group0(af_table)
|
||||
rds.set_af(af_table)
|
||||
return "+\r\n"
|
||||
elseif cmd == "afo" then
|
||||
local af_table = {}
|
||||
|
||||
if value == "" or value == "0" then
|
||||
set_rds_af_oda({})
|
||||
rds.ext.set_af_oda({})
|
||||
return "+\r\n"
|
||||
end
|
||||
|
||||
@@ -394,7 +394,7 @@ function data_handle(data)
|
||||
|
||||
if #af_table > 25 then return "-\r\n" end
|
||||
|
||||
set_rds_af_oda(af_table)
|
||||
rds.ext.set_af_oda(af_table)
|
||||
return "+\r\n"
|
||||
else
|
||||
return "?\r\n"
|
||||
|
||||
425
src/lua_api.c
Normal file
425
src/lua_api.c
Normal file
@@ -0,0 +1,425 @@
|
||||
#include "lua_api.h"
|
||||
#include "lua_rds.h"
|
||||
|
||||
static int in_set_defaults = 0;
|
||||
|
||||
extern lua_State *L;
|
||||
extern RDSModulator* mod;
|
||||
extern uint8_t unload_refs[33];
|
||||
|
||||
int lua_get_userdata(lua_State *localL) {
|
||||
lua_pushlstring(localL, (const char*)&mod->enc->data[mod->enc->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*)&mod->enc->data[mod->enc->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(mod->enc->data[mod->enc->program].lua_data, 0, LUA_USER_DATA);
|
||||
memcpy(mod->enc->data[mod->enc->program].lua_data, data, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
int lua_set_userdata_offset(lua_State *localL) {
|
||||
uint16_t offset = luaL_checkinteger(localL, 1);
|
||||
uint16_t size = luaL_checkinteger(localL, 2);
|
||||
|
||||
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(mod->enc->data[mod->enc->program].lua_data + offset, 0, size);
|
||||
memcpy(mod->enc->data[mod->enc->program].lua_data + offset, data, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_force_save(lua_State *localL) {
|
||||
(void)localL;
|
||||
encoder_saveToFile(mod->enc);
|
||||
Modulator_saveToFile(&mod->params);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_set_rds_program_defaults(lua_State *localL) {
|
||||
(void)localL;
|
||||
if (in_set_defaults) {
|
||||
fprintf(stderr, "Warning: Recursive call to lua_set_rds_program_defaults blocked\n");
|
||||
return 0;
|
||||
}
|
||||
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(mod->enc, mod->enc->program);
|
||||
lua_call_tfunction_nolock("on_init");
|
||||
lua_call_tfunction_nolock("on_state");
|
||||
in_set_defaults = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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] = 1;
|
||||
encoder_saveToFile(mod->enc);
|
||||
Modulator_saveToFile(&mod->params);
|
||||
|
||||
encoder_loadFromFile(mod->enc);
|
||||
for(int i = 0; i < PROGRAMS; i++) reset_rds_state(mod->enc, i);
|
||||
Modulator_loadFromFile(&mod->params);
|
||||
lua_call_tfunction_nolock("on_state");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#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)); \
|
||||
mod->enc->data[mod->enc->program].name = lua_toboolean(localL, 1); \
|
||||
return 0; \
|
||||
}
|
||||
#define INT_SETTER(name) \
|
||||
int lua_set_rds_##name(lua_State *localL) { \
|
||||
mod->enc->data[mod->enc->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(mod->enc, convert_to_rdscharset(str)); \
|
||||
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(mod->enc, str); \
|
||||
return 0; \
|
||||
}
|
||||
#define AF_SETTER(name, af_field, af_struct, add_func) \
|
||||
int lua_set_rds_##name(lua_State *localL) { \
|
||||
luaL_checktype(localL, 1, LUA_TTABLE); \
|
||||
\
|
||||
int n = lua_rawlen(localL, 1); \
|
||||
if (n == 0) { \
|
||||
memset(&(mod->enc->data[mod->enc->program].af_field), 0, sizeof(af_struct)); \
|
||||
return 0; \
|
||||
} \
|
||||
if(n > 25) return luaL_error(localL, "table length over 25"); \
|
||||
\
|
||||
af_struct new_af; \
|
||||
memset(&new_af, 0, sizeof(af_struct)); \
|
||||
\
|
||||
for (int i = 1; i <= n; i++) { \
|
||||
lua_rawgeti(localL, 1, i); \
|
||||
if (lua_isnumber(localL, -1)) add_func(&new_af, lua_tonumber(localL, -1)); \
|
||||
else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1)); \
|
||||
lua_pop(localL, 1); \
|
||||
} \
|
||||
memcpy(&(mod->enc->data[mod->enc->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, mod->enc->data[mod->enc->program].name); \
|
||||
return 1; \
|
||||
}
|
||||
#define BOOL_GETTER(name) \
|
||||
int lua_get_rds_##name(lua_State *localL) { \
|
||||
lua_pushboolean(localL, mod->enc->data[mod->enc->program].name); \
|
||||
return 1; \
|
||||
}
|
||||
#define STR_RAW_GETTER(name, length) \
|
||||
int lua_get_rds_##name(lua_State *localL) { \
|
||||
lua_pushlstring(localL, mod->enc->data[mod->enc->program].name, length); \
|
||||
return 1; \
|
||||
}
|
||||
INT_SETTER(pi)
|
||||
INT_GETTER(pi)
|
||||
|
||||
INT_SETTER(pty)
|
||||
INT_GETTER(pty)
|
||||
|
||||
INT_SETTER(ecc)
|
||||
INT_GETTER(ecc)
|
||||
|
||||
INT_SETTER(slc_data)
|
||||
INT_GETTER(slc_data)
|
||||
|
||||
BOOL_SETTER(ct)
|
||||
BOOL_GETTER(ct)
|
||||
|
||||
BOOL_SETTER(dpty)
|
||||
BOOL_GETTER(dpty)
|
||||
|
||||
BOOL_SETTER(tp)
|
||||
BOOL_GETTER(tp)
|
||||
|
||||
BOOL_SETTER(ta)
|
||||
BOOL_GETTER(ta)
|
||||
|
||||
BOOL_SETTER(rt1_enabled)
|
||||
BOOL_GETTER(rt1_enabled)
|
||||
|
||||
BOOL_SETTER(rt2_enabled)
|
||||
BOOL_GETTER(rt2_enabled)
|
||||
|
||||
BOOL_SETTER(ptyn_enabled)
|
||||
BOOL_GETTER(ptyn_enabled)
|
||||
|
||||
INT_SETTER(rt_type)
|
||||
INT_GETTER(rt_type)
|
||||
|
||||
int lua_set_rds2_mode(lua_State *localL) {
|
||||
mod->enc->encoder_data.rds2_mode = luaL_checkinteger(localL, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_get_rds2_mode(lua_State *localL) {
|
||||
lua_pushinteger(localL, mod->enc->encoder_data.rds2_mode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_set_rds_streams(lua_State *localL) {
|
||||
mod->params.rdsgen = luaL_checkinteger(localL, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_get_rds_streams(lua_State *localL) {
|
||||
lua_pushinteger(localL, mod->params.rdsgen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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));
|
||||
mod->enc->state[mod->enc->program].eon_linkage = lua_toboolean(localL, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_get_rds_link(lua_State *localL) {
|
||||
lua_pushboolean(localL, mod->enc->state[mod->enc->program].eon_linkage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_set_rds_program(lua_State *localL) {
|
||||
int program = luaL_checkinteger(localL, 1);
|
||||
if(program >= PROGRAMS) program = (PROGRAMS-1);
|
||||
if(program < 0) program = 0;
|
||||
|
||||
if(mod->enc->program == program) return 0;
|
||||
|
||||
mod->enc->data[mod->enc->program].ta = 0;
|
||||
mod->enc->data[(uint8_t)program].ta = 0;
|
||||
mod->enc->program = (uint8_t)program;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_get_rds_program(lua_State *localL) {
|
||||
lua_pushinteger(localL, mod->enc->program);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_set_rds_rt_switching_period(lua_State *localL) {
|
||||
mod->enc->data[mod->enc->program].rt_switching_period = luaL_checkinteger(localL, 1);
|
||||
mod->enc->state[mod->enc->program].rt_switching_period_state = mod->enc->data[mod->enc->program].rt_switching_period;
|
||||
return 0;
|
||||
}
|
||||
INT_GETTER(rt_switching_period)
|
||||
|
||||
int lua_set_rds_rt_text_timeout(lua_State *localL) {
|
||||
mod->enc->data[mod->enc->program].rt_text_timeout = luaL_checkinteger(localL, 1);
|
||||
mod->enc->state[mod->enc->program].rt_text_timeout_state = mod->enc->data[mod->enc->program].rt_text_timeout;
|
||||
return 0;
|
||||
}
|
||||
INT_GETTER(rt_text_timeout)
|
||||
|
||||
int lua_set_rds_level(lua_State *localL) {
|
||||
mod->params.level = luaL_checknumber(localL, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_get_rds_level(lua_State *localL) {
|
||||
lua_pushnumber(localL, mod->params.level);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_put_rds_custom_group(lua_State *localL) {
|
||||
mod->enc->state[mod->enc->program].custom_group[0] = 1;
|
||||
mod->enc->state[mod->enc->program].custom_group[1] = luaL_checkinteger(localL, 1);
|
||||
mod->enc->state[mod->enc->program].custom_group[2] = luaL_checkinteger(localL, 2);
|
||||
mod->enc->state[mod->enc->program].custom_group[3] = luaL_checkinteger(localL, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_put_rds2_custom_group(lua_State *localL) {
|
||||
mod->enc->state[mod->enc->program].custom_group2[0] = 1;
|
||||
mod->enc->state[mod->enc->program].custom_group2[1] = luaL_checkinteger(localL, 1);
|
||||
mod->enc->state[mod->enc->program].custom_group2[2] = luaL_checkinteger(localL, 2);
|
||||
mod->enc->state[mod->enc->program].custom_group2[3] = luaL_checkinteger(localL, 3);
|
||||
mod->enc->state[mod->enc->program].custom_group2[4] = luaL_checkinteger(localL, 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STR_SETTER(ptyn, set_rds_ptyn)
|
||||
STR_SETTER(ps, set_rds_ps)
|
||||
STR_SETTER(tps, set_rds_tps)
|
||||
STR_SETTER(rt1, set_rds_rt1)
|
||||
STR_SETTER(rt2, set_rds_rt2)
|
||||
STR_SETTER(default_rt, set_rds_default_rt)
|
||||
|
||||
STR_RAW_SETTER(lps, set_rds_lps)
|
||||
STR_RAW_GETTER(lps, LPS_LENGTH)
|
||||
|
||||
STR_RAW_SETTER(grp_sqc_rds2, set_rds_grpseq2)
|
||||
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(mod->enc, DEFAULT_GRPSQC);
|
||||
else set_rds_grpseq(mod->enc, str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STR_RAW_GETTER(grp_sqc, 32)
|
||||
|
||||
AF_SETTER(af_group0, af, RDSAFs, add_rds_af)
|
||||
|
||||
int lua_set_rds_eon(lua_State *localL) {
|
||||
int eon = luaL_checkinteger(localL, 1);
|
||||
if(eon >= EONs) return luaL_error(localL, "eon index exceeded");
|
||||
if (!lua_isboolean(localL, 2)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 2));
|
||||
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);
|
||||
mod->enc->data[mod->enc->program].eon[eon].enabled = lua_toboolean(localL, 2);
|
||||
mod->enc->data[mod->enc->program].eon[eon].pi = luaL_checkinteger(localL, 3);
|
||||
mod->enc->data[mod->enc->program].eon[eon].tp = lua_toboolean(localL, 4);
|
||||
mod->enc->data[mod->enc->program].eon[eon].ta = lua_toboolean(localL, 5);
|
||||
mod->enc->data[mod->enc->program].eon[eon].pty = luaL_checkinteger(localL, 6);
|
||||
_strncpy(mod->enc->data[mod->enc->program].eon[eon].ps, luaL_checklstring(localL, 7, NULL), 8);
|
||||
|
||||
int n = lua_rawlen(localL, 8);
|
||||
if (n == 0) {
|
||||
memset(&(mod->enc->data[mod->enc->program].eon[eon].af), 0, sizeof(RDSAFs));
|
||||
return 0;
|
||||
}
|
||||
if(n > 25) return luaL_error(localL, "table length over 25");
|
||||
|
||||
RDSAFs new_af;
|
||||
memset(&new_af, 0, sizeof(RDSAFs));
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
lua_rawgeti(localL, 8, i);
|
||||
if (lua_isnumber(localL, -1)) add_rds_af(&new_af, lua_tonumber(localL, -1));
|
||||
else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
memcpy(&(mod->enc->data[mod->enc->program].eon[eon].af), &new_af, sizeof(new_af));
|
||||
|
||||
mod->enc->data[mod->enc->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, mod->enc->data[mod->enc->program].eon[eon].enabled);
|
||||
lua_pushinteger(localL, mod->enc->data[mod->enc->program].eon[eon].pi);
|
||||
lua_pushboolean(localL, mod->enc->data[mod->enc->program].eon[eon].tp);
|
||||
lua_pushboolean(localL, mod->enc->data[mod->enc->program].eon[eon].ta);
|
||||
lua_pushinteger(localL, mod->enc->data[mod->enc->program].eon[eon].pty);
|
||||
lua_pushlstring(localL, mod->enc->data[mod->enc->program].eon[eon].ps, 8);
|
||||
lua_createtable(localL, 0, 0); // don't have decoding for AF, so just return empty table
|
||||
lua_pushinteger(localL, mod->enc->data[mod->enc->program].eon[eon].data);
|
||||
return 8;
|
||||
}
|
||||
|
||||
int lua_set_rds_udg(lua_State *localL) {
|
||||
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
|
||||
int xy = lua_toboolean(localL, 1);
|
||||
luaL_checktype(localL, 2, LUA_TTABLE);
|
||||
int n = lua_rawlen(localL, 2);
|
||||
if(n > 8) return luaL_error(localL, "table length over 8");
|
||||
|
||||
uint16_t blocks[8][3] = {0};
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
lua_rawgeti(localL, 2, i);
|
||||
if(lua_istable(localL, -1)) {
|
||||
int n2 = lua_rawlen(localL, -1);
|
||||
if(n2 > 3) return luaL_error(localL, "table length over 3");
|
||||
for(int j = 1; j <= n2; j++) {
|
||||
lua_rawgeti(localL, -1, j);
|
||||
if (lua_isinteger(localL, -1)) blocks[i-1][j-1] = lua_tointeger(localL, -1);
|
||||
else return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
}
|
||||
else return luaL_error(localL, "table expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
|
||||
if(xy) {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg2), blocks, n * sizeof(uint16_t[3]));
|
||||
mod->enc->data[mod->enc->program].udg2_len = n;
|
||||
} else {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg1), blocks, n * sizeof(uint16_t[3]));
|
||||
mod->enc->data[mod->enc->program].udg1_len = n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_set_rds_udg2(lua_State *localL) {
|
||||
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
|
||||
int xy = lua_toboolean(localL, 1);
|
||||
luaL_checktype(localL, 2, LUA_TTABLE);
|
||||
int n = lua_rawlen(localL, 2);
|
||||
if(n > 8) return luaL_error(localL, "table length over 8");
|
||||
|
||||
uint16_t blocks[8][4] = {0};
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
lua_rawgeti(localL, 2, i);
|
||||
if(lua_istable(localL, -1)) {
|
||||
int n2 = lua_rawlen(localL, -1);
|
||||
if(n2 > 4) return luaL_error(localL, "table length over 4");
|
||||
for(int j = 1; j <= n2; j++) {
|
||||
lua_rawgeti(localL, -1, j);
|
||||
if (lua_isinteger(localL, -1)) blocks[i-1][j-1] = lua_tointeger(localL, -1);
|
||||
else return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
}
|
||||
else return luaL_error(localL, "table expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
|
||||
if(xy) {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg2_rds2), blocks, n * sizeof(uint16_t[4]));
|
||||
mod->enc->data[mod->enc->program].udg2_len_rds2 = n;
|
||||
} else {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg1_rds2), blocks, n * sizeof(uint16_t[4]));
|
||||
mod->enc->data[mod->enc->program].udg1_len_rds2 = n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_get_available_rds_streams(lua_State *localL) {
|
||||
lua_pushinteger(localL, mod->num_streams);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_crc16(lua_State *localL) {
|
||||
size_t len;
|
||||
const char* data = luaL_checklstring(localL, 1, &len);
|
||||
lua_pushinteger(localL, crc16_ccitt(data, len));
|
||||
return 1;
|
||||
}
|
||||
101
src/lua_api.h
Normal file
101
src/lua_api.h
Normal file
@@ -0,0 +1,101 @@
|
||||
#pragma once
|
||||
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
#include "rds.h"
|
||||
#include "fs.h"
|
||||
#include "modulator.h"
|
||||
|
||||
int lua_get_userdata(lua_State *localL);
|
||||
int lua_get_userdata_offset(lua_State *localL);
|
||||
int lua_set_userdata(lua_State *localL);
|
||||
int lua_set_userdata_offset(lua_State *localL);
|
||||
int lua_force_save(lua_State *localL);
|
||||
int lua_set_rds_program_defaults(lua_State *localL);
|
||||
int lua_reset_rds(lua_State *localL);
|
||||
|
||||
int lua_set_rds_pi(lua_State *localL);
|
||||
int lua_get_rds_pi(lua_State *localL);
|
||||
|
||||
int lua_set_rds_pty(lua_State *localL);
|
||||
int lua_get_rds_pty(lua_State *localL);
|
||||
|
||||
int lua_set_rds_ecc(lua_State *localL);
|
||||
int lua_get_rds_ecc(lua_State *localL);
|
||||
|
||||
int lua_set_rds_slc_data(lua_State *localL);
|
||||
int lua_get_rds_slc_data(lua_State *localL);
|
||||
|
||||
int lua_set_rds_ct(lua_State *localL);
|
||||
int lua_get_rds_ct(lua_State *localL);
|
||||
|
||||
int lua_set_rds_dpty(lua_State *localL);
|
||||
int lua_get_rds_dpty(lua_State *localL);
|
||||
|
||||
int lua_set_rds_tp(lua_State *localL);
|
||||
int lua_get_rds_tp(lua_State *localL);
|
||||
|
||||
int lua_set_rds_ta(lua_State *localL);
|
||||
int lua_get_rds_ta(lua_State *localL);
|
||||
|
||||
int lua_set_rds_rt1_enabled(lua_State *localL);
|
||||
int lua_get_rds_rt1_enabled(lua_State *localL);
|
||||
|
||||
int lua_set_rds_rt2_enabled(lua_State *localL);
|
||||
int lua_get_rds_rt2_enabled(lua_State *localL);
|
||||
|
||||
int lua_set_rds_ptyn_enabled(lua_State *localL);
|
||||
int lua_get_rds_ptyn_enabled(lua_State *localL);
|
||||
|
||||
int lua_set_rds_rt_type(lua_State *localL);
|
||||
int lua_get_rds_rt_type(lua_State *localL);
|
||||
|
||||
int lua_set_rds2_mode(lua_State *localL);
|
||||
int lua_get_rds2_mode(lua_State *localL);
|
||||
|
||||
int lua_set_rds_streams(lua_State *localL);
|
||||
int lua_get_rds_streams(lua_State *localL);
|
||||
int lua_get_available_rds_streams(lua_State *localL);
|
||||
|
||||
int lua_set_rds_grp_sqc(lua_State *localL);
|
||||
int lua_get_rds_grp_sqc(lua_State *localL);
|
||||
|
||||
int lua_set_rds_grp_sqc_rds2(lua_State *localL);
|
||||
int lua_get_rds_grp_sqc_rds2(lua_State *localL);
|
||||
|
||||
int lua_set_rds_link(lua_State *localL);
|
||||
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_rt_switching_period(lua_State *localL);
|
||||
int lua_get_rds_rt_switching_period(lua_State *localL);
|
||||
|
||||
int lua_set_rds_rt_text_timeout(lua_State *localL);
|
||||
int lua_get_rds_rt_text_timeout(lua_State *localL);
|
||||
|
||||
int lua_set_rds_level(lua_State *localL);
|
||||
int lua_get_rds_level(lua_State *localL);
|
||||
|
||||
int lua_put_rds_custom_group(lua_State *localL);
|
||||
int lua_put_rds2_custom_group(lua_State *localL);
|
||||
|
||||
int lua_set_rds_lps(lua_State *localL);
|
||||
int lua_get_rds_lps(lua_State *localL);
|
||||
int lua_set_rds_af_group0(lua_State *localL);
|
||||
int lua_set_rds_default_rt(lua_State *localL);
|
||||
int lua_set_rds_rt2(lua_State *localL);
|
||||
int lua_set_rds_rt1(lua_State *localL);
|
||||
int lua_set_rds_tps(lua_State *localL);
|
||||
int lua_set_rds_ps(lua_State *localL);
|
||||
int lua_set_rds_ptyn(lua_State *localL);
|
||||
int lua_set_rds_grp_sqc(lua_State *localL);
|
||||
|
||||
int lua_set_rds_eon(lua_State *localL);
|
||||
int lua_get_rds_eon(lua_State *localL);
|
||||
int lua_set_rds_udg(lua_State *localL);
|
||||
int lua_set_rds_udg2(lua_State *localL);
|
||||
|
||||
int lua_crc16(lua_State *localL);
|
||||
651
src/lua_rds.c
651
src/lua_rds.c
@@ -1,418 +1,13 @@
|
||||
#include "lua_rds.h"
|
||||
#include <pthread.h>
|
||||
#include "lua_api.h"
|
||||
|
||||
static RDSModulator* mod = NULL;
|
||||
static lua_State *L = NULL;
|
||||
RDSModulator* mod = NULL;
|
||||
lua_State *L = NULL;
|
||||
static pthread_mutex_t lua_mutex;
|
||||
static uint8_t unload_refs[33] = {LUA_REFNIL};
|
||||
static int in_set_defaults = 0;
|
||||
|
||||
int lua_get_userdata(lua_State *localL) {
|
||||
lua_pushlstring(localL, (const char*)&mod->enc->data[mod->enc->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*)&mod->enc->data[mod->enc->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(mod->enc->data[mod->enc->program].lua_data, 0, LUA_USER_DATA);
|
||||
memcpy(mod->enc->data[mod->enc->program].lua_data, data, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
int lua_set_userdata_offset(lua_State *localL) {
|
||||
uint16_t offset = luaL_checkinteger(localL, 1);
|
||||
uint16_t size = luaL_checkinteger(localL, 2);
|
||||
|
||||
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(mod->enc->data[mod->enc->program].lua_data + offset, 0, size);
|
||||
memcpy(mod->enc->data[mod->enc->program].lua_data + offset, data, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_force_save(lua_State *localL) {
|
||||
(void)localL;
|
||||
encoder_saveToFile(mod->enc);
|
||||
Modulator_saveToFile(&mod->params);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_set_rds_program_defaults(lua_State *localL) {
|
||||
(void)localL;
|
||||
if (in_set_defaults) {
|
||||
fprintf(stderr, "Warning: Recursive call to lua_set_rds_program_defaults blocked\n");
|
||||
return 0;
|
||||
}
|
||||
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(mod->enc, mod->enc->program);
|
||||
lua_call_function_nolock("on_init");
|
||||
lua_call_function_nolock("on_state");
|
||||
in_set_defaults = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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] = 1;
|
||||
encoder_saveToFile(mod->enc);
|
||||
Modulator_saveToFile(&mod->params);
|
||||
|
||||
encoder_loadFromFile(mod->enc);
|
||||
for(int i = 0; i < PROGRAMS; i++) reset_rds_state(mod->enc, i);
|
||||
Modulator_loadFromFile(&mod->params);
|
||||
lua_call_function_nolock("on_state");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#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)); \
|
||||
mod->enc->data[mod->enc->program].name = lua_toboolean(localL, 1); \
|
||||
return 0; \
|
||||
}
|
||||
#define INT_SETTER(name) \
|
||||
int lua_set_rds_##name(lua_State *localL) { \
|
||||
mod->enc->data[mod->enc->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(mod->enc, convert_to_rdscharset(str)); \
|
||||
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(mod->enc, str); \
|
||||
return 0; \
|
||||
}
|
||||
#define AF_SETTER(name, af_field, af_struct, add_func) \
|
||||
int lua_set_rds_##name(lua_State *localL) { \
|
||||
luaL_checktype(localL, 1, LUA_TTABLE); \
|
||||
\
|
||||
int n = lua_rawlen(localL, 1); \
|
||||
if (n == 0) { \
|
||||
memset(&(mod->enc->data[mod->enc->program].af_field), 0, sizeof(af_struct)); \
|
||||
return 0; \
|
||||
} \
|
||||
if(n > 25) return luaL_error(localL, "table length over 25"); \
|
||||
\
|
||||
af_struct new_af; \
|
||||
memset(&new_af, 0, sizeof(af_struct)); \
|
||||
\
|
||||
for (int i = 1; i <= n; i++) { \
|
||||
lua_rawgeti(localL, 1, i); \
|
||||
if (lua_isnumber(localL, -1)) add_func(&new_af, lua_tonumber(localL, -1)); \
|
||||
else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1)); \
|
||||
lua_pop(localL, 1); \
|
||||
} \
|
||||
memcpy(&(mod->enc->data[mod->enc->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, mod->enc->data[mod->enc->program].name); \
|
||||
return 1; \
|
||||
}
|
||||
#define BOOL_GETTER(name) \
|
||||
int lua_get_rds_##name(lua_State *localL) { \
|
||||
lua_pushboolean(localL, mod->enc->data[mod->enc->program].name); \
|
||||
return 1; \
|
||||
}
|
||||
#define STR_RAW_GETTER(name, length) \
|
||||
int lua_get_rds_##name(lua_State *localL) { \
|
||||
lua_pushlstring(localL, mod->enc->data[mod->enc->program].name, length); \
|
||||
return 1; \
|
||||
}
|
||||
INT_SETTER(pi)
|
||||
INT_GETTER(pi)
|
||||
|
||||
INT_SETTER(pty)
|
||||
INT_GETTER(pty)
|
||||
|
||||
INT_SETTER(ecc)
|
||||
INT_GETTER(ecc)
|
||||
|
||||
INT_SETTER(slc_data)
|
||||
INT_GETTER(slc_data)
|
||||
|
||||
BOOL_SETTER(ct)
|
||||
BOOL_GETTER(ct)
|
||||
|
||||
BOOL_SETTER(dpty)
|
||||
BOOL_GETTER(dpty)
|
||||
|
||||
BOOL_SETTER(tp)
|
||||
BOOL_GETTER(tp)
|
||||
|
||||
BOOL_SETTER(ta)
|
||||
BOOL_GETTER(ta)
|
||||
|
||||
BOOL_SETTER(rt1_enabled)
|
||||
BOOL_GETTER(rt1_enabled)
|
||||
|
||||
BOOL_SETTER(rt2_enabled)
|
||||
BOOL_GETTER(rt2_enabled)
|
||||
|
||||
BOOL_SETTER(ptyn_enabled)
|
||||
BOOL_GETTER(ptyn_enabled)
|
||||
|
||||
INT_SETTER(rt_type)
|
||||
INT_GETTER(rt_type)
|
||||
|
||||
int lua_set_rds2_mode(lua_State *localL) {
|
||||
mod->enc->encoder_data.rds2_mode = luaL_checkinteger(localL, 1);
|
||||
return 0;
|
||||
}
|
||||
int lua_get_rds2_mode(lua_State *localL) {
|
||||
lua_pushinteger(localL, mod->enc->encoder_data.rds2_mode);
|
||||
return 1;
|
||||
}
|
||||
int lua_set_rds_streams(lua_State *localL) {
|
||||
mod->params.rdsgen = luaL_checkinteger(localL, 1);
|
||||
return 0;
|
||||
}
|
||||
int lua_get_rds_streams(lua_State *localL) {
|
||||
lua_pushinteger(localL, mod->params.rdsgen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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));
|
||||
mod->enc->state[mod->enc->program].eon_linkage = lua_toboolean(localL, 1);
|
||||
return 0;
|
||||
}
|
||||
int lua_get_rds_link(lua_State *localL) {
|
||||
lua_pushboolean(localL, mod->enc->state[mod->enc->program].eon_linkage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_set_rds_program(lua_State *localL) {
|
||||
int program = luaL_checkinteger(localL, 1);
|
||||
if(program >= PROGRAMS) program = (PROGRAMS-1);
|
||||
if(program < 0) program = 0;
|
||||
|
||||
if(mod->enc->program == program) return 0;
|
||||
|
||||
mod->enc->data[mod->enc->program].ta = 0;
|
||||
mod->enc->data[(uint8_t)program].ta = 0;
|
||||
mod->enc->program = (uint8_t)program;
|
||||
return 0;
|
||||
}
|
||||
int lua_get_rds_program(lua_State *localL) {
|
||||
lua_pushinteger(localL, mod->enc->program);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_set_rds_rt_switching_period(lua_State *localL) {
|
||||
mod->enc->data[mod->enc->program].rt_switching_period = luaL_checkinteger(localL, 1);
|
||||
mod->enc->state[mod->enc->program].rt_switching_period_state = mod->enc->data[mod->enc->program].rt_switching_period;
|
||||
return 0;
|
||||
}
|
||||
INT_GETTER(rt_switching_period)
|
||||
int lua_set_rds_rt_text_timeout(lua_State *localL) {
|
||||
mod->enc->data[mod->enc->program].rt_text_timeout = luaL_checkinteger(localL, 1);
|
||||
mod->enc->state[mod->enc->program].rt_text_timeout_state = mod->enc->data[mod->enc->program].rt_text_timeout;
|
||||
return 0;
|
||||
}
|
||||
INT_GETTER(rt_text_timeout)
|
||||
|
||||
int lua_set_rds_level(lua_State *localL) {
|
||||
mod->params.level = luaL_checknumber(localL, 1);
|
||||
return 0;
|
||||
}
|
||||
int lua_get_rds_level(lua_State *localL) {
|
||||
lua_pushnumber(localL, mod->params.level);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_put_rds_custom_group(lua_State *localL) {
|
||||
mod->enc->state[mod->enc->program].custom_group[0] = 1;
|
||||
mod->enc->state[mod->enc->program].custom_group[1] = luaL_checkinteger(localL, 1);
|
||||
mod->enc->state[mod->enc->program].custom_group[2] = luaL_checkinteger(localL, 2);
|
||||
mod->enc->state[mod->enc->program].custom_group[3] = luaL_checkinteger(localL, 3);
|
||||
return 0;
|
||||
}
|
||||
int lua_put_rds2_custom_group(lua_State *localL) {
|
||||
mod->enc->state[mod->enc->program].custom_group2[0] = 1;
|
||||
mod->enc->state[mod->enc->program].custom_group2[1] = luaL_checkinteger(localL, 1);
|
||||
mod->enc->state[mod->enc->program].custom_group2[2] = luaL_checkinteger(localL, 2);
|
||||
mod->enc->state[mod->enc->program].custom_group2[3] = luaL_checkinteger(localL, 3);
|
||||
mod->enc->state[mod->enc->program].custom_group2[4] = luaL_checkinteger(localL, 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STR_SETTER(ptyn, set_rds_ptyn)
|
||||
STR_SETTER(ps, set_rds_ps)
|
||||
STR_SETTER(tps, set_rds_tps)
|
||||
STR_SETTER(rt1, set_rds_rt1)
|
||||
STR_SETTER(rt2, set_rds_rt2)
|
||||
STR_SETTER(default_rt, set_rds_default_rt)
|
||||
|
||||
STR_RAW_SETTER(lps, set_rds_lps)
|
||||
STR_RAW_GETTER(lps, LPS_LENGTH)
|
||||
|
||||
STR_RAW_SETTER(grp_sqc_rds2, set_rds_grpseq2)
|
||||
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(mod->enc, DEFAULT_GRPSQC);
|
||||
else set_rds_grpseq(mod->enc, str);
|
||||
return 0;
|
||||
}
|
||||
STR_RAW_GETTER(grp_sqc, 32)
|
||||
|
||||
AF_SETTER(af_group0, af, RDSAFs, add_rds_af)
|
||||
|
||||
int lua_set_rds_eon(lua_State *localL) {
|
||||
int eon = luaL_checkinteger(localL, 1);
|
||||
if(eon >= EONs) return luaL_error(localL, "eon index exceeded");
|
||||
if (!lua_isboolean(localL, 2)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 2));
|
||||
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);
|
||||
mod->enc->data[mod->enc->program].eon[eon].enabled = lua_toboolean(localL, 2);
|
||||
mod->enc->data[mod->enc->program].eon[eon].pi = luaL_checkinteger(localL, 3);
|
||||
mod->enc->data[mod->enc->program].eon[eon].tp = lua_toboolean(localL, 4);
|
||||
mod->enc->data[mod->enc->program].eon[eon].ta = lua_toboolean(localL, 5);
|
||||
mod->enc->data[mod->enc->program].eon[eon].pty = luaL_checkinteger(localL, 6);
|
||||
_strncpy(mod->enc->data[mod->enc->program].eon[eon].ps, luaL_checklstring(localL, 7, NULL), 8);
|
||||
|
||||
int n = lua_rawlen(localL, 8);
|
||||
if (n == 0) {
|
||||
memset(&(mod->enc->data[mod->enc->program].eon[eon].af), 0, sizeof(RDSAFs));
|
||||
return 0;
|
||||
}
|
||||
if(n > 25) return luaL_error(localL, "table length over 25");
|
||||
|
||||
RDSAFs new_af;
|
||||
memset(&new_af, 0, sizeof(RDSAFs));
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
lua_rawgeti(localL, 8, i);
|
||||
if (lua_isnumber(localL, -1)) add_rds_af(&new_af, lua_tonumber(localL, -1));
|
||||
else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
memcpy(&(mod->enc->data[mod->enc->program].eon[eon].af), &new_af, sizeof(new_af));
|
||||
|
||||
mod->enc->data[mod->enc->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, mod->enc->data[mod->enc->program].eon[eon].enabled);
|
||||
lua_pushinteger(localL, mod->enc->data[mod->enc->program].eon[eon].pi);
|
||||
lua_pushboolean(localL, mod->enc->data[mod->enc->program].eon[eon].tp);
|
||||
lua_pushboolean(localL, mod->enc->data[mod->enc->program].eon[eon].ta);
|
||||
lua_pushinteger(localL, mod->enc->data[mod->enc->program].eon[eon].pty);
|
||||
lua_pushlstring(localL, mod->enc->data[mod->enc->program].eon[eon].ps, 8);
|
||||
lua_createtable(localL, 0, 0); // don't have decoding for AF, so just return empty table
|
||||
lua_pushinteger(localL, mod->enc->data[mod->enc->program].eon[eon].data);
|
||||
return 8;
|
||||
}
|
||||
|
||||
int lua_set_rds_udg(lua_State *localL) {
|
||||
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
|
||||
int xy = lua_toboolean(localL, 1);
|
||||
luaL_checktype(localL, 2, LUA_TTABLE);
|
||||
int n = lua_rawlen(localL, 2);
|
||||
if(n > 8) return luaL_error(localL, "table length over 8");
|
||||
|
||||
uint16_t blocks[8][3] = {0};
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
lua_rawgeti(localL, 2, i);
|
||||
if(lua_istable(localL, -1)) {
|
||||
int n2 = lua_rawlen(localL, -1);
|
||||
if(n2 > 3) return luaL_error(localL, "table length over 3");
|
||||
for(int j = 1; j <= n2; j++) {
|
||||
lua_rawgeti(localL, -1, j);
|
||||
if (lua_isinteger(localL, -1)) blocks[i-1][j-1] = lua_tointeger(localL, -1);
|
||||
else return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
}
|
||||
else return luaL_error(localL, "table expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
|
||||
if(xy) {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg2), blocks, n * sizeof(uint16_t[3]));
|
||||
mod->enc->data[mod->enc->program].udg2_len = n;
|
||||
} else {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg1), blocks, n * sizeof(uint16_t[3]));
|
||||
mod->enc->data[mod->enc->program].udg1_len = n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
int lua_set_rds_udg2(lua_State *localL) {
|
||||
if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1));
|
||||
int xy = lua_toboolean(localL, 1);
|
||||
luaL_checktype(localL, 2, LUA_TTABLE);
|
||||
int n = lua_rawlen(localL, 2);
|
||||
if(n > 8) return luaL_error(localL, "table length over 8");
|
||||
|
||||
uint16_t blocks[8][4] = {0};
|
||||
|
||||
for (int i = 1; i <= n; i++) {
|
||||
lua_rawgeti(localL, 2, i);
|
||||
if(lua_istable(localL, -1)) {
|
||||
int n2 = lua_rawlen(localL, -1);
|
||||
if(n2 > 4) return luaL_error(localL, "table length over 4");
|
||||
for(int j = 1; j <= n2; j++) {
|
||||
lua_rawgeti(localL, -1, j);
|
||||
if (lua_isinteger(localL, -1)) blocks[i-1][j-1] = lua_tointeger(localL, -1);
|
||||
else return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
}
|
||||
else return luaL_error(localL, "table expected, got %s", luaL_typename(localL, -1));
|
||||
lua_pop(localL, 1);
|
||||
}
|
||||
|
||||
if(xy) {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg2_rds2), blocks, n * sizeof(uint16_t[4]));
|
||||
mod->enc->data[mod->enc->program].udg2_len_rds2 = n;
|
||||
} else {
|
||||
memcpy(&(mod->enc->data[mod->enc->program].udg1_rds2), blocks, n * sizeof(uint16_t[4]));
|
||||
mod->enc->data[mod->enc->program].udg1_len_rds2 = n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lua_get_available_rds_streams(lua_State *localL) {
|
||||
lua_pushinteger(localL, mod->num_streams);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_crc16(lua_State *localL) {
|
||||
size_t len;
|
||||
const char* data = luaL_checklstring(localL, 1, &len);
|
||||
lua_pushinteger(localL, crc16_ccitt(data, len));
|
||||
return 1;
|
||||
}
|
||||
uint8_t unload_refs[33] = {LUA_REFNIL};
|
||||
|
||||
#define lua_registertotable(L,n,f) (lua_pushcfunction(L, (f)), lua_setfield(L, -2, (n)))
|
||||
void init_lua(RDSModulator* rds_mod) {
|
||||
static int mutex_initialized = 0;
|
||||
mod = rds_mod;
|
||||
@@ -430,109 +25,131 @@ void init_lua(RDSModulator* rds_mod) {
|
||||
|
||||
lua_pushstring(L, VERSION);
|
||||
lua_setglobal(L, "core_version");
|
||||
lua_pushinteger(L, PROGRAMS);
|
||||
lua_setglobal(L, "max_programs");
|
||||
lua_pushinteger(L, EONs);
|
||||
lua_setglobal(L, "eon_count");
|
||||
|
||||
lua_newtable(L);
|
||||
lua_setglobal(L, "ext");
|
||||
|
||||
lua_newtable(L);
|
||||
lua_setglobal(L, "on_inits");
|
||||
lua_newtable(L);
|
||||
lua_setglobal(L, "on_starts");
|
||||
lua_newtable(L);
|
||||
lua_setglobal(L, "on_states");
|
||||
lua_newtable(L);
|
||||
lua_setglobal(L, "ticks");
|
||||
|
||||
lua_newtable(L);
|
||||
lua_registertotable(L, "get", lua_get_userdata);
|
||||
lua_registertotable(L, "get_offset", lua_get_userdata_offset);
|
||||
lua_registertotable(L, "set", lua_set_userdata);
|
||||
lua_registertotable(L, "set_offset", lua_set_userdata_offset);
|
||||
lua_pushinteger(L, LUA_USER_DATA);
|
||||
lua_setglobal(L, "user_data_len");
|
||||
lua_setfield(L, -2, "len");
|
||||
lua_setglobal(L, "userdata");
|
||||
|
||||
lua_register(L, "set_rds_program_defaults", lua_set_rds_program_defaults);
|
||||
lua_register(L, "reset_rds", lua_reset_rds);
|
||||
lua_register(L, "force_save", lua_force_save);
|
||||
lua_newtable(L);
|
||||
lua_registertotable(L, "crc16", lua_crc16);
|
||||
lua_registertotable(L, "force_save", lua_force_save);
|
||||
lua_registertotable(L, "reset_rds", lua_reset_rds);
|
||||
lua_registertotable(L, "set_rds_program_defaults", lua_set_rds_program_defaults);
|
||||
lua_pushinteger(L, PROGRAMS);
|
||||
lua_setfield(L, -2, "max_programs");
|
||||
lua_registertotable(L, "set_rds_program", lua_set_rds_program);
|
||||
lua_registertotable(L, "get_rds_program", lua_get_rds_program);
|
||||
lua_setglobal(L, "dp");
|
||||
|
||||
lua_register(L, "set_rds_pi", lua_set_rds_pi);
|
||||
lua_register(L, "get_rds_pi", lua_get_rds_pi);
|
||||
lua_newtable(L);
|
||||
|
||||
lua_register(L, "set_rds_pty", lua_set_rds_pty);
|
||||
lua_register(L, "get_rds_pty", lua_get_rds_pty);
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, -2, "ext");
|
||||
|
||||
lua_register(L, "set_rds_ecc", lua_set_rds_ecc);
|
||||
lua_register(L, "get_rds_ecc", lua_get_rds_ecc);
|
||||
lua_pushinteger(L, EONs);
|
||||
lua_setfield(L, -2, "eon_count");
|
||||
|
||||
lua_register(L, "set_rds_slc_data", lua_set_rds_slc_data);
|
||||
lua_register(L, "get_rds_slc_data", lua_get_rds_slc_data);
|
||||
lua_registertotable(L, "set_pi", lua_set_rds_pi);
|
||||
lua_registertotable(L, "get_pi", lua_get_rds_pi);
|
||||
|
||||
lua_register(L, "set_rds_ct", lua_set_rds_ct);
|
||||
lua_register(L, "get_rds_ct", lua_get_rds_ct);
|
||||
lua_registertotable(L, "set_pty", lua_set_rds_pty);
|
||||
lua_registertotable(L, "get_pty", lua_get_rds_pty);
|
||||
|
||||
lua_register(L, "set_rds_dpty", lua_set_rds_dpty);
|
||||
lua_register(L, "get_rds_dpty", lua_get_rds_dpty);
|
||||
lua_registertotable(L, "set_ecc", lua_set_rds_ecc);
|
||||
lua_registertotable(L, "get_ecc", lua_get_rds_ecc);
|
||||
|
||||
lua_register(L, "set_rds_tp", lua_set_rds_tp);
|
||||
lua_register(L, "get_rds_tp", lua_get_rds_tp);
|
||||
lua_registertotable(L, "set_slc_data", lua_set_rds_slc_data);
|
||||
lua_registertotable(L, "get_slc_data", lua_get_rds_slc_data);
|
||||
|
||||
lua_register(L, "set_rds_ta", lua_set_rds_ta);
|
||||
lua_register(L, "get_rds_ta", lua_get_rds_ta);
|
||||
lua_registertotable(L, "set_ct", lua_set_rds_ct);
|
||||
lua_registertotable(L, "get_ct", lua_get_rds_ct);
|
||||
|
||||
lua_register(L, "set_rds_rt1_enabled", lua_set_rds_rt1_enabled);
|
||||
lua_register(L, "get_rds_rt1_enabled", lua_get_rds_rt1_enabled);
|
||||
lua_registertotable(L, "set_dpty", lua_set_rds_dpty);
|
||||
lua_registertotable(L, "get_dpty", lua_get_rds_dpty);
|
||||
|
||||
lua_register(L, "set_rds_rt2_enabled", lua_set_rds_rt2_enabled);
|
||||
lua_register(L, "get_rds_rt2_enabled", lua_get_rds_rt2_enabled);
|
||||
lua_registertotable(L, "set_tp", lua_set_rds_tp);
|
||||
lua_registertotable(L, "get_tp", lua_get_rds_tp);
|
||||
|
||||
lua_register(L, "set_rds_ptyn_enabled", lua_set_rds_ptyn_enabled);
|
||||
lua_register(L, "get_rds_ptyn_enabled", lua_get_rds_ptyn_enabled);
|
||||
lua_registertotable(L, "set_ta", lua_set_rds_ta);
|
||||
lua_registertotable(L, "get_ta", lua_get_rds_ta);
|
||||
|
||||
lua_register(L, "set_rds_rt_type", lua_set_rds_rt_type);
|
||||
lua_register(L, "get_rds_rt_type", lua_get_rds_rt_type);
|
||||
lua_registertotable(L, "set_rt1_enabled", lua_set_rds_rt1_enabled);
|
||||
lua_registertotable(L, "get_rt1_enabled", lua_get_rds_rt1_enabled);
|
||||
|
||||
lua_register(L, "set_rds2_mode", lua_set_rds2_mode);
|
||||
lua_register(L, "get_rds2_mode", lua_get_rds2_mode);
|
||||
lua_registertotable(L, "set_rt2_enabled", lua_set_rds_rt2_enabled);
|
||||
lua_registertotable(L, "get_rt2_enabled", lua_get_rds_rt2_enabled);
|
||||
|
||||
lua_registertotable(L, "set_ptyn_enabled", lua_set_rds_ptyn_enabled);
|
||||
lua_registertotable(L, "get_ptyn_enabled", lua_get_rds_ptyn_enabled);
|
||||
|
||||
lua_registertotable(L, "set_rt_type", lua_set_rds_rt_type);
|
||||
lua_registertotable(L, "get_rt_type", lua_get_rds_rt_type);
|
||||
|
||||
lua_registertotable(L, "set_rds2_mode", lua_set_rds2_mode);
|
||||
lua_registertotable(L, "get_rds2_mode", lua_get_rds2_mode);
|
||||
|
||||
lua_registertotable(L, "set_link", lua_set_rds_link);
|
||||
lua_registertotable(L, "get_link", lua_get_rds_link);
|
||||
|
||||
lua_registertotable(L, "set_rt_switching_period", lua_set_rds_rt_switching_period);
|
||||
lua_registertotable(L, "get_rt_switching_period", lua_get_rds_rt_switching_period);
|
||||
|
||||
lua_registertotable(L, "set_rt_text_timeout", lua_set_rds_rt_text_timeout);
|
||||
lua_registertotable(L, "get_rt_text_timeout", lua_get_rds_rt_text_timeout);
|
||||
|
||||
lua_registertotable(L, "set_ptyn", lua_set_rds_ptyn);
|
||||
lua_registertotable(L, "set_ps", lua_set_rds_ps);
|
||||
lua_registertotable(L, "set_tps", lua_set_rds_tps);
|
||||
lua_registertotable(L, "set_rt1", lua_set_rds_rt1);
|
||||
lua_registertotable(L, "set_rt2", lua_set_rds_rt2);
|
||||
lua_registertotable(L, "set_default_rt", lua_set_rds_default_rt);
|
||||
|
||||
lua_registertotable(L, "set_lps", lua_set_rds_lps);
|
||||
lua_registertotable(L, "get_lps", lua_get_rds_lps);
|
||||
|
||||
lua_registertotable(L, "set_grpseq", lua_set_rds_grp_sqc);
|
||||
lua_registertotable(L, "get_grpseq", lua_get_rds_grp_sqc);
|
||||
|
||||
lua_registertotable(L, "set_grpseq2", lua_set_rds_grp_sqc_rds2);
|
||||
lua_registertotable(L, "get_grpseq2", lua_get_rds_grp_sqc_rds2);
|
||||
|
||||
lua_registertotable(L, "put_custom_group", lua_put_rds_custom_group);
|
||||
lua_registertotable(L, "put_rds2_custom_group", lua_put_rds2_custom_group);
|
||||
|
||||
lua_registertotable(L, "set_af", lua_set_rds_af_group0);
|
||||
|
||||
lua_registertotable(L, "set_eon", lua_set_rds_eon);
|
||||
lua_registertotable(L, "get_eon", lua_get_rds_eon);
|
||||
|
||||
lua_registertotable(L, "set_udg", lua_set_rds_udg);
|
||||
lua_registertotable(L, "set_udg2", lua_set_rds_udg2);
|
||||
|
||||
lua_setglobal(L, "rds");
|
||||
|
||||
lua_register(L, "set_rds_streams", lua_set_rds_streams);
|
||||
lua_register(L, "get_rds_streams", lua_get_rds_streams);
|
||||
lua_register(L, "get_available_rds_streams", lua_get_available_rds_streams);
|
||||
|
||||
lua_register(L, "set_rds_grpseq", lua_set_rds_grp_sqc);
|
||||
lua_register(L, "get_rds_grpseq", lua_get_rds_grp_sqc);
|
||||
|
||||
lua_register(L, "set_rds_grpseq2", lua_set_rds_grp_sqc_rds2);
|
||||
lua_register(L, "get_rds_grpseq2", lua_get_rds_grp_sqc_rds2);
|
||||
|
||||
lua_register(L, "set_rds_link", lua_set_rds_link);
|
||||
lua_register(L, "get_rds_link", lua_get_rds_link);
|
||||
|
||||
lua_register(L, "set_rds_program", lua_set_rds_program);
|
||||
lua_register(L, "get_rds_program", lua_get_rds_program);
|
||||
|
||||
lua_register(L, "set_rds_rt_switching_period", lua_set_rds_rt_switching_period);
|
||||
lua_register(L, "get_rds_rt_switching_period", lua_get_rds_rt_switching_period);
|
||||
|
||||
lua_register(L, "set_rds_rt_text_timeout", lua_set_rds_rt_text_timeout);
|
||||
lua_register(L, "get_rds_rt_text_timeout", lua_get_rds_rt_text_timeout);
|
||||
|
||||
lua_register(L, "set_rds_level", lua_set_rds_level);
|
||||
lua_register(L, "get_rds_level", lua_get_rds_level);
|
||||
|
||||
lua_register(L, "set_rds_ptyn", lua_set_rds_ptyn);
|
||||
lua_register(L, "set_rds_ps", lua_set_rds_ps);
|
||||
lua_register(L, "set_rds_tps", lua_set_rds_tps);
|
||||
lua_register(L, "set_rds_rt1", lua_set_rds_rt1);
|
||||
lua_register(L, "set_rds_rt2", lua_set_rds_rt2);
|
||||
lua_register(L, "set_rds_default_rt", lua_set_rds_default_rt);
|
||||
|
||||
lua_register(L, "set_rds_lps", lua_set_rds_lps);
|
||||
lua_register(L, "get_rds_lps", lua_get_rds_lps);
|
||||
|
||||
lua_register(L, "put_rds_custom_group", lua_put_rds_custom_group);
|
||||
lua_register(L, "put_rds2_custom_group", lua_put_rds2_custom_group);
|
||||
|
||||
lua_register(L, "set_rds_af_group0", lua_set_rds_af_group0);
|
||||
|
||||
lua_register(L, "set_rds_eon", lua_set_rds_eon);
|
||||
lua_register(L, "get_rds_eon", lua_get_rds_eon);
|
||||
|
||||
lua_register(L, "set_rds_udg", lua_set_rds_udg);
|
||||
lua_register(L, "set_rds_udg2", lua_set_rds_udg2);
|
||||
|
||||
lua_register(L, "set_userdata", lua_set_userdata);
|
||||
lua_register(L, "set_userdata_offset", lua_set_userdata_offset);
|
||||
lua_register(L, "get_userdata", lua_get_userdata);
|
||||
lua_register(L, "get_userdata_offset", lua_get_userdata_offset);
|
||||
|
||||
lua_register(L, "crc16", lua_crc16);
|
||||
|
||||
if (luaL_loadfile(L, "/etc/rds95.lua") != LUA_OK) {
|
||||
fprintf(stderr, "Lua error loading file: %s\n", lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
@@ -562,6 +179,7 @@ void run_lua(char *str, char *cmd_output, size_t* out_len) {
|
||||
lua_pop(L, 1);
|
||||
pthread_mutex_unlock(&lua_mutex);
|
||||
}
|
||||
|
||||
int lua_group(RDSGroup* group, const char grp) {
|
||||
pthread_mutex_lock(&lua_mutex);
|
||||
lua_getglobal(L, "group");
|
||||
@@ -703,7 +321,58 @@ void lua_call_function(const char* function) {
|
||||
pthread_mutex_unlock(&lua_mutex);
|
||||
}
|
||||
|
||||
void destroy_lua(void) {
|
||||
void lua_call_table_nolock(const char *table_name) {
|
||||
lua_getglobal(L, table_name);
|
||||
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
lua_Integer len = lua_rawlen(L, -1);
|
||||
for (lua_Integer i = 1; i <= len; i++) {
|
||||
lua_rawgeti(L, -1, i);
|
||||
if (lua_isfunction(L, -1)) {
|
||||
if (lua_pcall(L, 0, 0, 0) != LUA_OK) {
|
||||
fprintf(stderr,
|
||||
"Lua error: %s at '%s[%lld]'\n",
|
||||
lua_tostring(L, -1),
|
||||
table_name,
|
||||
(long long)i);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1); // pop table
|
||||
}
|
||||
void lua_call_table(const char* function) {
|
||||
int need_lock = (pthread_mutex_trylock(&lua_mutex) == 0);
|
||||
if (!need_lock) {
|
||||
fprintf(stderr, "Warning: lua_mutex already locked when table calling %s\n", function);
|
||||
return;
|
||||
}
|
||||
lua_call_table_nolock(function);
|
||||
pthread_mutex_unlock(&lua_mutex);
|
||||
}
|
||||
|
||||
void lua_call_tfunction_nolock(const char* name) {
|
||||
char table_name[256];
|
||||
lua_call_function_nolock(name);
|
||||
snprintf(table_name, sizeof(table_name), "%ss", name);
|
||||
lua_call_table_nolock(table_name);
|
||||
}
|
||||
|
||||
void lua_call_tfunction(const char* name) {
|
||||
int need_lock = (pthread_mutex_trylock(&lua_mutex) == 0);
|
||||
if (!need_lock) {
|
||||
fprintf(stderr, "Warning: lua_mutex already locked when table tcalling %s\n", name);
|
||||
return;
|
||||
}
|
||||
lua_call_tfunction_nolock(name);
|
||||
pthread_mutex_unlock(&lua_mutex);
|
||||
}
|
||||
|
||||
void destroy_lua() {
|
||||
if (L) {
|
||||
for (int i = 1; i < *unload_refs; i++) luaL_unref(L, LUA_REGISTRYINDEX, unload_refs[i]);
|
||||
*unload_refs = 1;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
#include "rds.h"
|
||||
#include "modulator.h"
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
#include "rds.h"
|
||||
#include "fs.h"
|
||||
#include "modulator.h"
|
||||
|
||||
void init_lua(RDSModulator* rds_mod);
|
||||
void run_lua(char *str, char *cmd_output, size_t* out_len);
|
||||
@@ -12,5 +12,9 @@ int lua_group(RDSGroup* group, const char grp);
|
||||
int lua_rds2_group(RDSGroup* group, int stream);
|
||||
void lua_call_function_nolock(const char* function);
|
||||
void lua_call_function(const char* function);
|
||||
void lua_call_table_nolock(const char *table_name);
|
||||
void lua_call_table(const char* function);
|
||||
void lua_call_tfunction_nolock(const char* name);
|
||||
void lua_call_tfunction(const char* name);
|
||||
void lua_group_ref(RDSGroup* group, int ref);
|
||||
void destroy_lua();
|
||||
@@ -155,7 +155,7 @@ void get_rds_group(RDSEncoder* enc, RDSGroup *group, uint8_t stream) {
|
||||
}
|
||||
}
|
||||
|
||||
lua_call_function("tick");
|
||||
lua_call_tfunction("tick");
|
||||
}
|
||||
|
||||
if (utc->tm_min != enc->state[enc->program].last_minute) {
|
||||
@@ -378,10 +378,10 @@ void init_rds_encoder(RDSEncoder* enc) {
|
||||
|
||||
if (encoder_loadFromFile(enc)) {
|
||||
printf("Encoder file will be reinitialized.\n");
|
||||
lua_call_function("on_init");
|
||||
lua_call_tfunction("on_init");
|
||||
}
|
||||
for(int i = 0; i < PROGRAMS; i++) reset_rds_state(enc, i);
|
||||
lua_call_function("on_start");
|
||||
lua_call_function("on_state");
|
||||
lua_call_tfunction("on_start");
|
||||
lua_call_tfunction("on_state");
|
||||
encoder_saveToFile(enc);
|
||||
}
|
||||
23
src/rds95.c
23
src/rds95.c
@@ -101,12 +101,12 @@ int main(int argc, char **argv) {
|
||||
|
||||
const char *short_opt = "c:ah";
|
||||
|
||||
struct option long_opt[] =
|
||||
struct option long_opt[] =
|
||||
{
|
||||
{"config", required_argument, NULL, 'c'},
|
||||
{"asciig", no_argument, NULL, 'a'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{ 0, 0, 0, 0 }
|
||||
{"config", required_argument, NULL, 'c'},
|
||||
{"asciig", no_argument, NULL, 'a'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int opt;
|
||||
@@ -144,7 +144,6 @@ int main(int argc, char **argv) {
|
||||
pthread_attr_init(&attr);
|
||||
|
||||
struct sigaction sa_stop;
|
||||
|
||||
sa_stop.sa_handler = stop;
|
||||
sigemptyset(&sa_stop.sa_mask);
|
||||
sa_stop.sa_flags = 0;
|
||||
@@ -160,17 +159,7 @@ int main(int argc, char **argv) {
|
||||
buffer.tlength = buffer.maxlength = NUM_MPX_FRAMES * config.num_streams;
|
||||
|
||||
if(config.asciig == 0) {
|
||||
rds_device = pa_simple_new(
|
||||
NULL,
|
||||
"rds95",
|
||||
PA_STREAM_PLAYBACK,
|
||||
config.rds_device_name,
|
||||
"RDS Generator",
|
||||
&format,
|
||||
NULL,
|
||||
&buffer,
|
||||
NULL
|
||||
);
|
||||
rds_device = pa_simple_new(NULL, "rds95", PA_STREAM_PLAYBACK, config.rds_device_name, "RDS Generator", &format, NULL, &buffer, NULL);
|
||||
if (rds_device == NULL) {
|
||||
fprintf(stderr, "Error: cannot open sound device.\n");
|
||||
goto exit;
|
||||
|
||||
Reference in New Issue
Block a user