= Alarmd - The Event Daemon =

== Introduction ==

Alarmd is a daemon that runs in the background and calls other applications
at certain times. It's function is similar to that of cron or at. The
applicationss need to specify when and how they want to be called.

Unlike cron/at, there is no multiuser support, all commands are run as the
user the daemon itself is running. Also, unlike cron, there is no way of
defining alarms to be run only on weekdays and so on, to achieve such
behavior, you need to add multiple alarms. The time difference between
recurrencies of an event is constant.

== Features ==

=== Event ===

The basic functionality of the daemon is to do something at certain times.
An event must always have the time when it is supposed to be run. This time
is measured in seconds since 00:00:00 1970-01-01 UTC and thus is time zone
independent. If your alarm time should depend on time zone, you need some
additional magic. Optionally an event can be specified to boot up the device
when due, for events that must not be missed. An event may also choose to
show up in status bar as an alarm icon.

Each event also has a unique identifier for removing and querying.

==== Recurring event ====

Normally an event is removed off the alarm queue, once it has been
acknowledged (and possible action run). However, it is possible to specify an
alarm that will repeat multiple times over certain time intervals. One can
either specify, how many times the event should repeat, or it can be repeated
indefinitely.

=== Action ===

An event may have an action associated, the action type decides what happends
when the event is due. An action may require the device to be fully powered
on (i.e. will not be run in acting dead) or require that there is some kind
of connection, otherwise it will not be run. A missed action (due to power off
or outage) will by default just be lost, but can be made to be run, when
the daemon starts the next time.

==== Dialog action ====

An action may show a dialog to the user, when the action is run. This dialog
may play a sound and show a certain message. The dialog may also allow the
user to snooze the action and postpone it by the time specified. If the
action has also dbus or exec action specified, these will be run only after
the user acknowledges the alarm. Optionally the snooze button can be disabled.

==== DBus action ====

An action may send a DBus method call or signal when it is run. This
functionality may be combined with dialog and the real dbus call is done only
after the user has acknowledged the alarm; thus allowing the user to postpone
the dbus action. DBus actions may give an arbitary number of basic DBus
arguments for the call or signal.

==== Exec action ====

An action may run a certain command when it is run. All commands will be run
as the user the daemon is run. (Should be "user"). The command may have
command line arguments, as supported by g_shell_parse_argv(). The standard
PATH is searched, if the command is not with full path.

=== Queue ===

The events live in a queue, sorted by their next due time. The queue can be
queried for events due in certain time frame and with certain flags. Any event
can also be removed from the queue.

== Programming ==

=== C API ===

==== Event struct ====

When handling events from your applications, the most important thing is the
alarm_event_t struct. It will contain all information about the given event.

===== alarm_time field =====

The field alarm_time will contain the time the event should happend (in
seconds since 00:00:00 1970-01-01 UTC).

===== recurrence field =====

The recurrence field specifies, how often should an alarm be repeated after
being acknowledged in minutes. The new time will always be calculated from the
previous occurr, snoozing does not affect here. (Unless snoozed longer than
the recurrency interval). I.e. Theres an alarm at 00:00 with recurrency of 10
minutes, the alarm is snoozed once for 5 minutes and then acknowledged, the
next occurr will happend at 00:10, not 00:15. Value 0 means the event happends
only once.

===== recurrence_count field =====

The recurrence_count field specifies, how many times should the event happend.
(at intervals specified in recurrence field).

===== snooze field =====

The snooze field specifies, how long should it take for an alarm dialog to be
reshown after the user has pressed snooze button. (Only applies to events
that don't have ALARM_EVENT_NO_DIALOG nor ALARM_EVENT_NO_SNOOZE in flags).

===== title field =====

The title field specifies a title for the alarm dialog. (Only applies to
events that don't have ALARM_EVENT_NO_DIALOG in flags.)

===== message field =====

The message field specifies a message shown in the alarm dialog when it is
shown. (Only applies to events that don't have ALARM_EVENT_NO_DIALOG in
flags).

===== sound field =====

The message field specifies a sound played during an alarm dialog is
shown. (Only applies to events that don't have ALARM_EVENT_NO_DIALOG in
flags).

===== icon field =====

The icon field specifies a icon shown in the alarm dialog when it is shown.
The icon should be either a file name with full path, or a icon name found
from the default GtkIconTheme. (Only applies to events that don't have
ALARM_EVENT_NO_DIALOG in flags).

===== dbus_interface field =====

The dbus_interface field specifies an interface used in a dbus method call or
signal. (Only applies to events that have dbus_path set.)

===== dbus_service field =====

The dbus_service field specifies a service being called in a dbus method call.
If this field is specified (not NULL), the dbus action will be a method call.
(Only applies to events that have dbus_path set.)

===== dbus_path field =====

The dbus_path field specifies a path of an object being called / a path a
signal is sent from. If this field is specified, the action will be a dbus
action.

===== dbus_name field =====

The dbus_name field specifies a name of the dbus method call or signal.
(Only applies to events that have dbus_path set.)

===== exec_name field =====

The exec_name field specifies a command line that should be run when the event
is due. (Only applies to events that don't have dbus_path set.)

===== flags field =====

The flags field specifies some properties of the event. The properties are
specified by the alarmeventflags enumeration, and different properties should
be bitwisely OR'ed together.

====== ALARM_EVENT_NO_DIALOG ======

If this flag is set, the event will not show a dialog when due, but only run
the action associated with it.

====== ALARM_EVENT_NO_SNOOZE ======

If this flag is set, the (possible) dialog will have the snooze button
disabled and thus cannot be snoozed by the user.

====== ALARM_EVENT_SYSTEM ======

If this flag is set, the (possible) dbus call/signal will be sent on the
system bus, instead of the session bus.

====== ALARM_EVENT_BOOT ======

If this flag is set, the event will power up the device from poweroff, when
the event is due.

====== ALARM_EVENT_ACTDEAD ======

If this flag is set and the device is powered off, the device will only be
booted to acting dead. The device will then only go to real power up only, if
mce is told to do it, alarm dialog is used with the power up dialog or if user
presses the power key.

====== ALARM_EVENT_SHOW_ICON ======

If this flag is set, the event will cause a alarm icon to be shown in the
status bar.

====== ALARM_EVENT_RUN_DELAYED ======

Normally event is removed if the alarm time passes while the device is off and
the flag ALARM_EVENT_BOOT is not set.

If the flag ALARM_EVENT_RUN_DELAYED is set, the event will be run when the
device is powered up next time.

====== ALARM_EVENT_CONNECTED ======

If this flag is set, the action of the event will only be run when there is an
ongoing connection.

==== alarm_event_add function ====

The alarm_event_add function adds an event into the event queue. The struct
passed to the function will define the type of the event (see alarm_event_t
struct). The returned value is a unique identifier for the event (or 0 on
failure).

==== alarm_event_add_with_dbus_params function ====

Like alarm_event_add, but adds an arbitary amount of arguments that will be
passed to the DBus call once made. This, of course, only applies to to
events that use the DBus type action, but it is safe to call this for other
types too, then the extra arguments have no effect. The extra arguments are
given in same manner as for dbus_message_append_args, i.e. type of argument -
pointer to argument data pairs, list ended with DBUS_TYPE_INVALID.

==== alarm_event_del function ====

The alarm_event_del function removes an event from the event queue. The
identifier passed should be as acquired from either alarm_event_add or
alarm_event_query. If the event was found and successfully removed, returns 1,
if the event was not found returns 0, and if an error occurred returns -1.

==== alarm_event_query function ====

The alarm_event_query function queries the event queue for events within
certain timeframe and with certain flags. Events with time between first and
last and flags specified on flag_mask matching the values in flags are
returned. To get all events between certain timeframe, pass 0 as flag_mask.
(see C API Example 3) The array is zero terminated and should be free'd with
free(). Note, empty array (contains only the zero terminator) is different
from NULL (returned on error).

==== alarm_event_get function ====

The alarm_event_get function gets information about an event in the event
queue. The identifier passed should be as acquired from either alarm_event_add
or alarm_event_query. If the event is not found returns NULL. The value
returned should be freed with alarm_event_free.

==== alarm_event_free function ====

The alarm_event_free function frees an alarm_event_t struct and all strings
in it.

== Appendices ==

=== C API examples ===

==== C API Example 1 ====

An event that shows a dialog in 30 minutes with message "foo" and with icon
named "foo" and a sound "/foo.mp3" played. No other action. Should the device
be powered off during this time, it will be started up. Snooze interval is 5
minutes and the alarm causes an icon to be shown in the status bar.

alarm_event_t event = {
	.alarm_time = time(NULL) + 10 * 60,
	.recurrence = 0,
	.snooze = 5,
	.message = "foo",
	.sound = "/foo.mp3",
	.icon = "foo",
	.flags = ALARM_EVENT_SHOW_ICON | ALARM_EVENT_BOOT
};
alarm_event_add(&event);

(Note this is not good code, but rather just a demonstration.)

==== C API Example 2 ====

An event that will do a dbus call every 10 minutes, if a connection is up,
indefinitely, starting after 10 minutes. A string "asdf" is passed as
argument to the call.

const char *argument = "asdf";
alarm_event_t event = {
	.alarm_time = time(NULL) + 10 * 60,
	.recurrence = 10,
	.recurrence_count = -1,
	.dbus_interface = "com.nokia.foo",
	.dbus_service = "com.nokia.foo",
	.dbus_path = "/com/nokia/foo",
	.dbus_name = "bar",
	.flags = ALARM_EVENT_NO_DIALOG
};
alarm_event_add_with_dbus_params(&event,
		DBUS_TYPE_STRING, &argument,
		DBUS_TYPE_INVALID);

==== C API Example 3 ====

Queries all events within 5 minutes, that need the power up funcionality, but
do not require connection.

cookie_t *events = alarm_event_query(time(NULL), time(NULL) + 5 * 60,
				     ALARM_EVENT_BOOT | ALARM_EVENT_CONNECTED,
				     ALARM_EVENT_BOOT);

=== C API header ===

typedef long cookie_t;

typedef enum {
	ALARM_EVENT_NO_DIALOG = 1 << 0,	/* Do not show the alarm dialog */
	ALARM_EVENT_NO_SNOOZE = 1 << 1,	/* Disable the snooze button */
	ALARM_EVENT_SYSTEM = 1 << 2,	/* Use the DBus system bus */
	ALARM_EVENT_BOOT = 1 << 3,	/* Boot up the system */
	ALARM_EVENT_ACTDEAD = 1 << 4,	/* Boot into alarm mode */
	ALARM_EVENT_SHOW_ICON = 1 << 5, /* Show alarm icon on statusbar */
	ALARM_EVENT_RUN_DELAYED = 1 << 6, /* Should the alarm be run on
					     startup if missed. */
	ALARM_EVENT_CONNECTED = 1 << 7, /* Run only when connected. */
	ALARM_EVENT_ACTIVATION = 1 << 8, /* Should DBus call use activation. */
	ALARM_EVENT_POSTPONE_DELAYED = 1 << 9, /* Should the alarm be postponed
						  if missed. */
	ALARM_EVENT_BACK_RESCHEDULE = 1 << 10, /* Should the event be moved
						  backwards, if time is changed
                                                  backwards. */
} alarmeventflags;

typedef struct {
	time_t alarm_time;		/* Time of alarm; UTC */
	uint32_t recurrence;		/* Number of minutes between
					 * each recurrence;
					 * 0 for one-shot alarms
					 */
	int32_t recurrence_count;	/* Number of recurrences, use -1 for
       					   infinite. */
	uint32_t snooze;		/* Number of minutes an alarm is
					 * potstponed on snooze. 0 for
					 * default */
	char *message;			/* Alarm message to display */
	char *sound;			/* Alarm sound to play */
	char *icon;			/* Alarm icon to use */
	char *dbus_interface;		/* DBus callback: interface */
	char *dbus_service;		/* DBus callback: service
					 * set to NULL to send a signal
					 */
	char *dbus_path;		/* DBus callback: path */
	char *dbus_name;		/* DBus callback: method_call/signal */
	char *exec_name;		/* File callback: file to execute */
	int32_t flags;			/* Event specific behaviour */

	uint32_t snoozed;		/* How much the event has been
					   snoozed. */
} alarm_event_t;

cookie_t alarm_event_add(alarm_event_t *event);
cookie_t alarm_event_add_with_dbus_params(alarm_event_t *event,
		int first_arg_type, ...);

int alarm_event_del(cookie_t event_cookie);
cookie_t *alarm_event_query(const time_t first, const time_t last,
		int32_t flag_mask, int32_t flags);
alarm_event_t *alarm_event_get(cookie_t event_cookie);
void alarm_event_free(alarm_event_t *event);

== License ==

Copyright (C) 2006 Nokia Corporation.

This is free software; see /usr/share/common-licenses/LGPL-2.1 for license
conditions.  There is NO  warranty;  not even for MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.

