summaryrefslogtreecommitdiff
path: root/library/alarmserver.cpp
Unidiff
Diffstat (limited to 'library/alarmserver.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--library/alarmserver.cpp2
1 files changed, 0 insertions, 2 deletions
diff --git a/library/alarmserver.cpp b/library/alarmserver.cpp
index 177a0cb..02bca3d 100644
--- a/library/alarmserver.cpp
+++ b/library/alarmserver.cpp
@@ -1,289 +1,287 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#include <qdir.h> 21#include <qdir.h>
22#include <qfile.h> 22#include <qfile.h>
23#include <qmessagebox.h> 23#include <qmessagebox.h>
24#include <qtextstream.h> 24#include <qtextstream.h>
25 25
26 26
27#include <qpe/qpeapplication.h> 27#include <qpe/qpeapplication.h>
28#include "global.h" 28#include "global.h"
29#include "resource.h" 29#include "resource.h"
30 30
31#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
32#include <qpe/qcopenvelope_qws.h> 31#include <qpe/qcopenvelope_qws.h>
33#endif
34#include "alarmserver.h" 32#include "alarmserver.h"
35#include <qpe/timeconversion.h> 33#include <qpe/timeconversion.h>
36 34
37#include <sys/types.h> 35#include <sys/types.h>
38#include <sys/stat.h> 36#include <sys/stat.h>
39 37
40#include <stdlib.h> 38#include <stdlib.h>
41#include <unistd.h> 39#include <unistd.h>
42 40
43struct timerEventItem { 41struct timerEventItem {
44 time_t UTCtime; 42 time_t UTCtime;
45 QCString channel, message; 43 QCString channel, message;
46 int data; 44 int data;
47 bool operator==( const timerEventItem &right ) const 45 bool operator==( const timerEventItem &right ) const
48 { 46 {
49 return ( UTCtime == right.UTCtime 47 return ( UTCtime == right.UTCtime
50 && channel == right.channel 48 && channel == right.channel
51 && message == right.message 49 && message == right.message
52 && data == right.data ); 50 && data == right.data );
53 } 51 }
54}; 52};
55 53
56class TimerReceiverObject : public QObject 54class TimerReceiverObject : public QObject
57{ 55{
58public: 56public:
59 TimerReceiverObject() { } 57 TimerReceiverObject() { }
60 ~TimerReceiverObject() { } 58 ~TimerReceiverObject() { }
61 void resetTimer(); 59 void resetTimer();
62 void setTimerEventItem(); 60 void setTimerEventItem();
63 void deleteTimer(); 61 void deleteTimer();
64protected: 62protected:
65 void timerEvent( QTimerEvent *te ); 63 void timerEvent( QTimerEvent *te );
66private: 64private:
67 QString atfilename; 65 QString atfilename;
68}; 66};
69 67
70TimerReceiverObject *timerEventReceiver = NULL; 68TimerReceiverObject *timerEventReceiver = NULL;
71QList<timerEventItem> timerEventList; 69QList<timerEventItem> timerEventList;
72timerEventItem *nearestTimerEvent = NULL; 70timerEventItem *nearestTimerEvent = NULL;
73 71
74 72
75// set the timer to go off on the next event in the list 73// set the timer to go off on the next event in the list
76void setNearestTimerEvent() 74void setNearestTimerEvent()
77{ 75{
78 nearestTimerEvent = NULL; 76 nearestTimerEvent = NULL;
79 QListIterator<timerEventItem> it( timerEventList ); 77 QListIterator<timerEventItem> it( timerEventList );
80 if ( *it ) 78 if ( *it )
81 nearestTimerEvent = *it; 79 nearestTimerEvent = *it;
82 for ( ; *it; ++it ) 80 for ( ; *it; ++it )
83 if ( (*it)->UTCtime < nearestTimerEvent->UTCtime ) 81 if ( (*it)->UTCtime < nearestTimerEvent->UTCtime )
84 nearestTimerEvent = *it; 82 nearestTimerEvent = *it;
85 if (nearestTimerEvent) 83 if (nearestTimerEvent)
86 timerEventReceiver->resetTimer(); 84 timerEventReceiver->resetTimer();
87 else 85 else
88 timerEventReceiver->deleteTimer(); 86 timerEventReceiver->deleteTimer();
89} 87}
90 88
91 89
92//store current state to file 90//store current state to file
93//Simple implementation. Should run on a timer. 91//Simple implementation. Should run on a timer.
94 92
95static void saveState() 93static void saveState()
96{ 94{
97 QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" ); 95 QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" );
98 if ( timerEventList.isEmpty() ) { 96 if ( timerEventList.isEmpty() ) {
99 unlink( savefilename ); 97 unlink( savefilename );
100 return; 98 return;
101 } 99 }
102 100
103 QFile savefile(savefilename+".new"); 101 QFile savefile(savefilename+".new");
104 if ( savefile.open(IO_WriteOnly) ) { 102 if ( savefile.open(IO_WriteOnly) ) {
105 QDataStream ds( &savefile ); 103 QDataStream ds( &savefile );
106 104
107 //save 105 //save
108 106
109 QListIterator<timerEventItem> it( timerEventList ); 107 QListIterator<timerEventItem> it( timerEventList );
110 for ( ; *it; ++it ) { 108 for ( ; *it; ++it ) {
111 ds << it.current()->UTCtime; 109 ds << it.current()->UTCtime;
112 ds << it.current()->channel; 110 ds << it.current()->channel;
113 ds << it.current()->message; 111 ds << it.current()->message;
114 ds << it.current()->data; 112 ds << it.current()->data;
115 } 113 }
116 114
117 115
118 savefile.close(); 116 savefile.close();
119 unlink( savefilename ); 117 unlink( savefilename );
120 QDir d; d.rename(savefilename+".new",savefilename); 118 QDir d; d.rename(savefilename+".new",savefilename);
121 119
122 } 120 }
123} 121}
124 122
125/*! 123/*!
126 Sets up the alarm server. Restoring to previous state (session management). 124 Sets up the alarm server. Restoring to previous state (session management).
127 */ 125 */
128void AlarmServer::initialize() 126void AlarmServer::initialize()
129{ 127{
130 //read autosave file and put events in timerEventList 128 //read autosave file and put events in timerEventList
131 129
132 QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" ); 130 QString savefilename = Global::applicationFileName( "AlarmServer", "saveFile" );
133 131
134 QFile savefile(savefilename); 132 QFile savefile(savefilename);
135 if ( savefile.open(IO_ReadOnly) ) { 133 if ( savefile.open(IO_ReadOnly) ) {
136 QDataStream ds( &savefile ); 134 QDataStream ds( &savefile );
137 while ( !ds.atEnd() ) { 135 while ( !ds.atEnd() ) {
138 timerEventItem *newTimerEventItem = new timerEventItem; 136 timerEventItem *newTimerEventItem = new timerEventItem;
139 ds >> newTimerEventItem->UTCtime; 137 ds >> newTimerEventItem->UTCtime;
140 ds >> newTimerEventItem->channel; 138 ds >> newTimerEventItem->channel;
141 ds >> newTimerEventItem->message; 139 ds >> newTimerEventItem->message;
142 ds >> newTimerEventItem->data; 140 ds >> newTimerEventItem->data;
143 timerEventList.append( newTimerEventItem ); 141 timerEventList.append( newTimerEventItem );
144 } 142 }
145 savefile.close(); 143 savefile.close();
146 if (!timerEventReceiver) 144 if (!timerEventReceiver)
147 timerEventReceiver = new TimerReceiverObject; 145 timerEventReceiver = new TimerReceiverObject;
148 setNearestTimerEvent(); 146 setNearestTimerEvent();
149 } 147 }
150} 148}
151 149
152 150
153 151
154 152
155static const char* atdir = "/var/spool/at/"; 153static const char* atdir = "/var/spool/at/";
156 154
157static bool triggerAtd( bool writeHWClock = FALSE ) 155static bool triggerAtd( bool writeHWClock = FALSE )
158{ 156{
159 QFile trigger(QString(atdir) + "trigger"); 157 QFile trigger(QString(atdir) + "trigger");
160 if ( trigger.open(IO_WriteOnly|IO_Raw) ) { 158 if ( trigger.open(IO_WriteOnly|IO_Raw) ) {
161 159
162 const char* data = 160 const char* data =
163#ifdef QT_QWS_CUSTOM 161#ifdef QT_QWS_CUSTOM
164 //custom atd only writes HW Clock if we write a 'W' 162 //custom atd only writes HW Clock if we write a 'W'
165 ( writeHWClock ) ? "W\n" : 163 ( writeHWClock ) ? "W\n" :
166#endif 164#endif
167 data = "\n"; 165 data = "\n";
168 int len = strlen(data); 166 int len = strlen(data);
169 int total_written = trigger.writeBlock(data,len); 167 int total_written = trigger.writeBlock(data,len);
170 if ( total_written != len ) { 168 if ( total_written != len ) {
171 QMessageBox::critical( 0, QObject::tr( "Out of Space" ), 169 QMessageBox::critical( 0, QObject::tr( "Out of Space" ),
172 QObject::tr( "Unable to schedule alarm.\nFree some memory and try again." ) ); 170 QObject::tr( "Unable to schedule alarm.\nFree some memory and try again." ) );
173 trigger.close(); 171 trigger.close();
174 QFile::remove( trigger.name() ); 172 QFile::remove( trigger.name() );
175 return FALSE; 173 return FALSE;
176 } 174 }
177 return TRUE; 175 return TRUE;
178 } 176 }
179 return FALSE; 177 return FALSE;
180} 178}
181 179
182void TimerReceiverObject::deleteTimer() 180void TimerReceiverObject::deleteTimer()
183{ 181{
184 if ( !atfilename.isEmpty() ) { 182 if ( !atfilename.isEmpty() ) {
185 unlink( atfilename ); 183 unlink( atfilename );
186 atfilename = QString::null; 184 atfilename = QString::null;
187 triggerAtd( FALSE ); 185 triggerAtd( FALSE );
188 } 186 }
189} 187}
190 188
191void TimerReceiverObject::resetTimer() 189void TimerReceiverObject::resetTimer()
192{ 190{
193 const int maxsecs = 2147000; 191 const int maxsecs = 2147000;
194 int total_written; 192 int total_written;
195 QDateTime nearest = TimeConversion::fromUTC(nearestTimerEvent->UTCtime); 193 QDateTime nearest = TimeConversion::fromUTC(nearestTimerEvent->UTCtime);
196 QDateTime now = QDateTime::currentDateTime(); 194 QDateTime now = QDateTime::currentDateTime();
197 if ( nearest < now ) 195 if ( nearest < now )
198 nearest = now; 196 nearest = now;
199 int secs = TimeConversion::secsTo( now, nearest ); 197 int secs = TimeConversion::secsTo( now, nearest );
200 if ( secs > maxsecs ) { 198 if ( secs > maxsecs ) {
201 // too far for millisecond timing 199 // too far for millisecond timing
202 secs = maxsecs; 200 secs = maxsecs;
203 } 201 }
204 202
205 // System timer (needed so that we wake from deep sleep), 203 // System timer (needed so that we wake from deep sleep),
206 // from the Epoch in seconds. 204 // from the Epoch in seconds.
207 // 205 //
208 int at_secs = TimeConversion::toUTC(nearest); 206 int at_secs = TimeConversion::toUTC(nearest);
209 // qDebug("reset timer to %d seconds from Epoch",at_secs); 207 // qDebug("reset timer to %d seconds from Epoch",at_secs);
210 QString fn = atdir + QString::number(at_secs) + "." 208 QString fn = atdir + QString::number(at_secs) + "."
211 + QString::number(getpid()); 209 + QString::number(getpid());
212 if ( fn != atfilename ) { 210 if ( fn != atfilename ) {
213 QFile atfile(fn+".new"); 211 QFile atfile(fn+".new");
214 if ( atfile.open(IO_WriteOnly|IO_Raw) ) { 212 if ( atfile.open(IO_WriteOnly|IO_Raw) ) {
215 // just wake up and delete the at file 213 // just wake up and delete the at file
216 QString cmd = "#!/bin/sh\nrm " + fn; 214 QString cmd = "#!/bin/sh\nrm " + fn;
217 total_written = atfile.writeBlock(cmd.latin1(),cmd.length()); 215 total_written = atfile.writeBlock(cmd.latin1(),cmd.length());
218 if ( total_written != int(cmd.length()) ) { 216 if ( total_written != int(cmd.length()) ) {
219 QMessageBox::critical( 0, tr("Out of Space"), 217 QMessageBox::critical( 0, tr("Out of Space"),
220 tr("Unable to schedule alarm.\n" 218 tr("Unable to schedule alarm.\n"
221 "Please free up space and try again") ); 219 "Please free up space and try again") );
222 atfile.close(); 220 atfile.close();
223 QFile::remove( atfile.name() ); 221 QFile::remove( atfile.name() );
224 return; 222 return;
225 } 223 }
226 atfile.close(); 224 atfile.close();
227 unlink( atfilename ); 225 unlink( atfilename );
228 QDir d; d.rename(fn+".new",fn); 226 QDir d; d.rename(fn+".new",fn);
229 chmod(fn.latin1(),0755); 227 chmod(fn.latin1(),0755);
230 atfilename = fn; 228 atfilename = fn;
231 triggerAtd( FALSE ); 229 triggerAtd( FALSE );
232 } else { 230 } else {
233 qWarning("Cannot open atd file %s",fn.latin1()); 231 qWarning("Cannot open atd file %s",fn.latin1());
234 } 232 }
235 } 233 }
236 // Qt timers (does the actual alarm) 234 // Qt timers (does the actual alarm)
237 // from now in milliseconds 235 // from now in milliseconds
238 // 236 //
239 qDebug("AlarmServer waiting %d seconds",secs); 237 qDebug("AlarmServer waiting %d seconds",secs);
240 startTimer( 1000 * secs + 500 ); 238 startTimer( 1000 * secs + 500 );
241} 239}
242 240
243void TimerReceiverObject::timerEvent( QTimerEvent * ) 241void TimerReceiverObject::timerEvent( QTimerEvent * )
244{ 242{
245 bool needSave = FALSE; 243 bool needSave = FALSE;
246 killTimers(); 244 killTimers();
247 if (nearestTimerEvent) { 245 if (nearestTimerEvent) {
248 if ( nearestTimerEvent->UTCtime 246 if ( nearestTimerEvent->UTCtime
249 <= TimeConversion::toUTC(QDateTime::currentDateTime()) ) { 247 <= TimeConversion::toUTC(QDateTime::currentDateTime()) ) {
250#ifndef QT_NO_COP 248#ifndef QT_NO_COP
251 QCopEnvelope e( nearestTimerEvent->channel, 249 QCopEnvelope e( nearestTimerEvent->channel,
252 nearestTimerEvent->message ); 250 nearestTimerEvent->message );
253 e << TimeConversion::fromUTC( nearestTimerEvent->UTCtime ) 251 e << TimeConversion::fromUTC( nearestTimerEvent->UTCtime )
254 << nearestTimerEvent->data; 252 << nearestTimerEvent->data;
255#endif 253#endif
256 timerEventList.remove( nearestTimerEvent ); 254 timerEventList.remove( nearestTimerEvent );
257 needSave = TRUE; 255 needSave = TRUE;
258 } 256 }
259 setNearestTimerEvent(); 257 setNearestTimerEvent();
260 } else { 258 } else {
261 resetTimer(); 259 resetTimer();
262 } 260 }
263 if ( needSave ) 261 if ( needSave )
264 saveState(); 262 saveState();
265} 263}
266 264
267/*! 265/*!
268 \class AlarmServer alarmserver.h 266 \class AlarmServer alarmserver.h
269 \brief The AlarmServer class allows alarms to be scheduled and unscheduled. 267 \brief The AlarmServer class allows alarms to be scheduled and unscheduled.
270 268
271 Applications can schedule alarms with addAlarm() and can 269 Applications can schedule alarms with addAlarm() and can
272 unschedule alarms with deleteAlarm(). When the time for an alarm 270 unschedule alarms with deleteAlarm(). When the time for an alarm
273 to go off is reached the specified \link qcop.html QCop\endlink 271 to go off is reached the specified \link qcop.html QCop\endlink
274 message is sent on the specified channel (optionally with 272 message is sent on the specified channel (optionally with
275 additional data). 273 additional data).
276 274
277 Scheduling an alarm using this class is important (rather just using 275 Scheduling an alarm using this class is important (rather just using
278 a QTimer) since the machine may be asleep and needs to get woken up using 276 a QTimer) since the machine may be asleep and needs to get woken up using
279 the Linux kernel which implements this at the kernel level to minimize 277 the Linux kernel which implements this at the kernel level to minimize
280 battery usage while asleep. 278 battery usage while asleep.
281 279
282 \ingroup qtopiaemb 280 \ingroup qtopiaemb
283 \sa QCopEnvelope 281 \sa QCopEnvelope
284*/ 282*/
285 283
286/*! 284/*!
287 Schedules an alarm to go off at (or soon after) time \a when. When 285 Schedules an alarm to go off at (or soon after) time \a when. When
288 the alarm goes off, the \link qcop.html QCop\endlink \a message will 286 the alarm goes off, the \link qcop.html QCop\endlink \a message will
289 be sent to \a channel, with \a data as a parameter. 287 be sent to \a channel, with \a data as a parameter.