mirror of
git://projects.qi-hardware.com/gmenu2x.git
synced 2024-11-22 21:59:43 +02:00
Monitor OPK folders using inotify and automatically add/delete links
This commit is contained in:
parent
1467c9b9d7
commit
13b3d8e0ca
@ -78,6 +78,10 @@ AC_ARG_ENABLE(cpufreq,
|
||||
[ --disable-cpufreq disable support for CPU frequency scaling],
|
||||
[CPUFREQ=no],,)
|
||||
|
||||
AC_ARG_ENABLE(inotify,
|
||||
[ --disable-inotify disable file monitoring],
|
||||
[INOTIFY=no],,)
|
||||
|
||||
AC_SUBST(PLATFORM)
|
||||
AC_SUBST(SCREEN_RES)
|
||||
AC_DEFINE_UNQUOTED(PLATFORM, "${PLATFORM}")
|
||||
@ -86,5 +90,9 @@ if test "x$CPUFREQ" != xno ; then
|
||||
AC_DEFINE(ENABLE_CPUFREQ)
|
||||
fi
|
||||
|
||||
if test "x$INOTIFY" != xno ; then
|
||||
AC_DEFINE(ENABLE_INOTIFY)
|
||||
fi
|
||||
|
||||
|
||||
AC_OUTPUT(Makefile src/Makefile data/Makefile)
|
||||
|
@ -12,7 +12,7 @@ gmenu2x_SOURCES = asfont.cpp button.cpp cpu.cpp dirdialog.cpp filedialog.cpp \
|
||||
textdialog.cpp textmanualdialog.cpp touchscreen.cpp translator.cpp \
|
||||
utilities.cpp wallpaperdialog.cpp \
|
||||
browsedialog.cpp buttonbox.cpp dialog.cpp \
|
||||
imageio.cpp powersaver.cpp
|
||||
imageio.cpp powersaver.cpp monitor.cpp
|
||||
|
||||
noinst_HEADERS = asfont.h button.h cpu.h dirdialog.h FastDelegate.h \
|
||||
filedialog.h filelister.h gmenu2x.h gp2x.h iconbutton.h imagedialog.h \
|
||||
@ -25,7 +25,7 @@ noinst_HEADERS = asfont.h button.h cpu.h dirdialog.h FastDelegate.h \
|
||||
surfacecollection.h surface.h textdialog.h textmanualdialog.h \
|
||||
touchscreen.h translator.h utilities.h wallpaperdialog.h \
|
||||
browsedialog.h buttonbox.h dialog.h \
|
||||
imageio.h powersaver.h
|
||||
imageio.h powersaver.h monitor.h
|
||||
|
||||
AM_CFLAGS= @CFLAGS@ @SDL_CFLAGS@
|
||||
|
||||
|
@ -244,7 +244,7 @@ GMenu2X::GMenu2X()
|
||||
DEBUG("Loading system input.conf file: %s.\n", input_file.c_str());
|
||||
}
|
||||
|
||||
input.init(input_file);
|
||||
input.init(input_file, menu);
|
||||
|
||||
if (confInt["backlightTimeout"] > 0)
|
||||
PowerSaver::getInstance()->setScreenTimeout( confInt["backlightTimeout"] );
|
||||
|
@ -22,13 +22,16 @@
|
||||
#include "inputmanager.h"
|
||||
#include "utilities.h"
|
||||
#include "powersaver.h"
|
||||
#include "menu.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void InputManager::init(const string &conffile) {
|
||||
void InputManager::init(const string &conffile, Menu *menu) {
|
||||
this->menu = menu;
|
||||
|
||||
for (int i = 0; i < BUTTON_TYPE_SIZE; i++) {
|
||||
buttonMap[i].source = UNMAPPED;
|
||||
}
|
||||
@ -174,6 +177,15 @@ bool InputManager::getEvent(ButtonEvent *bevent, bool wait) {
|
||||
source = JOYSTICK;
|
||||
break;
|
||||
#endif
|
||||
case SDL_USEREVENT:
|
||||
if (!event.user.code)
|
||||
menu->removePackageLink((const char *) event.user.data1);
|
||||
else
|
||||
menu->openPackage((const char *) event.user.data1);
|
||||
free(event.user.data1);
|
||||
bevent->state = PRESSED;
|
||||
bevent->button = REPAINT;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <SDL.h>
|
||||
#include <string>
|
||||
|
||||
class Menu;
|
||||
|
||||
class InputManager {
|
||||
public:
|
||||
enum Button {
|
||||
@ -32,7 +34,8 @@ public:
|
||||
ALTLEFT, ALTRIGHT,
|
||||
MENU, SETTINGS,
|
||||
VOLUP, VOLDOWN,
|
||||
POWER, LOCK
|
||||
POWER, LOCK,
|
||||
REPAINT,
|
||||
};
|
||||
#define BUTTON_TYPE_SIZE 14
|
||||
|
||||
@ -45,7 +48,7 @@ public:
|
||||
InputManager();
|
||||
~InputManager();
|
||||
|
||||
void init(const std::string &conffile);
|
||||
void init(const std::string &conffile, Menu *menu);
|
||||
bool waitForEvent(ButtonEvent *event);
|
||||
Button waitForPressedButton();
|
||||
Button waitForReleasedButton();
|
||||
@ -58,6 +61,8 @@ private:
|
||||
unsigned int code;
|
||||
};
|
||||
|
||||
Menu *menu;
|
||||
|
||||
void readConfFile(const std::string &conffile);
|
||||
bool getEvent(ButtonEvent *bevent, bool wait);
|
||||
Button waitForButton(ButtonState state);
|
||||
|
@ -61,6 +61,7 @@ public:
|
||||
#ifdef HAVE_LIBOPK
|
||||
const std::string &getCategory() { return category; }
|
||||
bool isOpk() { return isOPK; }
|
||||
const std::string &getOpkFile() { return opkFile; }
|
||||
|
||||
LinkApp(GMenu2X *gmenu2x, Touchscreen &ts, InputManager &inputMgr,
|
||||
const char* linkfile, struct OPK *opk = NULL);
|
||||
|
31
src/menu.cpp
31
src/menu.cpp
@ -34,6 +34,7 @@
|
||||
#include "gmenu2x.h"
|
||||
#include "linkapp.h"
|
||||
#include "menu.h"
|
||||
#include "monitor.h"
|
||||
#include "filelister.h"
|
||||
#include "utilities.h"
|
||||
#include "debug.h"
|
||||
@ -67,6 +68,9 @@ Menu::Menu(GMenu2X *gmenu2x, Touchscreen &ts)
|
||||
continue;
|
||||
|
||||
readPackages(path);
|
||||
#ifdef ENABLE_INOTIFY
|
||||
monitors.push_back(new Monitor(path.c_str()));
|
||||
#endif
|
||||
}
|
||||
closedir(dirp);
|
||||
}
|
||||
@ -533,6 +537,33 @@ void Menu::readPackages(std::string parentDir)
|
||||
|
||||
closedir(dirp);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_INOTIFY
|
||||
void Menu::removePackageLink(std::string path)
|
||||
{
|
||||
for (vector< vector<Link*> >::iterator section = links.begin();
|
||||
section < links.end(); section++) {
|
||||
for (vector<Link*>::iterator link = section->begin();
|
||||
link < section->end(); link++) {
|
||||
LinkApp *app = dynamic_cast<LinkApp *> (*link);
|
||||
if (!app || !app->isOpk() || app->getOpkFile().empty())
|
||||
continue;
|
||||
|
||||
if (app->isOpk() && app->getOpkFile().compare(path) == 0) {
|
||||
DEBUG("Removing link corresponding to package %s\n",
|
||||
app->getOpkFile().c_str());
|
||||
section->erase(link);
|
||||
if (section - links.begin() == iSection
|
||||
&& iLink == (int) section->size())
|
||||
setLinkIndex(iLink - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ERROR("Unable to find link corresponding to %s\n", path.c_str());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void Menu::readLinksOfSection(std::string path, std::vector<std::string> &linkfiles)
|
||||
|
12
src/menu.h
12
src/menu.h
@ -28,6 +28,7 @@
|
||||
|
||||
class LinkApp;
|
||||
class GMenu2X;
|
||||
class Monitor;
|
||||
|
||||
/**
|
||||
Handles the menu structure
|
||||
@ -52,7 +53,9 @@ private:
|
||||
#ifdef HAVE_LIBOPK
|
||||
// Load all the .opk packages of the given directory
|
||||
void readPackages(std::string parentDir);
|
||||
void openPackage(std::string path);
|
||||
#ifdef ENABLE_INOTIFY
|
||||
std::vector<Monitor *> monitors;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Load all the links on the given section directory.
|
||||
@ -62,6 +65,13 @@ public:
|
||||
Menu(GMenu2X *gmenu2x, Touchscreen &ts);
|
||||
~Menu();
|
||||
|
||||
#ifdef HAVE_LIBOPK
|
||||
void openPackage(std::string path);
|
||||
#ifdef ENABLE_INOTIFY
|
||||
void removePackageLink(std::string path);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
std::vector<Link*> *sectionLinks(int i = -1);
|
||||
|
||||
int selSectionIndex();
|
||||
|
71
src/monitor.cpp
Normal file
71
src/monitor.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#ifdef ENABLE_INOTIFY
|
||||
#include "debug.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <pthread.h>
|
||||
#include <SDL.h>
|
||||
#include <signal.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "monitor.h"
|
||||
|
||||
static void * inotify_thd(void *p)
|
||||
{
|
||||
const char *path = (const char *) p;
|
||||
int wd, fd;
|
||||
|
||||
DEBUG("Starting inotify thread for path %s...\n", path);
|
||||
|
||||
fd = inotify_init();
|
||||
if (fd == -1) {
|
||||
ERROR("Unable to start inotify\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wd = inotify_add_watch(fd, path, IN_MOVED_FROM | IN_MOVED_TO |
|
||||
IN_CLOSE_WRITE | IN_DELETE);
|
||||
if (wd == -1) {
|
||||
ERROR("Unable to add inotify watch\n");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG("Starting watching directory %s\n", path);
|
||||
|
||||
for (;;) {
|
||||
size_t len = sizeof(struct inotify_event) + NAME_MAX + 1;
|
||||
struct inotify_event event;
|
||||
char buf[256];
|
||||
|
||||
read(fd, &event, len);
|
||||
sprintf(buf, "%s/%s", path, event.name);
|
||||
|
||||
/* Don't bother other files than OPKs */
|
||||
len = strlen(event.name);
|
||||
if (len < 5 || strncmp(event.name + len - 4, ".opk", 4))
|
||||
continue;
|
||||
|
||||
SDL_UserEvent e = {
|
||||
.type = SDL_USEREVENT,
|
||||
.code = (int) (event.mask & (IN_MOVED_TO | IN_CLOSE_WRITE)),
|
||||
.data1 = strdup(buf),
|
||||
.data2 = NULL,
|
||||
};
|
||||
|
||||
/* Inject an user event, that will be handled as a "repaint"
|
||||
* event by the InputManager */
|
||||
SDL_PushEvent((SDL_Event *) &e);
|
||||
}
|
||||
}
|
||||
|
||||
Monitor::Monitor(std::string path) : path(path)
|
||||
{
|
||||
pthread_create(&thd, NULL, inotify_thd, (void *) path.c_str());
|
||||
}
|
||||
|
||||
Monitor::~Monitor(void)
|
||||
{
|
||||
pthread_kill(thd, SIGINT);
|
||||
}
|
||||
#endif
|
17
src/monitor.h
Normal file
17
src/monitor.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef __MONITOR_H__
|
||||
#define __MONITOR_H__
|
||||
|
||||
#include <string>
|
||||
#include <pthread.h>
|
||||
|
||||
class Monitor {
|
||||
public:
|
||||
Monitor(std::string path);
|
||||
~Monitor();
|
||||
|
||||
private:
|
||||
std::string path;
|
||||
pthread_t thd;
|
||||
};
|
||||
|
||||
#endif /* __MONITOR_H__ */
|
Loading…
Reference in New Issue
Block a user