illume avatar illume committed e4bef2f

symbian branch merging

Comments (0)

Files changed (42)

symbian/BuildPygameRelease.py

+""" Full build configuration for pygame 
+For SVN support, install pysvn.
+"""
+
+import sys
+import time
+import os
+import shutil
+
+import build_config as config
+
+from glob import glob
+from scons_symbian.config.constants import CAPS_SELF_SIGNED
+from scons_symbian.arguments import COMPILER, RELEASE
+
+
+BASE_CMD = "scons dosis=true"
+
+UID_PACKAGE   = 0xE0006020
+__uid = UID_PACKAGE 
+def getuid(): 
+    global __uid
+    __uid += 1
+    return __uid  
+
+UID_PYGAMEAPP = getuid()
+UID_SDL       = getuid()
+UID_JPEG      = getuid()
+
+#: Base uid for PyS60 CE scripts
+UID_BASE = getuid()
+
+#: Capability configuration
+CAPABILITIES = CAPS_SELF_SIGNED[:]
+CAPABILITIES.remove("UserEnvironment") # Missing from sdl.dll
+CAPABILITIES = "+".join(CAPABILITIES)
+
+def dobuild(args):    
+    cmd = ""
+    for x in args:
+        cmd += "%s=%s " % ( x, str(args[x]) )
+    
+    cmd = " ".join( [BASE_CMD, cmd] )
+    cmd = " ".join( [cmd] + sys.argv[1:] )
+
+    print cmd
+    if os.system( cmd ): 
+        raise SystemExit( "Error: Build failed" )
+    
+
+def build():
+
+    version = list(time.gmtime()[:3])    
+    version = [ str(x).zfill(2) for x in version ]
+    version = "".join( version )
+        
+    sisname = "python_for_pygame_%s.sis" % version
+    
+    args = { "applications" : "",
+             "capabilities" : CAPABILITIES,
+             "builtin"      : "sysinfo,socket",
+             #"pyds"         : "gles",
+             "basename"     : "pygame_python",            
+             "uidbase"      : hex(UID_BASE).replace("L",""),             
+             "sisappname"   : '"Python for Pygame"',
+             # Convert to int or may be converted to octal due to zero at beginning
+             'sisversion'   : '"(1,%d,%d%s)"' % ( int(version[2:4]), int( version[4:6]),version[6:]),
+             'pythonsis'    : sisname,
+             'libpath'      : "data/pygame/libs",
+             'pycompiler'   : "d:\\python22\\python.exe"
+             }
+    
+    # Add certificate stuff
+    if config.cert is not None:
+        args['cert'] = config.cert        
+        args['privkey'] = config.privkey
+        args['passphrase'] = config.passphrase
+        
+    # Build PyS60 CE
+    sisname   = ""  
+    if config.build_python:
+        curdir = os.getcwd()
+        os.chdir(config.pys60_ce_src)   
+        a = args.copy()
+        a["gcce_options"] = '"-O2 -fno-unit-at-a-time"'             
+        dobuild(a)    
+        os.chdir(curdir)
+    
+        sisname = "python_for_pygame_%s_signed.sisx" % version
+        pys60_sis = os.path.join( config.pys60_ce_src, sisname )
+                
+        # Copy the sis to current directory
+        if os.path.exists(pys60_sis):
+            import shutil
+            shutil.copyfile(pys60_sis, sisname)
+        
+        args['pythondll'] =  args['basename']
+         
+    else:
+        sisname = config.pys60_sis
+        if config.pythondll is not None:
+            args['pythondll'] = config.pythondll
+     
+    # Build pygame
+    args["pythonsis"]  = sisname
+    args["pythonsis"]  = sisname
+    args["sisappname"] = '"pygame for S60"' 
+    args['sisversion'] = '1,%d,%d%s' % ( int(version[2:4]), int( version[4:6]),version[6:])
+    args['sisuid'] = hex(UID_PACKAGE).replace("L","")
+    args['appuid'] = hex(UID_PYGAMEAPP).replace("L","")
+    args['sdluid'] = hex(UID_SDL).replace("L","")
+    args['jpeguid']= hex(UID_JPEG).replace("L","")
+    args['pythoninclude'] = config.pythoninclude
+    #args['defines'] = "STDERR_TO_STDOUT"
+    args['winscw_options'] = "-nostderr" # Don't show the stdioserver output
+    dobuild(args)
+    
+    
+if __name__ == "__main__":
+    build() 

symbian/SConscript.Ogg.py

+Import("*")
+
+# This file is generated with mmp2sconscript
+from scons_symbian import *
+
+target     = "ogg"
+targettype = "lib"
+libraries  = []
+# Static libs
+libraries += []
+
+uid3 = 0
+sources = ['deps/ogg/src/bitwise.c', 'deps/ogg/src/framing.c']
+
+includes    = ['/SDLS60/symbian']
+sysincludes = [ EPOC32_INCLUDE, C_INCLUDE, 'deps/ogg/include']
+defines     = []
+
+SymbianProgram( target, targettype,
+    sources = sources,
+    includes    = includes,
+    sysincludes = sysincludes,
+    libraries   = libraries,
+    defines     = defines,
+    epocstacksize = 8192,
+    epocheapsize  = (0x400,0x100000),
+    uid3 = uid3,
+)
+

symbian/SConscript.SDL.py

+Import("*")
+
+# This file is generated with mmp2sconscript
+from scons_symbian import *
+
+target     = TARGET_NAME
+targettype = "dll"
+
+
+includes    = [ 'deps/SDL/src', 'deps/SDL/src/video', 
+                'deps/SDL/src/events', 'deps/SDL/src/audio', 
+                'deps/SDL/src/audio/symbian', 'deps/SDL/src/main/symbian', 
+                'deps/SDL/src/video/symbian', 'deps/SDL/src/thread', 
+                'deps/SDL/src/thread/generic', 'deps/SDL/src/thread/symbian', 
+                'deps/SDL/src/timer', 'deps/SDL/src/joystick', 
+                'deps/SDL/symbian/inc', 
+				'deps/SDL/symbian/inc/internal',
+				'deps/SDL/include',
+]
+
+sysincludes = [EPOC32_INCLUDE,
+               join( EPOC32_INCLUDE, "gles"),
+               join( EPOC32_INCLUDE, "EGL"),
+               C_INCLUDE, 
+               ]
+
+libraries  = C_LIBRARY + ['euser',
+ 'fbscli',
+ 'ws32',
+ 'gdi',
+ 'mediaclientaudiostream',
+ 'avkon',
+ 'efsrv',
+ 'bafl',
+ 'apparc',
+ 'eikcore',
+ 'cone',
+ 'bitgdi',
+ 'scdv',
+ 'hal',
+# 'libc',
+# 'libm',
+ ]
+
+# Static libraries
+staticlibs = [ 'vorbis.lib', 'ogg.lib', 
+             #'SDL_ttf.lib', 
+             'libsft2.lib',
+             'pygame_libjpeg'
+             ]
+defines = []
+sources = ['deps/SDL/symbian/src/vectorbuffer.cpp',
+ 'deps/SDL/symbian/src/sdlappsrv.cpp',
+ 'deps/SDL/symbian/src/sdlenv.cpp',
+ 'deps/SDL/symbian/src/dsa.cpp',
+ 'deps/SDL/symbian/src/streamplayer.cpp',
+ 'deps/SDL/symbian/src/sdlenvutils.cpp',
+ 'deps/SDL/src/SDL.c',
+ 'deps/SDL/src/SDL_error.c',
+ 'deps/SDL/src/SDL_fatal.c',
+ 'deps/SDL/src/main/symbian/SDL_libutils.cpp',
+ 'deps/SDL/src/main/symbian/SDL_main.cpp',
+ 'deps/SDL/src/cpuinfo/SDL_cpuinfo.c',
+ 'deps/SDL/src/video/SDL_blit.c',
+ 'deps/SDL/src/video/SDL_blit_0.c',
+ 'deps/SDL/src/video/SDL_blit_1.c',
+ 'deps/SDL/src/video/SDL_blit_A.c',
+ 'deps/SDL/src/video/SDL_blit_N.c',
+ 'deps/SDL/src/video/SDL_bmp.c',
+ 'deps/SDL/src/video/SDL_cursor.c',
+ 'deps/SDL/src/video/SDL_gamma.c',
+ 'deps/SDL/src/video/SDL_pixels.c',
+ 'deps/SDL/src/video/SDL_RLEaccel.c',
+ 'deps/SDL/src/video/SDL_stretch.c',
+ 'deps/SDL/src/video/SDL_surface.c',
+ 'deps/SDL/src/video/SDL_video.c',
+ 'deps/SDL/src/video/SDL_yuv.c',
+ 'deps/SDL/src/video/SDL_yuv_mmx.c',
+ 'deps/SDL/src/video/SDL_yuv_sw.c',
+ 'deps/SDL/src/video/symbian/SDL_epocvideo.cpp',
+ 'deps/SDL/src/video/symbian/SDL_epocevents.cpp',
+ 'deps/SDL/src/audio/SDL_audio.c',
+ 'deps/SDL/src/audio/SDL_audiocvt.c',
+ 'deps/SDL/src/audio/SDL_audiodev.c',
+ 'deps/SDL/src/audio/SDL_mixer.c',
+ 'deps/SDL/src/audio/SDL_wave.c',
+ 'deps/SDL/src/audio/symbian/SDL_epocaudio.cpp',
+ 'deps/SDL/src/thread/SDL_thread.c',
+ 'deps/SDL/src/thread/generic/SDL_syscond.c',
+ 'deps/SDL/src/thread/symbian/SDL_sysmutex.cpp',
+ 'deps/SDL/src/thread/symbian/SDL_syssem.cpp',
+ 'deps/SDL/src/thread/symbian/SDL_systhread.cpp',
+ 'deps/SDL/src/events/SDL_active.c',
+ 'deps/SDL/src/events/SDL_events.c',
+ 'deps/SDL/src/events/SDL_keyboard.c',
+ 'deps/SDL/src/events/SDL_mouse.c',
+ 'deps/SDL/src/events/SDL_quit.c',
+ 'deps/SDL/src/events/SDL_resize.c',
+ 'deps/SDL/src/timer/SDL_timer.c',
+ 'deps/SDL/src/timer/symbian/SDL_systimer.cpp',
+ 'deps/SDL/src/file/SDL_rwops.c',
+ 'deps/SDL/src/stdlib/SDL_string.c',
+ 'deps/SDL/src/stdlib/SDL_getenv.c']
+
+ # Configure SDL_Mixer
+sources += [
+ 'deps/SDL_mixer/mixer.c',
+ 'deps/SDL_mixer/music.c',
+ #'deps/SDL_mixer/playwave.c',
+ 'deps/SDL_mixer/wavestream.c',
+ 'deps/SDL_mixer/effects_internal.c',
+ 'deps/SDL_mixer/effect_position.c',
+ 'deps/SDL_mixer/effect_stereoreverse.c',
+ 'deps/SDL_mixer/load_aiff.c',
+ 'deps/SDL_mixer/load_voc.c',
+ 'deps/SDL_mixer/load_ogg.c',
+ 'deps/SDL_mixer/dynamic_ogg.c',
+ 'deps/SDL_mixer/music_ogg.c',
+]
+sysincludes += ['deps/vorbis/include', 
+               'deps/vorbis/include/vorbis', 
+               'deps/ogg/include', 
+               'deps/ogg/include/ogg']
+
+defines += [ 'WAV_MUSIC', 'OGG_MUSIC', ]
+
+# Configure SDL_ttf
+sources += [
+ 'deps/SDL_ttf/SDL_ttf.c',
+]
+
+# Configure SDL_image
+sources += Glob('deps/SDL_image/IMG*.c',)
+[sources.remove(x) for x in Glob('deps/SDL_image/IMG_png*c') ]
+
+defines += [
+            'LOAD_JPG',
+            'LOAD_BMP',
+            'LOAD_GIF',
+            'LOAD_TGA',            
+            ]
+sysincludes += [
+    'deps/jpeg/',    
+]
+
+C_LIB_DEFINE = ""
+if not USE_OPENC:
+    # Tell SDL to use "estlib" then
+    C_LIB_DEFINE = 'SYMBIANC'
+else:
+    C_LIB_DEFINE = 'OPENC'
+
+defines.append( C_LIB_DEFINE )
+    
+# png.h does not like __DLL__ define
+SymbianProgram( "pygame_SDL_libpng", TARGETTYPE_LIB,
+                sources = ["deps/SDL_Image/IMG_png.c"],
+                includes = includes,
+                sysincludes = sysincludes + ["deps/libpng"],
+                defines = ["LOAD_PNG", C_LIB_DEFINE],                
+                )
+staticlibs += ["pygame_SDL_libpng.lib", "pygame_libpng.lib"]
+libraries  += ["ezlib"] # For libpng
+
+defines += ['SYMBIAN_SERIES60', 
+               'NO_SIGNAL_H', 'ENABLE_EPOC', 
+               'DISABLE_JOYSTICK', 'DISABLE_CDROM',                
+               ]
+    
+includes += ["deps/SDL_ttf/", "deps/sft2/inc/sys"]
+
+SymbianProgram( target, targettype,
+    sources = sources,
+    includes    = includes,
+    sysincludes = sysincludes,
+    libraries   = staticlibs + libraries,
+    defines     = defines,
+    capabilities = CAPABILITIES,
+    uid3 = UID3,
+    package = PACKAGE_NAME,
+)

symbian/SConscript.Vorbis.py

+Import("*")
+
+# This file is generated with mmp2sconscript
+from scons_symbian import *
+
+target     = "vorbis"
+targettype = "lib"
+libraries  = []
+# Static libs
+libraries += []
+
+
+uid3 = 0
+
+
+
+sources = ['deps/vorbis/lib/analysis.c',
+ 'deps/vorbis/lib/barkmel.c',
+ 'deps/vorbis/lib/bitrate.c',
+ 'deps/vorbis/lib/block.c',
+ 'deps/vorbis/lib/codebook.c',
+ 'deps/vorbis/lib/envelope.c',
+ 'deps/vorbis/lib/floor0.c',
+ 'deps/vorbis/lib/floor1.c',
+ 'deps/vorbis/lib/info.c',
+ 'deps/vorbis/lib/lookup.c',
+ 'deps/vorbis/lib/lpc.c',
+ 'deps/vorbis/lib/lsp.c',
+ 'deps/vorbis/lib/mapping0.c',
+ 'deps/vorbis/lib/mdct.c',
+ 'deps/vorbis/lib/psy.c',
+ 'deps/vorbis/lib/registry.c',
+ 'deps/vorbis/lib/res0.c',
+ 'deps/vorbis/lib/sharedbook.c',
+ 'deps/vorbis/lib/smallft.c',
+ 'deps/vorbis/lib/synthesis.c',
+ 'deps/vorbis/lib/vorbisfile.c',
+ 'deps/vorbis/lib/window.c']
+
+
+includes    = ['deps/SDL/symbian', 'deps/vorbis/include', 'deps/vorbis/include/vorbis']
+sysincludes = [EPOC32_INCLUDE, C_INCLUDE, 'deps/ogg/include', 'deps/ogg/symbian']
+
+defines     = []
+if COMPILER == COMPILER_GCCE: 
+    defines += ['alloca=__builtin_alloca']
+if USE_OPENC:
+    defines += [ 'OPENC' ]
+    
+SymbianProgram( target, targettype,
+    sources = sources,
+    includes    = includes,
+    sysincludes = sysincludes,
+    libraries   = libraries,
+    defines     = defines,
+    uid3 = uid3,
+    winscw_options = "-relax_pointers",   
+)
+

symbian/SConscript.app.py

+from scons_symbian import *
+
+# Import all from main SConstruct
+Import("*")
+
+python_includes = [ PYTHON_INCLUDE ]
+
+pygame_rss = File("app/pygame.rss")
+pygame_reg_rss = File( "app/pygame_reg.rss")
+
+SymbianProgram( "pygame", TARGETTYPE_EXE,
+                resources = [pygame_rss, pygame_reg_rss],
+                sources = ["app/pygame_app.cpp", 
+                           "app/pygame_main.cpp"                           
+                           ],
+                includes = ["app", "common",
+                            join( "deps", "SDL", "include"),                              
+                            join( "deps", "SDL", "symbian", "inc"),
+                            C_INCLUDE ] + python_includes
+                            
+                ,
+                defines = [
+                    #"__LOGMAN_ENABLED__", 
+                ],
+                libraries = C_LIBRARY + ["euser", "avkon", "apparc", 
+                             "cone","eikcore", "libGLES_CM", 
+                             "bafl", # arrays and command line                            
+                             PYTHON_LIB_NAME,
+                             SDL_DLL_NAME,
+                             "pygame.lib",
+                             'pygame_libjpeg',
+                             #"LogMan"
+                             ],
+                uid3=UID_PYGAMEAPP,
+                icons = [ ("../lib/pygame_icon.svg", "pygame") ],
+                package=PACKAGE_NAME,
+                capabilities = CAPABILITIES,
+                epocheapsize = ( 0x5000, 0x200000 ),
+                epocstacksize = 0x14000,
+                winscw_options = "-w noempty",
+)
+
+# Install pygame app resources
+from glob import glob
+
+def to_package(**kwargs):
+    kwargs["source"] = abspath( kwargs["source"] )
+    #kwargs["target"] = abspath( kwargs["target"] )
+    ToPackage( package = PACKAGE_NAME, **kwargs )
+
+#for x in glob("*.bmp"):
+#    to_package( source = x, target = "data/pygame")
+
+to_package( source = "app/pygame_main.py", target = "data/pygame" )
+to_package( source = "app/launcher/logo.jpg", target = "data/pygame/launcher" )
+to_package( source = "app/launcher/pygame_launcher.py", target = "data/pygame/launcher" )
+to_package( source = "app/apps/liquid_s60.py", target = "data/pygame/apps" )
+
+

symbian/SConscript.jpeg.py

+""" Defines project for JPEG library """
+Import("*")
+
+from scons_symbian import *
+
+Import("TARGET_NAME UID3 PACKAGE_NAME CAPABILITIES")
+
+# Built as dll because needed by SDL and the application
+target     = TARGET_NAME
+targettype = "dll"
+libraries  = C_LIBRARY + ['euser']
+
+# Static libs
+libraries += []
+
+uid3 = UID3
+
+sources = [
+ 'deps/jpeg/jcomapi.c',
+ 'deps/jpeg/jutils.c',
+ 'deps/jpeg/jerror.c',
+ 'deps/jpeg/jmemmgr.c',
+ 'deps/jpeg/jmemnobs.c',
+ 'deps/jpeg/jcapimin.c',
+ 'deps/jpeg/jcapistd.c',
+ 'deps/jpeg/jctrans.c',
+ 'deps/jpeg/jcparam.c',
+ 'deps/jpeg/jdatadst.c',
+ 'deps/jpeg/jcinit.c',
+ 'deps/jpeg/jcmaster.c',
+ 'deps/jpeg/jcmarker.c',
+ 'deps/jpeg/jcmainct.c',
+ 'deps/jpeg/jcprepct.c',
+ 'deps/jpeg/jccoefct.c',
+ 'deps/jpeg/jccolor.c',
+ 'deps/jpeg/jcsample.c',
+ 'deps/jpeg/jchuff.c',
+ 'deps/jpeg/jcphuff.c',
+ 'deps/jpeg/jcdctmgr.c',
+ 'deps/jpeg/jfdctfst.c',
+ 'deps/jpeg/jfdctflt.c',
+ 'deps/jpeg/jfdctint.c',
+ 'deps/jpeg/jdapimin.c',
+ 'deps/jpeg/jdapistd.c',
+ 'deps/jpeg/jdtrans.c',
+ 'deps/jpeg/jdatasrc.c',
+ 'deps/jpeg/jdmaster.c',
+ 'deps/jpeg/jdinput.c',
+ 'deps/jpeg/jdmarker.c',
+ 'deps/jpeg/jdhuff.c',
+ 'deps/jpeg/jdphuff.c',
+ 'deps/jpeg/jdmainct.c',
+ 'deps/jpeg/jdcoefct.c',
+ 'deps/jpeg/jdpostct.c',
+ 'deps/jpeg/jddctmgr.c',
+ 'deps/jpeg/jidctfst.c',
+ 'deps/jpeg/jidctflt.c',
+ 'deps/jpeg/jidctint.c',
+ 'deps/jpeg/jidctred.c',
+ 'deps/jpeg/jdsample.c',
+ 'deps/jpeg/jdcolor.c',
+ 'deps/jpeg/jquant1.c',
+ 'deps/jpeg/jquant2.c',
+ 'deps/jpeg/jdmerge.c']
+
+
+includes    = []
+sysincludes = ['/epoc32/include', C_INCLUDE ]
+defines     = ['JPEG_DLL']
+
+SymbianProgram( target, targettype,
+    sources = sources,
+    includes    = includes,
+    sysincludes = sysincludes,
+    libraries   = libraries,
+    defines     = defines,
+    capabilities = CAPABILITIES,
+    uid3 = uid3,
+    package = PACKAGE_NAME,
+)
+

symbian/SConscript.libpng.py

+""" Defines project for PNG library """
+
+Import("*")
+
+# This file is generated with mmp2sconscript
+from scons_symbian import *
+from glob import glob
+
+Import("TARGET_NAME UID3 PACKAGE_NAME")
+
+# Built as dll because needed by SDL and the application
+target     = TARGET_NAME
+targettype = TARGETTYPE_LIB
+libraries  = C_LIBRARY + ['euser']
+
+# Static libs
+libraries += []
+
+#uid3 = UID3
+
+sources = glob( "deps/libpng/png*.c")
+[ sources.remove(x) for x in glob("deps/libpng/pngtes*.c")]
+
+
+includes    = ['deps/libpng/']
+sysincludes = ['/epoc32/include', C_INCLUDE ]
+defines     = []
+
+SymbianProgram( target, targettype,
+    sources = sources,
+    includes    = includes,
+    sysincludes = sysincludes,
+    libraries   = libraries,
+    defines     = defines,
+    #uid3 = uid3, 
+    package = PACKAGE_NAME,
+)
+

symbian/SConscript.pygame.py

+Import("*")
+
+from scons_symbian import *
+import glob
+
+python_includes = [ PYTHON_INCLUDE ]
+
+#music.c
+#mixer.c
+#font.c
+#imageext.c
+IGNORED = r"""
+pypm.c
+camera.c
+ffmovie.c
+movie.c
+movieext.c
+pixelarray_methods.c
+scale_mmx32.c
+scale_mmx64.c
+scrap.c
+scrap_mac.c
+scrap_qnx.c
+scrap_win.c
+scrap_x11.c
+_numericsndarray.c
+joystick.c
+cdrom.c""".split()
+
+pygame_sources = glob.glob( "../src/*.c" )
+pygame_sources += glob.glob( "../src/SDL_gfx/*.c" )
+removed = []
+for x in pygame_sources:
+    for y in IGNORED:        
+        if x.endswith(y):
+            removed.append(x)
+            break
+
+for x in removed:    
+    pygame_sources.remove(x)
+
+pygame_sources.append("common/builtins.c")
+
+if USE_OPENC:
+    C_LIB_INCLUDE = "OPENC"
+else:
+    C_LIB_INCLUDE = ""
+    
+# Build pygame library
+SymbianProgram( "pygame", TARGETTYPE_LIB,
+                sources = pygame_sources,
+                defines = [ 
+                   C_LIB_INCLUDE                   
+                ],
+                includes = python_includes + [
+                             "common",
+                             join( "..", "src", "SDL_gfx"),                         
+                             join( "deps", "jpeg"),
+                             join( "deps", "SDL_image"),
+                             join( "deps", "SDL_ttf"),
+                             join( "deps", "SDL_mixer"),
+                             join( "deps", "SDL", "include"),                              
+                             join( "deps", "SDL", "symbian", "inc"),
+                             C_INCLUDE,                             
+                             #join( "..", "..", "tools", "debug" )
+                           ],
+                package = PACKAGE_NAME,
+                libraries = C_LIBRARY + [
+                     PYTHON_LIB_NAME,                     
+                     "euser", "avkon", "apparc", 
+                     "cone","eikcore", "libGLES_CM",                     
+                     SDL_DLL_NAME,
+                     ],
+                winscw_options = "-w noempty",
+                )
+
+# Install pygame python libraries
+from glob import glob
+
+def to_package(**kwargs):
+    kwargs["source"] = abspath( kwargs["source"] )
+    ToPackage( package = PACKAGE_NAME, **kwargs )
+
+pygame_lib = join( PATH_PY_LIBS, "pygame" )
+
+# Copy main pygame libs
+for x in glob( "../lib/*.py"):
+    to_package( source = x, target = pygame_lib )
+
+for x in glob( "../lib/threads/*.py"):
+    to_package( source = x, target = join( pygame_lib, "threads") )
+    
+# Copy Symbian specific libs
+for x in glob( "lib/*.py"): 
+    to_package( source = x, target = pygame_lib )
+    
+# Install default font
+to_package( source = "../lib/freesansbold.ttf", target = pygame_lib )

symbian/SConscript.sft2.py

+Import("*")
+
+# This file is generated with mmp2sconscript
+from scons_symbian import *
+
+
+target     = "libsft2"
+targettype = "lib"
+libraries  = C_LIBRARY + ['euser', 'gdi', 'fbscli']
+
+# Static libs
+libraries += []
+
+sources = ['deps/sft2/src/libsft2.cpp',
+ 'deps/sft2/src/libsft2DllMain.cpp',
+ 'deps/sft2/src/base/ftapi.c',
+ 'deps/sft2/src/base/ftbase.c',
+ 'deps/sft2/src/base/ftbbox.c',
+ 'deps/sft2/src/base/ftbdf.c',
+ 'deps/sft2/src/base/ftbitmap.c',
+ 'deps/sft2/src/base/ftdebug.c',
+ 'deps/sft2/src/base/ftgasp.c',
+ 'deps/sft2/src/base/ftglyph.c',
+ 'deps/sft2/src/base/ftgxval.c',
+ 'deps/sft2/src/base/ftinit.c',
+ 'deps/sft2/src/base/ftlcdfil.c',
+ 'deps/sft2/src/base/ftmm.c',
+ 'deps/sft2/src/base/ftotval.c',
+ 'deps/sft2/src/base/ftpfr.c',
+ 'deps/sft2/src/base/ftstroke.c',
+ 'deps/sft2/src/base/ftsynth.c',
+ 'deps/sft2/src/base/ftsystem.c',
+ 'deps/sft2/src/base/fttype1.c',
+ 'deps/sft2/src/base/ftwinfnt.c',
+ 'deps/sft2/src/base/ftxf86.c',
+ 'deps/sft2/src/winfonts/winfnt.c',
+ 'deps/sft2/src/bdf/bdf.c',
+ 'deps/sft2/src/type42/type42.c',
+ 'deps/sft2/src/type1/type1.c',
+ 'deps/sft2/src/truetype/truetype.c',
+ 'deps/sft2/src/cid/type1cid.c',
+ 'deps/sft2/src/pcf/pcf.c',
+ 'deps/sft2/src/psaux/psaux.c',
+ 'deps/sft2/src/pfr/pfr.c',
+ 'deps/sft2/src/cff/cff.c',
+ 'deps/sft2/src/psnames/psnames.c',
+ 'deps/sft2/src/pshinter/pshinter.c',
+ 'deps/sft2/src/autofit/autofit.c',
+ 'deps/sft2/src/autofit/afwarp.c',
+ 'deps/sft2/src/gzip/ftgzip.c',
+ 'deps/sft2/src/smooth/smooth.c',
+ 'deps/sft2/src/raster/raster.c',
+ 'deps/sft2/src/sfnt/sfnt.c',
+ 'deps/sft2/src/lzw/ftlzw.c']
+
+
+includes    = ['deps/sft2/inc']
+sysincludes = [ C_INCLUDE, EPOC32_INCLUDE, 'deps/sft2/inc/sys']
+defines     = ['FT2_BUILD_LIBRARY', 
+    #'LOGN_ENABLE', 
+    #'LOGP_ENABLE', 
+    'cplusplus']
+
+SymbianProgram( target, targettype,
+    sources = sources,
+    includes    = includes,
+    sysincludes = sysincludes,
+    libraries   = libraries,
+    defines     = defines,        
+)
+
+
+
+

symbian/SConstruct

+import time
+from scons_symbian import *
+
+constants.SIGNSIS_OUTPUT_EXTENSION = ".sisx"
+gcce.GCCE_OPTIMIZATION_FLAGS = "-O2 -fno-unit-at-a-time"
+
+
+SVNREVISION = ""
+
+#-------------------------------------------------------------------Get SVN info
+try:
+    import pysvn
+    SVNCLIENT = pysvn.Client()
+    SVNREVISION = "SVN-%d" % ( SVNCLIENT.info(".")["revision"].number )
+except ImportError:
+    pass
+
+#-------------------------------------------------------------Initialize globals
+
+DATE = list(time.gmtime()[:3])    
+DATE = [ str(x).zfill(2) for x in DATE ]
+DATE = "".join( DATE )    
+ 
+#: Name of the title on installer.
+PACKAGE_TITLE = ARGUMENTS.get( "sisappname", "pygame for S60" )
+
+#: Name of the python dll to use
+PYTHON_LIB_NAME = ARGUMENTS.get( "pythondll", "pygame_python" )
+
+#: Path to the libraries of pygame
+PATH_PY_LIBS = ARGUMENTS.get( "pylibs", "data/pygame/libs" )
+
+#: Name of the used sdl.dll ( pygame_sdl.dll )
+SDL_DLL_NAME = ARGUMENTS.get( "sdldll", "pygame_sdl" )
+
+#: Name of the used jpeg.dll
+JPEG_DLL_NAME = ARGUMENTS.get( "jpegdll", "pygame_libjpeg" )
+
+#: Name of the used libpng.dll
+PNG_DLL_NAME = ARGUMENTS.get( "pngdll", "pygame_libpng" )
+
+#: Using OpenC or estlib?
+USE_OPENC = ARGUMENTS.get( "openc", True )
+if USE_OPENC:
+    C_LIBRARY = ["libc", "libm"]
+    C_INCLUDE = join( EPOC32_INCLUDE, "stdapis" )
+else:
+    C_LIBRARY = ["estlib"]
+    C_INCLUDE = join( EPOC32_INCLUDE, "libc" )
+
+CAPABILITIES  = ARGUMENTS.get( "capabilities", "").split("+")
+if len(CAPABILITIES) == 0:
+    CAPABILITIES = CAPS_SELF_SIGNED
+    constants.SIGNSIS_OUTPUT_EXTENSION = "selfsigned.sisx"
+
+SISVERSION     = ARGUMENTS.get( "sisversion", "1,0,0").split(",")
+PYTHON_INCLUDE = ARGUMENTS.get( "pythoninclude", EPOC32_INCLUDE + "/python")
+PYTHON_VERSION = PYTHON_INCLUDE[-2:] # epoc32/include/python25
+if not PYTHON_VERSION.isdigit(): # But missing on pre 1.9.x PyS60( Python 2.2 )
+    PYTHON_VERSION = "22"
+
+# Pygame's installer package
+PACKAGE_NAME = ARGUMENTS.get( "package", "pygame-S60_py%(PYVER)s_%(REVISION)s_%(DATE)s_%(COMPILER)s-%(RELEASE)s.sis" % \
+                            {   "DATE"     : DATE, 
+                                "REVISION" : SVNREVISION, 
+                                "COMPILER" : COMPILER.upper(), 
+                                "RELEASE"  : RELEASE.upper(),
+                                "PYVER"    : PYTHON_VERSION 
+                            } )
+
+# SIS certificate 
+CERT = ARGUMENTS.get("cert", None)
+KEY  = ARGUMENTS.get("privkey", None)
+PASSPHRASE  = ARGUMENTS.get("passphrase", "" )
+
+#-----------------------------------------------------------------------Get UIDs     
+UID_PACKAGE    = ARGUMENTS["sisuid"] 
+UID_PYGAMEAPP  = ARGUMENTS["appuid"] 
+UID_SDL        = ARGUMENTS["sdluid"] 
+UID_JPEG       = ARGUMENTS["jpeguid"]
+UID_PNG        = 0#ARGUMENTS["pnguid"] 
+
+
+EMBEDDED_PYTHON_SIS = ARGUMENTS.get( "pythonsis", "none" )
+if EMBEDDED_PYTHON_SIS.lower() != "none" and COMPILER != COMPILER_WINSCW:
+    # Read the UID
+    f=open( EMBEDDED_PYTHON_SIS,'rb')
+    # First 16 bytes are for UIDs
+    # See: http://homepage.ntlworld.com/thouky/software/psifs/sis.html
+    data=f.read(16)
+    f.close()
+    import struct
+    uids = struct.unpack("IIII", data )
+    EMBEDDED_PYTHON_SIS_UID = hex(uids[2]).replace("L","")
+    print "Read UID %s from '%s'" % ( EMBEDDED_PYTHON_SIS_UID, EMBEDDED_PYTHON_SIS  )
+else:
+    EMBEDDED_PYTHON_SIS = None
+    EMBEDDED_PYTHON_SIS_UID = 0x0
+      
+Export("PACKAGE_NAME PYTHON_LIB_NAME PATH_PY_LIBS SDL_DLL_NAME CAPABILITIES PYTHON_INCLUDE USE_OPENC C_LIBRARY C_INCLUDE")
+
+# Build external libraries. Conditional because needed only once and takes extra time after that.
+if ARGUMENTS.get( "buildlibs", True ):
+    SConscript( "SConscript.sft2.py" )
+    SConscript( "SConscript.Ogg.py" )    
+    SConscript( "SConscript.Vorbis.py" )
+    
+    UID3 = UID_JPEG
+    TARGET_NAME = JPEG_DLL_NAME  
+    Export("TARGET_NAME UID3")
+    SConscript( "SConscript.jpeg.py" )  
+    
+    UID3 = UID_PNG
+    TARGET_NAME = PNG_DLL_NAME  
+    Export("TARGET_NAME UID3")
+    SConscript( "SConscript.libpng.py" )  
+    
+    TARGET_NAME = SDL_DLL_NAME  
+    UID3        = UID_SDL     
+    Export( "TARGET_NAME UID3" )
+    SConscript( "SConscript.SDL.py" )
+    
+# Build pygame.lib
+SConscript( "SConscript.pygame.py")
+
+# Build pygame application
+Export("UID_PYGAMEAPP CAPABILITIES")
+
+SConscript( "SConscript.app.py")
+
+#===============================================================================
+# Create the package
+#===============================================================================
+pkgtemplate = "pygame_pkgtemplate.txt"
+
+# Python is embedded as a sis
+pkgargs = {
+    "version" : SISVERSION,
+    "uid"     : UID_PACKAGE,
+    "appname" : PACKAGE_TITLE,
+    'cert':      CERT,
+    'key':       KEY,
+    'passwd':    PASSPHRASE,
+    "EMBEDDED_PYTHON_SIS"     : EMBEDDED_PYTHON_SIS, 
+    "EMBEDDED_PYTHON_SIS_UID" : EMBEDDED_PYTHON_SIS_UID,
+}
+
+Depends( PACKAGE_NAME, EMBEDDED_PYTHON_SIS )
+SymbianPackage(PACKAGE_NAME, pkgargs=pkgargs, pkgtemplate = pkgtemplate )
+
+

symbian/app/apps/liquid_s60.py

+#!/usr/bin/env python
+
+"""This examples demonstrates a simplish water effect of an
+image. It attempts to create a hardware display surface that
+can use pageflipping for faster updates. Note that the colormap
+from the loaded GIF image is copied to the colormap for the
+display surface.
+
+This is based on the demo named F2KWarp by Brad Graham of Freedom2000
+done in BlitzBasic. I was just translating the BlitzBasic code to
+pygame to compare the results. I didn't bother porting the text and
+sound stuff, that's an easy enough challenge for the reader :]"""
+
+import pygame, os
+from pygame.locals import *
+from math import sin
+
+THISDIR = os.path.dirname( __file__ )
+DISPLAY_SIZE = 240, 320
+def main():
+    #initialize and setup screen
+    pygame.init()
+    if os.name == "e32":
+        size = pygame.display.list_modes()[0]
+    else:
+        size =  DISPLAY_SIZE
+        
+    screen = pygame.display.set_mode(size)#, DOUBLEBUF)#, HWSURFACE)
+
+    #load image and quadruple
+    imagename = os.path.join( THISDIR, '..', 'launcher', 'logo.jpg')
+    bitmap = pygame.image.load(imagename)
+    bitmap = pygame.transform.scale(bitmap, size )
+    #bitmap = pygame.transform.scale2x(bitmap)
+    #bitmap = pygame.transform.scale2x(bitmap)
+    s = bitmap.get_size()
+    
+    #get the image and screen in the same format
+    if screen.get_bitsize() == 8:
+        screen.set_palette(bitmap.get_palette())
+    else:
+        bitmap = bitmap.convert()
+
+    #prep some variables
+    anim = 0.0
+
+    #mainloop
+    xblocks = range(0, s[0], 20)
+    yblocks = range(0, s[1], 20)
+    stopevents = QUIT, KEYDOWN, MOUSEBUTTONDOWN
+    clock = pygame.time.Clock()
+    while 1:
+        for e in pygame.event.get():
+            if e.type in stopevents:
+                return
+
+        anim = anim + 0.2
+        for x in xblocks:
+            xpos = (x + (sin(anim + x * .01) * 15)) + 20
+            for y in yblocks:
+                ypos = (y + (sin(anim + y * .01) * 15)) + 20
+                screen.blit(bitmap, (x, y), (xpos, ypos, 20, 20))
+
+        pygame.display.flip()
+        clock.tick(30)
+
+if __name__ == '__main__': main()
+
+
+
+"""BTW, here is the code from the BlitzBasic example this was derived
+from. i've snipped the sound and text stuff out.
+-----------------------------------------------------------------
+; Brad@freedom2000.com
+
+; Load a bmp pic (800x600) and slice it into 1600 squares
+Graphics 640,480
+SetBuffer BackBuffer()
+bitmap$="f2kwarp.bmp"
+pic=LoadAnimImage(bitmap$,20,15,0,1600)
+
+; use SIN to move all 1600 squares around to give liquid effect
+Repeat
+f=0:w=w+10:If w=360 Then w=0
+For y=0 To 599 Step 15
+For x = 0 To 799 Step 20
+f=f+1:If f=1600 Then f=0
+DrawBlock pic,(x+(Sin(w+x)*40))/1.7+80,(y+(Sin(w+y)*40))/1.7+60,f
+Next:Next:Flip:Cls
+Until KeyDown(1)
+"""
Add a comment to this file

symbian/app/launcher/logo.jpg

Added
New image

symbian/app/launcher/pygame_launcher.py

+"""
+pygame launcher for S60 - Application for launching others
+"""
+import time
+__author__ = "Jussi Toivola"
+
+from glob import glob
+
+import math
+
+import sys
+import os
+from os.path import join
+
+import pygame
+from pygame.locals import *
+from pygame import constants
+
+BLACK = 0, 0, 0
+TRANSPARENT = 0, 0, 0
+WHITE = 255, 255, 255
+TITLE_BG = 0, 64, 0
+TITLE_STROKE = 0, 255, 0
+DISPLAY_SIZE = 240, 320
+MENU_BG = 0, 128, 0
+ITEM_UNSELECTED_TEXT = 0, 128, 0
+ITEM_SELECTED_TEXT = 0, 255, 0
+ITEM_UNSELECTED = 0, 128, 0
+ITEM_SELECTED = TITLE_BG
+
+THISDIR = os.path.dirname(__file__)
+
+def load_image(name, colorkey=None):
+    """ Image loading utility from chimp.py """
+    fullname = os.path.join(THISDIR, name)
+    try:
+        image = pygame.image.load(fullname)
+    except pygame.error, message:
+        print 'Cannot load image:', name
+        raise SystemExit, message
+    image = image.convert()
+    if colorkey is not None:
+        if colorkey is - 1:
+            colorkey = image.get_at((0, 0))
+        image.set_colorkey(colorkey, RLEACCEL)
+    return image, image.get_rect()
+
+class SystemData:
+    """ Common resources """
+    def __init__(self):
+        self.screen = None
+        self.ticdiff = 0
+        self.tics = 0
+    
+        # Cache fonts to improve performance
+        # Fonts using the same font file works with OpenC only.
+        # SDL wants to keep the font's file handle open.
+        # Symbian's c-library (estlib) does not let one to have
+        # multiple handles open to a single file.
+        # (even though the Symbian's RFile implementation does )
+        self.font_title = pygame.font.Font(None, 36)
+        self.font_small = pygame.font.Font(None, 18)
+        self.font_normal = pygame.font.Font(None, 25)
+        
+        self.font_normal_bold = pygame.font.Font(None, 25)
+        self.font_normal_bold.set_bold(True)
+        
+    # Used by TextCache class, which caches the surfaces of the rendered texts.
+    def getFontTitle(self):
+        return self.font_title
+    def getFontNormal(self):
+        return self.font_normal
+    def getFontNormalBold(self):
+        return self.font_normal_bold
+    def getFontSmall(self):
+        return self.font_small
+
+class Effects(object):
+    """ Class for generic effects
+    TODO: multiple simultaneous effects in parallel( move left, fade out )
+    """
+    
+    def __init__(self, screen, clock, surf1, surf2, render_callback=None):
+        self.screen = screen
+        self.clock = clock
+        self.surf1 = surf1
+        self.surf2 = surf2 
+        
+        self.duration = 0
+        self.tween = lambda x:None
+        
+        #: Called for each update to allow update of other surfaces.
+        self.render_callback = render_callback
+    
+    
+#===============================================================================
+#    @see: http://coderepos.org/share/browser/lang/javascript/jstweener/trunk/src/JSTweener.js
+#    @see: http://sol.gfxile.net/interpolation/index.html about tween animations
+#===============================================================================
+    def tweenEaseOutSine(self, t, b, c, d):
+        return c * math.sin(t / d * (math.pi / 2)) + b
+    
+    def tweenEaseInOutSine(self, t, b, c, d, s=1.70158):
+        return - c / 2 * (math.cos(math.pi * t / d) - 1) + b;
+    
+    def tweenEaseInBack(self, t, b, c, d, s=1.7158):
+        t /= d
+        return c * (t) * t * ((s + 1) * t - s) + b;
+
+    def _slide_and_replace(self, direction, surf, surfold, surfnew, v):
+        
+        r = surf.get_rect()
+        
+        tween = self.tween
+          
+        B = - r.width
+        X = B * v 
+        
+        if direction == 1: 
+            surf.blit(surfnew, (B - X, 0))
+            surf.blit(surfold, (-X, 0))
+        elif direction == - 1:
+            surf.blit(surfnew, ((-B) + X, 0))
+            surf.blit(surfold, (X, 0))
+        
+        return surf, 0, 0
+    
+    def effectSlideRightReplace(self, surf, surfold, surfnew, v):
+        """ This makes the old surface move right and the new slides in it's place """
+        return self._slide_and_replace(1,surf, surfold, surfnew, v)
+    
+    def effectSlideLeftReplace(self, surf, surfold, surfnew, v):
+        """ This makes the old surface move left and the new slides in it's place """
+        return self._slide_and_replace(-1,surf, surfold, surfnew, v)
+    
+    def effectFadeTo(self, surf, surfold, surfnew, v ):
+        """ This makes the old surface fade and new surface appear """
+        
+        r = surf.get_rect()
+        
+        a1 = 255 * v
+        a2 = 255 - a1 
+        
+        #print "blend blit 1", time.time(),"->"
+        surfnew.set_alpha(a1)
+        surf.blit(surfnew, (0, 0))
+        #surf.fill((a1, a1, a1), None, BLEND_RGB_MULT)
+        #print time.time()
+        
+        #print "blend blit 2", time.time(),"->"
+        surfold.set_alpha(a2)
+        surf.blit(surfold, (0, 0))
+        
+        #surf.fill((a2, a2, a2), None, BLEND_RGB_MULT)
+        #print time.time()
+        
+        return surf, 0, 0
+    
+    def effectZoomOut(self, surf, surfold, surfnew, v):
+        """
+        This creates an effect where the surface is scaled and moved 
+        so that it looks like the surface moves to the distance.
+        """
+        
+        r = surf.get_rect()
+        
+        w = int(r.width * (1 - v))
+        h = int(r.height * (1 - v))
+        
+        #print "scale", time.time(),"->",
+        s = pygame.transform.scale(surfold, (w, h))
+        #print time.time()
+        
+        #print "blits", time.time(),"->"
+        surf.blit(surfnew,(0,0))
+        #print 1,time.time()
+        surf.blit(s, (r.width / 2 * (v), r.height / 2 * (v)))
+        #print 2,time.time()
+        
+        return surf, 0,0
+    
+    def do(self, effect_tween, duration):
+        """
+        @param effect_tween: List of effect-tween pairs
+            effect - Function of the effect.
+            tween  - Tweening function.
+        @param duration: How long the effect takes in seconds( 1, 0.5, etc )
+        """
+        # FIXME: Multiple does not work as expected. The chain is failing.
+        
+        self.duration = duration
+        
+        tics = 20
+        steps = 15.
+        surfold = self.surf1
+        surfnew = self.surf2
+
+        if type(effect_tween) != list:
+            effect_tween = [effect_tween]
+        
+        start = time.time()
+        end = start + self.duration
+        
+        
+        
+        exitnext = False
+        now = time.time()
+        while True: 
+            t = now - start
+            
+            s = self.surf1
+            if self.render_callback is not None:
+                self.render_callback(s)
+            
+            for effect, tween in effect_tween:
+                #print "effect", time.time(),"->",
+                v = tween(t, 0, 1, self.duration)
+                surf = pygame.Surface(self.surf1.get_size(), )
+                surf, x, y = effect( surf, s, self.surf2, v )
+                s = surf
+                #print time.time()
+            
+            #print "blit", time.time(),"->",
+            self.screen.blit(s, (x,y))
+            #print time.time()
+            
+            pygame.display.flip()
+            #print "tick", time.time(),"->",
+            self.clock.tick(30)
+            
+            if exitnext:
+                break
+            
+            now = time.time()
+            if now >= end:
+                # Let one more frame to draw, then exit 
+                exitnext = True
+                now = end
+            
+            #fps += 1
+        
+        #print "fps"
+        
+class TextCache(object):
+    """ Handles text rendering and caches the surfaces of the texts for speed.
+    Suitable for small static texts, such as menu items and titles.
+    To avoid memory problems with very long lists, maximum cache size can be set.
+    If the cache's size is exceeded the new surface is added into the cache and
+    the oldest is removed.
+    """
+    def __init__(self, max_size=0):
+        
+        #: id->surface mapping
+        self.map = {}
+        
+        self.max_size = max_size
+        
+        #: dict does not preseve order so we'll need to manage it with a list
+        self.order = []
+        
+    def render(self, id, string, fontgetter, renderargs, force_update=False):
+        """ Render string on the first time, but use it's cached surface next time. 
+        @param id: ID of the string
+        @param string: The text to render.
+        @param fontgetter: Function taking no parameters which returns a Font object.
+        @param renderargs: Arguments for font.render
+        @param force_update: Force re-rendering of the surface.
+        """
+        
+        # Check if exists
+        if id in self.map and not force_update:
+            return self.map[id]
+        
+        font = fontgetter()
+        surface = font.render(string, *renderargs)
+        self.map[id] = surface
+        
+        # Update cache's max size.
+        if self.max_size != 0:
+            
+            # No need to handle order if max_size is not set
+            self.order.append(id)
+            if len(self.order) > self.max_size:
+                del self.map[self.order[0]]
+                del self.order[0]
+        
+        return surface
+
+class DrawUtils:
+    """ Utility class for drawing common UI components. """
+    
+    @classmethod
+    def drawRectWithText(cl, surf, size, bgcolor, fgcolor, textsurf=None, textpos=None):
+        """
+        @param surf: Surface to draw to
+        @param size: Size of the rect
+        @param bgcolor: Background color of the rect
+        @param fgcolor: Foreground color of the rect( Text and surrounding rect )
+        @param textsurf: Surface containing pre-rendered text
+        @param textpos: Position of the text surface on the 'surf'
+        @param startpos: Start position
+        """
+        
+        # Make the dimmer( alpha ) foreground color for faded border
+        dim = list(fgcolor)
+        dim[0] *= 0.5
+        dim[1] *= 0.5
+        dim[2] *= 0.5
+        
+        if len(size) == 2:
+            rect = pygame.Rect(4, 4, size[0] - 7, size[1] - 7)
+        else:
+            rect = pygame.Rect(*size)
+        
+        # Draw the background
+        pygame.draw.rect(surf, bgcolor, rect)
+        
+        # Blit the text surface if defined
+        if textsurf is not None: 
+            surf.blit(textsurf, textpos)
+        
+        # Draw dim outer rect
+        pygame.draw.rect(surf, dim, rect, 1)
+        
+        # Draw the center rect
+        diff = [0,0,0] 
+        diff[0] = abs( fgcolor[0] - bgcolor[0])
+        diff[1] = abs( fgcolor[1] - bgcolor[1])
+        diff[2] = abs( fgcolor[2] - bgcolor[2])
+        
+        for x in xrange(0, 3):
+            # Draw dim inner rect
+            #color = list(fgcolor)
+            #color[ - 1] -= (alpha_diff / 3. * x)
+            #print diff
+            dim = list(fgcolor)#[0,0,0]
+            dim[0] -= diff[0] / 3. * x
+            dim[1] -= diff[1] / 3. * x
+            dim[2] -= diff[2] / 3. * x
+            #print "dim", dim
+            offset = rect[0] + x
+            
+            pos = pygame.Rect(rect[0] + x, rect[1] + x, rect[2] - (x * 2 - 1), rect[3] - (x * 2 - 1))
+            #print rect, pos
+            pygame.draw.rect(surf, dim, pos, 1)
+            
+
+class BackgroundBase(pygame.sprite.Sprite):
+    def __init__(self, sysdata):
+        pygame.sprite.Sprite.__init__(self)
+        self.sysdata = sysdata
+        self.screen = sysdata.screen
+        screen_size = self.screen.get_size()
+        self.surface = pygame.Surface(screen_size, )
+
+class BackgroundTransparent(BackgroundBase):
+    
+    def __init__(self, sysdata):
+        BackgroundBase.__init__(self, sysdata) 
+        self.surface.fill(BLACK)
+        self.surface.set_alpha(200)
+        
+    def update(self):pass
+        #self.surface.fill(TRANSPARENT)
+        
+class Background(BackgroundBase):
+    """Main background"""
+    def __init__(self, sysdata):
+        BackgroundBase.__init__(self, sysdata) 
+        
+        self.surface.fill(BLACK)
+        
+        self.rect = self.surface.get_rect()
+        
+        #: The logo
+        self.img_logo, r = load_image("logo.jpg")
+        
+        # Position the logo on middle of the screen.
+        c = self.rect.center
+        self.img_pos = [ c[0] - r.w / 2, c[1] - r.h / 2 ]
+        
+        #: Make alpha the same size as the image
+        #self.alpha = pygame.Surface(r.size, )
+        
+        self.alphaval = 0.
+        self.alphaprev = -1
+        self.alphadir = - 1. # per second
+        
+        self.surface.fill(BLACK)
+        self.surface.blit(self.img_logo, self.img_pos)
+        self.surface.set_alpha(10)
+        
+    def updateAlphaValue(self):
+        """ Update the visibility of the logo """
+        min = 6.
+        max = 12.
+        
+        s = self.sysdata.ticdiff / 1000.
+        
+        self.alphaval += s * self.alphadir
+        
+        if self.alphaval > max:
+            self.alphaval = max
+            self.alphadir = - self.alphadir
+            
+        if self.alphaval < min:
+            self.alphaval = min
+            self.alphadir = - self.alphadir
+        return self.alphaval
+    
+    def update(self):
+        self.surface.set_alpha(self.updateAlphaValue())
+        #print a
+        #a = self.alphaval
+        #self.surface.fill(BLACK)
+        #self.surface.blit(self.img_logo, self.img_pos)
+        #self.surface.fill( (a,a,a), None, BLEND_RGB_MULT )
+        
+class TextField(pygame.sprite.Sprite):
+    """ Handles text rendering and updating when necessary """
+    MODE_NONE = 0
+    MODE_CENTER = 1
+    
+    def __init__(self, background, sysdata, exit_callback, title="", text="", mode=MODE_NONE):
+        pygame.sprite.Sprite.__init__(self)
+        
+        self.sysdata = sysdata
+        self.bg = background
+        self._title = title
+        self.title_changed = True
+        
+        self._text = text
+        self.text_changed = True
+        self._selected_index = 0
+        
+        self.mode = mode
+        
+        self.exit_callback = exit_callback
+        
+    def updateText(self):
+        """ Redraw text contents """
+        if not self.text_changed: return
+        
+        text = self._text
+        
+        # Below title
+        startposy = self.titlesurface.get_size()[1] + 10
+        startposx = 10
+        
+        # Position on parent
+        self.itemspos = (0, startposy)
+        
+        psize = self.bg.surface.get_size()
+        size = (psize[0], psize[1] - startposy)
+        surf = pygame.Surface(size, )
+        
+        # Create text contents
+        DrawUtils.drawRectWithText(surf, size, TITLE_BG, TITLE_STROKE,
+                                    textsurf=None)
+        #text = textwrap.dedent(text)
+        font = self.sysdata.getFontSmall()
+        
+        lines = text.split("\n")
+        height = font.get_height()
+        posy = height
+        for line in lines:
+            line = line.strip()
+            text = font.render(line, 1, (0, 255, 0))
+            if self.mode == TextField.MODE_CENTER:
+                x, y = text.get_size()
+                x = size[0] - x
+                x /= 2
+            
+            surf.blit(text, (x, posy))
+            posy += height
+        
+        self.textsurface = surf
+        self.text_changed = False
+        
+    def updateTitle(self):
+        """ Redraw title text """
+        if not self.title_changed: return
+            
+        text = self.sysdata.getFontTitle().render(self._title, 1, (0, 255, 0))
+        textpos = text.get_rect()
+        textpos.centerx = self.bg.surface.get_rect().centerx
+        textpos.centery = textpos.size[1] / 2 + 7
+        
+        self.size = size = self.bg.surface.get_size()
+        size = (size[0], 40)
+
+        # Draw the surrounding rect
+        surf = titlebg = pygame.Surface(size, )
+        DrawUtils.drawRectWithText(surf, size, TITLE_BG, TITLE_STROKE,
+                                    textsurf=text, textpos=textpos)
+        
+        self.title_changed = False
+        self.titlesurface = surf
+        # Position on parent
+        self.titlepos = (0, 0)
+        
+    def update(self):
+        self.updateTitle()
+        self.updateText()
+        
+        self.bg.surface.blit(self.titlesurface, self.titlepos)
+        self.bg.surface.blit(self.textsurface, self.itemspos)
+    
+    def exit(self):
+        self.exit_callback()
+        
+    def handleEvent(self, event):
+        """ Exit on any key """
+        if event.type == pygame.KEYDOWN:
+            self.exit()
+            return True
+        elif event.type == pygame.MOUSEBUTTONUP:
+            self.exit()
+            return True
+        
+        return False
+    
+class Menu(pygame.sprite.Sprite):
+    
+    def __init__(self, bg, sysdata, title, items, cancel_callback):
+        pygame.sprite.Sprite.__init__(self)
+        
+        #: General information about the system
+        self.sysdata = sysdata
+        
+        #: Background object
+        self.bg = bg
+        
+        #: Text of the title
+        self._title = title
+        
+        #: If True, title surface is updated
+        self.title_changed = True
+        
+        #: Surface containing the rendered menu items.
+        self.itemsurface = None
+        
+        #: Strings of the items
+        self._items = items
+        
+        #: Rects of list items to be used for mouse hit checking
+        self._itemrects = []
+        
+        #: If True, the item surfaces are updated
+        self.items_changed = True
+        
+        #: Index of selected menu item
+        self._selected_index = 0
+        
+        #: Index of previous selection
+        self._prev_index = 0
+        
+        #: Index of the topmost visible item
+        self.visibletop = 0
+        
+        #: How many items the list can display
+        self.shownitems = 0
+        
+        #: Callback called at exit
+        self.cancel_callback = cancel_callback
+        
+        #: Cached texts
+        self.textcache = TextCache()
+        
+        #: Flag to indicate if mouse/pen is down
+        self._mousedown = False
+        
+        #: Rect for scrollbar. Used to scroll the list with mouse/pen.
+        self._scrollbar_rect = Rect(0, 0, 0, 0)
+        
+        #: Rect for scrollbar indicator. User can drag this around with mouse/pen.
+        self._scrollbar_indic_rect = Rect(0, 0, 0, 0) 
+        
+        #: Flag to determine if user is dragging the scrollbar
+        self.scrollbar_dragged = False
+        
+        #: Last position of the drag so we know the direction
+        self.scrollbar_drag_pos = [0,0]
+        
+    #------------------------------------------------ Selection property get/set
+    def _set_selection(self, index):
+        self._prev_index = self._selected_index
+        self._selected_index = index
+        self.items_changed = True
+        self.updateVisible()
+        
+    def _get_selection(self): return self._selected_index
+    selection = property(fget=_get_selection, fset=_set_selection)
+
+    #---------------------------------------------------- Title property get/set
+    def _set_title(self, title):
+        self._title = title
+        self.title_changed = True
+        
+    def _get_title(self): return self._title
+    title = property(fget=_get_title, fset=_set_title)
+
+    #----------------------------------------------------- Item property get/set
+    def _set_items(self, title): 
+        self._items = items
+        self.items_changed = True
+        
+    def _get_items(self): return self._items
+    items = property(fget=_get_items, fset=_set_items)
+
+    #---------------------------------------------------------- Public functions
+    def selectNextItem(self):
+        """ Select next item from list. Loops the items """
+        last = len(self._items) - 1
+        if last < 1: return
+        
+        next = self._selected_index + 1
+        if next > last:
+            next = 0
+        self.selection = next
+        
+    def selectPrevItem(self):
+        """ Select previous item from list. Loops the items """
+        last = len(self._items) - 1
+        if last < 1: return
+        
+        first = 0
+        next = self._selected_index - 1
+        if next < first:
+            next = last
+        self.selection = next
+         
+    def doSelect(self):
+        """ Handle item selection by invoking its callback function """
+        title, callback, args = self._items[self._selected_index]
+        callback(*args)
+    
+    def cancel(self):
+        """ Invokes the menu cancellation handler """
+        cb, args = self.cancel_callback
+        cb(*args)
+        
+    def clear(self):
+        " Remove the used surfaces from memory "
+        self.itemsurface = None
+        self.titlesurface = None
+        self.items_changed = True
+        self.title_changed = True
+        
+    def checkMouseCollision(self, event):
+        """ Checks if mouse event collides with any of the menu items """
+        # Not yet known.
+        if self.itemsurface is None: return False
+        
+        # Check if we hit the surface containing the items
+        menurect = pygame.Rect(self.itemsurface.get_rect())
+        menurect.top = self.itemspos[1]
+        
+        # Handle indicator dragging
+        if event.type == pygame.MOUSEMOTION:
+            if self.scrollbar_dragged:
+                
+                # Determine direction by comparing to previous position
+                # We simply change the topmost item when dragging
+                # Not very fancy but works.
+                y = self.scrollbar_drag_pos[1]
+                diff = self.selection - self.visibletop
+                if y < event.pos[1]:
+                    # Down
+                    self.visibletop = min( len(self.items) - self.shownitems, self.visibletop + 1 )
+                    self.selection  = self.visibletop + diff
+                    
+                elif y > event.pos[1]:
+                    # Up
+                    self.visibletop = max( 0, self.visibletop - 1 )
+                    self.selection  = self.visibletop + diff
+                
+                self.scrollbar_drag_pos = event.pos
+                
+                return 2
+            
+        if menurect.collidepoint(event.pos):
+            
+            # Check if user clicked the scrollbar
+            r = Rect(self._scrollbar_rect)
+            r.top += self.itemspos[1]
+            
+            if r.collidepoint(event.pos):
+                if event.type in [pygame.MOUSEBUTTONUP, pygame.MOUSEBUTTONDOWN]:
+                    r = Rect(self._scrollbar_indic_rect)
+                    r.top += self.itemspos[1]
+                    if r.collidepoint(event.pos):
+                        # Start dragging the scrollbar
+                        self.scrollbar_dragged = ( event.type == pygame.MOUSEBUTTONDOWN )
+                        return 2
+                    else:
+                        # TODO: Handle user clicking empty scrollbar area to move the view area
+                        return 2
+            elif not self.scrollbar_dragged:
+                for x in xrange(len(self._itemrects)):
+                    r = Rect(self._itemrects[x])
+                    r.top += self.itemspos[1]
+                    if r.collidepoint(event.pos):
+                        self.selection = self.visibletop + x
+                        return 1
+        
+        return 0
+    
+    def handleEvent(self, event):
+        """ Handle events of this component """
+        
+        was_scrollbar_dragging = self.scrollbar_dragged
+        if event.type == pygame.MOUSEBUTTONUP:
+            self.scrollbar_dragged = False
+            
+        if event.type == pygame.KEYDOWN:
+            if event.key == constants.K_DOWN:
+                self.selectNextItem()
+                return True
+            
+            elif event.key == constants.K_UP:
+                self.selectPrevItem()
+                return True
+            
+            if event.key == constants.K_RETURN:
+                self.doSelect()
+                return True
+            
+            if event.key == constants.K_ESCAPE:
+                self.cancel()
+                return True
+        
+        # Mouse button down and movement only marks the item selected
+        if event.type == pygame.MOUSEBUTTONDOWN:
+            self.checkMouseCollision(event)
+            self._mousedown = True
+        
+        # When pen is pressed on surface, user can keep changing the
+        # selection and activate the selection by releasing the pen.
+        elif event.type == pygame.MOUSEMOTION:
+           self.checkMouseCollision(event)
+        
+        # Mouse button up selects the item
+        elif event.type == pygame.MOUSEBUTTONUP and not was_scrollbar_dragging:
+            self._mousedown = False
+            
+            # User can cancel selection by moving the pen outside of all items
+            if self.checkMouseCollision(event) == 1:
+                self.doSelect()
+        
+        return False
+    
+     
+    def computeVisibleItemCount(self):
+        """ Calculate the amount of items that fit inside the list """
+
+        height = self.sysdata.getFontNormal().get_height()
+        h = self.itemsurface.get_height()
+        c = int(round((h / height))) - 1
+        return c
+    
+    def update(self):
+        
+        self.updateTitle()
+        self.updateItems()
+        
+        self.bg.surface.blit(self.titlesurface, self.titlepos)
+        self.bg.surface.blit(self.itemsurface, self.itemspos)
+    
+    def _create_list_bg(self, size):
+        
+        surf = pygame.Surface(size, )
+        DrawUtils.drawRectWithText(surf, size, TITLE_BG, TITLE_STROKE, textsurf=None)
+        self.itemsurface = surf
+        return surf
+    
+    def _get_list_size(self):
+        psize = self.bg.surface.get_size()
+        size = (psize[0], psize[1] - self.itemspos[1])
+        return size
+    
+    def _draw_scrollbar(self, surf):
+        r = surf.get_rect()
+        xs = r[2] - 10
+        ys = r[1] + 10
+        h = r[3] - 20
+        w = 10
+        r = Rect(xs, ys, w, h)
+        
+        DrawUtils.drawRectWithText(surf, r, TITLE_BG, TITLE_STROKE, textsurf=None)
+        
+        # Compute the size of the scrollbar's indicator bar
+        # Visible items vs total items
+        factor = (float(self.shownitems) / float(len(self.items)))
+        indic_h = h - 4
+        indic_h *= min(1.0, factor)
+        
+        # Compute the position of the scrollbar's indicator bar
+        # topmost item vs how many items
+        empty_h = h - indic_h - 4
+        factor = float(len(self.items) - self.shownitems)
+        if factor != 0:
+            factor = float(self.visibletop) / factor
+        else:
+            factor = 1
+        ys += 2
+        ys += empty_h * factor
+        indic_r = Rect(xs + 2, ys, 5, indic_h)
+        DrawUtils.drawRectWithText(surf, indic_r, TITLE_STROKE, TITLE_STROKE, textsurf=None)
+        
+        self._scrollbar_rect = r 
+        self._scrollbar_indic_rect = indic_r
+        
+    def updateItems(self):
+        """ Update list item surface """
+        if not self.items_changed: return
+        
+        items = self._items
+        
+        # Below title
+        startposy = self.titlesurface.get_size()[1] + 10
+        startposx = 10
+        self.itemspos = (0, startposy)
+        
+        # Create and cache the list background
+        size = self._get_list_size()
+        surf = self._create_list_bg(size)
+        self.shownitems = self.computeVisibleItemCount()
+        
+        # Initialize data
+        startposy = 5
+        self.visibletop = min(self.visibletop, self._selected_index)
+        maximumpos = min(len(items), self.visibletop + self.shownitems)
+        height = self.sysdata.getFontNormal().get_height()
+        spaceheight = height + 10
+        
+        # Refresh positions of items for mouse support
+        self._itemrects = []
+        
+        
+        # Draw the items
+        for x in xrange(self.visibletop, maximumpos):
+            textdata, cb, args = items[x]
+            # Textcache id
+            id = textdata
+            if x == self._selected_index:
+                font = self.sysdata.getFontNormalBold
+                color = ITEM_SELECTED_TEXT
+                bgcolor = ITEM_SELECTED
+                id = "_" + id
+            else:
+                font = self.sysdata.getFontNormal
+                color = ITEM_UNSELECTED_TEXT
+                bgcolor = ITEM_UNSELECTED
+                
+            s = (size[0] - startposx * 2 - 15, spaceheight)
+            pos = (startposx, startposy)
+            
+            # Use the text cache for speed.
+            text = self.textcache.render(id, textdata, font, (1, color))
+            textpos = text.get_rect()
+            textpos.centerx = self.bg.surface.get_rect().centerx
+            textpos.centery = pos[1] + s[1] / 2
+            
+            # Add to list
+            surf.blit(text, textpos)
+            startposy = startposy + height
+            
+            self._itemrects.append(textpos)
+        
+        self._draw_scrollbar(surf)
+        
+        self.items_changed = False
+        #self.itemsurface = self.itemsurface
+    def updateTitle(self):
+        """ Update title surface """
+        if not self.title_changed: return
+        
+        # Render the title text
+        text = self.sysdata.getFontTitle().render(self._title, 1, (0, 255, 0))
+        self.textpos = textpos = text.get_rect()
+        textpos.centerx = self.bg.surface.get_rect().centerx
+        textpos.centery = textpos.size[1] / 2 + 7
+        
+        self.size = size = self.bg.surface.get_size()
+        size = (size[0], 40)
+
+        # Render the final title surface with combined background and text 
+        surf = pygame.Surface(size, )
+        DrawUtils.drawRectWithText(surf, size , TITLE_BG, TITLE_STROKE, text, textpos)
+        
+        # Update data
+        self.title_changed = False
+        self.titlesurface = surf
+        
+        # Position on parent
+        self.titlepos = (0, 0)
+    
+    def updateVisible(self):
+        """ Updates position of the topmost visible item in the list """
+        diff = abs(self.visibletop - self._selected_index)
+        if diff >= self.shownitems:
+            self.visibletop = max(0, min(self._selected_index - self.shownitems + 1, self._selected_index))
+         
+class Application(object):
+    """ Main application handler.
+    Takes care of system initialization and main application states.
+    """
+    def __init__(self):
+        
+        if sys.platform == "symbian_s60":
+            size = pygame.display.list_modes(16)[0]
+            self.screen = pygame.display.set_mode(size, )
+        else:
+            self.screen = pygame.display.set_mode(DISPLAY_SIZE, 16) 
+        
+        self.sysdata = SystemData()
+        self.sysdata.screen = self.screen
+        
+        self.mainbg = Background(self.sysdata)
+        self.bg = BackgroundTransparent(self.sysdata)
+        
+        items = [("Applications", self.mhApplications, ()),
+                 # TODO: Disabled settings for now...
+                 #("Settings", self.mhSettings, ()), 
+                 ("About", self.mhAbout, ()),
+                 ("Exit", self.mhExit, ()), ]
+        self._main_menu = Menu(self.bg, self.sysdata,
+                        title="pygame launcher",
+                        items=items,
+                        cancel_callback=(self.mhExit, ())
+                        )
+        self.focused = self._main_menu
+        self.sprites = pygame.sprite.OrderedUpdates()
+        self.sprites.add(self.mainbg)
+        self.sprites.add(self.bg)
+        self.sprites.add(self.focused)
+        self.running = True
+        self.clock = pygame.time.Clock()
+        
+        self.app_to_run = None
+        
+        #: Updated by foreground event
+        self.is_foreground = True
+        
+    def initialize(self):
+        pass
+    
+    def run(self):
+        """ Main application loop """
+        self.initialize()       
+        
+        # From black
+        black = pygame.Surface(self.screen.get_size(), )
+        self.sprites.update()
+        self.screen.blit(self.bg.surface, (0, 0))
+            
+        # Start the tween animation
+        e = Effects(self.screen, self.clock, black, self.bg.surface )
+        
+        # Blocks for the duration of the animation
+        e.do( [
+               (e.effectFadeTo, e.tweenEaseOutSine),
+               #(e.effectSlideRightReplace, e.tweenEaseInBack),
+               ], 0.5)
+        
+        self.sysdata.tics = pygame.time.get_ticks()
+        
+        eventhandler = self.handleEvent
+        while self.running:
+            
+            for event in pygame.event.get():
+                #print event
+                eventhandler(event)
+                
+            if not self.running:
+                break
+                    
+            if self.is_foreground:
+                self.sprites.update()
+            
+            self.screen.blit(self.mainbg.surface, (0, 0))
+            self.bg.surface.set_alpha(96) # This creates a nice fade effect for menu items
+            self.screen.blit(self.bg.surface, (0, 0))
+            
+            
+            pygame.display.flip()
+            
+            if self.is_foreground:
+                self.clock.tick(30)
+            else:
+                # Longer delay when in backround
+                self.clock.tick(5)
+
+            tics = pygame.time.get_ticks()
+            self.sysdata.ticdiff = tics - self.sysdata.tics
+            self.sysdata.tics = tics
+            
+        return self.app_to_run
+        
+    def mhLaunchApplication(self, app_path):
+        """ Menu handler for application item """
+        
+        if app_path is None:
+            # Restore pygame launcher menu
+            
+            self.__handle_transition_animation(self.focused, self._main_menu, effect=1)
+            
+            self.focused.clear()
+            self.sprites.remove(self.focused)
+            self.sprites.add(self._main_menu)
+            self.focused = self._main_menu
+            return
+        
+        # Start the tween animation
+        blacksurf = pygame.Surface(self.screen.get_size(), )
+        blacksurf.fill(BLACK)
+        e = Effects(self.screen, self.clock, self.focused.bg.surface, blacksurf,
+                    render_callback=None)
+
+        # Blocks for the duration of the animation
+        effect = e.effectZoomOut
+        e.do((effect, e.tweenEaseInBack), 0.75)
+        
+        # Remove so it won't flash at the end
+        self.sprites.remove(self.focused)
+        
+        self.focused = None
+        self.app_to_run = app_path
+        self.running = 0
+    
+    def __handle_transition_animation(self, menu1, menu2, effect):
+        bg1 = BackgroundTransparent(self.sysdata)
+        bg2 = BackgroundTransparent(self.sysdata)
+        menu1.bg = bg1
+        menu2.bg = bg2
+        
+        def render_callback(surf): 
+            # We'll need to update the logo in the background, 
+            # which depends on the tick counter.
+            #tics = pygame.time.get_ticks()
+            #self.sysdata.ticdiff = tics - self.sysdata.tics
+            #self.sysdata.tics = tics
+            
+            #self.mainbg.update()
+            #self.screen.blit(self.mainbg.surface, (0, 0))
+            #surf.blit(self.bg.surface, (0, 0))
+            #surf.set_alpha(96)
+            
+            #bg1.update()
+            #bg2.update()
+            menu1.update()
+            menu2.update()
+        
+        # Start the tween animation
+        e = Effects(self.screen, self.clock, bg1.surface, bg2.surface,
+                    render_callback=render_callback)
+        
+        # Blocks for the duration of the animation
+        effect = [e.effectSlideLeftReplace, e.effectSlideRightReplace, e.effectFadeTo][effect]
+        e.do([
+              (effect, lambda t, b, c, d, s=1.01:e.tweenEaseInOutSine(t, b, c, d, s)),
+              (e.effectFadeTo, e.tweenEaseOutSine),
+              ], 0.5)
+        
+        # The animation completed.
+        menu2.bg = self.bg
+        menu2.update()
+        
+        bg1.surface.blit(bg2.surface, (0, 0))
+        
+    def mhApplications(self):
+        """ Menu handler for 'Applications' item """
+        
+        # Get list of applications
+        join = os.path.join
+        appdir = join(THISDIR, "..", "apps")
+        apps = glob(join(appdir, "*.py"))
+        apps += glob(join(appdir, "*.pyc"))
+        apps += glob(join(appdir, "*.pyo"))
+
+        items = []
+        for a in apps:
+            name = os.path.basename(a)
+            name = ".".join(name.split(".")[: - 1])
+            if len(name) == 0: continue
+            
+            i = (name, self.mhLaunchApplication, (a,))
+            items.append(i)
+        
+        # The last button for getting out of the menu
+        items.append(("Back", self.mhLaunchApplication, (None,)))
+        
+        self.sprites.remove(self.focused)
+        
+        # Create tween effect for transition
+        background = Background(self.sysdata)
+        
+        menu = Menu(background, self.sysdata,
+                        title="Applications",
+                        items=items,
+                        cancel_callback=(self.mhLaunchApplication, (None,)),
+                        )
+        menu.textcache.max_size = 24
+        menu.update()
+        self.__handle_transition_animation(self.focused, menu, effect=0)
+        
+        se