A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1
2--RB LUA show all global variables; BILGUS
3if not ... then --if executed directly this is nil
4 require "actions"
5 require "audio"
6 require "buttons"
7 require "color"
8 require "draw"
9 require "draw_floodfill"
10 require "draw_poly"
11 require "draw_text"
12
13 require "image"
14 require "image_save"
15
16 require "lcd"
17 require "math_ex"
18 require "pcm"
19 require "playlist"
20 require "print"
21 --require "settings" --uses a lot of memory
22 require "sound"
23end
24collectgarbage("collect")
25
26local sDumpFile = "/rb-lua_functions.txt"
27local filehandle
28
29local function a2m_m2a(addr_member)
30 --turns members into addresses; addresses back into members
31 return addr_member
32end
33
34local function dtTag(sType)
35--convert named type; 'number'.. to short type '[n]...'
36--if '?' supplied print out datatype key; number = [n]...
37 local retType = "?"
38 local typ = {
39 ["nil"] = "nil",
40 ["boolean"] = "b",
41 ["number"] = "n",
42 ["string"] = "s",
43 ["userdata"] = "u",
44 ["function"] = "f",
45 ["thread"] = "thr",
46 ["table"] = "t"
47 }
48 if sType == "?" then retType = "Datatypes: " end
49 for k,v in pairs(typ) do
50 if sType == k then
51 retType = v break
52 elseif (sType == "?") then
53 retType = retType .. " [" ..v.. "] = " .. k
54 end
55 end
56 return " [" ..retType.. "] "
57end
58
59local function tableByName(tName)
60 --find the longest match possible to an actual table
61 --Name comes in as (table) tName.var so we can pass back out the name found PITA
62 --returns the table found (key and value)
63 local ld = {}
64 local sMatch = ""
65 local kMatch = nil
66 local vMatch = nil
67
68----FUNCTIONS for tableByName -----------------------------------------------------
69 local function search4Str(n, k, v)
70 local sKey = tostring(k)
71 if string.find (n, sKey,1,true) then
72 if sKey:len() > sMatch:len() then sMatch = sKey kMatch = k vMatch = v end
73 --find the longest match we can
74 end
75 end
76----END FUNCTIONS for tableByName -------------------------------------------------
77
78 if tName.val ~= nil and tName.val ~= "" then
79 for k, v in pairs(_G) do
80 --_G check both since some tables are only in _G or package.loaded
81 search4Str(tName.val, k, v)
82 end
83 for k, v in pairs(package.loaded) do --package.loaded
84 search4Str(tName.val, k, v)
85 end
86 if not string.find (sMatch, "_G",1,true) then sMatch = "_G." .. sMatch end
87 -- put the root _G in if not exist
88 if kMatch and vMatch then ld[kMatch] = vMatch tName.val = sMatch return ld end
89 end
90 tName.val = "_G"
91 return package.loaded --Not Found return default
92end
93
94local function dump_Tables(tBase, sFunc, tSeen, tRet)
95 --Based on: http://www.lua.org/cgi-bin/demo?globals
96 --Recurse through tBase tables copying all found Tables
97 local sSep=""
98 local ld={}
99 local tNameBuf = {}
100 local sName
101 if sFunc ~= "" then sSep = "." end
102
103 for k, v in pairs(tBase) do
104 k = tostring(k)
105 tNameBuf[1] = sFunc
106 tNameBuf[2] = sSep
107 tNameBuf[3] = k
108
109
110 if k ~= "loaded" and type(v) == "table" and not tSeen[v] then
111 tSeen[v]=sFunc
112 sName = table.concat(tNameBuf)
113 tRet[sName] = a2m_m2a(v) --place all keys into ld[i]=value
114 dump_Tables(v, sName, tSeen, tRet)
115 elseif type(v) == "table" and not tSeen[v] then
116 tSeen[v]=sFunc
117 tRet[table.concat(tNameBuf)] = a2m_m2a(v) -- dump 'loaded' table
118 for k1, v1 in pairs(v) do
119 if not _G[k1] and type(v1) == "table" and not tSeen[v1] then
120 -- dump tables that are loaded but not global
121 tSeen[v1]=sFunc
122 tNameBuf[3] = k1
123 sName = table.concat(tNameBuf)
124 tRet[sName] = a2m_m2a(v1) --place all keys into ld[i]=value
125 dump_Tables(v1, sName, tSeen, tRet)
126 end
127 end
128 end
129 end
130end
131
132local function dump_Functions(tBase)
133 --Based on: http://www.lua.org/cgi-bin/demo?globals
134 --We already recursed through tBase copying all found tables
135 --we look up the table by name and then (ab)use a2m_m2a() to load the address
136 --after finding the table by address in tBase we will
137 --put the table address of tFuncs in its place
138 local tFuncBuf = {}
139 for k,v in pairs(tBase) do
140 local tTable = a2m_m2a(v)
141 local tFuncs = {}
142
143 for key, val in pairs(tTable) do
144 if key ~= "loaded" then
145 tFuncBuf[1] = dtTag(type(val))
146 tFuncBuf[2] = tostring(key)
147 tFuncs[table.concat(tFuncBuf)]= val
148 --put the name and value in our tFuncs table
149 end
150 end
151 tBase[k] = a2m_m2a(tFuncs) -- copy the address back to tBase
152 end
153
154end
155
156local function get_common_branches(t, tRet)
157 --load t 'names(values)' into keys
158 --strip off long paths then iterate value if it exists
159 --local tRet={}
160 local sBranch = ""
161 local tName = {}
162 for k in pairs(t) do
163 tName["val"]=k
164 tableByName(tName)
165 sBranch = tName.val
166 if tRet[sBranch] == nil then
167 tRet[sBranch] = 1 --first instance of this branch
168 else
169 tRet[sBranch] = tRet[sBranch] + 1
170 end
171 end
172end
173
174local function pairsByPairs (t, tkSorted)
175 --tkSorted should be an already sorted (i)table with t[keys] in the values
176 --https://www.lua.org/pil/19.3.html
177 --!!Note: table sort default function does not like numbers as [KEY]!!
178 --see *sortbyKeys*cmp_alphanum*
179
180 local i = 0 -- iterator variable
181 local iter = function () -- iterator function
182 i = i + 1
183 if tkSorted[i] == nil then return nil
184 else return tkSorted[i], t[tkSorted[i]]
185 end
186 end
187 return iter
188end
189
190local function sortbyKeys(t, tkSorted)
191 --loads keys of (t) into values of tkSorted
192 --and then sorts them
193 --tkSorted has integer keys (see ipairs)
194----FUNCTIONS for sortByKeys -------------
195 local cmp_alphanum = function (op1, op2)
196 local type1= type(op1)
197 local type2 = type(op2)
198 if type1 ~= type2 then
199 return type1 < type2
200 else
201 return op1 < op2
202 end
203 end
204----END FUNCTIONS for sortByKeys ---------
205 for n in pairs(t) do table.insert(tkSorted, n) end
206 table.sort(tkSorted, cmp_alphanum)--table.sort(tkSorted)
207end
208
209local function funcprint(tBuf, strName, value)
210 local sType = type(value)
211 local sVal = ""
212 local sHex = ""
213 tBuf[#tBuf + 1] = "\t"
214 tBuf[#tBuf + 1] = strName
215 if nil ~= string.find (";string;number;userdata;boolean;", sType, 1, true) then
216 --If any of the above types print the contents of variable
217 sVal = tostring(value)
218
219 if type(value) == "number" then
220 sHex = " = 0x" .. string.format("%x", value)
221 else
222 sHex = ""
223 sVal = string.gsub(sVal, "\n", "\\n") --replace newline with \n
224 end
225 tBuf[#tBuf + 1] = " : "
226 tBuf[#tBuf + 1] = sVal
227 tBuf[#tBuf + 1] = sHex
228 end
229 tBuf[#tBuf + 1] = "\r\n"
230end
231
232local function errorHandler( err )
233 filehandle:write(" ERROR:" .. err .. "\n")
234end
235
236
237------------MAIN----------------------------------------------------------------
238 local _NIL = nil
239 local tSeen= {}
240 local tcBase = {}
241 local tkSortCbase = {}
242 local tMods= {}
243 local tkSortMods = {}
244 local tWriteBuf = {}
245 local n = 0 -- count of how many items were found
246
247 filehandle = io.open(sDumpFile, "w+") --overwrite
248 tWriteBuf[#tWriteBuf + 1] = "*Loaded Modules* \n"
249
250 xpcall( function()
251 dump_Tables(tableByName({["val"] = "_G"}),"", tSeen, tMods)
252 --you can put a table name here if you just wanted to display
253 --only its items, ex. "os" or "rb" or "io"
254 --However, it has to be accessible directly from _G
255 --so "rb.actions" wouldn't return anything since its technically
256 --enumerated through _G.rb
257 end , errorHandler )
258 tSeen = nil
259
260 xpcall( function()dump_Functions(tMods)end , errorHandler )
261
262 get_common_branches(tMods, tcBase)
263
264 sortbyKeys(tcBase, tkSortCbase)
265 sortbyKeys(tMods, tkSortMods)
266
267 for k, v in pairsByPairs(tcBase, tkSortCbase ) do
268 n = n + 1
269 if n ~= 1 then
270 tWriteBuf[#tWriteBuf + 1] = ", "
271 end
272 tWriteBuf[#tWriteBuf + 1] = tostring(k)
273 if n >= 3 then -- split loaded modules to multiple lines
274 n = 0
275 tWriteBuf[#tWriteBuf + 1] = "\r\n"
276 end
277 if #tWriteBuf > 25 then
278 filehandle:write(table.concat(tWriteBuf))
279 for i=1, #tWriteBuf do tWriteBuf[i] = _NIL end -- reuse table
280 end
281 end
282 if ... then
283 tcBase= nil tkSortCbase= nil
284 end
285 tWriteBuf[#tWriteBuf + 1] = "\r\n"
286 tWriteBuf[#tWriteBuf + 1] = dtTag("?")
287 tWriteBuf[#tWriteBuf + 1] = "\r\n\r\n"
288 tWriteBuf[#tWriteBuf + 1] = "Functions: \r\n"
289
290 n = 0
291 for key, val in pairsByPairs(tMods, tkSortMods) do
292 local tkSorted = {}
293 local tFuncs = a2m_m2a(val)
294 sortbyKeys(tFuncs, tkSorted)
295 tWriteBuf[#tWriteBuf + 1] = "\r\n"
296 tWriteBuf[#tWriteBuf + 1] = tostring(key)
297 tWriteBuf[#tWriteBuf + 1] = "\r\n"
298 for k, v in pairsByPairs(tFuncs, tkSorted) do
299 n = n + 1
300 funcprint(tWriteBuf, k,v)
301 if #tWriteBuf > 25 then
302 filehandle:write(table.concat(tWriteBuf))
303 for i=1, #tWriteBuf do tWriteBuf[i] = _NIL end -- reuse table
304 end
305 end
306 end
307 tWriteBuf[#tWriteBuf + 1] = "\r\n\r\n"
308 tWriteBuf[#tWriteBuf + 1] = n
309 tWriteBuf[#tWriteBuf + 1] = " Items Found \r\n"
310 filehandle:write(table.concat(tWriteBuf))
311 for i=1, #tWriteBuf do tWriteBuf[i] = _NIL end -- empty table
312 filehandle:close()
313 --rb.splash((rb.HZ or 100) * 5, n .. " Items dumped to : " .. sDumpFile)
314 --rb.splash(500, collectgarbage("count"))
315if not ... then
316 local lu = collectgarbage("collect")
317 local used, allocd, free = rb.mem_stats()
318 local lu = collectgarbage("count")
319 local fmt = function(t, v) return string.format("%s: %d Kb\n", t, v /1024) end
320 local s_t = {}
321 s_t[1] = n
322 s_t[2] = " Items dumped to:\n"
323 s_t[3] = sDumpFile
324 s_t[4] = "\n\nLoaded Modules:\n"
325 n = 0
326 for k, v in pairsByPairs(tcBase, tkSortCbase ) do
327 n = n + 1
328 if n ~= 1 then
329 s_t[#s_t + 1] = ", "
330 end
331 s_t[#s_t + 1] = tostring(k)
332 if n >= 3 then -- split loaded modules to multiple lines
333 n = 0
334 s_t[#s_t + 1] = "\n"
335 end
336 end
337 rb.splash_scroller(5 * (rb.HZ or 100), table.concat(s_t))
338end