diff options
Diffstat (limited to 'Tools/epg2timers')
-rw-r--r-- | Tools/epg2timers/README | 151 | ||||
-rw-r--r-- | Tools/epg2timers/epg2timers.cxx | 578 | ||||
-rw-r--r-- | Tools/epg2timers/epg_channel_names | 400 | ||||
-rwxr-xr-x | Tools/epg2timers/get_merkliste.pl | 82 | ||||
-rwxr-xr-x | Tools/epg2timers/loadvdr.pl | 89 | ||||
-rwxr-xr-x | Tools/epg2timers/update_timers | 22 | ||||
-rwxr-xr-x | Tools/epg2timers/update_timers.old | 24 |
7 files changed, 1251 insertions, 95 deletions
diff --git a/Tools/epg2timers/README b/Tools/epg2timers/README new file mode 100644 index 0000000..53888b1 --- /dev/null +++ b/Tools/epg2timers/README @@ -0,0 +1,151 @@ +Overview. +========= + +The 4 modules in this directory are designed to allow vdr timer +programming via the http://tvtv.de web EPG (Electronic Program Guide). + +Once you have these modules properly configured and installed, +you should be able to simply click on the things you want vdr +to record in the http://tvtv.de web EPG and be done with it. +Everything else can be handled automatically. + + + +Module description. +=================== + +The http://tvtv.de web EPG creates a so-called "merkliste" +("a list of items to remember") containing all the broadcasts +you selected. + +1. The perl script "get_merkliste.pl" transfers this "merkliste" + from the http://tvtv.de web site to a local file "merkliste.html". + +2. The C++ program "epg2timers" converts this HTML file into vdr's + timers.conf format. + +3. The perl script "loadvdr.pl" pumps these new timer entries + into a running vdr using telnet and the SVDRP protocol. + +4. The shell script "update_timers" implements the overall + control of the entire process. + It retrieves the latest merkliste from http://tvtv.de, + converts it to timers.conf format and sends the timer entries + to vdr. + + + +Configuration. +============== + +get_merkliste.pl requires configuration of the "files_to_fetch" +variable preset. +Log in to your http://tvtv.de account and click on the "Bookmark" +item in the "Setup" submenu of the "Mein Programm" side bar menu. +This will open a window with a URL in the location field that ends +with an ID value. Replace the xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +in the "files_to_fetch" variable preset with your ID value. +If you are using an HTTP proxy, uncomment the line containing +the $ua->proxy call and put your proxy details in. + +epg2timers.cxx allows various items to be configured, but it +should work out of the box. See "tvtv.de channel names" below. + +update_timers must know where to find the get_merkliste.pl +perl script and the compiled epg2timers binary. Both must be +in a directory pointed to by the TOOLDIR variable. +update_timers also must know where to find vdr's current +channels.conf file. Put that into the CHANPATH. + +Depending on the price of your internet access, you may want to +run update_timers more or less frequently. It may also be a good +idea to run it at times where it is unlikely to interfere with +your current use of vdr. Configure a crontab entry according to +these personal preferences. Here is the entry I use: +1 2 * * * /home/cko/bin/update_timers +It runs update_timers only once a night at 02:01 a.m. + + +Installation. +============= +Create your TOOLDIR directory if it does not already exist. +Copy get_merkliste.pl and loadvdr.pl into it, compile epg2timers.cxx +with the command: + g++ epg2timers.cxx -o epg2timers +and move the epg2timers binary into the TOOLDIR directory. + +The get_merkliste.pl script requires certain packages to run. +Besides of course perl, install perl-libwww-perl (at least +that's the name on SuSE 7.2, it may have a different name in +your distribution). + +If you have problems with SVDRP and loadvdr.pl, you may want to +try out the update_timers.old script, which replaces the timers.conf +file directly and kills vdr (assuming that it will be restarted +by the runvdr script) to make vdr reload the timers.conf file. + + +tvtv.de channel names. +====================== +The file epg_channel_names contains the names of all channels +currently (as of September 9, 2001) supported by the tvtv.de +web EPG. The variable "channel_map" in epg2timers.cxx maps +these names into PNRs (aka Service IDs). I have initialized +this table with provider names converted from a d-box channel +scan of Astra 19.2E, so the PNRs should be correct for that +satellite, but most of the names propably aren't yet- I simply +had not enough time yet to go through epg_channel_names +and insert all its channel names at the proper places in the +channel map. Consider the map supplied an example. ;-) +If you fix any of the entries, please send me a patch. +For my own humble purposes, the table works well as it is. +Of course, your channels.conf must contain the matching +PNRs (last field in each line). + + +To Do. +====== +These are just ideas. They MAY get implemented. +If you want them to happen, contribute a patch. ;-) + +* Support vdr hierarchical directories (after vdr does) + by mapping the http://tvtv.de genre texts into + directory names. +* start_time_safety_margin for epg2timers. + + +Authors. +======== +Carsten Koch: epg2timers.cxx, update_timers, this README file. + +Axel Gruber and +Rolf Hakenes: get_merkliste.pl + +Peter Ahlert: loadvdr.pl + + +Credits. +======== +I am grateful (in chronological order) to + +* Klaus Schmidinger for his excellent vdr program and for + keeping an open mind in all directions. + +* Suse (my wife, not the Linux distributor ;-) for encouraging me to + write epg2timers in June 2000 and for her constant patience and support. + +* Andreas Steinhauser for periodically criticizing the epg2timers + "manual mode" until I came up with the idea to fully automatize it + and for contributing ideas. + +* Axel Gruber for reminding me half a year later, for pushing + the idea until it got implemented, for asking for new features + all the time and for contributing ideas. + +* Axel Gruber and Rolf Hakenes for contributing the get_merkliste.pl + perl script. + +* Peter Ahlert for contributing the loadvdr.pl perl script. + + +Carsten, September 2001. diff --git a/Tools/epg2timers/epg2timers.cxx b/Tools/epg2timers/epg2timers.cxx index 07e8182..94e1c8a 100644 --- a/Tools/epg2timers/epg2timers.cxx +++ b/Tools/epg2timers/epg2timers.cxx @@ -1,13 +1,13 @@ /* - * epg2timers.cxx: Convert an EPG "merkliste" page (http://www.tvtv.de) to a timers.conf - * file for Klaus Schmidinger's vdr (http://www.cadsoft.de/people/kls/vdr). + * epg2timers.cxx: Convert an EPG "merkliste" HTML page (http://tvtv.de) + * to timers.conf format for Klaus Schmidinger's vdr + * (http://www.cadsoft.de/people/kls/vdr). * - * Copyright (C) 2000 Carsten Koch + * Copyright (C) 2000, 2001 Carsten Koch * * 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. + * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,65 +23,349 @@ */ +#include <malloc.h> #include <stdio.h> #include <string.h> +#include <unistd.h> +// User-configurable options. -static const char date_line[] = "\t<td align=center valign=middle colspan=3><span id=fb-b10>"; -static const char start_time_line[] = " \t\t<td bgcolor=\"#7f98bf\" align=center><span id=\"fb-w14\"><nobr> "; -static const char stop_time_line[] = "\t\t\t<tr><td bgcolor=\"#002b64\" align=center><span id=\"fn-w9\">bis "; -static const char channel_line[] = "\t\t\t<tr><td bgcolor=\"#002b64\" align=center><span id=\"fb-w9\">"; -static const char title_line[] = "\t\t\t\t<td bgcolor=\"#002b64\" align=left width=100%><span id=\"fb-w10\">"; -static const char summary_line[] = "\t\t\t<table border=0 cellpadding=10 cellspacing=0 bgcolor=\"white\" width=100%>"; -static const char * const channel_names[] = +static const int stop_time_safety_margin = 10; // add 10 minutes to stop time in case start was delayed +static const int recording_priority = 50; // vdr recording priority setting for all timer entries generated +static const int recording_lifetime = 98; // vdr recording life time setting for all timer entries generated + + +// Usually, you should not want to change any of these. + +static const int max_title = 256; // maximum length+1 of title file name generated +static const int max_genre = 32; // maximum length+1 of genre text parsed +static const int max_line = 1024; // line buffer (not used when parsing summary text) +static const int max_summary = 9000; // Summary can be up to 9000 bytes long (a bit shorter than vdr's SVDRP command buffer) +static const int max_vdr_channel = 1000; // maximum size+1 of your channels.conf + +// The following table maps http://tvtv.de channel names into Astra 19.2E PIDs. +// It is incomplete. Contributions welcome. + +typedef struct { -"3sat", -"ARTE", -"*B1 Berlin", -"BR3", -"Bloomberg TV", -"BR Alpha", -"CNN", -"ARD", -"*DW-tv", -"Eins Extra", -"Eins Festival", -"Eins MuXx", -"euroNEWS", -"HR3", -"Kabel1", -"Kinderkanal", -"MDR", -"MTV", -"NDR", -"NTV", -"ORB", -"*ORF1", -"Phoenix", -"PRO7", -"RTL", -"RTL2", -"SAT1", -"skynews", -"SWF", -"Super RTL", -"TM3", -"TW1", -"VOX", -"WDR", -"Theaterkanal", -"ZDF", -"ZDF.doku", -"ZDF.info", -"" + const char * tvtv_name; + unsigned short pnr; +} map_entry; + + +static const map_entry channel_map[] = +{ + // Deutschsprachig + {"13th Street", 42}, + {"3sat", 28007}, + {"ARTE", 28109}, + {"B1", 28206}, + {"BR3", 28107}, + {"BR-alpha", 28112}, + {"ARD", 28106}, + {"Discovery", 14}, + {"Disney Channel", 34}, + {"Eins Extra", 28201}, + {"Eins Festival", 28202}, + {"Eins MuXx", 28203}, + {"Filmpalast", 516}, + {"FOX KIDS", 28}, + {"Heimatkanal", 517}, + {"HR", 28108}, + {"Junior", 19}, + {"Kabel 1", 899}, + {"Kinderkanal", 28008}, + {"Krimi&Co", 23}, + {"K-Toon", 12}, + {"Liberty TV.com", 12199}, + {"MDR", 28204}, + {"NDR", 28224}, + {"NEUN LIVE", 897}, + {"ORB", 28205}, + {"ORF1", 13001}, + {"ORF2", 13002}, + {"Phoenix", 28114}, + {"Planet", 13}, + {"Premiere 1", 10}, + {"Premiere 2", 11}, + {"Premiere 3", 43}, + {"Premiere Action", 20}, + {"Premiere Comedy", 29}, + {"Premiere SCI-FI", 41}, + {"Premiere Star", 9}, + {"PREMIERE WORLD", 8}, + {"ProSieben", 898}, + {"RTL", 12003}, + {"RTL2", 12020}, + {"SAT.1", 46}, + {"SeaSonS", 33}, + {"SR", 28110}, + {"Studio Universal", 36}, + {"Sunset", 16}, + {"Super RTL", 12040}, + {"Test-Z1", 28305}, + {"TW1", 13013}, + {"Via 1 - Schöner Reise", 44}, + {"VOX", 12060}, + {"WDR", 28111}, + {"ZDF", 28006}, + {"ZDF.doku", 28014}, + {"ZDF.info", 28011}, + // Movies + {"AXN", 29506}, + {"CANAL+", 29100}, + {"CANAL+ AZUL", 29101}, + {"CANAL+ ROJO", 29102}, + {"CANAL+ VERT", 8208}, + {"CANAL+ 16/9", 8204}, + {"CANAL+ 16|9", 29024}, + {"C+ROOD", 4005}, + {"CINE CINEMA I", 8206}, + {"CINE CINEMA II", 8002}, + {"CINE CINEMA III", 8003}, + {"CINE CLASSICS", 8709}, + {"CINE CINEMA 16/9", 8301}, + {"cinecinemas", 4008}, + {"CINECLASSICS", 29203}, + {"Cinedom 1", 176}, + {"Cinedom 1B", 178}, + {"Cinedom 1C", 180}, + {"Cinedom 1D", 190}, + {"Cinedom 2", 179}, + {"Cinedom 2B", 183}, + {"Cinedom 2C", 184}, + {"Cinedom 2D", 188}, + {"Cinedom 2E", 193}, + {"Cinedom 3", 182}, + {"Cinedom 3B", 185}, + {"Cinedom 3C", 192}, + {"Cinedom 3D", 195}, + {"Cinedom 4", 181}, + {"Cinedom 4B", 187}, + {"Cinedom 4C", 191}, + {"Cinedom 5", 186}, + {"Cinedom 5B", 194}, + {"Cindedom Deluxe", 189}, + {"CINEMANÍA AZUL", 29501}, + {"CINEMANÍA ROJO", 29605}, + {"CINEMANÍA", 29500}, + {"K1", 8401}, + {"K2", 8402}, + {"K3", 8403}, + {"K4", 8404}, + {"K5", 8405}, + {"K6", 8406}, + {"K7", 8407}, + {"K9", 8409}, + {"K12", 8412}, + {"TAQUILLA 1", 29206}, + {"TAQUILLA 2", 29207}, + {"TAQUILLA 3", 29502}, + {"TAQUILLA 4", 29503}, + {"TAQUILLA 5", 29504}, + {"TAQUILLA 6", 29301}, + {"TAQUILLA 7", 29302}, + {"TAQUILLA 8", 29303}, + {"TAQUILLA 11", 29316}, + {"TAQUILLA 12", 29610}, + {"TAQUILLA 13", 29402}, + {"TAQUILLA 14", 29212}, + {"TAQUILLA 16|9", 29606}, + // Music + {"40 LATINO", 29031}, + {"40 TV", 29110}, + {"CANAL+ JAUNE", 8203}, + {"CLASSICA", 15}, + {"GOLDSTAR TV", 518}, + {"MCM 2", 8305}, + {"MCM AFRICA", 8307}, + {"MCM", 8302}, + {"MTV 2", 28649}, + {"MTV 6", 28641}, + {"MTV Base", 28645}, + {"MTV Central", 28643}, + {"MTV F", 28642}, + {"MTV Hits", 28644}, + {"MUZZIK", 8007}, + {"RFM TV", 17008}, + {"TMF", 5015}, + {"VH1 Classic", 28647}, + {"VH1", 28646}, + {"Video Italia", 12220}, + {"VIVA ZWEI", 12120}, + {"VIVA", 12732}, + {"ZIK'/XXL", 17004}, + // News + {"BBC WORLD", 17007}, + {"Bloomberg TV", 12160}, + {"CNBC", 28010}, + {"CNBC", 35}, + {"CNBC-NBC", 29202}, + {"CNN", 28512}, + {"DW-tv", 9005}, + {"EuroNews", 28015}, + {"FOX NEWS", 29032}, + {"N24", 47}, + {"n-tv", 12730}, + {"Sky News", 3995}, + // Netherlands + {"NED1", 4011}, + {"NED2", 4012}, + {"NED3", 4013}, + {"NET5", 5004}, + {"RTL4", 2004}, + {"RTL5", 2005}, + {"SBS6", 5005}, + {"V8/Fox Kids", 5020}, + {"Yorin", 5010}, + // Porn + {"BEATE-UHSE.TV", 21}, + {"Blue Movie1", 513}, + {"Blue Movie2", 514}, + {"Blue Movie3", 515}, + {"K10", 8410}, + {"TAQUILLA X", 29213}, + {"TAQUILLA X", 29602}, + {"TAQUILLA XX", 29607}, + {"X-ZONE", 4009}, + // Sports + {"C+BLAUW", 4006}, + {"DSF", 900}, + {"EUROSPORT", 8101}, + {"Eurosport", 28009}, + {"EUROSPORT", 29310}, + {"EUROSPORTNEWS", 29037}, + {"PATHE SPORT|", 8009}, + {"PREMIERE SPORT 1", 17}, + {"PREMIERE SPORT 2", 27}, + {"SUPERDOM", 26}, + // French + {"13EME RUE", 8703}, + {"AB 1", 17001}, + {"AB MOTEURS", 17000}, + {"ACTION", 17010}, + {"ALLOCINE TV", 8308}, + {"ANIMAUX", 17002}, + {"ARTE", 9009}, + {"BLOOMBERG TV", 8004}, + {"CA TV", 8610}, + {"CANAL+", 8201}, + {"CANAL+ BLEU", 8202}, + {"CANAL J", 8108}, + {"CANAL JIMMY", 8006}, + {"CANALCLUB", 8812}, + {"Cartoon Network", 28511}, + {"CLUB TELEACHAT", 8303}, + {"COMEDIE !", 8702}, + {"CONTACT TV", 8804}, + {"CUISINE.TV", 8112}, + {"DEMAIN !", 8701}, + {"DISNEY CHANNEL", 8207}, + {"DT CSAT 10", 9159}, + {"ENCYCLOPEDIA", 17003}, + {"ESCALES", 17005}, + {"EURONEWS", 8505}, + {"FORUM", 8707}, + {"FRANCE 2", 8801}, + {"FRANCE 3", 8802}, + {"GAME ONE", 8717}, + {"i TELEVISION", 8010}, + {"KIOSQUE", 8704}, + {"KTO", 8304}, + {"LA CHAINE METEO", 8008}, + {"LA CINQUIEME", 8501}, + {"LaChaîneHistoire", 17006}, + {"LCI", 8107}, + {"LCP", 8506}, + {"L'EQUIPE TV", 8706}, + {"LibertyTV.com", 12280}, + {"MANGAS", 17011}, + {"MONTECARLO TMC", 8102}, + {"Motors TV", 12300}, + {"NAT GEOGRAPHIC", 8310}, + {"PAD", 8211}, + {"PARIS PREMIERE", 8104}, + {"PLANETE 2", 8507}, + {"PLANETE", 8103}, + {"PMU sur Canal+", 8210}, + {"RFO SAT", 8708}, + {"SANTE - VIE", 8110}, + {"SEASONS", 8001}, + {"TCM", 28515}, + {"TEST CDN 1", 8616}, + {"TEST CDN 3", 8627}, + {"TiJi", 8309}, + {"TV 5", 9001}, + {"TV BREIZH", 8502}, + {"TV Puls", 20601}, + {"TV5 Europe", 12240}, + {"VOYAGE", 8105}, + // Spanish + {"ANDALUCÍA TV", 29011}, + {"Bloomberg", 12721}, + {"CALLE 13", 29609}, + {"Canal Canarias", 29700}, + {"Cartoon Network", 29314}, + {"CNN+", 29020}, + {"DISCOVERY", 29116}, + {"DISNEY CHANNEL", 29111}, + {"DOCUMANÍA", 29200}, + {"ESTILO", 29305}, + {"ETB", 29035}, + {"FASHION TV", 29115}, + {"FOX KIDS", 29209}, + {"FOX", 29507}, + {"MOSAICO", 29315}, + {"MÉTEO", 29014}, + {"Nat Geo Channel", 29034}, + {"NICK-PARAMOUNT", 29312}, + {"RTPI", 9006}, + {"SEASONS", 29204}, + {"TAQUILLA 0", 29205}, + {"TCM.", 28516}, + {"TVC INT.", 29701}, + {"VIAJAR", 29306}, + // Miscellaneous + {"Alice", 12200}, + {"Canal Algerie", 9008}, + {"CANALPRO TV", 8516}, + {"ESC1 - EGYPTE", 9003}, + {"FASHION TV.COM", 17009}, + {"Home Shopping Euro", 45}, + {"Home Shopping Euro", 40}, + {"Kabel 1 Austria", 20004}, + {"Kabel 1 Schweiz", 20003}, + {"Polonia 1/Top Sho", 20366}, + {"ProSieben A", 20002}, + {"ProSieben Schweiz", 20001}, + {"QVC GERMANY", 12100}, + {"RAI 1", 9004}, + {"REAL MADRID TV", 29019}, + {"RealityTV", 20309}, + {"RTL TELE Letzebuerg", 3994}, + {"RTM - MAROC", 9002}, + {"SÜDWEST BW", 28113}, + {"SÜDWEST RP", 28231}, + {"Super 1", 20364}, + {"Travel", 28001}, + {"TV7", 9007}, + {"TV-NIEP II", 12740}, + {"Wishline", 12320} }; + + +// Nothing user-configurable below this line. + +static const char date_line[] = "\t<td align=center valign=middle colspan=3><span id=fb-b10>"; +static const char start_time_line[] = " \t\t<td id=\"jobview-box-date\" align=center><nobr> "; +static const char stop_time_line[] = "\t\t\t<tr><td id=\"line\" align=center><span id=\"fn-w9\">bis "; +static const char channel_line[] = "\t\t\t<tr><td align=center><span id=\"fb-w9\">"; +static const char title_line[] = "\t\t\t\t<td align=left width=100%><span id=\"fb-w10\">"; +static const char summary_line[] = "<span id=\"fn-b8\">"; +static const char genre_line[] = "\t\t\t\t<td align=right valign=center nowrap><span id=\"fn-w10\">"; + static const int month_lengths[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -static const int max_channel = sizeof(channel_names)/sizeof(char *); -static const int max_title = 50; // maximum length of title file name generated -static const int max_line = 1024; // line buffer (not used when parsing summary text) -static const int max_summary = 5000; // Summary can be up to 5000 bytes long -static const int stop_time_safety_margin = 10; // add 10 minutes to stop time in case start was delayed @@ -102,6 +386,10 @@ char map_special_char(const char * const word) return 'Ü'; else if (strcmp(word, "szlig") == 0) return 'ß'; + else if (strcmp(word, "nbsp") == 0) + return ' '; + else if (strcmp(word, "amp") == 0) + return '&'; return ' '; } @@ -109,40 +397,52 @@ char map_special_char(const char * const word) -void read_file_name(const char * const line, char * const file_name) +void read_file_name_and_title(const char * const line, char * const file_name, char * const title) { int line_index = sizeof(title_line) - 1; int title_index = 0; - char ch = line[line_index++]; + int file_name_index = 0; + char ch; do { + ch = line[line_index++]; if (ch == '&') { char word[10]; int i = 0; while ((line[line_index + i] != ';') && (i < 9)) - word[i++] = line[line_index + i]; - word[i] = 0; - ch = map_special_char(word); - line_index += i; + { + word[i] = line[line_index + i]; i++; + } + if (line[line_index + i] == ';') + { + word[i] = 0; + ch = map_special_char(word); + line_index += i; + } } switch (ch) { - case 'ä': file_name[title_index++] = 'a'; file_name[title_index++] = 'e'; break; - case 'ö': file_name[title_index++] = 'o'; file_name[title_index++] = 'e'; break; - case 'ü': file_name[title_index++] = 'u'; file_name[title_index++] = 'e'; break; - case 'Ä': file_name[title_index++] = 'A'; file_name[title_index++] = 'e'; break; - case 'Ö': file_name[title_index++] = 'O'; file_name[title_index++] = 'e'; break; - case 'Ü': file_name[title_index++] = 'U'; file_name[title_index++] = 'e'; break; - case 'ß': file_name[title_index++] = 's'; file_name[title_index++] = 's'; break; + case 'ä': file_name[file_name_index++] = 'a'; file_name[file_name_index++] = 'e'; break; + case 'ö': file_name[file_name_index++] = 'o'; file_name[file_name_index++] = 'e'; break; + case 'ü': file_name[file_name_index++] = 'u'; file_name[file_name_index++] = 'e'; break; + case 'Ä': file_name[file_name_index++] = 'A'; file_name[file_name_index++] = 'e'; break; + case 'Ö': file_name[file_name_index++] = 'O'; file_name[file_name_index++] = 'e'; break; + case 'Ü': file_name[file_name_index++] = 'U'; file_name[file_name_index++] = 'e'; break; + case 'ß': file_name[file_name_index++] = 's'; file_name[file_name_index++] = 's'; break; + case ' ': file_name[file_name_index++] = '_'; break; + case '&': + file_name[file_name_index++] = 'u'; file_name[file_name_index++] = 'n'; file_name[file_name_index++] = 'd'; + break; default: - if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) || ((ch >= '0') && (ch <= '9'))) - file_name[title_index++] = ch; + if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) || ((ch >= '0') && (ch <= '9')) || (ch == '-')) + file_name[file_name_index++] = ch; } - ch = int(line[line_index++]); - } while ((title_index < max_title-1) && (ch != '<') && (ch != 0) && (line_index < max_line-1)); - file_name[title_index] = 0; + title[title_index++] = ch; + } while ((file_name_index < max_title-5) && (ch != '<') && (ch != 0)); + file_name[file_name_index] = 0; + title[title_index-1] = 0; } @@ -184,7 +484,7 @@ void read_summary(char * const summary) word[word_index++] = ch; } while ((word_index < 6) && (ch != '>') && (ch != EOF)); while ((ch != '>') && (ch != EOF)) ch = getchar(); - if (strncmp("/table", word, 6) == 0) + if (strncmp("/span", word, 4) == 0) done = true; } break; @@ -207,62 +507,150 @@ void read_summary(char * const summary) +int find_channel_number(const unsigned short * const vdr_pnrs, const char * const channel_name) + +{ + for (int tvtv_channel_number = 0; tvtv_channel_number < sizeof(channel_map)/sizeof(map_entry); tvtv_channel_number++) + if (strcmp(channel_name, channel_map[tvtv_channel_number].tvtv_name) == 0) + for (int vdr_channel_number = 0; vdr_pnrs[vdr_channel_number] != 0xFFFF; vdr_channel_number++) + if (vdr_pnrs[vdr_channel_number] == channel_map[tvtv_channel_number].pnr) + return vdr_channel_number; + fprintf(stderr, "Error - channel '%s' not recognized.\n", channel_name); + exit(1); + /*NOTREACHED*/ +} + + -main() +unsigned short * read_vdr_pnrs(const char * const channels_conf_file_name) + { - int channel = 0; + FILE * channels_conf = fopen(channels_conf_file_name, "r"); + if (channels_conf == NULL) + { + perror("unable to open channels.conf."); + exit(1); + } + unsigned short * vdr_pnrs = (unsigned short *) malloc(max_vdr_channel * sizeof(unsigned short)); + int vdr_channel_number = 0; + while (!feof(channels_conf) && (vdr_channel_number < max_vdr_channel-1)) + { + char line[1024]; + fgets(line, sizeof(line)-1, channels_conf); + int pnr; + if ((line[0] != ':') && + (sscanf(line, "%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%*[^:]:%d", &pnr) == 1)) + vdr_pnrs[vdr_channel_number++] = pnr; + } + vdr_pnrs[vdr_channel_number++] = 0xFFFF; // sentinel + fprintf(stderr, "%d pnrs.\n", vdr_channel_number); + return (unsigned short *) realloc(vdr_pnrs, vdr_channel_number * sizeof(unsigned short)); +} + + + + +void process_input(const unsigned short * const vdr_pnrs) + +{ + + int channel = -1; int day = -1; int next_day = -1; int start_time = -1; - int stop_time = -1; + int stop_hour = -1; + int stop_minute= -1; + char genre[max_genre] = {0}; char summary[max_summary] = {0}; char file_name[max_title] = {0}; + char title[max_title] = {0}; while (!feof(stdin)) { char line[max_line]; fgets(line, max_line-1, stdin); + line[max_line-1] = 0; if (strncmp(line, date_line, sizeof(date_line)-1) == 0) { const int month = (line[sizeof(date_line) + 6]- '0') * 10 + line[sizeof(date_line) + 7]-'0'; day = (line[sizeof(date_line) + 3]- '0') * 10 + line[sizeof(date_line) + 4]-'0'; - next_day = day == month_lengths[month]? 1 : day + 1; + next_day = day == month_lengths[month-1]? 1 : day + 1; } else if (strncmp(line, start_time_line, sizeof(start_time_line)-1) == 0) - { start_time = (line[sizeof(start_time_line) - 1] - '0') * 1000 + (line[sizeof(start_time_line) ] - '0') * 100 + (line[sizeof(start_time_line) + 2] - '0') * 10 + (line[sizeof(start_time_line) + 3] - '0'); - } else if (strncmp(line, stop_time_line, sizeof(stop_time_line)-1) == 0) { - stop_time = ((line[sizeof(stop_time_line) - 1] - '0') * 1000 + - (line[sizeof(stop_time_line) ] - '0') * 100 + - (line[sizeof(stop_time_line) + 2] - '0') * 10 + - (line[sizeof(stop_time_line) + 3] - '0') + stop_time_safety_margin) % 2400; - if ((day < 0) || (start_time < 0) || (file_name[0] == 0) || (channel == max_channel)) + stop_hour = (line[sizeof(stop_time_line) - 1] - '0') * 10 + + (line[sizeof(stop_time_line) ] - '0'); + stop_minute = (line[sizeof(stop_time_line) + 2] - '0') * 10 + + (line[sizeof(stop_time_line) + 3] - '0') + + stop_time_safety_margin; + if (stop_minute > 59) + { + stop_minute -= 60; + if (stop_hour == 23) + stop_hour = 0; + else + stop_hour++; + } + if ((day < 0) || (start_time < 0) || (file_name[0] == 0) || (channel == -1)) + { fprintf(stderr, "Input data error.\n"); + exit(1); + } else - printf("1:%03d:%02d:%04d:%04d:2:7:%s:%s\n", channel+1, start_time < 600? next_day : day, start_time, stop_time, file_name, summary); - start_time = -1; stop_time = -1; file_name[0] = 0; summary[0] = 0; channel = max_channel; + printf("1:%03d:%02d:%04d:%02d%02d:%d:%d:%s:\"%s\" %s||%s||||||(epg2timers)\n", + channel+1, start_time < 600? next_day : day, start_time, stop_hour, stop_minute, + recording_priority, recording_lifetime, file_name, + title, genre, summary); + start_time = -1; channel = -1; + file_name[0] = 0; summary[0] = 0; genre[0] = 0; } else if (strncmp(line, title_line, sizeof(title_line)-1) == 0) - read_file_name(line, file_name); + read_file_name_and_title(line, file_name, title); else if (strncmp(line, channel_line, sizeof(channel_line)-1) == 0) { int i = sizeof(channel_line); - while ((i < max_line-1) && (line[i] != '<')) i++; + while ((line[i] != '<') && (line[i] != 0)) i++; line[i] = 0; // end of string - for (channel = 0; (channel < max_channel) && - (strcmp(line + sizeof(channel_line) - 1, channel_names[channel]) != 0); - channel++); - if (channel == max_channel) - fprintf(stderr, "Error - channel '%s' not recognized.\n", line + sizeof(channel_line) - 1); + channel = find_channel_number(vdr_pnrs, line + sizeof(channel_line) - 1); } else if (strncmp(line, summary_line, sizeof(summary_line)-1) == 0) read_summary(summary); + else if (strncmp(line, genre_line, sizeof(genre_line)-1) == 0) + { + int genre_index; + for (genre_index = 0; genre_index < max_genre-1; genre_index++) + { + const char ch = line[genre_index + sizeof(genre_line)-1]; + if ((ch == 0) || (ch == '&') || (ch == '<')) + break; + genre[genre_index] = ch; + } + genre[genre_index] = 0; + } } } + + + +main(int argc, char *argv[]) + +{ + fprintf(stderr, "epg2timers Version 0.5, 15-Sep-2001.\n"); + + if (argc != 2) + { + fprintf(stderr, "usage: %s channels.conf\n", argv[0]); + exit(1); + } + + const unsigned short * const vdr_pnrs = read_vdr_pnrs(argv[1]); + process_input(vdr_pnrs); + exit(0); +} diff --git a/Tools/epg2timers/epg_channel_names b/Tools/epg2timers/epg_channel_names new file mode 100644 index 0000000..2633a99 --- /dev/null +++ b/Tools/epg2timers/epg_channel_names @@ -0,0 +1,400 @@ +ATV,at +ORF1,at +ORF2,at +TW1,at + +Club RTL,be +Ketnet/Canvas,be +TVI,be +tv1,be + +SF1,ch +sf2,ch + +13th Street,de +3sat,de,at,ch +ARD,de +ARTE,de +B1,de +BBC World,de +BEATE-UHSE.TV,de +BR-alpha,de +BR3,de +Bet on Jazz,de +Bloomberg TV,de +Blue Movie1,de +Blue Movie2,de +Blue Movie3,de +CNBC,de +CNN,de +Cartoon,de +Cindedom Deluxe,de +Cinedom 1,de +Cinedom 2,de +Cinedom 3,de +Cinedom 4,de +Cinedom 5,de +Classica,de +DSF,de +Discovery,de +Disney Channel,de +Eins Extra,de +Eins Festival,de +Eins MuXx,de +EuroNews,de +Eurosport,de +FOX KIDS,de +Filmpalast,de +Goldstar TV,de +HH-1,de +HR,de +Heimatkanal,de +Junior,de +K-Toon,de +Kabel 1,de +Kinderkanal,de +Krimi&Co,de +MDR,de +MTV,de +MTV2,de +N24,de +NBC,de +NDR,de +NEUN LIVE,de +ONYX,de +ORB,de +Phoenix,de +Planet,de +Premiere 1,de +Premiere 2,de +Premiere 3,de +Premiere Action,de +Premiere Comedy,de +Premiere SCI-FI,de +Premiere Sport1,de +Premiere Sport2,de +Premiere Sport3,de +Premiere Star,de +Premiere analog,de +ProSieben,de +QVC,de +RTL,de +RTL2,de +SAT.1,de +SR,de +SWR BW,de +SWR RP,de +SeaSonS,de +Studio Universal,de +Sunset,de +Super RTL,de +TNT,de +TRT,de,tr +TV.BERLIN,de +Theaterkanal,de +VIVA,de +VIVA2,de +VOX,de +WDR,de +ZDF,de +ZDF.doku,de +ZDF.info,de +n-tv,de +skynews,de +tv.m,de + +Danmark 1,dk +TV2 Danmark,dk + +MTV3,fi +Nelonen 4,fi +Subtv,fi +TV1,fi +TV2,fi + +13ème Rue,fr +AB 1,fr +Arte,fr +Arte Sat,fr +Canal J,fr +Canal Jimmy,fr +Canal+,fr +Canal+ Bel. bleu,fr +Canal+ Bel. jaune,fr +Canal+ Belgique,fr +Canal+ bleu,fr +Canal+ jaune,fr +Canal+ vert,fr +Ciné Cinémas 1,fr +Ciné Cinémas 2,fr +Ciné Cinémas 3,fr +Ciné Classics,fr +Cinéfaz,fr +Cinéstar 1,fr +Cinéstar 2,fr +Cinétoile,fr +Comédie !,fr +Disney Channel,fr +Escale,fr +Eurosport,fr +Festival,fr +Fox Kids,fr +France 2,fr +France 3,fr +Histoire,fr +LCI,fr +La Cinquième Sat,fr +La chaîne histoire,fr +La cinquième,fr +M6,fr +M6 Music,fr +MCM,fr +MTV,fr +Mangas,fr +Mezzo,fr +Muzzik,fr +Odyssée,fr +Paris Première,fr +Pathé sport,fr +Planète,fr +RTBF 1,fr +RTBF 2,fr +RTL 9,fr +Série Club,fr +TCM,fr +TF1,fr +TMC,fr +TSR 1,fr +TSR 2,fr +TV5,fr +Télétoon,fr +Téva,fr +Voyage,fr +XXL,fr + +ANIMALplanet,hu +Budapest TV,hu +Duna TV,hu +FILMMÚZEUM,hu +FOX KIDS/SPORTS,hu +FÕNIX TV,hu +Game Channel,hu +HBO,hu +Hallmark,hu +MAGYAR ATV,hu +Minimax,hu +National Geographic,hu +Nickelodeon,hu +RTL Klub,hu +Romantica,hu +SATeLIT,hu +SPORT1,hu +Spektrum TV,hu +TV2,hu +VIASAT3,hu +VIVA+,hu +fix.tv,hu +m1,hu +m2,hu + ++ Calcio,it ++ F1,it +Adult +,it +CANALE 5,it +Canal Jimmy,it +Canale Viaggi,it +Cartoon Network,it +Cine Classics,it +CineCinemas 1,it +CineCinemas 2,it +Classica,it +Cult Network,it +Discovery Channel,it +Disney Channel,it +Euro News,it +Eurosport,it +Hallmark,it +Happy Channel,it +ITALIA 1,it +La 7,it +MTV,it +MTV - TMC 2,it +Marcopolo,it +Match Music,it +Milan Channel,it +Nuvolari Motor,it +Odeon,it +Planete,it +Primafila,it +RAI 1,it +RAI 2,it +RAI 3,it +RAI Sat Fiction,it +RETE 4,it +Raisat Album,it +Raisat Art,it +Raisat Cinema,it +Raisat Educational,it +Raisat Gambero Rosso,it +Raisat Nettuno 1,it +Raisat Nettuno 2,it +Raisat Ragazzi,it +Raisat Show,it +Raisat Sport,it +SNAI Sat,it +Salute e benessere,it +Sat 2000,it +Satisfation Club TV,it +Seasons,it +Stream Calcio,it +Stream News,it +Studio Universal,it +TSI 1,it +TSI 2,it +TVL,it +Tele+ 16:9,it +Tele+ Bianco,it +Tele+ Grigio,it +Tele+ Nero,it +VIVA - Rete A,it + +Netherland 1,nl +Netherland 2,nl +Netherland 3,nl + +ATV Avrupa,tr +Kanal D,tr +Kral TV,tr +NTV Turkey,tr +Show TV,tr +Star TV,tr + +Adult Channel,uk +Adventure One,uk +Anglia,uk +BBC Choice,uk +BBC Choice NI,uk +BBC Choice Scotland,uk +BBC Choice Wales,uk +BBC Knowledge,uk +BBC News 24,uk +BBC Parliament,uk +BBC Prime,uk +BBC World,uk +BBC1,uk +BBC1 North. Ireland,uk +BBC1 Scotland,uk +BBC1 Wales,uk +BBC2,uk +BBC2 North. Ireland,uk +BBC2 Scotland,uk +BBC2 Wales,uk +Bangla TV,uk +Bloomberg TV,uk +Border,uk +Bravo (Analogue),uk +Bravo (Digital),uk +British Eurosport,uk +CNBC Europe,uk +CNN,uk +Carlton Central,uk +Carlton Cinema,uk +Carlton Food,uk +Carlton Westcountry,uk +Carlton/LWT,uk +Cartoon Network,uk +Challenge TV,uk +Channel 4,uk +Channel 5,uk +Channel Television,uk +Disc. Animal Planet,uk +Disc. Channel (Ana.),uk +Disc. Civilisations,uk +Disc. Home Leisure,uk +Disc. Sci-Trek,uk +Disc. Travel Advent.,uk +Discovery Channel,uk +Discovery Kids,uk +Discovery Wings,uk +Disney,uk +Euronews,uk +Fantasy Ch. Dig.,uk +Fantasy Channel,uk +Film Four,uk +Fox Kids,uk +Grampian,uk +Granada,uk +Granada Breeze,uk +Granada Men & Motors,uk +Granada Plus,uk +HTV Wales,uk +HTV West,uk +Hallmark,uk +History Channel,uk +ITN News Channel,uk +ITV Sport Channel,uk +ITV Sport Plus,uk +ITV2,uk +Landscape,uk +Living,uk +MTV UK,uk +MUTV,uk +Meridian,uk +National Geographic,uk +Network 2,uk +Nick Junior,uk +Nick Junior Analogue,uk +Nickelodeon (dig.),uk +Nickleodeon (ana.),uk +Pakistani Channel,uk +Paramount Comedy,uk +Performance,uk +Play UK,uk +Playboy TV,uk +QVC,uk +RTE1,uk +Racing Channel,uk +Rapture TV,uk +S2,uk +S4C,uk +S4C digidol,uk +SKY Cinema,uk +SKY Movie Max(SDig.),uk +SKY Movie Max(ana.),uk +SKY News,uk +SKY Premier(Digital),uk +SKY Premier(OnDigi),uk +SKY Sports 1,uk +SKY Sports 2,uk +SKY Sports 3,uk +Sci-Fi Cable,uk +Sci-Fi Satelite,uk +Scottish,uk +Screenshop,uk +Shop!,uk +Sky Movie Max(OnDig),uk +Sky One,uk +Sky One (OnDigital),uk +Sky Premier(Ana.),uk +Sky Sports .com,uk +Sky Sports Extra,uk +Sky Travel,uk +Sony Entertainment,uk +TCM,uk +TCM (Analogue),uk +TG4,uk +TV3,uk +Tara Television,uk +The Box,uk +Trouble Analogue,uk +Trouble Digital,uk +Tyne Tees Television,uk +UK Drama,uk +UK Gold,uk +UK Gold 2,uk +UK Horizons,uk +UK Style,uk +Ulster ,uk +VH1,uk +Yorkshire,uk +Zee TV,uk diff --git a/Tools/epg2timers/get_merkliste.pl b/Tools/epg2timers/get_merkliste.pl new file mode 100755 index 0000000..bb23fa3 --- /dev/null +++ b/Tools/epg2timers/get_merkliste.pl @@ -0,0 +1,82 @@ +#!/usr/bin/perl +# Create a user agent object + +use HTML::Entities; +use HTML::Parser; +use LWP::UserAgent; +use IO::Handle; + +STDOUT->autoflush(1); + +$ua = new LWP::UserAgent; +$ua->agent("Mozilla/9.1 " . $ua->agent); +# $ua->proxy('http', 'http://localhost:8080/'); + +$filename = "merkliste.html"; +$base_url = "http://www.tvtv.de"; +# Hier das Bookmark von TVTV eintragen: +@files_to_fetch = ("/cgi-bin/bookmark.cgi?id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + +$num = 0; +$state = 0; + +$p = HTML::Parser->new( api_version => 3, + start_h => [\&fparser_start, "tagname, attr"], + unbroken_text => 1 ); + +foreach $url (@files_to_fetch) { + $nurl = $base_url . $url; + print "Getting " . $nurl . "...\n"; + $req = new HTTP::Request GET => $nurl; + $res = $ua->request($req); + if ($res->is_success) { + open (OUTFILE, ">" . $filename); + print OUTFILE $res->content; + close (OUTFILE); + $p->parse ($res->content); + $p->eof; + } else { + print "...FAILED\n"; + } +} +# Zielordner fuer die Speicherung der Merkliste: + +print "...saved to 'merkliste.html'\n"; +sub fparser_start { + my($tagname, $attr_t) = @_; + my(%attr) = %$attr_t; + + if ($tagname eq "frame") { + if ($state == 1) { + if (($attr{name} eq "frame_main") || + ($attr{name} eq "frame_nav") || + ($attr{name} eq "frame_nav_bottom")) { + push @files_to_fetch, $attr{src}; + } + } + if ($state == 2) { + if (($attr{name} eq "frame_content")) { + push @files_to_fetch, $attr{src}; + } + } + } + if ($tagname eq "a") { + if ($attr{href} ne "") { + $last_href = $attr{href}; + if ($state == 0) { + push @files_to_fetch, $last_href; + $state = 1; + } + } + } + if ($tagname eq "img") { + if ($state == 1) { + if ($attr{src} =~ /b_joblist/i) { + $state = 2; + push @files_to_fetch, $last_href; + } + } + } +} + + diff --git a/Tools/epg2timers/loadvdr.pl b/Tools/epg2timers/loadvdr.pl new file mode 100755 index 0000000..485b0a4 --- /dev/null +++ b/Tools/epg2timers/loadvdr.pl @@ -0,0 +1,89 @@ +#!/usr/bin/perl +# +# 0.01 loadvdr (peter) +# 0.02 delete old entries before updating (peter) +# 0.03 dumped Net::Telnet because of lost connections +# +# please submit diffs to petera@gmx.net +# +# ./epg2timers < merkliste.html | perl -w loadvdr.pl +# +# + +use Socket; +use Getopt::Std; + +@resp = (); + +$Dest = "localhost"; +$Port = 2001; + +$Timeout = 10; # max. seconds to wait for response + +$SIG{ALRM} = sub { Error("timeout"); }; +alarm($Timeout); + +$iaddr = inet_aton($Dest) || Error("no host: $Dest"); +$paddr = sockaddr_in($Port, $iaddr); + +$proto = getprotobyname('tcp'); +socket(SOCK, PF_INET, SOCK_STREAM, $proto) || Error("socket: $!"); +connect(SOCK, $paddr) || Error("connect: $!"); +select(SOCK); $| = 1; +Receive_void(); + +Send("lstt"); + +foreach $item (reverse @resp){ + if ($item =~ /^250.(\d{1,2}).*\(epg2timers\)/) { + Send_void("DELT $1"); + } +} + +while (defined ($line = <STDIN>)) { + chomp $line; + Send_void("UPDT $line"); +} + +Send("quit"); +close(SOCK) || Error("close: $!"); + + + +sub Send +{ + my $cmd = shift || Error("no command to send"); + print SOCK "$cmd\r\n"; + Receive(); +} + +sub Send_void +{ + my $cmd = $_[0]; + print SOCK "$cmd\r\n"; + Receive_void(); +} + +sub Receive +{ + while (<SOCK>) { + chomp; + push @resp,$_; + last if substr($_, 3, 1) ne "-"; + } +} + +sub Receive_void +{ + while (<SOCK>) { + last if substr($_, 3, 1) ne "-"; + } +} + +sub Error +{ + print STDERR "@_\n"; + close(SOCK); + exit 0; +} + diff --git a/Tools/epg2timers/update_timers b/Tools/epg2timers/update_timers new file mode 100755 index 0000000..3849841 --- /dev/null +++ b/Tools/epg2timers/update_timers @@ -0,0 +1,22 @@ +#!/bin/sh + +# update_timers: retrieve a new "merkliste" from http://tvtv.de, +# convert it to vdr format and transmit it to vdr via SVDRP. + +TOOLDIR="/home/cko/bin" +CHANPATH="/home/cko/VDR/channels.conf" + +cd /tmp +rm -f merkliste.html + +# if you have a slow dial up connection to your name server and/or ISP, +# this will avoid a timeout in get_merkliste.pl. +ping -c 2 www.tvtv.de + +# get the "merkliste". +$TOOLDIR/get_merkliste.pl + +if [ -s merkliste.html ] ; then + # convert merkliste.html to timers.conf format and transmit it to vdr. + $TOOLDIR/epg2timers $CHANPATH < merkliste.html | $TOOLDIR/loadvdr.pl +fi diff --git a/Tools/epg2timers/update_timers.old b/Tools/epg2timers/update_timers.old new file mode 100755 index 0000000..c4c3f5c --- /dev/null +++ b/Tools/epg2timers/update_timers.old @@ -0,0 +1,24 @@ +#!/bin/sh + +# update_timers: load a new "merkliste" from http://tvtv.de +# and create a new VDR timer configuration file (timers.conf) +# from it. Restart VDR if the timers have changed. + +TOOLDIR="/home/cko/bin" +VDRDIR="/home/cko/VDR" + +cd /tmp +rm -f merkliste.html epgtimers.new epgtimers.old vdrtimers.old +ping -c 2 www.tvtv.de +$TOOLDIR/get_merkliste.pl +if [ -s merkliste.html ] ; then + $TOOLDIR/epg2timers $VDRDIR/channels.conf < merkliste.html | sort -t: +2.0 -5.0 > epgtimers.new + fgrep '(epg2timers)' $VDRDIR/timers.conf | sort -t: +2.0 -5.0 > epgtimers.old + if ! cmp -s epgtimers.old epgtimers.new ; then + /sbin/killproc $VDRDIR/vdr + fgrep -v '(epg2timers)' $VDRDIR/timers.conf > vdrtimers.old + cat epgtimers.new vdrtimers.old | sort -t: +2.0 -5.0 > $VDRDIR/timers.conf + echo "Timers updated." + fi +fi +rm -f merkliste.html epgtimers.new epgtimers.old vdrtimers.old |