Root/
Source at commit ba9af53 created 13 years 7 months ago. By bartbes, Changed the file browser to use / as root and added ability to see extensionless files (i.e. executables) | |
---|---|
1 | /*************************************************************************** |
2 | * Copyright (C) 2006 by Massimiliano Torromeo * |
3 | * massimiliano.torromeo@gmail.com * |
4 | * * |
5 | * This program is free software; you can redistribute it and/or modify * |
6 | * it under the terms of the GNU General Public License as published by * |
7 | * the Free Software Foundation; either version 2 of the License, or * |
8 | * (at your option) any later version. * |
9 | * * |
10 | * This program is distributed in the hope that it will be useful, * |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
13 | * GNU General Public License for more details. * |
14 | * * |
15 | * You should have received a copy of the GNU General Public License * |
16 | * along with this program; if not, write to the * |
17 | * Free Software Foundation, Inc., * |
18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
19 | ***************************************************************************/ |
20 | |
21 | #include <iostream> |
22 | #include <sstream> |
23 | #include <fstream> |
24 | #include <algorithm> |
25 | #include <stdlib.h> |
26 | #include <unistd.h> |
27 | #include <math.h> |
28 | #include <SDL.h> |
29 | #include <SDL_gfxPrimitives.h> |
30 | #include <signal.h> |
31 | |
32 | #include <sys/statvfs.h> |
33 | #include <errno.h> |
34 | |
35 | #include "gp2x.h" |
36 | #include <sys/fcntl.h> //for battery |
37 | |
38 | //for browsing the filesystem |
39 | #include <sys/stat.h> |
40 | #include <sys/types.h> |
41 | #include <dirent.h> |
42 | |
43 | //for soundcard |
44 | #include <sys/ioctl.h> |
45 | #include <linux/soundcard.h> |
46 | |
47 | #include "linkapp.h" |
48 | #include "linkaction.h" |
49 | #include "menu.h" |
50 | #include "asfont.h" |
51 | #include "sfontplus.h" |
52 | #include "surface.h" |
53 | #include "filedialog.h" |
54 | #include "gmenu2x.h" |
55 | #include "filelister.h" |
56 | |
57 | #include "iconbutton.h" |
58 | #include "messagebox.h" |
59 | #include "inputdialog.h" |
60 | #include "settingsdialog.h" |
61 | #include "wallpaperdialog.h" |
62 | #include "textdialog.h" |
63 | #include "menusettingint.h" |
64 | #include "menusettingbool.h" |
65 | #include "menusettingrgba.h" |
66 | #include "menusettingstring.h" |
67 | #include "menusettingmultistring.h" |
68 | #include "menusettingfile.h" |
69 | #include "menusettingimage.h" |
70 | #include "menusettingdir.h" |
71 | |
72 | #include <sys/mman.h> |
73 | |
74 | #ifdef TARGET_PANDORA |
75 | //#include <pnd_container.h> |
76 | //#include <pnd_conf.h> |
77 | //#include <pnd_discovery.h> |
78 | #endif |
79 | |
80 | const char *CARD_ROOT = "/"; //Note: Add a trailing /! |
81 | const int CARD_ROOT_LEN = 1; |
82 | |
83 | using namespace std; |
84 | using namespace fastdelegate; |
85 | |
86 | // Note: Keep this in sync with the enum! |
87 | static const char *colorNames[NUM_COLORS] = { |
88 | "topBarBg", |
89 | "bottomBarBg", |
90 | "selectionBg", |
91 | "messageBoxBg", |
92 | "messageBoxBorder", |
93 | "messageBoxSelection", |
94 | }; |
95 | |
96 | static enum color stringToColor(const string &name) |
97 | { |
98 | for (unsigned int i = 0; i < NUM_COLORS; i++) { |
99 | if (strcmp(colorNames[i], name.c_str()) == 0) { |
100 | return (enum color)i; |
101 | } |
102 | } |
103 | return (enum color)-1; |
104 | } |
105 | |
106 | static const char *colorToString(enum color c) |
107 | { |
108 | return colorNames[c]; |
109 | } |
110 | |
111 | int main(int /*argc*/, char */*argv*/[]) { |
112 | cout << "----" << endl; |
113 | cout << "GMenu2X starting: If you read this message in the logs, check http://gmenu2x.sourceforge.net/page/Troubleshooting for a solution" << endl; |
114 | cout << "----" << endl; |
115 | |
116 | signal(SIGINT,&exit); |
117 | GMenu2X app; |
118 | #ifdef DEBUG |
119 | cout << "Starting main()" << endl; |
120 | #endif |
121 | app.main(); |
122 | return 0; |
123 | } |
124 | |
125 | void GMenu2X::gp2x_init() { |
126 | #ifdef TARGET_GP2X |
127 | /* gp2x_mem = open("/dev/mem", O_RDWR); |
128 | gp2x_memregs=(unsigned short *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_mem, 0xc0000000); |
129 | MEM_REG=&gp2x_memregs[0]; |
130 | if (f200) { |
131 | //if wm97xx fails to open, set f200 to false to prevent any further access to the touchscreen |
132 | f200 = ts.init(); |
133 | }*/ |
134 | batteryHandle = fopen("/sys/class/power_supply/battery/capacity", "r"); |
135 | usbHandle = fopen("/sys/class/power_supply/usb/online", "r"); |
136 | acHandle = fopen("/sys/class/power_supply/ac/online", "r"); |
137 | backlightHandle = |
138 | fopen("/sys/class/backlight/pwm-backlight/brightness", "w+"); |
139 | #endif |
140 | } |
141 | |
142 | void GMenu2X::gp2x_deinit() { |
143 | #ifdef TARGET_GP2X |
144 | /* if (gp2x_mem!=0) { |
145 | gp2x_memregs[0x28DA>>1]=0x4AB; |
146 | gp2x_memregs[0x290C>>1]=640; |
147 | close(gp2x_mem); |
148 | } |
149 | |
150 | if (f200) ts.deinit();*/ |
151 | #endif |
152 | if (batteryHandle) fclose(batteryHandle); |
153 | if (backlightHandle) fclose(backlightHandle); |
154 | if (usbHandle) fclose(usbHandle); |
155 | if (acHandle) fclose(acHandle); |
156 | } |
157 | |
158 | void GMenu2X::gp2x_tvout_on(bool /*pal*/) { |
159 | #ifdef TARGET_GP2X |
160 | /* if (gp2x_mem!=0) { |
161 | // Ioctl_Dummy_t *msg; |
162 | // int TVHandle = ioctl(SDL_videofd, FBMMSP2CTRL, msg); |
163 | if (cx25874!=0) gp2x_tvout_off(); |
164 | //if tv-out is enabled without cx25874 open, stop |
165 | //if (gp2x_memregs[0x2800>>1]&0x100) return; |
166 | cx25874 = open("/dev/cx25874",O_RDWR); |
167 | ioctl(cx25874, _IOW('v', 0x02, unsigned char), pal ? 4 : 3); |
168 | gp2x_memregs[0x2906>>1]=512; |
169 | gp2x_memregs[0x28E4>>1]=gp2x_memregs[0x290C>>1]; |
170 | gp2x_memregs[0x28E8>>1]=239; |
171 | }*/ |
172 | #endif |
173 | } |
174 | |
175 | void GMenu2X::gp2x_tvout_off() { |
176 | #ifdef TARGET_GP2X |
177 | /* if (gp2x_mem!=0) { |
178 | close(cx25874); |
179 | cx25874 = 0; |
180 | gp2x_memregs[0x2906>>1]=1024; |
181 | }*/ |
182 | #endif |
183 | } |
184 | |
185 | GMenu2X::GMenu2X() { |
186 | //Detect firmware version and type |
187 | if (fileExists("/etc/open2x")) { |
188 | fwType = "open2x"; |
189 | fwVersion = ""; |
190 | } else { |
191 | fwType = "gph"; |
192 | fwVersion = ""; |
193 | } |
194 | #ifdef TARGET_GP2X |
195 | f200 = fileExists("/dev/touchscreen/wm97xx"); |
196 | #else |
197 | f200 = true; |
198 | #endif |
199 | |
200 | //open2x |
201 | savedVolumeMode = 0; |
202 | volumeMode = VOLUME_MODE_NORMAL; |
203 | volumeScalerNormal = VOLUME_SCALER_NORMAL; |
204 | volumeScalerPhones = VOLUME_SCALER_PHONES; |
205 | |
206 | o2x_usb_net_on_boot = false; |
207 | o2x_usb_net_ip = ""; |
208 | o2x_ftp_on_boot = false; |
209 | o2x_telnet_on_boot = false; |
210 | o2x_gp2xjoy_on_boot = false; |
211 | o2x_usb_host_on_boot = false; |
212 | o2x_usb_hid_on_boot = false; |
213 | o2x_usb_storage_on_boot = false; |
214 | |
215 | usbnet = samba = inet = web = false; |
216 | useSelectionPng = false; |
217 | |
218 | //load config data |
219 | readConfig(); |
220 | if (fwType=="open2x") { |
221 | readConfigOpen2x(); |
222 | // VOLUME MODIFIER |
223 | switch(volumeMode) { |
224 | case VOLUME_MODE_MUTE: setVolumeScaler(VOLUME_SCALER_MUTE); break; |
225 | case VOLUME_MODE_PHONES: setVolumeScaler(volumeScalerPhones); break; |
226 | case VOLUME_MODE_NORMAL: setVolumeScaler(volumeScalerNormal); break; |
227 | } |
228 | } else |
229 | readCommonIni(); |
230 | |
231 | halfX = resX/2; |
232 | halfY = resY/2; |
233 | bottomBarIconY = resY-18; |
234 | bottomBarTextY = resY-10; |
235 | |
236 | path = ""; |
237 | getExePath(); |
238 | |
239 | batteryHandle = 0; |
240 | backlightHandle = 0; |
241 | usbHandle = 0; |
242 | acHandle = 0; |
243 | |
244 | |
245 | #ifdef TARGET_GP2X |
246 | gp2x_mem = 0; |
247 | cx25874 = 0; |
248 | gp2x_init(); |
249 | |
250 | //Fix tv-out |
251 | /* if (gp2x_mem!=0) { |
252 | if (gp2x_memregs[0x2800>>1]&0x100) { |
253 | gp2x_memregs[0x2906>>1]=512; |
254 | //gp2x_memregs[0x290C>>1]=640; |
255 | gp2x_memregs[0x28E4>>1]=gp2x_memregs[0x290C>>1]; |
256 | } |
257 | gp2x_memregs[0x28E8>>1]=239; |
258 | }*/ |
259 | #endif |
260 | |
261 | //Screen |
262 | if( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_JOYSTICK)<0 ) { |
263 | cout << "\033[0;34mGMENU2X:\033[0;31m Could not initialize SDL:\033[0m " << SDL_GetError() << endl; |
264 | quit(); |
265 | } |
266 | |
267 | s = new Surface(); |
268 | #ifdef TARGET_GP2X |
269 | { |
270 | //I use a tmp variable to hide the cursor as soon as possible (and create the double buffer surface only after that) |
271 | //I'm forced to use SW surfaces since with HW there are issuse with changing the clock frequency |
272 | SDL_Surface *tmps = SDL_SetVideoMode(resX, resY, confInt["videoBpp"], SDL_SWSURFACE); |
273 | SDL_ShowCursor(0); |
274 | s->enableVirtualDoubleBuffer(tmps); |
275 | } |
276 | #else |
277 | s->raw = SDL_SetVideoMode(resX, resY, confInt["videoBpp"], SDL_HWSURFACE|SDL_DOUBLEBUF); |
278 | #endif |
279 | |
280 | bg = NULL; |
281 | font = NULL; |
282 | menu = NULL; |
283 | setSkin(confStr["skin"], false); |
284 | initMenu(); |
285 | |
286 | if (!fileExists(confStr["wallpaper"])) { |
287 | #ifdef DEBUG |
288 | cout << "Searching wallpaper" << endl; |
289 | #endif |
290 | FileLister fl("skins/"+confStr["skin"]+"/wallpapers",false,true); |
291 | fl.setFilter(".png,.jpg,.jpeg,.bmp"); |
292 | fl.browse(); |
293 | if (fl.getFiles().size()<=0 && confStr["skin"] != "Default") |
294 | fl.setPath("skins/Default/wallpapers",true); |
295 | if (fl.getFiles().size()>0) |
296 | confStr["wallpaper"] = fl.getPath()+fl.getFiles()[0]; |
297 | } |
298 | |
299 | initBG(); |
300 | input.init(path+"input.conf"); |
301 | setInputSpeed(); |
302 | initServices(); |
303 | setBacklight(confInt["backlight"]); |
304 | setVolume(confInt["globalVolume"]); |
305 | applyDefaultTimings(); |
306 | setClock(confInt["menuClock"]); |
307 | //recover last session |
308 | readTmp(); |
309 | if (lastSelectorElement>-1 && menu->selLinkApp()!=NULL && (!menu->selLinkApp()->getSelectorDir().empty() || !lastSelectorDir.empty())) |
310 | menu->selLinkApp()->selector(lastSelectorElement,lastSelectorDir); |
311 | } |
312 | |
313 | GMenu2X::~GMenu2X() { |
314 | writeConfig(); |
315 | if (fwType=="open2x") writeConfigOpen2x(); |
316 | |
317 | quit(); |
318 | |
319 | free(menu); |
320 | free(s); |
321 | free(font); |
322 | } |
323 | |
324 | void GMenu2X::quit() { |
325 | fflush(NULL); |
326 | sc.clear(); |
327 | s->free(); |
328 | SDL_Quit(); |
329 | #ifdef TARGET_GP2X |
330 | /* if (gp2x_mem!=0) { |
331 | //Fix tv-out |
332 | if (gp2x_memregs[0x2800>>1]&0x100) { |
333 | gp2x_memregs[0x2906>>1]=512; |
334 | gp2x_memregs[0x28E4>>1]=gp2x_memregs[0x290C>>1]; |
335 | } |
336 | gp2x_deinit(); |
337 | }*/ |
338 | #endif |
339 | } |
340 | |
341 | void GMenu2X::initBG() { |
342 | sc.del("bgmain"); |
343 | |
344 | if (bg != NULL) free(bg); |
345 | |
346 | if (!fileExists(confStr["wallpaper"])) { |
347 | bg = new Surface(s); |
348 | bg->box(0,0,resX,resY,0,0,0); |
349 | } else { |
350 | bg = new Surface(confStr["wallpaper"],false); |
351 | } |
352 | |
353 | drawTopBar(bg); |
354 | drawBottomBar(bg); |
355 | |
356 | Surface *bgmain = new Surface(bg); |
357 | sc.add(bgmain,"bgmain"); |
358 | |
359 | Surface sd("imgs/sd.png", confStr["skin"]); |
360 | Surface cpu("imgs/cpu.png", confStr["skin"]); |
361 | Surface volume("imgs/volume.png", confStr["skin"]); |
362 | string df = getDiskFree(); |
363 | |
364 | sd.blit( sc["bgmain"], 3, bottomBarIconY ); |
365 | sc["bgmain"]->write( font, df, 22, bottomBarTextY, SFontHAlignLeft, SFontVAlignMiddle ); |
366 | volumeX = 27+font->getTextWidth(df); |
367 | volume.blit( sc["bgmain"], volumeX, bottomBarIconY ); |
368 | volumeX += 19; |
369 | cpuX = volumeX+font->getTextWidth("100")+5; |
370 | cpu.blit( sc["bgmain"], cpuX, bottomBarIconY ); |
371 | cpuX += 19; |
372 | manualX = cpuX+font->getTextWidth("300Mhz")+5; |
373 | |
374 | int serviceX = resX-38; |
375 | if (usbnet) { |
376 | if (web) { |
377 | Surface webserver("imgs/webserver.png", confStr["skin"]); |
378 | webserver.blit( sc["bgmain"], serviceX, bottomBarIconY ); |
379 | serviceX -= 19; |
380 | } |
381 | if (samba) { |
382 | Surface sambaS("imgs/samba.png", confStr["skin"]); |
383 | sambaS.blit( sc["bgmain"], serviceX, bottomBarIconY ); |
384 | serviceX -= 19; |
385 | } |
386 | if (inet) { |
387 | Surface inetS("imgs/inet.png", confStr["skin"]); |
388 | inetS.blit( sc["bgmain"], serviceX, bottomBarIconY ); |
389 | serviceX -= 19; |
390 | } |
391 | } |
392 | } |
393 | |
394 | void GMenu2X::initFont() { |
395 | if (font != NULL) { |
396 | free(font); |
397 | font = NULL; |
398 | } |
399 | |
400 | string fontFile = sc.getSkinFilePath("imgs/font.png"); |
401 | if (fontFile.empty()) { |
402 | cout << "Font png not found!" << endl; |
403 | quit(); |
404 | exit(-1); |
405 | } |
406 | font = new ASFont(fontFile); |
407 | } |
408 | |
409 | void GMenu2X::initMenu() { |
410 | //Menu structure handler |
411 | menu = new Menu(this); |
412 | for (uint i=0; i<menu->getSections().size(); i++) { |
413 | //Add virtual links in the applications section |
414 | if (menu->getSections()[i]=="applications") { |
415 | menu->addActionLink(i,"Explorer",MakeDelegate(this,&GMenu2X::explorer),tr["Launch an application"],"skin:icons/explorer.png"); |
416 | } |
417 | |
418 | //Add virtual links in the setting section |
419 | else if (menu->getSections()[i]=="settings") { |
420 | menu->addActionLink(i,"GMenu2X",MakeDelegate(this,&GMenu2X::options),tr["Configure GMenu2X's options"],"skin:icons/configure.png"); |
421 | if (fwType=="open2x") |
422 | menu->addActionLink(i,"Open2x",MakeDelegate(this,&GMenu2X::settingsOpen2x),tr["Configure Open2x system settings"],"skin:icons/o2xconfigure.png"); |
423 | menu->addActionLink(i,tr["Skin"],MakeDelegate(this,&GMenu2X::skinMenu),tr["Configure skin"],"skin:icons/skin.png"); |
424 | menu->addActionLink(i,tr["Wallpaper"],MakeDelegate(this,&GMenu2X::changeWallpaper),tr["Change GMenu2X wallpaper"],"skin:icons/wallpaper.png"); |
425 | #ifdef TARGET_GP2X |
426 | /* menu->addActionLink(i,"TV",MakeDelegate(this,&GMenu2X::toggleTvOut),tr["Activate/deactivate tv-out"],"skin:icons/tv.png"); |
427 | menu->addActionLink(i,"USB Sd",MakeDelegate(this,&GMenu2X::activateSdUsb),tr["Activate Usb on SD"],"skin:icons/usb.png"); |
428 | if (fwType=="gph" && !f200) |
429 | menu->addActionLink(i,"USB Nand",MakeDelegate(this,&GMenu2X::activateNandUsb),tr["Activate Usb on Nand"],"skin:icons/usb.png"); |
430 | //menu->addActionLink(i,"USB Root",MakeDelegate(this,&GMenu2X::activateRootUsb),tr["Activate Usb on the root of the Gp2x Filesystem"],"skin:icons/usb.png");*/ |
431 | #endif |
432 | if (fileExists(path+"log.txt")) |
433 | menu->addActionLink(i,tr["Log Viewer"],MakeDelegate(this,&GMenu2X::viewLog),tr["Displays last launched program's output"],"skin:icons/ebook.png"); |
434 | menu->addActionLink(i,tr["About"],MakeDelegate(this,&GMenu2X::about),tr["Info about GMenu2X"],"skin:icons/about.png"); |
435 | } |
436 | } |
437 | |
438 | menu->setSectionIndex(confInt["section"]); |
439 | menu->setLinkIndex(confInt["link"]); |
440 | |
441 | menu->loadIcons(); |
442 | |
443 | //DEBUG |
444 | //menu->addLink( CARD_ROOT, "sample.pxml", "applications" ); |
445 | } |
446 | |
447 | void GMenu2X::about() { |
448 | vector<string> text; |
449 | split(text,"GMenu2X is developed by Massimiliano \"Ryo\" Torromeo, and is released under the GPL-v2 license.\n\ |
450 | Website: http://gmenu2x.sourceforge.net\n\ |
451 | E-Mail & PayPal account: massimiliano.torromeo@gmail.com\n\ |
452 | \n\ |
453 | Thanks goes to...\n\ |
454 | \n\ |
455 | Contributors\n\ |
456 | ----\n\ |
457 | NoidZ for his gp2x' buttons graphics\n\ |
458 | \n\ |
459 | Beta testers\n\ |
460 | ----\n\ |
461 | Goemon4, PokeParadox, PSyMastR and Tripmonkey_uk\n\ |
462 | \n\ |
463 | Translators\n\ |
464 | ----\n\ |
465 | English & Italian by me\n\ |
466 | French by Yodaz\n\ |
467 | Danish by claus\n\ |
468 | Dutch by superfly\n\ |
469 | Spanish by pedator\n\ |
470 | Portuguese (Portugal) by NightShadow\n\ |
471 | Slovak by Jozef\n\ |
472 | Swedish by Esslan and Micket\n\ |
473 | German by fusion_power, johnnysnet and Waldteufel\n\ |
474 | Finnish by Jontte and Atte\n\ |
475 | Norwegian by cowai\n\ |
476 | Russian by XaMMaX90\n\ |
477 | \n\ |
478 | Donors\n\ |
479 | ----\n\ |
480 | EvilDragon (www.gp2x.de)\n\ |
481 | Tecnologie Creative (www.tecnologiecreative.it)\n\ |
482 | TelcoLou\n\ |
483 | gaterooze\n\ |
484 | deepmenace\n\ |
485 | superfly\n\ |
486 | halo9\n\ |
487 | sbock\n\ |
488 | b._.o._.b\n\ |
489 | Jacopastorius\n\ |
490 | lorystorm90\n\ |
491 | and all the anonymous donors...\n\ |
492 | (If I missed to list you or if you want to be removed, contact me.)","\n"); |
493 | TextDialog td(this, "GMenu2X", tr.translate("Version $1 (Build date: $2)","0.10-test4",__DATE__,NULL), "icons/about.png", &text); |
494 | td.exec(); |
495 | } |
496 | |
497 | void GMenu2X::viewLog() { |
498 | string logfile = path+"log.txt"; |
499 | if (fileExists(logfile)) { |
500 | ifstream inf(logfile.c_str(), ios_base::in); |
501 | if (inf.is_open()) { |
502 | vector<string> log; |
503 | |
504 | string line; |
505 | while (getline(inf, line, '\n')) |
506 | log.push_back(line); |
507 | inf.close(); |
508 | |
509 | TextDialog td(this, tr["Log Viewer"], tr["Displays last launched program's output"], "icons/ebook.png", &log); |
510 | td.exec(); |
511 | |
512 | MessageBox mb(this, tr["Do you want to delete the log file?"], "icons/ebook.png"); |
513 | mb.setButton(ACTION_B, tr["Yes"]); |
514 | mb.setButton(ACTION_X, tr["No"]); |
515 | if (mb.exec() == ACTION_B) { |
516 | ledOn(); |
517 | unlink(logfile.c_str()); |
518 | sync(); |
519 | menu->deleteSelectedLink(); |
520 | ledOff(); |
521 | } |
522 | } |
523 | } |
524 | } |
525 | |
526 | void GMenu2X::readConfig() { |
527 | string conffile = path+"gmenu2x.conf"; |
528 | if (fileExists(conffile)) { |
529 | ifstream inf(conffile.c_str(), ios_base::in); |
530 | if (inf.is_open()) { |
531 | string line; |
532 | while (getline(inf, line, '\n')) { |
533 | string::size_type pos = line.find("="); |
534 | string name = trim(line.substr(0,pos)); |
535 | string value = trim(line.substr(pos+1,line.length())); |
536 | |
537 | if (value.length()>1 && value.at(0)=='"' && value.at(value.length()-1)=='"') |
538 | confStr[name] = value.substr(1,value.length()-2); |
539 | else |
540 | confInt[name] = atoi(value.c_str()); |
541 | } |
542 | inf.close(); |
543 | } |
544 | } |
545 | if (!confStr["lang"].empty()) tr.setLang(confStr["lang"]); |
546 | if (!confStr["wallpaper"].empty() && !fileExists(confStr["wallpaper"])) confStr["wallpaper"] = ""; |
547 | if (confStr["skin"].empty() || !fileExists("skins/"+confStr["skin"])) confStr["skin"] = "Default"; |
548 | |
549 | evalIntConf( &confInt["outputLogs"], 0, 0,1 ); |
550 | evalIntConf( &confInt["maxClock"], 430, 30, 500 ); |
551 | evalIntConf( &confInt["menuClock"], 200, 30, 430 ); |
552 | evalIntConf( &confInt["globalVolume"], 67, 0,100 ); |
553 | evalIntConf( &confInt["backlight"], 100, 5,100 ); |
554 | evalIntConf( &confInt["videoBpp"], 32,32,32 ); // 8,16 |
555 | |
556 | if (confStr["tvoutEncoding"] != "PAL") confStr["tvoutEncoding"] = "NTSC"; |
557 | resX = constrain( confInt["resolutionX"], 320,1920 ); |
558 | resY = constrain( confInt["resolutionY"], 240,1200 ); |
559 | } |
560 | |
561 | void GMenu2X::writeConfig() { |
562 | ledOn(); |
563 | string conffile = path+"gmenu2x.conf"; |
564 | ofstream inf(conffile.c_str()); |
565 | if (inf.is_open()) { |
566 | ConfStrHash::iterator endS = confStr.end(); |
567 | for(ConfStrHash::iterator curr = confStr.begin(); curr != endS; curr++) |
568 | inf << curr->first << "=\"" << curr->second << "\"" << endl; |
569 | |
570 | ConfIntHash::iterator endI = confInt.end(); |
571 | for(ConfIntHash::iterator curr = confInt.begin(); curr != endI; curr++) |
572 | inf << curr->first << "=" << curr->second << endl; |
573 | |
574 | inf.close(); |
575 | sync(); |
576 | } |
577 | ledOff(); |
578 | } |
579 | |
580 | |
581 | void GMenu2X::readConfigOpen2x() { |
582 | string conffile = "/etc/config/open2x.conf"; |
583 | if (fileExists(conffile)) { |
584 | ifstream inf(conffile.c_str(), ios_base::in); |
585 | if (inf.is_open()) { |
586 | string line; |
587 | while (getline(inf, line, '\n')) { |
588 | string::size_type pos = line.find("="); |
589 | string name = trim(line.substr(0,pos)); |
590 | string value = trim(line.substr(pos+1,line.length())); |
591 | |
592 | if (name=="USB_NET_ON_BOOT") o2x_usb_net_on_boot = value == "y" ? true : false; |
593 | else if (name=="USB_NET_IP") o2x_usb_net_ip = value; |
594 | else if (name=="TELNET_ON_BOOT") o2x_telnet_on_boot = value == "y" ? true : false; |
595 | else if (name=="FTP_ON_BOOT") o2x_ftp_on_boot = value == "y" ? true : false; |
596 | else if (name=="GP2XJOY_ON_BOOT") o2x_gp2xjoy_on_boot = value == "y" ? true : false; |
597 | else if (name=="USB_HOST_ON_BOOT") o2x_usb_host_on_boot = value == "y" ? true : false; |
598 | else if (name=="USB_HID_ON_BOOT") o2x_usb_hid_on_boot = value == "y" ? true : false; |
599 | else if (name=="USB_STORAGE_ON_BOOT") o2x_usb_storage_on_boot = value == "y" ? true : false; |
600 | else if (name=="VOLUME_MODE") volumeMode = savedVolumeMode = constrain( atoi(value.c_str()), 0, 2); |
601 | else if (name=="PHONES_VALUE") volumeScalerPhones = constrain( atoi(value.c_str()), 0, 100); |
602 | else if (name=="NORMAL_VALUE") volumeScalerNormal = constrain( atoi(value.c_str()), 0, 150); |
603 | } |
604 | inf.close(); |
605 | } |
606 | } |
607 | } |
608 | void GMenu2X::writeConfigOpen2x() { |
609 | ledOn(); |
610 | string conffile = "/etc/config/open2x.conf"; |
611 | ofstream inf(conffile.c_str()); |
612 | if (inf.is_open()) { |
613 | inf << "USB_NET_ON_BOOT=" << ( o2x_usb_net_on_boot ? "y" : "n" ) << endl; |
614 | inf << "USB_NET_IP=" << o2x_usb_net_ip << endl; |
615 | inf << "TELNET_ON_BOOT=" << ( o2x_telnet_on_boot ? "y" : "n" ) << endl; |
616 | inf << "FTP_ON_BOOT=" << ( o2x_ftp_on_boot ? "y" : "n" ) << endl; |
617 | inf << "GP2XJOY_ON_BOOT=" << ( o2x_gp2xjoy_on_boot ? "y" : "n" ) << endl; |
618 | inf << "USB_HOST_ON_BOOT=" << ( (o2x_usb_host_on_boot || o2x_usb_hid_on_boot || o2x_usb_storage_on_boot) ? "y" : "n" ) << endl; |
619 | inf << "USB_HID_ON_BOOT=" << ( o2x_usb_hid_on_boot ? "y" : "n" ) << endl; |
620 | inf << "USB_STORAGE_ON_BOOT=" << ( o2x_usb_storage_on_boot ? "y" : "n" ) << endl; |
621 | inf << "VOLUME_MODE=" << volumeMode << endl; |
622 | if (volumeScalerPhones != VOLUME_SCALER_PHONES) inf << "PHONES_VALUE=" << volumeScalerPhones << endl; |
623 | if (volumeScalerNormal != VOLUME_SCALER_NORMAL) inf << "NORMAL_VALUE=" << volumeScalerNormal << endl; |
624 | inf.close(); |
625 | sync(); |
626 | } |
627 | ledOff(); |
628 | } |
629 | |
630 | void GMenu2X::writeSkinConfig() { |
631 | ledOn(); |
632 | string conffile = path+"skins/"+confStr["skin"]+"/skin.conf"; |
633 | ofstream inf(conffile.c_str()); |
634 | if (inf.is_open()) { |
635 | ConfStrHash::iterator endS = skinConfStr.end(); |
636 | for(ConfStrHash::iterator curr = skinConfStr.begin(); curr != endS; curr++) |
637 | inf << curr->first << "=\"" << curr->second << "\"" << endl; |
638 | |
639 | ConfIntHash::iterator endI = skinConfInt.end(); |
640 | for(ConfIntHash::iterator curr = skinConfInt.begin(); curr != endI; curr++) |
641 | inf << curr->first << "=" << curr->second << endl; |
642 | |
643 | int i; |
644 | for (i = 0; i < NUM_COLORS; ++i) { |
645 | inf << colorToString((enum color)i) << "=#" << hex << skinConfColors[i].r << hex |
646 | << skinConfColors[i].g << hex << skinConfColors[i].b << hex |
647 | << skinConfColors[i].a << endl; |
648 | } |
649 | |
650 | inf.close(); |
651 | sync(); |
652 | } |
653 | ledOff(); |
654 | } |
655 | |
656 | void GMenu2X::readCommonIni() { |
657 | if (fileExists("/usr/gp2x/common.ini")) { |
658 | ifstream inf("/usr/gp2x/common.ini", ios_base::in); |
659 | if (inf.is_open()) { |
660 | string line; |
661 | string section = ""; |
662 | while (getline(inf, line, '\n')) { |
663 | line = trim(line); |
664 | if (line[0]=='[' && line[line.length()-1]==']') { |
665 | section = line.substr(1,line.length()-2); |
666 | } else { |
667 | string::size_type pos = line.find("="); |
668 | string name = trim(line.substr(0,pos)); |
669 | string value = trim(line.substr(pos+1,line.length())); |
670 | |
671 | if (section=="usbnet") { |
672 | if (name=="enable") |
673 | usbnet = value=="true" ? true : false; |
674 | else if (name=="ip") |
675 | ip = value; |
676 | |
677 | } else if (section=="server") { |
678 | if (name=="inet") |
679 | inet = value=="true" ? true : false; |
680 | else if (name=="samba") |
681 | samba = value=="true" ? true : false; |
682 | else if (name=="web") |
683 | web = value=="true" ? true : false; |
684 | } |
685 | } |
686 | } |
687 | inf.close(); |
688 | } |
689 | } |
690 | } |
691 | |
692 | void GMenu2X::writeCommonIni() {} |
693 | |
694 | void GMenu2X::readTmp() { |
695 | lastSelectorElement = -1; |
696 | if (fileExists("/tmp/gmenu2x.tmp")) { |
697 | ifstream inf("/tmp/gmenu2x.tmp", ios_base::in); |
698 | if (inf.is_open()) { |
699 | string line; |
700 | string section = ""; |
701 | while (getline(inf, line, '\n')) { |
702 | string::size_type pos = line.find("="); |
703 | string name = trim(line.substr(0,pos)); |
704 | string value = trim(line.substr(pos+1,line.length())); |
705 | |
706 | if (name=="section") |
707 | menu->setSectionIndex(atoi(value.c_str())); |
708 | else if (name=="link") |
709 | menu->setLinkIndex(atoi(value.c_str())); |
710 | else if (name=="selectorelem") |
711 | lastSelectorElement = atoi(value.c_str()); |
712 | else if (name=="selectordir") |
713 | lastSelectorDir = value; |
714 | } |
715 | inf.close(); |
716 | } |
717 | } |
718 | } |
719 | |
720 | void GMenu2X::writeTmp(int selelem, const string &selectordir) { |
721 | string conffile = "/tmp/gmenu2x.tmp"; |
722 | ofstream inf(conffile.c_str()); |
723 | if (inf.is_open()) { |
724 | inf << "section=" << menu->selSectionIndex() << endl; |
725 | inf << "link=" << menu->selLinkIndex() << endl; |
726 | if (selelem>-1) |
727 | inf << "selectorelem=" << selelem << endl; |
728 | if (selectordir!="") |
729 | inf << "selectordir=" << selectordir << endl; |
730 | inf.close(); |
731 | sync(); |
732 | } |
733 | } |
734 | |
735 | void GMenu2X::initServices() { |
736 | #ifdef TARGET_GP2X |
737 | /* if (usbnet) { |
738 | string services = "scripts/services.sh "+ip+" "+(inet?"on":"off")+" "+(samba?"on":"off")+" "+(web?"on":"off")+" &"; |
739 | system(services.c_str()); |
740 | }*/ |
741 | #endif |
742 | } |
743 | |
744 | void GMenu2X::ledOn() { |
745 | #ifdef TARGET_GP2X |
746 | // if (gp2x_mem!=0 && !f200) gp2x_memregs[0x106E >> 1] ^= 16; |
747 | //SDL_SYS_JoystickGp2xSys(joy.joystick, BATT_LED_ON); |
748 | #endif |
749 | } |
750 | |
751 | void GMenu2X::ledOff() { |
752 | #ifdef TARGET_GP2X |
753 | // if (gp2x_mem!=0 && !f200) gp2x_memregs[0x106E >> 1] ^= 16; |
754 | //SDL_SYS_JoystickGp2xSys(joy.joystick, BATT_LED_OFF); |
755 | #endif |
756 | } |
757 | |
758 | void GMenu2X::setBacklight(int val) |
759 | { |
760 | if (backlightHandle) { |
761 | fprintf(backlightHandle, "%d", (val * 255) / 100); |
762 | fflush(backlightHandle); |
763 | rewind(backlightHandle); |
764 | } |
765 | } |
766 | |
767 | int GMenu2X::getBackLight() |
768 | { |
769 | int val = 255; |
770 | if (backlightHandle) { |
771 | fscanf(backlightHandle, "%d", &val); |
772 | rewind(backlightHandle); |
773 | val = (val * 100) / 255; |
774 | if (val < 0) val = 0; else if (val > 100) val = 100; |
775 | } |
776 | return val; |
777 | } |
778 | |
779 | void GMenu2X::main() { |
780 | uint linksPerPage = linkColumns*linkRows; |
781 | int linkSpacingX = (resX-10 - linkColumns*skinConfInt["linkWidth"])/linkColumns; |
782 | int linkSpacingY = (resY-35 - skinConfInt["topBarHeight"] - linkRows*skinConfInt["linkHeight"])/linkRows; |
783 | uint sectionLinkPadding = (skinConfInt["topBarHeight"] - 32 - font->getLineHeight()) / 3; |
784 | |
785 | bool quit = false; |
786 | int x,y, offset = menu->sectionLinks()->size()>linksPerPage ? 2 : 6, helpBoxHeight = fwType=="open2x" ? 154 : 139; |
787 | uint i; |
788 | long tickBattery = -60000, tickNow; |
789 | string batteryIcon = "imgs/battery/0.png"; |
790 | stringstream ss; |
791 | uint sectionsCoordX = 24; |
792 | SDL_Rect re = {0,0,0,0}; |
793 | bool helpDisplayed = false; |
794 | #ifdef DEBUG |
795 | //framerate |
796 | long tickFPS = SDL_GetTicks(); |
797 | int drawn_frames = 0; |
798 | string fps = ""; |
799 | #endif |
800 | |
801 | IconButton btnContextMenu(this,"skin:imgs/menu.png"); |
802 | btnContextMenu.setPosition(resX-38, bottomBarIconY); |
803 | btnContextMenu.setAction(MakeDelegate(this, &GMenu2X::contextMenu)); |
804 | |
805 | while (!quit) { |
806 | tickNow = SDL_GetTicks(); |
807 | |
808 | //Background |
809 | sc["bgmain"]->blit(s,0,0); |
810 | |
811 | //Sections |
812 | sectionsCoordX = halfX - (constrain((uint)menu->getSections().size(), 0 , linkColumns) * skinConfInt["linkWidth"]) / 2; |
813 | if (menu->firstDispSection()>0) |
814 | sc.skinRes("imgs/l_enabled.png")->blit(s,0,0); |
815 | else |
816 | sc.skinRes("imgs/l_disabled.png")->blit(s,0,0); |
817 | if (menu->firstDispSection()+linkColumns<menu->getSections().size()) |
818 | sc.skinRes("imgs/r_enabled.png")->blit(s,resX-10,0); |
819 | else |
820 | sc.skinRes("imgs/r_disabled.png")->blit(s,resX-10,0); |
821 | for (i=menu->firstDispSection(); i<menu->getSections().size() && i<menu->firstDispSection()+linkColumns; i++) { |
822 | string sectionIcon = "skin:sections/"+menu->getSections()[i]+".png"; |
823 | x = (i-menu->firstDispSection())*skinConfInt["linkWidth"]+sectionsCoordX; |
824 | if (menu->selSectionIndex()==(int)i) |
825 | s->box(x, 0, skinConfInt["linkWidth"], |
826 | skinConfInt["topBarHeight"], skinConfColors[COLOR_SELECTION_BG]); |
827 | x += skinConfInt["linkWidth"]/2; |
828 | if (sc.exists(sectionIcon)) |
829 | sc[sectionIcon]->blit(s,x-16,sectionLinkPadding,32,32); |
830 | else |
831 | sc.skinRes("icons/section.png")->blit(s,x-16,sectionLinkPadding); |
832 | s->write( font, menu->getSections()[i], x, skinConfInt["topBarHeight"]-sectionLinkPadding, SFontHAlignCenter, SFontVAlignBottom ); |
833 | } |
834 | |
835 | //Links |
836 | s->setClipRect(offset,skinConfInt["topBarHeight"],resX-9,resY-74); //32*2+10 |
837 | for (i=menu->firstDispRow()*linkColumns; i<(menu->firstDispRow()*linkColumns)+linksPerPage && i<menu->sectionLinks()->size(); i++) { |
838 | int ir = i-menu->firstDispRow()*linkColumns; |
839 | x = (ir%linkColumns)*(skinConfInt["linkWidth"]+linkSpacingX)+offset; |
840 | y = ir/linkColumns*(skinConfInt["linkHeight"]+linkSpacingY)+skinConfInt["topBarHeight"]+2; |
841 | menu->sectionLinks()->at(i)->setPosition(x,y); |
842 | |
843 | if (i==(uint)menu->selLinkIndex()) |
844 | menu->sectionLinks()->at(i)->paintHover(); |
845 | |
846 | menu->sectionLinks()->at(i)->paint(); |
847 | } |
848 | s->clearClipRect(); |
849 | |
850 | drawScrollBar(linkRows,menu->sectionLinks()->size()/linkColumns + ((menu->sectionLinks()->size()%linkColumns==0) ? 0 : 1),menu->firstDispRow(),43,resY-81); |
851 | |
852 | switch(volumeMode) { |
853 | case VOLUME_MODE_MUTE: sc.skinRes("imgs/mute.png")->blit(s,279,bottomBarIconY); break; |
854 | case VOLUME_MODE_PHONES: sc.skinRes("imgs/phones.png")->blit(s,279,bottomBarIconY); break; |
855 | default: sc.skinRes("imgs/volume.png")->blit(s,279,bottomBarIconY); break; |
856 | } |
857 | |
858 | if (menu->selLink()!=NULL) { |
859 | s->write ( font, menu->selLink()->getDescription(), halfX, resY-19, SFontHAlignCenter, SFontVAlignBottom ); |
860 | if (menu->selLinkApp()!=NULL) { |
861 | s->write ( font, menu->selLinkApp()->clockStr(confInt["maxClock"]), cpuX, bottomBarTextY, SFontHAlignLeft, SFontVAlignMiddle ); |
862 | s->write ( font, menu->selLinkApp()->volumeStr(), volumeX, bottomBarTextY, SFontHAlignLeft, SFontVAlignMiddle ); |
863 | //Manual indicator |
864 | if (!menu->selLinkApp()->getManual().empty()) |
865 | sc.skinRes("imgs/manual.png")->blit(s,manualX,bottomBarIconY); |
866 | } |
867 | } |
868 | |
869 | if (f200) { |
870 | btnContextMenu.paint(); |
871 | } |
872 | //check battery status every 60 seconds |
873 | if (tickNow-tickBattery >= 60000) { |
874 | tickBattery = tickNow; |
875 | unsigned short battlevel = getBatteryLevel(); |
876 | if (battlevel>5) { |
877 | batteryIcon = "imgs/battery/ac.png"; |
878 | } else { |
879 | ss.clear(); |
880 | ss << battlevel; |
881 | ss >> batteryIcon; |
882 | batteryIcon = "imgs/battery/"+batteryIcon+".png"; |
883 | } |
884 | } |
885 | sc.skinRes(batteryIcon)->blit( s, resX-19, bottomBarIconY ); |
886 | //s->write( font, tr[batstr.c_str()], 20, 170 ); |
887 | //On Screen Help |
888 | |
889 | if(input[ACTION_A] ) |
890 | helpDisplayed = ! helpDisplayed; |
891 | |
892 | if (helpDisplayed) { |
893 | s->box(10,50,300,143, skinConfColors[COLOR_MESSAGE_BOX_BG]); |
894 | s->rectangle( 12,52,296,helpBoxHeight, |
895 | skinConfColors[COLOR_MESSAGE_BOX_BORDER] ); |
896 | s->write( font, tr["CONTROLS"], 20, 60 ); |
897 | s->write( font, tr["B, Stick press: Launch link / Confirm action"], 20, 80 ); |
898 | s->write( font, tr["L, R: Change section"], 20, 95 ); |
899 | s->write( font, tr["Y: Show manual/readme"], 20, 110 ); |
900 | s->write( font, tr["VOLUP, VOLDOWN: Change cpu clock"], 20, 125 ); |
901 | s->write( font, tr["A+VOLUP, A+VOLDOWN: Change volume"], 20, 140 ); |
902 | s->write( font, tr["SELECT: Show contextual menu"], 20, 155 ); |
903 | s->write( font, tr["START: Show options menu"], 20, 170 ); |
904 | if (fwType=="open2x") s->write( font, tr["X: Toggle speaker mode"], 20, 185 ); |
905 | |
906 | } |
907 | |
908 | #ifdef DEBUG |
909 | //framerate |
910 | drawn_frames++; |
911 | if (tickNow-tickFPS>=1000) { |
912 | ss.clear(); |
913 | ss << drawn_frames*(tickNow-tickFPS+1)/1000; |
914 | ss >> fps; |
915 | tickFPS = tickNow; |
916 | drawn_frames = 0; |
917 | } |
918 | s->write( font, fps+" FPS", resX-1,1 ,SFontHAlignRight ); |
919 | #endif |
920 | |
921 | s->flip(); |
922 | |
923 | //touchscreen |
924 | if (f200) { |
925 | ts.poll(); |
926 | btnContextMenu.handleTS(); |
927 | re.x = 0; re.y = 0; re.h = skinConfInt["topBarHeight"]; re.w = resX; |
928 | if (ts.pressed() && ts.inRect(re)) { |
929 | re.w = skinConfInt["linkWidth"]; |
930 | sectionsCoordX = halfX - (constrain((uint)menu->getSections().size(), 0 , linkColumns) * skinConfInt["linkWidth"]) / 2; |
931 | for (i=menu->firstDispSection(); !ts.handled() && i<menu->getSections().size() && i<menu->firstDispSection()+linkColumns; i++) { |
932 | re.x = (i-menu->firstDispSection())*re.w+sectionsCoordX; |
933 | |
934 | if (ts.inRect(re)) { |
935 | menu->setSectionIndex(i); |
936 | ts.setHandled(); |
937 | } |
938 | } |
939 | } |
940 | |
941 | i=menu->firstDispRow()*linkColumns; |
942 | while ( i<(menu->firstDispRow()*linkColumns)+linksPerPage && i<menu->sectionLinks()->size()) { |
943 | if (menu->sectionLinks()->at(i)->isPressed()) |
944 | menu->setLinkIndex(i); |
945 | if (menu->sectionLinks()->at(i)->handleTS()) |
946 | i = menu->sectionLinks()->size(); |
947 | i++; |
948 | } |
949 | } |
950 | |
951 | //#ifdef TARGET_GP2X |
952 | while (!input.update()) |
953 | usleep(LOOP_DELAY); |
954 | if ( input[ACTION_B] && menu->selLink()!=NULL ) menu->selLink()->run(); |
955 | else if ( input[ACTION_START] ) options(); |
956 | else if ( input[ACTION_SELECT] ) contextMenu(); |
957 | // VOLUME SCALE MODIFIER |
958 | else if ( fwType=="open2x" && input[ACTION_X] ) { |
959 | volumeMode = constrain(volumeMode-1, -VOLUME_MODE_MUTE-1, VOLUME_MODE_NORMAL); |
960 | if(volumeMode < VOLUME_MODE_MUTE) |
961 | volumeMode = VOLUME_MODE_NORMAL; |
962 | switch(volumeMode) { |
963 | case VOLUME_MODE_MUTE: setVolumeScaler(VOLUME_SCALER_MUTE); break; |
964 | case VOLUME_MODE_PHONES: setVolumeScaler(volumeScalerPhones); break; |
965 | case VOLUME_MODE_NORMAL: setVolumeScaler(volumeScalerNormal); break; |
966 | } |
967 | setVolume(confInt["globalVolume"]); |
968 | } |
969 | // LINK NAVIGATION |
970 | else if ( input[ACTION_LEFT ] ) menu->linkLeft(); |
971 | else if ( input[ACTION_RIGHT] ) menu->linkRight(); |
972 | else if ( input[ACTION_UP ] ) menu->linkUp(); |
973 | else if ( input[ACTION_DOWN ] ) menu->linkDown(); |
974 | // SELLINKAPP SELECTED |
975 | else if (menu->selLinkApp()!=NULL) { |
976 | if ( input[ACTION_Y] ) menu->selLinkApp()->showManual(); |
977 | else if ( input.isActive(ACTION_A) ) { |
978 | // VOLUME |
979 | if ( input[ACTION_VOLDOWN] && !input.isActive(ACTION_VOLUP) ) |
980 | menu->selLinkApp()->setVolume( constrain(menu->selLinkApp()->volume()-1,0,100) ); |
981 | if ( input[ACTION_VOLUP] && !input.isActive(ACTION_VOLDOWN) ) |
982 | menu->selLinkApp()->setVolume( constrain(menu->selLinkApp()->volume()+1,0,100) );; |
983 | if ( input.isActive(ACTION_VOLUP) && input.isActive(ACTION_VOLDOWN) ) menu->selLinkApp()->setVolume(-1); |
984 | } else { |
985 | // CLOCK |
986 | if ( input[ACTION_VOLDOWN] && !input.isActive(ACTION_VOLUP) ) |
987 | menu->selLinkApp()->setClock( constrain(menu->selLinkApp()->clock()-1,200,confInt["maxClock"]) ); |
988 | if ( input[ACTION_VOLUP] && !input.isActive(ACTION_VOLDOWN) ) |
989 | menu->selLinkApp()->setClock( constrain(menu->selLinkApp()->clock()+1,200,confInt["maxClock"]) ); |
990 | if ( input.isActive(ACTION_VOLUP) && input.isActive(ACTION_VOLDOWN) ) menu->selLinkApp()->setClock(336); |
991 | } |
992 | } |
993 | if ( input.isActive(ACTION_A) ) { |
994 | if (input.isActive(ACTION_L) && input.isActive(ACTION_R)) |
995 | saveScreenshot(); |
996 | } else { |
997 | // SECTIONS |
998 | if ( input[ACTION_L ] ) { |
999 | menu->decSectionIndex(); |
1000 | offset = menu->sectionLinks()->size()>linksPerPage ? 2 : 6; |
1001 | } else if ( input[ACTION_R ] ) { |
1002 | menu->incSectionIndex(); |
1003 | offset = menu->sectionLinks()->size()>linksPerPage ? 2 : 6; |
1004 | } |
1005 | } |
1006 | } |
1007 | } |
1008 | |
1009 | void GMenu2X::explorer() { |
1010 | FileDialog fd(this,tr["Select an application"],".gpu,.dge,.sh,"); |
1011 | if (fd.exec()) { |
1012 | if (confInt["saveSelection"] && (confInt["section"]!=menu->selSectionIndex() || confInt["link"]!=menu->selLinkIndex())) |
1013 | writeConfig(); |
1014 | if (fwType == "open2x" && savedVolumeMode != volumeMode) |
1015 | writeConfigOpen2x(); |
1016 | |
1017 | //string command = cmdclean(fd.path()+"/"+fd.file) + "; sync & cd "+cmdclean(getExePath())+"; exec ./gmenu2x"; |
1018 | string command = cmdclean(fd.getPath()+"/"+fd.getFile()); |
1019 | chdir(fd.getPath().c_str()); |
1020 | quit(); |
1021 | setClock(200); |
1022 | execlp("/bin/sh","/bin/sh","-c",command.c_str(),NULL); |
1023 | |
1024 | //if execution continues then something went wrong and as we already called SDL_Quit we cannot continue |
1025 | //try relaunching gmenu2x |
1026 | fprintf(stderr, "Error executing selected application, re-launching gmenu2x\n"); |
1027 | chdir(getExePath().c_str()); |
1028 | execlp("./gmenu2x", "./gmenu2x", NULL); |
1029 | } |
1030 | } |
1031 | |
1032 | void GMenu2X::options() { |
1033 | int curMenuClock = confInt["menuClock"]; |
1034 | int curGlobalVolume = confInt["globalVolume"]; |
1035 | //G |
1036 | int prevbacklight = confInt["backlight"]; |
1037 | bool showRootFolder = fileExists(CARD_ROOT); |
1038 | |
1039 | FileLister fl_tr("translations"); |
1040 | fl_tr.browse(); |
1041 | fl_tr.insertFile("English"); |
1042 | string lang = tr.lang(); |
1043 | |
1044 | vector<string> encodings; |
1045 | encodings.push_back("NTSC"); |
1046 | encodings.push_back("PAL"); |
1047 | |
1048 | SettingsDialog sd(this, input, ts, tr["Settings"]); |
1049 | sd.addSetting(new MenuSettingMultiString(this,tr["Language"],tr["Set the language used by GMenu2X"],&lang,&fl_tr.getFiles())); |
1050 | sd.addSetting(new MenuSettingBool(this,tr["Save last selection"],tr["Save the last selected link and section on exit"],&confInt["saveSelection"])); |
1051 | sd.addSetting(new MenuSettingInt(this,tr["Clock for GMenu2X"],tr["Set the cpu working frequency when running GMenu2X"],&confInt["menuClock"],200,430)); |
1052 | sd.addSetting(new MenuSettingInt(this,tr["Maximum overclock"],tr["Set the maximum overclock for launching links"],&confInt["maxClock"],200,430)); |
1053 | sd.addSetting(new MenuSettingInt(this,tr["Global Volume"],tr["Set the default volume for the gp2x soundcard"],&confInt["globalVolume"],0,100)); |
1054 | sd.addSetting(new MenuSettingBool(this,tr["Output logs"],tr["Logs the output of the links. Use the Log Viewer to read them."],&confInt["outputLogs"])); |
1055 | //G |
1056 | sd.addSetting(new MenuSettingInt(this,tr["Lcd Backlight"],tr["Set dingoo's Lcd Backlight value (default: 100)"],&confInt["backlight"],5,100)); |
1057 | // sd.addSetting(new MenuSettingMultiString(this,tr["Tv-Out encoding"],tr["Encoding of the tv-out signal"],&confStr["tvoutEncoding"],&encodings)); |
1058 | sd.addSetting(new MenuSettingBool(this,tr["Show root"],tr["Show root folder in the file selection dialogs"],&showRootFolder)); |
1059 | |
1060 | if (sd.exec() && sd.edited()) { |
1061 | //G |
1062 | if (prevbacklight != confInt["backlight"]) setBacklight(confInt["backlight"]); |
1063 | if (curMenuClock!=confInt["menuClock"]) setClock(confInt["menuClock"]); |
1064 | if (curGlobalVolume!=confInt["globalVolume"]) setVolume(confInt["globalVolume"]); |
1065 | if (lang == "English") lang = ""; |
1066 | if (lang != tr.lang()) tr.setLang(lang); |
1067 | /*if (fileExists(CARD_ROOT) && !showRootFolder) |
1068 | unlink(CARD_ROOT); |
1069 | else if (!fileExists(CARD_ROOT) && showRootFolder) |
1070 | symlink("/", CARD_ROOT);*/ |
1071 | //WARNING: Disabled because these functions get dangerous when run with / as CARD_ROOT |
1072 | writeConfig(); |
1073 | } |
1074 | } |
1075 | |
1076 | void GMenu2X::settingsOpen2x() { |
1077 | SettingsDialog sd(this, input, ts, tr["Open2x Settings"]); |
1078 | sd.addSetting(new MenuSettingBool(this,tr["USB net on boot"],tr["Allow USB networking to be started at boot time"],&o2x_usb_net_on_boot)); |
1079 | sd.addSetting(new MenuSettingString(this,tr["USB net IP"],tr["IP address to be used for USB networking"],&o2x_usb_net_ip)); |
1080 | sd.addSetting(new MenuSettingBool(this,tr["Telnet on boot"],tr["Allow telnet to be started at boot time"],&o2x_telnet_on_boot)); |
1081 | sd.addSetting(new MenuSettingBool(this,tr["FTP on boot"],tr["Allow FTP to be started at boot time"],&o2x_ftp_on_boot)); |
1082 | sd.addSetting(new MenuSettingBool(this,tr["GP2XJOY on boot"],tr["Create a js0 device for GP2X controls"],&o2x_gp2xjoy_on_boot)); |
1083 | sd.addSetting(new MenuSettingBool(this,tr["USB host on boot"],tr["Allow USB host to be started at boot time"],&o2x_usb_host_on_boot)); |
1084 | sd.addSetting(new MenuSettingBool(this,tr["USB HID on boot"],tr["Allow USB HID to be started at boot time"],&o2x_usb_hid_on_boot)); |
1085 | sd.addSetting(new MenuSettingBool(this,tr["USB storage on boot"],tr["Allow USB storage to be started at boot time"],&o2x_usb_storage_on_boot)); |
1086 | //sd.addSetting(new MenuSettingInt(this,tr["Speaker Mode on boot"],tr["Set Speaker mode. 0 = Mute, 1 = Phones, 2 = Speaker"],&volumeMode,0,2)); |
1087 | sd.addSetting(new MenuSettingInt(this,tr["Speaker Scaler"],tr["Set the Speaker Mode scaling 0-150\% (default is 100\%)"],&volumeScalerNormal,0,150)); |
1088 | sd.addSetting(new MenuSettingInt(this,tr["Headphones Scaler"],tr["Set the Headphones Mode scaling 0-100\% (default is 65\%)"],&volumeScalerPhones,0,100)); |
1089 | |
1090 | if (sd.exec() && sd.edited()) { |
1091 | writeConfigOpen2x(); |
1092 | switch(volumeMode) { |
1093 | case VOLUME_MODE_MUTE: setVolumeScaler(VOLUME_SCALER_MUTE); break; |
1094 | case VOLUME_MODE_PHONES: setVolumeScaler(volumeScalerPhones); break; |
1095 | case VOLUME_MODE_NORMAL: setVolumeScaler(volumeScalerNormal); break; |
1096 | } |
1097 | setVolume(confInt["globalVolume"]); |
1098 | } |
1099 | } |
1100 | |
1101 | void GMenu2X::skinMenu() { |
1102 | FileLister fl_sk("skins",true,false); |
1103 | fl_sk.addExclude(".."); |
1104 | fl_sk.browse(); |
1105 | string curSkin = confStr["skin"]; |
1106 | |
1107 | SettingsDialog sd(this, input, ts, tr["Skin"]); |
1108 | sd.addSetting(new MenuSettingMultiString(this,tr["Skin"],tr["Set the skin used by GMenu2X"],&confStr["skin"],&fl_sk.getDirectories())); |
1109 | sd.addSetting(new MenuSettingRGBA(this,tr["Top Bar Color"],tr["Color of the top bar"],&skinConfColors[COLOR_TOP_BAR_BG])); |
1110 | sd.addSetting(new MenuSettingRGBA(this,tr["Bottom Bar Color"],tr["Color of the bottom bar"],&skinConfColors[COLOR_BOTTOM_BAR_BG])); |
1111 | sd.addSetting(new MenuSettingRGBA(this,tr["Selection Color"],tr["Color of the selection and other interface details"],&skinConfColors[COLOR_SELECTION_BG])); |
1112 | sd.addSetting(new MenuSettingRGBA(this,tr["Message Box Color"],tr["Background color of the message box"],&skinConfColors[COLOR_MESSAGE_BOX_BG])); |
1113 | sd.addSetting(new MenuSettingRGBA(this,tr["Message Box Border Color"],tr["Border color of the message box"],&skinConfColors[COLOR_MESSAGE_BOX_BORDER])); |
1114 | sd.addSetting(new MenuSettingRGBA(this,tr["Message Box Selection Color"],tr["Color of the selection of the message box"],&skinConfColors[COLOR_MESSAGE_BOX_SELECTION])); |
1115 | |
1116 | if (sd.exec() && sd.edited()) { |
1117 | if (curSkin != confStr["skin"]) { |
1118 | setSkin(confStr["skin"]); |
1119 | writeConfig(); |
1120 | } |
1121 | writeSkinConfig(); |
1122 | initBG(); |
1123 | } |
1124 | } |
1125 | |
1126 | void GMenu2X::toggleTvOut() { |
1127 | #ifdef TARGET_GP2X |
1128 | /* if (cx25874!=0) |
1129 | gp2x_tvout_off(); |
1130 | else |
1131 | gp2x_tvout_on(confStr["tvoutEncoding"] == "PAL");*/ |
1132 | #endif |
1133 | } |
1134 | |
1135 | void GMenu2X::setSkin(const string &skin, bool setWallpaper) { |
1136 | confStr["skin"] = skin; |
1137 | |
1138 | //Clear previous skin settings |
1139 | skinConfStr.clear(); |
1140 | skinConfInt.clear(); |
1141 | |
1142 | //clear collection and change the skin path |
1143 | sc.clear(); |
1144 | sc.setSkin(skin); |
1145 | |
1146 | //reset colors to the default values |
1147 | skinConfColors[COLOR_TOP_BAR_BG] = (RGBAColor){255,255,255,130}; |
1148 | skinConfColors[COLOR_BOTTOM_BAR_BG] = (RGBAColor){255,255,255,130}; |
1149 | skinConfColors[COLOR_SELECTION_BG] = (RGBAColor){255,255,255,130}; |
1150 | skinConfColors[COLOR_MESSAGE_BOX_BG] = (RGBAColor){255,255,255,255}; |
1151 | skinConfColors[COLOR_MESSAGE_BOX_BORDER] = (RGBAColor){80,80,80,255}; |
1152 | skinConfColors[COLOR_MESSAGE_BOX_SELECTION] = (RGBAColor){160,160,160,255}; |
1153 | |
1154 | //load skin settings |
1155 | string skinconfname = "skins/"+skin+"/skin.conf"; |
1156 | if (fileExists(skinconfname)) { |
1157 | ifstream skinconf(skinconfname.c_str(), ios_base::in); |
1158 | if (skinconf.is_open()) { |
1159 | string line; |
1160 | while (getline(skinconf, line, '\n')) { |
1161 | line = trim(line); |
1162 | cout << "skinconf: " << line << endl; |
1163 | string::size_type pos = line.find("="); |
1164 | string name = trim(line.substr(0,pos)); |
1165 | string value = trim(line.substr(pos+1,line.length())); |
1166 | |
1167 | if (value.length()>0) { |
1168 | if (value.length()>1 && value.at(0)=='"' && value.at(value.length()-1)=='"') |
1169 | skinConfStr[name] = value.substr(1,value.length()-2); |
1170 | else if (value.at(0) == '#') |
1171 | skinConfColors[stringToColor(name)] = strtorgba( value.substr(1,value.length()) ); |
1172 | else |
1173 | skinConfInt[name] = atoi(value.c_str()); |
1174 | } |
1175 | } |
1176 | skinconf.close(); |
1177 | |
1178 | if (setWallpaper && !skinConfStr["wallpaper"].empty() && fileExists("skins/"+skin+"/wallpapers/"+skinConfStr["wallpaper"])) |
1179 | confStr["wallpaper"] = "skins/"+skin+"/wallpapers/"+skinConfStr["wallpaper"]; |
1180 | } |
1181 | } |
1182 | |
1183 | evalIntConf( &skinConfInt["topBarHeight"], 40, 32,120 ); |
1184 | evalIntConf( &skinConfInt["linkHeight"], 40, 32,120 ); |
1185 | evalIntConf( &skinConfInt["linkWidth"], 60, 32,120 ); |
1186 | |
1187 | //recalculate some coordinates based on the new element sizes |
1188 | linkColumns = (resX-10)/skinConfInt["linkWidth"]; |
1189 | linkRows = (resY-35-skinConfInt["topBarHeight"])/skinConfInt["linkHeight"]; |
1190 | |
1191 | if (menu != NULL) menu->loadIcons(); |
1192 | |
1193 | //Selection png |
1194 | useSelectionPng = sc.addSkinRes("imgs/selection.png") != NULL; |
1195 | |
1196 | //font |
1197 | initFont(); |
1198 | } |
1199 | |
1200 | void GMenu2X::activateSdUsb() { |
1201 | if (usbnet) { |
1202 | MessageBox mb(this,tr["Operation not permitted."]+"\n"+tr["You should disable Usb Networking to do this."]); |
1203 | mb.exec(); |
1204 | } else { |
1205 | system("scripts/usbon.sh sd"); |
1206 | MessageBox mb(this,tr["USB Enabled (SD)"],"icons/usb.png"); |
1207 | mb.setButton(ACTION_B, tr["Turn off"]); |
1208 | mb.exec(); |
1209 | system("scripts/usboff.sh sd"); |
1210 | } |
1211 | } |
1212 | |
1213 | void GMenu2X::activateNandUsb() { |
1214 | if (usbnet) { |
1215 | MessageBox mb(this,tr["Operation not permitted."]+"\n"+tr["You should disable Usb Networking to do this."]); |
1216 | mb.exec(); |
1217 | } else { |
1218 | system("scripts/usbon.sh nand"); |
1219 | MessageBox mb(this,tr["USB Enabled (Nand)"],"icons/usb.png"); |
1220 | mb.setButton(ACTION_B, tr["Turn off"]); |
1221 | mb.exec(); |
1222 | system("scripts/usboff.sh nand"); |
1223 | } |
1224 | } |
1225 | |
1226 | void GMenu2X::activateRootUsb() { |
1227 | if (usbnet) { |
1228 | MessageBox mb(this,tr["Operation not permitted."]+"\n"+tr["You should disable Usb Networking to do this."]); |
1229 | mb.exec(); |
1230 | } else { |
1231 | system("scripts/usbon.sh root"); |
1232 | MessageBox mb(this,tr["USB Enabled (Root)"],"icons/usb.png"); |
1233 | mb.setButton(ACTION_B, tr["Turn off"]); |
1234 | mb.exec(); |
1235 | system("scripts/usboff.sh root"); |
1236 | } |
1237 | } |
1238 | |
1239 | void GMenu2X::contextMenu() { |
1240 | vector<MenuOption> voices; |
1241 | { |
1242 | MenuOption opt = {tr.translate("Add link in $1",menu->selSection().c_str(),NULL), MakeDelegate(this, &GMenu2X::addLink)}; |
1243 | voices.push_back(opt); |
1244 | } |
1245 | |
1246 | if (menu->selLinkApp()!=NULL) { |
1247 | { |
1248 | MenuOption opt = {tr.translate("Edit $1",menu->selLink()->getTitle().c_str(),NULL), MakeDelegate(this, &GMenu2X::editLink)}; |
1249 | voices.push_back(opt); |
1250 | }{ |
1251 | MenuOption opt = {tr.translate("Delete $1 link",menu->selLink()->getTitle().c_str(),NULL), MakeDelegate(this, &GMenu2X::deleteLink)}; |
1252 | voices.push_back(opt); |
1253 | } |
1254 | } |
1255 | |
1256 | { |
1257 | MenuOption opt = {tr["Add section"], MakeDelegate(this, &GMenu2X::addSection)}; |
1258 | voices.push_back(opt); |
1259 | }{ |
1260 | MenuOption opt = {tr["Rename section"], MakeDelegate(this, &GMenu2X::renameSection)}; |
1261 | voices.push_back(opt); |
1262 | }{ |
1263 | MenuOption opt = {tr["Delete section"], MakeDelegate(this, &GMenu2X::deleteSection)}; |
1264 | voices.push_back(opt); |
1265 | }{ |
1266 | MenuOption opt = {tr["Scan for applications and games"], MakeDelegate(this, &GMenu2X::scanner)}; |
1267 | voices.push_back(opt); |
1268 | } |
1269 | |
1270 | bool close = false; |
1271 | uint i, sel=0, fadeAlpha=0; |
1272 | |
1273 | int h = font->getHeight(); |
1274 | int h2 = font->getHalfHeight(); |
1275 | SDL_Rect box; |
1276 | box.h = (h+2)*voices.size()+8; |
1277 | box.w = 0; |
1278 | for (i=0; i<voices.size(); i++) { |
1279 | int w = font->getTextWidth(voices[i].text); |
1280 | if (w>box.w) box.w = w; |
1281 | } |
1282 | box.w += 23; |
1283 | box.x = halfX - box.w/2; |
1284 | box.y = halfY - box.h/2; |
1285 | |
1286 | SDL_Rect selbox = {box.x+4, 0, box.w-8, h+2}; |
1287 | long tickNow, tickStart = SDL_GetTicks(); |
1288 | |
1289 | Surface bg(s); |
1290 | /*//Darken background |
1291 | bg.box(0, 0, resX, resY, 0,0,0,150); |
1292 | bg.box(box.x, box.y, box.w, box.h, skinConfColors["messageBoxBg"]); |
1293 | bg.rectangle( box.x+2, box.y+2, box.w-4, box.h-4, skinConfColors["messageBoxBorder"] );*/ |
1294 | while (!close) { |
1295 | tickNow = SDL_GetTicks(); |
1296 | |
1297 | selbox.y = box.y+4+(h+2)*sel; |
1298 | bg.blit(s,0,0); |
1299 | |
1300 | if (fadeAlpha<200) fadeAlpha = intTransition(0,200,tickStart,500,tickNow); |
1301 | s->box(0, 0, resX, resY, 0,0,0,fadeAlpha); |
1302 | s->box(box.x, box.y, box.w, box.h, skinConfColors[COLOR_MESSAGE_BOX_BG]); |
1303 | s->rectangle( box.x+2, box.y+2, box.w-4, box.h-4, skinConfColors[COLOR_MESSAGE_BOX_BORDER] ); |
1304 | |
1305 | |
1306 | //draw selection rect |
1307 | s->box( selbox.x, selbox.y, selbox.w, selbox.h, skinConfColors[COLOR_MESSAGE_BOX_SELECTION] ); |
1308 | for (i=0; i<voices.size(); i++) |
1309 | s->write( font, voices[i].text, box.x+12, box.y+h2+5+(h+2)*i, SFontHAlignLeft, SFontVAlignMiddle ); |
1310 | s->flip(); |
1311 | |
1312 | //touchscreen |
1313 | if (f200) { |
1314 | ts.poll(); |
1315 | if (ts.released()) { |
1316 | if (!ts.inRect(box)) |
1317 | close = true; |
1318 | else if (ts.getX() >= selbox.x |
1319 | && ts.getX() <= selbox.x + selbox.w) |
1320 | for (i=0; i<voices.size(); i++) { |
1321 | selbox.y = box.y+4+(h+2)*i; |
1322 | if (ts.getY() >= selbox.y |
1323 | && ts.getY() <= selbox.y + selbox.h) { |
1324 | voices[i].action(); |
1325 | close = true; |
1326 | i = voices.size(); |
1327 | } |
1328 | } |
1329 | } else if (ts.pressed() && ts.inRect(box)) { |
1330 | for (i=0; i<voices.size(); i++) { |
1331 | selbox.y = box.y+4+(h+2)*i; |
1332 | if (ts.getY() >= selbox.y |
1333 | && ts.getY() <= selbox.y + selbox.h) { |
1334 | sel = i; |
1335 | i = voices.size(); |
1336 | } |
1337 | } |
1338 | } |
1339 | } |
1340 | |
1341 | input.update(); |
1342 | if ( input[ACTION_SELECT] ) close = true; |
1343 | if ( input[ACTION_UP ] ) sel = max(0, sel-1); |
1344 | if ( input[ACTION_DOWN ] ) sel = min((int)voices.size()-1, sel+1); |
1345 | if ( input[ACTION_B] ) { voices[sel].action(); close = true; } |
1346 | } |
1347 | } |
1348 | |
1349 | void GMenu2X::changeWallpaper() { |
1350 | WallpaperDialog wp(this); |
1351 | if (wp.exec() && confStr["wallpaper"] != wp.wallpaper) { |
1352 | confStr["wallpaper"] = wp.wallpaper; |
1353 | initBG(); |
1354 | writeConfig(); |
1355 | } |
1356 | } |
1357 | |
1358 | void GMenu2X::saveScreenshot() { |
1359 | ledOn(); |
1360 | uint x = 0; |
1361 | stringstream ss; |
1362 | string fname; |
1363 | do { |
1364 | x++; |
1365 | fname = ""; |
1366 | ss.clear(); |
1367 | ss << x; |
1368 | ss >> fname; |
1369 | fname = "screen"+fname+".bmp"; |
1370 | } while (fileExists(fname)); |
1371 | SDL_SaveBMP(s->raw,fname.c_str()); |
1372 | sync(); |
1373 | ledOff(); |
1374 | } |
1375 | |
1376 | void GMenu2X::addLink() { |
1377 | FileDialog fd(this,tr["Select an application"]); |
1378 | if (fd.exec()) { |
1379 | ledOn(); |
1380 | menu->addLink(fd.getPath(), fd.getFile()); |
1381 | sync(); |
1382 | ledOff(); |
1383 | } |
1384 | } |
1385 | |
1386 | void GMenu2X::editLink() { |
1387 | if (menu->selLinkApp()==NULL) return; |
1388 | |
1389 | vector<string> pathV; |
1390 | split(pathV,menu->selLinkApp()->getFile(),"/"); |
1391 | string oldSection = ""; |
1392 | if (pathV.size()>1) |
1393 | oldSection = pathV[pathV.size()-2]; |
1394 | string newSection = oldSection; |
1395 | |
1396 | string linkTitle = menu->selLinkApp()->getTitle(); |
1397 | string linkDescription = menu->selLinkApp()->getDescription(); |
1398 | string linkIcon = menu->selLinkApp()->getIcon(); |
1399 | string linkManual = menu->selLinkApp()->getManual(); |
1400 | string linkParams = menu->selLinkApp()->getParams(); |
1401 | string linkSelFilter = menu->selLinkApp()->getSelectorFilter(); |
1402 | string linkSelDir = menu->selLinkApp()->getSelectorDir(); |
1403 | bool linkSelBrowser = menu->selLinkApp()->getSelectorBrowser(); |
1404 | bool linkUseRamTimings = menu->selLinkApp()->getUseRamTimings(); |
1405 | string linkSelScreens = menu->selLinkApp()->getSelectorScreens(); |
1406 | string linkSelAliases = menu->selLinkApp()->getAliasFile(); |
1407 | int linkClock = menu->selLinkApp()->clock(); |
1408 | int linkVolume = menu->selLinkApp()->volume(); |
1409 | //G |
1410 | //int linkGamma = menu->selLinkApp()->gamma(); |
1411 | int linkBacklight = menu->selLinkApp()->backlight(); |
1412 | |
1413 | string diagTitle = tr.translate("Edit link: $1",linkTitle.c_str(),NULL); |
1414 | string diagIcon = menu->selLinkApp()->getIconPath(); |
1415 | |
1416 | SettingsDialog sd(this, input, ts, diagTitle, diagIcon); |
1417 | sd.addSetting(new MenuSettingString(this,tr["Title"],tr["Link title"],&linkTitle, diagTitle,diagIcon)); |
1418 | sd.addSetting(new MenuSettingString(this,tr["Description"],tr["Link description"],&linkDescription, diagTitle,diagIcon)); |
1419 | sd.addSetting(new MenuSettingMultiString(this,tr["Section"],tr["The section this link belongs to"],&newSection,&menu->getSections())); |
1420 | sd.addSetting(new MenuSettingImage(this,tr["Icon"],tr.translate("Select an icon for the link: $1",linkTitle.c_str(),NULL),&linkIcon,".png,.bmp,.jpg,.jpeg")); |
1421 | sd.addSetting(new MenuSettingFile(this,tr["Manual"],tr["Select a graphic/textual manual or a readme"],&linkManual,".man.png,.txt")); |
1422 | sd.addSetting(new MenuSettingInt(this,tr["Clock (default: 336)"],tr["Cpu clock frequency to set when launching this link"],&linkClock,200,confInt["maxClock"])); |
1423 | // sd.addSetting(new MenuSettingBool(this,tr["Tweak RAM Timings"],tr["This usually speeds up the application at the cost of stability"],&linkUseRamTimings)); |
1424 | sd.addSetting(new MenuSettingInt(this,tr["Volume (default: -1)"],tr["Volume to set for this link"],&linkVolume,-1,100)); |
1425 | sd.addSetting(new MenuSettingInt(this,tr["Backlight (default: 100)"],tr["LCD backlight value to set when launching this link"],&linkBacklight,5,100)); |
1426 | sd.addSetting(new MenuSettingString(this,tr["Parameters"],tr["Parameters to pass to the application"],&linkParams, diagTitle,diagIcon)); |
1427 | sd.addSetting(new MenuSettingDir(this,tr["Selector Directory"],tr["Directory to scan for the selector"],&linkSelDir)); |
1428 | sd.addSetting(new MenuSettingBool(this,tr["Selector Browser"],tr["Allow the selector to change directory"],&linkSelBrowser)); |
1429 | sd.addSetting(new MenuSettingString(this,tr["Selector Filter"],tr["Filter for the selector (Separate values with a comma)"],&linkSelFilter, diagTitle,diagIcon)); |
1430 | sd.addSetting(new MenuSettingDir(this,tr["Selector Screenshots"],tr["Directory of the screenshots for the selector"],&linkSelScreens)); |
1431 | sd.addSetting(new MenuSettingFile(this,tr["Selector Aliases"],tr["File containing a list of aliases for the selector"],&linkSelAliases)); |
1432 | //G |
1433 | sd.addSetting(new MenuSettingBool(this,tr["Wrapper"],tr["Explicitly relaunch GMenu2X after this link's execution ends"],&menu->selLinkApp()->needsWrapperRef())); |
1434 | sd.addSetting(new MenuSettingBool(this,tr["Don't Leave"],tr["Don't quit GMenu2X when launching this link"],&menu->selLinkApp()->runsInBackgroundRef())); |
1435 | |
1436 | if (sd.exec() && sd.edited()) { |
1437 | ledOn(); |
1438 | |
1439 | menu->selLinkApp()->setTitle(linkTitle); |
1440 | menu->selLinkApp()->setDescription(linkDescription); |
1441 | menu->selLinkApp()->setIcon(linkIcon); |
1442 | menu->selLinkApp()->setManual(linkManual); |
1443 | menu->selLinkApp()->setParams(linkParams); |
1444 | menu->selLinkApp()->setSelectorFilter(linkSelFilter); |
1445 | menu->selLinkApp()->setSelectorDir(linkSelDir); |
1446 | menu->selLinkApp()->setSelectorBrowser(linkSelBrowser); |
1447 | menu->selLinkApp()->setUseRamTimings(linkUseRamTimings); |
1448 | menu->selLinkApp()->setSelectorScreens(linkSelScreens); |
1449 | menu->selLinkApp()->setAliasFile(linkSelAliases); |
1450 | menu->selLinkApp()->setClock(linkClock); |
1451 | menu->selLinkApp()->setVolume(linkVolume); |
1452 | //G |
1453 | menu->selLinkApp()->setBacklight(linkBacklight); |
1454 | |
1455 | #ifdef DEBUG |
1456 | cout << "New Section: " << newSection << endl; |
1457 | #endif |
1458 | //if section changed move file and update link->file |
1459 | if (oldSection!=newSection) { |
1460 | vector<string>::const_iterator newSectionIndex = find(menu->getSections().begin(),menu->getSections().end(),newSection); |
1461 | if (newSectionIndex==menu->getSections().end()) return; |
1462 | string newFileName = "sections/"+newSection+"/"+linkTitle; |
1463 | uint x=2; |
1464 | while (fileExists(newFileName)) { |
1465 | string id = ""; |
1466 | stringstream ss; ss << x; ss >> id; |
1467 | newFileName = "sections/"+newSection+"/"+linkTitle+id; |
1468 | x++; |
1469 | } |
1470 | rename(menu->selLinkApp()->getFile().c_str(),newFileName.c_str()); |
1471 | menu->selLinkApp()->renameFile(newFileName); |
1472 | #ifdef DEBUG |
1473 | cout << "New section index: " << newSectionIndex - menu->getSections().begin() << endl; |
1474 | #endif |
1475 | menu->linkChangeSection(menu->selLinkIndex(), menu->selSectionIndex(), newSectionIndex - menu->getSections().begin()); |
1476 | } |
1477 | menu->selLinkApp()->save(); |
1478 | sync(); |
1479 | |
1480 | ledOff(); |
1481 | } |
1482 | } |
1483 | |
1484 | void GMenu2X::deleteLink() { |
1485 | if (menu->selLinkApp()!=NULL) { |
1486 | MessageBox mb(this, tr.translate("Deleting $1",menu->selLink()->getTitle().c_str(),NULL)+"\n"+tr["Are you sure?"], menu->selLink()->getIconPath()); |
1487 | mb.setButton(ACTION_B, tr["Yes"]); |
1488 | mb.setButton(ACTION_X, tr["No"]); |
1489 | if (mb.exec() == ACTION_B) { |
1490 | ledOn(); |
1491 | menu->deleteSelectedLink(); |
1492 | sync(); |
1493 | ledOff(); |
1494 | } |
1495 | } |
1496 | } |
1497 | |
1498 | void GMenu2X::addSection() { |
1499 | InputDialog id(this, input, ts, tr["Insert a name for the new section"]); |
1500 | if (id.exec()) { |
1501 | //only if a section with the same name does not exist |
1502 | if (find(menu->getSections().begin(), menu->getSections().end(), id.getInput()) |
1503 | == menu->getSections().end()) { |
1504 | //section directory doesn't exists |
1505 | ledOn(); |
1506 | if (menu->addSection(id.getInput())) { |
1507 | menu->setSectionIndex( menu->getSections().size()-1 ); //switch to the new section |
1508 | sync(); |
1509 | } |
1510 | ledOff(); |
1511 | } |
1512 | } |
1513 | } |
1514 | |
1515 | void GMenu2X::renameSection() { |
1516 | InputDialog id(this, input, ts, tr["Insert a new name for this section"],menu->selSection()); |
1517 | if (id.exec()) { |
1518 | //only if a section with the same name does not exist & !samename |
1519 | if (menu->selSection() != id.getInput() |
1520 | && find(menu->getSections().begin(),menu->getSections().end(), id.getInput()) |
1521 | == menu->getSections().end()) { |
1522 | //section directory doesn't exists |
1523 | string newsectiondir = "sections/" + id.getInput(); |
1524 | string sectiondir = "sections/" + menu->selSection(); |
1525 | ledOn(); |
1526 | if (rename(sectiondir.c_str(), "tmpsection")==0 && rename("tmpsection", newsectiondir.c_str())==0) { |
1527 | string oldpng = sectiondir+".png", newpng = newsectiondir+".png"; |
1528 | string oldicon = sc.getSkinFilePath(oldpng), newicon = sc.getSkinFilePath(newpng); |
1529 | if (!oldicon.empty() && newicon.empty()) { |
1530 | newicon = oldicon; |
1531 | newicon.replace(newicon.find(oldpng), oldpng.length(), newpng); |
1532 | |
1533 | if (!fileExists(newicon)) { |
1534 | rename(oldicon.c_str(), "tmpsectionicon"); |
1535 | rename("tmpsectionicon", newicon.c_str()); |
1536 | sc.move("skin:"+oldpng, "skin:"+newpng); |
1537 | } |
1538 | } |
1539 | menu->renameSection(menu->selSectionIndex(), id.getInput()); |
1540 | sync(); |
1541 | } |
1542 | ledOff(); |
1543 | } |
1544 | } |
1545 | } |
1546 | |
1547 | void GMenu2X::deleteSection() { |
1548 | MessageBox mb(this,tr["You will lose all the links in this section."]+"\n"+tr["Are you sure?"]); |
1549 | mb.setButton(ACTION_B, tr["Yes"]); |
1550 | mb.setButton(ACTION_X, tr["No"]); |
1551 | if (mb.exec() == ACTION_B) { |
1552 | ledOn(); |
1553 | if (rmtree(path+"sections/"+menu->selSection())) { |
1554 | menu->deleteSelectedSection(); |
1555 | sync(); |
1556 | } |
1557 | ledOff(); |
1558 | } |
1559 | } |
1560 | |
1561 | void GMenu2X::scanner() { |
1562 | Surface scanbg(bg); |
1563 | drawButton(&scanbg, "x", tr["Exit"], |
1564 | drawButton(&scanbg, "b", "", 5)-10); |
1565 | scanbg.write(font,tr["Link Scanner"],halfX,7,SFontHAlignCenter,SFontVAlignMiddle); |
1566 | |
1567 | uint lineY = 42; |
1568 | |
1569 | #ifdef _TARGET_PANDORA |
1570 | //char *configpath = pnd_conf_query_searchpath(); |
1571 | #else |
1572 | if (confInt["menuClock"]<430) { |
1573 | setClock(336); |
1574 | scanbg.write(font,tr["Raising cpu clock to 336Mhz"],5,lineY); |
1575 | scanbg.blit(s,0,0); |
1576 | s->flip(); |
1577 | lineY += 26; |
1578 | } |
1579 | |
1580 | scanbg.write(font,tr["Scanning SD filesystem..."],5,lineY); |
1581 | scanbg.blit(s,0,0); |
1582 | s->flip(); |
1583 | lineY += 26; |
1584 | |
1585 | vector<string> files; |
1586 | scanPath(CARD_ROOT, &files); |
1587 | |
1588 | //Onyl gph firmware has nand |
1589 | /* if (fwType=="gph" && !f200) { |
1590 | scanbg.write(font,tr["Scanning NAND filesystem..."],5,lineY); |
1591 | scanbg.blit(s,0,0); |
1592 | s->flip(); |
1593 | lineY += 26; |
1594 | scanPath("/boot/local/nand",&files); |
1595 | } |
1596 | */ |
1597 | stringstream ss; |
1598 | ss << files.size(); |
1599 | string str = ""; |
1600 | ss >> str; |
1601 | scanbg.write(font,tr.translate("$1 files found.",str.c_str(),NULL),5,lineY); |
1602 | lineY += 26; |
1603 | scanbg.write(font,tr["Creating links..."],5,lineY); |
1604 | scanbg.blit(s,0,0); |
1605 | s->flip(); |
1606 | lineY += 26; |
1607 | |
1608 | string path, file; |
1609 | string::size_type pos; |
1610 | uint linkCount = 0; |
1611 | |
1612 | ledOn(); |
1613 | for (uint i = 0; i<files.size(); i++) { |
1614 | pos = files[i].rfind("/"); |
1615 | if (pos!=string::npos && pos>0) { |
1616 | path = files[i].substr(0, pos+1); |
1617 | file = files[i].substr(pos+1, files[i].length()); |
1618 | if (menu->addLink(path,file,"found "+file.substr(file.length()-3,3))) |
1619 | linkCount++; |
1620 | } |
1621 | } |
1622 | |
1623 | ss.clear(); |
1624 | ss << linkCount; |
1625 | ss >> str; |
1626 | scanbg.write(font,tr.translate("$1 links created.",str.c_str(),NULL),5,lineY); |
1627 | scanbg.blit(s,0,0); |
1628 | s->flip(); |
1629 | lineY += 26; |
1630 | |
1631 | if (confInt["menuClock"]<430) { |
1632 | setClock(confInt["menuClock"]); |
1633 | scanbg.write(font,tr["Decreasing cpu clock"],5,lineY); |
1634 | scanbg.blit(s,0,0); |
1635 | s->flip(); |
1636 | lineY += 26; |
1637 | } |
1638 | |
1639 | sync(); |
1640 | ledOff(); |
1641 | #endif |
1642 | |
1643 | bool close = false; |
1644 | while (!close) { |
1645 | input.update(); |
1646 | if (input[ACTION_START] || input[ACTION_B] || input[ACTION_X]) close = true; |
1647 | usleep(30000); |
1648 | } |
1649 | } |
1650 | |
1651 | void GMenu2X::scanPath(string path, vector<string> *files) { |
1652 | DIR *dirp; |
1653 | struct stat st; |
1654 | struct dirent *dptr; |
1655 | string filepath, ext; |
1656 | |
1657 | if (path[path.length()-1]!='/') path += "/"; |
1658 | if ((dirp = opendir(path.c_str())) == NULL) return; |
1659 | |
1660 | while ((dptr = readdir(dirp))) { |
1661 | if (dptr->d_name[0]=='.') |
1662 | continue; |
1663 | filepath = path+dptr->d_name; |
1664 | int statRet = stat(filepath.c_str(), &st); |
1665 | if (S_ISDIR(st.st_mode)) |
1666 | scanPath(filepath, files); |
1667 | if (statRet != -1) { |
1668 | ext = filepath.substr(filepath.length()-4,4); |
1669 | #ifdef TARGET_GP2X |
1670 | if (ext==".gpu" || ext==".dge") |
1671 | #else |
1672 | if (ext==".pxml") |
1673 | #endif |
1674 | files->push_back(filepath); |
1675 | } |
1676 | } |
1677 | |
1678 | closedir(dirp); |
1679 | } |
1680 | |
1681 | unsigned short GMenu2X::getBatteryLevel() { |
1682 | #ifdef TARGET_GP2X |
1683 | /* if (batteryHandle<=0) return 0; |
1684 | |
1685 | if (f200) { |
1686 | MMSP2ADC val; |
1687 | read(batteryHandle, &val, sizeof(MMSP2ADC)); |
1688 | |
1689 | if (val.batt==0) return 5; |
1690 | if (val.batt==1) return 3; |
1691 | if (val.batt==2) return 1; |
1692 | if (val.batt==3) return 0; |
1693 | } else { |
1694 | int battval = 0; |
1695 | unsigned short cbv, min=900, max=0; |
1696 | |
1697 | for (int i = 0; i < BATTERY_READS; i ++) { |
1698 | if ( read(batteryHandle, &cbv, 2) == 2) { |
1699 | battval += cbv; |
1700 | if (cbv>max) max = cbv; |
1701 | if (cbv<min) min = cbv; |
1702 | } |
1703 | } |
1704 | |
1705 | battval -= min+max; |
1706 | battval /= BATTERY_READS-2; |
1707 | |
1708 | if (battval>=850) return 6; |
1709 | if (battval>780) return 5; |
1710 | if (battval>740) return 4; |
1711 | if (battval>700) return 3; |
1712 | if (battval>690) return 2; |
1713 | if (battval>680) return 1; |
1714 | }*/ |
1715 | if (!batteryHandle) return 0; |
1716 | int battval = 0; |
1717 | char battvalcstr[5]; |
1718 | fscanf(batteryHandle, "%s", &battvalcstr[0]); |
1719 | rewind(batteryHandle); |
1720 | battval = atoi(battvalcstr); |
1721 | if (battval>90) return 5; |
1722 | if (battval>70) return 4; |
1723 | if (battval>50) return 3; |
1724 | if (battval>30) return 2; |
1725 | if (battval>10) return 1; |
1726 | |
1727 | if (!usbHandle) return 0; |
1728 | int usbval = 0; |
1729 | char usbvalcstr[5]; |
1730 | fscanf(usbHandle, "%s", &usbvalcstr[0]); |
1731 | rewind(usbHandle); |
1732 | usbval = atoi(usbvalcstr); |
1733 | if (usbval==1) return 6; |
1734 | |
1735 | return 0; |
1736 | //#else |
1737 | // return 6; //AC Power |
1738 | #endif |
1739 | } |
1740 | |
1741 | void GMenu2X::setInputSpeed() { |
1742 | input.setInterval(150); |
1743 | input.setInterval(30, ACTION_VOLDOWN); |
1744 | input.setInterval(30, ACTION_VOLUP ); |
1745 | input.setInterval(30, ACTION_A ); |
1746 | input.setInterval(500, ACTION_START ); |
1747 | input.setInterval(500, ACTION_SELECT ); |
1748 | input.setInterval(300, ACTION_X ); |
1749 | input.setInterval(300, ACTION_Y ); |
1750 | input.setInterval(1000,ACTION_B ); |
1751 | //joy.setInterval(1000,ACTION_CLICK ); |
1752 | input.setInterval(300, ACTION_L ); |
1753 | input.setInterval(300, ACTION_R ); |
1754 | SDL_EnableKeyRepeat(1,150); |
1755 | } |
1756 | |
1757 | void GMenu2X::applyRamTimings() { |
1758 | #ifdef TARGET_GP2X |
1759 | // 6 4 1 1 1 2 2 |
1760 | /* if (gp2x_mem!=0) { |
1761 | int tRC = 5, tRAS = 3, tWR = 0, tMRD = 0, tRFC = 0, tRP = 1, tRCD = 1; |
1762 | gp2x_memregs[0x3802>>1] = ((tMRD & 0xF) << 12) | ((tRFC & 0xF) << 8) | ((tRP & 0xF) << 4) | (tRCD & 0xF); |
1763 | gp2x_memregs[0x3804>>1] = ((tRC & 0xF) << 8) | ((tRAS & 0xF) << 4) | (tWR & 0xF); |
1764 | }*/ |
1765 | #endif |
1766 | } |
1767 | |
1768 | void GMenu2X::applyDefaultTimings() { |
1769 | #ifdef TARGET_GP2X |
1770 | // 8 16 3 8 8 8 8 |
1771 | /* if (gp2x_mem!=0) { |
1772 | int tRC = 7, tRAS = 15, tWR = 2, tMRD = 7, tRFC = 7, tRP = 7, tRCD = 7; |
1773 | gp2x_memregs[0x3802>>1] = ((tMRD & 0xF) << 12) | ((tRFC & 0xF) << 8) | ((tRP & 0xF) << 4) | (tRCD & 0xF); |
1774 | gp2x_memregs[0x3804>>1] = ((tRC & 0xF) << 8) | ((tRAS & 0xF) << 4) | (tWR & 0xF); |
1775 | }*/ |
1776 | #endif |
1777 | } |
1778 | |
1779 | |
1780 | |
1781 | void GMenu2X::setClock(unsigned mhz) { |
1782 | mhz = constrain(mhz, 30, confInt["maxClock"]); |
1783 | #ifdef TARGET_GP2X |
1784 | jz_cpuspeed(mhz); |
1785 | #endif |
1786 | } |
1787 | |
1788 | void GMenu2X::setGamma(int /*gamma*/) { |
1789 | #ifdef TARGET_GP2X |
1790 | /* float fgamma = (float)constrain(gamma,1,100)/10; |
1791 | fgamma = 1 / fgamma; |
1792 | MEM_REG[0x2880>>1]&=~(1<<12); |
1793 | MEM_REG[0x295C>>1]=0; |
1794 | |
1795 | for (int i=0; i<256; i++) { |
1796 | unsigned char g = (unsigned char)(255.0*pow(i/255.0,fgamma)); |
1797 | unsigned short s = (g<<8) | g; |
1798 | MEM_REG[0x295E>>1]= s; |
1799 | MEM_REG[0x295E>>1]= g; |
1800 | }*/ |
1801 | #endif |
1802 | } |
1803 | |
1804 | int GMenu2X::getVolume() { |
1805 | unsigned long mixer; |
1806 | int basevolume = -1; |
1807 | mixer = open("/dev/mixer", O_RDONLY); |
1808 | if(mixer) |
1809 | { |
1810 | if (ioctl(mixer, SOUND_MIXER_READ_VOLUME, &basevolume) == -1) { |
1811 | fprintf(stderr, "Failed opening mixer for read - VOLUME\n"); |
1812 | } |
1813 | close(mixer); |
1814 | if(basevolume != -1) |
1815 | return (basevolume>>8) & basevolume ; |
1816 | } |
1817 | return basevolume; |
1818 | } |
1819 | |
1820 | void GMenu2X::setVolume(int vol) { |
1821 | unsigned long mixer; |
1822 | int newvolume = vol; |
1823 | int oss_volume = newvolume | (newvolume << 8); // set volume for both channels |
1824 | mixer = open("/dev/mixer", O_WRONLY); |
1825 | if(mixer) |
1826 | { |
1827 | if (ioctl(mixer, SOUND_MIXER_WRITE_VOLUME, &oss_volume) == -1) { |
1828 | fprintf(stderr, "Failed opening mixer for write - VOLUME\n"); |
1829 | } |
1830 | close(mixer); |
1831 | } |
1832 | |
1833 | } |
1834 | |
1835 | void GMenu2X::setVolumeScaler(int scale) { |
1836 | scale = constrain(scale,0,MAX_VOLUME_SCALE_FACTOR); |
1837 | unsigned long soundDev = open("/dev/mixer", O_WRONLY); |
1838 | if (soundDev) { |
1839 | ioctl(soundDev, SOUND_MIXER_PRIVATE2, &scale); |
1840 | close(soundDev); |
1841 | } |
1842 | } |
1843 | |
1844 | int GMenu2X::getVolumeScaler() { |
1845 | int currentscalefactor = -1; |
1846 | unsigned long soundDev = open("/dev/mixer", O_RDONLY); |
1847 | if (soundDev) { |
1848 | ioctl(soundDev, SOUND_MIXER_PRIVATE1, ¤tscalefactor); |
1849 | close(soundDev); |
1850 | } |
1851 | return currentscalefactor; |
1852 | } |
1853 | |
1854 | const string &GMenu2X::getExePath() { |
1855 | if (path.empty()) { |
1856 | char buf[255]; |
1857 | memset(buf, 0, 255); |
1858 | int l = readlink("/proc/self/exe", buf, 255); |
1859 | |
1860 | path = buf; |
1861 | path = path.substr(0,l); |
1862 | l = path.rfind("/"); |
1863 | path = path.substr(0,l+1); |
1864 | } |
1865 | return path; |
1866 | } |
1867 | |
1868 | string GMenu2X::getDiskFree() { |
1869 | stringstream ss; |
1870 | string df = ""; |
1871 | struct statvfs b; |
1872 | |
1873 | int ret = statvfs(CARD_ROOT, &b); |
1874 | if (ret==0) { |
1875 | // Make sure that the multiplication happens in 64 bits. |
1876 | unsigned long long free = |
1877 | ((unsigned long long)b.f_bfree * b.f_bsize) / 1048576; |
1878 | unsigned long long total = |
1879 | ((unsigned long long)b.f_blocks * b.f_frsize) / 1048576; |
1880 | ss << free << "/" << total << "MB"; |
1881 | ss >> df; |
1882 | } else cout << "\033[0;34mGMENU2X:\033[0;31m statvfs failed with error '" << strerror(errno) << "'\033[0m" << endl; |
1883 | return df; |
1884 | } |
1885 | |
1886 | int GMenu2X::drawButton(Button *btn, int x, int y) { |
1887 | if (y<0) y = resY+y; |
1888 | btn->setPosition(x, y-7); |
1889 | btn->paint(); |
1890 | return x+btn->getRect().w+6; |
1891 | } |
1892 | |
1893 | int GMenu2X::drawButton(Surface *s, const string &btn, const string &text, int x, int y) { |
1894 | if (y<0) y = resY+y; |
1895 | SDL_Rect re = {x, y-7, 0, 16}; |
1896 | if (sc.skinRes("imgs/buttons/"+btn+".png") != NULL) { |
1897 | sc["imgs/buttons/"+btn+".png"]->blit(s, x, y-7); |
1898 | re.w = sc["imgs/buttons/"+btn+".png"]->raw->w+3; |
1899 | s->write(font, text, x+re.w, y, SFontHAlignLeft, SFontVAlignMiddle); |
1900 | re.w += font->getTextWidth(text); |
1901 | } |
1902 | return x+re.w+6; |
1903 | } |
1904 | |
1905 | int GMenu2X::drawButtonRight(Surface *s, const string &btn, const string &text, int x, int y) { |
1906 | if (y<0) y = resY+y; |
1907 | if (sc.skinRes("imgs/buttons/"+btn+".png") != NULL) { |
1908 | x -= 16; |
1909 | sc["imgs/buttons/"+btn+".png"]->blit(s, x, y-7); |
1910 | x -= 3; |
1911 | s->write(font, text, x, y, SFontHAlignRight, SFontVAlignMiddle); |
1912 | return x-6-font->getTextWidth(text); |
1913 | } |
1914 | return x-6; |
1915 | } |
1916 | |
1917 | void GMenu2X::drawScrollBar(uint pagesize, uint totalsize, uint pagepos, uint top, uint height) { |
1918 | if (totalsize<=pagesize) return; |
1919 | |
1920 | s->rectangle(resX-8, top, 7, height, skinConfColors[COLOR_SELECTION_BG]); |
1921 | |
1922 | //internal bar total height = height-2 |
1923 | //bar size |
1924 | uint bs = (height-2) * pagesize / totalsize; |
1925 | //bar y position |
1926 | uint by = (height-2) * pagepos / totalsize; |
1927 | by = top+2+by; |
1928 | if (by+bs>top+height-2) by = top+height-2-bs; |
1929 | |
1930 | |
1931 | s->box(resX-6, by, 3, bs, skinConfColors[COLOR_SELECTION_BG]); |
1932 | } |
1933 | |
1934 | void GMenu2X::drawTopBar(Surface *s) { |
1935 | if (s==NULL) s = this->s; |
1936 | |
1937 | Surface *bar = sc.skinRes("imgs/topbar.png"); |
1938 | if (bar != NULL) |
1939 | bar->blit(s, 0, 0); |
1940 | else |
1941 | s->box(0, 0, resX, skinConfInt["topBarHeight"], |
1942 | skinConfColors[COLOR_TOP_BAR_BG]); |
1943 | } |
1944 | |
1945 | void GMenu2X::drawBottomBar(Surface *s) { |
1946 | if (s==NULL) s = this->s; |
1947 | |
1948 | Surface *bar = sc.skinRes("imgs/bottombar.png"); |
1949 | if (bar != NULL) |
1950 | bar->blit(s, 0, resY-bar->raw->h); |
1951 | else |
1952 | s->box(0, resY-20, resX, 20, skinConfColors[COLOR_BOTTOM_BAR_BG]); |
1953 | } |
1954 |
Branches:
install_locations
master
opkrun
packages