A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1#!/usr/bin/env perl
2############################################################################
3# __________ __ ___.
4# Open \______ \ ____ ____ | | _\_ |__ _______ ___
5# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8# \/ \/ \/ \/ \/
9# $Id$
10#
11# Copyright (C) 2009 by Maurus Cuelenaere
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
22# The purpose of this script is to automatically generate Lua wrappers for
23# (easily) portable C functions used in the Rockbox plugin API.
24# It doesn't contain support for structs or pointers (apart from char*).
25#
26# The output will be written to <build_dir>/apps/plugins/lua/rocklib_aux.c
27
28sub trim
29{
30 my $text = $_[0];
31 $text =~ s/^\s+//;
32 $text =~ s/\s+$//;
33 return $text;
34}
35
36sub rand_string
37{
38 my @chars=('a'..'z');
39 my $ret;
40 foreach (1..5)
41 {
42 $ret .= $chars[rand @chars];
43 }
44 return $ret;
45}
46
47
48my @functions;
49my @ported_functions;
50# These functions are excluded from automatically wrapping. This is useful if
51# you want to manually port them to Lua. The format is a standard Perl regular
52# expression.
53my @forbidden_functions = ('^atoi$',
54 '^open$',
55 '^open_utf8$',
56 '^close$',
57 'dcache',
58 '^read$',
59 '^write$',
60 '^mkdir$',
61 '^rmdir$',
62 '^remove$',
63 '^rename$',
64 '^lseek$',
65 '^ftruncate$',
66 '^filesize$',
67 '^fdprintf$',
68 '^read_line$',
69 '^[a-z]+dir$',
70 '^strip_extension$',
71 '^create_numbered_filename$',
72 '^s?+rand$',
73 '^strlen$',
74 '^strl?+cpy$',
75 '^strl?+cat$',
76 'strn?+casecmp$',
77 '^iso_decode$',
78 '^utf8encode$',
79 '^utf16',
80 '^codec_',
81 '^timer_',
82 '^lcd_blit_(mono|grey_phase)$',
83 '^lcd_(mono_)?+bitmap',
84 '^lcd_(draw|fill|update_)rect$',
85 '^lcd_draw(line|pixel)$',
86 '^lcd_(h|v)line$',
87 '^lcd_(update|clear_display|set_drawmode)$',
88 '^lcd_setfont$',
89 '^lcd_(set|get)_(fore|back)ground$',
90 '^lcd_put(s|sxy|s_scroll)$',
91 '^lcd_scroll_stop$',
92 '^backlight_o(n|ff)$',
93 '^backlight_set_brightness$',
94 '^buttonlight_set_brightness$',
95 '^__.+$',
96 '^.+_(un)?cached$',
97 '^audio_(status|get_file_pos|flush_and_reload_tracks)$',
98 '^audio_(ff_rewind|next|prev|play|pause|resume|stop)$',
99 '^playlist_(amount|add|create|start|resume|shuffle)$',
100 '^playlist_(sync|resume_track|remove_all_tracks)$',
101 '^playlist_(insert_track|insert_directory)$',
102 '^pcm_is_(playing|paused)$',
103 '^pcm_play_(stop|pause|lock|unlock)$',
104 '^pcm_(apply_settings|get_bytes_waiting)$',
105 '^pcm_(set_frequency|calculate_peaks)$',
106 '^sound_(set|current|default|min|max|unit|pitch|val2phys)$',
107 '^mixer_channel.*$',
108 '^mixer_(set|get)_frequency$',
109 '^plugin_get_current_filename$',
110 '^plugin_release_audio_buffer$',
111 '^reload_directory$',
112 '^settings_save$',
113 '^set_current_file$',
114 '^set_dirfilter$',
115 '^show_logo$',
116 '^sleep$',
117 '^system_memory_guard$',
118 '^system_sound_play$',
119 '^talk_number$',
120 '^talk_force_shutup$',
121 '^talk_spell$',
122 '^talk_shutup$',
123 '^(trigger|cancel)_cpu_boost$',
124 '^thread_',
125 '^touchscreen_(get|set)_mode$',
126 '^viewportmanager_theme_undo$',
127 '^round_value_to_list32$');
128
129my $rocklib = sprintf("%s/rocklib.c", $ARGV[0]);
130open ROCKLIB, "<$rocklib" or die("Couldn't open $rocklib: $!");
131while(<ROCKLIB>)
132{
133 if(/^RB_WRAP\(([^)]+)\)/)
134 {
135 push(@ported_functions, $1);
136 }
137}
138close ROCKLIB;
139
140# Parse plugin.h
141my $start = 0;
142while(<STDIN>)
143{
144 if(/struct plugin_api \{/)
145 {
146 $start = 1;
147 }
148 elsif($start && /\};/)
149 {
150 $start = 0;
151 }
152
153 if($start == 1)
154 {
155 my $line = $_;
156 while($line !~ /;/)
157 {
158 $line .= <STDIN>;
159 }
160
161 $line =~ s/(\n|\r)//g;
162
163 if($line =~ /([a-zA-Z *_]+)?\s?\(\*([^)]+)?\)\(([^)]+)\).*?;/)
164 {
165 $return_type = $1;
166 $name = $2;
167 $arguments = $3;
168
169 $return_type = trim($return_type);
170 $arguments =~ s/\s{2,}/ /g;
171
172 if( !grep($_ eq $name, @ported_functions) &&
173 !grep($name =~ $_, @forbidden_functions))
174 {
175 push(@functions, {'name' => $name, 'return' => $return_type, 'arg' => $arguments});
176 }
177 }
178 }
179}
180
181my $svnrev = '$Revision$';
182
183# Print the header
184print <<EOF
185/* Automatically generated from rocklib.c & plugin.h ($svnrev)
186 *
187 * See apps/plugins/lua/rocklib_aux.pl for the generator.
188 */
189
190#define lrocklib_c
191#define LUA_LIB
192
193#define _ROCKCONF_H_ /* We don't need strcmp() etc. wrappers */
194#include "lua.h"
195#include "lauxlib.h"
196#include "plugin.h"
197
198EOF
199;
200
201my %in_types = ('void' => \&in_void,
202 'enum' => \&in_enum,
203 'int' => \&in_int,
204 'unsigned' => \&in_int,
205 'unsignedint' => \&in_int,
206 'signed' => \&in_int,
207 'signedint' => \&in_int,
208 'short' => \&in_int,
209 'unsignedshort' => \&in_int,
210 'signedshort' => \&in_int,
211 'long' => \&in_int,
212 'unsignedlong' => \&in_int,
213 'signedlong' => \&in_int,
214 'char' => \&in_int,
215 'unsignedchar' => \&in_int,
216 'signedchar' => \&in_int,
217 'size_t' => \&in_int,
218 'ssize_t' => \&in_int,
219 'off_t' => \&in_int,
220 'char*' => \&in_string,
221 'signedchar*' => \&in_string,
222 'unsignedchar*' => \&in_string,
223 'bool' => \&in_bool,
224 '_Bool' => \&in_bool
225), %out_types = ('void' => \&out_void,
226 'enum' => \&out_enum,
227 'int' => \&out_int,
228 'unsigned' => \&out_int,
229 'unsignedint' => \&out_int,
230 'signed' => \&out_int,
231 'signedint' => \&out_int,
232 'short' => \&out_int,
233 'unsignedshort' => \&out_int,
234 'signedshort' => \&out_int,
235 'long' => \&out_int,
236 'unsignedlong' => \&out_int,
237 'signedlong' => \&out_int,
238 'char' => \&out_int,
239 'unsignedchar' => \&out_int,
240 'signedchar' => \&out_int,
241 'size_t' => \&out_int,
242 'ssize_t' => \&out_int,
243 'off_t' => \&out_int,
244 'char*' => \&out_string,
245 'signedchar*' => \&out_string,
246 'unsignedchar*' => \&out_string,
247 'bool' => \&out_bool,
248 '_Bool' => \&out_bool
249);
250
251sub in_void
252{
253 return "\t(void)L;\n";
254}
255
256sub in_enum
257{
258 my ($name, $type, $pos) = @_;
259 return sprintf("\t%s %s = luaL_checkint(L, %d); /*(enum)*/\n", "int", $name, $pos);
260}
261
262sub in_int
263{
264 my ($name, $type, $pos) = @_;
265 return sprintf("\t%s %s = (%s) luaL_checkint(L, %d);\n", $type, $name, $type, $pos);
266}
267
268sub in_string
269{
270 my ($name, $type, $pos) = @_;
271 return sprintf("\t%s %s = (%s) luaL_checkstring(L, %d);\n", $type, $name, $type, $pos)
272}
273
274sub in_bool
275{
276 my ($name, $type, $pos) = @_;
277 return sprintf("\tbool %s = luaL_checkboolean(L, %d);\n", $name, $pos)
278}
279
280sub out_void
281{
282 my $name = $_[0];
283 return sprintf("\t%s;\n\treturn 0;\n", $name);
284}
285
286sub out_enum
287{
288 my ($name, $type) = @_;
289 return sprintf("\t%s result = %s;\n\tlua_pushinteger(L, result);\n\treturn 1; /*(enum)*/\n", "int", $name);
290}
291
292sub out_int
293{
294 my ($name, $type) = @_;
295 return sprintf("\t%s result = %s;\n\tlua_pushinteger(L, result);\n\treturn 1;\n", $type, $name);
296}
297
298sub out_string
299{
300 my ($name, $type) = @_;
301 return sprintf("\t%s result = %s;\n\tlua_pushstring(L, result);\n\treturn 1;\n", $type, $name);
302}
303
304sub out_bool
305{
306 my ($name, $type) = @_;
307 return sprintf("\tbool result = %s;\n\tlua_pushboolean(L, result);\n\treturn 1;\n", $name);
308}
309
310#Sort the functions
311my @sorted_functions = sort { @$a{'name'} cmp @$b{'name'} } @functions;
312
313# Print the functions
314my @valid_functions;
315foreach my $function (@sorted_functions)
316{
317 my $valid = 1, @arguments = ();
318 # Check for supported arguments
319 foreach my $argument (split(/,/, @$function{'arg'}))
320 {
321 $argument = trim($argument);
322 if($argument !~ /\[.+\]/ && ($argument =~ /^(.+[\s*])([^[*\s]*)/
323 || $argument eq "void"))
324 {
325 my $literal_type, $type, $name;
326 if($argument eq "void")
327 {
328 $literal_type = "void", $type = "void", $name = "";
329 }
330 else
331 {
332 $literal_type = trim($1), $name = trim($2), $type = trim($1);
333 $type =~ s/^enum\s+.*/enum/g;
334 $type =~ s/(\s|const)//g;
335
336 if($name eq "")
337 {
338 $name = rand_string();
339 }
340 }
341
342 #printf "/* %s: %s|%s */\n", @$function{'name'}, $type, $name;
343 if(!defined $in_types{$type})
344 {
345 $valid = 0;
346 break;
347 }
348
349 push(@arguments, {'name' => $name,
350 'type' => $type,
351 'literal_type' => $literal_type
352 });
353 }
354 else
355 {
356 $valid = 0;
357 break;
358 }
359 }
360
361 # Check for supported return value
362 my $return = @$function{'return'};
363 $return =~ s/^enum\s+.*/enum/g;
364 $return =~ s/(\s|const)//g;
365 #printf "/* %s: %s [%d] */\n", @$function{'name'}, $return, $valid;
366 if(!defined $out_types{$return})
367 {
368 $valid = 0;
369 }
370
371 if($valid == 1)
372 {
373 # Print the header
374 printf "static int rock_%s(lua_State *L)\n".
375 "{\n",
376 @$function{'name'};
377
378 # Print the arguments
379 my $i = 1;
380 foreach my $argument (@arguments)
381 {
382 print $in_types{@$argument{'type'}}->(@$argument{'name'}, @$argument{'literal_type'}, $i++);
383 }
384
385 # Generate the arguments string
386 my $func_args = $arguments[0]{'name'};
387 for(my $i = 1; $i < $#arguments + 1; $i++)
388 {
389 $func_args .= ", ".$arguments[$i]{'name'};
390 }
391
392 # Print the function call
393 my $func = sprintf("rb->%s(%s)", @$function{'name'}, $func_args);
394
395 # Print the footer
396 print $out_types{$return}->($func, @$function{'return'});
397 print "}\n\n";
398
399 push(@valid_functions, $function);
400 }
401}
402
403# Print the C array
404print "const luaL_Reg rocklib_aux[] =\n{\n";
405foreach my $function (@valid_functions)
406{
407 printf "\t{\"%s\", rock_%s},\n", @$function{'name'}, @$function{'name'};
408}
409print "\t{NULL, NULL}\n};\n\n";