1
0
mirror of git://projects.qi-hardware.com/gmenu2x.git synced 2024-08-19 06:42:25 +03:00
gmenu2x/src/gmenu2x.cpp
kyak 6646525731 Zero-pad hex values when saving config
writeSkinConfig() had a very naughty bug when RGBA values were written
to config file unpadded. This lead to a problem that, for example,
0x00000080 was written as 0x00080 in config file (Somehow gmenu2x
reads and re-saves config on selection). This, in turn, led
to problem when reading skin config file in strtorgba function,
because it parses the color string in token of two symbols
(substr(0,2) and etc).
2011-06-06 11:38:26 +04:00

2041 lines
64 KiB
C++

/***************************************************************************
* Copyright (C) 2006 by Massimiliano Torromeo *
* massimiliano.torromeo@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This 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, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <SDL.h>
#include <SDL_gfxPrimitives.h>
#include <signal.h>
#include <sys/statvfs.h>
#include <errno.h>
#include "gp2x.h"
#include <sys/fcntl.h> //for battery
//for browsing the filesystem
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
//for soundcard
#include <sys/ioctl.h>
#include <linux/soundcard.h>
#include "linkapp.h"
#include "linkaction.h"
#include "menu.h"
#include "asfont.h"
#include "surface.h"
#include "filedialog.h"
#include "gmenu2x.h"
#include "filelister.h"
#include "iconbutton.h"
#include "messagebox.h"
#include "inputdialog.h"
#include "settingsdialog.h"
#include "wallpaperdialog.h"
#include "textdialog.h"
#include "menusettingint.h"
#include "menusettingbool.h"
#include "menusettingrgba.h"
#include "menusettingstring.h"
#include "menusettingmultistring.h"
#include "menusettingfile.h"
#include "menusettingimage.h"
#include "menusettingdir.h"
#include "debug.h"
#include <sys/mman.h>
#ifdef TARGET_PANDORA
//#include <pnd_container.h>
//#include <pnd_conf.h>
//#include <pnd_discovery.h>
#endif
#ifdef _CARD_ROOT
const char *CARD_ROOT = _CARD_ROOT;
#else
const char *CARD_ROOT = "/card/"; //Note: Add a trailing /!
#endif
const int CARD_ROOT_LEN = 5;
static GMenu2X *app;
using namespace std;
using namespace fastdelegate;
// Note: Keep this in sync with the enum!
static const char *colorNames[NUM_COLORS] = {
"topBarBg",
"bottomBarBg",
"selectionBg",
"messageBoxBg",
"messageBoxBorder",
"messageBoxSelection",
};
static enum color stringToColor(const string &name)
{
for (unsigned int i = 0; i < NUM_COLORS; i++) {
if (strcmp(colorNames[i], name.c_str()) == 0) {
return (enum color)i;
}
}
return (enum color)-1;
}
static const char *colorToString(enum color c)
{
return colorNames[c];
}
static void quit_all(int err) {
delete app;
exit(err);
}
int main(int /*argc*/, char * /*argv*/[]) {
INFO("----\nGMenu2X starting: If you read this message in the logs, check http://gmenu2x.sourceforge.net/page/Troubleshooting for a solution\n----\n");
signal(SIGINT, &quit_all);
signal(SIGSEGV,&quit_all);
signal(SIGTERM,&quit_all);
app = new GMenu2X();
DEBUG("Starting main()\n");
app->main();
return 0;
}
void GMenu2X::gp2x_init() {
#ifdef TARGET_GP2X
/* gp2x_mem = open("/dev/mem", O_RDWR);
gp2x_memregs=(unsigned short *)mmap(0, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, gp2x_mem, 0xc0000000);
MEM_REG=&gp2x_memregs[0];
if (f200) {
//if wm97xx fails to open, set f200 to false to prevent any further access to the touchscreen
f200 = ts.init();
}*/
batteryHandle = fopen("/sys/class/power_supply/battery/capacity", "r");
usbHandle = fopen("/sys/class/power_supply/USB/online", "r");
acHandle = fopen("/sys/class/power_supply/ac/online", "r");
backlightHandle =
fopen("/sys/class/backlight/gpm940b0-bl/brightness", "w+");
#endif
}
void GMenu2X::gp2x_deinit() {
#ifdef TARGET_GP2X
/* if (gp2x_mem!=0) {
gp2x_memregs[0x28DA>>1]=0x4AB;
gp2x_memregs[0x290C>>1]=640;
close(gp2x_mem);
}
if (f200) ts.deinit();*/
#endif
if (batteryHandle) fclose(batteryHandle);
if (backlightHandle) fclose(backlightHandle);
if (usbHandle) fclose(usbHandle);
if (acHandle) fclose(acHandle);
}
void GMenu2X::gp2x_tvout_on(bool /*pal*/) {
#ifdef TARGET_GP2X
/* if (gp2x_mem!=0) {
// Ioctl_Dummy_t *msg;
// int TVHandle = ioctl(SDL_videofd, FBMMSP2CTRL, msg);
if (cx25874!=0) gp2x_tvout_off();
//if tv-out is enabled without cx25874 open, stop
//if (gp2x_memregs[0x2800>>1]&0x100) return;
cx25874 = open("/dev/cx25874",O_RDWR);
ioctl(cx25874, _IOW('v', 0x02, unsigned char), pal ? 4 : 3);
gp2x_memregs[0x2906>>1]=512;
gp2x_memregs[0x28E4>>1]=gp2x_memregs[0x290C>>1];
gp2x_memregs[0x28E8>>1]=239;
}*/
#endif
}
void GMenu2X::gp2x_tvout_off() {
#ifdef TARGET_GP2X
/* if (gp2x_mem!=0) {
close(cx25874);
cx25874 = 0;
gp2x_memregs[0x2906>>1]=1024;
}*/
#endif
}
GMenu2X::GMenu2X() {
//Detect firmware version and type
if (fileExists("/etc/open2x")) {
fwType = "open2x";
fwVersion = "";
} else {
fwType = "gph";
fwVersion = "";
}
#ifdef TARGET_GP2X
f200 = fileExists("/dev/touchscreen/wm97xx");
#else
f200 = true;
#endif
//open2x
savedVolumeMode = 0;
volumeMode = VOLUME_MODE_NORMAL;
volumeScalerNormal = VOLUME_SCALER_NORMAL;
volumeScalerPhones = VOLUME_SCALER_PHONES;
o2x_usb_net_on_boot = false;
o2x_usb_net_ip = "";
o2x_ftp_on_boot = false;
o2x_telnet_on_boot = false;
o2x_gp2xjoy_on_boot = false;
o2x_usb_host_on_boot = false;
o2x_usb_hid_on_boot = false;
o2x_usb_storage_on_boot = false;
usbnet = samba = inet = web = false;
useSelectionPng = false;
//load config data
readConfig();
if (fwType=="open2x") {
readConfigOpen2x();
// VOLUME MODIFIER
switch(volumeMode) {
case VOLUME_MODE_MUTE: setVolumeScaler(VOLUME_SCALER_MUTE); break;
case VOLUME_MODE_PHONES: setVolumeScaler(volumeScalerPhones); break;
case VOLUME_MODE_NORMAL: setVolumeScaler(volumeScalerNormal); break;
}
} else
readCommonIni();
halfX = resX/2;
halfY = resY/2;
bottomBarIconY = resY-18;
bottomBarTextY = resY-10;
path = "";
getExePath();
batteryHandle = 0;
backlightHandle = 0;
usbHandle = 0;
acHandle = 0;
#ifdef TARGET_GP2X
gp2x_mem = 0;
cx25874 = 0;
gp2x_init();
//Fix tv-out
/* if (gp2x_mem!=0) {
if (gp2x_memregs[0x2800>>1]&0x100) {
gp2x_memregs[0x2906>>1]=512;
//gp2x_memregs[0x290C>>1]=640;
gp2x_memregs[0x28E4>>1]=gp2x_memregs[0x290C>>1];
}
gp2x_memregs[0x28E8>>1]=239;
}*/
#endif
//Screen
if( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_JOYSTICK|SDL_INIT_TIMER)<0 ) {
ERROR("Could not initialize SDL: %s\n", SDL_GetError());
quit();
}
s = Surface::openOutputSurface(resX, resY, confInt["videoBpp"]);
bg = NULL;
font = NULL;
menu = NULL;
setSkin(confStr["skin"], false);
initMenu();
if (!fileExists(confStr["wallpaper"])) {
DEBUG("Searching wallpaper\n");
FileLister fl("skins/"+confStr["skin"]+"/wallpapers",false,true);
fl.setFilter(".png,.jpg,.jpeg,.bmp");
fl.browse();
if (fl.getFiles().size()<=0 && confStr["skin"] != "Default")
fl.setPath("skins/Default/wallpapers",true);
if (fl.getFiles().size()>0)
confStr["wallpaper"] = fl.getPath()+fl.getFiles()[0];
}
initBG();
input.init(path+"input.conf");
PowerSaver::getInstance()->setScreenTimeout( confInt["backlightTimeout"] );
setInputSpeed();
initServices();
setBacklight(confInt["backlight"]);
setVolume(confInt["globalVolume"]);
applyDefaultTimings();
setClock(confInt["menuClock"]);
//recover last session
readTmp();
if (lastSelectorElement>-1 && menu->selLinkApp()!=NULL && (!menu->selLinkApp()->getSelectorDir().empty() || !lastSelectorDir.empty()))
menu->selLinkApp()->selector(lastSelectorElement,lastSelectorDir);
}
GMenu2X::~GMenu2X() {
writeConfig();
if (fwType=="open2x") writeConfigOpen2x();
quit();
free(menu);
free(s);
free(font);
}
void GMenu2X::quit() {
fflush(NULL);
sc.clear();
free(s);
SDL_Quit();
#ifdef TARGET_GP2X
/* if (gp2x_mem!=0) {
//Fix tv-out
if (gp2x_memregs[0x2800>>1]&0x100) {
gp2x_memregs[0x2906>>1]=512;
gp2x_memregs[0x28E4>>1]=gp2x_memregs[0x290C>>1];
}
gp2x_deinit();
}*/
#endif
}
void GMenu2X::initBG() {
sc.del("bgmain");
// Load wallpaper.
free(bg);
bg = Surface::loadImage(confStr["wallpaper"]);
if (!bg) {
bg = Surface::emptySurface(resX, resY);
}
drawTopBar(bg);
drawBottomBar(bg);
Surface *bgmain = new Surface(bg);
sc.add(bgmain,"bgmain");
Surface *sd = Surface::loadImage("imgs/sd.png", confStr["skin"]);
if (sd) sd->blit(bgmain, 3, bottomBarIconY);
string df = getDiskFree();
bgmain->write(font, df, 22, bottomBarTextY, ASFont::HAlignLeft, ASFont::VAlignMiddle);
free(sd);
Surface *volume = Surface::loadImage("imgs/volume.png", confStr["skin"]);
volumeX = 27+font->getTextWidth(df);
if (volume) volume->blit(bgmain, volumeX, bottomBarIconY);
volumeX += 19;
free(volume);
Surface *cpu = Surface::loadImage("imgs/cpu.png", confStr["skin"]);
cpuX = volumeX+font->getTextWidth("100")+5;
if (cpu) cpu->blit(bgmain, cpuX, bottomBarIconY);
cpuX += 19;
manualX = cpuX+font->getTextWidth("300Mhz")+5;
free(cpu);
int serviceX = resX-38;
if (usbnet) {
if (web) {
Surface *webserver = Surface::loadImage(
"imgs/webserver.png", confStr["skin"]);
if (webserver) webserver->blit(bgmain, serviceX, bottomBarIconY);
serviceX -= 19;
free(webserver);
}
if (samba) {
Surface *sambaS = Surface::loadImage(
"imgs/samba.png", confStr["skin"]);
if (sambaS) sambaS->blit(bgmain, serviceX, bottomBarIconY);
serviceX -= 19;
free(sambaS);
}
if (inet) {
Surface *inetS = Surface::loadImage("imgs/inet.png", confStr["skin"]);
if (inetS) inetS->blit(bgmain, serviceX, bottomBarIconY);
serviceX -= 19;
free(inetS);
}
}
bgmain->convertToDisplayFormat();
}
void GMenu2X::initFont() {
if (font != NULL) {
free(font);
font = NULL;
}
string fontFile = sc.getSkinFilePath("imgs/font.png");
if (fontFile.empty()) {
ERROR("Font png not found!\n");
quit();
exit(-1);
}
font = new ASFont(fontFile);
}
void GMenu2X::initMenu() {
//Menu structure handler
menu = new Menu(this);
for (uint i=0; i<menu->getSections().size(); i++) {
//Add virtual links in the applications section
if (menu->getSections()[i]=="applications") {
menu->addActionLink(i,"Explorer",MakeDelegate(this,&GMenu2X::explorer),tr["Launch an application"],"skin:icons/explorer.png");
}
//Add virtual links in the setting section
else if (menu->getSections()[i]=="settings") {
menu->addActionLink(i,"GMenu2X",MakeDelegate(this,&GMenu2X::options),tr["Configure GMenu2X's options"],"skin:icons/configure.png");
if (fwType=="open2x")
menu->addActionLink(i,"Open2x",MakeDelegate(this,&GMenu2X::settingsOpen2x),tr["Configure Open2x system settings"],"skin:icons/o2xconfigure.png");
menu->addActionLink(i,tr["Skin"],MakeDelegate(this,&GMenu2X::skinMenu),tr["Configure skin"],"skin:icons/skin.png");
menu->addActionLink(i,tr["Wallpaper"],MakeDelegate(this,&GMenu2X::changeWallpaper),tr["Change GMenu2X wallpaper"],"skin:icons/wallpaper.png");
#ifdef TARGET_GP2X
/* menu->addActionLink(i,"TV",MakeDelegate(this,&GMenu2X::toggleTvOut),tr["Activate/deactivate tv-out"],"skin:icons/tv.png");
menu->addActionLink(i,"USB Sd",MakeDelegate(this,&GMenu2X::activateSdUsb),tr["Activate Usb on SD"],"skin:icons/usb.png");
if (fwType=="gph" && !f200)
menu->addActionLink(i,"USB Nand",MakeDelegate(this,&GMenu2X::activateNandUsb),tr["Activate Usb on Nand"],"skin:icons/usb.png");
//menu->addActionLink(i,"USB Root",MakeDelegate(this,&GMenu2X::activateRootUsb),tr["Activate Usb on the root of the Gp2x Filesystem"],"skin:icons/usb.png");*/
#endif
if (fileExists(path+"log.txt"))
menu->addActionLink(i,tr["Log Viewer"],MakeDelegate(this,&GMenu2X::viewLog),tr["Displays last launched program's output"],"skin:icons/ebook.png");
menu->addActionLink(i,tr["About"],MakeDelegate(this,&GMenu2X::about),tr["Info about GMenu2X"],"skin:icons/about.png");
}
}
menu->setSectionIndex(confInt["section"]);
menu->setLinkIndex(confInt["link"]);
menu->loadIcons();
//DEBUG
//menu->addLink( CARD_ROOT, "sample.pxml", "applications" );
}
void GMenu2X::about() {
vector<string> text;
split(text,"GMenu2X is developed by Massimiliano \"Ryo\" Torromeo, and is released under the GPL-v2 license.\n\
Website: http://gmenu2x.sourceforge.net\n\
E-Mail & PayPal account: massimiliano.torromeo@gmail.com\n\
\n\
Thanks goes to...\n\
\n\
Contributors\n\
----\n\
NoidZ for his gp2x' buttons graphics\n\
\n\
Beta testers\n\
----\n\
Goemon4, PokeParadox, PSyMastR and Tripmonkey_uk\n\
\n\
Translators\n\
----\n\
English & Italian by me\n\
French by Yodaz\n\
Danish by claus\n\
Dutch by superfly\n\
Spanish by pedator\n\
Portuguese (Portugal) by NightShadow\n\
Slovak by Jozef\n\
Swedish by Esslan and Micket\n\
German by fusion_power, johnnysnet and Waldteufel\n\
Finnish by Jontte and Atte\n\
Norwegian by cowai\n\
Russian by XaMMaX90\n\
\n\
Donors\n\
----\n\
EvilDragon (www.gp2x.de)\n\
Tecnologie Creative (www.tecnologiecreative.it)\n\
TelcoLou\n\
gaterooze\n\
deepmenace\n\
superfly\n\
halo9\n\
sbock\n\
b._.o._.b\n\
Jacopastorius\n\
lorystorm90\n\
and all the anonymous donors...\n\
(If I missed to list you or if you want to be removed, contact me.)","\n");
TextDialog td(this, "GMenu2X", tr.translate("Version $1 (Build date: $2)","0.10-test4",__DATE__,NULL), "icons/about.png", &text);
td.exec();
}
void GMenu2X::viewLog() {
string logfile = path+"log.txt";
if (fileExists(logfile)) {
ifstream inf(logfile.c_str(), ios_base::in);
if (inf.is_open()) {
vector<string> log;
string line;
while (getline(inf, line, '\n'))
log.push_back(line);
inf.close();
TextDialog td(this, tr["Log Viewer"], tr["Displays last launched program's output"], "icons/ebook.png", &log);
td.exec();
MessageBox mb(this, tr["Do you want to delete the log file?"], "icons/ebook.png");
mb.setButton(ACCEPT, tr["Yes"]);
mb.setButton(CLEAR, tr["No"]);
if (mb.exec() == ACCEPT) {
ledOn();
unlink(logfile.c_str());
sync();
menu->deleteSelectedLink();
ledOff();
}
}
}
}
void GMenu2X::readConfig() {
string conffile = path+"gmenu2x.conf";
if (fileExists(conffile)) {
ifstream inf(conffile.c_str(), ios_base::in);
if (inf.is_open()) {
string line;
while (getline(inf, line, '\n')) {
string::size_type pos = line.find("=");
string name = trim(line.substr(0,pos));
string value = trim(line.substr(pos+1,line.length()));
if (value.length()>1 && value.at(0)=='"' && value.at(value.length()-1)=='"')
confStr[name] = value.substr(1,value.length()-2);
else
confInt[name] = atoi(value.c_str());
}
inf.close();
}
}
if (!confStr["lang"].empty()) tr.setLang(confStr["lang"]);
if (!confStr["wallpaper"].empty() && !fileExists(confStr["wallpaper"])) confStr["wallpaper"] = "";
if (confStr["skin"].empty() || !fileExists("skins/"+confStr["skin"])) confStr["skin"] = "Default";
evalIntConf( &confInt["outputLogs"], 0, 0,1 );
evalIntConf( &confInt["maxClock"], 430, 30, 500 );
evalIntConf( &confInt["menuClock"], 200, 30, 430 );
evalIntConf( &confInt["globalVolume"], 67, 0,100 );
evalIntConf( &confInt["backlightTimeout"], 15, 0,120 );
evalIntConf( &confInt["backlight"], 100, 5,100 );
evalIntConf( &confInt["videoBpp"], 32,32,32 ); // 8,16
if (confStr["tvoutEncoding"] != "PAL") confStr["tvoutEncoding"] = "NTSC";
resX = constrain( confInt["resolutionX"], 320,1920 );
resY = constrain( confInt["resolutionY"], 240,1200 );
}
void GMenu2X::writeConfig() {
ledOn();
string conffile = path+"gmenu2x.conf";
ofstream inf(conffile.c_str());
if (inf.is_open()) {
ConfStrHash::iterator endS = confStr.end();
for(ConfStrHash::iterator curr = confStr.begin(); curr != endS; curr++)
inf << curr->first << "=\"" << curr->second << "\"" << endl;
ConfIntHash::iterator endI = confInt.end();
for(ConfIntHash::iterator curr = confInt.begin(); curr != endI; curr++)
inf << curr->first << "=" << curr->second << endl;
inf.close();
sync();
}
ledOff();
}
void GMenu2X::readConfigOpen2x() {
string conffile = "/etc/config/open2x.conf";
if (fileExists(conffile)) {
ifstream inf(conffile.c_str(), ios_base::in);
if (inf.is_open()) {
string line;
while (getline(inf, line, '\n')) {
string::size_type pos = line.find("=");
string name = trim(line.substr(0,pos));
string value = trim(line.substr(pos+1,line.length()));
if (name=="USB_NET_ON_BOOT") o2x_usb_net_on_boot = value == "y" ? true : false;
else if (name=="USB_NET_IP") o2x_usb_net_ip = value;
else if (name=="TELNET_ON_BOOT") o2x_telnet_on_boot = value == "y" ? true : false;
else if (name=="FTP_ON_BOOT") o2x_ftp_on_boot = value == "y" ? true : false;
else if (name=="GP2XJOY_ON_BOOT") o2x_gp2xjoy_on_boot = value == "y" ? true : false;
else if (name=="USB_HOST_ON_BOOT") o2x_usb_host_on_boot = value == "y" ? true : false;
else if (name=="USB_HID_ON_BOOT") o2x_usb_hid_on_boot = value == "y" ? true : false;
else if (name=="USB_STORAGE_ON_BOOT") o2x_usb_storage_on_boot = value == "y" ? true : false;
else if (name=="VOLUME_MODE") volumeMode = savedVolumeMode = constrain( atoi(value.c_str()), 0, 2);
else if (name=="PHONES_VALUE") volumeScalerPhones = constrain( atoi(value.c_str()), 0, 100);
else if (name=="NORMAL_VALUE") volumeScalerNormal = constrain( atoi(value.c_str()), 0, 150);
}
inf.close();
}
}
}
void GMenu2X::writeConfigOpen2x() {
ledOn();
string conffile = "/etc/config/open2x.conf";
ofstream inf(conffile.c_str());
if (inf.is_open()) {
inf << "USB_NET_ON_BOOT=" << ( o2x_usb_net_on_boot ? "y" : "n" ) << endl;
inf << "USB_NET_IP=" << o2x_usb_net_ip << endl;
inf << "TELNET_ON_BOOT=" << ( o2x_telnet_on_boot ? "y" : "n" ) << endl;
inf << "FTP_ON_BOOT=" << ( o2x_ftp_on_boot ? "y" : "n" ) << endl;
inf << "GP2XJOY_ON_BOOT=" << ( o2x_gp2xjoy_on_boot ? "y" : "n" ) << endl;
inf << "USB_HOST_ON_BOOT=" << ( (o2x_usb_host_on_boot || o2x_usb_hid_on_boot || o2x_usb_storage_on_boot) ? "y" : "n" ) << endl;
inf << "USB_HID_ON_BOOT=" << ( o2x_usb_hid_on_boot ? "y" : "n" ) << endl;
inf << "USB_STORAGE_ON_BOOT=" << ( o2x_usb_storage_on_boot ? "y" : "n" ) << endl;
inf << "VOLUME_MODE=" << volumeMode << endl;
if (volumeScalerPhones != VOLUME_SCALER_PHONES) inf << "PHONES_VALUE=" << volumeScalerPhones << endl;
if (volumeScalerNormal != VOLUME_SCALER_NORMAL) inf << "NORMAL_VALUE=" << volumeScalerNormal << endl;
inf.close();
sync();
}
ledOff();
}
void GMenu2X::writeSkinConfig() {
ledOn();
string conffile = path+"skins/"+confStr["skin"]+"/skin.conf";
ofstream inf(conffile.c_str());
if (inf.is_open()) {
ConfStrHash::iterator endS = skinConfStr.end();
for(ConfStrHash::iterator curr = skinConfStr.begin(); curr != endS; curr++)
inf << curr->first << "=\"" << curr->second << "\"" << endl;
ConfIntHash::iterator endI = skinConfInt.end();
for(ConfIntHash::iterator curr = skinConfInt.begin(); curr != endI; curr++)
inf << curr->first << "=" << curr->second << endl;
int i;
for (i = 0; i < NUM_COLORS; ++i) {
inf << colorToString((enum color)i) << "=#";
inf.width(2); inf.fill('0');
inf << right << hex << skinConfColors[i].r;
inf.width(2); inf.fill('0');
inf << right << hex << skinConfColors[i].g;
inf.width(2); inf.fill('0');
inf << right << hex << skinConfColors[i].b;
inf.width(2); inf.fill('0');
inf << right << hex << skinConfColors[i].a << endl;
}
inf.close();
sync();
}
ledOff();
}
void GMenu2X::readCommonIni() {
if (fileExists("/usr/gp2x/common.ini")) {
ifstream inf("/usr/gp2x/common.ini", ios_base::in);
if (inf.is_open()) {
string line;
string section = "";
while (getline(inf, line, '\n')) {
line = trim(line);
if (line[0]=='[' && line[line.length()-1]==']') {
section = line.substr(1,line.length()-2);
} else {
string::size_type pos = line.find("=");
string name = trim(line.substr(0,pos));
string value = trim(line.substr(pos+1,line.length()));
if (section=="usbnet") {
if (name=="enable")
usbnet = value=="true" ? true : false;
else if (name=="ip")
ip = value;
} else if (section=="server") {
if (name=="inet")
inet = value=="true" ? true : false;
else if (name=="samba")
samba = value=="true" ? true : false;
else if (name=="web")
web = value=="true" ? true : false;
}
}
}
inf.close();
}
}
}
void GMenu2X::writeCommonIni() {}
void GMenu2X::readTmp() {
lastSelectorElement = -1;
if (fileExists("/tmp/gmenu2x.tmp")) {
ifstream inf("/tmp/gmenu2x.tmp", ios_base::in);
if (inf.is_open()) {
string line;
string section = "";
while (getline(inf, line, '\n')) {
string::size_type pos = line.find("=");
string name = trim(line.substr(0,pos));
string value = trim(line.substr(pos+1,line.length()));
if (name=="section")
menu->setSectionIndex(atoi(value.c_str()));
else if (name=="link")
menu->setLinkIndex(atoi(value.c_str()));
else if (name=="selectorelem")
lastSelectorElement = atoi(value.c_str());
else if (name=="selectordir")
lastSelectorDir = value;
}
inf.close();
}
}
}
void GMenu2X::writeTmp(int selelem, const string &selectordir) {
string conffile = "/tmp/gmenu2x.tmp";
ofstream inf(conffile.c_str());
if (inf.is_open()) {
inf << "section=" << menu->selSectionIndex() << endl;
inf << "link=" << menu->selLinkIndex() << endl;
if (selelem>-1)
inf << "selectorelem=" << selelem << endl;
if (selectordir!="")
inf << "selectordir=" << selectordir << endl;
inf.close();
sync();
}
}
void GMenu2X::initServices() {
#ifdef TARGET_GP2X
/* if (usbnet) {
string services = "scripts/services.sh "+ip+" "+(inet?"on":"off")+" "+(samba?"on":"off")+" "+(web?"on":"off")+" &";
system(services.c_str());
}*/
#endif
}
void GMenu2X::ledOn() {
#ifdef TARGET_GP2X
// if (gp2x_mem!=0 && !f200) gp2x_memregs[0x106E >> 1] ^= 16;
//SDL_SYS_JoystickGp2xSys(joy.joystick, BATT_LED_ON);
#endif
}
void GMenu2X::ledOff() {
#ifdef TARGET_GP2X
// if (gp2x_mem!=0 && !f200) gp2x_memregs[0x106E >> 1] ^= 16;
//SDL_SYS_JoystickGp2xSys(joy.joystick, BATT_LED_OFF);
#endif
}
void GMenu2X::setBacklight(int val)
{
if (backlightHandle) {
fprintf(backlightHandle, "%d", (val * 255) / 100);
fflush(backlightHandle);
rewind(backlightHandle);
}
}
int GMenu2X::getBackLight()
{
int val = 255;
if (backlightHandle) {
fscanf(backlightHandle, "%d", &val);
rewind(backlightHandle);
val = (val * 100) / 255;
if (val < 0) val = 0; else if (val > 100) val = 100;
}
return val;
}
void GMenu2X::main() {
uint linksPerPage = linkColumns*linkRows;
int linkSpacingX = (resX-10 - linkColumns*skinConfInt["linkWidth"])/linkColumns;
int linkSpacingY = (resY-35 - skinConfInt["topBarHeight"] - linkRows*skinConfInt["linkHeight"])/linkRows;
uint sectionLinkPadding = (skinConfInt["topBarHeight"] - 32 - font->getLineHeight()) / 3;
bool quit = false;
int x,y, offset = menu->sectionLinks()->size()>linksPerPage ? 2 : 6, helpBoxHeight = fwType=="open2x" ? 154 : 139;
uint i;
long tickBattery = -60000, tickNow;
string batteryIcon = "imgs/battery/0.png";
stringstream ss;
uint sectionsCoordX = 24;
SDL_Rect re = {0,0,0,0};
bool helpDisplayed = false;
#ifdef WITH_DEBUG
//framerate
long tickFPS = SDL_GetTicks();
int drawn_frames = 0;
string fps = "";
#endif
IconButton btnContextMenu(this,"skin:imgs/menu.png");
btnContextMenu.setPosition(resX-38, bottomBarIconY);
btnContextMenu.setAction(MakeDelegate(this, &GMenu2X::contextMenu));
if (!fileExists(CARD_ROOT))
CARD_ROOT = "/";
while (!quit) {
tickNow = SDL_GetTicks();
//Background
sc["bgmain"]->blit(s,0,0);
//Sections
sectionsCoordX = halfX - (constrain((uint)menu->getSections().size(), 0 , linkColumns) * skinConfInt["linkWidth"]) / 2;
if (menu->firstDispSection()>0)
sc.skinRes("imgs/l_enabled.png")->blit(s,0,0);
else
sc.skinRes("imgs/l_disabled.png")->blit(s,0,0);
if (menu->firstDispSection()+linkColumns<menu->getSections().size())
sc.skinRes("imgs/r_enabled.png")->blit(s,resX-10,0);
else
sc.skinRes("imgs/r_disabled.png")->blit(s,resX-10,0);
for (i=menu->firstDispSection(); i<menu->getSections().size() && i<menu->firstDispSection()+linkColumns; i++) {
string sectionIcon = "skin:sections/"+menu->getSections()[i]+".png";
x = (i-menu->firstDispSection())*skinConfInt["linkWidth"]+sectionsCoordX;
if (menu->selSectionIndex()==(int)i)
s->box(x, 0, skinConfInt["linkWidth"],
skinConfInt["topBarHeight"], skinConfColors[COLOR_SELECTION_BG]);
x += skinConfInt["linkWidth"]/2;
if (sc.exists(sectionIcon))
sc[sectionIcon]->blit(s,x-16,sectionLinkPadding,32,32);
else
sc.skinRes("icons/section.png")->blit(s,x-16,sectionLinkPadding);
s->write( font, menu->getSections()[i], x, skinConfInt["topBarHeight"]-sectionLinkPadding, ASFont::HAlignCenter, ASFont::VAlignBottom );
}
//Links
s->setClipRect(offset,skinConfInt["topBarHeight"],resX-9,resY-74); //32*2+10
for (i=menu->firstDispRow()*linkColumns; i<(menu->firstDispRow()*linkColumns)+linksPerPage && i<menu->sectionLinks()->size(); i++) {
int ir = i-menu->firstDispRow()*linkColumns;
x = (ir%linkColumns)*(skinConfInt["linkWidth"]+linkSpacingX)+offset;
y = ir/linkColumns*(skinConfInt["linkHeight"]+linkSpacingY)+skinConfInt["topBarHeight"]+2;
menu->sectionLinks()->at(i)->setPosition(x,y);
if (i==(uint)menu->selLinkIndex())
menu->sectionLinks()->at(i)->paintHover();
menu->sectionLinks()->at(i)->paint();
}
s->clearClipRect();
drawScrollBar(linkRows,menu->sectionLinks()->size()/linkColumns + ((menu->sectionLinks()->size()%linkColumns==0) ? 0 : 1),menu->firstDispRow(),43,resY-81);
/*
switch(volumeMode) {
case VOLUME_MODE_MUTE: sc.skinRes("imgs/mute.png")->blit(s,279,bottomBarIconY); break;
case VOLUME_MODE_PHONES: sc.skinRes("imgs/phones.png")->blit(s,279,bottomBarIconY); break;
default: sc.skinRes("imgs/volume.png")->blit(s,279,bottomBarIconY); break;
}
*/
if (menu->selLink()!=NULL) {
s->write ( font, menu->selLink()->getDescription(), halfX, resY-19, ASFont::HAlignCenter, ASFont::VAlignBottom );
if (menu->selLinkApp()!=NULL) {
s->write ( font, menu->selLinkApp()->clockStr(confInt["maxClock"]), cpuX, bottomBarTextY, ASFont::HAlignLeft, ASFont::VAlignMiddle );
s->write ( font, menu->selLinkApp()->volumeStr(), volumeX, bottomBarTextY, ASFont::HAlignLeft, ASFont::VAlignMiddle );
//Manual indicator
if (!menu->selLinkApp()->getManual().empty())
sc.skinRes("imgs/manual.png")->blit(s,manualX,bottomBarIconY);
}
}
if (f200) {
btnContextMenu.paint();
}
//check battery status every 60 seconds
if (tickNow-tickBattery >= 60000) {
tickBattery = tickNow;
unsigned short battlevel = getBatteryLevel();
if (battlevel>5) {
batteryIcon = "imgs/battery/ac.png";
} else {
ss.clear();
ss << battlevel;
ss >> batteryIcon;
batteryIcon = "imgs/battery/"+batteryIcon+".png";
}
}
sc.skinRes(batteryIcon)->blit( s, resX-19, bottomBarIconY );
//s->write( font, tr[batstr.c_str()], 20, 170 );
//On Screen Help
if (helpDisplayed) {
s->box(10,50,300,143, skinConfColors[COLOR_MESSAGE_BOX_BG]);
s->rectangle( 12,52,296,helpBoxHeight,
skinConfColors[COLOR_MESSAGE_BOX_BORDER] );
s->write( font, tr["CONTROLS"], 20, 60 );
s->write( font, tr["B, Stick press: Launch link / Confirm action"], 20, 80 );
s->write( font, tr["L, R: Change section"], 20, 95 );
s->write( font, tr["Y: Show manual/readme"], 20, 110 );
s->write( font, tr["VOLUP, VOLDOWN: Change cpu clock"], 20, 125 );
s->write( font, tr["A+VOLUP, A+VOLDOWN: Change volume"], 20, 140 );
s->write( font, tr["SELECT: Show contextual menu"], 20, 155 );
s->write( font, tr["START: Show options menu"], 20, 170 );
if (fwType=="open2x") s->write( font, tr["X: Toggle speaker mode"], 20, 185 );
}
#ifdef WITH_DEBUG
//framerate
drawn_frames++;
if (tickNow-tickFPS>=1000) {
ss.clear();
ss << drawn_frames*(tickNow-tickFPS+1)/1000;
ss >> fps;
tickFPS = tickNow;
drawn_frames = 0;
}
s->write( font, fps+" FPS", resX-1,1 ,ASFont::HAlignRight );
#endif
s->flip();
//touchscreen
if (f200) {
ts.poll();
btnContextMenu.handleTS();
re.x = 0; re.y = 0; re.h = skinConfInt["topBarHeight"]; re.w = resX;
if (ts.pressed() && ts.inRect(re)) {
re.w = skinConfInt["linkWidth"];
sectionsCoordX = halfX - (constrain((uint)menu->getSections().size(), 0 , linkColumns) * skinConfInt["linkWidth"]) / 2;
for (i=menu->firstDispSection(); !ts.handled() && i<menu->getSections().size() && i<menu->firstDispSection()+linkColumns; i++) {
re.x = (i-menu->firstDispSection())*re.w+sectionsCoordX;
if (ts.inRect(re)) {
menu->setSectionIndex(i);
ts.setHandled();
}
}
}
i=menu->firstDispRow()*linkColumns;
while ( i<(menu->firstDispRow()*linkColumns)+linksPerPage && i<menu->sectionLinks()->size()) {
if (menu->sectionLinks()->at(i)->isPressed())
menu->setLinkIndex(i);
if (menu->sectionLinks()->at(i)->handleTS())
i = menu->sectionLinks()->size();
i++;
}
}
//#ifdef TARGET_GP2X
switch (input.waitForPressedButton()) {
case ACCEPT:
if (menu->selLink() != NULL) menu->selLink()->run();
break;
case CANCEL:
helpDisplayed = ! helpDisplayed;
break;
case SETTINGS:
options();
break;
case MENU:
contextMenu();
break;
case UP:
menu->linkUp();
break;
case DOWN:
menu->linkDown();
break;
case LEFT:
menu->linkLeft();
break;
case RIGHT:
menu->linkRight();
break;
case MANUAL:
menu->selLinkApp()->showManual();
break;
case ALTLEFT:
menu->decSectionIndex();
offset = menu->sectionLinks()->size()>linksPerPage ? 2 : 6;
break;
case ALTRIGHT:
menu->incSectionIndex();
offset = menu->sectionLinks()->size()>linksPerPage ? 2 : 6;
break;
default:
break;
}
/*
while (!input.update())
usleep(LOOP_DELAY);
if ( input[ACCEPT] && menu->selLink()!=NULL ) menu->selLink()->run();
else if ( input[SETTINGS] ) options();
else if ( input[MENU] ) contextMenu();
// VOLUME SCALE MODIFIER
else if ( fwType=="open2x" && input[CLEAR] ) {
volumeMode = constrain(volumeMode-1, -VOLUME_MODE_MUTE-1, VOLUME_MODE_NORMAL);
if(volumeMode < VOLUME_MODE_MUTE)
volumeMode = VOLUME_MODE_NORMAL;
switch(volumeMode) {
case VOLUME_MODE_MUTE: setVolumeScaler(VOLUME_SCALER_MUTE); break;
case VOLUME_MODE_PHONES: setVolumeScaler(volumeScalerPhones); break;
case VOLUME_MODE_NORMAL: setVolumeScaler(volumeScalerNormal); break;
}
setVolume(confInt["globalVolume"]);
}
// LINK NAVIGATION
else if ( input[ALTLEFTEFT ] ) menu->linkLeft();
else if ( input[ALTRIGHTIGHT] ) menu->linkRight();
else if ( input[UP ] ) menu->linkUp();
else if ( input[DOWN ] ) menu->linkDown();
// SELLINKAPP SELECTED
else if (menu->selLinkApp()!=NULL) {
if ( input[MANUAL] ) menu->selLinkApp()->showManual();
else if ( input.isActive(CANCEL) ) {
// VOLUME
if ( input[VOLDOWN] && !input.isActive(VOLUP) )
menu->selLinkApp()->setVolume( constrain(menu->selLinkApp()->volume()-1,0,100) );
if ( input[VOLUP] && !input.isActive(VOLDOWN) )
menu->selLinkApp()->setVolume( constrain(menu->selLinkApp()->volume()+1,0,100) );;
if ( input.isActive(VOLUP) && input.isActive(VOLDOWN) ) menu->selLinkApp()->setVolume(-1);
} else {
// CLOCK
if ( input[VOLDOWN] && !input.isActive(VOLUP) )
menu->selLinkApp()->setClock( constrain(menu->selLinkApp()->clock()-1,200,confInt["maxClock"]) );
if ( input[VOLUP] && !input.isActive(VOLDOWN) )
menu->selLinkApp()->setClock( constrain(menu->selLinkApp()->clock()+1,200,confInt["maxClock"]) );
if ( input.isActive(VOLUP) && input.isActive(VOLDOWN) ) menu->selLinkApp()->setClock(336);
}
}
if ( input.isActive(CANCEL) ) {
if (input.isActive(ALTLEFT) && input.isActive(ALTRIGHT))
saveScreenshot();
} else {
// SECTIONS
if ( input[ALTLEFT ] ) {
menu->decSectionIndex();
offset = menu->sectionLinks()->size()>linksPerPage ? 2 : 6;
} else if ( input[ALTRIGHT ] ) {
menu->incSectionIndex();
offset = menu->sectionLinks()->size()>linksPerPage ? 2 : 6;
}
}
*/
}
}
void GMenu2X::explorer() {
FileDialog fd(this,tr["Select an application"],".gpu,.dge,.sh,");
if (fd.exec()) {
if (confInt["saveSelection"] && (confInt["section"]!=menu->selSectionIndex() || confInt["link"]!=menu->selLinkIndex()))
writeConfig();
if (fwType == "open2x" && savedVolumeMode != volumeMode)
writeConfigOpen2x();
//string command = cmdclean(fd.path()+"/"+fd.file) + "; sync & cd "+cmdclean(getExePath())+"; exec ./gmenu2x";
string command = cmdclean(fd.getPath()+"/"+fd.getFile());
chdir(fd.getPath().c_str());
quit();
setClock(200);
execlp("/bin/sh","/bin/sh","-c",command.c_str(),NULL);
//if execution continues then something went wrong and as we already called SDL_Quit we cannot continue
//try relaunching gmenu2x
ERROR("Error executing selected application, re-launching gmenu2x\n");
chdir(getExePath().c_str());
execlp("./gmenu2x", "./gmenu2x", NULL);
}
}
void GMenu2X::options() {
int curMenuClock = confInt["menuClock"];
int curGlobalVolume = confInt["globalVolume"];
//G
int prevbacklight = confInt["backlight"];
bool showRootFolder = fileExists(CARD_ROOT);
FileLister fl_tr("translations");
fl_tr.browse();
fl_tr.insertFile("English");
string lang = tr.lang();
vector<string> encodings;
encodings.push_back("NTSC");
encodings.push_back("PAL");
SettingsDialog sd(this, input, ts, tr["Settings"]);
sd.addSetting(new MenuSettingMultiString(this,tr["Language"],tr["Set the language used by GMenu2X"],&lang,&fl_tr.getFiles()));
sd.addSetting(new MenuSettingBool(this,tr["Save last selection"],tr["Save the last selected link and section on exit"],&confInt["saveSelection"]));
sd.addSetting(new MenuSettingInt(this,tr["Clock for GMenu2X"],tr["Set the cpu working frequency when running GMenu2X"],&confInt["menuClock"],200,430));
sd.addSetting(new MenuSettingInt(this,tr["Maximum overclock"],tr["Set the maximum overclock for launching links"],&confInt["maxClock"],200,430));
sd.addSetting(new MenuSettingInt(this,tr["Global Volume"],tr["Set the default volume for the gp2x soundcard"],&confInt["globalVolume"],0,100));
sd.addSetting(new MenuSettingBool(this,tr["Output logs"],tr["Logs the output of the links. Use the Log Viewer to read them."],&confInt["outputLogs"]));
//G
sd.addSetting(new MenuSettingInt(this,tr["Lcd Backlight"],tr["Set dingoo's Lcd Backlight value (default: 100)"],&confInt["backlight"],5,100));
sd.addSetting(new MenuSettingInt(this,tr["Screen Timeout"],tr["Set screen's backlight timeout in seconds"],&confInt["backlightTimeout"],0,120));
// sd.addSetting(new MenuSettingMultiString(this,tr["Tv-Out encoding"],tr["Encoding of the tv-out signal"],&confStr["tvoutEncoding"],&encodings));
sd.addSetting(new MenuSettingBool(this,tr["Show root"],tr["Show root folder in the file selection dialogs"],&showRootFolder));
if (sd.exec() && sd.edited()) {
//G
if (prevbacklight != confInt["backlight"]) setBacklight(confInt["backlight"]);
if (curMenuClock!=confInt["menuClock"]) setClock(confInt["menuClock"]);
if (curGlobalVolume!=confInt["globalVolume"]) setVolume(confInt["globalVolume"]);
PowerSaver::getInstance()->setScreenTimeout( confInt["backlightTimeout"] );
if (lang == "English") lang = "";
if (lang != tr.lang()) {
tr.setLang(lang);
confStr["lang"] = lang;
}
/*if (fileExists(CARD_ROOT) && !showRootFolder)
unlink(CARD_ROOT);
else if (!fileExists(CARD_ROOT) && showRootFolder)
symlink("/", CARD_ROOT);*/
//WARNING: the above might be dangerous with CARD_ROOT set to /
writeConfig();
}
}
void GMenu2X::settingsOpen2x() {
SettingsDialog sd(this, input, ts, tr["Open2x Settings"]);
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));
sd.addSetting(new MenuSettingString(this,tr["USB net IP"],tr["IP address to be used for USB networking"],&o2x_usb_net_ip));
sd.addSetting(new MenuSettingBool(this,tr["Telnet on boot"],tr["Allow telnet to be started at boot time"],&o2x_telnet_on_boot));
sd.addSetting(new MenuSettingBool(this,tr["FTP on boot"],tr["Allow FTP to be started at boot time"],&o2x_ftp_on_boot));
sd.addSetting(new MenuSettingBool(this,tr["GP2XJOY on boot"],tr["Create a js0 device for GP2X controls"],&o2x_gp2xjoy_on_boot));
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));
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));
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));
//sd.addSetting(new MenuSettingInt(this,tr["Speaker Mode on boot"],tr["Set Speaker mode. 0 = Mute, 1 = Phones, 2 = Speaker"],&volumeMode,0,2));
sd.addSetting(new MenuSettingInt(this,tr["Speaker Scaler"],tr["Set the Speaker Mode scaling 0-150\% (default is 100\%)"],&volumeScalerNormal,0,150));
sd.addSetting(new MenuSettingInt(this,tr["Headphones Scaler"],tr["Set the Headphones Mode scaling 0-100\% (default is 65\%)"],&volumeScalerPhones,0,100));
if (sd.exec() && sd.edited()) {
writeConfigOpen2x();
switch(volumeMode) {
case VOLUME_MODE_MUTE: setVolumeScaler(VOLUME_SCALER_MUTE); break;
case VOLUME_MODE_PHONES: setVolumeScaler(volumeScalerPhones); break;
case VOLUME_MODE_NORMAL: setVolumeScaler(volumeScalerNormal); break;
}
setVolume(confInt["globalVolume"]);
}
}
void GMenu2X::skinMenu() {
FileLister fl_sk("skins",true,false);
fl_sk.addExclude("..");
fl_sk.browse();
string curSkin = confStr["skin"];
SettingsDialog sd(this, input, ts, tr["Skin"]);
sd.addSetting(new MenuSettingMultiString(this,tr["Skin"],tr["Set the skin used by GMenu2X"],&confStr["skin"],&fl_sk.getDirectories()));
sd.addSetting(new MenuSettingRGBA(this,tr["Top Bar Color"],tr["Color of the top bar"],&skinConfColors[COLOR_TOP_BAR_BG]));
sd.addSetting(new MenuSettingRGBA(this,tr["Bottom Bar Color"],tr["Color of the bottom bar"],&skinConfColors[COLOR_BOTTOM_BAR_BG]));
sd.addSetting(new MenuSettingRGBA(this,tr["Selection Color"],tr["Color of the selection and other interface details"],&skinConfColors[COLOR_SELECTION_BG]));
sd.addSetting(new MenuSettingRGBA(this,tr["Message Box Color"],tr["Background color of the message box"],&skinConfColors[COLOR_MESSAGE_BOX_BG]));
sd.addSetting(new MenuSettingRGBA(this,tr["Message Box Border Color"],tr["Border color of the message box"],&skinConfColors[COLOR_MESSAGE_BOX_BORDER]));
sd.addSetting(new MenuSettingRGBA(this,tr["Message Box Selection Color"],tr["Color of the selection of the message box"],&skinConfColors[COLOR_MESSAGE_BOX_SELECTION]));
if (sd.exec() && sd.edited()) {
if (curSkin != confStr["skin"]) {
setSkin(confStr["skin"]);
writeConfig();
}
writeSkinConfig();
initBG();
}
}
void GMenu2X::toggleTvOut() {
#ifdef TARGET_GP2X
/* if (cx25874!=0)
gp2x_tvout_off();
else
gp2x_tvout_on(confStr["tvoutEncoding"] == "PAL");*/
#endif
}
void GMenu2X::setSkin(const string &skin, bool setWallpaper) {
confStr["skin"] = skin;
//Clear previous skin settings
skinConfStr.clear();
skinConfInt.clear();
//clear collection and change the skin path
sc.clear();
sc.setSkin(skin);
//reset colors to the default values
skinConfColors[COLOR_TOP_BAR_BG] = (RGBAColor){255,255,255,130};
skinConfColors[COLOR_BOTTOM_BAR_BG] = (RGBAColor){255,255,255,130};
skinConfColors[COLOR_SELECTION_BG] = (RGBAColor){255,255,255,130};
skinConfColors[COLOR_MESSAGE_BOX_BG] = (RGBAColor){255,255,255,255};
skinConfColors[COLOR_MESSAGE_BOX_BORDER] = (RGBAColor){80,80,80,255};
skinConfColors[COLOR_MESSAGE_BOX_SELECTION] = (RGBAColor){160,160,160,255};
//load skin settings
string skinconfname = "skins/"+skin+"/skin.conf";
if (fileExists(skinconfname)) {
ifstream skinconf(skinconfname.c_str(), ios_base::in);
if (skinconf.is_open()) {
string line;
while (getline(skinconf, line, '\n')) {
line = trim(line);
DEBUG("skinconf: '%s'\n", line.c_str());
string::size_type pos = line.find("=");
string name = trim(line.substr(0,pos));
string value = trim(line.substr(pos+1,line.length()));
if (value.length()>0) {
if (value.length()>1 && value.at(0)=='"' && value.at(value.length()-1)=='"')
skinConfStr[name] = value.substr(1,value.length()-2);
else if (value.at(0) == '#')
skinConfColors[stringToColor(name)] = strtorgba( value.substr(1,value.length()) );
else
skinConfInt[name] = atoi(value.c_str());
}
}
skinconf.close();
if (setWallpaper && !skinConfStr["wallpaper"].empty() && fileExists("skins/"+skin+"/wallpapers/"+skinConfStr["wallpaper"]))
confStr["wallpaper"] = "skins/"+skin+"/wallpapers/"+skinConfStr["wallpaper"];
}
}
evalIntConf( &skinConfInt["topBarHeight"], 40, 32,120 );
evalIntConf( &skinConfInt["linkHeight"], 40, 32,120 );
evalIntConf( &skinConfInt["linkWidth"], 60, 32,120 );
//recalculate some coordinates based on the new element sizes
linkColumns = (resX-10)/skinConfInt["linkWidth"];
linkRows = (resY-35-skinConfInt["topBarHeight"])/skinConfInt["linkHeight"];
if (menu != NULL) menu->loadIcons();
//Selection png
useSelectionPng = sc.addSkinRes("imgs/selection.png") != NULL;
//font
initFont();
}
/*
void GMenu2X::activateSdUsb() {
if (usbnet) {
MessageBox mb(this,tr["Operation not permitted."]+"\n"+tr["You should disable Usb Networking to do this."]);
mb.exec();
} else {
system("scripts/usbon.sh sd");
MessageBox mb(this,tr["USB Enabled (SD)"],"icons/usb.png");
mb.setButton(ACCEPT, tr["Turn off"]);
mb.exec();
system("scripts/usboff.sh sd");
}
}
void GMenu2X::activateNandUsb() {
if (usbnet) {
MessageBox mb(this,tr["Operation not permitted."]+"\n"+tr["You should disable Usb Networking to do this."]);
mb.exec();
} else {
system("scripts/usbon.sh nand");
MessageBox mb(this,tr["USB Enabled (Nand)"],"icons/usb.png");
mb.setButton(ACCEPT, tr["Turn off"]);
mb.exec();
system("scripts/usboff.sh nand");
}
}
void GMenu2X::activateRootUsb() {
if (usbnet) {
MessageBox mb(this,tr["Operation not permitted."]+"\n"+tr["You should disable Usb Networking to do this."]);
mb.exec();
} else {
system("scripts/usbon.sh root");
MessageBox mb(this,tr["USB Enabled (Root)"],"icons/usb.png");
mb.setButton(ACCEPT, tr["Turn off"]);
mb.exec();
system("scripts/usboff.sh root");
}
}
*/
void GMenu2X::contextMenu() {
vector<MenuOption> voices;
{
MenuOption opt = {tr.translate("Add link in $1",menu->selSection().c_str(),NULL), MakeDelegate(this, &GMenu2X::addLink)};
voices.push_back(opt);
}
if (menu->selLinkApp()!=NULL) {
{
MenuOption opt = {tr.translate("Edit $1",menu->selLink()->getTitle().c_str(),NULL), MakeDelegate(this, &GMenu2X::editLink)};
voices.push_back(opt);
}{
MenuOption opt = {tr.translate("Delete $1 link",menu->selLink()->getTitle().c_str(),NULL), MakeDelegate(this, &GMenu2X::deleteLink)};
voices.push_back(opt);
}
}
{
MenuOption opt = {tr["Add section"], MakeDelegate(this, &GMenu2X::addSection)};
voices.push_back(opt);
}{
MenuOption opt = {tr["Rename section"], MakeDelegate(this, &GMenu2X::renameSection)};
voices.push_back(opt);
}{
MenuOption opt = {tr["Delete section"], MakeDelegate(this, &GMenu2X::deleteSection)};
voices.push_back(opt);
}{
MenuOption opt = {tr["Scan for applications and games"], MakeDelegate(this, &GMenu2X::scanner)};
voices.push_back(opt);
}
bool close = false;
uint i, sel=0, fadeAlpha=0;
int h = font->getHeight();
SDL_Rect box;
box.h = (h+2)*voices.size()+8;
box.w = 0;
for (i=0; i<voices.size(); i++) {
int w = font->getTextWidth(voices[i].text);
if (w>box.w) box.w = w;
}
box.w += 23;
box.x = halfX - box.w/2;
box.y = halfY - box.h/2;
SDL_Rect selbox = {box.x+4, 0, box.w-8, h+2};
long tickNow, tickStart = SDL_GetTicks();
Surface bg(s);
/*//Darken background
bg.box(0, 0, resX, resY, 0,0,0,150);
bg.box(box.x, box.y, box.w, box.h, skinConfColors["messageBoxBg"]);
bg.rectangle( box.x+2, box.y+2, box.w-4, box.h-4, skinConfColors["messageBoxBorder"] );*/
bevent_t event;
while (!close) {
tickNow = SDL_GetTicks();
selbox.y = box.y+4+(h+2)*sel;
bg.blit(s,0,0);
if (fadeAlpha<200) fadeAlpha = intTransition(0,200,tickStart,500,tickNow);
s->box(0, 0, resX, resY, 0,0,0,fadeAlpha);
s->box(box.x, box.y, box.w, box.h, skinConfColors[COLOR_MESSAGE_BOX_BG]);
s->rectangle( box.x+2, box.y+2, box.w-4, box.h-4, skinConfColors[COLOR_MESSAGE_BOX_BORDER] );
//draw selection rect
s->box( selbox.x, selbox.y, selbox.w, selbox.h, skinConfColors[COLOR_MESSAGE_BOX_SELECTION] );
for (i=0; i<voices.size(); i++)
s->write( font, voices[i].text, box.x+12, box.y+5+(h+2)*i, ASFont::HAlignLeft, ASFont::VAlignTop );
s->flip();
//touchscreen
if (f200) {
ts.poll();
if (ts.released()) {
if (!ts.inRect(box))
close = true;
else if (ts.getX() >= selbox.x
&& ts.getX() <= selbox.x + selbox.w)
for (i=0; i<voices.size(); i++) {
selbox.y = box.y+4+(h+2)*i;
if (ts.getY() >= selbox.y
&& ts.getY() <= selbox.y + selbox.h) {
voices[i].action();
close = true;
i = voices.size();
}
}
} else if (ts.pressed() && ts.inRect(box)) {
for (i=0; i<voices.size(); i++) {
selbox.y = box.y+4+(h+2)*i;
if (ts.getY() >= selbox.y
&& ts.getY() <= selbox.y + selbox.h) {
sel = i;
i = voices.size();
}
}
}
}
if (fadeAlpha < 200) {
if (!input.pollEvent(&event) || event.state != PRESSED) continue;
} else {
event.button = input.waitForPressedButton();
}
switch(event.button) {
case MENU:
close = true;
break;
case UP:
sel = max(0, sel-1);
break;
case DOWN:
sel = min((int)voices.size()-1, sel+1);
break;
case ACCEPT:
voices[sel].action();
close = true;
break;
default:
break;
}
}
}
void GMenu2X::changeWallpaper() {
WallpaperDialog wp(this);
if (wp.exec() && confStr["wallpaper"] != wp.wallpaper) {
confStr["wallpaper"] = wp.wallpaper;
initBG();
writeConfig();
}
}
void GMenu2X::addLink() {
FileDialog fd(this,tr["Select an application"]);
if (fd.exec()) {
ledOn();
menu->addLink(fd.getPath(), fd.getFile());
sync();
ledOff();
}
}
void GMenu2X::editLink() {
if (menu->selLinkApp()==NULL) return;
vector<string> pathV;
split(pathV,menu->selLinkApp()->getFile(),"/");
string oldSection = "";
if (pathV.size()>1)
oldSection = pathV[pathV.size()-2];
string newSection = oldSection;
string linkTitle = menu->selLinkApp()->getTitle();
string linkDescription = menu->selLinkApp()->getDescription();
string linkIcon = menu->selLinkApp()->getIcon();
string linkManual = menu->selLinkApp()->getManual();
string linkParams = menu->selLinkApp()->getParams();
string linkSelFilter = menu->selLinkApp()->getSelectorFilter();
string linkSelDir = menu->selLinkApp()->getSelectorDir();
bool linkSelBrowser = menu->selLinkApp()->getSelectorBrowser();
bool linkUseRamTimings = menu->selLinkApp()->getUseRamTimings();
string linkSelScreens = menu->selLinkApp()->getSelectorScreens();
string linkSelAliases = menu->selLinkApp()->getAliasFile();
int linkClock = menu->selLinkApp()->clock();
int linkVolume = menu->selLinkApp()->volume();
//G
//int linkGamma = menu->selLinkApp()->gamma();
int linkBacklight = menu->selLinkApp()->backlight();
string diagTitle = tr.translate("Edit link: $1",linkTitle.c_str(),NULL);
string diagIcon = menu->selLinkApp()->getIconPath();
SettingsDialog sd(this, input, ts, diagTitle, diagIcon);
sd.addSetting(new MenuSettingString(this,tr["Title"],tr["Link title"],&linkTitle, diagTitle,diagIcon));
sd.addSetting(new MenuSettingString(this,tr["Description"],tr["Link description"],&linkDescription, diagTitle,diagIcon));
sd.addSetting(new MenuSettingMultiString(this,tr["Section"],tr["The section this link belongs to"],&newSection,&menu->getSections()));
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"));
sd.addSetting(new MenuSettingFile(this,tr["Manual"],tr["Select a graphic/textual manual or a readme"],&linkManual,".man.png,.txt"));
sd.addSetting(new MenuSettingInt(this,tr["Clock (default: 336)"],tr["Cpu clock frequency to set when launching this link"],&linkClock,200,confInt["maxClock"]));
// sd.addSetting(new MenuSettingBool(this,tr["Tweak RAM Timings"],tr["This usually speeds up the application at the cost of stability"],&linkUseRamTimings));
sd.addSetting(new MenuSettingInt(this,tr["Volume (default: -1)"],tr["Volume to set for this link"],&linkVolume,-1,100));
sd.addSetting(new MenuSettingInt(this,tr["Backlight (default: -1)"],tr["LCD backlight value to set when launching this link"],&linkBacklight,-1,100));
sd.addSetting(new MenuSettingString(this,tr["Parameters"],tr["Parameters to pass to the application"],&linkParams, diagTitle,diagIcon));
sd.addSetting(new MenuSettingDir(this,tr["Selector Directory"],tr["Directory to scan for the selector"],&linkSelDir));
sd.addSetting(new MenuSettingBool(this,tr["Selector Browser"],tr["Allow the selector to change directory"],&linkSelBrowser));
sd.addSetting(new MenuSettingString(this,tr["Selector Filter"],tr["Filter for the selector (Separate values with a comma)"],&linkSelFilter, diagTitle,diagIcon));
sd.addSetting(new MenuSettingDir(this,tr["Selector Screenshots"],tr["Directory of the screenshots for the selector"],&linkSelScreens));
sd.addSetting(new MenuSettingFile(this,tr["Selector Aliases"],tr["File containing a list of aliases for the selector"],&linkSelAliases));
//G
sd.addSetting(new MenuSettingBool(this,tr["Wrapper"],tr["Explicitly relaunch GMenu2X after this link's execution ends"],&menu->selLinkApp()->needsWrapperRef()));
sd.addSetting(new MenuSettingBool(this,tr["Don't Leave"],tr["Don't quit GMenu2X when launching this link"],&menu->selLinkApp()->runsInBackgroundRef()));
if (sd.exec() && sd.edited()) {
ledOn();
menu->selLinkApp()->setTitle(linkTitle);
menu->selLinkApp()->setDescription(linkDescription);
menu->selLinkApp()->setIcon(linkIcon);
menu->selLinkApp()->setManual(linkManual);
menu->selLinkApp()->setParams(linkParams);
menu->selLinkApp()->setSelectorFilter(linkSelFilter);
menu->selLinkApp()->setSelectorDir(linkSelDir);
menu->selLinkApp()->setSelectorBrowser(linkSelBrowser);
menu->selLinkApp()->setUseRamTimings(linkUseRamTimings);
menu->selLinkApp()->setSelectorScreens(linkSelScreens);
menu->selLinkApp()->setAliasFile(linkSelAliases);
menu->selLinkApp()->setClock(linkClock);
menu->selLinkApp()->setVolume(linkVolume);
//G
if ((linkBacklight < 5) && (linkBacklight > -1))
linkBacklight = 5;
menu->selLinkApp()->setBacklight(linkBacklight);
INFO("New Section: '%s'\n", newSection.c_str());
//if section changed move file and update link->file
if (oldSection!=newSection) {
vector<string>::const_iterator newSectionIndex = find(menu->getSections().begin(),menu->getSections().end(),newSection);
if (newSectionIndex==menu->getSections().end()) return;
string newFileName = "sections/"+newSection+"/"+linkTitle;
uint x=2;
while (fileExists(newFileName)) {
string id = "";
stringstream ss; ss << x; ss >> id;
newFileName = "sections/"+newSection+"/"+linkTitle+id;
x++;
}
rename(menu->selLinkApp()->getFile().c_str(),newFileName.c_str());
menu->selLinkApp()->renameFile(newFileName);
INFO("New section index: %i.\n", newSectionIndex - menu->getSections().begin());
menu->linkChangeSection(menu->selLinkIndex(), menu->selSectionIndex(), newSectionIndex - menu->getSections().begin());
}
menu->selLinkApp()->save();
sync();
ledOff();
}
}
void GMenu2X::deleteLink() {
if (menu->selLinkApp()!=NULL) {
MessageBox mb(this, tr.translate("Deleting $1",menu->selLink()->getTitle().c_str(),NULL)+"\n"+tr["Are you sure?"], menu->selLink()->getIconPath());
mb.setButton(ACCEPT, tr["Yes"]);
mb.setButton(CLEAR, tr["No"]);
if (mb.exec() == ACCEPT) {
ledOn();
menu->deleteSelectedLink();
sync();
ledOff();
}
}
}
void GMenu2X::addSection() {
InputDialog id(this, input, ts, tr["Insert a name for the new section"]);
if (id.exec()) {
//only if a section with the same name does not exist
if (find(menu->getSections().begin(), menu->getSections().end(), id.getInput())
== menu->getSections().end()) {
//section directory doesn't exists
ledOn();
if (menu->addSection(id.getInput())) {
menu->setSectionIndex( menu->getSections().size()-1 ); //switch to the new section
sync();
}
ledOff();
}
}
}
void GMenu2X::renameSection() {
InputDialog id(this, input, ts, tr["Insert a new name for this section"],menu->selSection());
if (id.exec()) {
//only if a section with the same name does not exist & !samename
if (menu->selSection() != id.getInput()
&& find(menu->getSections().begin(),menu->getSections().end(), id.getInput())
== menu->getSections().end()) {
//section directory doesn't exists
string newsectiondir = "sections/" + id.getInput();
string sectiondir = "sections/" + menu->selSection();
ledOn();
if (rename(sectiondir.c_str(), "tmpsection")==0 && rename("tmpsection", newsectiondir.c_str())==0) {
string oldpng = sectiondir+".png", newpng = newsectiondir+".png";
string oldicon = sc.getSkinFilePath(oldpng), newicon = sc.getSkinFilePath(newpng);
if (!oldicon.empty() && newicon.empty()) {
newicon = oldicon;
newicon.replace(newicon.find(oldpng), oldpng.length(), newpng);
if (!fileExists(newicon)) {
rename(oldicon.c_str(), "tmpsectionicon");
rename("tmpsectionicon", newicon.c_str());
sc.move("skin:"+oldpng, "skin:"+newpng);
}
}
menu->renameSection(menu->selSectionIndex(), id.getInput());
sync();
}
ledOff();
}
}
}
void GMenu2X::deleteSection() {
MessageBox mb(this,tr["You will lose all the links in this section."]+"\n"+tr["Are you sure?"]);
mb.setButton(ACCEPT, tr["Yes"]);
mb.setButton(CLEAR, tr["No"]);
if (mb.exec() == ACCEPT) {
ledOn();
if (rmtree(path+"sections/"+menu->selSection())) {
menu->deleteSelectedSection();
sync();
}
ledOff();
}
}
void GMenu2X::scanner() {
Surface scanbg(bg);
drawButton(&scanbg, "x", tr["Exit"],
drawButton(&scanbg, "b", "", 5)-10);
scanbg.write(font,tr["Link Scanner"],halfX,7,ASFont::HAlignCenter,ASFont::VAlignMiddle);
scanbg.convertToDisplayFormat();
uint lineY = 42;
#ifdef _TARGET_PANDORA
//char *configpath = pnd_conf_query_searchpath();
#else
if (confInt["menuClock"]<430) {
setClock(336);
scanbg.write(font,tr["Raising cpu clock to 336Mhz"],5,lineY);
scanbg.blit(s,0,0);
s->flip();
lineY += 26;
}
scanbg.write(font,tr["Scanning SD filesystem..."],5,lineY);
scanbg.blit(s,0,0);
s->flip();
lineY += 26;
vector<string> files;
scanPath(CARD_ROOT, &files);
//Onyl gph firmware has nand
/* if (fwType=="gph" && !f200) {
scanbg.write(font,tr["Scanning NAND filesystem..."],5,lineY);
scanbg.blit(s,0,0);
s->flip();
lineY += 26;
scanPath("/boot/local/nand",&files);
}
*/
stringstream ss;
ss << files.size();
string str = "";
ss >> str;
scanbg.write(font,tr.translate("$1 files found.",str.c_str(),NULL),5,lineY);
lineY += 26;
scanbg.write(font,tr["Creating links..."],5,lineY);
scanbg.blit(s,0,0);
s->flip();
lineY += 26;
string path, file;
string::size_type pos;
uint linkCount = 0;
ledOn();
for (uint i = 0; i<files.size(); i++) {
pos = files[i].rfind("/");
if (pos!=string::npos && pos>0) {
path = files[i].substr(0, pos+1);
file = files[i].substr(pos+1, files[i].length());
if (menu->addLink(path,file,"found "+file.substr(file.length()-3,3)))
linkCount++;
}
}
ss.clear();
ss << linkCount;
ss >> str;
scanbg.write(font,tr.translate("$1 links created.",str.c_str(),NULL),5,lineY);
scanbg.blit(s,0,0);
s->flip();
lineY += 26;
if (confInt["menuClock"]<430) {
setClock(confInt["menuClock"]);
scanbg.write(font,tr["Decreasing cpu clock"],5,lineY);
scanbg.blit(s,0,0);
s->flip();
lineY += 26;
}
sync();
ledOff();
#endif
buttontype_t button;
do {
button = input.waitForPressedButton();
} while ((button != SETTINGS)
&& (button != ACCEPT)
&& (button != CLEAR));
/*
bevent_t event;
do {
input.getEvent(&event, true);
} while ((event.state != PRESSED) ||
( (event.button != SETTINGS)
&& (event.button != ACCEPT)
&& (event.button != CLEAR)));
*/
}
void GMenu2X::scanPath(string path, vector<string> *files) {
DIR *dirp;
struct stat st;
struct dirent *dptr;
string filepath, ext;
if (path[path.length()-1]!='/') path += "/";
if ((dirp = opendir(path.c_str())) == NULL) return;
while ((dptr = readdir(dirp))) {
if (dptr->d_name[0]=='.')
continue;
filepath = path+dptr->d_name;
int statRet = stat(filepath.c_str(), &st);
if (S_ISDIR(st.st_mode))
scanPath(filepath, files);
if (statRet != -1) {
ext = filepath.substr(filepath.length()-4,4);
#ifdef TARGET_GP2X
if (ext==".gpu" || ext==".dge")
#else
if (ext==".pxml")
#endif
files->push_back(filepath);
}
}
closedir(dirp);
}
unsigned short GMenu2X::getBatteryLevel() {
#ifdef TARGET_GP2X
/* if (batteryHandle<=0) return 0;
if (f200) {
MMSP2ADC val;
read(batteryHandle, &val, sizeof(MMSP2ADC));
if (val.batt==0) return 5;
if (val.batt==1) return 3;
if (val.batt==2) return 1;
if (val.batt==3) return 0;
} else {
int battval = 0;
unsigned short cbv, min=900, max=0;
for (int i = 0; i < BATTERY_READS; i ++) {
if ( read(batteryHandle, &cbv, 2) == 2) {
battval += cbv;
if (cbv>max) max = cbv;
if (cbv<min) min = cbv;
}
}
battval -= min+max;
battval /= BATTERY_READS-2;
if (battval>=850) return 6;
if (battval>780) return 5;
if (battval>740) return 4;
if (battval>700) return 3;
if (battval>690) return 2;
if (battval>680) return 1;
}*/
if (!batteryHandle) return 0;
int battval = 0;
char battvalcstr[5];
fscanf(batteryHandle, "%s", &battvalcstr[0]);
rewind(batteryHandle);
battval = atoi(battvalcstr);
if (battval>90) return 5;
if (battval>70) return 4;
if (battval>50) return 3;
if (battval>30) return 2;
if (battval>10) return 1;
if (!usbHandle) return 0;
int usbval = 0;
char usbvalcstr[5];
fscanf(usbHandle, "%s", &usbvalcstr[0]);
rewind(usbHandle);
usbval = atoi(usbvalcstr);
if (usbval==1) return 6;
return 0;
//#else
// return 6; //AC Power
#endif
}
void GMenu2X::setInputSpeed() {
/*
input.setInterval(150);
input.setInterval(30, VOLDOWN);
input.setInterval(30, VOLUP );
input.setInterval(30, CANCEL );
input.setInterval(500, SETTINGS );
input.setInterval(500, MENU );
input.setInterval(300, CLEAR );
input.setInterval(300, MANUAL );
input.setInterval(1000,ACCEPT );
//joy.setInterval(1000,ACTION_CLICK );
input.setInterval(300, ALTLEFT );
input.setInterval(300, ALTRIGHT );
*/
SDL_EnableKeyRepeat(1,150);
}
void GMenu2X::applyRamTimings() {
#ifdef TARGET_GP2X
// 6 4 1 1 1 2 2
/* if (gp2x_mem!=0) {
int tRC = 5, tRAS = 3, tWR = 0, tMRD = 0, tRFC = 0, tRP = 1, tRCD = 1;
gp2x_memregs[0x3802>>1] = ((tMRD & 0xF) << 12) | ((tRFC & 0xF) << 8) | ((tRP & 0xF) << 4) | (tRCD & 0xF);
gp2x_memregs[0x3804>>1] = ((tRC & 0xF) << 8) | ((tRAS & 0xF) << 4) | (tWR & 0xF);
}*/
#endif
}
void GMenu2X::applyDefaultTimings() {
#ifdef TARGET_GP2X
// 8 16 3 8 8 8 8
/* if (gp2x_mem!=0) {
int tRC = 7, tRAS = 15, tWR = 2, tMRD = 7, tRFC = 7, tRP = 7, tRCD = 7;
gp2x_memregs[0x3802>>1] = ((tMRD & 0xF) << 12) | ((tRFC & 0xF) << 8) | ((tRP & 0xF) << 4) | (tRCD & 0xF);
gp2x_memregs[0x3804>>1] = ((tRC & 0xF) << 8) | ((tRAS & 0xF) << 4) | (tWR & 0xF);
}*/
#endif
}
void GMenu2X::setClock(unsigned mhz) {
mhz = constrain(mhz, 30, confInt["maxClock"]);
#ifdef TARGET_GP2X
jz_cpuspeed(mhz);
#endif
}
void GMenu2X::setGamma(int /*gamma*/) {
#ifdef TARGET_GP2X
/* float fgamma = (float)constrain(gamma,1,100)/10;
fgamma = 1 / fgamma;
MEM_REG[0x2880>>1]&=~(1<<12);
MEM_REG[0x295C>>1]=0;
for (int i=0; i<256; i++) {
unsigned char g = (unsigned char)(255.0*pow(i/255.0,fgamma));
unsigned short s = (g<<8) | g;
MEM_REG[0x295E>>1]= s;
MEM_REG[0x295E>>1]= g;
}*/
#endif
}
int GMenu2X::getVolume() {
unsigned long mixer;
int basevolume = -1;
mixer = open("/dev/mixer", O_RDONLY);
if(mixer)
{
if (ioctl(mixer, SOUND_MIXER_READ_VOLUME, &basevolume) == -1) {
ERROR("Failed opening mixer for read - VOLUME\n");
}
close(mixer);
if(basevolume != -1)
return (basevolume>>8) & basevolume ;
}
return basevolume;
}
void GMenu2X::setVolume(int vol) {
unsigned long mixer;
int newvolume = vol;
int oss_volume = newvolume | (newvolume << 8); // set volume for both channels
mixer = open("/dev/mixer", O_WRONLY);
if(mixer)
{
if (ioctl(mixer, SOUND_MIXER_WRITE_VOLUME, &oss_volume) == -1) {
ERROR("Failed opening mixer for write - VOLUME\n");
}
close(mixer);
}
}
void GMenu2X::setVolumeScaler(int scale) {
scale = constrain(scale,0,MAX_VOLUME_SCALE_FACTOR);
unsigned long soundDev = open("/dev/mixer", O_WRONLY);
if (soundDev) {
ioctl(soundDev, SOUND_MIXER_PRIVATE2, &scale);
close(soundDev);
}
}
int GMenu2X::getVolumeScaler() {
int currentscalefactor = -1;
unsigned long soundDev = open("/dev/mixer", O_RDONLY);
if (soundDev) {
ioctl(soundDev, SOUND_MIXER_PRIVATE1, &currentscalefactor);
close(soundDev);
}
return currentscalefactor;
}
const string &GMenu2X::getExePath() {
if (path.empty()) {
char buf[255];
memset(buf, 0, 255);
int l = readlink("/proc/self/exe", buf, 255);
path = buf;
path = path.substr(0,l);
l = path.rfind("/");
path = path.substr(0,l+1);
}
return path;
}
string GMenu2X::getDiskFree() {
stringstream ss;
string df = "";
struct statvfs b;
int ret = statvfs(CARD_ROOT, &b);
if (ret==0) {
// Make sure that the multiplication happens in 64 bits.
unsigned long long free =
((unsigned long long)b.f_bfree * b.f_bsize) / 1048576;
unsigned long long total =
((unsigned long long)b.f_blocks * b.f_frsize) / 1048576;
ss << free << "/" << total << "MB";
ss >> df;
} else WARNING("statvfs failed with error '%s'.\n", strerror(errno));
return df;
}
int GMenu2X::drawButton(Button *btn, int x, int y) {
if (y<0) y = resY+y;
btn->setPosition(x, y-7);
btn->paint();
return x+btn->getRect().w+6;
}
int GMenu2X::drawButton(Surface *s, const string &btn, const string &text, int x, int y) {
if (y<0) y = resY+y;
SDL_Rect re = {x, y-7, 0, 16};
if (sc.skinRes("imgs/buttons/"+btn+".png") != NULL) {
sc["imgs/buttons/"+btn+".png"]->blit(s, x, y-7);
re.w = sc["imgs/buttons/"+btn+".png"]->width() + 3;
s->write(font, text, x+re.w, y, ASFont::HAlignLeft, ASFont::VAlignMiddle);
re.w += font->getTextWidth(text);
}
return x+re.w+6;
}
int GMenu2X::drawButtonRight(Surface *s, const string &btn, const string &text, int x, int y) {
if (y<0) y = resY+y;
if (sc.skinRes("imgs/buttons/"+btn+".png") != NULL) {
x -= 16;
sc["imgs/buttons/"+btn+".png"]->blit(s, x, y-7);
x -= 3;
s->write(font, text, x, y, ASFont::HAlignRight, ASFont::VAlignMiddle);
return x-6-font->getTextWidth(text);
}
return x-6;
}
void GMenu2X::drawScrollBar(uint pagesize, uint totalsize, uint pagepos, uint top, uint height) {
if (totalsize<=pagesize) return;
s->rectangle(resX-8, top, 7, height, skinConfColors[COLOR_SELECTION_BG]);
//internal bar total height = height-2
//bar size
uint bs = (height-2) * pagesize / totalsize;
//bar y position
uint by = (height-2) * pagepos / totalsize;
by = top+2+by;
if (by+bs>top+height-2) by = top+height-2-bs;
s->box(resX-6, by, 3, bs, skinConfColors[COLOR_SELECTION_BG]);
}
void GMenu2X::drawTopBar(Surface *s) {
if (s==NULL) s = this->s;
Surface *bar = sc.skinRes("imgs/topbar.png");
if (bar != NULL)
bar->blit(s, 0, 0);
else
s->box(0, 0, resX, skinConfInt["topBarHeight"],
skinConfColors[COLOR_TOP_BAR_BG]);
}
void GMenu2X::drawBottomBar(Surface *s) {
if (s==NULL) s = this->s;
Surface *bar = sc.skinRes("imgs/bottombar.png");
if (bar != NULL)
bar->blit(s, 0, resY-bar->height());
else
s->box(0, resY-20, resX, 20, skinConfColors[COLOR_BOTTOM_BAR_BG]);
}