Browse Source

launcher deot

cpi 4 years ago
commit
fd02cc3e12
100 changed files with 11870 additions and 0 deletions
  1. 27 0
      .cpirc
  2. 24 0
      .gitignore
  3. 3 0
      .gitmodules
  4. 38 0
      .twm/Bach
  5. 62 0
      .twm/Escher
  6. 46 0
      .twm/Linux64
  7. 14 0
      .twm/am
  8. 52 0
      .twm/amule
  9. 5 0
      .twm/close
  10. 14 0
      .twm/ff
  11. 5 0
      .twm/fullsize
  12. 5 0
      .twm/iconify
  13. 28 0
      .twm/moose
  14. 14 0
      .twm/mozilla
  15. 5 0
      .twm/resize
  16. 27 0
      .twm/torrent
  17. 14 0
      .twm/tv
  18. 14 0
      .twm/xlogo32
  19. 140 0
      .twmrc
  20. 25 0
      .xinitrc
  21. 7 0
      .xorg.conf
  22. 7 0
      .xorg_lima.conf
  23. 3 0
      CPI/version.json
  24. 674 0
      LICENSE
  25. 285 0
      Menu/GameShell/10_Settings/.Airplane.deot/__init__.py
  26. 0 0
      Menu/GameShell/10_Settings/.Brightness.stock/Icon\r
  27. 17 0
      Menu/GameShell/10_Settings/.Brightness.stock/__init__.py
  28. 186 0
      Menu/GameShell/10_Settings/.Brightness.stock/brightness_page.py
  29. 6 0
      Menu/GameShell/10_Settings/.Brightness.stock/myvars.py
  30. 13 0
      Menu/GameShell/10_Settings/.Brightness.stock/pages.py
  31. 55 0
      Menu/GameShell/10_Settings/.LauncherGo.stock/__init__.py
  32. 0 0
      Menu/GameShell/10_Settings/.Sound.stock/Icon\r
  33. 17 0
      Menu/GameShell/10_Settings/.Sound.stock/__init__.py
  34. 6 0
      Menu/GameShell/10_Settings/.Sound.stock/myvars.py
  35. 13 0
      Menu/GameShell/10_Settings/.Sound.stock/pages.py
  36. 170 0
      Menu/GameShell/10_Settings/.Sound.stock/sound_page.py
  37. 145 0
      Menu/GameShell/10_Settings/.Storage.deot/__init__.py
  38. 155 0
      Menu/GameShell/10_Settings/.list_page.py.stock
  39. 398 0
      Menu/GameShell/10_Settings/About/__init__.py
  40. 0 0
      Menu/GameShell/10_Settings/Airplane/Icon\r
  41. 279 0
      Menu/GameShell/10_Settings/Airplane/__init__.py
  42. 813 0
      Menu/GameShell/10_Settings/Bluetooth/__init__.py
  43. 224 0
      Menu/GameShell/10_Settings/Bluetooth/agent.py
  44. 128 0
      Menu/GameShell/10_Settings/Bluetooth/net_item.py
  45. 0 0
      Menu/GameShell/10_Settings/Brightness/Icon\r
  46. 17 0
      Menu/GameShell/10_Settings/Brightness/__init__.py
  47. 187 0
      Menu/GameShell/10_Settings/Brightness/brightness_page.py
  48. 6 0
      Menu/GameShell/10_Settings/Brightness/myvars.py
  49. 13 0
      Menu/GameShell/10_Settings/Brightness/pages.py
  50. 0 0
      Menu/GameShell/10_Settings/ButtonsLayout/Icon\r
  51. 267 0
      Menu/GameShell/10_Settings/ButtonsLayout/__init__.py
  52. 252 0
      Menu/GameShell/10_Settings/Cores/__init__.py
  53. 349 0
      Menu/GameShell/10_Settings/GateWay/__init__.py
  54. 309 0
      Menu/GameShell/10_Settings/Languages/__init__.py
  55. 302 0
      Menu/GameShell/10_Settings/Lima/__init__.py
  56. 264 0
      Menu/GameShell/10_Settings/Notification/__init__.py
  57. 90 0
      Menu/GameShell/10_Settings/PowerOFF/__init__.py
  58. 555 0
      Menu/GameShell/10_Settings/PowerOptions/__init__.py
  59. 294 0
      Menu/GameShell/10_Settings/Skins/__init__.py
  60. 0 0
      Menu/GameShell/10_Settings/Sound/Icon\r
  61. 17 0
      Menu/GameShell/10_Settings/Sound/__init__.py
  62. 6 0
      Menu/GameShell/10_Settings/Sound/myvars.py
  63. 13 0
      Menu/GameShell/10_Settings/Sound/pages.py
  64. 167 0
      Menu/GameShell/10_Settings/Sound/sound_page.py
  65. 0 0
      Menu/GameShell/10_Settings/Storage/Icon\r
  66. 138 0
      Menu/GameShell/10_Settings/Storage/__init__.py
  67. 19 0
      Menu/GameShell/10_Settings/Time/__init__.py
  68. 112 0
      Menu/GameShell/10_Settings/Time/list_item.py
  69. 16 0
      Menu/GameShell/10_Settings/Time/logger.py
  70. 5 0
      Menu/GameShell/10_Settings/Time/myvars.py
  71. 13 0
      Menu/GameShell/10_Settings/Time/pages.py
  72. 304 0
      Menu/GameShell/10_Settings/Time/timezone_lib_list_page.py
  73. 334 0
      Menu/GameShell/10_Settings/Update/__init__.py
  74. 26 0
      Menu/GameShell/10_Settings/Wifi/__init__.py
  75. 5 0
      Menu/GameShell/10_Settings/Wifi/myvars.py
  76. 196 0
      Menu/GameShell/10_Settings/Wifi/net_item.py
  77. 61 0
      Menu/GameShell/10_Settings/Wifi/pages.py
  78. 738 0
      Menu/GameShell/10_Settings/Wifi/wifi_list.py
  79. 29 0
      Menu/GameShell/10_Settings/__init__.py
  80. 57 0
      Menu/GameShell/10_Settings/list_item.py
  81. 155 0
      Menu/GameShell/10_Settings/list_page.py
  82. 12 0
      Menu/GameShell/10_Settings/myvars.py
  83. 13 0
      Menu/GameShell/10_Settings/pages.py
  84. 1188 0
      Menu/GameShell/21_Warehouse/__init__.py
  85. 1 0
      Menu/GameShell/30_RetroArch.sh
  86. 1 0
      Menu/GameShell/31_CaveStory.sh
  87. 6 0
      Menu/GameShell/32_ChocoDM/action.config
  88. 5 0
      Menu/GameShell/50_PICO-8/PICO-8.sh
  89. 12 0
      Menu/GameShell/50_PICO-8/Post-Up.sh
  90. 8 0
      Menu/GameShell/50_PICO-8/compkginfo.json
  91. 99 0
      Menu/GameShell/50_PICO-8/pico-8/config.txt
  92. 90 0
      Menu/GameShell/50_PICO-8/pico-8/log.txt
  93. 1 0
      Menu/GameShell/50_PICO-8/pico-8/sdl_controllers.txt
  94. 3 0
      Menu/GameShell/90_Reload UI.sh
  95. 24 0
      Menu/GameShell/97_Music Player/__init__.py
  96. 134 0
      Menu/GameShell/97_Music Player/list_item.py
  97. 420 0
      Menu/GameShell/97_Music Player/mpd_spectrum_page.py
  98. 328 0
      Menu/GameShell/97_Music Player/music_lib_list_page.py
  99. 8 0
      Menu/GameShell/97_Music Player/myvars.py
  100. 38 0
      Menu/GameShell/97_Music Player/pages.py

+ 27 - 0
.cpirc

@@ -0,0 +1,27 @@
+SCREEN=`cat /sys/class/graphics/fb0/modes`
+
+XORG_CONF="~/launcher/.xorg.conf"
+if [ -f /home/cpi/.lima ]
+then
+XORG_CONF="~/launcher/.xorg_lima.conf"
+fi
+
+if [ -f /tmp/autologin ]
+then
+   rm -f /tmp/autologin
+   mpd ~/.mpd.conf
+      if [[ $SCREEN =~ .*320.* ]]
+      then
+			while :
+			do
+        startx /home/cpi/launcher/.xinitrc -- -xf86config $XORG_CONF -nocursor > /tmp/x.log 2>&1
+				sleep 1
+			done
+      else
+			while :
+			do
+        startx /home/cpi/launcher/.xinitrc hdmi -- -xf86config $XORG_CONF > /tmp/x.log 2>&1
+				sleep 1
+			done
+      fi
+fi

+ 24 - 0
.gitignore

@@ -0,0 +1,24 @@
+retroarch-core-options.cfg
+*.lpl
+*.swp
+.bsv
+*.pyc
+sys.py/.powerlevel
+sys.py/.buttonslayout
+sys.py/.lang
+*.cfg
+**/Jobs/*
+!**/Jobs/.gitkeep
+!**/Jobs/00_lowpower.sh
+!**/Jobs/00_lowpower.alias
+.done
+bios
+bios/*
+screenshots
+screenshots/*
+.pcsx
+.pcsx/*
+*.log
+.DS_Store
+sys.py/.*
+sys.py/*.db

+ 3 - 0
.gitmodules

@@ -0,0 +1,3 @@
+[submodule "sys.py/pyaria2_rpc"]
+	path = sys.py/pyaria2_rpc
+	url = https://github.com/cuu/pyaria2_rpc.git

+ 38 - 0
.twm/Bach

@@ -0,0 +1,38 @@
+#define Bach_width 51
+#define Bach_height 60
+static unsigned char Bach_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfe,
+   0xf3, 0x07, 0x00, 0xf8, 0x00, 0x80, 0xff, 0xff, 0x1f, 0x00, 0xf8, 0x00,
+   0xe0, 0xff, 0xff, 0x3f, 0x00, 0xf8, 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00,
+   0xf8, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, 0xf8, 0x00, 0xf8, 0xff, 0xff,
+   0xff, 0x01, 0xf8, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x01, 0xf8, 0x00, 0xfe,
+   0xff, 0xff, 0xff, 0x03, 0xf8, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 0xf8,
+   0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0x80, 0xff, 0xff, 0xff, 0xbf,
+   0x07, 0xf8, 0x80, 0xff, 0xff, 0xff, 0x7f, 0x0f, 0xf8, 0x80, 0xff, 0xff,
+   0xff, 0x3f, 0x0f, 0xf8, 0xc0, 0xff, 0xff, 0xff, 0x3f, 0x06, 0xf8, 0xc0,
+   0xff, 0xff, 0xff, 0x3f, 0x0e, 0xf8, 0xc0, 0xff, 0xff, 0xff, 0x7f, 0x1e,
+   0xf8, 0xc0, 0xff, 0xff, 0xff, 0x7f, 0x1c, 0xf8, 0xc0, 0xff, 0xff, 0xff,
+   0x7f, 0x3c, 0xf8, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x3c, 0xf8, 0xc0, 0xff,
+   0xff, 0xf8, 0x0f, 0x38, 0xf8, 0xc0, 0xff, 0xff, 0xc7, 0x23, 0x38, 0xf8,
+   0xe0, 0xff, 0xff, 0xc3, 0x01, 0x38, 0xf8, 0xe0, 0xff, 0xff, 0xf9, 0x03,
+   0x38, 0xf8, 0xe0, 0xff, 0xff, 0xff, 0x3b, 0x18, 0xf8, 0xc0, 0xff, 0xfb,
+   0xff, 0x33, 0x00, 0xf8, 0xc0, 0xff, 0xff, 0xff, 0xf7, 0x30, 0xf8, 0xe0,
+   0xff, 0xfd, 0xff, 0xe7, 0x00, 0xf8, 0xe0, 0xff, 0xfd, 0xff, 0x6f, 0x30,
+   0xf8, 0xc0, 0xff, 0xfc, 0xff, 0x67, 0x00, 0xf8, 0x80, 0xff, 0xfc, 0x7f,
+   0xc0, 0x00, 0xf8, 0xc0, 0xff, 0xf8, 0xff, 0x41, 0x00, 0xf8, 0xc0, 0xff,
+   0xf8, 0xff, 0x03, 0x00, 0xf8, 0x80, 0x7c, 0xf8, 0xff, 0x07, 0x00, 0xf8,
+   0x00, 0x7e, 0xf8, 0xff, 0x43, 0x00, 0xf8, 0x00, 0x7e, 0xf8, 0x0f, 0x00,
+   0x00, 0xf8, 0x00, 0x37, 0xf0, 0xff, 0x07, 0x00, 0xf8, 0x00, 0x63, 0xf0,
+   0xff, 0x01, 0x00, 0xf8, 0x00, 0x27, 0xf0, 0xff, 0x07, 0x00, 0xf8, 0x00,
+   0x06, 0xe0, 0xff, 0x0f, 0x00, 0xf8, 0x00, 0x02, 0x40, 0xff, 0x0f, 0x00,
+   0xf8, 0x00, 0x00, 0x90, 0xf1, 0x07, 0x00, 0xf8, 0x00, 0x00, 0x30, 0xff,
+   0x01, 0x00, 0xf8, 0x00, 0x00, 0xf0, 0x7e, 0x00, 0x00, 0xf8, 0x00, 0x00,
+   0xf0, 0x7b, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf8,
+   0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xe0, 0xff, 0x01,
+   0x00, 0xf8, 0x00, 0x00, 0xe0, 0xff, 0x0f, 0x00, 0xf8, 0x00, 0x00, 0xc0,
+   0xff, 0x0f, 0x00, 0xf8, 0x00, 0x00, 0xc0, 0xff, 0x07, 0x00, 0xf8, 0x00,
+   0x00, 0x80, 0xff, 0x03, 0x00, 0xf8, 0x00, 0x00, 0x80, 0xff, 0x00, 0x00,
+   0xf8, 0x00, 0x00, 0x80, 0xff, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x7f,
+   0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xf8, 0x00, 0x00,
+   0x00, 0x1f, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0xf8};

+ 62 - 0
.twm/Escher

@@ -0,0 +1,62 @@
+#define Escher_width 101
+#define Escher_height 54
+static unsigned char Escher_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+   0x01, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0xc0, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x7e, 0x07, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x80, 0x7f, 0x06, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x06, 0x00, 0x00, 0x00, 0xe0, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x02, 0x00, 0x00, 0x00, 0xe0,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00,
+   0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf, 0x80, 0x7f, 0x00, 0x00,
+   0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xfe, 0xff, 0x0f,
+   0x00, 0x00, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xe0, 0xff, 0xff,
+   0x7f, 0x00, 0x00, 0xe0, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x7f,
+   0x7f, 0xfc, 0x03, 0x00, 0xe0, 0xf8, 0x07, 0x00, 0x00, 0xc0, 0x87, 0xff,
+   0x6f, 0x5f, 0xee, 0x0f, 0x00, 0xe0, 0xf8, 0x1f, 0x00, 0x00, 0xf0, 0xf1,
+   0xff, 0xf9, 0xe9, 0xfc, 0x3e, 0x00, 0xe0, 0xf8, 0x3f, 0x00, 0x00, 0x3c,
+   0xf8, 0xaf, 0xe8, 0x1d, 0xe0, 0x70, 0x00, 0xe0, 0xf8, 0x7f, 0x00, 0x00,
+   0x3e, 0xbf, 0xac, 0x88, 0x1f, 0x00, 0x3e, 0x00, 0xe0, 0xf0, 0x0f, 0x00,
+   0x00, 0x97, 0x3f, 0xac, 0xc2, 0x81, 0x01, 0xbf, 0x03, 0xe0, 0xf0, 0x1f,
+   0x00, 0xc0, 0xe7, 0xa3, 0x00, 0xca, 0x15, 0x80, 0xc7, 0x07, 0xe0, 0xe0,
+   0x1f, 0x00, 0x80, 0xf1, 0x02, 0x4a, 0x88, 0x50, 0x80, 0xe3, 0x0c, 0xe0,
+   0xc0, 0x1f, 0x1c, 0x00, 0x3c, 0x08, 0x28, 0x55, 0x20, 0xc0, 0xf1, 0x3f,
+   0xe0, 0xc0, 0x1f, 0xf0, 0x80, 0x0f, 0x68, 0x51, 0x50, 0xb4, 0xe0, 0xb1,
+   0x7e, 0xe0, 0x80, 0x1f, 0xc0, 0xff, 0x03, 0x80, 0x54, 0x29, 0x00, 0xe8,
+   0xb9, 0xfc, 0xe0, 0x00, 0x3f, 0x82, 0x3f, 0x28, 0x15, 0x00, 0x20, 0x2a,
+   0xe0, 0xb9, 0xe7, 0xe1, 0x00, 0x3e, 0x0a, 0x20, 0x00, 0x00, 0x00, 0x00,
+   0xe0, 0xe2, 0x79, 0xb3, 0xe3, 0x00, 0x3e, 0x80, 0x00, 0x40, 0x08, 0x80,
+   0x40, 0x01, 0xe0, 0xf9, 0xb8, 0xe3, 0x00, 0x3e, 0x01, 0x00, 0x50, 0x08,
+   0x00, 0x08, 0x40, 0xe0, 0xf9, 0xff, 0xe1, 0x00, 0x3e, 0x01, 0x00, 0x00,
+   0x00, 0x50, 0x81, 0xf0, 0xc3, 0xf9, 0xee, 0xe0, 0x00, 0x1e, 0x02, 0x08,
+   0x0a, 0x01, 0x00, 0x20, 0xf0, 0xc7, 0xfb, 0x7f, 0xe2, 0x00, 0x0f, 0x02,
+   0xbc, 0x03, 0x00, 0x0a, 0x00, 0xf0, 0xc1, 0xfb, 0xbf, 0xe3, 0x80, 0x07,
+   0xf0, 0xff, 0xc3, 0x02, 0x80, 0x41, 0xf1, 0x81, 0xf7, 0xf7, 0xe1, 0x80,
+   0x07, 0x3c, 0xc0, 0xbf, 0x5c, 0x09, 0x40, 0xf0, 0x83, 0xff, 0x7f, 0xe0,
+   0xc0, 0x13, 0x00, 0x00, 0xf8, 0x0f, 0x80, 0x92, 0xf0, 0x0f, 0x0f, 0x3e,
+   0xe0, 0xe0, 0x1f, 0x00, 0x00, 0xe3, 0x5f, 0x21, 0x16, 0xe0, 0x2f, 0xfe,
+   0x17, 0xe0, 0xf0, 0x1f, 0x00, 0x80, 0x01, 0xfe, 0x27, 0x0e, 0xe0, 0x27,
+   0xf8, 0x10, 0xe0, 0xf0, 0x07, 0x00, 0x80, 0x1b, 0xf0, 0x07, 0xe8, 0x8a,
+   0x15, 0x02, 0x00, 0xe0, 0xf8, 0x03, 0x00, 0x80, 0x1f, 0x80, 0xff, 0x6a,
+   0x00, 0xc0, 0x01, 0x00, 0xe0, 0xf8, 0x0f, 0x00, 0x80, 0x0f, 0x00, 0xf8,
+   0x3f, 0xfe, 0x7f, 0x00, 0x00, 0xe0, 0xf8, 0x07, 0x00, 0x00, 0x47, 0x00,
+   0x00, 0x1c, 0xfc, 0x0f, 0x00, 0x00, 0xe0, 0xf8, 0x01, 0x00, 0x00, 0x3f,
+   0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf8, 0x00, 0x00, 0x00,
+   0x3e, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00,
+   0x00, 0x1c, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x00, 0xe0, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00, 0xe0,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00,
+   0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00,
+   0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00,
+   0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00,
+   0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+   0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0xe0};

+ 46 - 0
.twm/Linux64

@@ -0,0 +1,46 @@
+#define Linux64_width 64
+#define Linux64_height 64
+static unsigned char Linux64_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+   0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x0f, 0x00, 0x00,
+   0x00, 0x00, 0xf8, 0x1f, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01,
+   0xc0, 0xff, 0x00, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0xfe, 0x01, 0x00,
+   0x00, 0xc0, 0x1f, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00,
+   0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xc0, 0x1f, 0x00,
+   0x00, 0xf8, 0x01, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0xfc, 0x01, 0x00,
+   0x00, 0x80, 0x7f, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
+   0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x00,
+   0x00, 0x00, 0xfe, 0x01, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03,
+   0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0xc0, 0x7f, 0x00, 0x00,
+   0x00, 0x00, 0xfc, 0x07, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07,
+   0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0xe0, 0x3f, 0x00, 0x00,
+   0x00, 0x00, 0xf8, 0x0f, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f,
+   0xf0, 0x3f, 0x00, 0x00, 0xe0, 0x01, 0xf0, 0x1f, 0xf0, 0x3f, 0xe0, 0x00,
+   0xf8, 0x01, 0xf0, 0x1f, 0xf0, 0x3f, 0xf0, 0x01, 0xfc, 0x03, 0xf0, 0x1f,
+   0xf0, 0x3f, 0xf8, 0x03, 0xfe, 0x03, 0xf0, 0x1f, 0xf8, 0x7f, 0x18, 0x07,
+   0x0f, 0x07, 0xf0, 0x3f, 0xf8, 0x7f, 0x08, 0x07, 0x47, 0x0e, 0xf0, 0x3f,
+   0xf8, 0x7f, 0x08, 0x06, 0x07, 0x0e, 0xf0, 0x3f, 0xf8, 0x7f, 0x88, 0x06,
+   0x07, 0x0e, 0xf0, 0x3f, 0xf8, 0x7f, 0x08, 0x06, 0x06, 0x0e, 0xf0, 0x3f,
+   0xf8, 0x7f, 0x08, 0xfe, 0x04, 0x0e, 0xf0, 0x3f, 0xf8, 0x7f, 0x18, 0x7c,
+   0x06, 0x0e, 0xf0, 0x3f, 0xf8, 0xff, 0x30, 0xff, 0x9f, 0x07, 0xf0, 0x3f,
+   0xf8, 0xff, 0x90, 0xff, 0x7f, 0x03, 0xf0, 0x3f, 0xf0, 0xff, 0xc0, 0xff,
+   0xff, 0x03, 0xe0, 0x1f, 0xf0, 0xff, 0xc0, 0xff, 0xff, 0x07, 0xe0, 0x1f,
+   0xf0, 0xff, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0x1f, 0xf0, 0xff, 0xe0, 0xff,
+   0x7f, 0x06, 0xe0, 0x1f, 0xe0, 0xff, 0xe0, 0xff, 0x9f, 0x07, 0xe0, 0x0f,
+   0xe0, 0xff, 0xe0, 0xff, 0xcf, 0x07, 0xc0, 0x0f, 0xe0, 0xff, 0xc1, 0xff,
+   0xf3, 0x01, 0xc0, 0x0f, 0xc0, 0xff, 0x01, 0x7f, 0x7c, 0x0c, 0xc0, 0x07,
+   0xc0, 0xff, 0x19, 0x80, 0x9f, 0x0f, 0x80, 0x07, 0x80, 0xff, 0x39, 0xfc,
+   0xc7, 0x0f, 0x00, 0x03, 0x80, 0xff, 0x78, 0x78, 0xf0, 0x1f, 0x00, 0x03,
+   0x00, 0x7f, 0xf8, 0x00, 0xf8, 0x1f, 0x80, 0x01, 0x00, 0x3e, 0xf8, 0x03,
+   0xfe, 0x3f, 0x80, 0x01, 0x00, 0x3e, 0xf8, 0xff, 0xff, 0x3f, 0xc0, 0x00,
+   0x00, 0x1c, 0xf8, 0xff, 0xff, 0x7f, 0x60, 0x00, 0x00, 0x18, 0xfc, 0xff,
+   0xff, 0x7f, 0x30, 0x00, 0x00, 0x30, 0xfc, 0xff, 0xff, 0xff, 0x18, 0x00,
+   0x00, 0x60, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0xc0, 0xff, 0xff,
+   0xff, 0xff, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
+   0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
+   0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x0f, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+   0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

+ 14 - 0
.twm/am

@@ -0,0 +1,14 @@
+#define am_width 32
+#define am_height 32
+static unsigned char am_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
+   0x63, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x7f, 0x1f, 0x00, 0x7c,
+   0x63, 0x3f, 0x00, 0x7e, 0x63, 0x7f, 0x00, 0x7f, 0x63, 0xff, 0x80, 0x7f,
+   0x63, 0xff, 0xc1, 0x7f, 0x00, 0xff, 0xe3, 0x7f, 0x00, 0xff, 0xf7, 0x7f,
+   0x00, 0xef, 0xff, 0x7b, 0x00, 0xcf, 0xff, 0x79, 0x00, 0x8f, 0xff, 0x78,
+   0x00, 0x0f, 0x7f, 0x78, 0x00, 0x0f, 0x3e, 0x78, 0x00, 0x0f, 0x1c, 0x78,
+   0x00, 0x0f, 0x08, 0x78, 0x00, 0x0f, 0x00, 0x78, 0x00, 0x0f, 0x00, 0x78,
+   0x00, 0x0f, 0x00, 0x78, 0x00, 0x0f, 0x00, 0x78, 0x00, 0x0f, 0x00, 0x78,
+   0x00, 0x0e, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

+ 52 - 0
.twm/amule

@@ -0,0 +1,52 @@
+#define Untitled_width 57
+#define Untitled_height 73
+static unsigned char Untitled_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+   0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xf0,
+   0x07, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00,
+   0x00, 0x1f, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xf8,
+   0x03, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00,
+   0x00, 0xfc, 0x01, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc,
+   0x03, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x4f, 0xfe, 0x03, 0x00, 0x00, 0x00,
+   0x00, 0xf8, 0xdf, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x9f, 0xff,
+   0x01, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+   0x00, 0xe0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff,
+   0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+   0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x9f,
+   0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x1f, 0x03, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x8e, 0x0f, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0f,
+   0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x3f, 0x06, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0xc6, 0x7e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x3e,
+   0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0x1f, 0x0e, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x0e, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xff,
+   0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
+   0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+   0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
+   0x00, 0x80, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
+   0xff, 0xff, 0x01, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
+   0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xc0, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
+   0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x80, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0x01, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
+   0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x80, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0x01, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x01, 0x00,
+   0x00, 0x1f, 0xfe, 0xff, 0xff, 0x40, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
+   0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xfc, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0x7f, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
+   0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
+   0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0x07, 0xff,
+   0xfb, 0xff, 0x7f, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0xfe, 0x3f, 0x00,
+   0xf0, 0x01, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

+ 5 - 0
.twm/close

@@ -0,0 +1,5 @@
+#define close_width 11
+#define close_height 11
+static unsigned char close_bits[] = {
+   0x00, 0x00, 0x06, 0x03, 0x8e, 0x03, 0xdc, 0x01, 0xf8, 0x00, 0x70, 0x00,
+   0xf8, 0x00, 0xdc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x00, 0x00};

+ 14 - 0
.twm/ff

@@ -0,0 +1,14 @@
+#define ff_width 32
+#define ff_height 32
+static unsigned char ff_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+   0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1f,
+   0xe0, 0xff, 0x3f, 0x1f, 0xf0, 0xff, 0x3f, 0x03, 0xf0, 0xff, 0x3f, 0x1f,
+   0xf0, 0x00, 0x00, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+   0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+   0xf0, 0xff, 0x0f, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0xf0, 0xff, 0x0f, 0x00,
+   0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+   0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+   0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+   0xf0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

+ 5 - 0
.twm/fullsize

@@ -0,0 +1,5 @@
+#define fullsize_width 11
+#define fullsize_height 11
+static unsigned char fullsize_bits[] = {
+   0x00, 0x00, 0xfc, 0x01, 0xfe, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+   0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0xfc, 0x01, 0x00, 0x00};

+ 5 - 0
.twm/iconify

@@ -0,0 +1,5 @@
+#define icon_width 11
+#define icon_height 11
+static unsigned char icon_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x02, 0x02, 0x02, 0x02,
+   0xfe, 0x03, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

+ 28 - 0
.twm/moose

@@ -0,0 +1,28 @@
+#define moose_width 45
+#define moose_height 49
+static unsigned char moose_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00,
+   0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00,
+   0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00,
+   0x00, 0x1f, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0x00, 0x00,
+   0x00, 0x07, 0xf1, 0x03, 0x00, 0x00, 0x00, 0x87, 0x71, 0x00, 0x00, 0x00,
+   0x00, 0xb7, 0x70, 0x00, 0x00, 0x00, 0x00, 0x57, 0x70, 0x00, 0x00, 0x00,
+   0x00, 0xe7, 0x71, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x71, 0x00, 0x00, 0x00,
+   0x00, 0x3f, 0x78, 0x00, 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00,
+   0xc0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00,
+   0xf8, 0xff, 0xf1, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0xf0, 0x51, 0x00, 0x00,
+   0xbe, 0x3f, 0xe0, 0xff, 0x03, 0x00, 0x3e, 0x3f, 0xc0, 0xff, 0x07, 0x00,
+   0x1e, 0x3d, 0xc0, 0xff, 0x0f, 0x00, 0x9e, 0x3c, 0xc0, 0xff, 0x1f, 0x08,
+   0x5e, 0x3e, 0xc0, 0xff, 0xff, 0x07, 0x7c, 0x3e, 0xe0, 0xff, 0xff, 0x01,
+   0xf8, 0x3f, 0xf0, 0xff, 0x7f, 0x00, 0xf0, 0x1f, 0xf8, 0xff, 0x3f, 0x00,
+   0xe0, 0x0f, 0xff, 0xff, 0x3f, 0x00, 0x80, 0x87, 0xff, 0xff, 0x1f, 0x00,
+   0x00, 0xc0, 0xe3, 0xff, 0x1f, 0x00, 0x00, 0xc0, 0xfb, 0xff, 0x1f, 0x00,
+   0x00, 0xc0, 0x7d, 0xf8, 0x0f, 0x00, 0x00, 0xe0, 0x3c, 0xf8, 0x07, 0x00,
+   0x00, 0xf8, 0x0c, 0xf8, 0x07, 0x00, 0x00, 0xfc, 0x1c, 0x98, 0x03, 0x00,
+   0x00, 0xdc, 0x1c, 0x98, 0x03, 0x00, 0x00, 0xf8, 0x3c, 0x38, 0x07, 0x00,
+   0x00, 0x70, 0x3c, 0x78, 0x1f, 0x00, 0x00, 0x00, 0x6c, 0xf8, 0xfe, 0x00,
+   0x00, 0x00, 0x6e, 0xf0, 0xfd, 0x00, 0x00, 0x00, 0x3e, 0xb0, 0xfb, 0x00,
+   0x00, 0x00, 0x0c, 0xe0, 0x79, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

+ 14 - 0
.twm/mozilla

@@ -0,0 +1,14 @@
+#define mozilla_width 32
+#define mozilla_height 32
+static unsigned char mozilla_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x3f, 0x02, 0xf0, 0xff, 0x7f,
+   0x01, 0xe2, 0xff, 0xff, 0xd9, 0xc4, 0xff, 0xff, 0xd9, 0x88, 0xff, 0xff,
+   0x5b, 0x16, 0xff, 0xff, 0x2f, 0x76, 0xfc, 0xff, 0x4f, 0xe4, 0xe0, 0xff,
+   0x19, 0xff, 0x87, 0xff, 0x31, 0xf8, 0x1f, 0xfe, 0xe3, 0xff, 0x7f, 0xf8,
+   0x83, 0xff, 0xff, 0xe1, 0x07, 0xff, 0xff, 0xc7, 0x0d, 0xfe, 0xff, 0x87,
+   0x0d, 0xfc, 0xff, 0x83, 0x09, 0xf0, 0xff, 0x81, 0x01, 0xe0, 0xff, 0x81,
+   0x01, 0xc0, 0xff, 0x93, 0x01, 0x00, 0xff, 0xb3, 0x01, 0x00, 0xfc, 0xbf,
+   0x01, 0x20, 0xe0, 0xbf, 0x03, 0x00, 0x00, 0x9c, 0x07, 0x00, 0x04, 0x80,
+   0x1f, 0x00, 0x18, 0x80, 0xff, 0x03, 0x40, 0xc1, 0xff, 0x3b, 0x00, 0xc0,
+   0x3f, 0xe0, 0x03, 0xe0, 0x01, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x1c, 0xf8,
+   0x02, 0x80, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f};

+ 5 - 0
.twm/resize

@@ -0,0 +1,5 @@
+#define resize_width 11
+#define resize_height 11
+static unsigned char resize_bits[] = {
+   0x00, 0x00, 0xfc, 0x00, 0x02, 0x01, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03,
+   0x02, 0x03, 0x02, 0x03, 0xfc, 0x03, 0xf8, 0x01, 0x00, 0x00};

+ 27 - 0
.twm/torrent

@@ -0,0 +1,27 @@
+#define torrent_width 48
+#define torrent_height 48
+static unsigned char torrent_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00,
+   0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0f,
+   0xe0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0f,
+   0x80, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01,
+   0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07,
+   0xe0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07,
+   0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01,
+   0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

+ 14 - 0
.twm/tv

@@ -0,0 +1,14 @@
+#define Untitled_width 32
+#define Untitled_height 32
+static unsigned char Untitled_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x00,
+   0x00, 0x36, 0x3e, 0x00, 0x00, 0x32, 0x33, 0x00, 0x00, 0x26, 0x1b, 0x00,
+   0x00, 0x6c, 0x19, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00,
+   0x80, 0xff, 0xff, 0x00, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0x01, 0xe0, 0x07,
+   0xe0, 0x00, 0xc0, 0x07, 0xe0, 0x0c, 0xc6, 0x07, 0xe0, 0x0c, 0xc6, 0x07,
+   0xe0, 0x00, 0xc0, 0x07, 0xe0, 0x00, 0xc0, 0x07, 0xe0, 0x00, 0xc0, 0x07,
+   0xe0, 0xf0, 0xc3, 0x07, 0xe0, 0xe0, 0xc1, 0x07, 0xe0, 0x00, 0x20, 0x06,
+   0xe0, 0x01, 0x20, 0x06, 0xe0, 0xff, 0x3f, 0x06, 0xe0, 0xff, 0xff, 0x07,
+   0xc0, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0x00, 0x00, 0x03, 0x20, 0x00,
+   0x00, 0x03, 0x60, 0x00, 0x80, 0x03, 0x60, 0x00, 0x00, 0x01, 0xc0, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

+ 14 - 0
.twm/xlogo32

@@ -0,0 +1,14 @@
+#define xlogo32_width 32
+#define xlogo32_height 32
+static unsigned char xlogo32_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0xfc, 0x03, 0x00, 0x20, 0xf8, 0x07, 0x00, 0x30, 0xf8, 0x07, 0x00, 0x18,
+   0xf0, 0x0f, 0x00, 0x0c, 0xe0, 0x1f, 0x00, 0x06, 0xc0, 0x3f, 0x00, 0x06,
+   0xc0, 0x3f, 0x00, 0x03, 0x80, 0x7f, 0x80, 0x01, 0x00, 0xff, 0xc0, 0x00,
+   0x00, 0xfe, 0x61, 0x00, 0x00, 0xfe, 0x31, 0x00, 0x00, 0xfc, 0x33, 0x00,
+   0x00, 0xf8, 0x1b, 0x00, 0x00, 0xf0, 0x0d, 0x00, 0x00, 0xf0, 0x0e, 0x00,
+   0x00, 0x60, 0x1f, 0x00, 0x00, 0xb0, 0x3f, 0x00, 0x00, 0x98, 0x7f, 0x00,
+   0x00, 0x98, 0x7f, 0x00, 0x00, 0x0c, 0xff, 0x00, 0x00, 0x06, 0xfe, 0x01,
+   0x00, 0x03, 0xfc, 0x03, 0x80, 0x01, 0xfc, 0x03, 0xc0, 0x00, 0xf8, 0x07,
+   0xc0, 0x00, 0xf0, 0x0f, 0x60, 0x00, 0xe0, 0x1f, 0x30, 0x00, 0xe0, 0x1f,
+   0x18, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00};

+ 140 - 0
.twmrc

@@ -0,0 +1,140 @@
+#---------------------------------
+# CPI   # PROJ. : twmrc
+#       # FILE  : .twmrc
+#   +   # VER.  : 20170828.0718UTC
+#    +  # EMAIL : hal@clockworkpi.com
+#  +++  # HOST  : clockworkpi.com
+#---------------------------------
+
+NoGrabServer
+RestartPreviousState
+DecorateTransients
+RandomPlacement
+BorderWidth 1 
+NoHighlight
+OpaqueMove
+MenuBorderWidth 1
+NoMenuShadows
+
+NoDefaults
+LeftTitleButton "~/launcher/.twm/close" = f.delete
+RightTitleButton "~/launcher/.twm/iconify" = f.iconify
+RightTitleButton "~/launcher/.twm/resize" = f.resize
+RightTitleButton "~/launcher/.twm/fullsize" = f.fullzoom
+
+TitleFont "-adobe-helvetica-bold-r-normal--*-100-*-*-*-*-*-*"
+ResizeFont "-adobe-helvetica-bold-r-normal--*-100-*-*-*-*-*-*"
+MenuFont "-misc-fixed-medium-r-semicondensed-*-*-120-*-*-c-*-iso8859-8"
+IconFont "-adobe-helvetica-bold-r-normal--*-100-*-*-*-*-*-*"
+IconManagerFont "-adobe-helvetica-bold-r-normal--*-100-*-*-*"
+
+Color
+{
+   BorderColor "grey30"
+   DefaultBackground "rgb:5/5/5"
+   DefaultForeground "gray80"
+   TitleBackground "rgb:5/5/5"
+   TitleForeground "gray80"
+   MenuBackground "rgb:5/5/5"
+   MenuForeground "gray80"
+   MenuTitleBackground "gray80"
+   MenuTitleForeground "rgb:5/5/5"
+   MenuBorderColor "gray60"
+   IconBackground "rgb:4/4/4"
+   IconForeground "gray80"
+   IconBorderColor "gray70"
+   IconManagerBackground "rgb:5/5/5"
+   IconManagerForeground "gray80"
+}
+
+Cursors
+{
+   Menu "hand2"
+}
+
+ForceIcons
+Icons
+{
+   "Chrome" "~/launcher/.twm/chrome.xbm"
+   "xterm" "~/launcher/.twm/xlogo32"
+}
+
+
+MoveDelta 3
+Function "move-or-lower" { f.move f.deltastop f.lower }
+Function "move-or-raise" { f.move f.deltastop f.raise }
+Function "move-or-iconify" { f.move f.deltastop f.iconify }
+
+
+Button1 = : root : f.menu "main"
+Button3 = : root : f.menu "exec"
+Button1 = m : window|icon : f.function "move-or-raise"
+Button2 = m : window|icon : f.iconify
+Button3 = m : window|icon : f.resize
+Button1 = : title : f.function "move-or-raise"
+Button2 = : title : f.raiselower
+Button1 = : icon : f.function "move-or-iconify"
+Button2 = : icon : f.iconify
+Button1 = : iconmgr : f.iconify
+Button2 = : iconmgr : f.iconify
+
+
+NoTitle
+{
+   "gkrellm"
+}
+
+
+menu "main"
+{
+   "CLOCKWORKPI" f.title
+   "Raise" f.raise
+   "Lower" f.lower
+   "Focus" f.focus
+   "Unfocus" f.unfocus
+   "-------------" f.nop
+   "Show Iconmgr" f.showiconmgr
+   "Hide Iconmgr" f.hideiconmgr
+   "Kill" f.destroy
+   "-------------" f.nop
+   "Restart" f.restart
+   "Exit" ("gray80":"#773333") f.menu "exit"
+}
+
+menu "exit"
+{
+   "Are you sure ?" ("gray80":"#773333") f.title
+   "No" f.nop
+   "Yes" f.quit
+}
+
+menu "exec"
+{
+   ":: Applications ::" f.title
+   "Xterm"  ("gray80":"#334455") f.exec "exec /usr/bin/xterm &"
+   "Xterm Orange"   ("gray80":"#aa5522") f.exec "exec /usr/bin/xterm  -fg '#dc8700' &"
+   "Xmag"   f.exec "exec /usr/bin/xmag &"
+   "Gkrellm"   f.exec "/usr/bin/gkrellm &"
+   "XClock" f.exec "exec /usr/bin/xclock &"
+   "XFig"   f.exec "exec /usr/bin/xfig -nosplash &"
+   "Wicd client"  f.exec "exec /usr/bin/wicd-client -n &"
+   "xpdf"  f.exec "exec /usr/bin/xpdf &"
+}
+
+WindowRing
+{
+   "xterm"
+   "xpdf"
+}
+
+"r" = m | c: all : f.exec "exec /usr/bin/xterm -fg '#dc8700' &"
+"s" = m | c: all : f.exec "exec /usr/bin/alsamixergui &"
+"t" = m | c: all : f.exec "exec /usr/bin/xterm +sb &"
+"w" = m | c: all : f.exec "exec /usr/bin/wicd-client -n &"
+
+"i" = m | s: all : f.iconify
+"x" = m | s: all : f.delete
+
+"F12" = m : all : f.fullzoom
+"Tab" = m : all : f.warpring "next"
+

+ 25 - 0
.xinitrc

@@ -0,0 +1,25 @@
+session=${1:-gameshell}
+
+case $session in
+hdmi )
+	exec ~/launcher/aria2c --conf-path=/home/cpi/launcher/aria2.conf &
+	feh --bg-center ~/launcher/sys.py/gameshell/wallpaper/desktopbg.jpg
+        cd ~/launcher/sys.py/ ; python appinstaller.py > /tmp/appinstaller.log & cd ~/
+	exec ~/launcher/load.sh &
+	exec ~/launcher/sys.py/gsnotify/gsnotify-arm daemon &
+	exec /usr/bin/twm -f ~/launcher/.twmrc
+	#exec ~/launcher/dwm-mod
+	;;
+gameshell )
+	exec ~/launcher/aria2c --conf-path=/home/cpi/launcher/aria2.conf & 
+	feh --bg-center ~/launcher/sys.py/gameshell/wallpaper/loading.png
+        cd ~/launcher/sys.py/ ; python appinstaller.py > /tmp/appinstaller.log  & cd ~/
+	exec ~/launcher/load.sh &
+	exec ~/launcher/sys.py/gsnotify/gsnotify-arm &
+	#exec awesome -c ~/launcher/awesome/rc.lua
+	exec ~/launcher/dwm-mod -w
+	;;
+*) 
+	exec $1;;
+esac
+

+ 7 - 0
.xorg.conf

@@ -0,0 +1,7 @@
+Section "Device"
+        Identifier      "Allwinner A10/A13 FBDEV"
+        Driver          "fbturbo"
+        Option          "fbdev" "/dev/fb0"
+
+        Option          "SwapbuffersWait" "true"
+EndSection

+ 7 - 0
.xorg_lima.conf

@@ -0,0 +1,7 @@
+Section "Device"
+        Identifier      "Allwinner A10/A13 FBDEV"
+        Driver          "modesetting"
+        Option          "fbdev" "/dev/fb0"
+
+        Option          "SwapbuffersWait" "true"
+EndSection

+ 3 - 0
CPI/version.json

@@ -0,0 +1,3 @@
+{
+  "gitversion":""
+}

+ 674 - 0
LICENSE

@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.

+ 285 - 0
Menu/GameShell/10_Settings/.Airplane.deot/__init__.py

@@ -0,0 +1,285 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+#import math
+import  commands
+
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+#import gobject
+#from wicd import misc 
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.icon_item  import IconItem
+from UI.multi_icon_item import MultiIconItem
+from UI.lang_manager import MyLangManager
+from UI.skin_manager import MySkinManager
+from UI.multilabel import MultiLabel
+
+class AirplanePage(Page):
+    _FootMsg =  ["Nav","","Rescue","Back","Toggle"]
+    _MyList = []
+    _ListFontObj = MyLangManager.TrFont("varela13")
+    
+    _AList = {}
+
+    _Scrolled = 0
+    
+    _BGwidth = 320
+    _BGheight = 240-24-20
+
+    _DrawOnce = False
+    _Scroller = None
+
+    _EasingDur = 30
+
+    _airwire_y = 0
+    _dialog_index = 0
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+
+    def GenList(self):
+        
+        self._MyList = []
+        
+        
+            
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._HWND = self._Screen._CanvasHWND
+                self._CanvasHWND = pygame.Surface( (self._Screen._Width,self._BGheight) )
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+
+        """
+        airwire = IconItem()
+        airwire._ImgSurf = MyIconPool._Icons["airwire"]
+        airwire._MyType = ICON_TYPES["STAT"]
+        airwire._Parent = self
+        airwire.Adjust(0,0,5,43,0)
+        self._Icons["airwire"] = airwire
+
+        GS = IconItem()
+        GS._ImgSurf = MyIconPool._Icons["GS"]
+        GS._MyType = ICON_TYPES["STAT"]
+        GS._Parent = self
+        GS.Adjust(0,0,72,95,0)
+        self._Icons["GS"] = GS
+        """
+
+        DialogBoxs = MultiIconItem()
+        DialogBoxs._ImgSurf = MyIconPool._Icons["DialogBoxs"]
+        DialogBoxs._MyType = ICON_TYPES["STAT"]
+        DialogBoxs._Parent = self
+        DialogBoxs._IconWidth = 180
+        DialogBoxs._IconHeight = 80
+        DialogBoxs.Adjust(0,0,180,320,0)
+        self._Icons["DialogBoxs"] = DialogBoxs
+
+        
+        """
+        bgpng = MultiIconItem()
+        bgpng._ImgSurf = MyIconPool._Icons["about_bg"]
+        bgpng._MyType = ICON_TYPES["STAT"]
+        bgpng._Parent = self
+        bgpng.Adjust(0,0,self._BGwidth,self._BGheight,0)
+        self._Icons["bg"] = bgpng
+        """
+        
+        
+        self.GenList()
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        self._Scroller.SetCanvasHWND(self._HWND)
+        
+        self.OnLoadCb()
+        
+    def ScrollDown(self):
+        dis = 10
+        if abs(self._Scrolled) <  (self._BGheight - self._Height)/2 + 0:
+            self._PosY -= dis
+            self._Scrolled -= dis
+        
+    def ScrollUp(self):
+        dis = 10
+        if self._PosY < 0:
+            self._PosY += dis
+            self._Scrolled += dis
+
+    def ToggleModeAni(self): ## with animation
+        out = commands.getstatusoutput('sudo rfkill list | grep yes | cut -d " " -f3')
+        if "yes" in out[1]:
+            data = self.EasingData(0,43)
+            for _,v in enumerate(data):
+                self._airwire_y -= v
+                self._dialog_index = 2
+                pygame.time.delay(40)
+
+                self._Screen.Draw()
+                self._Screen.SwapAndShow()
+                
+            commands.getstatusoutput("sudo rfkill unblock all")
+            self._Screen._TitleBar._InAirPlaneMode = False
+
+        else:
+            data = self.EasingData(0,43)
+            data.reverse()
+            for _,v in enumerate(data):
+                self._airwire_y += v
+                self._dialog_index = 3
+                pygame.time.delay(40)
+                self._Screen.Draw()
+                self._Screen.SwapAndShow()
+
+            commands.getstatusoutput("sudo rfkill block all")
+            self._Screen._TitleBar._InAirPlaneMode = True
+
+        
+    def ToggleMode(self):
+        out = commands.getstatusoutput('sudo rfkill list | grep yes | cut -d " " -f3')
+        print out
+        if "yes" in out[1]:
+            self._Screen._MsgBox.SetText("TurningOn")
+            self._Screen._MsgBox.Draw()
+            commands.getstatusoutput("sudo rfkill unblock all")
+            self._Screen._TitleBar._InAirPlaneMode = False
+        
+        else:
+            self._Screen._MsgBox.SetText("TurningOff")
+            self._Screen._MsgBox.Draw()
+            commands.getstatusoutput("sudo rfkill block all")
+            self._Screen._TitleBar._InAirPlaneMode = True
+    
+    def UnBlockAll(self):
+        self._Screen._MsgBox.SetText("TurningOn")
+        self._Screen._MsgBox.Draw()
+        commands.getstatusoutput("sudo rfkill unblock all")
+        self._Screen._TitleBar._InAirPlaneMode = False
+    
+        
+    def OnLoadCb(self):
+        self._Scrolled = 0
+        self._PosY = 0
+        self._DrawOnce = False
+        out = commands.getstatusoutput('sudo rfkill list | grep yes | cut -d " " -f3')
+        if "yes" in out[1]:
+            self._Screen._TitleBar._InAirPlaneMode = True
+            self._airwire_y = 50+43
+            self._dialog_index = 1
+        else:
+            self._airwire_y = 50
+            self._dialog_index = 0
+            self._Screen._TitleBar._InAirPlaneMode = False
+        
+        
+    def OnReturnBackCb(self):
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+            self.ToggleModeAni()
+            """
+            self.ToggleMode()
+            self._Screen.SwapAndShow()
+            
+            pygame.time.delay(1000)
+            
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            """
+        """
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        """
+        
+        if event.key == CurKeys["X"]:
+            self.UnBlockAll()
+            self._Screen.SwapAndShow()
+            pygame.time.delay(1000)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow() 
+        
+            
+    def Draw(self):
+        self.ClearCanvas()
+
+        self._Icons["DialogBoxs"].NewCoord(70,58)        
+        #self._Icons["airwire"].NewCoord(80,self._airwire_y)
+        
+        self._Icons["DialogBoxs"]._IconIndex = self._dialog_index
+        
+        self._Icons["DialogBoxs"].DrawTopLeft()
+        #self._Icons["airwire"].Draw()
+
+        #self._Icons["GS"].NewCoord(98,118)
+        #self._Icons["GS"].Draw()
+
+        self.DrawCross(10,10)
+        self.DrawCross(self._Screen._Width-20,10)
+        self.DrawCross(10,self._Screen._Height-20)
+        self.DrawCross(self._Screen._Width-20,self._Screen._Height-20)
+        
+        if self._HWND != None:
+            self._HWND.fill(MySkinManager.GiveColor("White"))
+            
+            self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) )
+            
+#            self._Scroller.UpdateSize(self._BGheight,abs(self._Scrolled)*3)
+#            self._Scroller.Draw()
+        
+        
+
+
+class APIOBJ(object):
+
+    _Page = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = AirplanePage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="Airplane Mode"
+        self._Page.Init()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 0 - 0
Menu/GameShell/10_Settings/.Brightness.stock/Icon\r


+ 17 - 0
Menu/GameShell/10_Settings/.Brightness.stock/__init__.py

@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*- 
+
+## local UI import
+import pages
+import myvars
+
+def Init(main_screen):
+    pages.InitBrightnessPage(main_screen)
+
+def API(main_screen):
+    
+    if main_screen !=None:
+        main_screen.PushCurPage()
+        main_screen.SetCurPage(myvars.BrightnessPage)
+        main_screen.Draw()
+        main_screen.SwapAndShow()
+        

+ 186 - 0
Menu/GameShell/10_Settings/.Brightness.stock/brightness_page.py

@@ -0,0 +1,186 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+
+
+#import math
+
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.icon_item import IconItem
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, IsKeyMenuOrB
+from UI.slider     import Slider
+from UI.icon_pool  import MyIconPool
+from UI.multi_icon_item import MultiIconItem
+from config import BackLight
+import myvars
+
+class BSlider(Slider):
+
+    
+    OnChangeCB = None
+    _BGpng = None
+    _BGwidth = 179
+    _BGheight = 153
+
+    _NeedleSurf = None
+    _Scale      = None
+    _Parent     = None
+    _Icons      = {}
+    
+    def __init__(self):
+        Slider.__init__(self)
+        self._Icons = {}
+    def Init(self):
+        self._Width = self._Parent._Width
+        self._Height = self._Parent._Height
+        
+        bgpng = IconItem()
+        bgpng._ImgSurf = MyIconPool.GiveIconSurface("light")
+        bgpng._MyType = ICON_TYPES["STAT"]
+        bgpng._Parent = self
+        bgpng.Adjust(0,0,self._BGwidth,self._BGheight,0)
+        self._Icons["bg"] = bgpng
+        ##self._NeedleSurf = pygame.Surface( (38,12),pygame.SRCALPHA )
+        
+        scale = MultiIconItem()
+        scale._MyType = ICON_TYPES["STAT"]
+        scale._Parent = self
+        scale._ImgSurf = MyIconPool.GiveIconSurface("scale")
+        scale._IconWidth = 82
+        scale._IconHeight = 63
+        scale.Adjust(0,0,82,63,0)
+        self._Icons["scale"] = scale
+
+    def SetValue(self,brt):
+        self._Value = brt
+        
+    def Further(self):
+        self._Value+=1
+        if self._Value > 9:
+            self._Value = 9
+            
+        if self.OnChangeCB != None:
+            if callable(self.OnChangeCB):
+                self.OnChangeCB(self._Value)
+                    
+    def StepBack(self):
+        self._Value-=1
+
+        if self._Value < 1:
+            self._Value = 1
+
+        if self.OnChangeCB != None:
+            if callable(self.OnChangeCB):
+                self.OnChangeCB(self._Value)
+    
+    def Draw(self):
+
+        self._Icons["bg"].NewCoord(self._Width/2,self._Height/2 +11 )
+        self._Icons["bg"].Draw()
+
+        self._Icons["scale"].NewCoord(self._Width/2,self._Height/2 )
+
+        icon_idx = self._Value - 1
+        if icon_idx < 0:
+            icon_idx = 0
+        
+        self._Icons["scale"]._IconIndex = icon_idx
+        self._Icons["scale"].Draw()
+        """
+        pygame.draw.line(self._CanvasHWND,(255,0,0), (posx,self._PosY),(self._Width,self._PosY),3) ## range line
+        pygame.draw.line(self._CanvasHWND,(0,0,255), (self._PosX,self._PosY),(posx,self._PosY),3) ## range line
+        
+        pygame.draw.circle(self._CanvasHWND,(255,255,255),( posx, self._PosY),7,0)        
+        pygame.draw.circle(self._CanvasHWND,(0,0,0)      ,( posx, self._PosY),7,1)## outer border
+        """
+        
+        
+        
+class BrightnessPage(Page):
+
+    _MySlider = None
+    _FootMsg = ["Nav","","","Back","Enter"]
+
+    
+    def Init(self):
+        self._CanvasHWND = self._Screen._CanvasHWND
+        self._Width =  self._Screen._Width
+        self._Height = self._Screen._Height
+        
+        self._MySlider = BSlider()
+#        self._MySlider._Width = Width - 20
+#        self._MySlider._Height = 30
+#        self._MySlider._PosX  = (self._Width - self._MySlider._Width)/2
+#        self._MySlider._PosY  = 40
+        self._MySlider._Parent = self
+        self._MySlider.SetCanvasHWND(self._CanvasHWND)
+        self._MySlider.OnChangeCB = self.WhenSliderDrag
+        self._MySlider.Init()
+
+        brt  = self.ReadBackLight()
+        
+        self._MySlider.SetValue( brt)
+
+    
+    def ReadBackLight(self):
+        try:
+            f = open(BackLight)
+        except IOError:
+            return 0
+        else:
+            with f:
+                content = f.readlines()
+                content = [x.strip() for x in content]
+                return int(content[0])
+
+        return 0
+
+    def OnLoadCb(self):
+         brt  = self.ReadBackLight()
+         
+         self._MySlider.SetValue( brt)
+         
+    def SetBackLight(self,newbrt):
+        try:
+            f = open(BackLight,'w')
+        except IOError:
+            print("Open write %s failed %d" % (BackLight,newbrt))
+            return False
+        else:
+            with f:
+                f.write(str(newbrt))
+                return True
+        
+    def WhenSliderDrag(self,value): ##value 
+        self.SetBackLight(value)
+        
+    def KeyDown(self,event):
+        
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Right"]:
+            self._MySlider.Further()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if event.key == CurKeys["Left"]:
+            self._MySlider.StepBack()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+    def Draw(self):
+        self.ClearCanvas()
+        
+        self._MySlider.Draw()
+
+        
+
+
+    

+ 6 - 0
Menu/GameShell/10_Settings/.Brightness.stock/myvars.py

@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*- 
+
+import os
+import sys
+
+SoundPage = None

+ 13 - 0
Menu/GameShell/10_Settings/.Brightness.stock/pages.py

@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*- 
+
+from brightness_page import BrightnessPage
+
+import myvars
+
+def InitBrightnessPage(main_screen):
+
+    myvars.BrightnessPage = BrightnessPage()
+    
+    myvars.BrightnessPage._Screen = main_screen
+    myvars.BrightnessPage._Name = "Brightness"
+    myvars.BrightnessPage.Init()

+ 55 - 0
Menu/GameShell/10_Settings/.LauncherGo.stock/__init__.py

@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*- 
+import os
+import pygame
+#import math
+#mport subprocess
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+
+## local UI import
+from UI.keys_def     import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.util_funcs import ArmSystem
+from UI.lang_manager import MyLangManager
+from UI.confirm_page import ConfirmPage
+
+class SwitchToLauncherGoConfirmPage(ConfirmPage):
+            
+    def KeyDown(self,event):
+        
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+            self._Screen._MsgBox.SetText("Rebooting to LauncherGo")
+            self._Screen._MsgBox.Draw()
+            self._Screen.SwapAndShow()
+            pygame.time.delay(300)
+            ArmSystem("sed -i s/launcher/launchergo/g ~/.bashrc" )
+            ArmSystem("sudo reboot")  
+            
+            
+class APIOBJ(object):
+
+    _Page = None
+    
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = SwitchToLauncherGoConfirmPage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="Switch To LauncherGo"
+        self._Page.Init()    
+
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()        
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)

+ 0 - 0
Menu/GameShell/10_Settings/.Sound.stock/Icon\r


+ 17 - 0
Menu/GameShell/10_Settings/.Sound.stock/__init__.py

@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*- 
+
+## local UI import
+import pages
+import myvars
+
+def Init(main_screen):
+    pages.InitSoundPage(main_screen)
+
+def API(main_screen):
+    
+    if main_screen !=None:
+        main_screen.PushCurPage()
+        main_screen.SetCurPage(myvars.SoundPage)
+        main_screen.Draw()
+        main_screen.SwapAndShow()
+        

+ 6 - 0
Menu/GameShell/10_Settings/.Sound.stock/myvars.py

@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*- 
+
+import os
+import sys
+
+SoundPage = None

+ 13 - 0
Menu/GameShell/10_Settings/.Sound.stock/pages.py

@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*- 
+
+from sound_page import SoundPage
+
+import myvars
+
+def InitSoundPage(main_screen):
+
+    myvars.SoundPage = SoundPage()
+
+    myvars.SoundPage._Screen = main_screen
+    myvars.SoundPage._Name = "Sound Volume"
+    myvars.SoundPage.Init()

+ 170 - 0
Menu/GameShell/10_Settings/.Sound.stock/sound_page.py

@@ -0,0 +1,170 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+
+#from libs.roundrects import aa_round_rect
+
+import alsaaudio
+
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.icon_item import IconItem
+from UI.label  import Label
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, IsKeyMenuOrB
+from UI.slider     import Slider
+from UI.multi_icon_item import MultiIconItem
+
+
+from UI.icon_pool  import MyIconPool
+
+import myvars
+
+class SoundSlider(Slider):
+    OnChangeCB = None
+    
+    _BGpng = None
+    _BGwidth = 192
+    _BGheight = 173
+
+    _NeedleSurf = None
+    _Scale      = None
+    _Parent     = None
+    
+    snd_segs = [ [0,20],[21,40],[41,50],[51,60],[61,70],[71,85],[86,90],[91,95],[96,100] ]
+
+    
+    def __init__(self):
+        Slider.__init__(self)
+        
+    def Init(self):
+        self._Width = self._Parent._Width
+        self._Height = self._Parent._Height
+        
+        self._BGpng = IconItem()
+        self._BGpng._ImgSurf = MyIconPool.GiveIconSurface("vol")
+        self._BGpng._MyType = ICON_TYPES["STAT"]
+        self._BGpng._Parent = self
+        self._BGpng.Adjust(0,0,self._BGwidth,self._BGheight,0)
+
+        ##self._NeedleSurf = pygame.Surface( (38,12),pygame.SRCALPHA )
+        
+        self._Scale = MultiIconItem()
+        self._Scale._MyType = ICON_TYPES["STAT"]
+        self._Scale._Parent = self
+        self._Scale._ImgSurf = MyIconPool.GiveIconSurface("scale")
+        self._Scale._IconWidth = 82
+        self._Scale._IconHeight = 63
+        self._Scale.Adjust(0,0,82,63,0)
+        
+    def SetValue(self,vol):#pct 0-100
+        for i,v in enumerate(self.snd_segs):
+            if vol  >= v[0] and vol <= v[1]:
+                self._Value = i # self._Value :  0 - 8
+                break
+        
+    def Further(self):
+        self._Value+=1
+
+        if self._Value > len(self.snd_segs)-1:
+            self._Value = len(self.snd_segs) -1
+
+        vol = self.snd_segs[self._Value][0] + (self.snd_segs[self._Value][1] - self.snd_segs[self._Value][0])/2 
+        
+        if self.OnChangeCB != None:
+            if callable(self.OnChangeCB):
+                self.OnChangeCB( vol )
+        
+    def StepBack(self):
+        self._Value-=1
+
+        if self._Value < 0:
+            self._Value = 0
+
+        vol = self.snd_segs[self._Value][0] + (self.snd_segs[self._Value][1] - self.snd_segs[self._Value][0])/2 
+        
+        if self.OnChangeCB != None:
+            if callable(self.OnChangeCB):
+                self.OnChangeCB( vol )
+    
+    def Draw(self):
+        
+        self._BGpng.NewCoord(self._Width/2,self._Height/2 )
+        self._BGpng.Draw()
+
+        self._Scale.NewCoord(self._Width/2,self._Height/2)
+
+        self._Scale._IconIndex = self._Value
+        
+        self._Scale.Draw()
+        
+        
+        
+class SoundPage(Page):
+
+    _MySlider = None
+    _FootMsg = ["Nav","","","Back","Enter"]
+
+    def Init(self):
+        self._CanvasHWND = self._Screen._CanvasHWND
+        self._Width =  self._Screen._Width
+        self._Height = self._Screen._Height
+        
+        self._MySlider = SoundSlider()
+
+        self._MySlider._Parent = self        
+        self._MySlider.SetCanvasHWND(self._CanvasHWND)
+
+        self._MySlider.OnChangeCB = self.WhenSliderDrag
+
+        self._MySlider.Init()
+        
+        try:
+            m = alsaaudio.Mixer()
+            self._MySlider.SetValue(m.getvolume()[0])
+        except Exception,e:
+            print(str(e))
+            self._MySlider.SetValue(0)
+
+
+    def OnLoadCb(self):
+        try:
+            m = alsaaudio.Mixer()
+            self._MySlider.SetValue(m.getvolume()[0])
+        except Exception,e:
+            print(str(e))
+                
+    def WhenSliderDrag(self,value): ##value 0-100
+        if value < 0 or value > 100:
+            return
+        
+        m = alsaaudio.Mixer()
+        m.setvolume(int(value))
+        
+    def KeyDown(self,event):
+        
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Right"]:
+            self._MySlider.Further()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if event.key == CurKeys["Left"]:
+            self._MySlider.StepBack()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+    def Draw(self):
+        self.ClearCanvas()
+        
+        self._MySlider.Draw()
+
+        
+
+
+    

+ 145 - 0
Menu/GameShell/10_Settings/.Storage.deot/__init__.py

@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+import os
+
+
+## local UI import
+from UI.page  import Page
+from UI.skin_manager import MySkinManager
+from UI.constants import ICON_TYPES,Width,Height
+from UI.icon_item import IconItem
+from UI.icon_pool import MyIconPool
+from UI.label  import Label
+from UI.util_funcs import midRect
+
+class StoragePage(Page):
+
+    _Icons = {}
+    _BGpng  = None
+    _BGwidth = 96
+    _BGheight = 73
+    _BGlabel  = None
+    _FreeLabel = None
+    
+    _GBmsg    = "%.1fGB of %.1fGB Used"
+    _DskUsg   = None
+
+    _TextColor = MySkinManager.GiveColor('Text')
+    _FootMsg    = ["Nav.","","","Back",""]
+    
+    def __init__(self):
+        Page.__init__(self)
+        
+        self._Icons = {}
+
+
+    def DiskUsage(self):
+        statvfs = os.statvfs('/')
+
+        total_space = (statvfs.f_frsize * statvfs.f_blocks)/1024.0/1024.0/1024.0
+
+        avail_space = ( statvfs.f_frsize * statvfs.f_bavail) / 1024.0 / 1024.0/ 1024.0
+
+        return avail_space,total_space
+        
+    def Init(self):
+
+        self._DskUsg = self.DiskUsage()
+        
+        self._CanvasHWND = self._Screen._CanvasHWND
+        self._Width =  self._Screen._Width
+        self._Height = self._Screen._Height
+        
+        self._GBLabel = Label()
+        self._GBLabel.SetCanvasHWND(self._CanvasHWND)
+        self._GBLabel.Init(self._GBmsg % (self._DskUsg[1]-self._DskUsg[0], self._DskUsg[1]),MySkinManager.GiveFont("varela11") )
+        self._GBLabel.SetColor(self._TextColor)
+        
+        self._PctLabel = Label()
+        self._PctLabel.SetCanvasHWND(self._CanvasHWND)
+
+        usage_percent = (self._DskUsg[0]/self._DskUsg[1] )*100.0
+        
+        
+        self._PctLabel.Init("%d%%"% int(usage_percent),MySkinManager.GiveFont("EurostileBold30"))
+        self._PctLabel.SetColor( self._TextColor )
+        
+        self._FreeLabel = Label()
+        self._FreeLabel.SetCanvasHWND(self._CanvasHWND)
+        self._FreeLabel.Init("FREE",MySkinManager.GiveFont("varela12"))
+        self._FreeLabel.SetColor(self._PctLabel._Color)
+
+        
+    def OnLoadCb(self):
+        pass
+    
+    def Draw(self):
+        self.ClearCanvas()
+        
+        self._PctLabel.NewCoord(32,102- 33)
+        self._PctLabel.Draw()
+
+        self._FreeLabel.NewCoord(33   ,130-25)
+        self._FreeLabel.Draw()
+
+        self._GBLabel.NewCoord(145,103-29)
+        self._GBLabel.Draw()
+        
+        #bgcolor = (238,238,238), fgcolor = (126,206,244)
+
+        usage_percent = (self._DskUsg[0]/self._DskUsg[1] )
+        if usage_percent < 0.1:
+            usage_percent = 0.1
+
+        rect_ = pygame.Rect(144,118-25, 283-144,139-117)
+
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Text'), rect_, 1)
+
+        
+        rect2 = pygame.Rect(144,118-25,int((283-144)*(1.0-usage_percent)),139-117)
+
+        rect2.left = rect_.left
+        rect2.top  = rect_.top
+        
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Text'),rect2, 0)   
+        
+        sep_rect = pygame.Rect(129,99-25,2,42)
+        
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Inactive'),sep_rect, 0)   
+        
+        ##4 cross
+        self.DrawCross(10,10)
+        self.DrawCross(self._Screen._Width-20,10)
+        self.DrawCross(10,self._Screen._Height-20)
+        self.DrawCross(self._Screen._Width-20,self._Screen._Height-20)
+        
+        
+class APIOBJ(object):
+
+    _StoragePage = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._StoragePage = StoragePage()
+
+        self._StoragePage._Screen = main_screen
+        self._StoragePage._Name ="Storage"
+        self._StoragePage.Init()
+        
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._StoragePage)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+    
+
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 155 - 0
Menu/GameShell/10_Settings/.list_page.py.stock

@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+import sys
+
+from libs.roundrects import aa_round_rect
+
+## local UI import
+from UI.constants import Width,Height
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect,FileExists
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+from UI.info_page_selector import InfoPageSelector
+
+from list_item  import ListItem
+
+import myvars
+
+class ListPage(Page):
+
+    _Icons = {}
+    _Selector=None
+    
+    _FootMsg = ["Nav","","","Back","Enter"]
+    _MyList = []
+    _ListFontObj = MyLangManager.TrFont("varela15")
+
+    _Scroller = None
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+        self._CanvasHWND = None
+        self._MyList = []
+        
+    def Init(self):
+        self._PosX = self._Index * self._Screen._Width
+        self._Width = self._Screen._Width
+        self._Height = self._Screen._Height
+
+        self._CanvasHWND = self._Screen._CanvasHWND
+
+        ps = InfoPageSelector()
+        ps._Parent = self
+        ps._PosX = 2
+        self._Ps = ps
+        self._PsIndex = 0
+        
+        #                ""   pkgname, label
+        alist         = [["","Airplane","Airplane Mode"],
+                         ["","PowerOptions","Power Options"],
+                         ["","Wifi","Wi-Fi"],
+                         ["","Bluetooth","Bluetooth"],
+                         ["","Sound","Sound  Volume"],
+                         ["","Brightness","BackLight Brightness"],
+                         ["","Storage",""],
+                         ["","Time","Timezone"],
+                         ["","Languages","Languages"],
+                         ["","Notification","Notification"],
+                         ["","Update", "Update Launcher"],
+                         ["","Cores", "Retroarch cores manager"],
+                         ["","About",  "About"],
+                         ["","PowerOFF","Power OFF"],
+                         ["","ButtonsLayout","Buttons Layout"],
+                         ["","Skins","Theme Manager"],
+                         #["","LauncherGo","Switch to LauncherGo"],
+                         ["","Lima","GPU Driver Switch"],
+                         ["","GateWay","Network Gateway Switch"]]
+
+        start_x  = 0
+        start_y  = 0
+
+        
+        sys.path.append(myvars.basepath)# add self as import path
+        for i,v in enumerate(alist):
+            li = ListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + i*ListItem._Height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFontObj
+
+            if v[2] != "":
+                li.Init(v[2])
+            else:
+                li.Init(v[1])
+            
+            #if v[1] == "Wifi" or v[1] == "Sound" or v[1] == "Brightness" or v[1] == "Storage" or v[1] == "Update" or v[1] == "About" or v[1] == "PowerOFF" or v[1] == "HelloWorld":
+            if FileExists(myvars.basepath+"/"+ v[1]):
+                li._LinkObj = __import__(v[1])
+                init_cb   = getattr(li._LinkObj,"Init",None)
+                if init_cb != None:
+                    if callable(init_cb):
+                        li._LinkObj.Init(self._Screen)
+                
+                self._MyList.append(li)
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+
+    def Click(self):
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._LinkObj != None:
+            api_cb = getattr(cur_li._LinkObj,"API",None)
+            if api_cb != None:
+                if callable(api_cb):
+                    cur_li._LinkObj.API(self._Screen)
+
+        
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+
+        if IsKeyStartOrA(event.key):
+            self.Click()
+            
+    def Draw(self):
+        self.ClearCanvas()
+
+        if len(self._MyList) * ListItem._Height > self._Height:
+            self._Ps._Width = self._Width - 11
+            
+            self._Ps.Draw()
+            
+            for i in self._MyList:
+                i.Draw()
+        
+            self._Scroller.UpdateSize( len(self._MyList)*ListItem._Height, self._PsIndex*ListItem._Height)
+            self._Scroller.Draw()
+        else:
+            self._Ps._Width = self._Width
+            self._Ps.Draw()
+            for i in self._MyList:
+                i.Draw()
+
+            

+ 398 - 0
Menu/GameShell/10_Settings/About/__init__.py

@@ -0,0 +1,398 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+#import math
+import subprocess
+
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+#import gobject
+#from wicd import misc 
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect,FileExists
+from UI.keys_def   import CurKeys, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.multi_icon_item  import MultiIconItem
+from UI.multilabel import MultiLabel
+from UI.lang_manager import MyLangManager
+from UI.skin_manager import MySkinManager
+
+from config import VERSION
+
+class InfoPageListItem(object):
+    _PosX = 0
+    _PosY = 0
+    _Width = 0
+    _Height = 20
+
+    _Labels = {}
+    _Icons  = {}
+    _Fonts  = {}
+
+    _LinkObj = None
+    
+    def __init__(self):
+        self._Labels = {}
+        self._Icons  = {}
+        self._Fonts  = {}
+
+    def SetSmallText(self,text):
+        
+        l = MultiLabel()
+        l.SetCanvasHWND(self._Parent._CanvasHWND)
+        l.Init(text,self._Fonts["small"])
+        
+        self._Labels["Small"] = l
+
+        #if self._Labels["Small"]._Width > self._Width:
+        #    self._Width = self._Labels["Small"]._Width
+        if self._Labels["Small"]._Height >= self._Height:
+            self._Height = self._Labels["Small"]._Height+10
+        
+    def Init(self,text):
+
+        #self._Fonts["normal"] = fonts["veramono12"]
+        
+        l = Label()
+        l._PosX = 10
+        l.SetCanvasHWND(self._Parent._CanvasHWND)
+
+        l.Init(text,self._Fonts["normal"])
+        self._Labels["Text"] = l
+        
+    def Draw(self):
+        
+        self._Labels["Text"]._PosY = self._PosY
+        self._Labels["Text"].Draw()
+
+        if "Small" in self._Labels:
+            self._Labels["Small"]._PosX = self._Labels["Text"]._Width + 16 
+            self._Labels["Small"]._PosY = self._PosY 
+            self._Labels["Small"].Draw()
+        
+        
+    
+
+class AboutPage(Page):
+    _FootMsg =  ["Nav.","","","Back",""]
+    _MyList = []
+    _ListFontObj = MyLangManager.TrFont("varela13")
+    
+    _AList = {}
+
+    _Scrolled = 0
+    
+    _BGwidth = 320
+    _BGheight = 300
+
+    _DrawOnce = False
+    _Scroller = None
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+
+    def Uname(self):
+        
+        out = {}
+        out["key"]="uname"
+        out["label"]= "Kernel:"
+        st = subprocess.check_output(["uname","-srmo"])
+        st = st.strip("\n")
+        st = st.strip("\t")
+        out["value"] = st
+        self._AList["uname"] = out
+
+        return
+    
+    def CpuMhz(self):
+
+        try:
+            with open("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq") as f:
+                content = f.readlines()
+            content = [x.strip() for x in content]
+            
+        except:
+            print("open %s failed" % "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq")
+            content = ["0"]
+        
+        mhz = int(content[0]) / 1000.0
+
+        cpuscalemhz = {}
+        cpuscalemhz["key"] = "cpuscalemhz"
+        cpuscalemhz["label"] = "CPU Mhz:"
+        cpuscalemhz["value"] = str(mhz)
+        self._AList["cpuscalemhz"] = cpuscalemhz
+        
+        return 
+    
+    def CpuInfo(self):
+        last_processor = 0
+        with open("/proc/cpuinfo") as f:
+            for line in f:
+                if line.startswith("processor"):
+                    parts = line.split(":")
+                    cur_processor_number = int( parts[1].strip())
+                    if cur_processor_number > last_processor:
+                        last_processor = cur_processor_number
+                    
+                if line.startswith("model name"):
+                    parts = line.split(":")
+#                    print( parts[1].strip() )
+                    processor = {}
+                    processor["key"]="processor"
+                    processor["label"] = "Processor:"
+                    processor["value"] = parts[1].strip()
+                    
+                    self._AList["processor"] = processor
+                    
+                if line.startswith("cpu MHz"):
+                    parts = line.split(":")
+#                    print(parts[1].strip() )
+                    cpumhz = {}
+                    cpumhz["key"] = "cpumhz"
+                    cpumhz["label"] = "CPU MHz:"
+                    cpumhz["value"] = parts[1].strip()
+
+                    self._AList["cpumhz"] = cpumhz
+                if line.startswith("cpu cores"):
+                    parts = line.split(":")
+#                    print(parts[1].strip() )
+                    cpucores = {}
+                    cpucores["key"] = "cpucores"
+                    cpucores["label"] = "CPU cores:"
+                    cpucores["value"] = parts[1].strip()
+                    self._AList["cpucores"] = cpucores
+                if line.startswith("Features"):
+                    parts = line.split(":")
+#                    print(parts[1].strip() )
+                    f_ = {}
+                    f_["key"] = "features"
+                    f_["label"] = "Features:"
+                    f_["value"] = parts[1].strip()
+                    self._AList["features"] = f_
+                    
+                if line.startswith("flags"):
+                    parts = line.split(":")
+#                    print(parts[1].strip() )
+                    flags = {}
+                    flags["key"] = "flags"
+                    flags["label"] = "Flags:"
+                    flags["value"] = parts[1].strip()
+                    self._AList["flags"] = flags
+                    
+
+        if last_processor > 0:
+            arm_cores = {}
+            arm_cores["key"]= "armcores"
+            arm_cores["label"] = "CPU cores:"
+            arm_cores["value"] = str(last_processor + 1)
+            self._AList["armcores"] = arm_cores
+        
+    def MemInfo(self):
+
+        with open("/proc/meminfo") as f:
+            for line in f:
+                if line.startswith("MemTotal"):
+                    parts = line.split(":")
+                    parts[1] = parts[1].replace("kB","")
+                    print(   parts[1].strip() )
+
+                    memory = {}
+                    memory["key"] = "memory"
+                    memory["label"] = "Memory:"
+                    memory["value"] = str( int(parts[1].strip())/1000.0) +" MB"
+                    self._AList["memory"] = memory                    
+                    break
+                    
+    def LauncherVersion(self):
+        launcher_version = {}
+        launcher_version["key"] = "launcher_ver"
+        launcher_version["label"] = "Launcher:"
+        launcher_version["value"] = VERSION
+        self._AList["launcher_ver"] = launcher_version
+    
+    def OsImageVersion(self):
+        if FileExists("/etc/clockworkpi_os_image_version"):
+            try:
+                with open("/etc/clockworkpi_os_image_version") as f:
+                    content = f.readlines()
+                content = [x.strip() for x in content]
+            
+            except:
+                print("open %s failed" % "/etc/clockworkpi_os_image_version")
+                content = None
+            
+            if content != None and len(content) > 0:
+                os_image_ver = {}
+                os_image_ver["key"] = "os_image_ver"
+                os_image_ver["label"] = "OS Image:"
+                os_image_ver["value"] = content[0][:12]
+                self._AList["os_image_ver"] = os_image_ver
+    
+    def GenList(self):
+        
+        self._MyList = []
+        
+        start_x  = 0
+        start_y  = 10
+        last_height = 0
+
+        for i,u in enumerate( ["processor","armcores","cpuscalemhz","features","memory","uname","launcher_ver","os_image_ver"] ):
+        #for i,u in enumerate( ["processor","cpucores","cpumhz","flags","memory","uname"] ):
+            if u not in self._AList:
+                continue
+            
+            v = self._AList[u]
+            
+            li = InfoPageListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + last_height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFontObj
+            li._Fonts["small"] = MySkinManager.GiveFont("varela12")
+            
+            if self._AList[u]["label"] != "":
+                li.Init(  self._AList[u]["label"] )
+            else:
+                li.Init( self._AList[u]["key"] )
+
+            li._Flag = self._AList[u]["key"]
+
+            li.SetSmallText( self._AList[u]["value"] )
+            
+            last_height += li._Height
+            
+            self._MyList.append(li)
+            
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._HWND = self._Screen._CanvasHWND
+                self._CanvasHWND = pygame.Surface( (self._Screen._Width,self._BGheight+50) )
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+        bgpng = MultiIconItem()
+        bgpng._ImgSurf = MyIconPool.GiveIconSurface("about_bg")
+        bgpng._MyType = ICON_TYPES["STAT"]
+        bgpng._Parent = self
+        bgpng.Adjust(0,0,self._BGwidth,self._BGheight,0)
+
+        self._Icons["bg"] = bgpng
+        
+        self.CpuInfo()
+        self.MemInfo()
+        self.CpuMhz()
+        self.Uname()
+        
+        self.LauncherVersion()
+        self.OsImageVersion()
+        
+        self.GenList()
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        self._Scroller.SetCanvasHWND(self._HWND)
+        
+    def ScrollDown(self):
+        dis = 10
+        if abs(self._Scrolled) <  (self._BGheight - self._Height)/2 + 100:
+            self._PosY -= dis
+            self._Scrolled -= dis
+        
+    def ScrollUp(self):
+        dis = 10
+        if self._PosY < 0:
+            self._PosY += dis
+            self._Scrolled += dis
+
+        
+    def OnLoadCb(self):
+        self._Scrolled = 0
+        self._PosY = 0
+        self._DrawOnce = False
+
+    def OnReturnBackCb(self):
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+                                
+    def Draw(self):
+
+        if self._DrawOnce == False:
+            self.ClearCanvas()
+            #self._Ps.Draw()
+        
+            for i in self._MyList:
+                i.Draw()
+                
+            self._DrawOnce = True
+            
+            self._Icons["bg"].DrawRect((230,0,82,184),(228,0,82,184))
+            
+            y = self._MyList[len(self._MyList)-1]._PosY+30
+            
+            self._Icons["bg"].DrawRect(( (self._Width-191)/2,y,191,68),(65,232,191,68))
+            
+        if self._HWND != None:
+            self._HWND.fill(MySkinManager.GiveColor("White"))
+            
+            self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) )
+            
+            self._Scroller.UpdateSize(self._BGheight,abs(self._Scrolled)*3)
+            self._Scroller.Draw()
+        
+        
+
+
+class APIOBJ(object):
+
+    _Page = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = AboutPage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="About"
+        self._Page.Init()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 0 - 0
Menu/GameShell/10_Settings/Airplane/Icon\r


+ 279 - 0
Menu/GameShell/10_Settings/Airplane/__init__.py

@@ -0,0 +1,279 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+#import math
+import  commands
+
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+#import gobject
+#from wicd import misc 
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.icon_item  import IconItem
+from UI.multi_icon_item import MultiIconItem
+from UI.lang_manager import MyLangManager
+
+from UI.multilabel import MultiLabel
+
+class AirplanePage(Page):
+    _FootMsg =  ["Nav","","Rescue","Back","Toggle"]
+    _MyList = []
+    _ListFontObj = MyLangManager.TrFont("varela13")
+    
+    _AList = {}
+
+    _Scrolled = 0
+    
+    _BGwidth = 320
+    _BGheight = 240-24-20
+
+    _DrawOnce = False
+    _Scroller = None
+
+    _EasingDur = 30
+
+    _airwire_y = 0
+    _dialog_index = 0
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+
+    def GenList(self):
+        
+        self._MyList = []
+        
+        
+            
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._HWND = self._Screen._CanvasHWND
+                self._CanvasHWND = pygame.Surface( (self._Screen._Width,self._BGheight) )
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+
+
+        airwire = IconItem()
+        airwire._ImgSurf = MyIconPool.GiveIconSurface("airwire")
+        airwire._MyType = ICON_TYPES["STAT"]
+        airwire._Parent = self
+        airwire.Adjust(0,0,5,43,0)
+        self._Icons["airwire"] = airwire
+
+        GS = IconItem()
+        GS._ImgSurf = MyIconPool.GiveIconSurface("GS")
+        GS._MyType = ICON_TYPES["STAT"]
+        GS._Parent = self
+        GS.Adjust(0,0,72,95,0)
+        self._Icons["GS"] = GS
+
+        DialogBoxs = MultiIconItem()
+        DialogBoxs._ImgSurf = MyIconPool.GiveIconSurface("DialogBoxs")
+        DialogBoxs._MyType = ICON_TYPES["STAT"]
+        DialogBoxs._Parent = self
+        DialogBoxs._IconWidth = 134
+        DialogBoxs._IconHeight = 93
+        DialogBoxs.Adjust(0,0,134,372,0)
+        self._Icons["DialogBoxs"] = DialogBoxs
+
+        
+        """
+        bgpng = MultiIconItem()
+        bgpng._ImgSurf = MyIconPool.GiveIconSurface("about_bg")
+        bgpng._MyType = ICON_TYPES["STAT"]
+        bgpng._Parent = self
+        bgpng.Adjust(0,0,self._BGwidth,self._BGheight,0)
+        self._Icons["bg"] = bgpng
+        """
+        
+        
+        self.GenList()
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        self._Scroller.SetCanvasHWND(self._HWND)
+        
+        self.OnLoadCb()
+        
+    def ScrollDown(self):
+        dis = 10
+        if abs(self._Scrolled) <  (self._BGheight - self._Height)/2 + 0:
+            self._PosY -= dis
+            self._Scrolled -= dis
+        
+    def ScrollUp(self):
+        dis = 10
+        if self._PosY < 0:
+            self._PosY += dis
+            self._Scrolled += dis
+
+    def ToggleModeAni(self): ## with animation
+        out = commands.getstatusoutput('sudo rfkill list | grep yes | cut -d " " -f3')
+        if "yes" in out[1]:
+            data = self.EasingData(0,43)
+            for _,v in enumerate(data):
+                self._airwire_y -= v
+                self._dialog_index = 2
+                pygame.time.delay(40)
+
+                self._Screen.Draw()
+                self._Screen.SwapAndShow()
+                
+            commands.getstatusoutput("sudo rfkill unblock all")
+            self._Screen._TitleBar._InAirPlaneMode = False
+
+        else:
+            data = self.EasingData(0,43)
+            data.reverse()
+            for _,v in enumerate(data):
+                self._airwire_y += v
+                self._dialog_index = 3
+                pygame.time.delay(40)
+                self._Screen.Draw()
+                self._Screen.SwapAndShow()
+
+            commands.getstatusoutput("sudo rfkill block all")
+            self._Screen._TitleBar._InAirPlaneMode = True
+
+        
+    def ToggleMode(self):
+        out = commands.getstatusoutput('sudo rfkill list | grep yes | cut -d " " -f3')
+        print out
+        if "yes" in out[1]:
+            self._Screen._MsgBox.SetText("TurningOn")
+            self._Screen._MsgBox.Draw()
+            commands.getstatusoutput("sudo rfkill unblock all")
+            self._Screen._TitleBar._InAirPlaneMode = False
+        
+        else:
+            self._Screen._MsgBox.SetText("TurningOff")
+            self._Screen._MsgBox.Draw()
+            commands.getstatusoutput("sudo rfkill block all")
+            self._Screen._TitleBar._InAirPlaneMode = True
+    
+    def UnBlockAll(self):
+        self._Screen._MsgBox.SetText("TurningOn")
+        self._Screen._MsgBox.Draw()
+        commands.getstatusoutput("sudo rfkill unblock all")
+        self._Screen._TitleBar._InAirPlaneMode = False
+    
+        
+    def OnLoadCb(self):
+        self._Scrolled = 0
+        self._PosY = 0
+        self._DrawOnce = False
+        out = commands.getstatusoutput('sudo rfkill list | grep yes | cut -d " " -f3')
+        if "yes" in out[1]:
+            self._Screen._TitleBar._InAirPlaneMode = True
+            self._airwire_y = 50+43
+            self._dialog_index = 1
+        else:
+            self._airwire_y = 50
+            self._dialog_index = 0
+            self._Screen._TitleBar._InAirPlaneMode = False
+        
+        
+    def OnReturnBackCb(self):
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+            self.ToggleModeAni()
+            """
+            self.ToggleMode()
+            self._Screen.SwapAndShow()
+            
+            pygame.time.delay(1000)
+            
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            """
+        """
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        """
+        
+        if event.key == CurKeys["X"]:
+            self.UnBlockAll()
+            self._Screen.SwapAndShow()
+            pygame.time.delay(1000)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow() 
+        
+            
+    def Draw(self):
+        self.ClearCanvas()
+
+        self._Icons["DialogBoxs"].NewCoord(145,23)        
+        self._Icons["airwire"].NewCoord(80,self._airwire_y)
+        
+        self._Icons["DialogBoxs"]._IconIndex = self._dialog_index
+        
+        self._Icons["DialogBoxs"].DrawTopLeft()
+        self._Icons["airwire"].Draw()
+
+        self._Icons["GS"].NewCoord(98,118)
+        self._Icons["GS"].Draw()
+        
+        if self._HWND != None:
+            self._HWND.fill((255,255,255))
+            
+            self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) )
+            
+#            self._Scroller.UpdateSize(self._BGheight,abs(self._Scrolled)*3)
+#            self._Scroller.Draw()
+        
+        
+
+
+class APIOBJ(object):
+
+    _Page = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = AirplanePage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="Airplane Mode"
+        self._Page.Init()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 813 - 0
Menu/GameShell/10_Settings/Bluetooth/__init__.py

@@ -0,0 +1,813 @@
+# -*- coding: utf-8 -*- 
+import re
+import pygame
+#import math
+import  commands
+import dbus
+from beeprint import pp
+from libs.roundrects import aa_round_rect
+
+from libs.DBUS import  bus, adapter,devices
+
+#import gobject
+#from wicd import misc 
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.icon_item  import IconItem
+from UI.multi_icon_item import MultiIconItem
+from UI.skin_manager import MySkinManager
+from UI.confirm_page import ConfirmPage
+from UI.info_page_list_item import InfoPageListItem
+
+from UI.multilabel import MultiLabel
+from UI.lang_manager import MyLangManager
+from UI.keyboard import Keyboard
+
+from net_item import NetItem
+
+from agent import BleAgent,BleAgentPairPage
+
+class BleForgetConfirmPage(ConfirmPage):
+
+    _ConfirmText = MyLangManager.Tr("ConfirmForgetQ")
+    
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if IsKeyStartOrA(event.key):
+            self.SnapMsg(MyLangManager.Tr("Deleting"))
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+            try:
+                #self._Parent._Adapter.RemoveDevice()
+                print("try to RemoveDevice")
+            except Exception,e:
+                print(str(e))
+            
+            pygame.time.delay(400)
+            
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+                    
+    def Draw(self):
+        #self.ClearCanvas()
+        self.DrawBG()
+        for i in self._MyList:
+            i.Draw()
+        
+        self.Reset()
+
+
+class BleInfoPageSelector(PageSelector):
+    _BackgroundColor = MySkinManager.GiveColor('Front')
+
+    def __init__(self):
+        self._PosX = 0
+        self._PosY = 0
+        self._Height = 0
+        
+    def AnimateDraw(self,x2,y2):
+        pass 
+
+    def Draw(self):
+        idx = self._Parent._PsIndex
+        if idx < len( self._Parent._MyList):
+            x = self._PosX+2
+            y = self._Parent._MyList[idx]._PosY+1
+            h = self._Parent._MyList[idx]._Height -3
+        
+            self._PosX = x
+            self._PosY = y
+            self._Height = h
+
+            aa_round_rect(self._Parent._CanvasHWND,  
+                          (x,y,self._Width-4,h),self._BackgroundColor,4,0,self._BackgroundColor)
+
+class BleInfoPage(Page):
+    _FootMsg =  ["Nav","Forget","Disconnect","Back",""]
+    _MyList = []
+    _ListFontObj = MyLangManager.TrFont("varela15")
+    _ListSmFontObj = MySkinManager.GiveFont("varela12")  # small font
+    _ListSm2FontObj= MySkinManager.GiveFont("varela11")
+    
+    _AList = {}
+    _Path = ""
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._CanvasHWND = self._Screen._CanvasHWND
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+        
+        ps = BleInfoPageSelector()
+        ps._Parent = self
+        self._Ps = ps
+        self._PsIndex = 0
+         
+        #_AList is an object 
+        self.GenList()
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = 2
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        
+        self._ConfirmPage1 = BleForgetConfirmPage()
+        self._ConfirmPage1._Screen = self._Screen
+        self._ConfirmPage1._Name   = "ConfirmForget"
+        self._ConfirmPage1._Parent = self
+        self._ConfirmPage1.Init() 
+        
+    def GenList(self):
+        if self._AList== None:
+            return
+        self._MyList = []
+        self._PsIndex = 0
+        start_x  = 0
+        start_y  = 0
+         
+        for i,v in enumerate( self._AList):
+            #print(i,v) # (0, dbus.String(u'AddressType'))
+            
+            li = InfoPageListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + i*InfoPageListItem._Height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFontObj
+            
+            if v == "UUIDs":
+                li._Fonts["small"] = self._ListSm2FontObj
+            else:
+                li._Fonts["small"] = self._ListSmFontObj
+            
+            li.Init( str(v) )
+            li._Flag = v
+            
+            if v =="UUIDs":
+                if len(self._AList[v]) > 1:
+                    pp(self._AList[v][0])
+                    sm_text = str(self._AList[v][0])
+                else:
+                    sm_text = "<empty>"
+            else:
+                sm_text = str(self._AList[v]) 
+            
+            if sm_text == "0":
+                sm_text="No"
+            elif sm_text == "1":
+                sm_text="Yes"
+            
+            sm_text = sm_text[:20]
+            li.SetSmallText(sm_text)
+            
+            li._PosX = 2
+            self._MyList.append(li)                      
+
+    def TryToForget(self):
+        global adapter
+        proxy_obj = bus.get_object("org.bluez", self._Path)
+        dev = dbus.Interface(proxy_obj, "org.bluez.Device1")
+        
+        self._Screen._MsgBox.SetText("Forgeting")
+        self._Screen._MsgBox.Draw()
+        self._Screen.SwapAndShow()        
+        
+        try:
+            adapter.RemoveDevice(dev)
+        except Exception,e:
+            err_name = e.get_dbus_name()
+            if err_name == "org.freedesktop.DBus.Error.NoReply":
+                self._Screen._MsgBox.SetText("DBus noreply")
+            else:
+                self._Screen._MsgBox.SetText("Forget failed")
+            
+            self._Screen._MsgBox.Draw()
+            self._Screen.SwapAndShow()
+        
+        pygame.time.delay(500)
+        
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()    
+    
+    def TryToDisconnect(self):
+        global bus
+        
+        if "Connected" in self._AList:
+            if self._AList["Connected"] == 0:
+                return
+        
+        proxy_obj = bus.get_object("org.bluez", self._Path)
+        dev = dbus.Interface(proxy_obj, "org.bluez.Device1")
+        
+        self._Screen._FootBar.UpdateNavText("Disconnecting")
+        self._Screen._MsgBox.SetText("Disconnecting")
+        self._Screen._MsgBox.Draw()
+        self._Screen.SwapAndShow()
+        
+        try:
+            dev.Disconnect()
+        except Exception,e:
+            err_name = e.get_dbus_name()
+            if err_name == "org.freedesktop.DBus.Error.NoReply":
+                self._Screen._MsgBox.SetText("DBus noreply")
+            else:
+                self._Screen._MsgBox.SetText("Disconnect failed")
+            self._Screen._MsgBox.Draw()
+            self._Screen.SwapAndShow()
+        
+        pygame.time.delay(500)
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+        self._Screen._FootBar.ResetNavText()        
+        
+    
+    def Click(self):
+        if self._PsIndex >= len(self._MyList):
+            return
+        
+        cur_li = self._MyList[self._PsIndex]
+        print(cur_li._Flag)
+        if cur_li._Flag in self._AList:
+            print(self._AList[ cur_li._Flag ])
+        
+    def OnLoadCb(self):
+        if self._AList != None:
+            if "Connected" in self._AList:
+                if self._AList["Connected"] == 1:
+                    self._FootMsg[1] = "Disconnect"
+                else:
+                    self._FootMsg[1] = ""
+        
+        self.GenList()
+
+    def OnReturnBackCb(self):
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if IsKeyStartOrA(event.key):
+            self.Click()
+            
+        if event.key == CurKeys["X"]:
+            self.TryToDisconnect()
+        
+        if event.key == CurKeys["Y"]:
+            self.TryToForget()
+        
+        
+    def Draw(self):
+        if len(self._MyList) == 0:
+            return
+        
+        self.ClearCanvas()
+
+        if len(self._MyList) * InfoPageListItem._Height > self._Height:
+            self._Ps._Width = self._Width - 10
+            self._Ps._PosX  = 9
+            self._Ps.Draw()        
+            for i in self._MyList:
+                i.Draw()
+            
+            self._Scroller.UpdateSize(len(self._MyList)*InfoPageListItem._Height, self._PsIndex*InfoPageListItem._Height)
+            self._Scroller.Draw()
+        
+        else:
+            self._Ps._Width = self._Width
+            self._Ps.Draw()
+            for i in self._MyList:
+                i.Draw() 
+        
+
+            
+
+class BleListSelector(PageSelector):
+    _BackgroundColor = MySkinManager.GiveColor('Front')
+
+    def __init__(self):
+        self._PosX = 0
+        self._PosY = 0
+        self._Height = 0
+
+    def AnimateDraw(self,x2,y2):
+        pass 
+
+    def Draw(self):
+        idx = self._Parent._PsIndex
+        if idx < len( self._Parent._MyList):
+            x = self._Parent._MyList[idx]._PosX+2
+            y = self._Parent._MyList[idx]._PosY+1
+            h = self._Parent._MyList[idx]._Height -3
+        
+            self._PosX = x
+            self._PosY = y
+            self._Height = h
+
+            aa_round_rect(self._Parent._CanvasHWND,  
+                          (x,y,self._Width-4,h),self._BackgroundColor,4,0,self._BackgroundColor)
+
+class BleListMessageBox(Label):
+    _Parent = None
+
+    def Draw(self):
+        my_text = self._FontObj.render( self._Text,True,self._Color)
+        w  = my_text.get_width()
+        h  = my_text.get_height()
+        x  = (self._Parent._Width - w)/2
+        y =  (self._Parent._Height - h)/2
+        padding = 10 
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('White'),(x-padding,y-padding, w+padding*2,h+padding*2))
+
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Black'),(x-padding,y-padding, w+padding*2,h+padding*2),1)
+
+        self._CanvasHWND.blit(my_text,(x,y,w,h))
+
+
+
+class BluetoothPage(Page):
+    _MyList = []
+    #Wicd dbus part
+    _Adapter = None
+    _Dbus     = None
+    _Devices  = None
+    
+    _BlePassword = ""
+    _Connecting = False
+    _Scanning   = False 
+    
+    _PrevState = None
+    _Selector = None
+    
+    _ShowingMessageBox = False 
+    _MsgBox            = None
+    _ConnectTry        = 0
+    _BlockCb           = None
+    
+    _LastStatusMsg     = ""
+    _FootMsg           = ["Nav","Info","Scan","Back","TryConnect"]
+    _Scroller          = None
+    _ListFontObj       = MyLangManager.TrFont("notosanscjk15")
+
+    _InfoPage          = None
+    
+    _ADAPTER_DEV  = "hci0"
+    
+    _Offline = False
+    
+    _Leader = None
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._MyList = []
+        self._CanvasHWND = None
+    
+    def ShowBox(self,msg):
+        
+        self._MsgBox._Text = msg
+        self._ShowingMessageBox = True
+        self._Screen.Draw()
+        self._MsgBox.Draw()
+        self._Screen.SwapAndShow()
+    
+    def HideBox(self):
+        self.Draw()
+        self._ShowingMessageBox = False
+        self._Screen.SwapAndShow()    
+    
+    def Init(self):
+        
+        self._PosX = self._Index * self._Screen._Width
+        self._Width = self._Screen._Width
+        self._Height = self._Screen._Height  
+    
+        #self._CanvasHWND = pygame.Surface((self._Width,self._Height))
+        self._CanvasHWND = self._Screen._CanvasHWND
+
+        ps = BleListSelector()
+        ps._Parent = self
+        ps._Width = Width - 12
+        
+        self._Ps = ps
+        self._PsIndex = 0
+        
+        msgbox = BleListMessageBox()
+        msgbox._CanvasHWND = self._CanvasHWND
+        msgbox.Init(" ",MyLangManager.TrFont("veramono12"))
+        msgbox._Parent = self
+        
+        self._MsgBox = msgbox     
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = 2
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        
+        self.GenNetworkList()
+        
+        self._InfoPage = BleInfoPage()
+        self._InfoPage._Screen = self._Screen
+        self._InfoPage._Name   = "BluetoothInfo"
+        self._InfoPage.Init()        
+
+    def print_normal(self,address, properties):
+        print("[ " + address + " ]")
+
+        for key in properties.keys():
+            value = properties[key]
+            if type(value) is dbus.String:
+                value = unicode(value).encode('ascii', 'replace')
+            if (key == "Class"):
+                print("    %s = 0x%06x" % (key, value))
+            else:
+                print("    %s = %s" % (key, value))
+
+        print()
+
+	properties["Logged"] = True
+
+    def skip_dev(self,old_dev, new_dev):
+        if not "Logged" in old_dev:
+            return False
+        if "Name" in old_dev:
+            return True
+        if not "Name" in new_dev:
+            return True
+        return False
+
+    def DbusPropertiesChanged(self, interface, changed, invalidated, path):
+        global devices
+        print("DbusPropertiesChanged")
+        if interface != "org.bluez.Device1":
+            return
+
+        if path in devices:
+            dev = devices[path]
+
+            if self.skip_dev(dev, changed):
+                return
+            devices[path] = dict(devices[path].items() + changed.items())
+        else:
+            devices[path] = changed
+
+        if "Address" in devices[path]:
+            address = devices[path]["Address"]
+        else:
+            address = "<unknown>"
+        
+        self._Devices = devices
+        self.print_normal(address, devices[path])
+        
+        self.RefreshDevices()
+        self.GenNetworkList()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+    def ShutDownConnecting(self):
+        print("Bluetooth Shutdown connecting...")
+    
+    def AbortedAndReturnToUpLevel(self):
+        self.HideBox()
+        self._Screen._FootBar.ResetNavText()
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+    
+    
+    def CheckIfBluetoothConnecting(self):
+        return True
+
+    def TryConnect(self):
+        global bus
+        
+        if self._PsIndex >= len(self._MyList):
+            return
+        
+        cur_li = self._MyList[self._PsIndex]
+        print(cur_li._Path)
+        
+        if "Connected" in cur_li._Atts:
+            if cur_li._Atts["Connected"] == 1:
+                return
+        
+        proxy_obj = bus.get_object("org.bluez", cur_li._Path)
+        dev = dbus.Interface(proxy_obj, "org.bluez.Device1")
+        
+        self._Screen._FootBar.UpdateNavText("Connecting")
+        self.ShowBox(MyLangManager.Tr("Connecting"))
+        
+        self._Leader._MyAgent.device_obj = dev
+        self._Leader._MyAgent.dev_path = cur_li._Path
+        
+        try:
+            dev.Pair(reply_handler=self._Leader._MyAgent.pair_reply, 
+                                error_handler=self._Leader._MyAgent.pair_error,timeout=60000)
+        except Exception,e:
+            print(str(e))        
+        
+        
+        #self.HideBox()
+        #self._Screen._FootBar.ResetNavText()
+        
+    def RefreshDevices(self):
+        global devices
+        devices = {}
+        try:
+            proxy_obj = bus.get_object("org.bluez", "/")
+            manager = dbus.Interface(proxy_obj,"org.freedesktop.DBus.ObjectManager")
+            objects = manager.GetManagedObjects()
+            for path, interfaces in objects.iteritems():
+                if "org.bluez.Device1" in interfaces:
+                    devices[path] = interfaces["org.bluez.Device1"] ## like /org/bluez/hci0/dev_xx_xx_xx_yy_yy_yy
+        except Exception,e:
+            print(str(e))
+            devices={}
+        
+        self._Devices = devices
+        
+    
+    def GenNetworkList(self):
+        self._MyList = []
+        start_x = 0
+        start_y = 0
+        
+        counter = 0
+        for i,v in enumerate(self._Devices):
+            if "Name" in self._Devices[v]:
+                if len(self._Devices[v]["Name"]) < 2:
+                    continue
+                if re.match("[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", self._Devices[v]["Name"].lower()): ## skip xx:xx:xx:xx:xx
+                    continue
+            else:
+                continue
+            
+            ni = NetItem()
+            ni._Parent = self
+            ni._PosX = start_x
+            ni._PosY = start_y + counter* NetItem._Height
+            ni._Width = Width
+            ni._FontObj = self._ListFontObj
+            
+            ni.Init(v,self._Devices[v])
+            
+            counter += 1
+            self._MyList.append(ni)
+
+        self._PsIndex = 0   
+    
+    def Rescan(self):
+        if self._Screen._CurrentPage != self:
+            return
+        
+        self._Scanning = True
+        self.ShowBox(MyLangManager.Tr("BluetoothScanning"))
+        self._Screen._FootBar.UpdateNavText("Scanning")
+        
+        proxy_obj = self._Dbus.get_object("org.bluez", "/org/bluez/" + self._ADAPTER_DEV)
+        adapter_props = dbus.Interface(proxy_obj,"org.freedesktop.DBus.Properties")
+        discoverying = adapter_props.Get("org.bluez.Adapter1", "Discovering") 
+        print("discoverying", discoverying)
+        
+        
+        if self._Adapter!= None:
+            try:
+                self._Adapter.StopDiscovery()
+            except Exception,e:
+                print(str(e))
+            
+            try:
+                self._Adapter.StartDiscovery()
+            except Exception,e:
+                err_name = e.get_dbus_name()
+                if err_name == "org.freedesktop.DBus.Error.NoReply":
+                    print("start discovery timeout")
+                else:
+                    print("start discovery unknown err: ", str(e))
+            
+    def OnReturnBackCb(self):
+        self.RefreshDevices()
+        self.GenNetworkList()
+    
+    def OnLoadCb(self):
+        self._Offline = False
+        if self._Screen._TitleBar._InAirPlaneMode == False:
+            out = commands.getstatusoutput("hcitool dev | grep hci0 |cut -f3") ## bluetooth maybe dead after airplane mode
+            if len(out[1]) < 17:
+                self._Offline = True
+                print("Bluetooth OnLoadCb ,can not find hci0 alive,try to reboot")
+            else:
+                self.RefreshDevices()
+                self.GenNetworkList()
+        else:
+            self._Offline = True
+            
+    def KeyDown(self,event):
+        
+        if IsKeyMenuOrB(event.key):
+            if self._Offline == True:
+                self.AbortedAndReturnToUpLevel()
+                return
+            
+            if self._Adapter != None:
+                try:
+                    self._Adapter.StopDiscovery()
+                except Exception,e:
+                    print(str(e))
+                
+                _connecting = self.CheckIfBluetoothConnecting()
+                if _connecting:
+                    self.ShutDownConnecting()
+                    self.ShowBox(MyLangManager.Tr("ShutDownConnecting"))
+                    self.AbortedAndReturnToUpLevel()
+                else:
+                    self.AbortedAndReturnToUpLevel()
+            else:
+                self.HideBox()
+                self.ReturnToUpLevelPage()
+                self._Screen.Draw()
+                self._Screen.SwapAndShow()
+            
+            self._Screen._FootBar.ResetNavText()
+            
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()       
+        
+        if event.key == CurKeys["X"]:
+            if self._Offline == False:
+                self.Rescan()   
+
+        if event.key == CurKeys["Y"]:
+            if len(self._MyList) == 0:
+                return
+            if self._Offline == True:
+                return
+            
+            self._InfoPage._AList = self._MyList[self._PsIndex]._Atts
+            self._InfoPage._Path  = self._MyList[self._PsIndex]._Path
+            self._Screen.PushPage(self._InfoPage)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if IsKeyStartOrA(event.key):
+            if self._Offline == False:
+                self.TryConnect()
+
+    def Draw(self):
+        self.ClearCanvas()
+        if len(self._MyList) == 0:
+            return
+                
+        if len(self._MyList) * NetItem._Height > self._Height:
+            self._Ps._Width = self._Width - 11
+            self._Ps.Draw()
+            
+            for i in self._MyList:
+                i.Draw()        
+            
+            self._Scroller.UpdateSize( len(self._MyList)*NetItem._Height, self._PsIndex*NetItem._Height)
+            self._Scroller.Draw()
+        else:
+            self._Ps._Width = self._Width
+            self._Ps.Draw()
+
+            for i in self._MyList:
+                i.Draw()
+
+
+
+BUS_NAME = 'org.bluez'
+AGENT_INTERFACE = 'org.bluez.Agent1'
+AGENT_PATH = "/gameshell/bleagent"
+
+class APIOBJ(object):
+
+    _Page = None
+    _PairPage = None
+    _Page3 = None
+    _Prompts = {} # string key,string value
+    _PromptType = None
+    _MyAgent = None
+    
+    def __init__(self):
+        self._Prompts["PIN"]=""
+        self._Prompts["PASS"]=""
+
+    def OnKbdReturnBackCb(self):
+        if self._PromptType == None:
+            return
+        else:
+            if self._PromptType in self._Prompts:
+                inputed = "".join(self._Page3._Textarea._MyWords)
+                self._Prompts[self._PromptType] = inputed
+            
+            self._PromptType = None ##clear 
+                
+        
+    def Ask(self,prompt,prompt_type=None):
+        
+        self._Screen.PushPage(self._Page3)
+        self._Page3.SetPassword("")
+        self._Page3._Name = prompt
+        self._Page3._Caller = self
+        
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+        if prompt_type != None:
+            self._PromptType = prompt_type
+        
+    def RegisterMyAgent(self):
+        global AGENT_PATH, bus,devices,adapter
+        
+        capability = "KeyboardDisplay"
+        self._MyAgent = BleAgent(bus, AGENT_PATH)
+        self._MyAgent._Leader = self
+        
+        obj = bus.get_object(BUS_NAME, "/org/bluez");
+        manager = dbus.Interface(obj, "org.bluez.AgentManager1")
+        manager.RegisterAgent(AGENT_PATH, capability)
+        print("BleAgent %s registered" % AGENT_PATH)
+        
+    def Init(self,main_screen):
+        global bus,devices,adapter
+        
+        self._Page = BluetoothPage()
+        self._Page._Dbus = bus
+        self._Page._Devices = devices
+        self._Page._Adapter = adapter
+        
+        self._Page._Screen = main_screen
+        self._Page._Name ="Bluetooth"
+        
+        self._Page._Leader = self
+        
+        self._Page.Init()
+        
+        self._PairPage = BleAgentPairPage()
+        self._PairPage._Screen = main_screen
+        self._PairPage._Name = "Bluetooth"
+        self._PairPage.Init()
+        
+        self._Page3= Keyboard()
+        self._Page3._Name = "Enter"
+        self._Page3._Screen = main_screen
+        self._Page3.Init()
+        
+        bus.add_signal_receiver(self._Page.DbusPropertiesChanged,
+            dbus_interface = "org.freedesktop.DBus.Properties",
+            signal_name = "PropertiesChanged",
+            arg0 = "org.bluez.Device1",
+            path_keyword = "path")
+        
+        self.RegisterMyAgent()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)

+ 224 - 0
Menu/GameShell/10_Settings/Bluetooth/agent.py

@@ -0,0 +1,224 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+#import math
+#import  commands
+import dbus
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+from UI.page   import Page,PageSelector
+from UI.keys_def   import CurKeys, IsKeyMenuOrB
+from libs.DBUS import  bus, adapter,devices
+
+
+BUS_NAME = 'org.bluez'
+AGENT_INTERFACE = 'org.bluez.Agent1'
+AGENT_PATH = "/gameshell/bleagent"
+
+class Rejected(dbus.DBusException):
+	_dbus_error_name = "org.bluez.Error.Rejected"
+
+class BleAgent(dbus.service.Object):
+    device_obj = None
+    _Leader = None
+    dev_path = ""
+    
+    def set_trusted(self,path):
+        global BUS_NAME
+        props = dbus.Interface(bus.get_object(BUS_NAME, path),
+                        "org.freedesktop.DBus.Properties")
+        props.Set("org.bluez.Device1", "Trusted", True)    
+        
+    def dev_connect(self,path):
+        global BUS_NAME
+        dev = dbus.Interface(bus.get_object(BUS_NAME, path),
+                                "org.bluez.Device1")
+                                
+        print("dev_connect %s" % path)
+        try:
+            dev.Connect() 
+        except Exception,e:
+            print(str(e))
+    
+    @dbus.service.method(AGENT_INTERFACE,in_signature="", out_signature="")
+    def Release(self):
+        print("Agent release")
+        
+
+    @dbus.service.method(AGENT_INTERFACE,in_signature="os", out_signature="")
+    def AuthorizeService(self, device, uuid):
+        print("AuthorizeService (%s, %s)" % (device, uuid)) ## directly authrized
+        return
+
+    @dbus.service.method(AGENT_INTERFACE,in_signature="o", out_signature="s")
+    def RequestPinCode(self, device):
+        print("RequestPinCode (%s)" % (device))
+        set_trusted(device)
+        return "0000"
+
+    @dbus.service.method(AGENT_INTERFACE,in_signature="o", out_signature="u")
+    def RequestPasskey(self, device):
+        print("RequestPasskey (%s)" % (device))
+        set_trusted(device)
+        passkey = "000000"
+        return dbus.UInt32(passkey)
+
+    @dbus.service.method(AGENT_INTERFACE,in_signature="ouq", out_signature="")
+    def DisplayPasskey(self, device, passkey, entered):
+        print("DisplayPasskey (%s, %06u entered %u)" % (device, passkey, entered))
+        self._Leader._PairPage.ShowPassKey(device,passkey,entered)
+        
+    @dbus.service.method(AGENT_INTERFACE,in_signature="os", out_signature="")
+    def DisplayPinCode(self, device, pincode):
+        print("DisplayPinCode (%s, %s)" % (device, pincode))
+        self._Leader._PairPage.ShowPinCode(device,pincode)
+        
+    @dbus.service.method(AGENT_INTERFACE,in_signature="ou", out_signature="")
+    def RequestConfirmation(self, device, passkey):
+        print("RequestConfirmation (%s, %06d)" % (device, passkey))
+        set_trusted(device)
+        return
+
+    @dbus.service.method(AGENT_INTERFACE,in_signature="o", out_signature="")
+    def RequestAuthorization(self, device):
+        print("RequestAuthorization (%s)" % (device))
+        
+        return
+
+    @dbus.service.method(AGENT_INTERFACE,in_signature="", out_signature="")
+    def Cancel(self):
+        print("Cancel")
+    
+    
+    def pair_reply(self):
+        print("Device paired under Agent")
+        self.set_trusted(self.dev_path)
+        self.dev_connect(self.dev_path)
+        
+        self._Leader._PairPage._dev_obj = self.device_obj
+        self._Leader._PairPage.PairReplyCb()
+        
+    def pair_error(self,error):
+        global adapter
+        err_msg = ""
+        err_name = error.get_dbus_name()
+        print(err_name)
+        if err_name == "org.freedesktop.DBus.Error.NoReply" and self.device_obj:
+            err_msg = "Timed out. Cancelling pairing"
+            print(err_msg)
+            self.device_obj.CancelPairing()
+        elif err_name == "org.bluez.Error.AuthenticationCanceled":
+            err_msg = "Authentication Canceled"
+        elif err_name == "org.bluez.Error.ConnectionAttemptFailed":
+            err_msg = "Page Timeout"
+        elif err_name == "org.bluez.Error.AlreadyExists":
+            err_msg ="Already Exists"
+            try:
+                adapter.RemoveDevice(self.device_obj)
+            except Exception,e:
+                print("pair_error forget err:",str(e))
+        
+        elif err_name == "org.bluez.Error.AuthenticationFailed":
+            err_msg = "Authentication Failed"
+        else:    
+            err_msg = "Pair error"
+            print( err_name,str(error) )
+            
+        self.device_obj = None
+        self._Leader._PairPage.PairErrorCb(err_msg)
+
+class BleAgentPairPage(Page):
+    
+    ##show pin/password 
+    ##show prompt 
+    _Pin = ""
+    _Pass = ""
+    _dev_obj = None
+    _FootMsg    = ["Nav","","","Back",""]
+    
+    def Init(self):
+        self._PosX = self._Index * self._Screen._Width
+        self._Width = self._Screen._Width
+        self._Height = self._Screen._Height  
+    
+        #self._CanvasHWND = pygame.Surface((self._Width,self._Height))
+        self._CanvasHWND = self._Screen._CanvasHWND
+    
+    def ShowPinCode(self,device,pincode):
+        print("ShowPinCode %s %s" % (device,pincode))
+        if self._Screen.CurPage() != self:
+            self._Screen.PushPage(self)
+            self.ClearCanvas()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        self._Pin = "%s" % pincode
+        txt = self.Pin
+        if len(self._Pin) > 0:
+            txt = "Pin code: %s" % self._Pin
+        self._Screen._MsgBox.SetText(txt)
+        self._Screen._MsgBox.Draw()
+        self._Screen.SwapAndShow() 
+        
+    def ShowPassKey(self,device,passkey,entered):
+        print("ShowPassKey %06u %u" % (passkey,entered))
+        if self._Screen.CurPage() != self:
+            self._Screen.PushPage(self)
+            self.ClearCanvas()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        self._Pass = "%06u" % passkey
+        if len(self._Pass) > 0:
+            txt = "Pair code: %s" % self._Pass
+        self._Screen._MsgBox.SetText(txt)
+        self._Screen._MsgBox.Draw()
+        self._Screen.SwapAndShow() 
+        
+    def PairReplyCb(self):
+        self.ClearCanvas()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+        self._Screen._MsgBox.SetText("Device paired")
+        self._Screen._MsgBox.Draw()
+        self._Screen.SwapAndShow()
+        pygame.time.delay(1500)
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()        
+        self._Screen._FootBar.ResetNavText()
+        
+    def PairErrorCb(self,error=None):
+        self.ClearCanvas()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+            
+        self._Screen._MsgBox.SetText(error)
+        self._Screen._MsgBox.Draw()
+        self._Screen.SwapAndShow()
+        pygame.time.delay(1500)
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()         
+        self._Screen._FootBar.ResetNavText()        
+        
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            if self._dev_obj != None:
+                try:
+                    self._dev_obj.CancelPairing()
+                except Exception,e:
+                    print(str(e))
+            
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+    
+    
+    def Draw(self):
+        pass
+        #self.ClearCanvas()
+        
+    
+    

+ 128 - 0
Menu/GameShell/10_Settings/Bluetooth/net_item.py

@@ -0,0 +1,128 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+
+## local UI import
+from UI.page   import Page
+from UI.label  import Label
+from UI.icon_item import IconItem
+from UI.multi_icon_item  import MultiIconItem
+from UI.icon_pool   import MyIconPool
+from UI.skin_manager import MySkinManager
+
+
+class NetItemMultiIcon(MultiIconItem):
+    _CanvasHWND = None
+    _Parent     = None
+    _Width      = 18
+    _Height     = 18
+    
+    def Draw(self):
+        self._CanvasHWND.blit(self._ImgSurf,(self._PosX,self._PosY+(self._Parent._Height-self._Height)/2,self._Width,self._Height),
+                              (0,self._IconIndex*self._IconHeight,self._IconWidth,self._IconHeight))
+    
+class NetItemIcon(IconItem):
+
+    _CanvasHWND = None
+    _Parent     = None
+    _Width      = 18
+    _Height     = 18
+    
+    def Draw(self):
+        self._CanvasHWND.blit(self._ImgSurf,(self._PosX,self._PosY+(self._Parent._Height-self._Height)/2,self._Width,self._Height))
+
+            
+class NetItem(object):
+    _PosX = 0
+    _PosY = 0
+    _Width = 0
+    _Height = 30
+    
+    _Atts  = {}
+    
+    _Channel=""  # '10' 
+    _Stren = ""  ## 19%
+
+    _Parent = None
+    _IsActive = False
+
+    _Icons  = {} ## wifi strength and security icons
+    _Labels = {}
+    _FontObj = None
+    
+    _RSSI = 0
+    _MacAddr=""
+    _Path  = "" #/org/bluez/hci0/dev_34_88_5D_97_FF_26
+    
+    def __init__(self):
+        self._Labels = {}
+        self._Icons = {}
+
+    def SetActive(self,act):
+        self._IsActive = act
+    
+    def Init(self, path, object):
+        self._Path = path
+        self._Atts = object 
+        
+        is_active=False
+        if "Address" in object:
+            self._MacAddr = object["Address"]
+        
+        if  "Connected" in object:
+            if object["Connected"] == 1:
+                is_active=True
+        
+        if is_active:
+            self.SetActive(is_active)
+        
+
+        name_label = Label()
+        name_label._PosX = 12
+        name_label._CanvasHWND = self._Parent._CanvasHWND
+
+        mac_addr = self._MacAddr
+        
+        if "Name" in object:
+            if len(object["Name"]) > 3:
+                mac_addr = object["Name"]
+        
+        if "RSSI" in object:
+            print(object["RSSI"])
+            self._RSSI = int(object["RSSI"])
+        
+        mac_addr = mac_addr[:34]
+        
+        name_label.Init(mac_addr,self._FontObj)
+        
+        self._Labels["mac_addr"] = name_label
+
+        done_icon = NetItemIcon()
+        done_icon._ImgSurf = MyIconPool.GiveIconSurface("done")
+        done_icon._CanvasHWND = self._Parent._CanvasHWND
+        done_icon._Parent = self
+        
+        self._Icons["done"] = done_icon
+        ## reuse the resource from TitleBar
+        #pp(theString)
+    
+    
+    def Connect(self,notworkentry=None):
+        """ Execute connection. """
+        #dev = dbus.Interface(bus.get_object("org.bluez", "/org/bluez/hci0/dev_"+"34_88_5D_97_FF_26"), "org.bluez.Device1")
+        proxy_obj = self._Parent._Dbus.get_object("org.bluez",self._Path)
+        dev = self._Parent._Dbus.Interface(proxy_obj, "org.bluez.Device1")
+        dev.Connect()
+
+    def Draw(self):
+        #pygame.draw.line(self._Parent._CanvasHWND,(169,169,169),(self._PosX,self._PosY),(self._PosX+self._Width,self._PosY),1)
+        for i in self._Labels:
+            self._Labels[i]._PosY = self._PosY + (self._Height - self._Labels[i]._Height)/2
+            self._Labels[i].Draw()
+            
+        if self._IsActive:
+            self._Icons["done"].NewCoord(320-22,self._PosY)
+            self._Icons["done"].Draw()
+        
+        pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),
+            (self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)

+ 0 - 0
Menu/GameShell/10_Settings/Brightness/Icon\r


+ 17 - 0
Menu/GameShell/10_Settings/Brightness/__init__.py

@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*- 
+
+## local UI import
+import pages
+import myvars
+
+def Init(main_screen):
+    pages.InitBrightnessPage(main_screen)
+
+def API(main_screen):
+    
+    if main_screen !=None:
+        main_screen.PushCurPage()
+        main_screen.SetCurPage(myvars.BrightnessPage)
+        main_screen.Draw()
+        main_screen.SwapAndShow()
+        

+ 187 - 0
Menu/GameShell/10_Settings/Brightness/brightness_page.py

@@ -0,0 +1,187 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+
+
+#import math
+
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.icon_item import IconItem
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, IsKeyMenuOrB
+from UI.slider     import Slider
+from UI.icon_pool  import MyIconPool
+from UI.multi_icon_item import MultiIconItem
+from UI.skin_manager import MySkinManager
+
+
+from config import BackLight
+
+
+import myvars
+
+class BSlider(Slider):
+
+    
+    OnChangeCB = None
+    _Parent     = None
+    _Icons      = {}
+    
+    def __init__(self):
+        Slider.__init__(self)
+        self._Icons = {}
+    def Init(self):
+        self._Width = self._Parent._Width
+        self._Height = self._Parent._Height
+        
+        self._BrightnessLabel = Label()
+        self._BrightnessLabel.SetCanvasHWND(self._CanvasHWND)
+        self._BrightnessLabel.Init("BRIGHT",MySkinManager.GiveFont("EurostileBold13"))
+        self._BrightnessLabel.SetColor(MySkinManager.GiveColor('Text'))
+        
+
+    def SetValue(self,brt):
+        self._Value = brt
+        
+    def Further(self):
+        self._Value+=1
+        if self._Value > 9:
+            self._Value = 9
+            
+        if self.OnChangeCB != None:
+            if callable(self.OnChangeCB):
+                self.OnChangeCB(self._Value)
+                    
+    def StepBack(self):
+        self._Value-=1
+
+        if self._Value < 1:
+            self._Value = 1
+
+        if self.OnChangeCB != None:
+            if callable(self.OnChangeCB):
+                self.OnChangeCB(self._Value)
+    
+    def Draw(self):
+        start_x = 82
+        start_y = self._Parent._Screen._Height/2-5
+        height = 30
+        width = 4
+        padding = 15
+        seg = self._Value-1
+
+        for i in range(0,9):
+            rect = pygame.Rect(start_x+i*(width+padding),start_y,width,height)
+            if i > seg:
+                pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Text'),rect, 1)
+                #aa_round_rect(self._CanvasHWND,rect, MySkinManager.GiveColor('Text'),1,1, MySkinManager.GiveColor('White'))
+            else:
+                pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Text'),rect, 0)   
+                #aa_round_rect(self._CanvasHWND,rect, MySkinManager.GiveColor('Text'),1,0, MySkinManager.GiveColor('White'))
+        
+        self._BrightnessLabel.NewCoord(118,self._Parent._Screen._Height/2-30)
+        self._BrightnessLabel.Draw(True)
+        
+        minus_box_rect = pygame.Rect(start_x- (4+6)*4,start_y,6*4,30)
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Text'),minus_box_rect, 0) 
+        
+        minus_rect     = pygame.Rect(start_x-8*4,start_y+14,2*4,2)
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('White'),minus_rect, 0) 
+        
+        plus_box_rect = pygame.Rect(start_x + 39*4 +4*4,start_y,6*4,30)
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Text'),plus_box_rect, 0) 
+        
+        cross1_rect     = pygame.Rect(start_x+39*4+4*4+2*4,start_y+14,2*4,2)
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('White'),cross1_rect, 0) 
+        cross2_rect     = pygame.Rect(start_x+39*4+4*4+2*4+3,start_y+14-3,2,2*4)
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('White'),cross2_rect, 0) 
+
+
+        
+class BrightnessPage(Page):
+
+    _MySlider = None
+    _FootMsg = ["Nav","","","Back","Enter"]
+
+    
+    def Init(self):
+        self._CanvasHWND = self._Screen._CanvasHWND
+        self._Width =  self._Screen._Width
+        self._Height = self._Screen._Height
+        
+        self._MySlider = BSlider()
+#        self._MySlider._Width = Width - 20
+#        self._MySlider._Height = 30
+#        self._MySlider._PosX  = (self._Width - self._MySlider._Width)/2
+#        self._MySlider._PosY  = 40
+        self._MySlider._Parent = self
+        self._MySlider.SetCanvasHWND(self._CanvasHWND)
+        self._MySlider.OnChangeCB = self.WhenSliderDrag
+        self._MySlider.Init()
+
+        brt  = self.ReadBackLight()
+        
+        self._MySlider.SetValue( brt)
+
+    
+    def ReadBackLight(self):
+        try:
+            f = open(BackLight)
+        except IOError:
+            return 0
+        else:
+            with f:
+                content = f.readlines()
+                content = [x.strip() for x in content]
+                return int(content[0])
+
+        return 0
+
+    def OnLoadCb(self):
+         brt  = self.ReadBackLight()
+         
+         self._MySlider.SetValue( brt)
+         
+    def SetBackLight(self,newbrt):
+        try:
+            f = open(BackLight,'w')
+        except IOError:
+            print("Open write %s failed %d" % (BackLight,newbrt))
+            return False
+        else:
+            with f:
+                f.write(str(newbrt))
+                return True
+        
+    def WhenSliderDrag(self,value): ##value 
+        self.SetBackLight(value)
+        
+    def KeyDown(self,event):
+        
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Right"]:
+            self._MySlider.Further()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if event.key == CurKeys["Left"]:
+            self._MySlider.StepBack()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+    def Draw(self):
+        self.ClearCanvas()
+        
+        self._MySlider.Draw()
+
+        
+
+
+    

+ 6 - 0
Menu/GameShell/10_Settings/Brightness/myvars.py

@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*- 
+
+import os
+import sys
+
+SoundPage = None

+ 13 - 0
Menu/GameShell/10_Settings/Brightness/pages.py

@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*- 
+
+from brightness_page import BrightnessPage
+
+import myvars
+
+def InitBrightnessPage(main_screen):
+
+    myvars.BrightnessPage = BrightnessPage()
+    
+    myvars.BrightnessPage._Screen = main_screen
+    myvars.BrightnessPage._Name = "Brightness"
+    myvars.BrightnessPage.Init()

+ 0 - 0
Menu/GameShell/10_Settings/ButtonsLayout/Icon\r


+ 267 - 0
Menu/GameShell/10_Settings/ButtonsLayout/__init__.py

@@ -0,0 +1,267 @@
+# -*- coding: utf-8 -*-
+
+import pygame
+import commands
+import shutil
+import os
+
+from libs.roundrects import aa_round_rect
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, GetButtonsLayoutMode, SetButtonsLayoutMode, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.icon_item  import IconItem
+from UI.multi_icon_item import MultiIconItem
+from UI.multilabel import MultiLabel
+from UI.confirm_page import ConfirmPage
+
+class UpdateConfirmPage(ConfirmPage):
+    _ConfirmText = "Apply to RetroArch?"
+    _RetroArchConf = "/home/cpi/.config/retroarch/retroarch.cfg"
+    _LayoutMode = "Unknown"
+
+    def ModifyRetroArchConf(self,keys):
+
+        try:
+            with open(self._RetroArchConf, mode="r") as f:
+                confarr = f.readlines()
+        except:
+            return "retroarch.cfg cannot open."
+
+        bka = bkb = bkx = bky = False
+        try:
+            for i, ln in enumerate(confarr):
+                lnk = ln.split("=")[0].strip()
+                if lnk == "input_player1_a":
+                    confarr[i] = "input_player1_a = \"" + keys[0] + "\"\n"
+                    bka = True
+                if lnk == "input_player1_b":
+                    confarr[i] = "input_player1_b = \"" + keys[1] + "\"\n"
+                    bkb = True
+                if lnk == "input_player1_x":
+                    confarr[i] = "input_player1_x = \"" + keys[2] + "\"\n"
+                    bkx = True
+                if lnk == "input_player1_y":
+                    confarr[i] = "input_player1_y = \"" + keys[3] + "\"\n"
+                    bky = True
+        except:
+            return "retroarch.cfg cannot parse."
+
+        if bka and bkb and bkx and bky:
+            None
+        else:
+            return "retroarch.cfg validation error."
+
+        try:
+            with open(self._RetroArchConf, mode="w") as f:
+                confarr = f.writelines(confarr)
+        except:
+            return "retroarch.cfg cannot write."
+
+        return "Completed! Your RA keymap: " + self._LayoutMode.upper()
+
+    def KeyDown(self,event):
+
+        def finalizeWithDialog(msg):
+            self._Screen._MsgBox.SetText(msg)
+            self._Screen._MsgBox.Draw()
+            self._Screen.SwapAndShow()
+            return
+
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+
+            if self._LayoutMode == "xbox":
+                keymap = ["j","k","u","i"]
+            elif self._LayoutMode == "snes":
+                keymap = ["k","j","i","u"]
+            else:
+                finalizeWithDialog("Internal error.")
+                return
+            print("mode: " + self._LayoutMode)
+
+            if not os.path.isfile(self._RetroArchConf):
+                finalizeWithDialog("retroarch.cfg was not found.")
+                return
+
+            try:
+                shutil.copyfile(self._RetroArchConf, self._RetroArchConf + ".blbak")
+            except:
+                finalizeWithDialog("Cannot create .blbak")
+                return
+
+            finalizeWithDialog(self.ModifyRetroArchConf(keymap))
+            return
+
+    def OnReturnBackCb(self):
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+
+    def Draw(self):
+        self.ClearCanvas()
+        self.DrawBG()
+        for i in self._MyList:
+            i.Draw()
+
+        self.Reset()
+
+class ButtonsLayoutPage(Page):
+    _FootMsg =  ["Nav.","","UpdateRetroArch","Back","Toggle"]
+    _MyList = []
+
+    _AList = {}
+
+    _Scrolled = 0
+
+    _BGwidth = 320
+    _BGheight = 240-24-20
+
+    _DrawOnce = False
+    _Scroller = None
+    _ConfirmPage = None
+
+    _EasingDur = 30
+
+    _dialog_index = 0
+
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+
+    def GenList(self):
+
+        self._MyList = []
+
+
+
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._HWND = self._Screen._CanvasHWND
+                self._CanvasHWND = pygame.Surface( (self._Screen._Width,self._BGheight) )
+
+        self._PosX = self._Index*self._Screen._Width
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+        DialogBoxs = MultiIconItem()
+        DialogBoxs._ImgSurf = MyIconPool.GiveIconSurface("buttonslayout")
+        DialogBoxs._MyType = ICON_TYPES["STAT"]
+        DialogBoxs._Parent = self
+        DialogBoxs._IconWidth = 300
+        DialogBoxs._IconHeight = 150
+        DialogBoxs.Adjust(0,0,134,372,0)
+        self._Icons["DialogBoxs"] = DialogBoxs
+
+        self.GenList()
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        self._Scroller.SetCanvasHWND(self._HWND)
+
+        self._ConfirmPage = UpdateConfirmPage()
+        self._ConfirmPage._LayoutMode = GetButtonsLayoutMode()
+        self._ConfirmPage._Screen = self._Screen
+        self._ConfirmPage._Name  = "Overwrite RA conf"
+        self._ConfirmPage._Parent = self
+        self._ConfirmPage.Init()
+
+
+    def ScrollDown(self):
+        dis = 10
+        if abs(self._Scrolled) <  (self._BGheight - self._Height)/2 + 0:
+            self._PosY -= dis
+            self._Scrolled -= dis
+
+    def ScrollUp(self):
+        dis = 10
+        if self._PosY < 0:
+            self._PosY += dis
+            self._Scrolled += dis
+
+    def ToggleMode(self):
+
+        if GetButtonsLayoutMode() == "xbox":
+            SetButtonsLayoutMode("snes")
+
+            self._dialog_index = 1
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        else:
+            SetButtonsLayoutMode("xbox")
+
+            self._dialog_index = 0
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+    def OnLoadCb(self):
+        self._Scrolled = 0
+        self._PosY = 0
+        self._DrawOnce = False
+
+        self._dialog_index = 0 if GetButtonsLayoutMode() == "xbox" else 1
+
+    def OnReturnBackCb(self):
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+            self.ToggleMode()
+
+        if event.key == CurKeys["X"]:
+            self._ConfirmPage._LayoutMode = GetButtonsLayoutMode()
+            self._Screen.PushPage(self._ConfirmPage)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+    def Draw(self):
+        self.ClearCanvas()
+
+        self._Icons["DialogBoxs"].NewCoord(0,30)
+        self._Icons["DialogBoxs"]._IconIndex = self._dialog_index
+        self._Icons["DialogBoxs"].DrawTopLeft()
+
+        if self._HWND != None:
+            self._HWND.fill((255,255,255))
+            self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) )
+
+class APIOBJ(object):
+
+    _Page = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = ButtonsLayoutPage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="Buttons Layout"
+        self._Page.Init()
+
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+

+ 252 - 0
Menu/GameShell/10_Settings/Cores/__init__.py

@@ -0,0 +1,252 @@
+# -*- coding: utf-8 -*-
+
+import os
+import platform
+import pygame
+import glob
+#import math
+import  commands
+
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+#import gobject
+#from wicd import misc 
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect,FileExists,IsExecutable,ArmSystem,CmdClean
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.icon_item  import IconItem
+from UI.confirm_page import ConfirmPage
+from UI.multi_icon_item import MultiIconItem
+from UI.lang_manager  import MyLangManager
+from UI.multilabel import MultiLabel
+from UI.info_page_list_item import InfoPageListItem
+from UI.info_page_selector  import InfoPageSelector
+from UI.skin_manager import MySkinManager
+
+
+class DeleteCoreConfirmPage(ConfirmPage):
+    
+    _ConfirmText = MyLangManager.Tr("Awaiting Input")
+    _FootMsg = ["Nav","","","Cancel","OK"]
+    CallbackA = None
+    
+    def KeyDown(self,event):
+        
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+            self._Screen._MsgBox.SetText("Applying")
+            self._Screen._MsgBox.Draw()
+            self._Screen.SwapAndShow()
+            
+            pygame.time.delay(638)
+            
+            self.CallbackA()
+            
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+    
+class CoresPage(Page):
+    _FootMsg =  ["Nav","Del","Scan","Back",""]
+    _MyList = []
+    _ListFontObj = MyLangManager.TrFont("varela13")
+    
+    _AList = {}
+
+    _Scrolled = 0
+    
+    _BGwidth = 320
+    _BGheight = 240-24-20
+
+    _DrawOnce = False
+    _Scroller = None
+
+    _EasingDur = 30
+    
+    _CORES_PATH = "%s/.config/retroarch/cores" % os.path.expanduser('~') 
+
+    _Config =None
+    _AllowedExts = [".so",".bin"]
+    _HiddenSos   = ["GBA.BIOS","gba_bios.bin"]
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+        
+        if "arm" in platform.machine():
+            pass
+        
+    def GenList(self):
+
+        self._MyList = []
+        ## map ini to self._AList
+        files_path = glob.glob(self._CORES_PATH+"/*")
+        
+        start_x  = 10
+        start_y  = 0
+        counter = 0 
+        for i,v in enumerate( files_path):
+            if os.path.basename(v) in self._HiddenSos:
+                continue
+            
+            filename, file_extension = os.path.splitext(v)
+
+            alias_file = filename+file_extension + ".alias"
+            
+            if file_extension in self._AllowedExts:
+                li = InfoPageListItem()
+                li._Parent = self
+                li._PosX   = start_x
+                li._PosY   = start_y + counter*InfoPageListItem._Height
+                li._Width  = Width-10
+                li._Fonts["normal"] = self._ListFontObj
+                li._Fonts["small"] = MySkinManager.GiveFont("varela12")
+                li._ReadOnly = True
+                
+                if os.path.isfile(alias_file):
+                    fp = open(alias_file, "r")
+                    alias = fp.read()
+                    alias = alias.strip()
+                    label_text = alias.decode("utf8")
+                    li.Init( label_text )
+                    fp.close()
+                else:
+                    li.Init( os.path.basename(v) )
+                li._Flag = v
+                ##li.SetSmallText( v )
+                
+                self._MyList.append(li)
+                counter += 1
+    
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._CanvasHWND = self._Screen._CanvasHWND
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+        ps = InfoPageSelector()
+        ps._PosX = 11
+        ps._Parent = self
+        ps._Width = self._Width-10
+        self._Ps = ps
+        self._PsIndex = 0
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = 2
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        
+        self._ConfirmBox = DeleteCoreConfirmPage()
+        self._ConfirmBox._Screen = self._Screen
+        self._ConfirmBox._Name = "Confirm to Delete?"
+        self._ConfirmBox._Parent = self
+        self._ConfirmBox.Init()
+        
+    def ReScan(self):
+        self.GenList()
+        self.RefreshPsIndex()
+      
+    def ConfirmBoxCallbackA(self):
+        if len(self._MyList) == 0:
+            return
+            
+        cur_li = self._MyList[self._PsIndex]
+        
+        os.system("rm %s" % CmdClean(cur_li._Flag))
+        self.GenList()
+        self.RefreshPsIndex()
+        
+    def OnLoadCb(self):
+        self._Scrolled = 0
+        self._PosY = 0
+        self._DrawOnce = False    
+        self.GenList()
+    
+    def OnReturnBackCb(self):
+        pass
+        
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["X"]: #Scan current
+           self.ReScan() 
+           self._Screen.Draw()
+           self._Screen.SwapAndShow()
+                       
+        if event.key == CurKeys["Y"]: #del
+            if len(self._MyList) == 0:
+                return
+            
+            self._ConfirmBox.CallbackA = self.ConfirmBoxCallbackA
+            
+            self._Screen.PushPage(self._ConfirmBox)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+ 
+
+    def Draw(self):
+        self.ClearCanvas()
+
+        if len(self._MyList) > 0:
+            self._Ps.Draw()
+            for i in self._MyList:
+                i.Draw()
+        
+            self._Scroller.UpdateSize( len(self._MyList)*InfoPageListItem._Height,
+                                   self._PsIndex*InfoPageListItem._Height) 
+            self._Scroller.Draw()
+        
+        
+
+
+class APIOBJ(object):
+
+    _Page = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = CoresPage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="Retroarch cores manager"
+        self._Page.Init()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 349 - 0
Menu/GameShell/10_Settings/GateWay/__init__.py

@@ -0,0 +1,349 @@
+# -*- coding: utf-8 -*- 
+import os
+import pygame
+import platform
+import commands
+#import glob
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES,RESTARTUI
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect,FileExists
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.icon_item  import IconItem
+from UI.multilabel import MultiLabel
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+from UI.info_page_list_item import InfoPageListItem
+from UI.info_page_selector  import InfoPageSelector
+
+from libs.DBUS  import is_wifi_connected_now
+import config
+
+class ListPageSelector(InfoPageSelector):
+    def Draw(self):
+        idx = self._Parent._PsIndex
+        
+        if idx < len(self._Parent._MyList):
+            x = self._Parent._MyList[idx]._PosX+2 ## ++
+            y = self._Parent._MyList[idx]._PosY+1
+            h = self._Parent._MyList[idx]._Height -3
+        
+            self._PosX = x
+            self._PosY = y
+            self._Height = h
+            
+            aa_round_rect(self._Parent._CanvasHWND,  
+                          (x,y,self._Width-4,h),self._BackgroundColor,4,0,self._BackgroundColor)
+
+
+class PageListItem(InfoPageListItem):
+    _PosX = 0
+    _PosY = 0
+    _Width = 0
+    _Height = 30
+
+    _Labels = {}
+    _Icons  = {}
+    _Fonts  = {}
+
+    _LinkObj = None
+
+    _Active  = False
+    _Value = ""
+    
+    def Draw(self):
+        
+        self._Labels["Text"]._PosY = self._PosY+ (self._Height-  self._Labels["Text"]._Height)/2
+        
+        if self._Active == True:
+            self._Parent._Icons["done"].NewCoord( self._Parent._Width-30,self._PosY+5)
+            self._Parent._Icons["done"].Draw()
+            
+        self._Labels["Text"].Draw(self._Active)
+            
+        if "Small" in self._Labels:
+            self._Labels["Small"]._PosX = self._Width - self._Labels["Small"]._Width -10
+            self._Labels["Small"]._PosY = self._PosY + (self._Height-  self._Labels["Small"]._Height)/2
+            self._Labels["Small"].Draw()
+        
+        pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),(self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)        
+    
+class GateWayPage(Page):
+    _FootMsg =  ["Nav","Clear All","","Back","Select"]
+    _MyList = []
+    _ListFont = MyLangManager.TrFont("notosanscjk15")
+    
+    _AList = {}
+
+    _Scrolled = 0
+    
+    _BGwidth = 320
+    _BGheight = 240-24-20
+
+    _DrawOnce = False
+    _Scroller = None
+    _InfoPage = None
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+
+    def GenList(self):
+        
+        self._MyList = []
+        
+        start_x  = 0
+        start_y  = 0
+        last_height = 0
+
+        drivers = [["usb0","USB Ethernet"],
+                    ["wlan0","Wi-Fi"]]
+                
+        
+        for i,u in enumerate( drivers ):            
+            #print(i,u)
+            li = PageListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + last_height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFont
+            li._Active = False
+            li._Value = u[0]
+            li.Init( u[1] )
+            
+            last_height += li._Height
+            
+            self._MyList.append(li)
+            
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._HWND = self._Screen._CanvasHWND
+                self._CanvasHWND = pygame.Surface( (self._Screen._Width,self._BGheight) )
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+        done = IconItem()
+        done._ImgSurf = MyIconPool.GiveIconSurface("done")
+        done._MyType = ICON_TYPES["STAT"]
+        done._Parent = self
+        self._Icons["done"] = done
+
+        ps = ListPageSelector()
+        ps._Parent = self
+        self._Ps = ps
+        self._PsIndex = 0
+
+        self.GenList()
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        self._Scroller.SetCanvasHWND(self._HWND)
+
+    def Click(self):
+        if len(self._MyList) == 0:
+            return
+        
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._Active == True:
+            out = commands.getstatusoutput("sudo ip route | grep default | cut -d \" \" -f3")
+            if len(out[1]) > 7:
+                self._Screen._MsgBox.SetText(out[1])
+                self._Screen._MsgBox.Draw()
+                self._Screen.SwapAndShow()      
+            return
+
+        print(cur_li._Value)
+        
+        if "arm" in platform.machine():
+            for i in self._MyList:
+                i._Active = False
+            
+            self._Screen._MsgBox.SetText("Applying")
+            self._Screen._MsgBox.Draw()
+            self._Screen.SwapAndShow()
+            
+            cur_li._Active = self.ApplyGateWay(cur_li._Value)
+            
+            pygame.time.delay(1000)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        else:
+            self._Screen._MsgBox.SetText("Do it in GameShell")
+            self._Screen._MsgBox.Draw()
+            self._Screen.SwapAndShow()
+    
+    def ClearAllGateways(self):
+        self._Screen._MsgBox.SetText("Cleaning up")
+        self._Screen._MsgBox.Draw()
+        self._Screen.SwapAndShow()          
+        os.system("sudo ip route del 0/0")
+        pygame.time.delay(800)
+        
+        for i in self._MyList:
+            i._Active = False 
+        
+        self._Screen.Draw()
+        self._Screen.SwapAndShow() 
+    
+    def ApplyGateWay(self,gateway):
+        os.system("sudo ip route del 0/0")
+        if gateway== "usb0":
+            out = commands.getstatusoutput("sudo ifconfig usb0 | grep inet | tr -s \" \"| cut -d \" \" -f3")
+            if len(out[1]) > 7:
+                if "error" not in out[1]:
+                    parts = out[1].split(".")
+                    if len(parts) == 4:##IPv4
+                        tp3 = int(parts[3])
+                        tmp = tp3
+                        if tp3 == 0:
+                            tmp = int(parts[3]) + 1
+                        elif tp3 == 1:
+                            tmp = int(parts[3]) + 1
+                        elif tp3 > 1:
+                            tmp = int(parts[3]) - 1
+                        
+                        parts[3] = str(tmp)
+                        ipaddress = ".".join(parts)
+                        os.system("sudo route add default gw "+ipaddress)
+                        return True
+        else:
+            if is_wifi_connected_now():
+                os.system("sudo dhclient wlan0")
+                return True
+            else:
+                self._Screen._MsgBox.SetText("Wi-Fi is not connected")
+                self._Screen._MsgBox.Draw()
+                self._Screen.SwapAndShow()            
+                return False
+        
+        return False
+        
+
+    def OnLoadCb(self):
+        self._Scrolled = 0
+        self._PosY = 0
+        self._DrawOnce = False
+        
+        ## grep Driver /etc/xorg.conf | tr -s " " | cut -d " " -f3
+        ## "fbturbo"
+        ## "modesetting"
+        thedrv = ""
+        
+        if "arm" in platform.machine():
+            out = commands.getstatusoutput("sudo ip route | grep default")
+            if len(out[1]) > 7:
+                if "usb0" in out[1]:
+                    thedrv = "usb0"
+                elif "wlan0" in out[1]:
+                    thedrv = "wlan0"
+                
+        for i in self._MyList:
+            i._Active = False
+        
+        if thedrv != "":
+            for i in self._MyList:
+                if thedrv in i._Value:
+                    i._Active = True 
+        ## if usb0 and wlan0 all actived, clear all
+        
+    def OnReturnBackCb(self):
+        pass
+        """
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        """
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+            self.Click()
+            
+        if event.key == CurKeys["Y"]:
+            self.ClearAllGateways()
+                        
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+    
+    def Draw(self):
+
+        self.ClearCanvas()
+        if len(self._MyList) == 0:
+            return
+        
+        else:
+            if len(self._MyList) * PageListItem._Height > self._Height:
+                self._Ps._Width = self._Width - 11
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+                    if i._PosY < 0:
+                        continue
+                    i.Draw()
+                self._Scroller.UpdateSize( len(self._MyList)*PageListItem._Height, self._PsIndex*PageListItem._Height)
+                self._Scroller.Draw()
+                
+            else:
+                self._Ps._Width = self._Width
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+                    if i._PosY < 0:
+                        continue
+                    i.Draw()                
+
+        if self._HWND != None:
+            self._HWND.fill(MySkinManager.GiveColor("White"))
+            
+            self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) )
+            
+
+class APIOBJ(object):
+
+    _Page = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = GateWayPage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="Gateway switch"
+        self._Page.Init()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 309 - 0
Menu/GameShell/10_Settings/Languages/__init__.py

@@ -0,0 +1,309 @@
+# -*- coding: utf-8 -*- 
+import os
+import pygame
+#import math
+#mport subprocess
+import glob
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES,RESTARTUI
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.icon_item  import IconItem
+from UI.multilabel import MultiLabel
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+from UI.info_page_list_item import InfoPageListItem
+from UI.info_page_selector  import InfoPageSelector
+
+import config
+
+class ListPageSelector(InfoPageSelector):
+    def Draw(self):
+        idx = self._Parent._PsIndex
+        
+        if idx < len(self._Parent._MyList):
+            x = self._Parent._MyList[idx]._PosX+2 ## ++
+            y = self._Parent._MyList[idx]._PosY+1
+            h = self._Parent._MyList[idx]._Height -3
+        
+            self._PosX = x
+            self._PosY = y
+            self._Height = h
+            
+            aa_round_rect(self._Parent._CanvasHWND,  
+                          (x,y,self._Width-4,h),self._BackgroundColor,4,0,self._BackgroundColor)
+
+
+class PageListItem(InfoPageListItem):
+    _PosX = 0
+    _PosY = 0
+    _Width = 0
+    _Height = 30
+
+    _Labels = {}
+    _Icons  = {}
+    _Fonts  = {}
+
+    _LinkObj = None
+
+    _Active  = False
+    _Value = ""
+    
+    def Draw(self):
+        
+        self._Labels["Text"]._PosY = self._PosY+ (self._Height-  self._Labels["Text"]._Height)/2
+        
+        if self._Active == True:
+            self._Parent._Icons["done"].NewCoord( self._Parent._Width-30,self._PosY+5)
+            self._Parent._Icons["done"].Draw()
+            
+        self._Labels["Text"].Draw(self._Active)
+            
+        if "Small" in self._Labels:
+            self._Labels["Small"]._PosX = self._Width - self._Labels["Small"]._Width -10
+            self._Labels["Small"]._PosY = self._PosY + (self._Height-  self._Labels["Small"]._Height)/2
+            self._Labels["Small"].Draw()
+        
+        pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),(self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)        
+    
+class LanguagesPage(Page):
+    _FootMsg =  ["Nav","","","Back","Select"]
+    _MyList = []
+    _ListFont = MyLangManager.TrFont("notosanscjk15")
+    
+    _AList = {}
+
+    _Scrolled = 0
+    
+    _BGwidth = 320
+    _BGheight = 240-24-20
+
+    _DrawOnce = False
+    _Scroller = None
+    _InfoPage = None
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+
+    def GenList(self):
+        
+        self._MyList = []
+        
+        start_x  = 0
+        start_y  = 0
+        last_height = 0
+
+        files_path = [os.path.basename(x) for x in sorted(glob.glob('langs/*.ini'))]
+        
+        for i,u in enumerate( files_path ):            
+            #print(i,u)
+            li = PageListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + last_height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFont
+            li._Active = False
+            li._Value = u.decode("utf8")
+            lang_name = u.split("_")[1]
+            lang_name = lang_name.split(".")[0]
+            
+            li.Init( lang_name.decode("utf8") )
+            
+            last_height += li._Height
+            
+            self._MyList.append(li)
+            
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._HWND = self._Screen._CanvasHWND
+                self._CanvasHWND = pygame.Surface( (self._Screen._Width,self._BGheight) )
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+        done = IconItem()
+        done._ImgSurf = MyIconPool.GiveIconSurface("done")
+        done._MyType = ICON_TYPES["STAT"]
+        done._Parent = self
+        self._Icons["done"] = done
+
+        ps = ListPageSelector()
+        ps._Parent = self
+        self._Ps = ps
+        self._PsIndex = 0
+
+        self.GenList()
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        self._Scroller.SetCanvasHWND(self._HWND)
+
+        
+    def ScrollDown(self):
+        if len(self._MyList) == 0:
+            return
+        self._PsIndex +=1
+        if self._PsIndex >= len(self._MyList):
+            self._PsIndex = len(self._MyList) -1
+
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._PosY +cur_li._Height > self._Height:
+            for i in range(0,len(self._MyList)):
+                self._MyList[i]._PosY -= self._MyList[i]._Height
+    
+    def ScrollUp(self):
+        if len(self._MyList) == 0:
+            return
+        self._PsIndex -= 1
+        if self._PsIndex < 0:
+            self._PsIndex = 0
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._PosY < 0:
+            for i in range(0, len(self._MyList)):
+                self._MyList[i]._PosY += self._MyList[i]._Height
+    
+
+    def Click(self):
+        if len(self._MyList) == 0:
+            return
+        
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._Active == True:
+            return
+        
+        for i in self._MyList:
+            i._Active = False
+
+        cur_li._Active = True
+        print(cur_li._Value)
+        with open(".lang","w") as f:
+            f.write(cur_li._Value)
+        
+        self._Screen._MsgBox.SetText("Applying")
+        self._Screen._MsgBox.Draw()
+        self._Screen.SwapAndShow()
+        
+        MyLangManager.UpdateLang()
+        
+        pygame.event.post( pygame.event.Event(RESTARTUI, message="")) ##Restart Launcher
+        
+        pygame.time.delay(1000)
+        
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+    def OnLoadCb(self):
+        self._Scrolled = 0
+        self._PosY = 0
+        self._DrawOnce = False
+        with open(".lang", "r") as f:
+            thelang = f.read()
+
+        thelang = thelang.strip()
+
+        if thelang == "":
+            thelang = "English"
+
+        for i in self._MyList:
+            if thelang in i._Value:
+                i._Active = True
+        
+    def OnReturnBackCb(self):
+        pass
+        """
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        """
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+            self.Click()
+            
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+    
+    def Draw(self):
+
+        self.ClearCanvas()
+        if len(self._MyList) == 0:
+            return
+        
+        else:
+            if len(self._MyList) * PageListItem._Height > self._Height:
+                self._Ps._Width = self._Width - 11
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+                    if i._PosY < 0:
+                        continue
+                    i.Draw()
+                self._Scroller.UpdateSize( len(self._MyList)*PageListItem._Height, self._PsIndex*PageListItem._Height)
+                self._Scroller.Draw()
+                
+            else:
+                self._Ps._Width = self._Width
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+                    if i._PosY < 0:
+                        continue
+                    i.Draw()                
+
+        if self._HWND != None:
+            self._HWND.fill(MySkinManager.GiveColor("White"))
+            
+            self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) )
+            
+
+class APIOBJ(object):
+
+    _Page = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = LanguagesPage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="Languages"
+        self._Page.Init()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 302 - 0
Menu/GameShell/10_Settings/Lima/__init__.py

@@ -0,0 +1,302 @@
+# -*- coding: utf-8 -*- 
+import os
+import pygame
+import platform
+#import commands
+import glob
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES,RESTARTUI
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect,FileExists,ArmSystem
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.icon_item  import IconItem
+from UI.multilabel import MultiLabel
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+from UI.info_page_list_item import InfoPageListItem
+from UI.info_page_selector  import InfoPageSelector
+
+import config
+
+class ListPageSelector(InfoPageSelector):
+    def Draw(self):
+        idx = self._Parent._PsIndex
+        
+        if idx < len(self._Parent._MyList):
+            x = self._Parent._MyList[idx]._PosX+2 ## ++
+            y = self._Parent._MyList[idx]._PosY+1
+            h = self._Parent._MyList[idx]._Height -3
+        
+            self._PosX = x
+            self._PosY = y
+            self._Height = h
+            
+            aa_round_rect(self._Parent._CanvasHWND,  
+                          (x,y,self._Width-4,h),self._BackgroundColor,4,0,self._BackgroundColor)
+
+
+class PageListItem(InfoPageListItem):
+    _PosX = 0
+    _PosY = 0
+    _Width = 0
+    _Height = 30
+
+    _Labels = {}
+    _Icons  = {}
+    _Fonts  = {}
+
+    _LinkObj = None
+
+    _Active  = False
+    _Value = ""
+    
+    def Draw(self):
+        
+        self._Labels["Text"]._PosY = self._PosY+ (self._Height-  self._Labels["Text"]._Height)/2
+        
+        if self._Active == True:
+            self._Parent._Icons["done"].NewCoord( self._Parent._Width-30,self._PosY+5)
+            self._Parent._Icons["done"].Draw()
+            
+        self._Labels["Text"].Draw(self._Active)
+            
+        if "Small" in self._Labels:
+            self._Labels["Small"]._PosX = self._Width - self._Labels["Small"]._Width -10
+            self._Labels["Small"]._PosY = self._PosY + (self._Height-  self._Labels["Small"]._Height)/2
+            self._Labels["Small"].Draw()
+        
+        pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),(self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)        
+    
+class GPUDriverPage(Page):
+    _FootMsg =  ["Nav","","","Back","Select"]
+    _MyList = []
+    _ListFont = MyLangManager.TrFont("notosanscjk12")
+    
+    _AList = {}
+
+    _Scrolled = 0
+    
+    _BGwidth = 320
+    _BGheight = 240-24-20
+
+    _DrawOnce = False
+    _Scroller = None
+    _InfoPage = None
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+
+    def GenList(self):
+        
+        self._MyList = []
+        
+        start_x  = 0
+        start_y  = 0
+        last_height = 0
+
+        drivers = [["fbturbo","FBTURBO driver (Software Rendering)"],
+                    ["modesetting","LIMA driver (Experimental GPU Rendering)"]]
+                
+        
+        for i,u in enumerate( drivers ):            
+            #print(i,u)
+            li = PageListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + last_height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFont
+            li._Active = False
+            li._Value = u[0]
+            li.Init( u[1] )
+            
+            last_height += li._Height
+            
+            self._MyList.append(li)
+            
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._HWND = self._Screen._CanvasHWND
+                self._CanvasHWND = pygame.Surface( (self._Screen._Width,self._BGheight) )
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+        done = IconItem()
+        done._ImgSurf = MyIconPool.GiveIconSurface("done")
+        done._MyType = ICON_TYPES["STAT"]
+        done._Parent = self
+        self._Icons["done"] = done
+
+        ps = ListPageSelector()
+        ps._Parent = self
+        self._Ps = ps
+        self._PsIndex = 0
+
+        self.GenList()
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        self._Scroller.SetCanvasHWND(self._HWND)
+
+    def Click(self):
+        if self._PsIndex > len(self._MyList) -1:
+            return
+        
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._Active == True:
+            return
+
+        print(cur_li._Value)
+        
+        if "arm" in platform.machine():
+            for i in self._MyList:
+                i._Active = False
+            
+            cur_li._Active = True
+            self._Screen._MsgBox.SetText("Applying")
+            self._Screen._MsgBox.Draw()
+            self._Screen.SwapAndShow()
+            
+            if "modesetting" in cur_li._Value: ## enable lima
+                os.system("touch %s/.lima" % os.path.expanduser('~') )
+                ArmSystem("sudo mv /usr/lib/xorg/modules/drivers/modesetting_drv.so.lima  /usr/lib/xorg/modules/drivers/modesetting_drv.so")
+                ArmSystem("sudo sed -i '/^#.*lima/s/^#//' /etc/ld.so.conf.d/00-arm-linux-gnueabihf.conf")
+                ArmSystem("sudo ldconfig")
+            else: #disable lima
+                os.system("rm %s/.lima" % os.path.expanduser('~') )
+                ArmSystem("sudo mv /usr/lib/xorg/modules/drivers/modesetting_drv.so /usr/lib/xorg/modules/drivers/modesetting_drv.so.lima")
+                ArmSystem("sudo sed -i 's/^[^#]*lima/#&/' /etc/ld.so.conf.d/00-arm-linux-gnueabihf.conf")
+                ArmSystem("sudo ldconfig")
+            
+            pygame.time.delay(800)
+            os.system("sudo reboot")
+        
+        else:
+            self._Screen._MsgBox.SetText("Do it in GameShell")
+            self._Screen._MsgBox.Draw()
+            self._Screen.SwapAndShow()
+        
+    def OnLoadCb(self):
+        self._Scrolled = 0
+        self._PosY = 0
+        self._DrawOnce = False
+        
+        ## grep Driver /etc/xorg.conf | tr -s " " | cut -d " " -f3
+        ## "fbturbo"
+        ## "modesetting"
+        thedrv = ""
+        
+        if "arm" in platform.machine():
+            if FileExists("%s/.lima" % os.path.expanduser('~')):
+                thedrv = "modesetting"
+            else:
+                thedrv = "fbturbo"
+        
+        if thedrv == "":
+                thedrv = "fbturbo"
+        
+        for i in self._MyList:
+            i._Active = False
+        
+        for i in self._MyList:
+            if thedrv in i._Value:
+                i._Active = True
+        
+    def OnReturnBackCb(self):
+        pass
+        """
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        """
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+            self.Click()
+            
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+    
+    def Draw(self):
+
+        self.ClearCanvas()
+        if len(self._MyList) == 0:
+            return
+        
+        else:
+            if len(self._MyList) * PageListItem._Height > self._Height:
+                self._Ps._Width = self._Width - 11
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+                    if i._PosY < 0:
+                        continue
+                    i.Draw()
+                self._Scroller.UpdateSize( len(self._MyList)*PageListItem._Height, self._PsIndex*PageListItem._Height)
+                self._Scroller.Draw()
+                
+            else:
+                self._Ps._Width = self._Width
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+                    if i._PosY < 0:
+                        continue
+                    i.Draw()                
+
+        if self._HWND != None:
+            self._HWND.fill(MySkinManager.GiveColor("White"))
+            
+            self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) )
+            
+
+class APIOBJ(object):
+
+    _Page = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = GPUDriverPage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="GPU Driver Switch"
+        self._Page.Init()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 264 - 0
Menu/GameShell/10_Settings/Notification/__init__.py

@@ -0,0 +1,264 @@
+# -*- coding: utf-8 -*-
+
+import os
+import platform
+import pygame
+import glob
+#import math
+import  commands
+
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+#import gobject
+#from wicd import misc 
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect,FileExists,IsExecutable
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.icon_item  import IconItem
+from UI.multi_icon_item import MultiIconItem
+from UI.lang_manager  import MyLangManager
+from UI.multilabel import MultiLabel
+from UI.info_page_list_item import InfoPageListItem
+from UI.info_page_selector  import InfoPageSelector
+from UI.skin_manager import MySkinManager
+
+class NotifyJobListItem(InfoPageListItem):
+    
+    _CanvasHWND = None
+    
+    def Init(self,text):
+
+        #self._Fonts["normal"] = fonts["veramono12"]
+        self._CanvasHWND = self._Parent._CanvasHWND
+        
+        l = Label()
+        l._PosX = 10
+        l.SetCanvasHWND(self._Parent._CanvasHWND)
+
+        l.Init(text,self._Fonts["normal"])
+        self._Labels["Text"] = l    
+        
+        done_icon = IconItem()
+        done_icon._ImgSurf = MyIconPool.GiveIconSurface("done")
+        done_icon._CanvasHWND = self._Parent._CanvasHWND
+        done_icon._Parent = self
+        
+        self._Icons["done"] = done_icon
+    
+    def Draw(self):
+        if self._ReadOnly == False:
+            self._Labels["Text"].SetColor(MySkinManager.GiveColor("ReadOnlyText"))
+        else:
+            self._Labels["Text"].SetColor(MySkinManager.GiveColor("Text"))
+
+        
+        self._Labels["Text"]._PosX = self._Labels["Text"]._PosX + self._PosX
+        self._Labels["Text"]._PosY = self._PosY + (self._Height - self._Labels["Text"]._Height)/2
+        self._Labels["Text"].Draw()
+        self._Labels["Text"]._PosX = self._Labels["Text"]._PosX - self._PosX
+
+        if "Small" in self._Labels:
+            self._Labels["Small"]._PosX = self._Width - self._Labels["Small"]._Width-5
+            
+            self._Labels["Small"]._PosY = self._PosY + (self._Height - self._Labels["Small"]._Height)/2
+            self._Labels["Small"].Draw()
+        
+        if self._ReadOnly:
+            self._Icons["done"].NewCoord(self._Width - 25,5)
+            self._Icons["done"].Draw()
+        
+        pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),(self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)    
+    
+    
+class NotificationPage(Page):
+    _FootMsg =  ["Nav","","","Back","Toggle"]
+    _MyList = []
+    _ListFontObj = MyLangManager.TrFont("varela13")
+    
+    _AList = {}
+
+    _Scrolled = 0
+    
+    _BGwidth = 320
+    _BGheight = 240-24-20
+
+    _DrawOnce = False
+    _Scroller = None
+
+    _EasingDur = 30
+    
+    _GSNOTIFY_JOBS = "gsnotify/Jobs"
+    _GSNOTIFY_SOCKET="/tmp/gsnotify.sock"
+    _Config =None
+    _AllowedExts = [".sh",".lsp",".lua",".bin",".py",".js"]
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+        
+        if "arm" in platform.machine():
+            os.system( "git config --global core.filemode false" )
+        
+    def GenList(self):
+
+        self._MyList = []
+        ## map ini to self._AList
+        files_path = glob.glob(self._GSNOTIFY_JOBS+"/*")
+        
+                
+        start_x  = 10
+        start_y  = 0
+        counter = 0 
+        for i,v in enumerate( files_path):
+            filename, file_extension = os.path.splitext(v)
+            alias_file = filename + ".alias"
+            
+            if file_extension in self._AllowedExts:
+                li = NotifyJobListItem()
+                li._Parent = self
+                li._PosX   = start_x
+                li._PosY   = start_y + counter*InfoPageListItem._Height
+                li._Width  = Width-10
+                li._Fonts["normal"] = self._ListFontObj
+                li._Fonts["small"] = MySkinManager.GiveFont("varela12")
+                
+                if IsExecutable(v):
+                    li._ReadOnly = True
+                
+                if os.path.isfile(alias_file):
+                    fp = open(alias_file, "r")
+                    alias = fp.read()
+                    alias = alias.strip()
+                    label_text = alias.decode("utf8")
+                    li.Init( label_text )
+                    fp.close()
+                else:
+                    li.Init( os.path.basename(v) )
+                li._Flag = v
+                ##li.SetSmallText( v )
+                
+                self._MyList.append(li)
+                counter += 1
+    
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._CanvasHWND = self._Screen._CanvasHWND
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+        ps = InfoPageSelector()
+        ps._PosX = 11
+        ps._Parent = self
+        ps._Width = self._Width-10
+        self._Ps = ps
+        self._PsIndex = 0
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = 2
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        
+    def Click(self):
+        if len(self._MyList) == 0:
+            return
+        
+        cur_li = self._MyList[self._PsIndex]
+        #print("Click ",cur_li._Flag)
+        if IsExecutable(cur_li._Flag):
+            os.system("chmod -x "+cur_li._Flag)
+        else:
+            os.system("chmod +x "+cur_li._Flag)
+        
+        self.GenList()
+        
+        
+    def OnLoadCb(self):
+        self._Scrolled = 0
+        self._PosY = 0
+        self._DrawOnce = False    
+        self.GenList()
+    
+    def OnReturnBackCb(self):
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+            
+            self._Screen._MsgBox.SetText("Applying")
+            self._Screen._MsgBox.Draw()
+            self._Screen.SwapAndShow()
+            
+            pygame.time.delay(638)
+            
+            self.Click()
+            
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+ 
+
+    def Draw(self):
+        self.ClearCanvas()
+        self._Ps.Draw()
+
+        if len(self._MyList) > 0:
+            for i in self._MyList:
+                i.Draw()
+        
+            self._Scroller.UpdateSize( len(self._MyList)*InfoPageListItem._Height,
+                                   self._PsIndex*InfoPageListItem._Height) 
+            self._Scroller.Draw()
+        
+        
+
+
+class APIOBJ(object):
+
+    _Page = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = NotificationPage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="Notify"
+        self._Page.Init()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 90 - 0
Menu/GameShell/10_Settings/PowerOFF/__init__.py

@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+
+#UI lib
+from UI.constants    import RUNSYS
+from UI.keys_def     import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.confirm_page import ConfirmPage
+from UI.lang_manager import MyLangManager
+from UI.skin_manager import MySkinManager
+
+import config
+
+class PowerOffConfirmPage(ConfirmPage):
+    
+    _ConfirmText = MyLangManager.Tr("Confirm Power OFF?")
+    
+    def CheckBattery(self):
+        try:
+            f = open(config.Battery)
+        except IOError:
+            print( "PowerOFF open %s failed" % config.Battery)
+            return 0
+        else:
+            with f:
+                bat_uevent = {}
+                content = f.readlines()
+                content = [x.strip() for x in content]
+                for i in content:
+                    pis = i.split("=")
+                    if len(pis) > 1:
+                        bat_uevent[pis[0]] = pis[1]
+
+                if "POWER_SUPPLY_CAPACITY" in bat_uevent:
+                    cur_cap = int(bat_uevent["POWER_SUPPLY_CAPACITY"])
+                else:
+                    cur_cap = 0
+                
+                return cur_cap
+                    
+        return 0
+        
+    def KeyDown(self,event):
+        
+        if IsKeyMenuOrB(event.key):
+            
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+            if self.CheckBattery() < 20:
+                cmdpath = "feh --bg-center %s;" % MySkinManager.GiveWallpaper("gameover.png")
+            else:
+                cmdpath = "feh --bg-center %s;" % MySkinManager.GiveWallpaper("seeyou.png")
+            
+            cmdpath += "sleep 3;"
+            
+            #cmdpath += "echo 'halt -p' > /tmp/halt_cmd"
+            
+            cmdpath += "sudo halt -p"
+            pygame.event.post( pygame.event.Event(RUNSYS, message=cmdpath))
+
+
+
+class APIOBJ(object):
+
+    _StoragePage = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = PowerOffConfirmPage()
+
+        self._Page._Screen = main_screen
+        self._Page._Name ="Power OFF"
+        self._Page.Init()
+        
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    

+ 555 - 0
Menu/GameShell/10_Settings/PowerOptions/__init__.py

@@ -0,0 +1,555 @@
+# -*- coding: utf-8 -*- 
+import os
+import pygame
+#import math
+#mport subprocess
+
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+#import gobject
+#from wicd import misc 
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES,POWEROPT
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.icon_item  import IconItem
+from UI.multilabel import MultiLabel
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+
+import config
+
+class ListPageSelector(PageSelector):
+    _BackgroundColor = MySkinManager.GiveColor('Front')
+
+    def __init__(self):
+        self._PosX = 0
+        self._PosY = 0
+        self._Height = 0
+        self._Width  = Width
+
+    def AnimateDraw(self,x2,y2):
+        pass
+
+    def Draw(self):
+        idx = self._Parent._PsIndex
+        
+        if idx < len(self._Parent._MyList):
+            x = self._Parent._MyList[idx]._PosX+2
+            y = self._Parent._MyList[idx]._PosY+1
+            h = self._Parent._MyList[idx]._Height -3
+        
+            self._PosX = x
+            self._PosY = y
+            self._Height = h
+            
+            aa_round_rect(self._Parent._CanvasHWND,  
+                          (x,y,self._Width-4,h),self._BackgroundColor,4,0,self._BackgroundColor)
+
+
+class PageListItem(object):
+    _PosX = 0
+    _PosY = 0
+    _Width = 0
+    _Height = 30
+
+    _Labels = {}
+    _Icons  = {}
+    _Fonts  = {}
+
+    _LinkObj = None
+
+    _Active  = False
+    _Value = ""
+    
+    def __init__(self):
+        self._Labels = {}
+        self._Icons  = {}
+        self._Fonts  = {}
+
+    def SetSmallText(self,text):
+        
+        l = Label()
+        l._PosX = 40
+        l.SetCanvasHWND(self._Parent._CanvasHWND)
+        l.Init(text,self._Fonts["small"])
+        self._Labels["Small"] = l
+    
+    def Init(self,text):
+
+        l = Label()
+        l._PosX = 10
+        l.SetCanvasHWND(self._Parent._CanvasHWND)
+        text = MyLangManager.Tr(text)
+        l.Init(text,self._Fonts["normal"])
+        self._Labels["Text"] = l
+        
+    def Draw(self):
+        
+        self._Labels["Text"]._PosY = self._PosY+ (self._Height-  self._Labels["Text"]._Height)/2
+        
+        if self._Active == True:
+            self._Parent._Icons["done"].NewCoord( self._Parent._Width-30,self._PosY+5)
+            self._Parent._Icons["done"].Draw()
+            
+        self._Labels["Text"].Draw(self._Active)
+            
+        if "Small" in self._Labels:
+            self._Labels["Small"]._PosX = self._Width - self._Labels["Small"]._Width -10
+            self._Labels["Small"]._PosY = self._PosY + (self._Height-  self._Labels["Small"]._Height)/2
+            self._Labels["Small"].Draw()
+        
+        pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),(self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)        
+    
+
+class InfoPage(Page):
+    _FootMsg =  ["Nav","","","Back",""]
+    _MyList = []
+    _ListFontObj = MyLangManager.TrFont("varela15")
+    _AList = {}
+
+    _Time1 = 40
+    _Time2 = 120
+    _Time3 = 300
+
+    def ConvertSecToMin(self, secs):
+        sec_str = ""
+        min_str = ""
+        if secs > 60:
+            m = int(secs/60)
+            s = secs % 60
+            if m > 1:
+                min_str =  ("%d "+MyLangManager.Tr("minutes")+" ") % m
+            else:
+                min_str =  ("%d "+MyLangManager.Tr("minute")+" ") % m
+            
+            if s == 1:
+                sec_str = ("%d "+MyLangManager.Tr("second")) % s
+            elif s > 1:
+                sec_str = ("%d "+MyLangManager.Tr("seconds")) % s
+        elif secs > 0:
+            if secs > 1:
+                sec_str = ("%d "+MyLangManager.Tr("seconds")) % secs
+            else:
+                sec_str = ("%d "+MyLangManager.Tr("second")) % secs
+        
+        elif secs == 0:
+            sec_str = MyLangManager.Tr("Never")
+        
+        return min_str + sec_str
+
+    def RefreshList(self):
+        ## after GenList ,reuse
+        self._AList["time1"]["value"] = self.ConvertSecToMin(self._Time1)
+        self._AList["time2"]["value"] = self.ConvertSecToMin(self._Time2)
+        self._AList["time3"]["value"] = self.ConvertSecToMin(self._Time3)
+
+        for i,v in enumerate( self._AList ):
+            self._MyList[i].SetSmallText(  self._AList[v]["value"] )
+        
+    def GenList(self):
+
+        time1 = {}
+        time1["key"] = "time1"
+        if self._Time1 == 0:
+            time1["value"] = MyLangManager.Tr("Never")
+        else:
+            time1["value"] = "%d secs" % self._Time1
+        time1["label"] = "Screen dimming"
+        
+        time2 = {}
+        time2["key"] = "time2"
+        if self._Time2 == 0:
+            time2["value"] = MyLangManager.Tr("Never")
+        else:
+            time2["value"] = "%d secs" % self._Time2
+            
+        time2["label"] = "Screen OFF"
+
+        time3 = {}
+        time3["key"] = "time3"
+        
+        if self._Time3 == 0:
+            time3["value"] = MyLangManager.Tr("Never")
+        else:
+            time3["value"] = "%d secs" % self._Time3
+        time3["label"] = "Power OFF"
+        
+        self._AList["time1"] = time1
+        self._AList["time2"] = time2
+        self._AList["time3"] = time3
+        
+        self._MyList = []
+        
+        start_x  = 0
+        start_y  = 0
+        
+        for i,v in enumerate( self._AList):
+            #print(v)
+            li = PageListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + i*PageListItem._Height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFontObj
+            li._Fonts["small"] = MyLangManager.TrFont("varela12")
+            
+            if self._AList[v]["label"] != "":
+                li.Init( self._AList[v]["label"] )
+            else:
+                li.Init( self._AList[v]["key"] )
+
+            li._Flag = self._AList[v]["key"]
+
+            li.SetSmallText( self._AList[v]["value"] )
+            
+            self._MyList.append(li)
+            
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._CanvasHWND = self._Screen._CanvasHWND
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+        ps = ListPageSelector()
+        ps._Parent = self
+        self._Ps = ps
+        self._PsIndex = 0
+        
+        self.GenList()
+
+        
+    def ScrollUp(self):
+        if len(self._MyList) == 0:
+            return
+        self._PsIndex -= 1
+        if self._PsIndex < 0:
+            self._PsIndex = 0
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._PosY < 0:
+            for i in range(0, len(self._MyList)):
+                self._MyList[i]._PosY += self._MyList[i]._Height
+        
+
+    def ScrollDown(self):
+        if len(self._MyList) == 0:
+            return
+        self._PsIndex +=1
+        if self._PsIndex >= len(self._MyList):
+            self._PsIndex = len(self._MyList) -1
+
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._PosY +cur_li._Height > self._Height:
+            for i in range(0,len(self._MyList)):
+                self._MyList[i]._PosY -= self._MyList[i]._Height
+
+    def Click(self):
+        cur_li = self._MyList[self._PsIndex]
+        print(cur_li._Flag)        
+
+        
+    def OnLoadCb(self):
+        self.RefreshList()
+
+    def OnReturnBackCb(self):
+        pass
+        """
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        """
+    
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+                                        
+    def Draw(self):
+        self.ClearCanvas()
+        self._Ps.Draw()
+
+        for i in self._MyList:
+            i.Draw()
+
+class PowerOptionsPage(Page):
+    _FootMsg =  ["Nav","Detail","","Back","Select"]
+    _MyList = []
+    _ListFont = MyLangManager.TrFont("notosanscjk15")
+    
+    _AList = {}
+
+    _Scrolled = 0
+    
+    _BGwidth = 320
+    _BGheight = 240-24-20
+
+    _DrawOnce = False
+    _Scroller = None
+    _InfoPage = None
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+
+    def GenList(self):
+        
+        self._MyList = []
+        
+        start_x  = 0
+        start_y  = 0
+        last_height = 0
+
+        
+        supersaving = {}
+        supersaving["key"] = "super"
+        supersaving["label"] = "Power saving"
+        supersaving["value"] = "supersaving"
+
+        powersaving = {}
+        powersaving["key"] = "saving"
+        powersaving["label"] = "Balanced"
+        powersaving["value"] = "powersaving"
+
+        balance_saving = {}
+        balance_saving["key"] = "balance"
+        balance_saving["label"] = "Performance"
+        balance_saving["value"] = "balance_saving"
+
+        server_saving = {}
+        server_saving["key"] = "server"
+        server_saving["label"] = "Server"
+        server_saving["value"] = "server"
+        
+        
+        self._AList["supersaving"] = supersaving
+        self._AList["powersaving"] = powersaving
+        self._AList["server"]      = server_saving
+        self._AList["balance_saving"] = balance_saving
+        
+        for i,u in enumerate( ["supersaving","powersaving","server","balance_saving"] ):
+            if u not in self._AList:
+                continue
+            
+            v = self._AList[u]
+            
+            li = PageListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + last_height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFont
+            li._Active = False
+            li._Value = self._AList[u]["value"]
+            
+            if self._AList[u]["label"] != "":
+                li.Init(  self._AList[u]["label"] )
+            else:
+                li.Init( self._AList[u]["key"] )
+            
+            last_height += li._Height
+            
+            self._MyList.append(li)
+            
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._HWND = self._Screen._CanvasHWND
+                self._CanvasHWND = pygame.Surface( (self._Screen._Width,self._BGheight) )
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+        done = IconItem()
+        done._ImgSurf = MyIconPool.GiveIconSurface("done")
+        done._MyType = ICON_TYPES["STAT"]
+        done._Parent = self
+        self._Icons["done"] = done
+
+        ps = ListPageSelector()
+        ps._Parent = self
+        self._Ps = ps
+        self._PsIndex = 0
+
+        self.GenList()
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        self._Scroller.SetCanvasHWND(self._HWND)
+
+        self._InfoPage = InfoPage()
+        self._InfoPage._Screen = self._Screen
+        self._InfoPage._Name   = "Power option detail"
+        self._InfoPage.Init()
+
+    def Click(self):
+        if len(self._MyList) == 0:
+            return
+        
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._Active == True:
+            return
+        
+        for i in self._MyList:
+            i._Active = False
+
+        cur_li._Active = True
+        print(cur_li._Value)
+        with open(".powerlevel","w") as f:
+            f.write(cur_li._Value)
+
+        config.PowerLevel = cur_li._Value
+
+        if config.PowerLevel!= "supersaving":
+            os.system("sudo iw wlan0 set power_save off > /dev/null")
+        else:
+            os.system("sudo iw wlan0 set power_save on > /dev/null")
+        
+        self._Screen._MsgBox.SetText("Applying")
+        self._Screen._MsgBox.Draw()
+        self._Screen.SwapAndShow()
+
+        pygame.event.post( pygame.event.Event(POWEROPT, message=""))
+        
+        pygame.time.delay(1000)
+        
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+    def OnLoadCb(self):
+        self._Scrolled = 0
+        self._PosY = 0
+        self._DrawOnce = False
+        with open(".powerlevel", "r") as f:
+            powerlevel = f.read()
+
+        powerlevel = powerlevel.strip()
+
+        if powerlevel == "":
+            powerlevel = "balance_saving"
+
+        for i in self._MyList:
+            if i._Value == powerlevel:
+                i._Active = True
+        
+    def OnReturnBackCb(self):
+        pass
+        """
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        """
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+            self.Click()
+            
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if event.key == CurKeys["Y"]:
+            cur_li = self._MyList[self._PsIndex]
+            time1 = config.PowerLevels[cur_li._Value][0]
+            time2 = config.PowerLevels[cur_li._Value][1]
+            time3 = config.PowerLevels[cur_li._Value][2]
+            
+            self._InfoPage._Time1 = time1
+            self._InfoPage._Time2 = time2
+            self._InfoPage._Time3 = time3
+            
+            self._Screen.PushPage(self._InfoPage)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()            
+    
+    def Draw(self):
+
+        self.ClearCanvas()
+        if len(self._MyList) == 0:
+            return
+        
+        else:
+            if len(self._MyList) * PageListItem._Height > self._Height:
+                self._Ps._Width = self._Width - 11
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+                    if i._PosY < 0:
+                        continue
+                    i.Draw()
+                self._Scroller.UpdateSize( len(self._MyList)*PageListItem._Height, self._PsIndex*PageListItem._Height)
+                self._Scroller.Draw()
+                
+            else:
+                self._Ps._Width = self._Width
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+                    if i._PosY < 0:
+                        continue
+                    i.Draw()                
+
+        if self._HWND != None:
+            self._HWND.fill(MySkinManager.GiveColor("White"))
+            
+            self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) )
+            
+        
+        
+
+
+class APIOBJ(object):
+
+    _Page = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = PowerOptionsPage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="Power Options"
+        self._Page.Init()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 294 - 0
Menu/GameShell/10_Settings/Skins/__init__.py

@@ -0,0 +1,294 @@
+# -*- coding: utf-8 -*- 
+import os
+import pygame
+#import commands
+import glob
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES,RESTARTUI
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect,FileExists
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.icon_item  import IconItem
+from UI.multilabel import MultiLabel
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+from UI.info_page_list_item import InfoPageListItem
+from UI.info_page_selector  import InfoPageSelector
+
+import config
+
+class ListPageSelector(InfoPageSelector):
+    def Draw(self):
+        idx = self._Parent._PsIndex
+        
+        if idx < len(self._Parent._MyList):
+            x = self._Parent._MyList[idx]._PosX+2 ## ++
+            y = self._Parent._MyList[idx]._PosY+1
+            h = self._Parent._MyList[idx]._Height -3
+        
+            self._PosX = x
+            self._PosY = y
+            self._Height = h
+            
+            aa_round_rect(self._Parent._CanvasHWND,  
+                          (x,y,self._Width-4,h),self._BackgroundColor,4,0,self._BackgroundColor)
+
+
+class PageListItem(InfoPageListItem):
+    _PosX = 0
+    _PosY = 0
+    _Width = 0
+    _Height = 30
+
+    _Labels = {}
+    _Icons  = {}
+    _Fonts  = {}
+
+    _LinkObj = None
+
+    _Active  = False
+    _Value = ""
+    
+    def Draw(self):
+        
+        self._Labels["Text"]._PosY = self._PosY+ (self._Height-  self._Labels["Text"]._Height)/2
+        
+        if self._Active == True:
+            self._Parent._Icons["done"].NewCoord( self._Parent._Width-30,self._PosY+5)
+            self._Parent._Icons["done"].Draw()
+            
+        self._Labels["Text"].Draw(self._Active)
+            
+        if "Small" in self._Labels:
+            self._Labels["Small"]._PosX = self._Width - self._Labels["Small"]._Width -10
+            self._Labels["Small"]._PosY = self._PosY + (self._Height-  self._Labels["Small"]._Height)/2
+            self._Labels["Small"].Draw()
+        
+        pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),(self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)        
+    
+class SkinsPage(Page):
+    _FootMsg =  ["Nav","","Scan","Back","Select"]
+    _MyList = []
+    _ListFont = MyLangManager.TrFont("notosanscjk15")
+    
+    _AList = {}
+
+    _Scrolled = 0
+    
+    _BGwidth = 320
+    _BGheight = 240-24-20
+
+    _DrawOnce = False
+    _Scroller = None
+    _InfoPage = None
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+
+    def GenList(self):
+        self._MyList = []
+        
+        start_x  = 0
+        start_y  = 0
+        last_height = 0
+
+
+        skins = [["../skin/default","Default"]]
+        files_path = glob.glob("/home/cpi/skins/*")
+        
+        for i ,v in enumerate(files_path):
+            if os.path.isdir(v):
+                bname = os.path.basename(v)
+                print(v,bname)
+                skins.append([v,bname])
+        
+        for i,u in enumerate( skins ):            
+            #print(i,u)
+            li = PageListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + last_height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFont
+            li._Active = False
+            li._Value = u[0]
+            li.Init( u[1] )
+            
+            last_height += li._Height
+            
+            self._MyList.append(li)
+            
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._HWND = self._Screen._CanvasHWND
+                self._CanvasHWND = pygame.Surface( (self._Screen._Width,self._BGheight) )
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+        done = IconItem()
+        done._ImgSurf = MyIconPool.GiveIconSurface("done")
+        done._MyType = ICON_TYPES["STAT"]
+        done._Parent = self
+        self._Icons["done"] = done
+
+        ps = ListPageSelector()
+        ps._Parent = self
+        self._Ps = ps
+        self._PsIndex = 0
+
+        self.GenList()
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        self._Scroller.SetCanvasHWND(self._HWND)
+
+    def Click(self):
+        if len(self._MyList) == 0:
+            return
+        
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._Active == True:
+            return
+
+        print(cur_li._Value)
+        
+        for i in self._MyList:
+            i._Active = False
+            
+        cur_li._Active = True
+        self._Screen._MsgBox.SetText("Applying")
+        self._Screen._MsgBox.Draw()
+        self._Screen.SwapAndShow()
+            
+        if "../skin/default" in cur_li._Value:
+            os.system("rm %s/.gameshell_skin" % os.path.expanduser('~') )
+        else:
+            os.system("echo %s > %s/.gameshell_skin" % (cur_li._Value,os.path.expanduser('~') ))
+        
+        pygame.time.delay(700)
+        pygame.event.post( pygame.event.Event(RESTARTUI, message=""))
+        
+    def OnLoadCb(self):
+        self._Scrolled = 0
+        self._PosY = 0
+        self._DrawOnce = False
+                        
+        for i in self._MyList:
+            i._Active = False
+        
+        for i in self._MyList:
+            if config.SKIN in i._Value:
+                i._Active = True
+        
+    def OnReturnBackCb(self):
+        pass
+        """
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        """
+    def KeyDown(self,event):
+    
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if IsKeyStartOrA(event.key):
+            self.Click()
+            
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["X"]:
+            self.GenList()
+            
+            for i in self._MyList:
+                i._Active = False
+        
+            for i in self._MyList:
+                if config.SKIN in i._Value:
+                    i._Active = True
+                
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()            
+    
+    def Draw(self):
+
+        self.ClearCanvas()
+        if len(self._MyList) == 0:
+            return
+        
+        else:
+            if len(self._MyList) * PageListItem._Height > self._Height:
+                self._Ps._Width = self._Width - 11
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+                    if i._PosY < 0:
+                        continue
+                    i.Draw()
+                self._Scroller.UpdateSize( len(self._MyList)*PageListItem._Height, self._PsIndex*PageListItem._Height)
+                self._Scroller.Draw()
+                
+            else:
+                self._Ps._Width = self._Width
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+                    if i._PosY < 0:
+                        continue
+                    i.Draw()                
+
+        if self._HWND != None:
+            self._HWND.fill(MySkinManager.GiveColor("White"))
+            
+            self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) )
+            
+
+class APIOBJ(object):
+
+    _Page = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = SkinsPage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="Skin selection"
+        self._Page.Init()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 0 - 0
Menu/GameShell/10_Settings/Sound/Icon\r


+ 17 - 0
Menu/GameShell/10_Settings/Sound/__init__.py

@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*- 
+
+## local UI import
+import pages
+import myvars
+
+def Init(main_screen):
+    pages.InitSoundPage(main_screen)
+
+def API(main_screen):
+    
+    if main_screen !=None:
+        main_screen.PushCurPage()
+        main_screen.SetCurPage(myvars.SoundPage)
+        main_screen.Draw()
+        main_screen.SwapAndShow()
+        

+ 6 - 0
Menu/GameShell/10_Settings/Sound/myvars.py

@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*- 
+
+import os
+import sys
+
+SoundPage = None

+ 13 - 0
Menu/GameShell/10_Settings/Sound/pages.py

@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*- 
+
+from sound_page import SoundPage
+
+import myvars
+
+def InitSoundPage(main_screen):
+
+    myvars.SoundPage = SoundPage()
+    
+    myvars.SoundPage._Screen = main_screen
+    myvars.SoundPage._Name = "Sound volume"
+    myvars.SoundPage.Init()

+ 167 - 0
Menu/GameShell/10_Settings/Sound/sound_page.py

@@ -0,0 +1,167 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+
+#from libs.roundrects import aa_round_rect
+
+import alsaaudio
+
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.icon_item import IconItem
+from UI.label  import Label
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, IsKeyMenuOrB
+from UI.slider     import Slider
+from UI.multi_icon_item import MultiIconItem
+from UI.skin_manager import MySkinManager
+
+from UI.icon_pool  import MyIconPool
+
+from libs.roundrects import aa_round_rect
+
+import myvars
+
+class SoundSlider(Slider):
+    OnChangeCB = None
+    
+    _Parent     = None
+    _VolumeLabel =None
+    
+    def __init__(self):
+        Slider.__init__(self)
+        
+    def Init(self):
+        self._Width = self._Parent._Width
+        self._Height = self._Parent._Height
+        
+        self._VolumeLabel = Label()
+        self._VolumeLabel.SetCanvasHWND(self._CanvasHWND)
+        self._VolumeLabel.Init("VOLUME",MySkinManager.GiveFont("EurostileBold13"))
+        self._VolumeLabel.SetColor(MySkinManager.GiveColor('Text'))
+        
+    def SetValue(self,vol):#pct 0-100
+        if vol  >= 0 and vol <= 100:
+            self._Value = vol
+        
+    def Further(self):
+        self._Value+=5
+
+        if self._Value > 100:
+            self._Value = 100
+        
+        if self.OnChangeCB != None:
+            if callable(self.OnChangeCB):
+                self.OnChangeCB( self._Value )
+        
+    def StepBack(self):
+        self._Value-=5
+
+        if self._Value < 0:
+            self._Value = 0
+            
+        if self.OnChangeCB != None:
+            if callable(self.OnChangeCB):
+                self.OnChangeCB( self._Value )
+    
+    def Draw(self):
+        start_x = 82
+        start_y = self._Parent._Screen._Height/2-5
+        height = 30
+        width = 4
+        seg = self._Value / 5
+
+        for i in range(0, 20):
+            rect = pygame.Rect(start_x+i*(width*2),start_y,width,height)
+            if i > seg:
+                pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Text'),rect, 1)
+                #aa_round_rect(self._CanvasHWND,rect, MySkinManager.GiveColor('Text'),1,1, MySkinManager.GiveColor('White'))
+            else:
+                pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Text'),rect, 0)   
+                #aa_round_rect(self._CanvasHWND,rect, MySkinManager.GiveColor('Text'),1,0, MySkinManager.GiveColor('White'))
+        
+        self._VolumeLabel.NewCoord(118,self._Parent._Screen._Height/2-30)
+        self._VolumeLabel.Draw(True)
+        
+        minus_box_rect = pygame.Rect(start_x- (4+6)*4,start_y,6*4,30)
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Text'),minus_box_rect, 0) 
+        
+        minus_rect     = pygame.Rect(start_x-8*4,start_y+14,2*4,2)
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('White'),minus_rect, 0) 
+        
+        plus_box_rect = pygame.Rect(start_x + 39*4 +4*4,start_y,6*4,30)
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Text'),plus_box_rect, 0) 
+        
+        cross1_rect     = pygame.Rect(start_x+39*4+4*4+2*4,start_y+14,2*4,2)
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('White'),cross1_rect, 0) 
+        cross2_rect     = pygame.Rect(start_x+39*4+4*4+2*4+3,start_y+14-3,2,2*4)
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('White'),cross2_rect, 0) 
+        
+class SoundPage(Page):
+
+    _MySlider = None
+    _FootMsg = ["Nav","","","Back","Enter"]
+
+    def Init(self):
+        self._CanvasHWND = self._Screen._CanvasHWND
+        self._Width =  self._Screen._Width
+        self._Height = self._Screen._Height
+        
+        self._MySlider = SoundSlider()
+
+        self._MySlider._Parent = self        
+        self._MySlider.SetCanvasHWND(self._CanvasHWND)
+
+        self._MySlider.OnChangeCB = self.WhenSliderDrag
+
+        self._MySlider.Init()
+        
+        try:
+            m = alsaaudio.Mixer()
+            self._MySlider.SetValue(m.getvolume()[0])
+        except Exception,e:
+            print(str(e))
+            self._MySlider.SetValue(0)
+
+
+    def OnLoadCb(self):
+        try:
+            m = alsaaudio.Mixer()
+            self._MySlider.SetValue(m.getvolume()[0])
+        except Exception,e:
+            print(str(e))
+                
+    def WhenSliderDrag(self,value): ##value 0-100
+        if value < 0 or value > 100:
+            return
+        
+        m = alsaaudio.Mixer()
+        m.setvolume(int(value))
+        
+    def KeyDown(self,event):
+        
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Right"]:
+            self._MySlider.Further()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if event.key == CurKeys["Left"]:
+            self._MySlider.StepBack()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+    def Draw(self):
+        self.ClearCanvas()
+        
+        self._MySlider.Draw()
+
+        
+
+
+    

+ 0 - 0
Menu/GameShell/10_Settings/Storage/Icon\r


+ 138 - 0
Menu/GameShell/10_Settings/Storage/__init__.py

@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+import os
+
+
+## local UI import
+from UI.page  import Page
+from UI.skin_manager import MySkinManager
+from UI.constants import ICON_TYPES,Width,Height
+from UI.icon_item import IconItem
+from UI.icon_pool import MyIconPool
+from UI.label  import Label
+from UI.util_funcs import midRect
+
+from libs.roundrects import aa_round_rect
+
+class StoragePage(Page):
+
+    _Icons = {}
+    _BGpng  = None
+    _BGwidth = 96
+    _BGheight = 73
+    _BGlabel  = None
+    _FreeLabel = None
+    
+    _BGmsg    = "%.1fGB of %.1fGB Used"
+    _DskUsg   = None
+
+    _HighColor = MySkinManager.GiveColor('High')
+    _FootMsg    = ["Nav.","","","Back",""]
+    
+    def __init__(self):
+        Page.__init__(self)
+        
+        self._Icons = {}
+
+
+    def DiskUsage(self):
+        statvfs = os.statvfs('/')
+
+        total_space = (statvfs.f_frsize * statvfs.f_blocks)/1024.0/1024.0/1024.0
+
+        avail_space = ( statvfs.f_frsize * statvfs.f_bavail) / 1024.0 / 1024.0/ 1024.0
+
+        return avail_space,total_space
+        
+    def Init(self):
+
+        self._DskUsg = self.DiskUsage()
+        
+        self._CanvasHWND = self._Screen._CanvasHWND
+        self._Width =  self._Screen._Width
+        self._Height = self._Screen._Height
+        
+        self._BGpng = IconItem()
+        self._BGpng._ImgSurf = MyIconPool.GiveIconSurface("icon_sd")
+        self._BGpng._MyType = ICON_TYPES["STAT"]
+        self._BGpng._Parent = self
+        
+        self._BGpng.AddLabel(self._BGmsg % (self._DskUsg[1]-self._DskUsg[0], self._DskUsg[1]), MySkinManager.GiveFont("varela15"))
+        self._BGpng.Adjust(0,0,self._BGwidth,self._BGheight,0)
+
+        
+        self._BGlabel = Label()
+        self._BGlabel.SetCanvasHWND(self._CanvasHWND)
+
+        usage_percent = (self._DskUsg[0]/self._DskUsg[1] )*100.0
+        
+        self._BGlabel.Init("%d%%"% int(usage_percent),MySkinManager.GiveFont("varela25"))
+        self._BGlabel.SetColor( self._HighColor )
+        
+        self._FreeLabel = Label()
+        self._FreeLabel.SetCanvasHWND(self._CanvasHWND)
+        self._FreeLabel.Init("Free",MySkinManager.GiveFont("varela13"))
+        self._FreeLabel.SetColor(self._BGlabel._Color)
+
+        
+    def OnLoadCb(self):
+        pass
+    
+    def Draw(self):
+        self.ClearCanvas()
+        
+        self._BGpng.NewCoord(self._Width/2,self._Height/2-10)
+        self._BGpng.Draw()
+        self._BGlabel.NewCoord(self._Width/2-28,self._Height/2-30)
+        self._BGlabel.Draw()
+
+        self._FreeLabel.NewCoord(self._BGlabel._PosX+10   ,self._Height/2)
+        self._FreeLabel.Draw()
+
+        #bgcolor = (238,238,238), fgcolor = (126,206,244)
+        #aa_round_rect
+        usage_percent = (self._DskUsg[0]/self._DskUsg[1] )
+        if usage_percent < 0.1:
+            usage_percent = 0.1
+
+        rect_ = midRect(self._Width/2,self._Height-30,170,17, Width,Height)
+
+        aa_round_rect(self._CanvasHWND, rect_, MySkinManager.GiveColor('Line'), 5, 0, MySkinManager.GiveColor('Line'))
+
+        
+        rect2 = midRect(self._Width/2,self._Height-30,int(170*(1.0-usage_percent)),17, Width,Height)
+
+        rect2.left = rect_.left
+        rect2.top  = rect_.top
+        
+        aa_round_rect(self._CanvasHWND,rect2, MySkinManager.GiveColor('Front'),5,0,MySkinManager.GiveColor('Front'))        
+        
+class APIOBJ(object):
+
+    _StoragePage = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._StoragePage = StoragePage()
+
+        self._StoragePage._Screen = main_screen
+        self._StoragePage._Name ="Storage"
+        self._StoragePage.Init()
+        
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._StoragePage)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+    
+
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 19 - 0
Menu/GameShell/10_Settings/Time/__init__.py

@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+
+## local UI import
+import pages
+import myvars
+
+def Init(main_screen):
+    pages.InitTimezoneListPage(main_screen)
+    
+def API(main_screen):
+    if main_screen !=None:
+        main_screen.PushCurPage()
+        main_screen.SetCurPage(myvars.TimezoneListPage)
+        main_screen.Draw()
+        main_screen.SwapAndShow()
+
+

+ 112 - 0
Menu/GameShell/10_Settings/Time/list_item.py

@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+from libs.roundrects import aa_round_rect
+
+## local UI import
+from UI.constants import ICON_TYPES
+from UI.page   import Page
+from UI.label  import Label
+from UI.icon_item import IconItem
+from UI.util_funcs import midRect
+from UI.skin_manager import MySkinManager
+
+# a item for List
+# - - - - - - - - - - - -- 
+# | Icon  Text.....    > |
+# ------------------------
+
+import myvars # icons_path
+
+class ListItemIcon(IconItem):
+
+    _CanvasHWND = None
+    _Parent     = None
+    _Width      = 18
+    _Height     = 18
+    
+    def Draw(self):
+        self._CanvasHWND.blit(self._ImgSurf,(self._PosX,self._PosY+(self._Parent._Height-self._Height)/2,self._Width,self._Height))
+
+
+class ListItemLabel(Label):
+
+    _ActiveColor = MySkinManager.GiveColor('Active')
+    _Active = False
+    def Draw(self):
+
+        self._FontObj.set_bold(self._Active)
+        
+        my_text = self._FontObj.render( self._Text,True,self._Color)
+        self._CanvasHWND.blit(my_text,(self._PosX,self._PosY,self._Width,self._Height))
+
+    
+class ListItem(object):
+    _PosX = 0
+    _PosY = 0
+    _Width = 0
+    _Height = 30
+
+    _Labels = {}
+    _Icons  = {}
+    _Fonts  = {}
+    _MyType = ICON_TYPES["EXE"]
+    _LinkObj = None
+    _Path    = ""
+    _Active  = False
+    _Parent  = None
+    
+    _Text = ""
+    def __init__(self):
+        self._Labels = {}
+        self._Icons  = {}
+        self._Fonts  = {}
+
+
+    def Init(self,text):
+        
+        self._Text = text
+        
+        l = ListItemLabel()
+        l._PosX = 22
+        l.SetCanvasHWND(self._Parent._CanvasHWND)
+
+        if self._MyType == ICON_TYPES["DIR"]:
+            l.Init(text,self._Fonts["normal"])
+            self._Path = text
+        else:
+            l.Init(text,self._Fonts["normal"])
+            self._Path = text
+
+
+        self._Labels["Text"] = l
+        
+        
+    def NewCoord(self,x,y):
+        self._PosX = x
+        self._PosY = y
+
+    def Draw(self):
+
+        if self._MyType == ICON_TYPES["DIR"] and self._Path != "[..]":
+            self._Parent._Icons["sys"]._IconIndex = 0
+            self._Parent._Icons["sys"].NewCoord(self._PosX+12,self._PosY+ (self._Height - self._Parent._Icons["sys"]._Height)/2+self._Parent._Icons["sys"]._Height/2)
+            self._Parent._Icons["sys"].Draw()
+
+        if self._MyType == ICON_TYPES["FILE"]:
+            self._Parent._Icons["sys"]._IconIndex = 1
+            self._Parent._Icons["sys"].NewCoord(self._PosX+12,self._PosY+ (self._Height - self._Parent._Icons["sys"]._Height)/2+self._Parent._Icons["sys"]._Height/2)
+            self._Parent._Icons["sys"].Draw()
+        
+        if self._Active == True:
+            self._Labels["Text"]._Active = True
+        else:
+            self._Labels["Text"]._Active = False
+
+        
+        self._Labels["Text"]._PosY = self._PosY + (self._Height - self._Labels["Text"]._Height)/2
+            
+        pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),(self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)
+
+        self._Labels["Text"].Draw()
+

+ 16 - 0
Menu/GameShell/10_Settings/Time/logger.py

@@ -0,0 +1,16 @@
+import logzero
+
+def get_logger():
+    # Set a custom formatter
+    log_format = '%(color)s[%(levelname)1.1s ' \
+                    '%(asctime)s.%(msecs)03d %(module)s:%(lineno)d]' \
+                    '%(end_color)s %(message)s'
+    formatter = logzero.LogFormatter(fmt=log_format)
+    logzero.setup_default_logger(formatter=formatter)
+
+    logzero.logfile(
+        'logzero.log',
+        maxBytes=1e6,
+        backupCount=3
+    )
+    return logzero.logger

+ 5 - 0
Menu/GameShell/10_Settings/Time/myvars.py

@@ -0,0 +1,5 @@
+
+
+TimePage = None
+TimezoneListPage = None
+

+ 13 - 0
Menu/GameShell/10_Settings/Time/pages.py

@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*- 
+
+from timezone_lib_list_page import TimezoneListPage
+import myvars
+
+def InitTimePage(main_screen):
+    myvars.TimePage = None
+
+def InitTimezoneListPage(main_screen):
+    myvars.TimezoneListPage = TimezoneListPage()
+    myvars.TimezoneListPage._Screen = main_screen
+    myvars.TimezoneListPage._Name   = "Timezone Selection"
+    myvars.TimezoneListPage.Init()

+ 304 - 0
Menu/GameShell/10_Settings/Time/timezone_lib_list_page.py

@@ -0,0 +1,304 @@
+# -*- coding: utf-8 -*- 
+
+import os
+import subprocess
+import pygame
+
+from libs.roundrects import aa_round_rect
+
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.icon_item import IconItem
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.multi_icon_item import MultiIconItem
+from UI.icon_pool           import MyIconPool
+from UI.scroller   import ListScroller
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+from list_item  import ListItem
+
+
+import myvars
+
+
+class TimeLibStack:
+    def __init__(self):
+        self.stack = list()
+
+    def Push(self,data):
+        if data not in self.stack:
+            self.stack.append(data)
+            return True
+        return False
+
+    def Pop(self):
+        if len(self.stack)<=0:
+            return None,False
+        return self.stack.pop(),True
+
+    def Last(self):
+        idx = len(self.stack) -1
+        if idx < 0:
+            return "/usr/share/zoneinfo/posix"
+        else:
+            return self.stack[ idx ]
+    
+    def Length(self):
+        return len(self.stack)
+
+class ListPageSelector(PageSelector):
+    _BackgroundColor = MySkinManager.GiveColor('Front')
+
+    def __init__(self):
+        self._PosX = 0
+        self._PosY = 0
+        self._Height = 0
+        self._Width  = Width
+
+    def AnimateDraw(self,x2,y2):
+        pass
+
+    def Draw(self):
+        idx = self._Parent._PsIndex
+        
+        if idx < len(self._Parent._MyList):
+            x = self._Parent._MyList[idx]._PosX+2
+            y = self._Parent._MyList[idx]._PosY+1
+            h = self._Parent._MyList[idx]._Height -3
+        
+            self._PosX = x
+            self._PosY = y
+            self._Height = h
+            
+            aa_round_rect(self._Parent._CanvasHWND,  
+                          (x,y,self._Width-4,h),self._BackgroundColor,4,0,self._BackgroundColor)
+
+
+
+class TimezoneListPage(Page):
+
+    _Icons = {}
+    _Selector=None
+    _FootMsg = ["Nav","","","Back","Select"]
+    _MyList = []
+    _SwapMyList = []
+    _ListFont = MyLangManager.TrFont("notosanscjk15")
+    _MyStack = None
+
+    _Scroller = None
+    
+    _BGpng = None
+    _BGwidth = 56
+    _BGheight = 70
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+        self._CanvasHWND = None
+        self._MyList = []
+        self._SwapMyList = []
+        self._MyStack = TimeLibStack()
+    
+    def buildDirectoryList(self, path):
+        elements = [
+            {
+                'name': f,
+                'file_path': os.path.join(path, f),
+                'is_file': os.path.isfile(os.path.join(path, f))
+            } 
+            for f in os.listdir(path) 
+            ]
+        return elements
+
+    def SyncList(self,path):
+        
+        alist = self.buildDirectoryList(path)
+        if not alist:
+            print("buildDirectoryList empty")
+            return 
+
+        self._MyList = []
+        self._SwapMyList = []
+        
+        start_x  = 0
+        start_y  = 0
+        hasparent = 0
+        if self._MyStack.Length() > 0:
+            hasparent = 1
+            li = ListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFont
+            li._MyType = ICON_TYPES["DIR"]
+            li.Init("[..]")
+            self._MyList.append(li)
+        
+        for i,v in enumerate(sorted(alist)):
+            li = ListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + (i+hasparent)*ListItem._Height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFont
+            li._MyType  = ICON_TYPES["FILE"]
+            
+            if not v['is_file']:
+                li._MyType = ICON_TYPES["DIR"]
+            else:
+                li._MyType  = ICON_TYPES["FILE"]
+            
+            li.Init( v['name']  )
+            li._Path = v["file_path"]
+            
+            
+            self._MyList.append(li)
+
+        for i in self._MyList:
+            self._SwapMyList.append(i)
+        
+    def Init(self):
+        self._PosX = self._Index * self._Screen._Width
+        self._Width = self._Screen._Width
+        self._Height = self._Screen._Height
+
+        self._CanvasHWND = self._Screen._CanvasHWND
+
+        ps = ListPageSelector()
+        ps._Parent = self
+        self._Ps = ps
+        self._PsIndex = 0
+
+        self.SyncList("/usr/share/zoneinfo/posix")
+
+        icon_for_list = MultiIconItem()
+        icon_for_list._ImgSurf = MyIconPool.GiveIconSurface("sys")
+        icon_for_list._MyType = ICON_TYPES["STAT"]
+        icon_for_list._Parent = self
+        
+        icon_for_list.Adjust(0,0,18,18,0)        
+        self._Icons["sys"] = icon_for_list
+
+
+        self._BGpng = IconItem()
+        self._BGpng._ImgSurf = MyIconPool.GiveIconSurface("empty")
+        self._BGpng._MyType = ICON_TYPES["STAT"]
+        self._BGpng._Parent = self
+        self._BGpng.AddLabel("No timezones found on system!", MyLangManager.TrFont("varela22"))
+        self._BGpng.SetLableColor(MySkinManager.GiveColor('Disabled'))
+        self._BGpng.Adjust(0,0,self._BGwidth,self._BGheight,0)
+
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        
+    def Click(self):
+        if len(self._MyList) == 0:
+            return
+        
+        cur_li = self._MyList[self._PsIndex]
+
+        if cur_li._MyType == ICON_TYPES["DIR"]:
+            if cur_li._Path == "[..]":
+                self._MyStack.Pop()
+                self.SyncList( self._MyStack.Last() )
+                self._PsIndex = 0
+            else:
+                self._MyStack.Push( self._MyList[self._PsIndex]._Path )
+                self.SyncList( self._MyStack.Last() )
+                self._PsIndex = 0
+                
+        if cur_li._MyType == ICON_TYPES["FILE"]: ## set the current timezone
+            subprocess.call(['sudo', 'cp', cur_li._Path, '/etc/localtime'])
+            #copyfile(cur_li._Path, '/etc/localtime')
+            print("add" , cur_li._Path)
+            
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+
+    def Rescan(self):
+        self.SyncList("/usr/share/zoneinfo/posix")
+        self._PsIndex = 0
+        
+    def KeyDown(self,event):
+        
+        if IsKeyMenuOrB(event.key):
+            
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Right"]:
+            self.FScrollDown(Step=5)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if event.key == CurKeys["Left"]:
+            self.FScrollUp(Step=5)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+                                     
+        if IsKeyStartOrA(event.key):
+            self.Click()
+            
+    def Draw(self):
+        self.ClearCanvas()
+
+        if len(self._MyList) == 0:
+            self._BGpng.NewCoord(self._Width/2,self._Height/2)
+            self._BGpng.Draw()
+            return
+        
+        else:
+            if len(self._MyList) * ListItem._Height > self._Height:
+                self._Ps._Width = self._Width - 11
+            
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if False:
+                        i._Active = True
+                    else:
+                        i._Active = False
+
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+
+                    if i._PosY < 0:
+                        continue
+                    
+                    i.Draw()
+                    
+                self._Scroller.UpdateSize( len(self._MyList)*ListItem._Height, self._PsIndex*ListItem._Height)
+                self._Scroller.Draw()
+            else:
+                self._Ps._Width = self._Width
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if False:
+                        i._Active = True
+                    else:
+                        i._Active = False
+
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+
+                    if i._PosY < 0:
+                        continue
+                        
+                    i.Draw()    

+ 334 - 0
Menu/GameShell/10_Settings/Update/__init__.py

@@ -0,0 +1,334 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+import os
+import requests
+import validators
+import gobject
+
+
+## local UI import
+from UI.page  import Page
+from UI.constants import ICON_TYPES,Width,Height,RUNEVT,RUNSH
+from UI.icon_item import IconItem
+from UI.icon_pool import MyIconPool
+from UI.label  import Label
+from UI.util_funcs import midRect,CmdClean,get_git_revision_short_hash
+from UI.keys_def import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.confirm_page import ConfirmPage
+from UI.download     import Download
+from UI.download_process_page import DownloadProcessPage
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+
+from UI.info_page_list_item import InfoPageListItem
+
+from libs.roundrects import aa_round_rect
+from libs.DBUS       import is_wifi_connected_now
+
+import config
+
+LauncherLoc = "/home/cpi/launcher"
+
+class UpdateDownloadPage(DownloadProcessPage):
+    _MD5 = ""
+
+    def GObjectUpdateProcessInterval(self):
+        if self._Screen.CurPage() == self:
+            if self._Downloader.isFinished():
+                if self._Downloader.isSuccessful():
+                    print("Success!")
+                    # Do something with obj.get_dest()
+                    filename = self._Downloader.get_dest()
+                    
+                    if filename.endswith(".tar.gz"):                    
+                        #/home/cpi/apps/[launcher]
+                        cmdpath = "tar zxf " + CmdClean(filename) + " -C /home/cpi/ ;rm -rf "+ filename
+                        pygame.event.post( pygame.event.Event(RUNEVT, message=cmdpath))
+                        
+                    self.ReturnToUpLevelPage()
+                    self._Screen.Draw()
+                    self._Screen.SwapAndShow()
+                    
+                else:
+                    print("Download failed with the following exceptions:")
+                    for e in self._Downloader.get_errors():
+                        print(unicode(e))
+
+                    try:
+                        self._Downloader.stop()
+                    except:
+                        pass
+
+                    filename = self._Downloader.get_dest()
+                    print(filename)
+                    os.system("rm -rf %s" % CmdClean(filename))
+                    
+                    self._Screen._MsgBox.SetText("DownloadFailed")
+                    self._Screen._MsgBox.Draw()
+                    self._Screen.SwapAndShow()
+                    return False
+            else:
+                self._Value =  self._Downloader.get_progress()
+                print("Progress: %d%%" % (self._Value))
+                self._Screen.Draw()
+                self._Screen.SwapAndShow()
+                return True
+        else:
+            return False
+    
+    def StartDownload(self,url,dst_dir):
+        if validators.url(url) and os.path.isdir(dst_dir):
+            self._URL = url
+            self._DST_DIR = dst_dir
+        else:
+            self._Screen._MsgBox.SetText("Invaid")
+            self._Screen._MsgBox.Draw()
+            self._Screen.SwapAndShow()            
+            return
+        
+        self._Downloader = Download(url,dst_dir,None)
+        if self._MD5 != None:
+            if len(self._MD5) == 32:
+                self._Downloader.add_hash_verification('md5' ,self._MD5) ## hashlib provide algorithms
+
+        self._Downloader.start()
+        
+        self._DownloaderTimer = gobject.timeout_add(100, self.GObjectUpdateProcessInterval)
+
+    
+
+class UpdateConfirmPage(ConfirmPage):
+    _ConfirmText = "Confirm Update ?"
+    
+    _DownloadPage = None
+
+    _URL = ""
+    _MD5 = ""
+    _Version = ""
+    _GIT = False
+    
+    def KeyDown(self,event):
+        global LauncherLoc
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if IsKeyStartOrA(event.key):
+            if self._GIT == True:
+                cmdpath = "%s/update.sh %s" % (LauncherLoc,self._Version)
+                pygame.event.post( pygame.event.Event(RUNSH, message=cmdpath))
+                return
+            
+            if self._DownloadPage == None:
+                self._DownloadPage = UpdateDownloadPage()
+                self._DownloadPage._Screen = self._Screen
+                self._DownloadPage._Name   = "Downloading"
+                self._DownloadPage.Init()
+
+            self._DownloadPage._MD5 = self._MD5
+            self._Screen.PushPage(self._DownloadPage)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+            if self._URL != None and validators.url(self._URL):
+                self._DownloadPage.StartDownload(self._URL, "/tmp")
+            else:
+                print "error url  %s " % self._URL
+            
+
+    def OnReturnBackCb(self):
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+            
+    def Draw(self):
+        self.ClearCanvas()
+        self.DrawBG()
+        for i in self._MyList:
+            i.Draw()
+        
+        self.Reset()
+
+
+class UpdatePage(Page):
+    _Icons = {}
+    _FootMsg = ["Nav","","Check Update","Back",""]
+
+    _ListFontObj = MyLangManager.TrFont("varela15")    
+    _ConfirmPage = None
+    _AList    = {}
+    _MyList   = []
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}    
+
+    def GenList(self):
+        
+        start_x  = 0
+        start_y  = 0
+        
+        for i,v in enumerate( self._AList):
+            li = InfoPageListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + i*InfoPageListItem._Height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFontObj
+            li._Fonts["small"] = MySkinManager.GiveFont("varela12")
+            
+            if self._AList[v]["label"] != "":
+                li.Init(  self._AList[v]["label"] )
+            else:
+                li.Init( self._AList[v]["key"] )
+
+            li._Flag = self._AList[v]["key"]
+
+            li.SetSmallText( self._AList[v]["value"] )
+            
+            self._MyList.append(li)
+        
+    def Init(self):
+        self._CanvasHWND = self._Screen._CanvasHWND
+        self._Width =  self._Screen._Width
+        self._Height = self._Screen._Height
+
+        self._ConfirmPage = UpdateConfirmPage()
+        self._ConfirmPage._Screen = self._Screen
+        self._ConfirmPage._Name  = "Update Confirm"
+        self._ConfirmPage._Parent = self
+        self._ConfirmPage.Init()
+
+        it = {}
+        it["key"] = "version"
+        it["label"] = "Version"
+        it["value"] = config.VERSION
+        self._AList["version"] = it
+        
+        self.GenList()
+        
+    def CheckUpdate(self):
+        global LauncherLoc
+        self._Screen._MsgBox.SetText("CheckingUpdate")
+        self._Screen._MsgBox.Draw()
+        self._Screen.SwapAndShow()
+
+        try:
+            r = requests.get(config.UPDATE_URL, verify=False, timeout=8)
+        except:
+            print("requests get error")
+            return
+        else:
+            if r.status_code == requests.codes.ok:
+                try:
+                    json_ = r.json()
+
+                    if "version" in json_ and "updatepath" in json_ and "md5sum" in json_:
+                        if config.VERSION != json_["version"]:
+                            
+                            self._ConfirmPage._URL = json_["updatepath"]
+                            self._ConfirmPage._MD5 = json_["md5sum"]
+                            self._ConfirmPage._GIT = False
+                            
+                            self._Screen.PushPage(self._ConfirmPage)
+                            
+                            self._Screen.Draw()
+                            self._ConfirmPage.SnapMsg(MyLangManager.Tr("ConfirmUpdateToFQ") % json_["version"] )
+                            self._Screen.SwapAndShow()
+                            
+                    elif "gitversion" in json_: ### just use git to  run update
+                        cur_dir = os.getcwd()
+                        os.chdir(LauncherLoc)
+                        current_git_version = get_git_revision_short_hash()
+                        current_git_version = current_git_version.strip("\n")
+                        current_git_version = current_git_version.strip("\t")
+                        os.chdir(cur_dir)
+                        if current_git_version != json_["gitversion"]:
+                            self._ConfirmPage._URL = None
+                            self._ConfirmPage._MD5 = None
+                            self._ConfirmPage._GIT = True
+                            self._ConfirmPage._Version = json_["gitversion"]
+                            
+                            self._Screen.PushPage(self._ConfirmPage)
+                            
+                            self._Screen.Draw()
+                            self._ConfirmPage.SnapMsg(MyLangManager.Tr("UpdateToFQ") % json_["gitversion"] )
+                            self._Screen.SwapAndShow()
+                        else:
+                            self._Screen.Draw()
+                            self._Screen._MsgBox.SetText("LauncherIsUpToDate")
+                            self._Screen._MsgBox.Draw()
+                            self._Screen.SwapAndShow()
+                            pygame.time.delay(765)
+                            
+                    return True
+                except Exception, e:
+                    print("r.json() error %s" % str(e))
+                
+            else:
+                print(" requests get error %d ", r.status_code)
+                    
+
+        return False
+    
+    def OnLoadCb(self):
+        pass
+
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if event.key == CurKeys["X"]:
+            if is_wifi_connected_now():
+                if self.CheckUpdate() == True:
+                    self._Screen.Draw()
+                    self._Screen.SwapAndShow()
+                else:
+                    self._Screen.Draw()
+                    self._Screen._MsgBox.SetText("CheckingUpdateFailed")
+                    self._Screen._MsgBox.Draw()
+                    self._Screen.SwapAndShow()
+            else:
+                self._Screen.Draw()
+                self._Screen._MsgBox.SetText("CheckWifiConnection")
+                self._Screen._MsgBox.Draw()
+                self._Screen.SwapAndShow()
+
+    def Draw(self):
+        self.ClearCanvas()
+#        self._Ps.Draw()
+
+        for i in self._MyList:
+            i.Draw()
+        
+    
+class APIOBJ(object):
+
+    _UpdatePage = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._UpdatePage = UpdatePage()
+
+        self._UpdatePage._Screen = main_screen
+        self._UpdatePage._Name = "Update Launcher"
+        self._UpdatePage.Init()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._UpdatePage)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+    
+
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    
+        

+ 26 - 0
Menu/GameShell/10_Settings/Wifi/__init__.py

@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*- 
+
+## local UI import
+import pages
+import myvars
+"""
+try:
+    from icons import preload
+except:
+    print("No icons package")
+"""
+
+def Init(main_screen):
+    pages.InitPasswordPage(main_screen)
+    pages.InitScanPage(main_screen)
+    myvars.PasswordPage._Caller = myvars.ScanPage
+    
+def API(main_screen):
+    
+    if main_screen != None:
+        main_screen.PushCurPage()
+        main_screen.SetCurPage(myvars.ScanPage)
+        main_screen.Draw()
+        main_screen.SwapAndShow()
+
+

+ 5 - 0
Menu/GameShell/10_Settings/Wifi/myvars.py

@@ -0,0 +1,5 @@
+# -*- coding: utf-8 -*- 
+
+
+ScanPage = None
+PasswordPage = None

+ 196 - 0
Menu/GameShell/10_Settings/Wifi/net_item.py

@@ -0,0 +1,196 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+
+## local UI import
+from UI.page   import Page
+from UI.label  import Label
+from UI.icon_item import IconItem
+from UI.multi_icon_item  import MultiIconItem
+from UI.icon_pool   import MyIconPool
+from UI.skin_manager import MySkinManager
+from UI.widget      import Widget
+
+class NetItemMultiIcon(MultiIconItem):
+    _CanvasHWND = None
+    _Parent     = None
+    _Width      = 18
+    _Height     = 18
+    
+    def Draw(self):
+        self._CanvasHWND.blit(self._ImgSurf,(self._PosX,self._PosY+(self._Parent._Height-self._Height)/2,self._Width,self._Height),
+                              (0,self._IconIndex*self._IconHeight,self._IconWidth,self._IconHeight))
+    
+class NetItemIcon(IconItem):
+
+    _CanvasHWND = None
+    _Parent     = None
+    _Width      = 18
+    _Height     = 18
+    
+    def Draw(self):
+        self._CanvasHWND.blit(self._ImgSurf,(self._PosX,self._PosY+(self._Parent._Height-self._Height)/2,self._Width,self._Height))
+
+            
+class NetItem(Widget):
+    _Height = 30
+
+    _Bssid=""    # 50:3A:A0:51:18:3C
+    _Essid=""    # MERCURY_EB88
+
+    ## extra infomations
+    _dhcphostname = "GameShell"
+    _ip   = None      #eg 192.168.31.141
+    _dns_domain = None
+    _gateway    = None  #eg 192.168.31.1
+    _use_global_dns = 0 ## eg 0 == False, 1 == True
+    _netmask    = None ##eg 255.255.255.0
+    _usedhcphostname= 0
+    _bitrate = "auto"
+    _allow_lower_bitrates = 0
+    _dns3 = None
+    _dns2 = None  ## eg 1.1.1.1
+    _dns1 = None  ## eg 8.8.8.8
+    _use_settings_globally = 0 
+    _use_static_dns = 0 # eg: 1 == True
+    _search_domain = None
+    
+    _Encrypt=""  # WPA2
+    _Channel=""  # '10' 
+    _Stren = ""  ## 19%
+    _NetId    = 0   ##  0-n
+    _Mode  = ""  ## Master or AdHoc
+    _Parent = None
+    _IsActive = False
+
+    _Icons  = {} ## wifi strength and security icons
+    _Labels = {}
+    _FontObj = None
+    
+    def __init__(self):
+        self._Labels = {}
+        self._Icons = {}
+
+    def SetActive(self,act):
+        self._IsActive = act
+    
+    def UpdateStrenLabel(self, strenstr): ## strenstr should be 'number',eg:'90'
+        self._Stren = self._Parent._Daemon.FormatSignalForPrinting(strenstr) 
+        self._Labels["stren"]._Text = self._Stren
+
+    def Init(self, i, is_active):
+        # Pick which strength measure to use based on what the daemon says
+        # gap allocates more space to the first module
+        if self._Parent._Daemon.GetSignalDisplayType() == 0:
+            strenstr = 'quality'
+            gap = 4  # Allow for 100%
+        else:
+            strenstr = 'strength'
+            gap = 7  # -XX dbm = 7
+        self._NetId = i
+        # All of that network property stuff
+        self._Stren = self._Parent._Daemon.FormatSignalForPrinting(
+                str(self._Parent._Wireless.GetWirelessProperty(self._NetId, strenstr)))
+        
+        self._Essid = self._Parent._Wireless.GetWirelessProperty(self._NetId, 'essid')
+        self._Bssid = self._Parent._Wireless.GetWirelessProperty(self._NetId, 'bssid')
+
+        if self._Parent._Wireless.GetWirelessProperty(self._NetId, 'encryption'):
+            self._Encrypt = \
+                self._Parent._Wireless.GetWirelessProperty(self._NetId, 'encryption_method')
+        else:
+            self._Encrypt = 'Unsecured'
+
+        self._Mode = \
+            self._Parent._Wireless.GetWirelessProperty(self._NetId, 'mode')  # Master, Ad-Hoc
+        self._Channel = self._Parent._Wireless.GetWirelessProperty(self._NetId, 'channel')
+        theString = '  %-*s %25s %9s %17s %6s %4s' % \
+            (gap, self._Stren, self._Essid, self._Encrypt, self._Bssid, self._Mode,
+                self._Channel)
+        
+        if is_active:
+            theString = ">> "+theString[1:]
+            self.SetActive(is_active)
+        
+
+
+        essid_label = Label()
+        essid_label._PosX = 36
+        #essid_label._PosY = self._PosY +  (self._Height - self._FontObj.render(self._Essid,True,(83,83,83)).get_height())/2
+        essid_label._CanvasHWND = self._Parent._CanvasHWND
+
+        if len(self._Essid) > 19:
+            essid_ = self._Essid[:20]
+        else:
+            essid_ = self._Essid
+        
+        essid_label.Init(essid_,self._FontObj)
+        self._Labels["essid"] = essid_label
+
+        stren_label = Label()
+        #stren_label._PosY = self._PosY +  (self._Height - self._FontObj.render(self._Stren,True,(83,83,83)).get_height())/2
+        stren_label._CanvasHWND = self._Parent._CanvasHWND
+
+        stren_label.Init(self._Stren,self._FontObj)
+        stren_label._PosX = self._Width - 23 - stren_label.Width() - 2
+        self._Labels["stren"] = stren_label
+        
+
+        lock_icon = NetItemIcon()
+        lock_icon._ImgSurf = MyIconPool.GiveIconSurface("lock")
+        lock_icon._CanvasHWND = self._Parent._CanvasHWND
+        lock_icon._Parent = self
+        self._Icons["lock"] = lock_icon
+        
+        done_icon = NetItemIcon()
+        done_icon._ImgSurf = MyIconPool.GiveIconSurface("done")
+        done_icon._CanvasHWND = self._Parent._CanvasHWND
+        done_icon._Parent = self
+        
+        self._Icons["done"] = done_icon
+
+
+        ## reuse the resource from TitleBar
+        nimt = NetItemMultiIcon()
+        nimt._ImgSurf = self._Parent._Screen._TitleBar._Icons["wifistatus"]._ImgSurf
+        nimt._CanvasHWND = self._Parent._CanvasHWND
+        nimt._Parent = self
+        self._Icons["wifistatus"] = nimt
+
+        #pp(theString)
+    
+    
+    def Connect(self,notworkentry=None):
+        """ Execute connection. """
+        self._Parent._Wireless.ConnectWireless(self._NetId)
+
+    
+    def Draw(self):
+        #pygame.draw.line(self._Parent._CanvasHWND,(169,169,169),(self._PosX,self._PosY),(self._PosX+self._Width,self._PosY),1)        
+        for i in self._Labels:
+            self._Labels[i]._PosY = self._PosY + (self._Height - self._Labels[i]._Height)/2
+            self._Labels[i].Draw()
+            
+        if self._IsActive:
+            self._Icons["done"].NewCoord(14,self._PosY)
+            self._Icons["done"].Draw()
+
+        if self._Encrypt != "Unsecured":
+            self._Icons["lock"].NewCoord( self._Width -23 - self._Labels["stren"].Width() - 2 - 18, self._PosY)
+            self._Icons["lock"].Draw()
+        
+        ge = self._Parent._Screen._TitleBar.GetWifiStrength( self._Stren.replace('%',''))
+        
+        if ge > 0:
+            self._Icons["wifistatus"]._IconIndex = ge
+            self._Icons["wifistatus"].NewCoord(self._Width-23,self._PosY)
+            self._Icons["wifistatus"].Draw()
+            
+        else:
+            self._Icons["wifistatus"]._IconIndex = 0
+            self._Icons["wifistatus"].NewCoord(self._Width-23,self._PosY)
+            self._Icons["wifistatus"].Draw()
+        
+        pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),(self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)        
+        
+

+ 61 - 0
Menu/GameShell/10_Settings/Wifi/pages.py

@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*- 
+
+
+#import dbus
+#import dbus.service
+#from wicd import misc 
+##misc.to_bool
+##misc.misc.noneToString
+##misc.to_unicode
+##misc.Noneify
+#from wicd.translations import _
+#from wicd import wpath
+#from wicd import dbusmanager
+
+
+## local UI import
+from libs.DBUS      import bus,daemon,wireless,wired
+
+from UI.keyboard import Keyboard
+from wifi_list import WifiList
+
+import myvars
+
+
+def InitScanPage(main_screen):
+    global wireless
+    global daemon
+    global bus
+    
+    myvars.ScanPage = WifiList()
+    myvars.ScanPage._Name = "Scan wifi"
+   
+    myvars.ScanPage._Wireless = wireless
+    myvars.ScanPage._Daemon = daemon
+    myvars.ScanPage._Dbus = bus
+   
+
+    myvars.ScanPage._Screen = main_screen
+    myvars.ScanPage.Init()
+
+
+    if daemon != None:
+        #Bind signals
+        myvars.ScanPage._Dbus.add_signal_receiver(myvars.ScanPage.DbusScanFinishedSig, 'SendEndScanSignal',
+                                                  'org.wicd.daemon.wireless')
+        myvars.ScanPage._Dbus.add_signal_receiver(myvars.ScanPage.DbusScanStarted, 'SendStartScanSignal',
+                                                  'org.wicd.daemon.wireless')
+        #
+        myvars.ScanPage._Dbus.add_signal_receiver(myvars.ScanPage.DbusDaemonStatusChangedSig, 'StatusChanged',
+                                                  'org.wicd.daemon')
+        myvars.ScanPage._Dbus.add_signal_receiver(myvars.ScanPage.DbusConnectResultsSent, 'ConnectResultsSent',
+                                                  'org.wicd.daemon')
+
+def InitPasswordPage(main_screen):
+
+    myvars.PasswordPage = Keyboard()
+    myvars.PasswordPage._Name = "Enter wifi password"
+
+    myvars.PasswordPage._Screen = main_screen
+    myvars.PasswordPage.Init()
+

+ 738 - 0
Menu/GameShell/10_Settings/Wifi/wifi_list.py

@@ -0,0 +1,738 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+
+from beeprint import pp
+from libs.roundrects import aa_round_rect
+import gobject
+from wicd import misc 
+## local UI import
+from UI.constants import Width,Height
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect,SwapAndShow
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.confirm_page import ConfirmPage
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+
+from UI.info_page_list_item import InfoPageListItem
+from UI.info_page_selector  import InfoPageSelector
+
+from libs.DBUS     import is_wifi_connected_now
+
+from net_item import NetItem
+
+import myvars
+
+class WifiDisconnectConfirmPage(ConfirmPage):
+
+    _ConfirmText = MyLangManager.Tr("ConfirmDisconnectQ")
+    
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if IsKeyStartOrA(event.key):
+            self.SnapMsg(MyLangManager.Tr("Disconnecting"))
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+            self._Parent._Daemon.Disconnect()
+            
+            pygame.time.delay(400)
+            
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+                    
+    def Draw(self):
+        #self.ClearCanvas()
+        self.DrawBG()
+        for i in self._MyList:
+            i.Draw()
+        
+        self.Reset()
+        
+class WifiInfoPage(Page):
+    _FootMsg =  ["Nav","","","Back",""]
+    _MyList = []
+    _ListFontObj = MyLangManager.TrFont("varela15")
+
+    _Wireless = None
+    _Daemon   = None
+    
+    _AList = {}
+    _NetworkId = -1
+    
+    def GenList(self):
+        
+        self._MyList = []
+        if self._NetworkId != -1:
+            self._AList["ip"]["value"] = "Not Connected"
+            
+            if self._Wireless.GetCurrentNetworkID(self._Wireless.GetIwconfig()) == self._NetworkId:
+                ip = self._Wireless.GetWirelessIP('')
+            
+                if ip is not None:
+                    self._AList["ip"]["value"] = ip
+            
+            self._AList["bssid"]["value"] = self._Wireless.GetWirelessProperty(self._NetworkId,"bssid")
+        
+        start_x  = 0
+        start_y  = 0
+        
+        for i,v in enumerate( self._AList):
+            li = InfoPageListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + i*InfoPageListItem._Height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFontObj
+            li._Fonts["small"] = MyLangManager.TrFont("varela12")
+            
+            if self._AList[v]["label"] != "":
+                li.Init(  self._AList[v]["label"] )
+            else:
+                li.Init( self._AList[v]["key"] )
+
+            li._Flag = self._AList[v]["key"]
+
+            li.SetSmallText( self._AList[v]["value"] )
+            
+            self._MyList.append(li)
+            
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._CanvasHWND = self._Screen._CanvasHWND
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+        ps = InfoPageSelector()
+        ps._Parent = self
+        ps._PosX = 2
+        self._Ps = ps
+        self._PsIndex = 0
+
+        ip = {}
+        ip["key"] = "ip"
+        ip["label"] = "IP"
+        ip["value"] = "Not Connected"
+        
+        bssid = {}
+        bssid["key"] = "bssid"
+        bssid["label"] = "BSSID"
+        bssid["value"] = ""
+        
+        self._AList["ip"] = ip
+        self._AList["bssid"] = bssid
+        
+        self.GenList()
+
+        self._DisconnectConfirmPage = WifiDisconnectConfirmPage()
+        self._DisconnectConfirmPage._Screen = self._Screen
+        self._DisconnectConfirmPage._Name   = "Confirm Disconnect"
+        self._DisconnectConfirmPage._Parent = self
+        self._DisconnectConfirmPage.Init()
+
+    def Click(self):
+        cur_li = self._MyList[self._PsIndex]
+        print(cur_li._Flag)        
+
+    def TryDisconnect(self):
+        if self._Wireless.GetCurrentNetworkID(self._Wireless.GetIwconfig()) == self._NetworkId \
+           and self._Wireless.GetWirelessIP('') is not None:
+            self._Screen.PushPage(self._DisconnectConfirmPage)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        else:
+            return
+        
+    def OnLoadCb(self):
+        if self._Wireless.GetCurrentNetworkID(self._Wireless.GetIwconfig()) == self._NetworkId \
+           and self._Wireless.GetWirelessIP('') is not None:
+            self._FootMsg[2] = "Disconnect"
+        else:
+            self._FootMsg[2] =  ""
+
+        self.GenList()
+
+    def OnReturnBackCb(self):
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+
+        if IsKeyStartOrA(event.key):
+            self.Click()
+
+        if event.key == CurKeys["X"]:
+            self.TryDisconnect()
+                                
+    def Draw(self):
+        self.ClearCanvas()
+        self._Ps.Draw()
+
+        for i in self._MyList:
+            i.Draw()
+
+
+        
+    
+class WifiListSelector(PageSelector):
+    _BackgroundColor = MySkinManager.GiveColor('Front')
+
+    def __init__(self):
+        pass
+
+    def AnimateDraw(self,x2,y2):
+        pass 
+
+
+    def Draw(self):
+        idx = self._Parent._PsIndex
+        if idx < len( self._Parent._MyList):
+            x = self._Parent._MyList[idx]._PosX+11
+            y = self._Parent._MyList[idx]._PosY+1
+            h = self._Parent._MyList[idx]._Height -3
+        
+            self._PosX = x
+            self._PosY = y
+            self._Height = h
+
+            aa_round_rect(self._Parent._CanvasHWND,  
+                          (x,y,self._Width,h),self._BackgroundColor,4,0,self._BackgroundColor)
+
+
+class WifiListMessageBox(Label):
+    _Parent = None
+
+    def Draw(self):
+        my_text = self._FontObj.render( self._Text,True,self._Color)
+        w  = my_text.get_width()
+        h  = my_text.get_height()
+        x  = (self._Parent._Width - w)/2
+        y =  (self._Parent._Height - h)/2
+        padding = 10 
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('White'),(x-padding,y-padding, w+padding*2,h+padding*2))        
+
+        pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('Black'),(x-padding,y-padding, w+padding*2,h+padding*2),1)
+
+        self._CanvasHWND.blit(my_text,(x,y,w,h))
+
+class WifiList(Page):
+    _MyList = []
+    #Wicd dbus part
+    _Wireless = None
+    _Daemon   = None
+    _Dbus     = None
+    _WifiPassword = ""
+    _Connecting = False
+    _Scanning   = False 
+    
+    _PrevWicdState = None
+    
+    _Selector = None
+    
+    _ShowingMessageBox = False 
+    _MsgBox            = None
+    _ConnectTry        = 0
+    _BlockingUI        = False
+    _BlockCb           = None
+    
+    _LastStatusMsg     = ""
+    _FootMsg           = ["Nav","Info","Scan","Back","Enter"]
+    _EncMethods        = None
+    _Scroller          = None
+    _ListFontObj       = MyLangManager.TrFont("notosanscjk15")
+
+    _InfoPage          = None
+    _CurBssid          = ""
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._MyList = []
+        self._CanvasHWND = None
+    
+    def ShowBox(self,msg):
+        
+        self._MsgBox._Text = msg
+        self._ShowingMessageBox = True
+        self._Screen.Draw()
+        self._MsgBox.Draw()
+        self._Screen.SwapAndShow()
+    
+    def HideBox(self):
+        self.Draw()
+        self._ShowingMessageBox = False
+        self._Screen.SwapAndShow()
+
+    def GenNetworkList(self):
+        self._MyList = []
+        start_x = 0
+        start_y = 0
+
+        for network_id in range(0,self._Wireless.GetNumberOfNetworks()):
+            is_active = \
+                self._Wireless.GetCurrentSignalStrength("") != 0 and \
+                self._Wireless.GetCurrentNetworkID(self._Wireless.GetIwconfig()) == network_id \
+                and self._Wireless.GetWirelessIP('') is not None
+
+            ni = NetItem()
+            ni._Parent = self
+            ni._PosX = start_x
+            ni._PosY = start_y + network_id* NetItem._Height
+            ni._Width = Width
+            ni._FontObj = self._ListFontObj
+            #ni._Bssid   = self._Wireless.GetWirelessProperty(network_id,"bssid")
+            
+            ni.Init(network_id,is_active)
+            self._MyList.append(ni)
+
+        self._PsIndex = 0
+        
+    def Disconnect(self):
+        self._Connecting= False
+        self._Daemon.Disconnect()
+    ## force to disconnect
+    def ShutDownConnecting(self):
+        print("Shutdownconnecting...",self._ConnectTry)
+        self._Daemon.CancelConnect()
+        self._Daemon.SetForcedDisconnect(True)
+        self._Connecting = False
+
+    def Rescan(self,sync=False):
+        print("start Rescan")
+        if self._Wireless != None:
+            self._Wireless.Scan(sync)
+
+## dbus signal functions
+    def DbusScanFinishedSig(self):
+
+        if self._Screen._CurrentPage != self:
+            return
+        self.ResetPageSelector()
+        
+        self.UpdateNetList(force_check=True)
+
+        self._Scanning = False
+        self.HideBox()
+        self._BlockingUI = False
+        print("dbus says scan finished")
+
+    def DbusScanStarted(self):
+        if self._Screen._CurrentPage !=self:
+            return
+        
+        self._Scanning = True
+        self.ShowBox(MyLangManager.Tr("Wifi scanning"))
+        self._BlockingUI = True
+        print("dbus says start scan...")
+
+
+    def UpdateNetList(self,state=None,info=None,force_check=False,firstrun=False):
+
+        if self._Daemon == None:
+            return
+        
+        if not state:
+            state,trash = self._Daemon.GetConnectionStatus()
+            print("state")
+            pp(state)
+            print("Trash: ")
+            pp(trash)
+
+        if force_check or self._PrevWicdState != state:
+            self.GenNetworkList() ## refresh the network list 
+        
+        if info != None:
+            if len(info) > 3:
+                _id  = int(info[3])
+                if _id < len(self._MyList):
+                    self._MyList[_id].UpdateStrenLabel( str(info[2]))
+
+        self._PrevWicdState = state
+        
+    def SetConnectingStatus(self,fast):
+        
+        wireless_connecting = self._Wireless.CheckIfWirelessConnecting()
+
+        """
+        if self._ConnectTry > 5000:
+            #wicd itself will take a very long time to try to connect ,will not block forever,just make it faster to dropout
+            self.ShutDownConnecting()
+            self._ConnectTry = 0
+            self._BlockingUI = False
+            return False
+        """
+        
+        if wireless_connecting:
+            
+            if not fast:
+                iwconfig = self._Wireless.GetIwconfig()
+            else:
+                iwconfig = ''
+            essid = self._Wireless.GetCurrentNetwork(iwconfig)
+            stat = self._Wireless.CheckWirelessConnectingMessage()
+            if self._LastStatusMsg != "%s: %s"%(essid,stat):
+                print("%s: %s" %(essid,stat))
+                self._LastStatusMsg = "%s: %s"%(essid,stat)
+                self.ShowBox(self._LastStatusMsg)
+                
+                self._Screen._FootBar.UpdateNavText(self._LastStatusMsg)
+                SwapAndShow()
+            #self._ConnectTry+=1
+
+            return True
+        else:
+            self._Connecting = False
+            return self._Connecting
+
+    def UpdateStatus(self):
+        print("UpdateStatus")
+        wireless_connecting = self._Wireless.CheckIfWirelessConnecting()
+        fast = not self._Daemon.NeedsExternalCalls()
+        
+        self._Connecting = wireless_connecting
+        
+        if self._Connecting:
+            gobject.timeout_add(250,self.SetConnectingStatus,fast)
+        else:
+            if not fast:
+                iwconfig = self._Wireless.GetIwconfig()
+            else:
+                iwconfig = ''
+
+            if self.CheckForWireless(iwconfig,self._Wireless.GetWirelessIP(''),None):
+                return True
+            else:
+                print("Not Connected")
+                return True
+
+    def DbusDaemonStatusChangedSig(self,state=None,info=None):
+        if self._Screen._CurrentPage != self:
+            return
+
+        print("in DbusDaemonStatusChangedSig")
+        """
+        dbus.UInt32(2L)
+        ['192.168.31.141', 'TP-LINK4G', '88', '0', '72.2 Mb/s']
+        """
+#        pp(info)
+        self.UpdateNetList(state,info)
+        if info != None:
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+
+    def DbusConnectResultsSent(self,result):
+        print(" in DbusConnectResultsSent")
+        """
+         in DbusConnectResultsSent
+        'dhcp_failed'
+        dbus says start scan...
+
+        """
+        if result != None:
+            print(result)
+            
+        self._Connecting = False
+        self._BlockingUI = False
+        if self._BlockCb != None:
+            self._BlockCb()
+            self._BlockCb = None
+
+        self._Screen._FootBar.ResetNavText()
+    
+    def CheckForWireless(self,iwconfig,wireless_ip,set_status):
+        if not wireless_ip:
+            return False
+        network = self._Wireless.GetCurrentNetwork(iwconfig)
+        if not network:
+            return False
+        network = misc.to_unicode(network)
+        if daemon.GetSignalDisplayType() == 0:
+            strength = self._Wireless.GetCurrentSignalStrength(iwconfig)
+        else:
+            strength = self._Wireless.GetCurrentDBMStrength(iwconfig)
+
+        if strength is None:
+            return False
+        strength = misc.to_unicode(self._Daemon.FormatSignalForPrinting(strength))
+        ip = misc.to_unicode(wireless_ip)
+
+        print(_('Connected to $A at $B (IP: $C)').replace
+                    ('$A', network).replace
+                    ('$B', strength).replace
+                    ('$C', ip))
+        
+        return True
+
+    def ConfigWireless(self,password):
+        
+        netid = self._PsIndex
+        
+        for i,v in enumerate(self._MyList):
+            if v._Bssid == self._CurBssid:
+                netid = i
+                break
+        
+        print(netid," ", password)
+        """
+        self._Wireless.SetWirelessProperty(netid,"dhcphostname","GameShell")
+        self._Wireless.SetWirelessProperty(netid,"ip","None")
+        self._Wireless.SetWirelessProperty(netid,"dns_domain","None")
+        self._Wireless.SetWirelessProperty(netid,"gateway","None")
+        self._Wireless.SetWirelessProperty(netid,"use_global_dns",0)
+        self._Wireless.SetWirelessProperty(netid,"netmask","None")
+        self._Wireless.SetWirelessProperty(netid,"usedhcphostname",0) ## set 1 to use hostname above
+        self._Wireless.SetWirelessProperty(netid,"bitrate","auto")
+        self._Wireless.SetWirelessProperty(netid,"allow_lower_bitrates",0)
+        self._Wireless.SetWirelessProperty(netid,"dns3","None")
+        self._Wireless.SetWirelessProperty(netid,"dns2","None")
+        self._Wireless.SetWirelessProperty(netid,"dns1","None")
+        self._Wireless.SetWirelessProperty(netid,"use_settings_globally",0)
+        self._Wireless.SetWirelessProperty(netid,"use_static_dns",0)
+        self._Wireless.SetWirelessProperty(netid,"search_domain","None")
+        """
+        self._Wireless.SetWirelessProperty(netid,"enctype","wpa-psk")
+        self._Wireless.SetWirelessProperty(netid,"apsk",password)
+        self._Wireless.SetWirelessProperty(netid,"automatic",1)
+
+        self.ShowBox(MyLangManager.Tr("Connecting"))
+        
+        self._MyList[netid].Connect()
+        print("after Connect")
+        self.UpdateStatus()
+
+    def GetWirelessEncrypt(self,network_id):
+        results = []
+        activeID = -1
+        for x,enc_type in enumerate(self._EncMethods):
+            if enc_type["type"] == self._Wireless.GetWirelessProperty(network_id,"enctype"):
+                activeID = x
+                break
+
+        if activeID == -1:
+            return results
+        
+        for type_ in ['required','optional']:
+            fields = self._EncMethods[activeID][type_]
+            for field in fields:
+                try:
+                    text = field[1].lower().replace(' ','_')
+                except KeyError:
+                    text = field[1].replace(' ','_')
+                
+                value = self._Wireless.GetWirelessProperty(network_id, field[0])
+                results.append({text:value})
+        """
+        [{'preshared_key': 'blah blah blah',},]
+
+        or nothing 
+        [{'identity': None,},{'password': None,},]
+
+        """
+        return results
+
+    def AbortedAndReturnToUpLevel(self):
+        self.HideBox()
+        self._Screen._FootBar.ResetNavText()
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+
+    def OnKbdReturnBackCb(self):
+        password_inputed = "".join(myvars.PasswordPage._Textarea._MyWords)
+        if is_wifi_connected_now() == False:
+            self.ConfigWireless(password_inputed)
+        else:
+            for i in range(0,10):
+                if is_wifi_connected_now() == True:
+                    self.ShowBox(MyLangManager.Tr("Launching"))
+                    self._Daemon.Disconnect()
+                    self._Daemon.SetForcedDisconnect(True)
+                    self._Connecting = False
+                else:
+                    break
+                
+                pygame.time.delay(100)
+                
+            if is_wifi_connected_now() == False:
+                self.ConfigWireless(password_inputed)
+            else:
+                self.ShowBox(MyLangManager.Tr("Disconnect first"))
+        
+    def OnReturnBackCb(self):
+        pass
+        
+        
+    def KeyDown(self,event):
+
+#        if self._BlockingUI == True:
+#            print("UI blocking ...")
+#            return
+        
+        if IsKeyMenuOrB(event.key):
+            if self._Wireless != None:
+                wireless_connecting = self._Wireless.CheckIfWirelessConnecting()
+                if wireless_connecting:
+                    self.ShutDownConnecting()
+                    self.ShowBox(MyLangManager.Tr("ShutDownConnecting"))
+                    self._BlockingUI=True
+                    self._BlockCb = self.AbortedAndReturnToUpLevel
+                else:
+                    self.AbortedAndReturnToUpLevel()
+            else:
+                self.HideBox()
+                self.ReturnToUpLevelPage()
+                self._Screen.Draw()
+                self._Screen.SwapAndShow()
+    
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if IsKeyStartOrA(event.key): ## enter to set password,enter is B on GM
+            if len(self._MyList) == 0:
+                return
+            
+            self._CurBssid = self._MyList[self._PsIndex]._Bssid
+            
+            wicd_wirelss_encrypt_pwd = self.GetWirelessEncrypt(self._PsIndex)
+            if self._MyList[self._PsIndex]._IsActive:
+                self.ShowBox( self._Wireless.GetWirelessIP('')    )
+            else:
+                self._Screen.PushCurPage()
+                self._Screen.SetCurPage( myvars.PasswordPage )
+                
+                thepass = ""
+                for i in wicd_wirelss_encrypt_pwd:
+                    if "preshared_key" in i:
+                        if i["preshared_key"] != None:
+                            if len(str(i["preshared_key"])) > 0:
+                                thepass = str(i["preshared_key"])
+                                break
+                
+                myvars.PasswordPage.SetPassword(thepass)
+                self._Screen.Draw()
+                self._Screen.SwapAndShow()
+                
+                """
+                try:
+                    self._Screen.Draw()
+                    self._Screen.SwapAndShow()
+                except Exception as e: 
+                    print(e)
+                    exit(-1)
+                """
+        if event.key == CurKeys["X"]:
+            self.Rescan(False)
+            
+        if event.key == CurKeys["Y"]:
+            if len(self._MyList) == 0:
+                return
+
+            self._InfoPage._NetworkId = self._PsIndex
+            self._InfoPage._Wireless  = self._Wireless
+            self._InfoPage._Daemon    = self._Daemon
+            
+            self._Screen.PushPage(self._InfoPage)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+
+    def Init(self):
+        
+        self._PosX = self._Index * self._Screen._Width
+        self._Width = self._Screen._Width
+        self._Height = self._Screen._Height
+
+        #self._CanvasHWND = pygame.Surface((self._Width,self._Height))
+        self._CanvasHWND = self._Screen._CanvasHWND
+
+        ps = WifiListSelector()
+        ps._Parent = self
+        ps._Width = Width - 12
+        
+        self._Ps = ps
+        self._PsIndex = 0
+        
+        msgbox = WifiListMessageBox()
+        msgbox._CanvasHWND = self._CanvasHWND
+        msgbox.Init(" ",MyLangManager.TrFont("veramono12"))
+        msgbox._Parent = self
+        
+        self._MsgBox = msgbox 
+
+        self._EncMethods = misc.LoadEncryptionMethods() # load predefined templates from /etc/wicd/...
+
+        """
+  {
+    'fields': [],
+    'name': 'WPA 1/2 (Passphrase)',
+    'optional': [],
+    'protected': [
+      ['apsk', 'Preshared_Key'],
+    ],
+    'required': [
+      ['apsk', 'Preshared_Key'],
+    ],
+    'type': 'wpa-psk',
+  },
+        """
+        
+        self.UpdateNetList(force_check=True,firstrun=True)
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = 2
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+
+
+        self._InfoPage = WifiInfoPage()
+        self._InfoPage._Screen = self._Screen
+        self._InfoPage._Name   = MyLangManager.Tr("Wifi info")
+        self._InfoPage.Init()
+        
+    def Draw(self):
+        self.ClearCanvas()
+
+        if len(self._MyList) == 0:
+            return
+        
+        self._Ps.Draw()
+        for i in self._MyList:
+            i.Draw()
+
+        
+        self._Scroller.UpdateSize( len(self._MyList)*NetItem._Height, self._PsIndex*NetItem._Height)
+        self._Scroller.Draw()

+ 29 - 0
Menu/GameShell/10_Settings/__init__.py

@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+from pygame.locals import *
+from sys import exit
+import os
+import sys
+
+from datetime import datetime
+
+import base64
+from beeprint import pp
+
+
+## local UI import
+import pages
+import myvars
+
+def Init(main_screen):
+    pages.InitListPage(main_screen)
+
+def API(main_screen):
+    
+    if main_screen !=None:
+        main_screen.PushCurPage()
+        main_screen.SetCurPage(myvars.ListPage)
+        main_screen.Draw()
+        main_screen.SwapAndShow()
+        

+ 57 - 0
Menu/GameShell/10_Settings/list_item.py

@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+
+
+
+## local UI import
+from UI.page   import Page
+from UI.label  import Label
+from UI.lang_manager import MyLangManager
+from UI.skin_manager import MySkinManager
+
+# a item for List
+# - - - - - - - - - - - -- 
+# | Icon  Text.....    > |
+# ------------------------
+
+import myvars # icons_path
+
+
+class ListItem(object):
+    _PosX = 0
+    _PosY = 0
+    _Width = 0
+    _Height = 30
+
+    _Labels = {}
+    _Icons  = {}
+    _Fonts  = {}
+
+    _LinkObj = None
+    
+    def __init__(self):
+        self._Labels = {}
+        self._Icons  = {}
+        self._Fonts  = {}
+
+    def Init(self,text):
+
+        #self._Fonts["normal"] = fonts["veramono12"]
+        
+        l = Label()
+        l._PosX = 16
+        l.SetCanvasHWND(self._Parent._CanvasHWND)
+        text = MyLangManager.Tr(text)
+        l.Init(text,self._Fonts["normal"])
+        self._Labels["Text"] = l
+
+
+    def Draw(self):
+
+        self._Labels["Text"]._PosY = self._PosY + (self._Height - self._Labels["Text"]._Height)/2
+        self._Labels["Text"].Draw()
+
+        pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),(self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)
+    
+

+ 155 - 0
Menu/GameShell/10_Settings/list_page.py

@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+import sys
+
+from libs.roundrects import aa_round_rect
+
+## local UI import
+from UI.constants import Width,Height
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect,FileExists
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+from UI.info_page_selector import InfoPageSelector
+
+from list_item  import ListItem
+
+import myvars
+
+class ListPage(Page):
+
+    _Icons = {}
+    _Selector=None
+    
+    _FootMsg = ["Nav","","","Back","Enter"]
+    _MyList = []
+    _ListFontObj = MyLangManager.TrFont("varela15")
+
+    _Scroller = None
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+        self._CanvasHWND = None
+        self._MyList = []
+        
+    def Init(self):
+        self._PosX = self._Index * self._Screen._Width
+        self._Width = self._Screen._Width
+        self._Height = self._Screen._Height
+
+        self._CanvasHWND = self._Screen._CanvasHWND
+
+        ps = InfoPageSelector()
+        ps._Parent = self
+        ps._PosX = 2
+        self._Ps = ps
+        self._PsIndex = 0
+        
+        #                ""   pkgname, label
+        alist         = [["","Airplane","Airplane Mode"],
+                         ["","PowerOptions","Power Options"],
+                         ["","Wifi","Wi-Fi"],
+                         ["","Bluetooth","Bluetooth"],
+                         ["","Sound","Sound  Volume"],
+                         ["","Brightness","BackLight Brightness"],
+                         ["","Storage",""],
+                         ["","Time","Timezone"],
+                         ["","Languages","Languages"],
+                         ["","Notification","Notification"],
+                         ["","Update", "Update Launcher"],
+                         ["","Cores", "Retroarch cores manager"],
+                         ["","About",  "About"],
+                         ["","PowerOFF","Power OFF"],
+                         ["","ButtonsLayout","Buttons Layout"],
+                         #["","Skins","Theme Manager"],
+                         #["","LauncherGo","Switch to LauncherGo"],
+                         ["","Lima","GPU Driver Switch"],
+                         ["","GateWay","Network Gateway Switch"]]
+
+        start_x  = 0
+        start_y  = 0
+
+        
+        sys.path.append(myvars.basepath)# add self as import path
+        for i,v in enumerate(alist):
+            li = ListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + i*ListItem._Height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFontObj
+
+            if v[2] != "":
+                li.Init(v[2])
+            else:
+                li.Init(v[1])
+            
+            #if v[1] == "Wifi" or v[1] == "Sound" or v[1] == "Brightness" or v[1] == "Storage" or v[1] == "Update" or v[1] == "About" or v[1] == "PowerOFF" or v[1] == "HelloWorld":
+            if FileExists(myvars.basepath+"/"+ v[1]):
+                li._LinkObj = __import__(v[1])
+                init_cb   = getattr(li._LinkObj,"Init",None)
+                if init_cb != None:
+                    if callable(init_cb):
+                        li._LinkObj.Init(self._Screen)
+                
+                self._MyList.append(li)
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+
+    def Click(self):
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._LinkObj != None:
+            api_cb = getattr(cur_li._LinkObj,"API",None)
+            if api_cb != None:
+                if callable(api_cb):
+                    cur_li._LinkObj.API(self._Screen)
+
+        
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+
+        if IsKeyStartOrA(event.key):
+            self.Click()
+            
+    def Draw(self):
+        self.ClearCanvas()
+
+        if len(self._MyList) * ListItem._Height > self._Height:
+            self._Ps._Width = self._Width - 11
+            
+            self._Ps.Draw()
+            
+            for i in self._MyList:
+                i.Draw()
+        
+            self._Scroller.UpdateSize( len(self._MyList)*ListItem._Height, self._PsIndex*ListItem._Height)
+            self._Scroller.Draw()
+        else:
+            self._Ps._Width = self._Width
+            self._Ps.Draw()
+            for i in self._MyList:
+                i.Draw()
+
+            

+ 12 - 0
Menu/GameShell/10_Settings/myvars.py

@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*- 
+
+from sys import exit
+import os
+import sys
+
+
+basepath = os.path.dirname(os.path.realpath(__file__))
+
+icons_path = basepath+"/icons"
+
+ListPage = None

+ 13 - 0
Menu/GameShell/10_Settings/pages.py

@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*- 
+
+from list_page import ListPage
+
+import myvars
+
+def InitListPage(main_screen):
+
+    myvars.ListPage = ListPage()
+    
+    myvars.ListPage._Screen = main_screen
+    myvars.ListPage._Name = "Setting List"
+    myvars.ListPage.Init()

+ 1188 - 0
Menu/GameShell/21_Warehouse/__init__.py

@@ -0,0 +1,1188 @@
+# -*- coding: utf-8 -*- 
+import os
+import pygame
+import platform
+#import commands
+import glob
+import json
+import gobject
+import sqlite3
+#from beeprint import pp
+from libs.roundrects import aa_round_rect
+from shutil import copyfile,rmtree
+
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES,RESTARTUI
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect,FileExists,ArmSystem
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.scroller   import ListScroller
+from UI.icon_pool  import MyIconPool
+from UI.icon_item  import IconItem
+from UI.multilabel import MultiLabel
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+from UI.info_page_list_item import InfoPageListItem
+from UI.info_page_selector  import InfoPageSelector
+from UI.yes_cancel_confirm_page import YesCancelConfirmPage
+from UI.keyboard import Keyboard
+
+from UI.download   import Download
+
+import config
+
+class RPCStack:
+    def __init__(self):
+        self.stack = list()
+
+    def Push(self,data):
+        if data not in self.stack:
+            self.stack.append(data)
+            return True
+        return False
+
+    def Pop(self):
+        if len(self.stack)<=0:
+            return None,False
+        return self.stack.pop(),True
+
+    def Last(self):
+        idx = len(self.stack) -1
+        if idx < 0:
+            return None
+        else:
+            return self.stack[ idx ]
+    
+    def Length(self):
+        return len(self.stack)
+
+class LoadHousePage(Page):
+    _FootMsg = ["Nav.","","","Back","Cancel"]
+    _Value = 0
+    _URL = None
+    _ListFontObj = MyLangManager.TrFont("varela18")
+    _URLColor  = MySkinManager.GiveColor('URL')
+    _TextColor = MySkinManager.GiveColor('Text')
+    _Caller=None
+    _img = None 
+    _Downloader=None
+    _DownloaderTimer=-1
+    def __init__(self):
+        Page.__init__(self)        
+        self._Icons = {}
+        self._CanvasHWND = None
+        
+    def Init(self):
+        self._PosX = self._Index * self._Screen._Width
+        self._Width = self._Screen._Width
+        self._Height = self._Screen._Height
+
+        self._CanvasHWND = self._Screen._CanvasHWND
+        self._LoadingLabel = Label()
+        self._LoadingLabel.SetCanvasHWND(self._CanvasHWND)
+        self._LoadingLabel.Init("Loading",self._ListFontObj)
+        self._LoadingLabel.SetColor(self._TextColor )
+ 
+    def OnLoadCb(self):
+        if self._URL is None:
+            return
+        self._img = None
+        self.ClearCanvas()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+        filename = self._URL.split("/")[-1].strip()
+        local_dir = self._URL.split("raw.githubusercontent.com")
+
+        if len(local_dir) >1:
+            menu_file = local_dir[1]
+            local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
+        
+            if FileExists(local_menu_file):
+                #load json
+                with open(local_menu_file) as json_file:
+                    try:
+                        local_menu_json = json.load(json_file)
+                        self._Caller._MyStack.Push(local_menu_json["list"])
+                    except:
+                        pass
+
+                    self.Leave()
+
+            else:
+                self._Downloader = Download(self._URL,"/tmp",None)
+                self._Downloader.start()
+                self._DownloaderTimer = gobject.timeout_add(400, self.GObjectUpdateProcessInterval)
+
+     
+    def GObjectUpdateProcessInterval(self):
+        ret = True
+        if self._Screen.CurPage() == self:
+                if self._Downloader._stop == True:
+                    ret = False
+ 
+                dst_filename = self._Downloader.get_dest()
+                if self._Downloader.isFinished():
+                    if self._Downloader.isSuccessful():
+                        filename = self._URL.split("/")[-1].strip()
+                        local_dir = self._URL.split("raw.githubusercontent.com")
+                        menu_file = local_dir[1]
+                        local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
+
+                        dl_file = os.path.join("/tmp",filename)
+                        if not os.path.exists(os.path.dirname(local_menu_file)):
+                            os.makedirs(os.path.dirname(local_menu_file))
+
+                        copyfile(dl_file, local_menu_file)
+                        with open(local_menu_file) as json_file:
+                            try:
+                                local_menu_json = json.load(json_file)
+                                self._Caller._MyStack.Push(local_menu_json["list"])
+                            except:
+                                pass
+
+                        ret = False
+
+                        self.Leave()
+                    else:
+                        self._Screen._MsgBox.SetText("Fetch house failed")
+                        self._Screen._MsgBox.Draw()
+                        self._Screen.SwapAndShow()
+                        ret = False
+                return ret
+        else:
+            return False
+    
+    def Leave(self):
+        if self._DownloaderTimer != -1:
+            gobject.source_remove(self._DownloaderTimer)
+        self._DownloaderTimer = -1
+            
+        if self._Downloader != None:
+            try:
+                self._Downloader.stop()
+            except:
+                print("user canceled ")
+            
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        self._URL = None
+
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            self.Leave()
+
+    def Draw(self):
+        self.ClearCanvas()
+        self._LoadingLabel.NewCoord( (Width-self._LoadingLabel._Width)/2,(Height-44)/2)
+        self._LoadingLabel.Draw()
+
+        if self._img is not None:
+            self._CanvasHWND.blit(self._img,midRect(Width/2,
+                                       (Height-44)/2,
+                                       pygame.Surface.get_width(self._img),pygame.Surface.get_height(self._img),Width,Height-44))
+
+
+class ImageDownloadProcessPage(Page):
+    _FootMsg = ["Nav.","","","Back",""]
+    _Value = 0
+    _URL = None
+    _ListFontObj = MyLangManager.TrFont("varela13")
+    _URLColor  = MySkinManager.GiveColor('URL')
+    _TextColor = MySkinManager.GiveColor('Text')
+    _img = None 
+    _Downloader=None
+    _DownloaderTimer=-1 
+    def __init__(self):
+        Page.__init__(self)        
+        self._Icons = {}
+        self._CanvasHWND = None
+        
+    def Init(self):
+        self._PosX = self._Index * self._Screen._Width
+        self._Width = self._Screen._Width
+        self._Height = self._Screen._Height
+
+        self._CanvasHWND = self._Screen._CanvasHWND
+        self._LoadingLabel = Label()
+        self._LoadingLabel.SetCanvasHWND(self._CanvasHWND)
+        self._LoadingLabel.Init("Loading",self._ListFontObj)
+        self._LoadingLabel.SetColor(self._TextColor )
+ 
+    def OnLoadCb(self):
+        if self._URL is None:
+            return
+        self._img = None
+        self.ClearCanvas()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        
+        filename = self._URL.split("/")[-1].strip()
+        local_dir = self._URL.split("raw.githubusercontent.com")
+
+        if len(local_dir) >1:
+            menu_file = local_dir[1]
+            local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
+        
+            if FileExists(local_menu_file):
+                self._img = pygame.image.load(local_menu_file).convert_alpha()
+                self._Screen.Draw()
+                self._Screen.SwapAndShow()
+            else:
+                self._Downloader = Download(self._URL,"/tmp",None)
+                self._Downloader.start()
+                self._DownloaderTimer = gobject.timeout_add(300, self.GObjectUpdateProcessInterval)
+
+     
+    def GObjectUpdateProcessInterval(self):
+        ret = True
+        if self._Screen.CurPage() == self:
+                if self._Downloader._stop == True:
+                    ret = False
+ 
+                dst_filename = self._Downloader.get_dest()
+                if self._Downloader.isFinished():
+                    if self._Downloader.isSuccessful():
+                        filename = self._URL.split("/")[-1].strip()
+                        local_dir = self._URL.split("raw.githubusercontent.com")
+                        menu_file = local_dir[1]
+                        local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
+                        
+                        dl_file = os.path.join("/tmp",filename)
+                        if not os.path.exists(os.path.dirname(local_menu_file)):
+                            os.makedirs(os.path.dirname(local_menu_file))
+
+                        copyfile(dl_file, local_menu_file)
+                        ret = False
+ 
+                #print("dest ",dst_filename)
+                if FileExists(dst_filename):
+                    try:
+                        #print("load and draw")
+                        self._img = pygame.image.load(dst_filename).convert_alpha()
+                        self._Screen.Draw()
+                        self._Screen.SwapAndShow()
+                    except Exception as ex:
+                        print(ex)
+
+                return ret
+        else:
+            return False
+    
+        
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            gobject.source_remove(self._DownloaderTimer)
+            self._DownloaderTimer = -1
+            
+            if self._Downloader != None:
+                try:
+                    self._Downloader.stop()
+                except:
+                    print("user canceled ")
+            
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            self._URL = None
+
+    def Draw(self):
+        self.ClearCanvas()
+        self._LoadingLabel.NewCoord( (Width-self._LoadingLabel._Width)/2,(Height-44)/2)
+        self._LoadingLabel.Draw()
+
+        if self._img is not None:
+            self._CanvasHWND.blit(self._img,midRect(Width/2,
+                                       (Height-44)/2,
+                                       pygame.Surface.get_width(self._img),pygame.Surface.get_height(self._img),Width,Height-44))
+
+
+class Aria2DownloadProcessPage(Page):
+    _FootMsg = ["Nav.","","Pause","Back","Cancel"]
+    _DownloaderTimer = -1
+    _Value = 0
+    _GID = None
+
+    _PngSize = {}
+
+    _FileNameLabel = None
+    _SizeLabel     = None
+
+    _URLColor  = MySkinManager.GiveColor('URL')
+    _TextColor = MySkinManager.GiveColor('Text')
+    
+    def __init__(self):
+        Page.__init__(self)        
+        self._Icons = {}
+        self._CanvasHWND = None
+        
+    def Init(self):
+        self._PosX = self._Index * self._Screen._Width
+        self._Width = self._Screen._Width
+        self._Height = self._Screen._Height
+
+        self._CanvasHWND = self._Screen._CanvasHWND
+
+        bgpng = IconItem()
+        bgpng._ImgSurf = MyIconPool.GiveIconSurface("rom_download")
+        bgpng._MyType = ICON_TYPES["STAT"]
+        bgpng._Parent = self
+        bgpng.Adjust(0,0,self._PngSize["bg"][0],self._PngSize["bg"][1],0)
+        self._Icons["bg"] = bgpng
+
+        
+        self._FileNameLabel = Label()
+        self._FileNameLabel.SetCanvasHWND(self._CanvasHWND)
+        self._FileNameLabel.Init("", MyLangManager.TrFont("varela12"))
+
+        self._SizeLabel = Label()
+        self._SizeLabel.SetCanvasHWND(self._CanvasHWND)
+        self._SizeLabel.Init("0/0Kb",MyLangManager.TrFont("varela12"))
+        self._SizeLabel.SetColor( self._URLColor )
+ 
+    @property
+    def GObjectUpdateProcessInterval(self):
+        downloaded = 0
+        if self._Screen.CurPage() == self and self._GID is not None:
+                self._Value =  config.RPC.tellStatus(self._GID)
+            
+                downloaded = 0
+                total = 0
+
+        if self._Value["status"] == "waiting":
+            self._FileNameLabel.SetText("waiting to download...")
+        if self._Value["status"] == "paused":
+            self._FileNameLabel.SetText("download paused...")
+        if self._Value["status"] == "error":
+            self._FileNameLabel.SetText("download errors,cancel it please")
+
+        if self._Value["status"] == "active":
+            downloaded = self._Value["completedLength"]
+            total = self._Value["totalLength"]
+
+            downloaded = downloaded / 1000.0 / 1000.0
+            total = total / 1000.0 / 1000.0
+
+        self._SizeLabel.SetText("%.2f" % downloaded+"/"+"%.2f" % total+"Mb")
+
+        print("Progress: %d%%" % (self._Value))
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        return True
+
+    
+    def CheckDownload(self,aria2_gid):
+        self._GID = aria2_gid 
+        self._DownloaderTimer = gobject.timeout_add(234, self.GObjectUpdateProcessInterval)
+        
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            gobject.source_remove(self._DownloaderTimer)
+            self._DownloaderTimer = -1
+            
+            #if self._Downloader != None:
+            #    try:
+            #        self._Downloader.stop()
+            #    except:
+            #        print("user canceled ")
+            
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+    def Draw(self):
+        self.ClearCanvas()
+
+        self._Icons["bg"].NewCoord(self._Width/2,self._Height/2-20)
+        self._Icons["bg"].Draw()
+        
+        percent = self._Value
+        if percent < 10:
+            percent = 10
+
+        
+        rect_ = midRect(self._Width/2,self._Height/2+33,170,17, Width,Height)
+        aa_round_rect(self._CanvasHWND,rect_,MySkinManager.GiveColor('TitleBg'),5,0,MySkinManager.GiveColor('TitleBg'))
+        
+        rect2 = midRect(self._Width/2,self._Height/2+33,int(170*(percent/100.0)),17, Width,Height)
+        rect2.left = rect_.left
+        rect2.top  = rect_.top
+        aa_round_rect(self._CanvasHWND,rect2,MySkinManager.GiveColor('Front'),5,0,MySkinManager.GiveColor('Front'))
+
+        rect3 = midRect(self._Width/2,self._Height/2+53,self._FileNameLabel._Width, self._FileNameLabel._Height,Width,Height)
+
+        rect4 = midRect(self._Width/2,self._Height/2+70,self._SizeLabel._Width, self._SizeLabel._Height,Width,Height)
+
+        self._FileNameLabel.NewCoord(rect3.left,rect3.top)
+        self._SizeLabel.NewCoord(rect4.left, rect4.top)
+
+        self._FileNameLabel.Draw()
+        self._SizeLabel.Draw()
+
+
+def dict_factory(cursor, row):
+    d = {}
+    for idx, col in enumerate(cursor.description):
+        d[col[0]] = row[idx]
+    return d
+
+class GameStoreListItem(InfoPageListItem):
+    _Type = None #source,dir,launcher,pico8 
+    _CanvasHWND = None 
+    def Init(self,text):
+
+        #self._Fonts["normal"] = fonts["veramono12"]
+        
+        l = Label()
+        l._PosX = 10
+        l.SetCanvasHWND(self._Parent._CanvasHWND)
+
+        l.Init(text,self._Fonts["normal"])
+        self._Labels["Text"] = l
+        
+        add_icon = IconItem()
+        add_icon._ImgSurf = MyIconPool.GiveIconSurface("add")
+        add_icon._CanvasHWND = self._CanvasHWND
+        add_icon._Parent = self
+        add_icon.Init(0,0,MyIconPool.Width("add"),MyIconPool.Height("add"),0)
+ 
+        ware_icon = IconItem()
+        ware_icon._ImgSurf = MyIconPool.GiveIconSurface("ware")
+        ware_icon._CanvasHWND = self._CanvasHWND
+        ware_icon._Parent = self
+        ware_icon.Init(0,0,MyIconPool.Width("ware"),MyIconPool.Height("ware"),0)
+
+        app_icon = IconItem()
+        app_icon._ImgSurf = MyIconPool.GiveIconSurface("app")
+        app_icon._CanvasHWND = self._CanvasHWND
+        app_icon._Parent = self
+        app_icon.Init(0,0,MyIconPool.Width("app"),MyIconPool.Height("app"),0)
+
+        appdling_icon = IconItem()
+        appdling_icon._ImgSurf = MyIconPool.GiveIconSurface("appdling")
+        appdling_icon._CanvasHWND = self._CanvasHWND
+        appdling_icon._Parent = self
+        appdling_icon.Init(0,0,MyIconPool.Width("appdling"),MyIconPool.Height("appdling"),0)
+
+        blackheart_icon = IconItem()
+        blackheart_icon._ImgSurf = MyIconPool.GiveIconSurface("blackheart")
+        blackheart_icon._Width = MyIconPool.Width("blackheart")
+        blackheart_icon._Height = MyIconPool.Height("blackheart")
+        blackheart_icon._CanvasHWND = self._CanvasHWND
+        blackheart_icon._Parent = self
+
+        self._Icons["add"] = add_icon
+        self._Icons["ware"] = ware_icon
+        self._Icons["app"]  = app_icon
+        self._Icons["appdling"] = appdling_icon
+        self._Icons["blackheart"] = blackheart_icon
+
+    
+    def Draw(self):
+        if self._ReadOnly == True:
+            self._Labels["Text"].SetColor(MySkinManager.GiveColor("ReadOnlyText"))
+        else:
+            self._Labels["Text"].SetColor(MySkinManager.GiveColor("Text"))
+
+        padding = 17
+
+        if self._Type == None:
+            padding = 0
+         
+        
+        if self._Type == "source" or self._Type == "dir":
+            self._Icons["ware"].NewCoord( 4, (self._Height - self._Icons["ware"]._Height)/2 )
+            self._Icons["ware"].DrawTopLeft()
+        
+        if self._Type == "launcher" or self._Type == "pico8" or self._Type == "tic80":
+            _icon = "app"
+            if self._ReadOnly == True:
+                _icon = "appdling"
+            
+            self._Icons[_icon].NewCoord( 4, (self._Height - self._Icons[_icon]._Height)/2)
+            self._Icons[_icon].DrawTopLeft()
+           
+        if self._Type == "add_house":
+            self._Icons["add"].NewCoord( 4, (self._Height - self._Icons["add"]._Height)/2)
+            self._Icons["add"].DrawTopLeft()
+
+
+        self._Labels["Text"]._PosX = self._Labels["Text"]._PosX + self._PosX + padding
+        self._Labels["Text"]._PosY = self._PosY + (self._Height - self._Labels["Text"]._Height)/2
+        self._Labels["Text"].Draw()
+        self._Labels["Text"]._PosX = self._Labels["Text"]._PosX - self._PosX - padding
+
+        if "Small" in self._Labels:
+            self._Labels["Small"]._PosX = self._Width - self._Labels["Small"]._Width-5
+            
+            self._Labels["Small"]._PosY = self._PosY + (self._Height - self._Labels["Small"]._Height)/2
+            self._Labels["Small"].Draw()
+        
+
+        pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),(self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)
+ 
+
+class GameStorePage(Page):
+    _FootMsg =  ["Nav","Update","Up","Back","Select"]
+    _MyList = []
+    _ListFont12 = MyLangManager.TrFont("notosanscjk12")
+    _ListFont15 = MyLangManager.TrFont("varela15")
+   
+    _AList = {}
+
+    _Scrolled = 0
+    
+    _BGwidth = 320
+    _BGheight = 240-24-20
+
+    _DrawOnce = False
+    _Scroller = None
+    _InfoPage = None
+    _Downloading = None
+    _aria2_db = "aria2tasks.db"
+    _warehouse_db = "warehouse.db"
+    _GobjTimer = -1
+
+    _Scrolled_cnt = 0
+
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+        self._MyStack = RPCStack()
+          #title file type
+        ## Two level url , only github.com
+        
+        repos = [
+         {"title":"github.com/clockworkpi/warehouse","file":"https://raw.githubusercontent.com/clockworkpi/warehouse/master/index.json","type":"source"}
+        ]
+        self._MyStack.Push(repos)
+ 
+    def GObjectUpdateProcessInterval(self):
+        ret = True
+        dirty = False
+        for x in self._MyList:
+            if x._Type == "launcher" or x._Type == "pico8" or x._Type == "tic80":
+                percent = config.RPC.getPercent(x._Value["file"])
+                if percent is not None:
+                    x.SetSmallText(str(percent)+"%")
+                    dirty = True
+                else:
+                    x.SetSmallText("")
+
+        if self._Screen.CurPage() == self and dirty == True:
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        return ret
+
+    def SyncWarehouse(self):
+        try:
+            conn = sqlite3.connect(self._warehouse_db)
+            conn.row_factory = dict_factory
+            c = conn.cursor()
+            ret = c.execute("SELECT * FROM warehouse").fetchall()
+            conn.close()
+            return ret
+        except Exception as ex:
+            print(ex)
+            return None
+        return None
+
+    def SyncTasks(self):
+        try:
+            conn = sqlite3.connect(self._aria2_db)
+            conn.row_factory = dict_factory
+            c = conn.cursor()
+            ret = c.execute("SELECT * FROM tasks").fetchall()
+            conn.close()
+            return ret
+        except Exception as ex:
+            print(ex)
+            return None
+        return None
+
+    def SyncList(self):
+        
+        self._MyList = []
+        
+        start_x  = 0
+        start_y  = 0
+        last_height = 0
+
+        repos = []
+        stk = self._MyStack.Last()
+        stk_lev = self._MyStack.Length()
+        repos.extend(stk)
+        add_new_house = [
+            {"title":"Add new warehouse...","file":"master/index.json","type":"add_house","status":"complete"}
+        ]
+
+        if stk_lev == 1: # on top
+            ware_menu= self.SyncWarehouse()
+            if ware_menu != None and len(ware_menu) > 0:
+                #print(ware_menu)
+                repos.extend(ware_menu )
+
+            tasks_menu= self.SyncTasks()
+            if tasks_menu != None and len(tasks_menu) > 0:
+                #print(tasks_menu)
+                repos.extend(tasks_menu )
+            
+            #print(repos)
+            repos.extend(add_new_house)
+
+        for i,u in enumerate( repos ):            
+            #print(i,u)
+            li = GameStoreListItem()
+            li._CanvasHWND = self._CanvasHWND
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + last_height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFont15
+            li._Fonts["small"]  = self._ListFont12
+            li._Active = False
+            li._ReadOnly = True
+            li._Value = u
+            li._Type = u["type"]
+            li.Init( u["title"] )
+            
+            if stk_lev >1:
+                remote_file_url = u["file"]
+                menu_file = remote_file_url.split("raw.githubusercontent.com")[1]
+                local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
+
+                if FileExists(local_menu_file):
+                    li._ReadOnly = False
+                else:
+                    li._ReadOnly = True
+            elif stk_lev == 1:
+                if "status" in u:
+                    if u["status"] == "complete":
+                        li._ReadOnly = False
+
+                if u["type"]=="source":
+                    li._ReadOnly = False
+
+            last_height += li._Height
+            
+            if li._Type == "launcher" or li._Type == "pico8" or li._Type == "tic80":
+                li.SetSmallText("")
+            
+            self._MyList.append(li)
+            
+        self.RefreshPsIndex()
+            
+        
+    def Init(self):
+        if self._Screen != None:
+            if self._Screen._CanvasHWND != None and self._CanvasHWND == None:
+                self._HWND = self._Screen._CanvasHWND
+                self._CanvasHWND = pygame.Surface( (self._Screen._Width,self._BGheight) )
+
+        self._PosX = self._Index*self._Screen._Width 
+        self._Width = self._Screen._Width ## equal to screen width
+        self._Height = self._Screen._Height
+
+        done = IconItem()
+        done._ImgSurf = MyIconPool.GiveIconSurface("done")
+        done._MyType = ICON_TYPES["STAT"]
+        done._Parent = self
+        self._Icons["done"] = done
+
+        ps = InfoPageSelector()
+        ps._Parent = self
+        self._Ps = ps
+        self._PsIndex = 0
+
+        self.SyncList()
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        self._Scroller.SetCanvasHWND(self._CanvasHWND)
+ 
+        self._remove_page = YesCancelConfirmPage()
+        self._remove_page._Screen = self._Screen
+        self._remove_page._StartOrA_Event = self.RemoveGame
+
+        self._remove_page._Name ="Are you sure?"
+        self._remove_page.Init()
+
+        self._Keyboard = Keyboard()
+        self._Keyboard._Name = "Enter warehouse addr"
+        self._Keyboard._FootMsg = ["Nav.","Add","ABC","Backspace","Enter"]
+        self._Keyboard._Screen = self._Screen
+        self._Keyboard.Init()
+        self._Keyboard.SetPassword("github.com/clockworkpi/warehouse")
+        self._Keyboard._Caller = self
+
+        self._PreviewPage = ImageDownloadProcessPage()
+        self._PreviewPage._Screen = self._Screen
+        self._PreviewPage._Name = "Preview"
+        self._PreviewPage.Init()
+
+        self._LoadHousePage = LoadHousePage()
+        self._LoadHousePage._Screen = self._Screen
+        self._LoadHousePage._Name = "Warehouse"
+        self._LoadHousePage._Caller = self
+        self._LoadHousePage.Init()
+
+
+    def ResetHouse(self):
+        if self._PsIndex > len(self._MyList) -1:
+            return
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._Value["type"] == "source":
+            remote_file_url = cur_li._Value["file"]
+            menu_file = remote_file_url.split("raw.githubusercontent.com")[1] #assume master branch
+            local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
+            local_menu_file_path = os.path.dirname(local_menu_file)
+            print(local_menu_file_path)
+            local_jsons = glob.glob(local_menu_file_path+"/**/*.json")
+            try:
+                if os.path.exists(local_menu_file):
+                    os.remove(local_menu_file)
+                if os.path.exists(local_menu_file+".aria2"):
+                    os.remove(local_menu_file+".aria2")
+
+                for x in local_jsons:
+                    os.remove(x)
+
+            except Exception as ex:
+                print(ex)
+
+            self._Screen._MsgBox.SetText("Done")
+            self._Screen._MsgBox.Draw()
+            self._Screen.SwapAndShow()
+
+    def LoadHouse(self):
+        if self._PsIndex > len(self._MyList) -1:
+            return
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._Value["type"] == "source" or cur_li._Value["type"] == "dir":
+
+            self._LoadHousePage._URL = cur_li._Value["file"]
+            self._Screen.PushPage(self._LoadHousePage)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+
+    def PreviewGame(self):
+        if self._PsIndex > len(self._MyList) -1:
+            return
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._Value["type"] == "launcher" or cur_li._Value["type"] == "pico8" or cur_li._Value["type"] == "tic80":
+            if "shots" in cur_li._Value:
+                print(cur_li._Value["shots"])
+                self._PreviewPage._URL = cur_li._Value["shots"]
+                self._Screen.PushPage(self._PreviewPage)
+                self._Screen.Draw()
+                self._Screen.SwapAndShow()
+
+
+    def RemoveGame(self):
+        if self._PsIndex > len(self._MyList) -1:
+            return
+
+        cur_li = self._MyList[self._PsIndex]
+        #if cur_li._Active == True:
+        #    return
+        print("Remove cur_li._Value",cur_li._Value)
+        
+        if cur_li._Value["type"] == "source":
+            print("remove a source")
+            try:
+                conn = sqlite3.connect(self._warehouse_db)
+                conn.row_factory = dict_factory
+                c = conn.cursor()
+                c.execute("DELETE FROM warehouse WHERE file = '%s'" % cur_li._Value["file"] )
+                conn.commit()
+                conn.close()
+            except Exception as ex:
+                print(ex)
+        elif cur_li._Value["type"] == "launcher" or cur_li._Value["type"] == "pico8" or cur_li._Value["type"] == "tic80":  
+            remote_file_url = cur_li._Value["file"]
+            menu_file = remote_file_url.split("raw.githubusercontent.com")[1]
+            local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
+            local_menu_file_path = os.path.dirname(local_menu_file)
+            
+            gid,ret = config.RPC.urlDownloading(remote_file_url)
+            if ret == True:
+                config.RPC.remove(gid)
+
+            try:
+                if os.path.exists(local_menu_file):
+                    os.remove(local_menu_file)
+                if os.path.exists(local_menu_file+".aria2"):
+                    os.remove(local_menu_file+".aria2")
+                if os.path.exists( os.path.join(local_menu_file_path,cur_li._Value["title"])):
+                    rmtree(os.path.join(local_menu_file_path,cur_li._Value["title"]) )
+                
+            except Exception as ex:
+                print(ex)
+
+    def Click(self):
+        if self._PsIndex > len(self._MyList) -1:
+            return
+
+        cur_li = self._MyList[self._PsIndex]
+        #if cur_li._Active == True:
+        #    return
+
+        print("cur_li._Value",cur_li._Value)
+
+        if cur_li._Value["type"] == "source" or cur_li._Value["type"] == "dir":
+            remote_file_url = cur_li._Value["file"]
+            menu_file = remote_file_url.split("raw.githubusercontent.com")[1] #assume master branch
+            local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
+            print(local_menu_file)
+            if FileExists( local_menu_file ) == False:
+                self.LoadHouse()
+            else:
+            #read the local_menu_file, push into stack,display menu
+                self._Downloading = None
+                try:
+                    with open(local_menu_file) as json_file:
+                        local_menu_json = json.load(json_file)
+                        print(local_menu_json)
+                        self._MyStack.Push(local_menu_json["list"])
+
+                    self.SyncList()
+                    self._Screen.Draw()
+                    self._Screen.SwapAndShow()
+                except Exception as ex:
+                    print(ex)
+                    self._Screen._MsgBox.SetText("Open house failed ")
+                    self._Screen._MsgBox.Draw()
+                    self._Screen.SwapAndShow()
+
+        elif cur_li._Value["type"] == "add_house":
+            print("show keyboard to add ware house")
+            self._Screen.PushCurPage()
+            self._Screen.SetCurPage( self._Keyboard )
+        else:
+            #download the game probably
+            remote_file_url = cur_li._Value["file"]
+            menu_file = remote_file_url.split("raw.githubusercontent.com")[1]
+            local_menu_file = "%s/aria2download%s" % (os.path.expanduser('~'),menu_file )
+
+            if FileExists( local_menu_file ) == False:
+                gid,ret = config.RPC.urlDownloading(remote_file_url)
+                if ret == False:
+                    gid = config.RPC.addUri( remote_file_url, options={"out": menu_file})
+                    self._Downloading = gid
+                    print("stack length ",self._MyStack.Length())
+                    """
+                    if self._MyStack.Length() > 1:## not on the top list page
+                        try:
+                            conn = sqlite3.connect(self._aria2_db)
+                            c = conn.cursor()
+                            c.execute("INSERT INTO tasks(gid,title,file,type,status,fav) VALUES ('"+gid+"','"+cur_li._Value["title"]+"','"+cur_li._Value["file"]+"','"+cur_li._Value["type"]+"','active','0')")
+
+                            conn.commit()
+                            conn.close()
+                        except Exception as ex:
+                            print("SQLITE3 ",ex)
+                    """
+                else:
+                    print(config.RPC.tellStatus(gid,["status","totalLength","completedLength"]))
+
+                    self._Screen._MsgBox.SetText("Getting the game now")
+                    self._Screen._MsgBox.Draw()
+                    self._Screen.SwapAndShow()
+
+                    pygame.time.delay(800)
+                    self._Screen._TitleBar.Redraw()
+
+            else:
+                print("file downloaded")# maybe check it if is installed,then execute it
+                if cur_li._Value["type"]=="launcher" and cur_li._ReadOnly == False:
+                    local_menu_file_path = os.path.dirname(local_menu_file)
+                    game_sh = os.path.join( local_menu_file_path, cur_li._Value["title"],cur_li._Value["title"]+".sh")
+                    #game_sh = reconstruct_broken_string( game_sh)
+                    print("run game: ",game_sh, os.path.exists(  game_sh))
+                    self._Screen.RunEXE(game_sh)
+
+                if cur_li._Value["type"]=="pico8" and cur_li._ReadOnly == False:
+                    if os.path.exists("/home/cpi/games/PICO-8/pico-8/pico8") == True:
+                        game_sh = "/home/cpi/launcher/Menu/GameShell/50_PICO-8/PICO-8.sh"
+                        self._Screen.RunEXE(game_sh)
+                    else:
+                        self._Screen._MsgBox.SetText("Purchase pico8")
+                        self._Screen._MsgBox.Draw()
+                        self._Screen.SwapAndShow()
+                        pygame.time.delay(800)
+
+                if cur_li._Value["type"]=="tic80" and cur_li._ReadOnly == False:
+                    game_sh = "/home/cpi/apps/Menu/51_TIC-80/TIC-80.sh"
+                    self._Screen.RunEXE(game_sh)
+
+    def OnAria2CompleteCb(self,gid):
+        print("OnAria2CompleteCb ", gid)
+        self.SyncList()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+ 
+    def raw_github_com(self,_url):#eg: github.com/clockworkpi/warehouse
+        if _url.startswith("github.com")== False:
+            return False
+        parts = _url.split("/")
+        if len(parts) != 3:
+            return False
+        return "/".join(["https://raw.githubusercontent.com",parts[1],parts[2],"master/index.json"])
+
+    def OnKbdReturnBackCb(self):
+        inputed = "".join(self._Keyboard._Textarea._MyWords).strip()
+        inputed = inputed.replace("http://","")
+        inputed = inputed.replace("https://","")
+        
+        if inputed.endswith(".git"):
+             inputed = inputed[:len(inputed)-4]
+        if inputed.endswith("/"):
+             inputed = inputed[:len(inputed)-1]
+        
+        print("last: ",inputed)
+        try:
+            conn = sqlite3.connect(self._warehouse_db)
+            conn.row_factory = dict_factory
+            c = conn.cursor()
+            ret = c.execute("SELECT * FROM warehouse WHERE title='%s'" % inputed ).fetchone()
+            if ret != None:
+                self._Screen._MsgBox.SetText("Warehouse existed!")
+                self._Screen._MsgBox.Draw()
+                self._Screen.SwapAndShow()
+            else:
+                if "github.com/clockworkpi/warehouse" in inputed:
+                    self._Screen._MsgBox.SetText("Warehouse existed!")
+                    self._Screen._MsgBox.Draw()
+                    self._Screen.SwapAndShow()
+                else:
+                    valid_url= self.raw_github_com(inputed)
+                
+                    if valid_url == False:
+                        self._Screen._MsgBox.SetText("Warehouse url error!")
+                        self._Screen._MsgBox.Draw()
+                        self._Screen.SwapAndShow()
+                    else:
+                        sql_insert = """ INSERT INTO warehouse(title,file,type) VALUES(
+                                     '%s',
+                                     '%s',
+                                     'source');""" % (inputed,valid_url)
+
+                        c.execute(sql_insert)
+                        conn.commit()
+                        self.SyncList()
+                        self._Screen.Draw()
+                        self._Screen.SwapAndShow()
+            conn.close()
+        except Exception as ex:
+            print(ex)
+     
+    def OnLoadCb(self):
+        self._Scrolled = 0
+        self._PosY = 0
+        self._DrawOnce = False
+        #sync 
+        print("OnLoadCb")
+        if self._MyStack.Length() == 1:
+            self._FootMsg[2] = "Remove"
+            self._FootMsg[1] = "Update"
+        else:
+            self._FootMsg[2] = "Remove"
+            self._FootMsg[1] = "Preview"
+        
+        self._GobjTimer = gobject.timeout_add(500, self.GObjectUpdateProcessInterval)
+        
+        self.SyncList()
+ 
+    def OnReturnBackCb(self):
+        if self._MyStack.Length() == 1:
+            self._FootMsg[2] = "Remove"
+            self._FootMsg[1] = "Update"
+        else:
+            self._FootMsg[2] = "Remove"
+            self._FootMsg[1] = "Preview"
+
+        self.SyncList()
+        self.RestoreScrolled()
+
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+       
+        """
+        self.ReturnToUpLevelPage()
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+        """
+
+    def ScrollDown(self):
+        if len(self._MyList) == 0:
+            return
+        self._PsIndex += 1
+        if self._PsIndex >= len(self._MyList):
+            self._PsIndex = len(self._MyList)-1
+
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._PosY+cur_li._Height > self._Height:
+            for i in range(0, len(self._MyList)):
+                self._MyList[i]._PosY -= self._MyList[i]._Height
+
+            self._Scrolled_cnt -= self._MyList[i]._Height
+
+    def ScrollUp(self):
+        if len(self._MyList) == 0:
+            return
+        self._PsIndex -= 1
+        if self._PsIndex < 0:
+            self._PsIndex = 0
+        cur_li = self._MyList[self._PsIndex]
+        if cur_li._PosY < 0:
+            for i in range(0, len(self._MyList)):
+                self._MyList[i]._PosY += self._MyList[i]._Height
+
+            self._Scrolled_cnt += self._MyList[i]._Height
+
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+
+            if self._MyStack.Length() > 1:
+               self._MyStack.Pop()
+               if self._MyStack.Length() == 1:
+                   self._FootMsg[2] = "Remove"
+                   self._FootMsg[1] = "Update"
+               else:
+                   self._FootMsg[2] = "Remove"
+                   self._FootMsg[1] = "Preview"
+                   if self._MyStack.Length() == 2:
+                       self._FootMsg[2] = ""
+                       self._FootMsg[1] = ""
+
+               self.SyncList()
+               self._Screen.Draw()
+               self._Screen.SwapAndShow()
+
+            elif self._MyStack.Length() == 1:
+                self.ReturnToUpLevelPage()
+                self._Screen.Draw()
+                self._Screen.SwapAndShow()
+                gobject.source_remove(self._GobjTimer)
+
+        if IsKeyStartOrA(event.key):
+            self.Click()
+
+            if self._MyStack.Length() == 1:
+                self._FootMsg[2] = "Remove"
+                self._FootMsg[1] = "Update"
+            else:
+                self._FootMsg[2] = "Remove"
+                self._FootMsg[1] = "Preview"
+                if self._MyStack.Length() == 2:
+                    self._FootMsg[2] = ""
+                    self._FootMsg[1] = ""
+                
+
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+
+        if event.key == CurKeys["X"]:
+            #print(self._MyStack.Length() )
+            if  self._PsIndex <= len(self._MyList) -1:
+                cur_li = self._MyList[self._PsIndex]
+                if  cur_li._Type != "dir":
+                    if self._MyStack.Length() == 1 and self._PsIndex == 0:
+                        pass
+                        #predefined source
+                    else:
+                        self._Screen.PushPage(self._remove_page)
+                        self._remove_page._StartOrA_Event = self.RemoveGame
+                        self._Screen.Draw()
+                        self._Screen.SwapAndShow()
+                return 
+
+            self.SyncList()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if event.key == CurKeys["Y"]:
+            if self._MyStack.Length() == 1:
+                self.ResetHouse()
+            else:
+                self.PreviewGame()
+ 
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+    def RestoreScrolled(self):
+        for i in range(0, len(self._MyList)):
+            self._MyList[i]._PosY += self._Scrolled_cnt
+
+    def Draw(self):
+
+        self.ClearCanvas()
+        if len(self._MyList) == 0:
+            return
+        
+        else:
+            if len(self._MyList) * self._MyList[0]._Height > self._Height:
+                self._Ps._Width = self._Width - 11
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+                    if i._PosY < 0:
+                        continue
+                    i.Draw()
+                self._Scroller.UpdateSize( len(self._MyList)*self._MyList[0]._Height, self._PsIndex*self._MyList[0]._Height)
+                self._Scroller.Draw()
+                
+            else:
+                self._Ps._Width = self._Width
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+                    if i._PosY < 0:
+                        continue
+                    i.Draw()                
+
+        if self._HWND != None:
+            self._HWND.fill(MySkinManager.GiveColor("White"))
+            
+            self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) )
+
+class APIOBJ(object):
+
+    _Page = None
+    def __init__(self):
+        pass
+    def Init(self,main_screen):
+        self._Page = GameStorePage()
+        self._Page._Screen = main_screen
+        self._Page._Name ="Warehouse"
+        self._Page.Init()
+        
+    def API(self,main_screen):
+        if main_screen !=None:
+            main_screen.PushPage(self._Page)
+            main_screen.Draw()
+            main_screen.SwapAndShow()
+
+OBJ = APIOBJ()
+def Init(main_screen):    
+    OBJ.Init(main_screen)
+def API(main_screen):
+    OBJ.API(main_screen)
+    

+ 1 - 0
Menu/GameShell/30_RetroArch.sh

@@ -0,0 +1 @@
+retroarch 

+ 1 - 0
Menu/GameShell/31_CaveStory.sh

@@ -0,0 +1 @@
+retroarch -L /home/cpi/apps/emulators/nxengine_libretro.so /home/cpi/games/nxengine/cavestory/data

+ 6 - 0
Menu/GameShell/32_ChocoDM/action.config

@@ -0,0 +1,6 @@
+ROM=/home/cpi/games/ChocoDM
+ROM_SO=
+EXT=wad
+LAUNCHER=chocolate-doom -iwad
+TITLE=ChocoDM
+SO_URL=

+ 5 - 0
Menu/GameShell/50_PICO-8/PICO-8.sh

@@ -0,0 +1,5 @@
+#!/bin/bash
+
+#SDL_VIDEODRIVER=x11 DISPLAY=:0 ./pico-8/pico8_dyn -splore -draw_rect 32,0,256,240
+cd /home/cpi/games/PICO-8/pico-8
+SDL_VIDEODRIVER=x11 DISPLAY=:0 ./pico8_dyn -splore -draw_rect 32,0,256,240

+ 12 - 0
Menu/GameShell/50_PICO-8/Post-Up.sh

@@ -0,0 +1,12 @@
+#!/bin/bash
+
+mkdir ~/.lexaloffle
+
+cp -rf pico-8 ~/.lexaloffle
+
+mkdir ~/.lexaloffle/pico-8/carts
+
+ln -s ~/.lexaloffle/pico-8/carts/ ~/games/PICO-8/carts
+
+touch .done
+

+ 8 - 0
Menu/GameShell/50_PICO-8/compkginfo.json

@@ -0,0 +1,8 @@
+{
+"GameDir":"/home/cpi/games/PICO-8/",
+"InstallDir":"pico-8",
+"NotFoundMsg":["Please purchase the PICO-8 \n|None|varela16",
+"and copy it to the \"~/games/PICO-8\"|None|varela16"],
+"MD5":{"pico-8_0.1.11g_raspi.zip":"a3f2995cf117499f880bd964d6a0e1f2","pico-8_0.1.11g_amd64.zip":"6726141c784afd4a41be6b7414c1b932","pico-8_0.1.12_raspi.zip":"08eda95570e63089a2b9f5531503431e","pico-8_0.1.12c_raspi.zip":"1a62b0d7d4e4be65f89f23ec9757cb66","pico-8_0.1.12c2_raspi.zip":"7a878795472fa39304e9a10128c1f712","pico-8.zip":"whatever it takes"},
+"Post-Up":"bash Post-Up.sh" 
+}

+ 99 - 0
Menu/GameShell/50_PICO-8/pico-8/config.txt

@@ -0,0 +1,99 @@
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// Configuration for pico-8
+// 
+// config.txt is read on startup and saved on exit.
+// To generate the default config.txt, delete this file.
+// 
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+// :: Video Settings
+
+window_size 0 0 // window width, height
+screen_size 0 0 // screen width, height (stretched to window) 
+show_fps 0 // Draw frames per second in the corner
+
+
+// :: Window Settings
+
+windowed 0 // 1 to start up in windowed mode
+window_position -1 -1 // x and y position of window, or -1, -1 to let the window manager decide
+frameless 0 // 1 to use a window with no frame
+fullscreen_method 0 // 0 maximized window (linux)  1 borderless desktop-sized window  2 fullscreen
+
+
+// :: System Settings
+
+foreground_sleep_ms 1 // number of milliseconds to sleep each frame. Try 10 to conserve battery power
+
+background_sleep_ms 20 // number of milliseconds to sleep each frame when running in the background
+
+sessions 4 // number of times program has been run
+
+// (scancode) hold this key down and left-click to simulate right-click
+rmb_key 0 // 0 for none  226 for LALT
+
+// 0:off  1: ignore SDL_TEXTINPUT and use SDL_GetKeyboardState instead (mapped to a US layout)
+emulate_textinput 1 
+
+// Desktop for saving screenshots etc. Defaults to $HOME/Desktop
+desktop_path 
+
+
+
+// :: Audio Settings
+
+sound_volume 256 // 0..256
+music_volume 256 // 0..256
+mix_buffer_size 1024 // usually 1024. Try 2048 if you get choppy sound
+
+
+// :: 
+
+version 0.1.11g
+
+
+// Location of pico-8's root folder
+root_path /home/cpi/.lexaloffle/pico-8/carts/
+
+
+// Location of cartridge save data
+cdata_path /home/cpi/.lexaloffle/pico-8/cdata/
+
+
+// Specify which player index joystick control begins at (0..7)
+joystick_index 0
+
+
+// Custom keyboard scancodes for buttons. player0 0..6, player1 0..5
+button_keys 0 0 0 0 13 14 0 0 0 0 0 0 0 
+
+// Play notes as they are plotted in frequency mode
+live_notes 0
+
+// iff 1: when using keyboard cursor, snap to closest pixel / map cel
+cursor_snap 0
+
+// maximum length of gif in seconds (1..120, default 8)
+gif_len 8
+
+// 0 classic  1 dark blue background in code editor
+gui_theme 0
+
+// scale of screenshots and gifs // 2 means 256x256
+screenshot_scale 3
+gif_scale 2
+
+// when 1 can enter glyphs using shift-A..Z
+shift_glyphs 1
+
+// 0 for off. 1 to notify whenever unsaved changes are backed up
+show_backup_messages 1
+
+// 0 for off. 1 to allow control of a cart's framerate due to host machine's cpu capacity (recommended)
+host_framerate_control 1
+
+// filter splore content
+// 0 for no filter (18+)  1 medium (13+)  2 maximum (kid-friendly)
+content_filter 1
+

+ 90 - 0
Menu/GameShell/50_PICO-8/pico-8/log.txt

@@ -0,0 +1,90 @@
+codo_init
+  platform: Linux
+  Found config.txt
+  
+    01 window_size 0 0 // window width, height
+    02 screen_size 0 0 // screen width, height (stretched to window) 
+    03 show_fps 0 // Draw frames per second in the corner
+    04 windowed 0 // 1 to start up in windowed mode
+    05 window_position -1 -1 // x and y position of window, or -1, -1 to let the window manager decide
+    new window position: -1, -1
+    06 frameless 0 // 1 to use a window with no frame
+    07 fullscreen_method 1 // 0 maximized window (linux)  1 borderless desktop-sized window  2 fullscreen
+    08 foreground_sleep_ms 1 // number of milliseconds to sleep each frame. Try 10 to conserve battery power
+    09 background_sleep_ms 20 // number of milliseconds to sleep each frame when running in the background
+    10 sessions 3 // number of times program has been run
+    11 rmb_key 0 // 0 for none  226 for LALT
+    12 emulate_textinput 1 
+    13 desktop_path 
+    14 sound_volume 256 // 0..256
+    15 music_volume 256 // 0..256
+    16 mix_buffer_size 1024 // usually 1024. Try 2048 if you get choppy sound
+    17 version 0.1.11g
+    18 root_path /home/cpi/.lexaloffle/pico-8/carts/
+    19 cdata_path /home/cpi/.lexaloffle/pico-8/cdata/
+    20 joystick_index 0
+    21 button_keys 0 0 0 0 0 0 0 0 0 0 0 0 0 
+    22 live_notes 0
+    23 cursor_snap 0
+    24 gif_len 8
+    25 gui_theme 0
+    26 screenshot_scale 3
+    27 gif_scale 2
+    28 shift_glyphs 1
+    29 show_backup_messages 1
+    30 host_framerate_control 1
+    31 content_filter 1
+  
+  codo_system_init
+  Compiled against SDL version: 2.0.7
+  Linked against SDL version:   2.0.5
+  Built-in video drivers:   0 x11   1 wayland   2 dummy  
+  Current video driver: x11
+  Built-in render drivers:
+  Renderer opengl:
+    Flags: 0x0000000E ( |  | )
+    Texture formats (1): ARGB8888
+  Renderer opengles2:
+    Flags: 0x0000000E ( |  | )
+    Texture formats (4): ARGB8888, ABGR8888, RGB888, BGR888
+  Renderer software:
+    Flags: 0x00000009 ( | )
+    Texture formats (8): ARGB8888, ABGR8888, RGBA8888, BGRA8888, RGB888, BGR888, RGB565, RGB555
+  codo_reset_timer
+  codo_gui_init
+  codo_keys_init
+  codo_text_init
+  codo_video_init
+  codo_mouse_init
+  codo_joystick_init
+  Reading controller mappings: /home/cpi/.lexaloffle/pico-8/sdl_controllers.txt
+  searching for joysticks
+    found 0 joysticks
+  ok
+ok
+codo_load_pod: /home/cpi/apps/Menu/50_PICO-8/pico8.dat ok 
+codo_set_screen 128 128 8 100
+ set pixel_perfect 1
+ window size: 640 480
+codo_plat_pi: forcing fullscreen mode
+Current renderer:
+  Renderer opengl:
+    Flags: 0x0000000A ( | )
+    Texture formats (5): ARGB8888, YV12, IYUV, 0x3231564e, 0x3132564e
+    Max Texture Size: 8192x8192
+codo_sound_init mix_buffer_size: 1024
+codo_sound_init
+SDL_INIT_AUDIO ok
+SDL_OpenAudio ok
+Built-in audio drivers: 0 pulseaudio 1 alsa 2 sndio 3 dsp 4 disk 5 dummy
+Current audio driver: alsa
+codo_exit
+  cmusic_stop
+  codo_main_exit
+  codo_config_save
+  codo_sound_exit
+  codo_video_exit
+  codo_joystick_exit
+  codo_system_exit
+  codo_items_created: 1023
+ok

+ 1 - 0
Menu/GameShell/50_PICO-8/pico-8/sdl_controllers.txt

@@ -0,0 +1 @@
+// add SDL2 game controller mappings to this file

+ 3 - 0
Menu/GameShell/90_Reload UI.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+exit 0

+ 24 - 0
Menu/GameShell/97_Music Player/__init__.py

@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+
+## local UI import
+import pages
+import myvars
+
+def Init(main_screen):
+    pages.InitPoller()
+
+    pages.InitListPage(main_screen)
+    pages.InitMusicLibPage(main_screen)
+    pages.InitSpectrumPage(main_screen)
+    
+def API(main_screen):
+    
+    if main_screen !=None:
+        main_screen.PushCurPage()
+        main_screen.SetCurPage(myvars.PlayListPage)
+        main_screen.Draw()
+        main_screen.SwapAndShow()
+
+

+ 134 - 0
Menu/GameShell/97_Music Player/list_item.py

@@ -0,0 +1,134 @@
+# -*- coding: utf-8 -*- 
+
+import pygame
+from libs.roundrects import aa_round_rect
+
+## local UI import
+from UI.constants import ICON_TYPES
+from UI.page   import Page
+from UI.label  import Label
+from UI.icon_item import IconItem
+from UI.util_funcs import midRect
+from UI.skin_manager import MySkinManager
+
+# a item for List
+# - - - - - - - - - - - -- 
+# | Icon  Text.....    > |
+# ------------------------
+
+import myvars # icons_path
+
+class ListItemIcon(IconItem):
+
+    _CanvasHWND = None
+    _Parent     = None
+    _Width      = 18
+    _Height     = 18
+    
+    def Draw(self):
+        self._CanvasHWND.blit(self._ImgSurf,(self._PosX,self._PosY+(self._Parent._Height-self._Height)/2,self._Width,self._Height))
+
+
+class ListItemLabel(Label):
+
+    _ActiveColor  = MySkinManager.GiveColor('Active')
+    _Active = False
+    def Draw(self):
+
+        self._FontObj.set_bold(self._Active)
+        
+        """
+        if self._Active == True:
+            my_text = self._FontObj.render( self._Text,True,self._ActiveColor)
+        else:
+            my_text = self._FontObj.render( self._Text,True,self._Color)
+        """
+        
+        my_text = self._FontObj.render( self._Text,True,self._Color)
+        self._CanvasHWND.blit(my_text,(self._PosX,self._PosY,self._Width,self._Height))
+
+    
+class ListItem(object):
+    _PosX = 0
+    _PosY = 0
+    _Width = 0
+    _Height = 30
+
+    _Labels = {}
+    _Icons  = {}
+    _Fonts  = {}
+    _MyType = ICON_TYPES["EXE"]
+    _LinkObj = None
+    _Path    = ""
+    _Active  = False
+    _Playing = False ## play or pause
+    _PlayingProcess = 0 # 0 - 100
+    _Parent  = None
+    
+    _Text = ""
+    def __init__(self):
+        self._Labels = {}
+        self._Icons  = {}
+        self._Fonts  = {}
+
+
+    def Init(self,text):
+
+        #self._Fonts["normal"] = fonts["veramono12"]
+        self._Text = text
+        
+        l = ListItemLabel()
+        l._PosX = 22
+        l.SetCanvasHWND(self._Parent._CanvasHWND)
+
+        if self._MyType == ICON_TYPES["DIR"]:
+            l.Init(text,self._Fonts["normal"])
+            self._Path = text
+        else:
+            l.Init(text,self._Fonts["normal"])
+            self._Path = text
+
+
+        self._Labels["Text"] = l
+        
+        
+    def NewCoord(self,x,y):
+        self._PosX = x
+        self._PosY = y
+
+    def Draw(self):
+
+        if self._MyType == ICON_TYPES["DIR"] and self._Path != "[..]":
+            self._Parent._Icons["sys"]._IconIndex = 0
+            self._Parent._Icons["sys"].NewCoord(self._PosX+12,self._PosY+ (self._Height - self._Parent._Icons["sys"]._Height)/2+self._Parent._Icons["sys"]._Height/2)
+            self._Parent._Icons["sys"].Draw()
+
+        if self._MyType == ICON_TYPES["FILE"]:
+            self._Parent._Icons["sys"]._IconIndex = 1
+            self._Parent._Icons["sys"].NewCoord(self._PosX+12,self._PosY+ (self._Height - self._Parent._Icons["sys"]._Height)/2+self._Parent._Icons["sys"]._Height/2)
+            self._Parent._Icons["sys"].Draw()
+        
+        if self._Active == True:
+            self._Labels["Text"]._Active = True
+        else:
+            self._Labels["Text"]._Active = False
+
+        
+        self._Labels["Text"]._PosY = self._PosY + (self._Height - self._Labels["Text"]._Height)/2
+            
+        pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Line'),(self._PosX,self._PosY+self._Height-1),(self._PosX+self._Width,self._PosY+self._Height-1),1)
+
+        if self._Playing == True:
+            self._Labels["Text"]._Active =True
+            self._Labels["Text"].Draw()
+            #_rect = midRect(10,self._PosY+15,10,10,self._Parent._Width,self._Parent._Height)
+            #aa_round_rect(self._Parent._CanvasHWND,_rect,(0,0,0),3,0,(0,0,0))
+            #pygame.draw.polygon(self._Parent._CanvasHWND, (0,0,0), [[6, self._PosY+7], [11, self._PosY+14],[6, self._PosY+21]], 2)
+            
+            if self._PlayingProcess > 0:
+                seek_posx = int(self._Width * self._PlayingProcess/100.0)
+                pygame.draw.line(self._Parent._CanvasHWND,MySkinManager.GiveColor('Active'),(self._PosX,self._PosY+self._Height-2),(self._PosX+seek_posx,self._PosY+self._Height-2),2)   
+
+        else:
+            self._Labels["Text"].Draw()
+

+ 420 - 0
Menu/GameShell/97_Music Player/mpd_spectrum_page.py

@@ -0,0 +1,420 @@
+# -*- coding: utf-8 -*- 
+
+import os
+import time
+import pygame
+
+import numpy
+import math
+
+import gobject
+
+from beeprint import pp
+
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.icon_item import IconItem
+from UI.icon_pool  import MyIconPool
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+
+from threading  import Thread
+
+from list_item  import ListItem
+
+import myvars
+
+class PIFI(object):
+    _MPD_FIFO = "/tmp/mpd.fifo"
+    _SAMPLE_SIZE = 1024
+    _SAMPLING_RATE = 44100
+    _FIRST_SELECTED_BIN = 5
+    _NUMBER_OF_SELECTED_BINS = 1024
+
+    _samples_buffer = None
+    
+    def __init__(self):
+        self.sampleSize = self._SAMPLE_SIZE
+        self.samplingRate = self._SAMPLING_RATE
+        
+    def GetSpectrum(self,fifoFile,trim_by=4,log_scale=False,div_by=100):
+        try:
+            rawSamples = os.read(fifoFile,self.sampleSize)    # will return empty lines (non-blocking)
+            if len(rawSamples) < 1:
+#               print("Read error")
+                pass
+            else:
+                self._samples_buffer = rawSamples
+        except Exception,e:
+            pass
+
+        if self._samples_buffer == None:
+            return ""
+        
+        data = numpy.fromstring(self._samples_buffer, dtype=numpy.int16)
+
+        data = data * numpy.hanning(len(data))
+
+        left,right = numpy.split(numpy.abs(numpy.fft.fft(data)),2)
+        spec_y     = numpy.add(left,right[::-1])
+
+        if log_scale:
+            spec_y=numpy.multiply(20,numpy.log10(spec_y))
+        if trim_by:
+            i=int((self.sampleSize/2)/trim_by)
+            spec_y=spec_y[:i]
+        if div_by:
+            spec_y=spec_y/float(div_by)
+        
+        return spec_y
+    
+    
+class MPDSpectrumPage(Page):
+
+    _Icons = {}
+    _Selector=None
+    _FootMsg = ["Nav","","","Back",""]
+    _MyList = []
+    _ListFont = MyLangManager.TrFont("veramono12")
+    _SongFont = MyLangManager.TrFont("notosanscjk12")
+    _PIFI   =  None
+    _FIFO   = None
+    _Color  = MySkinManager.GiveColor('Front')
+    _GobjectIntervalId = -1
+    _Queue = None
+    _KeepReading = True
+    _ReadingThread = None
+    
+    _BGpng = None
+    _BGwidth = 320
+    _BGheight = 200
+
+    _SheepHead = None
+    _SheepHeadW = 69
+    _SheepHeadH = 66
+
+    _SheepBody = None
+    _SheepBodyW = 105
+    _SheepBodyH = 81
+
+    _RollCanvas = None
+    _RollW     = 180
+    _RollH     = 18
+    
+    _freq_count = 0
+    _head_dir = 0
+
+    _Neighbor = None
+
+
+    _bby  = []
+    _bbs  = []
+    _capYPositionArray = []
+    _frames = 0
+    read_retry = 0
+    _queue_data = []
+    _vis_values = []
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+        self._CanvasHWND = None
+        self._MyList = []
+        self._PIFI = PIFI()
+            
+    def Init(self):
+        self._PosX = self._Index * self._Screen._Width
+        self._Width = self._Screen._Width
+        self._Height = self._Screen._Height
+
+        self._CanvasHWND = self._Screen._CanvasHWND
+        self._RollCanvas = pygame.Surface(( self._RollW,self._RollH))
+        
+        """
+        self._BGpng = IconItem()
+        self._BGpng._ImgSurf = MyIconPool.GiveIconSurface("sheep_bg")
+        self._BGpng._MyType = ICON_TYPES["STAT"]
+        self._BGpng._Parent = self
+        self._BGpng.Adjust(0,0,self._BGwidth,self._BGheight,0)
+        
+        self._SheepHead = IconItem()
+        self._SheepHead._ImgSurf = MyIconPool.GiveIconSurface("sheep_head")
+        self._SheepHead._MyType = ICON_TYPES["STAT"]
+        self._SheepHead._Parent = self
+        self._SheepHead.Adjust(0,0,self._SheepHeadW,self._SheepHeadH,0)
+
+        self._SheepBody = IconItem()
+        self._SheepBody._ImgSurf = MyIconPool.GiveIconSurface("sheep_body")
+        self._SheepBody._MyType = ICON_TYPES["STAT"]
+        self._SheepBody._Parent = self
+        self._SheepBody.Adjust(0,0,self._SheepBodyW,self._SheepBodyH,0)
+        """
+        
+        self._cwp_png = IconItem()
+        self._cwp_png._ImgSurf = MyIconPool.GiveIconSurface("tape")
+        self._cwp_png._MyType = ICON_TYPES["STAT"]
+        self._cwp_png._Parent = self
+        self._cwp_png.Adjust(0,0,79,79,0)
+
+
+        self._song_title = Label()
+        self._song_title.SetCanvasHWND(self._RollCanvas)
+        self._song_title.Init("Untitled",self._SongFont,MySkinManager.GiveColor('White'))
+
+
+        self._title = Label()
+        self._title.SetCanvasHWND(self._CanvasHWND)
+        self._title.Init("Title:",self._ListFont,MySkinManager.GiveColor('White'))
+
+        self._time = Label()
+        self._time.SetCanvasHWND(self._CanvasHWND)
+        self._time.Init("Time:",self._ListFont,MySkinManager.GiveColor('White'))        
+
+
+        self._time2 = Label()
+        self._time2.SetCanvasHWND(self._CanvasHWND)
+        self._time2.Init("00:00-00:00", self._ListFont,
+                         MySkinManager.GiveColor('White'))
+
+        
+        self.Start()
+                
+    def Start(self):
+
+        if self._Screen.CurPage() != self:
+            return
+        
+        try:
+            self._FIFO = os.open(self._PIFI._MPD_FIFO, os.O_RDONLY | os.O_NONBLOCK)
+            
+            t = Thread(target=self.GetSpectrum)
+            t.daemon = True # thread dies with the program
+            t.start()
+            self._ReadingThread = t
+            
+        except IOError:
+            print("open %s failed"%self._PIFI._MPD_FIFO)
+            self._FIFO = None
+            return
+
+
+    def GetSpectrum(self):
+        while self._KeepReading and self._FIFO != None:
+            raw_samples = self._PIFI.GetSpectrum(self._FIFO)
+            if len(raw_samples) < 1:
+                #print("sleeping... 0.01")
+                time.sleep(0.01)
+                self.read_retry+=1
+                if self.read_retry > 20:
+                    os.close(self._FIFO)
+                    self._FIFO = os.open(self._PIFI._MPD_FIFO, os.O_RDONLY | os.O_NONBLOCK)
+                    self.read_retry = 0
+                
+                self.Playing()
+                
+            else:
+                self.read_retry = 0
+                self._queue_data = raw_samples
+                self.Playing()        
+        
+
+    def Playing(self):
+        
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+
+
+    def ClearCanvas(self):
+        self._CanvasHWND.fill(MySkinManager.GiveColor('Black'))
+
+    def SgsSmooth(self):
+        passes = 1
+        points = 3
+        origs = self._bby[:]
+        for p in range(0,passes):
+            pivot = int(points/2.0)
+            
+            for i in range(0,pivot):
+                self._bby[i] = origs[i]
+                self._bby[ len(origs) -i -1 ] = origs[ len(origs) -i -1 ]
+
+            smooth_constant = 1.0/(2.0*pivot+1.0)
+            for i in range(pivot, len(origs)-pivot):
+                _sum = 0.0
+                for j in range(0,(2*pivot)+1):
+                    _sum += (smooth_constant * origs[i+j-pivot]) +j -pivot
+
+                self._bby[i] = _sum
+
+            if p < (passes - 1):
+                origs = self._bby[:]
+    
+    def OnLoadCb(self):
+        if self._Neighbor != None:
+            pass
+        
+        if self._KeepReading == False:
+            self._KeepReading = True
+        
+        if self._FIFO == None:
+            self.Start()
+            
+    
+    def KeyDown(self,event):
+        if IsKeyMenuOrB(event.key):
+            try:
+                os.close(self._FIFO)
+                self._FIFO = None
+                    
+            except Exception, e:
+                print(e)
+                
+            self._KeepReading = False
+            self._ReadingThread.join()
+            self._ReadingThread = None
+            
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+
+        
+    def Draw(self):
+        self.ClearCanvas()
+        self._frames+=1
+        
+        bw = 10
+        gap = 2
+        margin_bottom = 72
+
+        spects = None
+        meterNum =  self._Width / float(bw +gap )  ## 320/12= 26
+        meter_left = meterNum - int(meterNum)
+        meter_left = meter_left*int(bw+gap)
+        margin_left = meter_left / 2 + gap
+        meterNum = int(meterNum)
+        
+        self._cwp_png.NewCoord(43,159)
+        self._cwp_png.Draw()
+
+        if self._Neighbor != None:
+            if self._Neighbor._CurSongName != "":
+                self._song_title.SetText(self._Neighbor._CurSongName)
+            if self._Neighbor._CurSongTime != "":
+                times = self._Neighbor._CurSongTime
+                times_ = times.split(":")
+                if len(times_)> 1:
+                    cur = int(times_[0])
+                    end = int(times_[1])
+                    if cur > 3600:
+                        cur_text = time.strftime('%H:%M:%S', time.gmtime(cur))
+                    else:
+                        cur_text = time.strftime('%M:%S', time.gmtime(cur))
+
+                    if end > 3600:
+                        end_text = time.strftime('%H:%M:%S', time.gmtime(end))
+                    else:
+                        end_text = time.strftime('%M:%S', time.gmtime(end))
+                else:
+                    cur_text = ""
+                    end_text = times
+                
+                self._time2.SetText(cur_text+"-"+end_text)
+                
+                
+        self._title.NewCoord(90,167)
+        self._title.Draw()
+
+        self._time.NewCoord(90,140)
+        self._time.Draw()
+
+        self._time2.NewCoord(135,140)
+        self._time2.Draw()
+    
+        if self._RollCanvas != None:
+#            self._RollCanvas.fill((111,22,33))
+            self._RollCanvas.fill(MySkinManager.GiveColor('Black'))
+            if self._song_title._Width > self._RollW:
+                if (self._song_title._PosX + self._song_title._Width) > self._RollW and self._frames % 30 == 0:
+                    self._song_title._PosX -= 1
+                elif (self._song_title._PosX + self._song_title._Width) <= self._RollW and self._frames % 30 == 0:
+                    self._song_title._PosX  = 0
+            else:
+                self._song_title._PosX = 0
+            
+            self._song_title.Draw()
+            
+            self._CanvasHWND.blit(self._RollCanvas,(135,165,self._RollW,self._RollH))
+        
+        
+        try:
+            spects = self._queue_data
+            if len(spects) == 0:
+                return
+#            print("spects:",spects)
+            
+            step = int( round( len( spects ) / meterNum) )
+#            print(len(spects))
+            self._bbs = []
+            a = numpy.logspace(0, 1, num=meterNum,endpoint=True)
+            
+            for i in range(0,meterNum):
+                index = int(a[i] * step)
+                total = 0
+                
+                value = spects[index]
+                self._bbs.append(value)
+            
+            if len(self._bby) < len(self._bbs):
+                self._bby = self._bbs
+            elif len(self._bby) == len(self._bbs):
+                for i in range(0,len(self._bbs)):
+                    self._bby[i] = (self._bby[i]+self._bbs[i])/2
+                    
+            self.SgsSmooth()
+            
+            for i in range(0,meterNum):
+                value = self._bby[ i ]
+                if math.isnan(value) or math.isinf(value):
+                    value = 0
+
+                value = value/32768.0
+                value = value * 123
+                value = value %  (self._Height-gap-margin_bottom)
+                
+                if len(self._vis_values) < len(self._bby):
+                    self._vis_values.append(value)
+                elif len(self._vis_values) == len(self._bby):
+                    if self._vis_values[i] < value:
+                        self._vis_values[i] = value
+
+
+        except Exception,e:
+            print(e)
+            return
+        else: # got line
+            if len(self._vis_values) == 0:
+                return
+
+            for i in range(0,meterNum):
+                value = self._vis_values[i]
+         
+                if len(self._capYPositionArray) < round(meterNum):
+                    self._capYPositionArray.append(value)
+
+                if value < self._capYPositionArray[i]:
+                    self._capYPositionArray[i]-=0.5
+                else:
+                    self._capYPositionArray[i] = value
+
+                pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('White'),(i*(bw+gap)+margin_left,self._Height-gap-self._capYPositionArray[i]-margin_bottom,bw,gap),0)
+                
+                pygame.draw.rect(self._CanvasHWND,MySkinManager.GiveColor('White'),(i*(bw+gap)+margin_left,self._Height-value-gap-margin_bottom,bw,value+gap),0)
+                
+                self._vis_values[i] -= 2       
+
+
+    

+ 328 - 0
Menu/GameShell/97_Music Player/music_lib_list_page.py

@@ -0,0 +1,328 @@
+# -*- coding: utf-8 -*- 
+import os
+import pygame
+
+from libs.roundrects import aa_round_rect
+
+## local UI import
+from UI.constants import Width,Height,ICON_TYPES
+from UI.page   import Page,PageSelector
+from UI.label  import Label
+from UI.icon_item import IconItem
+from UI.util_funcs import midRect
+from UI.keys_def   import CurKeys, IsKeyStartOrA, IsKeyMenuOrB
+from UI.multi_icon_item import MultiIconItem
+from UI.icon_pool           import MyIconPool
+from UI.scroller   import ListScroller
+from UI.skin_manager import MySkinManager
+from UI.lang_manager import MyLangManager
+
+from list_item  import ListItem
+
+
+import myvars
+
+
+class MusicLibStack:
+    def __init__(self):
+        self.stack = list()
+
+    def Push(self,data):
+        if data not in self.stack:
+            self.stack.append(data)
+            return True
+        return False
+
+    def Pop(self):
+        if len(self.stack)<=0:
+            return None,False
+        return self.stack.pop(),True
+
+    def Last(self):
+        idx = len(self.stack) -1
+        if idx < 0:
+            return "/"
+        else:
+            return self.stack[ idx ]
+    
+    def Length(self):
+        return len(self.stack)
+
+class ListPageSelector(PageSelector):
+    _BackgroundColor = MySkinManager.GiveColor('Front')
+
+    def __init__(self):
+        self._PosX = 0
+        self._PosY = 0
+        self._Height = 0
+        self._Width  = Width
+
+    def AnimateDraw(self,x2,y2):
+        pass
+
+    def Draw(self):
+        idx = self._Parent._PsIndex
+        
+        if idx < len(self._Parent._MyList):
+            x = self._Parent._MyList[idx]._PosX+2
+            y = self._Parent._MyList[idx]._PosY+1
+            h = self._Parent._MyList[idx]._Height -3
+        
+            self._PosX = x
+            self._PosY = y
+            self._Height = h
+            
+            aa_round_rect(self._Parent._CanvasHWND,  
+                          (x,y,self._Width-4,h),self._BackgroundColor,4,0,self._BackgroundColor)
+
+
+
+class MusicLibListPage(Page):
+
+    _Icons = {}
+    _Selector=None
+    _FootMsg = ["Nav","","Scan","Back","Add to Playlist"]
+    _MyList = []
+    _SwapMyList = []
+    _ListFont = MyLangManager.TrFont("notosanscjk15")
+    _MyStack = None
+
+    _Scroller = None
+    
+    _BGpng = None
+    _BGwidth = 56
+    _BGheight = 70
+    
+    def __init__(self):
+        Page.__init__(self)
+        self._Icons = {}
+        self._CanvasHWND = None
+        self._MyList = []
+        self._SwapMyList = []
+        self._MyStack = MusicLibStack()
+        
+    def SyncList(self,path):
+        if myvars.Poller == None:
+            return
+        
+        alist = myvars.Poller.listfiles(path)
+        if alist == False:
+            print("listfiles return false")
+            return 
+
+        self._MyList = []
+        self._SwapMyList = []
+        
+        start_x  = 0
+        start_y  = 0
+        hasparent = 0
+        if self._MyStack.Length() > 0:
+            hasparent = 1
+            li = ListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFont
+            li._MyType = ICON_TYPES["DIR"]
+            li._Parent = self
+            li.Init("[..]")
+            self._MyList.append(li)
+        
+        for i,v in enumerate(sorted(alist)):
+            li = ListItem()
+            li._Parent = self
+            li._PosX   = start_x
+            li._PosY   = start_y + (i+hasparent)*ListItem._Height
+            li._Width  = Width
+            li._Fonts["normal"] = self._ListFont
+            li._MyType  = ICON_TYPES["FILE"]
+            li._Parent  = self
+            
+            if "directory" in v:
+                li._MyType = ICON_TYPES["DIR"]
+                dir_base_name = os.path.basename(v["directory"])
+                li.Init(  dir_base_name )
+                li._Path = v["directory"] 
+            elif "file" in v:
+                bname = os.path.basename(v["file"])
+                li.Init( bname  )
+                li._Path = v["file"]
+                
+            else:
+                li.Init("NoName")
+            
+            self._MyList.append(li)
+
+        for i in self._MyList:
+            self._SwapMyList.append(i)
+        
+    def Init(self):
+        self._PosX = self._Index * self._Screen._Width
+        self._Width = self._Screen._Width
+        self._Height = self._Screen._Height
+
+        self._CanvasHWND = self._Screen._CanvasHWND
+
+        ps = ListPageSelector()
+        ps._Parent = self
+        self._Ps = ps
+        self._PsIndex = 0
+
+        self.SyncList("/")
+
+        icon_for_list = MultiIconItem()
+        icon_for_list._ImgSurf = MyIconPool.GiveIconSurface("sys")
+        icon_for_list._MyType = ICON_TYPES["STAT"]
+        icon_for_list._Parent = self
+        
+        icon_for_list.Adjust(0,0,18,18,0)        
+        self._Icons["sys"] = icon_for_list
+
+
+        self._BGpng = IconItem()
+        self._BGpng._ImgSurf = MyIconPool.GiveIconSurface("empty")
+        self._BGpng._MyType = ICON_TYPES["STAT"]
+        self._BGpng._Parent = self
+        self._BGpng.AddLabel(MyLangManager.Tr("Please upload data over Wi-Fi"), MyLangManager.TrFont("varela22"))
+        self._BGpng.SetLableColor(MySkinManager.GiveColor('Disabled'))
+        self._BGpng.Adjust(0,0,self._BGwidth,self._BGheight,0)
+
+
+        self._Scroller = ListScroller()
+        self._Scroller._Parent = self
+        self._Scroller._PosX = self._Width - 10
+        self._Scroller._PosY = 2
+        self._Scroller.Init()
+        
+    def Click(self):
+        self.RefreshPsIndex()
+        if len(self._MyList) == 0:
+            return
+        
+        cur_li = self._MyList[self._PsIndex]
+
+        if cur_li._MyType == ICON_TYPES["DIR"]:
+            if cur_li._Path == "[..]":
+                self._MyStack.Pop()
+                self.SyncList( self._MyStack.Last() )
+                self._PsIndex = 0
+            else:
+                self._MyStack.Push( self._MyList[self._PsIndex]._Path )
+                self.SyncList( self._MyStack.Last() )
+                self._PsIndex = 0
+                
+        if cur_li._MyType == ICON_TYPES["FILE"]: ## add to playlist only
+            myvars.Poller.addfile(cur_li._Path)
+            myvars.PlayListPage.SyncList()            
+            print("add" , cur_li._Path)
+            
+        self._Screen.Draw()
+        self._Screen.SwapAndShow()
+
+    def Rescan(self):
+        self.SyncList("/")
+        self._PsIndex = 0
+        
+    def KeyDown(self,event):
+        
+        if IsKeyMenuOrB(event.key) or event.key == CurKeys["Left"]:
+            
+            self.ReturnToUpLevelPage()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        if event.key == CurKeys["Up"]:
+            self.ScrollUp()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        if event.key == CurKeys["Down"]:
+            self.ScrollDown()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        
+        """
+        if event.key == CurKeys["Right"]:
+            self.FScrollDown(Step=5)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+            
+        if event.key == CurKeys["Left"]:
+            self.FScrollUp(Step=5)
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+        """
+        
+        if event.key == CurKeys["X"]:
+            self.Rescan()
+            self._Screen.Draw()
+            self._Screen.SwapAndShow()
+                                     
+        if IsKeyStartOrA(event.key):
+            self.Click()
+            
+    def Draw(self):
+        self.ClearCanvas()
+
+
+        """
+        start_x = 0
+        start_y = 0
+        counter = 0
+        
+        self._MyList = []
+        
+        for i,v in enumerate(self._SwapMyList):
+            if myvars.PlayListPage.InPlayList(v._Path):
+                v._Active = True
+            else:
+                v._Active = False
+
+            if v._Active == False:
+                v.NewCoord(start_x, start_y+counter* ListItem._Height)
+                counter+=1
+                self._MyList.append(v)
+        """
+
+        if len(self._MyList) == 0:
+            self._BGpng.NewCoord(self._Width/2,self._Height/2)
+            self._BGpng.Draw()
+            return
+        
+        else:
+            if len(self._MyList) * ListItem._Height > self._Height:
+                self._Ps._Width = self._Width - 11
+            
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if myvars.PlayListPage.InPlayList(i._Path):
+                        i._Active = True
+                    else:
+                        i._Active = False
+
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+
+                    if i._PosY < 0:
+                        continue
+                    
+                    i.Draw()
+                    
+                self._Scroller.UpdateSize( len(self._MyList)*ListItem._Height, self._PsIndex*ListItem._Height)
+                self._Scroller.Draw()
+            else:
+                self._Ps._Width = self._Width
+                self._Ps.Draw()
+                for i in self._MyList:
+                    if myvars.PlayListPage.InPlayList(i._Path):
+                        i._Active = True
+                    else:
+                        i._Active = False
+
+                    if i._PosY > self._Height + self._Height/2:
+                        break
+
+                    if i._PosY < 0:
+                        continue
+                        
+                    i.Draw()    

+ 8 - 0
Menu/GameShell/97_Music Player/myvars.py

@@ -0,0 +1,8 @@
+
+
+Poller = None # MPD Poller
+PlayListPage = None
+MusicLibListPage = None
+
+SpectrumPage = None
+

+ 38 - 0
Menu/GameShell/97_Music Player/pages.py

@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*- 
+
+from libs.MPD import poller
+
+from play_list_page      import PlayListPage
+from music_lib_list_page import MusicLibListPage
+from mpd_spectrum_page   import MPDSpectrumPage
+import myvars
+
+from config import MPD_socket
+
+def InitPoller():
+    try:
+        myvars.Poller = poller.MPDPoller(host=MPD_socket)
+        myvars.Poller.connect()
+    except:
+        myvars.Poller = None
+        
+
+def InitMusicLibPage(main_screen):
+    myvars.MusicLibListPage = MusicLibListPage()
+    myvars.MusicLibListPage._Screen = main_screen
+    myvars.MusicLibListPage._Name   = "Music Library"
+    myvars.MusicLibListPage.Init()
+
+def InitListPage(main_screen):
+
+    myvars.PlayListPage = PlayListPage()
+    
+    myvars.PlayListPage._Screen = main_screen
+    myvars.PlayListPage._Name = "Play List"
+    myvars.PlayListPage.Init()
+
+def InitSpectrumPage(main_screen):
+    myvars.SpectrumPage = MPDSpectrumPage()
+    myvars.SpectrumPage._Screen = main_screen
+    myvars.SpectrumPage._Name   = "GameShell RTA"
+    myvars.SpectrumPage.Init()

Some files were not shown because too many files changed in this diff