diff -urN /tmp/xawtv-3.11/Changes xawtv-3.12/Changes --- /tmp/xawtv-3.11/Changes Sat Mar 25 18:49:08 2000 +++ xawtv-3.12/Changes Mon Apr 3 20:05:13 2000 @@ -1,4 +1,18 @@ +3.11 => 3.12 +============ + + * Added the missing -D_REENTRANT to the Makefile + * picked up the r@dio.mp3 client from the v4l list, put it + into the contrib directory. + * avi recording fix (audio+video stream length are identical now). + * xawtv-remote protocol supports more than one command now. Commands + are separated by a zero-length string, i.e. 'xawtv-remote foo "" bar' + * new xawtv-remote command: vtx (interface for subtitles). Check + the man-page for details. + * webcam fixes. + + 3.10 => 3.11 ============ diff -urN /tmp/xawtv-3.11/TODO xawtv-3.12/TODO --- /tmp/xawtv-3.11/TODO Fri Feb 4 20:16:56 2000 +++ xawtv-3.12/TODO Mon Apr 3 20:11:00 2000 @@ -7,13 +7,13 @@ general ======= - * frequency= option for .xawtv - * volume= option for .xawtv + * volume= option for .xawtv (not trivial - to make this a useful feature + it should be a station-specific offset to the overall volume. Try to + get this right for every soundcard / high + low volume / ... ). * videotext decoder (for station ID, maybe subtitles) * keep-aspect-ratio option * switch to another toolkit, Xaw keyboard/menu support sucks - (gtk maybe?) - * use threads (instead of fork()ing off children) + (gtk maybe? How to do low-level X11 stuff with gtk?) * config file args for avi-params? * i18n/locale @@ -21,12 +21,8 @@ avi === - * mjpeg compression has alot of (partly design) problems, have to think - about how to handle this in a clever way... * grayscale avi recording (anybody knows how to do this? 256 color with a gray palette?) * OpenDML index support - * showriff has problems with files > 2 GB. - * fix audio/video sync problems [ is'nt trivial ... ] - * The windows media player seems to have problems with our avi - files... + * showriff has problems with files > 2 GB. Not sure if it's me or glibc... + diff -urN /tmp/xawtv-3.11/contrib/r@dio.mp3/Makefile xawtv-3.12/contrib/r@dio.mp3/Makefile --- /tmp/xawtv-3.11/contrib/r@dio.mp3/Makefile Thu Jan 1 01:00:00 1970 +++ xawtv-3.12/contrib/r@dio.mp3/Makefile Fri Mar 31 23:47:14 2000 @@ -0,0 +1,11 @@ + +BINDIR=$(HOME)/bin +CFLAGS=-Wall -g -O2 + +all: nbc-vbi + +install: nbc-vbi + install nbc-vbi nbc $(BINDIR) + +clean: + -rm -f nbc-vbi *~ diff -urN /tmp/xawtv-3.11/contrib/r@dio.mp3/README xawtv-3.12/contrib/r@dio.mp3/README --- /tmp/xawtv-3.11/contrib/r@dio.mp3/README Thu Jan 1 01:00:00 1970 +++ xawtv-3.12/contrib/r@dio.mp3/README Sat Apr 1 00:12:10 2000 @@ -0,0 +1,20 @@ + +Picked it up from the v4l mailing list. Original message below. +Fixed some minor problems (seems not to segfault any more now). +Added a wrapper shell script. Does work fine with bttv. + +It's public domain. Have fun, + + Gerd + +----------------------------------------------------------------------- +Here's a codelet capturing you know what. It hasn't been tested with +bttv (but it works with _my_ hw, something I can't even say about +their W9x stuff). It segfaults sometimes and has no FEC code. I +couldn't figure out how that works, possibly a Galois field or some +weird kind of CRC. mpg123 derivatives don't like these mangled .mp3 +files, freeamp works sufficiently well. Heck, this is so cool I just +couldn't keep it. + +Enjoy, +Michael diff -urN /tmp/xawtv-3.11/contrib/r@dio.mp3/nbc xawtv-3.12/contrib/r@dio.mp3/nbc --- /tmp/xawtv-3.11/contrib/r@dio.mp3/nbc Thu Jan 1 01:00:00 1970 +++ xawtv-3.12/contrib/r@dio.mp3/nbc Sat Apr 1 17:04:19 2000 @@ -0,0 +1,40 @@ +#!/bin/sh + +# config +DEST=/media/mp3/nbc + +# startup in xterm if X11 is running +if test "$DISPLAY" != "" -a "$NBC" = ""; then + export NBC=on + exec xterm -geometry 55x10 -title "NBC r@dio.mp3" -e $0 +fi + +# setup everything (assumes you have NBC in your ~/.xawtv) +v4lctl setstation nbc +sleep 1 +v4lctl volume mute +cd $DEST + +# monitor loop: queues up new files to xmms, deletes unused files +( + last="`ls -t *.mp3 | head -1`" + while sleep 10; do + this="`ls -t *.mp3 | head -1`" + if test "$this" != "$last"; then + last="$this" + if test "$DISPLAY" != ""; then + # put it into the xmms playlist. Note: + # xmms should already be started, otherwise + # the script will block here... + xmms -e "$this" + else + # any fancy console player? + echo "new file: $this" + fi + rm -f *.JPG crop-* + fi + done +)& + +# finally startup the decoder +exec nbc-vbi diff -urN /tmp/xawtv-3.11/contrib/r@dio.mp3/nbc-vbi.c xawtv-3.12/contrib/r@dio.mp3/nbc-vbi.c --- /tmp/xawtv-3.11/contrib/r@dio.mp3/nbc-vbi.c Thu Jan 1 01:00:00 1970 +++ xawtv-3.12/contrib/r@dio.mp3/nbc-vbi.c Sun Apr 2 16:07:55 2000 @@ -0,0 +1,635 @@ +/* + * Capture NBC GIGA Musicplay MP3 broadcast (w/o FEC) + * + * Placed in the public domain. + * + * gcc -Wall mp3cap.c -omp3cap -O2 -fomit-frame-pointer + */ + +#include +#include +#include +#include + +int line; +int row; +int block_ic; +int last_row = -1; +int last_block_ic = -1; +int audio_x1 = -1; +char audio_name[256]; +struct { + int x1; + int off; + int max; + unsigned char * buf; +} streams[16]; +unsigned char line_buf[64]; +unsigned char block[15][896]; + +/* + * ETS 300 706 May 1997 8.2 Hamming 8/4 + */ +unsigned char +hamming84[256] = +{ + 0x41, 0xff, 0x01, 0x41, 0xff, 0x40, 0x41, 0xff, 0xff, 0x42, 0x41, 0xff, 0x4a, 0xff, 0xff, 0x47, + 0xff, 0x40, 0x41, 0xff, 0x40, 0x00, 0xff, 0x40, 0x46, 0xff, 0xff, 0x4b, 0xff, 0x40, 0x43, 0xff, + 0xff, 0x4c, 0x41, 0xff, 0x44, 0xff, 0xff, 0x47, 0x46, 0xff, 0xff, 0x47, 0xff, 0x47, 0x47, 0x07, + 0x46, 0xff, 0xff, 0x45, 0xff, 0x40, 0x4d, 0xff, 0x06, 0x46, 0x46, 0xff, 0x46, 0xff, 0xff, 0x47, + 0xff, 0x42, 0x41, 0xff, 0x44, 0xff, 0xff, 0x49, 0x42, 0x02, 0xff, 0x42, 0xff, 0x42, 0x43, 0xff, + 0x48, 0xff, 0xff, 0x45, 0xff, 0x40, 0x43, 0xff, 0xff, 0x42, 0x43, 0xff, 0x43, 0xff, 0x03, 0x43, + 0x44, 0xff, 0xff, 0x45, 0x04, 0x44, 0x44, 0xff, 0xff, 0x42, 0x4f, 0xff, 0x44, 0xff, 0xff, 0x47, + 0xff, 0x45, 0x45, 0x05, 0x44, 0xff, 0xff, 0x45, 0x46, 0xff, 0xff, 0x45, 0xff, 0x4e, 0x43, 0xff, + 0xff, 0x4c, 0x41, 0xff, 0x4a, 0xff, 0xff, 0x49, 0x4a, 0xff, 0xff, 0x4b, 0x0a, 0x4a, 0x4a, 0xff, + 0x48, 0xff, 0xff, 0x4b, 0xff, 0x40, 0x4d, 0xff, 0xff, 0x4b, 0x4b, 0x0b, 0x4a, 0xff, 0xff, 0x4b, + 0x4c, 0x0c, 0xff, 0x4c, 0xff, 0x4c, 0x4d, 0xff, 0xff, 0x4c, 0x4f, 0xff, 0x4a, 0xff, 0xff, 0x47, + 0xff, 0x4c, 0x4d, 0xff, 0x4d, 0xff, 0x0d, 0x4d, 0x46, 0xff, 0xff, 0x4b, 0xff, 0x4e, 0x4d, 0xff, + 0x48, 0xff, 0xff, 0x49, 0xff, 0x49, 0x49, 0x09, 0xff, 0x42, 0x4f, 0xff, 0x4a, 0xff, 0xff, 0x49, + 0x08, 0x48, 0x48, 0xff, 0x48, 0xff, 0xff, 0x49, 0x48, 0xff, 0xff, 0x4b, 0xff, 0x4e, 0x43, 0xff, + 0xff, 0x4c, 0x4f, 0xff, 0x44, 0xff, 0xff, 0x49, 0x4f, 0xff, 0x0f, 0x4f, 0xff, 0x4e, 0x4f, 0xff, + 0x48, 0xff, 0xff, 0x45, 0xff, 0x4e, 0x4d, 0xff, 0xff, 0x4e, 0x4f, 0xff, 0x4e, 0x0e, 0xff, 0x4e +}; + +inline int +unhamb(unsigned char *d, int *b) +{ + unsigned char c1, c2; + + c1 = hamming84[d[0]]; + c2 = hamming84[d[1]]; + + if ((c1 | c2) & 0xC0) + return -1; + + *b = c2 * 16 + c1; + return 0; +} + +inline int +unhamn(unsigned char *d, int *b) +{ + unsigned char c1; + + c1 = hamming84[d[0]]; + + if (c1 & 0xC0) + return -1; + + *b = c1; + return 0; +} + +void FlatStream(int x1, int x2, int x3, unsigned char *data, int size) +{ + char buf[256]; + FILE *fi; + + sprintf(buf, "%04x", x1); + + if (x2 == 0) + fi = fopen(buf, "w"); + else + fi = fopen(buf, "a"); + + fwrite(data, size, 1, fi); + fclose(fi); + + if (x3 > 1000000) { + audio_x1 = x1; + printf("%7.1f %%\r", 100.0 * x2 / x3); + fflush(stdout); + } +} + +void +WriteFile(char *name, unsigned char *data, int size) +{ + FILE *fi; + + fi = fopen(name, "w"); + fwrite(data, sizeof data[0], size, fi); + fclose(fi); +} + +#define LEW(s) ((s)[0] | ((s)[1] << 8)) +#define LEDW(s) ((s)[0] | ((s)[1] << 8) | ((s)[2] << 16) | ((s)[3] << 24)) + +void +Names(unsigned char *data) +{ + char *n[20]; + int i = 0; + + memset(n,0,20*sizeof(char*)); + while (*data) { + n[i++] = data; + do { + if (*data != 0 && iscntrl(*data)) + *data = '.'; + } + while (*data++); + } + +// for (j = 0; j < i; j++) +// printf("%d: %s\n", j, n[j]); + + printf("%s\n\n" + "On Air: %-16s %s\n" + "Next: %-16s %s\n" + " %-16s %s\n" + " %-16s %s\n\n", + n[3], + n[2], n[1], n[5], n[4], + n[7], n[6], n[9], n[8]); + + snprintf(audio_name, sizeof audio_name, "%s - %s.mp3", n[2], n[1]); +} + +void +Unpack(unsigned char *data, int x1, int size) +{ + char name[256]; + int files = LEDW(data); + + if (!memcmp(data, "hipZeigen", 10) || + !memcmp(data, "hipNichtZeigen", 10)) { + Names(data); + return; + } + + if (files < 1 || files > 20) { + // something else + sprintf(name, "crop-%04x", x1); + WriteFile(name, data, size); + } else { + unsigned char *s = data + 4 + 4 * files; + int i; + + for (i = 0; i < files; i++) { + int len; + + if (s + 2 - data > size) + return; + len = s[1]; + if (s + 2 + len - data > size) + return; + memcpy(name, s + 2, len); + name[len] = 0; + s += 2 + len; + + len = LEDW(data + 4 + 4 * i); + if (s + len - data > size) + return; + WriteFile(name, s, len); + s += len; + } + } +} + +void +ResetStreams(void) +{ + int i; + + for (i = 0; i < 16; i++) { + if (streams[i].x1 > 0) { + Unpack(streams[i].buf, streams[i].x1, streams[i].off); + free(streams[i].buf); + } + + streams[i].x1 = -1; + } + + if (audio_x1 > 0 && audio_name[0]) { + char buf[16]; + + snprintf(buf, sizeof buf, "%04x", audio_x1); + rename(buf, audio_name); + } + + audio_x1 = -1; + audio_name[0] = 0; +} + +void +OtherStream(int x1, int x2, int x3, unsigned char *data, int size) +{ + int i; + + if (x1 == 0) { // new generation + ResetStreams(); + return; + } + + if (x2 == 0) { // first chunk + for (i = 0; i < 16; i++) + if (streams[i].x1 < 0) + break; + if (i >= 16) + return; + + streams[i].x1 = x1; + streams[i].off = 0; + streams[i].max = x3; + streams[i].buf = malloc(x3 + 1000); + } else { + for (i = 0; i < 16; i++) + if (streams[i].x1 == x1) + break; + if (i >= 16) + return; + } + + if (x2 != streams[i].off + || x3 != streams[i].max + || streams[i].off + size > streams[i].max + 1000) { + printf("%8d ** File size/offset mismatch\n", line); + } + + memcpy(streams[i].buf + streams[i].off, data, size); + streams[i].off += size; + + if (x2 + size >= x3) { // last chunk + Unpack(streams[i].buf, x1, x3); + free(streams[i].buf); + streams[i].x1 = -1; + } +} + +int +NewBlock(void) +{ + int x1, x2, x3; + int x, y; + + if (last_block_ic < 0) + return 0; + + if (0) { + for (y = 0; y < 15; y++) { + x1 = LEW(&block[y][0]); + x2 = LEDW(&block[y][2]); + x3 = LEDW(&block[y][6]); + + printf("%04x %08x %08x ", x1, x2, x3); + + for (x = 10; x < 896; x++) + printf("%c", ((block[y][x] & 0x7F) >= 0x20) ? block[y][x] : '.'); + // printf("%02x", block[y][x]); + + printf("\n"); + } + + printf("\n"); + } + + /* Error correction here */ + + for (y = 0; y < 13; y++) { + x1 = LEW(&block[y][0]); + x2 = LEDW(&block[y][2]); + x3 = LEDW(&block[y][6]); + + if (x3 > 1000000) // ?syntax magic? + FlatStream(x1, x2, x3, &block[y][16], 880); // Audio + else + OtherStream(x1, x2, x3, &block[y][16 + 22], 880 - 22); + } + + return 0; +} + +int +RowHeader(void) +{ + if (unhamn(line_buf + 3, &row) < 0 || + unhamn(line_buf + 4, &block_ic) < 0 || + block_ic < 1 || block_ic > 9) { + printf("%8d ** Row header error\n", line); + return -1; + } + +// printf("%8d -- Row header %02x\n", line, block_ic * 16 + row); + + switch (row) { + case 0x1: + NewBlock(); + memset(block, 0, sizeof block); + break; + + case 0x2 ... 0xF: + if (last_row < 0) + return 0; + else if (last_row + 1 != row) { + printf("%8d ** Row lost (0x%x follows 0x%x)\n", line, row, last_row); + // return -1; + } + break; + + default: + printf("%8d ** Row number 0x%x out of bounds\n", line, row); + return -1; + } + + memcpy(&block[row - 1][0], line_buf + 5, 38); + + last_block_ic = block_ic; + last_row = row; + + return 0; +} + +static int +RowPacket(int packet) +{ + int row1; + + if (unhamn(line_buf + 3, &row1) < 0) { + printf("%8d ** Row packet error\n", line); + return -1; + } + +// printf("%8d -- Row packet 0x%x\n", line, row1); + + if (last_row < 1) + return 0; + + if (row != row1) { + printf("%8d ** Row header lost\n", line); + return -1; + } + + memcpy(&block[row - 1][38 + (packet - 2) * 39], line_buf + 4, 39); + + return 0; +} + +static int +Teletext(void) +{ + static int last_packet = -1; + int pmag, magazine, packet; + int php[8], pnum, subc, i; + + if (unhamb(line_buf + 1, &pmag) < 0) { + printf("%8d ** Pmag error\n", line); + return -1; + } + + magazine = pmag & 7; + packet = pmag >> 3; + + if (magazine != 0) { +// printf("%8d -- Packet ignored: %d-%d\n", line, magazine, packet); + return 0; + } + + switch (packet) { + case 0: + for (i = 0; i < 8; i++) { + if (unhamn(line_buf + i + 3, php + i) < 0) { + printf("%8d ** Page header error\n", line); + return -1; + } + } + + pnum = php[1] * 16 + php[0]; + subc = (php[5] & 3) * 4096 + php[4] * 256 + (php[3] & 7) * 16 + php[2]; + +// printf("%8d -- Page header 8%02x - %04x\n", line, pnum, subc); + + break; + + case 1: + if (last_packet < 0) + return 0; + else if (last_packet != 0) { + printf("%8d ** Packet order mismatch - header lost?\n", line); + return -1; + } + + if (RowHeader() < 0) + return -1; + + break; + + case 2 ... 23: + if (last_packet < 0) + return 0; + else if (last_packet + 1 != packet) { + printf("%8d ** Packets lost (#%d follows #%d)\n", line, packet, last_packet); + // return -1; + } + + RowPacket(packet); + + break; + + default: + + printf("%8d ** Packet number %d out of bounds\n", line, packet); + return -1; + } + + last_packet = packet; + + return 0; +} + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef V4L2_MAJOR_VERSION + +struct v4l2_capability cap; +struct v4l2_format format; + +#endif + +unsigned char *raw; +int lines, samples, rate; +int rawsize, step; + +/* Data acquisition routine from AleVT (should use error feedback) */ + +#define FAC (1<<16) + +int vbi_fine_tune = 0; // delay decoding n/10 bit length + +typedef unsigned char u8; + +static int +vbi_line(u8 *p) +{ + u8 min, max; + int dt[256], hi[6], lo[6]; + int i, n, sync, thr; + + /* remove DC. edge-detector */ + for (i = 0; i < 240; ++i) + dt[i] = p[i+step/FAC] - p[i]; // amplifies the edges best. + + /* set barrier */ + for (i = 240; i < 256; i += 2) + dt[i] = 100, dt[i+1] = -100; + + /* find 6 rising and falling edges */ + for (i = 0, n = 0; n < 6; ++n) + { + while (dt[i] < 32) + i++; + hi[n] = i; + while (dt[i] > -32) + i++; + lo[n] = i; + } + if (i >= 240) + return -1; // not enough periods found + +// i = hi[5] - hi[1]; // length of 4 periods (8 bits), normally 40.9 +// if (i < 39 || i > 42) +// return -1; // bad frequency + + /* AGC and sync-reference */ + + min = 255, max = 0, sync = 0; + for (i = hi[4]; i < hi[5]; ++i) + if (p[i] > max) + max = p[i], sync = i; + for (i = lo[4]; i < lo[5]; ++i) + if (p[i] < min) + min = p[i]; + thr = (min + max) / 2; + + p += sync; + + /* search start-byte 11100100 */ + for (i = 4*step + vbi_fine_tune*step/10; i < 16*step; i += step) + if (p[i/FAC] > thr && p[(i+step)/FAC] > thr) // two ones is enough... + { + /* got it... */ + memset(line_buf, 0, sizeof(line_buf)); + + for (n = 0; n < 43*8; ++n, i += step) + if (p[i/FAC] > thr) + line_buf[n/8] |= 1 << (n%8); + + if (line_buf[0] != 0x27) // really 11100100? (rev order!) + return -1; +/* + if (i = vt_line(vbi, data+1)) + if (i < 0) + pll_add(vbi, 2, -i); + else + pll_add(vbi, 1, i); +*/ + Teletext(); + + return 0; + } + return -1; +} + +int +main(int ac, char **av) +{ + char *dev_name = "/dev/vbi0"; + int i, fd; + + if (ac > 1) + dev_name = av[1]; + + if ((fd = open(dev_name, O_RDONLY)) < 0) { + perror("open"); + exit(EXIT_FAILURE); + } + +#ifdef V4L2_MAJOR_VERSION + + if (ioctl(fd, VIDIOC_QUERYCAP, &cap) >= 0) { + + printf("Opened %s (\'%s\')\n", dev_name, cap.name); + + if (cap.type != V4L2_TYPE_VBI) { + fprintf(stderr, "Not a VBI device: %s\n", dev_name); + exit(EXIT_FAILURE); + } + + /* Should request PAL scanning here */ + + memset(&format, 0, sizeof format); + + /* Let's be a nice application and make some suggestions */ + + format.type = V4L2_BUF_TYPE_CAPTURE; + format.fmt.vbi.sampling_rate = 6937500 * 2; + format.fmt.vbi.sample_format = V4L2_VBI_SF_UBYTE; + format.fmt.vbi.start[0] = 6; + format.fmt.vbi.count[0] = 16; + format.fmt.vbi.start[1] = 318; + format.fmt.vbi.count[1] = 16; + + if (ioctl(fd, VIDIOC_S_FMT, &format) < 0) { + perror("VIDIOC_S_FMT"); + exit(EXIT_FAILURE); + } + + if (format.fmt.vbi.sampling_rate < 6937500 * 2 || + format.fmt.vbi.start[0] > 6 || + format.fmt.vbi.start[1] > 318 || + format.fmt.vbi.start[0] + format.fmt.vbi.count[0] < 22 || + format.fmt.vbi.start[1] + format.fmt.vbi.count[1] < 334) { + fprintf(stderr, "Cannot capture Teletext with this device\n"); + exit(EXIT_FAILURE); + } + + if (format.fmt.vbi.sample_format != V4L2_VBI_SF_UBYTE || + format.fmt.vbi.flags & V4L2_VBI_INTERLACED) { + fprintf(stderr, "VBI format not supported\n"); + exit(EXIT_FAILURE); + } + + fprintf(stderr, "Using V4L2 VBI interface...\n"); + + lines = format.fmt.vbi.count[0] + format.fmt.vbi.count[1]; + samples = format.fmt.vbi.samples_per_line; + rate = format.fmt.vbi.sampling_rate; + } + + /* Not a V4L2 device... */ +#else + fprintf(stderr, "Using BTTV VBI interface...\n"); + + lines = 16 * 2; + samples = 2048; + rate = 35468950; // from AleVT, not verified +#endif + + rawsize = lines * samples; + + step = (int)(rate / 6.9375E6 * FAC + .5); + + if (!(raw = malloc(rawsize))) { + fprintf(stderr, "No memory\n"); + exit(EXIT_FAILURE); + } + + for (;;) { + if (rawsize != read(fd, raw, rawsize)) { + perror("read"); + exit(EXIT_FAILURE); + } + + for (i = 0; i < rawsize; i += samples, line++) + vbi_line(raw + i); + } + + return EXIT_SUCCESS; +} diff -urN /tmp/xawtv-3.11/man/xawtv-remote.man xawtv-3.12/man/xawtv-remote.man --- /tmp/xawtv-3.11/man/xawtv-remote.man Sat Mar 25 18:53:56 2000 +++ xawtv-3.12/man/xawtv-remote.man Mon Apr 3 21:01:53 2000 @@ -97,7 +97,20 @@ Toggle fullscreen mode. .TP .B msg text -Display text on the on-screen display. +Display text on the on-screen display (window title / upper left corner in +fullscreen mode). +.TP +.B vtx line1 line2 [ ... ] +Display subtitles. It pops up a small window at the bottom of the screen. +It is supported to be used as interface for displaying subtitles (often on +videotext page 150 in europe, thats why the name) by external programs. +.br +Every command line argument is one line, zero lines removes the window. +You can colorize the text with the control sequence "ESC foreground +background". foreground/background has the range 0-7 (ansi term colors). +Example: "\\03347 hello world " is blue on white. "\\033" must be a real +escape character, the string does'nt work. With the bash you'll get it +with ^V ESC. .TP .B quit quit xawtv diff -urN /tmp/xawtv-3.11/src/Makefile.in xawtv-3.12/src/Makefile.in --- /tmp/xawtv-3.11/src/Makefile.in Sat Mar 25 16:41:08 2000 +++ xawtv-3.12/src/Makefile.in Mon Apr 3 20:17:02 2000 @@ -16,11 +16,12 @@ VERSION=xawtv-@XAWTV_VERSION@ -CFLAGS=-g -Wall @CFLAGS@ -I$(srcdir)/.. -I.. @X_CFLAGS@ -DVERSION='"$(VERSION)"' +CFLAGS=-g -Wall @CFLAGS@ -I$(srcdir)/.. -I.. @X_CFLAGS@ \ + -D_REENTRANT -DVERSION='"$(VERSION)"' LDLIBS=@X_LIBS@ @LIBS@ -l@XAWLIB@ -lXmu -lXt @X_PRE_LIBS@ -lXext \ -lX11 @X_EXTRA_LIBS@ -lpthread -PROGS=xawtv xawtv-remote v4l-conf v4lctl streamer xvideo fbtv lfs +PROGS=xawtv xawtv-remote v4l-conf v4lctl streamer xvideo fbtv COMMON_OBJS= sound.o grab.o grab-v4l.o grab-v4l2.o colorspace.o webcam.o \ frequencies.o writefile.o commands.o parseconfig.o mjpeg.o @@ -54,9 +55,6 @@ xawtv-remote: xawtv-remote.o $(CC) $(CFLAGS) -o $@ $< @X_LIBS@ @LIBS@ -lXmu -lXt @X_PRE_LIBS@ -lXext -lX11 @X_EXTRA_LIBS@ - -lfs: lfs.c - $(CC) -D_FILE_OFFSET_BITS=64 -o $@ $< channel-no-x11.o: channel.c $(CC) $(CFLAGS) -DNO_X11=1 -c -o $@ $< diff -urN /tmp/xawtv-3.11/src/Xawtv.ad xawtv-3.12/src/Xawtv.ad --- /tmp/xawtv-3.11/src/Xawtv.ad Mon Jan 31 20:53:44 2000 +++ xawtv-3.12/src/Xawtv.ad Sun Apr 2 20:19:03 2000 @@ -331,6 +331,17 @@ xawtv.onscreen.label.font: -*-ledfixed-medium-r-semicondensed--39-* +xawtv.vtx.allowShellResize: true +xawtv.vtx.label.resize: true + +xawtv.vtx*background: black +xawtv.vtx*borderColor: black +xawtv.vtx*foreground: lightgreen +xawtv.vtx*shadowWidth: 0 +xawtv.vtx.label.justify: center +xawtv.vtx.label.font: 7x13bold + + ! ---------------------------------------------------------------------------- ! Config window diff -urN /tmp/xawtv-3.11/src/capture.c xawtv-3.12/src/capture.c --- /tmp/xawtv-3.11/src/capture.c Sun Mar 19 12:41:31 2000 +++ xawtv-3.12/src/capture.c Sun Apr 2 16:53:53 2000 @@ -99,6 +99,7 @@ static int saudio,svideo; static int iaudio,ivideo; static int naudio,nvideo; +static int caudio,cvideo; static void* avi_audio_writer(void *arg) @@ -165,6 +166,7 @@ naudio = slots+2; saudio = sound_bufsize(); baudio = malloc(saudio*naudio); + caudio = 0; } /* video */ @@ -179,6 +181,7 @@ if (0 == svideo) svideo = params->width * params->height * 3; bvideo = malloc(svideo*nvideo); + cvideo = 0; /* init */ memcpy(&avi_par,params,sizeof(struct MOVIE_PARAMS)); @@ -204,10 +207,30 @@ avi_stop_writer() { void *dummy; + long long ausec,vusec; + int soundbytes; if (debug) fprintf(stderr,"avi_stop_writer\n"); - /* TODO: sync up a+v */ + + if (avi_par.channels > 0) { + vusec = cvideo * 1000 / avi_par.fps; + ausec = ((long long)caudio*saudio*8*1000) / + (avi_par.rate*avi_par.bits*avi_par.channels); + while (vusec < ausec) { + grab_put_video(); + vusec = cvideo * 1000 / avi_par.fps; + } + soundbytes = + (int)(vusec-ausec)*avi_par.rate*avi_par.bits*avi_par.channels; + fprintf(stderr,"%d/%d\n",soundbytes,saudio); + while (soundbytes > saudio) { + grab_put_audio(); + soundbytes -= saudio; + } + sound_read(baudio + iaudio*saudio); + fifo_put(&faudio,baudio + iaudio*saudio,soundbytes); + } /* send EOF + join threads */ if (avi_par.channels > 0) { @@ -248,6 +271,7 @@ if (0 == svideo) svideo = *width * *height * 3; bvideo = malloc(svideo*nvideo); + cvideo = 0; return 0; } @@ -294,6 +318,7 @@ fifo_put(&fvideo,bvideo + ivideo*svideo,size); ivideo = (ivideo+1) % nvideo; + cvideo++; return 0; } @@ -306,5 +331,6 @@ sound_read(baudio + iaudio*saudio); fifo_put(&faudio,baudio + iaudio*saudio,saudio); iaudio = (iaudio+1) % naudio; + caudio++; return 0; } diff -urN /tmp/xawtv-3.11/src/commands.c xawtv-3.12/src/commands.c --- /tmp/xawtv-3.11/src/commands.c Sat Mar 25 18:30:54 2000 +++ xawtv-3.12/src/commands.c Mon Apr 3 20:18:37 2000 @@ -24,6 +24,7 @@ /* feedback for the user */ void (*update_title)(char *message); void (*display_message)(char *message); +void (*vtx_message)(int argc, char **argv); /* for updating GUI elements / whatever */ void (*norm_notify)(void); @@ -69,6 +70,7 @@ static int movie_handler(char *name, int argc, char **argv); static int fullscreen_handler(char *name, int argc, char **argv); static int msg_handler(char *name, int argc, char **argv); +static int vtx_handler(char *name, int argc, char **argv); static int exit_handler(char *name, int argc, char **argv); static int keypad_handler(char *name, int argc, char **argv); @@ -97,6 +99,7 @@ { "movie", 1, movie_handler }, { "fullscreen", 0, fullscreen_handler }, { "msg", 1, msg_handler }, + { "vtx", 0, vtx_handler }, { "message", 0, msg_handler }, { "exit", 0, exit_handler }, { "quit", 0, exit_handler }, @@ -875,15 +878,29 @@ static int webcam_handler(char *hname, int argc, char **argv) { + int width = grab_width, height = grab_height, linelength = 0; + if (webcam) free(webcam); webcam = strdup(argv[0]); + /* if either avi recording or grabdisplay is active, we do + /not/ stop capture and switch the video format. The next + capture will send a copy of the frame to the webcam thread + and it has to deal with it as-is */ if (cur_movie) return 0; if (cur_capture == CAPTURE_GRABDISPLAY) return 0; + + /* if no capture is running we can switch to RGB first to make + the webcam happy */ + if (capture_get_hook) + capture_get_hook(); + grabber_setparams(VIDEO_RGB24,&width,&height,&linelength,0); grabber_capture(NULL,0,NULL); + if (capture_rel_hook) + capture_rel_hook(); return 0; } @@ -908,6 +925,14 @@ { if (display_message) display_message(argv[0]); + return 0; +} + +static int +vtx_handler(char *name, int argc, char **argv) +{ + if (vtx_message) + vtx_message(argc,argv); return 0; } diff -urN /tmp/xawtv-3.11/src/commands.h xawtv-3.12/src/commands.h --- /tmp/xawtv-3.11/src/commands.h Sun Mar 19 12:29:56 2000 +++ xawtv-3.12/src/commands.h Sun Apr 2 21:48:22 2000 @@ -1,6 +1,7 @@ /* feedback for the user */ extern void (*update_title)(char *message); extern void (*display_message)(char *message); +extern void (*vtx_message)(int argc, char **argv); /* for updating GUI elements / whatever */ extern void (*norm_notify)(void); diff -urN /tmp/xawtv-3.11/src/lfs.c xawtv-3.12/src/lfs.c --- /tmp/xawtv-3.11/src/lfs.c Tue Feb 1 22:36:53 2000 +++ xawtv-3.12/src/lfs.c Thu Jan 1 01:00:00 1970 @@ -1,8 +0,0 @@ -#include -#include - -int main() -{ - printf("sizeof(off_t)=%d\n",sizeof(off_t)); - return 0; -} diff -urN /tmp/xawtv-3.11/src/main.c xawtv-3.12/src/main.c --- /tmp/xawtv-3.11/src/main.c Sat Mar 25 15:11:00 2000 +++ xawtv-3.12/src/main.c Mon Apr 3 21:05:14 2000 @@ -104,6 +104,7 @@ Widget app_shell, tv; Widget opt_shell, opt_paned, chan_shell, conf_shell, str_shell; Widget on_shell, on_label; +Widget vtx_shell, vtx_label; Widget launch_shell, launch_paned; Widget c_norm,c_input,c_freq,c_audio,c_cap; Widget s_bright,s_color,s_hue,s_contrast,s_volume; @@ -653,6 +654,141 @@ } } +/*--- videotext ----------------------------------------------------------*/ + +struct TEXTELEM { + char *str; + int len; + int nl; + int x,y; + Pixel fg,bg; +}; + +void create_vtx() +{ + vtx_shell = XtVaCreateWidget("vtx",transientShellWidgetClass, + app_shell, + XtNoverrideRedirect,True, + XtNvisual,vinfo.visual, + XtNcolormap,colormap, + XtNdepth,vinfo.depth, + NULL); + vtx_label = XtVaCreateManagedWidget("label", labelWidgetClass, vtx_shell, + NULL); +} + +void +display_vtx(int lines, char **text) +{ + static char *names[8] = { "black", "red", "green", "yellow", + "blue", "magenta", "cyan", "white" }; + static XColor colors[8], dummy; + static XFontStruct *font; + static Pixmap pix; + static GC gc; + static int first = 1; + XGCValues values; + Dimension x,y,w,h,sw,sh; + int maxwidth,width,height,direction,ascent,descent,i,n,t; + struct TEXTELEM tt[32]; + XCharStruct cs; + + if (0 == lines) { + XtPopdown(vtx_shell); + return; + } + + if (NULL == font) { + XtVaGetValues(vtx_label,XtNfont,&font,NULL); + for (i = 0; i < 8; i++) + XAllocNamedColor(dpy,colormap,names[i], + &colors[i],&dummy); + values.font = font->fid; + gc = XCreateGC(dpy, XtWindow(vtx_label), GCFont, &values); + } + + /* parse */ + t = 0; + memset(tt,0,sizeof(tt)); + for (i = 0; i < lines; i++) { + tt[t].fg = colors[7].pixel; + tt[t].bg = colors[0].pixel; + tt[t].str = text[i]; + tt[t].nl = 1; + for (n = 0; text[i][n] != 0;) { + if (text[i][n] == '\033') { + if (tt[t].len) { + t++; + if (32 == t) + goto calc; + } + n++; + if (text[i][n] >= '0' && text[i][n] < '8') { + tt[t].fg = colors[text[i][n]-'0'].pixel; + n++; + } + if (text[i][n] >= '0' && text[i][n] < '8') { + tt[t].bg = colors[text[i][n]-'0'].pixel; + n++; + } + tt[t].str = text[i]+n; + } else { + tt[t].len++; + n++; + } + } + t++; + if (32 == t) + break; + } + + calc: + /* calc size + positions */ + width = 0; height = 0; maxwidth = 0; + for (i = 0; i < t; i++) { + XTextExtents(font,tt[i].str,tt[i].len, + &direction,&ascent,&descent,&cs); + if (tt[i].nl) { + if (maxwidth < width) + maxwidth = width; + width = 0; + height += ascent+descent; + } + tt[i].x = width; + tt[i].y = height - descent; + width += cs.width; + } + if (maxwidth < width) + maxwidth = width; + + /* alloc pixmap + draw text */ + if (pix) + XFreePixmap(dpy,pix); + pix = XCreatePixmap(dpy, RootWindowOfScreen(XtScreen(vtx_label)), + maxwidth, height, + DefaultDepthOfScreen(XtScreen(vtx_label))); + for (i = 0; i < t; i++) { + values.foreground = tt[i].fg; + values.background = tt[i].bg; + XChangeGC(dpy, gc, GCForeground | GCBackground, &values); + XDrawImageString(dpy,pix,gc,tt[i].x,tt[i].y,tt[i].str,tt[i].len); + } + XtVaSetValues(vtx_label,XtNbitmap,pix,XtNlabel,NULL,NULL); + + XtVaGetValues(app_shell,XtNx,&x,XtNy,&y,XtNwidth,&w,XtNheight,&h,NULL); + XtVaGetValues(vtx_shell,XtNwidth,&sw,XtNheight,&sh,NULL); + XtVaSetValues(vtx_shell,XtNx,x+(w-sw)/2,XtNy,y+h-10-sh,NULL); + XtPopup(vtx_shell, XtGrabNone); + if (wm_stay_on_top && stay_on_top > 0) + wm_stay_on_top(dpy,XtWindow(vtx_shell),1); + + if (first) { + first = 0; + XDefineCursor(dpy, XtWindow(vtx_shell), left_ptr); + XDefineCursor(dpy, XtWindow(vtx_label), left_ptr); + } +} + /*--- tv -----------------------------------------------------------------*/ static XImage *grab_ximage; @@ -1259,18 +1395,15 @@ &type, &format, &nitems, &bytesafter, &args) && nitems != 0) { - if (debug) - fprintf(stderr, "remote control: "); - for (i = 0, argc = 0; i < nitems; i += strlen(args + i) + 1) { - if(debug) - fprintf(stderr, "%s ", args+i); - argv[argc++] = args+i; + for (i = 0, argc = 0; i <= nitems; i += strlen(args + i) + 1) { + if (i == nitems || args[i] == '\0') { + argv[argc] = NULL; + do_command(argc,argv); + argc = 0; + } else { + argv[argc++] = args+i; + } } - if (debug) - fprintf(stderr, "\n"); - argv[argc] = NULL; - - do_command(argc,argv); XFree(args); } } @@ -2581,6 +2714,7 @@ /* set hooks (command.c) */ update_title = new_title; display_message = new_message; + vtx_message = display_vtx; norm_notify = new_norm; input_notify = new_input; attr_notify = new_attr; @@ -2635,6 +2769,7 @@ wm_detect(dpy); create_optwin(); create_onscreen(); + create_vtx(); create_chanwin(); create_confwin(); create_strwin(); diff -urN /tmp/xawtv-3.11/src/v4l-conf.c xawtv-3.12/src/v4l-conf.c --- /tmp/xawtv-3.11/src/v4l-conf.c Sun Jan 16 12:40:47 2000 +++ xawtv-3.12/src/v4l-conf.c Mon Apr 3 20:55:30 2000 @@ -318,6 +318,10 @@ fbuf.bytesperline = d->bpl; if (NULL != d->base) fbuf.base = d->base; + if (NULL == fbuf.base) + fprintf(stderr, + "WARNING: couldn't find framebuffer base address, try manual\n" + " configuration (\"v4l-conf -a \")\n"); /* XXX bttv confuses color depth and bits/pixel */ if (d->depth == 15) @@ -402,7 +406,7 @@ " -b displays color depth is bpp\n" " -s shift display by bytes\n" " -f query frame buffer device for info\n" - " -a set framebuffer address to \n" + " -a set framebuffer address to \n" " (in hex, root only, successful autodetect\n" " will overwrite this address)\n", argv[0], diff -urN /tmp/xawtv-3.11/tools/showriff.c xawtv-3.12/tools/showriff.c --- /tmp/xawtv-3.11/tools/showriff.c Mon Mar 20 21:25:44 2000 +++ xawtv-3.12/tools/showriff.c Wed Mar 29 00:35:59 2000 @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include #include typedef unsigned long DWORD; diff -urN /tmp/xawtv-3.11/xawtv.spec xawtv-3.12/xawtv.spec --- /tmp/xawtv-3.11/xawtv.spec Sun Mar 26 10:39:48 2000 +++ xawtv-3.12/xawtv.spec Mon Apr 3 21:10:29 2000 @@ -1,7 +1,7 @@ # Installs in /usr/X11R6/bin Summary: Video4Linux Stream Capture Viewer Name: xawtv -Version: 3.11 +Version: 3.12 Release: 1 Source0: xawtv-%{version}.tar.gz Group: X11/Applications