aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changes72
-rw-r--r--Channelmaps/README2
-rw-r--r--Makefile.in23
-rw-r--r--README72
-rw-r--r--Trouble-Shooting123
-rw-r--r--Xawtv.ad26
-rw-r--r--acconfig.h7
-rw-r--r--bttv/MAKEDEV4
-rw-r--r--bttv/MODULES5
-rw-r--r--bttv/Makefile3
-rw-r--r--bttv/bttv.c68
-rw-r--r--bttv/bttv.h2
-rw-r--r--bttv/i2c.c13
-rw-r--r--bttv/i2c.h13
-rw-r--r--bttv/i2c_chardev.c309
-rw-r--r--bttv/linux-2.0.33.diff10
-rw-r--r--bttv/msp3400.c400
-rw-r--r--bttv/msp3400.h5
-rw-r--r--bttv/nicam106
-rw-r--r--bttv/tuner.c2
-rw-r--r--bttv/update21
-rw-r--r--bttv/videodev.c29
-rw-r--r--bttv/videodev.h34
-rw-r--r--chan.h59
-rw-r--r--chan2c.pl50
-rw-r--r--channel.c295
-rw-r--r--channel.h14
-rw-r--r--channels.h106
-rw-r--r--config.h.in9
-rwxr-xr-xconfigure275
-rw-r--r--configure.in51
-rw-r--r--dump-mixers.c66
-rw-r--r--grab-bttv.c286
-rw-r--r--grab-v4l.c143
-rw-r--r--grab.h6
-rw-r--r--grabber-video4linux.cc474
-rw-r--r--kradio.cpp10
-rw-r--r--main.c370
-rw-r--r--radio.c8
-rw-r--r--set-tv.c21
-rw-r--r--v4l-conf.c14
-rw-r--r--vtx/.vtx.o.flags3
-rw-r--r--vtx/Makefile75
-rw-r--r--vtx/README44
-rw-r--r--vtx/VideoteXt-0.6-patch11
-rw-r--r--vtx/i2c.h165
-rw-r--r--vtx/vtx.c759
-rw-r--r--vtx/vtx.h128
-rw-r--r--x11.c224
-rw-r--r--x11.h8
-rw-r--r--xawtv.man34
51 files changed, 4098 insertions, 959 deletions
diff --git a/Changes b/Changes
new file mode 100644
index 0000000..30d047e
--- /dev/null
+++ b/Changes
@@ -0,0 +1,72 @@
+2.07 => 2.08
+============
+
+ * Ha! Found a complete (?) frequency table on the web, using this
+ one now (and a complete different channel-to-freqency mapping
+ method).
+ Expect a few new bugs and tuning problems -- pointers to frequency
+ lists are welcome. Check channels.h for details.
+ The names of the freqency mappings have changed, you have to
+ adopt $HOME/.xawtv
+
+ * fixed a bug in the msp3400 module (system hangs on control
+ thread kill)
+ * With the 2.1.x modular sound driver, the msp3400 module registers
+ as mixer device. This allows to control volume, bass and treble with
+ a mixer application of your choice.
+ * the config file parser prints more detailed error messages and
+ does not exit on errors.
+ * Added a workaround for buggy (wrt static gravity) Window managers,
+ see manpage (wm-off-by= ...)
+ * Started non-overlay displaying (try Shift-ESC). Not completed, not
+ stable yet.
+ * Changed v4l-conf handling: It is installed suid-root now and called
+ by xawtv.
+
+
+2.06 => 2.07
+============
+
+ * Two hours after releasing 2.06 I noticed that the driver did'nt
+ compile with 2.0.33 :-(
+
+
+2.05 => 2.06
+============
+
+ * You can grab both full size and window size now (hold down Ctrl
+ for window size).
+ * Merged some of the latest vger CVS changes to bttv-0.5.6 to keep
+ both versions in sync (at least the ioctl interface). The included
+ driver version supports currently both the new
+ VIDIOCMCAPTURE+VIDIOCSYNC and old BTTV_GRAB+BTTV_SYNC. xawtv uses
+ the new ones.
+ The minor numbers for vbi have changed (from 32 to 224)
+ * hacked msp3400 stereo handling, it does permanent monitoring now
+ and should handle mono/stereo/bilang switches by the TV station
+ correctly.
+
+
+2.04 => 2.05
+============
+
+ * Started writing a Changes file
+ * fixed a quite stupid getopt bug
+ * ditched support for the old-style bttv interface.
+ * The screen saver is turned off now in fullscreen mode
+ * xawtv can switch video modes now (for fullscreen mode). There is
+ a new config file entry for this, check the manpage.
+ * fixed configure script (check for c++ only if required)
+
+ * For the bleeding edge people:
+
+ Added some code for the new VIDIOCMCAPTURE and VIDIOCSYNC ioctl's
+ (new video4linux code in the vger CVS tree) as compile time
+ option. The configure script should detect the new version and
+ use the kernel driver then.
+
+ The ioctl's are'n really new, the are basically slightly modified
+ BTTV_GRAB and BTTV_SYNC. Well, this change breaks _again_ grabbing
+ applications, but now there is a standardized interface for
+ mmap-based grabbing available.
+
diff --git a/Channelmaps/README b/Channelmaps/README
new file mode 100644
index 0000000..c5ad250
--- /dev/null
+++ b/Channelmaps/README
@@ -0,0 +1,2 @@
+This is obsolete now, check channels.h and the huge table
+at the bottom of channel.c
diff --git a/Makefile.in b/Makefile.in
index d4e4e32..fbc9e4d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -6,7 +6,6 @@ prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=$(exec_prefix)/bin
-sbindir=$(exec_prefix)/sbin
mandir=$(prefix)/man
kdebindir=$(KDEDIR)/bin
@@ -27,7 +26,7 @@ CXXFLAGS = $(CFLAGS) -I$(QTDIR)/include -I$(KDEDIR)/include
LDLIBS=@X_LIBS@ -l@XAWLIB@ -lXt @X_PRE_LIBS@ -lXext -lXmu \
-lX11 @X_EXTRA_LIBS@ @LIBS@
-PROGS=xawtv v4l-conf radio set-tv @KRADIO@
+PROGS=xawtv v4l-conf set-tv dump-mixers radio @KRADIO@
CHAN_SRCS= $(shell echo Channelmaps/*.chan)
SRCS= $(srcdir)/main.c\
@@ -35,10 +34,8 @@ SRCS= $(srcdir)/main.c\
$(srcdir)/mixer.c\
$(srcdir)/channel.c\
$(srcdir)/x11.c\
- $(srcdir)/grab-bttv.c\
$(srcdir)/grab-v4l.c
-OBJS= main.o toolbox.o mixer.o channel.o x11.o\
- grab-bttv.o grab-v4l.o
+OBJS= main.o toolbox.o mixer.o channel.o x11.o grab-v4l.o
##########################################################################
@@ -63,7 +60,10 @@ v4l-conf: v4l-conf.c
radio: radio.c
$(CC) $(CFLAGS) -o $@ $<
-set-tv: set-tv.o channel.o mixer.o grab-bttv.o grab-v4l.o
+dump-mixers: dump-mixers.c
+ $(CC) $(CFLAGS) -o $@ $<
+
+set-tv: set-tv.o channel.o mixer.o grab-v4l.o
$(CC) $(CFLAGS) -o $@ $^
@@ -72,10 +72,10 @@ kradio: kradio.moc kradio.o
-lkdeui -lkdecore -lqt @X_PRE_LIBS@ -lXext -lX11 @X_EXTRA_LIBS@
-install: xawtv
+install: all
$(INSTALL_PROGRAM) -s xawtv $(bindir)
$(INSTALL_PROGRAM) -s set-tv $(bindir)
- $(INSTALL_PROGRAM) -s v4l-conf $(sbindir)
+ $(INSTALL_PROGRAM) -s -m4711 -o root -g root v4l-conf $(bindir)
$(INSTALL_DATA) xawtv.man $(mandir)/man1/xawtv.1
$(INSTALL_DATA) Xawtv.ad @x_libraries@/X11/app-defaults/Xawtv
if test -x kradio; then \
@@ -83,11 +83,9 @@ install: xawtv
$(INSTALL_DATA) *.kdelnk $(kdelnkdir); \
$(INSTALL_DIR) $(kradiodir)/toolbar; \
$(INSTALL_DATA) *.xpm $(kradiodir)/toolbar; \
+ make -C font install; \
fi
-chan.h: $(CHAN_SRCS)
- perl chan2c.pl $(CHAN_SRCS) > $@
-
clean:
-rm -f *.o *.moc *~ core* *.bak TAGS
@@ -101,7 +99,7 @@ realclean: distclean
-rm -f chan.h
-rm -f $(PROGS)
-depend dep: chan.h
+depend dep:
$(DEPEND) -- $(CFLAGS) -- $(SRCS) $(SRCS2)
#########################
@@ -115,6 +113,7 @@ check:
dist: distclean
rm -f snap0*.ppm
+ rm -f snap0*.jpeg
make -C bttv clean
make -C font dist
dir=`pwd`; rel=`basename $$dir`; cd ..; tar cvzf $$rel.tar.gz $$rel
diff --git a/README b/README
index e2ea71d..b6a6ad3 100644
--- a/README
+++ b/README
@@ -9,21 +9,17 @@ video4linux (included in 2.1.7x). Copy Policy is GNU GPL.
compile & install
=================
-The bttv "old-style interface" support is still present, but untested
-and probably will go away over time...
-Disabled now, as it does'nt compile with the current bttv driver. You
-have to do some Makefile hacking to compile it. Or simply stay with a
-older version, if you don't want to use the new driver for some reason.
+There is modified bttv-0.5.6 in the bttv subdirectory. Only the
+driver itself is included. If you use the bttv for the first time, I
+recommend to get the whole bttv package from Ralph's page (see below)
+and check out the documentation. Some (very limited) informations can
+be found in the bttv/MODULES file.
-The video4linux interface is backported to 2.0.x, new bttv releases
-support the new video4linux interface only. Grabbing does'nt work
-yet.
-
-
-There is bttv-0.5.6 (with minor msp3400 changes wrt nicam) in the bttv
-subdirectory. Only the driver itself is included. If you use the bttv
-for the first time, I recommend to get the whole bttv package from
-Ralph's page (see below) and check out the documentation.
+I merged the latest video4linux changes from the vger CVS tree to the
+bttv driver. This xawtv version does _not_ work (read: the included
+binary can't grab and it does'nt compile) with plain bttv-0.5.6, you
+need either the included version or the latest video4linux bits from
+vger's CVS tree. Check also the Changes file.
$ ./configure --with-bttv=/path/to/bttv/driver && make
@@ -50,18 +46,8 @@ problem probably will be solved in a better way later on (Alan plans
to write a X-Server extention). Try "v4l-conf -h" for a short
description.
-The easiest way to make this work is to compile the driver as
-module, let kerneld load it and run v4l-conf via post-install. My
-module settings look like this:
-
-$ grep bttv /etc/modules.conf
-alias char-major-81 bttv
-post-install bttv /usr/local/sbin/v4l-conf -q
-
-This might require a "xhost +localhost", becauce v4l-conf must be able
-to contact your X-Server. You could also install v4l-conf suid-root
-and write a small wrapper script for xawtv. It's up to you, there are
-many ways to solve the puzzle...
+It is installed suid-root now, and xawtv runs it at startup. Should
+work out-of-the-box without extra configuration.
xawtv
@@ -89,17 +75,34 @@ set-tv
Simple command line tuner. Reads like xawtv the config file $HOME/.xawtv.
Expects a channel name on the command line. Assuming you have a station
named [ZDF] in your $HOME/.xawtv file, "set-tv zdf" will tune in the
-channel defined there. Prints some useless messages about video resolution
-due to the fact that it shares alot of code with xawtv, maybe I fix this
-later.
+channel defined there. That way you can tune in a station to grab
+teletext (or whatever) without starting up X11.
+
+It prints some useless messages about video resolution due to the fact that
+it shares alot of code with xawtv, maybe I fix this later.
+
+
+dump-mixers
+-----------
+
+Just does what the name suggests: It simply dumps the current mixer
+settings to stdout.
vic
---
-The grabber-bttv-0.5.6.cc file is a grabber driver for vic. If you plan
-to compile vic: It is'nt trivial, you should have some basic knowledge
-about C and writing/editing Makefiles.
+The grabber-bttv-0.5.6.cc file is a grabber driver for vic, works with
+plain bttv-0.5.6. Up to 12 fps.
+
+There is newer version, grabber-video4linux.cc. Requires the included
+modified bttv version or a kernel >= 2.1.94. Handles up to 25 fps.
+
+Both versions are tested only with PAL. The "large" picture size probably
+doest'nt work with NTSC.
+
+If you plan to compile vic: It is'nt trivial, you should have some
+basic knowledge about C and writing/editing Makefiles.
radio & kradio
@@ -122,8 +125,9 @@ set correctly. Yes, the volume slider does'nt work yet.
resources
=========
-http://www.cs.tu-berlin.de/~kraxel/linux/#xawtv - xawtv
-http://www.thp.uni-koeln.de/~rjkm/linux/bttv.html - bttv driver
+http://www.cs.tu-berlin.de/~kraxel/linux/#xawtv - xawtv [me]
+http://www.thp.uni-koeln.de/~rjkm/linux/bttv.html - bttv driver [Ralph]
+http://roadrunner.swansea.linux.org.uk/v4l.shtml - video4linux [Alan]
http://www-nrg.ee.lbl.gov/vic/ - vic
http://www.kde.org - KDE
diff --git a/Trouble-Shooting b/Trouble-Shooting
new file mode 100644
index 0000000..e89b398
--- /dev/null
+++ b/Trouble-Shooting
@@ -0,0 +1,123 @@
+
+Here are a few hints if you have trouble to make bttv work:
+
+
+general
+=======
+
+* Check the PROBLEMS file in Ralph's bttv Documentation
+
+* There are a few known incompatibilities, see below.
+
+* The insmod options for the modules are documented in the
+ MODULES file. Use the "verbose=" and "debug=" args to make
+ the modules more verbose.
+
+* Just in case you don't know: With the "dmesg" command you can
+ display the (last 4k of) kernel/module messages.
+
+* Try a newer version of the X-Server (if available).
+
+
+video
+=====
+
+* Make sure capture is turned on (xtvscreen starts up with capture
+ off)
+
+* Black screen, no picture at all: Bad, probably the video frame buffer
+ address is wrong.
+ The bttv module has a vidmem= argument, so you can pass the correct one.
+ xawtv should print it (if the X-Server supports DGA), you can check the
+ X-Server startup messages and /proc/pci too.
+
+* Black screen after some time of normal operation: try to reload the
+ bttv module.
+
+* Blue Screen: That's what you get if there is no input signal
+ (Composite1 and no input source connected, sometimes happens with
+ the wrong tuner type too). The Blue Screen already comes from
+ the Grabber card, so the interaction between Grabber and Graphics
+ board already works fine.
+
+* noisy, sort-of-white screen: There is no TV Station tuned in.
+ Possible reasons:
+ - There is really no station present on that channel...
+ - tuner module not loaded
+ - Wrong tuner type. You can set the tuner type with the "type="
+ insmod argument of the tuner module, see the MODULES file for
+ details.
+ - Wrong channel map (the channel-to-freqency mapping is
+ different in different countries)
+
+* Trouble with TrueColor mode: It's impossible to find what color depth
+ the X-Server uses internally, you might have to use the -b switch to
+ tell if it runs 24 or 32 bpp. Both xawtv and v4l-conf have this switch.
+
+
+sound
+=====
+
+* it might be nessesary to initialize the sound card with a
+ "insmod sound" to get sound at all.
+
+* With stereo cards you need the msp3400 module.
+
+ There is some trouble with the MIRO cards: They can do both
+ mono (without msp3400 chip) & stereo (using msp3400), but nobody
+ knows how to kick them into stereo mode.
+ Result: it works even without msp3400, but loading the msp3400
+ does'nt give stereo sound...
+
+* For radio support (WinTV/Radio) you have to do "insmod radio=1"
+
+
+if it still does'nt work... -- hardware problems/conflicts
+============================================================
+
+* As far I know, the bttv driver can't do IRQ sharing, make sure it
+ has its own interrupt.
+
+* There are reports that the tuner works only if the *graphic board*
+ has its own IRQ. Don't ask me why...
+
+* Sometimes there are memory conflicts beetween bttv and some other
+ card. With the remap insmod option of the bttv module you can move
+ the memory of the bt848 chip to some other place.
+
+* If you have to boot Win95 first to make the grabber board work, you
+ might want to save /proc/pci before and after running Win95 and look
+ for changes to track the problem down.
+
+* /proc/pci, /proc/interrupts and /proc/ioports are your friends...
+
+
+Known incompatibilities
+=======================
+
+[Alan on linux-kernel]
+
+o Some SiS boards it doesnt work on. I don't know if it works on
+ the new SiS socket 7 stuff (5598 etc) but I'd like to know
+
+o S3 video cards it flickers when windows are scrolling etc. Windows
+ & Linux. You cant DMA video to an S3 while it is using the onboard
+ accelerator
+
+o Lot of noise with 3c59x ethernet. Caused by the latency for the
+ 3c59x having to be really high to avoid a silicon bug.
+
+[Ralph, see also his PROBLEMS file]
+
+o Some S3 cards (mostly Trio 64) don't work with XFree (but with
+ AccelX).
+
+
+
+More hints/suggestions/corrections/updates are welcome,
+
+ Gerd
+
+
+--
+Gerd Knorr <kraxel@cs.tu-berlin.de>
diff --git a/Xawtv.ad b/Xawtv.ad
index b85db4f..30066c8 100644
--- a/Xawtv.ad
+++ b/Xawtv.ad
@@ -1,4 +1,3 @@
-
! ----------------------------------------------------------------------------
! general settings
@@ -33,6 +32,7 @@ Xawtv*lang2.label: Language 2
Xawtv*menu.translations: #override \n\
<Motion>: highlight()
+
! ----------------------------------------------------------------------------
! TV Window
@@ -44,6 +44,7 @@ xawtv.translations: #override \n\
xawtv.tv.background: black
xawtv.tv.translations: #override \n\
+ Shift<Key>Escape: GrabDisplay() \n\
<Key>0: SetRes(audio,0) \n\
<Key>1: SetRes(audio,1) \n\
<Key>2: SetRes(audio,2) \n\
@@ -70,8 +71,10 @@ xawtv.tv.translations: #override \n\
<Key>A: Volume(mute) \n\
<Key>M: Pointer() \n\
<Key>F: FullScreen() \n\
- <Key>G: Snap(ppm) \n\
- <Key>J: Snap(jpeg) \n\
+ Ctrl<Key>G: Snap(ppm,win) \n\
+ Ctrl<Key>J: Snap(jpeg,win) \n\
+ <Key>G: Snap(ppm,full) \n\
+ <Key>J: Snap(jpeg,full) \n\
<Key>Up: Tune(next) \n\
<Key>Down: Tune(prev) \n\
<Key>Right: Tune(fine_up) \n\
@@ -84,10 +87,11 @@ xawtv.tv.translations: #override \n\
! ----------------------------------------------------------------------------
! Options window
-Options.Paned.internalBorderWidth: 0
-Options*Scrollbar*orientation: horizontal
-Options*Scrollbar*length: 120
-Options*Scrollbar*minimumThumb: 3
+Options.paned.internalBorderWidth: 0
+Options.paned*Scrollbar.orientation: horizontal
+Options.paned*Scrollbar.length: 120
+Options.paned*Scrollbar.width: 120
+Options.paned*Scrollbar.minimumThumb: 3
Options.translations: #override \n\
<Message>WM_PROTOCOLS: Options()
@@ -108,8 +112,10 @@ Options.paned.translations: #override\n\
<Key>A: Volume(mute) \n\
<Key>M: Pointer() \n\
<Key>F: FullScreen() \n\
- <Key>G: Snap(ppm) \n\
- <Key>J: Snap(jpeg) \n\
+ Ctrl<Key>G: Snap(ppm,win) \n\
+ Ctrl<Key>J: Snap(jpeg,win) \n\
+ <Key>G: Snap(ppm,full) \n\
+ <Key>J: Snap(jpeg,full) \n\
<Key>Up: Tune(next) \n\
<Key>Down: Tune(prev) \n\
<Key>Right: Tune(fine_up) \n\
@@ -118,3 +124,5 @@ Options.paned.translations: #override\n\
<Key>Page_Down: SetChannel(prev) \n\
<Key>V: SetRes(capture,toggle)
+
+! ----------------------------------------------------------------------------
diff --git a/acconfig.h b/acconfig.h
index 45a9191..35c5622 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -1,2 +1,5 @@
-/* bttv driver */
-#undef HAVE_BTTV
+/* use kernel include (videodev.h) */
+#undef USE_KERNEL_VIDEODEV
+
+/* MIT shared memory extention */
+#undef HAVE_MITSHM
diff --git a/bttv/MAKEDEV b/bttv/MAKEDEV
index de69d2d..e148eef 100644
--- a/bttv/MAKEDEV
+++ b/bttv/MAKEDEV
@@ -11,8 +11,8 @@ mknod /dev/bttv2 c 81 2
mknod /dev/bttv3 c 81 3
# videotext
-mknod /dev/bttv-vbi0 c 81 32
-mknod /dev/bttv-vbi1 c 81 33
+mknod /dev/bttv-vbi0 c 81 224
+mknod /dev/bttv-vbi1 c 81 225
# radio
mknod /dev/bttv-fm0 c 81 64
diff --git a/bttv/MODULES b/bttv/MODULES
index 2ab1382..161e68b 100644
--- a/bttv/MODULES
+++ b/bttv/MODULES
@@ -54,3 +54,8 @@ tuner.o
You can't load the i2c chip driver modules (tuner,msp3400) with kerneld,
you should modprobe them within a boot script.
+NEW: Well, you can't without a kernel patch. There is a tiny kernel patch
+ for 2.0.33. With the request_module() in bttv.c enabled (you have to
+ change a "#if 0" to "#if 1" at the end of bttv.c) and a patched kernel
+ loading _all_ the modules on demand works just fine.
+
diff --git a/bttv/Makefile b/bttv/Makefile
index 48867fa..62fa894 100644
--- a/bttv/Makefile
+++ b/bttv/Makefile
@@ -30,6 +30,7 @@ CURRENT=$(shell uname -r)
# where the kernel sources are located
#KERNEL_LOCATION=/usr/src/kernel/$(CURRENT)
+#KERNEL_LOCATION=/usr/src/kernel/vger
KERNEL_LOCATION=/usr/src/linux
@@ -37,7 +38,7 @@ KERNEL_LOCATION=/usr/src/linux
# some magic for using linux kernel settings
# when compiling module(s)
-M_OBJS = bttv.o i2c.o msp3400.o tuner.o videodev.o
+M_OBJS = bttv.o i2c.o msp3400.o tuner.o videodev.o #i2c_chardev.o
EXTRA_CFLAGS = -DTUNER_DEFAULT=$(TUNER) -DCARD_DEFAULT=$(CARD) \
-DBTTV_MAJOR=$(BTTV_MAJOR) $(INTERFACE) -DEXPORT_SYMTAB
diff --git a/bttv/bttv.c b/bttv/bttv.c
index 9abaec7..e29c857 100644
--- a/bttv/bttv.c
+++ b/bttv/bttv.c
@@ -1157,8 +1157,13 @@ vgrab(struct bttv *btv, struct gbuf *gb)
//bt848_set_risc_jmps(btv);
btor(3, BT848_CAP_CTL);
btor(3, BT848_GPIO_DMA_CTL);
- btv->gro=virt_to_bus(ro);
- btv->gre=virt_to_bus(re);
+ if (btv->grabbing) {
+ btv->gro_next=virt_to_bus(ro);
+ btv->gre_next=virt_to_bus(re);
+ } else {
+ btv->gro=virt_to_bus(ro);
+ btv->gre=virt_to_bus(re);
+ }
if (!(btv->grabbing++))
btv->risc_jmp[12]=BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ;
//interruptible_sleep_on(&btv->capq);
@@ -1299,6 +1304,8 @@ static int bttv_open(struct video_device *dev, int flags)
btv->user--;
return -EINVAL;
}
+ btv->grab=0;
+ btv->lastgrab=0;
break;
case 1:
break;
@@ -1936,12 +1943,20 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
v.flags|=VIDEO_AUDIO_MUTABLE;
strcpy(v.name,"TV");
if (btv->have_msp3400) {
- v.flags|=VIDEO_AUDIO_VOLUME;
+ v.flags|=VIDEO_AUDIO_VOLUME |
+ VIDEO_AUDIO_BASS |
+ VIDEO_AUDIO_TREBLE;
i2c_control_device(&(btv->i2c),
I2C_DRIVERID_MSP3400,
MSP_GET_VOLUME,&(v.volume));
i2c_control_device(&(btv->i2c),
I2C_DRIVERID_MSP3400,
+ MSP_GET_BASS,&(v.bass));
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_MSP3400,
+ MSP_GET_TREBLE,&(v.treble));
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_MSP3400,
MSP_GET_STEREO,&(v.mode));
} else
v.mode = VIDEO_SOUND_MONO;
@@ -1967,6 +1982,12 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
MSP_SET_VOLUME,&(v.volume));
i2c_control_device(&(btv->i2c),
I2C_DRIVERID_MSP3400,
+ MSP_SET_BASS,&(v.bass));
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_MSP3400,
+ MSP_SET_TREBLE,&(v.treble));
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_MSP3400,
MSP_SET_STEREO,&(v.mode));
}
btv->audio_dev=v;
@@ -1984,10 +2005,11 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
if(copy_to_user((void *) arg, (void *) eedata, 256))
return -EFAULT;
break;
+ case VIDIOCSYNC:
case BTTV_SYNC:
- if (btv->grabbing && btv->grab==btv->lastgrab)
- interruptible_sleep_on(&btv->capq);
- btv->lastgrab=btv->grab;
+ if (btv->grabbing && btv->lastgrab == btv->grab)
+ interruptible_sleep_on(&btv->capq);
+ btv->lastgrab++;
break;
case BTTV_GRAB:
{
@@ -1995,6 +2017,19 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
copy_from_user((void *) &gb, (void *) arg, sizeof(gb));
return vgrab(btv, &gb);
}
+ case VIDIOCMCAPTURE:
+ {
+ struct video_mmap vm;
+ struct gbuf gb;
+
+ if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm)))
+ return -EFAULT;
+ gb.adr = vm.frame ? 0x144000 : 0;
+ gb.fmt = vm.format; /* FIXME */
+ gb.width = vm.width;
+ gb.height = vm.height;
+ return vgrab(btv, &gb);
+ }
default:
return -ENOIOCTLCMD;
}
@@ -2706,16 +2741,16 @@ static int init_bt848(int i)
memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template));
idcard(btv);
- if(video_register_device(&btv->video_dev,0)<0)
+ if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0)
return -1;
- if(video_register_device(&btv->vbi_dev,32)<0)
+ if(video_register_device(&btv->vbi_dev,VFL_TYPE_VBI)<0)
{
video_unregister_device(&btv->video_dev);
return -1;
}
if (radio)
{
- if(video_register_device(&btv->radio_dev,64)<0)
+ if(video_register_device(&btv->radio_dev,VFL_TYPE_RADIO)<0)
{
video_unregister_device(&btv->vbi_dev);
video_unregister_device(&btv->video_dev);
@@ -2786,10 +2821,10 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
/* captured full frame */
if (stat&(2<<28))
{
- btv->grab++;
- wake_up_interruptible(&btv->capq);
if ((--btv->grabbing))
{
+ btv->gro = btv->gro_next;
+ btv->gre = btv->gre_next;
btv->risc_jmp[5]=btv->gro;
btv->risc_jmp[11]=btv->gre;
bt848_set_geo(btv, btv->gwidth,
@@ -2801,9 +2836,11 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
btv->win.height,
btv->win.color_fmt);
}
+ btv->grab++;
+ wake_up_interruptible(&btv->capq);
break;
}
- if (stat&(8<<28))
+ if (stat&(8<<28))
{
btv->risc_jmp[5]=btv->gro;
btv->risc_jmp[11]=btv->gre;
@@ -3062,6 +3099,13 @@ int init_bttv_cards(struct video_init *unused)
return -EIO;
}
}
+
+#if 0
+ /* load i2c chip drivers (requires a tiny patch for 2.0.x) */
+ request_module("tuner");
+ request_module("msp3400");
+#endif
+
return 0;
}
diff --git a/bttv/bttv.h b/bttv/bttv.h
index 6e76a2b..a7f1fcd 100644
--- a/bttv/bttv.h
+++ b/bttv/bttv.h
@@ -148,6 +148,8 @@ struct bttv {
dword *grisc;
ulong gro;
ulong gre;
+ ulong gro_next;
+ ulong gre_next;
char *fbuffer;
int gmode;
int grabbing;
diff --git a/bttv/i2c.c b/bttv/i2c.c
index 79fd915..7d019ad 100644
--- a/bttv/i2c.c
+++ b/bttv/i2c.c
@@ -153,9 +153,10 @@ int i2c_register_bus(struct i2c_bus *bus)
bus_count++;
REGPRINT(printk("i2c: bus registered: %s\n",bus->name));
+ LOCK_I2C_BUS(bus);
+ i2c_reset(bus);
if (scan) {
/* scan whole i2c bus */
- LOCK_I2C_BUS(bus);
for (i = 0; i < 256; i+=2) {
i2c_start(bus);
ack = i2c_sendbyte(bus,i,0);
@@ -165,8 +166,8 @@ int i2c_register_bus(struct i2c_bus *bus)
bus->name,i);
}
}
- UNLOCK_I2C_BUS(bus);
}
+ UNLOCK_I2C_BUS(bus);
/* probe available drivers */
for (i = 0; i < I2C_DRIVER_MAX; i++)
@@ -275,6 +276,12 @@ int i2c_control_device(struct i2c_bus *bus, int id,
#define I2C_SET(bus,ctrl,data) (bus->i2c_setlines(bus,ctrl,data))
#define I2C_GET(bus) (bus->i2c_getdataline(bus))
+void i2c_reset(struct i2c_bus *bus)
+{
+ I2C_SET(bus,1,1);
+ I2C_DEBUG(printk("%s: bus reset",bus->name));
+}
+
void i2c_start(struct i2c_bus *bus)
{
I2C_SET(bus,0,1);
@@ -384,6 +391,7 @@ int i2c_write(struct i2c_bus *bus, unsigned char addr,
/* ----------------------------------------------------------------------- */
#ifdef MODULE
+
int init_module(void)
{
return i2c_init();
@@ -392,4 +400,5 @@ int init_module(void)
void cleanup_module(void)
{
}
+
#endif
diff --git a/bttv/i2c.h b/bttv/i2c.h
index 931c89e..4aabc67 100644
--- a/bttv/i2c.h
+++ b/bttv/i2c.h
@@ -32,6 +32,7 @@ struct i2c_device;
#define I2C_DRIVERID_MSP3400 1
#define I2C_DRIVERID_TUNER 2
+#define I2C_DRIVERID_CHARDEV 4
/*
* struct for a driver for a i2c chip (tuner, soundprocessor,
@@ -148,6 +149,7 @@ int i2c_control_device(struct i2c_bus *bus, int id,
unsigned int cmd, void *arg);
/* i2c bus access functions */
+void i2c_reset(struct i2c_bus *bus);
void i2c_start(struct i2c_bus *bus);
void i2c_stop(struct i2c_bus *bus);
void i2c_one(struct i2c_bus *bus);
@@ -162,4 +164,15 @@ int i2c_read(struct i2c_bus *bus, unsigned char addr);
int i2c_write(struct i2c_bus *bus, unsigned char addr,
unsigned char b1, unsigned char b2, int both);
+/* ------------------------------------------------------------------------ */
+/* this allows i2c bus access from userspace */
+
+/* ioctls */
+#define I2C_SLAVE 0x0706
+#define I2C_WRITE_SIZE 0x0712
+#define I2C_WRITE_BUF 0x0713
+#define I2C_RESET 0x07fd
+
+#define I2C_BUFFER_SIZE 64 /* buffer size for write b4 read */
+
#endif /* I2C_H */
diff --git a/bttv/i2c_chardev.c b/bttv/i2c_chardev.c
new file mode 100644
index 0000000..bba81d9
--- /dev/null
+++ b/bttv/i2c_chardev.c
@@ -0,0 +1,309 @@
+/*
+ * 2.1.x only
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/locks.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <asm/uaccess.h>
+
+#include "i2c.h"
+
+/* ------------------------------------------------------------------------ */
+/* FIXME: stick this into a header file */
+
+/* ioctls */
+#define I2C_SLAVE 0x0706
+#define I2C_WRITE_SIZE 0x0712
+#define I2C_WRITE_BUF 0x0713
+#define I2C_RESET 0x07fd
+
+#define I2C_BUFFER_SIZE 64 /* buffer size for write b4 read */
+
+/* ----------------------------------------------------------------------- */
+/* this allows i2c bus access from userspace
+ *
+ * taken from the i2c package:
+ * available from http://www.tk.uni-linz.ac.at/~simon/private/i2c/
+ * written by Simon G. Vogl <simon@tk.uni-linz.ac.at>
+ *
+ * interface is binary compatible, the detect utility from the i2c package
+ * finds all the chips on my hauppauge card, and eeprom tool reads happily
+ * the content of the eeprom chip.
+ *
+ * Not all ioctl's implemented yet, only the most important stuff is in now.
+ * Note: address handling (I2C_SLAVE ioctl) is different here:
+ * 7bit address+direction bit instead of 8bit "write address"
+ *
+ */
+
+#define I2C_MAJOR 89 /* Device major number */
+
+#define MAX_BUSSES 8
+static struct i2c_bus *busses[MAX_BUSSES];
+
+/*
+ * private information for each open file:
+ */
+struct i2c_data {
+ int address; /* address slave chip */
+ int writelength; /* bytes to write before read */
+ char buf[I2C_BUFFER_SIZE];/* write buffer */
+};
+
+
+static long long i2c_dev_lseek(struct file * file, long long offset,
+ int origin)
+{
+ return -ESPIPE;
+}
+
+
+static int i2c_dev_open(struct inode * inode, struct file * file)
+{
+ unsigned int minor = MINOR(inode->i_rdev);
+ struct i2c_data *data;
+
+ if (!busses[minor])
+ return -ENODEV;
+
+ if (NULL == (data = kmalloc(sizeof(struct i2c_data),GFP_KERNEL)))
+ return -ENOMEM;
+
+ data->address = 0x00;
+ file->private_data = data;
+
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int i2c_dev_release(struct inode * inode, struct file * file)
+{
+ struct i2c_data *data;
+
+ data=(struct i2c_data *)file->private_data;
+ kfree(data);
+ file->private_data=NULL;
+
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static ssize_t i2c_dev_write(struct file * file, const char * buf,
+ size_t count, loff_t *ppos)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ unsigned int minor = MINOR(inode->i_rdev);
+ const char *ptr = buf;
+ struct i2c_data *data;
+ int c,ret = 0;
+ unsigned long flags;
+
+ if (!busses[minor])
+ return -EINVAL;
+ data=(struct i2c_data *)file->private_data;
+
+ LOCK_I2C_BUS(busses[minor]);
+ i2c_start(busses[minor]);
+ if (0 != i2c_sendbyte(busses[minor], data->address << 1, 0))
+ goto ioerr;
+ while (count > 0) {
+ if (get_user(c,ptr))
+ goto fault;
+ if (0 != i2c_sendbyte(busses[minor],c,0))
+ goto ioerr;
+ ptr++;
+ ret++;
+ count--;
+ }
+ i2c_stop(busses[minor]);
+ UNLOCK_I2C_BUS(busses[minor]);
+
+ return ret;
+
+ioerr:
+ i2c_stop(busses[minor]);
+ UNLOCK_I2C_BUS(busses[minor]);
+ return -EREMOTEIO;
+
+fault:
+ i2c_stop(busses[minor]);
+ UNLOCK_I2C_BUS(busses[minor]);
+ return -EFAULT;
+}
+
+static ssize_t i2c_dev_read(struct file * file,char * buf,
+ size_t count, loff_t *ppos)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ unsigned int minor = MINOR(inode->i_rdev);
+ char *ptr = buf;
+ struct i2c_data *data;
+ int i,val,ret = 0;
+ unsigned long flags;
+
+ if (!busses[minor])
+ return -EINVAL;
+ data=(struct i2c_data *)file->private_data;
+
+ LOCK_I2C_BUS(busses[minor]);
+ if (data->writelength > 0) {
+ i2c_start(busses[minor]);
+ if (0 != i2c_sendbyte(busses[minor], data->address << 1, 0))
+ goto ioerr;
+ for (i = 0; i < data->writelength; i++) {
+ if (0 != i2c_sendbyte(busses[minor],data->buf[i],0))
+ goto ioerr;
+ }
+ }
+ i2c_start(busses[minor]);
+ if (0 != i2c_sendbyte(busses[minor], data->address << 1 | 0x01, 0))
+ goto ioerr;
+ while (count > 0) {
+ val = i2c_readbyte(busses[minor], (count == 1) ? 1 : 0);
+ if (put_user((char)(val),ptr))
+ goto fault;
+ ptr++;
+ ret++;
+ count--;
+ }
+ i2c_stop(busses[minor]);
+ UNLOCK_I2C_BUS(busses[minor]);
+
+ return ret;
+
+ioerr:
+ i2c_stop(busses[minor]);
+ UNLOCK_I2C_BUS(busses[minor]);
+ return -EREMOTEIO;
+
+fault:
+ i2c_stop(busses[minor]);
+ UNLOCK_I2C_BUS(busses[minor]);
+ return -EFAULT;
+}
+
+static int i2c_dev_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ unsigned int minor = MINOR(inode->i_rdev);
+ struct i2c_data *data;
+ int ret = 0;
+ unsigned long flags;
+
+ if (!busses[minor])
+ return -EINVAL;
+ data=(struct i2c_data*)file->private_data;
+
+ switch (cmd) {
+#if 0
+ case I2C_RETRIES:
+ i2c_table[minor].retries = arg;
+ break;
+#endif
+ case I2C_SLAVE:
+ data->address = arg;
+ break;
+ case I2C_WRITE_SIZE:
+ if (arg >= I2C_BUFFER_SIZE)
+ return -E2BIG;
+ data->writelength = arg;
+ break;
+ case I2C_WRITE_BUF:
+ copy_from_user(data->buf,(char*)arg,data->writelength);
+ break;
+ case I2C_RESET:
+ LOCK_I2C_BUS(busses[minor]);
+ i2c_reset(busses[minor]);
+ UNLOCK_I2C_BUS(busses[minor]);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static struct file_operations i2c_fops = {
+ i2c_dev_lseek,
+ i2c_dev_read,
+ i2c_dev_write,
+ NULL, /* i2c_readdir */
+ NULL, /* i2c_select */
+ i2c_dev_ioctl,
+ NULL, /* i2c_mmap */
+ i2c_dev_open,
+ i2c_dev_release,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int chardev_attach(struct i2c_device *device)
+{
+ int i;
+
+ for (i = 0; i < MAX_BUSSES; i++)
+ if (NULL == busses[i])
+ break;
+ if (i == MAX_BUSSES)
+ return -1;
+ busses[i] = device->bus;
+ strcpy(device->name,"chardev");
+ printk("i2c_chardev: attached bus %s to minor %d\n",busses[i]->name,i);
+
+ return 0;
+}
+
+static int chardev_detach(struct i2c_device *device)
+{
+ int i;
+
+ for (i = 0; i < MAX_BUSSES; i++)
+ if (device->bus == busses[i])
+ break;
+ if (i == MAX_BUSSES)
+ return -1;
+ printk("i2c_chardev: detached bus %s from minor %d\n",busses[i]->name,i);
+ busses[i] = NULL;
+
+ return 0;
+}
+
+struct i2c_driver i2c_driver_chardev = {
+ "chardev", /* name */
+ I2C_DRIVERID_CHARDEV, /* ID */
+ 0, 0xfe, /* addr range */
+
+ chardev_attach,
+ chardev_detach,
+ NULL
+};
+
+/* ----------------------------------------------------------------------- */
+
+#ifdef MODULE
+
+int init_module(void)
+{
+ if (register_chrdev(I2C_MAJOR,"i2c",&i2c_fops)) {
+ printk("i2c: unable to get major %d\n", I2C_MAJOR);
+ return -EBUSY;
+ }
+ i2c_register_driver(&i2c_driver_chardev);
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ i2c_unregister_driver(&i2c_driver_chardev);
+ unregister_chrdev(I2C_MAJOR,"i2c");
+}
+
+#endif
+
diff --git a/bttv/linux-2.0.33.diff b/bttv/linux-2.0.33.diff
new file mode 100644
index 0000000..39431cb
--- /dev/null
+++ b/bttv/linux-2.0.33.diff
@@ -0,0 +1,10 @@
+--- linux/kernel/ksyms.c-orig Mon Apr 6 23:46:19 1998
++++ linux/kernel/ksyms.c Mon Apr 6 23:46:09 1998
+@@ -87,6 +87,7 @@
+
+ /* stackable module support */
+ X(register_symtab_from),
++ X(request_module),
+ #ifdef CONFIG_KERNELD
+ X(kerneld_send),
+ #endif
diff --git a/bttv/msp3400.c b/bttv/msp3400.c
index d5fc4da..2d83c37 100644
--- a/bttv/msp3400.c
+++ b/bttv/msp3400.c
@@ -48,6 +48,17 @@
#include "msp3400.h"
+
+/* sound mixer stuff */
+#include <linux/config.h>
+
+#if LINUX_VERSION_CODE > 0x020140 /* need modular sound driver */
+# if defined(CONFIG_SOUND) || defined(CONFIG_SOUND_MODULE)
+# define REGISTER_MIXER 1
+# endif
+#endif
+
+
int debug = 0; /* insmod parameter */
struct msp3400c {
@@ -56,14 +67,19 @@ struct msp3400c {
int nicam;
int mode;
int norm;
- int volume;
int stereo;
+ int mixer;
+ int volume, bass, treble;
+
/* thread */
struct task_struct *thread;
struct semaphore *wait;
struct semaphore *notify;
int active,restart,rmmod;
+
+ int watch_stereo;
+ struct timer_list wake_stereo;
};
#define VIDEO_MODE_RADIO 16 /* norm magic for radio mode */
@@ -263,7 +279,7 @@ msp3400c_setvolume(struct i2c_bus *bus, int vol)
{
int val = (vol * 0x73 / 65535) << 8;
- dprintk("msp3400: setvolume: 0x%02x\n",val>>8);
+ dprintk("msp3400: setvolume: %d 0x%02x\n",vol, val>>8);
msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */
msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */
/* scart - on/off only */
@@ -271,6 +287,24 @@ msp3400c_setvolume(struct i2c_bus *bus, int vol)
}
static void
+msp3400c_setbass(struct i2c_bus *bus, int bass)
+{
+ int val = ((bass-32768) * 0x60 / 65535) << 8;
+
+ dprintk("msp3400: setbass: %d 0x%02x\n",bass, val>>8);
+ msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0002, val); /* loudspeaker */
+}
+
+static void
+msp3400c_settreble(struct i2c_bus *bus, int treble)
+{
+ int val = ((treble-32768) * 0x60 / 65535) << 8;
+
+ dprintk("msp3400: settreble: %d 0x%02x\n",treble, val>>8);
+ msp3400c_write(bus,I2C_MSP3400C_DFP, 0x0003, val); /* loudspeaker */
+}
+
+static void
msp3400c_setmode(struct msp3400c *msp, int type)
{
int i;
@@ -407,6 +441,15 @@ struct REGISTER_DUMP d1[] = {
* in the ioctl while doing the sound carrier & stereo detect
*/
+void
+msp3400c_stereo_wake(unsigned long data)
+{
+ struct msp3400c *msp = (struct msp3400c*)data; /* XXX alpha ??? */
+
+ if (!msp->active)
+ up(msp->wait);
+}
+
int
msp3400c_thread(void *data)
{
@@ -415,8 +458,8 @@ msp3400c_thread(void *data)
struct semaphore sem = MUTEX_LOCKED;
struct CARRIER_DETECT *cd;
- int count, max1,max2,val1,val2, val,this, check_stereo;
- int i;
+ int count, max1,max2,val1,val2, val,this;
+ int newstereo;
/* lock_kernel(); */
@@ -442,37 +485,80 @@ msp3400c_thread(void *data)
dprintk("msp3400: thread: sleep\n");
down_interruptible(&sem);
dprintk("msp3400: thread: wakeup\n");
- if (msp->rmmod)
+ if (msp->rmmod || signal_pending(current))
goto done;
-#if 0
- if (VIDEO_MODE_RADIO == msp->norm) {
- msp->active = 1;
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + HZ/10;
- schedule();
- if (signal_pending(current))
- goto done;
+ if (VIDEO_MODE_RADIO == msp->norm)
+ continue; /* nothing to do */
+
+ msp->active = 1;
+
+ if (msp->watch_stereo) {
+ /* do that stereo/multilang handling */
LOCK_I2C_BUS(msp->bus);
- val1 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b);
- val2 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1c);
+ newstereo = msp->stereo;
+ switch (msp->mode) {
+ case MSP_MODE_FM_TERRA:
+ val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x18);
+ dprintk("msp3400: stereo detect register: %d\n",val);
+
+ if (val > 4096) {
+ newstereo = VIDEO_SOUND_STEREO;
+ } else if (val < -4096) {
+ newstereo = VIDEO_SOUND_LANG1;
+ } else {
+ newstereo = VIDEO_SOUND_MONO;
+ }
+ break;
+ case MSP_MODE_FM_NICAM1:
+ val = msp3400c_read(msp->bus, I2C_MSP3400C_DEM, 0x23);
+ switch ((val & 0x1e) >> 1) {
+ case 0:
+ case 8:
+ newstereo = VIDEO_SOUND_STEREO;
+ break;
+ default:
+ newstereo = VIDEO_SOUND_MONO;
+ break;
+ }
+#if 0
+ /* dump registers (for debugging) */
+ if (debug) {
+ int i;
+
+ for (i=0; i<sizeof(d1)/sizeof(struct REGISTER_DUMP); i++) {
+ val = msp3400c_read(msp->bus,I2C_MSP3400C_DEM,
+ d1[i].addr);
+ printk(KERN_DEBUG "msp3400: %s = 0x%x\n",
+ d1[i].name,val);
+ }
+ }
+#endif
+ break;
+ }
+ if (msp->stereo != newstereo) {
+ dprintk("msp3400: watch: stereo %d ==> %d\n",
+ msp->stereo,newstereo);
+ msp3400c_setstereo(msp,newstereo);
+ }
UNLOCK_I2C_BUS(msp->bus);
- printk("msp3400: DC %d/%d\n",val1,val2);
+ if (msp->watch_stereo) {
+ del_timer(&msp->wake_stereo);
+ msp->wake_stereo.expires = jiffies + 5*HZ;
+ add_timer(&msp->wake_stereo);
+ }
+
msp->active = 0;
continue;
}
-#endif
-
- if (VIDEO_MODE_RADIO == msp->norm)
- continue; /* nothing to do */
- msp->active = 1;
-
restart:
LOCK_I2C_BUS(msp->bus);
msp3400c_setvolume(msp->bus, 0);
msp3400c_setmode(msp, MSP_MODE_AM_DETECT);
- val1 = val2 = max1 = max2 = check_stereo = 0;
+ val1 = val2 = max1 = max2 = 0;
+ del_timer(&msp->wake_stereo);
+ msp->watch_stereo = 0;
/* carrier detect pass #1 -- main carrier */
cd = carrier_detect_main; count = CARRIER_COUNT(carrier_detect_main);
@@ -542,7 +628,7 @@ msp3400c_thread(void *data)
if (max2 == 0) {
/* B/G FM-stereo */
msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
- check_stereo = 1;
+ msp->watch_stereo = 1;
}
if (max2 == 1 && msp->nicam) {
/* B/G NICAM */
@@ -550,7 +636,7 @@ msp3400c_thread(void *data)
/* msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x21, 0x01); */
msp3400c_setcarrier(msp->bus, MSP_CARRIER(5.85),
MSP_CARRIER(5.5));
- check_stereo = 1;
+ msp->watch_stereo = 1;
}
break;
case 2: /* 6.0 */
@@ -565,61 +651,13 @@ msp3400c_thread(void *data)
/* unmute */
msp3400c_setvolume(msp->bus, msp->volume);
+ UNLOCK_I2C_BUS(msp->bus);
- if (check_stereo) {
- /* stereo available -- check current mode */
- UNLOCK_I2C_BUS(msp->bus);
-
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + HZ;
- schedule();
- if (signal_pending(current))
- goto done;
- if (msp->restart) {
- msp->restart = 0;
- goto restart;
- }
-
- LOCK_I2C_BUS(msp->bus);
- switch (msp->mode) {
- case MSP_MODE_FM_TERRA:
- val = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x18);
- dprintk("msp3400: stereo detect register: %d\n",val);
-
- if (val > 4096) {
- msp3400c_setstereo(msp, VIDEO_SOUND_STEREO);
- } else if (val < -4096) {
- msp3400c_setstereo(msp, VIDEO_SOUND_LANG1);
- } else {
- msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
- }
- break;
- case MSP_MODE_FM_NICAM1:
- val = msp3400c_read(msp->bus, I2C_MSP3400C_DEM, 0x23);
- switch ((val & 0x1e) >> 1) {
- case 0:
- case 8:
- msp3400c_setstereo(msp, VIDEO_SOUND_STEREO);
- break;
- default:
- msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
- break;
- }
-
- /* dump registers (for debugging) */
- if (debug) {
- for (i=0; i<sizeof(d1)/sizeof(struct REGISTER_DUMP); i++) {
- val = msp3400c_read(msp->bus,I2C_MSP3400C_DEM,
- d1[i].addr);
- printk(KERN_DEBUG "msp3400: %s = 0x%x\n",
- d1[i].name,val);
- }
- }
- break;
- }
+ if (msp->watch_stereo) {
+ del_timer(&msp->wake_stereo);
+ msp->wake_stereo.expires = jiffies + HZ;
+ add_timer(&msp->wake_stereo);
}
- UNLOCK_I2C_BUS(msp->bus);
-
msp->active = 0;
}
@@ -634,6 +672,9 @@ done:
return 0;
}
+
+#if 0 /* not finished yet */
+
int
msp3410d_thread(void *data)
{
@@ -720,6 +761,142 @@ done:
up(msp->notify);
return 0;
}
+#endif
+
+/* ----------------------------------------------------------------------- */
+/* mixer stuff -- with the modular sound driver in 2.1.x we can easily */
+/* register the msp3400 as mixer device */
+
+#ifdef REGISTER_MIXER
+
+#include <linux/soundcard.h>
+#include <../drivers/sound/sound_config.h>
+#include <../drivers/sound/dev_table.h>
+
+static int
+mix_to_v4l(int i)
+{
+ int r;
+
+ r = ((i & 0xff) * 65536 + 50) / 100;
+ if (r > 65535) r = 65535;
+ if (r < 0) r = 0;
+ return r;
+}
+
+static int
+v4l_to_mix(int i)
+{
+ int r;
+
+ r = (i * 100 + 32768) / 65536;
+ if (r > 100) r = 100;
+ if (r < 0) r = 0;
+ return r | (r << 8);
+}
+
+static int
+msp3400c_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+ struct msp3400c *msp = mixer_devs[dev]->devc;
+ unsigned long flags;
+ int ret,val = 0;
+
+ if (_SIOC_DIR(cmd) & _SIOC_WRITE)
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+
+ switch (cmd) {
+ case MIXER_READ(SOUND_MIXER_RECMASK):
+ case MIXER_READ(SOUND_MIXER_STEREODEVS):
+ case MIXER_READ(SOUND_MIXER_CAPS):
+ case MIXER_READ(SOUND_MIXER_RECSRC):
+ case MIXER_WRITE(SOUND_MIXER_RECSRC):
+ ret = 0;
+ break;
+
+ case MIXER_READ(SOUND_MIXER_DEVMASK):
+ ret = SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE;
+ break;
+
+ case MIXER_WRITE(SOUND_MIXER_VOLUME):
+ msp->volume = mix_to_v4l(val);
+ LOCK_I2C_BUS(msp->bus);
+ msp3400c_setvolume(msp->bus,msp->volume);
+ UNLOCK_I2C_BUS(msp->bus);
+ /* fall */
+ case MIXER_READ(SOUND_MIXER_VOLUME):
+ ret = v4l_to_mix(msp->volume);
+ break;
+
+ case MIXER_WRITE(SOUND_MIXER_BASS):
+ msp->bass = mix_to_v4l(val);
+ LOCK_I2C_BUS(msp->bus);
+ msp3400c_setbass(msp->bus,msp->bass);
+ UNLOCK_I2C_BUS(msp->bus);
+ /* fall */
+ case MIXER_READ(SOUND_MIXER_BASS):
+ ret = v4l_to_mix(msp->bass);
+ break;
+
+ case MIXER_WRITE(SOUND_MIXER_TREBLE):
+ msp->treble = mix_to_v4l(val);
+ LOCK_I2C_BUS(msp->bus);
+ msp3400c_settreble(msp->bus,msp->treble);
+ UNLOCK_I2C_BUS(msp->bus);
+ /* fall */
+ case MIXER_READ(SOUND_MIXER_TREBLE):
+ ret = v4l_to_mix(msp->treble);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ if (put_user(ret, (int *)arg))
+ return -EFAULT;
+ return 0;
+}
+
+struct mixer_operations msp3400c_mixer = {
+ "video4linux",
+ "TV card sound (msp3400)",
+ msp3400c_mixer_ioctl
+};
+
+static int
+msp3400c_mixer_init(struct msp3400c *msp)
+{
+ int m;
+
+ msp->mixer = m = sound_alloc_mixerdev();
+ if (m == -1)
+ return -1;
+
+ mixer_devs[m] = (struct mixer_operations *)
+ kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
+ if (mixer_devs[m] == NULL) {
+ printk(KERN_ERR "msp3400c: can't allocate memory\n");
+ sound_unload_mixerdev(m);
+ return -1;
+ }
+ memcpy(mixer_devs[m],&msp3400c_mixer,sizeof(struct mixer_operations));
+ mixer_devs[m]->devc = msp;
+ return 0;
+}
+
+static int
+msp3400c_mixer_close(struct msp3400c *msp)
+{
+ int m = msp->mixer;
+
+ if (m != -1 ) {
+ sound_unload_mixerdev(m);
+ kfree(mixer_devs[m]);
+ }
+ return 0;
+}
+
+#endif
/* ----------------------------------------------------------------------- */
@@ -737,6 +914,8 @@ msp3400c_attach(struct i2c_device *device)
memset(msp,0,sizeof(struct msp3400c));
msp->bus = device->bus;
msp->volume = 65535;
+ msp->bass = 32768;
+ msp->treble = 32768;
LOCK_I2C_BUS(msp->bus);
if (-1 == msp3400c_reset(msp->bus)) {
@@ -747,7 +926,9 @@ msp3400c_attach(struct i2c_device *device)
msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
msp3400c_setvolume(msp->bus, msp->volume);
-
+ msp3400c_setbass(msp->bus, msp->bass);
+ msp3400c_settreble(msp->bus, msp->treble);
+
rev1 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1e);
rev2 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1f);
@@ -760,10 +941,13 @@ msp3400c_attach(struct i2c_device *device)
sprintf(device->name,"MSP34%02d%c-%c%d",
(rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
msp->nicam = (((rev2>>8)&0xff) == 10) ? 1 : 0;
- printk(KERN_INFO "msp3400: init: chip=%s%s\n",
- device->name, msp->nicam ? ", can decode nicam" : "");
+
+ /* timer for stereo checking */
+ msp->wake_stereo.function = msp3400c_stereo_wake;
+ msp->wake_stereo.data = (unsigned long)msp;
/* startup control thread */
+ MOD_INC_USE_COUNT;
msp->notify = &sem;
kernel_thread(msp3400c_thread, (void *)msp, 0);
down(&sem);
@@ -771,6 +955,14 @@ msp3400c_attach(struct i2c_device *device)
if (!msp->active)
up(msp->wait);
+ printk(KERN_INFO "msp3400: init: chip=%s",device->name);
+ if (msp->nicam)
+ printk(", has NICAM support");
+#ifdef REGISTER_MIXER
+ if (0 == msp3400c_mixer_init(msp))
+ printk(", registered as sound mixer");
+#endif
+ printk("\n");
return 0;
}
@@ -781,19 +973,27 @@ msp3400c_detach(struct i2c_device *device)
struct semaphore sem = MUTEX_LOCKED;
struct msp3400c *msp = (struct msp3400c*)device->data;
+#ifdef REGISTER_MIXER
+ msp3400c_mixer_close(msp);
+#endif
+
/* shutdown control thread */
- msp->notify = &sem;
- msp->rmmod = 1;
- if (!msp->active)
- up(msp->wait);
- down(&sem);
- msp->notify = NULL;
+ del_timer(&msp->wake_stereo);
+ if (msp->thread) {
+ msp->notify = &sem;
+ msp->rmmod = 1;
+ if (!msp->active)
+ up(msp->wait);
+ down(&sem);
+ msp->notify = NULL;
+ }
LOCK_I2C_BUS(msp->bus);
msp3400c_reset(msp->bus);
UNLOCK_I2C_BUS(msp->bus);
kfree(msp);
+ MOD_DEC_USE_COUNT;
return 0;
}
@@ -808,6 +1008,8 @@ msp3400c_command(struct i2c_device *device,
switch (cmd) {
case MSP_SET_RADIO:
msp->norm = VIDEO_MODE_RADIO;
+ msp->watch_stereo=0;
+ del_timer(&msp->wake_stereo);
LOCK_I2C_BUS(msp->bus);
msp3400c_setmode(msp,MSP_MODE_FM_RADIO);
msp3400c_setcarrier(msp->bus, MSP_CARRIER(10.7),MSP_CARRIER(10.7));
@@ -817,6 +1019,8 @@ msp3400c_command(struct i2c_device *device,
msp->norm = *iarg;
break;
case MSP_NEWCHANNEL:
+ msp->watch_stereo=0;
+ del_timer(&msp->wake_stereo);
if (!msp->active)
up(msp->wait);
else
@@ -833,11 +1037,33 @@ msp3400c_command(struct i2c_device *device,
UNLOCK_I2C_BUS(msp->bus);
break;
+ case MSP_GET_BASS:
+ *iarg = msp->bass;
+ break;
+ case MSP_SET_BASS:
+ msp->bass = *iarg;
+ LOCK_I2C_BUS(msp->bus);
+ msp3400c_setbass(msp->bus,msp->bass);
+ UNLOCK_I2C_BUS(msp->bus);
+ break;
+
+ case MSP_GET_TREBLE:
+ *iarg = msp->treble;
+ break;
+ case MSP_SET_TREBLE:
+ msp->treble = *iarg;
+ LOCK_I2C_BUS(msp->bus);
+ msp3400c_settreble(msp->bus,msp->treble);
+ UNLOCK_I2C_BUS(msp->bus);
+ break;
+
case MSP_GET_STEREO:
*iarg = msp->stereo;
break;
case MSP_SET_STEREO:
if (*iarg) {
+ msp->watch_stereo=0;
+ del_timer(&msp->wake_stereo);
LOCK_I2C_BUS(msp->bus);
msp3400c_setstereo(msp,*iarg);
UNLOCK_I2C_BUS(msp->bus);
diff --git a/bttv/msp3400.h b/bttv/msp3400.h
index 1b4eeda..e4029c0 100644
--- a/bttv/msp3400.h
+++ b/bttv/msp3400.h
@@ -15,4 +15,9 @@
#define MSP_GET_DC _IOW('m',8,int)
+#define MSP_GET_BASS _IOR('m', 9,int)
+#define MSP_SET_BASS _IOW('m',10,int)
+#define MSP_GET_TREBLE _IOR('m',11,int)
+#define MSP_SET_TREBLE _IOW('m',12,int)
+
#endif /* MSP3400_H */
diff --git a/bttv/nicam b/bttv/nicam
deleted file mode 100644
index d148896..0000000
--- a/bttv/nicam
+++ /dev/null
@@ -1,106 +0,0 @@
-
-From pp@netppl.fi Mon Mar 23 09:44:03 1998
-Date: Thu, 19 Mar 1998 22:35:47 +0200
-From: Pekka Pietik{inen <pp@netppl.fi>
-To: rjkm@thp.uni-koeln.de
-Cc: kraxel@cs.tu-berlin.de
-Subject: NICAM support for msp3400
-
-I just finished this and it works nicely (haven't tested the dual language
-support yet, but I think I got it right. Can't test it now as they don't
-use it much here (mostly for sports).
-
---- msp3400.c-orig Tue Mar 3 01:48:24 1998
-+++ msp3400.c Thu Mar 19 22:29:57 1998
-@@ -19,13 +19,12 @@
- * should work, no autodetect (i.e. default is mono, but you can
- * switch to stereo -- untested)
- *
-- * NICAM
-- * does'nt work yet (well, detecting the NICAM-cable chip version
-- * works, but nothing more).
-+ * NICAM (B/G, used in Scandinavia and Spain)
-+ * should work, with autodetect. Support for NICAM was added by
-+ * Pekka Pietikainen <pp@netppl.fi>
- *
- *
- * TODO:
-- * - NICAM support
- * - better SAT support
- *
- */
-@@ -315,6 +314,7 @@
- msp3400c_setstereo(struct msp3400c *msp, int mode)
- {
- /* switch demodulator */
-+ int nicam=0;
- switch (msp->mode) {
- case MSP_MODE_FM_TERRA:
- dprintk("msp3400: B/G setstereo: %d\n",mode);
-@@ -349,6 +349,13 @@
- break;
- }
- break;
-+ case MSP_MODE_FM_NICAM1:
-+ dprintk("msp3400: NICAM setstereo: %d\n",mode);
-+ msp->stereo = mode;
-+ msp3400c_setcarrier(msp->bus,MSP_CARRIER(5.85),MSP_CARRIER(5.5));
-+ msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0010, 0x3000);
-+ nicam=0x0100;
-+ break;
- default:
- /* can't do stereo - abort here */
- return;
-@@ -357,21 +364,21 @@
- /* switch audio */
- switch (mode) {
- case VIDEO_SOUND_STEREO:
-- msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008, 0x0020);
-- msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009, 0x0020);
-- msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a, 0x0020);
-- msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0005, 0x4000);
-+ msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008, 0x0020|nicam);
-+ msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009, 0x0020|nicam);
-+ msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a, 0x0020|nicam);
-+ msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0005, 0x4000|nicam);
- break;
- case VIDEO_SOUND_MONO:
- case VIDEO_SOUND_LANG1:
-- msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008, 0x0000);
-- msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009, 0x0000);
-- msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a, 0x0000);
-+ msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008, 0x0000|nicam);
-+ msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009, 0x0000|nicam);
-+ msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a, 0x0000|nicam);
- break;
- case VIDEO_SOUND_LANG2:
-- msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008, 0x0010);
-- msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009, 0x0010);
-- msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a, 0x0010);
-+ msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008, 0x0010|nicam);
-+ msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009, 0x0010|nicam);
-+ msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a, 0x0010|nicam);
- break;
- }
- }
-@@ -570,8 +577,15 @@
- break;
- case MSP_MODE_FM_NICAM1:
- val = msp3400c_read(msp->bus, I2C_MSP3400C_DEM, 0x23);
-- printk(KERN_DEBUG "msp3400: C_AD_BITS=0x%x\n",val);
-- break;
-+ dprintk(KERN_DEBUG "msp3400: C_AD_BITS=0x%x\n",val);
-+ switch ((val & 0x1e) >> 1) {
-+ case 0:
-+ case 8: msp3400c_setstereo(msp, VIDEO_SOUND_STEREO); break;
-+ default: msp3400c_setstereo(msp, VIDEO_SOUND_MONO); break;
-+ }
-+ val = msp3400c_read(msp->bus, I2C_MSP3400C_DEM, 0x58);
-+ dprintk(KERN_DEBUG "msp3400: ERROR_RATE=%d\n",val); break;
-+ break;
- }
- }
- UNLOCK_I2C_BUS(msp->bus);
-
---
-Pekka Pietikainen, Net People Ltd., Oulu, Finland
diff --git a/bttv/tuner.c b/bttv/tuner.c
index ceff88e..db37406 100644
--- a/bttv/tuner.c
+++ b/bttv/tuner.c
@@ -172,6 +172,7 @@ tuner_attach(struct i2c_device *device)
t->addr = device->addr;
t->type = type;
dprintk("tuner: type is %d (%s)\n",t->type,tuners[t->type].name);
+ MOD_INC_USE_COUNT;
return 0;
}
@@ -180,6 +181,7 @@ tuner_detach(struct i2c_device *device)
{
struct tuner *t = (struct tuner*)device->data;
kfree(t);
+ MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/bttv/update b/bttv/update
index b09dac1..ad2b972 100644
--- a/bttv/update
+++ b/bttv/update
@@ -1,26 +1,39 @@
#!/bin/sh
+if test "$UID" = "0"; then
+ # running as root anyway, don't need sudo
+ INSMOD="/sbin/insmod"
+ RMMOD="/sbin/rmmod"
+else
+ INSMOD="sudo /sbin/insmod"
+ RMMOD="sudo /sbin/rmmod"
+fi
+
+# handy functions for rmmod/insmod
function xrmmod () {
grep -qe "^$1" /proc/modules || return
echo rmmod $1
- sudo /sbin/rmmod $1 || exit 1
+ $RMMOD $1 || exit 1
}
-
function xinsmod () {
echo insmod $*
- sudo /sbin/insmod $* || exit 1
+ $INSMOD $* || exit 1
}
+# prepare for crashing the box -- flush dirty buffers
sync; sleep 1; sync
+# kill old modules ...
+xrmmod bttv
xrmmod msp3400
xrmmod tuner
-xrmmod bttv
xrmmod i2c
xrmmod videodev
+# ... and load the new ones
xinsmod videodev
xinsmod i2c verbose=1 scan=1 i2c_debug=0
xinsmod tuner debug=0 type=5
xinsmod msp3400 debug=0
xinsmod bttv radio=1
+
diff --git a/bttv/videodev.c b/bttv/videodev.c
index 3083443..47f7b20 100644
--- a/bttv/videodev.c
+++ b/bttv/videodev.c
@@ -203,16 +203,39 @@ static int video_ioctl(struct inode *inode, struct file *file,
* Video For Linux device drivers request registration here.
*/
-int video_register_device(struct video_device *vfd, int base)
+int video_register_device(struct video_device *vfd, int type)
{
int i=0;
+ int base;
int err;
+ int end;
- for(i=base;i<VIDEO_NUM_DEVICES;i++)
+ switch(type)
+ {
+ case VFL_TYPE_GRABBER:
+ base=0;
+ end=64;
+ break;
+ case VFL_TYPE_VTX:
+ base=192;
+ end=224;
+ break;
+ case VFL_TYPE_VBI:
+ base=224;
+ end=240;
+ break;
+ case VFL_TYPE_RADIO:
+ base=64;
+ end=128;
+ break;
+ default:
+ return -1;
+ }
+
+ for(i=base;i<end;i++)
{
if(video_device[i]==NULL)
{
- printk("v4l: register: minor %d for %s\n",i,vfd->name);
video_device[i]=vfd;
vfd->minor=i;
/* The init call may sleep so we book the slot out
diff --git a/bttv/videodev.h b/bttv/videodev.h
index 4c52105..960ffad 100644
--- a/bttv/videodev.h
+++ b/bttv/videodev.h
@@ -16,19 +16,21 @@ struct video_device
long (*write)(struct video_device *, const char *, unsigned long, int noblock);
int (*ioctl)(struct video_device *, unsigned int , void *);
int (*mmap)(struct video_device *, const char *, unsigned long);
- int (*initialize)(struct video_device *);
-#if defined(c_plusplus) || defined (__cplusplus)
- void *priv;
-#else
- void *private;
-#endif
+ int (*initialize)(struct video_device *);
+ void *priv; /* Used to be 'private' but that upsets C++ */
int busy;
int minor;
};
extern int videodev_init(void);
#define VIDEO_MAJOR 81
-extern int video_register_device(struct video_device *, int base);
+extern int video_register_device(struct video_device *, int type);
+
+#define VFL_TYPE_GRABBER 0
+#define VFL_TYPE_VBI 1
+#define VFL_TYPE_RADIO 2
+#define VFL_TYPE_VTX 3
+
extern void video_unregister_device(struct video_device *);
#endif
@@ -43,10 +45,9 @@ extern void video_unregister_device(struct video_device *);
#define VID_TYPE_SCALES 128 /* Scalable */
#define VID_TYPE_MONOCHROME 256 /* Monochrome only */
-
struct video_capability
{
- char name[32];
+ char name[32];
int type;
int channels; /* Num channels */
int audios; /* Num audio devices */
@@ -114,7 +115,7 @@ struct video_audio
#define VIDEO_AUDIO_VOLUME 4
#define VIDEO_AUDIO_BASS 8
#define VIDEO_AUDIO_TREBLE 16
- char name[16];
+ char name[16];
#define VIDEO_SOUND_MONO 1
#define VIDEO_SOUND_STEREO 2
#define VIDEO_SOUND_LANG1 3
@@ -148,6 +149,12 @@ struct video_buffer
int bytesperline;
};
+struct video_mmap
+{
+ unsigned int frame; /* Frame (0 or 1) for double buffer */
+ int height,width;
+ unsigned int format;
+};
struct video_key
{
@@ -168,10 +175,12 @@ struct video_key
#define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */
#define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */
#define VIDIOCKEY _IOR('v',13, struct video_key) /* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */
-#define VIDIOCGFREQ _IOR('v',15, unsigned long) /* Set tuner */
+#define VIDIOCGFREQ _IOR('v',14, unsigned long) /* Set tuner */
#define VIDIOCSFREQ _IOW('v',15, unsigned long) /* Set tuner */
#define VIDIOCGAUDIO _IOR('v',16, struct video_audio) /* Get audio info */
#define VIDIOCSAUDIO _IOW('v',17, struct video_audio) /* Audio source, mute etc */
+#define VIDIOCSYNC _IO('v',18) /* Sync with mmap grabbing */
+#define VIDIOCMCAPTURE _IOW('v',19, struct video_mmap) /* Grab frames */
#define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */
@@ -180,6 +189,9 @@ struct video_key
#define VID_HARDWARE_BT848 1
#define VID_HARDWARE_QCAM_BW 2
#define VID_HARDWARE_PMS 3
+#define VID_HARDWARE_QCAM_C 4
+#define VID_HARDWARE_PSEUDO 5
+#define VID_HARDWARE_SAA5249 6
/*
* Initialiser list
diff --git a/chan.h b/chan.h
deleted file mode 100644
index 8d6b095..0000000
--- a/chan.h
+++ /dev/null
@@ -1,59 +0,0 @@
-
-struct CHAN_FREQ {
- float freq_low;
- float freq_high;
- int chan_low;
- int chan_high;
- float factor;
-};
-
-struct CHAN_FREQ chan_Europe[] = {
- { 48.25, 66.25, 2, 4, 7.0 },
- { 112.25, 172.25, 72, 80, 7.0 },
- { 175.25, 228.25, 5, 12, 7.0 },
- { 231.25, 298.25, 81, 90, 7.0 },
- { 303.25, 451.25, 91, 109, 8.0 },
- { 455.25, 471.25, 110, 112, 8.0 },
- { 471.25, 859.25, 21, 69, 8.0 },
- { 859.25, 1175.25, 161, 200, 8.0 },
- { 0, 0, 0, 0, 0 }
-};
-
-struct CHAN_FREQ chan_USA[] = {
- { 55.25, 73.25, 2, 4, 6.0 },
- { 77.25, 87.25, 5, 6, 6.0 },
- { 175.25, 215.25, 7, 13, 6.0 },
- { 471.25, 805.25, 14, 69, 6.0 },
- { 121.25, 173.25, 114, 122, 6.0 },
- { 217.25, 299.25, 123, 136, 6.0 },
- { 301.25, 1031.25, 137, 258, 6.0 },
- { 0, 0, 0, 0, 0 }
-};
-
-struct CHAN_FREQ chan_USAcable[] = {
- { 73.25, 73.25, 1, 1, 6.0 },
- { 55.25, 67.25, 2, 4, 6.0 },
- { 77.25, 83.25, 5, 6, 6.0 },
- { 175.25, 211.25, 7, 13, 6.0 },
- { 121.25, 169.25, 14, 22, 6.0 },
- { 217.25, 277.25, 23, 33, 6.0 },
- { 293.25, 293.25, 34, 34, 6.0 },
- { 289.25, 643.25, 35, 94, 6.0 },
- { 91.25, 115.25, 95, 99, 6.0 },
- { 649.25, 799.25, 100, 125, 6.0 },
- { 0, 0, 0, 0, 0 }
-};
-
-struct STRTAB chan_names[] = {
- { 0, "Europe" },
- { 1, "USA" },
- { 2, "USAcable" },
- { -1, NULL }
-};
-
-struct CHAN_FREQ *chan_tabs[] = {
- chan_Europe,
- chan_USA,
- chan_USAcable,
- NULL
-};
diff --git a/chan2c.pl b/chan2c.pl
deleted file mode 100644
index 99fa9e3..0000000
--- a/chan2c.pl
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/perl
-
-print <<__EOF__;
-
-struct CHAN_FREQ {
- float freq_low;
- float freq_high;
- int chan_low;
- int chan_high;
- float factor;
-};
-
-__EOF__
-
-foreach $file (@ARGV) {
- $tag = $file;
- $tag =~ s/\.chan//;
- $tag =~ s/.*\///;
- print "struct CHAN_FREQ chan_$tag\[\] = {\n";
-
- open(FILE,"<$file") || die;
- while(<FILE>) {
- @cols = split;
- next if $#cols != 4;
- print " { $cols[0], $cols[1], $cols[2], $cols[3], $cols[4] },\n";
- }
- print " { 0, 0, 0, 0, 0 }\n";
- print "};\n\n";
-}
-
-print "struct STRTAB chan_names[] = {\n";
-$i = 0;
-foreach $file (@ARGV) {
- $tag = $file;
- $tag =~ s/\.chan//;
- $tag =~ s/.*\///;
- print " { $i, \"$tag\" },\n";
- $i++;
-}
-print " { -1, NULL }\n};\n\n";
-
-print "struct CHAN_FREQ *chan_tabs[] = {\n";
-foreach $file (@ARGV) {
- $tag = $file;
- $tag =~ s/\.chan//;
- $tag =~ s/.*\///;
- print " chan_$tag,\n";
-}
-print " NULL\n};\n";
-
diff --git a/channel.c b/channel.c
index 78347a5..c4ac2f6 100644
--- a/channel.c
+++ b/channel.c
@@ -3,6 +3,9 @@
Copyright (C) 1996,97 Marcus Metzler (mocm@thp.uni-koeln.de)
+ many changes by Gerd Knorr <kraxel@cs.tu-berlin.de>
+ [ hmm, think by now nearly nothing left from the original code ... ]
+
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
@@ -21,20 +24,22 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include <math.h>
#include <X11/Intrinsic.h>
#include "grab.h"
+#include "channels.h"
#include "channel.h"
#include "mixer.h"
-#include "chan.h"
/* ----------------------------------------------------------------------- */
/* misc common stuff, not only channel related */
struct CHANNEL defaults = { "defaults", NULL,
- 1, 0, 0, 5, 0, 0,
+ "5", 0, 0, 0,
+ 1, 0, 0,
32768, 32768, 32768, 32768 };
struct CHANNEL **channels = NULL;
int count = 0;
@@ -43,30 +48,55 @@ int have_mixer = 0;
int cur_sender = -1, cur_channel = 5, cur_fine = 0;
int cur_norm = -1, cur_input = -1;
-int chan_tab = 0;
+int chan_tab = 4;
extern struct GRABBER *grabbers[];
extern int grabber;
+extern int fs_width,fs_height,fs_xoff,fs_yoff;
/* ----------------------------------------------------------------------- */
-int cf2freq(int channel, int fine)
+int lookup_channel(char *channel)
{
- double freq = 0;
- int i;
-
- for (i = 0; chan_tabs[chan_tab][i].chan_low != 0; i++) {
- if (chan_tabs[chan_tab][i].chan_low <= channel &&
- chan_tabs[chan_tab][i].chan_high >= channel) {
-
- freq = chan_tabs[chan_tab][i].freq_low +
- chan_tabs[chan_tab][i].factor *
- (channel - chan_tabs[chan_tab][i].chan_low);
- break;
- }
+ int i,nr;
+ char tag;
+
+ if (isdigit(channel[0])) {
+ tag = 0;
+ nr = atoi(channel);
+ } else {
+ tag = channel[0];
+ nr = atoi(channel+1);
}
- return (int)(freq*16)+fine;
+ for (i = 0; i < CHAN_ENTRIES; i++) {
+ if (tag && !isdigit(tvtuner[i].name[0]))
+ if (atoi(tvtuner[i].name+1) == nr && tvtuner[i].name[0] == tag)
+ break;
+ if (!tag && isdigit(tvtuner[i].name[0]))
+ if (atoi(tvtuner[i].name) == nr)
+ break;
+ }
+ if (i == CHAN_ENTRIES)
+ return -1;
+
+ return i;
+}
+
+int get_freq(int i)
+{
+ if (!tvtuner[i].freq[chan_tab])
+ return -1;
+ return tvtuner[i].freq[chan_tab]*16/1000;
+}
+
+int cf2freq(char *name, int fine)
+{
+ int i;
+
+ if (-1 == (i = lookup_channel(name)))
+ return -1;
+ return get_freq(i)+fine;
}
/* ----------------------------------------------------------------------- */
@@ -102,21 +132,36 @@ read_config()
continue;
}
if (2 != sscanf(line," %31[^= ] = %99[^\n]",tag,val)) {
- fprintf(stderr,"parse error line %d\n",nr);
- exit(1);
+ fprintf(stderr,"%s:%d: parse error\n",filename,nr);
+ continue;
}
if (0 == strcmp(tag,"key"))
current->key = strdup(val);
- else if (0 == strcmp(tag,"capture"))
+ else if (0 == strcmp(tag,"capture")) {
current->capture = str_to_int(val,booltab);
- else if (0 == strcmp(tag,"source"))
+ if (-1 == current->capture)
+ fprintf(stderr,"%s:%d: invalid value for %s: %s\n",
+ filename,nr,tag,val);
+ } else if (0 == strcmp(tag,"source")) {
current->source = str_to_int(val,grabbers[grabber]->inputs);
- else if (0 == strcmp(tag,"norm"))
+ if (-1 == current->capture)
+ fprintf(stderr,"%s:%d: invalid value for %s: %s\n",
+ filename,nr,tag,val);
+ } else if (0 == strcmp(tag,"norm")) {
current->norm = str_to_int(val,grabbers[grabber]->norms);
- else if (0 == strcmp(tag,"channel"))
- current->channel = atoi(val);
+ if (-1 == current->capture)
+ fprintf(stderr,"%s:%d: invalid value for %s: %s\n",
+ filename,nr,tag,val);
+ } else if (0 == strcmp(tag,"channel")) {
+ current->cname = strdup(val);
+ current->channel = lookup_channel(current->cname);
+ current->freq = get_freq(current->channel);
+ if (-1 == current->channel)
+ fprintf(stderr,"%s:%d: invalid value for %s: %s\n",
+ filename,nr,tag,val);
+ }
else if (0 == strcmp(tag,"fine"))
current->fine = atoi(val);
@@ -132,13 +177,34 @@ read_config()
else if (0 == count && 0 == strcmp(tag,"mixer")) {
if (-1 != mixer_open("/dev/mixer", val))
have_mixer = 1;
+ else
+ fprintf(stderr,"%s:%d: invalid value for %s: %s\n",
+ filename,nr,tag,val);
+
} else if (0 == count && 0 == strcmp(tag,"freqtab")) {
if (-1 != (i = str_to_int(val,chan_names)))
chan_tab = i;
+ else
+ fprintf(stderr,"%s:%d: invalid value for %s: %s\n",
+ filename,nr,tag,val);
+
+ } else if (0 == count && 0 == strcmp(tag,"fullscreen")) {
+ if (2 != sscanf(val,"%d x %d",&fs_width,&fs_height)) {
+ fprintf(stderr,"%s:%d: invalid value for %s: %s\n",
+ filename,nr,tag,val);
+ fs_width = fs_height = 0;
+ }
+
+ } else if (0 == count && 0 == strcmp(tag,"wm-off-by")) {
+ if (2 != sscanf(val,"%d %d",&fs_xoff,&fs_yoff)) {
+ fprintf(stderr,"%s:%d: invalid value for %s: %s\n",
+ filename,nr,tag,val);
+ fs_xoff = fs_yoff = 0;
+ }
} else {
- fprintf(stderr,"parse error line %d: unknown tag %s\n",nr,tag);
- exit(1);
+ fprintf(stderr,"%s:%d: unknown tag %s\n",filename,nr,tag);
+
}
}
fclose(fp);
@@ -146,6 +212,20 @@ read_config()
/* ----------------------------------------------------------------------- */
+struct STRTAB chan_names[] = {
+ { 0, "ntsc-bcast" },
+ { 1, "ntsc-cable" },
+ { 2, "ntsc-bcast-jp" },
+ { 3, "ntsc-cable-jp" },
+ { 4, "pal-europe" },
+ { 5, "pal-italy" },
+ { 6, "pal-newzealand" },
+ { 7, "pal-australia" },
+ { 8, "pal-uhf-ireland" },
+ { 9, "pal-cable-bg" },
+ { -1, NULL }
+};
+
struct STRTAB booltab[] = {
{ 0, "no" },
{ 0, "false" },
@@ -168,3 +248,166 @@ str_to_int(char *str, struct STRTAB *tab)
return(tab[i].nr);
return -1;
}
+
+/* ------------------------------------------------------------------------- */
+/* moved here from channels.h */
+
+/* NOTE : NTSC BROADCAST OVER 69 WERE RE-ALLOCATED CELLULAR, included anyway */
+
+struct freqlist tvtuner[] = {
+/* CH US-TV US-CATV JP-TV JP-CATV EUROPE ITALY NZ AU UHF_GHI BGCATV*/
+{"S1",{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 69250}},
+{"S2",{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 76250}},
+{"S3",{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 83250}},
+
+{"E2",{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 48250}},
+{"E3",{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 55250}},
+{"E4",{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 62250}},
+{"E5",{ 0, 0, 0, 0, 0, 0, 0, 0, 0,175250}},
+{"E6",{ 0, 0, 0, 0, 0, 0, 0, 0, 0,182250}},
+{"E7",{ 0, 0, 0, 0, 0, 0, 0, 0, 0,189250}},
+{"E8",{ 0, 0, 0, 0, 0, 0, 0, 0, 0,196250}},
+{"E9",{ 0, 0, 0, 0, 0, 0, 0, 0, 0,203250}},
+{"E10",{ 0, 0, 0, 0, 0, 0, 0, 0, 0,210250}},
+{"E11",{ 0, 0, 0, 0, 0, 0, 0, 0, 0,217250}},
+{"E12",{ 0, 0, 0, 0, 0, 0, 0, 0, 0,224250}},
+
+{"0",{ 0, 0, 0, 0, 0, 0, 0, 46250, 45750, 0}},
+{"1",{ 0, 73250, 91250, 0, 0, 0, 45250, 57250, 53750,105250}},
+{"2",{ 55250, 55250, 97250, 0, 48250, 53750, 55250, 64250, 61750,112250}},
+{"3",{ 61250, 61250,103250, 0, 55250, 62250, 62250, 86250,175250,119250}},
+{"4",{ 67250, 67250,171250, 0, 62250, 82250,175250, 95250,183250,126250}},
+{"5",{ 77250, 77250,177250, 0,175250,175250,182250,102250,191250,133250}},
+{"5A",{ 0, 0, 0, 0, 0, 0, 0,138250, 0, 0}},
+{"6",{ 83250, 83250,183250, 0,182250,183750,189250,175250,199250,140250}},
+{"7",{175250,175250,189250, 0,189250,192250,196250,182250,207250,147250}},
+{"8",{181250,181250,193250, 0,196250,201250,203250,189250,215250,154250}},
+{"9",{187250,187250,199250, 0,203250,210250,210250,196250, 0,161250}},
+{"10",{193250,193250,205250, 0,210250,210250,217250,209250, 0,168250}},
+{"11",{199250,199250,211250, 0,217250,217250, 0,216250, 0,231250}},
+{"12",{205250,205250,217250, 0,224250,224250, 0, 0, 0,238250}},
+
+{"13",{211250,211250, 0,109250, 0, 0, 0, 0, 0,245250}},
+{"14",{471250,121250, 0,115250, 0, 0, 0, 0, 0,252250}},
+{"15",{477250,127250, 0,121250, 0, 0, 0, 0, 0,259250}},
+{"16",{483250,133250, 0,127250, 0, 0, 0, 0, 0,266250}},
+{"17",{489250,139250, 0,133250, 0, 0, 0, 0, 0,273250}},
+{"18",{495250,145250, 0,139250, 0, 0, 0, 0, 0,280250}},
+{"19",{501250,151250, 0,145250, 0, 0, 0, 0, 0,287250}},
+{"20",{507250,157250, 0,151250, 0, 0, 0, 0, 0,294250}},
+
+{"21",{513250,163250, 0,157250,471250, 0, 0, 0,471250,303250}},
+{"22",{519250,169250, 0,165250,479250, 0, 0, 0,479250,311250}},
+{"23",{525250,217250, 0,223250,478250, 0, 0, 0,487250,319250}},
+{"24",{531250,223250, 0,231250,495250, 0, 0, 0,495250,327250}},
+{"25",{537250,229250, 0,237250,503250, 0, 0, 0,503250,335250}},
+{"26",{543250,235250, 0,243250,511250, 0, 0, 0,511250,343250}},
+{"27",{549250,241250, 0,249250,519250, 0, 0, 0,519250,351250}},
+{"28",{555250,247250, 0,253250,527250, 0, 0, 0,527250,359250}},
+{"29",{561250,253250, 0,259250,535250, 0, 0, 0,535250,367250}},
+{"30",{567250,259250, 0,265250,543250, 0, 0, 0,543250,375250}},
+{"31",{573250,265250, 0,271250,551250, 0, 0, 0,551250,383250}},
+{"32",{579250,271250, 0,277250,559250, 0, 0, 0,559250,391250}},
+{"33",{585250,277250, 0,283250,567250, 0, 0, 0,567250,399250}},
+{"34",{591250,283250, 0,289250,575250, 0, 0, 0,575250,407250}},
+{"35",{597250,289250, 0,295250,583250, 0, 0, 0,583250,415250}},
+{"36",{603250,295250, 0,301250,591250, 0, 0, 0,591250,423250}},
+{"37",{609250,301250, 0,307250,599250, 0, 0, 0,599250,431250}},
+{"38",{615250,307250, 0,313250,607250, 0, 0, 0,607250,439250}},
+{"39",{621250,313250, 0,319250,615250, 0, 0, 0,615250,447250}},
+{"40",{627250,319250, 0,325250,623250, 0, 0, 0,623250,455250}},
+{"41",{633250,325250, 0,331250,631250, 0, 0, 0,631250,463250}},
+{"42",{639250,331250, 0,337250,639250, 0, 0, 0,639250, 0}},
+{"43",{645250,337250, 0,343250,647250, 0, 0, 0,647250, 0}},
+{"44",{651250,343250, 0,349250,655250, 0, 0, 0,655250, 0}},
+{"45",{657250,349250,663250,355250,663250, 0, 0, 0,663250, 0}},
+{"46",{663250,355250,669250,361250,671250, 0, 0, 0,671250, 0}},
+{"47",{669250,361250,675250,367250,679250, 0, 0, 0,679250, 0}},
+{"48",{675250,367250,681250,373250,687250, 0, 0, 0,687250, 0}},
+{"49",{681250,373250,687250,379250,695250, 0, 0, 0,695250, 0}},
+{"50",{687250,379250,693250,385250,703250, 0, 0, 0,703250, 0}},
+{"51",{693250,385250,699250,391250,711250, 0, 0, 0,711250, 0}},
+{"52",{699250,391250,705250,397250,719250, 0, 0, 0,719250, 0}},
+{"53",{705250,397250,711250,403250,727250, 0, 0, 0,727250, 0}},
+{"54",{711250,403250,717250,409250,735250, 0, 0, 0,735250, 0}},
+{"55",{717250,409250,723250,415250,743250, 0, 0, 0,743250, 0}},
+{"56",{723250,415250,729250,421250,751250, 0, 0, 0,751250, 0}},
+{"57",{729250,421250,735250,427250,759250, 0, 0, 0,759250, 0}},
+{"58",{735250,427250,741250,433250,767250, 0, 0, 0,767250, 0}},
+{"59",{741250,433250,747250,439250,775250, 0, 0, 0,775250, 0}},
+{"60",{747250,439250,753250,445250,783250, 0, 0, 0,783250, 0}},
+{"61",{753250,445250,759250,451250,791250, 0, 0, 0,791250, 0}},
+{"62",{759250,451250,765250,457250,799250, 0, 0, 0,799250, 0}},
+{"63",{765250,457250, 0,463250,807250, 0, 0, 0,807250, 0}},
+{"64",{771250,463250, 0, 0,815250, 0, 0, 0,815250, 0}},
+{"65",{777250,469250, 0, 0,823250, 0, 0, 0,823250, 0}},
+{"66",{783250,475250, 0, 0,831250, 0, 0, 0,831250, 0}},
+{"67",{789250,481250, 0, 0,839250, 0, 0, 0,839250, 0}},
+{"68",{795250,487250, 0, 0,847250, 0, 0, 0,847250, 0}},
+{"69",{801250,493250, 0, 0,855250, 0, 0, 0,855250, 0}},
+
+{"70",{807250,499250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"71",{813250,505250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"72",{819250,511250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"73",{825250,517250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"74",{831250,523250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"75",{837250,529250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"76",{843250,535250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"77",{849250,541250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"78",{855250,547250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"79",{861250,553250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"80",{867250,559250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"81",{873250,565250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"82",{879250,571250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"83",{885250,577250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"84",{ 0,583250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"85",{ 0,589250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"86",{ 0,595250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"87",{ 0,601250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"88",{ 0,607250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"89",{ 0,613250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"90",{ 0,619250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"91",{ 0,625250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"92",{ 0,631250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"93",{ 0,637250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"94",{ 0,643250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"95",{ 0, 91250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"96",{ 0, 97250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"97",{ 0,103250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"98",{ 0,109250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"99",{ 0,115250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"100",{ 0,649250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"101",{ 0,655250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"102",{ 0,661250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"103",{ 0,667250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"104",{ 0,673250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"105",{ 0,679250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"106",{ 0,685250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"107",{ 0,691250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"108",{ 0,697250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"109",{ 0,703250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"110",{ 0,709250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"111",{ 0,715250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"112",{ 0,721250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"113",{ 0,727250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"114",{ 0,733250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"115",{ 0,739250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"116",{ 0,745250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"117",{ 0,751250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"118",{ 0,757250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"119",{ 0,763250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"120",{ 0,769250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"121",{ 0,775250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"122",{ 0,781250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"123",{ 0,787250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"124",{ 0,793250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"125",{ 0,799250, 0, 0, 0, 0, 0, 0, 0, 0}},
+
+{"T7",{ 0, 8250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"T8",{ 0, 14250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"T9",{ 0, 20250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"T10",{ 0, 26250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"T11",{ 0, 32250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"T12",{ 0, 38250, 0, 0, 0, 0, 0, 0, 0, 0}},
+{"T13",{ 0, 44250, 0, 0, 0, 0, 0, 0, 0, 0}}
+};
diff --git a/channel.h b/channel.h
index a2a60ef..6355788 100644
--- a/channel.h
+++ b/channel.h
@@ -2,12 +2,14 @@ struct CHANNEL {
char *name;
char *key;
+ char *cname; /* name of the channel */
+ int channel; /* index into tvtuner[] */
+ int fine;
+ int freq;
+
int capture;
int source;
int norm;
- int channel;
- int fine;
- int freq;
int color;
int bright;
@@ -25,9 +27,9 @@ extern int cur_sender, cur_channel, cur_fine, cur_norm, cur_input;
extern int chan_tab;
extern struct STRTAB chan_names[];
-int freq2chan(int f);
-int cf2freq(int chan, int fine);
-int freq2fine(int f);
+int lookup_channel(char *channel);
+int get_freq(int i);
+int cf2freq(char *name, int fine);
void read_config();
diff --git a/channels.h b/channels.h
new file mode 100644
index 0000000..d38ddf4
--- /dev/null
+++ b/channels.h
@@ -0,0 +1,106 @@
+/*
+ * Worldwide channel/frequency list
+ *
+ * Nathan Laredo (laredo@broked.net)
+ *
+ * Frequencies are given in kHz
+ */
+#define NTSC_AUDIO_CARRIER 4500
+#define PAL_AUDIO_CARRIER_I 6000
+#define PAL_AUDIO_CARRIER_BGHN 5500
+#define PAL_AUDIO_CARRIER_MN 4500
+#define PAL_AUDIO_CARRIER_D 6500
+#define SEACAM_AUDIO_DKK1L 6500
+#define SEACAM_AUDIO_BG 5500
+/* NICAM 728 32-kHz, 14-bit digital stereo audio is transmitted in 1ms frames
+ containing 8 bits frame sync, 5 bits control, 11 bits additional data, and
+ 704 bits audio data. The bit rate is reduced by transmitting only 10 bits
+ plus parity of each 14 bit sample, the largest sample in a frame determines
+ which 10 bits are transmitted. The parity bits for audio samples also
+ specify the scaling factor used for that channel during that frame. The
+ companeded audio data is interleaved to reduce the influence of dropouts
+ and the whole frame except for sync bits is scrambled for spectrum shaping.
+ Data is modulated using QPSK, at below following subcarrier freqs */
+#define NICAM728_PAL_BGH 5850
+#define NICAM728_PAL_I 6552
+
+/* COMPREHENSIVE LIST OF FORMAT BY COUNTRY
+ (M) NTSC used in:
+ Antigua, Aruba, Bahamas, Barbados, Belize, Bermuda, Bolivia, Burma,
+ Canada, Chile, Colombia, Costa Rica, Cuba, Curacao, Dominican Republic,
+ Ecuador, El Salvador, Guam Guatemala, Honduras, Jamaica, Japan,
+ South Korea, Mexico, Montserrat, Myanmar, Nicaragua, Panama, Peru,
+ Philippines, Puerto Rico, St Christopher and Nevis, Samoa, Suriname,
+ Taiwan, Trinidad/Tobago, United States, Venezuela, Virgin Islands
+ (B) PAL used in:
+ Albania, Algeria, Australia, Austria, Bahrain, Bangladesh, Belgium,
+ Bosnia-Herzegovinia, Brunei Darussalam, Cambodia, Cameroon, Croatia,
+ Cyprus, Denmark, Egypt, Ethiopia, Equatorial Guinea, Finland, Germany,
+ Ghana, Gibraltar, Greenland, Iceland, India, Indonesia, Israel, Italy,
+ Jordan, Kenya, Kuwait, Liberia, Libya, Luxembourg, Malaysa, Maldives,
+ Malta, Nepal, Netherlands, New Zeland, Nigeria, Norway, Oman, Pakistan,
+ Papua New Guinea, Portugal, Qatar, Sao Tome and Principe, Saudi Arabia,
+ Seychelles, Sierra Leone, Singapore, Slovenia, Somali, Spain,
+ Sri Lanka, Sudan, Swaziland, Sweden, Switzeland, Syria, Thailand,
+ Tunisia, Turkey, Uganda, United Arab Emirates, Yemen
+ (N) PAL used in: (Combination N = 4.5MHz audio carrier, 3.58MHz burst)
+ Argentina (Combination N), Paraguay, Uruguay
+ (M) PAL (525/60, 3.57MHz burst) used in:
+ Brazil
+ (G) PAL used in:
+ Albania, Algeria, Austria, Bahrain, Bosnia/Herzegovinia, Cambodia,
+ Cameroon, Croatia, Cyprus, Denmark, Egypt, Ethiopia, Equatorial Guinea,
+ Finland, Germany, Gibraltar, Greenland, Iceland, Israel, Italy, Jordan,
+ Kenya, Kuwait, Liberia, Libya, Luxembourg, Malaysia, Monaco,
+ Mozambique, Netherlands, New Zealand, Norway, Oman, Pakistan,
+ Papa New Guinea, Portugal, Qatar, Romania, Sierra Leone, Singapore,
+ Slovenia, Somalia, Spain, Sri Lanka, Sudan, Swaziland, Sweeden,
+ Switzerland, Syria, Thailand, Tunisia, Turkey, United Arab Emirates,
+ Yemen, Zambia, Zimbabwe
+ (D) PAL used in:
+ China, North Korea, Romania
+ (H) PAL used in:
+ Belgium
+ (I) PAL used in:
+ Angola, Botswana, Gambia, Guinea-Bissau, Hong Kong, Ireland, Lesotho,
+ Malawi, Nambia, Nigeria, South Africa, Tanzania, United Kingdom,
+ Zanzibar
+ (B) SECAM used in:
+ Djibouti, Greece, Iran, Iraq, Lebanon, Mali, Mauritania, Mauritus,
+ Morocco
+ (D) SECAM used in:
+ Afghanistan, Armenia, Azerbaijan, Belarus, Bulgaria, Czech Republic,
+ Estonia, Georgia, Hungary, Zazakhstan, Lithuania, Mongolia, Moldova,
+ Poland, Russia, Slovak Republic, Ukraine, Vietnam
+ (G) SECAM used in:
+ Greecem Iran, Iraq, Mali, Mauritus, Morocco, Saudi Arabia
+ (K) SECAM used in:
+ Armenia, Azerbaijan, Bulgaria, Czech Republic, Estonia, Georgia,
+ Hungary, Kazakhstan, Lithuania, Madagascar, Moldova, Poland, Russia,
+ Slovak Republic, Ukraine, Vietnam
+ (K1) SECAM used in:
+ Benin, Burkina Faso, Burundi, Chad, Cape Verde, Central African
+ Republic, Comoros, Congo, Gabon, Madagascar, Niger, Rwanda, Senegal,
+ Togo, Zaire
+ (L) SECAM used in:
+ France
+*/
+struct freqlist {
+ char name[4];
+ int freq[10];
+};
+
+#define NTSC_BROADCAST 0
+#define NTSC_CABLE 1
+#define NTSC_JP_BCAST 2
+#define NTSC_JP_CABLE 3
+#define PAL_EUROPE 4
+#define PAL_ITALY 5
+#define PAL_NEWZEALAND 6
+#define PAL_AUSTRALIA 7
+#define PAL_UHF_GHI 8
+#define PAL_IRELAND 8
+#define PAL_CABLE_BG 9
+
+extern struct freqlist tvtuner[];
+#define CHAN_ENTRIES 148
diff --git a/config.h.in b/config.h.in
index 35cc5ca..785187c 100644
--- a/config.h.in
+++ b/config.h.in
@@ -3,8 +3,17 @@
/* Define if the X Window System is missing or not being used. */
#undef X_DISPLAY_MISSING
+/* use kernel include (videodev.h) */
+#undef USE_KERNEL_VIDEODEV
+
+/* MIT shared memory extention */
+#undef HAVE_MITSHM
+
/* Define if you have the Xxf86dga library (-lXxf86dga). */
#undef HAVE_LIBXXF86DGA
+/* Define if you have the Xxf86vm library (-lXxf86vm). */
+#undef HAVE_LIBXXF86VM
+
/* Define if you have the jpeg library (-ljpeg). */
#undef HAVE_LIBJPEG
diff --git a/configure b/configure
index 19a9572..1e2d0e9 100755
--- a/configure
+++ b/configure
@@ -755,12 +755,16 @@ else
fi
echo "$ac_t""$CPP" 1>&6
-for ac_prog in $CCC c++ g++ gcc CC cxx cc++
+
+if test "$KDEDIR" != "" -a -d "$KDEDIR"; then
+ KRADIO=kradio
+ # for kradio we need c++
+ for ac_prog in $CCC c++ g++ gcc CC cxx cc++
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:764: checking for $ac_word" >&5
+echo "configure:768: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -791,7 +795,7 @@ test -n "$CXX" || CXX="gcc"
echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:795: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
+echo "configure:799: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5
ac_ext=C
# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -801,11 +805,11 @@ ac_link='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $L
cross_compiling=$ac_cv_prog_cxx_cross
cat > conftest.$ac_ext <<EOF
-#line 805 "configure"
+#line 809 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
-if { (eval echo configure:809: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
ac_cv_prog_cxx_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
@@ -831,12 +835,12 @@ if test $ac_cv_prog_cxx_works = no; then
{ echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:835: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:839: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6
cross_compiling=$ac_cv_prog_cxx_cross
echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6
-echo "configure:840: checking whether we are using GNU C++" >&5
+echo "configure:844: checking whether we are using GNU C++" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -845,7 +849,7 @@ else
yes;
#endif
EOF
-if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:849: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:853: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gxx=yes
else
ac_cv_prog_gxx=no
@@ -860,7 +864,7 @@ if test $ac_cv_prog_gxx = yes; then
ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS=
echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6
-echo "configure:864: checking whether ${CXX-g++} accepts -g" >&5
+echo "configure:868: checking whether ${CXX-g++} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -887,6 +891,11 @@ else
test "${CXXFLAGS+set}" = set || CXXFLAGS="-g"
fi
+else
+ KRADIO=""
+fi
+
+
ac_aux_dir=
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
if test -f $ac_dir/install-sh; then
@@ -917,7 +926,7 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:921: checking for a BSD compatible install" >&5
+echo "configure:930: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -971,7 +980,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:975: checking for $ac_word" >&5
+echo "configure:984: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_DEPEND'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1007,7 +1016,7 @@ test -n "$DEPEND" || DEPEND="true"
# Uses ac_ vars as temps to allow command line to override cache and checks.
# --without-x overrides everything else, but does not touch the cache.
echo $ac_n "checking for X""... $ac_c" 1>&6
-echo "configure:1011: checking for X" >&5
+echo "configure:1020: checking for X" >&5
# Check whether --with-x or --without-x was given.
if test "${with_x+set}" = set; then
@@ -1069,12 +1078,12 @@ if test "$ac_x_includes" = NO; then
# First, try using that file with no special directory specified.
cat > conftest.$ac_ext <<EOF
-#line 1073 "configure"
+#line 1082 "configure"
#include "confdefs.h"
#include <$x_direct_test_include>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1078: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1087: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1143,14 +1152,14 @@ if test "$ac_x_libraries" = NO; then
ac_save_LIBS="$LIBS"
LIBS="-l$x_direct_test_library $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1147 "configure"
+#line 1156 "configure"
#include "confdefs.h"
int main() {
${x_direct_test_function}()
; return 0; }
EOF
-if { (eval echo configure:1154: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1163: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
LIBS="$ac_save_LIBS"
# We can link X programs with no special library path.
@@ -1256,17 +1265,17 @@ else
case "`(uname -sr) 2>/dev/null`" in
"SunOS 5"*)
echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6
-echo "configure:1260: checking whether -R must be followed by a space" >&5
+echo "configure:1269: checking whether -R must be followed by a space" >&5
ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries"
cat > conftest.$ac_ext <<EOF
-#line 1263 "configure"
+#line 1272 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
-if { (eval echo configure:1270: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1279: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
ac_R_nospace=yes
else
@@ -1282,14 +1291,14 @@ rm -f conftest*
else
LIBS="$ac_xsave_LIBS -R $x_libraries"
cat > conftest.$ac_ext <<EOF
-#line 1286 "configure"
+#line 1295 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
-if { (eval echo configure:1293: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1302: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
ac_R_space=yes
else
@@ -1321,7 +1330,7 @@ rm -f conftest*
# libraries were built with DECnet support. And karl@cs.umb.edu says
# the Alpha needs dnet_stub (dnet does not exist).
echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6
-echo "configure:1325: checking for dnet_ntoa in -ldnet" >&5
+echo "configure:1334: checking for dnet_ntoa in -ldnet" >&5
ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1329,7 +1338,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldnet $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1333 "configure"
+#line 1342 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1340,7 +1349,7 @@ int main() {
dnet_ntoa()
; return 0; }
EOF
-if { (eval echo configure:1344: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1353: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1362,7 +1371,7 @@ fi
if test $ac_cv_lib_dnet_dnet_ntoa = no; then
echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6
-echo "configure:1366: checking for dnet_ntoa in -ldnet_stub" >&5
+echo "configure:1375: checking for dnet_ntoa in -ldnet_stub" >&5
ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1370,7 +1379,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldnet_stub $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1374 "configure"
+#line 1383 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1381,7 +1390,7 @@ int main() {
dnet_ntoa()
; return 0; }
EOF
-if { (eval echo configure:1385: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1394: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1410,12 +1419,12 @@ fi
# The nsl library prevents programs from opening the X display
# on Irix 5.2, according to dickey@clark.net.
echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6
-echo "configure:1414: checking for gethostbyname" >&5
+echo "configure:1423: checking for gethostbyname" >&5
if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1419 "configure"
+#line 1428 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char gethostbyname(); below. */
@@ -1438,7 +1447,7 @@ gethostbyname();
; return 0; }
EOF
-if { (eval echo configure:1442: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1451: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_gethostbyname=yes"
else
@@ -1459,7 +1468,7 @@ fi
if test $ac_cv_func_gethostbyname = no; then
echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
-echo "configure:1463: checking for gethostbyname in -lnsl" >&5
+echo "configure:1472: checking for gethostbyname in -lnsl" >&5
ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1467,7 +1476,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lnsl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1471 "configure"
+#line 1480 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1478,7 +1487,7 @@ int main() {
gethostbyname()
; return 0; }
EOF
-if { (eval echo configure:1482: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1491: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1508,12 +1517,12 @@ fi
# -lsocket must be given before -lnsl if both are needed.
# We assume that if connect needs -lnsl, so does gethostbyname.
echo $ac_n "checking for connect""... $ac_c" 1>&6
-echo "configure:1512: checking for connect" >&5
+echo "configure:1521: checking for connect" >&5
if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1517 "configure"
+#line 1526 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char connect(); below. */
@@ -1536,7 +1545,7 @@ connect();
; return 0; }
EOF
-if { (eval echo configure:1540: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1549: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_connect=yes"
else
@@ -1557,7 +1566,7 @@ fi
if test $ac_cv_func_connect = no; then
echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6
-echo "configure:1561: checking for connect in -lsocket" >&5
+echo "configure:1570: checking for connect in -lsocket" >&5
ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1565,7 +1574,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lsocket $X_EXTRA_LIBS $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1569 "configure"
+#line 1578 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1576,7 +1585,7 @@ int main() {
connect()
; return 0; }
EOF
-if { (eval echo configure:1580: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1589: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1600,12 +1609,12 @@ fi
# gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX.
echo $ac_n "checking for remove""... $ac_c" 1>&6
-echo "configure:1604: checking for remove" >&5
+echo "configure:1613: checking for remove" >&5
if eval "test \"`echo '$''{'ac_cv_func_remove'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1609 "configure"
+#line 1618 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char remove(); below. */
@@ -1628,7 +1637,7 @@ remove();
; return 0; }
EOF
-if { (eval echo configure:1632: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1641: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_remove=yes"
else
@@ -1649,7 +1658,7 @@ fi
if test $ac_cv_func_remove = no; then
echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6
-echo "configure:1653: checking for remove in -lposix" >&5
+echo "configure:1662: checking for remove in -lposix" >&5
ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1657,7 +1666,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lposix $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1661 "configure"
+#line 1670 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1668,7 +1677,7 @@ int main() {
remove()
; return 0; }
EOF
-if { (eval echo configure:1672: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1681: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1692,12 +1701,12 @@ fi
# BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
echo $ac_n "checking for shmat""... $ac_c" 1>&6
-echo "configure:1696: checking for shmat" >&5
+echo "configure:1705: checking for shmat" >&5
if eval "test \"`echo '$''{'ac_cv_func_shmat'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1701 "configure"
+#line 1710 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char shmat(); below. */
@@ -1720,7 +1729,7 @@ shmat();
; return 0; }
EOF
-if { (eval echo configure:1724: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1733: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_shmat=yes"
else
@@ -1741,7 +1750,7 @@ fi
if test $ac_cv_func_shmat = no; then
echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6
-echo "configure:1745: checking for shmat in -lipc" >&5
+echo "configure:1754: checking for shmat in -lipc" >&5
ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1749,7 +1758,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lipc $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1753 "configure"
+#line 1762 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1760,7 +1769,7 @@ int main() {
shmat()
; return 0; }
EOF
-if { (eval echo configure:1764: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1773: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1793,7 +1802,7 @@ fi
# libraries we check for below, so use a different variable.
# --interran@uluru.Stanford.EDU, kb@cs.umb.edu.
echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6
-echo "configure:1797: checking for IceConnectionNumber in -lICE" >&5
+echo "configure:1806: checking for IceConnectionNumber in -lICE" >&5
ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1801,7 +1810,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lICE $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1805 "configure"
+#line 1814 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1812,7 +1821,7 @@ int main() {
IceConnectionNumber()
; return 0; }
EOF
-if { (eval echo configure:1816: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1825: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1846,7 +1855,7 @@ fi
echo $ac_n "checking for Xaw3dComputeTopShadowRGB in -lXaw3d""... $ac_c" 1>&6
-echo "configure:1850: checking for Xaw3dComputeTopShadowRGB in -lXaw3d" >&5
+echo "configure:1859: checking for Xaw3dComputeTopShadowRGB in -lXaw3d" >&5
ac_lib_var=`echo Xaw3d'_'Xaw3dComputeTopShadowRGB | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1854,7 +1863,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lXaw3d $X_LIBS $X_PRE_LIBS -lXext -lXmu -lXt -lX11 $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1858 "configure"
+#line 1867 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1865,7 +1874,7 @@ int main() {
Xaw3dComputeTopShadowRGB()
; return 0; }
EOF
-if { (eval echo configure:1869: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1878: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1889,15 +1898,15 @@ fi
echo $ac_n "checking for XF86DGAQueryExtension in -lXxf86dga""... $ac_c" 1>&6
-echo "configure:1893: checking for XF86DGAQueryExtension in -lXxf86dga" >&5
+echo "configure:1902: checking for XF86DGAQueryExtension in -lXxf86dga" >&5
ac_lib_var=`echo Xxf86dga'_'XF86DGAQueryExtension | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_save_LIBS="$LIBS"
-LIBS="-lXxf86dga $X_LIBS $X_PRE_LIBS -lXext -lX11 $LIBS"
+LIBS="-lXxf86dga $X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1901 "configure"
+#line 1910 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1908,7 +1917,7 @@ int main() {
XF86DGAQueryExtension()
; return 0; }
EOF
-if { (eval echo configure:1912: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1921: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1935,9 +1944,99 @@ else
echo "$ac_t""no" 1>&6
fi
+echo $ac_n "checking for XF86VidModeQueryExtension in -lXxf86vm""... $ac_c" 1>&6
+echo "configure:1949: checking for XF86VidModeQueryExtension in -lXxf86vm" >&5
+ac_lib_var=`echo Xxf86vm'_'XF86VidModeQueryExtension | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lXxf86vm $X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1957 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char XF86VidModeQueryExtension();
+
+int main() {
+XF86VidModeQueryExtension()
+; return 0; }
+EOF
+if { (eval echo configure:1968: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo Xxf86vm | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lXxf86vm $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for XShmAttach in -lXext""... $ac_c" 1>&6
+echo "configure:1996: checking for XShmAttach in -lXext" >&5
+ac_lib_var=`echo Xext'_'XShmAttach | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lXext $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2004 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char XShmAttach();
+
+int main() {
+XShmAttach()
+; return 0; }
+EOF
+if { (eval echo configure:2015: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_MITSHM 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
echo $ac_n "checking for jpeg_start_compress in -ljpeg""... $ac_c" 1>&6
-echo "configure:1941: checking for jpeg_start_compress in -ljpeg" >&5
+echo "configure:2040: checking for jpeg_start_compress in -ljpeg" >&5
ac_lib_var=`echo jpeg'_'jpeg_start_compress | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1945,7 +2044,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ljpeg $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1949 "configure"
+#line 2048 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1956,7 +2055,7 @@ int main() {
jpeg_start_compress()
; return 0; }
EOF
-if { (eval echo configure:1960: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2059: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1985,25 +2084,47 @@ fi
-# Check whether --with-bttv or --without-bttv was given.
+kernel_v4l=0
+
+cat > conftest.$ac_ext <<EOF
+#line 2091 "configure"
+#include "confdefs.h"
+#include <linux/videodev.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "video_mmap" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define USE_KERNEL_VIDEODEV 1
+EOF
+ kernel_v4l=1
+fi
+rm -f conftest*
+
+
+echo
+if test "$kernel_v4l" = "1"; then
+ echo "*** using kernel's video4linux driver"
+ # dummy
+ bttvdir=.
+else
+ # Check whether --with-bttv or --without-bttv was given.
if test "${with_bttv+set}" = set; then
withval="$with_bttv"
bttvdir="$withval"
else
- bttvdir="bttv"
+ bttvdir="`pwd`/bttv"
fi
-
-
-echo -n "checking for bttv... "
-if test -f "$bttvdir/bttv.h"; then
- echo "in $bttvdir"
-else
- echo "no (you might want to try --with-path=/path_to_bttv)"
+
+ if test -f "$bttvdir/bttv.h"; then
+ echo "*** using bttv driver in $bttvdir"
+ else
+ echo "oops, no driver in $bttvdir"
+ exit 1
+ fi
fi
-
-if test "$KDEDIR" != ""; then KRADIO=kradio; else KRADIO=""; fi
-
+echo
trap '' 1 2 15
cat > confcache <<\EOF
@@ -2139,6 +2260,7 @@ s%@mandir@%$mandir%g
s%@CC@%$CC%g
s%@CPP@%$CPP%g
s%@CXX@%$CXX%g
+s%@KRADIO@%$KRADIO%g
s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
s%@INSTALL_DATA@%$INSTALL_DATA%g
s%@DEPEND@%$DEPEND%g
@@ -2149,7 +2271,6 @@ s%@X_EXTRA_LIBS@%$X_EXTRA_LIBS%g
s%@x_libraries@%$x_libraries%g
s%@XAWLIB@%$XAWLIB%g
s%@bttvdir@%$bttvdir%g
-s%@KRADIO@%$KRADIO%g
CEOF
EOF
diff --git a/configure.in b/configure.in
index 456df19..da68e37 100644
--- a/configure.in
+++ b/configure.in
@@ -7,7 +7,16 @@ dnl ---------------------------------------------------------------------
dnl Checks for programs.
AC_PROG_CC
AC_PROG_CPP
-AC_PROG_CXX
+
+if test "$KDEDIR" != "" -a -d "$KDEDIR"; then
+ KRADIO=kradio
+ # for kradio we need c++
+ AC_PROG_CXX
+else
+ KRADIO=""
+fi
+AC_SUBST(KRADIO)
+
AC_PROG_INSTALL
AC_CHECK_PROGS(DEPEND,gccmakedep makedepend,true)
@@ -30,30 +39,40 @@ AC_CHECK_LIB(Xaw3d, Xaw3dComputeTopShadowRGB,
AC_SUBST(XAWLIB)
AC_CHECK_LIB(Xxf86dga, XF86DGAQueryExtension,,,
- $X_LIBS $X_PRE_LIBS -lXext -lX11)
+ $X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS)
+AC_CHECK_LIB(Xxf86vm, XF86VidModeQueryExtension,,,
+ $X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS)
+AC_CHECK_LIB(Xext, XShmAttach,AC_DEFINE(HAVE_MITSHM),,
+ $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS)
AC_CHECK_LIB(jpeg, jpeg_start_compress,,,)
dnl ---------------------------------------------------------------------
dnl video dev checks
-AC_ARG_WITH(bttv,
- [ --with-bttv=/path give the path of the bttv package],
- bttvdir="$withval", bttvdir="bttv")
-AC_SUBST(bttvdir)
+kernel_v4l=0
-echo -n "checking for bttv... "
-if test -f "$bttvdir/bttv.h"; then
- echo "in $bttvdir"
-dnl AC_DEFINE(HAVE_BTTV)
+AC_EGREP_HEADER(video_mmap, linux/videodev.h,
+ AC_DEFINE(USE_KERNEL_VIDEODEV) kernel_v4l=1,)
+
+echo
+if test "$kernel_v4l" = "1"; then
+ echo "*** using kernel's video4linux driver"
+ # dummy
+ bttvdir=.
else
- echo "no (you might want to try --with-path=/path_to_bttv)"
+ AC_ARG_WITH(bttv,
+ [ --with-bttv=/path give the path of the bttv package],
+ bttvdir="$withval", bttvdir="`pwd`/bttv")
+ AC_SUBST(bttvdir)
+ if test -f "$bttvdir/bttv.h"; then
+ echo "*** using bttv driver in $bttvdir"
+ else
+ echo "oops, no driver in $bttvdir"
+ exit 1
+ fi
fi
-
-dnl ---------------------------------------------------------------------
-dnl KDE (kradio)
-if test "$KDEDIR" != ""; then KRADIO=kradio; else KRADIO=""; fi
-AC_SUBST(KRADIO)
+echo
dnl ---------------------------------------------------------------------
AC_OUTPUT(Makefile)
diff --git a/dump-mixers.c b/dump-mixers.c
new file mode 100644
index 0000000..a7abf96
--- /dev/null
+++ b/dump-mixers.c
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+
+char *labels[] = SOUND_DEVICE_LABELS;
+char *names[] = SOUND_DEVICE_NAMES;
+
+int
+dump_mixer(char *devname)
+{
+ struct mixer_info info;
+ int mix,i,devmask,recmask,recsrc,stereomask,volume;
+
+ if (-1 == (mix = open(devname,O_RDONLY)))
+ return -1;
+
+ printf("%s",devname);
+ if (-1 != ioctl(mix,SOUND_MIXER_INFO,&info))
+ printf(" = %s (%s)",info.id,info.name);
+ printf("\n");
+
+ if (-1 == ioctl(mix,MIXER_READ(SOUND_MIXER_DEVMASK),&devmask) ||
+ -1 == ioctl(mix,MIXER_READ(SOUND_MIXER_STEREODEVS),&stereomask) ||
+ -1 == ioctl(mix,MIXER_READ(SOUND_MIXER_RECMASK),&recmask) ||
+ -1 == ioctl(mix,MIXER_READ(SOUND_MIXER_RECSRC),&recsrc)) {
+ perror("mixer ioctl");
+ return -1;
+ }
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if ((1<<i) & devmask) {
+ if (-1 == ioctl(mix,MIXER_READ(i),&volume)) {
+ perror("mixer read volume");
+ return -1;
+ }
+ printf(" %-10s (%2d) : %s %s%s",
+ names[i],i,
+ (1<<i) & stereomask ? "stereo" : "mono ",
+ (1<<i) & recmask ? "rec" : " ",
+ (1<<i) & recsrc ? "*" : " ");
+ if ((1<<i) & stereomask)
+ printf(" %d/%d\n",(volume >> 8) & 0xff,volume & 0xff);
+ else
+ printf(" %d\n",volume & 0xff);
+ }
+ }
+ return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ char devname[32];
+ int i;
+
+ for (i = 0;; i++) {
+ sprintf(devname,"/dev/mixer%d",i);
+ if (-1 == dump_mixer(devname))
+ break;
+ }
+ return 0;
+}
diff --git a/grab-bttv.c b/grab-bttv.c
deleted file mode 100644
index ac7094c..0000000
--- a/grab-bttv.c
+++ /dev/null
@@ -1,286 +0,0 @@
-#include "config.h"
-#ifdef HAVE_BTTV
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <math.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include <X11/Intrinsic.h>
-
-#define OLDBTTV
-#include "bttv.h"
-#include "bt848.h"
-#include "videodev.h" /* audio */
-
-#include "grab.h"
-
-/* ---------------------------------------------------------------------- */
-
-static struct bttv_window wtw;
-static struct cliprec cr[MAX_CLIPRECS];
-static int overlay;
-static int fwintv = -1;
-static int framecount;
-static struct timeval start;
-
-/* PAL NTSC */
-static int maxwidth[] = { 768, 640 };
-static int maxheight[] = { 576, 480 };
-
-static struct STRTAB normtab[] = {
- { 0, "PAL" },
- { 1, "NTSC" },
- { 2, "SECAM" },
- { -1, NULL }
-};
-
-static struct STRTAB srctab[] = {
- { 0, "Television" },
- { 1, "Composite1" },
- { 2, "Composite2" },
- { 3, "SVHS" },
- { -1, NULL }
-};
-
-/* ---------------------------------------------------------------------- */
-
-static int
-grab_open(char *filename, int sw, int sh, int format, void *base)
-{
- int val;
-
- if (-1 != fwintv)
- goto err;
-
- if (-1 == (fwintv=open(filename ? filename : "/dev/bttv",O_RDWR)))
- goto err;
-
- if (debug)
- fprintf(stderr, "bttv: open\n");
-
- /* init bttv */
- ioctl(fwintv, BTTV_GETWTW, &wtw);
- wtw.x = 0;
- wtw.y = 0;
- wtw.cropx = 0;
- wtw.cropy = 0;
- wtw.swidth = sw;
- wtw.sheight = sh;
-
- wtw.norm = 0;
- wtw.cropwidth = maxwidth[wtw.norm];
- wtw.cropheight= maxheight[wtw.norm];
- wtw.width = maxwidth[wtw.norm];
- wtw.height = maxheight[wtw.norm];
-
- /* defaults */
- val = 254; ioctl(fwintv, BTTV_COLOR, &val);
- val = 254; ioctl(fwintv, BTTV_CONTRAST, &val);
- val = 0; ioctl(fwintv, BTTV_BRIGHT, &val);
- val = 0; ioctl(fwintv, BTTV_HUE, &val);
- if (NULL != base)
- ioctl(fwintv, BTTV_SETVIRTADR, &base);
-
- gettimeofday(&start,NULL);
- framecount = 0;
- return 0;
-
-err:
- if (fwintv != -1) {
- close(fwintv);
- fwintv = -1;
- }
- return -1;
-}
-
-static int
-grab_close()
-{
- if (-1 == fwintv)
- return 0;
-
- if (debug)
- fprintf(stderr, "bttv: close\n");
-
- close(fwintv);
- fwintv = -1;
- return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int
-grab_overlay(int x, int y, int width, int height, int format,
- struct OVERLAY_CLIP *oc, int count)
-{
- int i;
-
- ioctl(fwintv, BTTV_CAP_OFF, NULL);
- if (width == 0 || height == 0) {
- if (debug)
- fprintf(stderr, "bttv: overlay off\n");
- overlay = 0;
- return 0;
- }
-
- switch (format) {
- case VIDEO_RGB16:
- wtw.bpp = 2;
- wtw.color_fmt = BT848_COLOR_FMT_RGB16;
- break;
- case VIDEO_RGB24:
- wtw.bpp = 3;
- wtw.color_fmt = BT848_COLOR_FMT_RGB24;
- break;
- case VIDEO_RGB32:
- wtw.bpp = 4;
- wtw.color_fmt = BT848_COLOR_FMT_RGB32;
- break;
- default:
- TRAP("unsupported video format (overlay)");
- }
-
- wtw.bpl = wtw.swidth * wtw.bpp;
- wtw.x = x;
- wtw.y = y;
-#if 0
- wtw.cropx = 0;
- wtw.cropy = 0;
- wtw.cropwidth = width;
- wtw.cropheight= height;
-#endif
- wtw.width = width;
- wtw.height = height;
- wtw.interlace = ((wtw.height > maxheight[wtw.norm]/2) ||
- (wtw.width > maxwidth[wtw.norm]/2)) ? 1:0;
- ioctl(fwintv, BTTV_SETWTW, &wtw);
-
- for (i = 0; i < count; i++) {
- cr[i].x = oc[i].x1;
- cr[i].y = oc[i].y1;
- cr[i].x2 = oc[i].x2-1;
- cr[i].y2 = oc[i].y2-1;
- if (debug)
- fprintf(stderr,"bttv: clip=%d,%d->%d,%d\n",
- cr[i].x ,cr[i].y, cr[i].x2,cr[i].y2);
- }
- cr[MAX_CLIPRECS-1].x = count;
- ioctl(fwintv, BTTV_SETCLIP, cr);
-
- if (debug)
- fprintf(stderr,
- "bttv: overlay win=%dx%d+%d+%d, screen=%dx%d, %d clips\n",
- wtw.width,wtw.height, wtw.x,wtw.y,
- wtw.swidth,wtw.sheight,count);
-
- ioctl(fwintv, BTTV_CAP_ON, NULL);
- overlay = 1;
-
- return 0;
-}
-
-static int
-grab_tune(unsigned long freq)
-{
- if (debug)
- fprintf(stderr,"bttv: freq %.3f\n",(float)freq/16);
- ioctl(fwintv, BTTV_SETFREQ, &freq);
- return 0;
-}
-
-static int
-grab_input(int input, int norm)
-{
- if (-1 != input) {
- if (debug)
- fprintf(stderr,"bttv: input %s\n",srctab[input].str);
- ioctl(fwintv, BTTV_INPUT, &input);
- }
- if (-1 != norm) {
- if (debug)
- fprintf(stderr,"bttv: norm %s\n",normtab[norm].str);
- wtw.norm = norm;
- if (overlay)
- ioctl(fwintv, BTTV_SETWTW, &wtw);
- }
- return 0;
-}
-
-int
-grab_picture(int color, int bright, int hue, int contrast)
-{
- int val;
-
- if (color != -1) {
- val = color / 128;
- ioctl(fwintv,BTTV_COLOR,&val);
- }
- if (contrast != -1) {
- val = contrast / 128;
- ioctl(fwintv,BTTV_CONTRAST,&val);
- }
- if (bright != -1) {
- val = (bright / 256) - 128;
- ioctl(fwintv,BTTV_BRIGHT,&val);
- }
- if (hue != -1) {
- val = (hue / 256) - 128;
- ioctl(fwintv,BTTV_HUE,&val);
- }
- return 0;
-}
-
-static struct video_audio audio;
-
-int
-grab_audio(int mute, int volume, int *mode)
-{
- if (!audio.flags)
- ioctl(fwintv,VIDIOCGAUDIO,&audio);
- if (mute != -1) {
- if (mute)
- audio.flags |= VIDEO_AUDIO_MUTE;
- else
- audio.flags &= ~VIDEO_AUDIO_MUTE;
- }
- if (volume != -1)
- audio.volume = volume;
-
- audio.mode = mode ? *mode : 0;
- if (-1 == ioctl(fwintv,VIDIOCSAUDIO,&audio))
- perror("ioctl VIDIOCSAUDIO");
-
- if (mode) {
- if (-1 == ioctl(fwintv,VIDIOCGAUDIO,&audio))
- perror("ioctl VIDIOCGAUDIO");
- *mode = audio.mode;
- }
- return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-struct GRABBER grab_bttv = {
- "bttv",
- VIDEO_RGB16 | VIDEO_RGB24 | VIDEO_RGB32,
- CAN_AUDIO_VOLUME,
- normtab,srctab,
-
- grab_open,grab_close,
- grab_overlay,
- NULL,
- grab_tune,
- grab_input,
- grab_picture,
- grab_audio
-};
-
-#endif
diff --git a/grab-v4l.c b/grab-v4l.c
index eb2de8e..7082c02 100644
--- a/grab-v4l.c
+++ b/grab-v4l.c
@@ -17,16 +17,24 @@
#include "grab.h"
#include <asm/types.h> /* XXX glibc */
-#include "videodev.h"
-#include "bttv.h"
+
+#if USE_KERNEL_VIDEODEV
+# include <linux/videodev.h>
+#else
+# include "videodev.h"
+#endif
+
+#define MEM_SIZE 0x144000
/* ---------------------------------------------------------------------- */
/* prototypes */
-static int grab_open(char *filename, int sw, int sh, int format, void *base);
+static int grab_open(char *filename, int sw, int sh,
+ int format, int pixmap, void *base, int width);
static int grab_close();
static int grab_overlay(int x, int y, int width, int height, int format,
struct OVERLAY_CLIP *oc, int count);
+static void* grab_scr(void *dest, int width, int height);
static void* grab_one(int width, int height);
static int grab_tune(unsigned long freq);
static int grab_input(int input, int norm);
@@ -41,7 +49,7 @@ static char *device_cap[] = {
};
static char *device_pal[] = {
- "-", "grey", "hi240", "rgb565", "rgb24", "rgb32", "rgb555", NULL
+ "-", "grey", "hi240", "rgb16", "rgb24", "rgb32", "rgb15", NULL
};
static struct STRTAB norms[] = {
@@ -67,6 +75,11 @@ static struct video_window ov_win;
static struct video_clip ov_clips[32];
static struct video_buffer ov_fbuf;
+/* screen grab */
+static struct video_mmap gb_even;
+static struct video_mmap gb_odd;
+static int gb_count,even,pixmap_bytes;
+
static char *map = NULL;
/* state */
@@ -80,6 +93,7 @@ struct GRABBER grab_v4l = {
grab_open,grab_close,
grab_overlay,
+ grab_scr,
grab_one,
grab_tune,
grab_input,
@@ -90,7 +104,8 @@ struct GRABBER grab_v4l = {
/* ---------------------------------------------------------------------- */
static int
-grab_open(char *filename, int sw, int sh, int format, void *base)
+grab_open(char *filename, int sw, int sh,
+ int format, int pixmap, void *base, int width)
{
int i;
@@ -245,13 +260,34 @@ grab_open(char *filename, int sw, int sh, int format, void *base)
}
if (0 == strncmp(capability.name,"BT848",5)) {
- map = mmap(0,768*576*4,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
+ map = mmap(0,MEM_SIZE*2,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if ((char*)-1 == map)
perror("mmap");
}
else
map = (char*)-1;
+ switch (pixmap) {
+ case VIDEO_RGB15:
+ gb_even.format = gb_odd.format = 0x33; /* FIXME */
+ pixmap_bytes = 2;
+ break;
+ case VIDEO_RGB16:
+ gb_even.format = gb_odd.format = 0x22; /* FIXME */
+ pixmap_bytes = 2;
+ break;
+ case VIDEO_RGB24:
+ gb_even.format = gb_odd.format = 0x11; /* FIXME */
+ pixmap_bytes = 3;
+ break;
+ case VIDEO_RGB32:
+ gb_even.format = gb_odd.format = 0x11; /* FIXME (RGB24 too) */
+ pixmap_bytes = 4;
+ break;
+ }
+ gb_even.frame = 0;
+ gb_odd.frame = 1;
+
return 0;
err:
@@ -265,8 +301,14 @@ err:
static int
grab_close()
{
+ while (gb_count > 0) {
+ if (-1 == ioctl(fd,VIDIOCSYNC,0))
+ perror("ioctl VIDIOCSYNC");
+ gb_count--;
+ }
+
if ((char*)-1 != map)
- munmap(map,768*576*4);
+ munmap(map,MEM_SIZE*2);
if (-1 == fd)
return 0;
@@ -288,6 +330,12 @@ grab_overlay(int x, int y, int width, int height, int format,
int one = 1, zero = 0;
int i;
+ while (gb_count > 0) {
+ if (-1 == ioctl(fd,VIDIOCSYNC,0))
+ perror("ioctl VIDIOCSYNC");
+ gb_count--;
+ }
+
if (width == 0 || height == 0) {
if (debug)
fprintf(stderr,"v4l: overlay off\n");
@@ -300,7 +348,7 @@ grab_overlay(int x, int y, int width, int height, int format,
ov_win.y = y;
ov_win.width = width;
ov_win.height = height;
- ov_win.flags = 0; /* ??? */
+ ov_win.flags = 0;
if (capability.type & VID_TYPE_CLIPPING) {
ov_win.clips = ov_clips;
@@ -347,6 +395,7 @@ grab_overlay(int x, int y, int width, int height, int format,
default:
TRAP("unsupported video format (overlay)");
}
+
if (-1 == ioctl(fd,VIDIOCSPICT,&pict))
perror("ioctl VIDIOCSPICT");
if (-1 == ioctl(fd, VIDIOCCAPTURE, &one))
@@ -373,24 +422,88 @@ static void rgb_swap(char *mem, int n)
}
}
+void
+rgb24_to_rgb32(void *d, void *s, int p)
+{
+ unsigned char *dest = d;
+ unsigned char *src = s;
+ int i = p;
+
+ while (i--) {
+ *(dest++) = *(src++);
+ *(dest++) = *(src++);
+ *(dest++) = *(src++);
+ *(dest++) = 0;
+ }
+}
+
+static void*
+grab_scr(void *dest, int width, int height)
+{
+ void *buf;
+
+ if ((char*)-1 == map)
+ return NULL;
+ if (!gb_even.format)
+ return NULL;
+
+ gb_even.width = width;
+ gb_even.height = height;
+ gb_odd.width = width;
+ gb_odd.height = height;
+
+ if (gb_count == 0) {
+ if (-1 == ioctl(fd,VIDIOCMCAPTURE,even ? &gb_even : &gb_odd))
+ perror("ioctl VIDIOCMCAPTURE");
+ gb_count++;
+ }
+
+ if (-1 == ioctl(fd,VIDIOCMCAPTURE,even ? &gb_odd : &gb_even))
+ perror("ioctl VIDIOCMCAPTURE");
+ if (-1 == ioctl(fd,VIDIOCSYNC,0))
+ perror("ioctl VIDIOCSYNC");
+ buf = even ? map : map + MEM_SIZE;
+ even = !even;
+
+ if (pixmap_bytes == 4) {
+ rgb24_to_rgb32(dest, buf, width*height);
+ } else {
+ memcpy(dest, buf, width*height*pixmap_bytes);
+ }
+
+ return dest;
+}
+
static void*
grab_one(int width, int height)
{
- struct gbuf gb;
+ struct video_mmap gb;
if ((char*)-1 == map)
return NULL;
-
- gb.adr = 0;
- gb.fmt = BT848_COLOR_FMT_RGB24;
+
+ while (gb_count > 0) {
+ if (-1 == ioctl(fd,VIDIOCSYNC,0))
+ perror("ioctl VIDIOCSYNC");
+ gb_count--;
+ }
+
+ gb.format = 0x11; /* FIXME: BT848_COLOR_FMT_RGB24 */
+ gb.frame = 0;
gb.width = width;
gb.height = height;
- ioctl(fd,BTTV_GRAB,&gb);
- ioctl(fd,BTTV_SYNC,0);
+ memset(map,0,width*height*3);
+ if (-1 == ioctl(fd,VIDIOCMCAPTURE,&gb)) {
+ perror("ioctl VIDIOCMCAPTURE");
+ return NULL;
+ }
+ if (-1 == ioctl(fd,VIDIOCSYNC,0)) {
+ perror("ioctl VIDIOCSYNC");
+ return NULL;
+ }
rgb_swap(map,width*height);
-
return map;
}
diff --git a/grab.h b/grab.h
index e31b364..d150886 100644
--- a/grab.h
+++ b/grab.h
@@ -32,12 +32,14 @@ struct GRABBER {
struct STRTAB *inputs;
/* open+close */
- int (*grab_open)(char *opt, int sw, int sh, int format, void *base);
+ int (*grab_open)(char *opt, int sw, int sh,
+ int format, int pixmap, void *base, int width);
int (*grab_close)();
int (*grab_overlay)(int x, int y, int width, int height, int format,
struct OVERLAY_CLIP *oc, int count);
- void* (*grab_one)(int width, int height);
+ void* (*grab_scr)(void *dest, int width, int height); /* grab for screen display */
+ void* (*grab_one)(int width, int height); /* RGB24 snap */
int (*grab_tune)(unsigned long freq);
int (*grab_input)(int input, int norm);
diff --git a/grabber-video4linux.cc b/grabber-video4linux.cc
new file mode 100644
index 0000000..132c45b
--- /dev/null
+++ b/grabber-video4linux.cc
@@ -0,0 +1,474 @@
+/* =========================================================================
+
+ Copyright (c) 1997 Regents of Koji OKAMURA, oka@kobe-u.ac.jp
+ All rights reserved.
+
+ largely rewritten for new bttv/video4linux interface
+ by Gerd Knorr <kraxel@cs.tu-berlin.de>
+
+ ========================================================================= */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+
+
+extern "C" {
+#include <linux/videodev.h>
+}
+
+#include "grabber.h"
+#include "Tcl.h"
+#include "device-input.h"
+#include "module.h"
+
+/* here you can tune the device names */
+const char *devlist[] = { "/dev/bttv0", "/dev/bttv1", NULL };
+
+//#define DEBUG(x)
+#define DEBUG(x) (x)
+
+#define BT848_COLOR_FMT_YUY2 0x44 /* FIXME */
+
+#define NTSC_WIDTH 640
+#define NTSC_HEIGHT 480
+#define PAL_WIDTH 768
+#define PAL_HEIGHT 576
+#define CIF_WIDTH 352
+#define CIF_HEIGHT 288
+
+#define MEM_SIZE (PAL_WIDTH * PAL_HEIGHT * 3)
+
+#define CF_422 0
+#define CF_411 1
+#define CF_CIF 2
+
+class V4lGrabber : public Grabber {
+public:
+ V4lGrabber(const char * cformat, const char *dev);
+ virtual ~V4lGrabber();
+
+ virtual int command(int argc, const char*const* argv);
+ virtual void start();
+ virtual void stop();
+ virtual int grab();
+
+protected:
+ void format();
+ void setsize();
+
+ void packed422_to_planar422(char *, char*);
+ void packed422_to_planar411(char *, char*);
+
+ struct video_capability capability;
+ struct video_channel *channels;
+ struct video_picture pict;
+ struct video_window win;
+
+ /* mmap */
+ int have_mmap;
+ int even;
+ struct video_mmap gb_even;
+ struct video_mmap gb_odd;
+ char *mem;
+
+ int fd_;
+ int format_;
+ int cformat_;
+ int port_;
+
+ unsigned char *tm_;
+ int width_;
+ int height_;
+ int max_width_;
+ int max_height_;
+ int decimate_;
+};
+
+/* ----------------------------------------------------------------- */
+
+class V4lDevice : public InputDevice {
+public:
+ V4lDevice(const char *dev, const char*, char *attr);
+ virtual int command(int argc, const char*const* argv);
+
+private:
+ const char *dev_;
+};
+
+
+V4lDevice::V4lDevice(const char *dev, const char *name, char *attr) : InputDevice(name)
+{
+ dev_ = dev;
+ attributes_ = attr;
+ fprintf(stderr,"V4l: ==> %s\n",attr);
+}
+
+int V4lDevice::command(int argc, const char*const* argv)
+{
+ Tcl& tcl = Tcl::instance();
+ if (argc == 3) {
+ if (strcmp(argv[1], "open") == 0) {
+ TclObject* o = 0;
+ o = new V4lGrabber(argv[2],dev_);
+ if (o != 0)
+ tcl.result(o->name());
+ return (TCL_OK);
+ }
+ }
+ return (InputDevice::command(argc, argv));
+}
+
+/* ----------------------------------------------------------------- */
+
+class V4lScanner {
+public:
+ V4lScanner(const char **dev);
+};
+
+static V4lScanner find_video4linux_devices(devlist);
+
+V4lScanner::V4lScanner(const char **dev)
+{
+ static const char *palette_name[] = {
+ "", "grey", "hi240", "rgb16", "rgb24", "rgb32", "rgb15" };
+
+ struct video_capability capability;
+ struct video_channel channel;
+ struct video_picture pict;
+ int j,i,fd;
+ char *nick, *attr;
+
+ for (i = 0; dev[i] != NULL; i++) {
+ fprintf(stderr,"V4l: trying %s... ",dev[i]);
+ if (-1 == (fd = open(dev[i],O_RDONLY))) {
+ perror("open");
+ continue;
+ }
+ if (-1 == ioctl(fd,VIDIOCGCAP,&capability)) {
+ perror("ioctl VIDIOCGCAP");
+ close(fd);
+ continue;
+ }
+
+ if (!(capability.type & VID_TYPE_CAPTURE)) {
+ fprintf(stderr,"device can't capture\n");
+ close(fd);
+ continue;
+ }
+
+ fprintf(stderr,"ok, %s\nV4l: %s; size: %dx%d => %dx%d%s\n",
+ capability.name,
+ capability.type & VID_TYPE_MONOCHROME ? "mono" : "color",
+ capability.minwidth,capability.minheight,
+ capability.maxwidth,capability.maxheight,
+ capability.type & VID_TYPE_SCALES ? " (scales)" : "");
+
+ attr = new char[512];
+ strcpy(attr,"format { 411 422 cif } ");
+
+ if (capability.maxwidth > PAL_WIDTH/2 &&
+ capability.maxheight > PAL_HEIGHT/2) {
+ strcat(attr,"size { small large cif } ");
+ } else {
+ strcat(attr,"size { small cif } ");
+ }
+
+ fprintf(stderr,"V4l: ports:");
+ strcat(attr,"port { ");
+ for (j = 0; j < capability.channels; j++) {
+ channel.channel = j;
+ if (-1 == ioctl(fd,VIDIOCGCHAN,&channel)) {
+ perror("ioctl VIDIOCGCHAN");
+ } else {
+ fprintf(stderr," %s",channel.name);
+ strcat(attr,channel.name);
+ strcat(attr," ");
+ }
+ }
+ fprintf(stderr,"\n");
+ strcat(attr,"} ");
+
+ if (-1 == ioctl(fd,VIDIOCGPICT,&pict)) {
+ perror("ioctl VIDIOCGPICT");
+ }
+ fprintf(stderr,"V4l: depth=%d, palette=%s\n",
+ pict.depth,palette_name[pict.palette]);
+
+ nick = new char[strlen(capability.name)+6];
+ sprintf(nick,"v4l: %s",capability.name);
+ new V4lDevice(dev[i],nick,attr);
+
+ close(fd);
+ }
+}
+
+/* ----------------------------------------------------------------- */
+
+V4lGrabber::V4lGrabber(const char *cformat, const char *dev)
+{
+ int i,zero=0;
+
+ DEBUG(fprintf(stderr,"V4l: constructor %s\n",cformat));
+
+ fd_ = open(dev, O_RDWR);
+ if (fd_ < 0) {
+ perror("open");
+ exit(1);
+ }
+
+ /* ask for capabilities */
+ if (-1 == ioctl(fd_,VIDIOCGCAP,&capability)) {
+ perror("ioctl VIDIOCGCAP");
+ exit(1);
+ }
+ channels = (struct video_channel*)
+ calloc(capability.channels,sizeof(struct video_channel));
+ for (i = 0; i < capability.channels; i++) {
+ channels[i].channel = i;
+ if (-1 == ioctl(fd_,VIDIOCGCHAN,&channels[i])) {
+ perror("ioctl VIDIOCGCHAN");
+ }
+ }
+ if (-1 == ioctl(fd_,VIDIOCGPICT,&pict)) {
+ perror("ioctl VIDIOCGPICT");
+ }
+
+ /* map grab buffer */
+ mem = (char*)mmap(0,MEM_SIZE * 2,PROT_READ|PROT_WRITE,MAP_SHARED,fd_,0);
+ if (-1 == (int)mem) {
+ perror("mmap");
+ fprintf(stderr,"V4l: device has no mmap support\n");
+ } else {
+ fprintf(stderr,"V4l: using mmap()'ed buffer\n");
+ have_mmap = 1;
+ }
+
+ /* fill in defaults */
+ if(!strcmp(cformat, "411"))
+ cformat_ = CF_411;
+ if(!strcmp(cformat, "422"))
+ cformat_ = CF_422;
+ if(!strcmp(cformat, "cif"))
+ cformat_ = CF_CIF;
+
+ port_ = 0;
+ decimate_ = 2;
+}
+
+V4lGrabber::~V4lGrabber()
+{
+ DEBUG(fprintf(stderr,"V4l: destructor %s\n"));
+
+ if (have_mmap)
+ munmap(mem,MEM_SIZE * 2);
+ close(fd_);
+}
+
+int V4lGrabber::command(int argc, const char*const* argv)
+{
+ int i;
+
+ if (argc == 3) {
+ if (strcmp(argv[1], "decimate") == 0) {
+ decimate_ = atoi(argv[2]);
+ if (running_)
+ format();
+ }
+
+ if (strcmp(argv[1], "port") == 0) {
+ for (i = 0; i < capability.channels; i++)
+ if(!strcmp(argv[2], channels[i].name))
+ port_ = i;
+ if (running_)
+ format();
+ return (TCL_OK);
+ }
+
+ if (strcmp(argv[1], "fps") == 0) {
+ DEBUG(fprintf(stderr,"V4l: fps %s\n",argv[2]));
+ }
+ }
+
+ return (Grabber::command(argc, argv));
+}
+
+void V4lGrabber::start()
+{
+ DEBUG(fprintf(stderr,"V4l: start\n"));
+
+ format();
+
+ if (have_mmap) {
+ even = 1;
+ if (-1 == ioctl(fd_, VIDIOCMCAPTURE, &gb_even))
+ perror("ioctl VIDIOCMCAPTURE even");
+ if (-1 == ioctl(fd_, VIDIOCMCAPTURE, &gb_odd))
+ perror("ioctl VIDIOCMCAPTURE odd");
+ }
+
+ Grabber::start();
+}
+
+void V4lGrabber::stop()
+{
+ DEBUG(fprintf(stderr,"V4l: stop\n"));
+
+ if (mmap) {
+ if (-1 == ioctl(fd_, VIDIOCSYNC, 0))
+ perror("ioctl VIDIOCSYNC (stop 1)");
+ if (-1 == ioctl(fd_, VIDIOCSYNC, 0))
+ perror("ioctl VIDIOCSYNC (stop 2)");
+ }
+
+ Grabber::stop();
+}
+
+int V4lGrabber::grab()
+{
+ DEBUG(fprintf(stderr,even ? "e" : "o"));
+
+ if (mmap) {
+ if (-1 == ioctl(fd_, VIDIOCSYNC, 0))
+ perror("ioctl VIDIOCSYNC");
+ } else {
+ /* FIXME: read() */
+ }
+
+ switch (cformat_) {
+ case CF_411:
+ case CF_CIF:
+ packed422_to_planar411((char*)frame_,mem + (even ? 0 : MEM_SIZE));
+ break;
+ case CF_422:
+ packed422_to_planar422((char*)frame_,mem + (even ? 0 : MEM_SIZE));
+ break;
+ }
+
+ if (mmap) {
+ if (even) {
+ if (-1 == ioctl(fd_, VIDIOCMCAPTURE, &gb_even))
+ perror("ioctl VIDIOCSYNC even");
+ } else {
+ if (-1 == ioctl(fd_, VIDIOCMCAPTURE, &gb_odd))
+ perror("ioctl VIDIOCSYNC odd");
+ }
+ even = !even;
+ }
+
+ suppress(frame_);
+ saveblks(frame_);
+ YuvFrame f(media_ts(), frame_, crvec_, outw_, outh_);
+ return (target_->consume(&f));
+}
+
+void V4lGrabber::packed422_to_planar422(char *dest, char *src)
+{
+ int i;
+ char *s, *y,*u,*v;
+
+ i = (width_ * height_)/2;
+ s = src;
+ y = dest;
+ u = y + width_ * height_;
+ v = u + width_ * height_ / 2;
+
+ while (--i) {
+ *(y++) = *(src++);
+ *(u++) = *(src++);
+ *(y++) = *(src++);
+ *(v++) = *(src++);
+ }
+}
+
+void V4lGrabber::packed422_to_planar411(char *dest, char *src)
+{
+ int a,b;
+ char *s, *y,*u,*v;
+
+ s = src;
+ y = dest;
+ u = y + width_ * height_;
+ v = u + width_ * height_ / 4;
+
+ for (a = height_; a > 0; a -= 2) {
+ for (b = width_; b > 0; b -= 2) {
+
+ *(y++) = *(src++);
+ *(u++) = *(src++);
+ *(y++) = *(src++);
+ *(v++) = *(src++);
+ }
+ for (b = width_; b > 0; b -= 2) {
+ *(y++) = *(src++);
+ *(src++);
+ *(y++) = *(src++);
+ *(src++);
+ }
+ }
+}
+
+void V4lGrabber::format()
+{
+ DEBUG(fprintf(stderr,"V4l: format"));
+
+ width_ = CIF_WIDTH *2 / decimate_;
+ height_ = CIF_HEIGHT *2 / decimate_;
+
+ if (have_mmap) {
+ gb_even.frame = 0;
+ gb_even.format = BT848_COLOR_FMT_YUY2;
+ gb_even.width = width_;
+ gb_even.height = height_;
+ gb_odd.frame = 1;
+ gb_odd.format = BT848_COLOR_FMT_YUY2;
+ gb_odd.width = width_;
+ gb_odd.height = height_;
+ } else {
+ memset(&win,0,sizeof(win));
+ win.width = width_;
+ win.height = height_;
+ if (-1 == ioctl(fd_,VIDIOCSWIN,&win))
+ perror("ioctl VIDIOCSWIN");
+ if (-1 == ioctl(fd_,VIDIOCGWIN,&win))
+ perror("ioctl VIDIOCGWIN");
+ width_ = win.width;
+ height_ = win.height;
+ }
+
+ switch (cformat_) {
+ case CF_CIF:
+ set_size_411(width_, height_);
+ DEBUG(fprintf(stderr," cif"));
+ break;
+ case CF_411:
+ set_size_411(width_, height_);
+ DEBUG(fprintf(stderr," 411"));
+ break;
+ case CF_422:
+ set_size_422(width_, height_);
+ DEBUG(fprintf(stderr," 422"));
+ break;
+ }
+
+ DEBUG(fprintf(stderr," size=%dx%d",width_,height_));
+
+ if (-1 == ioctl(fd_, VIDIOCSCHAN, &port_))
+ perror("ioctl VIDIOCSCHAN");
+ DEBUG(fprintf(stderr," port=%d\n",port_));
+
+ allocref();
+}
diff --git a/kradio.cpp b/kradio.cpp
index 6c68775..8d76664 100644
--- a/kradio.cpp
+++ b/kradio.cpp
@@ -38,7 +38,13 @@ int main(int argc, char **argv)
/* ------------------------------------------------------------------------ */
#include <asm/types.h> /* XXX glibc */
-#include "videodev.h"
+
+#include "config.h"
+#if USE_KERNEL_VIDEODEV
+# include <linux/videodev.h>
+#else
+# include "videodev.h"
+#endif
static int hw_fd = -1;
@@ -179,6 +185,7 @@ void KRadio::mkpanel()
}
x = PANEL_WIDTH;
+#if 0 /* does'nt work ... */
if (hw_audio.flags & VIDEO_AUDIO_VOLUME) {
volume = new QSlider(0,65535,512,65535-hw_audio.volume,
QSlider::Vertical,this,"volume");
@@ -189,6 +196,7 @@ void KRadio::mkpanel()
volume->setGeometry(x+2,0,i,y1+y2+y3);
x += i+4;
}
+#endif
this->resize(x,y1+y2+y3);
this->setMaximumWidth(x);
diff --git a/main.c b/main.c
index 9516237..048f3ab 100644
--- a/main.c
+++ b/main.c
@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <time.h>
#include <ctype.h>
#include <errno.h>
#include <math.h>
@@ -26,6 +27,9 @@
#ifdef HAVE_LIBXXF86DGA
# include <X11/extensions/xf86dga.h>
#endif
+#ifdef HAVE_LIBXXF86VM
+# include <X11/extensions/xf86vmode.h>
+#endif
#ifdef HAVE_LIBJPEG
# include "jpeglib.h"
@@ -33,14 +37,20 @@
#include "mixer.h"
#include "channel.h"
+#include "channels.h"
#include "grab.h"
#include "x11.h"
#include "toolbox.h"
-#define TITLE_TIME 6000
-#define WIDTH_INC 64
-#define HEIGHT_INC 48
-#define LABEL_WIDTH "16"
+#define TITLE_TIME 6000
+#define WIDTH_INC 64
+#define HEIGHT_INC 48
+#define LABEL_WIDTH "16"
+#define VIDMODE_DELAY 100 /* 0.1 sec */
+
+#define CAPTURE_OFF 0
+#define CAPTURE_OVERLAY 1
+#define CAPTURE_GRABDISPLAY 2
/*--- public variables ----------------------------------------------------*/
@@ -56,6 +66,7 @@ XtIntervalId title_timer;
int pointer_on = 1;
int debug = 0;
int fs = 0;
+int fs_width,fs_height,fs_xoff,fs_yoff;
int bpp = 0;
char *ppmfile;
char *jpegfile;
@@ -65,6 +76,11 @@ char *progname;
#ifdef HAVE_LIBXXF86DGA
int have_dga;
#endif
+#ifdef HAVE_LIBXXF86VM
+int have_vm;
+int vm_count;
+XF86VidModeModeInfo **vm_modelines;
+#endif
/* PAL NTSC SECAM */
static int maxwidth[] = { 768, 640, 768 };
@@ -74,14 +90,8 @@ static int maxheight[] = { 576, 480, 576 };
/*--- drivers -------------------------------------------------------------*/
extern struct GRABBER grab_v4l;
-#ifdef HAVE_BTTV
-extern struct GRABBER grab_bttv;
-#endif
struct GRABBER *grabbers[] = {
&grab_v4l,
-#ifdef HAVE_BTTV
- &grab_bttv,
-#endif
};
int grabber;
@@ -113,19 +123,21 @@ void PointerAction(Widget, XEvent*, String*, Cardinal*);
void FullScreenAction(Widget, XEvent*, String*, Cardinal*);
void OptionsAction(Widget, XEvent*, String*, Cardinal*);
void SnapAction(Widget, XEvent*, String*, Cardinal*);
+void GrabDisplayAction(Widget, XEvent*, String*, Cardinal*);
static XtActionsRec actionTable[] = {
- { "CloseMain", CloseMainAction },
- { "SetRes", SetResAction },
- { "SetChannel", SetChannelAction },
- { "Tune", TuneAction },
- { "Menu", MenuAction },
- { "Channel", ChannelAction },
- { "Volume", VolumeAction },
- { "Pointer", PointerAction },
- { "FullScreen", FullScreenAction },
- { "Options", OptionsAction },
- { "Snap", SnapAction },
+ { "CloseMain", CloseMainAction },
+ { "SetRes", SetResAction },
+ { "SetChannel", SetChannelAction },
+ { "Tune", TuneAction },
+ { "Menu", MenuAction },
+ { "Channel", ChannelAction },
+ { "Volume", VolumeAction },
+ { "Pointer", PointerAction },
+ { "FullScreen", FullScreenAction },
+ { "Options", OptionsAction },
+ { "Snap", SnapAction },
+ { "GrabDisplay", GrabDisplayAction },
};
static struct STRTAB try[] = {
@@ -158,8 +170,6 @@ ExitWP(XtPointer client_data)
/* exit if the application is idle,
* i.e. all the DestroyCallback's are called.
*/
- if (have_mixer)
- mixer_close();
exit(0);
}
@@ -168,6 +178,10 @@ ExitCB(Widget widget, XtPointer client_data, XtPointer calldata)
{
video_overlay(NULL);
video_close();
+ if (have_mixer)
+ mixer_close();
+ if (fs)
+ XtCallActionProc(widget,"FullScreen",NULL,NULL,0);
XtAppAddWorkProc (app_context,ExitWP, NULL);
XtDestroyWidget(app_shell);
}
@@ -247,7 +261,7 @@ set_title()
if (-1 != cur_sender) {
strcpy(title,channels[cur_sender]->name);
} else {
- sprintf(title,"channel %d",cur_channel);
+ sprintf(title,"channel %s",tvtuner[cur_channel].name);
if (cur_fine != 0)
sprintf(title+strlen(title)," (%d)",cur_fine);
sprintf(title+strlen(title)," (%s/%s)",
@@ -311,15 +325,38 @@ void set_source(int j)
void set_freqtab(int j)
{
- int freq;
-
sprintf(title,"%-" LABEL_WIDTH "s: %s","Frequency table",
chan_names[j].str);
if (c_freq)
XtVaSetValues(c_freq,XtNlabel,title,NULL);
chan_tab = j;
- freq = cf2freq(cur_channel,cur_fine);
- grabbers[grabber]->grab_tune(freq);
+}
+
+void
+set_capture(int capture)
+{
+ if (cur_capture == capture)
+ return;
+
+ cur_capture = capture;
+
+ switch (capture) {
+ case CAPTURE_OFF:
+ strcpy(title,"capture: off");
+ video_overlay(NULL);
+ break;
+ case CAPTURE_OVERLAY:
+ default:
+ strcpy(title,"capture: overlay");
+ video_overlay(grabbers[grabber]->grab_overlay);
+ break;
+#if 0
+ case CAPTURE_GRABDISPLAY:
+ strcpy(title,"capture: grabdisplay");
+ /* TODO */
+ break;
+#endif
+ }
}
/* the RightWay[tm] to set float resources (copyed from Xaw specs) */
@@ -376,13 +413,9 @@ set_channel(struct CHANNEL *channel)
/* image parameters */
set_picparams(channel->color, channel->bright,
channel->hue, channel->contrast);
+ set_capture(channel->capture);
/* input source */
- if (cur_capture != channel->capture)
- video_overlay(channel->capture ?
- grabbers[grabber]->grab_overlay : NULL);
- cur_capture = channel->capture;
-
if (cur_input != channel->source)
set_source(channel->source);
if (cur_norm != channel->norm)
@@ -432,9 +465,7 @@ SetResAction(Widget widget, XEvent *event,
change_int(params[0],params[1],&cur_hue);
set_picparams(-1,-1,cur_hue,-1);
} else if (0 == strcmp(params[0],"capture")) {
- cur_capture = !cur_capture;
- sprintf(title,"capture: %s",cur_capture ? "on" : "off");
- video_overlay(cur_capture ? grabbers[grabber]->grab_overlay : NULL);
+ set_capture(!cur_capture);
} else if (0 == strcmp("audio",params[0])) {
change_audio(atoi(params[1]));
} else
@@ -523,10 +554,14 @@ TuneAction(Widget widget, XEvent *event,
return;
if (0 == strcasecmp(params[0],"next")) {
- cur_channel++;
+ do {
+ cur_channel = (cur_channel+1) % CHAN_ENTRIES;
+ } while (!tvtuner[cur_channel].freq[chan_tab]);
cur_fine = 0;
} else if (0 == strcasecmp(params[0],"prev")) {
- cur_channel--;
+ do {
+ cur_channel = (cur_channel+CHAN_ENTRIES-1) % CHAN_ENTRIES;
+ } while (!tvtuner[cur_channel].freq[chan_tab]);
cur_fine = 0;
} else if (0 == strcasecmp(params[0],"fine_up")) {
cur_fine++;
@@ -536,11 +571,9 @@ TuneAction(Widget widget, XEvent *event,
cur_sender = -1;
- if (!cur_capture) {
- cur_capture = 1;
- video_overlay(cur_capture ? grabbers[grabber]->grab_overlay : NULL);
- }
- freq = cf2freq(cur_channel,cur_fine);
+ set_capture(CAPTURE_OVERLAY);
+
+ freq = get_freq(cur_channel)+cur_fine;
grabbers[grabber]->grab_tune(freq);
set_title();
}
@@ -555,9 +588,7 @@ MenuAction(Widget widget, XEvent *event,
title[0] = 0;
switch(i=popup_menu(widget,"Settings",try)) {
case 1:
- cur_capture = !cur_capture;
- sprintf(title,"capture: %s",cur_capture ? "on" : "off");
- video_overlay(cur_capture ? grabbers[grabber]->grab_overlay : NULL);
+ set_capture(!cur_capture);
break;
case 2:
XtCallActionProc(widget,"Volume",event,mute,1);
@@ -629,54 +660,109 @@ MyResize(XtPointer client_data)
return TRUE;
}
+static void
+vidmode_timer(XtPointer clientData, XtIntervalId *id)
+{
+ set_capture(CAPTURE_OVERLAY);
+}
+
+static void
+set_vidmode(int nr)
+{
+ if (cur_capture)
+ video_overlay(NULL);
+ usleep(VIDMODE_DELAY*1000);
+ if (debug)
+ fprintf(stderr,"switching video mode to %dx%d now\n",
+ vm_modelines[nr]->hdisplay,
+ vm_modelines[nr]->vdisplay);
+ XF86VidModeSwitchToMode(dpy,XDefaultScreen(dpy),vm_modelines[nr]);
+
+ if (cur_capture) {
+ cur_capture = 0;
+ XtAppAddTimeOut(app_context,VIDMODE_DELAY,vidmode_timer,NULL);
+ }
+}
+
void
FullScreenAction(Widget widget, XEvent *event,
String *params, Cardinal *num_params)
{
static Dimension x,y,w,h;
+ static int timeout,interval,prefer_blanking,allow_exposures;
+ static int vm_switched;
if (fs) {
+#ifdef HAVE_LIBXXF86VM
+ if (have_vm && vm_switched) {
+ set_vidmode(0);
+ vm_switched = 0;
+ }
+#endif
+
XtVaSetValues(app_shell,
XtNwidthInc, WIDTH_INC,
XtNheightInc,HEIGHT_INC,
- XtNx, x,
- XtNy, y,
+ XtNx, x + fs_xoff,
+ XtNy, y + fs_yoff,
XtNwidth, w,
XtNheight, h,
NULL);
+
+ XSetScreenSaver(dpy,timeout,interval,prefer_blanking,allow_exposures);
fs = 0;
} else {
- int vp_width = swidth;
- int vp_height = sheight;
-
-#ifdef HAVE_LIBXXF86DGA
- if (have_dga) {
- XF86DGAGetViewPortSize(dpy,XDefaultScreen(dpy),
- &vp_width, &vp_height);
+ int vp_x, vp_y, vp_width, vp_height, i;
+
+ vp_x = 0;
+ vp_y = 0;
+ vp_width = swidth;
+ vp_height = sheight;
+#ifdef HAVE_LIBXXF86VM
+ if (have_vm) {
+ XF86VidModeGetAllModeLines(dpy,XDefaultScreen(dpy),
+ &vm_count,&vm_modelines);
+ for (i = 0; i < vm_count; i++)
+ if (fs_width == vm_modelines[i]->hdisplay &&
+ fs_height == vm_modelines[i]->vdisplay)
+ break;
+ if (i != 0 && i != vm_count) {
+ set_vidmode(i);
+ vm_switched = 1;
+ vp_width = vm_modelines[i]->hdisplay;
+ vp_height = vm_modelines[i]->vdisplay;
+ } else {
+ vm_switched = 0;
+ vp_width = vm_modelines[0]->hdisplay;
+ vp_height = vm_modelines[0]->vdisplay;
+ }
+ XF86VidModeGetViewPort(dpy,XDefaultScreen(dpy),&vp_x,&vp_y);
if (debug)
- fprintf(stderr,"dga: viewport size: %dx%d\n",
- vp_width,vp_height);
- if (vp_width < swidth || vp_height < sheight)
- XF86DGASetViewPort(dpy,XDefaultScreen(dpy),0,0);
+ fprintf(stderr,"viewport: %dx%d+%d+%d\n",
+ vp_width,vp_height,vp_x,vp_y);
}
#endif
XtVaGetValues(app_shell,
- XtNx, &x,
- XtNy, &y,
- XtNwidth, &w,
- XtNheight, &h,
+ XtNx, &x,
+ XtNy, &y,
+ XtNwidth, &w,
+ XtNheight, &h,
NULL);
XtVaSetValues(app_shell,
- XtNwidthInc, 1,
- XtNheightInc, 1,
+ XtNwidthInc, 1,
+ XtNheightInc, 1,
NULL);
XtVaSetValues(app_shell,
- XtNx, 0,
- XtNy, 0,
- XtNwidth, vp_width,
- XtNheight, vp_height,
+ XtNx, (vp_x & 0xfffc) + fs_xoff,
+ XtNy, vp_y + fs_yoff,
+ XtNwidth, vp_width,
+ XtNheight, vp_height,
NULL);
+
+ XGetScreenSaver(dpy,&timeout,&interval,
+ &prefer_blanking,&allow_exposures);
+ XSetScreenSaver(dpy,0,0,DefaultBlanking,DefaultExposures);
fs = 1;
}
XtAppAddWorkProc (app_context,MyResize, NULL);
@@ -695,9 +781,7 @@ channel_menu()
if (max < len)
max = len;
}
- defaults.freq = cf2freq(defaults.channel,defaults.fine);
for (i = 0; i < count; i++) {
- channels[i]->freq = cf2freq(channels[i]->channel,channels[i]->fine);
cmenu[i].nr = i+1;
cmenu[i].str = channels[i]->name;
if (channels[i]->key) {
@@ -714,6 +798,59 @@ channel_menu()
}
}
+static Boolean
+idle_grabdisplay(XtPointer data)
+{
+ static long count,lastsec;
+ struct timeval tv;
+ struct timezone tz;
+
+ if (cur_capture) {
+ if (debug)
+ fprintf(stderr,"grabdisplay off\n");
+ return TRUE;
+ }
+ if (!grabbers[grabber]->grab_scr)
+ return TRUE;
+
+ gettimeofday(&tv,&tz);
+ if (tv.tv_sec != lastsec) {
+ /* statistics */
+ sprintf(title,"grabdisplay: %ld fps", count);
+ XtVaSetValues(app_shell,XtNtitle,title,NULL);
+ lastsec = tv.tv_sec;
+ count = 0;
+ }
+ count++;
+
+ if (-1 == video_displayframe(grabbers[grabber]->grab_scr))
+ return TRUE;
+ return FALSE;
+}
+
+void
+GrabDisplayAction(Widget widget, XEvent *event,
+ String *params, Cardinal *num_params)
+{
+#if 1
+ static int niced = 0;
+
+ if (!niced) {
+ nice(10);
+ niced = 1;
+ if (debug)
+ fprintf(stderr,"nice\n");
+ }
+#endif
+ if (cur_capture) {
+ cur_capture = 0;
+ video_overlay(NULL);
+ }
+ XtAppAddWorkProc(app_context, idle_grabdisplay, NULL);
+ if (debug)
+ fprintf(stderr,"grabdisplay on\n");
+}
+
/*--- option window ------------------------------------------------------*/
#define PANED_FIX \
@@ -1051,8 +1188,8 @@ SnapAction(Widget widget, XEvent *event,
{
void *buffer;
int jpeg = 0;
- int width = maxwidth[cur_norm];
- int height = maxheight[cur_norm];
+ Dimension width = maxwidth[cur_norm];
+ Dimension height = maxheight[cur_norm];
if (*num_params > 0) {
if (0 == strcasecmp(params[0],"jpeg"))
@@ -1060,6 +1197,15 @@ SnapAction(Widget widget, XEvent *event,
if (0 == strcasecmp(params[0],"ppm"))
jpeg = 0;
}
+
+ if (*num_params > 1) {
+ if (0 == strcasecmp(params[1],"full")) {
+ width = maxwidth[cur_norm];
+ height = maxheight[cur_norm];
+ }
+ if (0 == strcasecmp(params[1],"win"))
+ XtVaGetValues(tv,XtNwidth,&width,XtNheight,&height,NULL);
+ }
if (!grabbers[grabber]->grab_one) {
fprintf(stderr,"grabbing: not supported\n");
@@ -1103,22 +1249,52 @@ SnapAction(Widget widget, XEvent *event,
/*--- main ---------------------------------------------------------------*/
static void
-grabber_init()
+xfree_init()
{
- int sw,sh;
- void *base = NULL;
-#ifdef HAVE_LIBXXF86DGA
- int foo,bar,fred,flags;
+ int flags,foo,bar,i,ma,mi;
- have_dga = 0;
+#ifdef HAVE_LIBXXF86DGA
if (XF86DGAQueryExtension(dpy,&foo,&bar)) {
XF86DGAQueryDirectVideo(dpy,XDefaultScreen(dpy),&flags);
if (flags & XF86DGADirectPresent) {
+ XF86DGAQueryVersion(dpy,&ma,&mi);
have_dga = 1;
- XF86DGAGetVideoLL(dpy,XDefaultScreen(dpy),(int*)&base,
- &foo,&bar,&fred);
- fprintf(stderr,"dga: base=%p\n",base);
+ fprintf(stderr,"X-Server supports DGA extention (version %d.%d)\n",
+ ma,mi);
+ }
+ }
+#endif
+#ifdef HAVE_LIBXXF86VM
+ if (XF86VidModeQueryExtension(dpy,&foo,&bar)) {
+ XF86VidModeQueryVersion(dpy,&ma,&mi);
+ have_vm = 1;
+ fprintf(stderr,"X-Server supports VidMode extention (version %d.%d)\n",
+ ma,mi);
+ fprintf(stderr," available video mode(s):");
+ XF86VidModeGetAllModeLines(dpy,XDefaultScreen(dpy),
+ &vm_count,&vm_modelines);
+ for (i = 0; i < vm_count; i++) {
+ fprintf(stderr," %dx%d",
+ vm_modelines[i]->hdisplay,
+ vm_modelines[i]->vdisplay);
}
+ fprintf(stderr,"\n");
+ }
+#endif
+}
+
+static void
+grabber_init()
+{
+ int sw,sh;
+ void *base = NULL;
+#ifdef HAVE_LIBXXF86DGA
+ int width = 0,bar,fred;
+
+ if (have_dga) {
+ XF86DGAGetVideoLL(dpy,XDefaultScreen(dpy),(int*)&base,
+ &width,&bar,&fred);
+ fprintf(stderr,"dga: base=%p, width=%d\n",base,width);
}
#endif
sw = XtScreen(app_shell)->width;
@@ -1126,7 +1302,7 @@ grabber_init()
for (grabber = 0; grabber < sizeof(grabbers)/sizeof(struct GRABBERS*);
grabber++) {
if (-1 != grabbers[grabber]->grab_open
- (NULL,sw,sh,x11_native_format,base))
+ (NULL,sw,sh,x11_native_format,x11_pixmap_format,base,width))
break;
}
if (grabber == sizeof(grabbers)/sizeof(struct GRABBERS*)) {
@@ -1138,7 +1314,8 @@ grabber_init()
int main(int argc, char *argv[])
{
- int c,noconf,fullscreen,nomouse;
+ int c,noconf,fullscreen,nomouse,xfree_ext;
+ char v4l_conf[32] = "v4l-conf -q";
progname = strdup(argv[0]);
app_shell = XtAppInitialize(&app_context,
@@ -1150,8 +1327,9 @@ int main(int argc, char *argv[])
/* parse options */
debug = noconf = fullscreen = nomouse = 0;
+ xfree_ext = 1;
for (;;) {
- if (-1 == (c = getopt(argc, argv, "hnmfv:c:o:")))
+ if (-1 == (c = getopt(argc, argv, "hxnmfv:c:o:j:b:")))
break;
switch (c) {
case 'v':
@@ -1169,8 +1347,14 @@ int main(int argc, char *argv[])
case 'f':
fullscreen = 1;
break;
+ case 'x':
+ xfree_ext = 0;
+ break;
case 'b':
bpp = atoi(optarg);
+ /* v4l-conf needs this too */
+ strcat(v4l_conf," -b ");
+ strcat(v4l_conf,optarg);
break;
case 'o':
ppmfile = strdup(optarg);
@@ -1185,6 +1369,18 @@ int main(int argc, char *argv[])
}
}
+ switch (system(v4l_conf)) {
+ case -1: /* can't run */
+ fprintf(stderr,"could'nt start v4l-conf\n");
+ break;
+ case 0: /* ok */
+ break;
+ default: /* non-zero return */
+ fprintf(stderr,"v4l-conf had some trouble, "
+ "trying to continue anyway\n");
+ break;
+ }
+
XtAppAddActions(app_context,actionTable,
sizeof(actionTable)/sizeof(XtActionsRec));
wm_protocols[0] =
@@ -1192,6 +1388,8 @@ int main(int argc, char *argv[])
wm_protocols[1] =
XInternAtom(XtDisplay(app_shell), "WM_SAVE_YOURSELF", False);
dpy = XtDisplay(app_shell);
+ if (xfree_ext)
+ xfree_init();
create_optwin();
tv = video_init(app_shell);
@@ -1208,6 +1406,8 @@ int main(int argc, char *argv[])
if (!noconf)
read_config();
set_freqtab(chan_tab);
+ defaults.channel = lookup_channel(defaults.cname);
+ defaults.freq = get_freq(defaults.channel);
channel_menu();
if (have_mixer)
cur_volume = mixer_get_volume() * 65535/100;
diff --git a/radio.c b/radio.c
index 56a224d..25edc96 100644
--- a/radio.c
+++ b/radio.c
@@ -14,7 +14,13 @@
#include <sys/ioctl.h>
#include <asm/types.h> /* XXX glibc */
-#include "videodev.h"
+
+#include "config.h"
+#if USE_KERNEL_VIDEODEV
+# include <linux/videodev.h>
+#else
+# include "videodev.h"
+#endif
#define DEVICE "/dev/bttv-fm" /* major=81, minor=64 */
diff --git a/set-tv.c b/set-tv.c
index 39488aa..8acac40 100644
--- a/set-tv.c
+++ b/set-tv.c
@@ -1,5 +1,5 @@
/*
- * main.c -- (c) 1997 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ * set-tv.c -- (c) 1997 Gerd Knorr <kraxel@cs.tu-berlin.de>
*
*/
@@ -19,14 +19,8 @@
/*--- drivers -------------------------------------------------------------*/
extern struct GRABBER grab_v4l;
-#ifdef HAVE_BTTV
-extern struct GRABBER grab_bttv;
-#endif
struct GRABBER *grabbers[] = {
&grab_v4l,
-#ifdef HAVE_BTTV
- &grab_bttv,
-#endif
};
int grabber;
@@ -37,6 +31,7 @@ int cur_color;
int cur_bright;
int cur_hue;
int cur_contrast;
+int fs_width,fs_height,fs_xoff,fs_yoff;
/*------------------------------------------------------------------------*/
@@ -78,15 +73,6 @@ set_channel(struct CHANNEL *channel)
grabbers[grabber]->inputs[cur_input].str);
}
-void
-channel_menu()
-{
- int i;
-
- for (i = 0; i < count; i++)
- channels[i]->freq = cf2freq(channels[i]->channel,channels[i]->fine);
-}
-
/*--- main ---------------------------------------------------------------*/
static void
@@ -95,7 +81,7 @@ grabber_init()
for (grabber = 0; grabber < sizeof(grabbers)/sizeof(struct GRABBERS*);
grabber++) {
if (-1 != grabbers[grabber]->grab_open
- (NULL,0,0,0,NULL))
+ (NULL,0,0,0,0,NULL,0))
break;
}
if (grabber == sizeof(grabbers)/sizeof(struct GRABBERS*)) {
@@ -129,7 +115,6 @@ int main(int argc, char *argv[])
grabber_init();
read_config();
- channel_menu();
cur_sender = -1;
for (i = 0; i < count; i++)
diff --git a/v4l-conf.c b/v4l-conf.c
index 91c02d3..764444f 100644
--- a/v4l-conf.c
+++ b/v4l-conf.c
@@ -9,7 +9,11 @@
#include "config.h"
#include <asm/types.h> /* XXX glibc */
-#include "videodev.h"
+#if USE_KERNEL_VIDEODEV
+# include <linux/videodev.h>
+#else
+# include "videodev.h"
+#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -35,7 +39,7 @@ main(int argc, char *argv[])
struct video_buffer fbuf;
int fd,c;
#ifdef HAVE_LIBXXF86DGA
- int foo,bar,fred,flags;
+ int width,bar,foo,flags;
void *base = 0;
#endif
@@ -98,9 +102,9 @@ main(int argc, char *argv[])
if (XF86DGAQueryExtension(dpy,&foo,&bar)) {
XF86DGAQueryDirectVideo(dpy,XDefaultScreen(dpy),&flags);
if (flags & XF86DGADirectPresent) {
- XF86DGAGetVideoLL(dpy,XDefaultScreen(dpy),(int*)&base,&fred,&foo,&bar);
+ XF86DGAGetVideoLL(dpy,XDefaultScreen(dpy),(int*)&base,&width,&foo,&bar);
if (verbose)
- fprintf(stderr,"dga: base=%p\n",base);
+ fprintf(stderr,"dga: base=%p, width=%d\n",base, width);
}
}
#endif
@@ -134,7 +138,7 @@ main(int argc, char *argv[])
}
#endif
fbuf.depth = wts.depth;
- fbuf.width = wts.width;
+ fbuf.width = (flags & XF86DGADirectPresent) ? width : wts.width;
fbuf.height = wts.height;
fbuf.bytesperline = fbuf.width * fbuf.depth/8;
if (-1 == ioctl(fd,VIDIOCSFBUF,&fbuf)) {
diff --git a/vtx/.vtx.o.flags b/vtx/.vtx.o.flags
new file mode 100644
index 0000000..4d26430
--- /dev/null
+++ b/vtx/.vtx.o.flags
@@ -0,0 +1,3 @@
+ifeq (-Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=686 -DMODULE -DMODVERSIONS -include /usr/src/kernel/2.1.91/include/linux/modversions.h -DEXPORT_SYMTAB -DVTX_DEFAULT_MAJOR=28 -DDEBUG_VTX,$(strip $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_vtx.o)))
+FILES_FLAGS_UP_TO_DATE += vtx.o
+endif
diff --git a/vtx/Makefile b/vtx/Makefile
new file mode 100644
index 0000000..5d3574c
--- /dev/null
+++ b/vtx/Makefile
@@ -0,0 +1,75 @@
+# GNUmakefile for the videotext-driver
+#
+# Copyright (c) 1994-97 Martin Buck <martin-2.buck@student.uni-ulm.de>
+#
+# $Id: Makefile,v 1.6 1998/03/29 12:19:50 richard Exp $
+
+# 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.
+
+
+# Uncomment the suitable line for your VTX-interface
+
+# IF_WINTVPCI is a PCI card containing a video grabber, a tuner and a
+# videotext interface made by Hauppauge Computer Works, Inc.
+# (thanks to Ralph Metzler for patches)
+
+VTXIF = IF_WINTVPCI
+
+
+# Choose your favourite major-number here (can be overridden on the insmod-
+# commandline with major=??):
+
+VTX_DEFAULT_MAJOR = 28
+
+
+# To get debugging messages, uncomment the following line and use debug=x
+# (with x > 0) when loading the driver (WARNING: x >= 2 is *very* verbose, you
+# definitely want to kill your klogd before you do this)
+
+DEBUG = -DDEBUG_VTX
+
+
+# Uncomment the next line to make the driver quiet on (un)loading (i.e. no
+# version- and interface-type messages). This is useful if you load vtx with
+# kerneld. You can override this setting with quiet=0 or quiet=1 on the
+# insmod-commandline (or in /etc/conf.modules).
+
+#VTX_QUIET = -DVTX_QUIET
+
+
+#
+# Module compile magic
+#
+
+CURRENT=$(shell uname -r)
+
+KERNEL_LOCATION=/usr/src/linux
+
+M_OBJS = vtx.o
+EXTRA_CFLAGS = -DEXPORT_SYMTAB -DVTX_DEFAULT_MAJOR=$(VTX_DEFAULT_MAJOR) \
+ $(DEBUG) $(VTX_QUIET)
+
+here:
+ DIR=`pwd`; (cd $(KERNEL_LOCATION); make SUBDIRS=$$DIR modules)
+
+install:
+ su -c "cp -v $(M_OBJS) /lib/modules/$(CURRENT)/misc"
+
+clean:
+ -rm -f $(M_OBJS) .*.o.flags *~
+
+include $(KERNEL_LOCATION)/Rules.make
+
diff --git a/vtx/README b/vtx/README
new file mode 100644
index 0000000..d269226
--- /dev/null
+++ b/vtx/README
@@ -0,0 +1,44 @@
+Just included a new vtx driver version here. Hav'nt tested it myself,
+becauce I hav'nt a vtx chip on my card. Compiles with 2.1.x only.
+
+ Gerd
+
+------------------------------------------------------------------------
+From zxmpm11@student.uni-tuebingen.de Mon Mar 30 15:36:32 1998
+Date: Mon, 30 Mar 1998 11:50:52 +0200 (METDST)
+From: Richard Guenther <zxmpm11@student.uni-tuebingen.de>
+To: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Cc: Gerd Knorr <kraxel@cs.tu-berlin.de>, martin-2.buck@student.uni-ulm.de,
+ alan@lxorguk.ukuu.org.uk
+Subject: Re: Bttv driver and teletext
+
+Hi!
+
+Ok, I have just done this. Get a working (well you need the included
+patch to VideoteXt because parity is somehow corrupted!??) copy
+at http://www.anatom.uni-tuebingen.de/~richi/vtx.tar.gz
+
+Richard.
+
+PS: its not nice code, but it works.
+
+
+On Tue, 24 Feb 1998, Alan Cox wrote:
+
+> > Had a short look at the driver, I think it shoult'nt be a big problem to
+> > build a new vtx driver on top of the i2c module which comes with newer
+> > bttv/xawtv versions. This removes the
+> > "two-drivers-talking-to-one-device" and the trouble resulting of this. As
+> > far I know, there is'nt one yet.
+>
+> Its gross to try and fix the existing vtx driver. I could hack the vtx code
+> to be clean and just support the bttv cards for now (but with hooks for
+> someone to sort others out over time). RIght now its broken for things like
+> 2 bttv cards
+>
+> Alan
+
+--
+Richard Guenther <richard.guenther@student.uni-tuebingen.de>
+PGP: 2E829319 - 2F 83 FC 93 E9 E4 19 E2 93 7A 32 42 45 37 23 57
+WWW: http://www.anatom.uni-tuebingen.de/~richi/
diff --git a/vtx/VideoteXt-0.6-patch b/vtx/VideoteXt-0.6-patch
new file mode 100644
index 0000000..f5cac12
--- /dev/null
+++ b/vtx/VideoteXt-0.6-patch
@@ -0,0 +1,11 @@
+--- VideoteXt-0.6/vtxtools.c.original Sun Mar 29 20:36:03 1998
++++ VideoteXt-0.6/vtxtools.c Sun Mar 29 20:36:39 1998
+@@ -54,7 +54,7 @@
+ vtx_chkparity(byte_t *val) {
+ if (!init_done)
+ tools_init();
+- if (parity_table[*val] & 0x80) {
++ if (1/*parity_table[*val] & 0x80*/) {
+ *val &= 0x7f;
+ return TRUE;
+ } else return FALSE;
diff --git a/vtx/i2c.h b/vtx/i2c.h
new file mode 100644
index 0000000..931c89e
--- /dev/null
+++ b/vtx/i2c.h
@@ -0,0 +1,165 @@
+#ifndef I2C_H
+#define I2C_H
+
+/*
+ * linux i2c interface. Works a little bit like the scsi subsystem.
+ * There are:
+ *
+ * i2c the basic control module (like scsi_mod)
+ * bus driver a driver with a i2c bus (hostadapter driver)
+ * chip driver a driver for a chip connected
+ * to a i2c bus (cdrom/hd driver)
+ *
+ + a devices will be attached to one bus and one chip driver. Every chip
+ * driver gets a unique ID.
+ *
+ * A chip driver can provide a ioctl-like callback for the
+ * communication with other parts of the kernel (not every i2c chip is
+ * useful without other devices, a TV card tuner for example).
+ *
+ * "i2c internal" parts of the structs: only the i2c module is allowed to
+ * write to them, for others they are read-only.
+ *
+ */
+
+#define I2C_BUS_MAX 4 /* max # of bus drivers */
+#define I2C_DRIVER_MAX 8 /* max # of chip drivers */
+#define I2C_DEVICE_MAX 8 /* max # if devices per bus/driver */
+
+struct i2c_bus;
+struct i2c_driver;
+struct i2c_device;
+
+#define I2C_DRIVERID_MSP3400 1
+#define I2C_DRIVERID_TUNER 2
+
+/*
+ * struct for a driver for a i2c chip (tuner, soundprocessor,
+ * videotext, ... ).
+ *
+ * a driver will register within the i2c module. The i2c module will
+ * callback the driver (i2c_attach) for every device it finds on a i2c
+ * bus at the specified address. If the driver decides to "accept"
+ * the, device, it must return a struct i2c_device, and NULL
+ * otherwise.
+ *
+ * i2c_detach = i2c_attach ** -1
+ *
+ * i2c_command will be used to pass commands to the driver in a
+ * ioctl-line manner.
+ *
+ */
+
+struct i2c_driver {
+ char name[32]; /* some useful label */
+ int id; /* device type ID */
+ unsigned char addr_l, addr_h; /* address range of the chip */
+
+ int (*attach)(struct i2c_device *device);
+ int (*detach)(struct i2c_device *device);
+ int (*command)(struct i2c_device *device,
+ unsigned int cmd, void *arg);
+
+ /* i2c internal */
+ struct i2c_device *devices[I2C_DEVICE_MAX];
+ int devcount;
+};
+
+
+/*
+ * this holds the informations about a i2c bus available in the system.
+ *
+ * a chip with a i2c bus interface (like bt848) registers the bus within
+ * the i2c module. This struct provides functions to access the i2c bus.
+ *
+ * One must hold the spinlock to access the i2c bus (XXX: is the irqsave
+ * required? Maybe better use a semaphore?).
+ *
+ * attach/detach_inform is a callback to inform the bus driver about
+ * attached chip drivers.
+ *
+ */
+
+/* needed: unsigned long flags */
+#if LINUX_VERSION_CODE >= 0x020100
+#define LOCK_I2C_BUS(bus) spin_lock_irqsave(&(bus->bus_lock),flags);
+#define UNLOCK_I2C_BUS(bus) spin_unlock_irqrestore(&(bus->bus_lock),flags);
+#else
+#define LOCK_I2C_BUS(bus) { save_flags(flags); cli(); }
+#define UNLOCK_I2C_BUS(bus) { restore_flags(flags); }
+#endif
+
+struct i2c_bus {
+ char name[32]; /* some useful label */
+ void *data; /* free for use by the bus driver */
+
+#if LINUX_VERSION_CODE >= 0x020100
+ spinlock_t bus_lock;
+#endif
+
+ /* attach/detach inform callbacks */
+ void (*attach_inform)(struct i2c_bus *bus, int id);
+ void (*detach_inform)(struct i2c_bus *bus, int id);
+
+ /* Software I2C */
+ void (*i2c_setlines)(struct i2c_bus *bus, int ctrl, int data);
+ int (*i2c_getdataline)(struct i2c_bus *bus);
+
+ /* Hardware I2C */
+ int (*i2c_read)(struct i2c_bus *bus, unsigned char addr);
+ int (*i2c_write)(struct i2c_bus *bus, unsigned char addr,
+ unsigned char b1, unsigned char b2, int both);
+
+ /* internal data for i2c module */
+ struct i2c_device *devices[I2C_DEVICE_MAX];
+ int devcount;
+};
+
+
+/*
+ * this holds per-device data for a i2c device
+ *
+ */
+
+struct i2c_device {
+ char name[32]; /* some useful label */
+ void *data; /* free for use by the chip driver */
+ unsigned char addr; /* chip addr */
+
+ /* i2c internal */
+ struct i2c_bus *bus;
+ struct i2c_driver *driver;
+};
+
+
+/* ------------------------------------------------------------------- */
+/* i2c module functions */
+
+/* register/unregister a i2c bus */
+int i2c_register_bus(struct i2c_bus *bus);
+int i2c_unregister_bus(struct i2c_bus *bus);
+
+/* register/unregister a chip driver */
+int i2c_register_driver(struct i2c_driver *driver);
+int i2c_unregister_driver(struct i2c_driver *driver);
+
+/* send a command to a chip using the ioctl-like callback interface */
+int i2c_control_device(struct i2c_bus *bus, int id,
+ unsigned int cmd, void *arg);
+
+/* i2c bus access functions */
+void i2c_start(struct i2c_bus *bus);
+void i2c_stop(struct i2c_bus *bus);
+void i2c_one(struct i2c_bus *bus);
+void i2c_zero(struct i2c_bus *bus);
+int i2c_ack(struct i2c_bus *bus);
+
+int i2c_sendbyte(struct i2c_bus *bus,unsigned char data,int wait_for_ack);
+unsigned char i2c_readbyte(struct i2c_bus *bus,int last);
+
+/* i2c (maybe) hardware functions */
+int i2c_read(struct i2c_bus *bus, unsigned char addr);
+int i2c_write(struct i2c_bus *bus, unsigned char addr,
+ unsigned char b1, unsigned char b2, int both);
+
+#endif /* I2C_H */
diff --git a/vtx/vtx.c b/vtx/vtx.c
new file mode 100644
index 0000000..2c49d00
--- /dev/null
+++ b/vtx/vtx.c
@@ -0,0 +1,759 @@
+/* NOTE!!!
+ * The original driver was heavily modified to match the i2c interface
+ * It was truncated to use the WinTV boards, too.
+ *
+ * Copyright (c) 1998 Richard Guenther <richard.guenther@student.uni-tuebingen.de>
+ *
+ * $Id: vtx.c,v 1.11 1998/03/29 18:39:20 root Exp $
+ *
+ * $Log: vtx.c,v $
+ * Revision 1.11 1998/03/29 18:39:20 root
+ * fixed one last bug, it seems, i2c is messing with the
+ * parity bit, so you need a patch for VideoteXt-0.6 to
+ * ignore the parity bit.
+ *
+ * Revision 1.10 1998/03/29 12:19:50 richard
+ * bug fixes, cleanup
+ *
+ * Revision 1.9 1998/03/29 11:11:29 richard
+ * Bugfixes, first (sort of) working version. We get (sometimes)
+ * corrupted bytes, though... seems like a timing problem??
+ *
+ * Revision 1.8 1998/03/28 16:18:47 richard
+ * fixes
+ *
+ *
+ */
+
+/*
+ * vtx.c:
+ * This is a loadable character-device-driver for videotext-interfaces
+ * (aka teletext). Please check the Makefile/README for a list of supported
+ * interfaces.
+ *
+ * Copyright (c) 1994-97 Martin Buck <martin-2.buck@student.uni-ulm.de>
+ *
+ */
+
+/*
+ * 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.
+ */
+
+#include <linux/module.h>
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/bios32.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <stdarg.h>
+#include "i2c.h"
+#include "vtx.h"
+
+
+
+#define VTX_VER_MAJ 1
+#define VTX_VER_MIN 7
+#define VTX_NAME "videotext"
+
+struct i2c_bus *bus = NULL;
+
+static int videotext_attach(struct i2c_device *device)
+{
+ printk(KERN_DEBUG "videotext_attach: bus %p\n", device->bus);
+ strcpy(device->name, VTX_NAME);
+ bus = device->bus;
+ return 0;
+}
+
+static int videotext_detach(struct i2c_device *device)
+{
+ printk(KERN_DEBUG "videotext_detach\n");
+ return 0;
+}
+
+static int videotext_command(struct i2c_device *device,
+ unsigned int cmd, void *arg)
+{
+ printk(KERN_DEBUG "videotext_command\n");
+ return -EINVAL;
+}
+
+/* new I2C driver support */
+static struct i2c_driver i2c_driver_videotext = {
+ VTX_NAME, /* name */
+ 111, /* FIXME: I2C_DRIVERID_VIDEOTEXT in i2c.h */
+ 34, 35, /* FIXME: addr range */
+ videotext_attach,
+ videotext_detach,
+ videotext_command
+};
+
+
+
+#ifndef PCI_VENDOR_ID_BROOKTREE
+#define PCI_VENDOR_ID_BROOKTREE 0x109e
+#endif
+#ifndef PCI_DEVICE_ID_BT848
+#define PCI_DEVICE_ID_BT848 0x350
+#endif
+#define VTX_PCI_VENDOR PCI_VENDOR_ID_BROOKTREE
+#define VTX_PCI_DEVICE PCI_DEVICE_ID_BT848
+#define NUM_DAUS 4
+#define NUM_BUFS 8
+#define IF_NAME "Hauppauge Win/TV PCI"
+
+
+/* These variables are settable when loading the driver (with modutils-1.1.67 & up) */
+unsigned int io_base;
+unsigned char *pci_memio_base;
+
+int major = VTX_DEFAULT_MAJOR;
+#ifdef VTX_QUIET
+int quiet = 1;
+#else
+int quiet = 0;
+#endif
+
+
+static int vtx_use_count;
+static int is_searching[NUM_DAUS], disp_mode = DISPOFF;
+static const int disp_modes[8][3] = {
+ { 0x46, 0x03, 0x03 }, /* DISPOFF */
+ { 0x46, 0xcc, 0xcc }, /* DISPNORM */
+ { 0x44, 0x0f, 0x0f }, /* DISPTRANS */
+ { 0x46, 0xcc, 0x46 }, /* DISPINS */
+ { 0x44, 0x03, 0x03 }, /* DISPOFF, interlaced */
+ { 0x44, 0xcc, 0xcc }, /* DISPNORM, interlaced */
+ { 0x44, 0x0f, 0x0f }, /* DISPTRANS, interlaced */
+ { 0x44, 0xcc, 0x46 } /* DISPINS, interlaced */
+};
+
+
+
+#define PAGE_WAIT 30 /* Time in jiffies between requesting page and */
+ /* checking status bits */
+#define PGBUF_EXPIRE 1500 /* Time in jiffies to wait before retransmitting */
+ /* page regardless of infobits */
+typedef struct {
+ byte_t pgbuf[VTX_VIRTUALSIZE]; /* Page-buffer */
+ byte_t laststat[10]; /* Last value of infobits for DAU */
+ byte_t sregs[7]; /* Page-request registers */
+ unsigned long expire; /* Time when page will be expired */
+ unsigned clrfound : 1; /* VTXIOCCLRFOUND has been called */
+ unsigned stopped : 1; /* VTXIOCSTOPDAU has been called */
+} vdau_t;
+static vdau_t vdau[NUM_DAUS]; /* Data for virtual DAUs (the 5249 only has one */
+ /* real DAU, so we have to simulate some more) */
+
+
+#define CCTWR 34 /* IC write/read-address of vtx-chip */
+#define CCTRD 35
+#define NOACK_REPEAT 10 /* Retry access this many times on failure */
+#define CLEAR_DELAY 5 /* Time in jiffies required to clear a page */
+#define I2C_TIMEOUT 300 /* open/close/SDA-check timeout in jiffies */
+#define READY_TIMEOUT 3 /* Time in jiffies to wait for ready signal of IC-bus interface */
+#define INIT_DELAY 500 /* Time in usec to wait at initialization of CEA interface */
+#define START_DELAY 10 /* Time in usec to wait before starting write-cycle (CEA) */
+
+#define VTX_DEV_MINOR 0
+
+/* General defines and debugging support */
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#define RESCHED \
+ do { \
+ if (need_resched) \
+ schedule(); \
+ } while (0)
+
+#ifdef DEBUG_VTX
+int debug = 1;
+#define RETURN(val, str) \
+ do { \
+ if (debug > 1 || (debug == 1 && (val))) { \
+ printk("%svtx: " str "\n", (val) ? KERN_ERR : KERN_DEBUG); \
+ } \
+ return (val); \
+ } while (0)
+#define RETURNx1(val, str, arg1) \
+ do { \
+ if (debug > 1 || (debug == 1 && (val))) { \
+ printk("%svtx: " str "\n", (val) ? KERN_ERR : KERN_DEBUG, (arg1)); \
+ } \
+ return (val); \
+ } while (0)
+#define RETURNx2(val, str, arg1, arg2) \
+ do { \
+ if (debug > 1 || (debug == 1 && (val))) { \
+ printk("%svtx: " str "\n", (val) ? KERN_ERR : KERN_DEBUG, (arg1), (arg2)); \
+ } \
+ return (val); \
+ } while (0)
+#define NOTIFY(level, str) \
+ do { \
+ if (debug >= (level)) { \
+ printk("%svtx: " str "\n", (level) > 1 ? KERN_DEBUG : KERN_NOTICE); \
+ } \
+ } while (0)
+#define NOTIFYx1(level, str, arg1) \
+ do { \
+ if (debug >= (level)) { \
+ printk("%svtx: " str "\n", (level) > 1 ? KERN_DEBUG : KERN_NOTICE, (arg1)); \
+ } \
+ } while (0)
+#define NOTIFYx2(level, str, arg1, arg2) \
+ do { \
+ if (debug >= (level)) { \
+ printk("%svtx: " str "\n", (level) > 1 ? KERN_DEBUG : KERN_NOTICE, (arg1), (arg2)); \
+ } \
+ } while (0)
+#else
+#define RETURN(val, str) return (val)
+#define RETURNx1(val, str, arg1) return (val)
+#define RETURNx2(val, str, arg1, arg2) return (val)
+#define NOTIFY(level, str)
+#define NOTIFYx1(level, str, arg1)
+#define NOTIFYx2(level, str, arg1, arg2)
+#endif
+
+
+/* Wait the given number of jiffies (10ms). This calls the scheduler, so the actual
+ * delay may be longer.
+ */
+static void
+jdelay(unsigned long delay) {
+ sigset_t oldblocked = current->blocked;
+
+ spin_lock_irq(&current->sigmask_lock);
+ sigfillset(&current->blocked);
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + delay;
+ schedule();
+
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked = oldblocked;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->sigmask_lock);
+}
+
+
+/* Send arbitrary number of bytes to IC-bus. Start & stop handshaking is done by this routine.
+ * adr should be address of IC-device, varargs-list of values to send must be terminated by -1
+ * Returns -1 if IC-device didn't send acknowledge, 0 otherwise
+ */
+static int
+i2c_senddata(int adr, ...) {
+ int val, loop;
+ va_list argp;
+
+ for (loop = 0; loop <= NOACK_REPEAT; loop++) {
+ i2c_start(bus);
+ if (i2c_sendbyte(bus, adr, 0) != 0)
+ goto loopend;
+
+ va_start(argp, adr);
+ while ((val = va_arg(argp, int)) != -1) {
+ if (val < 0 || val > 255) {
+ printk(KERN_ERR "vtx: internal error in i2c_senddata\n");
+ break;
+ }
+ if (i2c_sendbyte(bus, val, 0) != 0)
+ goto loopend;
+ }
+ va_end(argp);
+ i2c_stop(bus);
+ return 0;
+loopend:
+ i2c_stop(bus);
+ NOTIFYx1(1, "i2c_senddata: retry (loop=%d)", loop);
+ }
+ va_end(argp);
+ return -1;
+}
+
+
+/* Send count number of bytes from buffer buf to IC-device adr. Start & stop handshaking is
+ * done by this routine. If uaccess is TRUE, data is read from user-space with get_user.
+ * Returns -1 if IC-device didn't send acknowledge, 0 otherwise
+ */
+static int
+i2c_sendbuf(int adr, int reg, int count, byte_t *buf, int uaccess) {
+ int pos, loop;
+ byte_t val;
+
+ for (loop = 0; loop <= NOACK_REPEAT; loop++) {
+ i2c_start(bus);
+ if (i2c_sendbyte(bus, adr, 0) != 0
+ || i2c_sendbyte(bus, reg, 0) != 0)
+ goto loopend;
+ for (pos = 0; pos < count; pos++) {
+ if (uaccess)
+ get_user(val, buf + pos);
+ else
+ val = buf[pos];
+ if (i2c_sendbyte(bus, val, 0) != 0)
+ goto loopend;
+ RESCHED;
+ }
+ i2c_stop(bus);
+ return 0;
+loopend:
+ i2c_stop(bus);
+ NOTIFYx1(1, "i2c_sendbuf: retry (loop=%d)", loop);
+ }
+ return -1;
+}
+
+
+/* Get count number of bytes from IC-device at address adr, store them in buf. Start & stop
+ * handshaking is done by this routine, ack will be sent after the last byte to inhibit further
+ * sending of data. If uaccess is TRUE, data is written to user-space with put_user.
+ * Returns -1 if IC-device didn't send acknowledge, 0 otherwise
+ */
+static int
+i2c_getdata(int adr, int count, byte_t *buf, int uaccess) {
+ int pos, loop, val;
+
+ for (loop = 0; loop <= NOACK_REPEAT; loop++) {
+ i2c_start(bus);
+ if (i2c_sendbyte(bus, adr, 1) != 0)
+ goto loopend;
+ for (pos = 0; pos < count; pos++) {
+ val = i2c_readbyte(bus, (pos==count-1) ? 1 : 0);
+ if (uaccess) {
+ put_user(val, buf + pos);
+ } else {
+ buf[pos] = val;
+ }
+ RESCHED;
+ }
+ i2c_stop(bus);
+ return 0;
+loopend:
+ i2c_stop(bus);
+ NOTIFYx1(1, "i2c_getdata: retry (loop=%d)", loop);
+ }
+ return -1;
+}
+
+
+/* Standard character-device-driver functions
+ */
+
+static int
+vtx_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {
+ int err;
+ static int virtual_mode = FALSE;
+
+ NOTIFY(2, "vtx_ioctl");
+
+ switch(cmd) {
+ case VTXIOCGETINFO: {
+ vtx_info_t info;
+
+ info.version_major = VTX_VER_MAJ;
+ info.version_minor = VTX_VER_MIN;
+ info.numpages = NUM_DAUS;
+ /*info.cct_type = CCT_TYPE;*/
+ if ((err = verify_area(VERIFY_WRITE, (void*)arg, sizeof(vtx_info_t))))
+ RETURN(err, "VTXIOCGETINFO: EFAULT");
+ copy_to_user((void*)arg, &info, sizeof(vtx_info_t));
+ RETURN(0, "VTXIOCGETINFO: OK");
+ }
+
+ case VTXIOCCLRPAGE: {
+ vtx_pagereq_t req;
+
+ if ((err = verify_area(VERIFY_READ, (void*)arg, sizeof(vtx_pagereq_t))))
+ RETURN(err, "VTXIOCCLRPAGE: EFAULT");
+ copy_from_user(&req, (void*)arg, sizeof(vtx_pagereq_t));
+ if (req.pgbuf < 0 || req.pgbuf >= NUM_DAUS)
+ RETURN(-EINVAL, "VTXIOCCLRPAGE: EINVAL");
+ memset(vdau[req.pgbuf].pgbuf, ' ', sizeof(vdau[0].pgbuf));
+ vdau[req.pgbuf].clrfound = TRUE;
+ RETURN(0, "VTXIOCCLRPAGE: OK");
+ }
+
+ case VTXIOCCLRFOUND: {
+ vtx_pagereq_t req;
+
+ if ((err = verify_area(VERIFY_READ, (void*)arg, sizeof(vtx_pagereq_t))))
+ RETURN(err, "VTXIOCCLRFOUND: EFAULT");
+ copy_from_user(&req, (void*)arg, sizeof(vtx_pagereq_t));
+ if (req.pgbuf < 0 || req.pgbuf >= NUM_DAUS)
+ RETURN(-EINVAL, "VTXIOCCLRFOUND: EINVAL");
+ vdau[req.pgbuf].clrfound = TRUE;
+ RETURN(0, "VTXIOCCLRFOUND: OK");
+ }
+
+ case VTXIOCPAGEREQ: {
+ vtx_pagereq_t req;
+
+ if ((err = verify_area(VERIFY_READ, (void*)arg, sizeof(vtx_pagereq_t))))
+ RETURN(err, "VTXIOCPAGEREQ: EFAULT");
+ copy_from_user(&req, (void*)arg, sizeof(vtx_pagereq_t));
+ if (!(req.pagemask & PGMASK_PAGE))
+ req.page = 0;
+ if (!(req.pagemask & PGMASK_HOUR))
+ req.hour = 0;
+ if (!(req.pagemask & PGMASK_MINUTE))
+ req.minute = 0;
+ if (req.page < 0 || req.page > 0x8ff)
+ RETURN(-EINVAL, "VTXIOCPAGEREQ: EINVAL (1)");
+ req.page &= 0x7ff;
+ if (req.hour < 0 || req.hour > 0x3f || req.minute < 0 || req.minute > 0x7f ||
+ req.pagemask < 0 || req.pagemask >= PGMASK_MAX || req.pgbuf < 0 || req.pgbuf >= NUM_DAUS)
+ RETURN(-EINVAL, "VTXIOCPAGEREQ: EINVAL (2)");
+ vdau[req.pgbuf].sregs[0] = (req.pagemask & PG_HUND ? 0x10 : 0) | (req.page / 0x100);
+ vdau[req.pgbuf].sregs[1] = (req.pagemask & PG_TEN ? 0x10 : 0) | ((req.page / 0x10) & 0xf);
+ vdau[req.pgbuf].sregs[2] = (req.pagemask & PG_UNIT ? 0x10 : 0) | (req.page & 0xf);
+ vdau[req.pgbuf].sregs[3] = (req.pagemask & HR_TEN ? 0x10 : 0) | (req.hour / 0x10);
+ vdau[req.pgbuf].sregs[4] = (req.pagemask & HR_UNIT ? 0x10 : 0) | (req.hour & 0xf);
+ vdau[req.pgbuf].sregs[5] = (req.pagemask & MIN_TEN ? 0x10 : 0) | (req.minute / 0x10);
+ vdau[req.pgbuf].sregs[6] = (req.pagemask & MIN_UNIT ? 0x10 : 0) | (req.minute & 0xf);
+ vdau[req.pgbuf].stopped = FALSE;
+ vdau[req.pgbuf].clrfound = TRUE;
+ is_searching[req.pgbuf] = TRUE;
+ RETURN(0, "VTXIOCPAGEREQ: OK");
+ }
+
+ case VTXIOCGETSTAT: {
+ vtx_pagereq_t req;
+ byte_t infobits[10];
+ vtx_pageinfo_t info;
+ int a;
+
+ if ((err = verify_area(VERIFY_READ, (void*)arg, sizeof(vtx_pagereq_t))))
+ RETURN(err, "VTXIOCGETSTAT: EFAULT (read)");
+ copy_from_user(&req, (void*)arg, sizeof(vtx_pagereq_t));
+ if (req.pgbuf < 0 || req.pgbuf >= NUM_DAUS)
+ RETURN(-EINVAL, "VTXIOCGETSTAT: EINVAL");
+ if (!vdau[req.pgbuf].stopped) {
+ if (i2c_senddata(CCTWR, 2, 0, -1) ||
+ i2c_sendbuf(CCTWR, 3, sizeof(vdau[0].sregs), vdau[req.pgbuf].sregs, FALSE) ||
+ i2c_senddata(CCTWR, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) ||
+ i2c_senddata(CCTWR, 2, 0, vdau[req.pgbuf].sregs[0] | 8, -1) ||
+ i2c_senddata(CCTWR, 8, 0, 25, 0, -1))
+ RETURN(-EIO, "VTXIOCGETSTAT: EIO (pagereq)");
+ jdelay(PAGE_WAIT);
+ if (i2c_getdata(CCTRD, 10, infobits, FALSE))
+ RETURN(-EIO, "VTXIOCGETSTAT: EIO (getinfo)");
+
+ if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */
+ (memcmp(infobits, vdau[req.pgbuf].laststat, sizeof(infobits)) ||
+ jiffies >= vdau[req.pgbuf].expire)) { /* check if new page arrived */
+ if (i2c_senddata(CCTWR, 8, 0, 0, 0, -1) ||
+ i2c_getdata(CCTRD, VTX_PAGESIZE, vdau[req.pgbuf].pgbuf, FALSE))
+ RETURN(-EIO, "VTXIOCGETSTAT: EIO (normal_page)");
+ vdau[req.pgbuf].expire = jiffies + PGBUF_EXPIRE;
+ memset(vdau[req.pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE);
+ if (virtual_mode) {
+ /* Packet X/24 */
+ if (i2c_senddata(CCTWR, 8, 0, 0x20, 0, -1) ||
+ i2c_getdata(CCTRD, 40, vdau[req.pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40, FALSE))
+ RETURN(-EIO, "VTXIOCGETSTAT: EIO (virtual_row_24)");
+ /* Packet X/27/0 */
+ if (i2c_senddata(CCTWR, 8, 0, 0x21, 0, -1) ||
+ i2c_getdata(CCTRD, 40, vdau[req.pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40, FALSE))
+ RETURN(-EIO, "VTXIOCGETSTAT: EIO (virtual_row_27)");
+ /* Packet 8/30/0...8/30/15
+ * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30,
+ * so we should undo this here.
+ */
+ if (i2c_senddata(CCTWR, 8, 0, 0x22, 0, -1) ||
+ i2c_getdata(CCTRD, 40, vdau[req.pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40, FALSE))
+ RETURN(-EIO, "VTXIOCGETSTAT: EIO (virtual_row_30)");
+ }
+ vdau[req.pgbuf].clrfound = FALSE;
+ memcpy(vdau[req.pgbuf].laststat, infobits, sizeof(infobits));
+ } else {
+ memcpy(infobits, vdau[req.pgbuf].laststat, sizeof(infobits));
+ }
+ } else {
+ memcpy(infobits, vdau[req.pgbuf].laststat, sizeof(infobits));
+ }
+
+ info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) |
+ (infobits[0] & 0x0f);
+ if (info.pagenum < 0x100)
+ info.pagenum += 0x800;
+ info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f);
+ info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f);
+ info.charset = ((infobits[7] >> 1) & 7);
+ info.delete = !!(infobits[3] & 8);
+ info.headline = !!(infobits[5] & 4);
+ info.subtitle = !!(infobits[5] & 8);
+ info.supp_header = !!(infobits[6] & 1);
+ info.update = !!(infobits[6] & 2);
+ info.inter_seq = !!(infobits[6] & 4);
+ info.dis_disp = !!(infobits[6] & 8);
+ info.serial = !!(infobits[7] & 1);
+ info.notfound = !!(infobits[8] & 0x10);
+ info.pblf = !!(infobits[9] & 0x20);
+ info.hamming = 0;
+ for (a = 0; a <= 7; a++) {
+ if (infobits[a] & 0xf0) {
+ info.hamming = 1;
+ break;
+ }
+ }
+ if (vdau[req.pgbuf].clrfound)
+ info.notfound = 1;
+ if ((err = verify_area(VERIFY_WRITE, req.buffer, sizeof(vtx_pageinfo_t))))
+ RETURN(err, "VTXIOCGETSTAT: EFAULT (write)");
+ copy_to_user(req.buffer, &info, sizeof(vtx_pageinfo_t));
+ if (!info.hamming && !info.notfound) {
+ is_searching[req.pgbuf] = FALSE;
+ }
+ RETURN(0, "VTXIOCGETSTAT: OK");
+ }
+
+ case VTXIOCGETPAGE: {
+ vtx_pagereq_t req;
+ int start, end;
+
+ if ((err = verify_area(VERIFY_READ, (void*)arg, sizeof(vtx_pagereq_t))))
+ RETURN(err, "VTXIOCGETPAGE: EFAULT (read)");
+ copy_from_user(&req, (void*)arg, sizeof(vtx_pagereq_t));
+ if (req.pgbuf < 0 || req.pgbuf >= NUM_DAUS || req.start < 0 ||
+ req.start > req.end || req.end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE))
+ RETURN(-EINVAL, "VTXIOCGETPAGE: EINVAL");
+ if ((err = verify_area(VERIFY_WRITE, req.buffer, req.end - req.start + 1)))
+ RETURN(err, "VTXIOCGETPAGE: EFAULT (write)");
+ copy_to_user(req.buffer, &vdau[req.pgbuf].pgbuf[req.start], req.end - req.start + 1);
+ /* Always read the time directly from SAA5249
+ */
+ if (req.start <= 39 && req.end >= 32) {
+ start = MAX(req.start, 32);
+ end = MIN(req.end, 39);
+ if (i2c_senddata(CCTWR, 8, 0, 0, start, -1) ||
+ i2c_getdata(CCTRD, end - start + 1, req.buffer + start - req.start, TRUE))
+ RETURN(-EIO, "VTXIOCGETPAGE: EIO (time)");
+ }
+ /* Insert the current header if DAU is still searching for a page */
+ if (req.start <= 31 && req.end >= 7 && is_searching[req.pgbuf]) {
+ start = MAX(req.start, 7);
+ end = MIN(req.end, 31);
+ if (i2c_senddata(CCTWR, 8, 0, 0, start, -1) ||
+ i2c_getdata(CCTRD, end - start + 1, req.buffer + start - req.start, TRUE))
+ RETURN(-EIO, "VTXIOCGETPAGE: EIO (header)");
+ }
+ RETURN(0, "VTXIOCGETPAGE: OK");
+ }
+
+ case VTXIOCSTOPDAU: {
+ vtx_pagereq_t req;
+
+ if ((err = verify_area(VERIFY_READ, (void*)arg, sizeof(vtx_pagereq_t))))
+ RETURN(err, "VTXIOCSTOPDAU: EFAULT");
+ copy_from_user(&req, (void*)arg, sizeof(vtx_pagereq_t));
+ if (req.pgbuf < 0 || req.pgbuf >= NUM_DAUS)
+ RETURN(-EINVAL, "VTXIOCSTOPDAU: EINVAL");
+ vdau[req.pgbuf].stopped = TRUE;
+ is_searching[req.pgbuf] = FALSE;
+ RETURN(0, "VTXIOCSTOPDAU: OK");
+ }
+
+ case VTXIOCPUTPAGE: {
+ RETURN(0, "VTXIOCPUTPAGE: OK (dummy)");
+ }
+
+ case VTXIOCSETDISP: {
+ RETURN(0, "VTXIOCSETDISP: OK (dummy)");
+ }
+
+ case VTXIOCPUTSTAT: {
+ RETURN(0, "VTXIOCPUTSTAT: OK (dummy)");
+ }
+
+ case VTXIOCCLRCACHE: {
+ if (i2c_senddata(CCTWR, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(CCTWR, 11,
+ ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
+ ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', -1))
+ RETURN(-EIO, "VTXIOCCLRCACHE (clear_header)");
+ if (i2c_senddata(CCTWR, 3, 0x20, -1))
+ RETURN(-EIO, "VTXIOCCLRCACHE: EIO (clear_cache)");
+ jdelay(10 * CLEAR_DELAY); /* I have no idea how long we have to wait here */
+ RETURN(0, "VTXIOCCLRCACHE: OK");
+ }
+
+ case VTXIOCSETVIRT: {
+ /* The SAA5249 has virtual-row reception turned on always */
+ virtual_mode = arg;
+ RETURN(0, "VTXIOCSETVIRTUAL: OK (dummy)");
+ }
+ }
+ RETURN(-EINVAL, "vtx_ioctl: EINVAL (unknown command)");
+}
+
+
+static int
+common_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {
+ int retval;
+
+ NOTIFY(2, "common_ioctl");
+ if (MINOR(inode->i_rdev) == VTX_DEV_MINOR) {
+ retval = vtx_ioctl(inode, file, cmd, arg);
+ return retval;
+ }
+ RETURN(-ENODEV, "common_ioctl: ENODEV *** can't happen ***");
+}
+
+
+static int
+vtx_open(struct inode *inode, struct file *file) {
+ int pgbuf;
+
+ if (vtx_use_count++) {
+ RETURN(-EBUSY, "vtx_open: EBUSY (vtx_in_use)");
+ }
+
+ if (!bus) {
+ RETURN(-ENODEV, "vtx_open: ENODEV (could not attach to i2c bus)");
+ }
+
+ if (i2c_senddata(CCTWR, 0, 0, -1) || /* Select R11 */
+ /* Turn off parity checks (we do this ourselves) */
+ i2c_senddata(CCTWR, 1, disp_modes[disp_mode][0], 0, -1) ||
+ /* Display TV-picture, no virtual rows */
+ i2c_senddata(CCTWR, 4, NUM_DAUS, disp_modes[disp_mode][1], disp_modes[disp_mode][2], 7, -1)) {
+ /* Set display to page 4 */
+ RETURN(-EIO, "vtx_open: EIO (init)");
+ }
+
+ for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) {
+ memset(vdau[pgbuf].pgbuf, ' ', sizeof(vdau[0].pgbuf));
+ memset(vdau[pgbuf].sregs, 0, sizeof(vdau[0].sregs));
+ memset(vdau[pgbuf].laststat, 0, sizeof(vdau[0].laststat));
+ vdau[pgbuf].expire = 0;
+ vdau[pgbuf].clrfound = TRUE;
+ vdau[pgbuf].stopped = TRUE;
+ is_searching[pgbuf] = FALSE;
+ }
+
+ RETURN(0, "vtx_open: OK");
+}
+
+
+
+static int
+common_open(struct inode *inode, struct file *file) {
+ int retval;
+
+ NOTIFY(2, "common_open");
+ MOD_INC_USE_COUNT;
+
+ if (MINOR(inode->i_rdev) == VTX_DEV_MINOR) {
+ if ((retval = vtx_open(inode, file)) < 0) {
+ vtx_use_count--;
+ MOD_DEC_USE_COUNT;
+ }
+ return retval;
+ }
+ MOD_DEC_USE_COUNT;
+ RETURN(-ENODEV, "common_open: ENODEV");
+}
+
+
+static int
+common_release(struct inode *inode, struct file *file) {
+ NOTIFY(2, "common_release");
+
+ if (MINOR(inode->i_rdev) == VTX_DEV_MINOR) {
+ i2c_senddata(CCTWR, 1, 0x20, -1); /* Turn off CCT */
+ i2c_senddata(CCTWR, 5, 3, 3, -1); /* Turn off TV-display */
+ }
+ if (MINOR(inode->i_rdev) == VTX_DEV_MINOR) {
+ vtx_use_count--;
+ }
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+
+static struct file_operations vtx_fops = {
+ NULL, /* lseek */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ common_ioctl,
+ NULL, /* mmap */
+ common_open,
+ common_release,
+};
+
+
+/* Routines for loadable modules
+ */
+
+int
+init_module(void) {
+ unsigned char pci_bus, pci_dev_fn;
+
+ if (!quiet) {
+ printk(KERN_INFO "videotext driver (" IF_NAME " interface) version %d.%d\n",
+ VTX_VER_MAJ, VTX_VER_MIN);
+ }
+ if (pcibios_find_device(VTX_PCI_VENDOR, VTX_PCI_DEVICE, 0, &pci_bus, &pci_dev_fn)) {
+ printk(KERN_ERR "vtx: No PCI videotext device found\n");
+ return -EIO;
+ }
+ pcibios_read_config_dword(pci_bus, pci_dev_fn, PCI_BASE_ADDRESS_0, &io_base);
+ pci_memio_base = ioremap(io_base & PCI_BASE_ADDRESS_MEM_MASK, 4096);
+ if (!quiet) {
+ printk(KERN_INFO "vtx: PCI device at bus %u, device %u, function %u, address 0x%x\n",
+ pci_bus, PCI_SLOT(pci_dev_fn), PCI_FUNC(pci_dev_fn), io_base);
+ }
+ if (register_chrdev(major, VTX_NAME, &vtx_fops)) {
+ printk(KERN_ERR "vtx: Error: Cannot register major number %d\n", major);
+ iounmap(pci_memio_base);
+ return -EIO;
+ }
+
+ i2c_register_driver(&i2c_driver_videotext);
+
+ return 0;
+}
+
+
+void
+cleanup_module(void) {
+ if (!quiet) {
+ printk(KERN_INFO "removing videotext driver\n");
+ }
+ iounmap(pci_memio_base);
+
+ i2c_unregister_driver(&i2c_driver_videotext);
+
+ if (unregister_chrdev(major, VTX_NAME))
+ printk(KERN_WARNING "vtx: Warning: unregister_chrdev() failed\n");
+}
diff --git a/vtx/vtx.h b/vtx/vtx.h
new file mode 100644
index 0000000..e6cb904
--- /dev/null
+++ b/vtx/vtx.h
@@ -0,0 +1,128 @@
+#ifndef _VTX_H
+#define _VTX_H
+
+/* $Id: vtx.h,v 1.1.1.1 1998/03/28 12:11:30 root Exp $
+ *
+ * Copyright (c) 1994-97 Martin Buck <martin-2.buck@student.uni-ulm.de>
+ * Read COPYING for more information
+ *
+ */
+
+
+typedef unsigned char byte_t;
+
+
+/* videotext ioctls
+ */
+#define VTXIOCGETINFO 0x7101 /* get version of driver & capabilities of vtx-chipset */
+#define VTXIOCCLRPAGE 0x7102 /* clear page-buffer */
+#define VTXIOCCLRFOUND 0x7103 /* clear bits indicating that page was found */
+#define VTXIOCPAGEREQ 0x7104 /* search for page */
+#define VTXIOCGETSTAT 0x7105 /* get status of page-buffer */
+#define VTXIOCGETPAGE 0x7106 /* get contents of page-buffer */
+#define VTXIOCSTOPDAU 0x7107 /* stop data acquisition unit */
+#define VTXIOCPUTPAGE 0x7108 /* display page on TV-screen */
+#define VTXIOCSETDISP 0x7109 /* set TV-mode */
+#define VTXIOCPUTSTAT 0x710a /* set status of TV-output-buffer */
+#define VTXIOCCLRCACHE 0x710b /* clear cache on VTX-interface (if avail.) */
+#define VTXIOCSETVIRT 0x710c /* turn on virtual mode (this disables TV-display) */
+
+
+/* definitions for VTXIOCGETINFO
+ */
+#define SAA5243 0
+#define SAA5246 1
+#define SAA5249 2
+#define SAA5248 3
+#define XSTV5346 4
+
+typedef struct {
+ int version_major, version_minor; /* version of driver; if version_major changes, driver */
+ /* is not backward compatible!!! CHECK THIS!!! */
+ int numpages; /* number of page-buffers of vtx-chipset */
+ int cct_type; /* type of vtx-chipset (SAA5243, SAA5246, SAA5248 or
+ * SAA5249) */
+} vtx_info_t;
+
+
+/* definitions for VTXIOC{CLRPAGE,CLRFOUND,PAGEREQ,GETSTAT,GETPAGE,STOPDAU,PUTPAGE,SETDISP}
+ */
+#define MIN_UNIT (1<<0)
+#define MIN_TEN (1<<1)
+#define HR_UNIT (1<<2)
+#define HR_TEN (1<<3)
+#define PG_UNIT (1<<4)
+#define PG_TEN (1<<5)
+#define PG_HUND (1<<6)
+#define PGMASK_MAX (1<<7)
+#define PGMASK_PAGE (PG_HUND | PG_TEN | PG_UNIT)
+#define PGMASK_HOUR (HR_TEN | HR_UNIT)
+#define PGMASK_MINUTE (MIN_TEN | MIN_UNIT)
+
+typedef struct {
+ int page; /* number of requested page (hexadecimal) */
+ int hour; /* requested hour (hexadecimal) */
+ int minute; /* requested minute (hexadecimal) */
+ int pagemask; /* mask defining which values of the above are set */
+ int pgbuf; /* buffer where page will be stored */
+ int start; /* start of requested part of page */
+ int end; /* end of requested part of page */
+ void* buffer; /* pointer to beginning of destination buffer */
+} vtx_pagereq_t;
+
+
+/* definitions for VTXIOC{GETSTAT,PUTSTAT}
+ */
+#define VTX_PAGESIZE (40 * 24)
+#define VTX_VIRTUALSIZE (40 * 49)
+
+typedef struct {
+ int pagenum; /* number of page (hexadecimal) */
+ int hour; /* hour (hexadecimal) */
+ int minute; /* minute (hexadecimal) */
+ int charset; /* national charset */
+ unsigned delete : 1; /* delete page (C4) */
+ unsigned headline : 1; /* insert headline (C5) */
+ unsigned subtitle : 1; /* insert subtitle (C6) */
+ unsigned supp_header : 1; /* suppress header (C7) */
+ unsigned update : 1; /* update page (C8) */
+ unsigned inter_seq : 1; /* interrupted sequence (C9) */
+ unsigned dis_disp : 1; /* disable/suppress display (C10) */
+ unsigned serial : 1; /* serial mode (C11) */
+ unsigned notfound : 1; /* /FOUND */
+ unsigned pblf : 1; /* PBLF */
+ unsigned hamming : 1; /* hamming-error occured */
+} vtx_pageinfo_t;
+
+
+/* definitions for VTXIOCSETDISP
+ */
+typedef enum { DISPOFF, DISPNORM, DISPTRANS, DISPINS, INTERLACE_OFFSET } vtxdisp_t;
+
+
+
+/* tuner ioctls
+ */
+#define TUNIOCGETINFO 0x7201 /* get version of driver & capabilities of tuner */
+#define TUNIOCRESET 0x7202 /* reset tuner */
+#define TUNIOCSETFREQ 0x7203 /* set tuning frequency (unit: kHz) */
+#define TUNIOCGETFREQ 0x7204 /* get tuning frequency (unit: kHz) */
+#define TUNIOCSETCHAN 0x7205 /* set tuning channel */
+#define TUNIOCGETCHAN 0x7206 /* get tuning channel */
+
+
+typedef struct {
+ int version_major, version_minor; /* version of driver; if version_major changes, driver */
+ /* is not backward compatible!!! CHECK THIS!!! */
+ unsigned freq : 1; /* tuner can be set to given frequency */
+ unsigned chan : 1; /* tuner stores several channels */
+ unsigned scan : 1; /* tuner supports scanning */
+ unsigned autoscan : 1; /* tuner supports scanning with automatic stop */
+ unsigned afc : 1; /* tuner supports AFC */
+ unsigned dummy1, dummy2, dummy3, dummy4, dummy5, dummy6, dummy7, dummy8, dummy9, dummy10,
+ dummy11 : 1;
+ int dummy12, dummy13, dummy14, dummy15, dummy16, dummy17, dummy18, dummy19;
+} tuner_info_t;
+
+
+#endif /* _VTX_H */
diff --git a/x11.c b/x11.c
index 22b0872..4005a5c 100644
--- a/x11.c
+++ b/x11.c
@@ -14,6 +14,12 @@
#include <X11/Xaw/XawInit.h>
#include <X11/Xaw/Simple.h>
+#ifdef HAVE_MITSHM
+# include <sys/ipc.h>
+# include <sys/shm.h>
+# include <X11/extensions/XShm.h>
+#endif
+
#include "grab.h"
#include "x11.h"
@@ -23,23 +29,44 @@
#define DEL_TIMER(proc) XtRemoveTimeOut(proc)
#define ADD_TIMER(proc) XtAppAddTimeOut(app_context,200,proc,NULL)
+#ifdef HAVE_MITSHM
+#define XPUTIMAGE(dpy,dr,gc,xi,a,b,c,d,w,h) \
+ if (have_shmem) \
+ XShmPutImage(dpy,dr,gc,xi,a,b,c,d,w,h,True); \
+ else \
+ XPutImage(dpy,dr,gc,xi,a,b,c,d,w,h)
+#else
+#define XPUTIMAGE(dpy,dr,gc,xi,a,b,c,d,w,h) \
+ XPutImage(dpy,dr,gc,xi,a,b,c,d,w,h)
+#endif
+
/* ------------------------------------------------------------------------ */
-extern XtAppContext app_context;
+extern XtAppContext app_context;
static int display_bits = 0;
static int display_bytes = 0;
+static int pixmap_bytes = 0;
+static int have_shmem = 0;
+static int x11_error = 0;
int
x11_init(Display *dpy)
{
XVisualInfo *info, template;
- int found;
+ XPixmapFormatValues *pf;
+ int found,i,n;
int format = 0;
Screen *scr = DefaultScreenOfDisplay(dpy);
Window root;
XWindowAttributes wts;
+#ifdef HAVE_MITSHM
+ if (XShmQueryExtension(dpy)) {
+ have_shmem = 1;
+ }
+#endif
+
/* Ask for visual type */
template.screen = XDefaultScreen(dpy);
template.visualid =
@@ -52,13 +79,19 @@ x11_init(Display *dpy)
display_bits = wts.depth;
display_bytes = (display_bits+7)/8;
+
+ pf = XListPixmapFormats(dpy,&n);
+ for (i = 0; i < n; i++)
+ if (pf[i].depth == display_bits)
+ pixmap_bytes = pf[i].bits_per_pixel/8;
+
if (debug)
- fprintf(stderr,"x11: display: %d bits, %d bytes\n",
- display_bits,display_bytes);
+ fprintf(stderr,"x11: display: %d bits, %d bytes - pixmap: %d bytes\n",
+ display_bits,display_bytes,pixmap_bytes);
if (info->class == TrueColor) {
switch (display_bytes) {
case 2:
- format = (display_bits == 15) ? VIDEO_RGB15 : VIDEO_RGB16;
+ format = (display_bits==15) ? VIDEO_RGB15 : VIDEO_RGB16;
break;
case 3:
format = VIDEO_RGB24;
@@ -67,6 +100,17 @@ x11_init(Display *dpy)
format = VIDEO_RGB32;
break;
}
+ switch (pixmap_bytes) {
+ case 2:
+ x11_pixmap_format = (display_bits==15) ? VIDEO_RGB15 : VIDEO_RGB16;
+ break;
+ case 3:
+ x11_pixmap_format = VIDEO_RGB24;
+ break;
+ case 4:
+ x11_pixmap_format = VIDEO_RGB32;
+ break;
+ }
}
if (0 == format) {
fprintf(stderr, "sorry, visual not supported\n");
@@ -76,10 +120,132 @@ x11_init(Display *dpy)
return format;
}
+int
+x11_error_dev_null(Display * dpy, XErrorEvent * event)
+{
+ x11_error++;
+ if (debug > 1)
+ fprintf(stderr," x11-error");
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+/* ximage handling for grab & display */
+
+XImage *
+x11_create_ximage(Display *dpy, int width, int height, void **shm)
+{
+ XImage *ximage = NULL;
+ unsigned char *ximage_data;
+ Screen *scr = DefaultScreenOfDisplay(dpy);
+#ifdef HAVE_MITSHM
+ XShmSegmentInfo *shminfo = NULL;
+ void *old_handler;
+#endif
+
+ if (debug)
+ fprintf(stderr,"video: x11_create_ximage\n");
+#ifdef HAVE_MITSHM
+ if (have_shmem) {
+ x11_error = 0;
+ old_handler = XSetErrorHandler(x11_error_dev_null);
+ (*shm) = shminfo = malloc(sizeof(XShmSegmentInfo));
+ memset(shminfo, 0, sizeof(XShmSegmentInfo));
+ ximage = XShmCreateImage(dpy,
+ DefaultVisualOfScreen(scr),
+ DefaultDepthOfScreen(scr),
+ ZPixmap, NULL,
+ shminfo, width, height);
+ if (ximage) {
+ shminfo->shmid = shmget(IPC_PRIVATE,
+ ximage->bytes_per_line * ximage->height,
+ IPC_CREAT | 0777);
+ if (-1 == shminfo->shmid) {
+ perror("shmget");
+ goto oom;
+ }
+ shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0);
+ if ((void *) -1 == shminfo->shmaddr) {
+ perror("shmat");
+ goto oom;
+ }
+ ximage->data = shminfo->shmaddr;
+ shminfo->readOnly = False;
+
+ XShmAttach(dpy, shminfo);
+ XSync(dpy, False);
+ shmctl(shminfo->shmid, IPC_RMID, 0);
+ if (x11_error) {
+ have_shmem = 0;
+ shmdt(shminfo->shmaddr);
+ free(shminfo);
+ shminfo = *shm = NULL;
+ XDestroyImage(ximage);
+ ximage = NULL;
+ }
+ } else {
+ have_shmem = 0;
+ free(shminfo);
+ shminfo = *shm = NULL;
+ }
+ XSetErrorHandler(old_handler);
+ }
+#endif
+
+ if (ximage == NULL) {
+ (*shm) = NULL;
+ if (NULL == (ximage_data = malloc(width * height * display_bytes))) {
+ fprintf(stderr,"out of memory\n");
+ goto oom;
+ }
+ ximage = XCreateImage(dpy,
+ DefaultVisualOfScreen(scr),
+ DefaultDepthOfScreen(scr),
+ ZPixmap, 0, ximage_data,
+ width, height,
+ 8, 0);
+ }
+ memset(ximage->data, 0, ximage->bytes_per_line * ximage->height);
+
+ return ximage;
+
+oom:
+#ifdef HAVE_MITSHM
+ if (shminfo) {
+ if (shminfo->shmid && shminfo->shmid != -1)
+ shmctl(shminfo->shmid, IPC_RMID, 0);
+ free(shminfo);
+ }
+#endif
+ if (ximage)
+ XDestroyImage(ximage);
+ return NULL;
+}
+
+void
+x11_destroy_ximage(Display *dpy, XImage * ximage, void *shm)
+{
+#ifdef HAVE_MITSHM
+ XShmSegmentInfo *shminfo = shm;
+
+ if (shminfo) {
+ XShmDetach(dpy, shminfo);
+ XDestroyImage(ximage);
+ shmdt(shminfo->shmaddr);
+ free(shminfo);
+ } else
+#endif
+ XDestroyImage(ximage);
+
+ if (debug)
+ fprintf(stderr,"video: x11_destroy_ximage\n");
+}
+
/* ------------------------------------------------------------------------ */
/* video overlay stuff */
int x11_native_format;
+int x11_pixmap_format;
int swidth,sheight; /* screen */
static Widget video,video_parent;
@@ -94,6 +260,10 @@ static int visibility = VisibilityFullyObscured;
static int conf = 1, overlay_on = 0;
static struct OVERLAY_CLIP oc[32];
+static XImage *ximage;
+static void *ximage_shm; /* used for MIT shmem */
+static GC gc;
+
/* ------------------------------------------------------------------------ */
static char *events[] = {
@@ -135,14 +305,6 @@ static char *events[] = {
/* ------------------------------------------------------------------------ */
-int
-x11_error_dev_null(Display * dpy, XErrorEvent * event)
-{
- if (debug > 1)
- fprintf(stderr," x11-error");
- return 0;
-}
-
static void
add_clip(int x1, int y1, int x2, int y2)
{
@@ -314,6 +476,11 @@ video_new_size()
if (ox < wx) ox += 4;
if (ox+owidth > wx+wwidth) owidth -= 4;
+ if (ximage) {
+ x11_destroy_ximage(DISPLAY(video), ximage, ximage_shm);
+ ximage = NULL;
+ }
+
conf = 1;
configure_overlay();
}
@@ -439,7 +606,6 @@ video_setmax(int x, int y)
void
video_overlay(set_overlay cb)
{
-
if (cb) {
overlay_cb = cb;
conf = 1;
@@ -454,6 +620,29 @@ video_overlay(set_overlay cb)
}
}
+int
+video_displayframe(get_frame cb)
+{
+ if (!WINDOW(video))
+ return -1;
+ if (!gc)
+ gc = XCreateGC(DISPLAY(video),WINDOW(video),0,NULL);
+ if (!ximage) {
+ ximage = x11_create_ximage(DISPLAY(video),owidth,oheight,&ximage_shm);
+ if (NULL == ximage) {
+ fprintf(stderr,"oops: out of memory\n");
+ exit(1);
+ }
+ }
+
+ if (NULL == cb(ximage->data,owidth,oheight))
+ return -1;
+ XPUTIMAGE(DISPLAY(video), WINDOW(video), gc, ximage,
+ 0,0,ox-wx,oy-wy, owidth, oheight);
+ return 0;
+}
+
+
Widget
video_init(Widget parent)
{
@@ -496,6 +685,9 @@ video_close(void)
XSelectInput(DISPLAY(video),root,0);
XtUnregisterDrawable(DISPLAY(video),root);
-}
-
+ if (ximage) {
+ x11_destroy_ximage(DISPLAY(video), ximage, ximage_shm);
+ ximage = NULL;
+ }
+}
diff --git a/x11.h b/x11.h
index 5607538..e314e70 100644
--- a/x11.h
+++ b/x11.h
@@ -1,13 +1,15 @@
extern int x11_native_format;
+extern int x11_pixmap_format;
extern int swidth,sheight;
-typedef int (*set_overlay)(int x, int y, int w, int h, int f,
- struct OVERLAY_CLIP *oc, int count);
+typedef int (*set_overlay)(int x, int y, int w, int h, int f,
+ struct OVERLAY_CLIP *oc, int count);
+typedef void* (*get_frame)(void *dest, int width, int height);
void video_new_size();
void video_overlay(set_overlay);
+int video_displayframe(get_frame cb);
void video_setmax(int x, int y);
Widget video_init(Widget parent);
void video_close(void);
-
diff --git a/xawtv.man b/xawtv.man
index 56472e1..04f9d2c 100644
--- a/xawtv.man
+++ b/xawtv.man
@@ -64,8 +64,10 @@ V Video (Capture) on/off
A Audio on/off
M Mouse pointer on/off
F Fullscreen on/off
-G Grab picture (ppm)
-J Grab picture (jpeg)
+G Grab picture (full size, ppm)
+J Grab picture (full size, jpeg)
+Ctrl+G Grab picture (window size, ppm)
+Ctrl+J Grab picture (window size, jpeg)
up+down tune up/down one channel
left+right fine tuning
@@ -121,9 +123,21 @@ input source
.B contrast = n
Valid range is 0-65535, default is 32768
.P
-There are two global options allowed before the first station only:
+There are three global options allowed before the first station only:
.TP
-.B freqtab = europe | usa
+.B fullscreen = width x height
+specify which video mode should be used for full-screen. Works with
+XFree only, and of cource you need a valid modeline for this mode in
+your XF86Config file.
+.TP
+.B wm-off-by = [+-]x[+-]y
+Some WM's handle static gravity not correct (I know mwm and
+kwm). This is somewhat boring with fullscreen mode. With this
+options you can correct this with a displacement for moving
+windows. For example, wm-off-by = -4-24 does the trick for kwm (the
+KDE window manager).
+.TP
+.B freqtab =
select a channel-to-freqency mapping
.TP
.B mixer = device
@@ -138,10 +152,17 @@ mute.
My config file looks like this:
.P
.nf
+# this is a comment
+# empty lines are ignored too
+
source = television
norm = pal
-freqtab = europe
+freqtab = pal-europe
#mixer = synth
+fullscreen = 768x576
+
+# for /etc/XF86Config
+# Modeline "pal" 50.00 768 832 856 1000 576 590 595 630 -hsync -vsync
[ZDF]
channel=33
@@ -161,9 +182,6 @@ key = K
Whats this?
.SH SEE ALSO
http://www.cs.tu-berlin.de/~kraxel/linux/#xawtv (xawtv homepage)
-
-http://www.thp.uni-koeln.de/~rjkm/linux/bttv.html (bttv driver
-homepage)
.SH AUTHOR
Gerd Knorr <kraxel@cs.tu-berlin.de>
.SH COPYRIGHT

Privacy Policy