mirror of
git://projects.qi-hardware.com/gmenu2x.git
synced 2024-11-25 21:36:15 +02:00
Launch application after destructing menu
This allows all destructors to do their job before we pass control to a new process.
This commit is contained in:
parent
303ecf298a
commit
7c4fa5d77a
@ -126,6 +126,7 @@ static const char *colorToString(enum color c)
|
|||||||
|
|
||||||
static void quit_all(int err) {
|
static void quit_all(int err) {
|
||||||
delete app;
|
delete app;
|
||||||
|
SDL_Quit();
|
||||||
exit(err);
|
exit(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,11 +164,31 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
|||||||
|
|
||||||
DEBUG("Home path: %s.\n", gmenu2x_home.c_str());
|
DEBUG("Home path: %s.\n", gmenu2x_home.c_str());
|
||||||
|
|
||||||
app = new GMenu2X();
|
GMenu2X::run();
|
||||||
DEBUG("Starting main()\n");
|
|
||||||
app->main();
|
|
||||||
|
|
||||||
return 0;
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMenu2X::run() {
|
||||||
|
auto menu = new GMenu2X();
|
||||||
|
app = menu;
|
||||||
|
DEBUG("Starting main()\n");
|
||||||
|
menu->mainLoop();
|
||||||
|
|
||||||
|
app = nullptr;
|
||||||
|
Launcher *toLaunch = menu->toLaunch.release();
|
||||||
|
delete menu;
|
||||||
|
|
||||||
|
SDL_Quit();
|
||||||
|
unsetenv("SDL_FBCON_DONT_CLEAR");
|
||||||
|
|
||||||
|
if (toLaunch) {
|
||||||
|
toLaunch->exec();
|
||||||
|
// If control gets here, execution failed. Since we already destructed
|
||||||
|
// everything, the easiest solution is to exit and let the system
|
||||||
|
// respawn the menu.
|
||||||
|
delete toLaunch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_CPUFREQ
|
#ifdef ENABLE_CPUFREQ
|
||||||
@ -194,7 +215,6 @@ void GMenu2X::initCPULimits() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
GMenu2X::GMenu2X()
|
GMenu2X::GMenu2X()
|
||||||
: appToLaunch(nullptr)
|
|
||||||
{
|
{
|
||||||
usbnet = samba = inet = web = false;
|
usbnet = samba = inet = web = false;
|
||||||
useSelectionPng = false;
|
useSelectionPng = false;
|
||||||
@ -219,7 +239,9 @@ GMenu2X::GMenu2X()
|
|||||||
|
|
||||||
if( SDL_Init(SDL_INIT_TIMER) < 0) {
|
if( SDL_Init(SDL_INIT_TIMER) < 0) {
|
||||||
ERROR("Could not initialize SDL: %s\n", SDL_GetError());
|
ERROR("Could not initialize SDL: %s\n", SDL_GetError());
|
||||||
quit();
|
// TODO: We don't use exceptions, so don't put things that can fail
|
||||||
|
// in a constructor.
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bg = NULL;
|
bg = NULL;
|
||||||
@ -232,7 +254,9 @@ GMenu2X::GMenu2X()
|
|||||||
* a black screen for a couple of seconds. */
|
* a black screen for a couple of seconds. */
|
||||||
if( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
|
if( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
|
||||||
ERROR("Could not initialize SDL: %s\n", SDL_GetError());
|
ERROR("Could not initialize SDL: %s\n", SDL_GetError());
|
||||||
quit();
|
// TODO: We don't use exceptions, so don't put things that can fail
|
||||||
|
// in a constructor.
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
s = Surface::openOutputSurface(resX, resY, confInt["videoBpp"]);
|
s = Surface::openOutputSurface(resX, resY, confInt["videoBpp"]);
|
||||||
@ -275,22 +299,17 @@ GMenu2X::GMenu2X()
|
|||||||
}
|
}
|
||||||
|
|
||||||
GMenu2X::~GMenu2X() {
|
GMenu2X::~GMenu2X() {
|
||||||
if (PowerSaver::isRunning())
|
if (PowerSaver::isRunning()) {
|
||||||
delete PowerSaver::getInstance();
|
delete PowerSaver::getInstance();
|
||||||
quit();
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_INOTIFY
|
|
||||||
delete monitor;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMenu2X::quit() {
|
|
||||||
fflush(NULL);
|
fflush(NULL);
|
||||||
sc.clear();
|
sc.clear();
|
||||||
delete s;
|
delete s;
|
||||||
|
|
||||||
SDL_Quit();
|
#ifdef ENABLE_INOTIFY
|
||||||
unsetenv("SDL_FBCON_DONT_CLEAR");
|
delete monitor;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMenu2X::initBG() {
|
void GMenu2X::initBG() {
|
||||||
@ -567,12 +586,10 @@ void GMenu2X::writeTmp(int selelem, const string &selectordir) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMenu2X::main() {
|
void GMenu2X::mainLoop() {
|
||||||
if (!fileExists(CARD_ROOT))
|
if (!fileExists(CARD_ROOT))
|
||||||
CARD_ROOT = "";
|
CARD_ROOT = "";
|
||||||
|
|
||||||
appToLaunch = nullptr;
|
|
||||||
|
|
||||||
// Recover last session
|
// Recover last session
|
||||||
readTmp();
|
readTmp();
|
||||||
if (lastSelectorElement > -1 && menu->selLinkApp() &&
|
if (lastSelectorElement > -1 && menu->selLinkApp() &&
|
||||||
@ -600,10 +617,12 @@ void GMenu2X::main() {
|
|||||||
for (auto layer : layers) {
|
for (auto layer : layers) {
|
||||||
layer->paint(*s);
|
layer->paint(*s);
|
||||||
}
|
}
|
||||||
if (appToLaunch) {
|
s->flip();
|
||||||
|
|
||||||
|
// Exit main loop once we have something to launch.
|
||||||
|
if (toLaunch) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
s->flip();
|
|
||||||
|
|
||||||
// Handle touchscreen events.
|
// Handle touchscreen events.
|
||||||
if (ts.available()) {
|
if (ts.available()) {
|
||||||
@ -630,11 +649,6 @@ void GMenu2X::main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appToLaunch) {
|
|
||||||
appToLaunch->drawRun();
|
|
||||||
appToLaunch->launch(fileToLaunch);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMenu2X::explorer() {
|
void GMenu2X::explorer() {
|
||||||
@ -645,24 +659,20 @@ void GMenu2X::explorer() {
|
|||||||
|
|
||||||
string command = cmdclean(fd.getPath()+"/"+fd.getFile());
|
string command = cmdclean(fd.getPath()+"/"+fd.getFile());
|
||||||
chdir(fd.getPath().c_str());
|
chdir(fd.getPath().c_str());
|
||||||
quit();
|
|
||||||
#ifdef ENABLE_CPUFREQ
|
#ifdef ENABLE_CPUFREQ
|
||||||
setClock(cpuFreqAppDefault);
|
setClock(cpuFreqAppDefault);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Launcher launcher(vector<string> { "/bin/sh", "-c", command });
|
toLaunch.reset(new Launcher(
|
||||||
launcher.exec();
|
vector<string> { "/bin/sh", "-c", command }));
|
||||||
|
|
||||||
//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");
|
|
||||||
main();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMenu2X::queueLaunch(LinkApp *app, const std::string &file) {
|
void GMenu2X::queueLaunch(
|
||||||
appToLaunch = app;
|
unique_ptr<Launcher>&& launcher, shared_ptr<Layer> launchLayer
|
||||||
fileToLaunch = file;
|
) {
|
||||||
|
toLaunch = move(launcher);
|
||||||
|
layers.push_back(launchLayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMenu2X::showHelpPopup() {
|
void GMenu2X::showHelpPopup() {
|
||||||
|
@ -38,8 +38,8 @@ class Button;
|
|||||||
class Font;
|
class Font;
|
||||||
class HelpPopup;
|
class HelpPopup;
|
||||||
class IconButton;
|
class IconButton;
|
||||||
|
class Launcher;
|
||||||
class Layer;
|
class Layer;
|
||||||
class LinkApp;
|
|
||||||
class MediaMonitor;
|
class MediaMonitor;
|
||||||
class Menu;
|
class Menu;
|
||||||
class Surface;
|
class Surface;
|
||||||
@ -76,8 +76,7 @@ private:
|
|||||||
MediaMonitor *monitor;
|
MediaMonitor *monitor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LinkApp *appToLaunch;
|
std::unique_ptr<Launcher> toLaunch;
|
||||||
std::string fileToLaunch;
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Layer>> layers;
|
std::vector<std::shared_ptr<Layer>> layers;
|
||||||
|
|
||||||
@ -120,9 +119,10 @@ private:
|
|||||||
void initBG();
|
void initBG();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static void run();
|
||||||
|
|
||||||
GMenu2X();
|
GMenu2X();
|
||||||
~GMenu2X();
|
~GMenu2X();
|
||||||
void quit();
|
|
||||||
|
|
||||||
/* Returns the home directory of gmenu2x, usually
|
/* Returns the home directory of gmenu2x, usually
|
||||||
* ~/.gmenu2x */
|
* ~/.gmenu2x */
|
||||||
@ -162,7 +162,7 @@ public:
|
|||||||
std::unique_ptr<Font> font;
|
std::unique_ptr<Font> font;
|
||||||
|
|
||||||
//Status functions
|
//Status functions
|
||||||
void main();
|
void mainLoop();
|
||||||
void showContextMenu();
|
void showContextMenu();
|
||||||
void showHelpPopup();
|
void showHelpPopup();
|
||||||
void showManual();
|
void showManual();
|
||||||
@ -184,7 +184,9 @@ public:
|
|||||||
* The launch won't happen immediately; it will happen after control
|
* The launch won't happen immediately; it will happen after control
|
||||||
* returns to the main loop.
|
* returns to the main loop.
|
||||||
*/
|
*/
|
||||||
void queueLaunch(LinkApp *app, const std::string &file);
|
void queueLaunch(std::unique_ptr<Launcher>&& launcher,
|
||||||
|
std::shared_ptr<Layer> launchLayer);
|
||||||
|
|
||||||
void saveSelection();
|
void saveSelection();
|
||||||
void writeConfig();
|
void writeConfig();
|
||||||
void writeSkinConfig();
|
void writeSkinConfig();
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "delegate.h"
|
#include "delegate.h"
|
||||||
#include "gmenu2x.h"
|
#include "gmenu2x.h"
|
||||||
#include "launcher.h"
|
#include "launcher.h"
|
||||||
|
#include "layer.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "selector.h"
|
#include "selector.h"
|
||||||
#include "surface.h"
|
#include "surface.h"
|
||||||
@ -55,6 +56,31 @@ using namespace std;
|
|||||||
|
|
||||||
static array<const char *, 4> tokens = { "%f", "%F", "%u", "%U", };
|
static array<const char *, 4> tokens = { "%f", "%F", "%u", "%U", };
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the launch message (loading screen).
|
||||||
|
*/
|
||||||
|
class LaunchLayer: public Layer {
|
||||||
|
public:
|
||||||
|
LaunchLayer(LinkApp& app) : app(app) {}
|
||||||
|
|
||||||
|
void paint(Surface &s) override {
|
||||||
|
app.drawLaunch(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handleButtonPress(InputManager::Button) override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handleTouchscreen(Touchscreen&) override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
LinkApp& app;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBOPK
|
#ifdef HAVE_LIBOPK
|
||||||
LinkApp::LinkApp(GMenu2X *gmenu2x_, const char* linkfile,
|
LinkApp::LinkApp(GMenu2X *gmenu2x_, const char* linkfile,
|
||||||
struct OPK *opk, const char *metadata_)
|
struct OPK *opk, const char *metadata_)
|
||||||
@ -323,9 +349,9 @@ bool LinkApp::save() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkApp::drawRun() {
|
void LinkApp::drawLaunch(Surface& s) {
|
||||||
//Darkened background
|
//Darkened background
|
||||||
gmenu2x->s->box(0, 0, gmenu2x->resX, gmenu2x->resY, 0,0,0,150);
|
s.box(0, 0, gmenu2x->resX, gmenu2x->resY, 0,0,0,150);
|
||||||
|
|
||||||
string text = getLaunchMsg().empty()
|
string text = getLaunchMsg().empty()
|
||||||
? gmenu2x->tr.translate("Launching $1", getTitle().c_str(), nullptr)
|
? gmenu2x->tr.translate("Launching $1", getTitle().c_str(), nullptr)
|
||||||
@ -336,25 +362,25 @@ void LinkApp::drawRun() {
|
|||||||
int halfBoxW = boxW/2;
|
int halfBoxW = boxW/2;
|
||||||
|
|
||||||
//outer box
|
//outer box
|
||||||
gmenu2x->s->box(gmenu2x->halfX-2-halfBoxW, gmenu2x->halfY-23, halfBoxW*2+5, 47, gmenu2x->skinConfColors[COLOR_MESSAGE_BOX_BG]);
|
s.box(gmenu2x->halfX-2-halfBoxW, gmenu2x->halfY-23, halfBoxW*2+5, 47, gmenu2x->skinConfColors[COLOR_MESSAGE_BOX_BG]);
|
||||||
//inner rectangle
|
//inner rectangle
|
||||||
gmenu2x->s->rectangle(gmenu2x->halfX-halfBoxW, gmenu2x->halfY-21, boxW, 42, gmenu2x->skinConfColors[COLOR_MESSAGE_BOX_BORDER]);
|
s.rectangle(gmenu2x->halfX-halfBoxW, gmenu2x->halfY-21, boxW, 42, gmenu2x->skinConfColors[COLOR_MESSAGE_BOX_BORDER]);
|
||||||
|
|
||||||
int x = gmenu2x->halfX+10-halfBoxW;
|
int x = gmenu2x->halfX+10-halfBoxW;
|
||||||
/*if (!getIcon().empty())
|
/*if (!getIcon().empty())
|
||||||
gmenu2x->sc[getIcon()]->blit(gmenu2x->s,x,104);
|
gmenu2x->sc[getIcon()]->blit(gmenu2x->s,x,104);
|
||||||
else
|
else
|
||||||
gmenu2x->sc["icons/generic.png"]->blit(gmenu2x->s,x,104);*/
|
gmenu2x->sc["icons/generic.png"]->blit(gmenu2x->s,x,104);*/
|
||||||
iconSurface->blit(gmenu2x->s,x,gmenu2x->halfY-16);
|
iconSurface->blit(&s, x, gmenu2x->halfY - 16);
|
||||||
gmenu2x->font->write(gmenu2x->s, text, x+42, gmenu2x->halfY+1, Font::HAlignLeft, Font::VAlignMiddle );
|
gmenu2x->font->write(&s, text, x + 42, gmenu2x->halfY + 1, Font::HAlignLeft, Font::VAlignMiddle);
|
||||||
gmenu2x->s->flip();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkApp::start() {
|
void LinkApp::start() {
|
||||||
if (!selectordir.empty())
|
if (selectordir.empty()) {
|
||||||
|
gmenu2x->queueLaunch(prepareLaunch(""), make_shared<LaunchLayer>(*this));
|
||||||
|
} else {
|
||||||
selector();
|
selector();
|
||||||
else
|
}
|
||||||
gmenu2x->queueLaunch(this, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkApp::showManual() {
|
void LinkApp::showManual() {
|
||||||
@ -510,11 +536,13 @@ void LinkApp::selector(int startSelection, const string &selectorDir) {
|
|||||||
selectordir = selectedDir;
|
selectordir = selectedDir;
|
||||||
}
|
}
|
||||||
gmenu2x->writeTmp(selection, selectedDir);
|
gmenu2x->writeTmp(selection, selectedDir);
|
||||||
gmenu2x->queueLaunch(this, selectedDir + sel.getFile());
|
gmenu2x->queueLaunch(
|
||||||
|
prepareLaunch(selectedDir + sel.getFile()),
|
||||||
|
make_shared<LaunchLayer>(*this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinkApp::launch(const string &selectedFile) {
|
unique_ptr<Launcher> LinkApp::prepareLaunch(const string &selectedFile) {
|
||||||
save();
|
save();
|
||||||
|
|
||||||
if (!isOpk()) {
|
if (!isOpk()) {
|
||||||
@ -568,7 +596,6 @@ void LinkApp::launch(const string &selectedFile) {
|
|||||||
gmenu2x->setClock(clock());
|
gmenu2x->setClock(clock());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
gmenu2x->quit();
|
|
||||||
|
|
||||||
vector<string> commandLine;
|
vector<string> commandLine;
|
||||||
if (isOpk()) {
|
if (isOpk()) {
|
||||||
@ -582,12 +609,8 @@ void LinkApp::launch(const string &selectedFile) {
|
|||||||
commandLine = { "/bin/sh", "-c", exec + " " + params };
|
commandLine = { "/bin/sh", "-c", exec + " " + params };
|
||||||
}
|
}
|
||||||
|
|
||||||
Launcher launcher(move(commandLine), consoleApp);
|
return std::unique_ptr<Launcher>(new Launcher(
|
||||||
launcher.exec();
|
move(commandLine), consoleApp));
|
||||||
|
|
||||||
//if execution continues then something went wrong and as we already called SDL_Quit we cannot continue
|
|
||||||
//try relaunching gmenu2x
|
|
||||||
gmenu2x->main();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const string &LinkApp::getExec() {
|
const string &LinkApp::getExec() {
|
||||||
|
@ -23,9 +23,11 @@
|
|||||||
|
|
||||||
#include "link.h"
|
#include "link.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class GMenu2X;
|
class GMenu2X;
|
||||||
|
class Launcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Parses links files.
|
Parses links files.
|
||||||
@ -95,8 +97,11 @@ public:
|
|||||||
const std::string &getFile() { return file; }
|
const std::string &getFile() { return file; }
|
||||||
void renameFile(const std::string &name);
|
void renameFile(const std::string &name);
|
||||||
|
|
||||||
void drawRun();
|
private:
|
||||||
void launch(const std::string &selectedFile);
|
void drawLaunch(Surface& s);
|
||||||
|
std::unique_ptr<Launcher> prepareLaunch(const std::string &selectedFile);
|
||||||
|
|
||||||
|
friend class LaunchLayer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user