From 7496af7c8678b4ee97f9913b26dad028149eed79 Mon Sep 17 00:00:00 2001 From: mzuther Date: Sun, 7 Feb 2010 14:03:46 +0000 Subject: added grouping of widgets by update interval (new file "timer_group.c") git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@1106 3ae390bd-cb1e-0410-b409-cd5a39f66f1f --- timer_group.c | 261 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 timer_group.c (limited to 'timer_group.c') diff --git a/timer_group.c b/timer_group.c new file mode 100644 index 0000000..0a72e84 --- /dev/null +++ b/timer_group.c @@ -0,0 +1,261 @@ +/* $Id$ + * $URL$ + * + * generic grouping of widget timers that have been set to the same + * update interval, thus allowing synchronized updates + * + * Copyright (C) 2010 Martin Zuther + * + * Based on "timer.c" which is + * Copyright (C) 2003, 2004 Michael Reinelt + * Copyright (C) 2004 The LCD4Linux Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * exported functions: + * + * int timer_add_group(void (*callback) (void *data), const int interval) + * make sure that generic timer exists for given update interval + * + * int timer_remove_group(void (*callback) (void *data), const int interval) + * remove generic timer for given update interval + * + * void timer_process_group(void *data) + * process all widgets of a given update interval (*data) + * + * void timer_exit_group(void) + * release all timers and free reserved memory + * + * int timer_add_widget(void (*callback) (void *data), void *data, const int interval, const int one_shot) + * add widget to group of the given update interval (creates a new group if + * necessary) + * + * int timer_remove_widget(void (*callback) (void *data), void *data) + * remove widget from group of the given update interval (als removes emtpy + * groups) + * + */ + + +#include "config.h" + +#include +#include +#include + +#include "debug.h" +#include "cfg.h" +#include "timer.h" +#include "timer_group.h" + +#ifdef WITH_DMALLOC +#include +#endif + + +/* contains the actual timers, one for each update interval */ +typedef struct TIMER_GROUP { + void (*callback) (void *data); + int *interval; + int active; +} TIMER_GROUP; + +TIMER_GROUP *GroupTimers = NULL; +int nGroupTimers = 0; + +/* contains callback and data for each widget */ +typedef struct SINGLE_TIMER { + void (*callback) (void *data); + void *data; + int interval; + int one_shot; + int active; +} SINGLE_TIMER; + +SINGLE_TIMER *SingleTimers = NULL; +int nSingleTimers = 0; + +int timer_add_group(void (*callback) (void *data), const int interval) +{ + int group; + + /* check whether timer exists for given update interval */ + for (group = 0; group < nGroupTimers; group++) { + if (*GroupTimers[group].interval == interval) + return 0; + } + + /* otherwise look for a free group */ + for (group = 0; group < nGroupTimers; group++) { + if (GroupTimers[group].active == 0) + break; + } + + /* none found, allocate a new group */ + if (group >= nGroupTimers) { + nGroupTimers++; + GroupTimers = realloc(GroupTimers, nGroupTimers * sizeof(*GroupTimers)); + + /* also allocate memory for callback data */ + GroupTimers[group].interval = malloc(sizeof(int)); + } + + /* initialize group */ + info("Creating new timer group (%d ms)", interval); + + GroupTimers[group].callback = callback; + *GroupTimers[group].interval = interval; + GroupTimers[group].active = 1; + + /* finally, request a generic timer */ + return timer_add(GroupTimers[group].callback, GroupTimers[group].interval, interval, 0); +} + +int timer_remove_group(void (*callback) (void *data), const int interval) +{ + int group; + + /* look for group with given callback function and update interval */ + for (group = 0; group < nGroupTimers; group++) { + if (GroupTimers[group].callback == callback && *GroupTimers[group].interval == interval + && GroupTimers[group].active) { + /* inactivate group */ + GroupTimers[group].active = 0; + + /* remove generic timer */ + return timer_remove(GroupTimers[group].callback, GroupTimers[group].interval); + } + } + return -1; +} + +void timer_process_group(void *data) +{ + int slot; + int *interval = (int *) data; + + /* sanity check */ + if (nSingleTimers == 0) { + error("huh? not even a single widget timer to process? dazed and confused..."); + return; + } + + /* process every (active) widget associated with given update interval */ + for (slot = 0; slot < nSingleTimers; slot++) { + if (SingleTimers[slot].active == 0) + continue; + + if (SingleTimers[slot].interval == *interval) { + /* call one-shot timers only once */ + if (SingleTimers[slot].one_shot) + SingleTimers[slot].active = 0; + /* execute callback function */ + if (SingleTimers[slot].callback != NULL) + SingleTimers[slot].callback(SingleTimers[slot].data); + } + } +} + +int timer_add_widget(void (*callback) (void *data), void *data, const int interval, const int one_shot) +{ + int slot; + + /* make sure that group for update interval exists or can be created */ + if (timer_add_group(timer_process_group, interval) != 0) + return -1; + + /* find a free slot for callback data */ + for (slot = 0; slot < nSingleTimers; slot++) { + if (SingleTimers[slot].active == 0) + break; + } + + /* none found, allocate a new slot */ + if (slot >= nSingleTimers) { + nSingleTimers++; + SingleTimers = realloc(SingleTimers, nSingleTimers * sizeof(*SingleTimers)); + } + + /* fill slot with callback data */ + SingleTimers[slot].callback = callback; + SingleTimers[slot].data = data; + SingleTimers[slot].interval = interval; + SingleTimers[slot].one_shot = one_shot; + SingleTimers[slot].active = 1; + + return 0; +} + +int timer_remove_widget(void (*callback) (void *data), void *data) +{ + int slot, interval; + + interval = 0; + /* look for (active) widget with given callback function and data */ + for (slot = 0; slot < nSingleTimers; slot++) { + if (SingleTimers[slot].callback == callback && SingleTimers[slot].data == data && SingleTimers[slot].active) { + /* deactivate widget */ + SingleTimers[slot].active = 0; + interval = SingleTimers[slot].interval; + break; + } + } + + /* signal an error if no matching widget was found */ + if (interval == 0) + return -1; + + /* look for other widgets with given update interval */ + for (slot = 0; slot < nSingleTimers; slot++) { + if (SingleTimers[slot].active == 0) + continue; + /* at least one other widget with given update interval exists */ + if (SingleTimers[slot].interval == interval) + return 0; + } + + /* remove group with given update interval */ + return timer_remove_group(timer_process_group, interval); +} + +void timer_exit_group(void) +{ + int group; + + /* remove generic timer and free memory for callback data */ + for (group = 0; group < nGroupTimers; group++) { + timer_remove(GroupTimers[group].callback, GroupTimers[group].interval); + free(GroupTimers[group].interval); + } + + /* free memory for groups */ + nGroupTimers = 0; + + if (GroupTimers != NULL) { + free(GroupTimers);; + GroupTimers = NULL; + } + + /* free memory for widget callback data */ + nSingleTimers = 0; + + if (SingleTimers != NULL) { + free(SingleTimers);; + SingleTimers = NULL; + } +} -- cgit v1.2.3