{\rtf1\mac\deff2 {\fonttbl{\f0\fswiss Chicago;}{\f2\froman New York;}{\f3\fswiss Geneva;}{\f4\fmodern Monaco;}{\f13\fnil Zapf Dingbats;}{\f14\fnil Bookman;}{\f15\fnil N Helvetica Narrow;}{\f16\fnil Palatino;}{\f18\fnil Zapf Chancery;}{\f20\froman Times;} {\f21\fswiss Helvetica;}{\f22\fmodern Courier;}{\f23\ftech Symbol;}{\f33\fnil Avant Garde;}{\f34\fnil New Century Schlbk;}{\f55\fnil Code 3 of 9;}{\f256\fnil TaxType;}{\f257\fnil TaxTypeCondensed;}{\f258\fnil TaxType Mono;}{\f259\fnil TaxType Pi;} {\f1904\fnil AppleIcon;}{\f2029\fnil Nadianne;}{\f2052\fnil Zeal;}{\f12899\fnil AppleGaramond LtIt;}{\f12900\fnil AppleGaramond BkIt;}{\f12901\fnil AppleGaramond BdIt;}{\f12902\fnil AppleGaramond Lt;}{\f12903\fnil AppleGaramond Bk;} {\f12904\fnil AppleGaramond Bd;}{\f14003\fnil Newt Espy Plain;}{\f14004\fnil Newt Espy Bold;}}{\colortbl\red0\green0\blue0;\red0\green0\blue255;\red0\green255\b lue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\ red255\green255\blue0; \red255\green255\blue255;}{\stylesheet{\s243\qj\fi180\sa240\keep\tqc\tx43 20\tqr\tx8640 \f20 \sbasedon0\snext243 footer;}{\s254\qj\sb120\sa240\keep \b\f20 \sbasedon0\snext0 heading 2;}{\s255\qj\sb240\sa240\keep \f20\fs36 \sbasedon0\snext0 heading 1;}{ \qj\fi180\sa240\keep \f20 \sbasedon222\snext0 Normal;}{\s2\li360\sa240\keep \f20 \sbasedon0\snext0 BulletList;}{\s3\sa240\keep \f22 \sbasedon0\snext0 code;}{\s4\qc\fi180\sa240\keep \f20\fs48 \sbasedon0\snext4 Title;}{\s5\qc\fi180\sa240\keep \f20\fs28 \sbasedon0\snext5 Byline;}{\s6\qc\fi180\sa240\keep \f20 \sbasedon0\snext0 Caption;}{\s7\qj\sb240\sa240\keep \f22\fs36 \sbasedon255\snext7 CodeRef;}{\s8\fi-720\li1080\sa240\keep \f20 \sbasedon0\snext8 ParmDescr;}} \margl720\margr720\margt1080\margb720\deftab360\widowctrl\ftnbj \sectd \sbknone\linemod0\linex0\cols1\endnhere \pard\plain \s4\qc\fi180\sa240\keep \f20\fs48 Up In Alarms\par \pard\plain \qc\fi180\sa240\keep \f20 {\fs36 Draft 2\par }\pard\plain \s5\qr\fi180\sa240\keep \f20\fs28 Michael S. Engber\line Apple Computer - Newton ToolBox Group\line Copyright \'a9 1994 - Michael S. Engber\par \pard\plain \fi180\sa240\keep \f20 This article was (will be) published in the May 1994 issue of PIE Developers magazine. For information about PIE Developers, contact Creative Digital Systems at CDS.SEM@APPLELINK.APPLE.COM or 415.621.4252.\par \pard\plain \s255\qj\sb240\sa240\keep \f20\fs36 Introduction\par \pard\plain \qj\fi180\sa240\keep \f20 This articles discuses how third party applications can set alarms on the Newton like the built-in Calendar application. The library for using alarms is included in the NTK 1.0 final platform file. Therefore, you need the NTK 1.0 final (or later) platform file to actually test out the alarms. The alarm library is different than other libraries in the NTK platform in that it permanently installs alarm code on your user's Newton. Mak e sure you understand this issue thoroughly before distributing code using alarms. I assume the reader has some experience using NTK to write Newton applications and is familiar with how to use library code provided in the NTK platform files.\par \pard\plain \s255\qj\sb240\sa240\keep \f20\fs36 What Alarms Can Do\par \pard\plain \qj\fi180\sa240\keep \f20 The alarm library allows you to set an alarm to go off at some time in the future. If the Newton is asleep at that time the alarm will wake up the Newton. You can specify the alarm time to the nearest minute. The alarm action can be as simple as putt ing up a Notify alert (\'88 la the built-in Calendar) or it can execute a callback function to do whatever you like.\par \pard\plain \s255\qj\sb240\sa240\keep \f20\fs36 Trying Out Alarms From the Inspector\par \pard\plain \qj\fi180\sa240\keep \f20 First, recall that if the NTK platform provide a function named Foo that the constant you use to refer to the function is call kFooFunc. The five constants for the alarm API are:\par \pard\plain \s3\li360\sa240\keep \f22 kAddAlarmFunc\line kRemoveAlarmFunc\line kGetAlarmFunc\line kGetAppAlarmKeysFunc\line kRemoveAppAlarmsFunc\par \pard\plain \qj\fi180\sa240\keep \f20 The first thing to try is setting an alarm:\par \pard\plain \s3\li360\sa240\keep \f22 {\fs20 call kAddAlarmFunc with ("foo:PIEDTS",Time()+1,[kNotifyAlert,"foo","bar"],nil,nil);\line #440D559 "foo:PIEDTS"\par }\pard\plain \qj\fi180\sa240\keep \f20 This sets an alarm to go off one minute from now. Within a minute you should see the following message in Figure 1 on the Newton screen. Remember that Time() returns the current time in minutes. If you execute the above code at 2:42:45, then Time() will re turn 2:42 and the alarm will be set for 2:43, 15 seconds later.\par \pard \qc\fi180\sa240\keep {{\pict\macpict\picw207\pich115 10bc0078003800eb0107001102ff0c00ffffffff00380000007800000107000000eb00000 000000000a0008200a0303900a0008e0001000a0000000002500240009880d60078003800 eb010e00000000000000000048000000480000000000080001000800000000009bb078000 0000000000008800000ff0000ffffffffff ff0000ffffffffcccc0000ffffffff99990000ffffffff66660000ffffffff33330000fff fffff00000000ffffccccffff0000ffffcccccccc0000ffffcccc99990000ffffcccc6666 0000ffffcccc33330000ffffcccc00000000ffff9999ffff0000ffff9999cccc0000ffff9 99999990000ffff999966660000ffff9999 33330000ffff999900000000ffff6666ffff0000ffff6666cccc0000ffff666699990000f fff666666660000ffff666633330000ffff666600000000ffff3333ffff0000ffff3333cc cc0000ffff333399990000ffff333366660000ffff333333330000ffff333300000000fff f0000ffff0000ffff0000cccc0000ffff00 0099990000ffff000066660000ffff000033330000ffff000000000000ccccffffffff000 0ccccffffcccc0000ccccffff99990000ccccffff66660000ccccffff33330000ccccffff 00000000ccccccccffff0000cccccccccccc0000cccccccc99990000cccccccc66660000c ccccccc33330000cccccccc00000000cccc 9999ffff0000cccc9999cccc0000cccc999999990000cccc999966660000cccc999933330 000cccc999900000000cccc6666ffff0000cccc6666cccc0000cccc666699990000cccc66 6666660000cccc666633330000cccc666600000000cccc3333ffff0000cccc3333cccc000 0cccc333399990000cccc333366660000cc cc333333330000cccc333300000000cccc0000ffff0000cccc0000cccc0000cccc0000999 90000cccc000066660000cccc000033330000cccc0000000000009999ffffffff00009999 ffffcccc00009999ffff999900009999ffff666600009999ffff333300009999ffff00000 0009999ccccffff00009999cccccccc0000 9999cccc999900009999cccc666600009999cccc333300009999cccc0000000099999999f fff000099999999cccc000099999999999900009999999966660000999999993333000099 9999990000000099996666ffff000099996666cccc0000999966669999000099996666666 60000999966663333000099996666000000 0099993333ffff000099993333cccc0000999933339999000099993333666600009999333 333330000999933330000000099990000ffff000099990000cccc00009999000099990000 9999000066660000999900003333000099990000000000006666ffffffff00006666ffffc ccc00006666ffff999900006666ffff6666 00006666ffff333300006666ffff000000006666ccccffff00006666cccccccc00006666c ccc999900006666cccc666600006666cccc333300006666cccc0000000066669999ffff00 0066669999cccc00006666999999990000666699996666000066669999333300006666999 90000000066666666ffff000066666666cc cc00006666666699990000666666666666000066666666333300006666666600000000666 63333ffff000066663333cccc000066663333999900006666333366660000666633333333 0000666633330000000066660000ffff000066660000cccc0000666600009999000066660 00066660000666600003333000066660000 000000003333ffffffff00003333ffffcccc00003333ffff999900003333ffff666600003 333ffff333300003333ffff000000003333ccccffff00003333cccccccc00003333cccc99 9900003333cccc666600003333cccc333300003333cccc0000000033339999ffff0000333 39999cccc00003333999999990000333399 99666600003333999933330000333399990000000033336666ffff000033336666cccc000 0333366669999000033336666666600003333666633330000333366660000000033333333 ffff000033333333cccc00003333333399990000333333336666000033333333333300003 33333330000000033330000ffff00003333 0000cccc00003333000099990000333300006666000033330000333300003333000000000 0000000ffffffff00000000ffffcccc00000000ffff999900000000ffff666600000000ff ff333300000000ffff000000000000ccccffff00000000cccccccc00000000cccc9999000 00000cccc666600000000cccc3333000000 00cccc0000000000009999ffff000000009999cccc0000000099999999000000009999666 600000000999933330000000099990000000000006666ffff000000006666cccc00000000 66669999000000006666666600000000666633330000000066660000000000003333ffff0 00000003333cccc00000000333399990000 00003333666600000000333333330000000033330000000000000000ffff000000000000c ccc0000000000009999000000000000666600000000000033330000eeee000000000000dd dd000000000000bbbb000000000000aaaa000000000000888800000000000077770000000 00000555500000000000044440000000000 00222200000000000011110000000000000000eeee000000000000dddd000000000000bbb b000000000000aaaa00000000000088880000000000007777000000000000555500000000 00004444000000000000222200000000000011110000000000000000eeee000000000000d ddd000000000000bbbb000000000000aaaa 0000000000008888000000000000777700000000000055550000000000004444000000000 000222200000000000011110000eeeeeeeeeeee0000dddddddddddd0000bbbbbbbbbbbb00 00aaaaaaaaaaaa00008888888888880000777777777777000055555555555500004444444 44444000022222222222200001111111111 1100000000000000000078003800eb01070078003800eb010700002afd00edfff300fbfff 500fbfff500fbfff500fbfff500fbfff500fbfff500fbfff500fafff500edfff6002b0100 00e8fff900f5fffb00f5fffb00f5fffb00f5fffb00f5fffb00f5fffb00f5fffb00f4fffb0 0e8fff80008000081ffb4fff90008000081 ffb4fff9000681ffb2fffa000681ffb2fffa000681ffb2fffa002cf9fff100f3fffb00f5f ffb00f5fffb00f5fffb00f5fffb00f5fffb00f5fffb00f5fffa00f5fff000fafffa002cfa ffed00f9fff500fbfff500fbfff500fbfff500fbfff500fbfff500fbfff500fbfff400fbf fec00fbfffa000afaff8100bf00fbfffa00 0afaff8100bf00fbfffa000afaff8100bf00fbfffa000afaff8100bf00fbfffa000afaff8 100bf00fbfffa000afaff8100bf00fbfffa000efafff500fdff8100cf00fbfffa000efaff f700f9ff8100d100fbfffa0016fafff800fefffd00fefffb00feff8100db00fbfffa001cf afff80009ffff0000ffff0000fffffc0001 ffff8100d900fbfffa0021fafff90001fffff90001fffffe00fdff010000fdfffe00fdff8 100e700fbfffa002cfafff90003ffff0000fefffe0001fffffd0010ffff0000ffff0000ff ff00ffff0000ffff8100e800fbfffa002dfafff90001fffffe0001fffffe0001fffffd001 0ffff0000ffff0000ffff00ffff0000ffff 8100e800fbfffa002dfafff90001fffffe0001fffffe0001fffffd0010ffff0000ffff000 0ffff00ffff0000ffff8100e800fbfffa002afafff80002ffff00fdff0200fffffc0010ff ff0000ffff0000ffff00ffff0000ffff8100e900fafffa00210000fbfff800fefffd00fef ffc0001fffffe00fdfffe00fdff8100e800 fafffa00100000fafff800f9ff8100d200fafffa00100000fafff600fdff8100d100fafff 9000d010000faff8100c400fafff8000d010000faff8100c400fafff8000d010000faff81 00c400fafff8000d010000faff8100c400fafff8000d010000faff8100c400fafff800120 10000fafffb0001ffff8100cc00fafff800 110000fafffa0001ffff8100cb00fafff9001b0000fafffa00fdfffe00feff050000ffff0 0ff8100d900fafff9001c0000fafffa0004ffff00fffffd0002ffff00fdff8100d900faff f9001afafff90006ffff00ffff0000fdff0200ffff8100d600fafffa001bfafff9000dfff f00ffff00ffff00ffff00ffff8100d600fa fffa0016fafff900fdfffe00fdff0200ffff8100d600fafffa000afaff8100c000fafffa0 00afaff8100c000fafffa000afaff8100c000fafffa000af9ff8100c100fafffa000c0000 faff8100c200fafff9000c0000faff8100c200fafff9000c0000f9ff8100c300fafff9000 d010000faff8100c400fafff8000d010000 faff8100c400fafff8000d010000faff8100c400fafff8000d010000faff8100c400fafff 8000d010000faff8100c400fafff8000c0000f9ff8100c400fafff8000c0000faff8100c2 00fafff9000c0000faff8100c200fafff9000af9ff8100c200fafff9000afaff8100c000f afffa000afaff8100c000fafffa000afaff 8100c000fafffa000afaff8100c000fafffa000afaff8100c000fafffa000af9ff8100c10 0fafffa000c0000faff8100c200fafff9000c0000faff8100c200fafff9000c0000f9ff81 00c300fafff9000d010000faff8100c400fafff8000d010000faff8100c400fafff8000d0 10000faff8100c400fafff8000d010000fa ff8100c400fafff8000d010000faff8100c400fafff8000c0000f9ff8100c400fafff8000 c0000faff8100c200fafff9000c0000faff8100c200fafff9000af9ff8100c200fafff900 0afaff8100c000fafffa000afaff8100c000fafffa000afaff8100c000fafffa000afaff8 100c000fafffa000afaff8100c000fafffa 000afaff8100c000fafffa000c0000faff8100c200fafff9000c0000faff8100c200fafff 9000c0000faff8100c200fafff9000d010000faff8100c400fafff8000d010000faff8100 c400fafff8000d010000faff8100c400fafff80011010000faff8100c400faff020000fff b0012010000faff8100c400faff010000fd fffe0010010000faff8100c400faff010000faff0e0000faff8100c200faff0000faff0e0 000faff8100c200faff0000faff0e0000faff8100c200faff0000faff0cfaff8100d000f6 fffc00f3ff10faff8100d100f4fffd00faff0000fbff16faff8100d10001fffff80001fff ffd00fafffd00feff1afaff8100d10004ff ff00fffffe0004ffff00fffffd00fafffa001afaff8100d10002ffff00feff0000feff020 0fffffd00fafffa0018faff8100d10003ffff0000fcff030000fffffd00fafffa0018faff 8100d10001fffffe00fefffe0001fffffd00fafffa0018faff8100d10003ffff0000fcff0 30000fffffd00fafffa001afaff8100d100 02ffff00feff0000feff0200fffffd00fafffa001afaff8100d10004ffff00fffffe0004f fff00fffffd00fafffa0014faff8100d10001fffff80001fffffd00fafffa000efaff8100 d100f4fffd00fafffa000efaff8100d000f6fffc00fafffa000afaff8100c000fafffa000 afaff8100c000fafffa002cfaffed00f9ff f500fbfff500fbfff500fbfff500fbfff500fbfff500fbfff500fbfff400fbffed00fafff a002cf9fff100f3fffb00f5fffb00f5fffb00f5fffb00f5fffb00f5fffb00f5fffb00f5ff fa00f5fff100f9fffa000681ffb2fffa000681ffb2fffa000681ffb2fffa0008000081ffb 4fff90008000081ffb4fff9002b010000e8 fff900f5fffb00f5fffb00f5fffb00f5fffb00f5fffb00f5fffb00f5fffb00f4fffb00e8f ff8002afd00edfff300fbfff500fbfff500fbfff500fbfff500fbfff500fbfff500fbfff5 00fafff500edfff6000000a0008f00a0008300ff}}\par \pard\plain \s6\qc\fi180\sa240\keep \f20 Figure 1 - Simple Alarm Notify Message\par \pard\plain \qj\fi180\sa240\keep \f20 The first argument to {\f22 AddAlarm} is a string used to uniquely identify the alarm for future reference \endash for example, if you want to cancel it. Use your signature as a suffix to generate unique alarm keys just as you use it to generate unique package names. The second argument is the time in minutes (since January 1, 1904) that the alarm will go off. T he third argument is an array of arguments to pass to Notify when the alarm goes off. The last two arguments are a call back function and arguments to be executed when the alarm goes off. This example doesn't take advantage of call back functions.\par \pard \qj\fi180\sa240\keep Next we can try out {\f22 GetAlarm} and {\f22 RemoveAlarm}:\par \pard\plain \s3\li360\sa240\keep \f22 {\fs20 call kAddAlarmFunc with ("foo:PIEDTS",Time()+2,[kNotifyAlert,"foo","bar"],nil,nil);\line #440FA69 "foo:PIEDTS"\line \line call kGetAlarmFunc with ("foo:PIEDTS");\line #44116D9 \{key: "foo:PIEDTS", \line Time: 46813104, \line notifyArgs: [3, "foo", "bar"], \line callBackFn: NIL, \line callBackParams: NIL, \line _uniqueID: 2\}\line \line call kRemoveAlarmFunc with ("foo:PIEDTS");\line #44116D9 \{ key: "foo:PIEDTS", \line Time: 46813104, \line notifyArgs: [3, "foo", "bar"], \line callBackFn: NIL, \line callBackParams: NIL, \line _uniqueID: 2\}\line \line call kGetAlarmFunc with ("foo:PIEDTS"); \line #2 NIL\par }\pard\plain \qj\fi180\sa240\keep \f20 This time we set the alarm for two minutes to give us enough time to execute the rest of the code. Next we use {\f22 GetAlarm} to retrieve the alarm. The frame it returns basically contains all the information we originally passed to {\f22 AddAlarm}. You should be careful not to modify this frame or its contents. The more observant among you will notice it is a soup entry. Alarms are kept in a soup. The implications of this will be discussed later in the "Warnings and Gotchas" section of this article.\par \pard \qj\fi180\sa240\keep The third line of code removes the alarm. If you entered it in time, the alarm will not go off. {\f22 RemoveAlarm} returns an unspecified non-nil value to indicate it successfully removed the alarm. As you can see, it returns the same thing as {\f22 GetAlarm}, but this is not a fact you should rely on.\par \pard \qj\fi180\sa240\keep Finally, we use {\f22 GetAlarm} again to double check that the alarm was removed. It returns nil indicating no alarm with the specified alarm key was found.\par \pard \qj\fi180\sa240\keep Next we'll use the following code to try out the two other functions from the alarm API.\par \pard\plain \s3\li360\sa240\keep \f22 {\fs20 call func()\line begin\line local i;\line for i := 1 to 5 do\line begin\line local alarmTime := Time() + i;\line local key := i & "foo:PIEDTS";\line local notifyArgs := [kNotifyAlert,HourMinute(alarmTime),"Alarm#" && i];\line call kAddAlarmFunc with (key,alarmTime,notifyArgs,nil,nil);\line end;\line end with ();\line #2 NIL\line \line call kGetAppAlarmKeysFunc with (":PIEDTS") \line #440B249 ["2foo:PIEDTS", "3foo:PIEDTS", "4foo:PIEDTS", "5foo:PIEDTS"]\line \line call kRemoveAppAlarmsFunc with (":PIEDTS")\line #C 3\par }\pard\plain \qj\fi180\sa240\keep \f20 First we use a loop to set up 5 different alarms. Notice that we generate a different alarm key for each alarm. If we didn't do this we'd end up only setting a single alarm. Each time we called {\f22 AddAlarm} the new alarm would replace the one we previously set.\par \pard \qj\fi180\sa240\keep Next we use {\f22 GetAppAlarmKeys} to see all the alarms we set. We pass it the common suffix all our alarm keys share. You'll notice that only four alarm keys were returned. I wasn't quick enough on the enter key. The first alarm went off before I executed the call to {\f22 GetAppAlarmKeys}.\par Finally, we use {\f22 RemoveAppAlarms} to remove all the remaining alarms we have installed. It takes an alarm key suffix just like {\f22 GetAppAlarmKeys} and returns the number of alarms it actually removed. Again, I wasn't quick enough to beat the next alarm we had scheduled. That's why it returned a value of three.\par \pard \qj\fi180\sa240\keep For more examples of how to use alarms, including using callback functions, see the PIE DTS sample code called FalseAlarm.\par \pard\plain \s255\qj\sb240\sa240\keep \f20\fs36 Alarm API Function Descriptions\par \pard\plain \qj\fi180\sa240\keep \f20 This section discusses each of the alarm function in detail.\par \pard\plain \s254\qj\sb120\sa240\keep \b\f20 {\f22 AddAlarm}{\plain \f20 (}{\plain \i\f20 alarmKey}{\plain \f20 ,}{\plain \i\f20 time}{\plain \f20 ,}{\plain \i\f20 notifyArgs}{\plain \f20 ,}{\plain \i\f20 callBackFn}{\plain \f20 ,}{\plain \i\f20 callBackParams}{\plain \f20 )}\par \trowd \trgaph80\trleft280 \clshdng0\cellx2160\clshdng0\cellx10080\pard\plain \qj\fi180\sa240\keep\intbl \f20 return value\cell \pard \qj\sa240\keep\intbl {\i alarmKey}\cell \pard \intbl \row \trowd \trgaph80\trleft280 \clshdng0\cellx2160\clshdng0 \cellx10080\pard \qj\fi180\sa240\keep\intbl {\i alarmKey}\cell \pard \qj\sa240\keep\intbl A string used to uniquely identify the alarm. You should use your signature or app symbol as a suffix to guarantee uniqueness among different applications. For example, {\f22 "wakeUpReg:PIEDTS"}. If there is already an alarm with with the same {\i alarmKey}, it is removed and replaced with the new alarm.\cell \pard \intbl \row \pard \qj\fi180\sa240\keep\intbl {\i time}\cell \pard \qj\sa240\keep\intbl Integer encoding the time of the alarm in minutes since midnight, January 1, 1904 (\'88 la the Time() global function).\cell \pard \intbl \row \pard \qj\fi180\sa240\keep\intbl {\i notifyArgs}\cell \pard \qj\sa240\keep\intbl An array of 3 arguments to pass to Notify when the alarm goes off. Pass nil to indicate Notify shouldn't be called. \cell \pard \intbl \row \pard \qj\fi180\sa240\keep\intbl {\i callBackFn}\cell \pard \qj\sa240\keep\intbl A closure to be executed when your alarm goes off. Pass nil to indicate no call back function is being used.\cell \pard \intbl \row \trowd \trgaph80\trleft280 \clshdng0\cellx2160\clshdng0\cellx10080\pard \qj\fi180\sa240\keep\intbl {\i callBackParams}\cell \pard \qj\sa240\keep\intbl An array of parameters to be passed to {\i callBackFn}. Use nil if no call back functions is being used.\cell \pard \intbl \row \pard \qj\fi180\sa240\keep {\f22 AddAlarm} is used to register an alarm to execute at a specified time. The alarm will wake up the Newton if necessary. You can specify a system notify message to be displayed. You can take other actions by specifying a closure.\par \pard \qj\fi180\sa240\keep The time an alarm executes is approximate. There may be multiple alarms scheduled for the same time, if one of the alarms does something time consuming it can delay the execution of other alarms. In the case of simultaneously scheduled alarms the execution order is unspecified. \par \pard \qj\fi180\sa240\keep Once an alarm executes it's removed. You only need to call {\f22 RemoveAlarm} if you want to abort an alarm. If you want to change an existing alarm, simply call {\f22 AddAlarm} with the same alarm key. The new version of the alarm will replace the old one. If you want to schedule an alarm periodically, your {\i callBackFn} should call {\f22 AddAlarm} to schedule the next occurrence. \par \pard\plain \s254\qj\sb120\sa240\keep \b\f20 {\f22 RemoveAlarm}{\plain \f20 (}{\plain \i\f20 alarmKey}{\plain \f20 )}\par \trowd \trgaph80\trleft280 \clshdng0\cellx2160\clshdng0\cellx10080\pard\plain \qj\sa240\keep\intbl \f20 return value\cell \pard \qj\sa240\keep\intbl nil if no alarm with {\i alarmKey} was found. An unspecified non-nil value if the alarm was found and removed.\cell \pard \intbl \row \trowd \trgaph80\trleft280 \clshdng0\cellx2160\clshdng0\cellx10080\pard \qj\sa240\keep\intbl {\i alarmKey}\cell \pard \qj\sa240\keep\intbl The unique string passed to {\f22 AddAlarm} which identifies the alarm. {\f22 RemoveAlarm} unschedules an alarm. If you want your application's alarms to execute only if your application is installed, you'll need to call {\f22 RemoveAlarm} in your remove script.\cell \pard \intbl \row \pard \qj\fi180\sa240\keep {\f22 RemoveAlarm} unschedules an alarm. This function is used to abort a pending alarm.\par \pard\plain \s254\qj\sb120\sa240\keep \b\f20 {\f22 GetAlarm}{\plain \f20 (}{\plain \i\f20 alarmKey}{\plain \f20 )}\par \trowd \trgaph80\trleft280 \clshdng0\cellx2160\clshdng0\cellx10080\pard\plain \qj\sa240\keep\intbl \f20 return value\cell \pard \qj\sa120\keep\intbl A frame containing the 5 slots described below or nil if no alarm is found.\par \pard \li360\sa240\keep\tx2160\intbl key:\tab the unique string which identifies the alarm\line time: \tab the time at which the alarm will "go off"\line notifyArgs:\tab array of 3 argument for Notify (or nil)\line callBackFn:\tab closure (or nil)\line callBackParams:\tab array of arguments for callBackFn (or nil)\cell \pard \intbl \row \trowd \trgaph80\trleft280 \clshdng0\cellx2160\clshdng0\cellx10080\pard \qj\sa240\keep\intbl {\i alarmKey}\cell \pard \qj\sa240\keep\intbl The unique string passed to { \f22 AddAlarm} which identifies the alarm.\cell \pard \intbl \row \pard \qj\fi180\sa240\keep {\f22 GetAlarm} returns information on the specified alarm. The frame returned by {\f22 GetAlarm} and its contents should not be modified. Any undocumented slots you find in it should be ignored.\par \pard\plain \s254\qj\sb120\sa240\keep \b\f20 {\f22 GetAppAlarmKeys}{\plain \f20 (}{\plain \i\f20 alarmKeySuffix}{\plain \f20 )}\par \trowd \trgaph80\trleft280 \clshdng0\cellx2160\clshdng0\cellx10080\pard\plain \qj\sa240\keep\intbl \f20 return value\cell \pard \qj\sa240\keep\intbl An array of alarm keys (strings)\cell \pard \intbl \row \trowd \trgaph80\trleft280 \clshdng0\cellx2160 \clshdng0\cellx10080\pard \qj\sa240\keep\intbl {\i alarmKeySuffix}\cell \pard \qj\sa240\keep\intbl A string which specifies the suffix which ends all your alarm keys. For example, {\f22 ":PIEDTS"} or {\f22 ":AlarmSample1:PIEDTS"}.\cell \pard \intbl \row \pard \qj\fi180\sa240\keep Returns an array of all an application's alarm keys. They will be in execution order, earliest alarm to latest alarm.\par \pard\plain \s254\qj\sb120\sa240\keep \b\f20 {\f22 RemoveAppAlarms}{\plain \f20 (}{\plain \i\f20 alarmKeySuffix}{\plain \f20 )}\par \trowd \trgaph80\trleft280 \clshdng0\cellx2160\clshdng0\cellx10080\pard\plain \qj\sa240\keep\intbl \f20 return value\cell \pard \qj\sa240\keep\intbl An integer, the number of alarms removed\cell \pard \intbl \row \trowd \trgaph80\trleft280 \clshdng0 \cellx2160\clshdng0\cellx10080\pard \qj\sa240\keep\intbl {\i alarmKeySuffix}\cell \pard \qj\sa240\keep\intbl A string which specifies the suffix which ends all your alarm keys. For example, {\f22 ":PIEDTS"} or {\f22 ":AlarmSample1:PIEDTS"}.\cell \pard \intbl \row \pard \qj\fi180\sa240\keep Removes all of an application's alarms. This would be a useful routine to call in your {\f22 RemoveScript} if your alarms can't meaningfully execute when your application is not installed.\par \pard\plain \s255\qj\sb240\sa240\keep \f20\fs36 Why is the Alarm Library Different from All Other Libraries?\par \pard\plain \qj\fi180\sa240\keep \f20 The NTK platform file provides a variety of libraries which extend the functionality of the Message Pad ROMs. For example, it provides a function to change an existing icon in the extras drawer, something for which no API was provided by the original Newto n ROM. Generally, using these libraries simply means including some extra code in your package (somewhat similar linking in a library in to a C program).\par \pard \qj\fi180\sa240\keep The Alarm library is special. In addition to including some extra code in your package, it also installs code on the internal store of your user's Newton. This code uses about 4K of storage and provides alarm functionality even after your package has been removed.\par \pard \qj\fi180\sa240\keep The installation of the alarm functionality happens automatically, the first time any of the routines in the alarm library is called. The installation is permanent. It remains installed until the user does a cold boot.\par \pard \qj\fi180\sa240\keep This is a very serious matter. Your users need to be warned they may lose ~4K of internal storage if they use your application. This storage is not lost every time your application runs or for every different application that uses alarms. It is lost only o nce, when the alarm functionality is initially installed. Of course, on Newtons that have this functionality already built into ROM, this installation is not necessary and will not take place . The current Message Pad ROMs do not have the alarm functionality built in.\par \pard \qj\fi180\sa240\keep The alarm library is currently the only set of functions in the NTK platform file that does this type of permanent installation. Alarms are a special case. Many applications require the alarm functionality to persist in the Newton even if the application i s not installed (e.g. on a card that has been removed). This means the code for the alarm API cannot reside in your application's package as is the case for the other libraries in the platform file. \par \pard\plain \s255\qj\sb240\sa240\keep \f20\fs36 AlarmPkgUtil\par \pard\plain \qj\fi180\sa240\keep \f20 AlarmPkgUtil is a utility for programmers to use in testing their alarm code. It is distributed along with the PIE DTS FalseAlarm sample code. It allows you to easily install and remove the alarm functionality into a Newton - something your users will neve r have to deal with explicitly.\par You will want to use AlarmPkgUtil in order to test your application's robustness. For example, test your application with the alarm functionality already installed, not previously installed, becoming installed while your application is already running, \'c9\par \pard \qj\fi180\sa240\keep The user interface to the AlarmPkgUtil should be self explanatory. There is only a single button that is labeled either "Install Alarm Package" or "Remove Alarm Package" whichever is appropriate.\par \pard \qj\fi180\sa240\keep There is a status box below which tells you the current state of the system with respect to the installation of alarm functionality. If the state is {\f22 *error*} , the message box will contain a list of items, each preceded by a {\f22 +} or {\f22 \endash } character. This information may be useful to DTS in debugging any problems you encounter.\par \pard\plain \s255\qj\sb240\sa240\keep \f20\fs36 Warnings and Gotchas\par \pard\plain \s254\qj\sb120\sa240\keep \b\f20 Call Back Functions\par \pard\plain \qj\fi180\sa240\keep \f20 Alarms are kept in a soup so they will persist across restarts and when your package is removed. This means the arguments you pass will be stored in a soup. This, in turn, means these arguments will be deeply copied. You should be careful to avoid indirect ly referencing large objects.\par \pard \qj\fi180\sa240\keep A classic example of accidentally referencing a large object is dynamically creating closure you pass for your callb ack function. Closures contain references the lexical environment and the current receiver (self) at the time they are created. For example, closures created from a view method will reference the root view through their parent chain. So if you pass such a closure to {\f22 AddAlarm} the Newton will attempt to copy the entire root view into the alarm soup. Functions created in the NTK inspector also do not have empty environments. This means if you're hacking in the Inspector and you pass a closure to {\f22 AddAlarm}, the Newton will appear to hang.\par \pard \qj\fi180\sa240\keep The best way to avoid this problem is to create your alarm callback closures when your package is built. (i.e. make sure the {\f22 func(\'c9)\'c9} expression is evaluated at build-time, not at run time) Functions defined in "Project Data" or evaluate slot should will have empty environments.\par Debugging your call back function will be difficult. When it executes, any exceptions raised will be caught and ignored by the alarm mechanism. I suggest debugging your call back functions thoroughly before passing them to {\f22 AddAlarm}. \par \pard \qj\fi180\sa240\keep Note, that when your alarm runs your application may not be open. In fact, your application may not even be installed. You need to be sure and handle these cases appropriately. For example, the following code tests for the presence of the application befor e sending a message to it.\par \pard\plain \s3\li360\sa240\keep \f22 if GetRoot().(kAppSymbol) then\line GetRoot().(kAppSymbol):DoSomething()\line else\line GetRoot():Notify(...)\par \pard\plain \qj\fi180\sa240\keep \f20 If your alarms aren't useful when your application isn't installed, you should consider simply removing them, using {\f22 RemoveAlarm} or {\f22 RemoveAppAlarms}, in your {\f22 RemoveScript} . There is no point in wasting space with useless alarms that put up Notify messages like "Sorry, this alarm can't execute since application Fwiblob isn't installed."\par \pard\plain \s254\qj\sb120\sa240\keep \b\f20 Using Alarm Functions From Install and Remove Scripts\par \pard\plain \qj\fi180\sa240\keep \f20 Alarm functionality may not be added to a Newton during an {\f22 InstallScript} or a {\f22 RemoveScript} . This means, if the alarm functionality is not already present in the Newton and you use one of the five alarm functions it may not succeed. This situation can cause the Newton to hang, requiring a reset. Note that a reset will cause your {\f22 InstallScript} to run again. So, it may require a cold boot to finally end the cycle.\par \pard \qj\fi180\sa240\keep You can avoid this problem entirely by not using the alarm functions during your install or remove scripts. Alternately, your install or remove scripts can spawn deferred actions to execute alarm related code. \par \pard\plain \s254\qj\sb120\sa240\keep \b\f20 Using AddAlarm and RemoveAlarm as Global Functions\par \pard\plain \qj\fi180\sa240\keep \f20 You will find that once the alarm functionality has been installed on a Newton that you can simply call {\f22 AddAlarm} and {\f22 RemoveAlarm} as if they were part of the ROM. However, this will not be the case for the rest of the functions in the alarm API. Do not take advantage of this in your application. Remember, your users will not initially have the alarm functionality installed in their Newtons.\par \pard\plain \s254\qj\sb120\sa240\keep \b\f20 Installation and Removal of Alarm Functionality\par \pard\plain \qj\fi180\sa240\keep \f20 It is important that you {\b do not} {\b delete the alarm soup} (take note, "Souper" users). If you do so, AlarmPkgUtil will not work properl y until you cold-boot the Newton. The details about the alarm soup are being purposely left undocumented. You should only interact with it indirectly, through the alarm API functions.\par \pard \qj\fi180\sa240\keep Using AlarmPkgUtil is the only safe way to remove the alarm functionality from a Newton without doing a cold-boot. The AlarmPkgUtil will also let you check if a Newton already has the alarm functionality installed.\par \pard\plain \s254\qj\sb120\sa240\keep \b\f20 Alarms and Sound\par \pard\plain \qj\fi180\sa240\keep \f20 You may have noticed the Alarm Sound Effects checkbox in the sound preferences panel. This contr ols whether or not the system beeps when an alarm goes off. If your alarms make their own sounds you may want to tell your users to turn off this setting in Prefs.\par \pard\plain \s254\qj\sb120\sa240\keep \b\f20 Courteous Usage of Alarms\par \pard\plain \qj\fi180\sa240\keep \f20 Applications need to be courteous in their usage of alarms. Limiting your applications to a single alarm might be too restrictive. On the other hand, scheduling a daily wake-up alarm for the next year by scheduling 365 different alarms would chew up a lot of the internal store. Use reasonable judgment. Remember, each alarm you schedule takes up space in the Newton's internal store.\par \pard \qj\fi180\sa240\keep Similarly, your alarm actions should be quick so you don't block other alarms. If you need to do something time consuming or repetitive, use a deferred action or set up an idle script.\par \pard \qj\fi180\sa240\keep Recall that idle scripts stop when the Newton goes to sleep. So using an idle script can only ensure the user notices your alarm next time they turn on the Newton. You can set more alarms to make sure the Newton wakes up periodically and tries to get the u ser's attention. However, each wake up uses power so you probably want to put a limit on this or you will eventually drain their Newton.\par }