41
* Snooze any running (read: playing sound) alarms.
43
* Snooze any triggered alarms.
45
* Returns the number of snoozed alarms
44
alarm_applet_snooze_alarms (AlarmApplet *applet)
48
alarm_applet_alarms_snooze (AlarmApplet *applet)
51
Alarm *a, *last_snoozed = NULL;
53
gchar *summary, *body;
49
56
g_debug ("Snoozing alarms...");
51
// Loop through alarms and snooze all of 'em
58
// Loop through alarms and snooze all triggered ones
52
59
for (l = applet->alarms; l; l = l->next) {
53
60
a = ALARM (l->data);
57
// Close notification if present.
60
alarm_applet_notification_close (applet);
63
alarm_applet_alarm_snooze (applet, a);
72
// Single alarm snoozed
73
summary = g_strdup_printf (_("%s snoozed"), last_snoozed->message);
74
body = g_strdup_printf (_("You can stop the alarm from the Alarm Clock menu."));
75
icon = (last_snoozed->type == ALARM_TYPE_TIMER) ? TIMER_ICON : ALARM_ICON;
76
alarm_applet_notification_show (applet, summary, body, icon);
78
// More than 1 alarm snoozed
79
summary = g_strdup_printf (_("Snoozed %d alarms"), n_snoozed);
80
body = g_strdup_printf (_("You can stop alarms from the Alarm Clock menu."));
82
alarm_applet_notification_show (applet, summary, body, icon);
89
// Reset the triggered counter
90
applet->n_triggered = 0;
93
alarm_applet_status_update (applet);
66
* Clear any running (read: playing sound) alarms.
99
* Stop any running (read: playing sound) alarms.
69
alarm_applet_clear_alarms (AlarmApplet *applet)
102
alarm_applet_alarms_stop (AlarmApplet *applet)
74
g_debug ("Clearing alarms...");
105
Alarm *a, *last_stopped = NULL;
107
gchar *summary, *body;
110
g_debug ("Stopping alarms...");
76
112
// Loop through alarms and clear all of 'em
77
113
for (l = applet->alarms; l; l = l->next) {
78
114
a = ALARM (l->data);
82
// Close notification if present.
85
alarm_applet_notification_close (applet);
116
if (alarm_is_playing (a)) {
125
if (n_stopped == 1) {
126
// Single alarm stopped
127
summary = g_strdup_printf (_("%s stopped"), last_stopped->message);
128
body = g_strdup_printf (_("Repeating alarms will still continue according to schedule."));
129
icon = (last_stopped->type == ALARM_TYPE_TIMER) ? TIMER_ICON : ALARM_ICON;
130
alarm_applet_notification_show (applet, summary, body, icon);
132
// More than 1 alarm stopped
133
summary = g_strdup_printf (_("Stopped %d alarm(s)"), n_stopped);
134
body = g_strdup_printf (_("Repeating alarms will still continue according to schedule."));
135
icon = "alarm-clock";
136
alarm_applet_notification_show (applet, summary, body, icon);
143
// Reset the triggered counter
144
applet->n_triggered = 0;
146
// Update status icon
147
alarm_applet_status_update (applet);
153
* Snooze an alarm, according to UI settings
156
alarm_applet_alarm_snooze (AlarmApplet *applet, Alarm *alarm)
158
guint mins = applet->snooze_mins;
160
if (alarm->type == ALARM_TYPE_CLOCK) {
161
// Clocks always snooze for 9 minutes
162
mins = ALARM_STD_SNOOZE;
165
g_debug ("AlarmApplet: snooze '%s' for %d minutes", alarm->message, mins);
167
alarm_snooze (alarm, mins * 60);
169
// Update status icon
170
alarm_applet_status_update (applet);
174
* Stop an alarm, keeping UI consistent
177
alarm_applet_alarm_stop (AlarmApplet *applet, Alarm *alarm)
179
g_debug ("Stopping alarm #%d...", alarm->id);
184
// Update status icon
185
alarm_applet_status_update (applet);
244
361
xmlNode *root, *section, *element;
245
362
gchar *executable;
246
363
const gchar *tmp;
364
const gchar* const *sysdirs;
248
367
if (applet->apps != NULL)
249
368
alarm_list_entry_list_free (&(applet->apps));
251
// We'll get the default media players from g-d-a.xml
252
// from gnome-control-center
253
filename = g_build_filename (ALARM_DATADIR,
254
"gnome-control-center",
256
"gnome-default-applications.xml",
259
if (!g_file_test (filename, G_FILE_TEST_EXISTS)) {
260
g_critical ("Could not find %s.", filename);
264
xml_doc = xmlParseFile (filename);
267
g_warning ("Could not load %s.", filename);
271
root = xmlDocGetRootElement (xml_doc);
273
for (section = root->children; section != NULL; section = section->next) {
274
if (!xmlStrncmp (section->name, "media-players", 13)) {
275
for (element = section->children; element != NULL; element = element->next) {
276
if (!xmlStrncmp (element->name, "media-player", 12)) {
277
executable = gnome_da_xml_get_string (element, "executable");
278
if (is_executable_valid (executable)) {
279
name = gnome_da_xml_get_string (element, "name");
280
icon = gnome_da_xml_get_string (element, "icon-name");
282
// Lookup executable in app command map
283
tmp = get_app_command (executable);
285
command = g_strdup (tmp);
287
// Fall back to command specified in XML
288
command = gnome_da_xml_get_string (element, "command");
293
g_debug ("LOAD-APPS: Adding '%s': %s [%s]", name, command, icon);
295
entry = alarm_list_entry_new (name, command, icon);
301
applet->apps = g_list_append (applet->apps, entry);
371
sysdirs = g_get_system_data_dirs ();
372
for (i = 0; sysdirs[i] != NULL; i++) {
373
// We'll get the default media players from g-d-a.xml
374
// from gnome-control-center
375
filename = g_build_filename (sysdirs[i],
376
"gnome-control-center",
378
"gnome-default-applications.xml",
381
if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
382
xml_doc = xmlParseFile (filename);
385
g_warning ("Could not load %s.", filename);
389
root = xmlDocGetRootElement (xml_doc);
391
for (section = root->children; section != NULL; section = section->next) {
392
if (!xmlStrncmp (section->name, (const xmlChar *)"media-players", 13)) {
393
for (element = section->children; element != NULL; element = element->next) {
394
if (!xmlStrncmp (element->name, (const xmlChar *)"media-player", 12)) {
395
executable = gnome_da_xml_get_string (element, "executable");
396
if (is_executable_valid (executable)) {
397
name = gnome_da_xml_get_string (element, "name");
398
icon = gnome_da_xml_get_string (element, "icon-name");
400
// Lookup executable in app command map
401
tmp = get_app_command (executable);
403
command = g_strdup (tmp);
405
// Fall back to command specified in XML
406
command = gnome_da_xml_get_string (element, "command");
411
g_debug ("LOAD-APPS: Adding '%s': %s [%s]", name, command, icon);
413
entry = alarm_list_entry_new (name, command, icon);
419
applet->apps = g_list_append (applet->apps, entry);
316
436
// entry = alarm_list_entry_new("Rhythmbox Music Player", "rhythmbox", "rhythmbox");
317
437
// applet->apps = g_list_append (applet->apps, entry);
326
* Find the soonest-to-trigger upcoming alarm
329
alarm_applet_upcoming_alarm_update (AlarmApplet *applet)
334
applet->upcoming_alarm = NULL;
336
/* Loop through alarms looking for all active upcoming alarms and locate
337
* the one which will trigger sooner.
340
for (l = applet->alarms; l; l = l->next) {
343
if (!a->active) continue;
345
if (!applet->upcoming_alarm || a->timestamp < applet->upcoming_alarm->timestamp) {
346
// This alarm is most recent
347
applet->upcoming_alarm = a;
353
* Callback for when an alarm is activated / deactivated.
354
* We use this to update our closest upcoming alarm.
357
alarm_active_changed (GObject *object,
361
Alarm *alarm = ALARM (object);
362
AlarmApplet *applet = (AlarmApplet *)data;
364
g_debug ("alarm_active_changed: #%d to %d", alarm->id, alarm->active);
366
// Check if this was the upcoming alarm
367
if (!alarm->active) {
368
if (applet->upcoming_alarm == alarm) {
369
applet->upcoming_alarm = NULL;
371
alarm_applet_upcoming_alarm_update (applet);
372
alarm_applet_label_update (applet);
373
alarm_applet_icon_update (applet);
379
if (!applet->upcoming_alarm || alarm->timestamp < applet->upcoming_alarm->timestamp) {
381
applet->upcoming_alarm = alarm;
383
alarm_applet_label_update (applet);
390
* Callback for when an alarm is triggered
391
* We show the notification bubble here if appropriate.
394
alarm_triggered (Alarm *alarm, gpointer data)
396
AlarmApplet *applet = (AlarmApplet *)data;
398
g_debug ("Alarm triggered: #%d", alarm->id);
400
if (alarm->notify_bubble) {
401
g_debug ("Alarm #%d NOTIFICATION DISPLAY", alarm->id);
402
alarm_applet_notification_display (applet, alarm);
414
// TODO: Refactor to use a GHashTable instead
444
// TODO: Refactor to use a GHashTable instead?
416
446
alarm_applet_alarms_load (AlarmApplet *applet)
418
451
if (applet->alarms != NULL) {
421
/* Free old alarm objects */
452
// Free old alarm objects
422
453
for (l = applet->alarms; l != NULL; l = l->next) {
423
454
g_object_unref (ALARM (l->data));
427
458
g_list_free (applet->alarms);
430
/* Fetch list of alarms */
431
applet->alarms = alarm_get_list (ALARM_GCONF_DIR);
461
// Fetch list of alarms and add them
462
applet->alarms = NULL;
463
list = alarm_get_list (ALARM_GCONF_DIR);
465
for (l = list; l != NULL; l = l->next) {
466
alarm_applet_alarms_add (applet, ALARM (l->data));
437
473
applet->alarms = g_list_append (applet->alarms, alarm);
475
g_signal_connect (alarm, "notify", G_CALLBACK (alarm_applet_alarm_changed), applet);
439
476
g_signal_connect (alarm, "notify::sound-file", G_CALLBACK (alarm_sound_file_changed), applet);
440
g_signal_connect (alarm, "notify::active", G_CALLBACK (alarm_active_changed), applet);
441
g_signal_connect (alarm, "notify::time", G_CALLBACK (alarm_active_changed), applet);
443
g_signal_connect (alarm, "alarm", G_CALLBACK (alarm_triggered), applet);
478
g_signal_connect (alarm, "alarm", G_CALLBACK (alarm_applet_alarm_triggered), applet);
479
g_signal_connect (alarm, "cleared", G_CALLBACK (alarm_applet_alarm_cleared), applet);
481
// Update alarm list window model
482
if (applet->list_window) {
483
alarm_list_window_alarm_add (applet->list_window, alarm);
447
488
alarm_applet_alarms_remove (AlarmApplet *applet, Alarm *alarm)
452
491
applet->alarms = g_list_remove (applet->alarms, alarm);
455
* Clear list store. This will decrease the refcount of our alarms by 1.
457
if (applet->list_alarms_store)
458
gtk_list_store_clear (applet->list_alarms_store);
493
// Clear list store. This will decrease the refcount of our alarms by 1.
494
/*if (applet->list_alarms_store)
495
gtk_list_store_clear (applet->list_alarms_store);*/
460
497
g_debug ("alarm_applet_alarms_remove (..., %p): refcount = %d", alarm, G_OBJECT (alarm)->ref_count);
463
* If this is the upcoming alarm, update it.
465
if (applet->upcoming_alarm == alarm) {
466
alarm_applet_upcoming_alarm_update (applet);
470
* Remove any signal handlers for this alarm instance.
499
// Remove any signal handlers for this alarm instance.
472
500
g_signal_handlers_disconnect_matched (alarm, 0, 0, 0, NULL, NULL, NULL);
502
// Update alarm list window model
503
if (applet->list_window) {
504
alarm_list_window_alarm_remove (applet->list_window, alarm);
477
508
g_object_unref (alarm);
538
560
// Free GConf dir
539
g_free (applet->gconf_dir);
561
//g_free (applet->gconf_dir);
541
563
// Finally free the AlarmApplet struct itself
568
static UniqueResponse
569
unique_app_message_cb (UniqueApp *app,
570
UniqueCommand command,
571
UniqueMessageData *message,
575
AlarmApplet *applet = (AlarmApplet *)user_data;
580
case UNIQUE_ACTIVATE:
581
g_debug ("AlarmApplet: unique_app_message: ACTIVATE");
582
if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (applet->action_toggle_list_win))) {
583
// Already visible, present to user
584
alarm_list_window_show (applet->list_window);
586
// Toggle list window visibility
587
gtk_action_activate (GTK_ACTION (applet->action_toggle_list_win));
590
res = UNIQUE_RESPONSE_OK;
593
g_warning ("AlarmApplet: unique_app_message: Unknown command %d",
596
res = UNIQUE_RESPONSE_INVALID;
551
alarm_applet_factory (PanelApplet *panelapplet,
555
612
AlarmApplet *applet;
557
if (strcmp (iid, "OAFIID:AlarmClock") != 0)
560
/* Initialize applet struct,
561
* fill with zero's */
614
// Initialize applet struct */
562
615
applet = g_new0 (AlarmApplet, 1);
564
applet->parent = panelapplet;
565
applet->edit_alarm_dialogs = g_hash_table_new (NULL, NULL);
567
/* Preferences (defaults).
568
* ...gconf_get_string can return NULL if the key is not found. We can't
569
* assume the schema provides the default values for strings. */
570
applet->show_label = TRUE;
571
applet->label_type = LABEL_TYPE_TIME;
574
panel_applet_add_preferences (applet->parent, ALARM_SCHEMA_DIR, NULL);
575
panel_applet_set_flags (PANEL_APPLET (panelapplet), PANEL_APPLET_EXPAND_MINOR);
576
applet->gconf_dir = panel_applet_get_preferences_key (applet->parent);
578
/* Set up gconf handlers */
617
//applet->edit_alarm_dialogs = g_hash_table_new (NULL, NULL);
619
// Preferences (defaults).
620
// ...gconf_get_string can return NULL if the key is not found. We can't
621
// assume the schema provides the default values for strings.
623
// TODO: Add to gconf
624
applet->snooze_mins = 5;
626
// Set up gconf handlers
579
627
alarm_applet_gconf_init (applet);
581
/* Load gconf values */
582
630
alarm_applet_gconf_load (applet);
585
633
alarm_applet_alarms_load (applet);
587
/* Find any upcoming active alarms */
588
alarm_applet_upcoming_alarm_update (applet);
590
/* Load sounds from alarms */
635
// Load sounds from alarms
591
636
alarm_applet_sounds_load (applet);
593
/* Load apps for alarms */
638
// Load apps for alarms
594
639
alarm_applet_apps_load (applet);
596
/* Connect sound_file notify callback to all alarms */
597
alarm_signal_connect_list (applet->alarms, "notify::sound-file",
598
G_CALLBACK (alarm_sound_file_changed), applet);
600
/* Connect active & time notify callback to all alarms */
601
alarm_signal_connect_list (applet->alarms, "notify::active",
602
G_CALLBACK (alarm_active_changed), applet);
603
alarm_signal_connect_list (applet->alarms, "notify::time",
604
G_CALLBACK (alarm_active_changed), applet);
606
/* Connect alarm trigger notify to all alarms */
607
alarm_signal_connect_list (applet->alarms, "alarm",
608
G_CALLBACK (alarm_triggered), applet);
610
/* Set up properties menu */
611
alarm_applet_menu_init (applet);
614
642
alarm_applet_ui_init (applet);
619
PANEL_APPLET_BONOBO_FACTORY ("OAFIID:AlarmClock_Factory",
623
alarm_applet_factory,
651
main (int argc, char *argv[])
653
UniqueApp *unique_app;
656
// Internationalization
657
bindtextdomain (GETTEXT_PACKAGE, ALARM_CLOCK_DATADIR "/locale");
658
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
659
textdomain (GETTEXT_PACKAGE);
661
// Terminate on critical errors
662
//g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
665
gtk_init (&argc, &argv);
667
// Initialize unique app
668
unique_app = unique_app_new ("com.pseudoberries.AlarmClock", NULL);
670
// Check if we're already running
671
if (unique_app_is_running (unique_app)) {
672
g_printerr(_("%s is already running, exiting...\n"), PACKAGE);
674
// Send activate message
675
UniqueMessageData *message = unique_message_data_new ();
677
unique_app_send_message (unique_app, UNIQUE_ACTIVATE, message);
679
unique_message_data_free (message);
680
g_object_unref (unique_app);
688
applet = alarm_applet_init ();
690
// Connect unique app message-received signal
691
g_signal_connect (unique_app, "message-received",
692
G_CALLBACK (unique_app_message_cb), applet);
697
g_object_unref (unique_app);