summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/lua/include_lua/rbsettings.lua164
-rw-r--r--apps/plugins/lua/lua.make2
-rw-r--r--apps/plugins/lua/rocklib.c42
-rwxr-xr-xapps/plugins/lua/settings_helper.pl5
-rw-r--r--apps/plugins/lua_scripts/dump_rbsettings.lua49
-rw-r--r--apps/plugins/lua_scripts/track_metadata.lua90
6 files changed, 342 insertions, 10 deletions
diff --git a/apps/plugins/lua/include_lua/rbsettings.lua b/apps/plugins/lua/include_lua/rbsettings.lua
new file mode 100644
index 0000000000..defdb11b77
--- /dev/null
+++ b/apps/plugins/lua/include_lua/rbsettings.lua
@@ -0,0 +1,164 @@
1--[[ Lua rb settings reader
2/***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2019 William Wilgus
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22]]
23
24rb.settings = rb.settings or {}
25
26local var = {offset = 1, size = 2, type = 3, fields = 3}
27
28local function bytesLE_n(str)
29 str = str or ""
30 local tbyte={str:byte(1, -1)}
31 local bpos, num = 1, 0
32 for k = 1,#tbyte do -- (k = #t, 1, -1 for BE)
33 num = num + tbyte[k] * bpos
34 bpos = bpos * 256 --1<<8
35 end
36 return num
37end
38
39local function get_var_fields(s_var)
40 -- converts member string into table
41 -- var = {offset, size, "type"}
42 s_var = s_var or ""
43 local o, s, t = string.match(s_var, "(0x%x+),%s*(%d+),%s*(.+)")
44 local tvar = {o, s, t}
45
46 return #tvar == var.fields and tvar or nil
47end
48
49local function format_val(val, var_type)
50 local ret, num
51 if var_type == nil then
52 return nil
53 elseif var_type == "str" then
54 -- stop at first null byte, return nil if str doesn't exist
55 return val and string.match(val, "^%Z+") or nil
56 end
57
58 num = bytesLE_n(val)
59 if string.find(var_type, "^b") then
60 if(num <= 0) then
61 ret = false
62 else
63 ret = true
64 end
65 elseif string.find(var_type, "^u_[cil]") then
66 -- Lua integers are signed so we need to do a bit of extra processing
67 ret = (string.format("%u", num))
68 else
69 ret = num
70 end
71
72 return ret
73end
74
75local function dump_struct(t_settings, t_struct, n_elems, t_var)
76 --Internal function dumps structs
77 local tdata = {}
78
79 local function struct_get_elem(v, elem_offset)
80 local val, offset, tvar1
81 tvar1 = get_var_fields(v)
82 offset = t_var[var.offset] + tvar1[var.offset] + elem_offset
83 val = t_settings(offset, tvar1[var.size])
84 return format_val(val, tvar1[var.type])
85 end
86
87 if n_elems > 0 then
88 -- Array of structs, struct[elems];
89 local elemsize = (t_var[var.size] / n_elems)
90 for i = 0, n_elems - 1 do
91 tdata[i] = tdata[i] or {}
92 for k1, v1 in pairs(t_struct) do
93 tdata[i][k1] = struct_get_elem(v1, (elemsize * i))
94 end
95 end
96 else
97 -- single struct, struct;
98 for k1, v1 in pairs(t_struct) do
99 tdata[k1] = struct_get_elem(v1, 0)
100 end
101 end
102 return tdata
103end
104
105local function get_array_elems(var_type)
106 --extract the number of elements, returns 0 if not found
107 local elems = string.match(var_type,".*%[(%d+)%]")
108 return tonumber(elems) or 0
109end
110
111local function get_struct_name(var_type)
112 --extract the name of a struct, returns nil if not found
113 return string.match(var_type,"^s_([^%[%]%s]+)")
114end
115
116function rb.settings.read(s_settings, s_var, s_groupname)
117 local data, val
118 local tvar = get_var_fields(s_var)
119 if tvar == nil then return nil end
120
121 local elems = get_array_elems(tvar[var.type])
122 local structname = get_struct_name(tvar[var.type])
123
124 local tsettings = rb[s_settings]
125 if not tsettings then error(s_settings .. " does not exist") end
126
127 if structname and rb[s_groupname] then
128 return dump_struct(tsettings, rb[s_groupname][structname], elems, tvar)
129 end
130
131 local voffset, vsize, vtype = tvar[var.offset], tvar[var.size], tvar[var.type]
132 if elems > 0 then
133 -- Arrays of values, val[elems];
134 data = {}
135 local elemsize = (vsize / elems)
136
137 for i = 0, elems - 1 do
138 val = tsettings(voffset + (elemsize * i), elemsize)
139 data[i] = format_val(val, vtype)
140 end
141 else
142 -- Single value, val;
143 if vtype == "ptr_char" then -- (**char)
144 vtype = "str"
145 val = tsettings(voffset, vsize, nil, true)
146 else
147 val = tsettings(voffset, vsize)
148 end
149 data = format_val(val, vtype)
150 end
151 return data
152end
153
154function rb.settings.dump(s_settings, s_groupname, s_structname, t_output)
155 t_output = t_output or {}
156 local tgroup = rb[s_groupname]
157 s_structname = s_structname or s_settings
158 for k, v in pairs(tgroup[s_structname]) do
159 t_output[k] = rb.settings.read(s_settings, v, s_groupname)
160 end
161 return t_output
162end
163
164return true
diff --git a/apps/plugins/lua/lua.make b/apps/plugins/lua/lua.make
index 66c1e67855..5e46692f3f 100644
--- a/apps/plugins/lua/lua.make
+++ b/apps/plugins/lua/lua.make
@@ -19,7 +19,7 @@ LUA_INCLUDEDIR := $(LUA_SRCDIR)/include_lua
19LUA_INCLUDELIST := $(addprefix $(LUA_BUILDDIR)/,audio.lua blit.lua color.lua draw.lua draw_floodfill.lua draw_poly.lua \ 19LUA_INCLUDELIST := $(addprefix $(LUA_BUILDDIR)/,audio.lua blit.lua color.lua draw.lua draw_floodfill.lua draw_poly.lua \
20 draw_num.lua draw_text.lua image.lua image_save.lua lcd.lua math_ex.lua \ 20 draw_num.lua draw_text.lua image.lua image_save.lua lcd.lua math_ex.lua \
21 print.lua timer.lua playlist.lua pcm.lua sound.lua \ 21 print.lua timer.lua playlist.lua pcm.lua sound.lua \
22 rbcompat.lua poly_points.lua printtable.lua) 22 rbcompat.lua rbsettings.lua poly_points.lua printtable.lua)
23 23
24 24
25ifndef APP_TYPE 25ifndef APP_TYPE
diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c
index 3c38440850..033975d7fe 100644
--- a/apps/plugins/lua/rocklib.c
+++ b/apps/plugins/lua/rocklib.c
@@ -640,8 +640,12 @@ RB_WRAP(strncasecmp)
640 return 1; 640 return 1;
641} 641}
642 642
643static int mem_read_write(lua_State *L, uintptr_t address, size_t maxsize) 643static int mem_read_write(lua_State *L, uintptr_t address, size_t maxsize, bool isstr_p)
644{ 644{
645 if(isstr_p) /*pointer to string (**char)*/
646 {
647 lua_settop(L, 2); /* no writes allowed */
648 }
645 intptr_t offset = (intptr_t) luaL_optnumber(L, 1, 0); 649 intptr_t offset = (intptr_t) luaL_optnumber(L, 1, 0);
646 size_t size = (size_t) luaL_optnumber(L, 2, maxsize); 650 size_t size = (size_t) luaL_optnumber(L, 2, maxsize);
647 size_t written; 651 size_t written;
@@ -716,6 +720,11 @@ static int mem_read_write(lua_State *L, uintptr_t address, size_t maxsize)
716 case LUA_TNIL: 720 case LUA_TNIL:
717 case LUA_TNONE: /* reader */ 721 case LUA_TNONE: /* reader */
718 { 722 {
723 if(isstr_p && mem)
724 {
725 lua_pushstring (L, *(char**) mem);
726 return 1;
727 }
719 luaL_Buffer b; 728 luaL_Buffer b;
720 luaL_buffinit(L, &b); 729 luaL_buffinit(L, &b);
721 while(size > 0) 730 while(size > 0)
@@ -746,32 +755,51 @@ RB_WRAP(global_status)
746{ 755{
747 const uintptr_t address = (uintptr_t) rb->global_status; 756 const uintptr_t address = (uintptr_t) rb->global_status;
748 const size_t maxsize = sizeof(struct system_status); 757 const size_t maxsize = sizeof(struct system_status);
749 return mem_read_write(L, address, maxsize); 758 /*const bool isstr_p = lua_toboolean(L, 4);*/
759 return mem_read_write(L, address, maxsize, false);
750} 760}
751 761
752RB_WRAP(global_settings) 762RB_WRAP(global_settings)
753{ 763{
754 const uintptr_t address = (uintptr_t) rb->global_settings; 764 const uintptr_t address = (uintptr_t) rb->global_settings;
755 const size_t maxsize = sizeof(struct user_settings); 765 const size_t maxsize = sizeof(struct user_settings);
756 return mem_read_write(L, address, maxsize); 766 /*const bool isstr_p = lua_toboolean(L, 4);*/
767 return mem_read_write(L, address, maxsize, false);
757} 768}
758 769
759RB_WRAP(audio_next_track) 770RB_WRAP(audio_next_track)
760{ 771{
761 lua_settop(L, 2); /* no writes allowed */ 772
762 const uintptr_t address = (uintptr_t) rb->audio_next_track(); 773 const uintptr_t address = (uintptr_t) rb->audio_next_track();
763 const size_t maxsize = sizeof(struct mp3entry); 774 const size_t maxsize = sizeof(struct mp3entry);
764 return mem_read_write(L, address, maxsize); 775 const bool isstr_p = lua_toboolean(L, 4);
776 lua_settop(L, 2); /* no writes allowed */
777 return mem_read_write(L, address, maxsize, isstr_p);
765} 778}
766 779
767RB_WRAP(audio_current_track) 780RB_WRAP(audio_current_track)
768{ 781{
769 lua_settop(L, 2); /* no writes allowed */ 782
770 const uintptr_t address = (uintptr_t) rb->audio_current_track(); 783 const uintptr_t address = (uintptr_t) rb->audio_current_track();
771 const size_t maxsize = sizeof(struct mp3entry); 784 const size_t maxsize = sizeof(struct mp3entry);
772 return mem_read_write(L, address, maxsize); 785 const bool isstr_p = lua_toboolean(L, 4);
786 lua_settop(L, 2); /* no writes allowed */
787 return mem_read_write(L, address, maxsize, isstr_p);
773} 788}
774 789
790#if 0
791RB_WRAP(read_mem)
792{
793 lua_settop(L, 2); /* no writes allowed */
794 const uintptr_t address = lua_tonumber(L, 1);
795 const size_t maxsize = luaL_optnumber(L, 2, strlen((char *)address));
796 luaL_argcheck(L, address > 0, 1, ERR_IDX_RANGE);
797 lua_pushnil(L);
798 lua_replace(L, -3);/* stk pos 1 is no longer offset it is starting address */
799 return mem_read_write(L, address, maxsize, false);
800}
801#endif
802
775RB_WRAP(restart_lua) 803RB_WRAP(restart_lua)
776{ 804{
777 /*close lua state, open a new lua state, load script @ filename */ 805 /*close lua state, open a new lua state, load script @ filename */
diff --git a/apps/plugins/lua/settings_helper.pl b/apps/plugins/lua/settings_helper.pl
index 2945afd354..4a280e60c7 100755
--- a/apps/plugins/lua/settings_helper.pl
+++ b/apps/plugins/lua/settings_helper.pl
@@ -293,7 +293,7 @@ sub Print_Variable {
293 $type = sprintf('%s[%d]', $1, $arr); 293 $type = sprintf('%s[%d]', $1, $arr);
294 } 294 }
295 295
296 printf "\t%s = {0x%x, %d, \"%s\"},\n", $member, $offset, $size, $type; 296 printf "\t%s = \"0x%x, %d, %s\",\n", $member, $offset, $size, $type;
297 return 1; 297 return 1;
298 } 298 }
299 return 0; 299 return 0;
@@ -303,7 +303,7 @@ if($header) #output sections to lua file [PASS 2]
303{ 303{
304 print "-- Don't change this file!\n"; 304 print "-- Don't change this file!\n";
305 printf "-- It is automatically generated %s\n", $svnrev; 305 printf "-- It is automatically generated %s\n", $svnrev;
306 print "-- member = {offset, size, \"type\"}\n\n"; 306 print "-- member = \"offset, size, type\"\n\n";
307 307
308 print "--"; 308 print "--";
309 foreach my $key (sort(keys %replace_type_prefix)) { 309 foreach my $key (sort(keys %replace_type_prefix)) {
@@ -337,6 +337,7 @@ if($header) #output sections to lua file [PASS 2]
337 } 337 }
338 } 338 }
339 } 339 }
340 print "\nreturn false\n";
340 #my ($user,$system,$cuser,$csystem) = times; 341 #my ($user,$system,$cuser,$csystem) = times;
341 #warn "Pass2 ".$user." ".$system." ".$cuser." ".$csystem."\n"; 342 #warn "Pass2 ".$user." ".$system." ".$cuser." ".$csystem."\n";
342 exit; 343 exit;
diff --git a/apps/plugins/lua_scripts/dump_rbsettings.lua b/apps/plugins/lua_scripts/dump_rbsettings.lua
new file mode 100644
index 0000000000..2811d27487
--- /dev/null
+++ b/apps/plugins/lua_scripts/dump_rbsettings.lua
@@ -0,0 +1,49 @@
1require("rbsettings")
2require("settings")
3rb.metadata = nil -- remove track metadata settings
4-------------------------------------------------------------------------------
5
6local function print_setting_table(t_tbl, s_sep)
7 s_sep = s_sep or ""
8 local str = ""
9 local function pfunct(t, sep, s, n) -- recursive print function
10 local vtype
11 for k, v in pairs(t) do
12 vtype = type(v)
13 if vtype == "table" then
14 local f = string.format("%s[%s]", n, k)
15 s = pfunct(v, sep, s, f)
16 elseif vtype == "boolean" then
17 v = v and "true" or "false"
18 s = string.format("%s%s[%s] = %s%s", s, n, k, v, sep)
19 elseif v then
20 s = string.format("%s%s[%s] = %s%s", s, n, k, v, sep)
21 end
22 end
23 return s
24 end
25 return pfunct(t_tbl, s_sep, str, "")
26end
27
28local filename = "/settings.txt"
29local file = io.open(filename, "w+") -- overwrite
30local t_settings
31
32if not file then
33 rb.splash(rb.HZ, "Error writing " .. filename)
34 return
35end
36
37t_settings = rb.settings.dump('global_settings', "system")
38file:write("global_settings:\n")
39file:write(print_setting_table(t_settings, "\n"))
40file:write("\n\n")
41
42t_settings = rb.settings.dump('global_status', "system")
43file:write("global_status:\n")
44file:write(print_setting_table(t_settings, "\n"))
45file:write("\n\n")
46
47file:close()
48
49rb.splash(100, "rb settings dumped: " .. filename)
diff --git a/apps/plugins/lua_scripts/track_metadata.lua b/apps/plugins/lua_scripts/track_metadata.lua
new file mode 100644
index 0000000000..08c1c865f3
--- /dev/null
+++ b/apps/plugins/lua_scripts/track_metadata.lua
@@ -0,0 +1,90 @@
1require("rbsettings")
2require("settings") --settings.lua
3rb.system = nil -- remove system settings
4-------------------------------------------------------------------------------
5local track_data = rb.metadata.mp3_entry
6local cur_trk = "audio_current_track"
7-------------------------------------------------------------------------------
8local trackname = rb.settings.read(cur_trk, track_data.title) or
9 rb.settings.read(cur_trk, track_data.path)
10if not trackname or trackname == "" then
11 os.exit(1, "No track loaded")
12else
13 rb.splash(100, trackname)
14end
15-------------------------------------------------------------------------------
16local function dump_albumart(fileout)
17 local t_albumart = rb.settings.read(cur_trk, track_data.albumart, "metadata")
18 local t_aaext = {".bmp",".png", ".jpg"}
19 local path = rb.settings.read(cur_trk, track_data.path)
20 if t_albumart.pos > 0 and t_albumart.size > 0 and t_albumart.type > 0 then
21
22 if t_aaext[t_albumart.type] then
23 local filename = "/" .. fileout .. t_aaext[t_albumart.type]
24 local aa = io.open(filename, "w+") -- overwrite
25 if not aa then
26 rb.splash(rb.HZ, "Error writing " .. filename)
27 return
28 end
29
30 local track = io.open(path, "r")
31 if not track then
32 rb.splash(rb.HZ, "Error opening " .. path)
33 return
34 end
35 track:seek("set", t_albumart.pos )
36 for i = 0, t_albumart.size, 32 do
37 aa:write(track:read(32))
38 end
39 rb.splash(rb.HZ, "Saved: " .. filename)
40 track:close()
41 aa:close()
42 else
43
44 end
45 end
46end
47
48local function print_setting_table(t_tbl, s_sep)
49 s_sep = s_sep or ""
50 local str = ""
51 local function pfunct(t, sep, s, n) -- recursive print function
52 local vtype
53 for k, v in pairs(t) do
54 vtype = type(v)
55 if vtype == "table" then
56 local f = string.format("%s[%s]", n, k)
57 s = pfunct(v, sep, s, f)
58 elseif vtype == "boolean" then
59 v = v and "true" or "false"
60 s = string.format("%s%s[%s] = %s%s", s, n, k, v, sep)
61 elseif v then
62 s = string.format("%s%s[%s] = %s%s", s, n, k, v, sep)
63 end
64 end
65 return s
66 end
67 return pfunct(t_tbl, s_sep, str, "")
68end
69
70local filename = "/metadata.txt"
71local file = io.open(filename, "w+") -- overwrite
72local t_settings
73
74if not file then
75 rb.splash(rb.HZ, "Error writing " .. filename)
76 return
77end
78
79---[[
80t_settings = rb.settings.dump(cur_trk, "metadata", "mp3_entry")
81file:write(trackname .. ":\n")
82file:write(print_setting_table(t_settings, "\n"))
83file:write("\n\n")
84file:close()
85
86rb.splash(100, "metadata dumped: " .. filename)
87
88if rb.settings.read(cur_trk, track_data.has_embedded_albumart) then
89 dump_albumart("/albumart")
90end