summaryrefslogtreecommitdiff
path: root/apps/plugins/lua
diff options
context:
space:
mode:
authorWilliam Wilgus <me.theuser@yahoo.com>2018-12-15 13:50:00 -0600
committerWilliam Wilgus <me.theuser@yahoo.com>2018-12-16 13:33:18 -0600
commit9d66b5459ecb9f85ffb194194abca5d46535774f (patch)
treeef24c34702e44f28173c5f09c921263bd76f08c3 /apps/plugins/lua
parentc2308bdf400e79b6f821885034e0f44abd6877a3 (diff)
downloadrockbox-9d66b5459ecb9f85ffb194194abca5d46535774f.tar.gz
rockbox-9d66b5459ecb9f85ffb194194abca5d46535774f.zip
Lua add read/write access to global_status, global_settings, audio_current_track
moved items to rb.system added read access to audio_current_track and audio_next_track Change-Id: Ia055b8cb3848e540067818f596ffd1058da057fb
Diffstat (limited to 'apps/plugins/lua')
-rw-r--r--apps/plugins/lua/lua.make7
-rw-r--r--apps/plugins/lua/rocklib.c137
-rwxr-xr-xapps/plugins/lua/settings_helper.pl397
3 files changed, 540 insertions, 1 deletions
diff --git a/apps/plugins/lua/lua.make b/apps/plugins/lua/lua.make
index a464bddace..ef9705a63d 100644
--- a/apps/plugins/lua/lua.make
+++ b/apps/plugins/lua/lua.make
@@ -35,11 +35,16 @@ else
35 ROCKS += $(LUA_BUILDDIR)/lua.rock 35 ROCKS += $(LUA_BUILDDIR)/lua.rock
36endif 36endif
37 37
38$(LUA_BUILDDIR)/lua.rock: $(LUA_OBJ) $(TLSFLIB) $(LUA_BUILDDIR)/actions.lua $(LUA_BUILDDIR)/buttons.lua $(LUA_BUILDDIR)/rocklib_aux.o $(LUA_INCLUDELIST) 38$(LUA_BUILDDIR)/lua.rock: $(LUA_OBJ) $(TLSFLIB) $(LUA_BUILDDIR)/actions.lua $(LUA_BUILDDIR)/buttons.lua $(LUA_BUILDDIR)/settings.lua $(LUA_BUILDDIR)/rocklib_aux.o $(LUA_INCLUDELIST)
39 39
40$(LUA_BUILDDIR)/actions.lua: $(LUA_OBJ) $(LUA_SRCDIR)/action_helper.pl 40$(LUA_BUILDDIR)/actions.lua: $(LUA_OBJ) $(LUA_SRCDIR)/action_helper.pl
41 $(call PRINTS,GEN $(@F))$(CC) $(PLUGINFLAGS) $(INCLUDES) -E $(APPSDIR)/plugins/lib/pluginlib_actions.h | $(LUA_SRCDIR)/action_helper.pl > $(LUA_BUILDDIR)/actions.lua 41 $(call PRINTS,GEN $(@F))$(CC) $(PLUGINFLAGS) $(INCLUDES) -E $(APPSDIR)/plugins/lib/pluginlib_actions.h | $(LUA_SRCDIR)/action_helper.pl > $(LUA_BUILDDIR)/actions.lua
42 42
43$(LUA_BUILDDIR)/settings.lua: $(LUA_OBJ) $(LUA_SRCDIR)/settings_helper.pl
44 $(SILENT)$(CC) $(INCLUDES) -E $(TARGET) $(CFLAGS) -include plugin.h -include cuesheet.h - < /dev/null | $(LUA_SRCDIR)/settings_helper.pl | \
45 $(CC) $(INCLUDES) $(TARGET) $(CFLAGS) -S -x c -include config.h -include plugin.h -o $(LUA_BUILDDIR)/settings_helper.s -
46 $(call PRINTS,GEN $(@F))$(LUA_SRCDIR)/settings_helper.pl < $(LUA_BUILDDIR)/settings_helper.s > $(LUA_BUILDDIR)/settings.lua
47
43HOST_INCLUDES := $(filter-out %/libc/include,$(INCLUDES)) 48HOST_INCLUDES := $(filter-out %/libc/include,$(INCLUDES))
44$(LUA_BUILDDIR)/buttons.lua: $(LUA_OBJ) $(LUA_SRCDIR)/button_helper.pl 49$(LUA_BUILDDIR)/buttons.lua: $(LUA_OBJ) $(LUA_SRCDIR)/button_helper.pl
45 $(SILENT)$(CC) $(INCLUDES) -dM -E -include button-target.h - < /dev/null | $(LUA_SRCDIR)/button_helper.pl | $(HOSTCC) -fno-builtin $(HOST_INCLUDES) -x c -o $(LUA_BUILDDIR)/button_helper - 50 $(SILENT)$(CC) $(INCLUDES) -dM -E -include button-target.h - < /dev/null | $(LUA_SRCDIR)/button_helper.pl | $(HOSTCC) -fno-builtin $(HOST_INCLUDES) -x c -o $(LUA_BUILDDIR)/button_helper -
diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c
index a6a23f3381..6c96f37a94 100644
--- a/apps/plugins/lua/rocklib.c
+++ b/apps/plugins/lua/rocklib.c
@@ -564,6 +564,137 @@ RB_WRAP(strncasecmp)
564 return 1; 564 return 1;
565} 565}
566 566
567static int mem_read_write(lua_State *L, uintptr_t address, size_t maxsize)
568{
569 intptr_t offset = (intptr_t) luaL_optint(L, 1, 0);
570 size_t size = (size_t) luaL_optint(L, 2, maxsize);
571 size_t written;
572 int type = lua_type(L, 3);
573
574 if(offset < 0)
575 {
576 /* allows pointer within structure to be calculated offset */
577 offset = -(address + offset);
578 size = (size_t) maxsize - offset;
579 }
580
581 luaL_argcheck(L, ((uintptr_t) offset) + size <= maxsize, 2, ERR_IDX_RANGE);
582
583 char *mem = (char*) address + ((uintptr_t) offset);
584 const void *value = NULL;
585
586 lua_Integer var_luaint;
587#ifdef UINT64_MAX
588 int64_t var_64;
589#endif
590 int32_t var_32;
591 int16_t var_16;
592 int8_t var_8;
593 bool var_bool;
594
595 switch(type)
596 {
597 case LUA_TSTRING:
598 {
599 size_t len;
600 const char* str = lua_tolstring (L, 3, &len);
601
602 luaL_argcheck(L, len + 1 <= size, 3, ERR_DATA_OVF);
603 size = len + 1; /* include \0 */
604 value = str;
605 break;
606 }
607 case LUA_TBOOLEAN:
608 {
609 var_bool = (bool) lua_toboolean(L, 3);
610 value = &var_bool;
611 break;
612 }
613 case LUA_TNUMBER:
614 {
615 var_luaint = lua_tointeger(L, 3);
616 switch(size)
617 {
618 case sizeof(var_8):
619 var_8 = (int8_t) var_luaint;
620 value = &var_8;
621 break;
622 case sizeof(var_16):
623 var_16 = (int16_t) var_luaint;
624 value = &var_16;
625 break;
626 case sizeof(var_32):
627 var_32 = (int32_t) var_luaint;
628 value = &var_32;
629 break;
630#ifdef UINT64_MAX
631 case sizeof(var_64):
632 var_64 = (int64_t) var_luaint;
633 value = &var_64;
634 break;
635#endif
636 } /* switch size */
637 break;
638 }
639 case LUA_TNIL:
640 case LUA_TNONE: /* reader */
641 {
642 luaL_Buffer b;
643 luaL_buffinit(L, &b);
644 while(size > 0)
645 {
646 written = MIN(LUAL_BUFFERSIZE, size);
647 luaL_addlstring (&b, mem, written);
648 mem += written;
649 size -= written;
650 }
651
652 luaL_pushresult(&b);
653 return 1;
654 }
655
656 default:
657 break;
658 } /* switch type */
659
660 /* writer */
661 luaL_argcheck(L, value != NULL, 3, "Unknown Type");
662 rb->memcpy(mem, value, size);
663 lua_pushinteger(L, 1);
664
665 return 1;
666}
667
668RB_WRAP(global_status)
669{
670 const uintptr_t address = (uintptr_t) rb->global_status;
671 const size_t maxsize = sizeof(struct system_status);
672 return mem_read_write(L, address, maxsize);
673}
674
675RB_WRAP(global_settings)
676{
677 const uintptr_t address = (uintptr_t) rb->global_settings;
678 const size_t maxsize = sizeof(struct user_settings);
679 return mem_read_write(L, address, maxsize);
680}
681
682RB_WRAP(audio_next_track)
683{
684 lua_settop(L, 2); /* no writes allowed */
685 const uintptr_t address = (uintptr_t) rb->audio_next_track();
686 const size_t maxsize = sizeof(struct mp3entry);
687 return mem_read_write(L, address, maxsize);
688}
689
690RB_WRAP(audio_current_track)
691{
692 lua_settop(L, 2); /* no writes allowed */
693 const uintptr_t address = (uintptr_t) rb->audio_current_track();
694 const size_t maxsize = sizeof(struct mp3entry);
695 return mem_read_write(L, address, maxsize);
696}
697
567#define RB_FUNC(func) {#func, rock_##func} 698#define RB_FUNC(func) {#func, rock_##func}
568#define RB_ALIAS(name, func) {name, rock_##func} 699#define RB_ALIAS(name, func) {name, rock_##func}
569static const luaL_Reg rocklib[] = 700static const luaL_Reg rocklib[] =
@@ -625,6 +756,12 @@ static const luaL_Reg rocklib[] =
625 RB_FUNC(utf8encode), 756 RB_FUNC(utf8encode),
626 RB_FUNC(strncasecmp), 757 RB_FUNC(strncasecmp),
627 758
759 /* ROCKBOX SETTINGS / INFO */
760 RB_FUNC(global_status),
761 RB_FUNC(global_settings),
762 RB_FUNC(audio_next_track),
763 RB_FUNC(audio_current_track),
764
628 {NULL, NULL} 765 {NULL, NULL}
629}; 766};
630#undef RB_FUNC 767#undef RB_FUNC
diff --git a/apps/plugins/lua/settings_helper.pl b/apps/plugins/lua/settings_helper.pl
new file mode 100755
index 0000000000..215d3a2a3c
--- /dev/null
+++ b/apps/plugins/lua/settings_helper.pl
@@ -0,0 +1,397 @@
1#!/usr/bin/env perl
2############################################################################
3# __________ __ ___.
4# Open \______ \ ____ ____ | | _\_ |__ _______ ___
5# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8# \/ \/ \/ \/ \/
9# $Id$
10#
11# Copyright (C) 2018 William Wilgus
12#
13# All files in this archive are subject to the GNU General Public License.
14# See the file COPYING in the source tree root for full license agreement.
15#
16# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17# KIND, either express or implied.
18#
19############################################################################
20
21# Extracts members from c struct
22# places them in a lua array 'member = {offset,size,"type"}'
23# requires two passes
24# first pass outputs a c file that shall be compiled with the -S option
25# second pass extracts the member, offset, size, type from the assembly
26
27my $svnrev = '$Revision$';
28my $helper_name = 'LUA_RB_SETTINGS_H_HELPER';
29
30############# configuration #############
31my @sections = (
32 '',
33 'struct system_status',
34 'struct user_settings',
35 'struct replaygain_settings',
36 'struct eq_band_setting',
37 'struct compressor_settings',
38 'struct mp3_enc_config',
39 '',
40 'struct mp3entry',
41 'struct mp3_albumart',
42 'struct embedded_cuesheet',
43 #'struct cuesheet',
44 #'struct cue_track_info',
45);
46
47my @sections_lua = (
48 'rb.system',
49 'rb.system.global_status',
50 'rb.system.global_settings',
51 'rb.system.replaygain_settings',
52 'rb.system.eq_band_setting',
53 'rb.system.compressor_settings',
54 'rb.system.mp3_enc_config',
55 'rb.metadata',
56 'rb.metadata.mp3_entry',
57 'rb.metadata.mp3_albumart',
58 'rb.metadata.embedded_cuesheet',
59 #'rb.metadata.cuesheet',
60 #'rb.metadata.cue_track_info',
61);
62
63# structs will have their dependencies included automagically
64my @includes = ();
65
66my $section_lua_suffix = '';
67
68my %replace_type_prefix = (
69 unsigned => 'u_',
70 signed => '',
71 struct => 's_',
72 const => 'const_',
73 enum => 'e_',
74 '#pointer#' => 'ptr_',
75);
76
77my %replace_type = (
78 int => 'i',
79 uint => 'u_i',
80 long => 'l',
81 char => 'c',
82 bool => 'b',
83 double => 'd',
84 '#string#' => 'str',
85);
86
87############# internal #############
88my @section_count = (); #variables found
89my @section_found = (); #{} bracket matches
90my @section_lists = (); #variable declarations
91my @section_asm_regex = ();
92my @section_begin_regex = ();
93
94my $header = '';
95my $array_marker = '_typeisarray_';
96my $pointer_marker = '_typeisptr_';
97my $current_include;
98
99############# precompile regex for speed #############
100my $array_mark_regex = qr/^.*${array_marker}$/;
101my $pointer_mark_regex = qr/^(.*)${pointer_marker}.*$/;
102
103my $incl_regex = qr/^.*\".+\/(.+\.h)\".*$/;
104my $extern_regex = qr/^extern\b.*$/;
105
106#type var ????;
107my $decl_regex = qr/^(.+?\s.+;)/;
108my $typevar_regex = qr/\W*(?<type>.*?)\W*(?<var>[^\s\[]+)(?<arr>)\W*;/;
109my$typevar_array_regex = qr/\W*(?<type>.*?)\W*(?<var>[^\s\[]+)\W*(?<arr>\[.+\]).*;/;
110
111#.."section",.."member"..=..offset,..size,..type,..arrayct
112my $asm_regex = qr/.*?,.*?(\".+?\".*?=.*?,.+?,.+?\".+\".*?,.*);/;
113my $asmMOST_regex = qr/\"(?<member>.+)\"=(?<offset>\d+),(?<size>\d+),\"(?<type>.+)\",(?<arr>\d+).*/;
114
115for(my $i = 0; $i < @sections; $i++)
116{
117 $section_asm_regex[$i] = qr/\"$sections[$i]\"${asm_regex}/;
118 $section_begin_regex[$i] = qr/^$sections[$i]\b\s*+[^\*;]*$/;
119 $section_count[$i] = 0;
120 $section_found[$i] = 0;
121 $section_lists[$i] = '';
122}
123
124my $section_end_regex = qr/}\s*;.*$/;
125
126#######################################################
127#extract all the variables within the structs(sections)
128#######################################################
129while(my $line = <STDIN>)
130{
131 next if($line =~ /^\s+$/);
132
133 chomp($line);
134
135 if($header) #second pass
136 {
137 for(my $i = 0; $i < @sections; $i++)
138 {
139 next if(!$sections[$i]);
140
141 if($line =~ $section_asm_regex[$i])
142 {
143 $section_lists[$i] .= $1.'@';
144 $section_count[$i]++;
145 last;
146 }
147 }
148 }
149 elsif($line =~ s/$helper_name\W*//) #is this the second pass?
150 {
151 $header = $line;
152 #warn $header."\n";
153 for(my $i = 0; $i < @sections; $i++)
154 {
155 @section_lists[$i] = '';
156 @section_count[$i] = 0;
157 }
158 }
159 else #first pass
160 {
161 if($line =~ $incl_regex){$current_include = $1; next;}
162 elsif($line =~ $extern_regex){next;}
163
164 for(my $i = 0; $i < @sections; $i++)
165 {
166 next if(!$sections[$i]);
167
168 if($section_found[$i] > 0)
169 {
170 # variable declaration?
171 if($line =~ $decl_regex)
172 {
173 $section_lists[$i] .= $1.'@';
174 $section_count[$i]++;
175 }
176
177 # struct end?
178 if($line =~ $section_end_regex)
179 {
180 $section_found[$i]--;
181 }
182 last;
183 }
184 elsif($line =~ $section_begin_regex[$i]) # struct begin?
185 {
186 if($current_include)
187 {
188 push (@includes, $current_include);
189 $current_include = '';
190 }
191 $section_found[$i]++;
192 $section_lists[$i] = '';
193 $section_count[$i] = 0;
194 last;
195 }
196 }
197 }#else
198}
199
200for(my $i = 0; $i < @sections; $i++)
201{
202 if($section_found[$i])
203 {
204 warn "$0 Warning formatting error in: $sections[$i]\n";
205 }
206}
207
208sub Extract_Variable {
209 #extracts the member, offset, size, and type from the include file
210 my $sinput = $_[0];
211 my ($type, $var, $arr);
212
213 $sinput =~ s{\s*\*\s*}{${pointer_marker}}gx;
214 if($sinput =~ $typevar_array_regex) #arrays
215 {
216 $type = $+{type};
217 $var = $+{var};
218 $arr = $+{var};
219 if($sinput =~ s/\bchar\b//){$type = $replace_type{'#string#'};}
220 else{$type .= ${array_marker};} #for identification of array .. stripped later
221 }
222 elsif($sinput =~ $typevar_regex)
223 {
224 $type = $+{type};
225 $var = $+{var};
226 $arr = $+{var};
227 }
228 else { return ('', '', ''); }
229
230 $type =~ s/^(unsigned|signed|struct)/$replace_type_prefix{$1}/x;
231 $type =~ s/\b(const|enum)\b/$replace_type_prefix{$1}/gx;
232 $type =~ s/^(?:.?+)(bool)\b/$replace_type{lc $1}/ix;
233 $type =~ s/^(uint|int)(?:\d\d_t)\b/$replace_type{lc $1}/ix;
234 $type =~ s/\b(int|long|char|double)(${array_marker}.*)?\b/$replace_type{$1}$2/;
235 $type =~ s{\s+}{}gx;
236
237 $var =~ s{[^\w\d_]+}{}gx; #strip non conforming chars
238
239 $arr =~ s{[^\[\d\]]+}{}gx;
240
241 return ($type, $var, $arr);
242}
243
244sub Print_Variable {
245 #prints the member, offset, size, and type from the assembly file
246 my $sinput = $_[0];
247 my ($member, $offset, $size, $type, $arr);
248
249 $sinput =~ s{[^\w\d_,=\"\*]+}{}gx;
250 if($sinput =~ $asmMOST_regex)
251 {
252 $member = $+{member};
253 $offset = $+{offset};
254 $size = $+{size};
255 $type = $+{type};
256 $arr = $+{arr};
257
258 if($type =~ /^(.*)${array_marker}$/) #strip array marker add [n]
259 {
260 $type = sprintf('%s[%d]', $1, $arr);
261 }
262
263 printf "\t%s = {0x%x, %d, \"%s\"},\n", $member, $offset, $size, $type;
264 return 1;
265 }
266 return 0;
267}
268
269if($header) #output sections to lua file
270{
271 print "-- Don't change this file!\n";
272 printf "-- It is automatically generated %s\n", $svnrev;
273 print "-- member = {offset, size, \"type\"}\n\n";
274
275 print "--";
276 foreach my $key (sort(keys %replace_type_prefix)) {
277 print $key, '= \'', $replace_type_prefix{$key}, '\', ';
278 }
279 print "\n--";
280 foreach my $key (sort(keys %replace_type)) {
281 print $key, '= \'', $replace_type{$key}, '\', ';
282 }
283 print "\n\n";
284
285 for(my $i = 0; $i < @sections_lua; $i++)
286 {
287 if($sections_lua[$i])
288 {
289 print "$sections_lua[$i]$section_lua_suffix = {\n";
290
291 my @members=split('@', $section_lists[$i]);
292 $section_lists[$i] = '';
293
294 foreach my $memb(@members)
295 {
296 $section_count[$i] -= Print_Variable($memb);
297 }
298
299 print "}\n\n";
300
301 if($sections[$i] && $section_count[$i] ne 0)
302 {
303 warn "$0 Warning: Failed to extract '$sections[$i]'\n";
304 }
305 }
306 }
307 #my ($user,$system,$cuser,$csystem) = times;
308 #warn "Pass2 ".$user." ".$system." ".$cuser." ".$csystem."\n";
309 exit;
310}
311
312#else output sections to .c file
313my $header = join(", ", $helper_name, @sections);
314my $print_variable = 'PRINT_M_O_S_T';
315my $print_array = 'PRINT_ARRAY_M_O_S_T';
316my $emit_asm = 'ASM_EMIT_M_O_S_T';
317
318foreach my $incl(@includes)
319{
320 printf "#include \"%s\"\n", $incl;
321}
322
323print <<EOF
324
325#include <stddef.h> /* offsetof */
326#include <stdbool.h>
327
328/* (ab)uses the compiler to emit member offset and size to asm comments */
329/* GAS supports C-style comments in asm files other compilers may not */
330/* "NAME", "MEMBER" = ?OFFSET, ?SIZE, "TYPE, ?ARRAYCT";
331 NOTE: ? may differ between machines */
332
333#undef ${emit_asm}
334#define ${emit_asm}(name, member, type, offset, size, elems) asm volatile\\
335("/* "#name ", " #member " = %0, %1, " #type ", %2; */\\n" : : \\
336"n"(offset), "n"(size), "n"(elems))
337
338#undef ${print_variable}
339#define ${print_variable}(name, member, value, type) ${emit_asm}(#name, \\
340#member, #type, offsetof(name, member), sizeof(value), 0)
341
342#undef ${print_array}
343#define ${print_array}(name, member, value, type) ${emit_asm}(#name, \\
344#member, #type, offsetof(name, member), sizeof(value), sizeof(value)/sizeof(value[0]))
345
346int main(void)
347{
348
349/* GAS supports C-style comments in asm files other compilers may not */
350/* This header identifies assembler output for second pass */
351asm volatile("/* $header; */");
352
353EOF
354;
355my $section_prefix = "section_";
356my $format_asm = " %s(%s, %s, ${section_prefix}%d.%s, %s);\n";
357
358
359for(my $i = 0; $i < @sections; $i++)
360{
361 if($sections[$i] && $section_lists[$i])
362 {
363 printf "%s %s%d;\n", $sections[$i], $section_prefix, $i; #create variable for each section
364 my @members=split('@', $section_lists[$i]);
365 $section_lists[$i] = '';
366
367 foreach my $memb(@members)
368 {
369 my ($type, $var, $arr) = Extract_Variable($memb);
370 my $call = ${print_variable};
371
372 if($var =~ $pointer_mark_regex) #strip pointer marker
373 {
374 $type = $type.$1;
375 $var =~ s{.*${pointer_marker}}{}gx;
376 $type = $replace_type_prefix{'#pointer#'}.$type;
377 }
378
379 if($type && $var)
380 {
381 if($type =~ $array_mark_regex){$call = ${print_array};}
382 printf $format_asm, $call, $sections[$i], $var, $i, $var, $type;
383 }
384 }
385 }
386}
387print <<EOF
388
389 return 0;
390}
391
392EOF
393;
394
395#my ($user,$system,$cuser,$csystem) = times;
396#warn "Pass1 ".$user." ".$system." ".$cuser." ".$csystem."\n";
397