SOLIB = libpnd.so.1 # canonicle name
SOLIB1 = libpnd.so.1.0.1 # versioned name
XMLOBJ = lib/tinyxml/tinystr.o lib/tinyxml/tinyxml.o lib/tinyxml/tinyxmlerror.o lib/tinyxml/tinyxmlparser.o
-ALLOBJ = pnd_conf.o pnd_container.o pnd_discovery.o pnd_pxml.o pnd_notify.o pnd_locate.o pnd_tinyxml.o pnd_pndfiles.o pnd_apps.o pnd_utility.o pnd_desktop.o pnd_io_gpio.o pnd_logger.o
+ALLOBJ = pnd_conf.o pnd_container.o pnd_discovery.o pnd_pxml.o pnd_notify.o pnd_locate.o pnd_tinyxml.o pnd_pndfiles.o pnd_apps.o pnd_utility.o pnd_desktop.o pnd_io_gpio.o pnd_logger.o pnd_dbusnotify.o
-all: ${SOLIB} ${LIB} conftest discotest notifytest pndnotifyd rawpxmltest pndvalidator loggertest pnd_run pndevmapperd pnd_info
+all: ${SOLIB} ${LIB} conftest discotest notifytest pndnotifyd rawpxmltest pndvalidator loggertest dbusnotifytest pnd_run pndevmapperd pnd_info
clean:
- ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o bin/discotest loggertest.o bin/loggertest bin/notifytest notifytest.o bin/rawpxmltest rawpxmltest.o bin/pnd_run pnd_run.o pnd_info.o bin/pnd_info bin/pndevmapperd pndevmapperd.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/menu/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/bin/pnd_run deployment/usr/bin/pnd_info deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd bin/pndvalidator pndvalidator.o deployment/usr/bin/pndevmapperd testdata/menuicons/*
+ ${RM} -f ${ALLOBJ} ${XMLOBJ} ${LIB} ${SOLIB1} locatetest.o bin/locatetest conftest.o bin/conftest discotest.o bin/discotest dbusnotifytest.o bin/dbusnotifytest loggertest.o bin/loggertest bin/notifytest notifytest.o bin/rawpxmltest rawpxmltest.o bin/pnd_run pnd_run.o pnd_info.o bin/pnd_info bin/pndevmapperd pndevmapperd.o bin/pndnotifyd pndnotifyd.o ${SOLIB} testdata/dotdesktop/*.desktop testdata/menu/*.desktop testdata/apps/*.pnd testdata/dotdesktop/*.png deployment/usr/lib/libpnd* deployment/usr/bin/pndnotifyd deployment/usr/bin/pnd_run deployment/usr/bin/pnd_info deployment/usr/pandora/scripts/* deployment/etc/sudoers deployment/etc/init.d/pndnotifyd bin/pndvalidator pndvalidator.o deployment/usr/bin/pndevmapperd testdata/menuicons/*
${RM} -rf deployment/media
find . -name "*~*" -exec rm {} \; -print
loggertest: loggertest.o ${LIB}
${CC} -lstdc++ -o bin/loggertest loggertest.o libpnd.a
+
+dbusnotifytest: dbusnotifytest.o ${LIB}
+ ${CC} -lstdc++ -o bin/dbusnotifytest dbusnotifytest.o libpnd.a
#include "pnd_utility.h"
#include "pnd_desktop.h"
#include "pnd_logger.h"
+#include "pnd_dbusnotify.h"
// this piece of code was simpler once; but need to grow it a bit and in a rush
// moving all these to globals rather than refactor the code a bit; tsk tsk..
char g_username [ 128 ]; // since we have to wait for login (!!), store username here
// notifier handle
pnd_notify_handle nh = 0;
+pnd_dbusnotify_handle dbh = 0;
// constants
#define PNDNOTIFYD_LOGLEVEL "pndnotifyd.loglevel"
// decl's
void consume_configuration ( void );
void setup_notifications ( void );
+void sigint_handler ( int n );
void sighup_handler ( int n );
void process_discoveries ( pnd_box_handle applist, char *emitdesktoppath, char *emiticonpath );
unsigned char perform_discoveries ( char *appspath, char *overridespath,
sigaction ( SIGHUP, &siggy, NULL );
+ siggy.sa_handler = sigint_handler;
+ sigaction ( SIGINT, &siggy, NULL );
+
/* set up notifies
*/
setup_notifications();
//}
+ dbh = pnd_dbusnotify_init();
+
/* daemon main loop
*/
+ unsigned char watch_inotify, watch_dbus;
while ( 1 ) {
+ watch_dbus = 0;
+ watch_inotify = 0;
+
+ if ( dbh ) {
+ watch_dbus = pnd_dbusnotify_rediscover_p ( dbh );
+ }
+
+ if ( ! watch_dbus && nh ) {
+ watch_inotify = pnd_notify_rediscover_p ( nh );
+ }
+
// need to rediscover?
- if ( scanonlaunch ||
- pnd_notify_rediscover_p ( nh ) )
- {
+ if ( scanonlaunch || watch_inotify || watch_dbus ) {
- if ( time ( NULL ) - createtime <= 2 ) {
- pnd_log ( pndn_rem, "Rediscovery request comes to soon after previous discovery; skipping.\n" );
- sleep ( interval_secs );
- continue;
- }
+ // by this point, the watched directories have notified us that something of relevent
+ // has occurred; we should be clever, but we're not, so just re-brute force the
+ // discovery and spit out .desktop files..
+ pnd_log ( pndn_rem, "------------------------------------------------------\n" );
- createtime = time ( NULL ); // all 'new' .destops are created at or after this time; prev are old.
+ pnd_log ( pndn_rem, "System changes detected in dbus or watched paths .. performing re-discover!\n" );
// if this was a forced scan, lets not do that next iteration
if ( scanonlaunch ) {
+ pnd_log ( pndn_rem, "scan-on-first-launch detected an event\n" );
scanonlaunch = 0;
}
- // by this point, the watched directories have notified us that something of relevent
- // has occurred; we should be clever, but we're not, so just re-brute force the
- // discovery and spit out .desktop files..
+ if ( watch_inotify ) {
+ pnd_log ( pndn_rem, "inotify detected an event\n" );
+ }
+
+ if ( watch_dbus ) {
+ pnd_log ( pndn_rem, "dbusnotify detected an event\n" );
+ pnd_notify_shutdown ( nh );
+ nh = 0;
+ }
+
+ if ( time ( NULL ) - createtime <= 2 ) {
+ pnd_log ( pndn_rem, "Rediscovery request comes to soon after previous discovery; skipping.\n" );
+ sleep ( interval_secs );
+ continue;
+ }
+
pnd_log ( pndn_rem, "------------------------------------------------------\n" );
- pnd_log ( pndn_rem, "Changes within watched paths .. performing re-discover!\n" );
+
+ createtime = time ( NULL ); // all 'new' .destops are created at or after this time; prev are old.
/* run the discovery
*/
- pnd_log ( pndn_rem, "Scanning desktop paths----------------------------\n" );
+ pnd_log ( pndn_rem, " Scanning desktop paths----------------------------\n" );
if ( ! perform_discoveries ( desktop_appspath, overridespath, desktop_dotdesktoppath, desktop_iconpath ) ) {
- pnd_log ( pndn_rem, "No applications found in desktop search path\n" );
+ pnd_log ( pndn_rem, " No applications found in desktop search path\n" );
}
if ( menu_appspath && menu_dotdesktoppath && menu_iconpath ) {
- pnd_log ( pndn_rem, "Scanning menu paths----------------------------\n" );
+ pnd_log ( pndn_rem, " Scanning menu paths----------------------------\n" );
if ( ! perform_discoveries ( menu_appspath, overridespath, menu_dotdesktoppath, menu_iconpath ) ) {
- pnd_log ( pndn_rem, "No applications found in menu search path\n" );
+ pnd_log ( pndn_rem, " No applications found in menu search path\n" );
}
}
// since its entirely likely new directories have been found (ie: SD with a directory structure was inserted)
// we should re-apply watches to catch all these new directories; ie: user might use on-device browser to
// drop in new applications, or use the shell to juggle them around, or any number of activities.
- //setup_notifications();
+ if ( watch_dbus ) {
+ setup_notifications();
+ }
} // need to rediscover?
/* shutdown
*/
pnd_notify_shutdown ( nh );
+ pnd_dbusnotify_shutdown ( dbh );
return ( 0 );
}
return;
}
+void sigint_handler ( int n ) {
+
+ pnd_log ( pndn_rem, "---[ SIGINT received ]---\n" );
+
+ if ( dbh ) {
+ pnd_dbusnotify_shutdown ( dbh );
+ }
+
+ if ( nh ) {
+ pnd_notify_shutdown ( nh );
+ }
+
+ return;
+}
+
// This very recently was inline code; just slight refactor to functionize it so that it can be
// reused in a couple of places. Simple code with simple design quickly became too large for
// its simple design; should revisit a lot of these little things..
searchpath /media/*/pandora/apps:/media/*/pandora/desktop:/media/*/pandora/menu:/usr/pandora/apps
# notifypath is a list of paths to monitor; if anything in those paths changes, the searchpath is rescanned
# note that for each path chunk, all current subdirs of that path are also watched)
-notifypath /media:/media/*/pandora/apps:/media/*/pandora/desktop:/media/*/pandora/menu:/usr/pandora/apps
+notifypath /media/*/pandora/apps:/media/*/pandora/desktop:/media/*/pandora/menu:/usr/pandora/apps
# PXMLs may be overridden .. ie: overrides are a subset of PXML, where the values are copied over the full PXML
[overrides]
--- /dev/null
+
+#ifndef h_dbusnotify_h
+#define h_dbusnotify_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* pnd_dbusnotify_handle;
+
+/* An option is to use dbus for a lot of things, or even specific things such as
+ * watching for media to be inserted or ejected; one could supplement such info
+ * with inotify for file-moves.
+ * Really, we need a serious model for watching and receiving system state changes
+ * but I started simple, so going to try to keep it simple. For now.
+ */
+
+/* must invoke this to obtain a handle; other notify functions require it of course.
+ * Returns NULL on failure.
+ */
+pnd_dbusnotify_handle pnd_dbusnotify_init ( void );
+
+/* shutdown..
+ */
+void pnd_dbusnotify_shutdown ( pnd_dbusnotify_handle h );
+
+/* HACK HACK HACK
+ * I'd like to have a real dbus-listener here using libdbus/whatever, but for now
+ * I'm going to implement a lame little hack to use dbus-monitor, as time is tight!
+ * HACK HACK HACK
+ *
+ */
+unsigned char pnd_dbusnotify_rediscover_p ( pnd_dbusnotify_handle h );
+
+#ifdef __cplusplus
+} /* "C" */
+#endif
+
+#endif
--- /dev/null
+
+#include <stdio.h> // for stdio, NULL
+#include <stdlib.h> // for malloc, etc
+#include <unistd.h> // for close
+#include <time.h> // for time()
+#include <sys/types.h> // for kill
+#include <signal.h> // for kill signal
+#include <string.h> // for bzero
+#include <poll.h> // for poll()
+
+#include "pnd_dbusnotify.h"
+#include "pnd_logger.h"
+
+/* HACK HACK HACK
+ * Not yet doing a real libdbus implementation.
+ * First cut is using dbus-monitor; I'll work on a real dbus listener soon.
+ * HACK HACK HACK
+ */
+
+typedef struct {
+ pid_t child_pid; // pid for dbus-monitor
+ int fd [ 2 ]; // pipe fd pair
+} pnd_dbusnotify_t;
+
+#define MONITOR "/usr/bin/dbus-monitor"
+#define MONARG1 "--system"
+#define MONARG2 "interface=org.freedesktop.Hal.Device"
+#define MONGREP "volume.is_mounted"
+
+pnd_dbusnotify_handle pnd_dbusnotify_init ( void ) {
+ pnd_dbusnotify_t *p;
+
+ // get thee a handle
+ // and I will brandish it for Zo Kath Ra
+
+ p = malloc ( sizeof(pnd_dbusnotify_t) );
+
+ if ( ! p ) {
+ return ( NULL ); // uhh..
+ }
+
+ bzero ( p, sizeof(pnd_dbusnotify_t) );
+
+ // can we make a pipe?
+ if ( pipe ( p -> fd ) == -1 ) {
+ free ( p );
+ return ( NULL );
+ }
+
+ // spawn child process
+ p -> child_pid = fork();
+
+ if ( p -> child_pid == -1 ) {
+ free ( p );
+ return ( NULL ); // borked
+
+ } else if ( p -> child_pid == 0 ) {
+ // child
+
+ close ( p -> fd [ 0 ] ); // ditch stdin on child
+ dup2 ( p -> fd [ 1 ], 1 ); // assign write-end of pipe to stdout
+ close ( p -> fd [ 1 ] ); // we don't need this anymore anyway
+ execlp ( MONITOR, MONITOR, MONARG1, MONARG2, NULL );
+
+ exit ( 1 ); // damnit
+
+ } else {
+ // parent
+
+ close ( p -> fd [ 1 ] ); // ditch write end, we're a grepper
+
+ } // child or parent?
+
+ return ( p );
+}
+
+void pnd_dbusnotify_shutdown ( pnd_dbusnotify_handle h ) {
+ pnd_dbusnotify_t *p = (pnd_dbusnotify_t*) h;
+
+ // free up
+ close ( p -> fd [ 0 ] ); // kill reader end of pipe
+
+ // destroy child process
+ kill ( p -> child_pid, SIGKILL );
+
+ free ( p );
+
+ return;
+}
+
+unsigned char pnd_dbusnotify_rediscover_p ( pnd_dbusnotify_handle h ) {
+ pnd_dbusnotify_t *p = (pnd_dbusnotify_t*) h;
+ int r;
+ struct pollfd fds [ 1 ];
+
+ fds [ 0 ].fd = p -> fd [ 0 ]; // read side of pipe
+ fds [ 0 ].events = POLLIN | POLLPRI /* | POLLRDHUP */;
+ fds [ 0 ].revents = 0;
+
+ r = poll ( fds, 1, 0 /* timeout*/ );
+
+ if ( r < 0 ) {
+ // error
+ // should rebuild a new child process
+ return ( 0 );
+
+ } else if ( r == 0 ) {
+ // no input on the pipe
+ return ( 0 );
+
+ } // activity
+
+ // something on the pipe, lets check it
+
+ if ( fds [ 0 ].revents & ( POLLERR|POLLHUP/*|POLLRDHUP*/ ) ) {
+ // bad
+ // should rebuild a new child process
+ return ( 0 );
+ }
+
+ // something useful on the pipe
+ char buf [ 4096 ];
+ int readcount;
+
+ readcount = read ( fds [ 0 ].fd, buf, 4000 );
+
+ if ( readcount < 0 ) {
+ // error
+ return ( 0 );
+ }
+
+ // terminate the string
+ *( buf + readcount + 1 ) = '\0';
+
+ if ( strstr ( buf, MONGREP ) != NULL ) {
+ return ( 1 );
+ }
+
+ return ( 0 );
+}
--- /dev/null
+
+#include <stdio.h> // for stdio
+#include <unistd.h> // for exit()
+#include <stdlib.h> // for exit()
+#include <time.h> // for time
+
+#include "pnd_conf.h"
+#include "pnd_dbusnotify.h"
+
+int main ( int argc, char *argv[] ) {
+ pnd_dbusnotify_handle h;
+
+ h = pnd_dbusnotify_init();
+
+ time_t start = time ( NULL );
+
+ while ( time ( NULL ) - start < 20 ) {
+ printf ( "Tick %u\n", (unsigned int) ( time ( NULL ) - start ) );
+
+ if ( pnd_dbusnotify_rediscover_p ( h ) ) {
+ printf ( "Event!\n" );
+ }
+
+ fflush ( stdout );
+ sleep ( 1 );
+
+ } // while
+
+ pnd_dbusnotify_shutdown ( h );
+
+ return ( 0 );
+}