aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2010-04-01 09:24:35 (GMT)
committerGerd Hoffmann <kraxel@redhat.com>2010-04-01 09:24:35 (GMT)
commitcd7382baf50d1f055264748ac67f13c98d2f4205 (patch)
tree83470b86a32c893fa73b353036b4f91d01977ceb /contrib
parentfc44df6ca9cad3b3e154f38c3a43397afacbc82b (diff)
v3.27
Diffstat (limited to 'contrib')
-rw-r--r--contrib/cc/Makefile8
-rw-r--r--contrib/cc/cc.c641
-rw-r--r--contrib/dot.lircrc92
-rw-r--r--contrib/r@dio.mp31
-rw-r--r--contrib/vtx2xawtv/README.vtx2xawtv29
-rw-r--r--contrib/vtx2xawtv/vtx2xawtv44
6 files changed, 815 insertions, 0 deletions
diff --git a/contrib/cc/Makefile b/contrib/cc/Makefile
new file mode 100644
index 0000000..24e6c44
--- /dev/null
+++ b/contrib/cc/Makefile
@@ -0,0 +1,8 @@
+
+CC=gcc
+CFLAGS=-Wall -g -O2
+
+all: cc
+
+clean:
+ -rm -f cc *~
diff --git a/contrib/cc/cc.c b/contrib/cc/cc.c
new file mode 100644
index 0000000..80c9ec0
--- /dev/null
+++ b/contrib/cc/cc.c
@@ -0,0 +1,641 @@
+/* cc.c -- closed caption decoder
+ * Mike Baker (mbm@linux.com)
+ * (based on code by timecop@japan.co.jp)
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <getopt.h>
+
+
+
+
+//#define XWIN 1 // visual debugging
+
+#ifdef XWIN
+ #include <X11/X.h>
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+ #include <X11/Xproto.h>
+ Display *dpy;
+ Window Win,Root;
+ char dpyname[256] = "";
+ GC WinGC;
+ GC WinGC0;
+ GC WinGC1;
+ int x;
+#endif
+
+
+//XDSdecode
+char info[8][25][256];
+char newinfo[8][25][256];
+char *infoptr=newinfo[0][0];
+int mode,type;
+char infochecksum;
+
+//ccdecode
+char *ratings[] = {"(NOT RATED)","TV-Y","TV-Y7","TV-G","TV-PG","TV-14","TV-MA","(NOT RATED)"};
+int rowdata[] = {11,-1,1,2,3,4,12,13,14,15,5,6,7,8,9,10};
+char *specialchar[] = {"®","°","½","¿","(TM)","¢","£","o/~ ","à"," ","è","â","ê","î","ô","û"};
+char *modes[]={"current","future","channel","miscellaneous","public service","reserved","invalid","invalid","invalid","invalid"};
+int lastcode;
+int ccmode=1; //cc1 or cc2
+char ccbuf[3][256]; //cc is 32 columns per row, this allows for extra characters
+int keywords=0;
+char *keyword[32];
+
+
+//args (this should probably be put into a structure later)
+char useraw=0;
+char usexds=0;
+char usecc=0;
+char plain=0;
+char usesen=0;
+
+char rawline=-1;
+
+int sen;
+int inval;
+
+int parityok(int n) /* check parity for 2 bytes packed in n */
+{
+ int mask=0;
+ int j, k;
+ for (k = 1, j = 0; j < 7; j++) {
+ if (n & (1<<j))
+ k++;
+ }
+ if ((k & 1) == ((n>>7)&1))
+ mask|=0x00FF;
+ for (k = 1, j = 8; j < 15; j++) {
+ if (n & (1<<j))
+ k++;
+ }
+ if ((k & 1) == ((n>>15)&1))
+ mask|=0xFF00;
+ return mask;
+}
+
+int decodebit(unsigned char *data, int threshold)
+{
+ int i, sum = 0;
+ for (i = 0; i < 23; i++)
+ sum += data[i];
+ return (sum > threshold*23);
+}
+
+int decode(unsigned char *vbiline)
+{
+ int max[7], min[7], val[7], i, clk, tmp, sample, packedbits = 0;
+
+ for (clk=0; clk<7; clk++)
+ max[clk] = min[clk] = val[clk] = -1;
+ clk = tmp = 0;
+ i=30;
+
+ while (i < 600 && clk < 7) { /* find and lock all 7 clocks */
+ sample = vbiline[i];
+ if (max[clk] < 0) { /* find maximum value before drop */
+ if (sample > 85 && sample > val[clk])
+ (val[clk] = sample, tmp = i); /* mark new maximum found */
+ else if (val[clk] - sample > 30) /* far enough */
+ (max[clk] = tmp, i = tmp + 10);
+ } else { /* find minimum value after drop */
+ if (sample < 85 && sample < val[clk])
+ (val[clk] = sample, tmp = i); /* mark new minimum found */
+ else if (sample - val[clk] > 30) /* searched far enough */
+ (min[clk++] = tmp, i = tmp + 10);
+ }
+ i++;
+ }
+
+ i=min[6]=min[5]-max[5]+max[6];
+
+ if (clk != 7 || vbiline[max[3]] - vbiline[min[5]] < 45) /* failure to locate clock lead-in */
+ return -1;
+
+#ifdef XWIN
+ for (clk=0;clk<7;clk++)
+ {
+ XDrawLine(dpy,Win,WinGC,min[clk]/2,0,min[clk]/2,128);
+ XDrawLine(dpy,Win,WinGC1,max[clk]/2,0,max[clk]/2,128);
+ }
+ XFlush(dpy);
+#endif
+
+
+ /* calculate threshold */
+ for (i=0,sample=0;i<7;i++)
+ sample=(sample + vbiline[min[i]] + vbiline[max[i]])/3;
+
+ for(i=min[6];vbiline[i]<sample;i++);
+
+#ifdef XWIN
+ for (clk=i;clk<i+57*18;clk+=57)
+ XDrawLine(dpy,Win,WinGC,clk/2,0,clk/2,128);
+ XFlush(dpy);
+#endif
+
+
+ tmp = i+57;
+ for (i = 0; i < 16; i++)
+ if(decodebit(&vbiline[tmp + i * 57], sample))
+ packedbits |= 1<<i;
+ return packedbits&parityok(packedbits);
+} /* decode */
+
+int XDSdecode(int data)
+{
+ int b1, b2, length;
+
+ if (data == -1)
+ return -1;
+
+ b1 = data & 0x7F;
+ b2 = (data>>8) & 0x7F;
+
+ if (b1 < 15) // start packet
+ {
+ mode = b1;
+ type = b2;
+ infochecksum = b1 + b2 + 15;
+ if (mode > 8 || type > 20)
+ {
+// printf("%% Unsupported mode %s(%d) [%d]\n",modes[(mode-1)>>1],mode,type);
+ mode=0; type=0;
+ }
+ infoptr = newinfo[mode][type];
+ }
+ else if (b1 == 15) // eof (next byte is checksum)
+ {
+#if 0 //debug
+ if (mode == 0)
+ {
+ length=infoptr - newinfo[0][0];
+ infoptr[1]=0;
+ printf("LEN: %d\n",length);
+ for (y=0;y<length;y++)
+ printf(" %03d",newinfo[0][0][y]);
+ printf(" --- %s\n",newinfo[0][0]);
+ }
+#endif
+ if (mode == 0) return 0;
+ if (b2 != 128-((infochecksum%128)&0x7F)) return 0;
+
+ length = infoptr - newinfo[mode][type];
+
+ //don't bug the user with repeated data
+ //only parse it if it's different
+ if (strncmp(info[mode][type],newinfo[mode][type],length-1))
+ {
+ infoptr = info[mode][type];
+ memcpy(info[mode][type],newinfo[mode][type],length+1);
+ printf("\33[33m%%");
+ switch ((mode<<8) + type)
+ {
+ case 0x0101:
+ printf(" TIMECODE: %d/%02d %d:%02d",
+ infoptr[3]&0x0f,infoptr[2]&0x1f,infoptr[1]&0x1f,infoptr[0]&0x3f);
+ case 0x0102:
+ if ((infoptr[1]&0x3f)>5)
+ break;
+ printf(" LENGTH: %d:%02d:%02d of %d:%02d:00",
+ infoptr[3]&0x3f,infoptr[2]&0x3f,infoptr[4]&0x3f,infoptr[1]&0x3f,infoptr[0]&0x3f);
+ break;
+ case 0x0103:
+ infoptr[length] = 0;
+ printf(" TITLE: %s",infoptr);
+ break;
+ case 0x0105:
+ printf(" RATING: %s (%d)",ratings[infoptr[0]&0x07],infoptr[0]);
+ if ((infoptr[0]&0x07)>0)
+ {
+ if (infoptr[0]&0x20) printf(" VIOLENCE");
+ if (infoptr[0]&0x10) printf(" SEXUAL");
+ if (infoptr[0]&0x08) printf(" LANGUAGE");
+ }
+ break;
+ case 0x0501:
+ infoptr[length] = 0;
+ printf(" NETWORK: %s",infoptr);
+ break;
+ case 0x0502:
+ infoptr[length] = 0;
+ printf(" CALL: %s",infoptr);
+ break;
+ case 0x0701:
+ printf(" CUR.TIME: %d:%02d %d/%02d/%04d UTC",infoptr[1]&0x1F,infoptr[0]&0x3f,infoptr[3]&0x0f,infoptr[2]&0x1f,(infoptr[5]&0x3f)+1990);
+ break;
+ case 0x0704: //timezone
+ printf(" TIMEZONE: UTC-%d",infoptr[0]&0x1f);
+ break;
+ case 0x0104: //program genere
+ break;
+ case 0x0110:
+ case 0x0111:
+ case 0x0112:
+ case 0x0113:
+ case 0x0114:
+ case 0x0115:
+ case 0x0116:
+ case 0x0117:
+ infoptr[length+1] = 0;
+ printf(" DESC: %s",infoptr);
+ break;
+ }
+ printf("\33[0m\n");
+ fflush(stdout);
+ }
+ mode = 0; type = 0;
+ }
+ else if( (infoptr - newinfo[mode][type]) < 250 ) // must be a data packet, check if we're in a supported mode
+ {
+ infoptr[0] = b1; infoptr++;
+ infoptr[0] = b2; infoptr++;
+ infochecksum += b1 + b2;
+ }
+ return 0;
+}
+
+int webtv_check(char * buf,int len)
+{
+ unsigned long sum;
+ unsigned long nwords;
+ unsigned short csum=0;
+ char temp[9];
+ int nbytes=0;
+
+ while (buf[0]!='<' && len > 6) //search for the start
+ {
+ buf++; len--;
+ }
+
+ if (len == 6) //failure to find start
+ return 0;
+
+
+ while (nbytes+6 <= len)
+ {
+ //look for end of object checksum, it's enclosed in []'s and there shouldn't be any [' after
+ if (buf[nbytes] == '[' && buf[nbytes+5] == ']' && buf[nbytes+6] != '[')
+ break;
+ else
+ nbytes++;
+ }
+ if (nbytes+6>len) //failure to find end
+ return 0;
+
+ nwords = nbytes >> 1; sum = 0;
+
+ //add up all two byte words
+ while (nwords-- > 0) {
+ sum += *buf++ << 8;
+ sum += *buf++;
+ }
+ if (nbytes & 1) {
+ sum += *buf << 8;
+ }
+ csum = (unsigned short)(sum >> 16);
+ while(csum !=0) {
+ sum = csum + (sum & 0xffff);
+ csum = (unsigned short)(sum >> 16);
+ }
+ sprintf(temp,"%04X\n",(int)~sum&0xffff);
+ buf++;
+ if(!strncmp(buf,temp,4))
+ {
+ buf[5]=0;
+ printf("\33[35mWEBTV: %s\33[0m\n",buf-nbytes-1);
+ fflush(stdout);
+ }
+ return 0;
+}
+
+int CCdecode(int data)
+{
+ int b1, b2, row, len, x,y;
+ if (data == -1) //invalid data. flush buffers to be safe.
+ {
+ memset(ccbuf[1],0,255);
+ memset(ccbuf[2],0,255);
+ return -1;
+ }
+ b1 = data & 0x7f;
+ b2 = (data>>8) & 0x7f;
+ len = strlen(ccbuf[ccmode]);
+
+ if (b1&0x60 && data != lastcode) // text
+ {
+ ccbuf[ccmode][len++]=b1;
+ if (b2&0x60) ccbuf[ccmode][len++]=b2;
+ if (b1 == ']' || b2 == ']')
+ webtv_check(ccbuf[ccmode],len);
+ }
+ else if ((b1&0x10) && (b2>0x1F) && (data != lastcode)) //codes are always transmitted twice (apparently not, ignore the second occurance)
+ {
+ ccmode=((b1>>3)&1)+1;
+ len = strlen(ccbuf[ccmode]);
+
+ if (b2 & 0x40) //preamble address code (row & indent)
+ {
+ row=rowdata[((b1<<1)&14)|((b2>>5)&1)];
+ if (len!=0)
+ ccbuf[ccmode][len++]='\n';
+
+ if (b2&0x10) //row contains indent flag
+ for (x=0;x<(b2&0x0F)<<1;x++)
+ ccbuf[ccmode][len++]=' ';
+ }
+ else
+ {
+ switch (b1 & 0x07)
+ {
+ case 0x00: //attribute
+ printf("<ATTRIBUTE %d %d>\n",b1,b2);
+ fflush(stdout);
+ break;
+ case 0x01: //midrow or char
+ switch (b2&0x70)
+ {
+ case 0x20: //midrow attribute change
+ switch (b2&0x0e)
+ {
+ case 0x00: //italics off
+ if (!plain)
+ strcat(ccbuf[ccmode],"\33[0m ");
+ break;
+ case 0x0e: //italics on
+ if (!plain)
+ strcat(ccbuf[ccmode],"\33[36m ");
+ break;
+ }
+ if (b2&0x01) { //underline
+ if (!plain)
+ strcat(ccbuf[ccmode],"\33[4m");
+ } else {
+ if (!plain)
+ strcat(ccbuf[ccmode],"\33[24m");
+ }
+ break;
+ case 0x30: //special character..
+ strcat(ccbuf[ccmode],specialchar[b2&0x0f]);
+ break;
+ }
+ break;
+ case 0x04: //misc
+ case 0x05: //misc + F
+// printf("ccmode %d cmd %02x\n",ccmode,b2);
+ switch (b2)
+ {
+ case 0x21: //backspace
+ ccbuf[ccmode][len--]=0;
+ break;
+
+ /* these codes are insignifigant if we're ignoring positioning */
+ case 0x25: //2 row caption
+ case 0x26: //3 row caption
+ case 0x27: //4 row caption
+ case 0x29: //resume direct caption
+ case 0x2B: //resume text display
+ case 0x2C: //erase displayed memory
+ break;
+
+ case 0x2D: //carriage return
+ if (ccmode==2)
+ break;
+ case 0x2F: //end caption + swap memory
+ case 0x20: //resume caption (new caption)
+ if (!strlen(ccbuf[ccmode]))
+ break;
+ for (x=0;x<strlen(ccbuf[ccmode]);x++)
+ for (y=0;y<keywords;y++)
+ if (!strncasecmp(keyword[y], ccbuf[ccmode]+x, strlen(keyword[y])))
+ printf("\a");
+ printf("%s\33[m\n",ccbuf[ccmode]);
+ fflush(stdout);
+ /* FALL */
+ case 0x2A: //text restart
+ case 0x2E: //erase non-displayed memory
+ memset(ccbuf[ccmode],0,255);
+ break;
+ }
+ break;
+ case 0x07: //misc (TAB)
+ for(x=0;x<(b2&0x03);x++)
+ ccbuf[ccmode][len++]=' ';
+ break;
+ }
+ }
+ }
+ lastcode=data;
+ return 0;
+}
+int RAW(int data)
+{
+ int b1, b2;
+ if (data == -1)
+ return -1;
+ b1 = data & 0x7f;
+ b2 = (data>>8) & 0x7f;
+ fprintf(stderr,"%c%c",b1,b2);
+ return 0;
+}
+int sentence(int data)
+{
+ int b1, b2;
+ if (data == -1)
+ return -1;
+ b1 = data & 0x7f;
+ b2 = (data>>8) & 0x7f;
+ inval++;
+ if (data==lastcode)
+ {
+ if (sen==1)
+ {
+ printf(" ");
+ sen=0;
+ }
+ if (inval>10 && sen)
+ {
+ printf("\n");
+ fflush(stdout);
+ sen=0;
+ }
+ return 0;
+ }
+ lastcode=data;
+
+ if (b1&96)
+ {
+ inval=0;
+ if (sen==2 && b1!='.' && b2!='.' && b1!='!' && b2!='!' && b1!='?' && b2!='?' && b1!=')' && b2!=')')
+ {
+ printf("\n");
+ fflush(stdout);
+ sen=1;
+ }
+ else if (b1=='.' || b2=='.' || b1=='!' || b2=='!' || b1=='?' || b2=='?' || b1==')' || b2==')')
+ sen=2;
+ else
+ sen=1;
+ printf("%c%c",tolower(b1),tolower(b2));
+
+ }
+ return 0;
+}
+#ifdef XWIN
+unsigned long getColor(char *colorName, float dim)
+{
+ XColor Color;
+ XWindowAttributes Attributes;
+
+ XGetWindowAttributes(dpy, Root, &Attributes);
+ Color.pixel = 0;
+
+ XParseColor (dpy, Attributes.colormap, colorName, &Color);
+ Color.red=(unsigned short)(Color.red/dim);
+ Color.blue=(unsigned short)(Color.blue/dim);
+ Color.green=(unsigned short)(Color.green/dim);
+ Color.flags=DoRed | DoGreen | DoBlue;
+ XAllocColor (dpy, Attributes.colormap, &Color);
+
+ return Color.pixel;
+}
+#endif
+int main(int argc,char **argv)
+{
+ char *vbifile = "/dev/vbi";
+ unsigned char buf[65536];
+ char arg;
+ int args=0;
+ int vbifd;
+ fd_set rfds;
+
+ int x;
+
+ #ifdef XWIN
+ dpy=XOpenDisplay(dpyname);
+ Root=DefaultRootWindow(dpy);
+ Win = XCreateSimpleWindow(dpy, Root, 10, 10, 1024, 128,0,0,0);
+ WinGC = XCreateGC(dpy, Win, 0, NULL);
+ WinGC0 = XCreateGC(dpy, Win, 0, NULL);
+ WinGC1 = XCreateGC(dpy, Win, 0, NULL);
+ XSetForeground(dpy, WinGC, getColor("blue",1));
+ XSetForeground(dpy, WinGC0, getColor("green",1));
+ XSetForeground(dpy, WinGC1, getColor("red",1));
+ #endif
+
+ for (;;) //commandline parsing
+ {
+ if (-1 == (arg = getopt(argc, argv, "h?xspckd:r:")))
+ break;
+ switch (arg)
+ {
+ case '?':
+ case 'h':
+ printf("CCDecoder 0.9.1 (mbm@linux.com)\n"
+ "\tx\tdecode XDS info\n"
+ "\tc\tdecode Closed Caption (includes webtv)\n"
+ "\tp (plain) \tdo not display underline and italic\n"
+ "\tr arg\traw dump of arg\n");
+ exit(0);
+ case 'x':
+ usexds=1; args++;
+ break;
+ case 's':
+ usesen=1; args++;
+ break;
+ case 'c':
+ usecc=1; args++;
+ break;
+ case 'k':
+ keyword[keywords++]=optarg;
+ break;
+ case 'p':
+ plain=1; args++;
+ break;
+ case 'r':
+ useraw=1; args++;
+ rawline=atoi(optarg);
+ #if XWIN
+ XMapWindow(dpy, Win);
+ #endif
+ break;
+ case 'd':
+ vbifile = optarg;
+ break;
+ }
+ }
+
+ if ((vbifd = open(vbifile, O_RDONLY)) < 0) {
+ perror(vbifile);
+ exit(1);
+ }
+
+ else if (!args)
+ exit(0);
+ for (x=0;x<keywords;x++)
+ printf("Keyword(%d): %s\n",x,keyword[x]);
+
+ //mainloop
+ while(1){
+ FD_ZERO(&rfds);
+ FD_SET(vbifd, &rfds);
+ select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
+ if (FD_ISSET(vbifd, &rfds)) {
+ if (read(vbifd, buf , 65536)!=65536)
+ printf("read error\n");
+ if (useraw)
+ {
+ #ifdef XWIN
+ XClearArea(dpy,Win,0,0,1024,128,0);
+ XDrawLine(dpy,Win,WinGC1,0,128-85/2,1024,128-85/2);
+ for (x=0;x<1024;x++)
+ if (buf[2048 * rawline+x*2]/2<128 && buf[2048 * rawline+x*2+2]/2 < 128)
+ XDrawLine(dpy,Win,WinGC0,x,128-buf[2048 * rawline+x*2]/2,x+1,128-buf[2048 * rawline+x*2+2]/2);
+ #endif
+ RAW(decode(&buf[2048 * rawline]));
+ #ifdef XWIN
+ XFlush(dpy);
+ usleep(100);
+ #endif
+ }
+ if (usexds)
+ XDSdecode(decode(&buf[2048 * 27]));
+ if (usecc)
+ CCdecode(decode(&buf[2048 * 11]));
+ if (usesen)
+ sentence(decode(&buf[2048 * 11]));
+ #ifdef XWIN
+ XFlush(dpy);
+ usleep(100);
+ #endif
+ }
+ }
+ return 0;
+}
diff --git a/contrib/dot.lircrc b/contrib/dot.lircrc
new file mode 100644
index 0000000..cb779c8
--- /dev/null
+++ b/contrib/dot.lircrc
@@ -0,0 +1,92 @@
+begin
+ prog = xawtv
+ button = CH+
+ config = setstation next
+end
+begin
+ prog = xawtv
+ button = CH-
+ config = setstation prev
+end
+begin
+ prog = xawtv
+ button = VOL+
+ config = volume inc
+end
+begin
+ prog = xawtv
+ button = VOL-
+ config = volume dec
+end
+begin
+ prog = xawtv
+ button = MUTE
+ config = volume mute
+end
+begin
+ prog = xawtv
+ button = FULL_SCREEN
+ config = fullscreen toggle
+end
+begin
+ prog = xawtv
+ button = SOURCE
+ config = setinput next
+end
+begin
+ prog = xawtv
+ button = RESERVED
+ config = quit
+end
+
+
+begin
+ prog = xawtv
+ button = 1
+ config = keypad 1
+end
+begin
+ prog = xawtv
+ button = 2
+ config = keypad 2
+end
+begin
+ prog = xawtv
+ button = 3
+ config = keypad 3
+end
+begin
+ prog = xawtv
+ button = 4
+ config = keypad 4
+end
+begin
+ prog = xawtv
+ button = 5
+ config = keypad 5
+end
+begin
+ prog = xawtv
+ button = 6
+ config = keypad 6
+end
+begin
+ prog = xawtv
+ button = 7
+ config = keypad 7
+end
+begin
+ prog = xawtv
+ button = 8
+ config = keypad 8
+end
+begin
+ prog = xawtv
+ button = 9
+ config = keypad 9
+end
+begin
+ prog = xawtv
+ button = 0
+ config = keypad 0
+end
diff --git a/contrib/r@dio.mp3 b/contrib/r@dio.mp3
new file mode 100644
index 0000000..4768494
--- /dev/null
+++ b/contrib/r@dio.mp3
@@ -0,0 +1 @@
+see http://www.nbc-vbi.de.vu for up-to-date versions
diff --git a/contrib/vtx2xawtv/README.vtx2xawtv b/contrib/vtx2xawtv/README.vtx2xawtv
new file mode 100644
index 0000000..c2da660
--- /dev/null
+++ b/contrib/vtx2xawtv/README.vtx2xawtv
@@ -0,0 +1,29 @@
+ vtx2xawtv
+ Public Domain, von Kai Fett
+ K@i-Fett.de
+
+Schonmal drüber geärgert, daß das Erfassen der Sendernamen ewgig
+lange dauert und noch dazu nervenaufreibend ist? Insbesondere bei den
+"Privaten", die die Hälfte der Zeit Werbung und damit kein Senderlogo
+zeigen?
+
+Das geht auch einfacher: Kabel 1 bietet ab Videotextseite 600 eine
+Kanalübersicht der Telekom, die sich herrlich zur Weiterverarbeitung
+mit Perl eignet:
+
+- Zunächst packt man die für seinen Ort passenden Seiten in Text-
+ dateien, z.B. in alevt mit Taste 's', oder mit vbidecode und
+ vtx2ascii -a. Bitte die Seiten als ASCII abspeichern!
+
+- Dann piped man diese Textdateien durch das beiliegende Script
+ vtx2xawtv, und fügt den Output an seine Konfigurationsdatei an:
+
+ cat vtx*.txt | ./vtx2xawtv >> ~/.xawtv
+
+Schon hat man alle Sender mit der offiziellen Senderbezeichnung in
+xawtv zur Verfügung.
+
+Über Feedback würde ich mich freuen!
+
+Viel Spaß
+ Kai \ No newline at end of file
diff --git a/contrib/vtx2xawtv/vtx2xawtv b/contrib/vtx2xawtv/vtx2xawtv
new file mode 100644
index 0000000..2f66556
--- /dev/null
+++ b/contrib/vtx2xawtv/vtx2xawtv
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+#
+# vtx2xawtv - Konvertiert Kabel1-Kanalliste ins .xawtv-Format
+#
+# 1) Mit Videotext-Tool aus dem Kabel1-Text die Seiten mit
+# den Kanal-Listen aufrufen und abspeichern, z.B. als
+# vtx1.txt bis vtx3.txt
+#
+# 2) Diese Seiten durch vtx2xawtv pipen:
+#
+# cat vtx?.txt | vtx2xawtv >> ~/.xawtv
+#
+#
+# Have Fun,
+# Kai (K@i-Fett.de)
+#
+# PS: Dieses Scriptchen ist natürlich Public Domain, es wäre aber schön,
+# wenn mein Name in weiteren Versionen drinbleibt.
+#
+#############################################################################
+ #
+while(<STDIN>){ #
+ if (/\*/) { #
+ #
+ # Zeile in 3 Teile zerlegen, jeweils feste Breite #
+ #
+ /(.........................)(..)(...)/; #
+ $name=$1; $typ=$2;
+ $chan=$3;
+
+ $name=~s/\(.*\)//; # Bemerkungen in Klammern löschen
+ $name=~s/(\ )*$//; # Leerzeichen am Ende...
+ $name=~s/^(\ )//; # ...und am Anfang löschen
+
+ if ($typ=~/K/){$typ='E'} # Die Kabel1-Liste notiert
+ if ($typ=~/S/ and $chan<21){$typ='SE'} # die Kanäle etwas
+ if ($typ=~/S/ and $chan>20){$typ='S'} # anders als xawtv
+
+ $chan=~s/(\ )*$//; # Auch wieder füllende
+ $chan=~s/^(\ )*//; # und führende Leerzeichen abschneiden
+
+ print "[$name]\nchannel=$typ$chan\n\n"; # Und im xawtv-Format ausgeben.
+ }
+} \ No newline at end of file

Privacy Policy