Version 0.95

- Fixed behaviour in case the shutdown didn't take place (there were many
  "next timer event at..." messages in that case).
- Reduced the default value for MinEventTimeout to 30 minutes.
- Fixed detecting manual start in shutdown feature.
- An error message is now displayed in case the Transfer Mode can't be
  started because the necessary DVB card is currently recording (or there
  is no DVB card that can access this channel).
- Fixed toggling channels with the '0' key in case the "Ok" button has been
  pressed to display the current/next information.
- Pressing the "Power" key now always initiates the shutdown sequence (after
  user confirmation in case of a recording timer), event if there is currently
  a menu or a replay session active. Note the additional remarks in INSTALL
  regarding the values of the two parameters given to the shutdown program
  in case of a currently recording timer.
- Switching through channel groups with the "Left" and "Right" keys now
  always starts at the group that contains the current channel.
- Implemented "Multi Speed Mode" (thanks to Stefan Huelswitt).
- Implemented backtracing to hit the right spot after fast forward/rewind
  (thanks to Stefan Huelswitt).
- Implemented replay mode display (thanks to Stefan Huelswitt, with a few
  rewrites by kls).
- Changed the size of all input buffers used to parse config files or receive
  SVDRP commands to the same value of 10KB. This allows long strings to be
  used in the 'summary' field of a timer, for instance.
- The pipe to the Dolby Digital replay command (option '-a') now closes all
  unused file descriptors in the child process to avoid crashing when the
  OSD is used (thanks to Andreas Vitting).
- Switched to the driver's new tuning API (VDR now requires a driver version
  dated 2001-09-14 or higher).
- Changed obsolete macro VIDEO_WINDOW_CHROMAKEY to VID_TYPE_CHROMAKEY (thanks
  to Guido Fiala).
- New version of the "Master-Timer" tool (thanks to Matthias Schniedermeyer).
- Better error handling when writing configuration files.
- Fixed putting the final editing mark into the edited version's marks file.
- Fixed manipulating an editing mark at the very end of a recording.
- Fixed starting a new replay immediately after stopping a previous one (had
  caused a mix between live video and replay).
- Three new keys ("Volume+", Volume-" and "Mute") to control the DVB card's
  audio output volume.
- New version of the 'epg2timers' tool (thanks to Carsten Koch).
This commit is contained in:
Klaus Schmidinger
2001-09-16 18:00:00 +02:00
parent bb18b9e0b4
commit 156831036e
39 changed files with 3989 additions and 1614 deletions

151
Tools/epg2timers/README Normal file
View File

@@ -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.

View File

@@ -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 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
{
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<63>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<EFBFBD>A AZUL", 29501},
{"CINEMAN<EFBFBD>A ROJO", 29605},
{"CINEMAN<EFBFBD>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<EFBFBD>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<EFBFBD>A TV", 29011},
{"Bloomberg", 12721},
{"CALLE 13", 29609},
{"Canal Canarias", 29700},
{"Cartoon Network", 29314},
{"CNN+", 29020},
{"DISCOVERY", 29116},
{"DISNEY CHANNEL", 29111},
{"DOCUMAN<EFBFBD>A", 29200},
{"ESTILO", 29305},
{"ETB", 29035},
{"FASHION TV", 29115},
{"FOX KIDS", 29209},
{"FOX", 29507},
{"MOSAICO", 29315},
{"M<EFBFBD>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<EFBFBD>DWEST BW", 28113},
{"S<EFBFBD>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 bgcolor=\"#7f98bf\" align=center><span id=\"fb-w14\"><nobr>&nbsp;";
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[] =
{
"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",
""
};
static const char start_time_line[] = " \t\t<td id=\"jobview-box-date\" align=center><nobr>&nbsp;";
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 '<EFBFBD>';
else if (strcmp(word, "szlig") == 0)
return '<EFBFBD>';
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 '<EFBFBD>': file_name[title_index++] = 'a'; file_name[title_index++] = 'e'; break;
case '<EFBFBD>': file_name[title_index++] = 'o'; file_name[title_index++] = 'e'; break;
case '<EFBFBD>': file_name[title_index++] = 'u'; file_name[title_index++] = 'e'; break;
case '<EFBFBD>': file_name[title_index++] = 'A'; file_name[title_index++] = 'e'; break;
case '<EFBFBD>': file_name[title_index++] = 'O'; file_name[title_index++] = 'e'; break;
case '<EFBFBD>': file_name[title_index++] = 'U'; file_name[title_index++] = 'e'; break;
case '<EFBFBD>': file_name[title_index++] = 's'; file_name[title_index++] = 's'; break;
case '<EFBFBD>': file_name[file_name_index++] = 'a'; file_name[file_name_index++] = 'e'; break;
case '<EFBFBD>': file_name[file_name_index++] = 'o'; file_name[file_name_index++] = 'e'; break;
case '<EFBFBD>': file_name[file_name_index++] = 'u'; file_name[file_name_index++] = 'e'; break;
case '<EFBFBD>': file_name[file_name_index++] = 'A'; file_name[file_name_index++] = 'e'; break;
case '<EFBFBD>': file_name[file_name_index++] = 'O'; file_name[file_name_index++] = 'e'; break;
case '<EFBFBD>': file_name[file_name_index++] = 'U'; file_name[file_name_index++] = 'e'; break;
case '<EFBFBD>': 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)
main()
int find_channel_number(const unsigned short * const vdr_pnrs, const char * const channel_name)
{
int channel = 0;
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*/
}
unsigned short * read_vdr_pnrs(const char * const channels_conf_file_name)
{
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);
}

View File

@@ -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<EFBFBD>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<EFBFBD> Cin<69>mas 1,fr
Cin<EFBFBD> Cin<69>mas 2,fr
Cin<EFBFBD> Cin<69>mas 3,fr
Cin<EFBFBD> Classics,fr
Cin<EFBFBD>faz,fr
Cin<EFBFBD>star 1,fr
Cin<EFBFBD>star 2,fr
Cin<EFBFBD>toile,fr
Com<EFBFBD>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<75>me Sat,fr
La cha<68>ne histoire,fr
La cinqui<75>me,fr
M6,fr
M6 Music,fr
MCM,fr
MTV,fr
Mangas,fr
Mezzo,fr
Muzzik,fr
Odyss<EFBFBD>e,fr
Paris Premi<6D>re,fr
Path<EFBFBD> sport,fr
Plan<EFBFBD>te,fr
RTBF 1,fr
RTBF 2,fr
RTL 9,fr
S<EFBFBD>rie Club,fr
TCM,fr
TF1,fr
TMC,fr
TSR 1,fr
TSR 2,fr
TV5,fr
T<EFBFBD>l<EFBFBD>toon,fr
T<EFBFBD>va,fr
Voyage,fr
XXL,fr
ANIMALplanet,hu
Budapest TV,hu
Duna TV,hu
FILMM<EFBFBD>ZEUM,hu
FOX KIDS/SPORTS,hu
F<EFBFBD>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

View File

@@ -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;
}
}
}
}

89
Tools/epg2timers/loadvdr.pl Executable file
View File

@@ -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;
}

22
Tools/epg2timers/update_timers Executable file
View File

@@ -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

View File

@@ -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