# How the Wombat generates alarm instances

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.

## What makes up an alarm trigger

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.

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.

## Generating trigger instances

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.

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.

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.

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.

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 end 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 start of the time range in an analogous way, by subtracting the time offset from it.

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.

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.

## Alarm trigger generation code

The main function to generate alarm trigger instances is `generate_alarms_for_comp()` in `evolution/calendar/pcs/cal-backend-file.c`. This function calls `compute_alarm_range()` 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 `add_alarm_occurrences_cb()` callback, which is used by `cal_recur_generate_instances()` 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 CalAlarmInstance structures to the final list of trigger instances. Finally, `generate_alarms_for_comp()` calls `generate_absolute_triggers()`, 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.