00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <glib.h>
00023 #include <glib-object.h>
00024 #include <libxml/parser.h>
00025 #include <libxml/tree.h>
00026 #include <string.h>
00027 #include "include/alarm_event.h"
00028 #include "initialize.h"
00029 #include "timer-loader.h"
00030 #include "xmlobjectfactory.h"
00031 #include "queue.h"
00032 #include "eventrecurring.h"
00033 #include "action.h"
00034 #include "actiondbus.h"
00035 #include "actionexec.h"
00036 #include "debug.h"
00037
00038 struct files_t {
00039 AlarmdQueue *queue;
00040 gchar *queue_file;
00041 gchar *next_time_file;
00042 gchar *next_mode_file;
00043 guint timer_id;
00044 };
00045
00046 static void _write_data(AlarmdQueue *queue, struct files_t *files);
00047 static gboolean _real_write_data(struct files_t *files);
00048 static void _free_data(struct files_t *files);
00049 static void _queue_changed(gpointer user_data);
00050
00051 AlarmdQueue *init_queue(const gchar *queue_file, const gchar *next_time_file,
00052 const gchar *next_mode_file)
00053 {
00054 AlarmdQueue *retval = NULL;
00055 xmlDoc *doc = NULL;
00056 xmlNode *root = NULL;
00057 struct files_t *files = NULL;
00058 GSList *timers = NULL;
00059 gboolean do_save = FALSE;
00060
00061 if (queue_file == NULL) {
00062 return NULL;
00063 }
00064
00065 retval = alarmd_queue_new();
00066 timers = load_timer_plugins(NULL);
00067
00068 g_object_set(retval, "timer", timers_get_plugin(timers, FALSE), NULL);
00069 g_object_set(retval, "timer_powerup", timers_get_plugin(timers, TRUE), NULL);
00070 g_object_set_data_full(G_OBJECT(retval), "timers", timers,
00071 (GDestroyNotify)close_timer_plugins);
00072
00073 DEBUG("%s", queue_file);
00074
00075 doc = xmlReadFile(queue_file, NULL, 0);
00076
00077 if (doc) {
00078 root = xmlDocGetRootElement(doc);
00079
00080 if (strcmp(root->name, "queue") == 0) {
00081 guint n_params, i;
00082 GParameter *param = elements_to_parameters(root,
00083 &n_params);
00084 gulong signal_id;
00085
00086 for (i = 0; i < n_params; i++) {
00087 g_object_set_property(G_OBJECT(retval), param[i].name, ¶m[i].value);
00088 }
00089 alarmd_gparameterv_free(param, n_params);
00090 signal_id = g_signal_connect_swapped(retval, "changed",
00091 G_CALLBACK(_queue_changed),
00092 &do_save);
00093
00094 for (root = root->children; root != NULL; root = root->next) {
00095 AlarmdObject *object = NULL;
00096 if (root->type != XML_ELEMENT_NODE) {
00097 continue;
00098 }
00099 object = object_factory(root);
00100
00101 if (!object) continue;
00102
00103 if (ALARMD_IS_EVENT(object)) {
00104 alarmd_queue_add_event(retval, ALARMD_EVENT(object));
00105 }
00106 g_object_unref(object);
00107 }
00108
00109 g_signal_handler_disconnect(retval, signal_id);
00110 }
00111
00112 xmlFreeDoc(doc);
00113 xmlCleanupParser();
00114 }
00115
00116 DEBUG("Connecting...");
00117 files = g_new(struct files_t, 1);
00118 files->queue = retval;
00119 files->queue_file = g_strdup(queue_file);
00120 files->next_time_file = g_strdup(next_time_file);
00121 files->next_mode_file = g_strdup(next_mode_file);
00122 files->timer_id = 0;
00123
00124 if (do_save) {
00125 _write_data(retval, files);
00126 }
00127 g_signal_connect_data(retval, "changed", (GCallback)_write_data, files, (GClosureNotify)_free_data, G_CONNECT_AFTER);
00128
00129 timer_plugins_set_startup(timers, FALSE);
00130
00131 return retval;
00132 }
00133
00134 void alarmd_type_init(void)
00135 {
00136 (void)ALARMD_TYPE_EVENT_RECURRING;
00137 (void)ALARMD_TYPE_ACTION;
00138 (void)ALARMD_TYPE_ACTION_DBUS;
00139 (void)ALARMD_TYPE_ACTION_EXEC;
00140 }
00141
00142 static void _write_data(AlarmdQueue *queue, struct files_t *files)
00143 {
00144 ENTER_FUNC;
00145
00146 (void)queue;
00147
00148 if (files->timer_id == 0) {
00149 files->timer_id = g_idle_add((GSourceFunc)_real_write_data,
00150 files);
00151 }
00152 LEAVE_FUNC;
00153 }
00154
00155 static gboolean _real_write_data(struct files_t *files)
00156 {
00157 ENTER_FUNC;
00158 xmlDoc *doc = xmlNewDoc("1.0");
00159 xmlNode *root_node = alarmd_object_to_xml(ALARMD_OBJECT(files->queue));
00160 glong *events = NULL;
00161 guint n_events = 0;
00162 FILE *write = NULL;
00163 gint flags = 0;
00164 time_t event_time = 0;
00165 const char *mode = "n/a";
00166 gchar *old_contents = NULL;
00167 gchar *new_contents = NULL;
00168
00169 files->timer_id = 0;
00170
00171 xmlDocSetRootElement(doc, root_node);
00172
00173 xmlSaveFormatFileEnc(files->queue_file, doc, "UTF-8", 1);
00174
00175 xmlFreeDoc(doc);
00176 xmlCleanupParser();
00177
00178 events = alarmd_queue_query_events(files->queue, 0, G_MAXINT64,
00179 ALARM_EVENT_BOOT, ALARM_EVENT_BOOT,
00180 &n_events);
00181
00182 if (n_events > 0) {
00183 AlarmdEvent *event = alarmd_queue_get_event(files->queue,
00184 events[0]);
00185 event_time = alarmd_event_get_time(event);
00186 AlarmdAction *action = NULL;
00187 g_object_get(event, "action", &action, NULL);
00188 if (action) {
00189 g_object_get(action, "flags", &flags, NULL);
00190 g_object_unref(action);
00191 }
00192 mode = (flags & ALARM_EVENT_ACTDEAD) ? "actdead" : "powerup";
00193 g_free(events);
00194 }
00195
00196
00197 g_file_get_contents(files->next_time_file,
00198 &old_contents,
00199 NULL,
00200 NULL);
00201 new_contents = g_strdup_printf("%ld", event_time);
00202 if (!(old_contents && new_contents &&
00203 strcmp(g_strchomp(old_contents),
00204 new_contents) == 0)) {
00205 write = fopen(files->next_time_file, "w");
00206 if (write) {
00207 fprintf(write, "%s\n", new_contents);
00208 fclose(write);
00209 }
00210 }
00211 g_free(new_contents);
00212 g_free(old_contents);
00213 old_contents = NULL;
00214 g_file_get_contents(files->next_mode_file,
00215 &old_contents,
00216 NULL,
00217 NULL);
00218
00219 if (!(old_contents && mode &&
00220 strcmp(g_strchomp(old_contents),
00221 mode) == 0)) {
00222 write = fopen(files->next_mode_file, "w");
00223 if (write) {
00224 fprintf(write, "%s\n", mode);
00225 fclose(write);
00226 }
00227 }
00228
00229 LEAVE_FUNC;
00230 return FALSE;
00231 }
00232
00233 static void _free_data(struct files_t *files)
00234 {
00235 g_free(files->queue_file);
00236 g_free(files->next_time_file);
00237 g_free(files->next_mode_file);
00238 g_free(files);
00239 }
00240
00241 static void _queue_changed(gpointer user_data)
00242 {
00243 gboolean *changed = user_data;
00244 *changed = TRUE;
00245 }