diff --git a/tools/buildzip.pl b/tools/buildzip.pl
index 6d25a01..3333c8a 100755
--- a/tools/buildzip.pl
+++ b/tools/buildzip.pl
@@ -625,9 +625,11 @@ STOP
# Now do the WPS dance
if(-d "$ROOT/wps") {
- my $wps_build_cmd="perl $ROOT/wps/wpsbuild.pl ";
- $wps_build_cmd=$wps_build_cmd."-v " if $verbose;
- $wps_build_cmd=$wps_build_cmd." --tempdir=$temp_dir --rbdir=$rbdir -r $ROOT -m $modelname $ROOT/wps/WPSLIST $target";
+# my $wps_build_cmd="perl $ROOT/wps/wpsbuild.pl ";
+ my $wps_build_cmd="perl $ROOT/wps/wpsbuild2.pl";
+ $wps_build_cmd=$wps_build_cmd." -v" if $verbose;
+# $wps_build_cmd=$wps_build_cmd." --tempdir=$temp_dir --rbdir=$rbdir -r $ROOT -m $modelname $ROOT/wps/WPSLIST $target";
+ $wps_build_cmd=$wps_build_cmd." --tempdir=$temp_dir --rbdir=$rbdir -r $ROOT -m $modelname $ROOT/wps/WPSLIST.xml";
print "wpsbuild: $wps_build_cmd\n" if $verbose;
system("$wps_build_cmd");
print "wps_build_cmd: done\n" if $verbose;
@@ -637,25 +639,25 @@ STOP
}
# until buildwps.pl is fixed, manually copy the classic_statusbar theme across
- mkdir "$temp_dir/wps/classic_statusbar", 0777;
- glob_copy("$ROOT/wps/classic_statusbar/*.bmp", "$temp_dir/wps/classic_statusbar");
- if ($swcodec) {
- if ($depth == 16) {
- copy("$ROOT/wps/classic_statusbar.sbs", "$temp_dir/wps");
- } elsif ($depth > 1) {
- copy("$ROOT/wps/classic_statusbar.grey.sbs", "$temp_dir/wps/classic_statusbar.sbs");
- } else {
- copy("$ROOT/wps/classic_statusbar.mono.sbs", "$temp_dir/wps/classic_statusbar.sbs");
- }
- } else {
- copy("$ROOT/wps/classic_statusbar.112x64x1.sbs", "$temp_dir/wps/classic_statusbar.sbs");
- }
- if ($remote_depth != $depth) {
- copy("$ROOT/wps/classic_statusbar.mono.sbs", "$temp_dir/wps/classic_statusbar.rsbs");
- } else {
- copy("$temp_dir/wps/classic_statusbar.sbs", "$temp_dir/wps/classic_statusbar.rsbs");
- }
- copy("$temp_dir/wps/rockbox_none.sbs", "$temp_dir/wps/rockbox_none.rsbs");
+# mkdir "$temp_dir/wps/classic_statusbar", 0777;
+# glob_copy("$ROOT/wps/classic_statusbar/*.bmp", "$temp_dir/wps/classic_statusbar");
+# if ($swcodec) {
+# if ($depth == 16) {
+# copy("$ROOT/wps/classic_statusbar.sbs", "$temp_dir/wps");
+# } elsif ($depth > 1) {
+# copy("$ROOT/wps/classic_statusbar.grey.sbs", "$temp_dir/wps/classic_statusbar.sbs");
+# } else {
+# copy("$ROOT/wps/classic_statusbar.mono.sbs", "$temp_dir/wps/classic_statusbar.sbs");
+# }
+# } else {
+# copy("$ROOT/wps/classic_statusbar.112x64x1.sbs", "$temp_dir/wps/classic_statusbar.sbs");
+# }
+# if ($remote_depth != $depth) {
+# copy("$ROOT/wps/classic_statusbar.mono.sbs", "$temp_dir/wps/classic_statusbar.rsbs");
+# } else {
+# copy("$temp_dir/wps/classic_statusbar.sbs", "$temp_dir/wps/classic_statusbar.rsbs");
+# }
+# copy("$temp_dir/wps/rockbox_none.sbs", "$temp_dir/wps/rockbox_none.rsbs");
# and the info file
copy("rockbox-info.txt", "$temp_dir/rockbox-info.txt");
diff --git a/wps/WPSLIST.xml b/wps/WPSLIST.xml
new file mode 100644
index 0000000..8ea4e6c
--- /dev/null
+++ b/wps/WPSLIST.xml
@@ -0,0 +1,304 @@
+
+
+ ipodVOL
+ xameius
+ 12-Nimbus.fnt
+ 08-Schumacher-Clean.fnt
+ top
+ top
+ -
+ -
+ -
+ bar (inverse)
+
+ ipodVOL.wps
+ rockbox_default.rwps
+
+
+
+ boxes
+ Christi Scarborough (after Magnus Westerlund)
+ 08-Schumacher-Clean.fnt
+ 08-Schumacher-Clean.fnt
+ top
+ top
+ 000000
+ B6C6E5
+ -
+ -
+ -
+ bar (inverse)
+ -
+ -
+
+ boxes.wps
+ boxes.rwps
+
+
+
+ engineeer2
+ Magnus Westerlund
+ 08-Nedore.fnt
+ 08-Nedore.fnt
+ top
+ top
+ -
+ -
+ -
+ bar (inverse)
+ -
+ -
+
+ engineeer2.wps
+ engineeer2.rwps
+
+
+
+ iAmp
+ Raymond Hoh
+ 12-Nimbus.fnt
+ 12-Nimbus.fnt
+ -
+ -
+ -
+ bar (inverse)
+ top
+ top
+ -
+ -
+
+ iAmp.wps
+ iAmp.rwps
+
+
+
+ zezayer
+ Jake Owen, Dominik Riebeling
+ 08-Nedore.fnt
+ 08-Nedore.fnt
+ top
+ top
+ -
+ -
+ -
+ bar (inverse)
+ -
+ -
+
+ zezayer.wps
+ zezayer.rwps
+
+
+
+ DancePuffDuo
+ Chris Oxtoby
+ 13-Nimbus.fnt
+ 13-Nimbus.fnt
+ top
+ top
+ 000000
+ B6C6E5
+ -
+ -
+ -
+ bar (inverse)
+ -
+ -
+
+ DancePuffDuo.wps
+ DancePuffDuo.rwps
+
+
+
+ iCatcher
+ Ioannis Koutoulakis
+ 08-Rockfont.fnt
+ 08-Rockfont.fnt
+ 09-Nedore.fnt
+ 09-Nedore.fnt
+ 08-Nedore.fnt
+ 09-Nedore.fnt
+ 09-Nedore.fnt
+ 09-Nedore.fnt
+ 12-Nimbus.fnt
+ 14-Nimbus.fnt
+ 19-Nimbus.fnt
+ 19-Nimbus.fnt
+ 19-Nimbus.fnt
+ 09-Nedore.fnt
+ 14-Nimbus.fnt
+ -
+ 000000
+ FFFFFF
+ top
+ top
+ -
+ -
+ bar (inverse)
+ -
+ -
+
+ iCatcher.wps
+ iCatcher.rwps
+
+
+
+ UniCatcher
+ Ioannis Koutoulakis
+ 16-GNU-Unifont.fnt
+ 16-GNU-Unifont.fnt
+ -
+ 000000
+ FFFFFF
+ top
+ top
+ -
+ -
+ bar (inverse)
+ -
+ -
+
+ UniCatcher.wps
+ UniCatcher.rwps
+
+
+
+ Rockboxed
+ Roan Horning
+ 08-Schumacher-Clean.fnt
+ 08-Schumacher-Clean.fnt
+ 12-Nimbus.fnt
+ 10-Nimbus.fnt
+ 12-Nimbus.fnt
+ 12-Nimbus.fnt
+ 12-Nimbus.fnt
+ 12-Nimbus.fnt
+ 12-Nimbus.fnt
+ 14-Nimbus.fnt
+ 19-Nimbus.fnt
+ 19-Nimbus.fnt
+ 19-Nimbus.fnt
+ 000000
+ FFC000
+ top
+ -
+ -
+ -
+ bar (inverse)
+ -
+ -
+
+ Rockboxed.wps
+ rockbox_default.rwps
+
+
+
+ progressive
+ Jens Arnold
+
+ progressive.wps
+
+
+
+ cabbiev2
+ Johannes Voggenthaler, Apoo Maha, Marc Guay, Alex Vanderpol, Jerry Lange, Keith Perri, Mark Fawcus, and Marianne Arnold with support from Rockbox developers and forums. Based on Cabbie by Yohann Misquitta.
+ 35-Adobe-Helvetica.fnt
+ 27-Adobe-Helvetica.fnt
+ 15-Adobe-Helvetica.fnt
+ 16-Adobe-Helvetica.fnt
+ 15-Adobe-Helvetica.fnt
+ 12-Adobe-Helvetica.fnt
+ 12-Adobe-Helvetica.fnt
+ 12-Adobe-Helvetica.fnt
+ 12-Adobe-Helvetica.fnt
+ 12-Adobe-Helvetica.fnt
+ 12-Adobe-Helvetica.fnt
+ 12-Adobe-Helvetica.fnt
+ 12-Adobe-Helvetica.fnt
+ 12-Adobe-Helvetica.fnt
+ 12-Adobe-Helvetica.fnt
+ 11-Sazanami-Mincho.fnt
+ 08-Rockfont.fnt
+ 08-Rockfont.fnt
+
+ 08-Rockfont.fnt
+ 12-Adobe-Helvetica.fnt
+
+ CCCCCC
+ 000000
+ fde89e
+ b58c00
+ 000000
+ -
+
+ backdrops/cabbiev2.480x800x16.bmp
+ backdrops/cabbiev2.320x480x16.bmp
+ backdrops/cabbiev2.320x240x16.bmp
+ backdrops/cabbiev2.128x128x16.bmp
+ backdrops/cabbiev2.128x160x16.bmp
+ backdrops/cabbiev2.132x80x16.bmp
+ backdrops/cabbiev2.138x110x2.bmp
+ backdrops/cabbiev2.160x128x16.bmp
+ backdrops/cabbiev2.160x128x2.bmp
+ backdrops/cabbiev2.176x132x16.bmp
+ backdrops/cabbiev2.176x220x16.bmp
+ backdrops/cabbiev2.220x176x16.bmp
+ backdrops/cabbiev2.240x320x16.bmp
+ backdrops/cabbiev2.240x400x16.bmp
+
+ bar (gradient)
+ bar (gradient)
+ bar (gradient)
+ bar (gradient)
+ bar (gradient)
+ bar (gradient)
+ bar (gradient)
+ bar (gradient)
+ bar (gradient)
+ bar (gradient)
+ bar (gradient)
+ bar (gradient)
+ bar (inverse)
+ bar (inverse)
+
+ icons/tango_small.bmp
+ icons/tango_small.bmp
+ icons/tango_small.bmp
+ icons/tango_small.bmp
+ icons/tango_small.bmp
+ icons/tango_small.bmp
+ icons/tango_small_mono.bmp
+ icons/tango_small.bmp
+ icons/tango_small_mono.bmp
+ icons/tango_small.bmp
+ icons/tango_small.bmp
+ icons/tango_small.bmp
+ icons/tango_small.bmp
+ icons/tango_small.bmp
+
+ icons/tango_small_viewers.bmp
+ icons/tango_small_viewers.bmp
+ icons/tango_small_viewers.bmp
+ icons/tango_small_viewers.bmp
+ icons/tango_small_viewers.bmp
+ icons/tango_small_viewers.bmp
+ icons/tango_small_viewers_mono.bmp
+ icons/tango_small_viewers.bmp
+ icons/tango_small_viewers_mono.bmp
+ icons/tango_small_viewers.bmp
+ icons/tango_small_viewers.bmp
+ icons/tango_small_viewers.bmp
+ icons/tango_small_viewers.bmp
+ icons/tango_small_viewers.bmp
+
+ top
+ top
+ -
+ -
+
+ cabbiev2.wps
+ cabbiev2.rwps
+ classic_statusbar.sbs
+ classic_statusbar.sbs
+
+
diff --git a/wps/classic_statusbar.color.sbs b/wps/classic_statusbar.color.sbs
new file mode 100644
index 0000000..5a01a5e
--- /dev/null
+++ b/wps/classic_statusbar.color.sbs
@@ -0,0 +1,104 @@
+#
+# Classic statusbar adapted to skin engine
+#
+# Bar at the top.. very easy to change to the bottom (change the y positions from 0 to -8
+#
+
+# specify the UI area viewport... everything but a bar 8 pixels high at the top
+%Vi(-,0,8,-,-,1)
+
+##############################################################
+# Options:
+# you can use icons or text for the volume and battery display
+# Just comment out the line for the one you dont want!
+
+# comment out the next line if you dont want battery icons
+%Vd(a)%Vd(e)
+
+# comment out the next line if you dont want battery number as text
+# %Vdb
+
+# comment out the next line if you dont want volume icons
+%Vd(c)
+# comment out the next line if you dont want volume number as text
+# %Vdd
+
+################################################################
+
+# Load some bitmaps
+%xl(B,battery.bmp,0,0,16)
+%xl(V,volume.bmp,1,0,17)
+%xl(S,status.bmp,0,0,15)
+%xl(D,access_disk.bmp,0,0)
+%xl(y,batter-y.bmp,0,0)
+
+%xl(m,rec_mpegbitrates.bmp,1,0,18)
+%xl(f,rec_frequencies.bmp,0,0,12)
+%xl(e,rec_encoders.bmp,0,0,3)
+%xl(c,rec_channels.bmp,13,0,2)
+
+# Enable the correct viewports
+%?cs<%Vd(c)%Vd(p)%Vd(r)%Vd(s)|%Vd(c)%Vd(p)%Vd(r)%Vd(s)|%Vd(z)|%Vd(c)%Vd(p)%Vd(r)%Vd(s)>
+
+# Charging animation viewports
+%t(2)%?bc<%Vd(x)|%Vd(a)>;%t(2)%Vd(a)
+
+# Battery area, Icons
+%Vl(a,0,0,17,7,0)
+%?bl<%xd(Ba)|%xd(Bb)|%xd(Bc)|%xd(Bd)|%xd(Be)|%xd(Bf)|%xd(Bg)|%xd(Bh)|%xd(Bi)|%xd(Bj)|%xd(Bk)|%xd(Bl)|%xd(Bm)|%xd(Bn)|%xd(Bo)>
+
+# Battery area, grey background viewport for charging animation
+%Vl(x,0,0,17,7,0)%Vb(555555)
+%?bl<%xd(Ba)|%xd(Bb)|%xd(Bc)|%xd(Bd)|%xd(Be)|%xd(Bf)|%xd(Bg)|%xd(Bh)|%xd(Bi)|%xd(Bj)|%xd(Bk)|%xd(Bl)|%xd(Bm)|%xd(Bn)|%xd(Bo)>
+
+# end of battery symbol (to exclude it from animation)
+%Vl(e,17,0,3,7,0)
+%xd(y)
+
+# usb power or charger icon
+%V(20,0,8,8,0)
+%?bu<%xd(Sa)|%?bc<%xd(Sa)|%?bp<%xd(So)>>>
+
+# battery area, no icons
+%Vl(b,0,0,18,8,0)
+%ar%bl
+
+# Volume area
+%Vl(c,28,0,19,8,0)
+%?mv<%ac%?pv<%pv|%pv| %pv| %pv>|%?pv<%xd(Va)|%xd(Vb)|%xd(Vc)|%xd(Vd)|%xd(Ve)|%xd(Vf)|%xd(Vg)|%xd(Vh)|%xd(Vi)|%xd(Vj)|%xd(Vk)|%xd(Vl)|%xd(Vm)|%xd(Vn)|%xd(Vo)|%xd(Vp)|%xd(Vq)>>
+%Vl(d,28,0,19,8,0)
+%ac%?pv<%pv|%pv| %pv| %pv>
+
+# Icons, all in the same bmp strip, so need to use multiple viewports
+# Playback mode
+%Vl(p,47,0,9,8,0)
+%?mp<%xd(Sc)|%xd(Sb)|%xd(Sd)|%xd(Se)|%xd(Sf)|%xd(Sg)|%xd(Sh)|%xd(Si)|%xd(Sj)>
+
+# Repeat mode
+%Vl(r,56,0,9,8,0)
+%?mm<|%xd(Sk)|%xd(Sl)|%xd(Sm)|%xd(Sn)>
+
+# Shuffle mode
+%Vl(s,65,0,-,8,0)
+%?ps<%xd(Sm)|>
+
+
+# Recording section
+# encoder/mpeg bitrate
+%Vl(z,28,0,19,8,0)
+%?Rp<%?Re<%xd(ea)|%xd(eb)|%xd(ec)|%?Rb<%xd(ma)|%xd(mb)|%xd(mc)|%xd(md)|%xd(me)|%xd(mf)|%xd(mg)|%xd(mh)|%xd(mi)|%xd(mj)|%xd(mk)|%xd(ml)|%xd(mm)|%xd(mn)|%xd(mo)|%xd(mp)|%xd(mq)|%xd(mr)>>>
+# status icon
+%Vl(z,47,0,8,8,0)
+%?mp<%xd(Sc)|%xd(Sb)|%xd(Sd)|%xd(Se)|%xd(Sf)|%xd(Sg)|%xd(Sh)|%xd(Si)|%xd(Sj)>
+# frequency and channels
+%Vl(z,55,0,-,8,0)
+%?Rp<%?Rf<%xd(fa)|%xd(fb)|%xd(fc)|%xd(fd)|%xd(fe)|%xd(ff)|%xd(fg)|%xd(fh)|%xd(fi)|%xd(fj)|%xd(fk)|%xd(fl)>>
+%?Rm<%xd(ca)|%xd(cb)>
+
+# Clock on RTC able targets, and disk access
+%V(-50,0,38,8,0) # align on the right with room for 5 SYSFONT digits
+%?cc<%?ca<%?St(time format)<%cH|%cI>:%cM|--:-->|>
+
+# disk access icon
+%V(-12,0,-,8,0)
+%?lh<%xd(D)|>
diff --git a/wps/classic_statusbar.sbs b/wps/classic_statusbar.sbs
deleted file mode 100644
index 5a01a5e..0000000
--- a/wps/classic_statusbar.sbs
+++ /dev/null
@@ -1,104 +0,0 @@
-#
-# Classic statusbar adapted to skin engine
-#
-# Bar at the top.. very easy to change to the bottom (change the y positions from 0 to -8
-#
-
-# specify the UI area viewport... everything but a bar 8 pixels high at the top
-%Vi(-,0,8,-,-,1)
-
-##############################################################
-# Options:
-# you can use icons or text for the volume and battery display
-# Just comment out the line for the one you dont want!
-
-# comment out the next line if you dont want battery icons
-%Vd(a)%Vd(e)
-
-# comment out the next line if you dont want battery number as text
-# %Vdb
-
-# comment out the next line if you dont want volume icons
-%Vd(c)
-# comment out the next line if you dont want volume number as text
-# %Vdd
-
-################################################################
-
-# Load some bitmaps
-%xl(B,battery.bmp,0,0,16)
-%xl(V,volume.bmp,1,0,17)
-%xl(S,status.bmp,0,0,15)
-%xl(D,access_disk.bmp,0,0)
-%xl(y,batter-y.bmp,0,0)
-
-%xl(m,rec_mpegbitrates.bmp,1,0,18)
-%xl(f,rec_frequencies.bmp,0,0,12)
-%xl(e,rec_encoders.bmp,0,0,3)
-%xl(c,rec_channels.bmp,13,0,2)
-
-# Enable the correct viewports
-%?cs<%Vd(c)%Vd(p)%Vd(r)%Vd(s)|%Vd(c)%Vd(p)%Vd(r)%Vd(s)|%Vd(z)|%Vd(c)%Vd(p)%Vd(r)%Vd(s)>
-
-# Charging animation viewports
-%t(2)%?bc<%Vd(x)|%Vd(a)>;%t(2)%Vd(a)
-
-# Battery area, Icons
-%Vl(a,0,0,17,7,0)
-%?bl<%xd(Ba)|%xd(Bb)|%xd(Bc)|%xd(Bd)|%xd(Be)|%xd(Bf)|%xd(Bg)|%xd(Bh)|%xd(Bi)|%xd(Bj)|%xd(Bk)|%xd(Bl)|%xd(Bm)|%xd(Bn)|%xd(Bo)>
-
-# Battery area, grey background viewport for charging animation
-%Vl(x,0,0,17,7,0)%Vb(555555)
-%?bl<%xd(Ba)|%xd(Bb)|%xd(Bc)|%xd(Bd)|%xd(Be)|%xd(Bf)|%xd(Bg)|%xd(Bh)|%xd(Bi)|%xd(Bj)|%xd(Bk)|%xd(Bl)|%xd(Bm)|%xd(Bn)|%xd(Bo)>
-
-# end of battery symbol (to exclude it from animation)
-%Vl(e,17,0,3,7,0)
-%xd(y)
-
-# usb power or charger icon
-%V(20,0,8,8,0)
-%?bu<%xd(Sa)|%?bc<%xd(Sa)|%?bp<%xd(So)>>>
-
-# battery area, no icons
-%Vl(b,0,0,18,8,0)
-%ar%bl
-
-# Volume area
-%Vl(c,28,0,19,8,0)
-%?mv<%ac%?pv<%pv|%pv| %pv| %pv>|%?pv<%xd(Va)|%xd(Vb)|%xd(Vc)|%xd(Vd)|%xd(Ve)|%xd(Vf)|%xd(Vg)|%xd(Vh)|%xd(Vi)|%xd(Vj)|%xd(Vk)|%xd(Vl)|%xd(Vm)|%xd(Vn)|%xd(Vo)|%xd(Vp)|%xd(Vq)>>
-%Vl(d,28,0,19,8,0)
-%ac%?pv<%pv|%pv| %pv| %pv>
-
-# Icons, all in the same bmp strip, so need to use multiple viewports
-# Playback mode
-%Vl(p,47,0,9,8,0)
-%?mp<%xd(Sc)|%xd(Sb)|%xd(Sd)|%xd(Se)|%xd(Sf)|%xd(Sg)|%xd(Sh)|%xd(Si)|%xd(Sj)>
-
-# Repeat mode
-%Vl(r,56,0,9,8,0)
-%?mm<|%xd(Sk)|%xd(Sl)|%xd(Sm)|%xd(Sn)>
-
-# Shuffle mode
-%Vl(s,65,0,-,8,0)
-%?ps<%xd(Sm)|>
-
-
-# Recording section
-# encoder/mpeg bitrate
-%Vl(z,28,0,19,8,0)
-%?Rp<%?Re<%xd(ea)|%xd(eb)|%xd(ec)|%?Rb<%xd(ma)|%xd(mb)|%xd(mc)|%xd(md)|%xd(me)|%xd(mf)|%xd(mg)|%xd(mh)|%xd(mi)|%xd(mj)|%xd(mk)|%xd(ml)|%xd(mm)|%xd(mn)|%xd(mo)|%xd(mp)|%xd(mq)|%xd(mr)>>>
-# status icon
-%Vl(z,47,0,8,8,0)
-%?mp<%xd(Sc)|%xd(Sb)|%xd(Sd)|%xd(Se)|%xd(Sf)|%xd(Sg)|%xd(Sh)|%xd(Si)|%xd(Sj)>
-# frequency and channels
-%Vl(z,55,0,-,8,0)
-%?Rp<%?Rf<%xd(fa)|%xd(fb)|%xd(fc)|%xd(fd)|%xd(fe)|%xd(ff)|%xd(fg)|%xd(fh)|%xd(fi)|%xd(fj)|%xd(fk)|%xd(fl)>>
-%?Rm<%xd(ca)|%xd(cb)>
-
-# Clock on RTC able targets, and disk access
-%V(-50,0,38,8,0) # align on the right with room for 5 SYSFONT digits
-%?cc<%?ca<%?St(time format)<%cH|%cI>:%cM|--:-->|>
-
-# disk access icon
-%V(-12,0,-,8,0)
-%?lh<%xd(D)|>
diff --git a/wps/wpsbuild2.pl b/wps/wpsbuild2.pl
new file mode 100755
index 0000000..95f74e5
--- /dev/null
+++ b/wps/wpsbuild2.pl
@@ -0,0 +1,810 @@
+#!/usr/bin/perl -w
+#
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# $Id$
+#
+# Copyright (C) 2011 Marcin Bukat
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+
+use strict;
+
+# pass_through so not confused by -DTYPE_STUFF (not needed anymore probably)
+use Getopt::Long qw(:config pass_through);
+use File::Basename;
+use XML::Simple qw(:strict);
+
+# boolean constants
+use constant TRUE => 1;
+use constant FALSE => 0;
+
+# global variables
+my $ROOT = "..";
+my $verbose = FALSE;
+my $rbdir = ".rockbox";
+my $tempdir = ".rockbox";
+my $modelname;
+
+# Get options
+GetOptions ( 'r|root=s' => \$ROOT,
+ 'm|modelname=s' => \$modelname,
+ 'v|verbose' => \$verbose,
+ 'rbdir=s' => \$rbdir, # If we want to put in a different
+ # directory
+ 'tempdir=s' => \$tempdir, # override .rockbox temporary dir
+ );
+
+my ($wpslist, @foo) = @ARGV;
+
+# list of the valid lcd depth
+my @depthlist = ( 16, 8, 4, 2, 1 );
+
+# list of the valid skin files
+my @skintags = ('wps','sbs','fms','rwps','rsbs','rfms');
+
+# LCD sizes
+my $has_remote;
+
+
+if(!$wpslist && !$modelname) {
+ print "Usage: wpsbuild2.pl [options] WPSLIST.xml\n",
+ "-r|--root Root dir of the rockbox sources (.. if ommited)\n",
+ "-m|--modelname Target name *MANDATORY* (e.g mpiohd300)\n",
+ "--rbdir Base dir used in config (.rockbox if ommited)\n",
+ "--tempdir Temporary output dir (.rockbox if ommited)\n",
+ "-v|--verbose Verbose output\n",
+ "\n",
+ "Run this in the root of the target build, and it will put all the\n",
+ "stuff in tempdir/wps/ and build the cfg according to rbdir\n";
+ exit;
+}
+
+# this function returns hash ref with LCD dimensions and depth
+# for modelname target
+# params:
+# no params
+sub getlcdsizes
+{
+ # populate hash
+ my %screen = ('remote_height' => '',
+ 'remote_width' => '',
+ 'remote_depth' => '',
+ 'main_height' => '',
+ 'main_width' => '',
+ 'main_depth' => '');
+
+ open (CONFIG, "$ROOT/firmware/export/config/$modelname" . ".h");
+ while()
+ {
+ if ($_ =~ /^\s*#define\s+LCD_REMOTE_HEIGHT\s+([0-9]+)\s*.*$/)
+ {
+ $screen{'remote_height'} = $1;
+ }
+ elsif ($_ =~ /^\s*#define\s+LCD_REMOTE_WIDTH\s+([0-9]+)\s*.*$/)
+ {
+ $screen{'remote_width'} = $1;
+ }
+ elsif ($_ =~ /^\s*#define\s+LCD_REMOTE_DEPTH\s+([0-9]+)\s*.*$/)
+ {
+ $screen{'remote_depth'} = $1;
+ }
+ elsif ($_ =~ /^\s*#define\s+LCD_HEIGHT\s+([0-9]+)\s*.*$/)
+ {
+ $screen{'main_height'} = $1;
+ }
+ elsif ($_ =~ /^\s*#define\s*LCD_WIDTH\s+([0-9]+)\s*.*$/)
+ {
+ $screen{'main_width'} = $1;
+ }
+ elsif ($_ =~ /^\s*#define\s+LCD_DEPTH\s+([0-9]+)\s*.*$/)
+ {
+ $screen{'main_depth'} = $1;
+ }
+ }
+ close(CONFIG);
+
+ return %screen;
+}
+
+# helper function which checks if passed key exists and
+# is not empty in theme parse tree
+# params:
+# 1) reference to parse tree node
+# 2) tag name to check
+sub tag_empty
+{
+ my ($ref, $tag) = @_;
+ # check if such element is present
+ if (exists $$ref->{$tag})
+ {
+ # check if referenced element is ARRAY
+ if (ref($$ref->{$tag}) ne 'ARRAY' && $$ref->{$tag} eq '')
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+# this helper function takes ref to screen hash as its argument,
+# ref to parse tree object and bool remote
+# then it returns value of the object corresponding to the desired
+# resolution and depth
+sub filter
+{
+ # get parameters
+ my ($screen_ref, $tag_ref, $remote) = @_;
+ my $element;
+
+ my $size_depth;
+ if ($remote)
+ {
+ $size_depth = $screen_ref->{remote_width} . "x" .
+ $screen_ref->{remote_height} . "x" .
+ $screen_ref->{remote_depth};
+ }
+ else
+ {
+ $size_depth = $screen_ref->{main_width} . "x" .
+ $screen_ref->{main_height} . "x" .
+ $screen_ref->{main_depth};
+ }
+
+ # check if referenced element is an array
+ if (ref($$tag_ref) eq 'ARRAY')
+ {
+ # loop though all array elements
+ foreach $element (@{$$tag_ref})
+ {
+ # check if element is a hash
+ # (it has screen constraints set)
+ if (ref($element) eq 'HASH')
+ {
+ # compare with given resolution
+ if (exists $element->{screen})
+ {
+ if ($element->{screen} eq $size_depth)
+ {
+ return $element->{content};
+ }
+ }
+ }
+ else
+ {
+ return $element;
+ }
+ }
+ }
+ else # single element
+ {
+ # check if this is hash (aka element specifies resolution)
+ if (ref($$tag_ref) eq 'HASH')
+ {
+ $element = $$tag_ref;
+ if (exists $element->{screen})
+ {
+ if ($element->{screen} eq $size_depth)
+ {
+ return $element->{content};
+ }
+ }
+ }
+ else
+ {
+ # no resolution constraints - return the content of tag
+ return $$tag_ref;
+ }
+ }
+}
+
+# helper function which returns the list of graphic files
+# used in skin file passed as argument
+sub scan_skin_graphics
+{
+ my $path = $_[0];
+ my @filelist;
+ open(SKINFILE, "$path");
+ while ()
+ {
+ push @filelist, $1 if (/[\(,]([^,]*?.bmp)[\),]/);
+ }
+ close(SKINFILE);
+
+ return @filelist;
+}
+
+# copies suitable wps/rwps/sbs/rsbs/fms/rfms
+# params:
+# 1) reference to screen hash
+# 2) reference (aka pointer) to theme parse tree
+sub copy_skin_files
+{
+ my ($screen_ref, $theme_ref) = @_;
+ my $file;
+ my $tag;
+ my $remote_tag;
+ my @g_filelist;
+ my $screen;
+ my $depth;
+ my $ret = FALSE;
+
+ # we assume that we copy the WPS files from the same dir the WPSLIST
+ # file is located in
+
+ # split full path into path and filename itself
+ my ($filename, $dir) = fileparse($wpslist);
+
+ # loop through all skins sections
+ foreach $tag (@skintags)
+ {
+ # destinguish between remote and main tags
+ # skip remote ones if target does not have remote
+ if ($tag =~ /^r.*/)
+ {
+ if (!$has_remote)
+ {
+ next;
+ }
+ $screen = $screen_ref->{remote_width} . "x" .
+ $screen_ref->{remote_height} . "x" .
+ $screen_ref->{remote_depth};
+ $remote_tag = TRUE;
+ }
+ else
+ {
+ $screen = $screen_ref->{main_width} . "x" .
+ $screen_ref->{main_height} . "x" .
+ $screen_ref->{main_depth};
+ $remote_tag = FALSE;
+ }
+
+ if (!tag_empty($theme_ref, $tag))
+ {
+ # split filename into base and extension
+ my ($name, $ext) = split(/\./, $$theme_ref->{$tag});
+
+ # check for someskinfile.txt.wps
+ $file = $name . ".txt" . "." . $ext;
+ if (!-f "$dir/$file")
+ {
+ # check for the model specific one
+ # someskinfile.WIDTHxHEIGHTxDEPTH.modelname.wps
+ $file = $name . "." . $screen . "." . $modelname . "." . $ext;
+ if (!-f "$dir/$file")
+ {
+ # resolution depth specific
+ # someskinfile.WIDTHxHEIGHTxDEPTH.wps
+ $file = $name . "." . $screen . "." . $ext;
+ if (!-f "$dir/$file")
+ {
+ # check for depth groups (mono,grey,ddcolor)
+ # someskinfile.{mono,grey,color}.wps
+ if ($remote_tag)
+ {
+ $depth = $screen_ref->{remote_depth};
+ }
+ else
+ {
+ $depth = $screen_ref->{main_depth};
+ }
+
+ if ($depth == 16)
+ {
+ $file = $name . ".color." . $ext;
+ }
+ elsif ($depth > 1)
+ {
+ $file = $name . ".grey." . $ext;
+ }
+ else
+ {
+ $file = $name . ".mono." . $ext;
+ }
+
+ if (!-f "$dir/$file")
+ {
+ # check for generic someskinfile.wps
+ # this means such file works in all sizes & depths
+ $file = $$theme_ref->{$tag};
+ }
+ }
+ }
+ }
+
+ if (-f "$dir/$file" && !-f "$tempdir/wps/$name.$tag")
+ {
+ # copy skin file if present
+ system("install -D $dir/$file $tempdir/wps/$name.$tag");
+
+ if ($verbose)
+ {
+ print "install -D $dir/$file $tempdir/wps/$name.$tag\n";
+ }
+
+ $ret = TRUE;
+
+ # scan skin file for graphics
+ @g_filelist = &scan_skin_graphics("$dir/$file");
+
+ if ($#g_filelist >= 0)
+ {
+ if (-d "$dir/$name/$screen")
+ {
+ foreach $file (@g_filelist)
+ {
+ if (-f "$dir/$name/$screen/$file" &&
+ !-f "$tempdir/wps/$name/$file")
+ {
+ system("install -D $dir/$name/$screen/$file" .
+ " " . "$tempdir/wps/$name/$file");
+
+ if ($verbose)
+ {
+ print "install -D $dir/$name/$screen/$file",
+ " $tempdir/wps/$name/$file\n";
+ }
+ }
+ }
+ }
+ elsif (-d "$dir/$name")
+ {
+ foreach $file (@g_filelist)
+ {
+ if (-f "$dir/$name/$file" &&
+ !-f "$tempdir/wps/$name/$file")
+ {
+ system("install -D $dir/$name/$file" .
+ " " . "$tempdir/wps/$name/$file");
+
+ if ($verbose)
+ {
+ print "install -D $dir/$name/$file ",
+ "$tempdir/wps/$name/$file\n";
+ }
+ }
+ }
+ }
+ else
+ {
+ print STDERR "beep, no dir to copy graphics from!\n";
+ }
+ }
+ }
+ }
+ }
+# give the hint if this function pass copied some files or not
+return $ret;
+}
+
+# copy backdrop
+# params:
+# 1) reference to screen hash
+# 2) reference (aka pointer) to theme parse tree
+sub copy_backdrop
+{
+ my ($screen_ref, $theme_ref) = @_;
+
+ if (!tag_empty($theme_ref, 'backdrop'))
+ {
+ my $backdrop = &filter($screen_ref, \$$theme_ref->{backdrop}, FALSE);
+ if ($backdrop ne '')
+ {
+ # clip resolution from filename
+ my $dst = $backdrop;
+ $dst =~ s/(\.[0-9]*x[0-9]*x[0-9]*)//;
+
+ if (-f "$ROOT/$backdrop" && !-f "$tempdir/$dst")
+ {
+ system("install -D $ROOT/$backdrop $tempdir/$dst");
+
+ if ($verbose)
+ {
+ print("install -D $ROOT/$backdrop $tempdir/$dst\n");
+ }
+ }
+ }
+ }
+}
+
+# copy font, remote font
+# params:
+# 1) reference to screen hash
+# 2) reference (aka pointer) to theme parse tree
+sub copy_fonts
+{
+ my ($screen_ref, $theme_ref) = @_;
+ my $tag;
+ my $font;
+
+ foreach $tag ('font', 'remote_font')
+ {
+ if (!tag_empty($theme_ref, $tag))
+ {
+ if ($tag =~ m/^remote.*/)
+ {
+ if (!$has_remote)
+ {
+ next;
+ }
+ $font = &filter($screen_ref, \$$theme_ref->{$tag}, TRUE);
+ }
+ else
+ {
+ $font = &filter($screen_ref, \$$theme_ref->{$tag}, FALSE);
+ }
+
+ if ($font ne '')
+ {
+ my $src = $font;
+ $src =~ s/\.fnt/\.bdf/;
+
+ if (!-d "$tempdir/fonts")
+ {
+ mkdir "$tempdir/fonts";
+ if ($verbose)
+ {
+ print "mkdir $tempdir/fonts\n";
+ }
+ }
+
+ if (-f "$ROOT/fonts/$src" && !-f "$tempdir/fonts/$font")
+ {
+ system("$ROOT/tools/convbdf -f -o " .
+ "\"$tempdir/fonts/$font\" \"$ROOT/fonts/$src\" ");
+ if ($verbose)
+ {
+ print "$ROOT/tools/convbdf -f -o ",
+ "\"$tempdir/fonts/$font\" \"$ROOT/fonts/$src\"\n";
+ }
+ }
+ }
+ }
+ }
+}
+
+# copy icons, viewers icons and its remote variants
+# params:
+# 1) reference to screen hash
+# 3) reference (aka pointer) to theme parse tree
+sub copy_icons
+{
+ my ($screen_ref, $theme_ref) = @_;
+ my $tag;
+ my $icons;
+
+ foreach $tag ('iconset', 'remote_iconset',
+ 'viewers_iconset', 'remote_viewers_iconset')
+ {
+ if (!tag_empty($theme_ref, $tag))
+ {
+ if ($tag =~ m/^remote.*/)
+ {
+ if (!$has_remote)
+ {
+ next;
+ }
+ $icons = &filter($screen_ref, \$$theme_ref->{$tag}, TRUE);
+ }
+ else
+ {
+ $icons = &filter($screen_ref, \$$theme_ref->{$tag}, FALSE);
+ }
+
+ my $dst = $tempdir . "/" . $icons;
+ $dst =~ /\/.*icons\/(.*)/i;
+
+ if (-f "$ROOT/$icons" && !-f "$dst")
+ {
+ system("install -D $ROOT/$icons $dst");
+
+ if ($verbose)
+ {
+ print "install -D $ROOT/$icons $dst\n";
+ }
+ }
+ }
+ }
+}
+
+# Builds theme config file
+# params:
+# 1) reference to screen hash
+# 3) reference (aka pointer) to theme parse tree
+#
+# tags parsed:
+# 1) wps, sbs, fms, rwps, rsbs, rfms
+# 2) font, remote_font
+# 3) foreground, background
+# 4) statusbar, remote_statusbar
+# 5) backdrop
+# 6) line_selector_start_color,
+# line_selector_end_color,
+# line_selector_text_color
+# 7) selector_type
+# 8) iconset, viewers_iconset
+# remote_iconset, remote_viewers_iconset
+# 9) filetype_colours
+# 10) ui_viewport, remote_ui_viewport
+# 11) volume_display
+# 12) battery_display
+#
+# Empty tags are ignored !!!
+# you have to explicitly set it to '-' if you want
+# setting to be reseted to defaults
+sub build_config
+{
+ my ($screen_ref, $theme_ref) = @_;
+ my @out;
+ my $tag;
+ my $resource;
+ my $element;
+ my $cfg_element;
+ my $cfg = $$theme_ref->{name} . ".cfg";
+
+ # config header
+ push @out, "#\n";
+ push @out, "# $cfg generated by wpsbuild2.pl\n";
+ push @out, "# " . $$theme_ref->{name} . " is made by " .
+ $$theme_ref->{author} . "\n";
+ push @out, "#\n";
+
+ foreach $element ('wps','sbs','fms')
+ {
+ # wps, sbs, fms config
+ if (!tag_empty($theme_ref, $element))
+ {
+ push @out, "$element: $rbdir/wps/$$theme_ref->{$element}\n";
+ }
+ }
+
+ foreach $element ('rwps','rsbs','rfms')
+ {
+ # rwps, rsbs, rfms config
+ if (!tag_empty($theme_ref, $element) && $has_remote)
+ {
+ push @out, "$element: $rbdir/wps/$$theme_ref->{$element}\n";
+ }
+ }
+
+ # font config
+ if (!tag_empty($theme_ref, 'font'))
+ {
+ $resource = filter($screen_ref, \$$theme_ref->{font}, FALSE);
+ if ($resource ne '')
+ {
+ push @out, "font: $rbdir/fonts/$resource\n";
+ }
+ }
+
+ # remote font config
+ if (!tag_empty($theme_ref, 'remote_font') && $has_remote)
+ {
+ $resource = filter($screen_ref, \$$theme_ref->{remote_font}, TRUE);
+ if ($resource ne '')
+ {
+ push @out, "remote font: $rbdir/fonts/$resource\n";
+ }
+ }
+
+ # foreground, background color
+ foreach $element ('foreground_color','background_color')
+ {
+ if (!tag_empty($theme_ref, $element) && $screen_ref->{main_depth} > 2)
+ {
+ $cfg_element = $element;
+ $cfg_element =~ s/_/\ /g;
+ push @out, "$cfg_element: $$theme_ref->{$element}\n";
+ }
+ }
+
+ # statusbar
+ if (!tag_empty($theme_ref, 'statusbar'))
+ {
+ push @out, "statusbar: $$theme_ref->{statusbar}\n";
+ }
+
+ # remote statusbar
+ if (!tag_empty($theme_ref, 'remote_statusbar') && $has_remote)
+ {
+ push @out, "remote statusbar: $$theme_ref->{remote_statusbar}\n";
+ }
+
+ # backdrop
+ if (!tag_empty($theme_ref,'backdrop'))
+ {
+ $resource = filter($screen_ref, \$$theme_ref->{backdrop}, FALSE);
+ if ($resource ne '')
+ {
+ # clip resolution from filename
+ $resource =~ s/(\.[0-9]*x[0-9]*x[0-9]*)//;
+ push @out, "backdrop: $rbdir/$resource\n";
+ }
+ }
+
+ # line selector start color
+ # line selector end color
+ # line selector text color
+ foreach $element ('line_selector_start_color',
+ 'line_selector_end_color',
+ 'line_selector_text_color')
+ {
+ if (!tag_empty($theme_ref, $element) && $screen_ref->{main_depth} > 2)
+ {
+ $cfg_element = $element;
+ $cfg_element =~ s/_/\ /g;
+ push @out, "$cfg_element: $$theme_ref->{$element}\n";
+ }
+ }
+
+ # selector type
+ if (!tag_empty($theme_ref, 'selector_type'))
+ {
+ $resource = filter($screen_ref, \$$theme_ref->{selector_type}, FALSE);
+ if ($resource ne '')
+ {
+ push @out, "selector type: $resource\n";
+ }
+ }
+
+ # iconset, viewers iconset
+ foreach $element ('iconset', 'viewers_iconset')
+ {
+ # iconset, viewers iconset
+ if (!tag_empty($theme_ref, $element))
+ {
+ $resource = filter($screen_ref, \$$theme_ref->{$element}, FALSE);
+ $cfg_element = $element;
+ $cfg_element =~ s/_/\ /g;
+ if ($resource ne '')
+ {
+ push @out, "$cfg_element: $rbdir/$resource\n";
+ }
+ }
+ }
+
+ # remote iconset, remote viewers iconset
+ foreach $element ('remote_iconset', 'remote_viewers_iconset')
+ {
+ if (!tag_empty($theme_ref, $element) && $has_remote)
+ {
+ $resource = filter($screen_ref, \$$theme_ref->{$element}, TRUE);
+ $cfg_element = $element;
+ $cfg_element =~ s/_/\ /g;
+ if ($resource ne '')
+ {
+ push @out, "$cfg_element: $rbdir/$resource\n";
+ }
+ }
+ }
+
+ # filetype colours
+ if (!tag_empty($theme_ref, 'filetype_colours') && $screen_ref->{main_depth} > 2)
+ {
+ push @out, "filetype colours: $$theme_ref->{filetype_colours}\n";
+ }
+
+ # ui viewport
+ if (!tag_empty($theme_ref, 'ui_viewport'))
+ {
+ push @out, "ui viewport: $$theme_ref->{ui_viewport}\n";
+ }
+
+ # remote ui vieport
+ if (!tag_empty($theme_ref, 'remote_ui_viewport') && $has_remote)
+ {
+
+ push @out, "remote ui viewport: $$theme_ref->{remote_ui_viewport}\n";
+ }
+
+ # volume display
+ if (!tag_empty($theme_ref, 'volume_display'))
+ {
+ if ($$theme_ref->{volume_display} eq 'numeric')
+ {
+ push @out, "volume display: $$theme_ref->{volume_display}\n";
+ }
+ }
+
+ # battery display
+ if (!tag_empty($theme_ref, 'battery_display'))
+ {
+ if ($$theme_ref->{battery_display} eq 'numeric')
+ {
+ push @out, "battery display: $$theme_ref->{battery_display}\n";
+ }
+ }
+
+ # dump config to file
+ if(-f "$tempdir/wps/$cfg")
+ {
+ print STDERR "wpsbuild warning: wps/$cfg already exists!\n";
+ }
+ else
+ {
+ open(CFG, ">$tempdir/themes/$cfg");
+ print CFG @out;
+ close(CFG);
+ }
+}
+
+# Get the LCD sizes first
+my %screen = getlcdsizes();
+my %pass_screen = ();
+
+if ($screen{'remote_height'} ne '' &&
+ $screen{'remote_width'} ne '' &&
+ $screen{'remote_depth'} ne '')
+{
+ $has_remote = TRUE;
+}
+
+# prefix $rbdir with / if needed (needed for the theme.cfg)
+unless ($rbdir =~ m/^\/.*/)
+{
+ $rbdir = "/" . $rbdir;
+}
+
+my $xml = new XML::Simple (KeyAttr=>[], ForceArray=>0, SuppressEmpty=>1);
+
+# parse input file
+my $data = $xml->XMLin("$wpslist");
+my $theme;
+my $depth;
+
+if ($verbose)
+{
+ print "wpsbuild2.pl in verbose mode\n";
+}
+
+# process all themes found in input file
+foreach $theme (@{$data->{theme}})
+{
+ foreach $depth (@depthlist)
+ {
+ # consider only valid depths
+ %pass_screen = %screen;
+ if ($screen{'main_depth'} >= $depth)
+ {
+ $pass_screen{'main_depth'} = $depth;
+ }
+
+ if ($has_remote && $screen{'remote_depth'} >= $depth)
+ {
+ $pass_screen{'remote_depth'} = $depth;
+ }
+
+ # process the skin with the highes depth satisfying all constraints
+ if (copy_skin_files(\%pass_screen, \$theme))
+ {
+ # copy backdrop
+ copy_backdrop(\%pass_screen, \$theme);
+
+ # copy fonts
+ copy_fonts(\%pass_screen, \$theme);
+
+ # copy icons (iconset and viewers icons)
+ copy_icons(\%pass_screen, \$theme);
+
+ # build .cfg file finally
+ build_config(\%pass_screen, \$theme);
+ last;
+ }
+ }
+}