aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivasa Ragavan <sragavan@src.gnome.org>2006-04-22 03:38:16 +0800
committerSrinivasa Ragavan <sragavan@src.gnome.org>2006-04-22 03:38:16 +0800
commit4900743e0d9b494e26e9c18df1ec4dbcb39b67ac (patch)
tree194f8412d1a2e86f368774a7e35bf49158eace54
parentd53bb7a4d7856cbcf1d0ca7f6c812af3ae9b91ad (diff)
downloadgsoc2013-evolution-4900743e0d9b494e26e9c18df1ec4dbcb39b67ac.tar
gsoc2013-evolution-4900743e0d9b494e26e9c18df1ec4dbcb39b67ac.tar.gz
gsoc2013-evolution-4900743e0d9b494e26e9c18df1ec4dbcb39b67ac.tar.bz2
gsoc2013-evolution-4900743e0d9b494e26e9c18df1ec4dbcb39b67ac.tar.lz
gsoc2013-evolution-4900743e0d9b494e26e9c18df1ec4dbcb39b67ac.tar.xz
gsoc2013-evolution-4900743e0d9b494e26e9c18df1ec4dbcb39b67ac.tar.zst
gsoc2013-evolution-4900743e0d9b494e26e9c18df1ec4dbcb39b67ac.zip
Rewrite Alarm Notify with EThread
svn path=/trunk/; revision=31858
-rw-r--r--calendar/ChangeLog36
-rw-r--r--calendar/gui/alarm-notify/alarm-notify.c121
-rw-r--r--calendar/gui/alarm-notify/alarm-notify.h14
-rw-r--r--calendar/gui/alarm-notify/alarm-queue.c665
-rw-r--r--calendar/gui/alarm-notify/alarm.c3
5 files changed, 709 insertions, 130 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 1e235d4ccb..2e801c8e97 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,39 @@
+2006-04-22 Srinivasa Ragavan <sragavan@novell.com>
+
+ Rewrite of Alarm daemon with EThread to make it thread safe. It also
+ fixes a lot of random crashes.
+
+ * gui/alarm-notify/alarm-notify.c: (process_removal_in_hash),
+ (list_changed_cb), (load_calendars), (alarm_notify_init),
+ (dequeue_client), (alarm_notify_finalize), (alarm_channel_setup),
+ (alarm_msg_destroy), (alarm_msgport_replied), (alarm_msg_received),
+ (alarm_notify_new), (cal_opened_cb), (alarm_notify_add_calendar),
+ (alarm_notify_remove_calendar):
+ * gui/alarm-notify/alarm-notify.h:
+ * gui/alarm-notify/alarm-queue.c: (queue_midnight_refresh),
+ (add_client_alarms_cb), (midnight_refresh_async),
+ (midnight_refresh_cb), (remove_queued_alarm), (alarm_trigger_cb),
+ (add_component_alarms), (load_alarms), (load_alarms_for_today),
+ (cal_opened_cb), (remove_alarms), (remove_comp), (duplicate_ical),
+ (duplicate_ecal), (query_objects_changed_async),
+ (query_objects_changed_cb), (query_objects_removed_async),
+ (query_objects_removed_cb), (create_snooze), (edit_component),
+ (on_dialog_objs_removed_async), (on_dialog_objs_removed_cb),
+ (tray_list_remove_cqa_async), (tray_list_remove_cqa),
+ (tray_list_remove_async), (tray_list_remove_icons),
+ (tray_list_remove_data_async), (tray_list_remove_data),
+ (notify_dialog_cb), (open_alarm_dialog), (tray_icon_clicked_cb),
+ (tray_list_add_async), (tray_list_add_new), (display_notification),
+ (popup_notification), (audio_notification), (mail_notification),
+ (procedure_notification_dialog), (procedure_notification),
+ (check_midnight_refresh), (alarm_queue_init),
+ (free_client_alarms_cb), (alarm_queue_done), (compare_ids),
+ (hash_ids), (alarm_queue_add_async), (alarm_queue_add_client),
+ (remove_cqa), (remove_comp_by_id), (remove_client_alarms),
+ (alarm_queue_remove_async), (alarm_queue_remove_client),
+ (update_cqa), (update_qa):
+ * gui/alarm-notify/alarm.c: (alarm_remove):
+
2006-02-16 Johnny Jacob <johnnyjacob@gmail.com>
** Fixes #330955
diff --git a/calendar/gui/alarm-notify/alarm-notify.c b/calendar/gui/alarm-notify/alarm-notify.c
index d268c6ffda..a773ab7644 100644
--- a/calendar/gui/alarm-notify/alarm-notify.c
+++ b/calendar/gui/alarm-notify/alarm-notify.c
@@ -44,6 +44,11 @@ struct _AlarmNotifyPrivate {
GMutex *mutex;
};
+EThread *alarm_operation_thread; /* for operations that can (or should) be queued */
+EMsgPort *alarm_reply_port;
+static GIOChannel *alarm_reply_channel;
+
+#define d(x) x
static void alarm_notify_class_init (AlarmNotifyClass *klass);
@@ -82,7 +87,7 @@ process_removal_in_hash (gpointer key, gpointer value, gpointer data)
ProcessRemovalsData *prd = data;
GSList *groups, *sources, *p, *q;
gboolean found = FALSE;
-
+
/* search the list of selected calendars */
groups = e_source_list_peek_groups (prd->source_list);
for (p = groups; p != NULL; p = p->next) {
@@ -120,8 +125,9 @@ list_changed_cb (ESourceList *source_list, gpointer data)
ProcessRemovalsData prd;
GList *l;
int i;
+
+ g_signal_handlers_block_by_func(source_list, list_changed_cb, data);
- printf("LIST CHANGED\n");
priv = an->priv;
/* Figure out the source type */
@@ -150,7 +156,7 @@ list_changed_cb (ESourceList *source_list, gpointer data)
uri = e_source_get_uri (source);
if (!g_hash_table_lookup (priv->uri_client_hash[source_type], uri)) {
- g_message ("Adding %s", uri);
+ d (printf("%s:%d (list_changed_cb) - Adding Calendar %s\n", __FILE__, __LINE__, uri));
alarm_notify_add_calendar (an, source_type, source, FALSE);
}
g_free (uri);
@@ -164,10 +170,12 @@ list_changed_cb (ESourceList *source_list, gpointer data)
g_hash_table_foreach (priv->uri_client_hash[source_type], (GHFunc) process_removal_in_hash, &prd);
for (l = prd.removals; l; l = l->next) {
- g_message ("Removing %s", (char *)l->data);
+ d (printf("%s:%d (list_changed_cb) - Removing Calendar %s\n", __FILE__, __LINE__, l->data));
alarm_notify_remove_calendar (an, source_type, l->data);
}
g_list_free (prd.removals);
+ g_signal_handlers_unblock_by_func(source_list, list_changed_cb, data);
+
}
ESourceList *
@@ -175,6 +183,7 @@ alarm_notify_get_selected_calendars (AlarmNotify *an)
{
return an->priv->selected_calendars;
}
+
static void
load_calendars (AlarmNotify *an, ECalSourceType source_type)
{
@@ -185,7 +194,7 @@ load_calendars (AlarmNotify *an, ECalSourceType source_type)
priv = an->priv;
if (!e_cal_get_sources (&source_list, source_type, NULL)) {
- g_message (G_STRLOC ": Could not get the list of sources to load");
+ d (printf("%s:%d (load_calendars) - Cannont get sources\n ", __FILE__, __LINE__));
priv->source_lists[source_type] = NULL;
return;
@@ -205,7 +214,7 @@ load_calendars (AlarmNotify *an, ECalSourceType source_type)
continue;
uri = e_source_get_uri (source);
- g_message ("Loading %s", uri);
+ d (printf("%s:%d (load_calendars) - Loading Calendar %s \n", __FILE__, __LINE__, uri));
alarm_notify_add_calendar (an, source_type, source, FALSE);
g_free (uri);
@@ -216,20 +225,6 @@ load_calendars (AlarmNotify *an, ECalSourceType source_type)
priv->source_lists[source_type] = source_list;
}
-static gboolean
-load_calendars_cb (gpointer data)
-{
- int i;
- AlarmNotify *an = ALARM_NOTIFY (data);
-
- for (i = 0; i < E_CAL_SOURCE_TYPE_LAST; i++) {
- if (an->priv->source_lists[i])
- list_changed_cb (an->priv->source_lists[i], an);
- }
-
- return FALSE;
-
-}
/* Object initialization function for the alarm notify system */
static void
alarm_notify_init (AlarmNotify *an, AlarmNotifyClass *klass)
@@ -242,7 +237,8 @@ alarm_notify_init (AlarmNotify *an, AlarmNotifyClass *klass)
priv->mutex = g_mutex_new ();
priv->selected_calendars = config_data_get_calendars ("/apps/evolution/calendar/sources");
-
+ d (printf("%s:%d (alarm_notify_init) - Initing Alarm Notify\n", __FILE__, __LINE__));
+
for (i = 0; i < E_CAL_SOURCE_TYPE_LAST; i++)
priv->uri_client_hash[i] = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
@@ -250,7 +246,6 @@ alarm_notify_init (AlarmNotify *an, AlarmNotifyClass *klass)
for (i = 0; i < E_CAL_SOURCE_TYPE_LAST; i++)
load_calendars (an, i);
- g_timeout_add (60000, (GSourceFunc)load_calendars_cb, an);
}
static void
@@ -258,6 +253,7 @@ dequeue_client (gpointer key, gpointer value, gpointer user_data)
{
ECal *client = value;
+ d (printf("%s:%d (dequeue_client) - Removing client %d\n ", __FILE__, __LINE__, client));
alarm_queue_remove_client (client);
}
@@ -271,7 +267,9 @@ alarm_notify_finalize (GObject *object)
g_return_if_fail (object != NULL);
g_return_if_fail (IS_ALARM_NOTIFY (object));
-
+
+ d (printf("%s:%d (alarm_notify_finalize) - Finalize \n ", __FILE__, __LINE__));
+
an = ALARM_NOTIFY (object);
priv = an->priv;
@@ -285,12 +283,72 @@ alarm_notify_finalize (GObject *object)
g_mutex_free (priv->mutex);
g_free (priv);
+ e_thread_destroy(alarm_operation_thread);
+ g_io_channel_unref(alarm_reply_channel);
+ e_msgport_destroy(alarm_reply_port);
if (G_OBJECT_CLASS (parent_class)->finalize)
(* G_OBJECT_CLASS (parent_class)->finalize) (object);
}
+static guint
+alarm_channel_setup(EMsgPort **port, GIOChannel **channel, GIOFunc func)
+{
+ GSource *source;
+ guint id;
+
+ d (printf("%s:%d (alarm_channel_setup) - Channel Setup\n ", __FILE__, __LINE__));
+ *port = e_msgport_new();
+#ifndef G_OS_WIN32
+ *channel = g_io_channel_unix_new(e_msgport_fd(*port));
+#else
+ *channel = g_io_channel_win32_new_socket(e_msgport_fd(*port));
+#endif
+ source = g_io_create_watch(*channel, G_IO_IN);
+ g_source_set_callback(source, (GSourceFunc)func, *port, NULL);
+ g_source_set_can_recurse(source, FALSE);
+ id = g_source_attach(source, NULL);
+ g_source_unref(source);
+
+ return id;
+}
+
+static void
+alarm_msg_destroy(EThread *e, EMsg *msg, void *data)
+{
+ AlarmMsg *m = (AlarmMsg *)msg;
+
+ /* Free the private */
+ g_free (m->data); /* Mostly it is a structure allocated as a carrier*/
+ g_free (m);
+}
+
+static gboolean
+alarm_msgport_replied(GIOChannel *source, GIOCondition cond, void *d)
+{
+ EMsgPort *port = (EMsgPort *)d;
+ AlarmMsg *m;
+
+ while (( m = (AlarmMsg *)e_msgport_get(port))) {
+ d (printf("%s:%d (alarm_msgport_replied) - %p: Replied to GUI thread\n", __FILE__, __LINE__, m));
+ alarm_msg_destroy(NULL, m, NULL);
+ }
+
+ return TRUE;
+}
+
+static void
+alarm_msg_received(EThread *e, EMsg *msg, void *data)
+{
+ AlarmMsg *m = (AlarmMsg *)msg;
+
+ d(printf("%s:%d (alarm_msg_received) - %p: Received at thread %" G_GINT64_MODIFIER "x\n", __FILE__, __LINE__, m, e_util_pthread_id(pthread_self())));
+ if (m->receive_msg) {
+ m->receive_msg (e, m, data);
+ }
+}
+
/**
* alarm_notify_new:
*
@@ -304,9 +362,20 @@ alarm_notify_new (void)
{
AlarmNotify *an;
+ d (printf("%s:%d (alarm_notify_new) - Alarm Notify New \n ", __FILE__, __LINE__));
+
+ /* Create a thread for alarm queue operation*/
+ alarm_channel_setup(&alarm_reply_port, &alarm_reply_channel, alarm_msgport_replied);
+
+ alarm_operation_thread = e_thread_new(E_THREAD_QUEUE);
+ e_thread_set_msg_destroy(alarm_operation_thread, alarm_msg_destroy, 0);
+ e_thread_set_msg_received(alarm_operation_thread, alarm_msg_received, 0);
+ e_thread_set_reply_port(alarm_operation_thread, alarm_reply_port);
+
an = g_object_new (TYPE_ALARM_NOTIFY,
"poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_PER_REQUEST, NULL),
NULL);
+
return an;
}
@@ -317,7 +386,9 @@ cal_opened_cb (ECal *client, ECalendarStatus status, gpointer user_data)
AlarmNotify *an = ALARM_NOTIFY (user_data);
priv = an->priv;
-
+
+ d (printf("%s:%d (cal_opened_cb) - Calendar Status %d\n", __FILE__, __LINE__, status==E_CALENDAR_STATUS_OK));
+
if (status == E_CALENDAR_STATUS_OK)
alarm_queue_add_client (client);
else {
@@ -379,6 +450,7 @@ alarm_notify_add_calendar (AlarmNotify *an, ECalSourceType source_type, ESource
client = auth_new_cal_from_source (source, source_type);
if (client) {
+ d (printf("%s:%d (alarm_notify_add_calendar) - Calendar Open Async... %d\n", __FILE__, __LINE__, client));
g_hash_table_insert (priv->uri_client_hash[source_type], g_strdup (str_uri), client);
g_signal_connect (G_OBJECT (client), "cal_opened", G_CALLBACK (cal_opened_cb), an);
e_cal_open_async (client, FALSE);
@@ -398,6 +470,7 @@ alarm_notify_remove_calendar (AlarmNotify *an, ECalSourceType source_type, const
client = g_hash_table_lookup (priv->uri_client_hash[source_type], str_uri);
if (client) {
+ d (printf("%s:%d (alarm_notify_remove_calendar) - Removing Client %d\n", __FILE__, __LINE__, client));
alarm_queue_remove_client (client);
g_hash_table_remove (priv->uri_client_hash[source_type], str_uri);
}
diff --git a/calendar/gui/alarm-notify/alarm-notify.h b/calendar/gui/alarm-notify/alarm-notify.h
index beb58acc1e..ef8c1fcf81 100644
--- a/calendar/gui/alarm-notify/alarm-notify.h
+++ b/calendar/gui/alarm-notify/alarm-notify.h
@@ -23,6 +23,7 @@
#define ALARM_NOTIFY_H
#include <bonobo/bonobo-object.h>
+#include <libedataserver/e-msgport.h>
#include "evolution-calendar.h"
@@ -38,6 +39,19 @@ typedef struct _AlarmNotifyClass AlarmNotifyClass;
typedef struct _AlarmNotifyPrivate AlarmNotifyPrivate;
+typedef struct _AlarmMsg AlarmMsg;
+typedef struct _AlarmMsgPrivate AlarmMsgPrivate;
+
+struct _AlarmMsg {
+ EMsg msg;
+
+ void (*receive_msg)(EThread *e, struct _AlarmMsg *msg, void *data); /* message received */
+ void *data;
+
+ /* Private Usage */
+ struct _AlarmMsgPrivate *priv;
+};
+
struct _AlarmNotify {
BonoboObject object;
diff --git a/calendar/gui/alarm-notify/alarm-queue.c b/calendar/gui/alarm-notify/alarm-queue.c
index d97d49af96..9b27990f4b 100644
--- a/calendar/gui/alarm-notify/alarm-queue.c
+++ b/calendar/gui/alarm-notify/alarm-queue.c
@@ -82,6 +82,9 @@
#include "e-util/e-error.h"
+
+#define d(x) x
+
/* The dialog with alarm nofications */
static AlarmNotificationsDialog *alarm_notifications_dialog = NULL;
@@ -112,6 +115,9 @@ static int tray_blink_id = -1;
static int tray_blink_state = FALSE;
static AlarmNotify *an;
+/* Main Tasks thread for dealing with the global structures */
+extern EThread *alarm_operation_thread;
+
/* Structure that stores a client we are monitoring */
typedef struct {
/* Monitored client */
@@ -185,6 +191,7 @@ static void query_objects_removed_cb (ECal *client, GList *objects, gpointer dat
static void remove_client_alarms (ClientAlarms *ca);
static void update_cqa (CompQueuedAlarms *cqa, ECalComponent *comp);
static void update_qa (ECalComponentAlarms *alarms, QueuedAlarm *qa);
+static void tray_list_remove_cqa (CompQueuedAlarms *cqa);
/* Alarm queue engine */
@@ -205,12 +212,13 @@ queue_midnight_refresh (void)
}
zone = config_data_get_timezone ();
-
midnight = time_day_end_with_zone (time (NULL), zone);
+ d(printf("%s:%d (queue_midnight_refresh) - Refresh at %s \n",__FILE__, __LINE__, ctime(&midnight)));
+
midnight_refresh_id = alarm_add (midnight, midnight_refresh_cb, NULL, NULL);
if (!midnight_refresh_id) {
- g_message ("queue_midnight_refresh(): Could not set up the midnight refresh alarm!");
+ d(printf("%s:%d (queue_midnight_refresh)) - Could not setup the midnight refresh alarm\n",__FILE__, __LINE__));
/* FIXME: what to do? */
}
}
@@ -220,22 +228,31 @@ static void
add_client_alarms_cb (gpointer key, gpointer value, gpointer data)
{
ClientAlarms *ca;
-
+
+ d(printf("%s:%d (add_client_alarms_cb) - Adding %d\n",__FILE__, __LINE__, ca));
+
ca = value;
load_alarms_for_today (ca);
}
+struct _midnight_refresh_msg {
+ gboolean remove;
+};
+
/* Loads the alarms for the new day every midnight */
static void
-midnight_refresh_cb (gpointer alarm_id, time_t trigger, gpointer data)
+midnight_refresh_async (EThread *e, AlarmMsg *msg, void *data)
{
- /* Re-load the alarms for all clients */
+ struct _midnight_refresh_msg *list = msg->data;
+ d(printf("%s:%d (midnight_refresh_async) \n",__FILE__, __LINE__));
+
+ /* Re-load the alarms for all clients */
g_hash_table_foreach (client_alarms_hash, add_client_alarms_cb, NULL);
/* Re-schedule the midnight update */
-
- if (midnight_refresh_id != NULL) {
+ if (list->remove && midnight_refresh_id != NULL) {
+ d(printf("%s:%d (midnight_refresh_async)) - Reschedule the midnight update \n",__FILE__, __LINE__));
alarm_remove (midnight_refresh_id);
midnight_refresh_id = NULL;
}
@@ -243,6 +260,25 @@ midnight_refresh_cb (gpointer alarm_id, time_t trigger, gpointer data)
queue_midnight_refresh ();
}
+static void
+midnight_refresh_cb (gpointer alarm_id, time_t trigger, gpointer data)
+{
+ AlarmMsg *msg;
+ struct _midnight_refresh_msg *list;
+
+ /* These two structures will be freed by the msg destroy function*/
+ msg = malloc (sizeof (AlarmMsg));
+ msg->receive_msg = midnight_refresh_async;
+
+ list = malloc (sizeof (struct _midnight_refresh_msg));
+
+ list->remove = TRUE;
+ msg->data = list;
+
+ d(printf("%s:%d (midnight_refresh_cb) - Invoking task for midnight refresh\n",__FILE__, __LINE__));
+ e_thread_put(alarm_operation_thread, (EMsg *)msg);
+}
+
/* Looks up a client in the client alarms hash table */
static ClientAlarms *
lookup_client (ECal *client)
@@ -276,10 +312,10 @@ static void
remove_queued_alarm (CompQueuedAlarms *cqa, gpointer alarm_id,
gboolean free_object, gboolean remove_alarm)
{
- QueuedAlarm *qa;
+ QueuedAlarm *qa=NULL;
GSList *l;
- qa = NULL;
+ d(printf("%s:%d (remove_queued_alarm) \n",__FILE__, __LINE__));
for (l = cqa->queued_alarms; l; l = l->next) {
qa = l->data;
@@ -308,9 +344,8 @@ remove_queued_alarm (CompQueuedAlarms *cqa, gpointer alarm_id,
if (cqa->queued_alarms != NULL)
return;
+ d(printf("%s:%d (remove_queued_alarm)) - Last Component. Removing CQA- Free=%d\n",__FILE__, __LINE__, free_object));
if (free_object) {
- g_hash_table_remove (cqa->parent_client->uid_alarms_hash, cqa->id);
- e_cal_component_free_id (cqa->id);
cqa->id = NULL;
cqa->parent_client = NULL;
e_cal_component_alarms_free (cqa->alarms);
@@ -335,6 +370,7 @@ alarm_trigger_cb (gpointer alarm_id, time_t trigger, gpointer data)
comp = cqa->alarms->comp;
config_data_set_last_notification_time (trigger);
+ d(printf("%s:%d (alarm_trigger_cb) - Setting Last notification time to %s\n",__FILE__, __LINE__, ctime (&trigger)));
saved_notification_time = trigger;
qa = lookup_queued_alarm (cqa, alarm_id);
@@ -379,6 +415,7 @@ alarm_trigger_cb (gpointer alarm_id, time_t trigger, gpointer data)
g_assert_not_reached ();
break;
}
+ d(printf("%s:%d (alarm_trigger_cb) - Notification sent:%d\n",__FILE__, __LINE__, action));
}
/* Adds the alarms in a ECalComponentAlarms structure to the alarms queued for a
@@ -393,7 +430,7 @@ add_component_alarms (ClientAlarms *ca, ECalComponentAlarms *alarms)
/* No alarms? */
if (alarms == NULL || alarms->alarms == NULL) {
- g_message ("No alarms to add");
+ d(printf("%s:%d (add_component_alarms) - No alarms to add\n",__FILE__, __LINE__));
if (alarms)
e_cal_component_alarms_free (alarms);
return;
@@ -405,19 +442,19 @@ add_component_alarms (ClientAlarms *ca, ECalComponentAlarms *alarms)
cqa->expecting_update = FALSE;
cqa->queued_alarms = NULL;
-
+ d(printf("%s:%d (add_component_alarms)) - Creating CQA %d\n",__FILE__, __LINE__, cqa));
+
for (l = alarms->alarms; l; l = l->next) {
ECalComponentAlarmInstance *instance;
gpointer alarm_id;
QueuedAlarm *qa;
-
+ time_t tnow = time(NULL);
+
instance = l->data;
- g_message ("Adding alarm at %lu (%lu)", instance->trigger, time (NULL));
alarm_id = alarm_add (instance->trigger, alarm_trigger_cb, cqa, NULL);
if (!alarm_id) {
- g_message ("add_component_alarms(): Could not schedule a trigger for "
- "%ld, discarding...", (long) instance->trigger);
+ d(printf("%s:%d (add_component_alarms)) - Could not schedule a trigger for %s. Discarding \n",__FILE__, __LINE__, ctime(&(instance->trigger))));
continue;
}
@@ -428,6 +465,7 @@ add_component_alarms (ClientAlarms *ca, ECalComponentAlarms *alarms)
qa->snooze = FALSE;
cqa->queued_alarms = g_slist_prepend (cqa->queued_alarms, qa);
+ d(printf("%s:%d (add_component_alarms)) - Adding alarm %d(%d)at %s (%s)\n",__FILE__, __LINE__, qa, alarm_id, ctime (&(instance->trigger)), ctime(&tnow)));
}
id = e_cal_component_get_id (alarms->comp);
@@ -436,13 +474,15 @@ add_component_alarms (ClientAlarms *ca, ECalComponentAlarms *alarms)
if (cqa->queued_alarms == NULL) {
e_cal_component_alarms_free (cqa->alarms);
cqa->alarms = NULL;
-
+ d(printf("%s:%d (add_component_alarms)) - Failed to add all : %d\n",__FILE__, __LINE__, cqa));
+ g_message ("Failed to add all\n");
g_free (cqa);
return;
}
cqa->queued_alarms = g_slist_reverse (cqa->queued_alarms);
cqa->id = id;
+ d(printf("%s:%d (add_component_alarms)) - Alarm added for %s\n",__FILE__, __LINE__, id->uid));
g_hash_table_insert (ca->uid_alarms_hash, cqa->id, cqa);
}
@@ -452,6 +492,8 @@ load_alarms (ClientAlarms *ca, time_t start, time_t end)
{
char *str_query, *iso_start, *iso_end;
+ d(printf("%s:%d (load_alarms) \n",__FILE__, __LINE__));
+
iso_start = isodate_from_time_t (start);
if (!iso_start)
return;
@@ -469,6 +511,7 @@ load_alarms (ClientAlarms *ca, time_t start, time_t end)
/* create the live query */
if (ca->query) {
+ d(printf("%s:%d (load_alarms) - Disconnecting old queries \n",__FILE__, __LINE__));
g_signal_handlers_disconnect_matched (ca->query, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, ca);
g_object_unref (ca->query);
ca->query = NULL;
@@ -478,6 +521,8 @@ load_alarms (ClientAlarms *ca, time_t start, time_t end)
if (!e_cal_get_query (ca->client, str_query, &ca->query, NULL)) {
g_warning (G_STRLOC ": Could not get query for client");
} else {
+ d(printf("%s:%d (load_alarms) - Setting Call backs \n",__FILE__, __LINE__));
+
g_signal_connect (G_OBJECT (ca->query), "objects_added",
G_CALLBACK (query_objects_changed_cb), ca);
g_signal_connect (G_OBJECT (ca->query), "objects_modified",
@@ -509,8 +554,8 @@ load_alarms_for_today (ClientAlarms *ca)
*/
from = MAX (config_data_get_last_notification_time () + 1, day_start);
- g_message ("Loading alarms for today");
day_end = time_day_end_with_zone (now, zone);
+ d(printf("%s:%d (load_alarms_for_today) - From %s to %s\n",__FILE__, __LINE__, ctime (&from), ctime(&day_end)));
load_alarms (ca, from, day_end);
}
@@ -522,6 +567,7 @@ cal_opened_cb (ECal *client, ECalendarStatus status, gpointer data)
ca = data;
+ d(printf("%s:%d (cal_opened_cb)) - Opened Calendar %d (Status %d)\n",__FILE__, __LINE__, client, status==E_CALENDAR_STATUS_OK));
if (status != E_CALENDAR_STATUS_OK)
return;
@@ -540,6 +586,7 @@ remove_alarms (CompQueuedAlarms *cqa, gboolean free_object)
{
GSList *l;
+ d(printf("%s:%d (remove_alarms) - Removing for %d\n",__FILE__, __LINE__, cqa));
for (l = cqa->queued_alarms; l;) {
QueuedAlarm *qa;
@@ -559,10 +606,17 @@ remove_alarms (CompQueuedAlarms *cqa, gboolean free_object)
/* Removes a component an its alarms */
static void
-remove_comp (ClientAlarms *ca, const ECalComponentId *id)
+remove_comp (ClientAlarms *ca, ECalComponentId *id)
{
CompQueuedAlarms *cqa;
+ d(printf("%s:%d (remove_comp) - Removing uid %s\n",__FILE__, __LINE__, id->uid));
+
+ if (id->rid && !(*(id->rid))) {
+ g_free (id->rid);
+ id->rid = NULL;
+ }
+
cqa = lookup_comp_queued_alarms (ca, id);
if (!cqa)
return;
@@ -571,20 +625,49 @@ remove_comp (ClientAlarms *ca, const ECalComponentId *id)
* for it.
*/
g_assert (cqa->queued_alarms != NULL);
-
+
+ d(printf("%s:%d (remove_comp) - Removing CQA %d\n",__FILE__, __LINE__, cqa));
remove_alarms (cqa, TRUE);
-
- /* The list should be empty now, and thus the queued component alarms
- * structure should have been freed and removed from the hash table.
- */
- g_assert (lookup_comp_queued_alarms (ca, id) == NULL);
}
/* Called when a calendar component changes; we must reload its corresponding
* alarms.
*/
+struct _query_msg {
+ ECal *client;
+ GList *objects;
+ gpointer data;
+};
+
+static GList *
+duplicate_ical (GList *in_list)
+{
+ GList *l, *out_list = NULL;
+ for (l = in_list; l; l = l->next) {
+ out_list = g_list_prepend (out_list, icalcomponent_new_clone (l->data));
+ }
+
+ return g_list_reverse (out_list);
+}
+
+static GList *
+duplicate_ecal (GList *in_list)
+{
+ GList *l, *out_list = NULL;
+ for (l = in_list; l; l = l->next) {
+ ECalComponentId *id, *old;
+ old = l->data;
+ id = g_new0 (ECalComponentId, 1);
+ id->uid = g_strdup (old->uid);
+ id->rid = g_strdup (old->rid);
+ out_list = g_list_prepend (out_list, id);
+ }
+
+ return g_list_reverse (out_list);
+}
+
static void
-query_objects_changed_cb (ECal *client, GList *objects, gpointer data)
+query_objects_changed_async (EThread *e, AlarmMsg *msg, void *data)
{
ClientAlarms *ca;
time_t from, day_end;
@@ -593,9 +676,14 @@ query_objects_changed_cb (ECal *client, GList *objects, gpointer data)
icaltimezone *zone;
CompQueuedAlarms *cqa;
GList *l;
-
- ca = data;
-
+ struct _query_msg *list = msg->data;
+ ECal *client;
+ GList *objects;
+
+ client = list->client;
+ ca = list->data;
+ objects = list->objects;
+
from = config_data_get_last_notification_time ();
if (from == -1)
from = time (NULL);
@@ -605,20 +693,24 @@ query_objects_changed_cb (ECal *client, GList *objects, gpointer data)
zone = config_data_get_timezone ();
day_end = time_day_end_with_zone (time (NULL), zone);
- g_message ("Query response for alarms");
+
+ d(printf("%s:%d (query_objects_changed_async) - Querying for object between %s to %s\n",__FILE__, __LINE__, ctime(&from), ctime(&day_end)));
+
for (l = objects; l != NULL; l = l->next) {
ECalComponentId *id;
GSList *sl;
ECalComponent *comp = e_cal_component_new ();
- e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (l->data));
+ e_cal_component_set_icalcomponent (comp, l->data);
id = e_cal_component_get_id (comp);
found = e_cal_get_alarms_for_object (ca->client, id, from, day_end, &alarms);
if (!found) {
- g_message ("No alarms found on object");
+ d(printf("%s:%d (query_objects_changed_async) - No Alarm found for client %d\n",__FILE__, __LINE__, ca->client));
+ tray_list_remove_cqa (lookup_comp_queued_alarms (ca, l->data));
remove_comp (ca, id);
+ g_hash_table_remove (ca->uid_alarms_hash, id);
e_cal_component_free_id (id);
g_object_unref (comp);
comp = NULL;
@@ -627,15 +719,14 @@ query_objects_changed_cb (ECal *client, GList *objects, gpointer data)
cqa = lookup_comp_queued_alarms (ca, id);
if (!cqa) {
- g_message ("No currently queue alarms");
+ d(printf("%s:%d (query_objects_changed_async) - No currently queued alarms for %s\n",__FILE__, __LINE__, id->uid));
add_component_alarms (ca, alarms);
g_object_unref (comp);
comp = NULL;
continue;
}
- g_message ("Already existing alarms");
-
+ d(printf("%s:%d (query_objects_changed_async) - Alarm Already Exist for %s\n",__FILE__, __LINE__, id->uid));
/* if the alarms or the alarms list is empty remove it after updating the cqa structure */
if (alarms == NULL || alarms->alarms == NULL) {
@@ -662,8 +753,7 @@ query_objects_changed_cb (ECal *client, GList *objects, gpointer data)
alarm_id = alarm_add (instance->trigger, alarm_trigger_cb, cqa, NULL);
if (!alarm_id) {
- g_message (G_STRLOC ": Could not schedule a trigger for "
- "%ld, discarding...", (long) instance->trigger);
+ d(printf("%s:%d (query_objects_changed_async) -Unable to schedule trigger for %s \n",__FILE__, __LINE__, ctime(&(instance->trigger))));
continue;
}
@@ -673,29 +763,85 @@ query_objects_changed_cb (ECal *client, GList *objects, gpointer data)
qa->snooze = FALSE;
qa->orig_trigger = instance->trigger;
cqa->queued_alarms = g_slist_prepend (cqa->queued_alarms, qa);
+ d(printf("%s:%d (query_objects_changed_async) - Adding %d to queue \n",__FILE__, __LINE__, qa));
}
cqa->queued_alarms = g_slist_reverse (cqa->queued_alarms);
g_object_unref (comp);
comp = NULL;
}
+ g_list_free (objects);
+}
+
+static void
+query_objects_changed_cb (ECal *client, GList *objects, gpointer data)
+{
+ AlarmMsg *msg;
+ struct _query_msg *list;
+
+ /* These two structures will be freed by the msg destroy function*/
+ msg = malloc (sizeof (AlarmMsg));
+ msg->receive_msg = query_objects_changed_async;
+ list = malloc (sizeof (struct _query_msg));
+ list->client = client;
+ list->objects = duplicate_ical (objects);
+ list->data = data;
+ msg->data = list;
+
+ d(printf("%s:%d (query_objects_changed_cb) - Posting a task\n",__FILE__, __LINE__));
+ e_thread_put(alarm_operation_thread, (EMsg *)msg);
+
}
/* Called when a calendar component is removed; we must delete its corresponding
* alarms.
*/
static void
-query_objects_removed_cb (ECal *client, GList *objects, gpointer data)
+query_objects_removed_async (EThread *e, AlarmMsg *msg, void *data)
{
ClientAlarms *ca;
GList *l;
-
- ca = data;
-
- for (l = objects; l != NULL; l = l->next)
+ struct _query_msg *list = msg->data;
+ ECal *client;
+ GList *objects;
+
+ client = list->client;
+ ca = list->data;
+ objects = list->objects;
+
+ d(printf("%s:%d (query_objects_removed_async) - Removing %d objects\n",__FILE__, __LINE__, g_list_length(objects)));
+
+ for (l = objects; l != NULL; l = l->next) {
+ /* If the alarm is already triggered remove it. */
+ tray_list_remove_cqa (lookup_comp_queued_alarms (ca, l->data));
remove_comp (ca, l->data);
+ g_hash_table_remove (ca->uid_alarms_hash, l->data);
+ e_cal_component_free_id (l->data);
+ }
+
+ g_list_free (objects);
}
+static void
+query_objects_removed_cb (ECal *client, GList *objects, gpointer data)
+{
+ AlarmMsg *msg;
+ struct _query_msg *list;
+
+ /* These two structures will be freed by the msg destroy function*/
+ msg = malloc (sizeof (AlarmMsg));
+ msg->receive_msg = query_objects_removed_async;
+
+ list = malloc (sizeof (struct _query_msg));
+ list->client = client;
+ list->objects = duplicate_ecal (objects);
+ list->data = data;
+ msg->data = list;
+
+ d(printf("%s:%d (query_objects_removed_cb) - Posting a task\n",__FILE__, __LINE__));
+ e_thread_put(alarm_operation_thread, (EMsg *)msg);
+
+}
/* Notification functions */
@@ -719,14 +865,14 @@ create_snooze (CompQueuedAlarms *cqa, gpointer alarm_id, int snooze_mins)
new_id = alarm_add (t, alarm_trigger_cb, cqa, NULL);
if (!new_id) {
- g_message ("create_snooze(): Could not schedule a trigger for "
- "%ld, discarding...", (long) t);
+ d(printf("%s:%d (create_snooze) -Unable to schedule trigger for %s \n",__FILE__, __LINE__, ctime(&t)));
return;
}
orig_qa->instance->trigger = t;
orig_qa->alarm_id = new_id;
orig_qa->snooze = TRUE;
+ d(printf("%s:%d (create_snooze) - Adding a alarm at %s\n",__FILE__, __LINE__, ctime(&t)));
}
/* Launches a component editor for a component */
@@ -740,6 +886,8 @@ edit_component (ECal *client, ECalComponent *comp)
GNOME_Evolution_Calendar_CompEditorFactory factory;
GNOME_Evolution_Calendar_CompEditorFactory_CompEditorMode corba_type;
+ d(printf("%s:%d (edit_component) - Client %d\n",__FILE__, __LINE__, client));
+
e_cal_component_get_uid (comp, &uid);
uri = e_cal_get_uri (client);
@@ -837,12 +985,21 @@ free_tray_icon_data (TrayIconData *tray_data)
}
static void
-on_dialog_objs_removed_cb (ECal *client, GList *objects, gpointer data)
+on_dialog_objs_removed_async (EThread *e, AlarmMsg *msg, void *data)
{
const char *our_uid;
GList *l;
- TrayIconData *tray_data = data;
+ TrayIconData *tray_data;
+ struct _query_msg *list = msg->data;
+ ECal *client;
+ GList *objects;
+ d(printf("%s:%d (on_dialog_objs_removed_async)\n",__FILE__, __LINE__));
+
+ client = list->client;
+ tray_data = list->data;
+ objects = list->objects;
+
e_cal_component_get_uid (tray_data->comp, &our_uid);
g_return_if_fail (our_uid && *our_uid);
@@ -861,19 +1018,186 @@ on_dialog_objs_removed_cb (ECal *client, GList *objects, gpointer data)
}
}
+static void
+on_dialog_objs_removed_cb (ECal *client, GList *objects, gpointer data)
+{
+ AlarmMsg *msg;
+ struct _query_msg *list;
+
+ /* These two structures will be freed by the msg destroy function*/
+ msg = malloc (sizeof (AlarmMsg));
+ msg->receive_msg = on_dialog_objs_removed_async;
+
+ list = malloc (sizeof (struct _query_msg));
+ list->client = client;
+ list->objects = objects;
+ list->data = data;
+ msg->data = list;
+
+ d(printf("%s:%d (on_dialog_objs_removed_cb) - Posting a task \n",__FILE__, __LINE__));
+ e_thread_put(alarm_operation_thread, (EMsg *)msg);
+}
+
+struct _tray_cqa_msg {
+ CompQueuedAlarms *cqa;
+};
+
+static void
+tray_list_remove_cqa_async(EThread *e, AlarmMsg *msg, void *data)
+{
+ struct _tray_cqa_msg *tmsg = msg->data;
+ CompQueuedAlarms *cqa = tmsg->cqa;
+ GList *list = tray_icons_list;
+
+ d(printf("%s:%d (tray_list_remove_cqa_async) - Removing CQA %d from tray list\n",__FILE__, __LINE__, cqa));
+
+ while (list) {
+ TrayIconData *tray_data = list->data;
+ GList *tmp = list;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ list = list->next;
+ if (tray_data->cqa == cqa) {
+ d(printf("%s:%d (tray_list_remove_cqa_async) - Found.\n", __FILE__, __LINE__));
+ tray_icons_list = g_list_delete_link (tray_icons_list, tmp);
+ if (alarm_notifications_dialog) {
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (alarm_notifications_dialog->treeview));
+ gtk_list_store_remove (GTK_LIST_STORE (model), &(tray_data->iter));
+ }
+ free_tray_icon_data (tray_data);
+ }
+ }
+
+ d(printf("%s:%d (tray_list_remove_cqa_async) - %d alarms left.\n", __FILE__, __LINE__, g_list_length (tray_icons_list)));
+
+ if (alarm_notifications_dialog) {
+ if (!g_list_length (tray_icons_list)) {
+ gtk_widget_destroy (alarm_notifications_dialog->dialog);
+ g_free (alarm_notifications_dialog);
+ alarm_notifications_dialog = NULL;
+ } else {
+ GtkTreeIter iter;
+ GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (alarm_notifications_dialog->treeview));
+ gboolean valid = gtk_tree_model_get_iter_first (model, &iter);
+ GtkTreeSelection *sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (alarm_notifications_dialog->treeview));
+ gtk_tree_selection_select_iter (sel, &iter);
+ }
+ }
+}
+
+static void
+tray_list_remove_cqa (CompQueuedAlarms *cqa)
+{
+ AlarmMsg *msg;
+ struct _tray_cqa_msg *list;
+ /* These two structures will be freed by the msg destroy function*/
+ msg = malloc (sizeof (AlarmMsg));
+ msg->receive_msg = tray_list_remove_cqa_async;
+
+ list = malloc (sizeof (struct _tray_cqa_msg));
+ list->cqa = cqa;
+ msg->data = list;
+
+ d(printf("%s:%d (tray_list_remove_cqa) - Posting a task\n",__FILE__, __LINE__));
+ e_thread_put(alarm_operation_thread, (EMsg *)msg);
+}
+
/* Callback used from the alarm notify dialog */
static void
+tray_list_remove_async(EThread *e, AlarmMsg *msg, void *data)
+{
+ GList *list = tray_icons_list;
+
+ d(printf("%s:%d (tray_list_remove_async) - Removing %d alarms\n",__FILE__, __LINE__, g_list_length(list)));
+ while (list != NULL) {
+
+ TrayIconData *tray_data = list->data;
+
+ if (!tray_data->snooze_set){
+ GList *temp = list->next;
+ tray_icons_list = g_list_remove_link (tray_icons_list, list);
+ remove_queued_alarm (tray_data->cqa, tray_data->alarm_id, FALSE, TRUE);
+ g_hash_table_remove (tray_data->cqa->parent_client->uid_alarms_hash, tray_data->cqa->id);
+ e_cal_component_free_id (tray_data->cqa->id);
+ g_free (tray_data->cqa);
+ free_tray_icon_data (tray_data);
+ tray_data = NULL;
+ g_list_free_1 (list);
+ if (tray_icons_list != list) /* List head is modified */
+ list = tray_icons_list;
+ else
+ list = temp;
+ } else
+ list = list->next;
+ }
+}
+
+static void
+tray_list_remove_icons ()
+{
+ AlarmMsg *msg;
+
+ /* These two structures will be freed by the msg destroy function*/
+ msg = malloc (sizeof (AlarmMsg));
+ msg->receive_msg = tray_list_remove_async;
+
+ msg->data = NULL;
+
+ d(printf("%s:%d (tray_list_remove_icons) - Posting a task\n",__FILE__, __LINE__));
+ e_thread_put(alarm_operation_thread, (EMsg *)msg);
+}
+
+struct _tray_msg {
+ TrayIconData *data;
+};
+
+static void
+tray_list_remove_data_async(EThread *e, AlarmMsg *msg, void *data)
+{
+ struct _tray_msg *tmsg = msg->data;
+ TrayIconData *tray_data = tmsg->data;
+
+ d(printf("%s:%d (tray_list_remove_data_async) - Removing %d from tray list\n",__FILE__, __LINE__, tray_data));
+
+ tray_icons_list = g_list_remove_all (tray_icons_list, tray_data);
+ free_tray_icon_data (tray_data);
+ tray_data = NULL;
+}
+
+static void
+tray_list_remove_data (TrayIconData *data)
+{
+ AlarmMsg *msg;
+ struct _tray_msg *list;
+ /* These two structures will be freed by the msg destroy function*/
+ msg = malloc (sizeof (AlarmMsg));
+ msg->receive_msg = tray_list_remove_data_async;
+
+ list = malloc (sizeof (struct _tray_msg));
+ list->data = data;
+ msg->data = list;
+
+ d(printf("%s:%d (tray_list_remove_data) - Posting a task\n",__FILE__, __LINE__));
+ e_thread_put(alarm_operation_thread, (EMsg *)msg);
+}
+
+static void
notify_dialog_cb (AlarmNotifyResult result, int snooze_mins, gpointer data)
{
TrayIconData *tray_data = data;
+
+ d(printf("%s:%d (notify_dialog_cb) - Received from dialog\n",__FILE__, __LINE__));
g_signal_handlers_disconnect_matched (tray_data->query, G_SIGNAL_MATCH_FUNC,
0, 0, NULL, on_dialog_objs_removed_cb, NULL);
switch (result) {
case ALARM_NOTIFY_SNOOZE:
+ d(printf("%s:%d (notify_dialog_cb) - Creating a snooze\n",__FILE__, __LINE__));
create_snooze (tray_data->cqa, tray_data->alarm_id, snooze_mins);
tray_data->snooze_set = TRUE;
+ tray_list_remove_data (tray_data);
if (alarm_notifications_dialog) {
GtkTreeSelection *selection =
gtk_tree_view_get_selection (
@@ -905,7 +1229,7 @@ notify_dialog_cb (AlarmNotifyResult result, int snooze_mins, gpointer data)
break;
case ALARM_NOTIFY_CLOSE:
-
+ d(printf("%s:%d (notify_dialog_cb) - Dialog close\n",__FILE__, __LINE__));
if (alarm_notifications_dialog) {
GList *list;
GtkTreeIter iter;
@@ -924,27 +1248,8 @@ notify_dialog_cb (AlarmNotifyResult result, int snooze_mins, gpointer data)
g_free (alarm_notifications_dialog);
alarm_notifications_dialog = NULL;
- /* FIXME tray_icons_list is a global data structure - make this thread safe */
-
- list = tray_icons_list;
- while (list != NULL) {
-
- tray_data = list->data;
-
- if (!tray_data->snooze_set){
- GList *temp = list->next;
- tray_icons_list = g_list_remove_link (tray_icons_list, list);
- remove_queued_alarm (tray_data->cqa, tray_data->alarm_id, TRUE, TRUE);
- free_tray_icon_data (tray_data);
- tray_data = NULL;
- g_list_free_1 (list);
- if (tray_icons_list != list) /* List head is modified */
- list = tray_icons_list;
- else
- list = temp;
- } else
- list = list->next;
- }
+ /* Task to remove the tray icons */
+ tray_list_remove_icons ();
}
break;
@@ -961,7 +1266,8 @@ static gboolean
open_alarm_dialog (TrayIconData *tray_data)
{
QueuedAlarm *qa;
-
+
+ d(printf("%s:%d (open_alarm_dialog) \n",__FILE__, __LINE__));
qa = lookup_queued_alarm (tray_data->cqa, tray_data->alarm_id);
if (qa) {
@@ -1010,6 +1316,7 @@ tray_icon_clicked_cb (GtkWidget *widget, GdkEventButton *event, gpointer user_da
TrayIconData *tray_data = user_data;
if (event->type == GDK_BUTTON_PRESS) {
+ d(printf("%s:%d (tray_icon_clicked_cb) - left click and %d alarms\n",__FILE__, __LINE__, g_list_length (tray_icons_list)));
if (event->button == 1 && g_list_length (tray_icons_list) > 0) {
GList *tmp;
for (tmp = tray_icons_list; tmp; tmp = tmp->next) {
@@ -1018,11 +1325,11 @@ tray_icon_clicked_cb (GtkWidget *widget, GdkEventButton *event, gpointer user_da
return TRUE;
} else if (event->button == 3) {
-
+ d(printf("%s:%d (tray_icon_clicked_cb) - right click\n",__FILE__, __LINE__));
if (tray_blink_id > -1)
g_source_remove (tray_blink_id);
tray_blink_id = -1;
-
+
gtk_widget_destroy (tray_icon);
tray_icon = NULL;
#ifndef USE_GTK_STATUS_ICON
@@ -1073,6 +1380,35 @@ tray_icon_blink_cb (gpointer data)
return TRUE;
}
+
+/* Add a new data to tray list */
+
+static void
+tray_list_add_async (EThread *e, AlarmMsg *msg, void *data)
+{
+ struct _tray_msg *list = msg->data;
+ d(printf("%s:%d (tray_list_add_async) - Add %d\n",__FILE__, __LINE__, list->data));
+ tray_icons_list = g_list_prepend (tray_icons_list, list->data);
+}
+
+static void
+tray_list_add_new (TrayIconData *data)
+{
+ AlarmMsg *msg;
+ struct _tray_msg *list;
+
+ /* These two structures will be freed by the msg destroy function*/
+ msg = malloc (sizeof (AlarmMsg));
+ msg->receive_msg = tray_list_add_async;
+
+ list = malloc (sizeof (struct _tray_msg));
+ list->data = data;
+ msg->data = list;
+
+ d(printf("%s:%d (tray_list_add_new) - Posting a task\n",__FILE__, __LINE__));
+ e_thread_put(alarm_operation_thread, (EMsg *)msg);
+}
+
/* Performs notification of a display alarm */
static void
display_notification (time_t trigger, CompQueuedAlarms *cqa,
@@ -1092,6 +1428,8 @@ display_notification (time_t trigger, CompQueuedAlarms *cqa,
icaltimezone *current_zone;
ECalComponentOrganizer organiser;
+ d(printf("%s:%d (display_notification)\n",__FILE__, __LINE__));
+
comp = cqa->alarms->comp;
qa = lookup_queued_alarm (cqa, alarm_id);
if (!qa)
@@ -1176,7 +1514,8 @@ display_notification (time_t trigger, CompQueuedAlarms *cqa,
g_object_ref (tray_data->client);
tray_data->tray_icon = tray_icon;
- tray_icons_list = g_list_prepend (tray_icons_list, tray_data);
+ /* Task to add tray_data to the global tray_icon_list */
+ tray_list_add_new (tray_data);
if (g_list_length (tray_icons_list) > 1) {
char *tip;
@@ -1231,6 +1570,8 @@ popup_notification (time_t trigger, CompQueuedAlarms *cqa,
icaltimezone *current_zone;
ECalComponentOrganizer organiser;
char *body;
+
+ d(printf("%s:%d (popup_notification)\n",__FILE__, __LINE__));
comp = cqa->alarms->comp;
qa = lookup_queued_alarm (cqa, alarm_id);
@@ -1302,6 +1643,8 @@ audio_notification (time_t trigger, CompQueuedAlarms *cqa,
icalattach *attach;
int flag = 0;
+ d(printf("%s:%d (audio_notification)\n",__FILE__, __LINE__));
+
comp = cqa->alarms->comp;
qa = lookup_queued_alarm (cqa, alarm_id);
if (!qa)
@@ -1341,6 +1684,8 @@ mail_notification (time_t trigger, CompQueuedAlarms *cqa, gpointer alarm_id)
/* FIXME */
+ d(printf("%s:%d (mail_notification)\n",__FILE__, __LINE__));
+
dialog = gtk_dialog_new_with_buttons (_("Warning"),
NULL, 0,
GTK_STOCK_OK, GTK_RESPONSE_CANCEL,
@@ -1361,6 +1706,8 @@ procedure_notification_dialog (const char *cmd, const char *url)
GtkWidget *dialog, *label, *checkbox;
char *str;
int btn;
+
+ d(printf("%s:%d (procedure_notification_dialog)\n",__FILE__, __LINE__));
if (config_data_is_blessed_program (url))
return TRUE;
@@ -1411,6 +1758,8 @@ procedure_notification (time_t trigger, CompQueuedAlarms *cqa, gpointer alarm_id
char *cmd;
int result;
+ d(printf("%s:%d (procedure_notification)\n",__FILE__, __LINE__));
+
comp = cqa->alarms->comp;
qa = lookup_queued_alarm (cqa, alarm_id);
if (!qa)
@@ -1469,14 +1818,27 @@ check_midnight_refresh (gpointer user_data)
time_t new_midnight;
icaltimezone *zone;
+ d(printf("%s:%d (check_midnight_refresh)\n",__FILE__, __LINE__));
+
zone = config_data_get_timezone ();
new_midnight = time_day_end_with_zone (time (NULL), zone);
if (new_midnight > midnight) {
- /* Re-load the alarms for all clients */
- g_hash_table_foreach (client_alarms_hash, add_client_alarms_cb, NULL);
+ AlarmMsg *msg;
+ struct _midnight_refresh_msg *list;
+
+ /* These two structures will be freed by the msg destroy function*/
+ msg = malloc (sizeof (AlarmMsg));
+ msg->receive_msg = midnight_refresh_async;
- queue_midnight_refresh ();
+ list = malloc (sizeof (struct _midnight_refresh_msg));
+
+ list->remove = FALSE;
+ /* We dont need it. So set it to NULL */
+ msg->data = list;
+
+ d(printf("%s:%d (check_midnight_refresh) - Posting a task to refresh\n",__FILE__, __LINE__));
+ e_thread_put(alarm_operation_thread, (EMsg *)msg);
}
return TRUE;
@@ -1494,12 +1856,15 @@ alarm_queue_init (gpointer data)
an = data;
g_return_if_fail (alarm_queue_inited == FALSE);
+ d(printf("%s:%d (alarm_queue_init)\n",__FILE__, __LINE__));
+
client_alarms_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
queue_midnight_refresh ();
saved_notification_time = config_data_get_last_notification_time ();
if (saved_notification_time == -1) {
saved_notification_time = time (NULL);
+ d(printf("%s:%d (alarm_queue_init) - Setting last notification time to %s\n",__FILE__, __LINE__, ctime(&saved_notification_time)));
config_data_set_last_notification_time (saved_notification_time);
}
@@ -1518,15 +1883,21 @@ free_client_alarms_cb (gpointer key, gpointer value, gpointer user_data)
{
ClientAlarms *ca = value;
+ d(printf("%s:%d (free_client_alarms_cb) - %d \n",__FILE__, __LINE__, ca));
+
if (ca) {
remove_client_alarms (ca);
if (ca->client) {
+ d(printf("%s:%d (free_client_alarms_cb) - Disconnecting Client \n",__FILE__, __LINE__));
+
g_signal_handlers_disconnect_matched (ca->client, G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL, ca);
g_object_unref (ca->client);
}
if (ca->query) {
+ d(printf("%s:%d (free_client_alarms_cb) - Disconnecting Query \n",__FILE__, __LINE__));
+
g_signal_handlers_disconnect_matched (ca->query, G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL, ca);
g_object_unref (ca->query);
@@ -1556,6 +1927,8 @@ alarm_queue_done (void)
/* All clients must be unregistered by now */
g_return_if_fail (g_hash_table_size (client_alarms_hash) == 0);
+ d(printf("%s:%d (alarm_queue_done)\n",__FILE__, __LINE__));
+
g_hash_table_foreach_remove (client_alarms_hash, (GHRFunc) free_client_alarms_cb, NULL);
g_hash_table_destroy (client_alarms_hash);
client_alarms_hash = NULL;
@@ -1575,9 +1948,9 @@ compare_ids (gpointer a, gpointer b)
id = a;
id1 = b;
-
if (id->uid != NULL && id1->uid != NULL) {
if (g_str_equal (id->uid, id1->uid)) {
+
if (id->rid && id1->rid)
return g_str_equal (id->rid, id1->rid);
else if (!(id->rid && id1->rid))
@@ -1587,24 +1960,23 @@ compare_ids (gpointer a, gpointer b)
return FALSE;
}
-/**
- * alarm_queue_add_client:
- * @client: A calendar client.
- *
- * Adds a calendar client to the alarm queueing system. Alarm trigger
- * notifications will be presented at the appropriate times. The client should
- * be removed with alarm_queue_remove_client() when receiving notifications
- * from it is no longer desired.
- *
- * A client can be added any number of times to the alarm queueing system,
- * but any single alarm trigger will only be presented once for a particular
- * client. The client must still be removed the same number of times from the
- * queueing system when it is no longer wanted.
- **/
-void
-alarm_queue_add_client (ECal *client)
+static guint
+hash_ids (gpointer a)
+{
+ ECalComponentId *id =a;
+
+ return g_str_hash (id->uid);
+}
+
+struct _alarm_client_msg {
+ ECal *client;
+};
+
+static void alarm_queue_add_async (EThread *e, AlarmMsg *msg, void *data)
{
ClientAlarms *ca;
+ struct _alarm_client_msg *list = msg->data;
+ ECal *client = list->client;
g_return_if_fail (alarm_queue_inited);
g_return_if_fail (client != NULL);
@@ -1612,18 +1984,21 @@ alarm_queue_add_client (ECal *client)
ca = lookup_client (client);
if (ca) {
+ /* We already have it. Unref the passed one*/
+ g_object_unref(client);
return;
}
+ d(printf("%s:%d (alarm_queue_add_async) - %d\n",__FILE__, __LINE__, client));
+
ca = g_new (ClientAlarms, 1);
ca->client = client;
ca->query = NULL;
- g_object_ref (ca->client);
g_hash_table_insert (client_alarms_hash, client, ca);
- ca->uid_alarms_hash = g_hash_table_new (g_direct_hash, (GEqualFunc) compare_ids);
+ ca->uid_alarms_hash = g_hash_table_new ((GHashFunc) hash_ids, (GEqualFunc) compare_ids);
if (e_cal_get_load_state (client) == E_CAL_LOAD_LOADED) {
load_alarms_for_today (ca);
@@ -1631,14 +2006,69 @@ alarm_queue_add_client (ECal *client)
g_signal_connect (client, "cal_opened",
G_CALLBACK (cal_opened_cb),
ca);
- }
+ }
+}
+
+/**
+ * alarm_queue_add_client:
+ * @client: A calendar client.
+ *
+ * Adds a calendar client to the alarm queueing system. Alarm trigger
+ * notifications will be presented at the appropriate times. The client should
+ * be removed with alarm_queue_remove_client() when receiving notifications
+ * from it is no longer desired.
+ *
+ * A client can be added any number of times to the alarm queueing system,
+ * but any single alarm trigger will only be presented once for a particular
+ * client. The client must still be removed the same number of times from the
+ * queueing system when it is no longer wanted.
+ **/
+void
+alarm_queue_add_client (ECal *client)
+{
+ AlarmMsg *msg;
+ struct _alarm_client_msg *list;
+
+ /* These two structures will be freed by the msg destroy function*/
+ msg = malloc (sizeof (AlarmMsg));
+ msg->receive_msg = alarm_queue_add_async;
+
+ list = malloc (sizeof (struct _alarm_client_msg));
+ list->client = client;
+ g_object_ref (client);
+ msg->data = list;
+
+ d(printf("%s:%d (alarm_queue_add_client) - Posting a task\n",__FILE__, __LINE__));
+ e_thread_put(alarm_operation_thread, (EMsg *)msg);
}
+/* Removes a component an its alarms */
static void
+remove_cqa (ClientAlarms *ca, ECalComponentId *id, CompQueuedAlarms *cqa)
+{
+
+ /* If a component is present, then it means we must have alarms queued
+ * for it.
+ */
+ g_assert (cqa->queued_alarms != NULL);
+
+ d(printf("%s:%d (remove_cqa) - removing %d alarms\n",__FILE__, __LINE__, g_list_length(cqa->queued_alarms)));
+ remove_alarms (cqa, TRUE);
+}
+
+static gboolean
remove_comp_by_id (gpointer key, gpointer value, gpointer userdata) {
ClientAlarms *ca = (ClientAlarms *)userdata;
- remove_comp (ca, (ECalComponentId *)key);
+
+ d(printf("%s:%d (remove_comp_by_id)\n",__FILE__, __LINE__));
+
+/* if (!g_hash_table_size (ca->uid_alarms_hash)) */
+/* return; */
+
+ remove_cqa (ca, (ECalComponentId *)key, (CompQueuedAlarms *) value);
+
+ return TRUE;
}
@@ -1646,7 +2076,10 @@ remove_comp_by_id (gpointer key, gpointer value, gpointer userdata) {
static void
remove_client_alarms (ClientAlarms *ca)
{
- g_hash_table_foreach (ca->uid_alarms_hash, (GHFunc)remove_comp_by_id, ca);
+ d(printf("%s:%d (remove_client_alarms) - size %d \n",__FILE__, __LINE__, g_hash_table_size (ca->uid_alarms_hash)));
+
+ g_hash_table_foreach_remove (ca->uid_alarms_hash, (GHFunc)remove_comp_by_id, ca);
+
/* The hash table should be empty now */
g_assert (g_hash_table_size (ca->uid_alarms_hash) == 0);
}
@@ -1657,10 +2090,12 @@ remove_client_alarms (ClientAlarms *ca)
*
* Removes a calendar client from the alarm queueing system.
**/
-void
-alarm_queue_remove_client (ECal *client)
+static void
+alarm_queue_remove_async (EThread *e, AlarmMsg *msg, void *data)
{
ClientAlarms *ca;
+ struct _alarm_client_msg *list = msg->data;
+ ECal *client = list->client;
g_return_if_fail (alarm_queue_inited);
g_return_if_fail (client != NULL);
@@ -1669,10 +2104,13 @@ alarm_queue_remove_client (ECal *client)
ca = lookup_client (client);
g_return_if_fail (ca != NULL);
+ d(printf("%s:%d (alarm_queue_remove_async) \n",__FILE__, __LINE__));
remove_client_alarms (ca);
/* Clean up */
if (ca->client) {
+ d(printf("%s:%d (alarm_queue_remove_async) - Disconnecting Client \n",__FILE__, __LINE__));
+
g_signal_handlers_disconnect_matched (ca->client, G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL, ca);
g_object_unref (ca->client);
@@ -1680,6 +2118,8 @@ alarm_queue_remove_client (ECal *client)
}
if (ca->query) {
+ d(printf("%s:%d (alarm_queue_remove_async) - Disconnecting Query \n",__FILE__, __LINE__));
+
g_signal_handlers_disconnect_matched (ca->query, G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL, ca);
g_object_unref (ca->query);
@@ -1694,6 +2134,24 @@ alarm_queue_remove_client (ECal *client)
g_hash_table_remove (client_alarms_hash, client);
}
+void
+alarm_queue_remove_client (ECal *client)
+{
+ AlarmMsg *msg;
+ struct _alarm_client_msg *list;
+
+ /* These two structures will be freed by the msg destroy function*/
+ msg = malloc (sizeof (AlarmMsg));
+ msg->receive_msg = alarm_queue_remove_async;
+
+ list = malloc (sizeof (struct _alarm_client_msg));
+ list->client = client;
+ msg->data = list;
+
+ d(printf("%s:%d (alarm_queue_remove_client) - Posting a task\n",__FILE__, __LINE__));
+ e_thread_put(alarm_operation_thread, (EMsg *)msg);
+}
+
/* Update non-time related variables for various structures on modification of an existing component
to be called only from query_objects_changed_cb */
static void
@@ -1712,7 +2170,7 @@ update_cqa (CompQueuedAlarms *cqa, ECalComponent *newcomp)
from = time_day_begin_with_zone (time (NULL), zone);
to = time_day_end_with_zone (time (NULL), zone);
-
+ d(printf("%s:%d (update_cqa) - Generating alarms between %s and %s\n",__FILE__, __LINE__, ctime(&from), ctime(&to)));
alarms = e_cal_util_generate_alarms_for_comp (newcomp, from, to, omit,
e_cal_resolve_tzid_cb, cqa->parent_client->client, zone);
@@ -1726,7 +2184,7 @@ update_cqa (CompQueuedAlarms *cqa, ECalComponent *newcomp)
else {
if (e_cal_component_get_alarm (oldcomp, check_auid)) { /* Need to update QueuedAlarms */
if (alarms == NULL) {
- g_warning ("No alarms found on the modified component\n");
+ d(printf("%s:%d (update_cqa) - No alarms found in the modified component\n",__FILE__, __LINE__));
break;
}
update_qa (alarms, qa);
@@ -1748,7 +2206,8 @@ update_qa (ECalComponentAlarms *alarms, QueuedAlarm *qa)
{
ECalComponentAlarmInstance *al_inst;
GSList *instance_list;
-
+
+ d(printf("%s:%d (update_qa)\n",__FILE__, __LINE__));
for (instance_list = alarms->alarms; instance_list; instance_list = instance_list->next) {
al_inst = instance_list->data;
if (al_inst->trigger == qa->orig_trigger) { /* FIXME if two or more alarm instances (audio, note) for same component have same trigger */
diff --git a/calendar/gui/alarm-notify/alarm.c b/calendar/gui/alarm-notify/alarm.c
index 1eb9d899b5..b360075d13 100644
--- a/calendar/gui/alarm-notify/alarm.c
+++ b/calendar/gui/alarm-notify/alarm.c
@@ -249,9 +249,6 @@ alarm_remove (gpointer alarm)
}
/* Reset the timeout */
-
- g_assert (timeout_id != 0);
-
if (!alarms) {
g_source_remove (timeout_id);
timeout_id = 0;