1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
<chapter id="calendar-alarm-generation">
<title>How the Wombat generates alarm instances</title>
<para>
This chapter describes the algorithm that the &Wombat; uses
internally to generate instances of a calendar component's
alarms. You do not need to read this chapter if you are simply
using the client-side functions.
</para>
<sect1 id="what-makes-up-an-alarm-trigger">
<title>What makes up an alarm trigger</title>
<para>
VTODO and VEVENT calendar components can have any number of
alarms defined for them. Each alarm has a trigger
specification, an alarm type (display, audio, email, or
procedure), and data corresponding to the alarm type. The
Wombat side of things is interested only in the trigger
specification, since this is all that the Wombat needs to
produce alarm instances.
</para>
<para>
An alarm trigger can be relative or absolute. Relative
triggers occur a certain time before or after the start or end
of a calendar component's occurrence. For example, you could
configure a trigger to notify you 15 minutes before an
appointment starts, so that you can get to its location on
time; or another one to notify you 5 minutes after another
person's meeting has ended, so that you can call that person
on the phone after the meeting and not disturb him while
there. Absolute triggers occur at a specific point in time;
you can configure an alarm to trigger exactly at a particular
date and time that has no relation to the component's
occurrences at all.
</para>
</sect1>
<sect1 id="generating-trigger-instances">
<title>Generating trigger instances</title>
<para>
Generating absolute triggers is trivial; you just use the date
and time they specify. However, relative triggers are
associated to recurrence instances, so in order to generate
trigger instances we must generate the corresponding
recurrence instances and compute the trigger times based on
those.
</para>
<para>
Since relative triggers are specified as occurring a certain
amount of time before or after each of a calendar component's
recurrence instances, we can compute a trigger time by adding
or subtracting that amount of time to the corresponding
recurrence instance's time.
</para>
<para>
Recurrence instances are generated by specifying a range of
time and asking the Wombat to generate the instances that
occur within that range. We shall see that the range of time
in which instances occur is not necessarily the same range of
time in which those instances' alarm triggers occur.
</para>
<para>
Consider an alarm that is set to trigger 10 minutes before the
start time of an event's occurrence, that is, the trigger has
an offset of -10 minutes. Say this event recurs every hour at
5 minutes past the hour: it would occur at 1:05, 2:05, 3:05,
etc.; the corresponding triggers would occur at 12:55, 1:55,
2:55, etc. If we wish to compute the alarm triggers that
occur between 4:00 and 6:00 (which would be at 4:55 and 5:55),
then we cannot just generate recurrence instances between 4:00
and 6:00 because we will miss the 6:05 occurrence which
corresponds to the 5:55 trigger.
</para>
<para>
The solution is to expand the range of time on both sides to
fit the relative triggers that have the largest time periods.
If a trigger's offset is negative, like the -10 minutes in the
example above, then we must expand the
<emphasis>end</emphasis> of the time range: in the case above,
the range's ending time of 6:00 must be grown by 10 minutes to
6:10 so that the last recurrence instance will be that of
6:05; computing the trigger's offset we will get the 5:55
trigger, which is what we wanted. For triggers with positive
offsets, like if an alarm were to trigger 20 minutes after an
event's occurrence, we must expand the
<emphasis>start</emphasis> of the time range in an analogous
way, by subtracting the time offset from it.
</para>
<para>
Again, absolute triggers need no special computation. We can
just see if the trigger time is within the requested range of
time, and if so, we take that trigger occurrence into account
for the final result.
</para>
<para>
In addition, alarms may specify a number of repetitions and a
duration time. For example, an alarm may be configured to
repeat 3 extra times after the original occurrence with 5
minutes between each repetition. Again, for absolute triggers
this does not present a problem, as we can just generate the
repetitions starting from the absolute trigger time. For
relative triggers, we expand the range as described above and
also add the total offset for the repetitions to the start of
the range, i.e. 15 extra minutes for the case of 3 repetitions
with 5 minutes between each. We do not need to modify the end
of the range because alarm repetitions always have positive
offsets, so they are equivalent to relative alarm triggers
with positive offsets.
</para>
</sect1>
<sect1 id="alarm-trigger-generation-code">
<title>Alarm trigger generation code</title>
<para>
The main function to generate alarm trigger instances is
<function>generate_alarms_for_comp()</function> in
<filename>evolution/calendar/pcs/cal-backend-file.c</filename>.
This function calls <function>compute_alarm_range()</function>
to expand the specified range of time in the way described in
the previous section. It then generates the instances for
relative alarm triggers inside the
<function>add_alarm_occurrences_cb()</function> callback,
which is used by
<function>cal_recur_generate_instances()</function> with the
expanded range of time. The callback goes through all of the
calendar component's relative alarm triggers and adds the
trigger offsets to the occurrence's time; the results are
added as <structname>CalAlarmInstance</structname> structures
to the final list of trigger instances. Finally,
<function>generate_alarms_for_comp()</function> calls
<function>generate_absolute_triggers()</function>, which
simply adds the instances for absolute alarm triggers; these
are the absolute times that are within the time range that was
requested originally. In the very end, the list of instances
is sorted to produce nicer results.
</para>
</sect1>
</chapter>
<!--
Local variables:
mode: sgml
sgml-parent-document: ("../evolution-devel-guide.sgml" "book" "part" "")
End:
-->
|