diff --git a/LCDd.conf b/LCDd.conf index 434e917..769bba9 100644 --- a/LCDd.conf +++ b/LCDd.conf @@ -69,11 +69,9 @@ User=nobody # if any, and run as this user instead. #ServerScreen=no -# Enables the built-in server screen [Default: noscreen] -# yes : always, -# noscreen : when there are no other screens active, -# no : never, the LCD display will be blank when there are -# no screens active. +# If yes, the the serverscreen will be rotated as a usual info screen. If no, +# it will be a background screen, only visible when no other screens are +# active. Foreground=yes # The server will stay in the foreground if set to true. diff --git a/server/clients.c b/server/clients.c index b85dc2e..2d4e6cc 100644 --- a/server/clients.c +++ b/server/clients.c @@ -25,7 +25,7 @@ #include "shared/report.h" #include "render.h" -LinkedList *clientlist; +LinkedList *clientlist = NULL; /* Initialize and kill client list...*/ int @@ -49,6 +49,11 @@ clients_shutdown () debug (RPT_DEBUG, "%s()", __FUNCTION__); + if( !clientlist ) { + /* Program shutdown before completed startup */ + return -1; + } + /* Free all client structures... */ for (c=LL_GetFirst (clientlist); c; c=LL_GetNext (clientlist) ) { debug (RPT_DEBUG, "%s: ...", __FUNCTION__); diff --git a/server/driver.c b/server/driver.c index 8a17796..f871e1b 100644 --- a/server/driver.c +++ b/server/driver.c @@ -24,7 +24,7 @@ #include "config.h" #endif -#include "screenlist.h" /* for timer */ +#include "main.h" /* for timer */ #include "shared/report.h" #include "shared/configfile.h" diff --git a/server/input.c b/server/input.c index 094f404..f7c87f5 100644 --- a/server/input.c +++ b/server/input.c @@ -35,7 +35,7 @@ void input_internal_key (char * key); LinkedList * keylist; -int init_input() +int input_init() { debug (RPT_DEBUG, "%s()", __FUNCTION__ ); @@ -44,17 +44,34 @@ int init_input() return 0; } +int input_shutdown() +{ + if (!keylist) { + /* Program shutdown before completed startup */ + return -1; + } + + free (keylist); + + return 0; +} + int handle_input () { char * key; + Screen * current_screen; Client * current_client; Client * target; KeyReservation * kr; debug (RPT_DEBUG, "%s()", __FUNCTION__ ); - current_client = screenlist_current()->client; + current_screen = screenlist_current(); + if( current_screen ) + current_client = current_screen->client; + else + current_client = NULL; /* Handle all keypresses */ while ((key = drivers_get_key ()) != NULL ) { diff --git a/server/input.h b/server/input.h index 455533b..1836cf0 100644 --- a/server/input.h +++ b/server/input.h @@ -40,8 +40,10 @@ typedef struct KeyReservation { } KeyReservation; -int init_input(); +int input_init(); /* Init the input handling system */ +int input_shutdown(); + /* Shut it down */ int input_reserve_key (char * key, bool exclusive, Client * client); /* Reserves a key for a client */ /* Return -1 if reservation of key is not possible */ diff --git a/server/main.c b/server/main.c index f6557ac..b4b715d 100644 --- a/server/main.c +++ b/server/main.c @@ -7,6 +7,9 @@ * * Copyright (c) 1999, William Ferrell, Scott Scriven * 2001, Joris Robijn + * 2001, Rene Wagner + * 2002, Mike Patnode + * 2002, Guillaume Filion * * * Contains main(), plus signal callback functions and a help screen. @@ -21,6 +24,8 @@ * */ +#include "config.h" + #include #include #include @@ -33,6 +38,11 @@ #include #include +#ifdef HAVE_SYS_TIME_H +# include +#endif +/* TODO: fill in what to include otherwise */ + extern char *optarg; extern int optind, optopt, opterr; @@ -52,28 +62,22 @@ extern int optind, optopt, opterr; #include "drivers.h" #include "main.h" -#define MAX_TIMER 0x10000 - #define DEFAULT_LCD_PORT LCDPORT #define DEFAULT_BIND_ADDR "127.0.0.1" #define DEFAULT_CONFIGFILE "/etc/LCDd.conf" #define DEFAULT_USER "nobody" #define DEFAULT_DRIVER "curses" #define DEFAULT_DRIVER_PATH -#define DEFAULT_WAITTIME 8 #define MAX_DRIVERS 8 #define DEFAULT_DAEMON_MODE 1 -#define DEFAULT_ENABLE_SERVER_SCREEN SERVER_SCREEN_NOSCREEN +#define DEFAULT_ROTATE_SERVER_SCREEN 1 #define DEFAULT_REPORTTOSYSLOG 0 #define DEFAULT_REPORTLEVEL RPT_WARNING +#define DEFAULT_ADDR "127.0.0.1" - -/* Store some standard defines into vars... */ -char *version = VERSION; -char *protocol_version = PROTOCOL_VERSION; -char *api_version = API_VERSION; -char *build_date = __DATE__; - +//#define DEFAULT_WAITTIME 8 +#define DEFAULT_SCREEN_DURATION 32 +#define DEFAULT_HEARTBEAT HEARTBEAT_ON /* Socket to bind to... @@ -84,7 +88,21 @@ char *build_date = __DATE__; and which address to bind to at run time. */ +/* Store some standard defines into vars... */ +char *version = VERSION; +char *protocol_version = PROTOCOL_VERSION; +char *api_version = API_VERSION; +char *build_date = __DATE__; + + /**** Configuration variables ****/ +/* Some variables are settable on the command line. This are variables that + * change the mode of operation. This includes settings that you can use to + * enable debugging: driver selection, report settings, bind address etc. + * All other settings do not need to be settable from the command line. They + * also do not necesarily need to be read in main.c but can better be read in + * in the file concerned. + */ /* All variables are set to 'unset' values*/ #define UNSET_INT -1 @@ -96,19 +114,23 @@ char configfile[256]; /* a lot of space in the executable. */ char user[64]; /* The values will be overwritten anyway... */ int daemon_mode = UNSET_INT; -int enable_server_screen = UNSET_INT; +int rotate_server_screen = UNSET_INT; static int reportLevel = UNSET_INT; static int reportToSyslog = UNSET_INT; -static int serverStarted = 0; -/* The drivers and their driver parameters*/ +/* The drivers and their driver parameters */ char *drivernames[MAX_DRIVERS]; int num_drivers = 0; +int stored_argc; +char **stored_argv; +short got_reload_signal = 0; +long int timer = 0; /**** Local functions ****/ void exit_program (int val); +void catch_reload_signal (int val); void HelpScreen (); void clear_settings(); @@ -123,21 +145,22 @@ int init_drivers(); int init_screens(); void do_mainloop(); -#define ESSENTIAL(f) {int r; if( ( r=(f) )<0 ) { report( RPT_CRIT,"Critical error, abort"); exit_program(0);}} +#define ESSENTIAL(f) {int r; if( ( r=(f) )<0 ) { report( RPT_CRIT,"Critical error, abort"); exit_program(0);}} int main (int argc, char **argv) { - /* FIXME: s is getting clobbered - in MANY places!!! - *screen *s = NULL; - *char buf[64]; - */ + + stored_argc = argc; + stored_argv = argv; signal (SIGINT, exit_program); /* Ctrl-C will cause a clean exit...*/ signal (SIGTERM, exit_program); /* and "kill"...*/ - signal (SIGHUP, exit_program); /* and "kill -HUP" (hangup)...*/ signal (SIGKILL, exit_program); /* and just in case, "kill -KILL" (which cannot be trapped; but oh well)*/ + signal (SIGHUP, catch_reload_signal); /* On SIGHUP reread config and restart the drivers ! */ + /* Let's see if we can actually get this to work ;) */ + /* If no paramaters given, give the help screen. *if (argc == 1) * HelpScreen (); @@ -188,17 +211,14 @@ main (int argc, char **argv) report( RPT_INFO, "Set report level to %d, output to %s", reportLevel, (reportToSyslog?"syslog":"stderr") ); /* Startup the server*/ + ESSENTIAL( screenlist_init() ); ESSENTIAL( init_drivers() ); ESSENTIAL( init_sockets() ); - ESSENTIAL( init_input() ); - ESSENTIAL( init_menu() ); - ESSENTIAL( init_screens() ); + ESSENTIAL( input_init() ); + ESSENTIAL( menuscreens_init() ); + ESSENTIAL( server_screen_init() ); ESSENTIAL( drop_privs(user) ); - /* Store it for exit_program()*/ - serverStarted = 1; - -#ifndef DEBUG /* Now, go into daemon mode...*/ if (daemon_mode) { report(RPT_INFO, "Server forking to background"); @@ -207,13 +227,13 @@ main (int argc, char **argv) output_GPL_notice(); report(RPT_INFO, "Server running in foreground"); } -#endif do_mainloop(); /* This loop never stops; we'll get out only with a signal...*/ return 0; } +#undef ESSENTIAL void @@ -228,7 +248,7 @@ clear_settings () strncpy( configfile, UNSET_STR, sizeof(configfile) ); strncpy( user, UNSET_STR, sizeof(user) ); daemon_mode = UNSET_INT; - enable_server_screen = UNSET_INT; + rotate_server_screen = UNSET_INT; backlight = UNSET_INT; default_duration = UNSET_INT; @@ -251,11 +271,15 @@ process_command_line (int argc, char **argv) debug( RPT_DEBUG, "%s( argc=%d, argv=...)", __FUNCTION__, argc ); + /* Reset getopt */ + optind = 0; + /* analyze options here..*/ while ((c = getopt(argc, argv, "a:p:d:hfib:w:c:u:sr:")) > 0) { /* FIXME: Setting of c in this loop clobbers s! * s is set equivalent to c. */ + report( RPT_INFO, ">>>> %i", (int) c ); switch(c) { case 'd': /* Add to a list of drivers to be initialized later...*/ @@ -285,7 +309,7 @@ process_command_line (int argc, char **argv) strncpy(configfile, optarg, sizeof(configfile)); break; case 'i': - enable_server_screen = 0; + rotate_server_screen = 0; break; case 'b': if( strcmp( optarg, "on" ) == 0 ) { @@ -374,20 +398,8 @@ process_configfile ( char *configfile ) daemon_mode = !fg; } - if( enable_server_screen == UNSET_INT ) { - s = config_get_string( "server", "serverscreen", 0, UNSET_STR ); - if( strcmp( s, "no" ) == 0 ) { - enable_server_screen = SERVER_SCREEN_NEVER; - } - else if( strcmp( s, "noscreen" ) == 0 ) { - enable_server_screen = SERVER_SCREEN_NOSCREEN; - } - else if( strcmp( s, "yes" ) == 0 ) { - enable_server_screen = SERVER_SCREEN_ALWAYS; - } - else if( strcmp( s, UNSET_STR ) != 0 ) { - report( RPT_ERR, "Serverscreen can only be no, noscreen or yes" ); - } + if( rotate_server_screen == UNSET_INT ) { + rotate_server_screen = config_get_bool( "server", "serverscreen", 0, UNSET_INT ); } if( backlight == UNSET_INT ) { @@ -407,10 +419,7 @@ process_configfile ( char *configfile ) } if( reportToSyslog == UNSET_INT ) { - /* Is the value set in the config file anyway ?*/ - if( strcmp( config_get_string( "server", "reportToSyslog", 0, "" ), "" ) != 0 ) { - reportToSyslog = config_get_bool( "server", "reportToSyslog", 0, 0 ); - } + reportToSyslog = config_get_bool( "server", "reportToSyslog", 0, UNSET_INT ); } if( reportLevel == UNSET_INT ) { reportLevel = config_get_int( "server", "reportLevel", 0, UNSET_INT ); @@ -457,8 +466,8 @@ set_default_settings() if (daemon_mode == UNSET_INT) daemon_mode = DEFAULT_DAEMON_MODE; - if (enable_server_screen == UNSET_INT) - enable_server_screen = DEFAULT_ENABLE_SERVER_SCREEN; + if (rotate_server_screen == UNSET_INT) + rotate_server_screen = DEFAULT_ROTATE_SERVER_SCREEN; if (default_duration == UNSET_INT) default_duration = DEFAULT_SCREEN_DURATION; @@ -631,101 +640,115 @@ init_screens () return -1; } - if (enable_server_screen > SERVER_SCREEN_NEVER) { - /* Add the server screen */ - if (server_screen_init () < 0) { - report(RPT_ERR, "Error initializing server screens"); - return -1; - } - - if (enable_server_screen == SERVER_SCREEN_NOSCREEN) { - /* Display the server screen only when there are no other screens */ - server_screen->priority = 256; - } + /* Add the server screen */ + if (server_screen_init () < 0) { + report(RPT_ERR, "Error initializing server screens"); + return -1; + } + if (!rotate_server_screen) { + /* Display the server screen only when there are no other screens */ + server_screen->priority = 256; } return 0; } +#define ESSENTIAL(f) {int r; if( ( r=(f) )<0 ) { report( RPT_CRIT,"Critical error while reloading, abort"); _exit(0);}} +void +do_reload () +{ + drivers_unload_all (); /* Close all drivers */ + + config_clear(); + clear_settings(); + + /* Reread command line*/ + ESSENTIAL( process_command_line (stored_argc, stored_argv) ); + + /* Reread config file */ + if (strcmp(configfile, UNSET_STR)==0) + strncpy (configfile, DEFAULT_CONFIGFILE, sizeof(configfile)); + ESSENTIAL( process_configfile (configfile) ); + + /* Set default values */ + set_default_settings(); + + /* Set reporting values */ + ESSENTIAL( set_reporting( "LCDd", reportLevel, (reportToSyslog?RPT_DEST_SYSLOG:RPT_DEST_STDERR) ) ); + report( RPT_INFO, "Set report level to %d, output to %s", reportLevel, (reportToSyslog?"syslog":"stderr") ); + + /* And restart the drivers */ + ESSENTIAL( init_drivers() ); + +} +#undef ESSENTIAL void do_mainloop () { - Screen *s = NULL; - char *message=NULL; + Screen * s; + struct timeval t; + struct timeval last_t; + int sleeptime; + long int process_lag = 0; + long int render_lag = 0; + long int t_diff; debug( RPT_DEBUG, "%s()", __FUNCTION__ ); - /*char buf[64];*/ + gettimeofday (&t, NULL); /* Get initial time */ - /* FIXME: s should still be null from initialization.... what's happening here?!*/ while (1) { - sock_poll_clients (); /* poll clients for input*/ - parse_all_client_messages (); /* analyze input from network clients*/ - handle_input (); /* handle key input from devices*/ + /* Get current time */ + last_t = t; + gettimeofday (&t, NULL); + t_diff = ((t.tv_sec - last_t.tv_sec) * 1e6 + (t.tv_usec - last_t.tv_usec)); - /* TODO: Move this code to screenlist.c... - * ... it should just say "handle_screens();" - * Timer gets reset by screenlist_next() - */ + process_lag += t_diff; + if (process_lag > 0) { + /* Time for a processing stroke */ + sock_poll_clients (); /* poll clients for input*/ + parse_all_client_messages (); /* analyze input from network clients*/ + handle_input (); /* handle key input from devices*/ - timer++; - - if (s && (timer >= s->duration)) - screenlist_next (); - - /* Just in case it gets out of hand...*/ - if (timer >= MAX_TIMER) - timer = 0; - - /* Update server screen with the right number - * of clients and screens... - */ - - /* TODO: Move this call to every client connection - * and every screen add... - */ - - update_server_screen (timer); - - /* draw the current scren*/ - - if ((s = screenlist_current ()) != NULL) - draw_screen (s, timer); - - usleep (TIME_UNIT); - - /* Check to see if the screen has a timeout value, if it does - * decrese it and then check to see if it has excpired. - * Remove if expired. - */ - if((message = malloc(256)) == NULL) - report(RPT_ERR, "Error allocating message string"); - else if (s) { - snprintf(message, 256, "Screen->%s has timeout->%d", s->name, s->timeout); - report(RPT_DEBUG, message); - free(message); + /* We've done the job... */ + process_lag = 0 - (1e6/PROCESS_FREQ); + /* Note : this does not make a fixed frequency */ } - if (s && s->timeout != -1) { - --(s->timeout); - if((message = malloc(256)) == NULL) - report(RPT_ERR, "Error allocating message string"); - else { - snprintf(message, 256, "Timeout matches check, screen %s has timeout->%d", s->name, s->timeout); - report(RPT_DEBUG, message); - free(message); + render_lag += t_diff; + if (render_lag > 0) { + /* Time for a rendering stroke */ + timer ++; + screenlist_update (); + s = screenlist_current (); + + /* TODO: Move this call to every client connection + * and every screen add... + */ + if( s == server_screen ) { + update_server_screen (timer); } - if (s->timeout <= 0) { - client_remove_screen (s->client, s); - screen_destroy (s); - if((message = malloc(256)) == NULL) - report(RPT_ERR, "Error allocating message string"); - else { - snprintf(message, 256, "Removing screen %s which has timeout->%d", s->name, s->timeout); - report(RPT_DEBUG, message); - free(message); - } + render_screen (s, timer); + + /* We've done the job... */ + if( render_lag > (1e6/RENDER_FREQ) * MAX_RENDER_LAG_FRAMES ) { + /* Cause rendering slowdown because too much lag */ + render_lag = (1e6/RENDER_FREQ) * MAX_RENDER_LAG_FRAMES; } + render_lag -= (1e6/RENDER_FREQ); + /* Note: this DOES make a fixed frequency (except with slowdown) */ + } + + /* Sleep just as long as needed */ + sleeptime = min (0-process_lag, 0-render_lag); + if( sleeptime > 0 ) { + usleep (sleeptime); + } + + /* Check if a SIGHUP has been caught */ + if( got_reload_signal ) { + got_reload_signal = 0; + do_reload (); } } @@ -753,10 +776,9 @@ exit_program (int val) default: snprintf(buf, sizeof(buf), "Server shutting down on signal %d", val); break; /* Other values should not be seen, but just in case.. */ } + report(RPT_NOTICE, buf); /* report it */ } - report(RPT_NOTICE, buf); /* report it */ - /* Set emergency reporting and flush all messages if not done already. */ if( reportLevel == UNSET_INT ) reportLevel = DEFAULT_REPORTLEVEL; @@ -768,14 +790,21 @@ exit_program (int val) drivers_unload_all (); /* release driver memory and file descriptors */ /* Shutdown things if server start was complete */ - if( serverStarted ) { - clients_shutdown (); /* shutdown clients (must come first) */ - screenlist_shutdown (); /* shutdown screens (must come after client_shutdown) */ - } + clients_shutdown (); /* shutdown clients (must come first) */ + menuscreens_shutdown (); + screenlist_shutdown (); /* shutdown screens (must come after client_shutdown) */ + input_shutdown (); /* shutdown key input part */ - exit (0); + _exit (0); } +void +catch_reload_signal (int val) +{ + debug( RPT_DEBUG, "%s( val=%d )", __FUNCTION__, val ); + + got_reload_signal = 1; +} void HelpScreen () diff --git a/server/main.h b/server/main.h index cfb79d0..dc3da72 100644 --- a/server/main.h +++ b/server/main.h @@ -21,21 +21,25 @@ contains a few things that other parts of the program might want to know about... */ +#define DEFAULT_SCREEN_PRIORITY 128 extern char *version; extern char *protocol_version; extern char *build_date; -void exit_program (int val); +/* You should be able to modify the following freqencies... */ +#define RENDER_FREQ 8 +/* We want 8 frames per second */ +#define PROCESS_FREQ 32 +/* And 32 times per second processing of messages and keypresses. */ +#define MAX_RENDER_LAG_FRAMES 16 +/* Allow the rendering strokes to lag behind this many frames. + * More lag will not be corrected, but will cause slow-down. */ +#define TIME_UNIT (1e6/RENDER_FREQ) +/* Variable from stone age, still used a lot. */ -/* 1/8th second is a single time unit...*/ -#define TIME_UNIT 125000 -/* But I plan to double the framerate soon, or make it variable...*/ -/*#define TIME_UNIT (125000/2)*/ - -#define DEFAULT_SCREEN_PRIORITY 128 -#define DEFAULT_SCREEN_DURATION 32 -#define DEFAULT_HEARTBEAT HEARTBEAT_ON -#define DEFAULT_ADDR "127.0.0.1" +extern long int timer; +/* 32 bits at 8Hz will overflow in 2 ^ 29 = 5e8 seconds = 17 years. + * Please mail us if you got an overflow :) */ #endif diff --git a/server/menuscreens.c b/server/menuscreens.c index 63360db..dd5f44e 100644 --- a/server/menuscreens.c +++ b/server/menuscreens.c @@ -39,10 +39,10 @@ char * enter_key; char * up_key; char * down_key; -Screen * menuscreen; -MenuItem * active_menuitem; -Menu * main_menu; -Menu * screens_menu; +Screen * menuscreen = NULL; +MenuItem * active_menuitem = NULL; +Menu * main_menu = NULL; +Menu * screens_menu = NULL; /* Local prototypes */ void menuscreen_switch_item (MenuItem * new_menuitem); @@ -52,10 +52,8 @@ MenuEventFunc (backlight_handler); MenuEventFunc (contrast_handler); MenuEventFunc (brightness_handler); -int init_menu() +int menuscreens_init() { - active_menuitem = NULL; - debug (RPT_DEBUG, "%s()", __FUNCTION__); /* Get keys from config file */ @@ -80,6 +78,39 @@ int init_menu() } +int menuscreens_shutdown() +{ + debug (RPT_DEBUG, "%s()", __FUNCTION__ ); + + if (!menuscreen) { + /* Program shutdown before completed startup */ + return -1; + } + + /* Quit menu just to make sure */ + menuscreen_switch_item (NULL); + + /* Destroy the menuscreen */ + screen_destroy (menuscreen); + menuscreen = NULL; + screens_menu = NULL; + + /* Destroy all menus */ + menuitem_destroy (main_menu); + main_menu = NULL; + + /* Forget menu's key reservations */ + input_release_client_keys (NULL); + + free (menu_key); + free (enter_key); + free (up_key); + free (down_key); + + return 0; +} + + void menuscreen_inform_item_destruction (MenuItem * item) { MenuItem * i; @@ -108,7 +139,7 @@ void menuscreen_inform_item_modified (MenuItem * item) bool is_menu_key (char * key) { - if (strcmp (key, menu_key) == 0) + if (menu_key && strcmp (key, menu_key) == 0) return true; else return false; @@ -128,12 +159,13 @@ void menuscreen_switch_item (MenuItem * new_menuitem) active_menuitem = new_menuitem; /* What was the state change ? */ - if (old_menuitem && !new_menuitem) { - /* Menu is being quit */ - + if (!old_menuitem && !new_menuitem) { + /* Nothing to be done */ + } else if (old_menuitem && !new_menuitem) { /* TODO: send menu to backgr */ if (screenlist_remove (menuscreen) < 0) { report (RPT_ERR, "%s: Error unqueueing menu screen", __FUNCTION__); + return; } } else if (!old_menuitem && new_menuitem) { /* Menu is becoming active */ @@ -142,9 +174,9 @@ void menuscreen_switch_item (MenuItem * new_menuitem) if (screenlist_add (menuscreen) < 0) { report (RPT_ERR, "%s: Error queueing menu screen", __FUNCTION__); + return; } /* TODO: raise it ! */ - return; } else { /* We're left with the usual case: a menu level switch */ if( old_menuitem->parent != new_menuitem) { @@ -409,6 +441,11 @@ menuscreen_remove_screen (Screen * s) debug (RPT_DEBUG, "%s( s=[%s] )", __FUNCTION__, s->id); + if (s == menuscreen) { + return; + /* To allow to remove the menuscreen itself */ + } + m = menu_find_item (screens_menu, s->id, false); menu_remove_item (screens_menu, m); menuitem_destroy (m); diff --git a/server/menuscreens.h b/server/menuscreens.h index 02479b8..a0e51ae 100644 --- a/server/menuscreens.h +++ b/server/menuscreens.h @@ -21,7 +21,9 @@ extern Screen * menuscreen; extern Menu * main_menu; -int init_menu(); +int menuscreens_init(); + +int menuscreens_shutdown(); bool is_menu_key (char * key); /* This function indicates to the input part whether this key was the diff --git a/server/render.c b/server/render.c index f1dba7e..bc2fb8f 100644 --- a/server/render.c +++ b/server/render.c @@ -38,6 +38,8 @@ #include "widget.h" #include "render.h" +int metronome = 0; /* This counter will be increased at every rendering */ + int heartbeat = HEARTBEAT_OPEN; int heartbeat_fallback = HEARTBEAT_ON; /* If no heartbeat setting has been set at all */ int backlight = BACKLIGHT_OPEN; @@ -50,10 +52,10 @@ static int reset; #define BUFSIZE 1024 -static int draw_frame (LinkedList * list, char fscroll, int left, int top, int right, int bottom, int fwid, int fhgt, int fspeed, int timer); +static int render_frame (LinkedList * list, char fscroll, int left, int top, int right, int bottom, int fwid, int fhgt, int fspeed, long int timer); int -draw_screen (Screen * s, int timer) +render_screen (Screen * s, long int timer) { static Screen * old_s = NULL; int tmp_state = 0; @@ -115,7 +117,7 @@ draw_screen (Screen * s, int timer) drivers_output (output_state); /* Draw a frame... */ - draw_frame (s->widgetlist, 'v', 0, 0, display_props->width, display_props->height, s->width, s->height, (((s->duration / s->height) < 1) ? 1 : (s->duration / s->height)), timer); + render_frame (s->widgetlist, 'v', 0, 0, display_props->width, display_props->height, s->width, s->height, (((s->duration / s->height) < 1) ? 1 : (s->duration / s->height)), timer); /* Set the cursor */ drivers_cursor (s->cursor_x, s->cursor_y, s->cursor); @@ -147,7 +149,7 @@ draw_screen (Screen * s, int timer) /* Best thing to do is to remove support for frames... but anyway... */ /* */ static int -draw_frame (LinkedList * list, +render_frame (LinkedList * list, char fscroll, /* direction of scrolling */ int left, /* left edge of frame */ int top, /* top edge of frame */ @@ -156,7 +158,7 @@ draw_frame (LinkedList * list, int fwid, /* frame width? */ int fhgt, /* frame height? */ int fspeed, /* speed of scrolling... */ - int timer) /* ? */ + long int timer) /* ? */ { #define VerticalScrolling (fscroll == 'v') @@ -498,7 +500,7 @@ draw_frame (LinkedList * list, new_bottom = bottom; if (new_left >= right || new_top >= bottom) { /* Do nothing if it's invisible...*/ } else { - draw_frame (w->frame_screen->widgetlist, w->length, new_left, new_top, new_right, new_bottom, w->width, w->height, w->speed, timer); + render_frame (w->frame_screen->widgetlist, w->length, new_left, new_top, new_right, new_bottom, w->width, w->height, w->speed, timer); } } break; diff --git a/server/render.h b/server/render.h index c793880..1dbd9a6 100644 --- a/server/render.h +++ b/server/render.h @@ -18,10 +18,6 @@ #define HEARTBEAT_ON 1 #define HEARTBEAT_OPEN 2 -#define SERVER_SCREEN_NEVER 0 -#define SERVER_SCREEN_NOSCREEN 1 -#define SERVER_SCREEN_ALWAYS 2 - #define BACKLIGHT_OFF 0 #define BACKLIGHT_ON 1 #define BACKLIGHT_OPEN 2 @@ -39,6 +35,6 @@ extern int backlight; extern int backlight_brightness; extern int backlight_off_brightness; extern int output_state; -int draw_screen (Screen * s, int timer); +int render_screen (Screen * s, long int timer); #endif diff --git a/server/screenlist.c b/server/screenlist.c index 73e45a8..65d9038 100644 --- a/server/screenlist.c +++ b/server/screenlist.c @@ -19,14 +19,18 @@ #include "shared/sockets.h" #include "shared/report.h" #include "screenlist.h" +#include "render.h" #include "screen.h" +#include "serverscreens.h" #include "clients.h" +#include "main.h" /* for timer */ + int screenlist_action = 0; +long int current_screen_start_time; -int timer = 0; - -LinkedList *screenlist; +LinkedList *screenlist = NULL; +Screen * current_screen = NULL; int screenlist_add_end (Screen * screen); Screen *screenlist_next_roll (); @@ -46,10 +50,7 @@ screenlist_init () report(RPT_ERR, "%s: error allocating list", __FUNCTION__); return -1; } - screenlist_action = 0; - timer = 0; - return 0; } @@ -58,6 +59,10 @@ screenlist_shutdown () { report (RPT_DEBUG, "%s()", __FUNCTION__); + if( !screenlist ) { + /* Program shutdown before completed startup */ + return -1; + } LL_Destroy (screenlist); return 0; @@ -89,72 +94,91 @@ screenlist_remove_all (Screen * s) return i; } -LinkedList * -screenlist_getlist () +void +screenlist_update () +/* Decide if we need to switch to an other screen. + */ { + Screen * s; + report (RPT_DEBUG, "%s()", __FUNCTION__); - return screenlist; + s = screenlist_current (); + if (!s) { + /* Try to switch to the first screen in the list */ + + s = LL_GetFirst(screenlist); + if (!s) { + /* There was no screen in the list */ + return; + } + screenlist_switch (s); + } + if (timer - current_screen_start_time >= s->duration) { + screenlist_switch( screenlist_next ()); + } + + /* Check to see if the screen has a timeout value, if it does + * decrese it and then check to see if it has excpired. + * Remove if expired. + */ + if (s && s->timeout != -1) { + --(s->timeout); + report(RPT_DEBUG, "Timeout matches check, screen %s has timeout->%d", s->name, s->timeout); + if (s->timeout <= 0) { + client_remove_screen (s->client, s); + screen_destroy (s); + report(RPT_DEBUG, "Removing screen %s which has timeout->%d", s->name, s->timeout); + } + } + for (s=LL_GetFirst(screenlist); s; s=LL_GetNext(screenlist)) { + report( RPT_DEBUG, "%s: [%s] %d %d", __FUNCTION__, s->id, s->priority, s->duration ); + } +} + +void +screenlist_switch (Screen * s) +/* Switch to an other screen */ +{ + Client * c; + char str[256]; + + if (!s) return; + + report (RPT_DEBUG, "%s( s=[%.40s] )", __FUNCTION__, s->id ); + + if (s == current_screen) { + /* Nothing to be done */ + return; + } + + if (current_screen) { + c = current_screen->client; + if (c) { + /* Tell the client we're not listening any more...*/ + snprintf (str, sizeof(str), "ignore %s\n", current_screen->id); + sock_send_string (c->sock, str); + } else { + /* It's a server screen, no need to inform it. */ + } + } + c = s->client; + if (c) { + /* Tell the client we're paying attention...*/ + snprintf (str, sizeof(str), "listen %s\n", s->id); + sock_send_string (c->sock, str); + } else { + /* It's a server screen, no need to inform it. */ + } + report (RPT_INFO, "%s: switched to screen [%.40s]", __FUNCTION__, s->id ); + current_screen = s; + current_screen_start_time = timer; } Screen * screenlist_current () { - char str[256]; - Screen * s; - static Screen * old_s = NULL; - Client * c; - - debug( RPT_DEBUG, "%s()", __FUNCTION__); - - /*LL_dprint(screenlist);*/ - - s = (Screen *) LL_GetFirst (screenlist); - - /* FIXME: Make sure the screen/client exists!*/ - if (s != old_s) { - /*debug (RPT_DEBUG, "screenlist_current: new screen");*/ - timer = 0; - - /* Tell the client we're done with the current screen*/ - if (old_s) { - /*debug(RPT_DEBUG, "screenlist_current: ignoring old screen");*/ - LL_Rewind (screenlist); - if (old_s != LL_Find (screenlist, compare_addresses, old_s)) { - report (RPT_WARNING, "screenlist: Didn't find screen 0x%8x! Client crashed?", (int) old_s); - } else { - /*debug(RPT_DEBUG, "screenlist_current: ... sending ignore");*/ - c = old_s->client; - if (c) /* Tell the client we're not listening any more...*/ - { - snprintf (str, sizeof(str), "ignore %s\n", old_s->id); - sock_send_string (c->sock, str); - } else /* The server has the display, so do nothing*/ - { - ; - } - /*debug(RPT_DEBUG, "screenlist_current: ... sent ignore");*/ - } - } - if (s) { - /*debug(RPT_DEBUG, "screenlist_current: listening to new screen");*/ - c = s->client; - if (c) /* Tell the client we're paying attention...*/ - { - snprintf (str, sizeof(str), "listen %s\n", s->id); - sock_send_string (c->sock, str); - } else /* The server has the display, so do nothing*/ - { - ; - } - } - } - - old_s = s; - - /*debug(RPT_DEBUG, "screenlist_current: return %8x", s);*/ - - return s; + return current_screen; } int @@ -252,7 +276,7 @@ screenlist_next_priority () LL_Sort (screenlist, compare_priority); - return screenlist_current (); + return LL_Get (screenlist); } /* Simple round-robin approach to screen cycling...*/ diff --git a/server/screenlist.h b/server/screenlist.h index 79d2df0..83d1025 100644 --- a/server/screenlist.h +++ b/server/screenlist.h @@ -22,12 +22,12 @@ #define RENDER_BACK 13 extern int screenlist_action; -extern int timer; int screenlist_init (); int screenlist_shutdown (); -LinkedList *screenlist_getlist (); +void screenlist_update (); +void screenlist_switch (Screen * s); Screen *screenlist_current (); int screenlist_add (Screen * s); diff --git a/server/serverscreens.c b/server/serverscreens.c index adf9559..bbdaa6d 100644 --- a/server/serverscreens.c +++ b/server/serverscreens.c @@ -50,7 +50,7 @@ server_screen_init () } server_screen->name = "Server screen"; server_screen->duration = 8; /* 1 second, instead of 4...*/ - server_screen->priority = -1; /* TODO: use priorities good */ + server_screen->priority = 255; /* Create all the widgets...*/ for (line=1; line<=4; line++) { @@ -83,7 +83,17 @@ server_screen_init () } int -update_server_screen (int timer) +server_screen_shutdown () +{ + if (!server_screen) return -1; + + screenlist_remove (server_screen); + screen_destroy (server_screen); + return 0; +} + +int +update_server_screen () { Client * c; Widget * w; diff --git a/server/serverscreens.h b/server/serverscreens.h index f1f7389..ec494a9 100644 --- a/server/serverscreens.h +++ b/server/serverscreens.h @@ -17,7 +17,8 @@ extern Screen * server_screen; int server_screen_init (); -int update_server_screen (int timer); +int server_screen_shutdown (); +int update_server_screen (); int goodbye_screen (); #endif