summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Hammerschmid <linux@home.pages.at>2002-07-21 19:46:06 +0200
committerMartin Hammerschmid <linux@home.pages.at>2002-07-21 19:46:06 +0200
commitb49a01e5a6304aeb0b6ad20c4d74468e7d19ef47 (patch)
tree95ff43114959fe9d1df1ebda272fc901e9781d65
downloadvdr-plugin-lcdproc-b49a01e5a6304aeb0b6ad20c4d74468e7d19ef47.tar.gz
vdr-plugin-lcdproc-b49a01e5a6304aeb0b6ad20c4d74468e7d19ef47.tar.bz2
-rw-r--r--COPYING340
-rw-r--r--HISTORY6
-rw-r--r--Makefile84
-rw-r--r--README78
-rw-r--r--lcd.c677
-rw-r--r--lcd.h75
-rw-r--r--lcdkeyconf.h7
-rw-r--r--lcdproc.c299
-rw-r--r--lcdtranstbl-CFontz.h265
-rw-r--r--lcdtranstbl-hd44780.h265
-rw-r--r--lcdtranstbl-nomap.h264
-rw-r--r--sockets.c230
-rw-r--r--sockets.h92
13 files changed, 2682 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/HISTORY b/HISTORY
new file mode 100644
index 0000000..2c42785
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,6 @@
+VDR Plugin 'lcdproc' Revision History
+------------------------------------
+
+2002-05-20: Version 0.0.1
+
+- Initial revision.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..32814dd
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,84 @@
+#
+# Makefile for a Video Disk Recorder plugin
+#
+# $Id$
+
+# The official name of this plugin.
+# This name will be used in the '-P...' option of VDR to load the plugin.
+# By default the main source file also carries this name.
+#
+PLUGIN = lcdproc
+
+### The version number of this plugin (taken from the main source file):
+
+VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g')
+
+### The directory environment:
+
+DVBDIR = ../../../../DVB/ost/include
+VDRDIR = ../../..
+VDRINC = $(VDRDIR)/include
+LIBDIR = ../../lib
+TMPDIR = /tmp
+
+### The version number of VDR (taken from VDR's "config.h"):
+
+VDRVERSION = $(shell grep 'define VDRVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g')
+
+### The name of the distribution archive:
+
+ARCHIVE = $(PLUGIN)-$(VERSION)
+PACKAGE = vdr-$(ARCHIVE)
+
+### Includes and Defines (add further entries here):
+
+INCLUDES = -I$(VDRINC) -I$(DVBDIR)
+
+DEFINES = -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+
+ifndef LCDTRANS
+LCDTRANS = hd44780
+endif
+DEFINES += -DLCD_$(LCDTRANS)
+
+### The object files (add further files here):
+
+OBJS = $(PLUGIN).o lcd.o sockets.o
+
+### The C++ compiler and options:
+
+CXX = g++
+CXXFLAGS = -g -O2 -Wall -Woverloaded-virtual -m486
+
+### Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+# Dependencies:
+
+MAKEDEP = g++ -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+### Targets:
+
+all: libvdr-$(PLUGIN).so
+
+libvdr-$(PLUGIN).so: $(OBJS)
+ $(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@
+ @cp $@ $(LIBDIR)/$@.$(VDRVERSION)
+
+package: clean
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @mkdir $(TMPDIR)/$(ARCHIVE)
+ @cp -a * $(TMPDIR)/$(ARCHIVE)
+ @tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE)
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @echo Distribution package created as $(PACKAGE).tgz
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~
diff --git a/README b/README
new file mode 100644
index 0000000..bf2c252
--- /dev/null
+++ b/README
@@ -0,0 +1,78 @@
+This is a "plugin" for the Video Disk Recorder (VDR).
+
+Written by: Martin Hammerschmid <martin@hammerschmid.com>
+
+Project's homepage: home.pages.at/linux/dvb.html
+
+Latest version available at: http://home.pages.at/linux/dvb.html
+
+See the file COPYING for license information.
+
+Description: Output to LCD modules that are supported by LCDproc
+
+-------------------------------------------------------------------------
+
+vdr -Plcdproc or -P"lcdproc -h <host> -p <port>" ... makes vdr connect to a LCDd.
+
+Current channel info and menus are then displayed on the LCD too.
+
+I had a 4x20 character display in mind but it should
+work with 4x16 up to 4x40.
+
+LCDd can be used in an xterm or console too, so it
+might be useful even without having the hardware.
+( ./LCDd -d curses )
+
+lcdtranstbl-xxx.h is used to map characters for output to LCDd.
+Depending on the LCD hardware some characters may not displayed
+correctly, you can fix that by altering this table ...
+use lcdtranstbl-nomap.h if you don't want anything mapped.
+what table is used can be selected at compile time:
+e.g. ... LCDTRANS=CFontz make plugins ...
+values for LCDTRANS are 'hd44780', 'CFontz' and 'nomap' ('hd44780' is the default value).
+Thanks to Stephan Schreiber <stephan@sschreiber.de> for lcdtranstbl-CFontz.h.
+
+LCDproc is available at http://lcdproc.omnipotent.net/
+or here http://sourceforge.net/projects/lcdproc/
+
+ What's needed to run a LCD?
+
+ Hardware:
+
+ I used a single 4x20 LCD that works with the hd44780 8-bit driver on
+ the printer port.
+ ( availible at http://www.conrad.com/ product ID: 187275
+ or see http://www.lcd-module.de/eng/doma/standard.htm )
+
+ printer port LCD
+ ----------------------------------------------------------------------
+ GND (1) (used the PC's power suppy (black cable))
+ +5V (2) (used the PC's power suppy (red cable))
+ Vadj (3) (contrast, conneced to GND works fine for me)
+
+ D0 (2) D0 (7)
+ D1 (3) D1 (8)
+ D2 (4) D2 (9)
+ D3 (5) D3 (10)
+ D4 (6) D4 (11)
+ D5 (7) D5 (12)
+ D6 (8) D6 (13)
+ D7 (9) D7 (14)
+ nSTRB (1) EN (6)
+ INIT (16) RS (4)
+ RW (5) (connected to GND (1) of the LCD)
+ GND (18-25)
+ --- optional for LCDs with background illumination ---
+
+ LED+ (15) (connected to +5V over a 100Ohm resisitor
+ to make it not too bright)
+ LED- (16) (connected to GND)
+
+ Software:
+
+ Last tested with lcdproc-0.4.1 ( http://prdownloads.sourceforge.net/lcdproc/lcdproc-0.4.1.tar.gz )
+ LCDd -d HD44780 "-p 0x3bc -c winamp"
+ should run LCDd for the hardware described above conneceted to the
+ printer port (in my case the port's base address is 0x3bc).
+
+Martin
diff --git a/lcd.c b/lcd.c
new file mode 100644
index 0000000..abd3e74
--- /dev/null
+++ b/lcd.c
@@ -0,0 +1,677 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <vdr/config.h>
+#include <vdr/i18n.h>
+#include <vdr/tools.h>
+#include "lcd.h"
+#include "sockets.h"
+#include "lcdkeyconf.h"
+
+// character mapping for output, see cLcd::Write
+#ifdef LCD_hd44780
+#include "lcdtranstbl-hd44780.h" // hd44780 output
+#endif
+#ifdef LCD_CFontz
+#include "lcdtranstbl-CFontz.h" // CFontz output thanks to Stephan Schreiber.
+#endif
+#ifdef LCD_nomap
+#include "lcdtranstbl-nomap.h" // unmapped output (usable for curses output)
+#endif
+
+#define LCDMENU 0
+#define LCDTITLE 1
+#define LCDREPLAY 2
+#define LCDMISC 3
+#define LCDVOL 4
+
+// public:
+
+cLcd::cLcd() {
+ int i,j;
+ connected=false; ThreadStateData.showvolume=false; sock=wid=hgt=cellwid=cellhgt=0;
+ replayDvbApi=NULL; primaryDvbApi=NULL;
+
+ for (i=0;i<LCDMAXSTATES;i++) for (j=0;j<4;j++) {
+ ThreadStateData.lcdbuffer[i][j][0]=' ';
+ ThreadStateData.lcdbuffer[i][j][1]='\0';
+ ThreadStateData.lcddirty[i][j]=true;
+ }
+ ThreadStateData.State=Menu;
+ for (i=0;i<LCDMAXSTATEBUF;i++) LastState[i]=Title; LastStateP=0;
+ ThreadStateData.barx=1, ThreadStateData.bary=1, ThreadStateData.barl=0;
+ for (i=0;i<LCDMAXCARDS;i++) ThreadStateData.CardStat[i]=0;
+}
+
+cLcd::~cLcd() {
+ if (connected) { /*cLcd::Stop();*/ cLcd::Close(); } //YYYY
+}
+
+bool cLcd::Connect( char *host, unsigned int port ) {
+
+ char istring[1024];
+ unsigned int i=0;
+
+ if ( ( sock = sock_connect(host,port) ) < 1) {
+ return connected=false;
+ }
+
+ sock_send_string(sock, "hello\n");
+ usleep(500000); // wait for a connect message
+ sock_recv(sock, istring, 1024);
+
+ if ( strncmp("connect LCDproc",istring,15) != 0 ) { cLcd::Close(); return connected=false; }
+
+ while ( (strncmp("lcd",istring+i,3) != 0 ) && (i<(strlen(istring)-5)) ) i++;
+
+ if (sscanf( istring+i,"lcd wid %d hgt %d cellwid %d cellhgt %d"
+ , &wid, &hgt, &cellwid, &cellhgt) ) connected=true;
+
+ if ((hgt < 4 ) || (wid < 16)) connected = false; // 4 lines are needed, may work with more than 4 though
+ if (!connected) { cLcd::Close(); return connected; }
+
+ sock_send_string(sock,"screen_add VDR\n"); sock_recv(sock, istring, 1024);
+ sock_send_string(sock,"screen_set VDR -heartbeat off\n"); sock_recv(sock, istring, 1024);
+ sock_send_string(sock,"widget_add VDR line1 string\n"); sock_recv(sock, istring, 1024);
+ sock_send_string(sock,"widget_add VDR line2 string\n"); sock_recv(sock, istring, 1024);
+ sock_send_string(sock,"widget_add VDR line3 string\n"); sock_recv(sock, istring, 1024);
+ sock_send_string(sock,"widget_add VDR line4 string\n"); sock_recv(sock, istring, 1024);
+ sock_send_string(sock,"widget_add VDR prbar hbar\n"); sock_recv(sock, istring, 1024);
+ sock_send_string(sock,"widget_set VDR prbar 1 1 0\n"); sock_recv(sock, istring, 1024);
+
+ for (i=0; i<LcdMaxKeys;i++) {
+ sprintf(istring,"client_add_key %c\n",LcdUsedKeys[i]);
+ sock_send_string(sock,istring);
+ sock_recv(sock, istring, 1024);
+ }
+
+ cLcd::Start(); SetThreadState(Title); // Start thread
+ return connected;
+}
+
+void cLcd::Close() {
+ sock_close(sock);
+ connected=false; sock=wid=hgt=cellwid=cellhgt=0;
+}
+
+void cLcd::Info() { // just for testing ...
+ if (connected)
+ printf("sock %d, wid %d, hgt %d, cellwid %d, cellhgt %d\n",sock, wid, hgt, cellwid, cellhgt);
+ else
+ printf("not connected\n");
+}
+
+void cLcd::SetTitle( const char *string) {
+ if (!connected) return;
+
+ unsigned int i;
+ char title[wid+1];
+ const char *trstring=tr("Schedule - %s");
+ int trstringlength=strlen(trstring)-3;
+
+ if (strncmp(trstring,string,trstringlength)==0) {
+ title[0]='>'; snprintf( title+1, wid,"%s",string+trstringlength);
+ } else if (strlen(string) > (wid-1)) {
+ snprintf( title, wid+1,"%s",string);
+ } else {
+ memset(title,' ',wid/2+1);
+ snprintf(title + ( (wid-strlen(string))/2 ),wid-( (wid-strlen(string))/2 ),"%s",string); // center title
+ for (i=0;i<strlen(title);i++) title[i]=toupper(title[i]); // toupper
+ }
+ cLcd::SetLine(LCDMENU,0,title);
+}
+
+void cLcd::SetMain( unsigned int n, const char *string) {
+ if (!connected) return;
+
+ char line2[wid+1];
+ char line3[wid+1];
+
+ if (string != NULL) {
+ cLcd::Copy(StringBuffer,string,2*wid);
+ cLcd::Split(StringBuffer,line2,line3);
+ }
+ cLcd::SetBuffer(n,NULL,line2,line3,NULL);
+}
+
+void cLcd::SetHelp( unsigned int n, const char *Red, const char *Green, const char *Yellow, const char *Blue) {
+ if (!connected) return;
+
+ char help[2*wid], red[wid+1], green[wid+1], yellow[wid+1], blue[wid+1];
+ unsigned int allchars=0, i, empty=0, spacewid=1;
+ char *longest, *longest1, *longest2;
+
+ if ( Red==NULL || Red[0]=='\0' ) {
+ empty++; red[0]=' '; red[1]='\0';
+ } else {
+ strncpy(red,Red,wid); allchars+=strlen(red);
+ }
+ if ( Green==NULL || Green[0]=='\0' ) {
+ empty++; green[0]=' '; green[1]='\0';
+ } else {
+ strncpy(green,Green,wid); allchars+=strlen(green);
+ }
+ if ( Yellow==NULL || Yellow[0]=='\0' ) {
+ empty++; yellow[0]=' '; yellow[1]='\0';
+ } else {
+ strncpy(yellow,Yellow,wid); allchars+=strlen(yellow);
+ }
+ if ( Blue==NULL || Blue[0]=='\0' ) {
+ empty++; blue[0]=' '; blue[1]='\0';
+ } else {
+ strncpy(blue,Blue,wid); allchars+=strlen(blue);
+ }
+
+ while (allchars > (wid-empty-3)) {
+ longest1=( strlen(red) > strlen(green) ) ? red : green;
+ longest2=( strlen(yellow) > strlen(blue) ) ? yellow : blue;
+ longest =( strlen(longest1) > strlen(longest2) ) ? longest1: longest2;
+ longest[strlen(longest)-1]='\0'; allchars--;
+ }
+
+ if (empty>0) {
+ spacewid=(wid-allchars-3)/empty;
+ if (spacewid<1) spacewid=1;
+ char spacer[spacewid+1]; memset(spacer,'-',spacewid); spacer[spacewid]='\0';
+ if ( Red==NULL || Red[0]=='\0' ) strncpy(red,spacer,spacewid+1);
+ if ( Green==NULL || Green[0]=='\0' ) strncpy(green,spacer,spacewid+1);
+ if ( Yellow==NULL || Yellow[0]=='\0' ) strncpy(yellow,spacer,spacewid+1);
+ if ( Blue==NULL || Blue[0]=='\0' ) strncpy(blue,spacer,spacewid+1);
+ }
+
+ #define MANYBLANKS "%s "
+
+ snprintf(help,wid,MANYBLANKS,red);
+ snprintf(help+strlen(red)+1,wid,MANYBLANKS,green);
+ snprintf(help+wid-strlen(blue)-strlen(yellow)-1,wid,MANYBLANKS,yellow);
+ snprintf(help+wid-strlen(blue),strlen(blue)+1,"%s",blue);
+ for (i=0;i<strlen(help);i++) help[i]=toupper(help[i]);
+ cLcd::SetLine(n,3,help);
+}
+
+void cLcd::SetStatus( const char *string) {
+ if (!connected) return;
+
+ char statstring[2*wid+1];
+
+ if (string == NULL) {
+ cLcd::SetMain(LCDMENU,StringBuffer);
+ } else {
+ cLcd::Copy(statstring,string,2*wid);
+ cLcd::SetMain(LCDMENU,statstring);
+ }
+}
+
+void cLcd::SetWarning( const char *string) {
+ if (!connected) return;
+
+ char statstring[2*wid+1];
+
+ if (string != NULL) {
+ cLcd::Copy(statstring,string,2*wid);
+ cLcd::Clear(LCDMISC);
+ cLcd::SetMain(LCDMISC,statstring);
+ cLcd::SetThreadState(Misc);
+ }
+}
+
+void cLcd::ShowVolume(unsigned int vol, bool muted ) {
+if (!connected) return;
+ BeginMutualExclusion();
+ ThreadStateData.volume=vol;
+ ThreadStateData.muted=muted;
+ ThreadStateData.showvolume=true;
+ EndMutualExclusion();
+ if (ThreadStateData.muted) {
+ cLcd::SetLine(Vol,0," ");
+ cLcd::SetLine(Vol,1,tr("Mute"));
+ cLcd::SetLine(Vol,2," ");
+ cLcd::SetLine(Vol,3," ");
+ } else {
+ cLcd::SetLine(Vol,0,tr("Volume "));
+ cLcd::SetLine(Vol,1,"|---|---|---|---|---|---|---|---|---|---");
+ cLcd::SetLine(Vol,2," ");
+ cLcd::SetLine(Vol,3,"|---|---|---|---|---|---|---|---|---|---");
+ }
+}
+
+void cLcd::SetProgress(const char *begin, const char *end, int percent) {
+ if (!connected) return;
+
+ char workstring[256];
+
+ if (percent>100) percent=100; if (percent<0) percent=0;
+ if (begin==NULL) {
+ BeginMutualExclusion();
+ ThreadStateData.barx=1; ThreadStateData.bary=1; ThreadStateData.barl=0;
+ EndMutualExclusion();
+ } else {
+ time_t t = time(NULL);
+ if (t != LastProgress) { // output only once a second
+ int beginw=strlen(begin);
+ int endw=strlen(end);
+ sprintf(workstring,"%s", begin);
+ memset(workstring+beginw,' ',wid-beginw-endw);
+ sprintf(workstring+wid-endw,"%s", end);
+ cLcd::SetLine(LCDREPLAY,3,workstring);
+ BeginMutualExclusion();
+ ThreadStateData.barx=beginw+1;
+ ThreadStateData.bary=4;
+ ThreadStateData.barl=(percent*cellwid*(wid-beginw-endw))/100;
+ EndMutualExclusion();
+ LastProgress = t;
+ }
+ }
+}
+
+void cLcd::SetLine(unsigned int n, unsigned int l, const char *string) {
+ if (!connected) return;
+
+ BeginMutualExclusion();
+ if (string != NULL) strncpy(ThreadStateData.lcdbuffer[n][l],string,wid+1);
+ ThreadStateData.lcddirty[n][l]=true;
+ EndMutualExclusion();
+}
+
+void cLcd::SetLineC(unsigned int n, unsigned int l, const char *string) {
+ if (!connected) return;
+
+ BeginMutualExclusion();
+ if (string != NULL) cLcd::Copy(ThreadStateData.lcdbuffer[n][l],string,wid);
+ ThreadStateData.lcddirty[n][l]=true;
+ EndMutualExclusion();
+}
+
+void cLcd::SetBuffer(unsigned int n, const char *l1,const char *l2,const char *l3,const char *l4) {
+ if (!connected) return;
+
+ BeginMutualExclusion();
+ if (l1 != NULL) strncpy(ThreadStateData.lcdbuffer[n][0],l1,wid+1); ThreadStateData.lcddirty[n][0]=true;
+ if (l2 != NULL) strncpy(ThreadStateData.lcdbuffer[n][1],l2,wid+1); ThreadStateData.lcddirty[n][1]=true;
+ if (l3 != NULL) strncpy(ThreadStateData.lcdbuffer[n][2],l3,wid+1); ThreadStateData.lcddirty[n][2]=true;
+ if (l4 != NULL) strncpy(ThreadStateData.lcdbuffer[n][3],l4,wid+1); ThreadStateData.lcddirty[n][3]=true;
+ EndMutualExclusion();
+}
+
+void cLcd::SetRunning( bool nownext, const char *string1, const char *string2, const char *string3) {
+ if (!connected) return;
+
+ char line[256];
+ char line1[256];
+
+ snprintf(line,256,"%s %s%s%s",
+ (string1==NULL || string1[0]=='\0')?" ":string1,
+ (string2==NULL || string2[0]=='\0')?" ":string2,
+ (string3==NULL || string3[0]=='\0')?"":"|",
+ (string3==NULL || string3[0]=='\0')?" ":string3);
+ cLcd::Copy(line1,line,2*wid);
+ if (nownext) {
+ cLcd::Split(line1,ThreadStateData.lcdbuffer[LCDMISC][2],ThreadStateData.lcdbuffer[LCDMISC][3]);
+ ThreadStateData.lcddirty[LCDMISC][2]=true; ThreadStateData.lcddirty[LCDMISC][3]=true;
+ } else {
+ BeginMutualExclusion();
+ cLcd::Split(line1,ThreadStateData.lcdbuffer[LCDTITLE][2],ThreadStateData.lcdbuffer[LCDTITLE][3]);
+ ThreadStateData.lcddirty[LCDTITLE][2]=true; ThreadStateData.lcddirty[LCDTITLE][3]=true;
+ EndMutualExclusion();
+ cLcd::SetBuffer(LCDMISC,ThreadStateData.lcdbuffer[LCDTITLE][2],ThreadStateData.lcdbuffer[LCDTITLE][3],NULL,NULL);
+ }
+}
+
+void cLcd::SummaryInit(char *string) {
+ SummaryText = string;
+ SummaryTextL = strlen(string);
+ SummaryCurrent=0;
+}
+
+void cLcd::SummaryDown() {
+ if (!connected) return;
+
+ SummaryCurrent=( (SummaryCurrent+4*wid) < SummaryTextL )?SummaryCurrent+4*wid:SummaryCurrent;
+}
+
+void cLcd::SummaryUp() {
+ if (!connected) return;
+
+ SummaryCurrent=( SummaryCurrent > 4*wid )?SummaryCurrent-4*wid:0;
+}
+
+void cLcd::SummaryDisplay() {
+ if ( (!connected) || (SummaryTextL < 1) ) return;
+
+ char workstring[256];
+ unsigned int i, offset=0;
+
+ for (i=0;i<4;i++) {
+ if (SummaryCurrent+offset < SummaryTextL) {
+ strncpy(workstring,SummaryText+SummaryCurrent+offset,wid+1);
+ workstring[wid]='\0';
+ cLcd::SetLine(LCDMENU,i,workstring);
+ offset+=wid;
+ } else cLcd::SetLine(LCDMENU,i," ");
+ }
+}
+
+void cLcd::SetCardStat(unsigned int card, unsigned int stat) {
+ if (!connected) return;
+ BeginMutualExclusion();
+ ThreadStateData.CardStat[card]=stat;
+ EndMutualExclusion();
+}
+
+void cLcd::Clear( unsigned int n) {
+ if (!connected) return;
+
+ cLcd::SetBuffer(n," "," "," "," ");
+}
+
+void cLcd::SetThreadState( ThreadStates newstate ) {
+ if (!connected) return;
+
+ BeginMutualExclusion();
+ if (ThreadStateData.State != newstate) {
+ cLcd::LastState[(++LastStateP)%LCDMAXSTATEBUF]=newstate;
+ ThreadStateData.State=newstate;
+ ThreadStateData.barx=1, ThreadStateData.bary=1, ThreadStateData.barl=0;
+ }
+ EndMutualExclusion();
+}
+
+void cLcd::PopThreadState() {
+ BeginMutualExclusion();
+ LastStateP=(LastStateP+LCDMAXSTATEBUF-1)%LCDMAXSTATEBUF;
+ ThreadStateData.State=cLcd::LastState[LastStateP];
+ ThreadStateData.barx=1, ThreadStateData.bary=1, ThreadStateData.barl=0;
+ EndMutualExclusion();
+}
+
+void cLcd::SetReplayDevice(cControl *DvbApi) {
+ replayDvbApi=DvbApi;
+}
+
+void cLcd::SetPrimaryDevice(cDevice *DvbApi) {
+ primaryDvbApi=DvbApi;
+}
+
+
+// private:
+
+// everything between BeginMutualExclusion(); and EndMutualExclusion();
+// should have exclusive access to ThreadStateData
+
+void cLcd::BeginMutualExclusion() {
+ CriticalArea.Lock();
+}
+
+void cLcd::EndMutualExclusion() {
+ cLcd::CriticalArea.Unlock();
+}
+
+void cLcd::Copy(char *to, const char *from, unsigned int max) { // eliminates tabs, double blanks ...
+
+ unsigned int i=0 , out=0;
+
+ if (from != NULL) {
+ while ((out < max) && (from[i] != '\0') ) {
+ to[out]=(isspace(from[i]))?' ':from[i];
+ if ( (out>0) && (to[out-1]==' ') && ispunct(to[out]) ) {to[out-1]=to[out]; to[out]=' '; }
+ if (!(( (out==0) && (to[out]==' ') ) ||
+ ( (out>0) && (to[out-1]==' ') && (to[out]==' ') ) ||
+ ( (out>0) && ispunct(to[out-1]) && (to[out]==' ') )
+ )) out++;
+ i++;
+ }
+ if (out==0) to[out++]=' ';
+ to[out]='\0';
+ } else {
+ to[0]=' '; to[1]='\0';
+ }
+}
+
+void cLcd::Split(const char *string, char *string1, char *string2) {
+
+ strncpy(string1,string,wid+1);
+ if ( strlen(string) >wid ) {
+ strncpy(string2,string+wid,wid+1);
+ } else {
+ string2[0]=' '; string2[1]='\0';
+ }
+}
+
+void cLcd::Write(int line, const char *string) { // used for any text output to LCDd
+
+ char workstring[256];
+ unsigned int i,out;
+
+ sprintf(workstring,"widget_set VDR line%d 1 %d \"",line,line);
+ out=strlen(workstring);
+ for (i=0;(i<strlen(string)) && (i<wid);i++)
+ workstring[out++] = LcdTransTbl[ (unsigned char) string[i] ]; // char mapping see lcdtranstbl.h
+ workstring[out++] = '"'; workstring[out++] = '\n'; workstring[out] = '\0';
+ sock_send_string(sock,workstring);
+}
+
+#define FullCycle 10 // seconds
+#define TimeCycle 7 // seconds
+
+void cLcd::GetTimeDateStat( char *string, unsigned int OutStateData[] ) {
+ time_t t;
+ struct tm *now;
+ unsigned int i;
+ const char States[] = ".-*>"; // '.' ... not present, '-' ... present, '*' ... recording, '>' ... replaying
+ bool ShowStates=false;
+ unsigned int offset;
+
+ offset=(wid>36)?20:0;
+ for (i=0; i<LCDMAXCARDS && (!ShowStates) ; i++) ShowStates = ShowStates || (OutStateData[i]>1);
+
+ t = time(NULL);
+ now = localtime(&t);
+
+ if ( offset || !( ShowStates && ((t%FullCycle) >= TimeCycle) )) {
+ if (wid > 19)
+ snprintf(string,wid+1,"<%s %02d.%02d %02d:%02d:%02d>",
+ WeekDayName(now->tm_wday), now->tm_mday, now->tm_mon+1, now->tm_hour, now->tm_min,now->tm_sec);
+ else
+ snprintf(string,wid+1,"<%02d.%02d %02d:%02d:%02d>",
+ now->tm_mday, now->tm_mon+1, now->tm_hour, now->tm_min,now->tm_sec);
+ }
+
+ if ( offset || ( ShowStates && ((t%FullCycle) >= TimeCycle) )) {
+ for (i=0; i<LCDMAXCARDS; i++) {
+ snprintf(string+offset,5," %d:%c", i,States[ OutStateData[i] ] );
+ offset+=4;
+ }
+ }
+
+}
+
+#define WakeUpCycle 125000 // us
+#define VolumeKeep 1500000 // us
+
+void cLcd::Action(void) { // LCD output thread
+ unsigned int i,j, barx=1, bary=1, barl=0;
+ int Current=0, Total=1;
+ struct timeval now, voltime;
+ char workstring[256];
+ cLcd::ThreadStates PrevState=Menu;
+ struct cLcd::StateData OutStateData;
+ bool Lcddirty[LCDMAXSTATES][4];
+ bool LcdShiftkeyPressed=false;
+
+ syslog(LOG_INFO, "LCD output thread started (pid=%d), display size: %dx%d", getpid(),hgt,wid);
+ cLcd::Write(1," Welcome to V D R\0");
+ cLcd::Write(2,"--------------------\0");
+ cLcd::Write(3,"Video Disk Recorder\0");
+ cLcd::Write(4,"Version: "VDRVERSION"\0");
+ sleep(5); bool volume=false; OutStateData.showvolume=false; ThreadStateData.showvolume=false;
+
+ if (primaryDvbApi) for (int k=0; k<primaryDvbApi->NumDevices() ; k++) SetCardStat(k,1);
+
+ voltime.tv_sec=0;
+ for (i=0;i<LCDMAXSTATES;i++) for (j=0;j<4;j++) Lcddirty[i][j]=true;
+ time_t nextLcdUpdate = (time(NULL)/60)*60+60;
+
+ while (true) { // main loop, wakes up every WakeUpCycle, any output to LCDd is done here
+ gettimeofday(&now,NULL);
+
+ // epg update
+
+ if ( time(NULL) > nextLcdUpdate ) {
+ const cEventInfo *Present = NULL;
+ cMutexLock MutexLock;
+ const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock);
+ if (Schedules) {
+ const cSchedule *Schedule = Schedules->GetSchedule();
+ if (Schedule) {
+ const char *PresentTitle, *PresentSubtitle;
+ PresentTitle = NULL; PresentSubtitle = NULL;
+ if ((Present = Schedule->GetPresentEvent()) != NULL) {
+ nextLcdUpdate=Present->GetTime()+Present->GetDuration();
+ PresentTitle = Present->GetTitle();
+ PresentSubtitle = Present->GetSubtitle();
+ if ( (!isempty(PresentTitle)) && (!isempty(PresentSubtitle)) )
+ SetRunning(false,Present->GetTimeString(),PresentTitle,PresentSubtitle);
+ else if (!isempty(PresentTitle)) SetRunning(false,Present->GetTimeString(),PresentTitle);
+ }
+ if ((Present = Schedule->GetFollowingEvent()) != NULL)
+ nextLcdUpdate=(Present->GetTime()<nextLcdUpdate)?Present->GetTime():nextLcdUpdate;
+ }
+ }
+ if ( nextLcdUpdate <= time(NULL) )
+ nextLcdUpdate=(time(NULL)/60)*60+60;
+ else if ( nextLcdUpdate > time(NULL)+60 )
+ nextLcdUpdate=(time(NULL)/60)*60+60;
+ }
+
+ // replaying
+
+ if ( (now.tv_usec < WakeUpCycle) && (replayDvbApi) ) {
+ char tempbuffer[16];
+ replayDvbApi->GetIndex(Current, Total, false);
+ sprintf(tempbuffer,IndexToHMSF(Total));
+ SetProgress(IndexToHMSF(Current),tempbuffer, (100 * Current) / Total);
+ }
+
+ // copy
+
+ BeginMutualExclusion(); // all data needed for output are copied here
+ memcpy(&OutStateData,&ThreadStateData, sizeof (cLcd::StateData));
+ ThreadStateData.showvolume=false;
+ for (i=0;i<LCDMAXSTATES;i++) for (j=0;j<4;j++) {
+ ThreadStateData.lcddirty[i][j]=false;
+ Lcddirty[i][j]= Lcddirty[i][j] || OutStateData.lcddirty[i][j];
+ }
+ EndMutualExclusion();
+
+ // volume
+
+ if (OutStateData.showvolume) gettimeofday(&voltime,NULL);
+ if ( voltime.tv_sec != 0) { // volume
+ if ( ((now.tv_sec - voltime.tv_sec)*1000000+now.tv_usec-voltime.tv_usec ) > 1500000 ) {
+ voltime.tv_sec=0;
+ OutStateData.barx=1; OutStateData.bary=1; OutStateData.barl=0; volume=false;
+ } else {
+ volume=true;
+ OutStateData.barx=1; OutStateData.bary=3;
+ OutStateData.barl=(cellwid*wid*OutStateData.volume)/255;
+ }
+ }
+ if (volume) OutStateData.State = Vol;
+ // modes
+
+ switch (OutStateData.State) {
+
+ case Menu: // display menu = 0
+ if (PrevState != Menu) for (i=0;i<4;i++) Lcddirty[LCDMENU][i]=true;
+ for (i=0;i<4;i++) if (Lcddirty[LCDMENU][i]) {
+ cLcd::Write(i+1,OutStateData.lcdbuffer[LCDMENU][i]);
+ Lcddirty[LCDMENU][i]=false;
+ }
+ PrevState=Menu;
+ break;
+
+ case Title: // Display 'titlescsreen' = 1
+ if ( (now.tv_usec < WakeUpCycle) || (PrevState != Title) ) {
+ cLcd::GetTimeDateStat(workstring,OutStateData.CardStat);
+ cLcd::Write(1,workstring);
+ }
+ if (PrevState != Title) for (i=1;i<4;i++) Lcddirty[LCDTITLE][i]=true;
+ for (i=1;i<4;i++) if (Lcddirty[LCDTITLE][i]) {
+ cLcd::Write(i+1,OutStateData.lcdbuffer[LCDTITLE][i]);
+ Lcddirty[LCDTITLE][i]=false;
+ }
+ PrevState = Title;
+ break;
+
+ case Replay: // Display date/time during replaying = 2
+ if ( (now.tv_usec < WakeUpCycle) || (PrevState != Replay) ) {
+ cLcd::GetTimeDateStat(workstring,OutStateData.CardStat);
+ cLcd::Write(1,workstring);
+ }
+ if (PrevState != Replay) for (i=1;i<4;i++) Lcddirty[LCDREPLAY][i]=true;
+ for (i=1;i<4;i++) if (Lcddirty[LCDREPLAY][i]) {
+ cLcd::Write(i+1,OutStateData.lcdbuffer[LCDREPLAY][i]);
+ Lcddirty[LCDREPLAY][i]=false;
+ }
+ PrevState = Replay;
+ break;
+
+ case Misc: // Display messages = 3
+ if (PrevState != Misc) for (i=0;i<4;i++) Lcddirty[LCDMISC][i]=true;
+ for (i=0;i<4;i++) if (Lcddirty[LCDMISC][i]) {
+ cLcd::Write(i+1,OutStateData.lcdbuffer[LCDMISC][i]);
+ Lcddirty[LCDMISC][i]=false;
+ }
+ PrevState = Misc;
+ break;
+
+ case Vol: // Display Volume = 4
+ if (PrevState != Vol) for (i=0;i<4;i++) Lcddirty[LCDVOL][i]=true;
+ for (i=0;i<4;i++) if (Lcddirty[LCDVOL][i]) {
+ cLcd::Write(i+1,OutStateData.lcdbuffer[LCDVOL][i]);
+ Lcddirty[LCDVOL][i]=false;
+ }
+ PrevState = Vol;
+ break;
+
+ default: // quite impossible :)
+ break;
+ }
+
+ // bargraph
+ if ( (OutStateData.barx != barx) || (OutStateData.bary != bary) || (OutStateData.barl != barl) ) {
+ sprintf(workstring,"widget_set VDR prbar %d %d %d\n",OutStateData.barx,OutStateData.bary,OutStateData.barl);
+ sock_send_string(sock,workstring);
+ barx=OutStateData.barx; bary=OutStateData.bary; barl=OutStateData.barl;
+ }
+
+ // keys
+ workstring[0]='\0'; sock_recv(sock, workstring, 256);
+ if ( strlen(workstring) > 4 ) {
+ for (i=0; i < (strlen(workstring)-4); i++ ) {
+ if (workstring[i]=='k' && workstring[i+1]=='e' && workstring[i+2]=='y' && workstring[i+3]==' ') {
+ if (workstring[i+4] == LcdShiftKey) {
+ LcdShiftkeyPressed = ! LcdShiftkeyPressed;
+ if (LcdShiftkeyPressed)
+ sock_send_string(sock,"screen_set VDR -heartbeat on\n");
+ else
+ sock_send_string(sock,"screen_set VDR -heartbeat off\n");
+ }
+ if ( (workstring[i+4] != LcdShiftKey) ) {
+ if (LcdShiftkeyPressed) {
+ syslog(LOG_INFO, "shiftkey pressed: %c", workstring[i+4] );
+ LcdShiftkeyPressed=false;
+ sock_send_string(sock,"screen_set VDR -heartbeat off\n");
+ } else {
+ syslog(LOG_INFO, "normalkey pressed: %c", workstring[i+4] );
+ }
+ }
+ }
+ }
+ }
+
+ usleep(WakeUpCycle-(now.tv_usec%WakeUpCycle)); // sync to systemtime for nicer time output
+ }
+}
diff --git a/lcd.h b/lcd.h
new file mode 100644
index 0000000..95efecd
--- /dev/null
+++ b/lcd.h
@@ -0,0 +1,75 @@
+#ifndef __LCD_H
+#define __LCD_H
+
+#include <vdr/thread.h>
+#include <vdr/device.h>
+#include <vdr/player.h>
+#include <vdr/dvbplayer.h>
+
+#define LCDPORT 13666
+#define LCDHOST "localhost"
+#define LCDMAXSTATES 5
+#define LCDMAXSTATEBUF 5
+#define LCDMAXWID 40
+#define LCDMAXCARDS 4
+
+class cLcd : public cThread {
+ public:
+ cControl *replayDvbApi;
+ cDevice *primaryDvbApi;
+ enum ThreadStates {Menu=0, Title=1, Replay=2, Misc=3, Vol=4};
+ ThreadStates LastState[LCDMAXSTATEBUF];
+ int LastStateP;
+ struct StateData {
+ char lcdbuffer[LCDMAXSTATES][4][LCDMAXWID+1];
+ bool lcddirty[LCDMAXSTATES][4], muted, showvolume;
+ ThreadStates State;
+ unsigned int barx, bary, barl, volume;
+ unsigned int CardStat[LCDMAXCARDS];
+ };
+ cLcd();
+ ~cLcd();
+ bool Connect( char *host = LCDHOST , unsigned int port = LCDPORT );
+ void Close();
+ void Info();
+ void SetTitle( const char *string);
+ void SetMain( unsigned int n, const char *string);
+ void SetHelp( unsigned int n, const char *Red, const char *Green, const char *Yellow, const char *Blue);
+ void SetStatus( const char *string);
+ void SetWarning( const char *string);
+ void ShowVolume(unsigned int vol, bool muted );
+ void SetProgress(const char *begin=NULL, const char *end=NULL, int percent=0);
+ void SetLine(unsigned int n, unsigned int l, const char *string);
+ void SetLineC(unsigned int n, unsigned int l, const char *string);
+ void SetBuffer(unsigned int n,const char *l1=NULL,const char *l2=NULL,const char *l3=NULL,const char *l4=NULL);
+ void SetRunning(bool nownext, const char *string1="\0", const char *string2="\0", const char *string3="\0");
+ void SummaryInit(char *string);
+ void SummaryUp();
+ void SummaryDown();
+ void SummaryDisplay();
+ void SetCardStat(unsigned int card, unsigned int stat);
+ void Clear(unsigned int n);
+ void SetThreadState( ThreadStates newstate );
+ void PopThreadState();
+ void SetReplayDevice(cControl *DvbApi);
+ void SetPrimaryDevice(cDevice *DvbApi);
+ private:
+ char *SummaryText;
+ unsigned int SummaryTextL;
+ unsigned int SummaryCurrent;
+ bool connected;
+ struct StateData ThreadStateData;
+ time_t LastProgress;
+ cMutex CriticalArea;
+ unsigned int sock, wid, hgt, cellwid, cellhgt;
+ char StringBuffer[2*LCDMAXWID+1];
+ void BeginMutualExclusion();
+ void EndMutualExclusion();
+ void Copy(char *to, const char *from, unsigned int max);
+ void Split(const char *string, char *string1, char *string2);
+ void Write(int line, const char *string);
+ void GetTimeDateStat( char *string, unsigned int OutStateData[] );
+ void Action(void);
+};
+
+#endif //__LCD_H
diff --git a/lcdkeyconf.h b/lcdkeyconf.h
new file mode 100644
index 0000000..ee4f843
--- /dev/null
+++ b/lcdkeyconf.h
@@ -0,0 +1,7 @@
+// LCDproc keys
+
+const unsigned int LcdMaxKeys = 5;
+const unsigned char LcdShiftKey = '#';
+const unsigned char LcdUsedKeys[LcdMaxKeys] = {'0', '3', '6', 'A', '#'};
+//const eKeys LcdNormalMap[LcdMaxKeys] = { kBack, kLeft, kPower, kVolDn, kMute};
+//const eKeys LcdShiftMap[LcdMaxKeys] = { k1, k2, kOk, k4, k8};
diff --git a/lcdproc.c b/lcdproc.c
new file mode 100644
index 0000000..d20ff80
--- /dev/null
+++ b/lcdproc.c
@@ -0,0 +1,299 @@
+/*
+ * status.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id$
+ */
+
+#include <getopt.h>
+#include <ctype.h>
+#include <vdr/plugin.h>
+#include <vdr/status.h>
+#include <vdr/recording.h>
+#include "lcd.h"
+
+static const char *VERSION = "0.0.1";
+static const char *MAINMENUENTRY = NULL;
+#ifdef LCD_hd44780
+static const char *DESCRIPTION = "LCDproc using hd44780 output-mapping";
+#endif
+#ifdef LCD_CFontz
+static const char *DESCRIPTION = "LCDproc using CFontz output-mapping";
+#endif
+#ifdef LCD_nomap
+static const char *DESCRIPTION = "LCDproc using no output-mapping";
+#endif
+
+cLcd *LCDproc = new cLcd;
+bool replaymode=false;
+bool menumode=false;
+bool switched=false;
+bool group=false;
+char tempstringbuffer[80];
+char *LCDprocHOST=LCDHOST;
+unsigned int LCDprocPORT=LCDPORT;
+
+// ---
+
+class cLcdFeed : public cStatus {
+protected:
+ virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber);
+ virtual void Recording(const cDevice *Device, const char *Name);
+ virtual void Replaying(const cControl *DvbPlayerControl, const char *Name);
+ virtual void SetVolume(int Volume, bool Absolute);
+ virtual void OsdClear(void);
+ virtual void OsdTitle(const char *Title);
+ virtual void OsdStatusMessage(const char *Message);
+ virtual void OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue);
+ virtual void OsdCurrentItem(const char *Text);
+ virtual void OsdTextItem(const char *Text, bool Scroll);
+ virtual void OsdChannel(const char *Text);
+ virtual void OsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle);
+ };
+
+
+void cLcdFeed::ChannelSwitch(const cDevice *Device, int ChannelNumber)
+{
+ syslog(LOG_INFO, "lcdproc: cLcdFeed::ChannelSwitch %d %d", Device->CardIndex(), ChannelNumber);
+ if (ChannelNumber) {
+ LCDproc->SetLine(1,2," ");
+ LCDproc->SetLine(1,3," ");
+ switched = true;
+ } else switched = false;
+ if (Device) LCDproc->SetPrimaryDevice( (cDevice *) Device );
+}
+
+void cLcdFeed::Recording(const cDevice *Device, const char *Name)
+{
+ syslog(LOG_INFO, "lcdproc: cLcdFeed::Recording %d %s", Device->CardIndex(), Name);
+ if (Name)
+ LCDproc->SetCardStat(Device->CardIndex(),2);
+ else
+ LCDproc->SetCardStat(Device->CardIndex(),1);
+}
+
+void cLcdFeed::Replaying(const cControl *DvbPlayerControl, const char *Name)
+{
+ syslog(LOG_INFO, "lcdproc: cLcdFeed::Replaying %s", Name);
+ replaymode=(Name)?true:false;
+ if ( replaymode ) {
+ LCDproc->SetReplayDevice( (cDvbPlayerControl *) DvbPlayerControl);
+ LCDproc->SetMain(2, Name);
+ LCDproc->SetThreadState( (cLcd::ThreadStates) 2); // Replaying
+ } else {
+ LCDproc->SetReplayDevice(NULL);
+ LCDproc->SetProgress(NULL);
+ LCDproc->SetLineC(1,1,tempstringbuffer);
+ LCDproc->SetThreadState( (cLcd::ThreadStates) 1); // Title
+ }
+ menumode=false;
+}
+
+void cLcdFeed::SetVolume(int Volume, bool Absolute)
+{
+ syslog(LOG_INFO, "lcdproc: cLcdFeed::SetVolume %d %d", Volume, Absolute);
+ LCDproc->ShowVolume( Volume, Absolute );
+}
+
+void cLcdFeed::OsdClear(void)
+{
+ syslog(LOG_INFO, "lcdproc: cLcdFeed::OsdClear");
+
+ if (replaymode)
+ LCDproc->SetThreadState( (cLcd::ThreadStates) 2); // Replaying
+ else
+ LCDproc->SetThreadState( (cLcd::ThreadStates) 1); // Title
+ menumode=false;
+ if (group) {LCDproc->SetLineC(1,1,tempstringbuffer); group=false; }
+}
+
+void cLcdFeed::OsdTitle(const char *Title)
+{
+ syslog(LOG_INFO, "lcdproc: cLcdFeed::OsdTitle '%s'", Title);
+ LCDproc->Clear(0);
+ LCDproc->SetTitle(Title);
+ LCDproc->SetThreadState( (cLcd::ThreadStates) 0); // MENU
+ menumode=true;
+}
+
+void cLcdFeed::OsdStatusMessage(const char *Message)
+{
+ syslog(LOG_INFO, "lcdproc: cLcdFeed::OsdStatusMessage '%s'", Message);
+ if ( Message )
+ if ( menumode )
+ LCDproc->SetStatus(Message);
+ else
+ LCDproc->SetWarning(Message);
+}
+
+void cLcdFeed::OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue)
+{
+ syslog(LOG_INFO, "lcdproc: cLcdFeed::OsdHelpKeys %s - %s - %s - %s", Red, Green, Yellow, Blue);
+ LCDproc->SetHelp(0,Red, Green, Yellow, Blue);
+}
+
+void cLcdFeed::OsdCurrentItem(const char *Text)
+{
+ syslog(LOG_INFO, "lcdproc: cLcdFeed::OsdCurrentItem %s", Text);
+ LCDproc->SetMain(0,Text);
+}
+
+void cLcdFeed::OsdTextItem(const char *Text, bool Scroll)
+{
+ syslog(LOG_INFO, "lcdproc: cLcdFeed::OsdTextItem %s %d", Text, Scroll);
+ if (Text)
+ LCDproc->SummaryInit( (char *) Text);
+ else if (Scroll)
+ LCDproc->SummaryUp();
+ else
+ LCDproc->SummaryDown();
+ LCDproc->SummaryDisplay();
+}
+
+void cLcdFeed::OsdChannel(const char *Text)
+{
+ syslog(LOG_INFO, "lcdproc: cLcdFeed::OsdChannel %s", Text);
+ LCDproc->SetLineC(1,1,Text);
+
+ bool switching = group = !isdigit(Text[0]);
+ if (!group) strcpy(tempstringbuffer,Text);
+ for (unsigned int i=0; ( i<strlen(Text)-1 ) && !switching ; i++) {
+ switching= isdigit(Text[i]) && Text[i+1]=='-' ;
+ }
+
+ if (switched || switching)
+ LCDproc->SetThreadState( (cLcd::ThreadStates) 1); // TITLE
+ else
+ LCDproc->SetThreadState( (cLcd::ThreadStates) 3); // MISC
+
+ switched=false; menumode=false;
+}
+
+void cLcdFeed::OsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle)
+{
+ char buffer[25];
+ struct tm tm_r;
+ syslog(LOG_INFO, "lcdproc: cLcdFeed::OsdProgramme");
+ strftime(buffer, sizeof(buffer), "%R", localtime_r(&PresentTime, &tm_r));
+ syslog(LOG_INFO, "%5s %s", buffer, PresentTitle);
+ syslog(LOG_INFO, "%5s %s", "", PresentSubtitle);
+
+
+ if ( (!isempty(PresentTitle)) && (!isempty(PresentSubtitle)) )
+ LCDproc->SetRunning(false,buffer,PresentTitle,PresentSubtitle);
+ else if (!isempty(PresentTitle)) LCDproc->SetRunning(false,buffer,PresentTitle);
+
+
+ strftime(buffer, sizeof(buffer), "%R", localtime_r(&FollowingTime, &tm_r));
+ syslog(LOG_INFO, "%5s %s", buffer, FollowingTitle);
+ syslog(LOG_INFO, "%5s %s", "", FollowingSubtitle);
+
+ if ( (!isempty(FollowingTitle)) && (!isempty(FollowingSubtitle)) )
+ LCDproc->SetRunning(true,buffer,FollowingTitle,FollowingSubtitle);
+ else if (!isempty(FollowingTitle)) LCDproc->SetRunning(true,buffer,FollowingTitle);
+
+}
+
+// ---
+
+class cPluginLcd : public cPlugin {
+private:
+ // Add any member variables or functions you may need here.
+ cLcdFeed *lcdFeed;
+public:
+ cPluginLcd(void);
+ virtual ~cPluginLcd();
+ virtual const char *Version(void) { return VERSION; }
+ virtual const char *Description(void) { return DESCRIPTION; }
+ virtual const char *CommandLineHelp(void);
+ virtual bool ProcessArgs(int argc, char *argv[]);
+ virtual bool Start(void);
+ virtual void Housekeeping(void);
+ virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
+ virtual cOsdMenu *MainMenuAction(void);
+ virtual cMenuSetupPage *SetupMenu(void);
+ virtual bool SetupParse(const char *Name, const char *Value);
+ };
+
+cPluginLcd::cPluginLcd(void)
+{
+ // Initialize any member varaiables here.
+ // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
+ // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
+ lcdFeed = NULL;
+
+}
+
+cPluginLcd::~cPluginLcd()
+{
+ // Clean up after yourself!
+ delete lcdFeed;
+ delete LCDproc;
+}
+
+const char *cPluginLcd::CommandLineHelp(void)
+{
+ // Return a string that describes all known command line options.
+ return " -h <host>, --host <host> LCDproc host (default=localhost)\n -p <port>, --port <port> LCDproc port (default=13666)\n";
+
+}
+
+bool cPluginLcd::ProcessArgs(int argc, char *argv[])
+{
+ // Implement command line argument processing here if applicable.
+
+ static struct option long_options[] = {
+ { "host", required_argument, NULL, 'h' },
+ { "port", required_argument, NULL, 'p' },
+ { NULL }
+ };
+
+ int c;
+ while ((c = getopt_long(argc, argv, "h:p:", long_options, NULL)) != -1) {
+ switch (c) {
+ case 'h': LCDprocHOST=optarg;
+ break;
+ case 'p': LCDprocPORT=atoi(optarg);
+ break;
+ default: return false;
+ }
+ }
+ return true;
+}
+
+bool cPluginLcd::Start(void)
+{
+ // Start any background activities the plugin shall perform.
+ lcdFeed = new cLcdFeed;
+ if ( LCDproc->Connect(LCDprocHOST,LCDprocPORT) ) {
+ syslog(LOG_INFO, "connection to LCDd at %s:%d established.",LCDprocHOST,LCDprocPORT);
+ return true;
+ }
+ return false;
+}
+
+void cPluginLcd::Housekeeping(void)
+{
+ // Perform any cleanup or other regular tasks.
+}
+
+cOsdMenu *cPluginLcd::MainMenuAction(void)
+{
+ // Perform the action when selected from the main VDR menu.
+ return NULL;
+}
+
+cMenuSetupPage *cPluginLcd::SetupMenu(void)
+{
+ // Return a setup menu in case the plugin supports one.
+ return NULL;
+}
+
+bool cPluginLcd::SetupParse(const char *Name, const char *Value)
+{
+ // Parse your own setup parameters and store their values.
+ return false;
+}
+
+VDRPLUGINCREATOR(cPluginLcd); // Don't touch this!
diff --git a/lcdtranstbl-CFontz.h b/lcdtranstbl-CFontz.h
new file mode 100644
index 0000000..0086a33
--- /dev/null
+++ b/lcdtranstbl-CFontz.h
@@ -0,0 +1,265 @@
+/*
+lcdtranstbl-CFontz.h
+this table is used to map characters for output to
+a Crystal Fontz LCD to display some special characters correctly.
+newline,tab and friends are mapped to ' '
+*/
+
+const unsigned char LcdTransTbl[256]={
+/* 0 ( '^@') */ (unsigned char) 0,
+/* 1 ( '^A') */ (unsigned char) 1,
+/* 2 ( '^B') */ (unsigned char) 2,
+/* 3 ( '^C') */ (unsigned char) 3,
+/* 4 ( '^D') */ (unsigned char) 4,
+/* 5 ( '^E') */ (unsigned char) 5,
+/* 6 ( '^F') */ (unsigned char) 6,
+/* 7 ( '^G') */ (unsigned char) 7,
+/* 8 ( '^H') */ (unsigned char) 8,
+/* 9 ( '' ) */ (unsigned char) 32,
+/* 10 ( '' ) */ (unsigned char) 32,
+/* 11 ( '^K') */ (unsigned char) 32,
+/* 12 ( '^L') */ (unsigned char) 32,
+/* 13 ( '^M') */ (unsigned char) 32,
+/* 14 ( '^N') */ (unsigned char) 14,
+/* 15 ( '^O') */ (unsigned char) 15,
+/* 16 ( '^P') */ (unsigned char) 16,
+/* 17 ( '^Q') */ (unsigned char) 17,
+/* 18 ( '^R') */ (unsigned char) 18,
+/* 19 ( '^S') */ (unsigned char) 19,
+/* 20 ( '^T') */ (unsigned char) 20,
+/* 21 ( '^U') */ (unsigned char) 21,
+/* 22 ( '^V') */ (unsigned char) 22,
+/* 23 ( '^W') */ (unsigned char) 23,
+/* 24 ( '^X') */ (unsigned char) 24,
+/* 25 ( '^Y') */ (unsigned char) 25,
+/* 26 ( '^Z') */ (unsigned char) 26,
+/* 27 ( '^[') */ (unsigned char) 27,
+/* 28 ( '^\') */ (unsigned char) 28,
+/* 29 ( '^]') */ (unsigned char) 29,
+/* 30 ( '^^') */ (unsigned char) 30,
+/* 31 ( '^_') */ (unsigned char) 31,
+/* 32 ( ' ' ) */ (unsigned char) 32,
+/* 33 ( '!' ) */ (unsigned char) 33,
+/* 34 ( '"' ) */ (unsigned char) 39,
+/* 35 ( '#' ) */ (unsigned char) 35,
+/* 36 ( '$' ) */ (unsigned char) 36,
+/* 37 ( '%' ) */ (unsigned char) 37,
+/* 38 ( '&' ) */ (unsigned char) 38,
+/* 39 ( ''' ) */ (unsigned char) 39,
+/* 40 ( '(' ) */ (unsigned char) 40,
+/* 41 ( ')' ) */ (unsigned char) 41,
+/* 42 ( '*' ) */ (unsigned char) 42,
+/* 43 ( '+' ) */ (unsigned char) 43,
+/* 44 ( ',' ) */ (unsigned char) 44,
+/* 45 ( '-' ) */ (unsigned char) 45,
+/* 46 ( '.' ) */ (unsigned char) 46,
+/* 47 ( '/' ) */ (unsigned char) 47,
+/* 48 ( '0' ) */ (unsigned char) 48,
+/* 49 ( '1' ) */ (unsigned char) 49,
+/* 50 ( '2' ) */ (unsigned char) 50,
+/* 51 ( '3' ) */ (unsigned char) 51,
+/* 52 ( '4' ) */ (unsigned char) 52,
+/* 53 ( '5' ) */ (unsigned char) 53,
+/* 54 ( '6' ) */ (unsigned char) 54,
+/* 55 ( '7' ) */ (unsigned char) 55,
+/* 56 ( '8' ) */ (unsigned char) 56,
+/* 57 ( '9' ) */ (unsigned char) 57,
+/* 58 ( ':' ) */ (unsigned char) 58,
+/* 59 ( ';' ) */ (unsigned char) 59,
+/* 60 ( '<' ) */ (unsigned char) 60,
+/* 61 ( '=' ) */ (unsigned char) 61,
+/* 62 ( '>' ) */ (unsigned char) 62,
+/* 63 ( '?' ) */ (unsigned char) 63,
+/* 64 ( '@' ) */ (unsigned char) 160,
+/* 65 ( 'A' ) */ (unsigned char) 65,
+/* 66 ( 'B' ) */ (unsigned char) 66,
+/* 67 ( 'C' ) */ (unsigned char) 67,
+/* 68 ( 'D' ) */ (unsigned char) 68,
+/* 69 ( 'E' ) */ (unsigned char) 69,
+/* 70 ( 'F' ) */ (unsigned char) 70,
+/* 71 ( 'G' ) */ (unsigned char) 71,
+/* 72 ( 'H' ) */ (unsigned char) 72,
+/* 73 ( 'I' ) */ (unsigned char) 73,
+/* 74 ( 'J' ) */ (unsigned char) 74,
+/* 75 ( 'K' ) */ (unsigned char) 75,
+/* 76 ( 'L' ) */ (unsigned char) 76,
+/* 77 ( 'M' ) */ (unsigned char) 77,
+/* 78 ( 'N' ) */ (unsigned char) 78,
+/* 79 ( 'O' ) */ (unsigned char) 79,
+/* 80 ( 'P' ) */ (unsigned char) 80,
+/* 81 ( 'Q' ) */ (unsigned char) 81,
+/* 82 ( 'R' ) */ (unsigned char) 82,
+/* 83 ( 'S' ) */ (unsigned char) 83,
+/* 84 ( 'T' ) */ (unsigned char) 84,
+/* 85 ( 'U' ) */ (unsigned char) 85,
+/* 86 ( 'V' ) */ (unsigned char) 86,
+/* 87 ( 'W' ) */ (unsigned char) 87,
+/* 88 ( 'X' ) */ (unsigned char) 88,
+/* 89 ( 'Y' ) */ (unsigned char) 89,
+/* 90 ( 'Z' ) */ (unsigned char) 90,
+/* 91 ( '[' ) */ (unsigned char) 250,
+/* 92 ( '\' ) */ (unsigned char) 251,
+/* 93 ( ']' ) */ (unsigned char) 252,
+/* 94 ( '^' ) */ (unsigned char) 222,
+/* 95 ( '_' ) */ (unsigned char) 196,
+/* 96 ( '`' ) */ (unsigned char) 39,
+/* 97 ( 'a' ) */ (unsigned char) 97,
+/* 98 ( 'b' ) */ (unsigned char) 98,
+/* 99 ( 'c' ) */ (unsigned char) 99,
+/* 100 ( 'd' ) */ (unsigned char) 100,
+/* 101 ( 'e' ) */ (unsigned char) 101,
+/* 102 ( 'f' ) */ (unsigned char) 102,
+/* 103 ( 'g' ) */ (unsigned char) 103,
+/* 104 ( 'h' ) */ (unsigned char) 104,
+/* 105 ( 'i' ) */ (unsigned char) 105,
+/* 106 ( 'j' ) */ (unsigned char) 106,
+/* 107 ( 'k' ) */ (unsigned char) 107,
+/* 108 ( 'l' ) */ (unsigned char) 108,
+/* 109 ( 'm' ) */ (unsigned char) 109,
+/* 110 ( 'n' ) */ (unsigned char) 110,
+/* 111 ( 'o' ) */ (unsigned char) 111,
+/* 112 ( 'p' ) */ (unsigned char) 112,
+/* 113 ( 'q' ) */ (unsigned char) 113,
+/* 114 ( 'r' ) */ (unsigned char) 114,
+/* 115 ( 's' ) */ (unsigned char) 115,
+/* 116 ( 't' ) */ (unsigned char) 116,
+/* 117 ( 'u' ) */ (unsigned char) 117,
+/* 118 ( 'v' ) */ (unsigned char) 118,
+/* 119 ( 'w' ) */ (unsigned char) 119,
+/* 120 ( 'x' ) */ (unsigned char) 120,
+/* 121 ( 'y' ) */ (unsigned char) 121,
+/* 122 ( 'z' ) */ (unsigned char) 122,
+/* 123 ( '{' ) */ (unsigned char) 253,
+/* 124 ( '|' ) */ (unsigned char) 221,
+/* 125 ( '}' ) */ (unsigned char) 255,
+/* 126 ( '~' ) */ (unsigned char) 206,
+/* 127 ( '^?') */ (unsigned char) 127,
+/* 128 ( '~@') */ (unsigned char) 128,
+/* 129 ( '~A') */ (unsigned char) 129,
+/* 130 ( '~B') */ (unsigned char) 130,
+/* 131 ( '~C') */ (unsigned char) 131,
+/* 132 ( '~D') */ (unsigned char) 132,
+/* 133 ( '~E') */ (unsigned char) 133,
+/* 134 ( '~F') */ (unsigned char) 134,
+/* 135 ( '~G') */ (unsigned char) 135,
+/* 136 ( '~H') */ (unsigned char) 136,
+/* 137 ( '~I') */ (unsigned char) 137,
+/* 138 ( '~J') */ (unsigned char) 138,
+/* 139 ( '~K') */ (unsigned char) 139,
+/* 140 ( '~L') */ (unsigned char) 140,
+/* 141 ( '~M') */ (unsigned char) 141,
+/* 142 ( '~N') */ (unsigned char) 142,
+/* 143 ( '~O') */ (unsigned char) 143,
+/* 144 ( '~P') */ (unsigned char) 144,
+/* 145 ( '~Q') */ (unsigned char) 145,
+/* 146 ( '~R') */ (unsigned char) 146,
+/* 147 ( '~S') */ (unsigned char) 147,
+/* 148 ( '~T') */ (unsigned char) 148,
+/* 149 ( '~U') */ (unsigned char) 149,
+/* 150 ( '~V') */ (unsigned char) 150,
+/* 151 ( '~W') */ (unsigned char) 151,
+/* 152 ( '~X') */ (unsigned char) 152,
+/* 153 ( '~Y') */ (unsigned char) 153,
+/* 154 ( '~Z') */ (unsigned char) 154,
+/* 155 ( '~[') */ (unsigned char) 155,
+/* 156 ( '~\') */ (unsigned char) 156,
+/* 157 ( '~]') */ (unsigned char) 157,
+/* 158 ( '~^') */ (unsigned char) 158,
+/* 159 ( '~_') */ (unsigned char) 159,
+/* 160 ( '| ') */ (unsigned char) 160,
+/* 161 ( '¡' ) */ (unsigned char) 64,
+/* 162 ( '¢' ) */ (unsigned char) 177,
+/* 163 ( '£' ) */ (unsigned char) 161,
+/* 164 ( '¤' ) */ (unsigned char) 36,
+/* 165 ( '¥' ) */ (unsigned char) 163,
+/* 166 ( '¦' ) */ (unsigned char) 254,
+/* 167 ( '§' ) */ (unsigned char) 95,
+/* 168 ( '¨' ) */ (unsigned char) 221,
+/* 169 ( '©' ) */ (unsigned char) 171,
+/* 170 ( 'ª' ) */ (unsigned char) 170,
+/* 171 ( '«' ) */ (unsigned char) 171,
+/* 172 ( '¬' ) */ (unsigned char) 172,
+/* 173 ( '­' ) */ (unsigned char) 173,
+/* 174 ( '®' ) */ (unsigned char) 174,
+/* 175 ( '¯' ) */ (unsigned char) 175,
+/* 176 ( '°' ) */ (unsigned char) 207,
+/* 177 ( '±' ) */ (unsigned char) 140,
+/* 178 ( '²' ) */ (unsigned char) 130,
+/* 179 ( '³' ) */ (unsigned char) 131,
+/* 180 ( '´' ) */ (unsigned char) 39,
+/* 181 ( 'µ' ) */ (unsigned char) 143,
+/* 182 ( '¶' ) */ (unsigned char) 182,
+/* 183 ( '·' ) */ (unsigned char) 183,
+/* 184 ( '¸' ) */ (unsigned char) 184,
+/* 185 ( '¹' ) */ (unsigned char) 129,
+/* 186 ( 'º' ) */ (unsigned char) 221,
+/* 187 ( '»' ) */ (unsigned char) 187,
+/* 188 ( '¼' ) */ (unsigned char) 139,
+/* 189 ( '½' ) */ (unsigned char) 138,
+/* 190 ( '¾' ) */ (unsigned char) 190,
+/* 191 ( '¿' ) */ (unsigned char) 96,
+/* 192 ( 'À' ) */ (unsigned char) 65,
+/* 193 ( 'Á' ) */ (unsigned char) 226,
+/* 194 ( 'Â' ) */ (unsigned char) 65,
+/* 195 ( 'Ã' ) */ (unsigned char) 65,
+/* 196 ( 'Ä' ) */ (unsigned char) 91,
+/* 197 ( 'Å' ) */ (unsigned char) 174,
+/* 198 ( 'Æ' ) */ (unsigned char) 188,
+/* 199 ( 'Ç' ) */ (unsigned char) 169,
+/* 200 ( 'È' ) */ (unsigned char) 197,
+/* 201 ( 'É' ) */ (unsigned char) 191,
+/* 202 ( 'Ê' ) */ (unsigned char) 198,
+/* 203 ( 'Ë' ) */ (unsigned char) 69,
+/* 204 ( 'Ì' ) */ (unsigned char) 73,
+/* 205 ( 'Í' ) */ (unsigned char) 227,
+/* 206 ( 'Î' ) */ (unsigned char) 73,
+/* 207 ( 'Ï' ) */ (unsigned char) 73,
+/* 208 ( 'Ð' ) */ (unsigned char) 68,
+/* 209 ( 'Ñ' ) */ (unsigned char) 43,
+/* 210 ( 'Ò' ) */ (unsigned char) 168,
+/* 211 ( 'Ó' ) */ (unsigned char) 228,
+/* 212 ( 'Ô' ) */ (unsigned char) 236,
+/* 213 ( 'Õ' ) */ (unsigned char) 79,
+/* 214 ( 'Ö' ) */ (unsigned char) 92,
+/* 215 ( '×' ) */ (unsigned char) 120,
+/* 216 ( 'Ø' ) */ (unsigned char) 171,
+/* 217 ( 'Ù' ) */ (unsigned char) 85,
+/* 218 ( 'Ú' ) */ (unsigned char) 229,
+/* 219 ( 'Û' ) */ (unsigned char) 85,
+/* 220 ( 'Ü' ) */ (unsigned char) 94,
+/* 221 ( 'Ý' ) */ (unsigned char) 250,
+/* 222 ( 'Þ' ) */ (unsigned char) 178,
+/* 223 ( 'ß' ) */ (unsigned char) 190,
+/* 224 ( 'à' ) */ (unsigned char) 127,
+/* 225 ( 'á' ) */ (unsigned char) 231,
+/* 226 ( 'â' ) */ (unsigned char) 97,
+/* 227 ( 'ã' ) */ (unsigned char) 97,
+/* 228 ( 'ä' ) */ (unsigned char) 123,
+/* 229 ( 'å' ) */ (unsigned char) 175,
+/* 230 ( 'æ' ) */ (unsigned char) 189,
+/* 231 ( 'ç' ) */ (unsigned char) 200,
+/* 232 ( 'è' ) */ (unsigned char) 164,
+/* 233 ( 'é' ) */ (unsigned char) 165,
+/* 234 ( 'ê' ) */ (unsigned char) 199,
+/* 235 ( 'ë' ) */ (unsigned char) 101,
+/* 236 ( 'ì' ) */ (unsigned char) 167,
+/* 237 ( 'í' ) */ (unsigned char) 232,
+/* 238 ( 'î' ) */ (unsigned char) 105,
+/* 239 ( 'ï' ) */ (unsigned char) 105,
+/* 240 ( 'ð' ) */ (unsigned char) 158,
+/* 241 ( 'ñ' ) */ (unsigned char) 125,
+/* 242 ( 'ò' ) */ (unsigned char) 168,
+/* 243 ( 'ó' ) */ (unsigned char) 228,
+/* 244 ( 'ô' ) */ (unsigned char) 237,
+/* 245 ( 'õ' ) */ (unsigned char) 237,
+/* 246 ( 'ö' ) */ (unsigned char) 124,
+/* 247 ( '÷' ) */ (unsigned char) 47,
+/* 248 ( 'ø' ) */ (unsigned char) 172,
+/* 249 ( 'ù' ) */ (unsigned char) 166,
+/* 250 ( 'ú' ) */ (unsigned char) 234,
+/* 251 ( 'û' ) */ (unsigned char) 239,
+/* 252 ( 'ü' ) */ (unsigned char) 126,
+/* 253 ( 'ý' ) */ (unsigned char) 235,
+/* 254 ( 'þ' ) */ (unsigned char) 178,
+/* 255 ( 'ÿ' ) */ (unsigned char) 183};
+
diff --git a/lcdtranstbl-hd44780.h b/lcdtranstbl-hd44780.h
new file mode 100644
index 0000000..783836a
--- /dev/null
+++ b/lcdtranstbl-hd44780.h
@@ -0,0 +1,265 @@
+/*
+lcdtranstbl-hd44780.h
+this table is used to map characters for output to
+a hd44780 LCD to display some special characters correctly.
+newline,tab and friends are mapped to ' '
+*/
+
+const unsigned char LcdTransTbl[256]={
+/* 0 ( '^@') */ (unsigned char) 0,
+/* 1 ( '^A') */ (unsigned char) 1,
+/* 2 ( '^B') */ (unsigned char) 2,
+/* 3 ( '^C') */ (unsigned char) 3,
+/* 4 ( '^D') */ (unsigned char) 4,
+/* 5 ( '^E') */ (unsigned char) 5,
+/* 6 ( '^F') */ (unsigned char) 6,
+/* 7 ( '^G') */ (unsigned char) 7,
+/* 8 ( '^H') */ (unsigned char) 8,
+/* 9 ( '' ) */ (unsigned char) 32,
+/* 10 ( '' ) */ (unsigned char) 32,
+/* 11 ( '^K') */ (unsigned char) 32,
+/* 12 ( '^L') */ (unsigned char) 32,
+/* 13 ( '^M') */ (unsigned char) 32,
+/* 14 ( '^N') */ (unsigned char) 14,
+/* 15 ( '^O') */ (unsigned char) 15,
+/* 16 ( '^P') */ (unsigned char) 16,
+/* 17 ( '^Q') */ (unsigned char) 17,
+/* 18 ( '^R') */ (unsigned char) 18,
+/* 19 ( '^S') */ (unsigned char) 19,
+/* 20 ( '^T') */ (unsigned char) 20,
+/* 21 ( '^U') */ (unsigned char) 21,
+/* 22 ( '^V') */ (unsigned char) 22,
+/* 23 ( '^W') */ (unsigned char) 23,
+/* 24 ( '^X') */ (unsigned char) 24,
+/* 25 ( '^Y') */ (unsigned char) 25,
+/* 26 ( '^Z') */ (unsigned char) 26,
+/* 27 ( '^[') */ (unsigned char) 27,
+/* 28 ( '^\') */ (unsigned char) 28,
+/* 29 ( '^]') */ (unsigned char) 29,
+/* 30 ( '^^') */ (unsigned char) 30,
+/* 31 ( '^_') */ (unsigned char) 31,
+/* 32 ( ' ' ) */ (unsigned char) 32,
+/* 33 ( '!' ) */ (unsigned char) 33,
+/* 34 ( '"' ) */ (unsigned char) 39,
+/* 35 ( '#' ) */ (unsigned char) 35,
+/* 36 ( '$' ) */ (unsigned char) 36,
+/* 37 ( '%' ) */ (unsigned char) 37,
+/* 38 ( '&' ) */ (unsigned char) 38,
+/* 39 ( ''' ) */ (unsigned char) 39,
+/* 40 ( '(' ) */ (unsigned char) 40,
+/* 41 ( ')' ) */ (unsigned char) 41,
+/* 42 ( '*' ) */ (unsigned char) 42,
+/* 43 ( '+' ) */ (unsigned char) 43,
+/* 44 ( ',' ) */ (unsigned char) 44,
+/* 45 ( '-' ) */ (unsigned char) 45,
+/* 46 ( '.' ) */ (unsigned char) 46,
+/* 47 ( '/' ) */ (unsigned char) 47,
+/* 48 ( '0' ) */ (unsigned char) 48,
+/* 49 ( '1' ) */ (unsigned char) 49,
+/* 50 ( '2' ) */ (unsigned char) 50,
+/* 51 ( '3' ) */ (unsigned char) 51,
+/* 52 ( '4' ) */ (unsigned char) 52,
+/* 53 ( '5' ) */ (unsigned char) 53,
+/* 54 ( '6' ) */ (unsigned char) 54,
+/* 55 ( '7' ) */ (unsigned char) 55,
+/* 56 ( '8' ) */ (unsigned char) 56,
+/* 57 ( '9' ) */ (unsigned char) 57,
+/* 58 ( ':' ) */ (unsigned char) 58,
+/* 59 ( ';' ) */ (unsigned char) 59,
+/* 60 ( '<' ) */ (unsigned char) 60,
+/* 61 ( '=' ) */ (unsigned char) 61,
+/* 62 ( '>' ) */ (unsigned char) 62,
+/* 63 ( '?' ) */ (unsigned char) 63,
+/* 64 ( '@' ) */ (unsigned char) 64,
+/* 65 ( 'A' ) */ (unsigned char) 65,
+/* 66 ( 'B' ) */ (unsigned char) 66,
+/* 67 ( 'C' ) */ (unsigned char) 67,
+/* 68 ( 'D' ) */ (unsigned char) 68,
+/* 69 ( 'E' ) */ (unsigned char) 69,
+/* 70 ( 'F' ) */ (unsigned char) 70,
+/* 71 ( 'G' ) */ (unsigned char) 71,
+/* 72 ( 'H' ) */ (unsigned char) 72,
+/* 73 ( 'I' ) */ (unsigned char) 73,
+/* 74 ( 'J' ) */ (unsigned char) 74,
+/* 75 ( 'K' ) */ (unsigned char) 75,
+/* 76 ( 'L' ) */ (unsigned char) 76,
+/* 77 ( 'M' ) */ (unsigned char) 77,
+/* 78 ( 'N' ) */ (unsigned char) 78,
+/* 79 ( 'O' ) */ (unsigned char) 79,
+/* 80 ( 'P' ) */ (unsigned char) 80,
+/* 81 ( 'Q' ) */ (unsigned char) 81,
+/* 82 ( 'R' ) */ (unsigned char) 82,
+/* 83 ( 'S' ) */ (unsigned char) 83,
+/* 84 ( 'T' ) */ (unsigned char) 84,
+/* 85 ( 'U' ) */ (unsigned char) 85,
+/* 86 ( 'V' ) */ (unsigned char) 86,
+/* 87 ( 'W' ) */ (unsigned char) 87,
+/* 88 ( 'X' ) */ (unsigned char) 88,
+/* 89 ( 'Y' ) */ (unsigned char) 89,
+/* 90 ( 'Z' ) */ (unsigned char) 90,
+/* 91 ( '[' ) */ (unsigned char) 91,
+/* 92 ( '\' ) */ (unsigned char) 92,
+/* 93 ( ']' ) */ (unsigned char) 93,
+/* 94 ( '^' ) */ (unsigned char) 94,
+/* 95 ( '_' ) */ (unsigned char) 95,
+/* 96 ( '`' ) */ (unsigned char) 96,
+/* 97 ( 'a' ) */ (unsigned char) 97,
+/* 98 ( 'b' ) */ (unsigned char) 98,
+/* 99 ( 'c' ) */ (unsigned char) 99,
+/* 100 ( 'd' ) */ (unsigned char) 100,
+/* 101 ( 'e' ) */ (unsigned char) 101,
+/* 102 ( 'f' ) */ (unsigned char) 102,
+/* 103 ( 'g' ) */ (unsigned char) 103,
+/* 104 ( 'h' ) */ (unsigned char) 104,
+/* 105 ( 'i' ) */ (unsigned char) 105,
+/* 106 ( 'j' ) */ (unsigned char) 106,
+/* 107 ( 'k' ) */ (unsigned char) 107,
+/* 108 ( 'l' ) */ (unsigned char) 108,
+/* 109 ( 'm' ) */ (unsigned char) 109,
+/* 110 ( 'n' ) */ (unsigned char) 110,
+/* 111 ( 'o' ) */ (unsigned char) 111,
+/* 112 ( 'p' ) */ (unsigned char) 112,
+/* 113 ( 'q' ) */ (unsigned char) 113,
+/* 114 ( 'r' ) */ (unsigned char) 114,
+/* 115 ( 's' ) */ (unsigned char) 115,
+/* 116 ( 't' ) */ (unsigned char) 116,
+/* 117 ( 'u' ) */ (unsigned char) 117,
+/* 118 ( 'v' ) */ (unsigned char) 118,
+/* 119 ( 'w' ) */ (unsigned char) 119,
+/* 120 ( 'x' ) */ (unsigned char) 120,
+/* 121 ( 'y' ) */ (unsigned char) 121,
+/* 122 ( 'z' ) */ (unsigned char) 122,
+/* 123 ( '{' ) */ (unsigned char) 123,
+/* 124 ( '|' ) */ (unsigned char) 124,
+/* 125 ( '}' ) */ (unsigned char) 125,
+/* 126 ( '~' ) */ (unsigned char) 126,
+/* 127 ( '^?') */ (unsigned char) 127,
+/* 128 ( '~@') */ (unsigned char) 128,
+/* 129 ( '~A') */ (unsigned char) 129,
+/* 130 ( '~B') */ (unsigned char) 130,
+/* 131 ( '~C') */ (unsigned char) 131,
+/* 132 ( '~D') */ (unsigned char) 132,
+/* 133 ( '~E') */ (unsigned char) 133,
+/* 134 ( '~F') */ (unsigned char) 134,
+/* 135 ( '~G') */ (unsigned char) 135,
+/* 136 ( '~H') */ (unsigned char) 136,
+/* 137 ( '~I') */ (unsigned char) 137,
+/* 138 ( '~J') */ (unsigned char) 138,
+/* 139 ( '~K') */ (unsigned char) 139,
+/* 140 ( '~L') */ (unsigned char) 140,
+/* 141 ( '~M') */ (unsigned char) 141,
+/* 142 ( '~N') */ (unsigned char) 142,
+/* 143 ( '~O') */ (unsigned char) 143,
+/* 144 ( '~P') */ (unsigned char) 144,
+/* 145 ( '~Q') */ (unsigned char) 145,
+/* 146 ( '~R') */ (unsigned char) 146,
+/* 147 ( '~S') */ (unsigned char) 147,
+/* 148 ( '~T') */ (unsigned char) 148,
+/* 149 ( '~U') */ (unsigned char) 149,
+/* 150 ( '~V') */ (unsigned char) 150,
+/* 151 ( '~W') */ (unsigned char) 151,
+/* 152 ( '~X') */ (unsigned char) 152,
+/* 153 ( '~Y') */ (unsigned char) 153,
+/* 154 ( '~Z') */ (unsigned char) 154,
+/* 155 ( '~[') */ (unsigned char) 155,
+/* 156 ( '~\') */ (unsigned char) 156,
+/* 157 ( '~]') */ (unsigned char) 157,
+/* 158 ( '~^') */ (unsigned char) 158,
+/* 159 ( '~_') */ (unsigned char) 159,
+/* 160 ( '| ') */ (unsigned char) 160,
+/* 161 ( '¡' ) */ (unsigned char) 161,
+/* 162 ( '¢' ) */ (unsigned char) 162,
+/* 163 ( '£' ) */ (unsigned char) 163,
+/* 164 ( '¤' ) */ (unsigned char) 164,
+/* 165 ( '¥' ) */ (unsigned char) 92,
+/* 166 ( '¦' ) */ (unsigned char) 166,
+/* 167 ( '§' ) */ (unsigned char) 167,
+/* 168 ( '¨' ) */ (unsigned char) 168,
+/* 169 ( '©' ) */ (unsigned char) 67,
+/* 170 ( 'ª' ) */ (unsigned char) 170,
+/* 171 ( '«' ) */ (unsigned char) 171,
+/* 172 ( '¬' ) */ (unsigned char) 172,
+/* 173 ( '­' ) */ (unsigned char) 173,
+/* 174 ( '®' ) */ (unsigned char) 174,
+/* 175 ( '¯' ) */ (unsigned char) 175,
+/* 176 ( '°' ) */ (unsigned char) 223,
+/* 177 ( '±' ) */ (unsigned char) 177,
+/* 178 ( '²' ) */ (unsigned char) 50,
+/* 179 ( '³' ) */ (unsigned char) 51,
+/* 180 ( '´' ) */ (unsigned char) 180,
+/* 181 ( 'µ' ) */ (unsigned char) 228,
+/* 182 ( '¶' ) */ (unsigned char) 182,
+/* 183 ( '·' ) */ (unsigned char) 183,
+/* 184 ( '¸' ) */ (unsigned char) 184,
+/* 185 ( '¹' ) */ (unsigned char) 185,
+/* 186 ( 'º' ) */ (unsigned char) 223,
+/* 187 ( '»' ) */ (unsigned char) 187,
+/* 188 ( '¼' ) */ (unsigned char) 188,
+/* 189 ( '½' ) */ (unsigned char) 189,
+/* 190 ( '¾' ) */ (unsigned char) 190,
+/* 191 ( '¿' ) */ (unsigned char) 191,
+/* 192 ( 'À' ) */ (unsigned char) 65,
+/* 193 ( 'Á' ) */ (unsigned char) 65,
+/* 194 ( 'Â' ) */ (unsigned char) 65,
+/* 195 ( 'Ã' ) */ (unsigned char) 65,
+/* 196 ( 'Ä' ) */ (unsigned char) 225,
+/* 197 ( 'Å' ) */ (unsigned char) 65,
+/* 198 ( 'Æ' ) */ (unsigned char) 225,
+/* 199 ( 'Ç' ) */ (unsigned char) 67,
+/* 200 ( 'È' ) */ (unsigned char) 69,
+/* 201 ( 'É' ) */ (unsigned char) 69,
+/* 202 ( 'Ê' ) */ (unsigned char) 69,
+/* 203 ( 'Ë' ) */ (unsigned char) 69,
+/* 204 ( 'Ì' ) */ (unsigned char) 73,
+/* 205 ( 'Í' ) */ (unsigned char) 73,
+/* 206 ( 'Î' ) */ (unsigned char) 73,
+/* 207 ( 'Ï' ) */ (unsigned char) 73,
+/* 208 ( 'Ð' ) */ (unsigned char) 68,
+/* 209 ( 'Ñ' ) */ (unsigned char) 78,
+/* 210 ( 'Ò' ) */ (unsigned char) 79,
+/* 211 ( 'Ó' ) */ (unsigned char) 79,
+/* 212 ( 'Ô' ) */ (unsigned char) 79,
+/* 213 ( 'Õ' ) */ (unsigned char) 79,
+/* 214 ( 'Ö' ) */ (unsigned char) 239,
+/* 215 ( '×' ) */ (unsigned char) 88,
+/* 216 ( 'Ø' ) */ (unsigned char) 48,
+/* 217 ( 'Ù' ) */ (unsigned char) 85,
+/* 218 ( 'Ú' ) */ (unsigned char) 85,
+/* 219 ( 'Û' ) */ (unsigned char) 85,
+/* 220 ( 'Ü' ) */ (unsigned char) 245,
+/* 221 ( 'Ý' ) */ (unsigned char) 89,
+/* 222 ( 'Þ' ) */ (unsigned char) 222,
+/* 223 ( 'ß' ) */ (unsigned char) 226,
+/* 224 ( 'à' ) */ (unsigned char) 97,
+/* 225 ( 'á' ) */ (unsigned char) 97,
+/* 226 ( 'â' ) */ (unsigned char) 97,
+/* 227 ( 'ã' ) */ (unsigned char) 97,
+/* 228 ( 'ä' ) */ (unsigned char) 225,
+/* 229 ( 'å' ) */ (unsigned char) 97,
+/* 230 ( 'æ' ) */ (unsigned char) 230,
+/* 231 ( 'ç' ) */ (unsigned char) 99,
+/* 232 ( 'è' ) */ (unsigned char) 101,
+/* 233 ( 'é' ) */ (unsigned char) 101,
+/* 234 ( 'ê' ) */ (unsigned char) 101,
+/* 235 ( 'ë' ) */ (unsigned char) 101,
+/* 236 ( 'ì' ) */ (unsigned char) 105,
+/* 237 ( 'í' ) */ (unsigned char) 105,
+/* 238 ( 'î' ) */ (unsigned char) 105,
+/* 239 ( 'ï' ) */ (unsigned char) 105,
+/* 240 ( 'ð' ) */ (unsigned char) 100,
+/* 241 ( 'ñ' ) */ (unsigned char) 110,
+/* 242 ( 'ò' ) */ (unsigned char) 111,
+/* 243 ( 'ó' ) */ (unsigned char) 111,
+/* 244 ( 'ô' ) */ (unsigned char) 111,
+/* 245 ( 'õ' ) */ (unsigned char) 111,
+/* 246 ( 'ö' ) */ (unsigned char) 239,
+/* 247 ( '÷' ) */ (unsigned char) 253,
+/* 248 ( 'ø' ) */ (unsigned char) 248,
+/* 249 ( 'ù' ) */ (unsigned char) 117,
+/* 250 ( 'ú' ) */ (unsigned char) 117,
+/* 251 ( 'û' ) */ (unsigned char) 117,
+/* 252 ( 'ü' ) */ (unsigned char) 245,
+/* 253 ( 'ý' ) */ (unsigned char) 121,
+/* 254 ( 'þ' ) */ (unsigned char) 254,
+/* 255 ( 'ÿ' ) */ (unsigned char) 121};
+
diff --git a/lcdtranstbl-nomap.h b/lcdtranstbl-nomap.h
new file mode 100644
index 0000000..a232640
--- /dev/null
+++ b/lcdtranstbl-nomap.h
@@ -0,0 +1,264 @@
+/*
+lcdtranstbl-nomap.h
+nothing except '"' is mapped here, seems that somone does not understand '\"' ...
+newline,tab and friends are mapped to ' '
+*/
+
+const unsigned char LcdTransTbl[256]={
+/* 0 ( '^@') */ (unsigned char) 0,
+/* 1 ( '^A') */ (unsigned char) 1,
+/* 2 ( '^B') */ (unsigned char) 2,
+/* 3 ( '^C') */ (unsigned char) 3,
+/* 4 ( '^D') */ (unsigned char) 4,
+/* 5 ( '^E') */ (unsigned char) 5,
+/* 6 ( '^F') */ (unsigned char) 6,
+/* 7 ( '^G') */ (unsigned char) 7,
+/* 8 ( '^H') */ (unsigned char) 8,
+/* 9 ( '' ) */ (unsigned char) 32,
+/* 10 ( '' ) */ (unsigned char) 32,
+/* 11 ( '^K') */ (unsigned char) 32,
+/* 12 ( '^L') */ (unsigned char) 32,
+/* 13 ( '^M') */ (unsigned char) 32,
+/* 14 ( '^N') */ (unsigned char) 14,
+/* 15 ( '^O') */ (unsigned char) 15,
+/* 16 ( '^P') */ (unsigned char) 16,
+/* 17 ( '^Q') */ (unsigned char) 17,
+/* 18 ( '^R') */ (unsigned char) 18,
+/* 19 ( '^S') */ (unsigned char) 19,
+/* 20 ( '^T') */ (unsigned char) 20,
+/* 21 ( '^U') */ (unsigned char) 21,
+/* 22 ( '^V') */ (unsigned char) 22,
+/* 23 ( '^W') */ (unsigned char) 23,
+/* 24 ( '^X') */ (unsigned char) 24,
+/* 25 ( '^Y') */ (unsigned char) 25,
+/* 26 ( '^Z') */ (unsigned char) 26,
+/* 27 ( '^[') */ (unsigned char) 27,
+/* 28 ( '^\') */ (unsigned char) 28,
+/* 29 ( '^]') */ (unsigned char) 29,
+/* 30 ( '^^') */ (unsigned char) 30,
+/* 31 ( '^_') */ (unsigned char) 31,
+/* 32 ( ' ' ) */ (unsigned char) 32,
+/* 33 ( '!' ) */ (unsigned char) 33,
+/* 34 ( '"' ) */ (unsigned char) 39,
+/* 35 ( '#' ) */ (unsigned char) 35,
+/* 36 ( '$' ) */ (unsigned char) 36,
+/* 37 ( '%' ) */ (unsigned char) 37,
+/* 38 ( '&' ) */ (unsigned char) 38,
+/* 39 ( ''' ) */ (unsigned char) 39,
+/* 40 ( '(' ) */ (unsigned char) 40,
+/* 41 ( ')' ) */ (unsigned char) 41,
+/* 42 ( '*' ) */ (unsigned char) 42,
+/* 43 ( '+' ) */ (unsigned char) 43,
+/* 44 ( ',' ) */ (unsigned char) 44,
+/* 45 ( '-' ) */ (unsigned char) 45,
+/* 46 ( '.' ) */ (unsigned char) 46,
+/* 47 ( '/' ) */ (unsigned char) 47,
+/* 48 ( '0' ) */ (unsigned char) 48,
+/* 49 ( '1' ) */ (unsigned char) 49,
+/* 50 ( '2' ) */ (unsigned char) 50,
+/* 51 ( '3' ) */ (unsigned char) 51,
+/* 52 ( '4' ) */ (unsigned char) 52,
+/* 53 ( '5' ) */ (unsigned char) 53,
+/* 54 ( '6' ) */ (unsigned char) 54,
+/* 55 ( '7' ) */ (unsigned char) 55,
+/* 56 ( '8' ) */ (unsigned char) 56,
+/* 57 ( '9' ) */ (unsigned char) 57,
+/* 58 ( ':' ) */ (unsigned char) 58,
+/* 59 ( ';' ) */ (unsigned char) 59,
+/* 60 ( '<' ) */ (unsigned char) 60,
+/* 61 ( '=' ) */ (unsigned char) 61,
+/* 62 ( '>' ) */ (unsigned char) 62,
+/* 63 ( '?' ) */ (unsigned char) 63,
+/* 64 ( '@' ) */ (unsigned char) 64,
+/* 65 ( 'A' ) */ (unsigned char) 65,
+/* 66 ( 'B' ) */ (unsigned char) 66,
+/* 67 ( 'C' ) */ (unsigned char) 67,
+/* 68 ( 'D' ) */ (unsigned char) 68,
+/* 69 ( 'E' ) */ (unsigned char) 69,
+/* 70 ( 'F' ) */ (unsigned char) 70,
+/* 71 ( 'G' ) */ (unsigned char) 71,
+/* 72 ( 'H' ) */ (unsigned char) 72,
+/* 73 ( 'I' ) */ (unsigned char) 73,
+/* 74 ( 'J' ) */ (unsigned char) 74,
+/* 75 ( 'K' ) */ (unsigned char) 75,
+/* 76 ( 'L' ) */ (unsigned char) 76,
+/* 77 ( 'M' ) */ (unsigned char) 77,
+/* 78 ( 'N' ) */ (unsigned char) 78,
+/* 79 ( 'O' ) */ (unsigned char) 79,
+/* 80 ( 'P' ) */ (unsigned char) 80,
+/* 81 ( 'Q' ) */ (unsigned char) 81,
+/* 82 ( 'R' ) */ (unsigned char) 82,
+/* 83 ( 'S' ) */ (unsigned char) 83,
+/* 84 ( 'T' ) */ (unsigned char) 84,
+/* 85 ( 'U' ) */ (unsigned char) 85,
+/* 86 ( 'V' ) */ (unsigned char) 86,
+/* 87 ( 'W' ) */ (unsigned char) 87,
+/* 88 ( 'X' ) */ (unsigned char) 88,
+/* 89 ( 'Y' ) */ (unsigned char) 89,
+/* 90 ( 'Z' ) */ (unsigned char) 90,
+/* 91 ( '[' ) */ (unsigned char) 91,
+/* 92 ( '\' ) */ (unsigned char) 92,
+/* 93 ( ']' ) */ (unsigned char) 93,
+/* 94 ( '^' ) */ (unsigned char) 94,
+/* 95 ( '_' ) */ (unsigned char) 95,
+/* 96 ( '`' ) */ (unsigned char) 96,
+/* 97 ( 'a' ) */ (unsigned char) 97,
+/* 98 ( 'b' ) */ (unsigned char) 98,
+/* 99 ( 'c' ) */ (unsigned char) 99,
+/* 100 ( 'd' ) */ (unsigned char) 100,
+/* 101 ( 'e' ) */ (unsigned char) 101,
+/* 102 ( 'f' ) */ (unsigned char) 102,
+/* 103 ( 'g' ) */ (unsigned char) 103,
+/* 104 ( 'h' ) */ (unsigned char) 104,
+/* 105 ( 'i' ) */ (unsigned char) 105,
+/* 106 ( 'j' ) */ (unsigned char) 106,
+/* 107 ( 'k' ) */ (unsigned char) 107,
+/* 108 ( 'l' ) */ (unsigned char) 108,
+/* 109 ( 'm' ) */ (unsigned char) 109,
+/* 110 ( 'n' ) */ (unsigned char) 110,
+/* 111 ( 'o' ) */ (unsigned char) 111,
+/* 112 ( 'p' ) */ (unsigned char) 112,
+/* 113 ( 'q' ) */ (unsigned char) 113,
+/* 114 ( 'r' ) */ (unsigned char) 114,
+/* 115 ( 's' ) */ (unsigned char) 115,
+/* 116 ( 't' ) */ (unsigned char) 116,
+/* 117 ( 'u' ) */ (unsigned char) 117,
+/* 118 ( 'v' ) */ (unsigned char) 118,
+/* 119 ( 'w' ) */ (unsigned char) 119,
+/* 120 ( 'x' ) */ (unsigned char) 120,
+/* 121 ( 'y' ) */ (unsigned char) 121,
+/* 122 ( 'z' ) */ (unsigned char) 122,
+/* 123 ( '{' ) */ (unsigned char) 123,
+/* 124 ( '|' ) */ (unsigned char) 124,
+/* 125 ( '}' ) */ (unsigned char) 125,
+/* 126 ( '~' ) */ (unsigned char) 126,
+/* 127 ( '^?') */ (unsigned char) 127,
+/* 128 ( '~@') */ (unsigned char) 128,
+/* 129 ( '~A') */ (unsigned char) 129,
+/* 130 ( '~B') */ (unsigned char) 130,
+/* 131 ( '~C') */ (unsigned char) 131,
+/* 132 ( '~D') */ (unsigned char) 132,
+/* 133 ( '~E') */ (unsigned char) 133,
+/* 134 ( '~F') */ (unsigned char) 134,
+/* 135 ( '~G') */ (unsigned char) 135,
+/* 136 ( '~H') */ (unsigned char) 136,
+/* 137 ( '~I') */ (unsigned char) 137,
+/* 138 ( '~J') */ (unsigned char) 138,
+/* 139 ( '~K') */ (unsigned char) 139,
+/* 140 ( '~L') */ (unsigned char) 140,
+/* 141 ( '~M') */ (unsigned char) 141,
+/* 142 ( '~N') */ (unsigned char) 142,
+/* 143 ( '~O') */ (unsigned char) 143,
+/* 144 ( '~P') */ (unsigned char) 144,
+/* 145 ( '~Q') */ (unsigned char) 145,
+/* 146 ( '~R') */ (unsigned char) 146,
+/* 147 ( '~S') */ (unsigned char) 147,
+/* 148 ( '~T') */ (unsigned char) 148,
+/* 149 ( '~U') */ (unsigned char) 149,
+/* 150 ( '~V') */ (unsigned char) 150,
+/* 151 ( '~W') */ (unsigned char) 151,
+/* 152 ( '~X') */ (unsigned char) 152,
+/* 153 ( '~Y') */ (unsigned char) 153,
+/* 154 ( '~Z') */ (unsigned char) 154,
+/* 155 ( '~[') */ (unsigned char) 155,
+/* 156 ( '~\') */ (unsigned char) 156,
+/* 157 ( '~]') */ (unsigned char) 157,
+/* 158 ( '~^') */ (unsigned char) 158,
+/* 159 ( '~_') */ (unsigned char) 159,
+/* 160 ( '| ') */ (unsigned char) 160,
+/* 161 ( '¡' ) */ (unsigned char) 161,
+/* 162 ( '¢' ) */ (unsigned char) 162,
+/* 163 ( '£' ) */ (unsigned char) 163,
+/* 164 ( '¤' ) */ (unsigned char) 164,
+/* 165 ( '¥' ) */ (unsigned char) 165,
+/* 166 ( '¦' ) */ (unsigned char) 166,
+/* 167 ( '§' ) */ (unsigned char) 167,
+/* 168 ( '¨' ) */ (unsigned char) 168,
+/* 169 ( '©' ) */ (unsigned char) 169,
+/* 170 ( 'ª' ) */ (unsigned char) 170,
+/* 171 ( '«' ) */ (unsigned char) 171,
+/* 172 ( '¬' ) */ (unsigned char) 172,
+/* 173 ( '­' ) */ (unsigned char) 173,
+/* 174 ( '®' ) */ (unsigned char) 174,
+/* 175 ( '¯' ) */ (unsigned char) 175,
+/* 176 ( '°' ) */ (unsigned char) 176,
+/* 177 ( '±' ) */ (unsigned char) 177,
+/* 178 ( '²' ) */ (unsigned char) 178,
+/* 179 ( '³' ) */ (unsigned char) 179,
+/* 180 ( '´' ) */ (unsigned char) 180,
+/* 181 ( 'µ' ) */ (unsigned char) 181,
+/* 182 ( '¶' ) */ (unsigned char) 182,
+/* 183 ( '·' ) */ (unsigned char) 183,
+/* 184 ( '¸' ) */ (unsigned char) 184,
+/* 185 ( '¹' ) */ (unsigned char) 185,
+/* 186 ( 'º' ) */ (unsigned char) 186,
+/* 187 ( '»' ) */ (unsigned char) 187,
+/* 188 ( '¼' ) */ (unsigned char) 188,
+/* 189 ( '½' ) */ (unsigned char) 189,
+/* 190 ( '¾' ) */ (unsigned char) 190,
+/* 191 ( '¿' ) */ (unsigned char) 191,
+/* 192 ( 'À' ) */ (unsigned char) 192,
+/* 193 ( 'Á' ) */ (unsigned char) 193,
+/* 194 ( 'Â' ) */ (unsigned char) 194,
+/* 195 ( 'Ã' ) */ (unsigned char) 195,
+/* 196 ( 'Ä' ) */ (unsigned char) 196,
+/* 197 ( 'Å' ) */ (unsigned char) 197,
+/* 198 ( 'Æ' ) */ (unsigned char) 198,
+/* 199 ( 'Ç' ) */ (unsigned char) 199,
+/* 200 ( 'È' ) */ (unsigned char) 200,
+/* 201 ( 'É' ) */ (unsigned char) 201,
+/* 202 ( 'Ê' ) */ (unsigned char) 202,
+/* 203 ( 'Ë' ) */ (unsigned char) 203,
+/* 204 ( 'Ì' ) */ (unsigned char) 204,
+/* 205 ( 'Í' ) */ (unsigned char) 205,
+/* 206 ( 'Î' ) */ (unsigned char) 206,
+/* 207 ( 'Ï' ) */ (unsigned char) 207,
+/* 208 ( 'Ð' ) */ (unsigned char) 208,
+/* 209 ( 'Ñ' ) */ (unsigned char) 209,
+/* 210 ( 'Ò' ) */ (unsigned char) 210,
+/* 211 ( 'Ó' ) */ (unsigned char) 211,
+/* 212 ( 'Ô' ) */ (unsigned char) 212,
+/* 213 ( 'Õ' ) */ (unsigned char) 213,
+/* 214 ( 'Ö' ) */ (unsigned char) 214,
+/* 215 ( '×' ) */ (unsigned char) 215,
+/* 216 ( 'Ø' ) */ (unsigned char) 216,
+/* 217 ( 'Ù' ) */ (unsigned char) 217,
+/* 218 ( 'Ú' ) */ (unsigned char) 218,
+/* 219 ( 'Û' ) */ (unsigned char) 219,
+/* 220 ( 'Ü' ) */ (unsigned char) 220,
+/* 221 ( 'Ý' ) */ (unsigned char) 221,
+/* 222 ( 'Þ' ) */ (unsigned char) 222,
+/* 223 ( 'ß' ) */ (unsigned char) 223,
+/* 224 ( 'à' ) */ (unsigned char) 224,
+/* 225 ( 'á' ) */ (unsigned char) 225,
+/* 226 ( 'â' ) */ (unsigned char) 226,
+/* 227 ( 'ã' ) */ (unsigned char) 227,
+/* 228 ( 'ä' ) */ (unsigned char) 228,
+/* 229 ( 'å' ) */ (unsigned char) 229,
+/* 230 ( 'æ' ) */ (unsigned char) 230,
+/* 231 ( 'ç' ) */ (unsigned char) 231,
+/* 232 ( 'è' ) */ (unsigned char) 232,
+/* 233 ( 'é' ) */ (unsigned char) 233,
+/* 234 ( 'ê' ) */ (unsigned char) 234,
+/* 235 ( 'ë' ) */ (unsigned char) 235,
+/* 236 ( 'ì' ) */ (unsigned char) 236,
+/* 237 ( 'í' ) */ (unsigned char) 237,
+/* 238 ( 'î' ) */ (unsigned char) 238,
+/* 239 ( 'ï' ) */ (unsigned char) 239,
+/* 240 ( 'ð' ) */ (unsigned char) 240,
+/* 241 ( 'ñ' ) */ (unsigned char) 241,
+/* 242 ( 'ò' ) */ (unsigned char) 242,
+/* 243 ( 'ó' ) */ (unsigned char) 243,
+/* 244 ( 'ô' ) */ (unsigned char) 244,
+/* 245 ( 'õ' ) */ (unsigned char) 245,
+/* 246 ( 'ö' ) */ (unsigned char) 246,
+/* 247 ( '÷' ) */ (unsigned char) 247,
+/* 248 ( 'ø' ) */ (unsigned char) 248,
+/* 249 ( 'ù' ) */ (unsigned char) 249,
+/* 250 ( 'ú' ) */ (unsigned char) 250,
+/* 251 ( 'û' ) */ (unsigned char) 251,
+/* 252 ( 'ü' ) */ (unsigned char) 252,
+/* 253 ( 'ý' ) */ (unsigned char) 253,
+/* 254 ( 'þ' ) */ (unsigned char) 254,
+/* 255 ( 'ÿ' ) */ (unsigned char) 255};
+
diff --git a/sockets.c b/sockets.c
new file mode 100644
index 0000000..5a9bb15
--- /dev/null
+++ b/sockets.c
@@ -0,0 +1,230 @@
+/********************************
+this file was taken from the
+LCDproc source see
+http://lcdproc.omnipotent.net/
+for more info.
+*********************************/
+
+#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/types.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include "sockets.h"
+
+/**************************************************
+ LCDproc client sockets code...
+
+ Feel free to use this in your own clients... :)
+**************************************************/
+
+// Length of longest transmission allowed at once...
+#define MAXMSG 8192
+
+typedef struct sockaddr_in sockaddr_in;
+
+static int
+sock_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, "sock_init_sockaddr: Unknown host %s.\n", hostname);
+ return -1;
+ }
+ name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
+
+ return 0;
+
+}
+
+ // Client functions...
+int
+sock_connect (char *host, unsigned short int port)
+{
+ struct sockaddr_in servername;
+ int sock;
+ int err = 0;
+
+ //debug ("sock_connect: Creating socket\n");
+ sock = socket (PF_INET, SOCK_STREAM, 0);
+ if (sock < 0) {
+ perror ("sock_connect: Error creating socket");
+ return sock;
+ }
+ //debug ("sock_connect: Created socket (%i)\n", sock);
+
+ sock_init_sockaddr (&servername, host, port);
+
+ err = connect (sock, (struct sockaddr *) &servername, sizeof (servername));
+ if (err < 0) {
+ perror ("sock_connect: connect failed");
+ shutdown (sock, 2);
+ return 0; // Normal exit if server doesn't exist...
+ }
+
+ fcntl (sock, F_SETFL, O_NONBLOCK);
+
+ return sock;
+}
+
+int
+sock_close (int fd)
+{
+ int err;
+
+ err = shutdown (fd, 2);
+ if (!err)
+ close (fd);
+
+ return err;
+}
+
+// Send/receive lines of text
+int
+sock_send_string (int fd, char *string)
+{
+ int len;
+ int offset = 0;
+
+ if (!string)
+ return -1;
+
+ len = strlen (string) ;
+ while (offset != len) {
+ // write isn't guaranteed to send the entire string at once,
+ // so we have to sent it in a loop like this
+ int sent = write (fd, string + offset, len - offset);
+ if (sent == -1) {
+ if (errno != EAGAIN) {
+ perror ("sock_send_string: socket write error");
+ printf ("Message was: %s\n", string);
+ //shutdown(fd, 2);
+ return sent;
+ }
+ continue;
+ } else if (sent == 0) {
+ // when this returns zero, it generally means
+ // we got disconnected
+ return sent + offset;
+ }
+
+ offset += sent;
+ }
+
+ return offset;
+}
+
+// Recv gives only one line per call...
+int
+sock_recv_string (int fd, char *dest, size_t maxlen)
+{
+ char *ptr = dest;
+ unsigned int recv = 0;
+
+ if (!dest)
+ return -1;
+ if (maxlen <= 0)
+ return 0;
+
+ while (1) {
+ int err = read (fd, ptr, 1);
+ if (err == -1) {
+ if (errno == EAGAIN) {
+ if (recv) {
+ // We've begun to read a string, but no bytes are
+ // available. Loop.
+ continue;
+ }
+ return 0;
+ } else {
+ perror ("sock_recv_string: socket read error");
+ return err;
+ }
+ } else if (err == 0) {
+ return recv;
+ }
+
+ recv++;
+
+ if (recv == maxlen || *ptr == 0 || *ptr == 10) {
+ *ptr = 0;
+ break;
+ }
+ ptr++;
+ }
+
+ if (recv == 1 && dest[0] == 0) {
+ // Don't return a null string
+ return 0;
+ }
+
+ if (recv < maxlen - 1) {
+ dest[recv] = 0;
+ }
+
+ return recv;
+}
+
+// Send/receive raw data
+int
+sock_send (int fd, void *src, size_t size)
+{
+ unsigned int offset = 0;
+
+ if (!src)
+ return -1;
+
+ while (offset != size) {
+ // write isn't guaranteed to send the entire string at once,
+ // so we have to sent it in a loop like this
+ int sent = write (fd, ((char *) src) + offset, size - offset);
+ if (sent == -1) {
+ if (errno != EAGAIN) {
+ perror ("sock_send: socket write error");
+ //shutdown(fd, 2);
+ return sent;
+ }
+ continue;
+ } else if (sent == 0) {
+ // when this returns zero, it generally means
+ // we got disconnected
+ return sent + offset;
+ }
+
+ offset += sent;
+ }
+
+ return offset;
+}
+
+int
+sock_recv (int fd, void *dest, size_t maxlen)
+{
+ int err;
+
+ if (!dest)
+ return -1;
+ if (maxlen <= 0)
+ return 0;
+
+ err = read (fd, dest, maxlen);
+ if (err < 0) {
+ //fprintf (stderr,"sock_recv: socket read error\n");
+ //shutdown(fd, 2);
+ return err;
+ }
+ //debug("sock_recv: Got message \"%s\"\n", (char *)dest);
+
+ return err;
+}
diff --git a/sockets.h b/sockets.h
new file mode 100644
index 0000000..86df31f
--- /dev/null
+++ b/sockets.h
@@ -0,0 +1,92 @@
+/********************************
+this file was taken from the
+LCDproc source see
+http://lcdproc.omnipotent.net/
+for more info.
+*********************************/
+
+#ifndef SOCKETS_H
+#define SOCKETS_H
+
+#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef LCDPORT
+#define LCDPORT 13666
+#endif
+
+/*
+ Socket functions available to server and clients...
+ (ignore the rest of the comments... I was babbling out random ideas)
+
+ This should have stuff to read/write sockets, open/close them, etc...
+ */
+
+// Client functions...
+int sock_connect (char *host, unsigned short int port);
+int sock_close (int fd);
+// Send/receive lines of text
+int sock_send_string (int fd, char *string);
+// Recv gives only one line per call...
+int sock_recv_string (int fd, char *dest, size_t maxlen);
+// Send/receive raw data
+int sock_send (int fd, void *src, size_t size);
+int sock_recv (int fd, void *dest, size_t maxlen);
+
+// Er, ignore the rest of this file. I'll clean it up sometime...
+
+/*****************************************************************
+ 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
+
+******************************************************************/
+
+#endif