My collection of historical open source code written over the years as part of the various ventures and involvements – mostly in C and Linux based – for archival purpose.

Pig Shoot (2000)

pig1.gif pig1.gif pig1.gif

Simple “shoot the pig” game for the Cybiko portable game device.

[ (129k) ]

jasciimovie (1999)

Play ASCII movies – sequences of digitized video converted into an ASCII representation – in a webbrowser via Java. Licenced under the GPL; see the file LICENSE in the archive for details.


[ jasciimovie-2.0.tar.gz (89k)]




(c) under GPL, A. Schiffler, 1999

[ Introduction ]

jasciimovie is a java program designed to play back an ascii-movie within a
browser. An ascii-movie is a plain text file of screens seperated by escape
codes for clearing the screen (in hex notation 1B 5B 48 1B 5B 4A).

These ascii-movies can get produced by the asciivideo sample program that is
included with the "libbgrab" package by me.

The movie files have to be compressed with "gzip -9" which saves incredible
amounts of space.

[ Compilation and Usage ]

- Prerequisites: JDK 1.1.x+ installed and in the path
- To compile type: make
- To test: fire up a java-capable browser with the file jasciimovie.html

See the file jasciimovie.html for how to incorporate the applet in your

Configurable parameters are: the filename (the movie file must be in the same 
directory as the .html file), the fontsize (usable are 8,10,12,14), a flag of the
movies gets repeated at the end, the frame rate and the colors.

The program tries to center the ascii-movie within the applet. 

A copyright message is beeing displayed for 2 seconds at the beginning of

A sample movie (cfilm.txt.gz) is included - look at the file also with
"zless cfilm.txt.gz" to see the individual frames.

Keep the image files 
also in the same directory as the .html file.

lcd2 (2001)

Commandline info display driver for Matrix Orbital 20×2 LCD displays.

robtrack16 (1998)

“robtrack16” is a visual tracking program that uses a segment of 16bit YUV-color-space to locate points in a 2D image.

The available tracking colors are determined manually and read from a configuation file. the program returns an x,y coordinate pair in the range between 0.0 and 1.0 for each color beeing tracked. The tracking shapes should be roughly circular for best results, although any shape will work since the “center-of-mass” (average x and y coordinates of all points in one set) is beeing formed. The interface to the results is a standard TCP socket with ASCII in- and output.

– Linux PC
– Matrox Meteor framegrabber card


ppm2dp (1999)

Image format converter for the (now defunct) Deskplayer interactive desktop graphics engine.

ppm2smap: Converts .ppm —into— .smap

Usage: ppm2smap [Input Filename] [Output Filename]

smap2dp: Concatenates .smap —onto— .dp

Usage:  smap2dp -input name [-delay delay] [ -url url] [-input ...] [-output name] [-version #] delay = 1/10th seconds url is optional


dpwatch (2001

Watchdog program for the Berkshire Products Internal-Serial Watchdog in Command mode which was developed for the Deskplayer servers (a rack of 14 computers) and can be run as a client service that hard-reboots the computer if it becomes unresponsive. Licenced under the GPL; see the file LICENSE in the archive for details.

dpwatch – Berkshire products watchdog driver
Device settings:
-device dev watchdog device (default: /dev/ttyS1)
Runtime settings:
-delay # # seconds delay between commands (default: 60)
-status # # loops between status messages (default: 60)
-error # tolerate # errors before exiting (default: 100) Special commands:
-reset reset computer after 10 seconds (use with caution)


furbyctl (2000)


Control a Tiger Electronics “Furby” [TM] via IR port of your PC. Licenced under the LGPL; see the file COPYING for details.


[ furbyctl.tar.gz (1k)]

asciireflector (1999)

Network-reflector for ASCII data – very useful tool to distribute data between different networked programs. Licenced under the GPL; see the file COPYING for details.


[ asciireflector-1.2.tar.gz (10k) ]


[ asciireflector Ver. 1.2 ]

(c) under the GPL, A. Schiffler.

Please see file LICENSE for GPL notes.

[ version history ]

Ver 1.2 - Fri Sep 17 15:36:33 CEST 1999
- Fixed connection count
- Added a few messages
- Fixed PUSH behaviour
Ver 1.1 - Sun Aug 29 12:24:30 CEST 1999
- Put timeouts in read routine to fix "hang" after clients terminated
Ver 1.0 - Thu Aug 19 14:56:04 CEST 1999
- Initial release

[ introduction ]

The asciireflector is a simple, unix based reflector program that allows
sharing of data between clients through a TCP stream-socket connection. The
reflector reads ASCII lines from each connected client, buffers them in a
shared pool (ringbuffer) and sends all lines back to each client.

[ usage and protocol ]

Client reception is initiated by sending a textline to the reflector. This
will usually be the data that is to be shared between clients. This line 
gets stored in the reflectors buffer unless it is the text "POLL". All lines
send to the reflector have to end with a newline character. If the line is
preceded by the keyword "PUSH", the line gets distributed by the reflector
with the PUSH removed, but no lines get send back to the client. Otherwise
immediately after the reception from the client, all textlines that have 
been received since the last sending of text will be written back to the 
client. This sequence is finished when the text "OVER" is send from the
reflector. This means no new textlines are in the ringbuffer. To close the
socket connection with the reflector, send the word "LOGOUT". 

Note that the reflector sends the last textline that was received from 
the client back to the client during the next iteration. This can be 
used to test if the speed of the network connection is sufficient 
to maintain complete reception of the ringbuffer. If the first line 
received is not equal to the last line send, the ringbuffer has been 
overwritten by another client in the mean time, indicating that 
reception is too slow. Reflector use should be stopped in such a case.

Thus the client should run the following sequence repeatedly:

1. Connect to reflector
2.)   Send data

2.1.) Send data as "textline", store as "last_textline"


2.2) Send "POLL"


2.3) Send "PUSH__and__some_text" to send text without having to receive
anything (i.e. proceed to 4.)

3.)  Read data
3.1.) Read "textline" unless PUSH was send
3.1.2) If first "textline" is not "last_textline" abort with an error
3.2.) Repeat from 3.1 until "textline" is the "OVER"
4.) ... do other stuff ...
5.) Goto 2. or send "LOGOUT"

The use of ASCII and stream-sockets was used for its easy of use and
transparency - its not very efficient though for realtime applications that
have to transport a lot of data.

[ compilation and test ]

To compile the source type

Then run

To test, connect to the reflector in (a few) different terminal(s) with
	telnet localhost 1522
and type a few lines.

The program was developed on a RedHat Linux system but should work with
any unix system that provides a pthread implementation.

[ limits and settings ]

The current (compiled-in defaults) are:

Port number		1522
Connections		20
Line Length		128 chars (including newline)
Size of Ringbuffer	1024 lines

Change the defines in the .h files to adjust to your application.

CloneIt (2000)

A Networked Harddisk Replication System


Please note that CloneIt is now completely out-of-date for current hardware and not actively developed for over a decade. For modern hardware your best bet would be to search “The Google” for “Backup with Knoppix”.


The CloneIt system was created to copy and essentially clone harddisks of identical PCs through a network. This is a common task when installing server racks or farms or update a computer-lab setup where one deals with identical machines. The system software consists of a Linux boot floppy and a ramdisk floppy with minimal system utilities that can perform the task of copying the complete content of disk devices through a network.

The CloneIt software is not specific to any operating system, since the raw harddrive is beeing copied. The limitation for the use of CloneIt is, that the hardware used in the cloning procedure has to be identical.

CloneIt can also be used to perform a Backup and Restore of harddisks to and from files using a Linux server. Refer to this document for more information. If you worry about getting the size of your backup files smaller, have a look at this email and the included script.

These disks were prepared for personal use and have not been extensively tested on a variety of platforms – after all its FREE (as in free beer).

Backup HD with CloneIt

Please check this added info and files on how to use CloneIt for Backup purposes.

Kernel and Supported Devices

The distributed boot floppy contains a 2.2.16 vintage kernel with support for the following devices:


  • IDE
  • SCSI

SCSI controller

  • AIC 7xxx
  • BusLogic
  • AdvanSys
  • Tekram DC390
  • Symbios 53c8xx
  • Initio A100U2W
  • Initio 9100U
  • AMI MegaRaid


  • 3COM 3c509
  • 3COM 3c90x
  • ISA NE2000
  • PCI NE2000
  • DEC DC21x4x
  • Intel EtherExpressPro 200
  • VIA Rhine
  • Sis 900/7016

The system has been developed and tested on the following systems:

  • Intel L440GX+ Server board with on-board Adaptec SCSI and Intel EEPro ethernet
  • Asus Athlon/IronGate board with IDE drive and 3COM 905B ethernet card
Usage and Software Notes

The CloneIt software will install itself and run completely from a 4MB ramdisk without mounting any filesystems or interacting in any way with the system harddrives.

During initialization the RedHat configuration tool netconfig is used to setup networking with either a static IP or by performing aDHCP query. To test the networking setup, tools such as ifconfig, route and ping are included.

After the computer is networked, one has to find out the device name of the harddisk or partition to clone. The utility fdisk is provided on the system for querying the partition table. Normally one will clone the /dev/hda (IDE) or /dev/sda (SCSI) devices that should have been detected during startup.

The command alias clone will start up a dialog based script for cloning a device. There are two options at this stage: server and client . One machine will act as a server and is beeing read from – the other is the client and is beeing written to. When server is choosen, the software will provide a network socket to a CloneIt client that will send the complete content of a device (i.e. the harddisk) that can be selected. When client is choosen, one can connect to a give CloneIt server by IP number and write the incoming data to a selected device. The transport programs is implemented using the tools faucet and hose which are part of the netpipes package (ver 4.0). They are not multicast capable but provide point-to-point connections.

To preserve network bandwidth, the transferred data is gzip compressed (in fast mode) when send by the server and decompressed on the client before beeing written to the target device. This allows parallel clone sessions over the same ethernet to be still feasable.

The boot floppy and ramdisk are build using the yard utility (ver 2.0). All software to create these disks is provided – so should the distributed kernel NOT work with your system, try to create a new boto floppy using yard.



Get rootdisk and bootdisk disk image (i.e. choose a rootdisk from the two provided), unpack them using GZIP and copy them to a 1.44MB HD floppy disk using cat file >/dev/fd0 under Linux or using RAWRITE.EXE under DOS. (GZIP.EXE and RAWRITE.EXE are available with most Linux distributions). Then boot the system using the freshly made bootdisk, insert the rootdisk when asked for and follow instructions on the screen after the system has reached the login prompt.

To use CloneIt for Backups:

For advanced users:

To build your own CloneIt disks, use the following set of configuration files for yard (extracts to etc/yard – so extract from root directory AFTER yard was installed).

The following utilities have to be installed as well for the yard build process to work:

libgaudio (2001)

Mixing engine for games as game audio library for multi-voice playback. Licenced under the dual MPL/GPL; see the file sources for details.


[ libgaudio-1.6.tar.gz (596k) ]

[ libgaudio-1.6-samples.tar.gz (5.95M)]


libgaudio  -  Game-Audio Library

(C) A. Schiffler, 1999-2001 under the dual MPL/GPL license. 

Please see source code for details.
Please see the file LICENSE for GPL info.

! Important Note ! 

Since Ver. 1.6 libgaudio usees 'libsoundfile' for all sample loading. 
For more info, see below.


libgaudio is a library to facilitate easy incorporation of sound and sound
effects in games. Samples are loaded into memory and playback is then
triggered or stopped. The system mixes any number of concurrently playing
samples together (up to a predefined maximum). Also possible is the
inclusion of a background MP3 soundfile (external program "mpg123" required).
Since version 1.4 panning and volume control has been added. Since version 1.5
each playing sample can be controlled individually. 

Currently this multithreaded library is set to mix a maximum of 12
concurrent 16bit signed stereo samples at 44100Hz. The included
shell-script will take any file with the extension .wav and convert it into
the proper .raw format used by libgaudio. The total number of samples that
can be loaded is 256. The total size of samples depends on the main memory
of the computer.

System load on my P3-450 is about 4% for the MP3-player and 0.5-4% for
the testaudio application.

See the sample program "testaudio.c" for a demo implementation. Get the
seperatly distributed file "Sample.mp3" (any .mp3 will actually do, but it 
has to be called Sample.mp3 for testaudio.c to use it) and 
activate its playback in the test application by editing the Makefile.

A second sample program called "halloween.c" shows how easy it can be to load
multiple WAV files and play them back at random. This was a great effect during
Halloween night. Start it up with the seperatly distributed "ScarySounds" WAV files
for a cool effect. 🙂

Version History

Ver. 1.0 - Wed Sep 22 14:15:01 CEST 1999
* Initial release.

Ver. 1.1 - Wed Sep 29 16:41:01 CEST 1999
* Changed audio format to 16bit/stereo/44.1KHz
* Added MP3 background-playback function

Ver. 1.2 - Thu Mar  9 12:20:27 CET 2000
* Changed header to include C++ defines
* Moved Sample.mp3 out of the main distribution

Ver. 1.3 - Thu Apr 27 09:47:44 EDT 2000
* Thanks to Karl Robillard  the following additions
  have been included in this version:
  - Added pauseAudio, unpauseAudio, stopAllSamples, and copySample functions.
  - Added audioValid and audioPaused query macros.
  - All functions handle a failed startAudio.
  - Added comments for each function in the source.
  - Added GAUDIO_RATE to header.
  - Renamed tsample/tplaying structures to ga_sample/ga_playing to 
    make the name more unique.
  - playBackground now specifies rate to mpg123 (it sometimes played too fast).
  - Re-wrote testaudio.c to take keyboard input.
* Updated README and testaudio.c

Ver. 1.4 - Sat Jul  8 22:08:19 EDT 2000
* Added stereo panning and volume control support.

Ver. 1.5 - Wed Jul 19 17:39:54 EDT 2000
* Changed licensing to a dual MPL/GPL license.
* Added function to load/copy only left or right channel of a sample (required
  for panning control).
* Added unique playing ID after each playSample() call for better control 
  of individual playing samples.

Ver 1.6 - Tue Dec 12 14:47:11 EST 2000
* Added support for libsndfile (included). 
  No more RAW audio loading required. Any WAV file can be loaded now.
* Added ScarySounds collection (distributed seperately) and halloween.c 
  demo application.
* Added function to query MP3 stream playing time.


Compile and install libsndfile.
	cd libsndfile-0.0.22
	make install
	cd ..

Now, have a look at the comments in the libgaudio Makefile and maybe edit it.

To compile the library use

When the library is to be linked into your program, add 
	-lpthread -D_REENTRANT_ 
for multithreading support plus the libsoundfile library
	-L/usr/local/lib -lsndfile

The MP3 functionality expects the mpg123 player at /usr/bin. 
To restart or queue background MP3s, the main program has to poll the status using 
checkBackground() and restart the MP3 player using playBackground(). libgaudio will
not do this automatically.
Note that the samples have to be using the same rate as libgaudio (default 44.1kHz).

Functions and Procedures

 int startAudio (struct gameaudio *ga, const char *device_name);

* Start gameaudio system: open device (usually /dev/dsp), setup device
parameters, initialize tables, start thread. Returns -1 on error.

 int stopAudio (struct gameaudio *ga);

* Stop gameaudio system: turn of all playing sounds, kill thread, close
device. Returns -1 on error.

 void pauseAudio( struct gameaudio* ga );

* Mutes all audio playback. No return code. 
Check pause-state with the macro audioPaused(ga).

 void unpauseAudio( struct gameaudio* ga );

* Turn off muting of audio playback set by pauseAudio(). No return code.
Check pause-state with the macro audioPaused(ga).

 int loadSample (struct gameaudio *ga, const char *filename);
 int loadSampleLeft (struct gameaudio *ga, const char *filename);
 int loadSampleRight (struct gameaudio *ga, const char *filename);

* Load a (signed 16bit stereo 44100Hz) sample into memory for use with the
gameaudio system. Returns sample id or -1 on error. 

The alternative functions loadSampleLeft() and loadSampleRight() will only load 
the left or the right channel of a stereo file. This function should help in 
creating sample sets from mono wave files that can be panned using the ctrlSample()

Since version 1.6 gaudio uses libsoundfile for sample loading. Several file formats
are supported. For more information on the available formats refer to the 
documentation for libsoundfile. The only restriction to the sample is, that the 
sample-rate must correspond to libgaudio's rate (since no resampling is done) - 
which defaults to 44.1kHz. It is possible to load 8bit or mono samples.

 int copySample( struct gameaudio* ga, void* data, int bytelen );
 int copySampleLeft( struct gameaudio* ga, void* data, int bytelen );
 int copySampleRight( struct gameaudio* ga, void* data, int bytelen );

* Copy a (signed 16bit stereo 44100Hz) sample from a memory location "data"
for use with the gameaudio system. Returns sample id or -1 on error.

The alternative functions copySampleLeft() and copySampleRight() will only copy 
the left or the right channel of a stereo set. This function should help in 
creating sample sets from sets that have equal volume on each channel to ones
that can be panned using the ctrlSample() function.

 int playSample (struct gameaudio *ga, int sample_id, int repeat_count);

* Play sample referenced by id 'repeat_count' times. if the repeat_count is
0 playing will loop forever. The return code is a negative number corresponding
to a unique playing ID or 0 on error. The playing id can be used to control
this instance of the playing sample using ctrlSample() or stopSample().

 void ctrlSample (struct gameaudio *ga, int sample_id, int volume, int pan);

* Change playback parameters of sample with the give id (sample or playing id).
Change volume of playing sound by adjusting volume parameter in the range 0-256. 
Adjust stereo channel panning using the pan variable in the range 0-256.
At a value of 0 (default) the left channel plays left and the right channel
right. At a value of 128 we have center (mono) playback. At a value of
256 the left channel plays right and the right channel plays left.

 void stopSample (struct gameaudio *ga, int sample_id);

* Stop all playing samples with the given id (sample or playing id). No return code.

 void stopAllSamples( struct gameaudio* ga );

* Stop all playing samples (regardless of id). Background audio continues to
play. No return code.

 void playBackground(struct gameaudio *ga, const char *filename);

* Start background playing of a MP3 file given in filename.

 void stopBackground(struct gameaudio *ga);

* Stop currently playing MP3 stream.

 int checkBackground(struct gameaudio *ga);

* Check if the background MP3 stream is playing (1=playing, 0=not playing).

 float timeBackground(struct gameaudio *ga);

* If the background stream is playing, this function will return the time of
playback since start (in seconds) or 0.0 of the stream is not playing.

There are two kinds of ID number used in the library. The sample_id is generated
during the loading (or copying) of a sample into the libgaudio library. It uniquely 
identifies a specific sample and is always a positive number. The playing_id 
is a unique negative number that identifes an instance of a playing sample. Since
the same sample can be triggered for playback several times, each time the
playSample() function will return a different number. Both forms of id can be used
to control a playing sample (as in ctrlSample() or stopSample()). Only the sample_id 
can be used to start a sample for playback (as in playSample()).

To use panning effects, either create stereo wave files with only one channel 
used for the samples or load using the loadSampleLeft()/loadSampleRight() functions.
Then control the pan value using ctrlSample().

See also the comments in the source code (gaudio.c) for even more gory details on 
how its done.


libbgrab (2005)

Easy to use framegrabber library with many demo programs. Licenced under the GPL/MPL, see the files in the archive for details.


[ libbgrab-2.1h.tar.gz (566k)]


[ libbgrab ]

... is an easy to use framegrabber interface library 
with many sample and utility programs ...
(C) A. Schiffler, 1999-2005 under the dual MPL/GPL license. 
Please see source code for details.
Please see the file LICENSE.GPL for GPL info.
Please see the file LICENSE.MPL for MPL info.

[ Introduction ]
[ ------------ ]
libbgrab is a video4linux grabbing library to facilitate easy use of the
brooktree/conexant (bt848/bt878) family of framegrabber cards through
a few function calls. 
To implement constant throughput and to avoid frame loss delays, triple 
buffering is used through local buffer copying in a separate grabbing thread.
The library consists of two parts that are usually used together:
1. framegrabber access (bgrab.c/bgrab.h) 
2. xwindows output (xutils.c/xutils.h)
Additional routines allow for image processing:
3. Motion JPG compression (RTjpeg.c, RTjpeg.h, mmx.h)
4. MMX optimized image filters (asm/*) 

[ Examples and Demo Programs ]
[ -------------------------- ]
Note: All demo programs are hardcoded for Tuner/NTSC input. You have to 
modify the code and recompile for other inputs!
+++ testgrab
See demo program "testgrab" for a quick intro on how to use libbgrab. See
source code comments for additional usage notes. The source code will
probably have to be edited to adapt for your video input - it is just a
demoprogram! Use Q to quit with the live-video window active. Use F and D
to change channels. 

+++ glgrab (GLX only)
A very similar program uses OpenGL as output driver and maps the live 
image as a texture on a polygon - try "glgrab" for nicely scaled, 
full-screen output ... not always at full frame rates ;-). Works fine with
my Matrox G400 and Geforce2MX cards and the GLX drivers.

+++ asciigrab
Also included is a demo "asciigrab" that converts video in realtime into 
ASCII CHARACTERS - just start it in a large enough terminal ... . 
See source code for additional usage notes. This program has actually been
exhibited in the "net_condition" art exhibition at the ZKM, Karlsruhe,
Germany on a big projection screen

+++ delaygrab
A nice example of using MUCH memory, try "delaygrab" in which a few
seconds of video is beeing stored and shown according to a delay-map. If it
runs, try pressing the keys 1, 2 and 3 to switch effects. This effect will
be used in upcoming exhibitions at the ZKM, Karlsruhe, Germany with
temperature sensors. A similar program with a network interface was
developed for the world exhibition Expo2000, Hannover 2000 and can be found
in the "expograb" directory.

+++ zoomgrab (3Dfx Glide only)
Also included is a demo "zoomgrab" that shows a live video image at any
scale using a 3dfx graphics card (required). The numbers in "zoomdef.txt" 
define zoom scales in ONE SECOND intervals (range: 0.01 to 200.0, first 
number in line) and mixer volume settings (range: 0 to 100, second number 
in line) that will be smoothly applied to the image and the volume. See
source code for additional usage notes. This program was also part of an art
exhibition at Weimar, Germany in 1999.

+++ artcam (3Dfx Glide only)
A similar demo called "artcam" also uses glide for display. This demo
changes the colors of an image in realtime using a precalculated 
conversion table.
+++ webcam
And then there is the really complete and useful "webcam" application - see
the README in the /webcam directory for more explanation and usage 
information of this nice little utility.

+++ greydetect
A utility program called "greydetect" makes measurements of the mean
greyscale values in rectangular areas. It can be used for scientific
measurements. See the README in the /greydetect subdirectory for more info
and usage information.

+++ difftrigger
The tool program "difftrigger" can be used as a security or interface 
application to detect changes in images (i.e. from moving objects). 
See the README in the /difftrigger subdirectory for more info and usage 
information. Very similar is the application "tracker". Here the 
difference images can be used to track the motion within a rectangular
area and send it to an external program via TCP/IP.

+++ rgbmix
Yet another art-program is the demo "rgbmix". It uses three framegrabber
inputs to get b/w images and mixes them together into a single RGB color
output image. This might make it into the lobby of a big company someday. 
Any buyers ... 🙂

+++ tracker
Yet another specialized tracking program is "tracker". Again this a program
that was developed for an installation and requires several other utilities
to be useful (asciireflector and reflector2midi). See the local README for 
information on this tool. If you want to see it in action, check the passage
from the Frankfurt Airport Terminal to the Trainstation June-December 2000.
Diagrams of the installation and documentation are included in the /tracker 

+++ rtjpegrecord
+++ rtjpegplay
A new addition to libbgrab for capturing live video is RTjpeg. This library 
works only on MMX capable CPUs and provides fast motion Jpeg compression
routines. The resulting format is NOT compatible with standard MPEG or JPEG
files - i.e. one needs the RTjpeg library to decompress the generated stream.
The sample applications for recording and playback can be found in the /examples
directory. Since the input video format is YUV420 and a color conversion
would be required for standard RGB X-windows screens, no output will be shown
during the recording phase. To record use "rtjpegrecord" - experiment with the 
quality settings for best results. The default setting achieves a 12:1 compression
ration at excellent image quality. To view use "rtjpegplay" on 16bit bpp screens.
See also the README files:

[ Version History ]
[ --------------- ]

See CHANGES file for what has changed.
[ Usage - Step-by-Step Programming Instructions ]
[ --------------------------------------------- ]

1. Define access structure
Define a variable with the "fgdevice" structure and use it as pointer 
to handle all accesses to the framegrabber. 
struct fgdevice fg;

2. Open (and close) the device
Use these calls to open the device. A typical device name is /dev/video
or /dev/video0. 
int fg_open_device (struct fgdevice *fg, char *devicename);
int fg_close_device (struct fgdevice *fg);

3. Get general framegrabber information
Use this optional call to retrieve general info and a channel list of the 
card. This can be helpful in debugging and setup of the card. The
information gets written to "stderr".
int fg_print_info(struct fgdevice *fg); 

4. Setup FPS calculation
Before grabbing, one can set the update interval for frames-per-second
(FPS) calculation. The FPS is the rate of image retrieval using 
fg_get_next_image() call and can be a useful performance parameter. If
"interval" is 100, then every 100 calls to fg_get_next_image() the FPS
number available through fg_get_fps() will be updated. Useful intervalls
are 1-100.
void fg_set_fps_interval(struct fgdevice *fg, int interval);
double fg_get_fps(struct fgdevice *fg);

5. Define the setting and channel values
To configure the framegrabber for different input channels and to
programm the brightness, contrast and color settings use the following
routines. The channel setup is required.
int fg_set_channel(struct fgdevice *fg, int channel, int videomode);
int fg_get_setting(struct fgdevice *fg, int which_setting);
int fg_set_setting(struct fgdevice *fg, int which_setting, int value);
Channel defines are these:
#define CHANNEL_TUNER           0
#define CHANNEL_COMPOSITE       1
#define CHANNEL_SVIDEO          2  
The channel defines can vary from card to card. Please see the output of the
fg_print_info() call for a list of available channel of your card.
Videomode defines are these:
Setting defines are these:
#define SETTING_HUE		1
The value can range from 0 to 32767.
To setup a tuner frequency for TUNER input use these calls:
if (fg_set_frequency (&fg, region, channel)!=0) exit(-1);

6. Start the background grabbing thread
Now you want to initiate grabbing at a specific size and format using the
fg_start_grab_image() call. Grabbing will constantly run in a thread in the
background. All one has to do now in the main program, is to retrieve 
the latest image through the fg_get_next_image() call. The thread can be 
stopped and CPU resources freed, using the fg_stop_grab_image() call. The
thread also stopps when the program terminates.
int fg_start_grab_image (struct fgdevice *fg, int width, int height, int format);
int fg_stop_grab_image (struct fgdevice *fg);
The format settings are:
The widht and height settings are usually limited by the framegrabber. 
Useful values are typically 32 to 800.

7. Get new images and use them
The fg_get_next_image() blocks until a new image is available and returns
the image as a pointer. A pointer to the latest image is also stored in the
fgdevice structure. If the grabbing is not active (i.e. the thread is
not running) the routine returns a NULL pointer.
void * fg_get_next_image(struct fgdevice *fg);
char *curimage;
if (fg_get_next_image(&fg)!=NULL) { 
curimage=(char *)fg.current_image;

8. XWindow output of the images
Normally we want to see the aquired images on the screen. To do that, the
XWindows utility routines can be used.
For following sample code shows how this can be done easily (see also
// Define structure and open window
struct xwinbuffer xwin; 
if (setup_xwinbuffer (&xwin, argv[0], WIDTH, HEIGHT, DEPTH)!=0) exit(-1); 
// ... setup framegrabber ...
// loop: get images and display them 
while (1) {
if (fg_get_next_image(&fg)!=NULL) {
/* Copy image to screenbuffer */
memcpy((char *)xwin.shmimage->data,(char *)fg.current_image,fg.image_size);
/* Draw it */
// Close window
if (close_xwinbuffer(&xwin)!=0) exit(-1);

9. Other features and function
Two tables are initialized within the framegrabber device structure that
allow fast color conversion between the RBG565 color-space and Y8 B/W screen
formats. This can be useful when one grabs greyscale images but want to
display on a 16bit color screen (i.e. the "greydetect" utility program).
unsigned short *y8_to_rgb565;
unsigned char  *rgb565_to_y8; 
To convert a 8bit Y8 value (pixel of a B/W image) to a 16bit RGB pixel:
(unsigned short)outpixel=fg.y8_to_rgb565[(unsigned char)inpixel]
To convert a 16bit RGB pixel to a Y8 value (pixel of a B/W image);
(unsigned char)outpixel=fg.rgb565_to_y8[(unsigned short)inpixel]

[ Compilation and Running the Programs ]
[ ------------------------------------ ]
- Make sure you have the required modules for video input loaded. The
provided "" might be used to load the drivers. It probably
requires customization of tuner type (type=XX) and the card type (card=YY).
Especially the tuner needs optne manual settings.
- The include file "linux/videodev.h" has to be available.
- Create the video devices if they are not alreay there. (Run "cd /dev; 
./MAKEDEV video").  
- Edit the optimization flags setting in the "Makefile". Possible options
are for the Pentium and Athlon CPUs or a general setting (default).
- Optionally install glide libraries if you have a 3Dfx graphics card.
- Run "make clean; make" to compile. 
- Test with "testgrab" (running XWindows at depth 16 weight 565) that can be
found in the ./examples directory.
- If you have a 3Dfx graphics card and the glide libraries installed, run
"make glideprgs" in the ./examples directory. Test with "artcam".
- If you have a 3D graphics card with GL/GLX drivers installed try 
"make glprgs" in the ./examples directory. 
Most demos and testprograms have the video device and framegrabber setup
hardcoded. To get an image, one probably needs to edit the source and 
recompile. Notable exceptions are: "webcam" and "greydetect" with a
command-line interface.
- To install the assembly demos and the tracker application, get NASM and
install it (see below). Then run "make" in the ./asm and ./tracker 

[ xutil - The XWindows utility functions ]
[ -------------------------------------- ]
These functions are added to the bgrab-library to facilitate easy X-Window
creation and use. See sample programs for details.
----- IMPORTANT note on shared memory use ---------------------------------- 
Crucial is the proper closure and removal of the X-Windows shared 
memory segment in the close_xwinbuffer() function. After abnormal program
termination (i.e. programm chashes), one usually has to manually remove 
the shared-memory segment using "ipcs" (to check for the SHM ID) and 
"ipcrm shm ID" (to actually remove the segment).
The best method is to install an exit handler that calls close_xwinbuffer()
and/or quit by user request only, rather than using Ctrl-C or coredumps :-). 

A.) Basic screen setup and drawing routines
int setup_xwinbuffer(struct xwinbuffer *xwin, char *prgname, int width, int height, int depth);
int sync_xwinbuffer(struct xwinbuffer *xwin);
int close_xwinbuffer (struct xwinbuffer *xwin);

B.) Keyboard and Mouse information
int keypoll_xwinbuffer (struct xwinbuffer *xwin, KeySym *key, int *button, int *mousex, *mousey);
See "Examples" section below.

C.) Simple Drawing Commands
void vline (struct xwinbuffer *xwin, int x, int y1, int y2, int color);
void hline (struct xwinbuffer *xwin, int x1, int x2, int y, int color);
void drawchar (struct xwinbuffer *xwin, int x, int y, char c, unsigned int color);
void drawstring (struct xwinbuffer *xwin, int x, int y, char *s, unsigned int color);
void drawpixel(struct xwinbuffer *xwin, int x, int y, unsigned int color);
void drawline(struct xwinbuffer *xwin, int x1, int y1, int x2, int y2, unsigned int color); 

D.) Video mode switching
void videoModeChange(struct xwinbuffer *xwin, int width, int height);
void videoModeReset(struct xwinbuffer *xwin);
To implement keyboard/mouse functionality use the following code fragment.
// Sample keyboard polling
// ...
KeySym key;
int button;
int x,y;
// ...
/* Poll keyboard */
if (keypoll_xwinbuffer (&xwin, &key, &button, &x, &y)) {
/* Check for mouse button press */
if (button) {
printf ("Mouse was pressed at coordinate (%i,%i)\n",x,y);
/* Check for keyboard press +/
switch (key) {
case XK_Home:
case XK_Left:
case XK_Right:
case XK_Up:
case XK_Down:
//     ...
case XK_q:

[ Assembly Image Processing Routines]
Experimental MMX assembly routines for image processing tasks have been
added as of version 2.1. They require the installation of the NASM compiler.
The NASM homepage with links for RPMs and source archives of NASM is here:
Once installed, the documentation for NASM 0.98 can be found here:
To compile the routines use:
make assembly
A demo program that uses the one of the assembly routines is called 
'testabsdiff' and can be compiled within the /examples directory using:
make asmprgs
Another program that relies on the assembly routines is 'tracker'.

[ Bugs & TO-DO List ]
[ ----------------- ]
I've got several 2.2 and 2.3 beta source trees hanging around, but my new 
job doesn't leave me much time. Maybe later ...
- Webcam appliction with support for logging and/or statistics.
- Webcam with multipart-mime support.
- Generic command line setup for all programs.
- Assembly image-transfer routines that do color conversion.


SDL based framegrabber client library with a threaded image capture architecture.





SDL convertion of libbgrab (a framegrabber lib from the same author).

The library uses a separate thread to grab images into a "triple buffer" 
queue independent of an external "game loop". This uses memory bandwidth
but makes it easy to integrate live video into other applications. 
Images are always grabbed at 32bit RGBx resolutions. YUV grabbing is 
currently not implemented. To improve image quality, several deinterlace 
algorithms are available.

This library is licenced under the LGPL, see the file LICENSE for details. 

Supported Platforms

The library compiles and is tested on a Linux target.

Windows will probably never be supported due to the lack of v4l API.
Other SDL platforms might be supported in the future if an API 
similar to v4l is available.

Installation and Test

To compile the library your need the SDL 1.2 installed from source or 
installed with the 'devel' RPM package. For example on Mandrake, run:
	urpmi libSDL1.2-devel

The run
	./	(optional)
	make install

to compile and install the library. The default location for the 
installation is /usr/local/lib and /usr/local/include. The libary 
path /usr/local/lib might need to be added to the file
Then run ldconfig again.

API and Usage

Create a variable of type tSDL_bgrab and reference a pointer to it on every 
library call.

  int bgrabOpen(tSDL_bgrab *bgrab, char *device);

Open framegrabber device. "device" is usually "/dev/video"

void bgrabSetFpsInterval(tSDL_bgrab *bgrab, int interval);

  double bgrabGetFps(tSDL_bgrab *bgrab);

Query internal framerate tracker.

  int bgrabPrintInfo(tSDL_bgrab *bgrab);

Print v4l device info.

  int bgrabGetSetting(tSDL_bgrab *bgrab, int which_setting);
  int bgrabSetSetting(tSDL_bgrab *bgrab, int which_setting, int value);

Get and set device settings (contrast, brightness, etc.). See the SDL_bgrab.h
file for the relevant device for the "which_setting" variable.

  int bgrabSetChannel(tSDL_bgrab *bgrab, int channel, int bgrabmode);

Set the input channel (tuner, svideo, composite) and mode (pal, ntsc, secam)
for your device.

  int bgrabSetFrequency(tSDL_bgrab *bgrab, int region, int index);

Set the tuner frequency (when in tuner mode). See the SDL_bgrab.h file for
region settings.

  int bgrabStart (tSDL_bgrab *bgrab, int width, int height, int bgra);
  int bgrabStop(tSDL_bgrab *bgrab);

Start and stop the grabbing thread. The "width" and "height" parameters define
the size of the 32bit RGB buffer to use. Set the "bgra" flag to 1 for some
cards that store pixels in BGR order.

  int bgrabBlitFramebuffer(tSDL_bgrab *bgrab, SDL_Surface *screen, int deinterlace);

Blit the current franebuffer to a target surface. Set "deinterlace" to a number >1
to enable processing of the frame with various deinterlace algorithms. Use TestVideo
to see the various algorithms at work (and check their CPU usage).

  int bgrabClose(tSDL_bgrab *bgrab);

Close device. Be sure to call bgrabStop() before. 

Quickie Sample Program

SDL_Surface *screen;
tSDL_bgrab bgrab;
int drawing;
// ... open screen ...
bgrabStart (&bgrab, 320, 240, 0);
while (drawing) {
 if (bgrabBlitFramebuffer(&bgrab, screen,  1)) {

Test Program

Change to the ./Test directory and run
to creates a sample TV player. You can check and maybe edit the 
default settings in the source for your device and input.

Best is to see some command line options. Run:
	./TestVideo -help

Use the source code TestVideo.c for some sample code on how to 
create a simple TV viewer in your SDL app.

Development and To-Do

Here is what I'd like to do.

* Implement a YUV mode for the lib.
* Make better use of v4l API capabilities 
  (i,e, when we have >2 mmap buffers, use them).
* Add faster (MMX) deinterlace routines.
* Add some other image-improvement and -modification 
  algorithms (greyscale, sharpen, soften, temporal smooth, etc.).


Thanks to 'AppWares Development Group' for supporting this project - please 
visit for more information.


* None so far. Want to be the first one ...??? Get coding!



SDL based VNC client library with a threaded renderer.

Current Development


SDL_vnc-1.0.0.tar.gz  (old)



The SDL_vnc library was created to offer a VNC client system that:
- is LGPL licensed and can be used in commercial applications
- integrates with SDL (framebuffer is a SDL surface)
- IO and processing runs as a thread, so it does not interfere 
  with a traditional "game loop"

Supported Platforms

The library compiles and is tested on a Linux target with a
TightVNC server running on windows.

Installation and Test

To compile the library your need the SDL 1.2 installed from source or 
installed with the 'devel' RPM package. For example on Mandrake, run:
	urpmi libSDL1.2-devel

The run
	./	(optional)
	make install

to compile and install the library. The default location for the 
installation is /usr/local/lib and /usr/local/include. The libary 
path /usr/local/lib might need to be added to the file
Then run ldconfig again.

API and Usage

int vncConnect(tSDL_vnc *vnc, char *host, int port, char *mode, 
               char *password, int framerate);

  Connect to VNC server 

   vnc  = pointer to tSDL_vnc structure
   host = hostname or hostip
   port = port
   mode = submode,submode,...
    submode =	raw | 
    		copyrect | 
    		rre | 
    		corre(broken) |
    		hextile | 
    		zrle(unimplemented) | 
    		cursor | 
   password = text
   framerate = 1 to 100

   - Returns 1 if connection was established, 0 otherwise.
   - This call will establish a connection to the VNC server requesting 
     a 32bit transfer.
   - framerate is the rate in which update requests are send to the server.

int vncBlitFramebuffer(tSDL_vnc *vnc, SDL_Surface *target, SDL_Rect *urec);

 Blit current framebuffer to target

  vnc = pointer to tSDL_vnc structure
  target = target surface to blit framebuffer to
  urec = pointer to SDL_Rect structure to receive updated area, can be NULL

   - Returns 1 if the blit occured, 0 otherwise.
   - Only blits if framebuffer exists and was updated. 
   - Updated region is stored in urec if it is not NULL.
   - Framebuffer is a RGB surface.

int vncBlitCursor(tSDL_vnc *vnc, SDL_Surface *target, SDL_Rect *trec);

  Blit current cursor to target

   vnc = pointer to tSDL_vnc structure
   target = target surface to blit cursoe to
   trec = pointer to SDL_Rect structure to receive updated area, can be NULL
   - Returns 1 if blit occured, 0 otherwise 
   - Blitting is at the trec position.
   - Cursor image is a 32x32 RGBA image (with A set).

SDL_Rect vncCursorHotspot(tSDL_vnc *vnc);

  Return cursor hotspot location

   vnc = pointer to tSDL_vnc structure

   - In the returned parameter, only .x and .y are used.

int vncClientKeyevent(tSDL_vnc *vnc, unsigned char downflag, unsigned int key);
int vncClientPointerevent(tSDL_vnc *vnc, unsigned char buttonmask, 
                          unsigned short x, unsigned short y);

  Send keyboard and pointer events to server

   vnc = pointer to tSDL_vnc structure
   downflag = 1 for key is down, 0 for key is up
   key = VNC keycode (basically X11/keysymdef.h plus some special codes)
   buttonmask = VNC mousebutton bitmask 1=left, 2-=middle, 4=right, 8/16=wheel
   x,y = mouse position

   - The client is responsible for key-code conversions into the VNC format.

void vncDisconnect(tSDL_vnc *vnc);

  Disconnect from vnc server

   vnc = pointer to tSDL_vnc structure

   - Closes socket connection and kills client thread. 

Test Program

Change to the ./Test directory and run
to creates a VNC client program. Run
	./TestVNC -help

Typically one connects to a VNC server like this:

	./TestVNC -server myserver -password mypass

Also see the source code TestVNC.c for sample code on how to 
create a simple VNC client.

Development and To-Do

One can edit the SDL_vnc.c code to enable extensive debugging by setting the
DEBUG flag.

- Add function to query server framebuffer size after connect.
- Fix CoRRE code
- Implement Desktop pseudoencoding
- Implement Bell (as callback)
- Implement ClientCutText
- Implement ZRLE protocol
- Implement tight protocol and options (zlib,tight,zlibhex)
  (Anyone have the specs for this?)
- Improved speed and interactive response
  (Implement a threaded socket reader. Check all code for optimizations.)
  ('vncviewer' feels a lot faster and more interactive.)
- Create proper SDL_keysym --> VNC key conversion routine.
- Add local-cursor sample code to TestVNC program.


Thanks to 'AppWares Development Group' for supporting this project - please 
visit for more information.


Historical Code
Tagged on:                         

Leave a Reply

Your email address will not be published. Required fields are marked *