00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "alarmserver.h"
00022
00023 #include <qpe/global.h>
00024 #include <qpe/qpeapplication.h>
00025 #include <qpe/qcopenvelope_qws.h>
00026 #include <qpe/timeconversion.h>
00027
00028 #include <qdir.h>
00029
00030 #include <sys/types.h>
00031 #include <sys/stat.h>
00032 #include <stdlib.h>
00033 #include <unistd.h>
00034
00035
00036 #undef USE_ATD // not used anymore -- we run opie-alarm on suspend/resume
00037
00038
00039 struct timerEventItem
00040 {
00041 time_t UTCtime;
00042 QCString channel, message;
00043 int data;
00044 bool operator==( const timerEventItem &right ) const
00045 {
00046 return ( UTCtime == right.UTCtime
00047 && channel == right.channel
00048 && message == right.message
00049 && data == right.data );
00050 }
00051 };
00052
00053 class TimerReceiverObject : public QObject
00054 {
00055 public:
00056 TimerReceiverObject()
00057 { }
00058 ~TimerReceiverObject()
00059 { }
00060 void resetTimer();
00061 void setTimerEventItem();
00062 void deleteTimer();
00063 protected:
00064 void timerEvent( QTimerEvent *te );
00065
00066 #ifdef USE_ATD
00067 private:
00068 QString atfilename;
00069 #endif
00070 };
00071
00072 TimerReceiverObject *timerEventReceiver = NULL;
00073 QList<timerEventItem> timerEventList;
00074 timerEventItem *nearestTimerEvent = NULL;
00075
00076
00077
00078 void setNearestTimerEvent()
00079 {
00080 nearestTimerEvent = NULL;
00081 QListIterator<timerEventItem> it( timerEventList );
00082 if ( *it )
00083 nearestTimerEvent = *it;
00084 for ( ; *it; ++it )
00085 if ( (*it)->UTCtime < nearestTimerEvent->UTCtime )
00086 nearestTimerEvent = *it;
00087 if (nearestTimerEvent)
00088 timerEventReceiver->resetTimer();
00089 else
00090 timerEventReceiver->deleteTimer();
00091 }
00092
00093
00094
00095
00096
00097 static void saveState()
00098 {
00099 QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" );
00100 if ( timerEventList.isEmpty() ) {
00101 unlink( savefilename );
00102 return ;
00103 }
00104
00105 QFile savefile(savefilename + ".new");
00106 if ( savefile.open(IO_WriteOnly) ) {
00107 QDataStream ds( &savefile );
00108
00109
00110
00111 QListIterator<timerEventItem> it( timerEventList );
00112 for ( ; *it; ++it ) {
00113 ds << it.current()->UTCtime;
00114 ds << it.current()->channel;
00115 ds << it.current()->message;
00116 ds << it.current()->data;
00117 }
00118
00119
00120 savefile.close();
00121 unlink( savefilename );
00122 QDir d;
00123 d.rename(savefilename + ".new", savefilename);
00124
00125 }
00126 }
00127
00131 void AlarmServer::initialize()
00132 {
00133
00134
00135 QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" );
00136
00137 QFile savefile(savefilename);
00138 if ( savefile.open(IO_ReadOnly) ) {
00139 QDataStream ds( &savefile );
00140 while ( !ds.atEnd() ) {
00141 timerEventItem *newTimerEventItem = new timerEventItem;
00142 ds >> newTimerEventItem->UTCtime;
00143 ds >> newTimerEventItem->channel;
00144 ds >> newTimerEventItem->message;
00145 ds >> newTimerEventItem->data;
00146 timerEventList.append( newTimerEventItem );
00147 }
00148 savefile.close();
00149 if (!timerEventReceiver)
00150 timerEventReceiver = new TimerReceiverObject;
00151 setNearestTimerEvent();
00152 }
00153 }
00154
00155
00156 #ifdef USE_ATD
00157
00158 static const char* atdir = "/var/spool/at/";
00159
00160 static bool triggerAtd( bool writeHWClock = FALSE )
00161 {
00162 QFile trigger(QString(atdir) + "trigger");
00163 if ( trigger.open(IO_WriteOnly | IO_Raw) ) {
00164 if ( trigger.writeBlock("\n", 2) != 2 ) {
00165 QMessageBox::critical( 0, QObject::tr( "Out of Space" ),
00166 QObject::tr( "Unable to schedule alarm.\nFree some memory and try again." ) );
00167 trigger.close();
00168 QFile::remove
00169 ( trigger.name() );
00170 return FALSE;
00171 }
00172 return TRUE;
00173 }
00174 return FALSE;
00175 }
00176
00177 #else
00178
00179 static bool writeResumeAt ( time_t wakeup )
00180 {
00181 FILE *fp = ::fopen ( "/var/run/resumeat", "w" );
00182
00183 if ( fp ) {
00184 ::fprintf ( fp, "%d\n", (int) wakeup );
00185 ::fclose ( fp );
00186 }
00187 else
00188 qWarning ( "Failed to write wakeup time to /var/run/resumeat" );
00189
00190 return ( fp );
00191 }
00192
00193 #endif
00194
00195 void TimerReceiverObject::deleteTimer()
00196 {
00197 #ifdef USE_ATD
00198 if ( !atfilename.isEmpty() ) {
00199 unlink( atfilename );
00200 atfilename = QString::null;
00201 triggerAtd( FALSE );
00202 }
00203 #else
00204 writeResumeAt ( 0 );
00205 #endif
00206 }
00207
00208 void TimerReceiverObject::resetTimer()
00209 {
00210 const int maxsecs = 2147000;
00211 QDateTime nearest = TimeConversion::fromUTC(nearestTimerEvent->UTCtime);
00212 QDateTime now = QDateTime::currentDateTime();
00213 if ( nearest < now )
00214 nearest = now;
00215 int secs = TimeConversion::secsTo( now, nearest );
00216 if ( secs > maxsecs ) {
00217
00218 secs = maxsecs;
00219 }
00220
00221
00222
00223
00224 int at_secs = TimeConversion::toUTC(nearest);
00225
00226
00227 #ifdef USE_ATD
00228
00229 QString fn = atdir + QString::number(at_secs) + "."
00230 + QString::number(getpid());
00231 if ( fn != atfilename ) {
00232 QFile atfile(fn + ".new");
00233 if ( atfile.open(IO_WriteOnly | IO_Raw) ) {
00234 int total_written;
00235
00236
00237 QString cmd = "#!/bin/sh\nrm " + fn;
00238 total_written = atfile.writeBlock(cmd.latin1(), cmd.length());
00239 if ( total_written != int(cmd.length()) ) {
00240 QMessageBox::critical( 0, tr("Out of Space"),
00241 tr("Unable to schedule alarm.\n"
00242 "Please free up space and try again") );
00243 atfile.close();
00244 QFile::remove
00245 ( atfile.name() );
00246 return ;
00247 }
00248 atfile.close();
00249 unlink( atfilename );
00250 QDir d;
00251 d.rename(fn + ".new", fn);
00252 chmod(fn.latin1(), 0755);
00253 atfilename = fn;
00254 triggerAtd( FALSE );
00255 }
00256 else {
00257 qWarning("Cannot open atd file %s", fn.latin1());
00258 }
00259 }
00260 #else
00261 writeResumeAt ( at_secs );
00262
00263 #endif
00264
00265
00266
00267
00268 qDebug("AlarmServer waiting %d seconds", secs);
00269 startTimer( 1000 * secs + 500 );
00270 }
00271
00272 void TimerReceiverObject::timerEvent( QTimerEvent * )
00273 {
00274 bool needSave = FALSE;
00275 killTimers();
00276 if (nearestTimerEvent) {
00277 if ( nearestTimerEvent->UTCtime
00278 <= TimeConversion::toUTC(QDateTime::currentDateTime()) ) {
00279 #ifndef QT_NO_COP
00280 QCopEnvelope e( nearestTimerEvent->channel,
00281 nearestTimerEvent->message );
00282 e << TimeConversion::fromUTC( nearestTimerEvent->UTCtime )
00283 << nearestTimerEvent->data;
00284 #endif
00285
00286 timerEventList.remove( nearestTimerEvent );
00287 needSave = TRUE;
00288 }
00289 setNearestTimerEvent();
00290 }
00291 else {
00292 resetTimer();
00293 }
00294 if ( needSave )
00295 saveState();
00296 }
00297
00388 void AlarmServer::addAlarm ( QDateTime when, const QCString& channel,
00389 const QCString& message, int data)
00390 {
00391 if ( qApp->type() == QApplication::GuiServer ) {
00392 bool needSave = FALSE;
00393
00394
00395 if (!timerEventReceiver)
00396 timerEventReceiver = new TimerReceiverObject;
00397
00398 timerEventItem *newTimerEventItem = new timerEventItem;
00399 newTimerEventItem->UTCtime = TimeConversion::toUTC( when );
00400 newTimerEventItem->channel = channel;
00401 newTimerEventItem->message = message;
00402 newTimerEventItem->data = data;
00403
00404 QListIterator<timerEventItem> it( timerEventList );
00405 for ( ; *it; ++it )
00406 if ( *(*it) == *newTimerEventItem )
00407 return ;
00408
00409 timerEventList.append( newTimerEventItem );
00410 needSave = TRUE;
00411
00412 if ( nearestTimerEvent ) {
00413 if (newTimerEventItem->UTCtime < nearestTimerEvent->UTCtime) {
00414 nearestTimerEvent = newTimerEventItem;
00415 timerEventReceiver->killTimers();
00416 timerEventReceiver->resetTimer();
00417 }
00418 }
00419 else {
00420 nearestTimerEvent = newTimerEventItem;
00421 timerEventReceiver->resetTimer();
00422 }
00423 if ( needSave )
00424 saveState();
00425 }
00426 else {
00427 #ifndef QT_NO_COP
00428 QCopEnvelope e( "QPE/System", "addAlarm(QDateTime,QCString,QCString,int)" );
00429 e << when << channel << message << data;
00430 #endif
00431
00432 }
00433 }
00434
00448 void AlarmServer::deleteAlarm (QDateTime when, const QCString& channel, const QCString& message, int data)
00449 {
00450 if ( qApp->type() == QApplication::GuiServer) {
00451 bool needSave = FALSE;
00452 if ( timerEventReceiver != NULL ) {
00453 timerEventReceiver->killTimers();
00454
00455
00456 QListIterator<timerEventItem> it( timerEventList );
00457 time_t deleteTime = TimeConversion::toUTC( when );
00458 for ( ; *it; ++it ) {
00459
00460 if ( ( (*it)->UTCtime == deleteTime || when.isNull() )
00461 && ( channel.isNull() || (*it)->channel == channel )
00462 && ( message.isNull() || (*it)->message == message )
00463 && ( data == -1 || (*it)->data == data ) ) {
00464
00465 if ( (*it) == nearestTimerEvent ) {
00466 timerEventList.remove(*it);
00467 setNearestTimerEvent();
00468 }
00469 else {
00470 timerEventList.remove(*it);
00471 }
00472 needSave = TRUE;
00473 }
00474 }
00475 if ( nearestTimerEvent )
00476 timerEventReceiver->resetTimer();
00477 }
00478 if ( needSave )
00479 saveState();
00480 }
00481 else {
00482 #ifndef QT_NO_COP
00483 QCopEnvelope e( "QPE/System", "deleteAlarm(QDateTime,QCString,QCString,int)" );
00484 e << when << channel << message << data;
00485 #endif
00486
00487 }
00488 }
00489
00496 void Global::writeHWClock()
00497 {
00498 #ifdef USE_ATD
00499 if ( !triggerAtd( TRUE ) ) {
00500
00501 system("/sbin/hwclock --systohc");
00502 }
00503 #else
00504
00505 #endif
00506 }