2
* alarm.c -- Core alarm functionality
4
* Copyright (C) 2007-2008 Johannes H. Jensen <joh@pseudoberries.com>
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
* Johannes H. Jensen <joh@pseudoberries.com>
30
G_DEFINE_TYPE (Alarm, alarm, G_TYPE_OBJECT);
32
/* Prototypes and constants for property manipulation */
33
static void alarm_set_property(GObject *object,
38
static void alarm_get_property(GObject *object,
43
static void alarm_constructed (GObject *object);
45
static void alarm_dispose (GObject *object);
47
static void alarm_gconf_associate_schemas (Alarm *alarm);
49
static void alarm_gconf_connect (Alarm *alarm);
51
static void alarm_gconf_disconnect (Alarm *alarm);
53
static void alarm_gconf_dir_changed (GConfClient *client,
58
static void alarm_timer_start (Alarm *alarm);
59
static void alarm_timer_remove (Alarm *alarm);
60
static gboolean alarm_timer_is_started (Alarm *alarm);
62
static void alarm_player_start (Alarm *alarm);
63
static void alarm_player_stop (Alarm *alarm);
64
static void alarm_command_run (Alarm *alarm);
66
#define ALARM_PRIVATE(o) \
67
(G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_ALARM, AlarmPrivate))
69
typedef struct _AlarmPrivate AlarmPrivate;
73
GConfClient *gconf_client;
77
guint player_timer_id;
81
static GConfEnumStringPair alarm_type_enum_map [] = {
82
{ ALARM_TYPE_CLOCK, "clock" },
83
{ ALARM_TYPE_TIMER, "timer" },
87
static GConfEnumStringPair alarm_repeat_enum_map [] = {
88
{ ALARM_REPEAT_SUN, "sun" },
89
{ ALARM_REPEAT_MON, "mon" },
90
{ ALARM_REPEAT_TUE, "tue" },
91
{ ALARM_REPEAT_WED, "wed" },
92
{ ALARM_REPEAT_THU, "thu" },
93
{ ALARM_REPEAT_FRI, "fri" },
94
{ ALARM_REPEAT_SAT, "sat" },
98
static GConfEnumStringPair alarm_notify_type_enum_map [] = {
99
{ ALARM_NOTIFY_SOUND, "sound" },
100
{ ALARM_NOTIFY_COMMAND, "command" },
104
/* Property indexes */
123
#define PROP_NAME_DIR "gconf-dir"
124
#define PROP_NAME_ID "id"
125
#define PROP_NAME_TYPE "type"
126
#define PROP_NAME_TIME "time"
127
#define PROP_NAME_TIMESTAMP "timestamp"
128
#define PROP_NAME_ACTIVE "active"
129
#define PROP_NAME_MESSAGE "message"
130
#define PROP_NAME_REPEAT "repeat"
131
#define PROP_NAME_SNOOZE "snooze"
132
#define PROP_NAME_NOTIFY_TYPE "notify_type"
133
#define PROP_NAME_SOUND_FILE "sound_file"
134
#define PROP_NAME_SOUND_LOOP "sound_repeat"
135
#define PROP_NAME_COMMAND "command"
136
#define PROP_NAME_NOTIFY_BUBBLE "notify_bubble"
147
/* Signal identifier map */
148
static guint alarm_signal[LAST_SIGNAL] = {0, 0, 0};
150
/* Prototypes for signal handlers */
151
static void alarm_alarm (Alarm *alarm);
152
static void alarm_error (Alarm *alarm, GError *err);
153
static void alarm_player_changed (Alarm *alarm, MediaPlayerState state);
155
/* For debugging purposes only */
157
dump_list (GSList *list)
162
for (l = list; l; l = l->next) {
163
g_print ("%s", (gchar *)l->data);
171
/* Initialize the Alarm class */
173
alarm_class_init (AlarmClass *class)
175
GParamSpec *dir_param;
176
GParamSpec *id_param;
177
GParamSpec *type_param;
178
GParamSpec *time_param;
179
GParamSpec *timestamp_param;
180
GParamSpec *active_param;
181
GParamSpec *message_param;
182
GParamSpec *repeat_param;
183
GParamSpec *snooze_param;
184
GParamSpec *notify_type_param;
185
GParamSpec *sound_file_param;
186
GParamSpec *sound_loop_param;
187
GParamSpec *command_param;
188
GParamSpec *notify_bubble_param;
190
GObjectClass *g_object_class;
192
/* get handle to base object */
193
g_object_class = G_OBJECT_CLASS (class);
195
/* << miscellaneous initialization >> */
197
/* create GParamSpec descriptions for properties */
198
dir_param = g_param_spec_string (PROP_NAME_DIR,
200
"GConf base directory",
202
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
204
id_param = g_param_spec_uint (PROP_NAME_ID,
210
G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
212
type_param = g_param_spec_uint (PROP_NAME_TYPE,
221
time_param = g_param_spec_uint (PROP_NAME_TIME,
223
"time when the alarm should trigger",
226
ALARM_DEFAULT_TIME, /* default */
229
timestamp_param = g_param_spec_uint (PROP_NAME_TIMESTAMP,
231
"UNIX timestamp when the alarm should trigger",
234
ALARM_DEFAULT_TIME, /* default */
237
active_param = g_param_spec_boolean (PROP_NAME_ACTIVE,
239
"whether the alarm is on or not",
240
ALARM_DEFAULT_ACTIVE,
243
message_param = g_param_spec_string (PROP_NAME_MESSAGE,
245
"message which describes this alarm",
246
ALARM_DEFAULT_MESSAGE,
249
repeat_param = g_param_spec_uint (PROP_NAME_REPEAT,
252
ALARM_REPEAT_NONE, /* min */
253
ALARM_REPEAT_ALL, /* max */
254
ALARM_DEFAULT_REPEAT, /* default */
257
snooze_param = g_param_spec_uint (PROP_NAME_SNOOZE,
259
"enable snoozing of the alarm",
262
ALARM_DEFAULT_SNOOZE, /* default */
265
notify_type_param = g_param_spec_uint (PROP_NAME_NOTIFY_TYPE,
267
"what kind of notification should be used",
269
ALARM_NOTIFY_COMMAND,
270
ALARM_DEFAULT_NOTIFY_TYPE,
273
sound_file_param = g_param_spec_string (PROP_NAME_SOUND_FILE,
275
"sound file to play",
276
ALARM_DEFAULT_SOUND_FILE,
279
sound_loop_param = g_param_spec_boolean (PROP_NAME_SOUND_LOOP,
281
"whether the sound should be looped",
282
ALARM_DEFAULT_SOUND_LOOP,
285
command_param = g_param_spec_string (PROP_NAME_COMMAND,
288
ALARM_DEFAULT_COMMAND,
291
notify_bubble_param = g_param_spec_boolean (PROP_NAME_NOTIFY_BUBBLE,
292
"notification bubble",
293
"whether the alarm should display a notification bubble when triggered",
294
ALARM_DEFAULT_NOTIFY_BUBBLE,
298
/* override base object methods */
299
g_object_class->set_property = alarm_set_property;
300
g_object_class->get_property = alarm_get_property;
301
g_object_class->constructed = alarm_constructed;
302
g_object_class->dispose = alarm_dispose;
304
/* install properties */
305
g_object_class_install_property (g_object_class, PROP_DIR, dir_param);
306
g_object_class_install_property (g_object_class, PROP_ID, id_param);
307
g_object_class_install_property (g_object_class, PROP_TYPE, type_param);
308
g_object_class_install_property (g_object_class, PROP_TIME, time_param);
309
g_object_class_install_property (g_object_class, PROP_TIMESTAMP, timestamp_param);
310
g_object_class_install_property (g_object_class, PROP_ACTIVE, active_param);
311
g_object_class_install_property (g_object_class, PROP_MESSAGE, message_param);
312
g_object_class_install_property (g_object_class, PROP_REPEAT, repeat_param);
313
g_object_class_install_property (g_object_class, PROP_SNOOZE, snooze_param);
314
g_object_class_install_property (g_object_class, PROP_NOTIFY_TYPE, notify_type_param);
315
g_object_class_install_property (g_object_class, PROP_SOUND_FILE, sound_file_param);
316
g_object_class_install_property (g_object_class, PROP_SOUND_LOOP, sound_loop_param);
317
g_object_class_install_property (g_object_class, PROP_COMMAND, command_param);
318
g_object_class_install_property (g_object_class, PROP_NOTIFY_BUBBLE, notify_bubble_param);
320
g_type_class_add_private (class, sizeof (AlarmPrivate));
322
/* set signal handlers */
323
class->alarm = alarm_alarm;
324
class->error = alarm_error;
325
class->player_changed = alarm_player_changed;
327
/* install signals and default handlers */
328
alarm_signal[SIGNAL_ALARM] = g_signal_new ("alarm", /* name */
329
TYPE_ALARM, /* class type identifier */
330
G_SIGNAL_RUN_LAST, /* options */
331
G_STRUCT_OFFSET (AlarmClass, alarm), /* handler offset */
332
NULL, /* accumulator function */
333
NULL, /* accumulator data */
334
g_cclosure_marshal_VOID__VOID, /* marshaller */
335
G_TYPE_NONE, /* type of return value */
338
alarm_signal[SIGNAL_ERROR] = g_signal_new ("error",
341
G_STRUCT_OFFSET (AlarmClass, error),
344
g_cclosure_marshal_VOID__POINTER,
349
alarm_signal[SIGNAL_PLAYER] = g_signal_new ("player_changed", /* name */
350
TYPE_ALARM, /* class type identifier */
351
G_SIGNAL_RUN_LAST, /* options */
352
G_STRUCT_OFFSET (AlarmClass, player_changed), /* handler offset */
353
NULL, /* accumulator function */
354
NULL, /* accumulator data */
355
g_cclosure_marshal_VOID__UINT, /* marshaller */
356
G_TYPE_NONE, /* type of return value */
362
* Utility function for extracting the strings out of a GConfValue of type
363
* GCONF_VALUE_LIST and placing them in a plan GSList of strings.
365
* Note: You should free the GSList returned but NOT the string contents.
368
alarm_gconf_extract_list_string (GConfValue *val)
370
GSList *list, *new_list, *l;
372
g_assert (GCONF_VALUE_STRING == gconf_value_get_list_type (val));
374
/* Fetch GSList of GConfValues. Extract them and put into a plain list of strings.
375
* Note that the returned string from gconf_value_get_string() is owned by the GConfValue
376
* and should thus NOT be freed.
378
list = gconf_value_get_list (val);
380
for (l = list; l; l = l->next) {
381
new_list = g_slist_append (new_list, (gpointer) gconf_value_get_string ((GConfValue *)l->data));
388
alarm_gconf_load (Alarm *alarm)
390
AlarmPrivate *priv = ALARM_PRIVATE (alarm);
391
GConfClient *client = priv->gconf_client;
400
key = alarm_gconf_get_full_key (alarm, PROP_NAME_TYPE);
401
tmp = gconf_client_get_string (client, key, NULL);
404
i = alarm_type_from_string (tmp);
409
// Not found in GConf, fall back to defaults
410
alarm->type = ALARM_DEFAULT_TYPE;
411
g_object_set (alarm, PROP_NAME_TYPE, ALARM_DEFAULT_TYPE, NULL);
420
key = alarm_gconf_get_full_key (alarm, PROP_NAME_TIME);
421
val = gconf_client_get (client, key, NULL);
425
alarm->time = (time_t)gconf_value_get_int (val);
426
gconf_value_free (val);
428
// Not found in GConf, fall back to defaults
429
g_object_set (alarm, PROP_NAME_TIME, ALARM_DEFAULT_TIME, NULL);
435
key = alarm_gconf_get_full_key (alarm, PROP_NAME_TIMESTAMP);
436
val = gconf_client_get (client, key, NULL);
440
alarm->timestamp = (time_t)gconf_value_get_int (val);
441
gconf_value_free (val);
443
// Not found in GConf, fall back to defaults
444
g_object_set (alarm, PROP_NAME_TIMESTAMP, ALARM_DEFAULT_TIMESTAMP, NULL);
450
key = alarm_gconf_get_full_key (alarm, PROP_NAME_ACTIVE);
451
val = gconf_client_get (client, key, NULL);
455
// We g_object_set here so the timer will be started for
457
g_object_set (alarm, "active", gconf_value_get_bool (val), NULL);
458
gconf_value_free (val);
460
// Not found in GConf, fall back to defaults
461
g_object_set (alarm, PROP_NAME_ACTIVE, ALARM_DEFAULT_ACTIVE, NULL);
467
key = alarm_gconf_get_full_key (alarm, PROP_NAME_MESSAGE);
468
tmp = gconf_client_get_string (client, key, NULL);
472
alarm->message = tmp;
474
// Not found in GConf, fall back to defaults
475
g_object_set (alarm, PROP_NAME_MESSAGE, ALARM_DEFAULT_MESSAGE, NULL);
481
key = alarm_gconf_get_full_key (alarm, PROP_NAME_REPEAT);
482
val = gconf_client_get (client, key, NULL);
486
list = alarm_gconf_extract_list_string (val);
488
alarm->repeat = alarm_repeat_from_list (list);
491
gconf_value_free (val);
493
// Not found in GConf, fall back to defaults
494
g_object_set (alarm, PROP_NAME_REPEAT, ALARM_DEFAULT_REPEAT, NULL);
500
key = alarm_gconf_get_full_key (alarm, PROP_NAME_SNOOZE);
501
val = gconf_client_get (client, key, NULL);
505
alarm->snooze = gconf_value_get_int (val);
506
gconf_value_free (val);
508
// Not found in GConf, fall back to defaults
509
g_object_set (alarm, PROP_NAME_SNOOZE, ALARM_DEFAULT_SNOOZE, NULL);
515
key = alarm_gconf_get_full_key (alarm, PROP_NAME_NOTIFY_TYPE);
516
tmp = gconf_client_get_string (client, key, NULL);
519
i = alarm_notify_type_from_string (tmp);
522
alarm->notify_type = i;
524
// Not found in GConf, fall back to defaults
525
g_object_set (alarm, PROP_NAME_NOTIFY_TYPE, ALARM_DEFAULT_NOTIFY_TYPE, NULL);
534
key = alarm_gconf_get_full_key (alarm, PROP_NAME_SOUND_FILE);
535
tmp = gconf_client_get_string (client, key, NULL);
539
alarm->sound_file = tmp;
541
// Not found in GConf, fall back to defaults
542
g_object_set (alarm, PROP_NAME_SOUND_FILE, ALARM_DEFAULT_SOUND_FILE, NULL);
548
key = alarm_gconf_get_full_key (alarm, PROP_NAME_SOUND_LOOP);
549
val = gconf_client_get (client, key, NULL);
553
alarm->sound_loop = gconf_value_get_bool (val);
554
gconf_value_free (val);
556
// Not found in GConf, fall back to defaults
557
g_object_set (alarm, PROP_NAME_SOUND_LOOP, ALARM_DEFAULT_SOUND_LOOP, NULL);
564
key = alarm_gconf_get_full_key (alarm, PROP_NAME_COMMAND);
565
tmp = gconf_client_get_string (client, key, NULL);
569
alarm->command = tmp;
571
// Not found in GConf, fall back to defaults
572
g_object_set (alarm, PROP_NAME_COMMAND, ALARM_DEFAULT_COMMAND, NULL);
579
key = alarm_gconf_get_full_key (alarm, PROP_NAME_NOTIFY_BUBBLE);
580
val = gconf_client_get (client, key, NULL);
584
alarm->notify_bubble = gconf_value_get_bool (val);
585
gconf_value_free (val);
587
// Not found in GConf, fall back to defaults
588
g_object_set (alarm, PROP_NAME_NOTIFY_BUBBLE, ALARM_DEFAULT_NOTIFY_BUBBLE, NULL);
593
alarm_init (Alarm *self)
595
AlarmPrivate *priv = ALARM_PRIVATE (self);
597
self->gconf_dir = NULL;
600
priv->gconf_listener = 0;
601
priv->gconf_client = gconf_client_get_default ();
605
alarm_constructed (GObject *object)
607
Alarm *alarm = ALARM (object);
609
// Load gconf settings
610
alarm_gconf_load (alarm);
612
// Connect gconf listener
613
//alarm_gconf_connect (alarm);
616
/* set an Alarm property */
618
alarm_set_property (GObject *object,
624
AlarmPrivate *priv = ALARM_PRIVATE (object);
631
AlarmType type, new_type;
637
alarm = ALARM (object);
638
client = priv->gconf_client;
640
g_debug ("set_property %s", pspec->name);
644
str = g_value_get_string (value);
648
g_critical ("Invalid gconf-dir value: \"%s\": NULL", str);
652
if (!gconf_valid_key (str, &tmp)) {
653
g_critical ("Invalid gconf-dir value: \"%s\": %s", str, tmp);
658
if (!alarm->gconf_dir || strcmp (str, alarm->gconf_dir) != 0) {
659
// Changed, remove old gconf listeners
660
alarm_gconf_disconnect (alarm);
662
if (alarm->gconf_dir != NULL)
663
g_free (alarm->gconf_dir);
664
alarm->gconf_dir = g_strdup (str);
667
alarm_gconf_associate_schemas (alarm);
669
alarm_gconf_connect (alarm);
673
d = g_value_get_uint (value);
675
if (d != alarm->id) {
676
alarm_gconf_disconnect (alarm);
679
alarm_gconf_associate_schemas (alarm);
681
alarm_gconf_load (alarm);
682
alarm_gconf_connect (alarm);
686
alarm->type = g_value_get_uint (value);
688
// If we changed from CLOCK to TIMER we need to update the time
689
if (alarm->type == ALARM_TYPE_TIMER && alarm->active) {
690
alarm_update_timestamp (alarm);
693
key = alarm_gconf_get_full_key (alarm, PROP_NAME_TYPE);
695
if (!gconf_client_set_string (client, key,
696
alarm_type_to_string (alarm->type),
699
g_critical ("Could not set %s (gconf): %s",
708
alarm->time = g_value_get_uint (value);
712
alarm_update_timestamp (alarm);
715
key = alarm_gconf_get_full_key (alarm, PROP_NAME_TIME);
717
if (!gconf_client_set_int (client, key, alarm->time, &err)) {
719
g_critical ("Could not set %s (gconf): %s",
728
alarm->timestamp = g_value_get_uint (value);
730
key = alarm_gconf_get_full_key (alarm, PROP_NAME_TIMESTAMP);
732
if (!gconf_client_set_int (client, key, alarm->timestamp, &err)) {
734
g_critical ("Could not set %s (gconf): %s",
743
bool = alarm->active;
744
alarm->active = g_value_get_boolean (value);
746
//g_debug ("[%p] #%d ACTIVE: old=%d new=%d", alarm, alarm->id, bool, alarm->active);
747
if (alarm->active && !alarm_timer_is_started(alarm)) {
749
alarm_timer_start (alarm);
751
else if (!alarm->active && alarm_timer_is_started(alarm)) {
753
alarm_timer_remove (alarm);
757
key = alarm_gconf_get_full_key (alarm, PROP_NAME_ACTIVE);
759
if (!gconf_client_set_bool (client, key, alarm->active, &err)) {
761
g_critical ("Could not set %s (gconf): %s",
771
g_free (alarm->message);
773
alarm->message = g_strdup (g_value_get_string (value));
775
key = alarm_gconf_get_full_key (alarm, PROP_NAME_MESSAGE);
777
if (!gconf_client_set_string (client, key,
781
g_critical ("Could not set %s (gconf): %s",
791
alarm->repeat = g_value_get_uint (value);
794
alarm_update_timestamp (alarm);
797
key = alarm_gconf_get_full_key (alarm, PROP_NAME_REPEAT);
798
list = alarm_repeat_to_list (alarm->repeat);
800
if (!gconf_client_set_list(client, key,
801
GCONF_VALUE_STRING, list,
804
g_critical ("Could not set %s (gconf): %s",
815
alarm->snooze = g_value_get_uint (value);
817
key = alarm_gconf_get_full_key (alarm, PROP_NAME_SNOOZE);
819
if (!gconf_client_set_int (client, key, alarm->snooze, &err)) {
821
g_critical ("Could not set %s (gconf): %s",
829
case PROP_NOTIFY_TYPE:
830
alarm->notify_type = g_value_get_uint (value);
832
key = alarm_gconf_get_full_key (alarm, PROP_NAME_NOTIFY_TYPE);
834
if (!gconf_client_set_string (client, key,
835
alarm_notify_type_to_string (alarm->notify_type),
838
g_critical ("Could not set %s (gconf): %s",
847
case PROP_SOUND_FILE:
848
alarm->sound_file = g_strdup (g_value_get_string (value));
850
key = alarm_gconf_get_full_key (alarm, PROP_NAME_SOUND_FILE);
852
if (!gconf_client_set_string (client, key,
856
g_critical ("Could not set %s (gconf): %s",
865
case PROP_SOUND_LOOP:
866
alarm->sound_loop = g_value_get_boolean (value);
868
key = alarm_gconf_get_full_key (alarm, PROP_NAME_SOUND_LOOP);
870
if (!gconf_client_set_bool (client, key, alarm->sound_loop, &err)) {
872
g_critical ("Could not set %s (gconf): %s",
881
alarm->command = g_strdup (g_value_get_string (value));
883
key = alarm_gconf_get_full_key (alarm, PROP_NAME_COMMAND);
885
if (!gconf_client_set_string (client, key,
889
g_critical ("Could not set %s (gconf): %s",
898
case PROP_NOTIFY_BUBBLE:
899
bool = alarm->notify_bubble;
900
alarm->notify_bubble = g_value_get_boolean (value);
902
key = alarm_gconf_get_full_key (alarm, PROP_NAME_NOTIFY_BUBBLE);
904
if (!gconf_client_set_bool (client, key, alarm->notify_bubble, &err)) {
906
g_critical ("Could not set %s (gconf): %s",
915
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
920
/* retrive an Alarm property */
922
alarm_get_property (GObject *object,
927
Alarm *alarm = ALARM (object);
931
g_value_set_string (value, alarm->gconf_dir);
934
g_value_set_uint (value, alarm->id);
937
g_value_set_uint (value, alarm->type);
940
g_value_set_uint (value, alarm->time);
943
g_value_set_uint (value, alarm->timestamp);
946
g_value_set_boolean (value, alarm->active);
949
g_value_set_string (value, alarm->message);
952
g_value_set_uint (value, alarm->repeat);
955
g_value_set_uint (value, alarm->snooze);
957
case PROP_NOTIFY_TYPE:
958
g_value_set_uint (value, alarm->notify_type);
960
case PROP_SOUND_FILE:
961
g_value_set_string (value, alarm->sound_file);
963
case PROP_SOUND_LOOP:
964
g_value_set_boolean (value, alarm->sound_loop);
967
g_value_set_string (value, alarm->command);
969
case PROP_NOTIFY_BUBBLE:
970
g_value_set_boolean (value, alarm->notify_bubble);
973
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
982
alarm_error_quark (void)
984
return g_quark_from_static_string ("alarm-error-quark");
988
alarm_error (Alarm *alarm, GError *err)
990
g_debug ("[%p] #%d: alarm_error: #%d: %s", alarm, alarm->id, err->code, err->message);
994
alarm_error_trigger (Alarm *alarm, AlarmErrorCode code, const gchar *msg)
996
GError *err = g_error_new (ALARM_ERROR, code, "%s", msg);
998
g_signal_emit (alarm, alarm_signal[SIGNAL_ERROR], 0, err, NULL);
1006
alarm_player_changed (Alarm *alarm, MediaPlayerState state)
1008
g_debug ("alarm_player_changed (%p, %d)", alarm, state);
1017
alarm_alarm (Alarm *alarm)
1019
g_debug ("[%p] #%d: alarm_alarm", alarm, alarm->id);
1023
alarm_trigger (Alarm *alarm)
1025
g_signal_emit (alarm, alarm_signal[SIGNAL_ALARM], 0, NULL);
1028
* Do we want to repeat this alarm?
1030
if (alarm_should_repeat (alarm)) {
1031
g_debug ("alarm_trigger REPEATING");
1032
alarm_update_timestamp_full (alarm, FALSE);
1034
alarm_disable (alarm);
1037
switch (alarm->notify_type) {
1038
case ALARM_NOTIFY_SOUND:
1039
// Start sound playback
1040
g_debug("[%p] #%d Start player", alarm, alarm->id);
1041
alarm_player_start (alarm);
1043
case ALARM_NOTIFY_COMMAND:
1045
g_debug("[%p] #%d Start command", alarm, alarm->id);
1046
alarm_command_run (alarm);
1049
g_debug ("NOTIFICATION TYPE %d Not yet implemented.", alarm->notify_type);
1054
* Convenience functions for enabling/disabling the alarm.
1056
* Will update timestamp if needed.
1059
alarm_set_enabled (Alarm *alarm, gboolean enabled)
1062
alarm_update_timestamp (alarm);
1065
g_object_set (alarm, "active", enabled, NULL);
1069
alarm_enable (Alarm *alarm)
1071
alarm_set_enabled (alarm, TRUE);
1075
alarm_disable (Alarm *alarm)
1077
alarm_set_enabled (alarm, FALSE);
1081
* Delete alarm. This will remove all configuration
1082
* associated with this alarm.
1085
alarm_delete (Alarm *alarm)
1087
AlarmPrivate *priv = ALARM_PRIVATE (alarm);
1088
GConfClient *client = priv->gconf_client;
1091
// Disconnect gconf listeners
1092
alarm_gconf_disconnect (alarm);
1094
// Remove configuration
1095
key = alarm_gconf_get_dir (alarm);
1096
g_debug ("alarm_delete: recursive unset on %s", key);
1097
gconf_client_recursive_unset (client, key, GCONF_UNSET_INCLUDING_SCHEMA_NAMES, NULL);
1098
gconf_client_suggest_sync (client, NULL);
1106
alarm_snooze (Alarm *alarm)
1109
if (alarm->snooze == 0) {
1110
alarm_clear (alarm);
1114
if (!alarm_is_playing (alarm)) return;
1116
g_debug ("alarm_snooze SNOOZING FOR %d minutes", alarm->snooze);
1118
time_t now = time (NULL);
1120
g_object_set (alarm,
1121
"timestamp", now + alarm->snooze * 60,
1125
alarm_clear (alarm);
1129
* Clear the alarm. This will stop any running players.
1132
alarm_clear (Alarm *alarm)
1134
alarm_player_stop (alarm);
1138
* Is the alarm playing?
1141
alarm_is_playing (Alarm *a)
1143
AlarmPrivate *priv = ALARM_PRIVATE (a);
1145
return priv->player && priv->player->state == MEDIA_PLAYER_PLAYING;
1151
alarm_timer_update (Alarm *alarm)
1157
if (now >= alarm->timestamp) {
1158
alarm_trigger (alarm);
1160
// Remove callback only if we don't intend to repeat the alarm
1161
return alarm_should_repeat (alarm);
1162
} else if (alarm->timestamp - now <= 10) {
1163
g_debug ("[%p] #%d %2d...", alarm, alarm->id, (int)(alarm->timestamp - now));
1171
alarm_timer_start (Alarm *alarm)
1173
AlarmPrivate *priv = ALARM_PRIVATE(alarm);
1175
g_debug ("[%p] #%d timer_start", alarm, alarm->id);
1177
// Remove old timer, if any
1178
alarm_timer_remove (alarm);
1180
// Keep us updated every 1 second
1181
priv->timer_id = g_timeout_add_seconds (1, (GSourceFunc) alarm_timer_update, alarm);
1185
alarm_timer_is_started (Alarm *alarm)
1187
AlarmPrivate *priv = ALARM_PRIVATE(alarm);
1189
return priv->timer_id > 0;
1193
alarm_timer_remove (Alarm *alarm)
1195
AlarmPrivate *priv = ALARM_PRIVATE(alarm);
1197
if (alarm_timer_is_started(alarm)) {
1198
g_debug ("#%d timer_remove (%p)", alarm->id, alarm);
1200
g_source_remove (priv->timer_id);
1212
* Taken from panel-applet.c
1215
alarm_gconf_associate_schemas (Alarm *alarm)
1217
AlarmPrivate *priv = ALARM_PRIVATE (alarm);
1218
GConfClient *client = priv->gconf_client;
1220
GError *error = NULL;
1225
list = gconf_client_all_entries (client, ALARM_GCONF_SCHEMA_DIR, &error);
1227
g_return_if_fail (error == NULL);
1229
for (l = list; l; l = l->next) {
1230
GConfEntry *entry = l->data;
1234
tmp = g_path_get_basename (gconf_entry_get_key (entry));
1236
if (strchr (tmp, '-'))
1237
g_warning ("Applet key '%s' contains a hyphen. Please "
1238
"use underscores in gconf keys\n", tmp);
1240
key = alarm_gconf_get_full_key (alarm, tmp);
1244
gconf_engine_associate_schema (
1245
client->engine, key, gconf_entry_get_key (entry), &error);
1249
gconf_entry_free (entry);
1252
g_slist_free (list);
1257
g_slist_free (list);
1261
alarm_gconf_connect (Alarm *alarm)
1263
AlarmPrivate *priv = ALARM_PRIVATE (alarm);
1267
// g_debug ("gconf_connect (%p) ? %d", alarm, IS_ALARM ((gpointer)alarm));
1272
dir = alarm_gconf_get_dir (alarm);
1274
// g_debug ("alarm_gconf_connect (%p) to dir %s", alarm, dir);
1276
gconf_client_add_dir (priv->gconf_client, dir,
1277
GCONF_CLIENT_PRELOAD_ONELEVEL, &err);
1280
g_warning ("alarm_gconf_connect (%p): gconf_client_add_dir (%s) failed: %s", alarm, dir, err->message);
1285
priv->gconf_listener =
1286
gconf_client_notify_add (
1287
priv->gconf_client, dir,
1288
(GConfClientNotifyFunc) alarm_gconf_dir_changed,
1292
g_warning ("alarm_gconf_connect (%p): gconf_client_notify_add (%s) failed: %s", alarm, dir, err->message);
1297
// g_debug ("alarm_gconf_connect: Added listener %d to alarm #%d %p", priv->gconf_listener, alarm->id, alarm);
1303
alarm_gconf_disconnect (Alarm *alarm)
1305
AlarmPrivate *priv = ALARM_PRIVATE (alarm);
1308
if (priv->gconf_listener) {
1309
//g_debug ("alarm_gconf_disconnect: Removing listener %d from alarm #%d %p", priv->gconf_listener, alarm->id, alarm);
1310
gconf_client_notify_remove (priv->gconf_client, priv->gconf_listener);
1311
priv->gconf_listener = 0;
1313
dir = alarm_gconf_get_dir (alarm);
1314
gconf_client_remove_dir (priv->gconf_client, dir, NULL);
1320
* Updates the local copy with the new value if it has changed.
1323
alarm_gconf_dir_changed (GConfClient *client,
1328
Alarm *alarm = ALARM (data);
1337
name = g_path_get_basename (entry->key);
1338
param = g_object_class_find_property (G_OBJECT_GET_CLASS (alarm), name);
1345
g_debug ("alarm_gconf changed #%d %p: %s", alarm->id, alarm, name);
1347
switch (param->param_id) {
1349
str = gconf_value_get_string (entry->value);
1350
i = alarm_type_from_string (str);
1351
if (i > 0 && i != alarm->type)
1352
g_object_set (alarm, name, i, NULL);
1355
i = gconf_value_get_int (entry->value);
1356
if (i != alarm->time)
1357
g_object_set (alarm, name, i, NULL);
1359
case PROP_TIMESTAMP:
1360
i = gconf_value_get_int (entry->value);
1361
if (i != alarm->timestamp)
1362
g_object_set (alarm, name, i, NULL);
1365
b = gconf_value_get_bool (entry->value);
1366
if (b != alarm->active) {
1367
g_debug ("[%p] #%d GCONF-ACTIVE changed from %d to %d", alarm, alarm->id, alarm->active, b);
1368
g_object_set (alarm, name, b, NULL);
1372
str = gconf_value_get_string (entry->value);
1373
if (strcmp (str, alarm->message) != 0)
1374
g_object_set (alarm, name, str, NULL);
1377
list = alarm_gconf_extract_list_string (entry->value);
1379
i = alarm_repeat_from_list (list);
1380
if (i != alarm->repeat)
1381
g_object_set (alarm, name, i, NULL);
1383
g_slist_free (list);
1386
i = gconf_value_get_int (entry->value);
1387
if (i != alarm->snooze)
1388
g_object_set (alarm, name, i, NULL);
1390
case PROP_NOTIFY_TYPE:
1391
str = gconf_value_get_string (entry->value);
1392
i = alarm_notify_type_from_string (str);
1393
if (i > 0 && i != alarm->notify_type)
1394
g_object_set (alarm, name, i, NULL);
1396
case PROP_SOUND_FILE:
1397
str = gconf_value_get_string (entry->value);
1398
if (strcmp (str, alarm->sound_file) != 0)
1399
g_object_set (alarm, name, str, NULL);
1401
case PROP_SOUND_LOOP:
1402
b = gconf_value_get_bool (entry->value);
1403
if (b != alarm->sound_loop)
1404
g_object_set (alarm, name, b, NULL);
1407
str = gconf_value_get_string (entry->value);
1408
if (strcmp (str, alarm->command) != 0)
1409
g_object_set (alarm, name, str, NULL);
1411
case PROP_NOTIFY_BUBBLE:
1412
b = gconf_value_get_bool (entry->value);
1413
if (b != alarm->notify_bubble)
1414
g_object_set (alarm, name, b, NULL);
1417
g_warning ("Valid property ID %d not handled!", param->param_id);
1425
alarm_dispose (GObject *object)
1427
Alarm *alarm = ALARM (object);
1428
AlarmPrivate *priv = ALARM_PRIVATE (object);
1429
GObjectClass *parent = (GObjectClass *)alarm_parent_class;
1431
g_debug ("alarm_dispose (%p)", alarm);
1433
if (parent->dispose)
1434
parent->dispose (object);
1436
alarm_gconf_disconnect (alarm);
1437
alarm_timer_remove(alarm);
1438
alarm_clear (alarm);
1442
* Convenience function for creating a new alarm instance.
1443
* Passing -1 as the id will generate a new ID with alarm_gen_id
1446
alarm_new (const gchar *gconf_dir, gint id)
1451
id = alarm_gen_id_dir (gconf_dir);
1454
alarm = g_object_new (TYPE_ALARM,
1455
"gconf-dir", gconf_dir,
1463
alarm_gen_id_dir (const gchar *gconf_dir)
1465
GConfClient *client;
1469
client = gconf_client_get_default ();
1476
key = g_strdup_printf("%s/" ALARM_GCONF_DIR_PREFIX "%d", gconf_dir, id);
1479
} while (gconf_client_dir_exists (client, key, NULL));
1483
return (guint)(id-1);
1487
* Will try to find the first available ID in gconf_dir
1490
alarm_gen_id (Alarm *alarm)
1492
return alarm_gen_id_dir (alarm->gconf_dir);
1495
const gchar *alarm_type_to_string (AlarmType type)
1497
return gconf_enum_to_string (alarm_type_enum_map, type);
1500
AlarmType alarm_type_from_string (const gchar *type)
1502
AlarmType ret = ALARM_TYPE_INVALID;
1507
gconf_string_to_enum (alarm_type_enum_map, type, (gint *)&ret);
1512
const gchar *alarm_notify_type_to_string (AlarmNotifyType type)
1514
return gconf_enum_to_string (alarm_notify_type_enum_map, type);
1517
AlarmNotifyType alarm_notify_type_from_string (const gchar *type)
1519
AlarmNotifyType ret = ALARM_NOTIFY_INVALID;
1524
gconf_string_to_enum (alarm_notify_type_enum_map, type, (gint *)&ret);
1530
alarm_gconf_get_dir (Alarm *alarm)
1534
g_return_val_if_fail (IS_ALARM (alarm), NULL);
1536
key = g_strdup_printf ("%s/" ALARM_GCONF_DIR_PREFIX "%d", alarm->gconf_dir, alarm->id);
1542
alarm_gconf_get_full_key (Alarm *alarm, const gchar *key)
1546
g_return_val_if_fail (IS_ALARM (alarm), NULL);
1551
full_key = g_strdup_printf ("%s/" ALARM_GCONF_DIR_PREFIX "%d/%s", alarm->gconf_dir, alarm->id, key);
1562
static AlarmBindArg *
1563
alarm_bind_arg_new (GObject *object, const gchar *name, gulong handler_id)
1567
arg = g_new (AlarmBindArg, 1);
1568
arg->object = object;
1570
arg->handler_id = handler_id;
1576
alarm_bind_arg_free (AlarmBindArg *arg)
1581
g_free ((gpointer)arg);
1585
alarm_bind_update (GObject *object,
1590
AlarmBindArg *arg = (AlarmBindArg *)data;
1594
* Determine which argument is the alarm
1596
/*if (IS_ALARM (object)) {
1597
alarm = ALARM (object);
1599
alarm = ALARM (arg->object);
1602
g_debug ("alarm_bind_update #%d(%p) [%s] -> %p [%s]", alarm->id, alarm, pspec->name, arg->object, arg->name);
1604
g_object_get (object, pspec->name, &d, NULL);
1606
// Block other signal handler
1607
g_signal_handlers_block_matched(arg->object,
1608
G_SIGNAL_MATCH_FUNC,
1609
0, 0, NULL, alarm_bind_update, NULL);
1611
g_object_set (arg->object, arg->name, d, NULL);
1613
g_signal_handlers_unblock_matched(arg->object,
1614
G_SIGNAL_MATCH_FUNC,
1615
0, 0, NULL, alarm_bind_update, NULL);
1619
* We would like to disconnect any signal handlers from the alarm
1620
* when the destination object is finalized. And vice versa.
1623
alarm_bind_weak_notify (gpointer data, GObject *where_the_object_was)
1625
AlarmBindArg *arg = (AlarmBindArg *)data;
1628
g_assert (arg->object);
1629
g_assert (arg->handler_id);
1631
if (G_IS_OBJECT (arg->object)) {
1632
if (g_signal_handler_is_connected (arg->object, arg->handler_id)) {
1633
g_signal_handler_disconnect (arg->object, arg->handler_id);
1637
alarm_bind_arg_free (arg);
1644
alarm_bind (Alarm *alarm,
1647
const gchar *dest_prop)
1649
AlarmBindArg *arg, *obj_arg;
1652
gulong handler, obj_handler;
1654
param = g_object_class_find_property (G_OBJECT_GET_CLASS(alarm), prop);
1656
param = g_object_class_find_property (G_OBJECT_GET_CLASS(dest), dest_prop);
1659
// g_debug ("Bind from %p [%s] -> %p [%s]", alarm, prop, dest, dest_prop);
1662
tmp = g_strdup_printf("notify::%s", prop);
1663
arg = alarm_bind_arg_new (dest, dest_prop, 0);
1664
handler = g_signal_connect (alarm, tmp, G_CALLBACK (alarm_bind_update), arg);
1668
tmp = g_strdup_printf ("notify::%s", dest_prop);
1669
obj_arg = alarm_bind_arg_new (G_OBJECT (alarm), prop, handler);
1670
obj_handler = g_signal_connect (dest, tmp, G_CALLBACK (alarm_bind_update), obj_arg);
1673
arg->handler_id = obj_handler;
1675
// Disconnect Object when Alarm is finalized (freed)
1676
g_object_weak_ref (G_OBJECT (alarm), alarm_bind_weak_notify, arg);
1678
// Disconnect Alarm when Object is finalized (freed)
1679
g_object_weak_ref (dest, alarm_bind_weak_notify, obj_arg);
1683
alarm_list_item_compare (gconstpointer a, gconstpointer b)
1685
Alarm *a1 = ALARM (a);
1686
Alarm *a2 = ALARM (b);
1688
return a1->id - a2->id;
1692
* Check if a gconf directory is a valid alarm dir.
1694
* Returns >= 0 for valid alarm directory, -1 otherwise.
1697
alarm_gconf_dir_get_id (const gchar *dir)
1702
d = g_path_get_basename (dir);
1704
if (sscanf (d, ALARM_GCONF_DIR_PREFIX "%d", &id) <= 0 || id < 0) {
1715
* Get list of alarms in gconf_dir
1718
alarm_get_list (const gchar *gconf_dir)
1720
GConfClient *client;
1721
GSList *dirs = NULL;
1729
client = gconf_client_get_default ();
1730
dirs = gconf_client_all_dirs (client, gconf_dir, NULL);
1735
for (l = dirs; l; l = l->next) {
1736
tmp = (gchar *)l->data;
1738
id = alarm_gconf_dir_get_id (tmp);
1740
g_debug ("alarm_get_list: found VALID %s #%d", tmp, id);
1742
alarm = alarm_new (gconf_dir, id);
1743
g_debug ("\tref = %d", G_OBJECT (alarm)->ref_count);
1744
ret = g_list_insert_sorted (ret, alarm, alarm_list_item_compare);
1745
g_debug ("\tappend ref = %d", G_OBJECT (alarm)->ref_count);
1751
g_slist_free (dirs);
1757
* Connect a signal callback to all alarms in list.
1760
alarm_signal_connect_list (GList *instances,
1761
const gchar *detailed_signal,
1762
GCallback c_handler,
1767
g_debug ("alarm_signal_connect_list");
1768
for (l = instances; l != NULL; l = l->next) {
1769
a = ALARM (l->data);
1771
g_debug (" - connecting #%d: %s...", a->id, detailed_signal);
1773
gboolean ret = g_signal_connect (a, detailed_signal, c_handler, data);
1774
g_debug (" = %d", ret);
1783
alarm_player_error_cb (MediaPlayer *player, GError *err, gpointer data)
1785
Alarm *alarm = ALARM (data);
1789
uri = media_player_get_uri (player);
1790
msg = g_strdup_printf ("Could not play '%s': %s", uri, err->message);
1794
/* Emit error signal */
1795
alarm_error_trigger (alarm, ALARM_ERROR_PLAY, msg);
1802
alarm_player_state_cb (MediaPlayer *player, MediaPlayerState state, gpointer data)
1804
static MediaPlayerState prev_state = MEDIA_PLAYER_INVALID;
1806
Alarm *alarm = ALARM (data);
1807
AlarmPrivate *priv = ALARM_PRIVATE (alarm);
1809
if (state != prev_state) {
1810
// Emit player_changed signal
1811
g_signal_emit (alarm, alarm_signal[SIGNAL_PLAYER], 0, state, NULL);
1814
if (state == MEDIA_PLAYER_STOPPED) {
1815
g_debug ("[%p] #%d Freeing media player %p", alarm, alarm->id, player);
1817
media_player_free (player);
1819
priv->player = NULL;
1824
alarm_player_timeout (gpointer data)
1826
Alarm *alarm = ALARM (data);
1828
g_debug ("[%p] #%d player_timeout", alarm, alarm->id);
1830
alarm_player_stop (alarm);
1837
* Play sound via gstreamer
1840
alarm_player_start (Alarm *alarm)
1842
AlarmPrivate *priv = ALARM_PRIVATE (alarm);
1844
if (priv->player == NULL) {
1845
priv->player = media_player_new (alarm->sound_file,
1847
alarm_player_state_cb, alarm,
1848
alarm_player_error_cb, alarm);
1850
media_player_set_uri (priv->player, alarm->sound_file);
1853
media_player_start (priv->player);
1855
g_debug ("[%p] #%d player_start...", alarm, alarm->id);
1860
priv->player_timer_id = g_timeout_add_seconds(ALARM_SOUND_TIMEOUT, alarm_player_timeout, alarm);
1867
alarm_player_stop (Alarm *alarm)
1869
AlarmPrivate *priv = ALARM_PRIVATE (alarm);
1871
if (priv->player != NULL) {
1872
media_player_stop (priv->player);
1874
if (priv->player_timer_id > 0) {
1875
g_source_remove (priv->player_timer_id);
1876
priv->player_timer_id = 0;
1885
alarm_command_run (Alarm *alarm)
1890
if (!g_spawn_command_line_async (alarm->command, &err)) {
1892
msg = g_strdup_printf ("Could not launch `%s': %s", alarm->command, err->message);
1896
/* Emit error signal */
1897
alarm_error_trigger (alarm, ALARM_ERROR_COMMAND, msg);
1910
* Set time according to hour, min, sec
1913
alarm_set_time (Alarm *alarm, guint hour, guint minute, guint second)
1915
g_debug ("alarm_set_time (%d:%d:%d)", hour, minute, second);
1917
g_object_set (alarm, "time", second + minute * 60 + hour * 60 * 60, NULL);
1921
* Calculates the distance from wday1 to wday2
1924
alarm_wday_distance (gint wday1, gint wday2)
1936
alarm_time_is_future (struct tm *tm, guint hour, guint minute, guint second)
1938
return (hour > tm->tm_hour ||
1939
(hour == tm->tm_hour && minute > tm->tm_min) ||
1940
(hour == tm->tm_hour && minute == tm->tm_min && second > tm->tm_sec));
1945
* Set time according to hour, min, sec and alarm->repeat
1948
alarm_set_timestamp (Alarm *alarm, guint hour, guint minute, guint second, gboolean include_today)
1955
g_debug ("alarm_set_time_full (%d, %d, %d, %d)", hour, minute, second, include_today);
1958
tm = localtime (&now);
1960
//i = (today == 6) ? 0 : today + 1;
1963
if (alarm->repeat == ALARM_REPEAT_NONE) {
1964
// Check if the alarm is for tomorrow
1965
if (!alarm_time_is_future (tm, hour, minute, second)) {
1968
g_debug("alarm_set_time_full: Alarm is for tomorrow.");
1971
// wday == tm->tm_wday
1972
g_debug("alarm_set_time_full: Alarm is in 1 week.");
1977
// REPEAT SET: Find the closest repeat day
1984
// Try finding a day in this week
1985
for (; i < 7; i++) {
1987
if (alarm->repeat & rep) {
1988
if (i == tm->tm_wday && !alarm_time_is_future (tm, hour, minute, second)) continue;
1991
//g_debug ("\tMATCH");
1997
// If we haven't found a day in the current week, check next week
1999
for (i = 0; i <= tm->tm_wday; i++) {
2001
if (alarm->repeat & rep/* && alarm_time_is_future (tm, hour, minute, second)*/) {
2003
//g_debug ("\tMATCH");
2010
g_debug ("Closest WDAY = %d", wday);
2012
if (wday == tm->tm_wday && (!include_today || !alarm_time_is_future (tm, hour, minute, second)))
2016
// Calculate distance from now to wday
2018
g_debug("alarm_set_time_full: Alarm is in (forced) 1 week.");
2021
g_debug ("d = tm->tm_wday(%d) - wday(%d)", tm->tm_wday, wday);
2022
d = alarm_wday_distance (tm->tm_wday, wday);
2025
g_debug ("alarm_set_time_full: Alarm is in %d days.", d);
2031
tm->tm_min = minute;
2032
tm->tm_sec = second;
2036
strftime (tmp, sizeof (tmp), "%c", tm);
2037
g_debug ("alarm_set_time_full: Alarm will trigger at %s", tmp);
2040
g_debug ("alarm_set_time_full: Setting to %d", new);
2041
g_object_set (alarm, "timestamp", new, NULL);
2045
* Update the alarm timestamp to point to the nearest future
2046
* hour/min/sec according to the time value.
2049
alarm_update_timestamp_full (Alarm *alarm, gboolean include_today)
2051
if (alarm->type == ALARM_TYPE_CLOCK) {
2052
struct tm *tm = alarm_get_time (alarm);
2053
g_debug ("update_timestamp_full: %d:%d:%d", tm->tm_hour, tm->tm_min, tm->tm_sec);
2054
alarm_set_timestamp (alarm, tm->tm_hour, tm->tm_min, tm->tm_sec, include_today);
2056
/* ALARM_TYPE_TIMER */
2057
g_object_set (alarm, "timestamp", time(NULL) + alarm->time, NULL);
2062
* Update the alarm timestamp to point to the nearest future
2063
* hour/min/sec according to the time value.
2065
* Equivalent to alarm_update_timestamp_full (alarm, TRUE)
2068
alarm_update_timestamp (Alarm *alarm)
2070
alarm_update_timestamp_full (alarm, TRUE);
2074
* Get the alarm time.
2077
alarm_get_time (Alarm *alarm)
2079
return gmtime (&(alarm->time));
2083
* Get the remaining alarm time.
2085
static struct tm tm;
2088
alarm_get_remain (Alarm *alarm)
2094
tm.tm_sec = alarm->timestamp - now;
2096
tm.tm_min = tm.tm_sec / 60;
2097
tm.tm_sec -= tm.tm_min * 60;
2099
tm.tm_hour = tm.tm_min / 60;
2100
tm.tm_min -= tm.tm_hour * 60;
2106
* AlarmRepeat utilities {{
2110
alarm_repeat_to_string (AlarmRepeat repeat)
2112
return gconf_enum_to_string (alarm_repeat_enum_map, repeat);
2116
alarm_repeat_from_string (const gchar *str)
2118
AlarmRepeat ret = ALARM_REPEAT_NONE;
2123
gconf_string_to_enum (alarm_repeat_enum_map, str, (gint *)&ret);
2129
alarm_repeat_from_list (GSList *list)
2132
AlarmRepeat repeat = ALARM_REPEAT_NONE;
2134
for (l = list; l; l = l->next) {
2135
repeat |= alarm_repeat_from_string ((gchar *)l->data);
2142
alarm_repeat_to_list (AlarmRepeat repeat)
2144
GSList *list = NULL;
2148
for (r = ALARM_REPEAT_SUN, i = 0; r <= ALARM_REPEAT_SAT; r = 1 << ++i) {
2150
list = g_slist_append (list, (gpointer) alarm_repeat_to_string (r));
2157
alarm_should_repeat (Alarm *alarm)
2159
return alarm->type == ALARM_TYPE_CLOCK && alarm->repeat != ALARM_REPEAT_NONE;
2163
* }} AlarmRepeat utilities