Main Page | Data Structures | File List | Data Fields | Globals

rpc-systemui.c

Go to the documentation of this file.
00001 /**
00002  * This file is part of alarmd
00003  *
00004  * Contact Person: David Weinehall <david.weinehall@nokia.com>
00005  *
00006  * Copyright (C) 2006 Nokia Corporation
00007  * alarmd and libalarm are free software; you can redistribute them
00008  * and/or modify them under the terms of the GNU Lesser General Public
00009  * License version 2.1 as published by the Free Software Foundation.
00010  *
00011  * alarmd and libalarm are distributed in the hope that they will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this software; if not, write to the Free
00018  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00019  * 02110-1301 USA
00020  */
00021 
00022 #include <dbus/dbus.h>
00023 #include <glib/gthread.h>
00024 #include <glib/gslist.h>
00025 #include <glib/gstrfuncs.h>
00026 #include <systemui/dbus-names.h>
00027 #include <systemui/alarm_dialog-dbus-names.h>
00028 #include <systemui/actingdead-dbus-names.h>
00029 #include <string.h>
00030 
00031 #include "debug.h"
00032 #include "include/alarm_dbus.h"
00033 #include "rpc-dbus.h"
00034 #include "rpc-systemui.h"
00035 #include "rpc-mce.h"
00036 
00037 #define ALARMD_ACTION_DBUS_METHOD "action_dbus_return"
00038 
00039 /* Must be in sync with GTK_RESPONSE_ACCEPT. */
00040 enum response {
00041         RESPONSE_ACCEPT = -3
00042 };
00043 
00044 enum flag {
00045         FLAG_CAN_SNOOZE = 1 << 0,
00046         FLAG_POWERUP = 1 << 1,
00047 };
00048 
00049 typedef struct _SystemuiAlarmdDialog SystemuiAlarmdDialog;
00050 struct _SystemuiAlarmdDialog {
00051         time_t alarm_time;
00052         gchar *title;
00053         gchar *message;
00054         gchar *sound;
00055         gchar *icon;
00056         gpointer user_data;
00057         SystemuiAlarmdDialogCallback cb;
00058         enum flag flags;
00059         gboolean status;
00060         guint count;
00061         guint timer_id;
00062 };
00063 
00064 static GStaticMutex queue_mutex = G_STATIC_MUTEX_INIT;
00065 static GSList *dialog_queue = NULL;
00066 static DBusConnection *system_bus = NULL;
00067 static gboolean mce_dialog_visible = FALSE;
00068 static void _dialog_free(SystemuiAlarmdDialog *dialog);
00069 
00070 static gboolean _resend_message(gpointer user_data);
00071 static DBusConnection *_dbus_connect(void);
00072 static void _dbus_disconnect(DBusConnection *conn);
00073 static void _queue_changed(void);
00074 static void _close_dialog(void);
00075 static gint _queue_compare(gconstpointer v1, gconstpointer v2);
00076 static gboolean _dialog_do_cb(gpointer data);
00077 static DBusHandlerResult _dialog_ackd(DBusConnection *connection,
00078                 DBusMessage *message,
00079                 void *user_data);
00080 static void _systemui_dialog_queue_append(time_t alarm_time, const gchar *title, const gchar *message, const gchar *sound, const gchar *icon, enum flag flags, SystemuiAlarmdDialogCallback cb, gpointer user_data);
00081 
00082 void systemui_powerup_dialog_queue_append(SystemuiAlarmdDialogCallback cb, gpointer user_data)
00083 {
00084         _systemui_dialog_queue_append(0, NULL, NULL, NULL, NULL, FLAG_POWERUP, cb, user_data);
00085 }
00086 
00087 void systemui_alarm_dialog_queue_append(time_t alarm_time, const gchar *title, const gchar *message, const gchar *sound, const gchar *icon, gboolean can_snooze, SystemuiAlarmdDialogCallback cb, gpointer user_data)
00088 {
00089         _systemui_dialog_queue_append(alarm_time, title, message, sound, icon, can_snooze ? FLAG_CAN_SNOOZE : 0, cb, user_data);
00090 }
00091 
00092 void systemui_powerup_dialog_queue_remove(SystemuiAlarmdDialogCallback cb, gpointer user_data)
00093 {
00094         systemui_alarm_dialog_queue_remove(0, NULL, NULL, NULL, NULL, cb, user_data);
00095 }
00096 
00097 void systemui_alarm_dialog_queue_remove(time_t alarm_time, const gchar *title, const gchar *message, const gchar *sound, const gchar *icon, SystemuiAlarmdDialogCallback cb, gpointer user_data)
00098 {
00099         SystemuiAlarmdDialog dlg = {
00100                 .alarm_time = alarm_time,
00101                 .title = (gchar *)title,
00102                 .message = (gchar *)message,
00103                 .sound = (gchar *)sound,
00104                 .icon = (gchar *)icon,
00105                 .user_data = user_data,
00106                 .cb = cb,
00107                 .flags = 0
00108         };
00109         GSList *iter = NULL;
00110         SystemuiAlarmdDialog *remove = NULL;
00111         ENTER_FUNC;
00112 
00113         g_static_mutex_lock(&queue_mutex);
00114         iter = g_slist_find_custom(dialog_queue, &dlg, _queue_compare);
00115         if (iter) {
00116                 remove = (SystemuiAlarmdDialog *)iter->data;
00117                 if (iter == dialog_queue && system_bus) {
00118                         _close_dialog();
00119                 }
00120         } else {
00121                 g_static_mutex_unlock(&queue_mutex);
00122                 LEAVE_FUNC;
00123                 return;
00124         }
00125         dialog_queue = g_slist_delete_link(dialog_queue, iter);
00126         g_static_mutex_unlock(&queue_mutex);
00127 
00128         if (remove->timer_id) {
00129                 g_source_remove(remove->timer_id);
00130                 remove->timer_id = 0;
00131         }
00132         _dialog_free(remove);
00133         _queue_changed();
00134         LEAVE_FUNC;
00135 }
00136 
00137 static gint _queue_compare(gconstpointer v1, gconstpointer v2)
00138 {
00139         SystemuiAlarmdDialog *lval = (SystemuiAlarmdDialog *)v1;
00140         SystemuiAlarmdDialog *rval = (SystemuiAlarmdDialog *)v2;
00141 
00142         ENTER_FUNC;
00143         gint retval;
00144 
00145         if ((retval = lval->alarm_time - rval->alarm_time)) {
00146                 LEAVE_FUNC;
00147                 return retval;
00148         }
00149         if (lval->title && rval->title && (retval = strcmp(lval->title, rval->title))) {
00150                 LEAVE_FUNC;
00151                 return retval;
00152         }
00153         if (lval->message && rval->message && (retval = strcmp(lval->message, rval->message))) {
00154                 LEAVE_FUNC;
00155                 return retval;
00156         }
00157         if (lval->sound && rval->sound && (retval = strcmp(lval->sound, rval->sound))) {
00158                 LEAVE_FUNC;
00159                 return retval;
00160         }
00161         if (lval->icon && rval->icon && (retval = strcmp(lval->icon, rval->icon))) {
00162                 LEAVE_FUNC;
00163                 return retval;
00164         }
00165         if ((retval = (gint)lval->user_data - (gint)rval->user_data)) {
00166                 LEAVE_FUNC;
00167                 return retval;
00168         }
00169         LEAVE_FUNC;
00170         return lval->cb != rval->cb;
00171 }
00172 
00173 static void _dialog_free(SystemuiAlarmdDialog *dialog)
00174 {
00175         ENTER_FUNC;
00176         if (!dialog) {
00177                 LEAVE_FUNC;
00178                 return;
00179         }
00180 
00181         if (dialog->title) {
00182                 g_free(dialog->title);
00183         }
00184         if (dialog->message) {
00185                 g_free(dialog->message);
00186         }
00187         if (dialog->sound) {
00188                 g_free(dialog->sound);
00189         }
00190         if (dialog->icon) {
00191                 g_free(dialog->icon);
00192         }
00193         g_free(dialog);
00194         LEAVE_FUNC;
00195 }
00196 
00197 static void _queue_changed(void)
00198 {
00199         ENTER_FUNC;
00200         g_static_mutex_lock(&queue_mutex);
00201         if (dialog_queue && !system_bus) {
00202                 SystemuiAlarmdDialog *dlg = (SystemuiAlarmdDialog *)dialog_queue->data;
00203                 const gchar *my_service = ALARMD_SERVICE;
00204                 const gchar *my_path = ALARMD_PATH;
00205                 const gchar *my_interface = ALARMD_INTERFACE;
00206                 const gchar *my_method = ALARMD_ACTION_DBUS_METHOD;
00207                 DBusMessage *reply = NULL;
00208                 system_bus = _dbus_connect();
00209                 dbus_int32_t retval = 0;
00210                 if (dlg->flags & FLAG_POWERUP) {
00211                         const int dialog_type = ALARM_MODE_SWITCHON;
00212 
00213                         dbus_do_call(system_bus,
00214                                         &reply,
00215                                         FALSE,
00216                                         SYSTEMUI_SERVICE,
00217                                         SYSTEMUI_REQUEST_PATH,
00218                                         SYSTEMUI_REQUEST_IF,
00219                                         SYSTEMUI_ALARM_OPEN_REQ,
00220                                         DBUS_TYPE_STRING, &my_service,
00221                                         DBUS_TYPE_STRING, &my_path,
00222                                         DBUS_TYPE_STRING, &my_interface,
00223                                         DBUS_TYPE_STRING, &my_method,
00224                                         DBUS_TYPE_UINT32, &dialog_type,
00225                                         DBUS_TYPE_INVALID);
00226                 } else {
00227                         const gchar *my_sound = dlg->sound == NULL ? "" : dlg->sound;
00228                         const gchar *my_icon = dlg->icon == NULL ? "" : dlg->icon;
00229                         const gchar *my_message = dlg->message == NULL ? "" : dlg->message;
00230                         const gchar *my_title = dlg->title == NULL ? "" : dlg->title;
00231                         const int dialog_type = (dlg->flags & FLAG_CAN_SNOOZE) ? ALARM_MODE_NORMAL : ALARM_MODE_NOSNOOZE;
00232 
00233                         DEBUG("sound = %s, icon = %s, message = %s", my_sound, my_icon, my_message);
00234                         dbus_do_call(system_bus,
00235                                         &reply,
00236                                         FALSE,
00237                                         SYSTEMUI_SERVICE,
00238                                         SYSTEMUI_REQUEST_PATH,
00239                                         SYSTEMUI_REQUEST_IF,
00240                                         SYSTEMUI_ALARM_OPEN_REQ,
00241                                         DBUS_TYPE_STRING, &my_service,
00242                                         DBUS_TYPE_STRING, &my_path,
00243                                         DBUS_TYPE_STRING, &my_interface,
00244                                         DBUS_TYPE_STRING, &my_method,
00245                                         DBUS_TYPE_UINT32, &dialog_type,
00246                                         DBUS_TYPE_STRING, &my_message,
00247                                         DBUS_TYPE_STRING, &my_sound,
00248                                         DBUS_TYPE_STRING, &my_icon,
00249                                         DBUS_TYPE_STRING, &my_title,
00250                                         DBUS_TYPE_UINT32, &dlg->alarm_time,
00251                                         DBUS_TYPE_INVALID);
00252                         dlg->timer_id = g_timeout_add(300000, _resend_message,
00253                                         dlg);
00254                 }
00255 
00256                 if (reply) {
00257                         dbus_message_get_args(reply, NULL, DBUS_TYPE_INT32, &retval, DBUS_TYPE_INVALID);
00258                         dbus_message_unref(reply);
00259                         reply = NULL;
00260                 }
00261                 if (retval != RESPONSE_ACCEPT) {
00262                         if (dlg->timer_id) {
00263                                 g_source_remove(dlg->timer_id);
00264                                 dlg->timer_id = 0;
00265                         }
00266                         _dbus_disconnect(system_bus);
00267                         system_bus = NULL;
00268                 }
00269         }
00270         g_static_mutex_unlock(&queue_mutex);
00271         LEAVE_FUNC;
00272 }
00273 
00274 static void _close_dialog(void)
00275 {
00276         ENTER_FUNC;
00277         g_static_mutex_lock(&queue_mutex);
00278         if (system_bus) {
00279                 dbus_do_call(system_bus,
00280                                 NULL,
00281                                 FALSE,
00282                                 SYSTEMUI_SERVICE,
00283                                 SYSTEMUI_REQUEST_PATH,
00284                                 SYSTEMUI_REQUEST_IF,
00285                                 SYSTEMUI_ALARM_CLOSE_REQ,
00286                                 DBUS_TYPE_INVALID);
00287                 _dbus_disconnect(system_bus);
00288                 system_bus = NULL;
00289         }
00290         g_static_mutex_unlock(&queue_mutex);
00291         LEAVE_FUNC;
00292 }
00293 
00294 static DBusConnection *_dbus_connect(void)
00295 {
00296         ENTER_FUNC;
00297         DBusConnection *retval = get_dbus_connection(DBUS_BUS_SYSTEM);
00298 
00299         if (retval) {
00300                 int status = dbus_bus_request_name(retval, ALARMD_SERVICE, 0, NULL);
00301                 if (!(status == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER || DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER))
00302                 {
00303                         dbus_connection_unref(retval);
00304                         LEAVE_FUNC;
00305                         return NULL;
00306                 }
00307                 dbus_connection_add_filter(retval, _dialog_ackd, NULL, NULL);
00308         }
00309 
00310         LEAVE_FUNC;
00311         return retval;
00312 }
00313 
00314 static void _dbus_disconnect(DBusConnection *conn)
00315 {
00316         ENTER_FUNC;
00317         if (conn) {
00318                 dbus_connection_remove_filter(conn, _dialog_ackd, NULL);
00319                 dbus_connection_unref(conn);
00320         }
00321         LEAVE_FUNC;
00322 }
00323 
00324 static gboolean _dialog_do_cb(gpointer data)
00325 {
00326         SystemuiAlarmdDialog *dlg = data;
00327         if (dlg->cb) {
00328                 dlg->cb(dlg->user_data, dlg->status);
00329         }
00330 
00331         return FALSE;
00332 }
00333 
00334 static DBusHandlerResult _dialog_ackd(DBusConnection *connection,
00335                 DBusMessage *message,
00336                 void *user_data)
00337 {
00338         ENTER_FUNC;
00339         (void)connection;
00340         (void)user_data;
00341 
00342         if (dbus_message_is_method_call(message,
00343                                 ALARMD_INTERFACE,
00344                                 ALARMD_ACTION_DBUS_METHOD)) {
00345                 dbus_int32_t retval = 0;
00346                 SystemuiAlarmdDialog *dlg = NULL;
00347 
00348                 dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &retval, DBUS_TYPE_INVALID);
00349 
00350                 g_static_mutex_lock(&queue_mutex);
00351                 if (dialog_queue) {
00352                         dlg = (SystemuiAlarmdDialog *)dialog_queue->data;
00353 
00354                         DEBUG("Deleting link from queue.");
00355                         dialog_queue = g_slist_delete_link(dialog_queue, dialog_queue);
00356                         DEBUG("Queue now %p", dialog_queue);
00357                 }
00358                 _dbus_disconnect(system_bus);
00359                 system_bus = NULL;
00360                 g_static_mutex_unlock(&queue_mutex);
00361 
00362                 dlg->status = (retval == ALARM_DIALOG_RESPONSE_SNOOZE
00363                         || retval == ALARM_DIALOG_RESPONSE_POWERUP);
00364                 if (dlg->timer_id) {
00365                         g_source_remove(dlg->timer_id);
00366                         dlg->timer_id = 0;
00367                 }
00368 
00369                 _queue_changed();
00370 
00371                 g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, 
00372                                 _dialog_do_cb, 
00373                                 dlg, (GDestroyNotify)_dialog_free);
00374 
00375                 LEAVE_FUNC;
00376                 return DBUS_HANDLER_RESULT_HANDLED;
00377         }
00378 
00379         LEAVE_FUNC;
00380         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00381 }
00382 
00383 static void _systemui_dialog_queue_append(time_t alarm_time, const gchar *title, const gchar *message, const gchar *sound, const gchar *icon, enum flag flags, SystemuiAlarmdDialogCallback cb, gpointer user_data)
00384 {
00385         SystemuiAlarmdDialog *new_dialog = g_new0(SystemuiAlarmdDialog, 1);
00386         ENTER_FUNC;
00387         new_dialog->alarm_time = alarm_time;
00388         new_dialog->title = g_strdup(title);
00389         new_dialog->message = g_strdup(message);
00390         new_dialog->sound = g_strdup(sound);
00391         new_dialog->icon = g_strdup(icon);
00392         new_dialog->flags = flags;
00393         new_dialog->cb = cb;
00394         new_dialog->user_data = user_data;
00395         g_static_mutex_lock(&queue_mutex);
00396         dialog_queue = g_slist_append(dialog_queue, new_dialog);
00397         g_static_mutex_unlock(&queue_mutex);
00398         _queue_changed();
00399         LEAVE_FUNC;
00400 }
00401 
00402 void update_mce_alarm_visibility(void)
00403 {
00404         DBusConnection *conn;
00405 
00406         conn = get_dbus_connection(DBUS_BUS_SYSTEM);
00407         g_static_mutex_lock(&queue_mutex);
00408         if ((dialog_queue && mce_dialog_visible)) {
00409                 g_static_mutex_unlock(&queue_mutex);
00410                 dbus_connection_unref(conn);
00411                 return;
00412         }
00413         mce_dialog_visible = dialog_queue ? TRUE : FALSE;
00414         mce_set_alarm_visibility(conn, mce_dialog_visible);
00415         g_static_mutex_unlock(&queue_mutex);
00416         dbus_connection_unref(conn);
00417 }
00418 
00419 void systemui_ack_all_dialogs(void)
00420 {
00421         GSList *my_list;
00422 
00423         ENTER_FUNC;
00424         g_static_mutex_lock(&queue_mutex);
00425         my_list = dialog_queue;
00426         dialog_queue = NULL;
00427         g_static_mutex_unlock(&queue_mutex);
00428 
00429         _close_dialog();
00430 
00431         while (my_list) {
00432                 SystemuiAlarmdDialog *dlg = my_list->data;
00433                 if (dlg->timer_id) {
00434                         g_source_remove(dlg->timer_id);
00435                         dlg->timer_id = 0;
00436                 }
00437                 dlg->cb(dlg->user_data, FALSE);
00438                 g_free(dlg);
00439 
00440                 my_list = g_slist_delete_link(my_list, my_list);
00441         }
00442 
00443         LEAVE_FUNC;
00444 }
00445 
00446 static gboolean _resend_message(gpointer user_data)
00447 {
00448         SystemuiAlarmdDialog *dlg = user_data;
00449 
00450         const gchar *my_service = ALARMD_SERVICE;
00451         const gchar *my_path = ALARMD_PATH;
00452         const gchar *my_interface = ALARMD_INTERFACE;
00453         const gchar *my_method = ALARMD_ACTION_DBUS_METHOD;
00454         const gchar *my_sound = dlg->sound == NULL ? "" : dlg->sound;
00455         const gchar *my_icon = dlg->icon == NULL ? "" : dlg->icon;
00456         const gchar *my_message = dlg->message == NULL ? "" : dlg->message;
00457         const gchar *my_title = dlg->title == NULL ? "" : dlg->title;
00458         const int dialog_type = (dlg->flags & FLAG_CAN_SNOOZE) ? ALARM_MODE_NORMAL : ALARM_MODE_NOSNOOZE;
00459         ENTER_FUNC;
00460 
00461         DEBUG("sound = %s, icon = %s, message = %s", my_sound, my_icon, my_message);
00462         g_static_mutex_unlock(&queue_mutex);
00463         if (system_bus) {
00464                 dbus_do_call(system_bus,
00465                                 NULL,
00466                                 FALSE,
00467                                 SYSTEMUI_SERVICE,
00468                                 SYSTEMUI_REQUEST_PATH,
00469                                 SYSTEMUI_REQUEST_IF,
00470                                 SYSTEMUI_ALARM_OPEN_REQ,
00471                                 DBUS_TYPE_STRING, &my_service,
00472                                 DBUS_TYPE_STRING, &my_path,
00473                                 DBUS_TYPE_STRING, &my_interface,
00474                                 DBUS_TYPE_STRING, &my_method,
00475                                 DBUS_TYPE_UINT32, &dialog_type,
00476                                 DBUS_TYPE_STRING, &my_message,
00477                                 DBUS_TYPE_STRING, &my_sound,
00478                                 DBUS_TYPE_STRING, &my_icon,
00479                                 DBUS_TYPE_STRING, &my_title,
00480                                 DBUS_TYPE_UINT32, &dlg->alarm_time,
00481                                 DBUS_TYPE_INVALID);
00482         }
00483         g_static_mutex_unlock(&queue_mutex);
00484         dlg->count++;
00485 
00486         if (dlg->count < 3) {
00487                 LEAVE_FUNC;
00488                 return TRUE;
00489         }
00490         dlg->timer_id = 0;
00491         LEAVE_FUNC;
00492         return FALSE;
00493 }
00494 
00495 gboolean systemui_is_acting_dead(void)
00496 {
00497         DBusMessage *reply = NULL;
00498         gboolean retval = FALSE;
00499         DBusConnection *system_bus;
00500 
00501         ENTER_FUNC;
00502         system_bus = get_dbus_connection(DBUS_BUS_SYSTEM);
00503         dbus_do_call(system_bus,
00504                         &reply,
00505                         FALSE,
00506                         SYSTEMUI_SERVICE,
00507                         SYSTEMUI_REQUEST_PATH,
00508                         SYSTEMUI_REQUEST_IF,
00509                         SYSTEMUI_ACTINGDEAD_GETSTATE_REQ,
00510                         DBUS_TYPE_INVALID);
00511         dbus_connection_unref(system_bus);
00512 
00513         if (reply) {
00514                 dbus_message_get_args(reply, NULL,
00515                                 DBUS_TYPE_BOOLEAN, &retval,
00516                                 DBUS_TYPE_INVALID);
00517                 dbus_message_unref(reply);
00518         }
00519 
00520         LEAVE_FUNC;
00521         return retval;
00522 }

Generated on Thu Dec 21 18:23:30 2006 for Alarmd by  doxygen 1.4.2