-rw-r--r-- | library/alarmserver.cpp | 11 |
1 files changed, 1 insertions, 10 deletions
diff --git a/library/alarmserver.cpp b/library/alarmserver.cpp index 7e6e515..5e4dd18 100644 --- a/library/alarmserver.cpp +++ b/library/alarmserver.cpp @@ -31,266 +31,257 @@ #include <qpe/qcopenvelope_qws.h> #include "alarmserver.h" #include <qpe/timeconversion.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> #include <unistd.h> struct timerEventItem { time_t UTCtime; QCString channel, message; int data; bool operator==( const timerEventItem &right ) const { return ( UTCtime == right.UTCtime && channel == right.channel && message == right.message && data == right.data ); } }; class TimerReceiverObject : public QObject { public: TimerReceiverObject() { } ~TimerReceiverObject() { } void resetTimer(); void setTimerEventItem(); void deleteTimer(); protected: void timerEvent( QTimerEvent *te ); private: QString atfilename; }; TimerReceiverObject *timerEventReceiver = NULL; QList<timerEventItem> timerEventList; timerEventItem *nearestTimerEvent = NULL; // set the timer to go off on the next event in the list void setNearestTimerEvent() { nearestTimerEvent = NULL; QListIterator<timerEventItem> it( timerEventList ); if ( *it ) nearestTimerEvent = *it; for ( ; *it; ++it ) if ( (*it)->UTCtime < nearestTimerEvent->UTCtime ) nearestTimerEvent = *it; if (nearestTimerEvent) timerEventReceiver->resetTimer(); else timerEventReceiver->deleteTimer(); } //store current state to file //Simple implementation. Should run on a timer. static void saveState() { QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" ); if ( timerEventList.isEmpty() ) { unlink( savefilename ); return; } QFile savefile(savefilename+".new"); if ( savefile.open(IO_WriteOnly) ) { QDataStream ds( &savefile ); //save QListIterator<timerEventItem> it( timerEventList ); for ( ; *it; ++it ) { ds << it.current()->UTCtime; ds << it.current()->channel; ds << it.current()->message; ds << it.current()->data; } savefile.close(); unlink( savefilename ); QDir d; d.rename(savefilename+".new",savefilename); } } /*! Sets up the alarm server. Restoring to previous state (session management). */ void AlarmServer::initialize() { //read autosave file and put events in timerEventList QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" ); QFile savefile(savefilename); if ( savefile.open(IO_ReadOnly) ) { QDataStream ds( &savefile ); while ( !ds.atEnd() ) { timerEventItem *newTimerEventItem = new timerEventItem; ds >> newTimerEventItem->UTCtime; ds >> newTimerEventItem->channel; ds >> newTimerEventItem->message; ds >> newTimerEventItem->data; timerEventList.append( newTimerEventItem ); } savefile.close(); if (!timerEventReceiver) timerEventReceiver = new TimerReceiverObject; setNearestTimerEvent(); } } static const char* atdir = "/var/spool/at/"; static bool triggerAtd( bool writeHWClock = FALSE ) { QFile trigger(QString(atdir) + "trigger"); if ( trigger.open(IO_WriteOnly|IO_Raw) ) { - - const char* data = -#ifdef QT_QWS_SHARP - //custom atd only writes HW Clock if we write a 'W' - ( writeHWClock ) ? "W\n" : -#endif - data = "\n"; - int len = strlen(data); - int total_written = trigger.writeBlock(data,len); - if ( total_written != len ) { + if ( trigger.writeBlock("\n",2) != 2 ) { QMessageBox::critical( 0, QObject::tr( "Out of Space" ), QObject::tr( "Unable to schedule alarm.\nFree some memory and try again." ) ); trigger.close(); QFile::remove( trigger.name() ); return FALSE; } return TRUE; } return FALSE; } void TimerReceiverObject::deleteTimer() { if ( !atfilename.isEmpty() ) { unlink( atfilename ); atfilename = QString::null; triggerAtd( FALSE ); } } void TimerReceiverObject::resetTimer() { const int maxsecs = 2147000; int total_written; QDateTime nearest = TimeConversion::fromUTC(nearestTimerEvent->UTCtime); QDateTime now = QDateTime::currentDateTime(); if ( nearest < now ) nearest = now; int secs = TimeConversion::secsTo( now, nearest ); if ( secs > maxsecs ) { // too far for millisecond timing secs = maxsecs; } // System timer (needed so that we wake from deep sleep), // from the Epoch in seconds. // int at_secs = TimeConversion::toUTC(nearest); // qDebug("reset timer to %d seconds from Epoch",at_secs); QString fn = atdir + QString::number(at_secs) + "." + QString::number(getpid()); if ( fn != atfilename ) { QFile atfile(fn+".new"); if ( atfile.open(IO_WriteOnly|IO_Raw) ) { // just wake up and delete the at file QString cmd = "#!/bin/sh\nrm " + fn; total_written = atfile.writeBlock(cmd.latin1(),cmd.length()); if ( total_written != int(cmd.length()) ) { QMessageBox::critical( 0, tr("Out of Space"), tr("Unable to schedule alarm.\n" "Please free up space and try again") ); atfile.close(); QFile::remove( atfile.name() ); return; } atfile.close(); unlink( atfilename ); QDir d; d.rename(fn+".new",fn); chmod(fn.latin1(),0755); atfilename = fn; triggerAtd( FALSE ); } else { qWarning("Cannot open atd file %s",fn.latin1()); } } // Qt timers (does the actual alarm) // from now in milliseconds // qDebug("AlarmServer waiting %d seconds",secs); startTimer( 1000 * secs + 500 ); } void TimerReceiverObject::timerEvent( QTimerEvent * ) { bool needSave = FALSE; killTimers(); if (nearestTimerEvent) { if ( nearestTimerEvent->UTCtime <= TimeConversion::toUTC(QDateTime::currentDateTime()) ) { #ifndef QT_NO_COP QCopEnvelope e( nearestTimerEvent->channel, nearestTimerEvent->message ); e << TimeConversion::fromUTC( nearestTimerEvent->UTCtime ) << nearestTimerEvent->data; #endif timerEventList.remove( nearestTimerEvent ); needSave = TRUE; } setNearestTimerEvent(); } else { resetTimer(); } if ( needSave ) saveState(); } /*! \class AlarmServer alarmserver.h \brief The AlarmServer class allows alarms to be scheduled and unscheduled. Applications can schedule alarms with addAlarm() and can unschedule alarms with deleteAlarm(). When the time for an alarm to go off is reached the specified \link qcop.html QCop\endlink message is sent on the specified channel (optionally with additional data). Scheduling an alarm using this class is important (rather just using a QTimer) since the machine may be asleep and needs to get woken up using the Linux kernel which implements this at the kernel level to minimize battery usage while asleep. \ingroup qtopiaemb \sa QCopEnvelope */ /*! Schedules an alarm to go off at (or soon after) time \a when. When the alarm goes off, the \link qcop.html QCop\endlink \a message will be sent to \a channel, with \a data as a parameter. If this function is called with exactly the same data as a previous call the subsequent call is ignored, so there is only ever one alarm with a given set of parameters. \sa deleteAlarm() */ void AlarmServer::addAlarm ( QDateTime when, const QCString& channel, const QCString& message, int data) |