  <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>
    </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:
-->
