aboutsummaryrefslogtreecommitdiffstats
path: root/doc/devel/calendar/alarm-generation.sgml
blob: 46f7e4bff1e2a10f3adda1e139edcdfbe26117c0 (plain) (blame)
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:
-->