2 # Copyright © 2008-2015 Jamie Zawinski <jwz@jwz.org>
\r
3 # Copyright © 2015 Dennis Sheil <dennis@panaceasupplies.com>
\r
5 # Permission to use, copy, modify, distribute, and sell this software and its
\r
6 # documentation for any purpose is hereby granted without fee, provided that
\r
7 # the above copyright notice appear in all copies and that both that
\r
8 # copyright notice and this permission notice appear in supporting
\r
9 # documentation. No representations are made about the suitability of this
\r
10 # software for any purpose. It is provided "as is" without express or
\r
13 # This parses the .c and .xml files and makes sure they are in sync: that
\r
14 # options are spelled the same, and that all the numbers are in sync.
\r
15 # Some of that functionality may be removed in the future.
\r
17 # This also generates necessary Android files based on the information in
\r
18 # those source and XML files.
\r
20 # For the moment, the get_keys_and_values() subroutine is where support for
\r
21 # previously unsupported Android live wallpapers is added.
\r
23 # Created: 13-May-2015.
\r
29 my $progname = $0; $progname =~ s@.*/@@g;
\r
30 my ($version) = ('$Revision: 1.0 $' =~ m/\s(\d[.\d]+)\s/s);
\r
35 my $xlockmore_default_opts = '';
\r
36 foreach (qw(count cycles delay ncolors size font)) {
\r
37 $xlockmore_default_opts .= "{\"-$_\", \".$_\", XrmoptionSepArg, 0},\n";
\r
39 $xlockmore_default_opts .=
\r
40 "{\"-wireframe\", \".wireframe\", XrmoptionNoArg, \"true\"},\n" .
\r
41 "{\"-3d\", \".use3d\", XrmoptionNoArg, \"true\"},\n" .
\r
42 "{\"-no-3d\", \".use3d\", XrmoptionNoArg, \"false\"},\n";
\r
44 my $thread_default_opts =
\r
45 "{\"-threads\", \".useThreads\", XrmoptionNoArg, \"True\"},\n" .
\r
46 "{\"-no-threads\", \".useThreads\", XrmoptionNoArg, \"False\"},\n";
\r
48 my $analogtv_default_opts = '';
\r
49 foreach (qw(color tint brightness contrast)) {
\r
50 $analogtv_default_opts .= "{\"-tv-$_\", \".TV$_\", XrmoptionSepArg, 0},\n";
\r
53 $analogtv_default_opts .= $thread_default_opts;
\r
56 sub parse_settings_xml($) {
\r
60 my $file = "project/xscreensaver/res/values/settings.xml";
\r
66 open (IN, '<', $file) || error ("$file: $!");
\r
73 while (<IN>) { $body .= $_; }
\r
76 $body =~ s/<!--.*?-->/ /gsi;
\r
77 $body =~ s/\s+/ /gs;
\r
78 $body =~ s/</\001</gs;
\r
83 foreach (split (m/\001/, $body)) {
\r
84 next if (m/^\s*$/s);
\r
85 my ($type, $args) = m@^<([?/]?[-_a-z]+)\b\s*(.*)$@si;
\r
86 error ("$progname: $file: unparsable: $_") unless $type;
\r
87 next if ($type =~ m@^/@);
\r
89 if ($type =~ m/^(\?xml|resources)/s) {
\r
91 } elsif ($type eq 'string-array') {
\r
92 my ($name) = ($args =~ m/\bname\s*=\s*\"([^\"]+)\"/);
\r
93 my ($value) = ($args =~ m/>([^\"]+)/);
\r
96 if ($name =~ /^$saver/) {
\r
97 error ("$saver: $saver already in $file");
\r
100 } elsif ($type eq 'item') {
\r
102 my ($item_value) = ($args =~ m/>(.+)/);
\r
103 my $item = $loop . " = " . $item_value;
\r
107 error ("$file: unknown type \"$type\" for no arg");
\r
116 sub parse_items_xml($) {
\r
120 my $file = "project/xscreensaver/res/values/items.xml";
\r
127 open (IN, '<', $file) || error ("$file: $!");
\r
134 while (<IN>) { $body .= $_; }
\r
137 $body =~ s/<!--.*?-->/ /gsi;
\r
139 $body =~ s/\s+/ /gs;
\r
140 $body =~ s/</\001</gs;
\r
142 foreach (split (m/\001/, $body)) {
\r
143 next if (m/^\s*$/s);
\r
144 my ($type, $args) = m@^<([?/]?[-_a-z]+)\b\s*(.*)$@si;
\r
145 error ("$progname: $file: unparsable: $_") unless $type;
\r
146 next if ($type =~ m@^/@);
\r
148 if ($type =~ m/^(\?xml|resources)/s) {
\r
150 } elsif ($type eq 'item') {
\r
151 my ($name) = ($args =~ m/\bname\s*=\s*\"([^\"]+)\"/);
\r
152 my ($value) = ($args =~ m/>([^\"]+)/);
\r
154 if ($name =~ /^$saver/) {
\r
155 error ("$saver: $saver already in $file");
\r
158 $pixkeys{$name} = $value;
\r
161 error ("$file: unknown type \"$type\" for no arg");
\r
169 sub parse_glue($) {
\r
171 my $file = "gen/glue.c";
\r
175 open ($in, '<', $file) || error ("$file: $!");
\r
183 while (<$in>) { $body .= $_; }
\r
186 $body =~ s@^#\s*(if|ifdef|ifndef|elif|else|endif).*$@@gm;
\r
189 if ($body =~ m/table\s*\*([a-z,\s\*_]+)xscreensaver_function_table;/s) {
\r
190 foreach (split (/,\s*\n/, $1)) {
\r
193 my @ftables = split (/_/, $_);
\r
194 my $ftable = $ftables[0];
\r
195 if ($ftable eq $saver) {
\r
196 error("$saver is already in glue");
\r
198 push @hacks, $ftable;
\r
204 # Returns two tables:
\r
205 # - A table of the default resource values.
\r
206 # - A table of "-switch" => "resource: value", or "-switch" => "resource: %"
\r
210 my $ffile = lc($saver) . ".c";
\r
213 $ffile = 'apple2-main.c' if ($ffile eq 'apple2.c');
\r
214 $ffile = 'sproingiewrap.c' if ($ffile eq 'sproingies.c');
\r
215 $ffile = 'b_lockglue.c' if ($ffile eq 'bubble3d.c');
\r
216 $ffile = 'polyhedra-gl.c' if ($ffile eq 'polyhedra.c');
\r
217 $ffile = 'companion.c' if ($ffile eq 'companioncube.c');
\r
219 my $file = "../hacks/" . $ffile;
\r
221 $file = "../hacks/glx/$ffile" unless (-f $file);
\r
223 open (my $in, '<', $file) || error ("$file: $!");
\r
224 while (<$in>) { $body .= $_; }
\r
228 my $xlockmore_p = 0;
\r
229 my $thread_p = ($body =~ m/THREAD_DEFAULTS/);
\r
230 my $analogtv_p = ($body =~ m/ANALOGTV_DEFAULTS/);
\r
232 $body =~ s@/\*.*?\*/@@gs;
\r
233 $body =~ s@^#\s*(if|ifdef|ifndef|elif|else|endif).*$@@gm;
\r
234 $body =~ s/(THREAD|ANALOGTV)_(DEFAULTS|OPTIONS)(_XLOCK)?//gs;
\r
236 print STDERR "$progname: $file: defaults:\n" if ($verbose > 2);
\r
238 if ($body =~ m/_defaults\s*\[\]\s*=\s*{(.*?)}\s*;/s) {
\r
239 foreach (split (/,\s*\n/, $1)) {
\r
243 my ($key, $val) = m@^\"([^:\s]+)\s*:\s*(.*?)\s*\"$@;
\r
244 print STDERR "$progname: $file: unparsable: $_\n" unless $key;
\r
245 $key =~ s/^[.*]//s;
\r
246 $res_to_val{$key} = $val;
\r
247 print STDERR "$progname: $file: $key = $val\n" if ($verbose > 2);
\r
249 } elsif ($body =~ m/\#\s*define\s*DEFAULTS\s*\\?\s*(.*?)\n[\n#]/s) {
\r
252 $str =~ s/\"\s*\\\n\s*\"//gs;
\r
253 $str =~ m/^\s*\"(.*?)\"\s*\\?\s*$/ ||
\r
254 error ("$file: unparsable defaults: $str");
\r
256 $str =~ s/\s*\\n\s*/\n/gs;
\r
257 foreach (split (/\n/, $str)) {
\r
258 my ($key, $val) = m@^([^:\s]+)\s*:\s*(.*?)\s*$@;
\r
259 print STDERR "$progname: $file: unparsable: $_\n" unless $key;
\r
260 $key =~ s/^[.*]//s;
\r
261 $res_to_val{$key} = $val;
\r
262 print STDERR "$progname: $file: $key = $val\n" if ($verbose > 2);
\r
265 while ($body =~ s/^#\s*define\s+(DEF_([A-Z\d_]+))\s+\"([^\"]+)\"//m) {
\r
266 my ($key1, $key2, $val) = ($1, lc($2), $3);
\r
267 $key2 =~ s/_(.)/\U$1/gs; # "foo_bar" -> "fooBar"
\r
268 $key2 =~ s/Rpm/RPM/; # kludge
\r
269 $res_to_val{$key2} = $val;
\r
270 print STDERR "$progname: $file: $key1 ($key2) = $val\n"
\r
275 error ("$file: no defaults");
\r
278 $body =~ m/XSCREENSAVER_MODULE(_2)?\s*\(\s*\"([^\"]+)\"/ ||
\r
279 error ("$file: no module name");
\r
280 $res_to_val{progclass} = $2;
\r
281 $res_to_val{doFPS} = 'false';
\r
282 print STDERR "$progname: $file: progclass = $2\n" if ($verbose > 2);
\r
284 print STDERR "$progname: $file: switches to resources:\n"
\r
287 $switch_to_res{-fps} = 'doFPS: true';
\r
288 $switch_to_res{-fg} = 'foreground: %';
\r
289 $switch_to_res{-bg} = 'background: %';
\r
291 my ($ign, $opts) = ($body =~ m/(_options|\bopts)\s*\[\]\s*=\s*{(.*?)}\s*;/s);
\r
292 if ($xlockmore_p || $thread_p || $analogtv_p || $opts) {
\r
293 $opts = '' unless $opts;
\r
294 $opts .= ",\n$xlockmore_default_opts" if ($xlockmore_p);
\r
295 $opts .= ",\n$thread_default_opts" if ($thread_p);
\r
296 $opts .= ",\n$analogtv_default_opts" if ($analogtv_p);
\r
298 foreach (split (/,\s*\n/, $opts)) {
\r
302 next if m/^{\s*0\s*,/s;
\r
303 my ($switch, $res, $type, $v0, $v1, $v2) =
\r
304 m@^ \s* { \s * \"([^\"]+)\" \s* ,
\r
305 \s * \"([^\"]+)\" \s* ,
\r
306 \s * ([^\s]+) \s* ,
\r
307 \s * (\"([^\"]*)\"|([a-zA-Z\d_]+)) \s* }@xi;
\r
308 print STDERR "$progname: $file: unparsable: $_\n" unless $switch;
\r
309 my $val = defined($v1) ? $v1 : $v2;
\r
310 $val = '%' if ($type eq 'XrmoptionSepArg');
\r
311 $res =~ s/^[.*]//s;
\r
312 $res =~ s/^[a-z\d]+\.//si;
\r
313 $switch =~ s/^\+/-no-/s;
\r
315 $val = "$res: $val";
\r
316 if (defined ($switch_to_res{$switch})) {
\r
317 print STDERR "$progname: $file: DUP! $switch = \"$val\"\n"
\r
320 $switch_to_res{$switch} = $val;
\r
321 print STDERR "$progname: $file: $switch = \"$val\"\n"
\r
326 error ("$file: no options");
\r
329 return (\%res_to_val, \%switch_to_res);
\r
332 # Returns a list of:
\r
333 # "resource = default value"
\r
334 # or "resource != non-default value"
\r
336 sub parse_manifest_xml($$) {
\r
338 my ($saver, $switch_to_res) = @_;
\r
339 my $file = "project/xscreensaver/AndroidManifest.xml";
\r
344 open (IN, "<$file") || error ("$file: $!");
\r
350 while (<IN>) { $body .= $_; }
\r
354 $body =~ s/<!--.*?-->/ /gsi;
\r
356 $body =~ s/\s+/ /gs;
\r
357 $body =~ s/</\001</gs;
\r
358 $body =~ s/\001(<option)/$1/gs;
\r
360 print STDERR "$progname: $file: options:\n" if ($verbose > 2);
\r
362 foreach (split (m/\001/, $body)) {
\r
363 next if (m/^\s*$/s);
\r
364 my ($type, $args) = m@^<([?/]?[-_a-z]+)\b\s*(.*)$@si;
\r
365 error ("$progname: $file: unparsable: $_") unless $type;
\r
366 next if ($type =~ m@^/@);
\r
367 if ($type eq 'meta-data') {
\r
368 my ($value) = ($args =~ m/\@xml\/([^\"]+)\"/);
\r
369 push @result, $value;
\r
375 # Returns a list of:
\r
376 # "resource = default value"
\r
377 # or "resource != non-default value"
\r
379 sub parse_strings_xml($$) {
\r
381 my ($saver, $switch_to_res) = @_;
\r
382 my $file = "project/xscreensaver/res/values/strings.xml";
\r
387 open (IN, "<$file") || error ("$file: $!");
\r
393 while (<IN>) { $body .= $_; }
\r
397 $body =~ s/<!--.*?-->/ /gsi;
\r
399 $body =~ s/\s+/ /gs;
\r
400 $body =~ s/</\001</gs;
\r
401 $body =~ s/\001(<option)/$1/gs;
\r
403 print STDERR "$progname: $file: options:\n" if ($verbose > 2);
\r
405 my $saver_name = $saver . "_name";
\r
407 foreach (split (m/\001/, $body)) {
\r
408 next if (m/^\s*$/s);
\r
409 my ($type, $args) = m@^<([?/]?[-_a-z]+)\b\s*(.*)$@si;
\r
410 error ("$progname: $file: unparsable: $_") unless $type;
\r
411 next if ($type =~ m@^/@);
\r
413 if ($type =~ m/^([hv]group|\?xml|resources|xscreensaver-(image|text|updater))/s) {
\r
415 } elsif ($type eq 'string') {
\r
416 my ($name) = ($args =~ m/\bname\s*=\s*\"([^\"]+)\"/);
\r
417 my ($value) = ($args =~ m/>([^\"]+)/);
\r
418 my ($val) = "$name = $value";
\r
419 if ($saver_name eq $name) {
\r
420 error ("$saver: $saver already in $file");
\r
422 push @result, $val;
\r
423 } elsif ($type eq 'item') {
\r
426 error ("$file: unknown type \"$type\" for no arg");
\r
435 # Returns a list of:
\r
436 # "resource = default value"
\r
437 # or "resource != non-default value"
\r
439 sub parse_xml($$) {
\r
440 my ($saver, $switch_to_res) = @_;
\r
441 my $file = "../hacks/config/" . lc($saver) . ".xml";
\r
444 open (IN, "<$file") || error ("$file: $!");
\r
445 while (<IN>) { $body .= $_; }
\r
451 $body =~ s/<!--.*?-->/ /gsi;
\r
453 $body =~ s/\s+/ /gs;
\r
454 $body =~ s/</\001</gs;
\r
455 $body =~ s/\001(<option)/$1/gs;
\r
459 print STDERR "$progname: $file: options:\n" if ($verbose > 2);
\r
460 foreach (split (m/\001/, $body)) {
\r
461 next if (m/^\s*$/s);
\r
462 my ($type, $args) = m@^<([?/]?[-_a-z]+)\b\s*(.*)$@si;
\r
465 error ("$progname: $file: unparsable: $_") unless $type;
\r
466 next if ($type =~ m@^/@);
\r
468 if ($type =~ m/^([hv]group|\?xml|command|string|file|_description|xscreensaver-(image|text|updater))/s) {
\r
470 } elsif ($type eq 'screensaver') {
\r
471 my ($name) = ($args =~ m/\b_label\s*=\s*\"([^\"]+)\"/);
\r
472 my $val = "progclass = $name";
\r
473 push @result, $val;
\r
474 print STDERR "$progname: $file: name: $name\n" if ($verbose > 2);
\r
476 } elsif ($type eq 'video') {
\r
477 error ("$file: multiple videos") if $video;
\r
478 ($video) = ($args =~ m/\bhref="(.*?)"/);
\r
479 error ("$file: unparsable video") unless $video;
\r
480 error ("$file: unparsable video URL")
\r
481 unless ($video =~ m@^https?://www\.youtube\.com/watch\?v=[^?&]+$@s);
\r
483 } elsif ($type eq 'number') {
\r
484 my ($arg) = ($args =~ m/\barg\s*=\s*\"([^\"]+)\"/);
\r
485 my ($val) = ($args =~ m/\bdefault\s*=\s*\"([^\"]+)\"/);
\r
486 $val = '' unless defined($val);
\r
488 my ($low) = ($args =~ m/\blow\s*=\s*\"([^\"]+)\"/);
\r
489 my ($high) = ($args =~ m/\bhigh\s*=\s*\"([^\"]+)\"/);
\r
491 my ($ll) = ($args =~ m/\b_low-label\s*=\s*\"([^\"]+)\"/);
\r
492 my ($hl) = ($args =~ m/\b_high-label\s*=\s*\"([^\"]+)\"/);
\r
495 $switch =~ s/\s+.*$//;
\r
496 my ($res) = $switch_to_res->{$switch};
\r
497 error ("$file: no resource for $type switch \"$arg\"") unless $res;
\r
499 error ("$file: unparsable value: $res") if ($res =~ m/:/);
\r
501 $type_val = "$res" . "_type = $type";
\r
502 push @result, $type_val;
\r
503 $val = "$res = $val";
\r
504 push @result, $val;
\r
505 $val = "$res" . "_low = $low";
\r
506 push @result, $val;
\r
507 $val = "$res" . "_high = $high";
\r
508 push @result, $val;
\r
509 $val = "$res" . "_low-label = $ll";
\r
510 push @result, $val;
\r
511 $val = "$res" . "_high-label = $hl";
\r
512 push @result, $val;
\r
514 print STDERR "$progname: $file: number: $val\n" if ($verbose > 2);
\r
516 } elsif ($type eq 'boolean') {
\r
517 my ($set) = ($args =~ m/\barg-set\s*=\s*\"([^\"]+)\"/);
\r
518 my ($unset) = ($args =~ m/\barg-unset\s*=\s*\"([^\"]+)\"/);
\r
519 my ($arg) = $set || $unset || error ("$file: unparsable: $args");
\r
520 my ($res) = $switch_to_res->{$arg};
\r
521 error ("$file: no resource for boolean switch \"$arg\"") unless $res;
\r
522 my ($res2, $val) = ($res =~ m/^(.*?): (.*)$/s);
\r
523 error ("$file: unparsable boolean resource: $res") unless $res2;
\r
525 $type_val = "$res" . "_type = $type";
\r
526 push @result, $type_val;
\r
527 # $val = ($set ? "$res != $val" : "$res = $val");
\r
528 $val = "$res != $val";
\r
529 push @result, $val;
\r
531 print STDERR "$progname: $file: boolean: $val\n" if ($verbose > 2);
\r
533 } elsif ($type eq 'select') {
\r
534 $args =~ s/</\001</gs;
\r
535 my @opts = split (/\001/, $args);
\r
538 my $this_res = undef;
\r
540 error ("$file: unparsable: $_") unless (m/^<option\s/);
\r
541 my ($set) = m/\barg-set\s*=\s*\"([^\"]+)\"/;
\r
543 my ($set2, $val) = ($set =~ m/^(.*?) (.*)$/s);
\r
544 $set = $set2 if ($set2);
\r
545 my ($res) = $switch_to_res->{$set};
\r
546 error ("$file: no resource for select switch \"$set\"") unless $res;
\r
548 my ($res2, $val2) = ($res =~ m/^(.*?): (.*)$/s);
\r
549 error ("$file: unparsable select resource: $res") unless $res2;
\r
551 $type_val = "$res" . "_type = $type";
\r
552 push @result, $type_val;
\r
553 $val = $val2 unless ($val2 eq '%');
\r
555 error ("$file: mismatched resources: $res vs $this_res")
\r
556 if (defined($this_res) && $this_res ne $res);
\r
559 $val = "$res != $val";
\r
560 push @result, $val;
\r
561 $val = "$res" . "_type = $type";
\r
562 push @result, $val;
\r
564 print STDERR "$progname: $file: select: $val\n" if ($verbose > 2);
\r
567 error ("$file: multiple default options: $set") if ($unset_p);
\r
573 error ("$file: unknown type \"$type\" for no arg");
\r
577 # error ("$file: no video") unless $video;
\r
578 print STDERR "\n$file: WARNING: no video\n\n" unless $video;
\r
584 sub parse_then_make($) {
\r
588 return 0 if ($saver =~ m/(-helper)$/);
\r
590 my ($src_opts, $switchmap) = parse_src ($saver);
\r
591 my (@xml_opts) = parse_xml ($saver, $switchmap);
\r
593 # tests if hack is supported yet
\r
594 my (@test) = get_keys_and_values($saver, @xml_opts);
\r
595 my (@strings_xml_opts) = parse_strings_xml ($saver, $switchmap);
\r
596 my (%pixkeys) = parse_items_xml($saver);
\r
597 my (@manifest_xml_opts) = parse_manifest_xml ($saver, $switchmap);
\r
598 my (@glue_hacks) = parse_glue($saver);
\r
599 my (@settings_xml_opts) = parse_settings_xml($saver);
\r
601 my (@all_settings) = get_settings($saver, $switchmap, \@xml_opts);
\r
603 make_settings($saver);
\r
604 make_service($saver);
\r
605 make_wallpaper($saver, @xml_opts);
\r
607 make_manifest($saver, @manifest_xml_opts);
\r
609 make_hack_xml($saver);
\r
610 make_hack_settings_xml($saver, @xml_opts);
\r
611 make_strings_xml($saver, \@xml_opts, \@strings_xml_opts);
\r
612 make_items_xml($saver, \@xml_opts, \%pixkeys);
\r
613 make_settings_xml($saver, \@all_settings, \@settings_xml_opts);
\r
615 make_glue($saver, @glue_hacks);
\r
621 sub make_manifest($$) {
\r
622 my ($saver, @manifest_opts) = @_;
\r
623 push @manifest_opts, $saver unless grep{$_ eq $saver} @manifest_opts;
\r
624 my $hack = ucfirst($saver);
\r
625 my $file = "project/xscreensaver/AndroidManifest.xml";
\r
626 open (my $in, '>', $file) || error ("$file: $!");
\r
628 my $body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
\r
630 "xmlns:android=\"http://schemas.android.com/apk/res/android\" " .
\r
631 "package=\"org.jwz.xscreensaver\"\n" .
\r
632 "android:versionCode=\"1\"\n" .
\r
633 "android:versionName=\"1.0\">\n" .
\r
634 "<uses-sdk android:minSdkVersion=\"14\" " .
\r
635 "android:targetSdkVersion=\"19\" />\n" .
\r
636 "<application android:icon=\"\@drawable/thumbnail\" " .
\r
637 "android:label=\"\@string/app_name\" " .
\r
638 "android:name=\".XscreensaverApp\">\n\n");
\r
640 foreach my $save (@manifest_opts) {
\r
641 my $hac = ucfirst($save);
\r
642 $body = $body . ("<service android:label=\"\@string/" . $save .
\r
643 "_name\" android:name=\".gen." . $hac . "Service\" " .
\r
644 "android:permission=\"android.permission.BIND_WALLPAPER\">\n" .
\r
645 " <intent-filter>\n" .
\r
647 "android:name=\"android.service.wallpaper.WallpaperService\" " .
\r
649 " </intent-filter>\n" .
\r
650 " <meta-data android:name=\"android.service.wallpaper\" " .
\r
651 "android:resource=\"\@xml/" . $save . "\" />\n" .
\r
654 "android:label=\"\@string/" . $save . "_settings\" " .
\r
655 "android:name=\"org.jwz.xscreensaver.gen." . $hac .
\r
657 "android:theme=\"\@android:style/Theme.Light.WallpaperSettings\" " .
\r
658 "android:exported=\"true\">\n" .
\r
659 "</activity>\n\n");
\r
663 $body = $body . ("</application>\n\n" .
\r
664 "<uses-sdk android:minSdkVersion=\"14\" />\n" .
\r
666 "android:name=\"android.software.live_wallpaper\" " .
\r
667 "android:required=\"true\" />\n" .
\r
675 sub make_hack_settings_xml($$) {
\r
677 my ($saver, @xml_opts) = @_;
\r
678 my $hack = ucfirst($saver);
\r
679 my $file = "project/xscreensaver/res/xml/" . $saver . "_settings.xml";
\r
680 my (%saver_keys) = get_keys_and_values($saver, @xml_opts);
\r
682 open (my $in, '>', $file) || error ("$file: $!");
\r
684 my $body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
\r
685 "<PreferenceScreen xmlns:android=" .
\r
686 "\"http://schemas.android.com/apk/res/android\">\n" .
\r
687 " <PreferenceCategory\n" .
\r
688 " android:title=\"\@string/" . $saver .
\r
690 " android:key=\"" . $saver .
\r
691 "wallpaper_settings\">\n");
\r
693 my @keyarray = keys %saver_keys;
\r
696 foreach my $sgkey (@keyarray) {
\r
698 my $type = get_type($sgkey, @xml_opts);
\r
701 if ($type eq "number") {
\r
702 $body = $body . " <org.jwz.xscreensaver.SliderPreference\n" .
\r
703 " android:defaultValue=\"\@string/" . $saver .
\r
706 " android:dialogMessage=\"\@string/" . $saver .
\r
708 "_settings_summary\"\n" .
\r
709 " android:key=\"" . $saver . "_" . $sgkey .
\r
711 " android:summary=\"\@array/" . $saver . "_" . $sgkey .
\r
713 " android:title=\"\@string/" . $saver . "_" . $sgkey .
\r
714 "_settings_title\" />\n";
\r
716 $body = $body . " <ListPreference\n" .
\r
717 " android:key=\"" . $saver . "_" . $sgkey .
\r
719 " android:title=\"\@string/" . $saver . "_" . $sgkey .
\r
720 "_settings_title\"\n" .
\r
721 " android:summary=\"\@string/$saver" . "_" . $sgkey .
\r
722 "_settings_summary\"\n" .
\r
723 " android:entries=\"\@array/$saver" . "_$sgkey" .
\r
725 " android:defaultValue=\"\@string/" . $saver .
\r
726 "_" . $sgkey . "_default" . "\"\n" .
\r
727 " android:entryValues=\"\@array/$saver" .
\r
733 $body = $body . " </PreferenceCategory>\n" .
\r
734 "</PreferenceScreen>\n";
\r
741 sub make_items_xml($\@\%) {
\r
743 my @xml_opts = @{$_[1]};
\r
744 my %pixkeys = %{$_[2]};
\r
746 my $file = "project/xscreensaver/res/values/items.xml";
\r
748 my $body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
\r
751 while(my($key, $value) = each %pixkeys) {
\r
752 $body = $body . " <item name=\"" . $key .
\r
753 "\" format=\"float\" type=\"string\">". $value . "</item>\n";
\r
757 my (%saver_keys) = get_keys_and_values($saver, @xml_opts);
\r
758 my @keyarray = keys %saver_keys;
\r
760 foreach my $item_key (@keyarray) {
\r
762 my $type = get_type($item_key, @xml_opts);
\r
764 if ($type eq "number") {
\r
766 my ($low, $high, $default) = get_low_high_def($item_key, @xml_opts);
\r
767 my $float = ($default - $low) / ($high - $low);
\r
770 " <item name=\"" . $saver . "_" . $item_key .
\r
771 "_float\" format=\"float\" type=\"string\">$float</item>\n");
\r
777 open (my $in, '>', $file) || error ("$file: $!");
\r
785 my($type_key, @xml_opts) = @_;
\r
788 foreach my $claim (@xml_opts) {
\r
790 my ($res, $compare, $xval) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
\r
791 if ($res eq $type_key . "_type") {
\r
801 sub get_low_high_def($@) {
\r
803 my($sgkey, @xml_opts) = @_;
\r
809 foreach my $claim (@xml_opts) {
\r
810 my ($res, $compare, $xval) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
\r
811 if ($res eq $sgkey . "_low") {
\r
814 elsif ($res eq $sgkey . "_high") {
\r
817 elsif ($res eq $sgkey) {
\r
822 return ($low, $high, $default);
\r
827 sub make_settings_xml($\@\@) {
\r
830 my @xml_opts = @{$_[1]};
\r
831 my @old_settings_xml = @{$_[2]};
\r
832 my $file = "project/xscreensaver/res/values/settings.xml";
\r
834 my $body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
\r
836 "xmlns:xliff=\"urn:oasis:names:tc:xliff:document:1.2\">\n");
\r
838 my $arrays_from_old_settings = old_settings_string_arrays(@old_settings_xml);
\r
840 $body = $body . $arrays_from_old_settings;
\r
842 my (%saver_keys) = get_keys_and_values($saver, @xml_opts);
\r
843 my @key_array = keys %saver_keys;
\r
845 my ($low, $high, $low_label, $high_label, $type);
\r
848 # for each setting of the hack which we chose to add
\r
849 foreach my $selected_setting_key (@key_array) {
\r
850 # see what values were in the relevant xml in hacks/config for this hack
\r
851 foreach my $claim (@xml_opts) {
\r
852 my ($xres, $xcompare, $xval) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
\r
853 if ($xres =~ /^$selected_setting_key/) {
\r
855 if ($xres =~ /_/ ) {
\r
856 ($one, $two) = ($xres =~ m/^(.*)_(.*)$/s);
\r
857 if ($two eq "type") {
\r
859 } elsif ($two eq "low-label") {
\r
860 $low_label = $xval;
\r
861 } elsif ($two eq "high-label") {
\r
862 $high_label = $xval;
\r
863 } elsif ($two eq "low") {
\r
865 } elsif ($two eq "high") {
\r
870 if ($type eq "select") {
\r
871 push @selects, $xval;
\r
877 # add setting values based on the setting type (boolean, number, select)
\r
878 if ($type eq "boolean") {
\r
879 $body = $body . " <string-array name=\"" . $saver .
\r
880 "_" . $selected_setting_key . "_names" . "\">\n" .
\r
881 " <item>\"True\"</item>\n" .
\r
882 " <item>\"False\"</item>\n" .
\r
883 " </string-array>\n" .
\r
884 " <string-array name=\"" . $saver . "_" . $selected_setting_key .
\r
885 "_prefix" . "\">\n" .
\r
886 " <item>\@string/t</item>\n" .
\r
887 " <item>\@string/f</item>\n" .
\r
888 " </string-array>\n";
\r
889 } elsif ($type eq "number") {
\r
890 $body = $body . " <string-array name=\"" . $saver .
\r
891 "_" . $selected_setting_key . "_names" . "\">\n" .
\r
892 " <item>\"" . $low_label . "\"</item>\n" .
\r
893 " <item>\"" . $high_label . "\"</item>\n" .
\r
894 " </string-array>\n" .
\r
895 " <string-array name=\"" . $saver . "_" . $selected_setting_key .
\r
896 "_prefix" . "\">\n" .
\r
897 " <item>\"" . $low . "\"</item>\n" .
\r
898 " <item>\"" . $high . "\"</item>\n" .
\r
899 " </string-array>\n";
\r
900 } elsif ($type eq "select") {
\r
901 $body = $body . " <string-array name=\"" . $saver .
\r
902 "_" . $selected_setting_key . "_names" . "\">\n";
\r
904 foreach my $item (@selects) {
\r
905 $body = $body . " <item>\"" . $item . "\"</item>\n" ;
\r
908 $body = $body . " </string-array>\n" .
\r
909 " <string-array name=\"" . $saver .
\r
910 "_" . $selected_setting_key . "_prefix" . "\">\n";
\r
912 foreach my $item (@selects) {
\r
913 $body = $body . " <item>\"" . $item . "\"</item>\n" ;
\r
916 $body = $body . " </string-array>\n";
\r
925 open (my $in, '>', $file) || error ("$file: $!");
\r
932 sub old_settings_string_arrays(@) {
\r
934 my (@old_settings_file) = @_;
\r
937 my $current_string_array='';
\r
940 foreach my $claim (@old_settings_file) {
\r
941 my ($res, $compare, $xval) = ($claim =~ m/^(.*) (=) (.*)$/s);
\r
942 error ("unparsable xml claim: $_") unless $compare;
\r
944 if ($current_string_array ne $res) {
\r
945 if (length($current_string_array) > 0) {
\r
946 $body = $body . " </string-array>\n";
\r
949 $current_string_array = $res;
\r
950 $body = $body . " <string-array name=\"" . $current_string_array .
\r
954 $body = $body . " <item>" . $xval . "</item>\n";
\r
957 if ($#old_settings_file > -1) {
\r
958 $body = $body . " </string-array>\n";
\r
967 # TODO: This adds the proper parameters to settings such as hilbert's, but it
\r
968 # does not remove the improper parameters from hacks such as Hilbert yet.
\r
970 sub get_settings($$\@) {
\r
972 my $switchmap = $_[1];
\r
973 my @xml_opts = @{$_[2]};
\r
975 my @keys = keys % { $switchmap};
\r
980 foreach my $sgkey (@keys) {
\r
981 my ($k, $v) = ($switchmap->{$sgkey} =~ m/^(.*): (.*)$/);
\r
984 foreach my $claim (@xml_opts) {
\r
985 my ($res, $compare, $val) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
\r
986 if ($res eq $k && $val eq $v) {
\r
987 $val_seen = $val_seen + 1;
\r
989 elsif ($res eq $k) {
\r
990 $res_seen = $res_seen + 1;
\r
994 if ($val_seen eq 0 && $res_seen > 0) {
\r
995 my $so = "$k != $v";
\r
1004 my @all = (@xml_opts, @also);
\r
1010 sub make_strings_xml($\@\@) {
\r
1012 my $saver = $_[0];
\r
1013 my @xml_opts = @{$_[1]};
\r
1014 my @strings_xml_opts = @{$_[2]};
\r
1016 my $saver_name = $saver . "_name";
\r
1017 my $hack = ucfirst($saver);
\r
1018 my $file = "project/xscreensaver/res/values/strings.xml";
\r
1019 my (%saver_keys) = get_keys_and_values($saver, @xml_opts);
\r
1021 my $body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
\r
1023 " <string name=\"hello\">Hello World!</string>\n" .
\r
1024 " <string name=\"service_label\">Xscreensaver</string>\n" .
\r
1025 " <string name=\"description\">A live wallpaper</string>\n\n" .
\r
1026 " <string name=\"app_name\">Xscreensaver</string>\n" .
\r
1027 " <string name=\"author\">jwz and helpers</string>\n" .
\r
1028 " <string name=\"t\">True</string>\n" .
\r
1029 " <string name=\"f\">False</string>\n");
\r
1031 foreach my $claim (@strings_xml_opts) {
\r
1032 my ($res, $compare, $xval) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
\r
1033 error ("$saver: unparsable xml claim: $_") unless $compare;
\r
1034 if ($res eq 'hello' ||
\r
1035 $res eq 'service_label' ||
\r
1036 $res eq 'description' ||
\r
1037 $res eq 'app_name' ||
\r
1038 $res eq 'author' ||
\r
1042 elsif ($res eq $saver_name) {
\r
1043 error ("$saver: $saver already in $file");
\r
1047 " <string name=\"" . $res . "\">" . $xval . "</string>\n");
\r
1052 " <string name=\"" . $saver . "_name\">" . $hack .
\r
1054 " <string name=\"" . $saver .
\r
1055 "_settings\">Settings</string>\n" .
\r
1056 " <string name=\"" . $saver . "_description\">" . $hack .
\r
1060 my @keyarray = keys %saver_keys;
\r
1062 foreach my $sgkey (@keyarray) {
\r
1064 my $type = get_type($sgkey, @xml_opts);
\r
1066 if ($type eq "number") {
\r
1068 my ($low, $high, $default) = get_low_high_def($sgkey, @xml_opts);
\r
1069 my $float = ($default - $low) / ($high - $low);
\r
1071 $body = ($body . " <string name=\"" . $saver . "_" . $sgkey .
\r
1072 "_settings_title\">" . "Set " . $sgkey . "</string>\n" .
\r
1073 " <string name=\"" . $saver . "_" . $sgkey .
\r
1074 "_settings_summary\">" . "Choose " . $sgkey . "</string>\n" .
\r
1075 " <string name=\"" . $saver . "_" . $sgkey .
\r
1076 "_low\">" . $low . "</string>\n" .
\r
1077 " <string name=\"" . $saver . "_" . $sgkey .
\r
1078 "_high\">" . $high . "</string>\n" .
\r
1079 " <string name=\"" . $saver . "_" . $sgkey .
\r
1080 "_default\">" . $saver_keys{$sgkey} . "</string>\n");
\r
1084 $body = ($body . " <string name=\"" . $saver . "_" . $sgkey .
\r
1085 "_settings_title\">" . "Set " . $sgkey . "</string>\n" .
\r
1086 " <string name=\"" . $saver . "_" . $sgkey .
\r
1088 "_settings_summary\">" . "Choose " . $sgkey . "</string>\n" .
\r
1089 " <string name=\"" . $saver . "_" . $sgkey .
\r
1090 "_default\">" . $saver_keys{$sgkey} . "</string>\n");
\r
1095 "</resources>\n");
\r
1097 open (my $in, '>', $file) || error ("$file: $!");
\r
1103 sub make_hack_xml($) {
\r
1105 my $hack = ucfirst($saver);
\r
1107 my $dir = "project/xscreensaver/res/xml/";
\r
1108 my $file = $dir . $saver . ".xml";
\r
1112 open ($in, '>', $file) || error ("$file: $!");
\r
1116 open ($in, '>', $file) || error ("$file: $!");
\r
1119 my $body = ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" .
\r
1120 "<wallpaper xmlns:android=" .
\r
1121 "\"http://schemas.android.com/apk/res/android\"\n" .
\r
1122 " android:description=\"\@string/" . $saver .
\r
1123 "_description\"\n" .
\r
1124 " android:settingsActivity=\"org.jwz.xscreensaver.gen.$hack" .
\r
1126 " android:thumbnail=\"\@drawable/" . $saver .
\r
1134 sub make_glue($$) {
\r
1135 my ($saver, @glue_hacks) = @_;
\r
1136 my (@hacks) = @glue_hacks;
\r
1138 push @hacks, $saver;
\r
1141 my $file = $dir . "glue.c";
\r
1145 open ($in, '>', $file) || error ("$file: $!");
\r
1149 open ($in, '>', $file) || error ("$file: $!");
\r
1153 my $body = ("#include <jni.h>\n" .
\r
1154 "#include <math.h>\n" .
\r
1155 "#include <stdlib.h>\n" .
\r
1156 "#include <stdio.h>\n" .
\r
1157 "#include <time.h>\n" .
\r
1158 "#include <pthread.h>\n" .
\r
1159 "#include <GLES/gl.h>\n\n" .
\r
1160 "#include \"screenhackI.h\"\n" .
\r
1161 "#include \"jwzglesI.h\"\n" .
\r
1162 "#include \"version.h\"\n\n" .
\r
1163 "void drawXscreensaver();\n\n" .
\r
1164 "int sWindowWidth = 0;\n" .
\r
1165 "int sWindowHeight = 0;\n" .
\r
1166 "int initTried = 0;\n" .
\r
1167 "int renderTried = 0;\n" .
\r
1168 "int resetTried = 0;\n" .
\r
1169 "int currentFlip = 0;\n\n" .
\r
1170 "pthread_mutex_t mutg = PTHREAD_MUTEX_INITIALIZER;\n\n" .
\r
1171 "extern struct xscreensaver_function_table " .
\r
1172 "*xscreensaver_function_table;\n\n" .
\r
1173 "// if adding a table here, increase the magic number\n" .
\r
1174 "struct xscreensaver_function_table\n");
\r
1176 for my $i (0 .. $#hacks) {
\r
1177 $body = $body . " *" . $hacks[$i] ;
\r
1178 $body = $body . "_xscreensaver_function_table";
\r
1179 if ($i eq $#hacks ) {
\r
1180 $body = $body . ";\n\n";
\r
1183 $body = $body . ",\n";
\r
1187 $body = $body . "struct running_hack {\n" .
\r
1188 " struct xscreensaver_function_table *xsft;\n" .
\r
1189 " Display *dpy;\n" .
\r
1190 " Window window;\n" .
\r
1191 " void *closure;\n" .
\r
1193 "const char *progname;\n" .
\r
1194 "const char *progclass;\n\n" .
\r
1195 "struct running_hack rh[";
\r
1196 $body = $body . scalar(@hacks);
\r
1197 $body = $body . "];\n" .
\r
1198 "// ^ magic number of hacks - TODO: remove magic number\n\n\n" .
\r
1200 "JNIEXPORT void JNICALL\n" .
\r
1201 " Java_org_jwz_xscreensaver_CallNative_nativeInit\n" .
\r
1202 " (JNIEnv * env);\n" .
\r
1203 "JNIEXPORT void JNICALL\n" .
\r
1204 " Java_org_jwz_xscreensaver_CallNative_nativeResize\n" .
\r
1205 " (JNIEnv * env, jobject thiz, jint w, jint h);\n" .
\r
1206 "JNIEXPORT void JNICALL\n" .
\r
1207 " Java_org_jwz_xscreensaver_CallNative_nativeRender\n" .
\r
1208 " (JNIEnv * env);\n" .
\r
1209 "JNIEXPORT void JNICALL\n" .
\r
1210 " Java_org_jwz_xscreensaver_CallNative_nativeDone\n" .
\r
1211 " (JNIEnv * env);\n";
\r
1213 foreach my $bighack (@hacks) {
\r
1214 my $bh = ucfirst($bighack);
\r
1215 $body = $body . "JNIEXPORT void JNICALL\n" .
\r
1216 " Java_org_jwz_xscreensaver_gen_" . $bh .
\r
1217 "Wallpaper_allnativeSettings\n" .
\r
1218 " (JNIEnv * env, jobject thiz, jstring jhack," .
\r
1219 " jstring hackPref,\n" .
\r
1220 " jint draw, jstring key);\n";
\r
1224 $body = $body . "\n\n\nvoid doinit()\n{\n\n" ;
\r
1226 for my $j (0 .. $#hacks) {
\r
1228 $body = $body . " if (chosen == " . $j . ") {\n" ;
\r
1229 } elsif ($j == $#hacks) {
\r
1230 $body = $body . " } else {\n" ;
\r
1232 $body = $body . " } else if (chosen == " . $j . ") {\n";
\r
1234 $body = $body . " progname = \"" . $hacks[$j] . "\";\n" .
\r
1235 " rh[chosen].xsft = &" . $hacks[$j] .
\r
1236 "_xscreensaver_function_table;\n" ;
\r
1239 $body = $body . " }\n\n" ;
\r
1240 $body = $body . " rh[chosen].dpy = jwxyz_make_display(0, 0);\n" .
\r
1241 " rh[chosen].window = XRootWindow(rh[chosen].dpy, 0);\n" .
\r
1242 "// TODO: Zero looks right, " .
\r
1243 "but double-check that is the right number\n\n" .
\r
1244 " progclass = rh[chosen].xsft->progclass;\n\n" .
\r
1245 " if (rh[chosen].xsft->setup_cb)\n" .
\r
1246 " rh[chosen].xsft->setup_cb(rh[chosen].xsft,\n" .
\r
1247 " rh[chosen].xsft->setup_arg);\n\n" .
\r
1248 " if (resetTried < 1) {\n" .
\r
1249 " resetTried++;\n" .
\r
1250 " jwzgles_reset();\n" .
\r
1252 " void *(*init_cb) (Display *, Window, void *) =\n" .
\r
1253 " (void *(*)(Display *, Window, void *)) " .
\r
1254 "rh[chosen].xsft->init_cb;\n\n" .
\r
1255 " rh[chosen].closure =\n" .
\r
1256 " init_cb(rh[chosen].dpy, rh[chosen].window,\n" .
\r
1257 " rh[chosen].xsft->setup_arg);\n\n}\n\n\n" .
\r
1258 "void drawXscreensaver()\n{\n" .
\r
1259 " pthread_mutex_lock(&mutg);\n" .
\r
1260 " rh[chosen].xsft->draw_cb(rh[chosen].dpy, " .
\r
1261 "rh[chosen].window,\n" .
\r
1262 " rh[chosen].closure);\n" .
\r
1263 " pthread_mutex_unlock(&mutg);\n\n}\n\n\n" .
\r
1264 "JNIEXPORT void JNICALL\n" .
\r
1265 " Java_org_jwz_xscreensaver_CallNative_nativeInit\n" .
\r
1266 " (JNIEnv * env) {\n\n" .
\r
1267 " if (initTried < 1) {\n" .
\r
1268 " initTried++;\n" .
\r
1270 " if (!rh[chosen].dpy) {\n" .
\r
1273 " rh[chosen].xsft->free_cb(rh[chosen].dpy, " .
\r
1274 "rh[chosen].window,\n" .
\r
1275 " rh[chosen].closure);\n" .
\r
1276 " jwxyz_free_display(rh[chosen].dpy);\n" .
\r
1277 " rh[chosen].dpy = NULL;\n" .
\r
1278 " rh[chosen].window = NULL;\n" .
\r
1279 " if (!rh[chosen].dpy) {\n" .
\r
1283 "JNIEXPORT void JNICALL\n" .
\r
1284 " Java_org_jwz_xscreensaver_CallNative_nativeResize\n" .
\r
1285 " (JNIEnv * env, jobject thiz, jint w, jint h) {\n\n" .
\r
1286 " sWindowWidth = w;\n" .
\r
1287 " sWindowHeight = h;\n\n" .
\r
1288 " if (!rh[chosen].dpy) {\n" .
\r
1291 " jwxyz_window_resized(rh[chosen].dpy, " .
\r
1292 "rh[chosen].window, 0, 0, w, h, 0);\n\n" .
\r
1293 " rh[chosen].xsft->reshape_cb(rh[chosen].dpy, " .
\r
1294 "rh[chosen].window,\n" .
\r
1295 " rh[chosen].closure, w, h);\n}\n\n" .
\r
1296 "JNIEXPORT void JNICALL\n" .
\r
1297 " Java_org_jwz_xscreensaver_CallNative_nativeRender\n" .
\r
1298 " (JNIEnv * env) {\n" .
\r
1299 " if (renderTried < 1) {\n" .
\r
1300 " renderTried++;\n" .
\r
1302 " drawXscreensaver();\n" .
\r
1304 "// TODO: Check Java side is calling this properly\n" .
\r
1305 "JNIEXPORT void JNICALL\n" .
\r
1306 " Java_org_jwz_xscreensaver_CallNative_nativeDone\n" .
\r
1307 " (JNIEnv * env) {\n\n" .
\r
1308 " rh[chosen].xsft->free_cb(rh[chosen].dpy, " .
\r
1309 "rh[chosen].window,\n" .
\r
1310 " rh[chosen].closure);\n" .
\r
1311 " jwxyz_free_display(rh[chosen].dpy);\n" .
\r
1312 " rh[chosen].dpy = NULL;\n" .
\r
1313 " rh[chosen].window = NULL;\n\n}\n\n" ;
\r
1315 for my $j (0 .. $#hacks) {
\r
1316 my $jhack = ucfirst($hacks[$j]);
\r
1318 $body = $body . "JNIEXPORT void JNICALL\n" .
\r
1319 " Java_org_jwz_xscreensaver_gen_" . $jhack .
\r
1320 "Wallpaper_allnativeSettings\n" .
\r
1321 " (JNIEnv * env, jobject thiz, jstring jhack," .
\r
1322 " jstring hackPref,\n" .
\r
1323 " jint draw, jstring key) {\n\n" .
\r
1324 " const char *chack = " .
\r
1325 "(*env)->GetStringUTFChars(env, hackPref, NULL);\n" .
\r
1326 " char *hck = (char *) chack;\n" .
\r
1327 " const char *kchack = " .
\r
1328 "(*env)->GetStringUTFChars(env, key, NULL);\n" .
\r
1329 " char *khck = (char *) kchack;\n\n" .
\r
1330 " if (draw == 2) {\n" .
\r
1331 " set" . $jhack . "Settings(hck, khck);\n" .
\r
1333 " chosen = " . $j . ";\n}\n\n";
\r
1342 sub make_wallpaper($$) {
\r
1343 my ($saver, @xml_opts) = @_;
\r
1344 my $hack = ucfirst($saver);
\r
1345 my $file = "project/xscreensaver/src/org/jwz/xscreensaver/gen/";
\r
1346 $file = $file . $hack . "Wallpaper.java";
\r
1347 my (%saver_keys) = get_keys_and_values($saver, @xml_opts);
\r
1349 open (my $in, '>', $file) || error ("$file: $!");
\r
1351 my $body = ("package org.jwz.xscreensaver.gen;\n" .
\r
1352 "import javax.microedition.khronos.egl.EGLConfig;\n" .
\r
1353 "import javax.microedition.khronos.opengles.GL10;\n" .
\r
1354 "import net.rbgrn.android.glwallpaperservice.*;\n" .
\r
1355 "import android.opengl.GLU;\n" .
\r
1356 "import android.content.Context;\n" .
\r
1357 "import android.content.SharedPreferences;\n" .
\r
1358 "import org.jwz.xscreensaver.*;\n" .
\r
1359 "public class " . $hack .
\r
1360 "Wallpaper extends ARenderer {\n" .
\r
1361 " private static native void allnativeSettings(" .
\r
1362 "String hack, String hackPref, int draw, String key);\n" .
\r
1363 " public static final String SHARED_PREFS_NAME=\"" . $saver .
\r
1365 " CallNative cn;\n" .
\r
1366 " public void onSurfaceCreated(" .
\r
1367 "GL10 gl, EGLConfig config) {\n" .
\r
1368 " super.onSurfaceCreated(gl, config);\n" .
\r
1369 " cn = new CallNative();\n" .
\r
1370 " NonSurfaceCreated();\n" .
\r
1372 " public void onDrawFrame(GL10 gl) {\n" .
\r
1373 " super.onDrawFrame(gl);\n" .
\r
1374 " allnativeSettings(\"bogus\", \"bogus\", 1, \"bogus\");\n" .
\r
1375 " NonDrawFrame();\n" .
\r
1377 " void NonDrawFrame() {\n" .
\r
1378 " cn.nativeRender();\n" .
\r
1380 " void doSP(SharedPreferences sspp) {\n" .
\r
1383 " String hack = \"" . $saver . "\";\n");
\r
1385 my @keyarray = keys %saver_keys;
\r
1386 foreach my $sgkey (@keyarray) {
\r
1388 my $type = get_type($sgkey, @xml_opts);
\r
1390 if ($type eq "number") {
\r
1392 my ($low, $high, $default) = get_low_high_def($sgkey, @xml_opts);
\r
1393 my $float = ($default - $low) / ($high - $low);
\r
1396 " String " . $sgkey .
\r
1397 "_low = sspp.getString(\"" . $saver .
\r
1398 "_" . $sgkey . "_low\", \"". $low . "\");\n" .
\r
1399 " String " . $sgkey .
\r
1400 "_high = sspp.getString(\"" . $saver .
\r
1401 "_" . $sgkey . "_high\", \"" . $high . "\");\n" .
\r
1402 " Float " . $sgkey . "PrefF = sspp.getFloat(\"" . $saver .
\r
1403 "_" . $sgkey . "\", " . $float . "f);\n" .
\r
1404 " String " . $sgkey . "Pref = getNumber(" . $sgkey .
\r
1405 "_low, " . $sgkey . "_high, " . $sgkey . "PrefF);\n" .
\r
1406 " allnativeSettings(hack, " . $sgkey .
\r
1407 "Pref, 2, \"" . $saver . "_" . $sgkey . "\");\n";
\r
1409 elsif ($type eq "boolean") {
\r
1411 $body = $body . " String " . $sgkey .
\r
1412 "Pref = sspp.getString(\"" . $saver . "_" . $sgkey .
\r
1413 "\", \"" . $saver_keys{$sgkey} . "\");\n" .
\r
1414 " allnativeSettings(hack, " . $sgkey .
\r
1415 "Pref, 2, \"" . $saver . "_" . $sgkey . "\");\n";
\r
1418 elsif ($type eq "select") {
\r
1420 $body = $body . " String " . $sgkey .
\r
1421 "Pref = sspp.getString(\"" . $saver . "_" . $sgkey .
\r
1422 "\", \"" . $saver_keys{$sgkey} . "\");\n" .
\r
1423 " allnativeSettings(hack, " . $sgkey .
\r
1424 "Pref, 2, \"" . $saver . "_" . $sgkey . "\");\n";
\r
1428 print STDERR "$progname: type $type not yet implemented \n";
\r
1433 $body = $body . " }\n" .
\r
1434 " String getNumber(String low, String high, Float pref) {\n" .
\r
1435 " Float lowF = Float.parseFloat(low);\n" .
\r
1436 " Float lowH = Float.parseFloat(high);\n" .
\r
1437 " Float diff = lowH - lowF;\n" .
\r
1438 " Float mult = pref * diff;\n" .
\r
1439 " Float add = mult + lowF;\n" .
\r
1442 " if (diff > 2.0) {\n" .
\r
1443 " i = (Integer) Math.round(add);\n" .
\r
1444 " s = Integer.toString(i);\n}\n" .
\r
1446 " s = Float.toString(add);\n}\n" .
\r
1451 " System.loadLibrary (\"xscreensaver\");\n" .
\r
1460 sub get_keys_and_values($$) {
\r
1462 my ($saver, @xml_opts) = @_;
\r
1463 my (%saver_keys) ;
\r
1465 foreach my $claim (@xml_opts) {
\r
1466 my ($res, $compare, $xval) = ($claim =~ m/^(.*) (=|!=) (.*)$/s);
\r
1467 error ("$saver: unparsable xml claim: $_") unless $compare;
\r
1469 if ($saver eq "sproingies") {
\r
1470 if ($res eq "count") {
\r
1471 $saver_keys{$res} = $xval;
\r
1473 elsif ($res eq "wireframe") {
\r
1474 #$saver_keys{$res} = $xval;
\r
1475 $saver_keys{$res} = "False";
\r
1479 elsif ($saver eq "hilbert") {
\r
1480 if ($res eq "mode") {
\r
1481 $saver_keys{$res} = $xval;
\r
1484 elsif ($saver eq "stonerview") {
\r
1485 if ($res eq "transparent") {
\r
1486 #$saver_keys{$res} = $xval;
\r
1487 $saver_keys{$res} = "False";
\r
1490 elsif ($saver eq "superquadrics") {
\r
1491 # spinspeed/speed. float/int
\r
1492 if ($res eq "spinspeed") {
\r
1493 $saver_keys{$res} = $xval;
\r
1496 elsif ($saver eq "bouncingcow") {
\r
1497 if ($res eq "count") {
\r
1498 $saver_keys{$res} = "3";
\r
1500 elsif ($res eq "speed") {
\r
1501 $saver_keys{$res} = "0.1";
\r
1504 elsif ($saver eq "unknownpleasures") {
\r
1505 if ($res eq "wireframe") {
\r
1506 $saver_keys{$res} = "True";
\r
1508 elsif ($res eq "speed") {
\r
1509 $saver_keys{$res} = "3.0";
\r
1511 #elsif ($res eq "count") {
\r
1512 # $saver_keys{$res} = $xval;
\r
1514 #elsif ($res eq "resolution") {
\r
1515 # $saver_keys{$res} = $xval;
\r
1517 #elsif ($res eq "ortho") {
\r
1518 # $saver_keys{$res} = $xval;
\r
1522 elsif ($saver eq "hypertorus") {
\r
1523 if ($res =~ /^(displayMode|appearance|colors|projection3d|projection4d|speedwx|speedwy|speedwz|speedxy|speedxz|speedyz)$/) {
\r
1524 $saver_keys{$res} = $xval;
\r
1527 elsif ($saver eq "glhanoi") {
\r
1528 if ($res =~ /^(light|fog|trails|poles|speed)$/) {
\r
1529 # TODO: check in xval for true/false should be higher up in logic
\r
1530 if ($xval =~ /^(true|false)$/) {
\r
1531 $saver_keys{$res} = ucfirst($xval);
\r
1534 $saver_keys{$res} = $xval;
\r
1539 error ("$saver: not yet supported for Android");
\r
1544 return (%saver_keys);
\r
1548 sub make_service($) {
\r
1550 my $hack = ucfirst($saver);
\r
1551 my $file = "project/xscreensaver/src/org/jwz/xscreensaver/gen/";
\r
1552 $file = $file . $hack . "Service.java";
\r
1553 open (my $in, '>', $file) || error ("$file: $!");
\r
1555 my $body = ("package org.jwz.xscreensaver.gen;\n\n" .
\r
1556 "import net.rbgrn.android.glwallpaperservice.*;\n" .
\r
1557 "import android.content.SharedPreferences;\n" .
\r
1558 "import org.jwz.xscreensaver.*;\n\n" .
\r
1559 "// Original code provided by Robert Green\n" .
\r
1560 "// http://www.rbgrn.net/content/354-glsurfaceview-adapted-3d-live-wallpapers\n" .
\r
1561 "public class " . $hack .
\r
1562 "Service extends GLWallpaperService {\n\n" .
\r
1563 " SharedPreferences sp;\n\n" .
\r
1564 " public " . $hack .
\r
1569 " public void onCreate() {\n" .
\r
1570 " sp = ((XscreensaverApp)getApplication())." .
\r
1571 "getThePrefs($hack" . "Wallpaper.SHARED_PREFS_NAME);\n" .
\r
1573 " public Engine onCreateEngine() {\n" .
\r
1574 " MyEngine engine = new MyEngine();\n" .
\r
1575 " return engine;\n" .
\r
1577 " class MyEngine extends GLEngine {\n" .
\r
1579 "Wallpaper renderer;\n" .
\r
1580 " public MyEngine() {\n" .
\r
1582 " // handle prefs, other initialization\n" .
\r
1583 " renderer = new " . $hack .
\r
1584 "Wallpaper();\n" .
\r
1585 " setRenderer(renderer);\n" .
\r
1586 " setRenderMode(RENDERMODE_CONTINUOUSLY);\n" .
\r
1588 " public void onDestroy() {\n" .
\r
1589 " super.onDestroy();\n" .
\r
1590 " if (renderer != null) {\n" .
\r
1591 " renderer.release(); " .
\r
1592 "// assuming yours has this method - it should!\n" .
\r
1594 " renderer = null;\n" .
\r
1597 " public void onVisibilityChanged(boolean visible) {\n" .
\r
1598 " super.onVisibilityChanged(visible);\n" .
\r
1599 " if (visible) {\n" .
\r
1600 " renderer.doSP(sp);\n" .
\r
1606 " System.loadLibrary (\"xscreensaver\");\n" .
\r
1615 sub make_settings($) {
\r
1617 my $hack = ucfirst($saver);
\r
1618 my $dir = "project/xscreensaver/src/org/jwz/xscreensaver/gen/";
\r
1619 my $file = $dir . $hack . "Settings.java";
\r
1623 open ($in, '>', $file) || error ("$file: $!");
\r
1627 open ($in, '>', $file) || error ("$file: $!");
\r
1630 my $body = ("/*\n" .
\r
1631 " * Copyright (C) 2009 Google Inc.\n" .
\r
1633 " * Licensed under the Apache License, Version 2.0 " .
\r
1634 "(the \"License\"); you may not\n" .
\r
1635 " * use this file except in compliance with the License. " .
\r
1636 "You may obtain a copy of\n" .
\r
1637 " * the License at\n" .
\r
1639 " * http://www.apache.org/licenses/LICENSE-2.0\n" .
\r
1641 " * Unless required by applicable law or agreed to in writing," .
\r
1643 " * distributed under the License is distributed" .
\r
1644 " on an \"AS IS\" BASIS, WITHOUT\n" .
\r
1645 " * WARRANTIES OR CONDITIONS OF ANY KIND," .
\r
1646 " either express or implied. See the\n" .
\r
1647 " * License for the specific language governing" .
\r
1648 "permissions and limitations under\n" .
\r
1649 " * the License.\n" .
\r
1651 "package org.jwz.xscreensaver.gen;\n\n" .
\r
1652 "import org.jwz.xscreensaver.R;\n\n" .
\r
1653 "import android.content.SharedPreferences;\n" .
\r
1654 "import android.os.Bundle;\n" .
\r
1655 "import android.preference.PreferenceActivity;\n\n" .
\r
1656 "public class " . $hack .
\r
1657 "Settings extends PreferenceActivity\n" .
\r
1659 "SharedPreferences.OnSharedPreferenceChangeListener {\n\n" .
\r
1661 " protected void onCreate(Bundle icicle) {\n" .
\r
1662 " super.onCreate(icicle);\n" .
\r
1663 " getPreferenceManager().setSharedPreferencesName(\n" .
\r
1665 "Wallpaper.SHARED_PREFS_NAME);\n" .
\r
1666 " addPreferencesFromResource(R.xml." . $saver .
\r
1668 " getPreferenceManager().getSharedPreferences()." .
\r
1669 "registerOnSharedPreferenceChangeListener(\n" .
\r
1673 " protected void onResume() {\n" .
\r
1674 " super.onResume();\n" .
\r
1677 " protected void onDestroy() {\n" .
\r
1678 " getPreferenceManager().getSharedPreferences()." .
\r
1679 "unregisterOnSharedPreferenceChangeListener(\n" .
\r
1681 " super.onDestroy();\n" .
\r
1683 " public void onSharedPreferenceChanged(" .
\r
1684 "SharedPreferences sharedPreferences,\n" .
\r
1685 " String key) {\n" .
\r
1696 print STDERR "$progname: $err\n";
\r
1701 print STDERR "usage: $progname [--verbose] files ...\n";
\r
1707 while ($#ARGV >= 0) {
\r
1709 if (m/^--?verbose$/) { $verbose++; }
\r
1710 elsif (m/^-v+$/) { $verbose += length($_)-1; }
\r
1711 elsif (m/^-./) { usage; }
\r
1712 else { push @files, $_; }
\r
1716 usage unless ($#files >= 0);
\r
1718 foreach (@files) { $failures += parse_then_make($_); }
\r