diff --git a/ChangeLog b/ChangeLog index 00dba8c..50a7a8d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,14 +1,30 @@ Recent changes: -Key: +Key: - Something removed + Something added * Something changed / fixed -Coming soon: (?) (my list of stuff to do soon...) - + Client menus - * Dynamically-loaded driver system - + LCDproc Developer's Guide +v0.5 +This version has split off from unstable-0.4.3. Includes major changes. + + LCDd now does dynamic loading of driver modules + * New API in use + + LCDd will use fill-in functions for drivers that don't support a certain + function. Available for: vbar, hbar, bignum, heartbeat, icon, cursor. + * Server internal functions cleaned up, moved to other files etc. + * Menu system rewritten + + Client-supplied menus are now supported + * Key support improved: now keys have descriptive names, not just a letter + anymore. + + Reloading of configuration and drivers by sending a SIGHUP. Probably + needs improvement ;) + * HD44780 output register support on winamp wiring + * Reporting levels are now used more consistently + + lcdexec client added + * Display update frequency is now exactly 8Hz. Key scan frequency increased + to 32Hz. + * Priority scheme changed. Priority classes are now used, that indicate what + kind of a screen we're dealing with. More useful for interactive clients. v0.4.3 - Removed possibility of passing arguments to the drivers from the @@ -17,6 +33,9 @@ v0.4.3 + Added ability of dropping root privileges to LCDd + Added LCDM001 driver (kernelconcepts.de) + Added Toshiba T6963 driver + + Added Seiko-Epson SED 1520 driver + + Added Seiko-Epson SED 1330 driver + + Added STV5730 driver composite TV signal character generation driver * Modified the CFontz driver so that the new ROM version is supported + Added ASCII emulation of BigNum to the drivers that did not @@ -117,7 +136,7 @@ v0.4-pre10: V0.4-pre9: * small fixes for irix - * Added flag in LCDd to shut off server screen: + * Added flag in LCDd to shut off server screen: "-i off" or "--serverinfo off" + Wirz SLI driver + 16x2 support (server only) @@ -130,7 +149,7 @@ V0.4-pre9: * sizes > 20x4 no longer crash V0.4-pre8: - * LCDd gives more updated info in the connect string: + * LCDd gives more updated info in the connect string: cell size, lcd dimensions. * bargraphs are now the correct length on CFontz displays, in the main lcdproc client. For other clients, please parse the connect string! diff --git a/server/client.c b/server/client.c index 62aa24e..3b63c01 100644 --- a/server/client.c +++ b/server/client.c @@ -210,10 +210,7 @@ client_add_screen (Client * c, Screen * s) LL_Push (c->screenlist, (void *) s); /* Now, add it to the screenlist...*/ - if (screenlist_add (s) < 0) { - report (RPT_ERR, "client_add_screen: Error queueing new screen"); - return -1; - } + screenlist_add (s); return 0; } @@ -232,11 +229,8 @@ client_remove_screen (Client * c, Screen * s) LL_Remove (c->screenlist, (void *) s); /* Now, remove it from the screenlist...*/ - if (screenlist_remove_all (s) < 0) { - /* Not a serious error..*/ - report (RPT_ERR, "%s: Error dequeueing screen", __FUNCTION__); - return 0; - } + screenlist_remove (s); + return 0; } diff --git a/server/commands/command_list.c b/server/commands/command_list.c index cf5871a..7bc9adb 100644 --- a/server/commands/command_list.c +++ b/server/commands/command_list.c @@ -6,6 +6,7 @@ * COPYING file distributed with this package. * * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2003, Joris Robijn * * * This contains definitions for all the functions which clients can run. @@ -42,6 +43,7 @@ client_function commands[] = { {"menu_add_item", menu_add_item_func}, {"menu_del_item", menu_del_item_func}, {"menu_set_item", menu_set_item_func}, + {"menu_goto", menu_goto_func}, /* Misc stuff...*/ {"backlight", backlight_func}, {"output", output_func}, diff --git a/server/commands/menu_commands.c b/server/commands/menu_commands.c index ddbcf3a..43b2635 100644 --- a/server/commands/menu_commands.c +++ b/server/commands/menu_commands.c @@ -36,8 +36,10 @@ #include "menuscreens.h" #include "client.h" +/* Local functions */ MenuEventFunc(menu_commands_handler); + /************************************************************************* * menu_add_item_func * @@ -59,7 +61,6 @@ MenuEventFunc(menu_commands_handler); * - numeric * - alpha */ - int menu_add_item_func (Client * c, int argc, char **argv) { @@ -307,20 +308,24 @@ menu_del_item_func (Client * c, int argc, char **argv) * * Hmm, this is getting very big. We might need a some real parser after all. */ - int menu_set_item_func (Client * c, int argc, char **argv) { typedef enum AttrType { NOVALUE, BOOLEAN, CHECKBOX_VALUE, SHORT, INT, FLOAT, STRING } AttrType; + /* This table generalizes the options. + * The table lists which options can exist for which menu items, + * what kind of parameter they should have and where this scanned + * parameter should be stored. + */ struct OptionTable { MenuItemType menuitem_type; /* For what MenuItem type is the option ? Use -1 for ALL types. */ char * name; /* The option concerned */ AttrType attr_type; /* Type of value */ - int attr_offset; /* Where to put it the value + int attr_offset; /* Where to put the value in the structure. Use -1 to process it yourself. */ @@ -608,6 +613,52 @@ menu_set_item_func (Client * c, int argc, char **argv) return 0; } +/*************************************************************** + * Requests the menu system to display the given menu screen. + * This will only work if the menu is not active at the moment. + * However, if a valid menu id has been given the function will + * always return "success". + * + * usage: menu_goto + */ +int +menu_goto_func (Client * c, int argc, char **argv) +{ + char * menu_id; + Menu * menu; + + if (!c->ack) + return 1; + + if ((argc < 2 )) { + sock_send_string (c->sock, "huh? Usage: menu_goto \n"); + return 0; + } + + menu_id = argv[1]; + + if ( menu_id[0] == 0 ) { + /* No menu specified = client's main menu */ + menu = c->menu; + } else { + /* A specified menu */ + menu = menu_find_item (c->menu, menu_id, true); + } + if (!menu) { + sock_send_string (c->sock, "huh? Cannot find menu id\n"); + return 0; + } + menuscreen_goto (menu); + /* Failure is not returned */ + sock_send_string(c->sock, "success\n"); + return 0; +} + +/*************************************************************** + * This function cathes the event for the menus that have been + * created on behalf of the clients. It informs the client with + * an event message. + */ MenuEventFunc (menu_commands_handler) { char buf[80] = ""; diff --git a/server/commands/menu_commands.h b/server/commands/menu_commands.h index cf9b556..dfaee4f 100644 --- a/server/commands/menu_commands.h +++ b/server/commands/menu_commands.h @@ -13,12 +13,10 @@ #ifndef COMMANDS_MENU_H #define COMMANDS_MENU_H -int menu_add_func (Client * c, int argc, char **argv); -int menu_del_func (Client * c, int argc, char **argv); -int menu_set_func (Client * c, int argc, char **argv); int menu_add_item_func (Client * c, int argc, char **argv); int menu_del_item_func (Client * c, int argc, char **argv); int menu_set_item_func (Client * c, int argc, char **argv); +int menu_goto_func (Client * c, int argc, char **argv); #endif diff --git a/server/commands/screen_commands.c b/server/commands/screen_commands.c index 9c416b0..6ed613c 100644 --- a/server/commands/screen_commands.c +++ b/server/commands/screen_commands.c @@ -199,11 +199,26 @@ screen_set_func (Client * c, int argc, char **argv) i++; debug (RPT_DEBUG, "screen_set: priority=\"%s\"", argv[i]); - /* set the priority...*/ + /* first try to interpret it as a number */ number = atoi (argv[i]); - if (number > 0) + if (number > 0) { + if (number <= 64) { + s->priority = PRI_FOREGROUND; + } else if (number < 192) { + s->priority = PRI_INFO; + } else { + s->priority = PRI_BACKGROUND; + } + } else { + /* Try if it is a priority class */ + number = screen_pri_name_to_pri (argv[i]); + } + if (number >= 0) { s->priority = number; - sock_send_string(c->sock, "success\n"); + sock_send_string(c->sock, "success\n"); + } else { + sock_send_string(c->sock, "huh? invalid argument at -priority\n"); + } } else { sock_send_string (c->sock, "huh? -priority requires a parameter\n"); } diff --git a/server/input.c b/server/input.c index f7c87f5..50c11ca 100644 --- a/server/input.c +++ b/server/input.c @@ -6,6 +6,7 @@ * COPYING file distributed with this package. * * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2003, Joris Robijn * * * Handles keypad (and other?) input from the user. @@ -28,12 +29,19 @@ #include "input.h" + +LinkedList * keylist; +char * toggle_rotate_key = "Enter"; +char * prev_screen_key = "Left"; +char * next_screen_key = "Right"; +char * scroll_up_key = "Up"; +char * scroll_down_key = "Down"; + +/* Local functions */ int server_input (int key); void input_send_to_client (Client * c, char * key); void input_internal_key (char * key); -LinkedList * keylist; - int input_init() { @@ -44,6 +52,7 @@ int input_init() return 0; } + int input_shutdown() { if (!keylist) { @@ -56,6 +65,7 @@ int input_shutdown() return 0; } + int handle_input () { @@ -93,12 +103,13 @@ handle_input () } else { /* It's an external client */ report (RPT_DEBUG, "%s: key is for external client on socket %d", __FUNCTION__, target->sock ); - input_send_to_client (current_client, key); + input_send_to_client (target, key); } } return 0; } + void input_send_to_client (Client * c, char * key) { char * s; @@ -112,52 +123,31 @@ void input_send_to_client (Client * c, char * key) free (s); } + void input_internal_key (char * key) { - if (is_menu_key(key) || screenlist_current() == menuscreen) { - menuscreen_key_handler (key); + if( is_menu_key(key) || screenlist_current() == menuscreen ) { + menuscreen_key_handler(key); } else { - /* TODO: give keys to server screen */ + /* Keys are for scrolling or rotating */ + if( strcmp(key,toggle_rotate_key) == 0 ) { + autorotate = !autorotate; + } + else if( strcmp(key,prev_screen_key) == 0 ) { + screenlist_goto_prev (); + } + else if( strcmp(key,next_screen_key) == 0 ) { + screenlist_goto_next (); + } + else if( strcmp(key,scroll_up_key) == 0 ) { + } + else if( strcmp(key,scroll_down_key) == 0 ) { + } } } - -/* TODO: REPLACE THE FOLLOWING FUNCTION BY SOMETHING NEW */ -int -server_input (int key) -{ - debug(RPT_DEBUG, "%s( key='%c' )", __FUNCTION__, (char) key); - - switch ((char) key) { - case INPUT_PAUSE_KEY: - if (screenlist_action == SCR_HOLD) - screenlist_action = 0; - else - screenlist_action = SCR_HOLD; - break; - case INPUT_BACK_KEY: - screenlist_action = SCR_BACK; - screenlist_prev (); - break; - case INPUT_FORWARD_KEY: - screenlist_action = SCR_SKIP; - screenlist_next (); - break; - case INPUT_MAIN_MENU_KEY: - debug (RPT_DEBUG, "%s: got the menu key!", __FUNCTION__); - //server_menu (); - report (RPT_ERR, "MENU TEMPORATY DISABLED"); - break; - default: - debug (RPT_DEBUG, "%s: Unused key \"%c\" (%i)", __FUNCTION__, (char) key, key); - break; - } - - return 0; -} - int input_reserve_key (char * key, bool exclusive, Client * client) { KeyReservation * kr; diff --git a/server/input.h b/server/input.h index 1836cf0..4abfcce 100644 --- a/server/input.h +++ b/server/input.h @@ -6,6 +6,7 @@ * COPYING file distributed with this package. * * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2003, Joris Robijn * */ @@ -42,15 +43,20 @@ typedef struct KeyReservation { 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 */ + void input_release_key (char * key, Client * client); /* Releases a key reservation */ + void input_release_client_keys (Client * client); /* Releases all key reservations for a given client */ + KeyReservation * input_find_key (char * key, Client * client); /* Finds if a key reservation causes a 'hit'. * If the key was reserved exclusively, the client will be ignored. diff --git a/server/main.c b/server/main.c index 5623656..3764c1f 100644 --- a/server/main.c +++ b/server/main.c @@ -159,7 +159,7 @@ main (int argc, char **argv) signal (SIGTERM, exit_program); /* and "kill"...*/ 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 ! */ + signal (SIGHUP, catch_reload_signal); /* On SIGHUP reread config and restart the drivers ! */ /* Let's see if we can actually get this to work ;) */ /* @@ -273,7 +273,7 @@ process_command_line (int argc, char **argv) /* Reset getopt */ optind = 0; - opterr = 0; /* Prevent some message to strerr */ + opterr = 0; /* Prevent some messages to stderr */ /* Analyze options here.. (please try to keep list of options the * same everywhere) */ @@ -707,7 +707,7 @@ do_mainloop () if (render_lag > 0) { /* Time for a rendering stroke */ timer ++; - screenlist_update (); + screenlist_process (); s = screenlist_current (); /* TODO: Move this call to every client connection @@ -797,7 +797,7 @@ catch_reload_signal (int val) int interpret_boolean_arg (char *s) { - if( strcmp( s, "on" ) == 0 || strcmp( s, "yes" ) == 0 + if( strcmp( s, "on" ) == 0 || strcmp( s, "yes" ) == 0 || strcmp( s, "true" ) == 0 || strcmp( s, "1" ) == 0 ) { return 1; } diff --git a/server/main.h b/server/main.h index dc3da72..d60aa5c 100644 --- a/server/main.h +++ b/server/main.h @@ -21,7 +21,6 @@ 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; @@ -40,6 +39,7 @@ extern char *build_date; 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 :) */ + * If you get an overflow, please mail us and we will fix this personally + * for you ! */ #endif diff --git a/server/menuscreens.c b/server/menuscreens.c index dd5f44e..a628282 100644 --- a/server/menuscreens.c +++ b/server/menuscreens.c @@ -70,6 +70,10 @@ int menuscreens_init() /* Create screen */ menuscreen = screen_create ("_menu_screen", NULL); + menuscreen->priority = PRI_HIDDEN; + active_menuitem = NULL; + + screenlist_add (menuscreen); /* Build menu */ menuscreen_create_menu (); @@ -91,13 +95,14 @@ int menuscreens_shutdown() menuscreen_switch_item (NULL); /* Destroy the menuscreen */ + screenlist_remove (menuscreen); screen_destroy (menuscreen); menuscreen = NULL; - screens_menu = NULL; /* Destroy all menus */ menuitem_destroy (main_menu); main_menu = NULL; + screens_menu = NULL; /* Forget menu's key reservations */ input_release_client_keys (NULL); @@ -148,6 +153,7 @@ bool is_menu_key (char * key) void menuscreen_switch_item (MenuItem * new_menuitem) /* This function changes the menuitem to the given one, and does necesary * actions. + * To leave the menu system, specify NULL for new_menuitem. * The item will not be reset when the new item is a child of the last one. */ { @@ -162,21 +168,13 @@ void menuscreen_switch_item (MenuItem * new_menuitem) 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; - } + menuscreen->priority = PRI_HIDDEN; } else if (!old_menuitem && new_menuitem) { /* Menu is becoming active */ menuitem_reset (active_menuitem); menuitem_rebuild_screen (active_menuitem, menuscreen); - if (screenlist_add (menuscreen) < 0) { - report (RPT_ERR, "%s: Error queueing menu screen", __FUNCTION__); - return; - } - /* TODO: raise it ! */ + menuscreen->priority = PRI_INPUT; } else { /* We're left with the usual case: a menu level switch */ if( old_menuitem->parent != new_menuitem) { @@ -184,6 +182,7 @@ void menuscreen_switch_item (MenuItem * new_menuitem) } menuitem_rebuild_screen (active_menuitem, menuscreen); } + return; } void menuscreen_key_handler (char *key) @@ -430,10 +429,11 @@ menuscreen_add_screen (Screen * s) mi = menuitem_create_numeric ("", NULL, "Duration", 2, 3600, s->duration); menu_add_item (m, mi); - mi = menuitem_create_numeric ("", NULL, "Priority", 0, 255, s->priority); + mi = menuitem_create_ring ("", NULL, "Priority", "Hidden\tBackground\tForeground\tAlert\tInput", s->priority); menu_add_item (m, mi); } + void menuscreen_remove_screen (Screen * s) { @@ -450,3 +450,18 @@ menuscreen_remove_screen (Screen * s) menu_remove_item (screens_menu, m); menuitem_destroy (m); } + + +int +menuscreen_goto (Menu * menu) +{ + if( !active_menuitem ) { + /* OK we can do it */ + menuscreen_switch_item (menu); + return 0; + } + else { + /* Sorry there is a menu already active. */ + return -1; + } +} diff --git a/server/menuscreens.h b/server/menuscreens.h index a0e51ae..f4e2265 100644 --- a/server/menuscreens.h +++ b/server/menuscreens.h @@ -6,6 +6,8 @@ * COPYING file distributed with this package. * * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2003, Joris Robijn + * * * Creates all menuscreens, menus and handles the keypresses for the * menuscreens. @@ -48,6 +50,8 @@ void menuscreen_add_screen (Screen * s); /* Adds a menu for the given screen */ void menuscreen_remove_screen (Screen * s); -/* Removes the menu of the screen */ +/* Removes the menu of the given screen */ + +int menuscreen_goto (Menu * menu); #endif diff --git a/server/render.c b/server/render.c index f3e77a0..fbe52e7 100644 --- a/server/render.c +++ b/server/render.c @@ -194,20 +194,6 @@ render_frame (LinkedList * list, if (fy < 0) fy = 0; - /* Make sure the whole frame gets displayed, at least... - * ...by setting the action to RENDER_HOLD if no other action - * is currently defined... - */ - - if (!screenlist_action) - screenlist_action = RENDER_HOLD; - - if ((fy) > fhgt - 1) { - /* Release hold after it has been displayed */ - if (!screenlist_action || screenlist_action == RENDER_HOLD) - screenlist_action = 0; - } - if (fhgt == 0) { fy = 0; } else { fy %= fhgt; } if (fy > fhgt - vis_height) fy = fhgt - vis_height; @@ -221,11 +207,6 @@ render_frame (LinkedList * list, /*debug(RPT_DEBUG, "%s: %8x, %i", __FUNCTION__, frame, timer); */ -#define PositiveX(a) ((a)->x > 0) -#define PositiveY(a) ((a)->y > 0) -#define ValidPoint(a) (PositiveX(a) && PositiveY(a)) -#define TextPresent(a) ((a)->text) - LL_Rewind (list); do { w = (Widget *) LL_Get (list); @@ -235,7 +216,7 @@ render_frame (LinkedList * list, /* TODO: Make this cleaner and more flexible!*/ switch (w->type) { case WID_STRING: - if (ValidPoint(w) && TextPresent(w)) { + if (w->x>0 && w->y>0 && w->text) { if ((w->y <= vis_height + fy) && (w->y > fy)) { if (w->x > vis_width) w->x=vis_width; strncpy (str, w->text, vis_width - w->x + 1); @@ -318,14 +299,6 @@ render_frame (LinkedList * list, x = timer / speed; y = x / length; - /* Make sure the whole title gets displayed, at least...*/ - if (!screenlist_action) - screenlist_action = RENDER_HOLD; - if (x > length - 6) { - /* Release hold after it has been displayed*/ - if (!screenlist_action || screenlist_action == RENDER_HOLD) - screenlist_action = 0; - } x %= (length); if (x < 0) x = 0; @@ -370,8 +343,6 @@ render_frame (LinkedList * list, } else { int effLength = length - screen_width; int necessaryTimeUnits = 0; - if (!screenlist_action) - screenlist_action = RENDER_HOLD; if (w->speed > 0) { necessaryTimeUnits = effLength * w->speed; if (((timer / (effLength * w->speed)) % 2) == 0) { @@ -395,12 +366,6 @@ render_frame (LinkedList * list, } } else { offset = 0; - if (screenlist_action == RENDER_HOLD) - screenlist_action = 0; - } - if (timer > necessaryTimeUnits) { - if (screenlist_action == RENDER_HOLD) - screenlist_action = 0; } if (offset <= length) { strncpy (str, &((w->text)[offset]), screen_width); @@ -437,8 +402,6 @@ render_frame (LinkedList * list, int necessaryTimeUnits = 0; int effLines = lines_required - available_lines + 1; int begin = 0; - if (!screenlist_action) - screenlist_action = RENDER_HOLD; /*debug(RPT_DEBUG, "length: %d sw: %d lines req: %d avail lines: %d effLines: %d ",length,screen_width,lines_required,available_lines,effLines);*/ if (w->speed > 0) { necessaryTimeUnits = effLines * w->speed; @@ -473,10 +436,6 @@ render_frame (LinkedList * list, /*str,w->text); */ drivers_string (w->left, w->top + (i - begin), str); } - if (timer > necessaryTimeUnits) { - if (screenlist_action == RENDER_HOLD) - screenlist_action = 0; - } } } break; diff --git a/server/screen.c b/server/screen.c index ede482c..aac403e 100644 --- a/server/screen.c +++ b/server/screen.c @@ -6,6 +6,7 @@ * COPYING file distributed with this package. * * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2003, Joris Robijn * * * Does screen management @@ -31,6 +32,16 @@ int default_duration = 0; int default_timeout = -1; +char *pri_names[] = { + "hidden", + "background", + "info", + "foreground", + "alert", + "input", + NULL, +}; + Screen * screen_create (char * id, Client * client) { @@ -56,7 +67,7 @@ screen_create (char * id, Client * client) } s->name = NULL; - s->priority = DEFAULT_SCREEN_PRIORITY; + s->priority = PRI_INFO; s->duration = default_duration; s->backlight = BACKLIGHT_OPEN; s->heartbeat = HEARTBEAT_OPEN; @@ -157,3 +168,24 @@ screen_find_widget (Screen * s, char *id) debug (RPT_DEBUG, "%s: Not found", __FUNCTION__); return NULL; } + +Priority +screen_pri_name_to_pri (char * priname) +{ + Priority pri = WID_NONE; + int i; + + for (i = 0; pri_names[i]; i++) { + if (strcmp (pri_names[i], priname) == 0) { + pri = i; + break; /* it's valid: skip out...*/ + } + } + return pri; +} + +char * +screen_pri_to_pri_name (Priority pri) +{ + return pri_names[pri]; +} diff --git a/server/screen.h b/server/screen.h index a5d5d51..fcf4849 100644 --- a/server/screen.h +++ b/server/screen.h @@ -6,6 +6,7 @@ * COPYING file distributed with this package. * * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2003, Joris Robijn * */ @@ -20,13 +21,17 @@ #include "shared/LL.h" #include "client.h" +typedef enum { PRI_HIDDEN, PRI_BACKGROUND, PRI_INFO, PRI_FOREGROUND, + PRI_ALERT, PRI_INPUT +} Priority; + typedef struct Screen { char *id; char *name; int width, height; int duration; int timeout; - short int priority; + Priority priority; short int heartbeat; short int backlight; short int cursor; @@ -72,4 +77,8 @@ static inline Widget * screen_getnext_widget (Screen * s) /* Find a widget in a screen */ Widget *screen_find_widget (Screen * s, char *id); +/* Convert priority names to priority and vv */ +Priority screen_pri_name_to_pri (char * pri_name); +char * screen_pri_to_pri_name (Priority pri); + #endif diff --git a/server/screenlist.c b/server/screenlist.c index 65d9038..c117e99 100644 --- a/server/screenlist.c +++ b/server/screenlist.c @@ -6,9 +6,11 @@ * COPYING file distributed with this package. * * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2003, Joris Robijn * * - * All actions that can be performed on the list of screens + * All actions that can be performed on the list of screens. + * This file also manages the rotation of screens. * */ @@ -19,26 +21,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; +/* Local functions */ +int compare_priority (void *one, void *two); +bool autorotate = 1; /* If on, INFO and FOREGROUND screens will rotate */ LinkedList *screenlist = NULL; Screen * current_screen = NULL; +long int current_screen_start_time = 0; -int screenlist_add_end (Screen * screen); -Screen *screenlist_next_roll (); -Screen *screenlist_prev_roll (); -Screen *screenlist_next_priority (); - -int compare_priority (void *one, void *two); -int compare_addresses (void *one, void *two); int screenlist_init () @@ -47,13 +41,13 @@ screenlist_init () screenlist = LL_new (); if (!screenlist) { - report(RPT_ERR, "%s: error allocating list", __FUNCTION__); + report(RPT_ERR, "%s: Error allocating", __FUNCTION__); return -1; } - screenlist_action = 0; return 0; } + int screenlist_shutdown () { @@ -68,77 +62,110 @@ screenlist_shutdown () return 0; } + +int +screenlist_add (Screen * s) +{ + if (!screenlist) + return -1; + return LL_Push (screenlist, s); +} + + int screenlist_remove (Screen * s) { debug (RPT_DEBUG, "%s( s=[%.40s] )", __FUNCTION__, s->id); - if (!LL_Remove (screenlist, s)) + if (!screenlist) return -1; - else - return 0; + + /* Are we trying to remove the current screen ? */ + if (s == current_screen) { + screenlist_goto_next (); + if (s == current_screen) { + /* Hmm, no other screen had same priority */ + void * res = LL_Remove (screenlist, s); + /* And now once more */ + screenlist_goto_next (); + return (res == NULL) ? -1 : 0; + } + } + return (LL_Remove (screenlist, s) == NULL) ? -1 : 0; } -int -screenlist_remove_all (Screen * s) -{ - int i = 0; - - debug (RPT_DEBUG, "%s( s=[%.40s] )", __FUNCTION__, s->id); - - while (LL_Remove (screenlist, s)) - i++; - - debug (RPT_DEBUG, "screenlist_remove_all()... got %i", i); - - return i; -} void -screenlist_update () -/* Decide if we need to switch to an other screen. - */ +screenlist_process () { Screen * s; + Screen * f; report (RPT_DEBUG, "%s()", __FUNCTION__); + if (!screenlist) + return; + + /* Sort the list acfording to priority class */ + LL_Sort (screenlist, compare_priority); + f = LL_GetFirst(screenlist); + + /**** First we need to check out the current situation. ****/ + + /* Check whether there is an active screen */ s = screenlist_current (); if (!s) { - /* Try to switch to the first screen in the list */ + /* We have no active screen yet. + * Try to switch to the first screen in the list... */ - s = LL_GetFirst(screenlist); + s = f; if (!s) { /* There was no screen in the list */ return; } screenlist_switch (s); + return; } - 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); + else { + /* There already was an active screen. + * Check to see if it has an expiry time. If so, decrease it + * and then check to see if it has expired. Remove the screen + * if expired. */ + if (s->timeout != -1) { + --(s->timeout); + report(RPT_DEBUG, "Active screen [%.40s] has timeout->%d", s->id, s->timeout); + if (s->timeout <= 0) { + /* Expired, we can destroy it */ + report(RPT_DEBUG, "Removing expired screen [%.40s]", s->id); + client_remove_screen (s->client, s); + screen_destroy (s); + } } } - for (s=LL_GetFirst(screenlist); s; s=LL_GetNext(screenlist)) { - report( RPT_DEBUG, "%s: [%s] %d %d", __FUNCTION__, s->id, s->priority, s->duration ); + + /**** OK, current situation examined. We can now see if we need to switch. */ + + /* Is there a screen of a higher priority class than the + * current one ? */ + if (f->priority > s->priority) { + /* Yes, switch to that screen, job done */ + screenlist_switch(f); + return; + } + + /* Current screen has been visible long enough and is it of 'normal' + * priority ? + */ + if (autorotate && (timer - current_screen_start_time >= s->duration) + && s->priority > PRI_BACKGROUND && s->priority <= PRI_FOREGROUND) { + /* Ah, rotate! */ + screenlist_goto_next(); } } + void screenlist_switch (Screen * s) -/* Switch to an other screen */ { Client * c; char str[256]; @@ -175,122 +202,70 @@ screenlist_switch (Screen * s) current_screen_start_time = timer; } + Screen * screenlist_current () { return current_screen; } -int -screenlist_add (Screen * s) -{ - /* TODO: Different queueing modes...*/ - return screenlist_add_end (s); -} -Screen * -screenlist_next () +int +screenlist_goto_next () { Screen *s; debug (RPT_DEBUG, "%s()", __FUNCTION__); - s = screenlist_current (); + if (!current_screen) + return -1; - /* If we're on hold, don't advance!*/ - if (screenlist_action == SCR_HOLD) - return s; - if (screenlist_action == RENDER_HOLD) - return s; + /* Find current screen in screenlist */ + for( s = LL_GetFirst(screenlist); s && s != current_screen; s = LL_GetNext(screenlist) ); - /* Otherwise, reset it to regular operation*/ - screenlist_action = 0; - - /*debug(RPT_DEBUG, "Screenlist_next: calling handler...");*/ - - /* Call the selected queuing function...*/ - /* TODO: Different queueing modes...*/ - s = screenlist_next_priority (); - /*s = screenlist_next_roll();*/ - - /*debug(RPT_DEBUG, "Screenlist_next() done");*/ - - return s; + /* One step forward */ + s = LL_GetNext(screenlist); + if( !s || s->priority < current_screen->priority) { + /* To far, go back to start of screenlist */ + s = LL_GetFirst(screenlist); + } + screenlist_switch (s); + return 0; } -Screen * -screenlist_prev () + +int +screenlist_goto_prev () { Screen *s; debug (RPT_DEBUG, "%s()", __FUNCTION__); - s = screenlist_current (); + if (!current_screen) + return -1; - /* If we're on hold, don't advance!*/ - if (screenlist_action == SCR_HOLD) - return s; - if (screenlist_action == RENDER_HOLD) - return s; + /* Find current screen in screenlist */ + for( s = LL_GetFirst(screenlist); s && s != current_screen; s = LL_GetNext(screenlist) ); - /* Otherwise, reset it no regular operation*/ - screenlist_action = 0; + /* One step back */ + s = LL_GetPrev(screenlist); + if( !s ) { + /* We're at the start of the screenlist. We should find the + * last screen with the same priority as the first screen. + */ + Screen * f = LL_GetFirst(screenlist); + Screen * n; - /* Call the selected queuing function...*/ - /* TODO: Different queueing modes...*/ - s = screenlist_prev_roll (); - - return s; -} - -/* Adds new screens to the end of the screenlist...*/ -int -screenlist_add_end (Screen * screen) -{ - debug (RPT_DEBUG, "%s( screen=[%.40s] )", __FUNCTION__, screen->id); - - return LL_Push (screenlist, (void *) screen); -} - -/* Simple round-robin approach to screen cycling...*/ -Screen * -screenlist_next_roll () -{ - debug (RPT_DEBUG, "%s()", __FUNCTION__); - - if (LL_UnRoll (screenlist) != 0) - return NULL; - - return screenlist_current (); -} - -/* Strict priority queue approach...*/ -Screen * -screenlist_next_priority () -{ - /*screen *s, *t;*/ - debug (RPT_DEBUG, "%s()", __FUNCTION__); - - if (LL_UnRoll (screenlist) != 0) - return NULL; - - LL_Sort (screenlist, compare_priority); - - return LL_Get (screenlist); -} - -/* Simple round-robin approach to screen cycling...*/ -Screen * -screenlist_prev_roll () -{ - debug (RPT_DEBUG, "%s()", __FUNCTION__); - - if (LL_Roll (screenlist) != 0) - return NULL; - - return screenlist_current (); + s = f; + while( (n = LL_GetNext(screenlist)) && n->priority == f->priority ) { + s = n; + } + } + screenlist_switch (s); + return 0; } +/* Internal function for sorting. */ int compare_priority (void *one, void *two) { @@ -308,12 +283,5 @@ compare_priority (void *one, void *two) /*debug(RPT_DEBUG, "compare_priority: done?");*/ - return (a->priority - b->priority); -} - -int -compare_addresses (void *one, void *two) -{ - /*debug(RPT_DEBUG, "compare_addresses: %p == %p ???", one, two);*/ - return (one != two); + return (b->priority - a->priority); } diff --git a/server/screenlist.h b/server/screenlist.h index 83d1025..4f88386 100644 --- a/server/screenlist.h +++ b/server/screenlist.h @@ -6,6 +6,7 @@ * COPYING file distributed with this package. * * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2003, Joris Robijn * */ @@ -21,20 +22,36 @@ #define RENDER_SKIP 12 #define RENDER_BACK 13 -extern int screenlist_action; +/*extern int screenlist_action;*/ +extern bool autorotate; int screenlist_init (); -int screenlist_shutdown (); + /* Initializes the screenlist. */ -void screenlist_update (); -void screenlist_switch (Screen * s); -Screen *screenlist_current (); +int screenlist_shutdown (); + /* Shuts down the screenlist. */ int screenlist_add (Screen * s); -Screen *screenlist_next (); -Screen *screenlist_prev (); + /* Adds a screen to the screenlist. */ int screenlist_remove (Screen * s); -int screenlist_remove_all (Screen * s); + /* Removes a screen from the screenlist. */ + +void screenlist_process (); + /* Processes the screenlist. Decides if we need to switch to an other + * screen. */ + +void screenlist_switch (Screen * s); + /* Switches to an other screen in the proper way. Informs clients of + * the switch. ALWAYS USE THIS FUNCTION TO SWITCH SCREENS. */ + +Screen *screenlist_current (); + /* Returns the currently active screen. */ + +int screenlist_goto_next (); + /* Moves on to the next screen. */ + +int screenlist_goto_prev (); + /* Moves on to the previous screen. */ #endif diff --git a/server/serverscreens.c b/server/serverscreens.c index bbdaa6d..35e009c 100644 --- a/server/serverscreens.c +++ b/server/serverscreens.c @@ -6,6 +6,7 @@ * COPYING file distributed with this package. * * Copyright (c) 1999, William Ferrell, Scott Scriven + * 2002, Joris Robijn * * * Implements the serverscreens @@ -50,7 +51,7 @@ server_screen_init () } server_screen->name = "Server screen"; server_screen->duration = 8; /* 1 second, instead of 4...*/ - server_screen->priority = 255; + server_screen->priority = PRI_INFO; /* Create all the widgets...*/ for (line=1; line<=4; line++) { diff --git a/shared/report.c b/shared/report.c index da86e28..f750b9a 100644 --- a/shared/report.c +++ b/shared/report.c @@ -71,7 +71,7 @@ void report( const int level, const char *format, .../*args*/ ) int set_reporting( char *application_name, int new_level, int new_dest ) { if( new_level < RPT_CRIT || new_level > RPT_DEBUG ) { - report( RPT_ERR, "debug level invalid: %d", new_level ); + report( RPT_ERR, "report level invalid: %d", new_level ); return -1; }