~ubuntu-branches/debian/jessie/alarm-clock-applet/jessie

« back to all changes in this revision

Viewing changes to src/alarm.c

  • Committer: Bazaar Package Importer
  • Author(s): Chow Loong Jin
  • Date: 2010-03-17 09:02:44 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100317090244-ni0ye04mva2hxe10
Tags: 0.3.0-1
* New upstream release
* debian/control:
  + No change bump of Standards-Version to 3.8.4
  + Update build-deps:
    - Drop libglade, libpanel-applet, libgnomevfs2, libgnome{2,ui}
    - Add libxml2-dev and libunique-dev, intltool
* debian/patches/01_update-alarms-eta,patch:
  + Dropped, applied upstream
* debian/(alarm-clock-applet.1, alarm-clock-applet.manpages):
  + Add manpage for alarm-clock-applet, now that the binary is moved to
    /usr/bin.

Show diffs side-by-side

added added

removed removed

Lines of Context:
106
106
        PROP_ALARM_0,
107
107
        PROP_DIR,
108
108
        PROP_ID,
 
109
    PROP_TRIGGERED,
109
110
        PROP_TYPE,
110
111
        PROP_TIME,
111
112
        PROP_TIMESTAMP,
112
113
        PROP_ACTIVE,
113
114
        PROP_MESSAGE,
114
115
        PROP_REPEAT,
115
 
        PROP_SNOOZE,
116
116
        PROP_NOTIFY_TYPE,
117
117
        PROP_SOUND_FILE,
118
118
        PROP_SOUND_LOOP,
119
 
        PROP_COMMAND,
120
 
        PROP_NOTIFY_BUBBLE
 
119
        PROP_COMMAND
121
120
} AlarmProp;
122
121
 
123
122
#define PROP_NAME_DIR                   "gconf-dir"
124
123
#define PROP_NAME_ID                    "id"
 
124
#define PROP_NAME_TRIGGERED     "triggered"
125
125
#define PROP_NAME_TYPE                  "type"
126
126
#define PROP_NAME_TIME                  "time"
127
127
#define PROP_NAME_TIMESTAMP             "timestamp"
128
128
#define PROP_NAME_ACTIVE                "active"
129
129
#define PROP_NAME_MESSAGE               "message"
130
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"
 
131
#define PROP_NAME_NOTIFY_TYPE   "notify-type"
 
132
#define PROP_NAME_SOUND_FILE    "sound-file"
 
133
#define PROP_NAME_SOUND_LOOP    "sound-repeat"
135
134
#define PROP_NAME_COMMAND               "command"
136
 
#define PROP_NAME_NOTIFY_BUBBLE "notify_bubble"
137
135
 
138
136
/* Signal indexes */
139
137
static enum
140
138
{
141
 
  SIGNAL_ALARM,
142
 
  SIGNAL_ERROR,
143
 
  SIGNAL_PLAYER,
144
 
  LAST_SIGNAL
 
139
    SIGNAL_ALARM,
 
140
    SIGNAL_CLEARED,
 
141
    SIGNAL_ERROR,
 
142
    SIGNAL_PLAYER,
 
143
    LAST_SIGNAL
145
144
} AlarmSignal;
146
145
 
147
146
/* Signal identifier map */
148
 
static guint alarm_signal[LAST_SIGNAL] = {0, 0, 0};
 
147
static guint alarm_signal[LAST_SIGNAL] = {0, 0, 0, 0};
149
148
 
150
149
/* Prototypes for signal handlers */
151
150
static void alarm_alarm (Alarm *alarm);
 
151
static void alarm_cleared (Alarm *alarm);
152
152
static void alarm_error (Alarm *alarm, GError *err);
153
153
static void alarm_player_changed (Alarm *alarm, MediaPlayerState state);
154
154
 
155
 
/* For debugging purposes only */
156
 
static void
157
 
dump_list (GSList *list)
158
 
{
159
 
        GSList *l;
160
 
        
161
 
        g_print ("[ ");
162
 
        for (l = list; l; l = l->next) {
163
 
                g_print ("%s", (gchar *)l->data);
164
 
                if (l->next)
165
 
                        g_print (", ");
166
 
        }
167
 
        g_print (" ]");
168
 
}
169
 
 
170
155
 
171
156
/* Initialize the Alarm class */
172
157
static void 
174
159
{
175
160
        GParamSpec *dir_param;
176
161
        GParamSpec *id_param;
 
162
    GParamSpec *triggered_param;
177
163
        GParamSpec *type_param;
178
164
        GParamSpec *time_param;
179
165
        GParamSpec *timestamp_param;
180
166
        GParamSpec *active_param;
181
167
        GParamSpec *message_param;
182
168
        GParamSpec *repeat_param;
183
 
        GParamSpec *snooze_param;
184
169
        GParamSpec *notify_type_param;
185
170
        GParamSpec *sound_file_param;
186
171
        GParamSpec *sound_loop_param;
187
172
        GParamSpec *command_param;
188
 
        GParamSpec *notify_bubble_param;
189
173
        
190
174
        GObjectClass *g_object_class;
191
175
 
208
192
                                                                  UINT_MAX,     /* max */
209
193
                                                                  0,            /* default */
210
194
                                                                  G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
211
 
        
 
195
 
 
196
    triggered_param = g_param_spec_boolean (PROP_NAME_TRIGGERED,
 
197
                                                                        "alarm triggered",
 
198
                                                                        "triggered flag of the alarm",
 
199
                                            FALSE,
 
200
                                                                        G_PARAM_READABLE);
 
201
 
212
202
        type_param = g_param_spec_uint (PROP_NAME_TYPE,
213
203
                                                                        "alarm type",
214
204
                                                                        "type of the alarm",
253
243
                                                                          ALARM_REPEAT_ALL,             /* max */
254
244
                                                                          ALARM_DEFAULT_REPEAT, /* default */
255
245
                                                                          G_PARAM_READWRITE);
256
 
        
257
 
        snooze_param = g_param_spec_uint (PROP_NAME_SNOOZE,
258
 
                                                                          "snooze",
259
 
                                                                          "enable snoozing of the alarm",
260
 
                                                                          0,                                    /* min */
261
 
                                                                          UINT_MAX,                             /* max */
262
 
                                                                          ALARM_DEFAULT_SNOOZE, /* default */
263
 
                                                                          G_PARAM_READWRITE);
264
 
        
 
246
                
265
247
        notify_type_param = g_param_spec_uint (PROP_NAME_NOTIFY_TYPE,
266
248
                                                                                "notification type",
267
249
                                                                                "what kind of notification should be used",
286
268
                                                                                 "command",
287
269
                                                                                 "command to run",
288
270
                                                                                 ALARM_DEFAULT_COMMAND,
289
 
                                                                                 G_PARAM_READWRITE);
290
 
        
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,
295
 
                                                                                                G_PARAM_READWRITE);
296
 
        
 
271
                                                                                 G_PARAM_READWRITE);    
297
272
        
298
273
        /* override base object methods */
299
274
        g_object_class->set_property = alarm_set_property;
304
279
        /* install properties */
305
280
        g_object_class_install_property (g_object_class, PROP_DIR, dir_param);
306
281
        g_object_class_install_property (g_object_class, PROP_ID, id_param);
 
282
    g_object_class_install_property (g_object_class, PROP_TRIGGERED, triggered_param);
307
283
        g_object_class_install_property (g_object_class, PROP_TYPE, type_param);
308
284
        g_object_class_install_property (g_object_class, PROP_TIME, time_param);
309
285
        g_object_class_install_property (g_object_class, PROP_TIMESTAMP, timestamp_param);
310
286
        g_object_class_install_property (g_object_class, PROP_ACTIVE, active_param);
311
287
        g_object_class_install_property (g_object_class, PROP_MESSAGE, message_param);
312
288
        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
289
        g_object_class_install_property (g_object_class, PROP_NOTIFY_TYPE, notify_type_param);
315
290
        g_object_class_install_property (g_object_class, PROP_SOUND_FILE, sound_file_param);
316
291
        g_object_class_install_property (g_object_class, PROP_SOUND_LOOP, sound_loop_param);
317
292
        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);
319
293
        
320
294
        g_type_class_add_private (class, sizeof (AlarmPrivate));
321
295
        
322
296
        /* set signal handlers */
323
297
        class->alarm = alarm_alarm;
 
298
    class->cleared = alarm_cleared;
324
299
        class->error = alarm_error;
325
300
        class->player_changed = alarm_player_changed;
326
301
 
327
302
        /* install signals and default handlers */
328
303
        alarm_signal[SIGNAL_ALARM] = g_signal_new ("alarm",             /* name */
329
304
                                                                                           TYPE_ALARM,  /* class type identifier */
330
 
                                                                                           G_SIGNAL_RUN_LAST, /* options */
 
305
                                                                                           G_SIGNAL_RUN_FIRST, /* options */
331
306
                                                                                           G_STRUCT_OFFSET (AlarmClass, alarm), /* handler offset */
332
307
                                                                                           NULL, /* accumulator function */
333
308
                                                                                           NULL, /* accumulator data */
334
309
                                                                                           g_cclosure_marshal_VOID__VOID, /* marshaller */
335
310
                                                                                           G_TYPE_NONE, /* type of return value */
336
311
                                                                                           0);
337
 
        
 
312
 
 
313
    alarm_signal[SIGNAL_CLEARED] = g_signal_new ("cleared",
 
314
                                                 TYPE_ALARM,
 
315
                                                                                             G_SIGNAL_RUN_FIRST,
 
316
                                                                                             G_STRUCT_OFFSET (AlarmClass, cleared),
 
317
                                                                                             NULL,
 
318
                                                                                             NULL,
 
319
                                                                                             g_cclosure_marshal_VOID__VOID,
 
320
                                                                                             G_TYPE_NONE,
 
321
                                                                                             0);
 
322
    
338
323
        alarm_signal[SIGNAL_ERROR] = g_signal_new ("error",
339
324
                                                                                           TYPE_ALARM,
340
325
                                                                                           G_SIGNAL_RUN_LAST,
495
480
        }
496
481
        
497
482
        /*
498
 
         * SNOOZE
499
 
         */
500
 
        key = alarm_gconf_get_full_key (alarm, PROP_NAME_SNOOZE);
501
 
        val = gconf_client_get (client, key, NULL);
502
 
        g_free (key);
503
 
        
504
 
        if (val) {
505
 
                alarm->snooze = gconf_value_get_int (val);
506
 
                gconf_value_free (val);
507
 
        } else {
508
 
                // Not found in GConf, fall back to defaults
509
 
                g_object_set (alarm, PROP_NAME_SNOOZE, ALARM_DEFAULT_SNOOZE, NULL);
510
 
        }
511
 
        
512
 
        /*
513
483
         * NOTIFY TYPE
514
484
         */
515
485
        key = alarm_gconf_get_full_key (alarm, PROP_NAME_NOTIFY_TYPE);
571
541
                // Not found in GConf, fall back to defaults
572
542
                g_object_set (alarm, PROP_NAME_COMMAND, ALARM_DEFAULT_COMMAND, NULL);
573
543
        }
574
 
        
575
 
        
576
 
        /*
577
 
         * NOTIFY_BUBBLE
578
 
         */
579
 
        key = alarm_gconf_get_full_key (alarm, PROP_NAME_NOTIFY_BUBBLE);
580
 
        val = gconf_client_get (client, key, NULL);
581
 
        g_free (key);
582
 
 
583
 
        if (val) {
584
 
                alarm->notify_bubble = gconf_value_get_bool (val);
585
 
                gconf_value_free (val);
586
 
        } else {
587
 
                // Not found in GConf, fall back to defaults
588
 
                g_object_set (alarm, PROP_NAME_NOTIFY_BUBBLE, ALARM_DEFAULT_NOTIFY_BUBBLE, NULL);
589
 
        }
590
544
}
591
545
 
592
546
static void
627
581
        GError          *err = NULL;
628
582
        
629
583
        const gchar     *str;
630
 
        guint            d, old;
631
 
        AlarmType        type, new_type;
632
 
        gboolean         bool;
 
584
        guint            d;
 
585
        gboolean         b;
633
586
        GSList          *list;
634
587
        
635
588
        gchar *key, *tmp;
636
589
 
637
590
        alarm = ALARM (object);
638
591
        client = priv->gconf_client;
639
 
        
640
 
        g_debug ("set_property %s", pspec->name);
 
592
 
 
593
    // DEBUGGING INFO
 
594
    GValue strval = {0};
 
595
    g_value_init (&strval, G_TYPE_STRING);
 
596
    g_value_transform (value, &strval);
 
597
        g_debug ("Alarm(%p) #%d: set %s=%s", alarm, alarm->id, pspec->name,
 
598
        g_value_get_string(&strval));
641
599
        
642
600
        switch (prop_id) {
643
601
        case PROP_DIR:
682
640
                        alarm_gconf_connect (alarm);
683
641
                }
684
642
                break;
 
643
    case PROP_TRIGGERED:
 
644
        // TODO: Should we map this to a GConf value?
 
645
        //       The only case where this might be useful is where the program
 
646
        //       is restarted while having a triggered alarm so that we could
 
647
        //       re-trigger it when the program starts again...
 
648
        b = g_value_get_boolean (value);
 
649
        
 
650
        if (b != alarm->triggered) {
 
651
            alarm->triggered = b;
 
652
        }
 
653
        
685
654
        case PROP_TYPE:
686
655
                alarm->type = g_value_get_uint (value);
687
656
                
740
709
                g_free (key);
741
710
                break;
742
711
        case PROP_ACTIVE:
743
 
                bool = alarm->active;
 
712
                b = alarm->active;
744
713
                alarm->active = g_value_get_boolean (value);
745
714
                
746
 
                //g_debug ("[%p] #%d ACTIVE: old=%d new=%d", alarm, alarm->id, bool, alarm->active);
 
715
                //g_debug ("[%p] #%d ACTIVE: old=%d new=%d", alarm, alarm->id, b, alarm->active);
747
716
                if (alarm->active && !alarm_timer_is_started(alarm)) {
748
717
                        // Start timer
749
718
                        alarm_timer_start (alarm);
811
780
                g_free (key);
812
781
                
813
782
                break;
814
 
        case PROP_SNOOZE:
815
 
                alarm->snooze = g_value_get_uint (value);
816
 
                
817
 
                key = alarm_gconf_get_full_key (alarm, PROP_NAME_SNOOZE);
818
 
                
819
 
                if (!gconf_client_set_int (client, key, alarm->snooze, &err)) {
820
 
                        
821
 
                        g_critical ("Could not set %s (gconf): %s", 
822
 
                                                key, err->message);
823
 
                        
824
 
                        g_error_free (err);
825
 
                }
826
 
                
827
 
                g_free (key);
828
 
                break;
829
783
        case PROP_NOTIFY_TYPE:
830
784
                alarm->notify_type = g_value_get_uint (value);
831
785
                
895
849
                g_free (key);
896
850
                
897
851
                break;
898
 
        case PROP_NOTIFY_BUBBLE:
899
 
                bool = alarm->notify_bubble;
900
 
                alarm->notify_bubble = g_value_get_boolean (value);
901
 
                
902
 
                key = alarm_gconf_get_full_key (alarm, PROP_NAME_NOTIFY_BUBBLE);
903
 
                
904
 
                if (!gconf_client_set_bool (client, key, alarm->notify_bubble, &err)) {
905
 
                        
906
 
                        g_critical ("Could not set %s (gconf): %s", 
907
 
                                                key, err->message);
908
 
                        
909
 
                        g_error_free (err);
910
 
                }
911
 
                
912
 
                g_free (key);
913
 
                break;
914
852
        default:
915
853
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
916
854
                break;
933
871
        case PROP_ID:
934
872
                g_value_set_uint (value, alarm->id);
935
873
                break;
 
874
    case PROP_TRIGGERED:
 
875
        g_value_set_boolean (value, alarm->triggered);
 
876
        break;
936
877
        case PROP_TYPE:
937
878
                g_value_set_uint (value, alarm->type);
938
879
                break;
951
892
        case PROP_REPEAT:
952
893
                g_value_set_uint (value, alarm->repeat);
953
894
                break;
954
 
        case PROP_SNOOZE:
955
 
                g_value_set_uint (value, alarm->snooze);
956
 
                break;
957
895
        case PROP_NOTIFY_TYPE:
958
896
                g_value_set_uint (value, alarm->notify_type);
959
897
                break;
966
904
        case PROP_COMMAND:
967
905
                g_value_set_string (value, alarm->command);
968
906
                break;
969
 
        case PROP_NOTIFY_BUBBLE:
970
 
                g_value_set_boolean (value, alarm->notify_bubble);
971
 
                break;
972
907
        default:
973
908
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
974
909
                break;
987
922
static void
988
923
alarm_error (Alarm *alarm, GError *err)
989
924
{
990
 
        g_debug ("[%p] #%d: alarm_error: #%d: %s", alarm, alarm->id, err->code, err->message);
 
925
        g_debug ("Alarm(%p) #%d: alarm_error: #%d: %s", alarm, alarm->id, err->code, err->message);
991
926
}
992
927
 
993
928
void
1005
940
static void
1006
941
alarm_player_changed (Alarm *alarm, MediaPlayerState state)
1007
942
{
1008
 
        g_debug ("alarm_player_changed (%p, %d)", alarm, state);
 
943
        g_debug ("Alarm(%p) #%d: player_changed to %d", alarm, alarm->id, state);
1009
944
}
1010
945
 
1011
946
 
1016
951
static void 
1017
952
alarm_alarm (Alarm *alarm)
1018
953
{
1019
 
        g_debug ("[%p] #%d: alarm_alarm", alarm, alarm->id);
1020
 
}
 
954
        g_debug ("Alarm(%p) #%d: alarm() DING!", alarm, alarm->id);
1021
955
 
1022
 
void
1023
 
alarm_trigger (Alarm *alarm)
1024
 
{
1025
 
        g_signal_emit (alarm, alarm_signal[SIGNAL_ALARM], 0, NULL);
 
956
    // Clear first, if needed
 
957
    alarm_clear (alarm);
 
958
    
 
959
    // Update triggered flag
 
960
    alarm->triggered = TRUE;
1026
961
        
1027
 
        /*
1028
 
         * Do we want to repeat this alarm?
1029
 
         */
 
962
        // Do we want to repeat this alarm?
1030
963
        if (alarm_should_repeat (alarm)) {
1031
 
                g_debug ("alarm_trigger REPEATING");
 
964
                g_debug ("Alarm(%p) #%d: alarm() Repeating...", alarm, alarm->id);
1032
965
                alarm_update_timestamp_full (alarm, FALSE);
1033
966
        } else {
1034
967
                alarm_disable (alarm);
1037
970
        switch (alarm->notify_type) {
1038
971
        case ALARM_NOTIFY_SOUND:
1039
972
                // Start sound playback
1040
 
                g_debug("[%p] #%d Start player", alarm, alarm->id);
 
973
                g_debug("Alarm(%p) #%d: alarm() Start player", alarm, alarm->id);
1041
974
                alarm_player_start (alarm);
1042
975
                break;
1043
976
        case ALARM_NOTIFY_COMMAND:
1044
977
                // Start app
1045
 
                g_debug("[%p] #%d Start command", alarm, alarm->id);
 
978
                g_debug("Alarm(%p) #%d: alarm() Start command", alarm, alarm->id);
1046
979
                alarm_command_run (alarm);
1047
980
                break;
1048
981
        default:
1049
 
                g_debug ("NOTIFICATION TYPE %d Not yet implemented.", alarm->notify_type);
 
982
                g_warning ("Alarm(%p) #%d: UNKNOWN NOTIFICATION TYPE %d", 
 
983
            alarm, alarm->id, alarm->notify_type);
1050
984
        }
1051
985
}
1052
986
 
 
987
void
 
988
alarm_trigger (Alarm *alarm)
 
989
{
 
990
        g_signal_emit (alarm, alarm_signal[SIGNAL_ALARM], 0, NULL);
 
991
}
 
992
 
1053
993
/*
1054
994
 * Convenience functions for enabling/disabling the alarm.
1055
995
 * 
1093
1033
        
1094
1034
        // Remove configuration
1095
1035
        key = alarm_gconf_get_dir (alarm);
1096
 
        g_debug ("alarm_delete: recursive unset on %s", key);
 
1036
        g_debug ("Alarm(%p) #%d: alarm_delete() recursive unset on %s", alarm, alarm->id, key);
1097
1037
        gconf_client_recursive_unset (client, key, GCONF_UNSET_INCLUDING_SCHEMA_NAMES, NULL);
1098
1038
        gconf_client_suggest_sync (client, NULL);
1099
1039
        g_free (key);
1100
1040
}
1101
1041
 
1102
1042
/*
1103
 
 * Snooze the alarm.
 
1043
 * Snooze the alarm for a number of seconds.
1104
1044
 */
1105
1045
void
1106
 
alarm_snooze (Alarm *alarm)
 
1046
alarm_snooze (Alarm *alarm, guint seconds)
1107
1047
{
1108
 
        // SNOOZE
1109
 
        if (alarm->snooze == 0) {
1110
 
                alarm_clear (alarm);
1111
 
                return;
1112
 
        }
1113
 
        
1114
 
        if (!alarm_is_playing (alarm)) return;
1115
 
        
1116
 
        g_debug ("alarm_snooze SNOOZING FOR %d minutes", alarm->snooze);
1117
 
        
1118
 
        time_t now = time (NULL);
 
1048
    g_assert (alarm->triggered);
 
1049
    
 
1050
        g_debug ("Alarm(%p) #%d: snooze() for %d minutes", alarm, alarm->id, seconds / 60);
 
1051
 
 
1052
    // Silence!
 
1053
    alarm_clear (alarm);    
 
1054
 
 
1055
    // Remind later
 
1056
    time_t now = time (NULL);
1119
1057
        
1120
1058
        g_object_set (alarm, 
1121
 
                                  "timestamp", now + alarm->snooze * 60,
1122
 
                                  "active", TRUE,
 
1059
                                  "timestamp", now + seconds,
 
1060
                                  "active", TRUE,        
1123
1061
                                  NULL);
1124
 
        
1125
 
        alarm_clear (alarm);
 
1062
 
 
1063
//    alarm_timer_start (alarm);
 
1064
}
 
1065
 
 
1066
/**
 
1067
 * Alarm cleared signal
 
1068
 */
 
1069
static void
 
1070
alarm_cleared (Alarm *alarm)
 
1071
{
 
1072
    g_debug ("Alarm(%p) #%d: cleared()", alarm, alarm->id);
 
1073
 
 
1074
    // Update triggered flag
 
1075
    alarm->triggered = FALSE;
 
1076
 
 
1077
    // Stop player
 
1078
        alarm_player_stop (alarm);
1126
1079
}
1127
1080
 
1128
1081
/*
1129
 
 * Clear the alarm. This will stop any running players.
 
1082
 * Clear the alarm. Resets the triggered flag and emits the "cleared" signal.
 
1083
 * This will also stop any running players.
1130
1084
 */
1131
1085
void
1132
1086
alarm_clear (Alarm *alarm)
1133
1087
{
1134
 
        alarm_player_stop (alarm);
 
1088
    if (alarm->triggered) {
 
1089
        g_signal_emit (alarm, alarm_signal[SIGNAL_CLEARED], 0, NULL);
 
1090
    }
1135
1091
}
1136
1092
 
1137
1093
/*
1160
1116
                // Remove callback only if we don't intend to repeat the alarm
1161
1117
                return alarm_should_repeat (alarm);
1162
1118
        } else if (alarm->timestamp - now <= 10) {
1163
 
                g_debug ("[%p] #%d %2d...", alarm, alarm->id, (int)(alarm->timestamp - now));
 
1119
                g_debug ("Alarm(%p) #%d: -%2d...", alarm, alarm->id, (int)(alarm->timestamp - now));
1164
1120
        }
1165
1121
        
1166
1122
        // Keep callback
1172
1128
{
1173
1129
        AlarmPrivate *priv = ALARM_PRIVATE(alarm);
1174
1130
        
1175
 
        g_debug ("[%p] #%d timer_start", alarm, alarm->id);
 
1131
        g_debug ("Alarm(%p) #%d: timer_start()", alarm, alarm->id);
1176
1132
        
1177
1133
        // Remove old timer, if any
1178
1134
        alarm_timer_remove (alarm);
1185
1141
alarm_timer_is_started (Alarm *alarm)
1186
1142
{
1187
1143
        AlarmPrivate *priv = ALARM_PRIVATE(alarm);
1188
 
                
 
1144
    
1189
1145
        return priv->timer_id > 0;
1190
1146
}
1191
1147
 
1195
1151
        AlarmPrivate *priv = ALARM_PRIVATE(alarm);
1196
1152
        
1197
1153
        if (alarm_timer_is_started(alarm)) {
1198
 
                g_debug ("#%d timer_remove (%p)", alarm->id, alarm);
 
1154
                g_debug ("Alarm(%p) #%d: timer_remove", alarm, alarm->id);
1199
1155
                
1200
1156
                g_source_remove (priv->timer_id);
1201
1157
                
1342
1298
                return;
1343
1299
        }
1344
1300
        
1345
 
        g_debug ("alarm_gconf changed #%d %p: %s", alarm->id, alarm, name);
 
1301
        g_debug ("Alarm(%p) #%d: gconf_dir_changed(): %s", alarm, alarm->id, name);
1346
1302
        
1347
1303
        switch (param->param_id) {
1348
1304
        case PROP_TYPE:
1364
1320
        case PROP_ACTIVE:
1365
1321
                b = gconf_value_get_bool (entry->value);
1366
1322
                if (b != alarm->active) {
1367
 
                        g_debug ("[%p] #%d GCONF-ACTIVE changed from %d to %d", alarm, alarm->id, alarm->active, b);
1368
1323
                        g_object_set (alarm, name, b, NULL);
1369
1324
                }
1370
1325
                break;
1382
1337
                
1383
1338
                g_slist_free (list);
1384
1339
                break;
1385
 
        case PROP_SNOOZE:
1386
 
                i = gconf_value_get_int (entry->value);
1387
 
                if (i != alarm->snooze)
1388
 
                        g_object_set (alarm, name, i, NULL);
1389
 
                break;
1390
1340
        case PROP_NOTIFY_TYPE:
1391
1341
                str = gconf_value_get_string (entry->value);
1392
1342
                i = alarm_notify_type_from_string (str);
1408
1358
                if (strcmp (str, alarm->command) != 0)
1409
1359
                        g_object_set (alarm, name, str, NULL);
1410
1360
                break;
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);
1415
 
                break;
1416
1361
        default:
1417
 
                g_warning ("Valid property ID %d not handled!", param->param_id);
 
1362
                g_warning ("Alarm(%p) #%d: gconf_dir_changed(): Property ID %d not handled!",
 
1363
            alarm, alarm->id, param->param_id);
1418
1364
                break;
1419
1365
        }
1420
1366
        
1425
1371
alarm_dispose (GObject *object)
1426
1372
{
1427
1373
        Alarm *alarm = ALARM (object);
1428
 
        AlarmPrivate *priv = ALARM_PRIVATE (object);
 
1374
//      AlarmPrivate *priv = ALARM_PRIVATE (object);
1429
1375
        GObjectClass *parent = (GObjectClass *)alarm_parent_class;
1430
1376
        
1431
 
        g_debug ("alarm_dispose (%p)", alarm);
 
1377
        g_debug ("Alarm(%p) #%d: dispose()", alarm, alarm->id);
1432
1378
        
1433
1379
        if (parent->dispose)
1434
1380
                parent->dispose (object);
1541
1487
gchar *
1542
1488
alarm_gconf_get_full_key (Alarm *alarm, const gchar *key)
1543
1489
{
 
1490
    gchar *gconf_key;
1544
1491
        gchar *full_key;
1545
1492
        
1546
1493
        g_return_val_if_fail (IS_ALARM (alarm), NULL);
1547
1494
 
1548
1495
        if (!key)
1549
1496
                return NULL;
1550
 
        
1551
 
        full_key = g_strdup_printf ("%s/" ALARM_GCONF_DIR_PREFIX "%d/%s", alarm->gconf_dir, alarm->id, key);
1552
 
 
 
1497
 
 
1498
    // Replace dashes with underscores
 
1499
    gconf_key = g_strdup (key);
 
1500
    g_strcanon (gconf_key, "abcdefghijklmnopqrstuvwxyz", '_');
 
1501
    
 
1502
        full_key = g_strdup_printf ("%s/" ALARM_GCONF_DIR_PREFIX "%d/%s", 
 
1503
        alarm->gconf_dir, alarm->id, gconf_key);
 
1504
 
 
1505
    g_free (gconf_key);
 
1506
    
1553
1507
        return full_key;
1554
1508
}
1555
1509
 
1556
 
typedef struct {
1557
 
        GObject *object;
1558
 
        const gchar *name;
1559
 
        gulong handler_id;
1560
 
} AlarmBindArg;
1561
 
 
1562
 
static AlarmBindArg *
1563
 
alarm_bind_arg_new (GObject *object, const gchar *name, gulong handler_id)
1564
 
{
1565
 
        AlarmBindArg *arg;
1566
 
        
1567
 
        arg = g_new (AlarmBindArg, 1);
1568
 
        arg->object = object;
1569
 
        arg->name = name;
1570
 
        arg->handler_id = handler_id;
1571
 
        
1572
 
        return arg;
1573
 
}
1574
 
 
1575
 
static void
1576
 
alarm_bind_arg_free (AlarmBindArg *arg)
1577
 
{
1578
 
        if (!arg)
1579
 
                return;
1580
 
        
1581
 
        g_free ((gpointer)arg);
1582
 
}
1583
 
 
1584
 
static void
1585
 
alarm_bind_update (GObject *object,
1586
 
                                   GParamSpec *pspec,
1587
 
                                   gpointer data)
1588
 
{
1589
 
        //Alarm *alarm;
1590
 
        AlarmBindArg *arg = (AlarmBindArg *)data;
1591
 
        gpointer d;
1592
 
        
1593
 
        /*
1594
 
         * Determine which argument is the alarm
1595
 
         */
1596
 
        /*if (IS_ALARM (object)) {
1597
 
                 alarm = ALARM (object);
1598
 
        } else {
1599
 
                alarm = ALARM (arg->object);
1600
 
        }
1601
 
        
1602
 
        g_debug ("alarm_bind_update #%d(%p) [%s] -> %p [%s]", alarm->id, alarm, pspec->name, arg->object, arg->name);
1603
 
        */
1604
 
        g_object_get (object, pspec->name, &d, NULL);
1605
 
        
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);
1610
 
        
1611
 
        g_object_set (arg->object, arg->name, d, NULL);
1612
 
        
1613
 
        g_signal_handlers_unblock_matched(arg->object, 
1614
 
                                                                          G_SIGNAL_MATCH_FUNC,
1615
 
                                                                          0, 0, NULL, alarm_bind_update, NULL);
1616
 
}
1617
 
 
1618
 
/*
1619
 
 * We would like to disconnect any signal handlers from the alarm
1620
 
 * when the destination object is finalized. And vice versa.
1621
 
 */
1622
 
static void
1623
 
alarm_bind_weak_notify (gpointer data, GObject *where_the_object_was)
1624
 
{
1625
 
        AlarmBindArg *arg = (AlarmBindArg *)data;
1626
 
        
1627
 
        g_assert (arg);
1628
 
        g_assert (arg->object);
1629
 
        g_assert (arg->handler_id);
1630
 
        
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);
1634
 
                }
1635
 
        }
1636
 
        
1637
 
        alarm_bind_arg_free (arg);
1638
 
}
1639
 
 
1640
 
/*
1641
 
 * Binds both ways.
1642
 
 */
1643
 
void
1644
 
alarm_bind (Alarm *alarm, 
1645
 
                        const gchar *prop, 
1646
 
                        GObject *dest, 
1647
 
                        const gchar *dest_prop)
1648
 
{
1649
 
        AlarmBindArg *arg, *obj_arg;
1650
 
        GParamSpec *param;
1651
 
        gchar *tmp;
1652
 
        gulong handler, obj_handler;
1653
 
        
1654
 
        param = g_object_class_find_property (G_OBJECT_GET_CLASS(alarm), prop);
1655
 
        g_assert (param);
1656
 
        param = g_object_class_find_property (G_OBJECT_GET_CLASS(dest), dest_prop);
1657
 
        g_assert (param);
1658
 
        
1659
 
//      g_debug ("Bind from %p [%s] -> %p [%s]", alarm, prop, dest, dest_prop);
1660
 
        
1661
 
        // Alarm -> Object
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);
1665
 
        g_free(tmp);
1666
 
        
1667
 
        // Object -> Alarm
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);
1671
 
        g_free(tmp);
1672
 
        
1673
 
        arg->handler_id = obj_handler;
1674
 
        
1675
 
        // Disconnect Object when Alarm is finalized (freed)
1676
 
        g_object_weak_ref (G_OBJECT (alarm), alarm_bind_weak_notify, arg);
1677
 
        
1678
 
        // Disconnect Alarm when Object is finalized (freed)
1679
 
        g_object_weak_ref (dest, alarm_bind_weak_notify, obj_arg);
1680
 
}
1681
 
 
 
1510
/**
 
1511
 * Compare two alarms based on ID
 
1512
 */
1682
1513
static gint
1683
1514
alarm_list_item_compare (gconstpointer a, gconstpointer b)
1684
1515
{
1720
1551
        GConfClient *client;
1721
1552
        GSList *dirs = NULL;
1722
1553
        GSList *l = NULL;
1723
 
        gchar *tmp, *dir;
 
1554
        gchar *tmp;
1724
1555
        
1725
1556
        GList *ret = NULL;
1726
1557
        Alarm *alarm;
1737
1568
                
1738
1569
                id = alarm_gconf_dir_get_id (tmp);
1739
1570
                if (id >= 0) {
1740
 
                        g_debug ("alarm_get_list: found VALID %s #%d", tmp, id);
 
1571
                        g_debug ("Alarm: get_list() found '%s' #%d", tmp, id);
1741
1572
                        
1742
1573
                        alarm = alarm_new (gconf_dir, id);
1743
 
                        g_debug ("\tref = %d", G_OBJECT (alarm)->ref_count);
 
1574
//                      g_debug ("\tref = %d", G_OBJECT (alarm)->ref_count);
1744
1575
                        ret = g_list_insert_sorted (ret, alarm, alarm_list_item_compare);
1745
 
                        g_debug ("\tappend ref = %d", G_OBJECT (alarm)->ref_count);
 
1576
//                      g_debug ("\tappend ref = %d", G_OBJECT (alarm)->ref_count);
1746
1577
                }
1747
1578
                
1748
1579
                g_free (tmp);
1764
1595
{
1765
1596
        GList *l;
1766
1597
        Alarm *a;
1767
 
        g_debug ("alarm_signal_connect_list");
 
1598
        g_debug ("Alarm: signal_connect_list()");
1768
1599
        for (l = instances; l != NULL; l = l->next) {
1769
1600
                a = ALARM (l->data);
1770
1601
                
1771
 
                g_debug (" - connecting #%d: %s...", a->id, detailed_signal);
 
1602
                g_debug ("\tconnecting Alarm(%p) #%d: %s...", a, a->id, detailed_signal);
1772
1603
                
1773
 
                gboolean ret = g_signal_connect (a, detailed_signal, c_handler, data);
1774
 
                g_debug (" = %d", ret);
 
1604
                g_signal_connect (a, detailed_signal, c_handler, data);
1775
1605
        }
1776
1606
}
1777
1607
 
1789
1619
        uri = media_player_get_uri (player);
1790
1620
        msg = g_strdup_printf ("Could not play '%s': %s", uri, err->message);
1791
1621
        
1792
 
        g_critical (msg);
 
1622
        g_critical ("%s", msg);
1793
1623
        
1794
1624
        /* Emit error signal */
1795
1625
        alarm_error_trigger (alarm, ALARM_ERROR_PLAY, msg);
1812
1642
        }
1813
1643
        
1814
1644
        if (state == MEDIA_PLAYER_STOPPED) {
1815
 
                g_debug ("[%p] #%d Freeing media player %p", alarm, alarm->id, player);
 
1645
                g_debug ("Alarm(%p) #%d: Freeing media player %p", alarm, alarm->id, player);
1816
1646
                
1817
1647
                media_player_free (player);
1818
1648
                
1825
1655
{
1826
1656
        Alarm *alarm = ALARM (data);
1827
1657
        
1828
 
        g_debug ("[%p] #%d player_timeout", alarm, alarm->id);
 
1658
        g_debug ("Alarm(%p) #%d: player_timeout", alarm, alarm->id);
1829
1659
        
1830
1660
        alarm_player_stop (alarm);
1831
1661
        
1852
1682
        
1853
1683
        media_player_start (priv->player);
1854
1684
        
1855
 
        g_debug ("[%p] #%d player_start...", alarm, alarm->id);
 
1685
        g_debug ("Alarm(%p) #%d: player_start...", alarm, alarm->id);
1856
1686
        
1857
1687
        /*
1858
1688
         * Add stop timeout
1891
1721
                
1892
1722
                msg = g_strdup_printf ("Could not launch `%s': %s", alarm->command, err->message);
1893
1723
                
1894
 
                g_critical (msg);
 
1724
                g_critical ("%s", msg);
1895
1725
                
1896
1726
                /* Emit error signal */
1897
1727
                alarm_error_trigger (alarm, ALARM_ERROR_COMMAND, msg);
1912
1742
void
1913
1743
alarm_set_time (Alarm *alarm, guint hour, guint minute, guint second)
1914
1744
{
1915
 
        g_debug ("alarm_set_time (%d:%d:%d)", hour, minute, second);
 
1745
        g_debug ("Alarm(%p) #%d: set_time (%d:%d:%d)", alarm, alarm->id, 
 
1746
        hour, minute, second);
1916
1747
        
1917
1748
        g_object_set (alarm, "time", second + minute * 60 + hour * 60 * 60, NULL);
1918
1749
}
1952
1783
        AlarmRepeat rep;
1953
1784
        struct tm *tm;
1954
1785
        
1955
 
        g_debug ("alarm_set_time_full (%d, %d, %d, %d)", hour, minute, second, include_today);
 
1786
        g_debug ("Alarm(%p) #%d: set_timestamp (%d, %d, %d, %d)", alarm, alarm->id,
 
1787
        hour, minute, second, include_today);
1956
1788
        
1957
1789
        time (&now);
1958
1790
        tm = localtime (&now);
1965
1797
                if (!alarm_time_is_future (tm, hour, minute, second)) {
1966
1798
                        
1967
1799
                        //if (wday < 0) {
1968
 
                                g_debug("alarm_set_time_full: Alarm is for tomorrow.");
 
1800
                                g_debug("\tAlarm is for tomorrow.");
1969
1801
                                tm->tm_mday++;
1970
1802
                        /*} else {
1971
1803
                                // wday == tm->tm_wday
2015
1847
                
2016
1848
                // Calculate distance from now to wday
2017
1849
                if (wday == 7) {
2018
 
                        g_debug("alarm_set_time_full: Alarm is in (forced) 1 week.");
 
1850
                        g_debug("\tAlarm is in (forced) 1 week.");
2019
1851
                        d = 7;
2020
1852
                } else {
2021
 
                        g_debug ("d = tm->tm_wday(%d) - wday(%d)", tm->tm_wday, wday);
 
1853
//                      g_debug ("\td = tm->tm_wday(%d) - wday(%d)", tm->tm_wday, wday);
2022
1854
                        d = alarm_wday_distance (tm->tm_wday, wday);
2023
1855
                }
2024
1856
                
2025
 
                g_debug ("alarm_set_time_full: Alarm is in %d days.", d);
 
1857
                g_debug ("\tAlarm is in %d days.", d);
2026
1858
                
2027
1859
                tm->tm_mday += d;
2028
1860
        }
2034
1866
        // DEBUG:
2035
1867
        char tmp[512];
2036
1868
        strftime (tmp, sizeof (tmp), "%c", tm);
2037
 
        g_debug ("alarm_set_time_full: Alarm will trigger at %s", tmp);
 
1869
        g_debug ("\tAlarm will trigger at %s", tmp);
2038
1870
        
2039
1871
        new = mktime (tm);
2040
 
        g_debug ("alarm_set_time_full: Setting to %d", new);
 
1872
        g_debug ("\tSetting to %d", (gint) new);
2041
1873
        g_object_set (alarm, "timestamp", new, NULL);
2042
1874
}
2043
1875
 
2050
1882
{
2051
1883
        if (alarm->type == ALARM_TYPE_CLOCK) {
2052
1884
                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);
 
1885
                g_debug ("Alarm(%p) #%d: update_timestamp_full: %d:%d:%d", alarm, alarm->id,
 
1886
            tm->tm_hour, tm->tm_min, tm->tm_sec);
2054
1887
                alarm_set_timestamp (alarm, tm->tm_hour, tm->tm_min, tm->tm_sec, include_today);
2055
1888
        } else {
2056
1889
                /* ALARM_TYPE_TIMER */
2079
1912
        return gmtime (&(alarm->time));
2080
1913
}
2081
1914
 
2082
 
/*
 
1915
static struct tm tm;
 
1916
 
 
1917
/**
2083
1918
 * Get the remaining alarm time.
 
1919
 *
 
1920
 * The return value is a direct pointer to an internal struct and must NOT
 
1921
 * be freed. The return value also changes for every call to alarm_get_remain,
 
1922
 * so copy it if needed.
2084
1923
 */
2085
 
static struct tm tm;
2086
 
 
2087
1924
struct tm *
2088
1925
alarm_get_remain (Alarm *alarm)
2089
1926
{
2102
1939
        return &tm;
2103
1940
}
2104
1941
 
 
1942
/**
 
1943
 * Get the remaining alarm time in seconds
 
1944
 */
 
1945
time_t
 
1946
alarm_get_remain_seconds (Alarm *alarm)
 
1947
{
 
1948
    time_t now = time (NULL);
 
1949
 
 
1950
    return alarm->timestamp - now;
 
1951
}
 
1952
 
 
1953
 
2105
1954
/*
2106
1955
 * AlarmRepeat utilities {{
2107
1956
 */
2160
2009
}
2161
2010
 
2162
2011
/*
 
2012
 * Create a pretty string representation of AlarmRepeat
 
2013
 *
 
2014
 * The return value must be freed afterwards
 
2015
 */
 
2016
gchar *
 
2017
alarm_repeat_to_pretty (AlarmRepeat repeat)
 
2018
{
 
2019
    gchar *str;
 
2020
 
 
2021
    GString *s;
 
2022
    struct tm tm;
 
2023
    gchar tmp[20];
 
2024
    AlarmRepeat r;
 
2025
    gint i;
 
2026
 
 
2027
    switch (repeat) {
 
2028
        case ALARM_REPEAT_NONE:
 
2029
            str = g_strdup (_("Once"));
 
2030
            break;
 
2031
        case ALARM_REPEAT_WEEKDAYS:
 
2032
            str = g_strdup (_("Weekdays"));
 
2033
            break;
 
2034
        case ALARM_REPEAT_WEEKENDS:
 
2035
            str = g_strdup (_("Weekends"));
 
2036
            break;
 
2037
        case ALARM_REPEAT_ALL:
 
2038
            str = g_strdup (_("Every day"));
 
2039
            break;
 
2040
        default:
 
2041
            // Custom repeat, create a list of weekdays
 
2042
            s = g_string_new ("");
 
2043
        
 
2044
                for (r = ALARM_REPEAT_SUN, i = 0; r <= ALARM_REPEAT_SAT; r = 1 << ++i) {
 
2045
                        if (repeat & r) {
 
2046
                    tm.tm_wday = i;
 
2047
                    strftime (tmp, sizeof(tmp), "%a", &tm);
 
2048
                    g_string_append_printf (s, "%s, ", tmp);
 
2049
                }
 
2050
                }
 
2051
 
 
2052
            g_string_truncate (s, s->len - 2);
 
2053
            
 
2054
            str = s->str;
 
2055
            
 
2056
            g_string_free (s, FALSE);
 
2057
            break;
 
2058
    }
 
2059
 
 
2060
    return str;
 
2061
}
 
2062
 
 
2063
/*
2163
2064
 * }} AlarmRepeat utilities
2164
2065
 */