Massive changes (first commit), including but not limited to:

* Ability to specify port and address to bind to
* By default, binds only to 127.0.0.1 port 13666
* Client commands now return usage when no options given
* New driver command: getinfo
* Added comments all over the place
* Used #defines to further document code
* Used #defines to set up compile-time defaults, etc.
* Cleaned up client command argument analysis in client_functions.c
* Beginning support of syslog
* Some bug fixes
This commit is contained in:
ddouthitt
2001-09-21 21:08:10 +00:00
parent 909f9791cf
commit 6a0e23dc3e
22 changed files with 1767 additions and 785 deletions
+1 -1
View File
@@ -153,7 +153,7 @@ main (int argc, char **argv)
usleep (500000); // wait for the server to start up
sock = sock_connect (server, port);
if (sock <= 0) {
printf ("Error connecting to server %s on port %i.\n", server, port);
printf ("Error connecting to LCD server %s on port %i.\nCheck to see that the server is running and operating normally.\n", server, port);
return 0;
}
sock_send_string (sock, "hello\n");
+11 -5
View File
@@ -16,6 +16,12 @@
#include "screen.h"
#include "screenlist.h"
#define ResetScreenList(a) LL_Rewind(a)
#define NewScreen LL_new
#define NextScreen(a) (screen *)LL_Get(a)
#define MoreScreens(a) (LL_Next(a) == 0)
#define DestroyScreenList(a) LL_Destroy(a)
int
client_data_init (client_data * d)
{
@@ -26,7 +32,7 @@ client_data_init (client_data * d)
d->name = NULL;
d->client_keys = NULL;
d->screenlist = LL_new ();
d->screenlist = NewScreen();
if (!d->screenlist) {
fprintf (stderr, "client_data_init: Error allocating screenlist\n");
return -1;
@@ -64,9 +70,9 @@ client_data_destroy (client_data * d)
// Clean up the screenlist...
debug ("client_data_destroy: Cleaning screenlist\n");
LL_Rewind (d->screenlist);
ResetScreenList (d->screenlist);
do {
s = (screen *) LL_Get (d->screenlist);
s = NextScreen(d->screenlist);
if (s) {
debug ("client_data_destroy: removing screen %s\n", s->id);
@@ -80,8 +86,8 @@ client_data_destroy (client_data * d)
// Free its memory...
screen_destroy (s);
}
} while (LL_Next (d->screenlist) == 0);
LL_Destroy (d->screenlist);
} while (MoreScreens(d->screenlist));
DestroyScreenList(d->screenlist);
// TODO: clean up the rest of the data...
+502 -203
View File
File diff suppressed because it is too large Load Diff
+13 -9
View File
@@ -15,7 +15,9 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include "sock.h"
#include "clients.h"
#include "client_data.h"
#include "shared/debug.h"
@@ -40,7 +42,6 @@ client_init ()
int
client_shutdown ()
{
// TODO: Close all connections first...
client *c;
debug ("client_shutdown()\n");
@@ -52,7 +53,7 @@ client_shutdown ()
debug ("client_shutdown: ...\n");
if (c) {
debug ("client_shutdown: ... %i ...\n", c->sock);
if (0 != client_destroy (c)) {
if (client_destroy (c) != 0) {
fprintf (stderr, "client_shutdown: Error freeing client\n");
} else {
debug ("client_shutdown: Freed client...\n");
@@ -70,6 +71,9 @@ client_shutdown ()
return 0;
}
// A client is identified by the file descriptor
// associated with it.
//
// Create and destroy clients....
client *
client_create (int sock)
@@ -117,7 +121,6 @@ client_create (int sock)
int
client_destroy (client * c)
{
// TODO: Close the socket connection here?
int err;
char *str;
@@ -136,17 +139,18 @@ client_destroy (client * c)
}
}
// close socket...
if (c->sock) {
// sock_send_string (c->sock, "bye\n");
close(c->sock);
syslog(LOG_NOTICE, "closed socket for #%d\n", c->sock);
}
err = LL_Destroy (c->messages);
// Free client's other data
client_data_destroy (c->data);
/*
// FIXME? Should the connection get closed here or elsewhere?
if(c->sock) close(c->sock);
c->sock = 0;
*/
// Remove the client from the clients list...
LL_Remove (clients, c);
+1
View File
@@ -6,6 +6,7 @@
typedef struct client {
int sock;
char addr[64];
LL *messages;
client_data *data;
+366 -86
View File
@@ -1,10 +1,24 @@
/*
* Matrix Orbital driver
*
* For the Matrix Orbital LCD* LKD* VFD* and VKD* displays
*
* September 16, 2001
*
* NOTE: GLK displays have a different driver.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <syslog.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -16,6 +30,26 @@
#include "shared/debug.h"
#include "shared/str.h"
#define DEFAULT_CONTRAST 140
#define DEFAULT_DEVICE "/dev/lcd"
#define DEFAULT_SPEED B19200
#define DEFAULT_LINEWRAP 1
#define DEFAULT_AUTOSCROLL 1
#define DEFAULT_CURSORBLINK 0
#define GENERIC (void *) -1
#define IS_LCD_DISPLAY (MtxOrb_type == MTXORB_LCD)
#define IS_LKD_DISPLAY (MtxOrb_type == MTXORB_LKD)
#define IS_VFD_DISPLAY (MtxOrb_type == MTXORB_VFD)
#define IS_VKD_DISPLAY (MtxOrb_type == MTXORB_VKD)
#define NotEnoughArgs (i + 1 > argc)
// NOTE: This does not appear to make use of the
// hbar and vbar functions present in the LKD202-25.
// Why I do not know.
static int custom = 0;
static enum {MTXORB_LCD, MTXORB_LKD, MTXORB_VFD, MTXORB_VKD} MtxOrb_type;
@@ -65,25 +99,102 @@ static void MtxOrb_linewrap (int on);
static void MtxOrb_autoscroll (int on);
static void MtxOrb_cursorblink (int on);
int
MtxOrb_set_type (char * str) {
char c;
c = str[0];
if (c == 'l') {
if (strcmp(str, "lcd") == 0) {
return MTXORB_LCD;
} else if (strcmp(str, "lkd") == 0) {
return MTXORB_LKD;
} else {
fprintf (stderr, "MtxOrb_init: unknwon display type %s; must be one of lcd, lkd, vfd, or vkd\n", str);
}
} else if (c == 'v') {
if (strcmp (str, "vfd") == 0) {
return MTXORB_VFD;
} else if (strcmp (str, "vkd") == 0) {
return MTXORB_VKD;
} else {
fprintf (stderr, "MtxOrb_init: unknwon display type %s; must be one of lcd, lkd, vfd, or vkd\n", str);
}
} else {
fprintf (stderr, "MtxOrb_init: unknwon display type %s; must be one of lcd, lkd, vfd, or vkd\n", str);
}
return (-1);
}
int
MtxOrb_get_speed (char *arg) {
int speed;
switch (atoi(arg)) {
case 1200: speed = B1200; break;
case 2400: speed = B2400; break;
case 9600: speed = B9600; break;
case 19200: speed = B19200; break;
default:
speed = DEFAULT_SPEED;
fprintf (stderr, "MtxOrb_init: argument must be 1200, 2400, 9600 or 19200. Using default value");
switch (speed) {
case B1200: fprintf(stderr, " of 1200 baud.\n"); break;
case B2400: fprintf(stderr, " of 2400 baud.\n"); break;
case B9600: fprintf(stderr, " of 9600 baud.\n"); break;
case B19200: fprintf(stderr, " of 19200 baud.\n"); break;
default: fprintf(stderr, ".\n"); break;
}
}
return speed;
}
void
MtxOrb_usage (void) {
printf ("LCDproc Matrix-Orbital LCD driver\n"
"\t-d\t--device\tSelect the output device to use [/dev/lcd]\n"
// "\t-t\t--type\t\tSelect the LCD type (size) [20x4]\n"
// "\t-b\t--backlight\tSelect the backlight state [on]\n"
"\t-c\t--contrast\tSet the initial contrast [140]\n"
"\t-s\t--speed\t\tSet the communication speed [19200]\n"
"\t-h\t--help\t\tShow this help information\n"
"\t-t\t--type\t\tdisplay type: lcd, lkd, vfd, vkd\n");
}
int
MtxOrb_set_contrast (char * str) {
int contrast;
contrast = atoi (str);
if ((contrast < 0) || (contrast > 255)) {
fprintf(stderr, "MtxOrb_init: argument must between 0 and 255 (found %s). Using default contrast value of %d.\n", str, DEFAULT_CONTRAST);
contrast = DEFAULT_CONTRAST;
}
return contrast;
}
// TODO: Get rid of this variable?
lcd_logical_driver *MtxOrb;
lcd_logical_driver *MtxOrb; // set by MtxOrb_init(); doesn't seem to be used anywhere
// TODO: Get the frame buffers working right
/////////////////////////////////////////////////////////////////
// Opens com port and sets baud correctly...
//
// Called to initialize driver settings
//
int
MtxOrb_init (lcd_logical_driver * driver, char *args)
{
char *argv[64];
char *argv[64]; // Notice: 64 arguments - overflows?
int argc;
struct termios portset;
int i;
int tmp;
int contrast = 140;
char device[256] = "/dev/lcd";
int speed = B19200;
int contrast = DEFAULT_CONTRAST;
char device[256] = DEFAULT_DEVICE;
int speed = DEFAULT_SPEED;
MtxOrb_type = MTXORB_LKD ; // Assume it's an LCD w/keypad
MtxOrb = driver;
@@ -166,10 +277,19 @@ MtxOrb_init (lcd_logical_driver * driver, char *args)
// Set up io port correctly, and open it...
fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
fprintf (stderr, "MtxOrb_init: failed (%s)\n", strerror (errno));
return -1;
}
//else fprintf(stderr, "MtxOrb_init: opened device %s\n", device);
switch (errno) {
case ENOENT: fprintf(stderr, "MtxOrb_init: %s device file missing!\n", device);
break;
case EACCES: fprintf(stderr, "MtxOrb_init: %s device could not be opened...\n", device);
fprintf(stderr, "MtxOrb_init: perhaps you should run LCDd as root?\n");
break;
default: fprintf (stderr, "MtxOrb_init: failed (%s)\n", strerror (errno));
break;
}
return -1;
} else
syslog(LOG_INFO, "opened Matrix Orbital display on %s\n", device);
tcgetattr (fd, &portset);
// We use RAW mode
@@ -193,29 +313,32 @@ MtxOrb_init (lcd_logical_driver * driver, char *args)
// Do it...
tcsetattr (fd, TCSANOW, &portset);
// Set display-specific stuff..
MtxOrb_linewrap (1);
MtxOrb_autoscroll (1);
MtxOrb_cursorblink (0);
/*
* Configure display
*/
MtxOrb_linewrap (DEFAULT_LINEWRAP);
MtxOrb_autoscroll (DEFAULT_AUTOSCROLL);
MtxOrb_cursorblink (DEFAULT_CURSORBLINK);
MtxOrb_contrast (contrast);
if (!driver->framebuf) {
fprintf (stderr, "MtxOrb_init: No frame buffer.\n");
driver->close ();
return -1;
}
// Set the functions the driver supports...
// driver->clear = (void *)-1;
driver->clear = MtxOrb_clear;
driver->string = (void *) -1;
// driver->chr = MtxOrb_chr;
driver->chr = (void *) -1;
/*
* Configure the display functions
*/
driver->clear = MtxOrb_clear; // was GENERIC
driver->string = GENERIC;
driver->chr = MtxOrb_chr; // was GENERIC
driver->vbar = MtxOrb_vbar;
driver->init_vbar = MtxOrb_init_vbar;
// driver->init_vbar = (void *)-1;
driver->init_vbar = MtxOrb_init_vbar; // was GENERIC
driver->hbar = MtxOrb_hbar;
driver->init_hbar = MtxOrb_init_hbar;
// driver->init_hbar = (void *)-1;
driver->init_hbar = MtxOrb_init_hbar; // was GENERIC
driver->num = MtxOrb_num;
driver->init_num = MtxOrb_init_num;
@@ -231,8 +354,7 @@ MtxOrb_init (lcd_logical_driver * driver, char *args)
driver->draw_frame = MtxOrb_draw_frame;
driver->getkey = MtxOrb_getkey;
MtxOrb_contrast (contrast);
driver->getinfo = MtxOrb_getinfo;
return fd;
}
@@ -243,11 +365,15 @@ MtxOrb_init (lcd_logical_driver * driver, char *args)
// forget bar caracter not in use anymore and reuse the
// slot for another bar caracter.
//
// Why not just use Matrix Orbital's "clear screen" function or output a "^L"?
// This reliance on drv_base_clear seems suspicious... especially as
// using a (void *) -1 in the driver structure does the same thing...
//
void
MtxOrb_clear ()
{
// REMOVE: fprintf(stderr, "GLU: MtxOrb_clear.\n");
drv_base_clear ();
drv_base_clear (); // do we need this?
write(fd, "\x0FEX", 2); // instant clear...
clear = 1;
}
@@ -280,7 +406,7 @@ MtxOrb_flush_box (int lft, int top, int rgt, int bot)
// printf("Flush (%i,%i)-(%i,%i)\n", lft, top, rgt, bot);
for (y = top; y <= bot; y++) {
sprintf (out, "%cG%c%c", 254, lft, y);
sprintf (out, "\x0FEG%c%c", lft, y);
write (fd, out, 4);
write (fd, lcd.framebuf + (y * lcd.wid) + lft, rgt - lft + 1);
@@ -295,9 +421,25 @@ MtxOrb_flush_box (int lft, int top, int rgt, int bot)
void
MtxOrb_chr (int x, int y, char c)
{
y--;
x--;
char out[10];
// validate x and y
if (y > lcd.hgt)
y = lcd.hgt;
if (x > lcd.wid)
x = lcd.wid;
if (y < 1)
y = 1;
if (x < 1)
x = 1;
// write immediately to screen... this code was taken
// from the LK202-25; should work for others, yes?
sprintf(out, "\x0FEG%c%c%c", x, y, c);
write (fd, out, 4);
// write to frame buffer
y--; x--;
lcd.framebuf[(y * lcd.wid) + x] = c;
}
@@ -310,35 +452,49 @@ int
MtxOrb_contrast (int contrast)
{
char out[4];
static int status = 140;
if ( ((MtxOrb_type == MTXORB_LCD) || (MtxOrb_type == MTXORB_LKD)) &&
(contrast > 0) ) {
status = contrast;
sprintf (out, "%cP%c", 254, status);
// validate contrast value
if (contrast > 255)
contrast = 255;
if (contrast < 0)
contrast = 0;
if (IS_LCD_DISPLAY || IS_LKD_DISPLAY) {
sprintf (out, "\x0FEP%c", contrast);
write (fd, out, 3);
}
return status;
return contrast;
}
/////////////////////////////////////////////////////////////////
// Sets the backlight on or off -- can be done quickly for
// an intermediate brightness...
// WARN: off switches vfd/vkd displays off
// -> so it's maybe the best to start LCDd with -b on
//
// WARNING: off switches vfd/vkd displays off entirely
// so maybe it is best to start LCDd with -b on
//
// WARNING: there seems to be a movement afoot to add more
// functions than just on/off to this..
#define BACKLIGHT_OFF 0
#define BACKLIGHT_ON 1
void
MtxOrb_backlight (int on)
{
char out[4];
if (on) {
sprintf (out, "%cB%c", 254, 0);
write (fd, out, 3);
} else {
sprintf (out, "%cF", 254);
write (fd, out, 2);
}
switch (on) {
case BACKLIGHT_ON:
write (fd, "\x0FE" "F", 2);
break;
case BACKLIGHT_OFF:
if (IS_VKD_DISPLAY || IS_VFD_DISPLAY)
; // turns display off entirely (whoops!)
else
write (fd, "\x0FE" "B" "\x000", 3);
break;
default: // ignored...
break;
}
}
/////////////////////////////////////////////////////////////////
@@ -350,21 +506,24 @@ void
MtxOrb_output (int on)
{
char out[5];
if ( ((MtxOrb_type == MTXORB_LCD) || (MtxOrb_type == MTXORB_VFD)) ) {
if (on) {
sprintf (out, "%cW", 254);
} else {
sprintf (out, "%cV", 254);
}
write (fd, out, 2);
if (IS_LCD_DISPLAY || IS_VFD_DISPLAY) {
// LCD and VFD displays only have one output port
(on) ?
write (fd, "\x0FEW", 2) :
write (fd, "\x0FEV", 2);
} else {
int i;
for(i=0; i<6; i++) {
if ( on & (1 << i) ) {
sprintf (out, "%cW%c", 254, i+1);
} else {
sprintf (out, "%cV%c", 254, i+1);
}
// Other displays have six output ports;
// the value "on" is a binary value determining which
// ports are turned on (1) and off (0).
on = on & 077; // strip to six bits
for(i = 0; i < 6; i++) {
(on & (1 << i)) ?
sprintf (out, "\x0FEW%c", i + 1) :
sprintf (out, "\x0FEV%c", i + 1);
write (fd, out, 3);
}
}
@@ -376,12 +535,7 @@ MtxOrb_output (int on)
static void
MtxOrb_linewrap (int on)
{
char out[4];
if (on)
sprintf (out, "%cC", 254);
else
sprintf (out, "%cD", 254);
write (fd, out, 2);
(on) ? write (fd, "\x0FE" "C", 2) : write (fd, "\x0FE" "D", 2);
}
/////////////////////////////////////////////////////////////////
@@ -390,12 +544,7 @@ MtxOrb_linewrap (int on)
static void
MtxOrb_autoscroll (int on)
{
char out[4];
if (on)
sprintf (out, "%cQ", 254);
else
sprintf (out, "%cR", 254);
write (fd, out, 2);
(on) ? write (fd, "\x0FEQ", 2) : write (fd, "\x0FER", 2);
}
// TODO: make sure this doesn't mess up non-VFD displays
@@ -405,12 +554,7 @@ MtxOrb_autoscroll (int on)
static void
MtxOrb_cursorblink (int on)
{
char out[4];
if (on)
sprintf (out, "%cS", 254);
else
sprintf (out, "%cT", 254);
write (fd, out, 2);
(on) ? write (fd, "\x0FES", 2) : write (fd, "\x0FET", 2);
}
//// TODO: Might not be needed anymore...
@@ -420,6 +564,7 @@ MtxOrb_cursorblink (int on)
void
MtxOrb_init_vbar ()
{
// Isn't this function supposed to go away?
MtxOrb_init_all (vbar);
}
@@ -430,9 +575,132 @@ MtxOrb_init_vbar ()
void
MtxOrb_init_hbar ()
{
// Isn't this function supposed to go away?
MtxOrb_init_all (hbar);
}
/////////////////////////////////////////////////////////////////
// Returns string with general information about the display
//
char *
MtxOrb_getinfo (void)
{
char in = 0;
static char info[255];
char tmp[255], buf[64];
int i = 0;
fd_set rfds;
struct timeval tv;
int retval;
memset(info, '\0', sizeof(info));
strcpy(info, "Matrix Orbital Driver ");
/*
* Read type of display
*/
write(fd, "\x0FE" "7", 2);
/* Watch fd to see when it has input. */
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
/* Wait the specified amount of time. */
tv.tv_sec = 0; // seconds
tv.tv_usec = 500; // microseconds
retval = select(1, &rfds, NULL, NULL, &tv);
if (retval) {
if (read (fd, &in, 1) < 0) {
syslog(LOG_WARNING, "MatrixOrbital driver: unable to read data");
} else {
switch (in) {
case '\x01': strcat(info, "LCD0821 "); break;
case '\x03': strcat(info, "LCD2021 "); break;
case '\x04': strcat(info, "LCD1641 "); break;
case '\x05': strcat(info, "LCD2041 "); break;
case '\x06': strcat(info, "LCD4021 "); break;
case '\x07': strcat(info, "LCD4041 "); break;
case '\x08': strcat(info, "LK202-25 "); break;
case '\x09': strcat(info, "LK204-25 "); break;
case '\x0A': strcat(info, "LK404-55 "); break;
case '\x0B': strcat(info, "VFD2021 "); break;
case '\x0C': strcat(info, "VFD2041 "); break;
case '\x0D': strcat(info, "VFD4021 "); break;
case '\x0E': strcat(info, "VK202-25 "); break;
case '\x0F': strcat(info, "VK204-25 "); break;
case '\x10': strcat(info, "GLC12232 "); break;
case '\x11': strcat(info, "GLC12864 "); break;
case '\x12': strcat(info, "GLC128128 "); break;
case '\x13': strcat(info, "GLC24064 "); break;
case '\x14': strcat(info, "GLK12864-25 "); break;
case '\x15': strcat(info, "GLK24064-25 "); break;
case '\x21': strcat(info, "GLK128128-25 "); break;
case '\x22': strcat(info, "GLK12232-25 "); break;
case '\x31': strcat(info, "LK404-AT "); break;
case '\x32': strcat(info, "VFD1621 "); break;
case '\x33': strcat(info, "LK402-12 "); break;
case '\x34': strcat(info, "LK162-12 "); break;
case '\x35': strcat(info, "LK204-25PC "); break;
default: //sprintf(tmp, "Unknown (%X) ", in); strcat(info, tmp);
break;
}
}
} else
syslog(LOG_WARNING, "MatrixOrbital driver: unable to read device type");
/*
* Read serial number of display
*/
memset(tmp, '\0', sizeof(tmp));
write(fd, "\x0FE" "5", 2);
/* Wait the specified amount of time. */
tv.tv_sec = 0; // seconds
tv.tv_usec = 500; // microseconds
retval = select(1, &rfds, NULL, NULL, &tv);
if (retval) {
if (read (fd, &tmp, 2) < 0) {
syslog(LOG_WARNING, "MatrixOrbital driver: unable to read data");
} else {
sprintf(buf, "Serial No: %ld ", (long int) tmp);
strcat(info, buf);
}
} else
syslog(LOG_WARNING, "MatrixOrbital driver: unable to read device serial number");
/*
* Read firmware revision number
*/
memset(tmp, '\0', sizeof(tmp));
write(fd, "\x0FE" "6", 2);
/* Wait the specified amount of time. */
tv.tv_sec = 0; // seconds
tv.tv_usec = 500; // microseconds
retval = select(1, &rfds, NULL, NULL, &tv);
if (retval) {
if (read (fd, &tmp, 2) < 0) {
syslog(LOG_WARNING, "MatrixOrbital driver: unable to read data");
} else {
sprintf(buf, "Firmware Rev. %ld ", (long int) tmp);
strcat(info, buf);
}
} else
syslog(LOG_WARNING, "MatrixOrbital driver: unable to read device firmware revision");
return info;
}
// TODO: Finish the support for bar growing reverse way.
// TODO: Need a "y" as input also !!!
/////////////////////////////////////////////////////////////////
@@ -447,9 +715,9 @@ MtxOrb_vbar (int x, int len)
int y;
// TODO: REMOVE THE NEXT LINE FOR TESTING ONLY...
// REMOVE THE NEXT LINE FOR TESTING ONLY...
// len=-len;
// TODO: REMOVE THE PREVIOUS LINE FOR TESTING ONLY...
// REMOVE THE PREVIOUS LINE FOR TESTING ONLY...
if (len > 0) {
for (y = lcd.hgt; y > 0 && len > 0; y--) {
@@ -518,10 +786,8 @@ MtxOrb_hbar (int x, int y, int len)
void
MtxOrb_init_num ()
{
char out[3];
if (custom != bign) {
sprintf (out, "%cn", 254);
write (fd, out, 2);
write (fd, "\x0FEn", 2);
custom = bign;
}
}
@@ -535,7 +801,7 @@ void
MtxOrb_num (int x, int num)
{
char out[5];
sprintf (out, "%c#%c%c", 254, x, num);
sprintf (out, "\x0FE#%c%c", x, num);
write (fd, out, 4);
}
@@ -560,7 +826,7 @@ MtxOrb_set_char (int n, char *dat)
if (!dat)
return;
sprintf (out, "%cN%c", 254, n);
sprintf (out, "\x0FEN%c", n);
write (fd, out, 3);
for (row = 0; row < lcd.cellhgt; row++) {
@@ -636,7 +902,7 @@ MtxOrb_draw_frame (char *dat)
write(fd, dat, lcd.wid*lcd.hgt);
*/
for (i = 0; i < lcd.hgt; i++) {
sprintf (out, "%cG%c%c", 254, 1, i + 1);
sprintf (out, "\x0FEG\x001%c", i + 1);
write (fd, out, 4);
write (fd, dat + (lcd.wid * i), lcd.wid);
}
@@ -650,6 +916,7 @@ char
MtxOrb_getkey ()
{
char in = 0;
read (fd, &in, 1);
return in;
}
@@ -802,6 +1069,17 @@ MtxOrb_ask_bar (int type)
return (pos);
}
/////////////////////////////////////////////////////////////
// Does the heartbeat...
//
char
MtxOrb_heartbeat (int timer)
{
MtxOrb_icon (!((timer + 4) & 5), 0);
MtxOrb_chr (lcd.wid, 1, 0);
return (char) 0;
}
/////////////////////////////////////////////////////////////////
// Sets up a well known character for use.
//
@@ -1044,6 +1322,8 @@ MtxOrb_set_known_char (int car, int type)
// TODO: Remove this code wich was use for developpement.
// PS: There might be reference to this code left, so keep it for some time.
//
// MtxOrb_init_hbar and MtxOrb_init_vbar use it; it's prototyped in MtxOrb.h ...
void
MtxOrb_init_all (int type)
{
+3 -1
View File
@@ -22,9 +22,11 @@ void MtxOrb_set_char (int n, char *dat);
void MtxOrb_icon (int which, char dest);
void MtxOrb_draw_frame (char *dat);
char MtxOrb_getkey ();
char * MtxOrb_getinfo ();
void MtxOrb_init_all (int type);
int MtxOrb_ask_bar (int type);
void MtxOrb_set_known_char (int car, int type);
// Isn't this function supposed to go away?
void MtxOrb_init_all (int type);
#endif
+17 -4
View File
@@ -1,3 +1,17 @@
/*
* Joystick input driver for LCDd
*
* Only two unique functions are defined:
*
* joy_getkey
* joy_close
*
* All others are at their defaults.
*
* The code here is configured for a Gravis Gamepad (2 axis, 4 button)
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
@@ -9,6 +23,9 @@
#include <sys/types.h>
#include <linux/joystick.h>
#ifndef JSIOCGNAME
#define JSIOCGNAME(len) _IOC(_IOC_READ, 'j', 0x13, len) /* get identifier string */
#endif
#include "shared/debug.h"
#include "shared/str.h"
@@ -18,10 +35,6 @@
#include "lcd.h"
#include "joy.h"
//////////////////////////////////////////////////////////////////////////
////////////////////// Base "class" to derive from ///////////////////////
//////////////////////////////////////////////////////////////////////////
lcd_logical_driver *joy;
int fd;
+59 -1
View File
@@ -11,6 +11,7 @@
#endif
#include "shared/LL.h"
#include "shared/debug.h"
#include "lcd.h"
@@ -68,6 +69,15 @@
#include "glk.h"
#endif
// Make program more readable and understandable;
// hide details...
#define ResetList(a) LL_Rewind(a)
#define GetDriverData(a) ((lcd_logical_driver *)LL_Get(a))
#define NextDriver(a) (LL_Next(a))
#define MoreDrivers(a) (LL_Next(a) == 0)
#define DriverPresent(a) (a)
#define FunctionPresent(a) ((a) != 0)
// TODO: Make a Windows server, and clients...?
lcd_logical_driver lcd;
@@ -120,7 +130,9 @@ lcd_physical_driver drivers[] = {
LL *list;
////////////////////////////////////////////////////////////
// This sets up which driver to use and initializes stuff.
// This function initializes a few basics as well as the
// "base" array. To initialize a specific driver, use the
// lcd_add_driver() function.
//
int
lcd_init (char *args)
@@ -134,8 +146,12 @@ lcd_init (char *args)
return -1;
}
// This sets up functions which call all drivers in
// round-robin fashion
lcd_drv_init (NULL, NULL);
// "base" driver is a special driver which is always
// loaded...
err = lcd_add_driver ("base", args);
lcd.wid = 20;
@@ -162,6 +178,10 @@ lcd_init (char *args)
// TODO: lcd_remove_driver()
// This initializes the specified driver and sends parameters to
// it. This is the function which calls, for example,
// MtxOrb_init. The specifics come from the drivers[] array.
//
int
lcd_add_driver (char *driver, char *args)
{
@@ -177,6 +197,8 @@ lcd_add_driver (char *driver, char *args)
//printf("Found driver: %s (%s)\n", drivers[i].name, driver);
// This creates an instance of the lcd structure specific to the
// driver... it is passed to the driver's init routine...
add = malloc (sizeof (lcd_logical_driver));
if (!add) {
printf ("Couldn't allocate driver \"%s\".\n", driver);
@@ -204,6 +226,7 @@ lcd_add_driver (char *driver, char *args)
LL_Push (list, (void *) add);
// This is where the driver itself is actually called;
return drivers[i].init (add, args);
}
}
@@ -241,6 +264,9 @@ lcd_shutdown ()
return 0;
}
// This sets up all of the "wrapper" driver functions
// which call all of the drivers in turn.
//
int
lcd_drv_init (struct lcd_logical_driver *driver, char *args)
{
@@ -290,6 +316,7 @@ lcd_drv_init (struct lcd_logical_driver *driver, char *args)
lcd.draw_frame = lcd_drv_draw_frame;
lcd.getkey = lcd_drv_getkey;
lcd.getinfo = lcd_drv_getinfo;
return 1; // 1 is arbitrary. (must be 1 or more)
}
@@ -713,3 +740,34 @@ lcd_drv_getkey ()
return 0;
}
#define MAX_INFO_BUF 1024
char *
lcd_drv_getinfo ()
{
static char info[MAX_INFO_BUF];
char *p;
lcd_logical_driver *driver;
memset(info, '\0', sizeof(info));
ResetList(list);
do {
driver = GetDriverData(list);
if (DriverPresent(driver)) {
if (FunctionPresent(driver->getinfo)) {
p = (char *) driver->getinfo ();
if (strlen(p) + strlen(info) < (MAX_INFO_BUF - 2)) {
strcat(info, p);
}
strcat(info, "\n");
}
}
} while (MoreDrivers(list));
return info;
}
+4
View File
@@ -52,6 +52,9 @@ typedef struct lcd_logical_driver {
// Returns 0 for "no key pressed", or (A-Z).
char (*getkey) ();
// Returns pointer to static string.
char * (*getinfo) ();
// more?
} lcd_logical_driver;
@@ -83,5 +86,6 @@ void lcd_drv_icon (int which, char dest);
void lcd_drv_flush_box (int lft, int top, int rgt, int bot);
void lcd_drv_draw_frame ();
char lcd_drv_getkey ();
char *lcd_drv_getinfo ();
#endif
+117 -52
View File
@@ -24,9 +24,49 @@
E-Z Ignored
*/
// These are the keys for a (likely) properly functioning LK202-25...
// #define KEY_UP 'I'
// #define KEY_DOWN 'J'
// #define KEY_LEFT 'O'
// #define KEY_RIGHT 'E'
// #define KEY_F1 'N'
// #define KEY_F2 'M'
// #define KEY_ENTER 'H'
// These are the keys for my (possibly) broken LK202-25...
#define KEY_UP 'I'
#define KEY_DOWN 'F'
#define KEY_LEFT 'K'
#define KEY_RIGHT 'A'
#define KEY_F1 'N'
// #define KEY_F2 'M'
// #define KEY_ENTER 'H'
// TODO: Generalize these into each driver...
//
// Really, what this comes down to, is different settings for
// different displays. Unless you want to recompile for all
// the defaults, these key settings must be in the driver.
//
// But then, which driver is active and which screen takes which
// input and... (sigh).
//
#define PAUSE_KEY KEY_F1
#define BACK_KEY KEY_LEFT
#define FORWARD_KEY KEY_RIGHT
#define MAIN_MENU_KEY KEY_DOWN
// This seems somewhat arbitrary, but it IS the original settings:
//
// #define PAUSE_KEY 'A'
// #define BACK_KEY 'B'
// #define FORWARD_KEY 'C'
// #define MAIN_MENU_KEY 'D'
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include "shared/sockets.h"
#include "shared/debug.h"
@@ -42,6 +82,11 @@
#include "input.h"
#define KeyWanted(a,b) ((a) && strchr((a), (b)))
#define CurrentScreen screenlist_current
#define FirstClient(a) (client *)LL_GetFirst(a);
#define NextClient(a) (client *)LL_GetNext(a);
int server_input (int key);
// FIXME! The server tends to crash when "E" is pressed.. (?!)
@@ -51,46 +96,65 @@ int server_input (int key);
int
handle_input ()
{
char str[256];
char str[15];
int key;
screen *s;
widget *w;
client *c;
key = lcd.getkey ();
if (!key)
if ((key = lcd.getkey ()) == 0)
return 0;
debug ("handle_input(%c)\n", (char) key);
//debug ("handle_input(%c)\n", (char) key);
if (key) {
// TODO: Interpret and translate keys!
// Sequence:
// Does the current screen want the key?
// IfTrue: handle and quit
// IfFalse:
// Let ALL clients handle it if they want
// Let Server handle it, too
//
// This leads to a unique situation:
// First: multiple clients may handle the same key in multiple ways
// Second: the server may handle the key differently yet
//
// Solution: Only the current screen can handle the key press.
// Alternately, only one client can handle the key press.
// Give current screen a shot at the key first
s = screenlist_current ();
if( s->keys && strchr( s->keys, key ) ) {
// This screen wants this key. Tell it we got one
sprintf(str, "key %c\n", key);
sock_send_string(s->parent->sock, str);
// Nobody else gets this key
} else {
// Give key to clients who want it
c = (client *)LL_GetFirst(clients);
while(c) {
// If the client should have this keypress...
if( c->data->client_keys && strchr(c->data->client_keys, key) ) {
// Send keypress to client
sprintf(str, "key %c\n", key);
sock_send_string(c->sock, str);
};
c = (client *)LL_GetNext(clients);
} // while clients
// TODO: Interpret and translate keys!
// Give server a shot at all keys
server_input (key);
}
};
// Give current screen a shot at the key first
s = CurrentScreen ();
if (KeyWanted(s->keys, key)) {
// This screen wants this key. Tell it we got one
snprintf(str, sizeof(str), "key %c\n", key);
sock_send_string(s->parent->sock, str);
// Nobody else gets this key
}
// if the current screen doesn't want it,
// ignore the key...
// else {
// // Give key to clients who want it
//
// c = FirstClient(clients);
//
// while (c) {
// // If the client should have this keypress...
// if(KeyWanted(c->data->client_keys,key)) {
// // Send keypress to client
// snprintf(str, sizeof(str), "key %c\n", key);
// sock_send_string(c->sock, str);
// break; // first come, first serve
// };
// c = NextClient(clients);
// } // while clients
//
// // Give server a shot at all keys
// server_input (key);
// }
return 0;
}
@@ -99,29 +163,30 @@ int
server_input (int key)
{
debug ("server_input(%c)\n", (char) key);
syslog(LOG_DEBUG, "key %d pressed on device", key);
switch (key) {
case 'A':
if (screenlist_action == SCR_HOLD)
screenlist_action = 0;
else
screenlist_action = SCR_HOLD;
break;
case 'B':
screenlist_action = SCR_BACK;
screenlist_prev ();
break;
case 'C':
screenlist_action = SCR_SKIP;
screenlist_next ();
break;
case 'D':
debug ("got the menu key!\n");
server_menu ();
break;
default:
debug ("server_input: Unused key \"%c\" (%i)\n", (char) key, key);
break;
switch ((char) key) {
case PAUSE_KEY:
if (screenlist_action == SCR_HOLD)
screenlist_action = 0;
else
screenlist_action = SCR_HOLD;
break;
case BACK_KEY:
screenlist_action = SCR_BACK;
screenlist_prev ();
break;
case FORWARD_KEY:
screenlist_action = SCR_SKIP;
screenlist_next ();
break;
case MAIN_MENU_KEY:
debug ("got the menu key!\n");
server_menu ();
break;
default:
debug ("server_input: Unused key \"%c\" (%i)\n", (char) key, key);
break;
}
return 0;
+121 -12
View File
@@ -18,6 +18,10 @@
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
#include <syslog.h>
#include "shared/debug.h"
@@ -32,10 +36,30 @@
#include "input.h"
#include "main.h"
#define MAX_TIMER 0x10000
#define DEFAULT_USER "nobody"
char *version = VERSION;
char *protocol_version = PROTOCOL_VERSION;
char *build_date = __DATE__;
/* Socket to bind to...
Using loopback is much more secure; it means that this port is
accessible only to programs running locally on the same host as LCDd.
Using variables for these means that (later) we can select which port
and which address to bind to at run time. */
char bind_addr[64] = "127.0.0.1";
int lcd_port = LCDPORT;
// The parameter structure and args[] should
// be removed when getopt(3) is implemented,
// as there won't be any need for them then.
typedef struct parameter {
char *sh, *lg; // short and long versions
} parameter;
// This is currently only a list of available arguments, but doesn't
// really *do* anything. It just helps to figure out which parameters
@@ -54,6 +78,34 @@ static parameter args[] = {
void exit_program (int val);
void HelpScreen ();
// At this point, this function will only succeed;
// all other options will stop the program.
// However, it may not always be thus; so we prepared
// for this possibility by making it return an int.
//
int drop_privs(char *user) {
struct passwd *pwent;
if (getuid() == 0 || geteuid() == 0) {
if ((pwent = getpwnam(user)) == NULL) {
if (errno) {
perror("LCDd: getpwnam");
exit(1);
} else {
fprintf(stderr, "user %s not a valid user!", user);
exit(1);
}
} else {
if (setuid(pwent->pw_uid) < 0) {
fprintf(stderr, "unable to switch to user %s\n", user);
perror("LCDd: setuid");
exit(1);
}
}
}
return 0;
}
int
main (int argc, char **argv)
{
@@ -64,6 +116,7 @@ main (int argc, char **argv)
int disable_server_screen = 1;
screen *s = NULL;
char *str, *ing; // strings for commandline handling
char *user = DEFAULT_USER;
// Ctrl-C will cause a clean exit...
signal (SIGINT, exit_program);
@@ -86,14 +139,31 @@ main (int argc, char **argv)
// Now, go into daemon mode...
#ifndef DEBUG
openlog("LCDd", LOG_PID, LOG_DAEMON);
syslog(LOG_NOTICE, "server version %s starting up (protocol version %s)",
version, protocol_version);
syslog(LOG_NOTICE, "server built on %s",
build_date);
if (daemon_mode) {
int child;
syslog(LOG_NOTICE, "server forking to background");
if ((child = fork ()) != 0) {
usleep (1500000); // Wait for child to initialize
exit (0); /* PARENT EXITS */
}
// This line removed because it eats error messages...
//setsid(); /* RELEASE TTY */
//
// After this point, as a daemon, no error messages should
// go to the console unless drastic; rather, they should go to syslog
//
// However, option processing is not yet done, nor is any initialization (!)
// So we must wait until the main loop.
} else {
syslog(LOG_NOTICE, "server running in foreground");
}
#endif
@@ -195,13 +265,20 @@ main (int argc, char **argv)
}
}
// Now init a bunch of required stuff...
// switch to a different user for the real work...
if (lcd_port >= 1024)
drop_privs(user);
if (sock_create_server () <= 0) {
if (sock_create_server (&bind_addr, lcd_port) <= 0) {
printf ("Error opening socket.\n");
return 1;
}
if (lcd_port > 1024)
drop_privs(user);
// Now init a bunch of required stuff...
if (client_init () < 0) {
printf ("Error initializing client list\n");
return 1;
@@ -218,29 +295,48 @@ main (int argc, char **argv)
} else if (disable_server_screen) {
server_screen->priority = 256;
}
// Probably a better place to fork
//
// Main loop...
syslog(LOG_NOTICE, "using %dx%d LCD with cells %dx%d",
lcd.wid, lcd.hgt, lcd.cellwid, lcd.cellhgt);
while (1) {
sock_poll_clients ();
parse_all_client_messages ();
handle_input ();
sock_poll_clients (); // poll clients for input
parse_all_client_messages (); // analyze input from network clients
handle_input (); // handle key input from devices
// TODO: Move this code to screenlist.c...
// ... it should just say "handle_screens();"
// Timer gets reset by screenlist_next()
timer++;
// this line's here because s was getting overwritten at one time...
//s = screenlist_current();
if (s && (timer >= s->duration)) {
screenlist_next ();
}
// Just in case it gets out of hand...
if (timer >= 0x10000)
timer = 0;
update_server_screen (timer);
s = screenlist_current ();
// render something here...
if (s)
// 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);
else
no_screen_screen (timer);
@@ -257,9 +353,22 @@ main (int argc, char **argv)
void
exit_program (int val)
{
char buf[64];
// TODO: These things shouldn't be so interdependent. The order
// things are shut down in shouldn't matter...
strcpy(buf, "server shutting down on ");
switch(val) {
case 1: strcat(buf, "SIGHUP"); break;
case 2: strcat(buf, "SIGINT"); break;
case 15: strcat(buf, "SIGTERM"); break;
default: sprintf(buf, "server shutting down on signal %d", val); break;
// Other values should not be seen, but just in case..
}
// Make note in the logs...
syslog(LOG_NOTICE, buf);
// Say goodbye!
goodbye_screen ();
// Can go anywhere...
+3 -3
View File
@@ -26,8 +26,8 @@ typedef struct screen_size {
int wid, hgt;
} screen_size;
typedef struct parameter {
char *sh, *lg; // short and long versions
} parameter;
#define DEFAULT_SCREEN_PRIORITY 128
#define DEFAULT_SCREEN_DURATION 32
#define DEFAULT_HEARTBEAT 1
#endif
+1 -1
View File
@@ -303,7 +303,7 @@ slid_func (menu_item * item)
value = readfunc (MENU_READ);
if (value < 0 || value >= MENU_CLOSE)
return value;
sprintf (str, "%i", value);
snprintf (str, sizeof(str), "%i", value);
if (lcd.hgt >= 4) {
lcd.string (8, 4, str);
value = (lcd.wid * lcd.cellwid * value / 256);
+1 -1
View File
@@ -260,7 +260,7 @@ Server_screen_func (int input)
if (server_screen->priority < 256)
server_screen->priority = 256;
else
server_screen->priority = 128;
server_screen->priority = DEFAULT_SCREEN_PRIORITY;
}
return (MENU_OK | (server_screen->priority < 256));
+101 -59
View File
@@ -20,21 +20,32 @@
#include "client_functions.h"
#include "parse.h"
// This is a big function... TOO big. How to trim....
// TODO: Simplify... simplify...
int
parse_all_client_messages ()
{
int i, j;
int i, j, len;
int newtoken, inquote;
client *c;
char *str;
char *str, *p, *q, *s;
// char *tok;
int argc;
char *argv[256];
char delimiters[] = " \0";
char leftquote[] = "\0\"'`([{\0";
char rightquote[] = "\0\"'`)]}\0";
char delimiters[] = " ";
char leftquote[] = "\"'`([{";
char rightquote[] = "\"'`)]}";
char errmsg[256];
int invalid = 0;
int quoteindex;
for (i = 0; i <= 256; i++) {
argv[i] == NULL;
}
#define SEPARATOR_CHAR ' '
#define LINE_TERM_CHAR '\0'
#define COMMENT_CHAR '#'
//debug("parse: Rewinding list...\n");
LL_Rewind (clients);
@@ -48,76 +59,107 @@ parse_all_client_messages ()
for (str = client_get_message (c); str; str = client_get_message (c)) {
debug ("parse: ...%s\n", str);
// Now, split up the string...
//len = strlen(str);
argc = 0;
newtoken = 1;
inquote = 0;
for (i = 0; str[i]; i++) {
if (inquote) // Scan for the end of the quote
{
if (str[i] == rightquote[inquote]) { // Found the end of the quote
inquote = 0;
str[i] = 0;
newtoken = 1;
}
} else // Normal operation; split at delimiters
{
for (j = 1; leftquote[j]; j++) {
// Found the beginning of a new quote...
if (str[i] == leftquote[j]) {
inquote = j;
str[i] = 0;
continue;
}
}
for (j = 0; delimiters[j]; j++) {
// Break into a new string...
if (str[i] == delimiters[j]) {
str[i] = 0;
newtoken = 1;
continue;
}
}
i = 0;
q = p = str;
if (*p == COMMENT_CHAR) {
continue; // found a comment line - skip it...
}
//fprintf(stderr, "starting string scan...\n");
do {
// bypass initial white space...
while ((*p == SEPARATOR_CHAR) && (*p)) {
p++;
q++;
}
if (newtoken && str[i]) {
newtoken = 0;
argv[argc] = str + i;
argc++;
// If (*p) is null here, we reached the end of
// an empty parameter... so one of two things
// is true:
//
// 1. There is nothing but white space on this line (odd..)
// 2. This is trailing white space (odd... but allowable)
if (*p == LINE_TERM_CHAR) {
break;
// if there are no arguments, argc == 0 and will fail
// appropriately...
//
// if this is trailing white space, ignore the argc++ at the
// end and claim this as the end...
}
// Handle quoted strings...
if ((s = strchr(leftquote, *p)) != NULL) {
quoteindex = s - leftquote;
//fprintf(stderr, "found <%c> at index [%d] = <%c>\n", *p, quoteindex, leftquote[quoteindex]);
q = ++p; // past open quote...
while ((rightquote[quoteindex] != *p) && (*p != LINE_TERM_CHAR)) {
p++;
}
if (*p == LINE_TERM_CHAR) {
// We just sucked up the rest of the command line: ERROR!!
snprintf (errmsg, sizeof(errmsg), "huh? unterminated string! missing ending %c\n",
rightquote[quoteindex]);
sock_send_string (c->sock, errmsg);
continue;
} else {
*p = LINE_TERM_CHAR; // terminate string
p++; // bypass to next character
// Note that next character could be a EndOfLine (null)
// if the string was last on the line, or it could be
// something else... is it a blank?
if (*p != SEPARATOR_CHAR && *p != LINE_TERM_CHAR) {
sock_send_string (c->sock, "huh? improperly terminated string! (missing whitespace)\n");
continue;
}
}
// Otherwise, normal string...
} else {
while (*p != SEPARATOR_CHAR && *p != LINE_TERM_CHAR)
p++;
}
}
if (inquote) {
sprintf (errmsg, "huh? Unterminated string: missing %c\n", rightquote[inquote]);
sock_send_string (c->sock, errmsg);
continue;
}
/*
for(tok = strtok(str, delimiters);
tok;
tok=strtok(NULL, delimiters))
{
argv[argc] = tok;
argc++;
}
*/
// Not end of line?
if (*p) {
*p = LINE_TERM_CHAR;
//fprintf(stderr, "found new token: %s\n", q);
argv[i++] = q;
q = ++p;
} else {
//fprintf(stderr, "found new token: %s\n", q);
argv[i++] = q;
}
// At the end of this statement,
// *p will be '\0' if end of input reached;
// otherwise, it is the first character of the
// next part of the string.
argc++;
} while (*p);
//fprintf(stderr, "exiting string scan...\n");
argv[argc] = NULL;
if (argc < 1)
continue;
// Now find and call the appropriate function...
// debug("parse: Finding function...\n");
invalid = 1;
for (i = 0; commands[i].keyword; i++) {
// debug("(checking %s)\n", commands[i].keyword);
if (0 == strcmp (argv[0], commands[i].keyword)) {
// debug("(FOUND %s)\n", commands[i].keyword);
invalid = commands[i].function (c, argc, argv);
// debug("parse: Returned %i...\n", err);
break; // found our function - don't continue on...
}
}
if (invalid) {
// FIXME: Check for buffer overflows here...
sprintf (errmsg, "huh? Invalid command \"%s\"\n", argv[0]);
snprintf (errmsg, sizeof(errmsg), "huh? Invalid command \"%s\"\n", argv[0]);
sock_send_string (c->sock, errmsg);
}
+322 -272
View File
@@ -11,6 +11,10 @@
THIS FILE IS MESSY! Anyone care to rewrite it nicely? Please?? :)
NOTE: (from David Douthitt) Multiple screen sizes? Multiple simultaneous
screens? Horrors of horrors... next thing you know it'll be making coffee...
Better believe it'll take a while to do...
*/
#include <string.h>
@@ -59,55 +63,75 @@ draw_screen (screen * s, int timer)
reset = 0;
old_s = s;
// Clear the LCD screen...
lcd.clear ();
switch (backlight_state) {
case BACKLIGHT_OFF:
lcd.backlight (backlight_off_brightness);
break;
case BACKLIGHT_ON:
lcd.backlight (backlight_brightness);
break;
default:
if (backlight_state & BACKLIGHT_FLASH) {
tmp = (!((timer & 7) == 7));
if (backlight_state & 1)
lcd.backlight (tmp ? backlight_brightness : backlight_off_brightness);
//lcd.backlight(backlight_brightness * (!((timer&7) == 7)));
else
lcd.backlight (!tmp ? backlight_brightness : backlight_off_brightness);
//lcd.backlight(backlight_brightness * ((timer&7) == 7));
} else if (backlight_state & BACKLIGHT_BLINK) {
tmp = (!((timer & 14) == 14));
if (backlight_state & 1)
lcd.backlight (tmp ? backlight_brightness : backlight_off_brightness);
//lcd.backlight(backlight_brightness * (!((timer&14) == 14)));
else
lcd.backlight (!tmp ? backlight_brightness : backlight_off_brightness);
//lcd.backlight(backlight_brightness * ((timer&14) == 14));
}
break;
// lcd.backlight --
//
// This should be in a separate function altogether.
// Perhaps several: lcd.backlight_off, lcd.backlight_on,
// lcd.backlight_brightness, lcd.backlight_flash ...
//
// Set up backlight to the correct state...
// NOTE: dirty stripping of other options...
switch (backlight_state & 1) {
// Backlight off (easy)
case BACKLIGHT_OFF:
lcd.backlight (BACKLIGHT_OFF);
break;
// Backlight on (easy)
case BACKLIGHT_ON:
lcd.backlight (BACKLIGHT_ON);
break;
default:
// Backlight flash: check timer and flip backlight as appropriate
if (backlight_state & BACKLIGHT_FLASH) {
tmp = (!((timer & 7) == 7));
if (backlight_state & 1)
lcd.backlight (tmp ? backlight_brightness : backlight_off_brightness);
//lcd.backlight(backlight_brightness * (!((timer&7) == 7)));
else
lcd.backlight (!tmp ? backlight_brightness : backlight_off_brightness);
//lcd.backlight(backlight_brightness * ((timer&7) == 7));
// Backlight blink: check timer and flip backlight as appropriate
} else if (backlight_state & BACKLIGHT_BLINK) {
tmp = (!((timer & 14) == 14));
if (backlight_state & 1)
lcd.backlight (tmp ? backlight_brightness : backlight_off_brightness);
//lcd.backlight(backlight_brightness * (!((timer&14) == 14)));
else
lcd.backlight (!tmp ? backlight_brightness : backlight_off_brightness);
//lcd.backlight(backlight_brightness * ((timer&14) == 14));
}
break;
}
// Output ports from LCD - outputs depend on the current screen
lcd.output (output_state);
// Draw a frame...
draw_frame (s->widgets, 'v', 0, 0, lcd.wid, lcd.hgt, s->wid, s->hgt, s->duration / s->hgt, timer);
//debug("draw_screen done\n");
if (heartbeat) {
if ((s->heartbeat == 1) || heartbeat == HEART_ON) {
if ((s->heartbeat == HEART_ON) || heartbeat == HEART_ON) {
// Set this to pulsate like a real heart beat...
// (binary is fun... :)
// lcd.heartbeat ();
lcd.icon (!((timer + 4) & 5), 0);
lcd.chr (lcd.wid, 1, 0);
}
if ((s->heartbeat == 2) && heartbeat != HEART_OFF) {
char *phases = "-\\|/";
lcd.chr (lcd.wid, 1, phases[timer & 3]);
}
// else
// This seems unnecessary... heartbeat is nicer...
// if ((s->heartbeat == HEART_OPEN) && heartbeat != HEART_OFF) {
// char *phases = "-\\|/";
// lcd.chr (lcd.wid, 1, phases[timer & 3]);
// }
}
// flush display out, frame and all...
lcd.flush ();
//debug("draw_screen: %8x, %i\n", s, timer);
@@ -116,15 +140,31 @@ draw_screen (screen * s, int timer)
}
// The following function is positively ghastly (as was mentioned above!)
// Best thing to do is to remove support for frames... but anyway...
//
static int
draw_frame (LL * list, char fscroll, int left, int top, int right, int bottom, int fwid, int fhgt, int fspeed, int timer)
draw_frame (LL * list,
char fscroll, // direction of scrolling
int left, // left edge of frame
int top, // top edge of frame
int right, // right edge of frame
int bottom, // bottom edge of frame
int fwid, // frame width?
int fhgt, // frame height?
int fspeed, // speed of scrolling...
int timer) // ?
{
#define VerticalScrolling (fscroll == 'v')
#define HorizontalScrolling (fscroll == 'h')
char str[BUFSIZE]; // scratch buffer
widget *w;
int wid, hgt; // Width and height of visible frame area
int wid, hgt; // Width and height of visible frame area
int x, y;
int fx, fy; // Scrolling offset for the frame...
int fx, fy; // Scrolling offset for the frame...
int length, speed;
//int lines;
@@ -135,18 +175,22 @@ draw_frame (LL * list, char fscroll, int left, int top, int right, int bottom, i
fx = 0;
fy = 0;
if (fscroll == 'v') {
if (VerticalScrolling) {
if (fspeed > 0)
fy = (timer - fspeed) / fspeed;
if (fspeed < 0)
else if (fspeed < 0)
fy = (-fspeed) * timer;
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)
@@ -156,8 +200,9 @@ draw_frame (LL * list, char fscroll, int left, int top, int right, int bottom, i
fy %= fhgt;
if (fy > fhgt - hgt)
fy = fhgt - hgt;
} else if (fscroll == 'h') { // TODO: Frames don't scroll horizontally yet!
} else if (HorizontalScrolling) {
// TODO: Frames don't scroll horizontally yet!
}
//debug("draw_screen: %8x, %i\n", s, timer);
@@ -166,6 +211,11 @@ draw_frame (LL * list, char fscroll, int left, int top, int right, int bottom, i
//debug("draw_frame: %8x, %i\n", 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);
@@ -174,266 +224,266 @@ draw_frame (LL * list, char fscroll, int left, int top, int right, int bottom, i
// TODO: Make this cleaner and more flexible!
switch (w->type) {
case WID_STRING:
if ((w->x > 0) && (w->y > 0) && (w->text)) {
if ((w->y <= hgt + fy) && (w->y > fy)) {
if (w->x > wid) { w->x=wid; };
strncpy (str, w->text, wid - w->x + 1);
str[wid - w->x + 1] = 0;
lcd.string (w->x + left, w->y + top - fy, str);
case WID_STRING:
if (ValidPoint(w) && TextPresent(w)) {
if ((w->y <= hgt + fy) && (w->y > fy)) {
if (w->x > wid) w->x=wid;
strncpy (str, w->text, wid - w->x + 1);
str[wid - w->x + 1] = 0;
lcd.string (w->x + left, w->y + top - fy, str);
}
}
}
break;
case WID_HBAR:
if (reset) {
lcd.init_hbar ();
reset = 0;
}
if ((w->x > 0) && (w->y > 0)) {
if ((w->y <= hgt + fy) && (w->y > fy)) {
break;
case WID_HBAR:
if (reset) {
lcd.init_hbar ();
reset = 0;
}
if ((w->x > 0) && (w->y > 0)) {
if ((w->y <= hgt + fy) && (w->y > fy)) {
if (w->length > 0) {
if ((w->length / lcd.cellwid) < wid - w->x + 1)
lcd.hbar (w->x + left, w->y + top - fy, w->length);
else
lcd.hbar (w->x + left, w->y + top - fy, wid * lcd.cellwid);
} else if (w->length < 0) {
// TODO: Rearrange stuff to get left-extending
// hbars to draw correctly...
// .. er, this'll require driver modifications,
// so I'll leave it out for now.
}
}
}
break;
case WID_VBAR: // FIXME: Vbars don't work in frames!
if (reset) {
lcd.init_vbar ();
reset = 0;
}
if ((w->x > 0) && (w->y > 0)) {
if (w->length > 0) {
if ((w->length / lcd.cellwid) < wid - w->x + 1)
lcd.hbar (w->x + left, w->y + top - fy, w->length);
else
lcd.hbar (w->x + left, w->y + top - fy, wid * lcd.cellwid);
lcd.vbar (w->x, w->length);
} else if (w->length < 0) {
// TODO: Rearrange stuff to get left-extending
// hbars to draw correctly...
// TODO: Rearrange stuff to get down-extending
// vbars to draw correctly...
// .. er, this'll require driver modifications,
// so I'll leave it out for now.
}
}
}
break;
case WID_VBAR: // FIXME: Vbars don't work in frames!
if (reset) {
lcd.init_vbar ();
reset = 0;
}
if ((w->x > 0) && (w->y > 0)) {
if (w->length > 0) {
lcd.vbar (w->x, w->length);
} else if (w->length < 0) {
// TODO: Rearrange stuff to get down-extending
// vbars to draw correctly...
// .. er, this'll require driver modifications,
// so I'll leave it out for now.
}
}
break;
case WID_ICON: // FIXME: Not implemented
break;
case WID_TITLE: // FIXME: Doesn't work quite right in frames...
if (!w->text)
break;
if (wid < 8)
case WID_ICON: // FIXME: Not implemented
break;
memset (str, 255, wid);
str[2] = ' ';
length = strlen (w->text);
if (length <= wid - 6) {
memcpy (str + 3, w->text, length);
str[length + 3] = ' ';
} else // Scroll the title, if it doesn't fit...
{
speed = 1;
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);
x -= 3;
if (x < 0)
x = 0;
if (x > length - (wid - 6))
x = length - (wid - 6);
if (y & 1) // Scrolling backwards...
{
x = (length - (wid - 6)) - x;
}
strncpy (str + 3, w->text + x, (wid - 6));
str[wid - 3] = ' ';
}
str[wid] = 0;
lcd.string (1 + left, 1 + top, str);
break;
case WID_SCROLLER: // FIXME: doesn't work in frames...
{
int offset;
int screen_width;
case WID_TITLE: // FIXME: Doesn't work quite right in frames...
if (!w->text)
break;
if (w->right < w->left)
if (wid < 8)
break;
//printf("rendering: %s %d\n",w->text,timer);
screen_width = w->right - w->left + 1;
switch (w->length) { // actually, direction...
// FIXED: Horz scrollers don't show the
// last letter in the string... (1-off error?)
case 'h':
length = strlen (w->text) + 1;
if (length <= screen_width) {
/* it fits within the box, just render it */
lcd.string (w->left, w->top, w->text);
} 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) {
//wiggle one way
offset = (timer % (effLength * w->speed))
/ w->speed;
} else {
//wiggle the other
offset = (((timer % (effLength * w->speed))
- (effLength * w->speed) + 1)
/ w->speed) * -1;
}
} else if (w->speed < 0) {
necessaryTimeUnits = effLength / (w->speed * -1);
if (((timer / (effLength / (w->speed * -1))) % 2) == 0) {
offset = (timer % (effLength / (w->speed * -1)))
* w->speed * -1;
} else {
offset = (((timer % (effLength / (w->speed * -1)))
* w->speed * -1) - effLength + 1) * -1;
}
} 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);
str[screen_width] = '\0';
//printf("%s : %d\n",str,length-offset);
} else {
str[0] = '\0';
}
lcd.string (w->left, w->top, str);
memset (str, 255, wid);
str[2] = ' ';
length = strlen (w->text);
if (length <= wid - 6) {
memcpy (str + 3, w->text, length);
str[length + 3] = ' ';
} else // Scroll the title, if it doesn't fit...
{
speed = 1;
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;
}
break;
// FIXME: Vert scrollers don't always seem to scroll
// back up after hitting the bottom. They jump back to
// the top instead... (nevermind?)
case 'v':
x %= (length);
x -= 3;
if (x < 0)
x = 0;
if (x > length - (wid - 6))
x = length - (wid - 6);
if (y & 1) // Scrolling backwards...
{
int i = 0;
length = strlen (w->text);
x = (length - (wid - 6)) - x;
}
strncpy (str + 3, w->text + x, (wid - 6));
str[wid - 3] = ' ';
}
str[wid] = 0;
lcd.string (1 + left, 1 + top, str);
break;
case WID_SCROLLER: // FIXME: doesn't work in frames...
{
int offset;
int screen_width;
if (!w->text)
break;
if (w->right < w->left)
break;
//printf("rendering: %s %d\n",w->text,timer);
screen_width = w->right - w->left + 1;
switch (w->length) { // actually, direction...
// FIXED: Horz scrollers don't show the
// last letter in the string... (1-off error?)
case 'h':
length = strlen (w->text) + 1;
if (length <= screen_width) {
/* no scrolling required... */
/* it fits within the box, just render it */
lcd.string (w->left, w->top, w->text);
} else {
int lines_required = (length / screen_width)
+ (length % screen_width ? 1 : 0);
int available_lines = (w->bottom - w->top + 1);
if (lines_required <= available_lines) {
// easy...
for (i = 0; i < lines_required; i++) {
strncpy (str, &((w->text)[i * screen_width]), screen_width);
str[screen_width] = '\0';
lcd.string (w->left, w->top + i, str);
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) {
//wiggle one way
offset = (timer % (effLength * w->speed))
/ w->speed;
} else {
//wiggle the other
offset = (((timer % (effLength * w->speed))
- (effLength * w->speed) + 1)
/ w->speed) * -1;
}
} else if (w->speed < 0) {
necessaryTimeUnits = effLength / (w->speed * -1);
if (((timer / (effLength / (w->speed * -1))) % 2) == 0) {
offset = (timer % (effLength / (w->speed * -1)))
* w->speed * -1;
} else {
offset = (((timer % (effLength / (w->speed * -1)))
* w->speed * -1) - effLength + 1) * -1;
}
} else {
int necessaryTimeUnits = 0;
int effLines = lines_required - available_lines + 1;
int begin = 0;
if (!screenlist_action)
screenlist_action = RENDER_HOLD;
//printf("length: %d sw: %d lines req: %d avail lines: %d effLines: %d \n",length,screen_width,lines_required,available_lines,effLines);
if (w->speed > 0) {
necessaryTimeUnits = effLines * w->speed;
if (((timer / (effLines * w->speed)) % 2) == 0) {
//printf("up ");
begin = (timer % (effLines * w->speed))
/ w->speed;
} else {
//printf("down ");
begin = (((timer % (effLines * w->speed))
- (effLines * w->speed) + 1) / w->speed)
* -1;
}
} else if (w->speed < 0) {
necessaryTimeUnits = effLines / (w->speed * -1);
if (((timer / (effLines / (w->speed * -1))) % 2) == 0) {
begin = (timer % (effLines / (w->speed * -1)))
* w->speed * -1;
} else {
begin = (((timer % (effLines / (w->speed * -1)))
* w->speed * -1) - effLines + 1)
* -1;
}
} else {
begin = 0;
}
//printf("rendering begin: %d timer: %d effLines: %d\n",begin,timer,effLines);
for (i = begin; i < begin + available_lines; i++) {
strncpy (str, &((w->text)[i * (screen_width)]), screen_width);
str[screen_width] = '\0';
//printf("rendering: '%s' of %s\n",
//str,w->text);
lcd.string (w->left, w->top + (i - begin), str);
}
if (timer > necessaryTimeUnits) {
if (screenlist_action == RENDER_HOLD)
screenlist_action = 0;
}
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);
str[screen_width] = '\0';
//printf("%s : %d\n",str,length-offset);
} else {
str[0] = '\0';
}
lcd.string (w->left, w->top, str);
}
break;
// FIXME: Vert scrollers don't always seem to scroll
// back up after hitting the bottom. They jump back to
// the top instead... (nevermind?)
case 'v':
{
int i = 0;
length = strlen (w->text);
if (length <= screen_width) {
/* no scrolling required... */
lcd.string (w->left, w->top, w->text);
} else {
int lines_required = (length / screen_width)
+ (length % screen_width ? 1 : 0);
int available_lines = (w->bottom - w->top + 1);
if (lines_required <= available_lines) {
// easy...
for (i = 0; i < lines_required; i++) {
strncpy (str, &((w->text)[i * screen_width]), screen_width);
str[screen_width] = '\0';
lcd.string (w->left, w->top + i, str);
}
} else {
int necessaryTimeUnits = 0;
int effLines = lines_required - available_lines + 1;
int begin = 0;
if (!screenlist_action)
screenlist_action = RENDER_HOLD;
//printf("length: %d sw: %d lines req: %d avail lines: %d effLines: %d \n",length,screen_width,lines_required,available_lines,effLines);
if (w->speed > 0) {
necessaryTimeUnits = effLines * w->speed;
if (((timer / (effLines * w->speed)) % 2) == 0) {
//printf("up ");
begin = (timer % (effLines * w->speed))
/ w->speed;
} else {
//printf("down ");
begin = (((timer % (effLines * w->speed))
- (effLines * w->speed) + 1) / w->speed)
* -1;
}
} else if (w->speed < 0) {
necessaryTimeUnits = effLines / (w->speed * -1);
if (((timer / (effLines / (w->speed * -1))) % 2) == 0) {
begin = (timer % (effLines / (w->speed * -1)))
* w->speed * -1;
} else {
begin = (((timer % (effLines / (w->speed * -1)))
* w->speed * -1) - effLines + 1)
* -1;
}
} else {
begin = 0;
}
//printf("rendering begin: %d timer: %d effLines: %d\n",begin,timer,effLines);
for (i = begin; i < begin + available_lines; i++) {
strncpy (str, &((w->text)[i * (screen_width)]), screen_width);
str[screen_width] = '\0';
//printf("rendering: '%s' of %s\n",
//str,w->text);
lcd.string (w->left, w->top + (i - begin), str);
}
if (timer > necessaryTimeUnits) {
if (screenlist_action == RENDER_HOLD)
screenlist_action = 0;
}
}
}
break;
}
}
break;
}
case WID_FRAME:
{
// FIXME: doesn't handle nested frames quite right!
// doesn't handle scrolling in nested frames at all...
int new_left, new_top, new_right, new_bottom;
new_left = left + w->left - 1;
new_top = top + w->top - 1;
new_right = left + w->right;
new_bottom = top + w->bottom;
if (new_right > right)
new_right = right;
if (new_bottom > bottom)
new_bottom = bottom;
if (new_left >= right || new_top >= bottom) { // Do nothing if it's invisible...
} else {
draw_frame (w->kids, w->length, new_left, new_top, new_right, new_bottom, w->wid, w->hgt, w->speed, timer);
}
}
break;
}
case WID_FRAME:
{
// FIXME: doesn't handle nested frames quite right!
// doesn't handle scrolling in nested frames at all...
int new_left, new_top, new_right, new_bottom;
new_left = left + w->left - 1;
new_top = top + w->top - 1;
new_right = left + w->right;
new_bottom = top + w->bottom;
if (new_right > right)
new_right = right;
if (new_bottom > bottom)
new_bottom = bottom;
if (new_left >= right || new_top >= bottom) { // Do nothing if it's invisible...
} else {
draw_frame (w->kids, w->length, new_left, new_top, new_right, new_bottom, w->wid, w->hgt, w->speed, timer);
case WID_NUM: // FIXME: doesn't work in frames...
// NOTE: y=10 means COLON (:)
if ((w->x > 0) && (w->y >= 0) && (w->y <= 10)) {
if (reset) {
lcd.init_num ();
reset = 0;
}
lcd.num (w->x + left, w->y);
}
}
break;
case WID_NUM: // FIXME: doesn't work in frames...
// NOTE: y=10 means COLON (:)
if ((w->x > 0) && (w->y >= 0) && (w->y <= 10)) {
if (reset) {
lcd.init_num ();
reset = 0;
}
lcd.num (w->x + left, w->y);
}
break;
case WID_NONE:
default:
break;
break;
case WID_NONE:
default:
break;
}
} while (LL_Next (list) == 0);
+4 -3
View File
@@ -11,6 +11,7 @@
#include "widget.h"
#include "screenlist.h"
#include "screen.h"
#include "main.h"
int default_priority = 128 ;
int default_duration = 64 ; // About 8 seconds
@@ -28,9 +29,9 @@ screen_create ()
s->id = NULL;
s->name = NULL;
s->priority = default_priority ;
s->duration = default_duration ;
s->heartbeat = 1;
s->priority = DEFAULT_SCREEN_PRIORITY;
s->duration = DEFAULT_SCREEN_DURATION;
s->heartbeat = DEFAULT_HEARTBEAT;
s->wid = lcd.wid;
s->hgt = lcd.hgt;
s->keys = NULL;
+2 -2
View File
@@ -112,7 +112,7 @@ screenlist_current ()
c = old_s->parent;
if (c) // Tell the client we're not listening any more...
{
sprintf (str, "ignore %s\n", old_s->id);
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
{
@@ -125,7 +125,7 @@ screenlist_current ()
c = s->parent;
if (c) // Tell the client we're paying attention...
{
sprintf (str, "listen %s\n", s->id);
snprintf (str, sizeof(str), "listen %s\n", s->id);
sock_send_string (c->sock, str);
} else // The server has the display, so do nothing
{
+61 -44
View File
@@ -26,6 +26,11 @@ char one[256] = "";
char two[256] = "";
char three[256] = "";
#define WidgetXPos(w,a) (w)->x = (a)
#define WidgetYPos(w,a) (w)->y = (a)
#define WidgetText(w,a) (w)->text = (a)
#define WidgetString(w,a,b,t) {WidgetXPos(w,a);WidgetYPos(w,b);WidgetText(w,t);}
int
server_screen_init ()
{
@@ -44,46 +49,39 @@ server_screen_init ()
server_screen->name = name;
server_screen->duration = 8; // 1 second, instead of 4...
// TODO: Error-checking?
widget_add (server_screen, "title", "title", NULL, 1);
widget_add (server_screen, "one", "string", NULL, 1);
widget_add (server_screen, "two", "string", NULL, 1);
widget_add (server_screen, "three", "string", NULL, 1);
if (widget_add (server_screen, "title", "title", NULL, 1) != 0) {
fprintf (stderr, "server_screen_init: internal error: could not add title widget\n");
}
if (widget_add (server_screen, "one", "string", NULL, 1) != 0) {
fprintf (stderr, "server_screen_init: internal error: could not add title widget\n");
}
if (widget_add (server_screen, "two", "string", NULL, 1) != 0) {
fprintf (stderr, "server_screen_init: internal error: could not add title widget\n");
}
if (widget_add (server_screen, "three", "string", NULL, 1) != 0) {
fprintf (stderr, "server_screen_init: internal error: could not add title widget\n");
}
// Now, initialize all the widgets...
w = widget_find (server_screen, "title");
if (w) {
w->text = title;
} else {
if ((w = widget_find (server_screen, "title")) != NULL) {
WidgetText(w,title);
} else
fprintf (stderr, "server_screen_init: Can't find title\n");
}
w = widget_find (server_screen, "one");
if (w) {
w->x = 1;
w->y = 2;
w->text = one;
} else {
if ((w = widget_find (server_screen, "one")) != NULL)
WidgetString(w,1,2,one)
else
fprintf (stderr, "server_screen_init: Can't find widget one\n");
}
w = widget_find (server_screen, "two");
if (w) {
w->x = 1;
w->y = 3;
w->text = two;
} else {
if ((w = widget_find (server_screen, "two")) != NULL)
WidgetString(w,1,3,two)
else
fprintf (stderr, "server_screen_init: Can't find widget two\n");
}
w = widget_find (server_screen, "three");
if (w) {
w->x = 1;
w->y = 4;
w->text = three;
} else {
if ((w = widget_find (server_screen, "three")) != NULL)
WidgetString(w,1,4,three)
else
fprintf (stderr, "server_screen_init: Can't find widget three\n");
}
// And enqueue the screen
screenlist_add (server_screen);
@@ -93,6 +91,20 @@ server_screen_init ()
return 0;
}
static int
screen_count (client *c) {
int n;
n = 0;
LL_Rewind (c->data->screenlist);
do {
if (LL_Get (c->data->screenlist) != NULL)
n++;
} while (LL_Next (c->data->screenlist) == 0);
return n;
}
int
update_server_screen (int timer)
{
@@ -112,24 +124,31 @@ update_server_screen (int timer)
c = LL_Get (clients);
if (c) {
num_clients++;
LL_Rewind (c->data->screenlist);
do {
s = LL_Get (c->data->screenlist);
if (s) {
num_screens++;
}
} while (LL_Next (c->data->screenlist) == 0);
num_screens += screen_count(c);
// LL_Rewind (c->data->screenlist);
// do {
// s = LL_Get (c->data->screenlist);
// if (s) {
// num_screens++;
// }
// } while (LL_Next (c->data->screenlist) == 0);
}
} while (LL_Next (clients) == 0);
// Format strings for the appropriate size display...
//
if (lcd.hgt >= 3) {
sprintf (one, "Clients: %i", num_clients);
sprintf (two, "Screens: %i", num_screens);
snprintf (one, sizeof(one), "Clients: %i", num_clients);
snprintf (two, sizeof(two), "Screens: %i", num_screens);
} else {
if (lcd.wid >= 20)
sprintf (one, "%i Client%s, %i Screen%s", num_clients, (num_clients == 1) ? "" : "s", num_screens, (num_screens == 1) ? "" : "s");
snprintf (one, sizeof(one), "%i Client%s, %i Screen%s", num_clients,
(num_clients == 1) ? "" : "s", num_screens,
(num_screens == 1) ? "" : "s");
else // 16x2 size
sprintf (one, "%i Cli%s, %i Scr%s", num_clients, (num_clients == 1) ? "" : "s", num_screens, (num_screens == 1) ? "" : "s");
snprintf (one, sizeof(one), "%i Cli%s, %i Scr%s", num_clients,
(num_clients == 1) ? "" : "s", num_screens,
(num_screens == 1) ? "" : "s");
}
return 0;
@@ -140,9 +159,7 @@ no_screen_screen (int timer)
{
lcd.clear ();
lcd.string (1, 1, "Error: No screen!");
lcd.flush ();
return 0;
+46 -18
View File
@@ -17,6 +17,10 @@
#include "sock.h"
#include "clients.h"
#include "shared/debug.h"
#include "syslog.h"
extern char bind_addr[64];
extern int lcd_port;
/**************************************************
LCDproc sockets code...
@@ -34,7 +38,7 @@ int read_from_client (int filedes);
// Creates a socket in internet space
int
sock_create_inet_socket (unsigned short int port)
sock_create_inet_socket (char * addr, unsigned int port)
{
struct sockaddr_in name;
int sock;
@@ -46,6 +50,7 @@ sock_create_inet_socket (unsigned short int port)
sock = socket (PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror ("Error creating socket");
syslog(LOG_ALERT, "could not create socket", port);
return -1;
}
@@ -53,10 +58,14 @@ sock_create_inet_socket (unsigned short int port)
//debug("Binding Inet Socket\n");
name.sin_family = AF_INET;
name.sin_port = htons (port);
name.sin_addr.s_addr = htonl (INADDR_ANY);
inet_aton(addr, &name.sin_addr);
if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
perror ("Error binding socket");
syslog(LOG_ALERT, "could not bind to port %d", port);
return -1;
} else {
syslog(LOG_NOTICE, "listening for queries on port %d", port);
}
return sock;
@@ -65,14 +74,14 @@ sock_create_inet_socket (unsigned short int port)
//int StartSocketServer()
int
sock_create_server ()
sock_create_server (char *bind_addr, int lcd_port)
{
int sock;
debug ("sock_create_server()\n");
/* Create the socket and set it up to accept connections. */
sock = sock_create_inet_socket (LCDPORT);
sock = sock_create_inet_socket (bind_addr, lcd_port);
if (sock < 0) {
perror ("sock_create_server: Error creating socket");
return -1;
@@ -80,6 +89,7 @@ sock_create_server ()
if (listen (sock, 1) < 0) {
perror ("sock_create_server: Listen error");
syslog(LOG_ALERT, "error in attempting to listen to port");
return -1;
}
@@ -107,6 +117,8 @@ sock_create_server ()
return sock;
}
// Service all clients with input pending...
int
sock_poll_clients ()
{
@@ -140,9 +152,12 @@ sock_poll_clients ()
new = accept (orig_sock, (struct sockaddr *) &clientname, &size);
if (new < 0) {
perror ("sock_poll_clients: Accept error");
syslog(LOG_WARNING, "error in accepting client");
return -1;
}
debug ("sock_poll_clients: connect from host %s, port %hd.\n", inet_ntoa (clientname.sin_addr), ntohs (clientname.sin_port));
syslog(LOG_NOTICE, "connect from host %s:%hd on #%d",
inet_ntoa (clientname.sin_addr), ntohs (clientname.sin_port), new);
FD_SET (new, &active_fd_set);
fcntl (new, F_SETFL, O_NONBLOCK);
@@ -168,6 +183,7 @@ sock_poll_clients ()
close (i);
FD_CLR (i, &active_fd_set);
debug ("sock_poll_clients: Closed connection %i\n", i);
syslog(LOG_NOTICE, "closed connection #%i", i);
} else
fprintf (stderr, "sock_poll_clients: Can't find client %i\n", i);
}
@@ -186,22 +202,22 @@ read_from_client (int filedes)
int nbytes, i;
client *c;
// nbytes = read (filedes, buffer, MAXMSG);
//nbytes = read (filedes, buffer, MAXMSG);
//debug("read_from_client(%i): reading...\n", filedes);
nbytes = sock_recv (filedes, buffer, MAXMSG);
//nbytes = sock_recv (filedes, buffer, MAXMSG);
//debug("read_from_client(%i): ...done\n", filedes);
debug ("read_from_client(%i): %i bytes\n", filedes, nbytes);
//debug ("read_from_client(%i): %i bytes\n", filedes, nbytes);
if (nbytes < 0) // Read error? No data available?
{
// TODO: check errno here!
//fprintf (stderr,"read_from_client: Read error\n");
errno = 0;
if ((nbytes = sock_recv (filedes, buffer, MAXMSG)) < 0) {
if (errno != EAGAIN)
fprintf (stderr, "read_from_client: (fd %d) %s\n", filedes, strerror(errno));
return 0;
} else if (nbytes == 0) // EOF
return -1;
else if (nbytes > (MAXMSG - (MAXMSG / 8))) // Very noisy client...
{
sock_send_string (filedes, "huh? Shut up!\n");
sock_send_string (filedes, "huh? Too much data received... quiet down!\n");
return -1;
} else // Data Read
{
@@ -229,16 +245,28 @@ read_from_client (int filedes)
int
sock_close_all ()
{
int i;
int fd;
debug ("sock_close_all()\n");
for (i = 0; i < FD_SETSIZE; i++) {
for (fd = 0; fd < FD_SETSIZE; fd++) {
// TODO: Destroy a "client" here...? Nope.
sock_send_string (i, "bye\n");
close (i);
FD_CLR (i, &active_fd_set);
debug ("sock_close_all: Closed connection %i\n", i);
// Instead of using STDIN_FILENO, STDOUT_FILENO,
// and STDERR_FILENO, one could use "fd = 4" in the
// for() call - but this would probably not be good
// practice...
if ( fd == STDIN_FILENO ||
fd == STDOUT_FILENO ||
fd == STDERR_FILENO)
continue;
else {
//sock_send_string (fd, "bye\n");
close (fd);
FD_CLR (fd, &active_fd_set);
debug ("sock_close_all: Closed connection %i\n", fd);
}
}
return 0;
+11 -8
View File
@@ -167,6 +167,7 @@ widget_add (screen * s, char *id, char *type, char *in, int sock)
s->heartbeat = 1;
return 0;
}
// Make sure this screen doesn't already exist...
w = widget_find (s, id);
if (w) {
@@ -193,13 +194,16 @@ widget_add (screen * s, char *id, char *type, char *in, int sock)
}
}
}
// Make sure it's a valid widget type
for (i = 1; types[i]; i++) {
if (0 == strcmp (types[i], type)) {
valid = 1;
wid_type = i;
break; // it's valid: skip out...
}
}
if (!valid) {
// invalid widget type
sock_send_string (sock, "huh? Invalid widget type\n");
@@ -233,6 +237,7 @@ widget_add (screen * s, char *id, char *type, char *in, int sock)
}
}
}
// TODO: Check for errors here?
LL_Push (list, (void *) w);
@@ -266,19 +271,17 @@ widget_remove (screen * s, char *id, int sock)
return 1;
}
/*
// TODO: Check for errors here?
// TODO: Make this work with frames...
// LL_Remove(list, (void *)w);
// TODO: Check for errors here?
// TODO: Make this work with frames...
// LL_Remove(list, (void *)w);
// TODO: Check for errors here?
// widget_destroy(w);
*/
// TODO: Check for errors here?
// widget_destroy(w);
return widget_remover (list, w);
// return 0;
// return 0;
}
int