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; + } + } +}