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:
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+13
-9
@@ -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);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
typedef struct client {
|
||||
int sock;
|
||||
char addr[64];
|
||||
LL *messages;
|
||||
client_data *data;
|
||||
|
||||
|
||||
+366
-86
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user