- Moved some code from main.c to screenlist.c

- Implemented reloading by sending SIGHUP.
- Now doing 'real 8Hz' rendering and 32Hz input processing.
- Removed noscreen feature (that we rejected).
This commit is contained in:
robijn
2002-08-04 20:58:51 +00:00
parent 8a1933e3b9
commit dc619e596f
15 changed files with 374 additions and 247 deletions
+162 -133
View File
@@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -33,6 +38,11 @@
#include <sys/types.h>
#include <fcntl.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#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 ()