Initial revision

This commit is contained in:
William Ferrell
1999-12-09 23:15:14 +00:00
commit 2635c3085d
139 changed files with 24298 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
Object methods and properties and some vars
Tcomms
Properties
int InboundFD (for select to watch if>0)
IMODE imode {none,polled,fd} (method for reading data)
Tconfig config
Methods
ParseConfig(TConfig config)
Init
poll
writechar
writestr
Tserial
Private Vars
char port[]
int speed
Properties
Tdriver
Properties
Tconfig config
int backlight_state
int disp_width
int disp_height
Methods
Init
ClearScr
NewCustomChar(struct CustChar defination)
PutCustChar(zoff,yoff,char)
PutChar(xoff,yoff,char)
PlaceString(xoff,yoff,string)
DrawHorizBar(xoff,yoff,chwidth,percentage)
DrawVertBar(xoff,yoff,chheight,percentage)
Tdisplay
Properties
Tdriver driver
Tconfig config
int RefreshInterval (for clock would be 500 for every half second)
Methods
HardInit (called once on prog start)
Init (called on every new cycle)
+92
View File
@@ -0,0 +1,92 @@
LCDproc suggestion object hierarchy
Tdriver
TVirtualDriver
TMtxOrbDriver
TTextDriver
Tcomms
TSerial
TParallel
TSCSI
Tdisplay
Tclock_dsp
Tmail_dsp
Tcpustate_dsp
Tcpugraph_dsp
Tmeminf_dsp
Tuptime_dsp
Txload_dsp
Tcredits_dsp
Theartbeat_dsp
Tstub_dsp
Tusercfg_dsp
Tremote
Ttcpsockd
TUNIXsockd
Tchannel
Ttcpsocket
TUNIXsocket
Tconfig
Tfeedback
TMtxOrb_keypad
Tserial_buttons
Tschedular
---------------------------------------------------
Object brief descriptions
Tdriver (and decendants) provide manipulation of the physical
LCD panel including backlight, typeface loading, etc.
Tdriver will provide default methods for tasks such as
text centering
scrolling
screen clearing
etc
TVirtualDriver could act as a frame buffer / virtual display.
This would allow several display objects to access the (virtual)
display in a single cycle and then the virtual driver can flush
the changes from the last display (delta display) in a single pass.
This provides a portable way to implement display objects
(like the heartbeat which only changes one character at a time)
but overlap a standard full screen display
Tcomms (and decendants) transmit and receive all data to and
from the communications interfaces. Tdriver and Tfeedback will
use these objects directly.
Tdisplay (and decendants) generate the actual display information
by manipulating the Tdriver object which has been given to it.
The Tdriver object should usually be a TVirtualDriver descendant.
Tremote (and decendants) create, keep track of and ultimately destroy
Tchannel objects. Each Tchannel can potentitally be an external
connection to a remote client. The remote client can generate
either complete screens in a similar style to a Tdisplay object with
Tchannel using a Tstub_dsp to generate the screen based on info
supplied to it or it can feed data into an existing Tdisplay object
(Tchannel will do this by setting Tdisplay properties).
Tconfig is responsible for parsing the command line and reading/re-reading
the contents of a configuration file.
Tfeedback (and its descendants) may communicate with a Tcomms object to
retrieve information from a keypad or other input device.
Tschedular is responsible for the overall co-ordination of everything.
Other notes:
I can't decide things like "should scroll stuff be down to Tdriver
or Tdisplay?".
Some sort of Thash would be a useful way of passing data from
sockets to display objects as well
+443
View File
@@ -0,0 +1,443 @@
/***********************************************
**
** cfg.c v0.01
**
** Generic config file handler
** (c) Gareth Watts 1998
** gareth@omnipotent.net
**
** Alpha code as of 980601
*/
#include <stddef.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "cfg.h"
/**************************
* PUBLIC METHODS
*/
void cfg_free(cfg *self) {
struct cfg_node *ptr, *nextptr;
int i;
for(i=0;i<CFG_HASHSIZE;i++) {
if(self->cfg_hash[i]) {
for(ptr=self->cfg_hash[i];ptr;ptr=nextptr) {
nextptr=ptr->next;
free(ptr->optname);
free(ptr->optvalue);
free(ptr);
}
}
}
free(self->filename);
free(self->lasterror);
self->_queuefree(self);
free(self);
}
#define CFG_BUZSIZE 4096
int cfg_openfile(cfg *self,char *fn,int mode) {
char buffer[CFG_BUZSIZE];
char *keyname,*keyvalue;
int comment;
FILE *fh;
self->filename=strdup(fn);
fh=fopen(fn,"r");
if (!fh) {
if (mode==CFG_READONLY) {
self->lasterror=strdup(strerror(errno));
return(1);
}
return(0); /* read/write but file not found */
}
// READ AND PARSE FILE HERE
while(feof(fh)==0) {
fgets(buffer,CFG_BUZSIZE-1,fh);
if (strlen(buffer)) {
if (buffer[strlen(buffer)-1]=='\n') {
buffer[strlen(buffer)-1]='\0';
}
if (buffer[0]=='#') {
comment=1;
} else {
comment=0;
}
} else { comment=1;}
if (!comment&&self->_splitline(self,buffer,&keyname,&keyvalue)) {
return(1); /* memory error or somesuch */
}
if (!comment&&keyname&&keyvalue) {
if (!self->_lookup(self,keyname)) {
self->_insert(self,keyname,keyvalue,0);
}
}
}
return(0);
}
char *cfg_getstring(cfg *self,char *keyname) {
return(self->_lookup(self,keyname));
}
int cfg_getint(cfg *self,char *keyname) {
int result=0;
char *keydata;
keydata=self->_lookup(self,keyname);
if (keydata)
sscanf(keydata,"%d",&result);
return(result);
}
/* This is virtually useless due to rounding errors */
float cfg_getfloat(cfg *self,char *keyname) {
float result=0.0;
char *keydata;
keydata=self->_lookup(self,keyname);
if (keydata)
sscanf(keydata,"%f",&result);
return(result);
}
int cfg_setstring(cfg *self,char *keyname, char *keyvalue) {
return(self->_set(self,keyname,keyvalue));
}
int cfg_setint(cfg *self,char *keyname, int keyvalue) {
char buffer[200];
sprintf(buffer,"%d",keyvalue);
return(self->_set(self,keyname,buffer));
}
int cfg_setfloat(cfg *self,char *keyname, float keyvalue) {
char buffer[200];
sprintf(buffer,"%f",keyvalue);
return(self->_set(self,keyname,buffer));
}
int cfg_flush(cfg *self) {
if (self->filemode==CFG_READONLY) {
return(0);
} else {
return(self->_flush(self));
}
}
int cfg_autoflush(cfg *self,int aflush) {
self->aflush=(aflush>0);
return(0);
}
/**************************
* PRIVATE/INTERNAL METHODS
*/
int _cfg_init(cfg *self) {
memset(self->cfg_hash,0,sizeof(self->cfg_hash));
return(0);
}
int _cfg_queuepush(cfg *self, struct cfg_node *node) {
struct cfg_queuenode *ptr;
ptr=(struct cfg_queuenode *)calloc(1,sizeof(struct cfg_queuenode));
if (!ptr) return(1);
ptr->ref=node;
if (self->cfg_newsttail) {
self->cfg_newsttail->next=ptr;
self->cfg_newsttail=ptr;
} else {
self->cfg_newsthead=self->cfg_newsttail=ptr;
}
return(0);
}
struct cfg_queuenode *_cfg_queuenext(cfg *self, struct cfg_queuenode *last) {
if (last) {
return(last->next);
} else {
return(self->cfg_newsthead);
}
}
int _cfg_queuefree(cfg *self) {
struct cfg_queuenode *ptr,*next;
for(ptr=self->cfg_newsthead;ptr;ptr=next) {
next=ptr->next;
free(ptr);
}
self->cfg_newsthead=self->cfg_newsttail=NULL;
return(0);
}
int _cfg_getkey(cfg *self,char *str) {
unsigned int total;
int i=1;
int j=0;
total=(*str)-0x20;
str++;
while(*str) {
total+=i*((*str)-0x20);
str++;
i+=(33+j++)*j;
}
return(total % CFG_HASHSIZE);
}
int _cfg_insert(cfg *self,char *keyname, char *keyval,int dirty) {
int key,match=0;
struct cfg_node *ptr,*nextptr;;
key=self->_getkey(self,keyname);
if (!self->cfg_hash[key]) {
self->cfg_hash[key]=(struct cfg_node *)calloc(1,sizeof(struct cfg_node));
if (!(self->cfg_hash[key]->optname=strdup(keyname))) {
return(1);
}
if (!(self->cfg_hash[key]->optvalue=strdup(keyval))) {
return(1);
}
if (dirty) self->_queuepush(self,self->cfg_hash[key]);
} else {
for(nextptr=self->cfg_hash[key];(nextptr)&&(!match);nextptr=ptr->next) {
ptr=nextptr;
match=(strcasecmp(ptr->optname,keyname)==0);
}
if (match) { /* node already exists / overwrite */
free(ptr->optvalue);
ptr->dirty=dirty;
} else { /* new node */
ptr->next=(struct cfg_node *)calloc(1,sizeof(struct cfg_node));
ptr=ptr->next;
if (!(ptr->optname=strdup(keyname))) {
return(1);
}
if (dirty) self->_queuepush(self,ptr);
}
if (!(ptr->optvalue=strdup(keyval))) {
return(1);
}
}
return(0);
}
struct cfg_node *_cfg_getnode(cfg *self, char *keyname) {
int key;
struct cfg_node *ptr,*next;
int match=0;
key=self->_getkey(self,keyname);
if (!self->cfg_hash[key])
return(NULL);
for(next=self->cfg_hash[key];next&&!match;next=ptr->next) {
ptr=next;
match=(strcasecmp(ptr->optname,keyname)==0);
}
if (match)
return(ptr);
return(NULL);
}
char *_cfg_lookup(cfg *self,char *keyname) {
struct cfg_node *ptr;
ptr=self->_getnode(self,keyname);
if (ptr)
return(ptr->optvalue);
else
return(NULL);
}
int _cfg_cleardirty(cfg *self,struct cfg_node *ptr) {
ptr->dirty=0;
return(0);
}
int _cfg_set(cfg *self,char *keyname,char *keyvalue) {
int key;
key=self->_getkey(self,keyname);
if (self->_insert(self,keyname,keyvalue,1)!=0) {
return(1); /* error */
}
if (self->aflush) {
return(self->flush(self));
}
return(0);
}
int _cfg_splitline(cfg *self,char *src, char **f, char **s) {
char *brkpoint;
int offset,slen,fpos;
static char first[4096],second[4096];
*f=*s=NULL;
if ((brkpoint=strchr(src,'='))==NULL) {
return(0);
}
offset=brkpoint-src;
slen=strlen(src);
if (offset==slen-1) {
return(0);
}
if (offset>4094) {offset=4094;}
memset(first,0,4096);
memset(second,0,4096);
strncpy(first,src,offset);
strncpy(second,brkpoint+1,4095);
fpos=strlen(first)-1;
while((first[fpos]==' ')&&fpos) {
first[fpos]='\0';
fpos--;
}
*f=first;
for(*s=second;(**s)&&(**s==' ');(*s)++);
return(0);
}
#define CFGF_MAXLINES 50000
#define CFGF_LINELEN 4096
int _cfg_realflush(cfg *self) {
char *outbuf[CFGF_MAXLINES];
char buffer[CFGF_LINELEN];
int linenum=0;
int comment,i;
char *keyname,*keyvalue;
struct cfg_queuenode *qptr;
struct cfg_node *ptr;
FILE *fh;
char *rd;
fh=fopen(self->filename,"r");
if (fh) {
while((feof(fh)==0)&&(linenum<CFGF_MAXLINES)) {
rd=fgets(buffer,CFGF_LINELEN-1,fh);
if (rd&&strlen(buffer)) {
if (buffer[strlen(buffer)-1]=='\n') {
buffer[strlen(buffer)-1]='\0';
}
if (buffer[0]=='#') {
comment=1;
} else {
comment=0;
}
if (comment) {
outbuf[linenum]=strdup(buffer);
} else {
if (self->_splitline(self,buffer,&keyname,&keyvalue)) {
fclose(fh);
return(1); /* memory error or somesuch */
}
if ((keyname)&&(ptr=self->_getnode(self,keyname))&&(ptr->dirty)) {
sprintf(buffer,"%s = %s",ptr->optname,ptr->optvalue);
outbuf[linenum]=strdup(buffer);
self->_cleardirty(self,ptr);
} else {
outbuf[linenum]=strdup(buffer);
}
}
linenum++;
}
}
fclose(fh);
}
for(qptr=self->_queuenext(self,NULL);qptr;qptr=self->_queuenext(self,qptr)) {
sprintf(buffer,"%s=%s",qptr->ref->optname,qptr->ref->optvalue);
outbuf[linenum]=strdup(buffer);
linenum++;
}
fh=fopen(self->filename,"w");
if (!fh) {
self->lasterror=strdup(strerror(errno));
return(1);
}
for(i=0;i<linenum;i++) {
fprintf(fh,"%s\n",outbuf[i]);
free(outbuf[i]);
}
fclose(fh);
self->_queuefree(self);
return(0);
}
/*****************
* THE CONSTRUCTOR
*/
cfg *cfg_new() {
cfg *ptr;
ptr=(cfg *)calloc(1,sizeof(cfg));
if (!ptr) return(NULL);
ptr->getstring=cfg_getstring;
ptr->getint=cfg_getint;
ptr->getfloat=cfg_getfloat;
ptr->openfile=cfg_openfile;
ptr->setstring=cfg_setstring;
ptr->setint=cfg_setint;
ptr->setfloat=cfg_setfloat;
ptr->flush=cfg_flush;
ptr->autoflush=cfg_autoflush;
ptr->free=cfg_free;
ptr->_getkey=_cfg_getkey;
ptr->_insert=_cfg_insert;
ptr->_lookup=_cfg_lookup;
ptr->_cleardirty=_cfg_cleardirty;
ptr->_set=_cfg_set;
ptr->_splitline=_cfg_splitline;
ptr->_queuepush=_cfg_queuepush;
ptr->_queuenext=_cfg_queuenext;
ptr->_queuefree=_cfg_queuefree;
ptr->_getnode=_cfg_getnode;
ptr->_flush=_cfg_realflush;
if (_cfg_init(ptr)) return(NULL);
return(ptr);
}
+70
View File
@@ -0,0 +1,70 @@
/***********************************************
**
** cfg.h v0.01
**
** Generic config file handler
** (c) Gareth Watts 1998
*/
#define CFG_READONLY 1
#define CFG_READWRITE 2
struct cfg_node {
char *optname;
char *optvalue;
int dirty;
struct cfg_node *next;
};
struct cfg_queuenode {
struct cfg_node *ref;
struct cfg_queuenode *next;
};
#define CFG_HASHSIZE 1297
typedef struct cfg {
// PUBLIC METHODS
void (*free)(struct cfg *self);
int (*openfile)(struct cfg *self,char *fn,int mode);
int (*autoflush)(struct cfg *self,int flushmode);
char *(*getstring)(struct cfg *self,char *key);
int (*getint)(struct cfg *self,char *key);
float (*getfloat)(struct cfg *self,char *key);
int (*setstring)(struct cfg *self,char *key, char *value);
int (*setint)(struct cfg *self,char *key, int value);
int (*setfloat)(struct cfg *self,char *key, float value);
int (*flush)(struct cfg *self);
// PUBLIC DATA
char *lasterror;
// PRIVATE METHODS
int (*_init)(struct cfg *self);
int (*_getkey)(struct cfg *self,char *str);
int (*_insert)(struct cfg *self,char *keyname,char *keyval,int dirty);
struct cfg_node *(*_getnode)(struct cfg *self,char *keyname);
char *(*_lookup)(struct cfg *self,char *keyname);
int (*_cleardirty)(struct cfg *self,struct cfg_node *ptr);
int (*_splitline)(struct cfg *self,char *src, char **f, char **s);
int (*_set)(struct cfg *self, char *keyname, char *keyvalue);
int (*_queuepush)(struct cfg *self, struct cfg_node *node);
struct cfg_queuenode *(*_queuenext)(struct cfg *self, struct cfg_queuenode *last);
int (*_queuefree)(struct cfg *self);
int (*_flush)(struct cfg *self);
// PRIVATE DATA
struct cfg_node *cfg_hash[CFG_HASHSIZE];
struct cfg_queuenode *cfg_newsthead;
struct cfg_queuenode *cfg_newsttail;
char *filename;
int filemode;
int aflush;
} cfg;
cfg *cfg_new();
+76
View File
@@ -0,0 +1,76 @@
/*********************************************
** cfg.c example
** gareth@omnipotent.net 1/June/1998
**
** This code will create cfg_testfile.cfg if
** it doesn't already exist and set some
** values within it. Simple really.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "cfg.h"
#define TESTFILE "cfg_testfile.cfg"
int main() {
cfg *cfgfile;
/* First create our object */
if ((cfgfile=cfg_new())==NULL) {
printf("Error creating config object\n");
exit(255);
}
/* Then find a config file to open */
if (cfgfile->openfile(cfgfile,TESTFILE,CFG_READWRITE)!=0) {
printf("Error reading file: %s\n",cfgfile->lasterror);
cfgfile->free(cfgfile);
}
/* Save to disk on every update */
cfgfile->autoflush(cfgfile,1);
/* print out the current settings - Will return NULL if */
/* they don't currently exist (eg. new file) */
printf("'A test string' is set to '%s'\n",
cfgfile->getstring(cfgfile,"A test string"));
printf("'A test integer' is set to %d\n\n",
cfgfile->getint(cfgfile,"A test integer"));
/* set to some new values */
cfgfile->setstring(cfgfile,"A test string","Marvin the paranoid android");
cfgfile->setint(cfgfile,"A test integer",42);
/* print out the new settings */
printf("'A test string' is now set to '%s'\n",
cfgfile->getstring(cfgfile,"A test string"));
printf("'A test integer' is now set to %d\n\n",
cfgfile->getint(cfgfile,"A test integer"));
/* set the values to something else with autoflush off */
cfgfile->autoflush(cfgfile,0);
cfgfile->setstring(cfgfile,"A test string","Life, don't talk to me about life");
cfgfile->setint(cfgfile,"A test integer",417362);
/* print out the new settings */
printf("'A test string' is finally set to '%s'\n",
cfgfile->getstring(cfgfile,"A test string"));
printf("'A test integer' is finally set to %d\n\n",
cfgfile->getint(cfgfile,"A test integer"));
/* flush the last set of data to disk as autoflush is off */
cfgfile->flush(cfgfile);
/* cleanup */
cfgfile->free(cfgfile);
return(0);
}
+15
View File
@@ -0,0 +1,15 @@
##########################
# Test file thingy! #
##########################
# A string of some sort...
A test string = Life, don't talk to me about life
# An integer...
A test integer = 417362
My flag = yes
My other flag = true
#################### Here's a big-ass comment! ############################################################################################ See, it goes on for a long time! ####################################################
And stuff = Hell, yeah!
+73
View File
@@ -0,0 +1,73 @@
1998-04-26: Scott
all: Implemented logical/physical drivers.. Whew!
main.c, mode.c, lcd.* have changed, and I've added text.* and
MtxOrb.* driver files...
New commandline option "-l driver" selects a driver.
1998-04-21: Scott
all: Lots of updates... (patches, etc)
Implemented a frame buffer, and custom characters...
Added lots of comments, and cleaned a few things...
Added a few function to lcd.c
1998-03-22: Scott
main.c: Should exit cleanly now, always... It sometimes wouldn't, if killed
by init at shutdown... (it would get stuck in a usleep for too
long, and then get killed instead of shutting down)
main.c: Changed timing method... Sequences now specify their length in
TIME_UNITs. A time unit is 1/8th of a second. This should make
blinking and other such things easy...
main.c: Removed command line options to specify timings... Why would the
user really need to change that anyway?
main.c: A few mode-feedback things are implemented: blinking, and backlight
on/off stuff...
mode.c: Xload_screen now sends feedback to toggle blinking for a high load,
or turn the backlight off for no load...
1998-03-13: Scott
Makefile: Installs man page in /usr/local/man/man1...
main.c: Now detects previously running lcdproc.
lock.?: New files for detecting another lcdproc...
Now detects an already-running process, and gets its pid. So far,
it just exits when this happens.
1998-02-28: Scott
Makefile: Now handles installation with "make install".
main.c: New command line stuff... (in man page) Also, default contrast is
140 now. Looks better from all angles, at least on my machine. :)
lcd.1: Man page. New.. :)
mode.c: Rearranged memory screen.. Shows Memory and Swap space separately,
with two graphs.
1998-02-24: Scott
mode.c: Rearranged memory screen. Worked around hbar bios bug. Added swap
info to this screen also, so get_mem_info is back to its former
state. (call it on an array)
mode.c: Fixed xload screen. It was displaying things one space to the left.
main.c: Changed command line style from "mode num_times delay_time" to
"mode total_time delay_time". Is this better or worse?
1998-02-22: Scott
main.c: Now handles SIGINT (Ctrl-C) and SIGTERM (kill) for a clean exit.
main.c: Default device now works. (device[] was getting overwritten by
argv[0], which would always be "lcd")
mode.c: Fixed CPU load meter. Decreased cpu buffer size back to 4.
mode.c: Made goodbye_screen() do something...
mode.c: Fixed am/pm on clock_screen(). Was previously displaying 12:xx:xxA
during the noon hour, instead of 12:xx:xxP.
1998-02-18: Scott
mode.c: Fixed crash on memory screen; commented out last two lines of
get_mem_info, which accessed a non-existent variable.
mode.c: Added "rep" parameter to all screen functions. Specifies how many times
that screen has been run. Using 0 will force screen clear/redraw, and
the time-based ones also use this to determine if colons should be drawn.
main.c: Implemented simple command-line parameters. Example:
lcd m 4 .5 /dev/cua1 x 1 2
uses /dev/cua1 for lcd, displaying memory info 4 times at .5 seconds each,
and the xload screen once for 2 seconds; then loops.
mode.c & lcd.c: created "NOLCD" preprocessor switch. When defined, lcd uses
text output (stdout) instead of the com port.
mode.c: Changed clock string generation to use "%02d" to achieve that
"02:37:06" look. (hint: printf can pad numbers with leading 0's)
main.c: Added minimal command-line help.
+429
View File
@@ -0,0 +1,429 @@
#include <stdio.h> // for NULL definition
#include "llistd.h" // function prototypes
/*****************************************************************************
* AUTHOR: Scott Scriven, SSN: 523-21-9640, CLASS: CS151.003, DATE: 96-11-21
******************************************************************************
* Doubly Linked Lists! (some of my really old code, commented for this class)
* This code will handle "generic" Doubly-Linked Lists. These lists can be
* any type as long as they satisfy a few requirements:
* Your structure must start with two integer pointers:
* struct mystruct {
* int *next, *prev;
* ...
* };
* That's all, pretty much.
*
* Most of the functions take integer pointers. This means you will have to
* call them in one of the following ways:
* function((int *)&mystruct);
* function((int *)mystruct);
* function(&mystruct.next);
*
******************************************************************************
* If I'm not mistaken, this code should work regardless of your machine's
* integer size (16/32/64/etc... bit)
******************************************************************************
* Note that we have to do NULL checking to make sure we don't try to write
* to protected areas of memory if we reach the beginning/end of a list.
*
* We also do some circular-link checking to avoid infinite loops.
* These loops will work fine:
* a <-> b <-> c <-> a <-> b...
* a <-> b <-> c -> c -> c...
* This loop might make this code puke:
* a <-> b <-> c <-> d -> c d <- e <-> f <-> g
*****************************************************************************/
/*****************************************************************************
* Function: LLMakeFirstNode()
******************************************************************************
* Description:
* Makes a node stand alone; creates the first node of a list. You must do
* the memory/node allocation manually. It returns the parameter you send it.
******************************************************************************
* Function Calls:
* None.
*****************************************************************************/
int * LLMakeFirstNode(int * first) // Make a standalone node...
{
(int *)first[0] = NULL;
(int *)first[1] = NULL;
return first;
}
/*****************************************************************************
* Function: LLFindFirst()
******************************************************************************
* Description:
* Given a node of a list, it returns the first node of the list (assuming
* that the first node either points to NULL or itself). If list is circular,
* it returns *next* node in the list.
******************************************************************************
* Function Calls:
* LLFindPrev See below...
*****************************************************************************/
int * LLFindFirst(int * current) // returns address of First node
{
int *prev=current;
// If prev[1] (pointer to previous node) is NULL, we hit the beginning.
// If prev[1] is the same as current, we've got a circular linked list...
while((int *)prev[1] != NULL && (int *)prev[1] != current)
{
prev = LLFindPrev(prev);
}
return prev;
}
/*****************************************************************************
* Function: LLFindNext()
******************************************************************************
* Description:
* Returns the address of the next node in the list, or NULL if we're at the
* end of the list.
******************************************************************************
* Function Calls:
* None.
*****************************************************************************/
int * LLFindNext(int * current) // returns address of next node
{
// Return the address of the next node
if((int *)current[0] != current)
return (int *)current[0];
else
return NULL;
}
/*****************************************************************************
* Function: LLFindPrev()
******************************************************************************
* Description:
* Returns the address of the previous node in the list, or NULL if we're
* at the beginning of the list.
******************************************************************************
* Function Calls:
* None.
*****************************************************************************/
int * LLFindPrev(int * current) // returns address of prev node
{
// Return the address of the previous node
if((int *)current[1] != current)
return (int *)current[1];
else
return NULL;
}
/*****************************************************************************
* Function: LLFindLast()
******************************************************************************
* Description:
* Given any node, returns the address of the last node of that list. This
* works just like LLFindFirst(), but in reverse.
******************************************************************************
* Function Calls:
* LLFindNext See above...
*****************************************************************************/
int * LLFindLast(int * current) // returns address of last node
{
int *next = current;
// If next[0] (pointer to next node) is NULL, we hit the end.
// If next[0] is the same as current, we've got a circular linked list...
while((int *)next[0] != NULL && (int *)next[0] != current)
{
next = LLFindNext(next);
}
return next;
}
/*****************************************************************************
* Function: LLAddNode()
******************************************************************************
* Description:
* Inserts a node in the list *after* the "current" node. It updates the
* list neighbors accordingly.
******************************************************************************
* Function Calls:
* LLFindNext See above...
*****************************************************************************/
int * LLAddNode(int * current, int * add) // Adds node AFTER current one
{
int *next;
if(current == add) return current; // We can't add a node to itself...
next = LLFindNext(current); // Get the next node address
(int *)current[0] = add; // Point the current node to the new node
(int *)add[0] = next; // Point the new node to next node
(int *)add[1] = current; // Make new node point back to the current node
if(next != NULL)
(int *)next[1] = add; // Point next node back to the new node
return add; // Return the address of the new node
}
/*****************************************************************************
* Function: LLInsertNode()
******************************************************************************
* Description:
* Inserts a node in the list *before* the "current" node. It updates the
* list neighbors accordingly.
******************************************************************************
* Function Calls:
* LLFindPrev See above...
*****************************************************************************/
int * LLInsertNode(int * current, int * add) // Adds node BEFORE current one
{
int *prev;
if(current == add) return current; // We can't add a node to itself...
prev = LLFindPrev(current); // Get the previous node's address
if(prev != NULL)
(int *)prev[0] = add; // Previous node points to new node
(int *)add[0] = current; // New node points to current node
(int *)add[1] = prev; // New node points back to previous node
(int *)current[1] = add; // Current node points back to new node
return add; // Return the address of the new node
}
/*****************************************************************************
* Function: LLCutNode()
******************************************************************************
* Description:
* Removes a node from the list, and joins its neighbors. Returns the
* address of the cut node. You must deallocate the node manually, if
* you want to free its memory.
******************************************************************************
* Function Calls:
* LLFindPrev See Above...
* LLFindNext See Above...
*****************************************************************************/
int * LLCutNode(int * cut) // Removes a node from the link
{
int * prev, * next;
prev = LLFindPrev(cut); // Find surrounding nodes...
next = LLFindNext(cut);
(int *)cut[0] = NULL; // Make the removed node point nowhere
(int *)cut[1] = NULL;
if(prev != NULL) // Join the surrounding nodes...
(int *)prev[0] = next;
if(next != NULL)
(int *)next[1] = prev;
return cut; // Return the address of the node that has been cut...
}
/*****************************************************************************
* Function: LLPush()
******************************************************************************
* Description:
* Inserts a node at the end of the whole list. "Current" can be any node
* in the list, and "add" is the node you want to add.
******************************************************************************
* Function Calls:
* LLFindLast() See above...
* LLAddNode() See above...
*****************************************************************************/
int * LLPush(int * current, int * add) // Add node to end of list
{
int *last;
last = LLFindLast(current);
return LLAddNode(last, add);
}
/*****************************************************************************
* Function: LLPop()
******************************************************************************
* Description:
* Pops (removes) a node off the end of the list. Returns the address of
* the node we chopped off. "current" can be any node in the list.
******************************************************************************
* Function Calls:
* LLFindLast See above...
* LLCutNode See above...
*****************************************************************************/
int * LLPop(int * current) // Remove node from end of list
{
int *last;
last = LLFindLast(current);
return LLCutNode(last);
}
/*****************************************************************************
* Function: LLShift()
******************************************************************************
* Description:
* Pops (removes) a node from the beginning of the list. Returns the address
* of the node we cut off.
******************************************************************************
* Function Calls:
* LLFindFirst See above...
* LLCutNode See above...
*****************************************************************************/
int * LLShift(int * current) // Remove node from start of list
{
int *begin;
begin = LLFindFirst(current);
return LLCutNode(begin);
}
/*****************************************************************************
* Function: LLUnshift()
******************************************************************************
* Description:
* Inserts a node at the beginning of the list.
******************************************************************************
* Function Calls:
* LLFindFirst See above...
* LLInsertNode See above...
*****************************************************************************/
int * LLUnshift(int * current, int * add) // Add node to beginning of list
{
int *begin;
begin = LLFindFirst(current);
return LLInsertNode(begin, add);
}
/*****************************************************************************
* Function: LLSwapNodes()
******************************************************************************
* Description:
* Switches two nodes' positions in the linked list. It can handle cases
* when the nodes are complete seperate, cases when the nodes are each
* other's neighbors, and cases when the two nodes are the same one.
* No return value.
******************************************************************************
* Function Calls:
* LLFindNext See Above...
* LLFindPrev See above...
*****************************************************************************/
void LLSwapNodes(int * one, int * two) // Switch two nodes' positions...
{
int *firstprev, *firstnext;
int *secondprev, *secondnext;
if(one == two) return; // if they're the same, do nothing
firstprev = LLFindPrev(one); // Store the addresses of their neighbors...
firstnext = LLFindNext(one);
secondprev = LLFindPrev(two);
secondnext = LLFindNext(two);
if(firstprev != NULL) (int *)firstprev[0] = two; // Swap their
if(firstnext != NULL) (int *)firstnext[1] = two; // Neighbors' pointers
if(secondprev != NULL) (int *)secondprev[0] = one;
if(secondnext != NULL) (int *)secondnext[1] = one;
(int *)one[0] = secondnext; // Swap the two nodes' pointers
(int *)one[1] = secondprev;
(int *)two[0] = firstnext;
(int *)two[1] = firstprev;
if(firstnext == two) (int *)one[1] = two; // Fix things if they were
if(firstprev == two) (int *)one[0] = two; // next to each other...
if(secondprev == one) (int *)two[0] = one;
if(secondnext == one) (int *)two[1] = one;
}
/*****************************************************************************
* Function: LLCountNodes()
******************************************************************************
* Description:
* Traverses the entire list and returns the number of nodes it finds.
******************************************************************************
* Function Calls:
* LLFindFirst See above...
* LLFindNext See above...
*****************************************************************************/
int LLCountNodes(int * current) // Returns # of nodes in entire list
{
int numnodes=1;
int *first, *next;
first = LLFindFirst(current); // Get the first node...
next = first;
// If next[0] (pointer to next node) is NULL, we hit the end.
// If next[0] is the same as current, we've got a circular linked list...
while((int *)next[0] != NULL && (int *)next[0] != first)
{
numnodes++;
next = LLFindNext(next);
}
return numnodes;
}
/*****************************************************************************
* Function: LLSelectSort()
******************************************************************************
* Description:
* Given any node in a list, sorts the whole list using a selection sort
* algorithm. You must supply a function to compare two nodes. The
* return value is the address of the new first node in the list.
******************************************************************************
* Function Calls:
* LLCountNodes See above...
* LLFindLast See above...
* LLFindFirst See above...
* LLFindNext See above...
* LLFindPrev See above...
* LLSwapNodes See above...
* compare The user-defined function which compares two nodes.
* If you've ever used qsort, this should be familiar.
*****************************************************************************/
// Sorts the list and returns a pointer to the first node
int * LLSelectSort(int * current, int compare(void *, void *))
{
int i,j; // Junk / loop variables
int numnodes; // number of nodes in list
int *best, *last; // best match and last node in the list
numnodes = LLCountNodes(current); // get the number of nodes...
last = LLFindLast(current); // Find the last node.
for(i=numnodes-1; i>1; i--)
{
current = LLFindFirst(current); // get the first node again
best = last; // reset our "best" node
for(j=0; j<i; j++)
{
if(compare(current, best) > 0) // If we found a better match...
{
best = current; // keep track of the "best" match
}
current = LLFindNext(current); // Go to the next node.
}
LLSwapNodes(last, best); // Switch two nodes...
last = LLFindPrev(best); // And go backwards by one node.
}
return LLFindFirst(current); // return pointer to the first node.
}
+63
View File
@@ -0,0 +1,63 @@
#ifndef LLISTD_H
#define LLISTD_H
/*****************************************************************************
* AUTHOR: Scott Scriven, SSN: 523-21-9640, CLASS: CS151.003, DATE: 96-11-21
******************************************************************************
* Doubly Linked Lists!
* This code will handle "generic" Doubly-Linked Lists. These lists can be
* any type as long as they satisfy a few requirements:
* Your structure must start with two integer pointers:
* struct mystruct {
* int *next, *prev;
* ...
* };
* That's all, pretty much.
*
* Most of the functions take integer pointers. This means you will have to
* call them in one of the following ways:
* function((int *)&mystruct);
* function((int *)mystruct);
* function(&mystruct.next);
*
******************************************************************************
* If I'm not mistaken, this code should work regardless of your machine's
* integer size (16/32/64/etc... bit)
******************************************************************************
* Note that we have to do NULL checking to make sure we don't try to write
* to protected areas of memory if we reach the beginning/end of a list.
*
* We also do some circular-link checking to avoid infinite loops.
* These loops will work fine:
* a <-> b <-> c <-> a <-> b...
* a <-> b <-> c -> c -> c...
* This loop might make this code puke:
* a <-> b <-> c <-> d -> c d <- e <-> f <-> g
*****************************************************************************/
// See llistd.c for detailed descriptions of these functions.
int * LLMakeFirstNode(int * first); // Make a standalone node...
int * LLFindFirst(int * current); // returns address of First node
int * LLFindNext(int * current); // returns address of next node
int * LLFindPrev(int * current); // returns address of prev node
int * LLFindLast(int * current); // returns address of last node
int * LLAddNode(int * current, int * add); // Adds node AFTER current one
int * LLInsertNode(int * current, int * add); // Adds node BEFORE current one
int * LLCutNode(int * cut); // Removes a node from the link
int * LLPush(int * current, int * add); // Add node to end of list
int * LLPop(int * current); // Remove node from end of list
int * LLShift(int * current); // Remove node from start of list
int * LLUnshift(int * current, int * add); // Add node to beginning of list
void LLSwapNodes(int * one, int * two); // Switch two nodes positions...
int LLCountNodes(int * current); // Returns # of nodes in entire list
// "Selection Sort"s the list and returns a pointer to the first node
int * LLSelectSort(int * current, int compare(void *, void *));
#endif
+318
View File
@@ -0,0 +1,318 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/time.h>
#include <termios.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
#include "main.h"
#include "lcd.h"
#include "mode.h"
//#include "lock.h"
#include "sockets.h"
// TODO: Commenting... Everything!
char version[] = "v0.3.4";
char build_date[] = "1998-06-20";
int Quit = 0;
/*
Mode List:
See below... (default_sequence[])
*/
typedef struct mode {
char which;
int num_times;
int delay_time;
} mode;
void HelpScreen();
void exit_program(int val);
void main_loop(mode *sequence);
#define MAX_SEQUENCE 256
// 1/8th second is a single time unit...
#define TIME_UNIT 125000
// Contains a list of modes to run
mode default_sequence[] =
{
{ 'C', 32, 1, },// [C]PU
{ 'M', 8, 4, },// [M]emory
{ 'X', 1, 32, },// [X]-load (load histogram)
{ 'T', 8, 4, },// [T]ime/Date
{ 'D', 32, 1, },// [D]isk stats
{ 'A', 1, 16, },// [A]bout (credits)
{ 1 , 0, 0, },// Modes after this line will not be run by default...
// ... all non-default modes must be in here!
// ... they will not show up otherwise.
{ 'O', 8, 4, },// [O]ld Timescreen
{ 'U', 8, 4, },// Old [U]ptime Screen
{ 'B', 32, 1, },// [B]attery Status
{ 'G', 32, 1, },// Cpu histogram [G]raph
{ 0, 0, 0, },// No more.. all done.
};
// TODO: Clean up main()... It is still way too big.
// TODO: Socket language, client handling...
// TODO: Config file; not just command line
int main(int argc, char **argv)
{
char device[256] = "/dev/lcd";
char cfgfile[256] = "/etc/lcdproc.cf";
mode sequence[MAX_SEQUENCE];
char driver[256] = "MtxOrb";
int i, j, k;
int already_running = 0;
int contrast = 140;
int tmp;
memset(sequence, 0, sizeof(mode) * MAX_SEQUENCE);
// Ctrl-C will cause a clean exit...
signal(SIGINT, exit_program);
// and "kill"...
signal(SIGTERM, exit_program);
// and "kill -HUP" (hangup)...
signal(SIGHUP, exit_program);
// and just in case, "kill -KILL" (which cannot be trapped; but oh well)
signal(SIGKILL, exit_program);
// Check to see if we are already running...
// already_running = CheckForLock();
already_running = PingLCDport();
if(already_running < 0)
{
printf("Error checking for another LCDproc.\n");
return -1;
}
// Communicate with the previously running LCDproc
if(already_running > 0)
{
// "already_running" holds the pid of the LCDproc we want to talk to...
// Do the command line ("lcd pet status", or "lcd contrast 50")
// And stuff...
// ...Then exit
printf("Detected another LCDproc. (%i) Exiting...\n", already_running);
// Remove me ^^^^
return 0;
}
tmp = StartSocketServer();
if (tmp <= 0)
{
printf("Error starting socket server.\n");
return 0;
}
// Command line
memcpy(sequence, default_sequence, sizeof(default_sequence));
for(i=1, j=0; i<argc; i++)
{
if(argv[i][0] == '-') switch(argv[i][1])
{
// "C is for cookie (erm, contrast), and that is good enough for me..."
case 'C':
case 'c': if(argc < i+1) HelpScreen();
contrast = atoi(argv[++i]);
if(contrast <= 0) HelpScreen();
break;
// D for Device...
case 'D':
case 'd': if(argc < i+1) HelpScreen();
strcpy(device, argv[++i]);
break;
case 'L':
case 'l': if(argc < i+1) HelpScreen();
strcpy(driver, argv[++i]);
break;
// otherwise... Get help!
default: HelpScreen(); break;
}
// Parse command line here... read the man page.
else if(strlen(argv[i]) == 1)
{
// Grab the mode letter...
sequence[j].which = argv[i][0];
// If we have just a letter with no numbers...
// Set the defaults...
for(tmp=0, k=0; default_sequence[k].which; k++)
{
if(toupper(sequence[j].which) == default_sequence[k].which)
{
memcpy(&sequence[j], &default_sequence[k], sizeof(mode));
tmp=1;
break;
}
}
if(!tmp) { printf("Invalid Mode: %c\n", argv[i][0]); exit(0); }
j++;
// Set the last element to 0...
memset(sequence + j, 0, sizeof(mode));
} // End if(strlen(argv == 1))
else
{
// A multicharacter parameter by itself is assumed to be a config file..
strcpy(cfgfile, argv[i]);
printf("Ignoring config file: %s\n", cfgfile);
}
}
// Init the com port
if(lcd_init(device, driver) < 1)
{
printf("Cannot initialize %s.\n", device);
exit(1);
}
mode_init();
lcd.contrast(contrast);
main_loop(sequence);
// Clean up
exit_program(0);
return 0;
}
void HelpScreen()
{
printf("LCDproc, %s\n", version);
printf("Usage: lcdproc [-d device] [-c contrast] [modelist]\n");
printf("\tOptions in []'s are optional.\n");
printf("\t-l driver is the output driver to use:\n");
printf("\t\tMtxOrb, curses, text, debug\n");
printf("\t-d device is what the lcd display is hooked to. (/dev/cua0?)\n");
printf("\t-c contrast sets the screen contrast (0 - 255)\n");
printf("\tmodelist is \"mode [mode mode ...]\"\n");
printf("\tMode letters: [C]pu [G]raph [T]ime [M]emory [X]load [D]isk [B]attery [O]ld Time screen [U]ptime [A]bout\n");
printf("\n");
printf("\tUse \"man lcdproc\" for more info.\n");
printf("Example:\n");
printf("\tlcdproc -d /dev/cua1 C M X -l MtxOrb\n");
printf("\n");
exit(0);
}
///////////////////////////////////////////////////////////////////
// Called upon TERM and INTR signals...
//
void exit_program(int val)
{
Quit = 1;
//unlock(); // Not needed any more...
CloseAllConnections();
goodbye_screen(0);
lcd.flush();
lcd.backlight(1);
lcd.close();
mode_close();
exit(0);
}
///////////////////////////////////////////////////////////////////
// Main program loop...
//
void main_loop(mode *sequence)
{
int i, j, k;
int Quit=0;
int status=0;
int timer=0;
int blink=0;
int hold=0;
int heartbeat=1;
// Main loop
// Run whatever screen we want, then wait. Woo-hoo!
for(i=0; !Quit; )
{
timer=0;
for(j=0; hold || (j<sequence[i].num_times && !Quit); j++)
{
switch(sequence[i].which)
{
case 'g':
case 'G': status = cpu_graph_screen(j); break;
case 'c':
case 'C': status = cpu_screen(j); break;
case 'o':
case 'O': status = clock_screen(j); break;
case 'm':
case 'M': status = mem_screen(j); break;
case 'u':
case 'U': status = uptime_screen(j); break;
case 't':
case 'T': status = time_screen(j); break;
case 'd':
case 'D': status = disk_screen(j); break;
case 'x':
case 'X': status = xload_screen(j); break;
case 'b':
case 'B': status = battery_screen(j); break;
case 'a':
case 'A': status = credit_screen(j); break;
default: status = dumbass_screen(j); break;
}
for(k=0; k<sequence[i].delay_time; k++)
{
usleep(TIME_UNIT); timer++;
// Modify lcd status here... (blinking, for example)
switch(status)
{
case BLINK_ON : blink=1; break;
case BLINK_OFF: blink=0; lcd.backlight(1); break;
case BACKLIGHT_OFF: blink=0; lcd.backlight(0); break;
case BACKLIGHT_ON : blink=0; lcd.backlight(1); break;
case HOLD_SCREEN : hold=1; break;
case CONTINUE : hold=0; break;
}
status=0;
if(blink) lcd.backlight(! ((timer&15) == 15));
if(heartbeat)
{
// Set this to pulsate like a real heart beat...
// (binary is fun... :)
lcd.icon(!((timer+4)&5), 0);
lcd.chr(lcd.wid, 1, 0);
}
lcd.flush();
PollSockets();
}
}
i++;
if(sequence[i].which < 2) i=0;
}
}
+16
View File
@@ -0,0 +1,16 @@
#ifndef MAIN_H
#define MAIN_H
extern char version[];
extern char build_date[];
extern int Quit;
#define BLINK_ON 0x10
#define BLINK_OFF 0x11
#define BACKLIGHT_OFF 0x20
#define BACKLIGHT_ON 0x21
#define HOLD_SCREEN 0x30
#define CONTINUE 0x31
#endif
+162
View File
@@ -0,0 +1,162 @@
#include "menu.h"
/////////////////////////////////////////
// THIS IS NOT READY YET!
/////////////////////////////////////////
/////////////////////////////////////////////////////////
// Read menu.h to find out how this works.
//
// Internal record of all important menu info...
typedef struct MenuInfo
{
MenuItem *menu; // User-specified menu information
struct MenuInfo *parent; // NULL if root-level
int items; // number of items in the menu
int sel; // selected item
} MenuInfo;
// Main menu function...
int do_menu(MenuItem *menu, MenuInfo *parent);
void FillMenuInfo(MenuInfo *m, MenuItem *menu, MenuInfo *parent);
void DrawMenu(MenuInfo *m);
void DrawMenuItem(MenuInfo *m, int item);
///////////////////////////////////////////////////////////////////
// User-callable function...
//
int menu(MenuItem *menu)
{
int ret;
CreateArrows(); // Set custom characters for menu use...
ret = do_menu(menu, NULL);
return ret;
}
int do_menu(MenuItem *menu, MenuInfo *parent)
{
int current;
int uparrow;
int downarrow;
int key;
int err=0;
while(! err)
{
// Draw the menu...
// Wait for input
}
}
int do_menu(MenuItem *menu, MenuInfo *parent)
{
int i;
int items;
MenuInfo ThisMenu;
int old_sel;
int redraw=1;
int ret=0;
FillMenuInfo(&ThisMenu, menu, parent);
//FIXME: Get input here... Move the selection thingy
DrawMenu(&ThisMenu);
do{
//FIXME: Get input here... Move the selection thingy
// Figure out which button should be highlighted...
// And... if the "execute" button was pressed...
if()
{
ThisMenu.sel = i;
}
DrawMenu(&ThisMenu);
redraw = 0;
// Dismiss menu?
if( // cancel was pressed...
)
ret = GUI_CONT;
// pop up another menu?
if( // execute was pressed...
&&ThisMenu.sel >= 0
&&ThisMenu.menu[ThisMenu.sel].child)
{
i = do_menu(ThisMenu.menu[ThisMenu.sel].child, &ThisMenu);
if(i == GUI_OK) ret = GUI_OK;
}
// Or call a function?
else if( // execute was pressed...
&&ThisMenu.sel >= 0
&&ThisMenu.menu[ThisMenu.sel].func)
{
ret = ThisMenu.menu[ThisMenu.sel].func();
//ret = GUI_OK;
}
} while(! ret);
return ret;
}
//////////////////////////////////////////////////////////////////////
// Initializes a menu...
//
void FillMenuInfo(MenuInfo *m, MenuItem *menu, MenuInfo * parent)
{
m->menu = menu;
m->parent = parent;
m->sel = 0;
}
void DrawMenu(MenuInfo *m)
{
int i;
for(i=0; i<m->items; i++)
DrawMenuItem(m, i);
}
void DrawMenuItem(MenuInfo *m, int item)
{
// Figure out how much to scroll down...
// Write each menu item...
// Put arrows where needed (next to current item, and up/down arrow)
// m->menu[item].text holds the text string...
}
+58
View File
@@ -0,0 +1,58 @@
#ifndef MENU_H
#define MENU_H
//////////////////////////////////////////////
// THIS IS NOT READY YET!
//////////////////////////////////////////////
/*
Pull-down menus...
To use a menu, first define it; then call menu().
To define a menu, just declare an array of MenuItems. The last element
must have all NULL fields.
MenuItem FileMenu[] =
{
"Open", OpenFile_proc, NULL,
"Close", CloseFile_proc, NULL,
"Save", SaveFile_proc, NULL,
"Save As...", NULL, SaveAsMenu,
"Quit", Quit_proc, NULL,
NULL, NULL, NULL,
};
The first field is the text for the menu item.
The second field is a function to call when the item is picked.
The function should take no parameters, and return an int.
The return values are:
MENU_OK Normal return value. Menu will close.
MENU_CONT Menu will stay up after function returns.
The third field is the child menu to display when the item is picked.
Note that either the second or third field must be NULL. If both are
NULL, the item is considered to be just a label. (for example, a title)
It will be non-pickable if both are NULL.
*/
#define MENU_OK 1
#define MENU_CONT 2
typedef struct MenuItem
{
char *text;
int (*func)();
struct MenuItem *child;
} MenuItem;
// This does a pull-down menu...
int menu(MenuItem *menu);
#endif
+1107
View File
File diff suppressed because it is too large Load Diff
+30
View File
@@ -0,0 +1,30 @@
#ifndef MODE_H
#define MODE_H
//TODO: Net stats screen...
//TODO: "Who"
//TODO: biff / mail checking
// Character to use for padding title bars, etc...
extern int PAD;
// Character for the "..." symbol.
extern int ELLIPSIS;
int mode_init();
void mode_close();
int cpu_screen(int rep);
int cpu_graph_screen(int rep);
int clock_screen(int rep);
int mem_screen(int rep);
int uptime_screen(int rep);
int time_screen(int rep);
int disk_screen(int rep);
int xload_screen(int rep);
int battery_screen(int rep);
int credit_screen(int rep);
int dumbass_screen(int rep);
int goodbye_screen(int rep);
#endif
+273
View File
@@ -0,0 +1,273 @@
#include <unistd.h>
#include <stddef.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "sockets.h"
/**************************************************
LCDproc sockets code...
This is messy, and needs to be finished.
**************************************************/
fd_set active_fd_set, read_fd_set;
int sock;
// Length of longest transmission allowed at once...
#define MAXMSG 8192
int init_sockaddr (sockaddr_in *name,
const char *hostname,
unsigned short int port)
{
struct hostent *hostinfo;
name->sin_family = AF_INET;
name->sin_port = htons (port);
hostinfo = gethostbyname (hostname);
if (hostinfo == NULL)
{
fprintf (stderr,"Unknown host %s.\n", hostname);
return -1;
}
name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
return 0;
}
#if 0
// Creates a socket as a file...
int CreateNamedSocket(char *filename)
{
struct sockaddr_un name;
size_t size;
sock=socket(PF_FILE, SOCK_STREAM, 0);
if(sock < 0) return -1;
name.sun_family = AF_FILE;
strcpy (name.sun_path, filename);
/* The size of the address is
the offset of the start of the filename,
plus its length,
plus one for the terminating null byte. */
size = (offsetof (struct sockaddr_un, sun_path)
+ strlen (name.sun_path) + 1);
if (bind (sock, (struct sockaddr *) &name, size) < 0)
return -1;
return sock;
}
#endif
// Creates a socket in internet space
int CreateInetSocket(unsigned short int port)
{
struct sockaddr_in name;
/* Create the socket. */
//fprintf(stderr,"Creating Inet Socket\n");
sock = socket (PF_INET, SOCK_STREAM, 0);
if (sock < 0)
return -1;
/* Give the socket a name. */
//fprintf(stderr,"Binding Inet Socket\n");
name.sin_family = AF_INET;
name.sin_port = htons (port);
name.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0)
return -1;
return sock;
}
// Checks the LCDproc port for a response...
int PingLCDport()
{
struct sockaddr_in servername;
int err=0;
char ping[16] = {0xFE, 0x01, 0};
//fprintf(stderr,"Creating socket (client)\n");
sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
fprintf(stderr,"Error creating socket (client)\n");
return sock;
}
//else fprintf(stderr,"Created socket (%i) (client)\n", sock);
init_sockaddr(&servername, "localhost", LCDPORT);
err = connect (sock,
(struct sockaddr *) &servername,
sizeof (servername));
if(err<0)
{
//fprintf (stderr,"connect failed (client)\n");
shutdown(sock, 2);
return 0; // Normal exit if server doesn't exist...
}
err = write (sock, ping, strlen(ping) + 1);
if (err < 0)
{
fprintf (stderr,"socket write error (client)");
shutdown(sock, 2);
return err;
}
shutdown(sock, 2);
return 1;
}
int ConnectAsClient()
{
return 0;
}
int StartSocketServer()
{
/* Create the socket and set it up to accept connections. */
sock = CreateInetSocket (LCDPORT);
if(sock < 0)
{
fprintf(stderr,"Error creating socket (server)\n");
return -1;
}
if (listen (sock, 1) < 0)
{
fprintf (stderr,"Listen error (server)\n");
return -1;
}
/* Initialize the set of active sockets. */
FD_ZERO (&active_fd_set);
FD_SET (sock, &active_fd_set);
return sock;
}
int PollSockets()
{
int i;
struct sockaddr_in clientname;
size_t size;
struct timeval t;
t.tv_sec = 0;
t.tv_usec = 0;
/* Block until input arrives on one or more active sockets. */
read_fd_set = active_fd_set;
if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, &t) < 0)
{
fprintf (stderr,"Select error (server)\n");
return -1;
}
/* Service all the sockets with input pending. */
for (i = 0; i < FD_SETSIZE; ++i)
if (FD_ISSET (i, &read_fd_set))
{
if (i == sock)
{
/* Connection request on original socket. */
int new;
size = sizeof (clientname);
new = accept (sock,
(struct sockaddr *) &clientname,
&size);
if (new < 0)
{
fprintf (stderr,"Accept error (server)\n");
return -1;
}
fprintf (stderr,"Server: connect from host %s, port %hd.\n",
inet_ntoa (clientname.sin_addr),
ntohs (clientname.sin_port));
FD_SET (new, &active_fd_set);
}
else
{
/* Data arriving on an already-connected socket. */
if (read_from_client (i) < 0)
{
close (i);
FD_CLR (i, &active_fd_set);
fprintf(stderr,"Closed connection %i\n", i);
}
}
}
return 0;
}
int read_from_client (int filedes)
{
char buffer[MAXMSG];
int nbytes;
nbytes = read (filedes, buffer, MAXMSG);
buffer[nbytes] = 0;
buffer[nbytes+1] = 0;
if (nbytes < 0) // Read error
{
fprintf (stderr,"Read error (server)\n");
return -1;
}
else if (nbytes == 0) // EOF
return -1;
else // Data Read
{
fprintf (stderr,"Server: got message: `%s'\n", buffer);
return 0;
}
}
int CloseAllConnections()
{
int i;
/* Service all the sockets with input pending. */
for (i = 0; i < FD_SETSIZE; ++i)
if (FD_ISSET (i, &read_fd_set))
{
/* Data arriving on an already-connected socket. */
close (i);
FD_CLR (i, &active_fd_set);
fprintf(stderr,"Closed connection %i\n", i);
}
return 0;
}
+99
View File
@@ -0,0 +1,99 @@
#define LCDPORT 13666
/**********************************************************************
LCDproc socket interface grammar:
RawText Print whatever you send, at whatever the current position is.
or...
0xFE Command prefix, followed by...
0x00 EOT. End of transmission, where applicicable.
0x01 Ping. Will respond with a "pong".
'k',x Send "keypad" input, character x (A-Z)
?,x,...,EOT Send new mode sequence (x,...)...
?,x Switch to new mode x immediately
?,xxxx Pause in current mode for x frames/seconds (0=infinite)
? Play -- continue mode cycle.
?,x,y,...,EOT
Send raw text to be displayed. x is style (raw, wrapped),
and y is num frames between lines displayed.
?,... Send MtxOrb-like control commands (bargraphs, etc)
... more to come later ...
**********************************************************************/
/*****************************************************************
LCDproc command line interface: (while running)
-command
Tells LCDproc to interpret stdin as raw commands to send through
the socket. Input must be formatted as above, in socket interface.
-function f
Runs LCDproc external function f, where f is one of the predefined
functions which can be assigned to keypad keys. (like NEXTMODE, etc)
-key x
Simulates keypad press of key 'x', where 'x' is (A-Z).
-print [time]
Prints stdin on LCD one line at a time, with no line-wrapping (raw),
with [time] frames between updates (lines).
-wrap [time]
Prints stdin as with "-print", but with line wrapping when possible.
-contrast xxx
Sets contrast to xxx (decimal)
-backlight [on/off]
Turns backlight [on/off/auto], or toggles it.
If [off], stays off.
If [on], stays on.
If [auto], LCDproc controls backlight based on load, etc...
-exit
-quit
Duh... :)
******************************************************************/
/*****************************************************************
LCDproc stuff supported in config file (loose approximation):
Grammar is tcl-style. I.e., "command arg1 arg2 ...".
Spaces are used as argument separators, *until* it thinks it has the final
argument. So, "function thing shell myprogram arg1 arg2 arg3" would be
split into "function", "thing", "shell", and "myprogram arg1 arg2 arg3".
User-definable functions (use built-in's to create new ones?):
Function mp3NextSong Shell /usr/local/bin/mp3player -next
Function MySequence Sequence cpu mem xload
Function OtherSequence Sequence time cd xload
Keypad keys can be bound to any _function_:
Key A mp3NextSong
Key B HaltSystem
Key C Menu
Key D Next/+
Key E OtherSequence
******************************************************************/
typedef struct sockaddr_in sockaddr_in;
int init_sockaddr (sockaddr_in *name,
const char *hostname,
unsigned short int port);
// Creates a socket in internet space
int CreateInetSocket(unsigned short int port);
// Checks the LCDproc port for a response...
int PingLCDport();
int StartSocketServer();
int PollSockets();
int read_from_client (int filedes);
int CloseAllConnections();
+644
View File
@@ -0,0 +1,644 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/utsname.h>
#include "stat.h"
#include "lcd.h"
/*
Don't use this yet! It's barely even started...
*/
struct load { unsigned long total, user, system, nice, idle; };
struct meminfo { int total, cache, buffers, free, shared; };
static char buffer[1024];
// Nothing else can see these...
static int meminfo_fd, load_fd, loadavg_fd, uptime_fd;
static char kver[SYS_NMLN];
static char sysname[SYS_NMLN];
static void reread(int f, char *errmsg);
static int getentry(const char *tag, const char *bufptr);
static void get_mem_info(struct meminfo *result);
static double get_loadavg(void);
static double get_uptime(void);
static void get_load(struct load * result);
int stat_init()
{
struct utsname *unamebuf =
(struct utsname *) malloc( sizeof(struct utsname) );
meminfo_fd = open("/proc/meminfo",O_RDONLY);
loadavg_fd = open("/proc/loadavg",O_RDONLY);
load_fd = open("/proc/stat",O_RDONLY);
uptime_fd = open("/proc/uptime",O_RDONLY);
#if 0
kversion_fd = open("/proc/sys/kernel/osrelease",O_RDONLY);
reread(kversion_fd, "main:");
sscanf(buffer, "%s", kver);
close(kversion_fd);
# endif
/* Get OS name and version from uname() */
if( uname( unamebuf ) != 0 ) {
perror( "Error calling uname:" );
}
strcpy( kver, unamebuf->release );
strcpy( sysname, unamebuf->sysname );
return 0;
}
void stat_close()
{
close(meminfo_fd);
close(loadavg_fd);
close(load_fd);
close(uptime_fd);
}
static void reread(int f, char *errmsg)
{
if (lseek(f, 0L, 0) == 0 && read(f, buffer, sizeof(buffer) - 1 ) > 0 )
return;
perror(errmsg);
exit(1);
}
static int getentry(const char *tag, const char *bufptr)
{
char *tail;
int retval, len = strlen(tag);
while (bufptr)
{
if (*bufptr == '\n') bufptr++;
if (!strncmp(tag, bufptr, len))
{
retval = strtol(bufptr + len, &tail, 10);
if (tail == bufptr + len) return -1;
else return retval;
}
bufptr = strchr( bufptr, '\n');
}
return -1;
}
static void get_mem_info(struct meminfo *result)
{
// int i, res; char *bufptr;
reread(meminfo_fd, "get_meminfo:");
result[0].total = getentry("MemTotal:", buffer);
result[0].free = getentry("MemFree:", buffer);
result[0].shared = getentry("MemShared:", buffer);
result[0].buffers = getentry("Buffers:", buffer);
result[0].cache = getentry("Cached:", buffer);
result[1].total = getentry("SwapTotal:", buffer);
result[1].free = getentry("SwapFree:", buffer);
}
static double get_loadavg(void)
{
double load;
reread(loadavg_fd, "get_load:");
sscanf(buffer, "%lf", &load);
return load;
}
static double get_uptime(void)
{
double uptime;
reread(uptime_fd, "get_uptime:");
sscanf(buffer, "%lf", &uptime);
return uptime;
}
static void get_load(struct load * result)
{
static struct load last_load = { 0, 0, 0, 0, 0 }; struct load curr_load;
reread(load_fd, "get_load:");
sscanf(buffer, "%*s %lu %lu %lu %lu\n",
&curr_load.user, &curr_load.nice, &curr_load.system, &curr_load.idle);
curr_load.total = curr_load.user + curr_load.nice
+ curr_load.system + curr_load.idle;
result->total = curr_load.total - last_load.total;
result->user = curr_load.user - last_load.user;
result->nice = curr_load.nice - last_load.nice;
result->system = curr_load.system - last_load.system;
result->idle = curr_load.idle - last_load.idle;
last_load.total = curr_load.total;
last_load.user = curr_load.user;
last_load.nice = curr_load.nice;
last_load.system = curr_load.system;
last_load.idle = curr_load.idle;
}
static char tmp[256];
// A couple of tables for later use...
static char *days[] = {
"Sunday, ",
"Monday, ",
"Tuesday, ",
"Wednesday,",
"Thursday, ",
"Friday, ",
"Saturday, ",
};
static char *months[] = {
" January",
" February",
" March",
" April",
" May",
" June",
" July",
" August",
"September",
" October",
" November",
" December",
};
//////////////////////////////////////////////////////////////////////////
// CPU screen shows info about percentage of the CPU being used
//
int cpu_screen(int rep)
{
#undef CPU_BUF_SIZE
#define CPU_BUF_SIZE 4
int i, j, n;
float value;
static float cpu[CPU_BUF_SIZE + 1][5];// last buffer is scratch
struct load load;
get_load(&load);
// Shift values over by one
for(i=0; i<(CPU_BUF_SIZE-1); i++)
for(j=0; j<5; j++)
cpu[i][j] = cpu[i+1][j];
// Read new data
cpu[CPU_BUF_SIZE-1][0] = ((float)load.user / (float)load.total) * 100.0;
cpu[CPU_BUF_SIZE-1][1] = ((float)load.system / (float)load.total) * 100.0;
cpu[CPU_BUF_SIZE-1][2] = ((float)load.nice / (float)load.total) * 100.0;
cpu[CPU_BUF_SIZE-1][3] = ((float)load.idle / (float)load.total) * 100.0;
cpu[CPU_BUF_SIZE-1][4] = (((float)load.user + (float)load.system +
(float)load.nice) / (float)load.total) * 100.0;
// Only clear on first display...
if(!rep)
{
lcd.clear();
lcd.init_hbar();
sprintf(tmp, "%c%c CPU LOAD %c%c", PAD, PAD, PAD, PAD);
lcd.string(1, 1, tmp);
lcd.string(1, 2, "Usr 0.0% Nice 0.0%");
lcd.string(1, 3, "Sys 0.0% Idle 0.0%");
lcd.string(1, 4, "0% 100%");
// Make all the same, if this is the first time...
for(i=0; i<CPU_BUF_SIZE-1; i++)
for(j=0; j<5; j++)
cpu[i][j] = cpu[CPU_BUF_SIZE-1][j];
}
// Average values for final result
for(i=0; i<5; i++)
{
value = 0;
for(j=0; j<CPU_BUF_SIZE; j++)
{
value += cpu[j][i];
}
value /= CPU_BUF_SIZE;
cpu[CPU_BUF_SIZE][i] = value;
}
value = cpu[CPU_BUF_SIZE][4];
n = (int)(value * 70.0);
if (value >= 99.9) { lcd.string(13, 1, " 100%"); }
else { sprintf(tmp, "%4.1f%%", value); lcd.string(13, 1, tmp); }
value = cpu[CPU_BUF_SIZE][0];
if (value >= 99.9) { lcd.string(5, 2, " 100%"); }
else { sprintf(tmp, "%4.1f%%", value); lcd.string(5, 2, tmp); }
value = cpu[CPU_BUF_SIZE][1];
if (value >= 99.9) { lcd.string(5, 3, " 100%"); }
else { sprintf(tmp, "%4.1f%%", value); lcd.string(5, 3, tmp); }
value = cpu[CPU_BUF_SIZE][2];
if (value >= 99.9) { lcd.string(16, 2, " 100%"); }
else { sprintf(tmp, "%4.1f%%", value); lcd.string(16, 2, tmp); }
value = cpu[CPU_BUF_SIZE][3];
if (value >= 99.9) { lcd.string(16, 3, " 100%"); }
else { sprintf(tmp, "%4.1f%%", value); lcd.string(16, 3, tmp); }
value = cpu[CPU_BUF_SIZE][4];
n = (int)(value * 70.0 / 100.0);
lcd.string(1, 4, "0% 100%");
lcd.hbar(3, 4, n);
return 0;
} // End cpu_screen()
//////////////////////////////////////////////////////////////////////////
// Cpu Graph Screen shows a quick-moving histogram of CPU use.
//
int cpu_graph_screen(int rep)
{
int i, j, n;
float value, maxload;
#undef CPU_BUF_SIZE
#define CPU_BUF_SIZE 2
static float cpu[CPU_BUF_SIZE + 1];// last buffer is scratch
static float cpu_past[LCD_MAX_WIDTH];
struct load load;
int status=0;
char out[LCD_MAX_WIDTH];
get_load(&load);
// Shift values over by one
for(i=0; i<(CPU_BUF_SIZE-1); i++)
cpu[i] = cpu[i+1];
// Read new data
cpu[CPU_BUF_SIZE-1] = ((float)load.user + (float)load.system
+ (float)load.nice) / (float)load.total;
// Only clear on first display...
if(!rep)
{
lcd.init_vbar();
// Make all the same, if this is the first time...
for(i=0; i<CPU_BUF_SIZE-1; i++)
cpu[i] = cpu[CPU_BUF_SIZE-1];
}
//lcd.clear();
for(i=2; i<=lcd.hgt; i++)
lcd.string(1,i," ");
// Average values for final result
value = 0;
for(j=0; j<CPU_BUF_SIZE; j++)
{
value += cpu[j];
}
value /= (float)CPU_BUF_SIZE;
cpu[CPU_BUF_SIZE] = value;
maxload=0;
for(i=0; i<lcd.wid-1; i++)
{
cpu_past[i] = cpu_past[i+1];
lcd.vbar(i+1, cpu_past[i]);
if(cpu_past[i] > maxload) maxload = cpu_past[i];
}
value = cpu[CPU_BUF_SIZE];
n = (int)(value * 8.0 * (float)(lcd.hgt-1));
cpu_past[lcd.wid-1] = n;
lcd.vbar(lcd.wid, cpu_past[lcd.wid-1]);
sprintf(out, "%c%c CPU GRAPH %c%c%c%c%c%c", PAD,PAD,
PAD,PAD,PAD,PAD,PAD,PAD);
lcd.string(1,1,out);
if(n > maxload) maxload = n;
if(cpu_past[lcd.wid-1] > 0 ) status = BACKLIGHT_ON;
if(maxload < 1) status = BACKLIGHT_OFF;
// return status;
return 0;
} // End cpu_graph_screen()
//////////////////////////////////////////////////////////////////////
// Clock Screen displays current time and date...
//
// TODO: 24-hour time, if desired.
int clock_screen(int rep)
{
char hr[8], min[8], sec[8], ampm[8];
char day[16], month[16];
time_t thetime;
struct tm *rtime;
int i;
if(!rep)
{
lcd.clear();
sprintf(tmp, "%c%c DATE & TIME %c%c%c%c%c", PAD, PAD, PAD, PAD, PAD, PAD, PAD);
lcd.string(1, 1, tmp);
}
time(&thetime);
rtime = localtime(&thetime);
strcpy(day, days[rtime->tm_wday]);
if (rtime->tm_hour > 12) { i = 1; sprintf(hr, "%02d", (rtime->tm_hour - 12)); }
else { i = 0; sprintf(hr, "%02d", rtime->tm_hour); }
if(rtime->tm_hour == 12) i=1;
sprintf(min, "%02d", rtime->tm_min);
sprintf(sec, "%02d", rtime->tm_sec);
if (i == 1) { sprintf(ampm, "%s", "P"); }
else { sprintf(ampm, "%s", "A"); }
if (rep & 1) { sprintf(tmp, "%s:%s:%s%s %s", hr, min, sec, ampm, day); }
else { sprintf(tmp, "%s %s %s%s %s", hr, min, sec, ampm, day); }
strcpy(month, months[rtime->tm_mon]);
lcd.string(1, 3, tmp);
sprintf(tmp, "%s %d, %d", month, rtime->tm_mday, (rtime->tm_year + 1900));
lcd.string(2, 4, tmp);
return 0;
} // End clock_screen()
/////////////////////////////////////////////////////////////////////////
// Mem Screen displays info about memory and swap usage...
//
int mem_screen(int rep)
{
int n;
struct meminfo mem[2];
if(!rep)
{
lcd.clear();
lcd.init_hbar();
sprintf(tmp, "%c%c%c MEM %c%c%c%c SWAP %c%c",
PAD,PAD,PAD,PAD,PAD,PAD,PAD,PAD,PAD);
lcd.string(1, 1, tmp);
lcd.string(9, 2, "Totl");
lcd.string(9, 3, "Free");
lcd.string(1, 4, "E F E F");
}
get_mem_info(mem);
sprintf(tmp, "%6dk", mem[0].total);
lcd.string(1, 2, tmp);
sprintf(tmp, "%6dk", mem[0].free);
lcd.string(1, 3, tmp);
sprintf(tmp, "%6dk", mem[1].total);
lcd.string(14, 2, tmp);
sprintf(tmp, "%6dk", mem[1].free);
lcd.string(14, 3, tmp);
// This gives just main memory usage
// n = (int)(50.0 - (float)mem[0].free / (float)mem[0].total * 50.0);
// This uses main + swap usage...
lcd.string(1, 4, "E F E F");
n = (int)(35.0 -
(float)mem[0].free / (float)mem[0].total
* 35.0);
lcd.hbar(2, 4, n);
n = (int)(35.0 -
(float)mem[1].free / (float)mem[1].total
* 35.0);
lcd.hbar(13, 4, n);
/*
{
int i;
for(i=0; i<100; i++)
{
lcd.hbar(1,1,i);
lcd.hbar(1,2,i);
lcd.hbar(1,3,i);
lcd.hbar(1,4,i);
usleep(100000);
}
}
*/
return 0;
} // End mem_screen()
////////////////////////////////////////////////////////////////////
// Uptime Screen shows info about system uptime and OS version
//
int uptime_screen(int rep)
{
int i;
char date[16], hour[8], min[8], sec[8];
double uptime;
if(!rep)
{
lcd.clear();
sprintf(tmp, "%c%c SYSTEM UPTIME %c%c%c", PAD, PAD, PAD, PAD, PAD);
lcd.string(1, 1, tmp);
sprintf(tmp, "%s %s", sysname, kver);
lcd.string(5, 4, tmp);
}
uptime = get_uptime();
i = (int)uptime / 86400;
sprintf(date, "%d day%s,", i, (i != 1 ? "s" : ""));
i = ((int)uptime % 86400) / 60 / 60;
sprintf(hour, "%02i",i);
i = (((int)uptime % 86400) % 3600) / 60;
sprintf(min, "%02i",i);
i = ((int)uptime % 60);
sprintf(sec, "%02i",i);
if (rep & 1)
sprintf(tmp, "%s %s:%s:%s", date, hour, min, sec);
else
sprintf(tmp, "%s %s %s %s", date, hour, min, sec);
i = ((20 - strlen(tmp)) / 2) + 1;
lcd.string(i, 3, tmp);
return 0;
} // End uptime_screen()
///////////////////////////////////////////////////////////////////////////
// Shows a display very similar to "xload"'s histogram.
//
int xload_screen(int rep)
{
static float loads[LCD_MAX_WIDTH];
static int first_time=1;
int n;
float loadmax=0, factor, x;
int status = 0;
if(first_time) // Only the first time this is ever called...
{
memset(loads, 0, sizeof(float)*LCD_MAX_WIDTH);
first_time = 0;
}
if(!rep)
{
lcd.clear();
}
for(n=0; n<(lcd.wid-2); n++) loads[n] = loads[n+1];
loads[lcd.wid-2] = get_loadavg();
for(n=0; n<lcd.wid-1; n++)
if(loads[n] > loadmax) loadmax = loads[n];
lcd.string(20, 4, "0");
n = (int)loadmax;
if ((float)n < loadmax) { n++; }
sprintf(tmp, "%i", n); lcd.string(20, 2, tmp);
if (loadmax < 1.0) factor = 24.0;
else factor = 24 / (float)n;
for(n=0; n<lcd.wid-1; n++)
{
x = (loads[n] * factor);
lcd.vbar(n+1, (int)x);
}
if(loadmax < 0.05) status = BACKLIGHT_OFF;
if(loadmax > 0.05) status = BACKLIGHT_ON;
if(loads[lcd.wid-2] > LOAD_THRESHOLD) status = BLINK_ON;
// This must be drawn *after* the vertical bars... (?)
sprintf(tmp, "%c%c LOAD AVG %2.2f %c%c", PAD, PAD, loads[lcd.wid-2], PAD, PAD);
lcd.string(1, 1, tmp);
if(!rep)
lcd.init_vbar();
return status;
} // End xload_screen()
////////////////////////////////////////////////////////////////////////
// Credit Screen shows who wrote this...
//
int credit_screen(int rep)
{
if(!rep)
{
lcd.clear();
sprintf(tmp, "%c%c LCDPROC %s %c%c%c%c",
PAD, PAD, version, PAD, PAD, PAD, PAD);
lcd.string(1, 1, tmp);
lcd.string(1, 2, " for Linux ");
lcd.string(1, 3, " by William Ferrell ");
lcd.string(1, 4, " and Scott Scriven ");
}
return 0;
} // End credit_screen()
//////////////////////////////////////////////////////////////////////
// This is mostly for debugging. It should never show up.
//
int dumbass_screen(int rep)
{
lcd.string(1,1, "---=== Haha... ==---");
lcd.string(1,2, " You specified an ");
lcd.string(1,3, " INVALID MODE!!! ");
lcd.string(1,4, "---== Ya LOSER! ==--");
/*
lcd.string(1,1, "--===GO AWAY!!!===--");
lcd.string(1,2, " You're a slimy, ");
lcd.string(1,3, " mold-ridden ");
lcd.string(1,4, " pop-tart! ");
*/
return BLINK_ON;
}
//////////////////////////////////////////////////////////////////////////
// This gets called upon program exit, to say "goodbye"
//
int goodbye_screen(int rep)
{
lcd.clear();
/*
lcd.string(1,1, "---===SHUTDOWN===---");
lcd.string(1,2, " DANGER, WILL ");
lcd.string(1,3, " ROBINSON! ");
lcd.string(1,4, "---===EJECT!!!===---");
usleep(250000);
*/
lcd.string(1,1, " ");
lcd.string(1,2, " Thanks for using ");
lcd.string(1,3, " LCDproc and Linux! ");
lcd.string(1,4, " ");
return 0;
}
+58
View File
@@ -0,0 +1,58 @@
#ifndef MODE_H
#define MODE_H
/*
Don't use this yet! It's barely even started!
*/
int stat_init();
void stat_close();
typedef struct status
{
// should hold persistent data somehow...
// data_type data;
// Takes position onscreen (x,y), and
// format (i=int, f=float, h=horz bar, v=vert bar, 2=24-hour, 1=12-hour,
// x=xload-style, etc...)
// Each stat will only draw valid formats...
// size is max size (graphs) or num digits, etc... (0 is "max" size)
// reread specifies to re-grab the value first.
void (*draw)(int x, int y, int size, char format, int reread);
void (*read)(int reread);
// Should also maybe be able to return the data?
// return_type (*get)();
};
extern status cpu;
extern status cpu_nice;
extern status cpu_idle;
extern status cpu_sys;
extern status cpu_usr;
extern status mem_free;
extern status mem_total;
extern status swap_free;
extern status swap_total;
extern status load;
extern status date;
extern status uptime;
extern status os_ver;
extern status disk_activity;
extern status disk_free;
extern status disk_total;
extern status net_sent;
extern status net_recv;
extern status net_rate;
#endif