A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 409 lines 13 kB view raw
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";