1
0
mirror of git://projects.qi-hardware.com/gmenu2x.git synced 2024-11-26 07:59:42 +02:00

Monitor OPK folders using inotify and automatically add/delete links

This commit is contained in:
Paul Cercueil 2013-07-16 13:36:18 -04:00
parent 1467c9b9d7
commit 13b3d8e0ca
10 changed files with 162 additions and 7 deletions

View File

@ -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)

View File

@ -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@

View File

@ -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"] );

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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
View 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
View 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__ */