busy.c

Go to the documentation of this file.
00001 /*
00002  * File Name: busy.c
00003  */
00004 
00005 /*
00006  * This file is part of sysd.
00007  *
00008  * sysd is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * sysd is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2009 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 //----------------------------------------------------------------------------
00028 // Include Files
00029 //----------------------------------------------------------------------------
00030 
00031 // system include files, between < >
00032 #include <glib.h>
00033 #include <stdio.h>
00034 
00035 // ereader include files, between < >
00036 
00037 // local include files, between " "
00038 #include "log.h"
00039 #include "ipc.h"
00040 
00041 #define UNUSED(x) (void)(x)
00042 
00043 
00044 //----------------------------------------------------------------------------
00045 // Type Declarations
00046 //----------------------------------------------------------------------------
00047  
00048 typedef struct
00049 {
00050     gint sender;
00051     GPid pid;
00052     gint fg_count;
00053     gint bg_count;
00054 } busy_count_t;
00055 
00056 
00057 //----------------------------------------------------------------------------
00058 // Global Constants
00059 //----------------------------------------------------------------------------
00060 
00061 enum 
00062 {
00063     BACKGROUND,
00064     FOREGROUND
00065 };
00066 
00067 const gint dialog_delay  = 1000; // ms
00068 const gint busyled_delay = 1000; // ms
00069 
00070 
00071 //----------------------------------------------------------------------------
00072 // Static Variables
00073 //----------------------------------------------------------------------------
00074 
00075 static GSList       *g_app_counters     = NULL;
00076 static gchar        *g_message          = NULL;
00077 static guint        g_dialog_source     = 0;
00078 static guint        g_background_count  = 0;
00079 static guint        g_foreground_count  = 0;
00080 
00081 
00082 //============================================================================
00083 // Local Function Definition
00084 //============================================================================
00085 
00086 static void          count_ref              (gint sender, gint mode);
00087 static void          count_unref            (gint sender, gint mode);
00088 static void          count_set_pid          (gint sender, GPid pid);
00089 static void          count_remove_pid       (GPid pid);
00090 static gint          ref_count              (gint mode);
00091 static void          update                 (void);
00092 static void          show_dialog            (gboolean on);
00093 static gboolean      delay_dialog_cb        (gpointer data);
00094 
00095 
00096 //============================================================================
00097 // Functions Implementation
00098 //============================================================================
00099 
00100 gboolean busy_add_background(gint sender)
00101 {
00102 //    LOGPRINTF("entry");
00103     
00104     count_ref(sender, BACKGROUND);
00105     
00106     return TRUE;
00107 }
00108 
00109 
00110 gboolean busy_remove_background(gint sender)
00111 {
00112 //    LOGPRINTF("entry");
00113     
00114     count_unref(sender, BACKGROUND);
00115 
00116     return TRUE;
00117 }
00118 
00119 
00120 gboolean busy_add_foreground(gint sender, enum busy_dialog dialog_mode, const char *message)
00121 {
00122     LOGPRINTF("entry");
00123 
00124     count_ref(sender, FOREGROUND);
00125 
00126     // replace message
00127     if (g_message)
00128     {
00129         g_free(g_message);
00130     }
00131     
00132     if (message)
00133     {
00134         g_message = g_strdup(message);
00135     }
00136     else
00137     {
00138         g_message = NULL;
00139     }
00140     
00141     if (dialog_mode == BUSY_DIALOG_DIRECT)
00142     {
00143         show_dialog(TRUE);
00144     }
00145     else if (dialog_mode == BUSY_DIALOG_DELAYED)
00146     {
00147         if (g_dialog_source == 0)
00148         {
00149             LOGPRINTF("delay %d ms before show busy DIALOG", dialog_delay);
00150             g_dialog_source = g_timeout_add(dialog_delay, delay_dialog_cb, NULL);
00151         }
00152         else
00153         {
00154             LOGPRINTF("already waiting for busy DIALOG");
00155         }
00156     }
00157 
00158     return TRUE;
00159 }
00160 
00161 
00162 gboolean busy_remove_foreground(gint sender)
00163 {
00164 //    LOGPRINTF("entry");
00165 
00166     count_unref(sender, FOREGROUND);
00167     
00168     return TRUE;
00169 }
00170 
00171 
00172 gboolean is_busy_foreground()
00173 {
00174     if (g_foreground_count > 0)
00175     {
00176         return TRUE;
00177     }
00178     return FALSE;
00179 }
00180 
00181 
00182 gboolean is_busy_background()
00183 {
00184     if (g_background_count > 0)
00185     {
00186         return TRUE;
00187     }
00188     return FALSE;
00189 }
00190 
00191 
00192 void busy_set_pid(gint sender, GPid pid)
00193 {
00194 //    LOGPRINTF("entry, sender [%d] pid [%d]", sender, pid);
00195     
00196     count_set_pid(sender, pid);
00197 }
00198 
00199 
00200 void busy_reset_pid(GPid pid)
00201 {
00202 //    LOGPRINTF("entry, pid [%d]", pid);
00203     
00204     count_remove_pid(pid);
00205 }
00206 
00207 
00208 //============================================================================
00209 // Local Function Implementation
00210 //============================================================================
00211 
00212 static void show_dialog(gboolean on)
00213 {
00214     static gboolean is_shown = FALSE;
00215     
00216     LOGPRINTF("entry: on [%d] is_shown [%d]", on, is_shown);
00217 
00218     if (on && !is_shown)
00219     {
00220         LOGPRINTF("show busy DIALOG!");
00221         ipc_show_busy(TRUE, g_message);
00222         is_shown = TRUE;
00223     }
00224     else if (!on && is_shown)
00225     {
00226         LOGPRINTF("hide busy DIALOG!");
00227         ipc_show_busy(FALSE, NULL);
00228         is_shown = FALSE;
00229     }
00230 }
00231 
00232 
00233 static gboolean delay_dialog_cb(gpointer data)
00234 {
00235     UNUSED(data);
00236     LOGPRINTF("entry");
00237 
00238     if (ref_count(FOREGROUND) > 0)
00239     {
00240         show_dialog(TRUE);
00241     }
00242     else
00243     {
00244         LOGPRINTF("busy DIALOG not needed anymore");
00245     }
00246     
00247     g_dialog_source = 0;
00248     // remove source
00249     return FALSE;
00250 }
00251 
00252 
00253 static void count_set_pid(gint sender, GPid pid)
00254 {
00255     LOGPRINTF("entry sender [%d] pid [%d]", sender, pid);
00256     
00257     GSList *busy_ptr = g_app_counters;
00258     busy_count_t *cur_busy = NULL;
00259 
00260     // get application from list
00261     while (busy_ptr)
00262     {
00263         cur_busy = (busy_count_t *) busy_ptr->data;
00264 
00265         if (cur_busy->sender == sender)
00266         {
00267             cur_busy->pid = pid;
00268             return;
00269         }
00270         busy_ptr = busy_ptr->next;
00271     }
00272     
00273     // application not yet in list, add now
00274     busy_count_t *busy = g_new0 (busy_count_t, 1);
00275     if (!busy)
00276     {
00277         ERRORPRINTF("mem alloc failed");
00278         return;
00279     }
00280     
00281     busy->sender = sender;
00282     busy->pid = pid;
00283     
00284     g_app_counters = g_slist_prepend(g_app_counters, busy);
00285     
00286     return;
00287 }
00288 
00289 
00290 static void count_ref(gint sender, gint mode)
00291 {
00292     LOGPRINTF("entry sender [%d], %s", sender, mode == 0 ? "BACKGROUND" : "FOREGROUND");
00293     
00294     GSList *busy_ptr = g_app_counters;
00295     busy_count_t *cur_busy = NULL;
00296 
00297     // get application from list
00298     while (busy_ptr)
00299     {
00300         cur_busy = (busy_count_t *) busy_ptr->data;
00301 
00302         if (cur_busy->sender == sender)
00303         {
00304             // increment reference count
00305             if (mode == FOREGROUND)
00306             {
00307                 cur_busy->fg_count++;
00308             }
00309             cur_busy->bg_count++;
00310             LOGPRINTF("sender [%d] bg_count [%d] fg_count [%d]", sender, cur_busy->bg_count, cur_busy->fg_count);
00311 
00312             update();
00313             return;
00314         }
00315         busy_ptr = busy_ptr->next;
00316     }
00317     
00318     // application not yet in list, add now
00319     busy_count_t *busy = g_new0 (busy_count_t, 1);
00320     if (!busy)
00321     {
00322         ERRORPRINTF("mem alloc failed");
00323         return;
00324     }
00325     
00326     busy->sender = sender;
00327     if (mode == FOREGROUND)
00328     {
00329         busy->fg_count = 1;
00330     }
00331     busy->bg_count = 1;
00332     
00333     g_app_counters = g_slist_prepend(g_app_counters, busy);
00334     
00335     LOGPRINTF("sender [%d] bg_count [%d] fg_count [%d]", sender, busy->bg_count, busy->fg_count);
00336     update();
00337     return;
00338 }
00339 
00340 
00341 static void count_unref(gint sender, gint mode)
00342 {
00343     LOGPRINTF("entry sender [%d], mode [%d]", sender, mode);
00344     
00345     GSList *busy_ptr = g_app_counters;
00346     busy_count_t *cur_busy = NULL;
00347 
00348     // get application from list
00349     while (busy_ptr)
00350     {
00351         cur_busy = (busy_count_t *) busy_ptr->data;
00352 
00353         if (cur_busy->sender == sender)
00354         {
00355             // decrement reference count
00356             if (mode == FOREGROUND)
00357             {
00358                 if (cur_busy->fg_count > 0)
00359                 {
00360                     cur_busy->fg_count--;
00361                 }
00362             }
00363             if (cur_busy->bg_count > 0)
00364             {
00365                 cur_busy->bg_count--;
00366             }
00367             
00368             LOGPRINTF("sender [%d] bg_count [%d] fg_count [%d]", sender, cur_busy->bg_count, cur_busy->fg_count);
00369             
00370             update();
00371             return;
00372         }
00373         busy_ptr = busy_ptr->next;
00374     }
00375     
00376     return;
00377 }
00378 
00379 
00380 static void count_remove_pid(GPid pid)
00381 {
00382     LOGPRINTF("entry pid [%d]", pid);
00383     
00384     GSList *busy_ptr = g_app_counters;
00385     busy_count_t *cur_busy = NULL;
00386 
00387     // get application from list
00388     while (busy_ptr)
00389     {
00390         cur_busy = (busy_count_t *) busy_ptr->data;
00391         if (cur_busy->pid == pid)
00392         {
00393             LOGPRINTF("found pid [%d] sender [%d] bg count [%d] fg count [%d]", cur_busy->pid, cur_busy->sender, cur_busy->bg_count, cur_busy->fg_count);
00394             g_app_counters = g_slist_delete_link(g_app_counters, busy_ptr);
00395             update();
00396             return;
00397         }
00398         busy_ptr = busy_ptr->next;
00399     }
00400     
00401     return;
00402 }
00403 
00404 
00405 static gint ref_count(gint mode)
00406 {
00407 //    LOGPRINTF("entry");
00408     
00409     gint count = 0;
00410     GSList *busy_ptr = g_app_counters;
00411     while (busy_ptr)
00412     {
00413         if (mode == FOREGROUND)
00414             count += ((busy_count_t *) busy_ptr->data)->fg_count;
00415         else
00416             count += ((busy_count_t *) busy_ptr->data)->bg_count;
00417         busy_ptr = busy_ptr->next;
00418     }
00419     
00420     if (mode == FOREGROUND)
00421       LOGPRINTF("foreground [%d]", count);
00422     else 
00423       LOGPRINTF("background [%d]", count);
00424     
00425     return count;
00426 }
00427 
00428 
00429 static gboolean do_update_rgb_led(gpointer data)
00430 {
00431     UNUSED(data);
00432     sys_update_rgb_led();
00433     return FALSE;
00434 }
00435 
00436 
00437 static void update()
00438 {
00439     LOGPRINTF("entry: background [%d] foreground [%d]", ref_count(BACKGROUND), ref_count(FOREGROUND));
00440     
00441     guint old_foreground_count = g_foreground_count;
00442     g_background_count = ref_count(BACKGROUND);
00443     g_foreground_count = ref_count(FOREGROUND);
00444     
00445     if (g_background_count == 0)
00446     {
00447         // reset idle because a screen update may follow
00448         // which resets the idle time anyhow
00449         sys_reset_idle_time();
00450     }
00451 
00452     if (g_foreground_count != old_foreground_count)
00453     {
00454         if (g_foreground_count == 1)
00455         {
00456             g_timeout_add(busyled_delay, do_update_rgb_led, NULL);
00457         }
00458         else if (g_foreground_count == 0)
00459         {
00460             if (g_dialog_source)
00461             {
00462                 LOGPRINTF("stop busy dialog timer");
00463                 g_source_remove(g_dialog_source);
00464                 g_dialog_source = 0;
00465             }
00466             sys_update_rgb_led();
00467             show_dialog(FALSE);
00468         }
00469     }
00470 }
Generated by  doxygen 1.6.2-20100208