Version 1.3.5

- Fixed reading the EPG preferred language parameter from 'setup.conf'.
- Fixed switching to a visible programme in case the current channel has neither
  a video nor an audio PID.
- Fixed editing channels (SID now range checked) and creating new channels (NID,
  TID and RID are now set to 0).
- Fixed transponder handling to make it work with satellites that provide two
  transponders on the same frequency, with different polarization, like Hispasat
  at S30.0W (thanks to Thomas Bergwinkl for pointing this out). See man vdr(5)
  for details about the enhanced channel ID format.
- Since there appears to be no general solution for the UPT error yet, a recording
  now initiates an "emergency exit" if the number of UPT errors during one
  recording exceeds 10 (suggested by Gregoire Favre). Since the UPT error doesn't
  happen on my system, this has not been explicitly tested.
  The "preliminary fix" for the UPT error in VDR/dvbdevice.c has been disabled
  by default, since it makes channel switching unpleasently slow. If you want
  to have that workaround back, you can uncomment the line
  //#define WAIT_FOR_LOCK_AFTER_TUNING 1
  in VDR/dvbdevice.c.
- Adapted the 'sky' plugin to use the actual channel IDs, and to fetch EPG data
  from www.bleb.org.
- Limited automatic retuning to devices that actually provide the transponder
  (necessary for the 'sky' plugin).
- Fixed handling receivers in the 'sky' plugin, so that a recording on the same
  channel won't interrupt an ongoing Transfer Mode.
- Added subtable ID and TSDT handling to 'libsi' (thanks to Marcel Wiesweg).
- Fixed some Russian OSD texts (thanks to Vyacheslav Dikonov).
- Added the 'running status' to the EPG events. This is necessary for implementing
  the VPS function for recording.
- Removed the obsolete 'present' and 'following' handling from the EPG data.
- The EPG data is now always kept sorted chronologically in the internal data
  structures. This also means that any EPG data retrieved through the SVRDP
  command LSTE is guaranteed to be sorted by start time.
- Now using the 'running status' in the channel display, so that a programme
  that has an end time that is before the current time, but is still running,
  will still be shown in the display (provided the broadcasters handle the
  'running status' flag correctly). This also applies to programmes that have
  a start time that is in the future, but are already running.
- Implemented an "EPG linger time", which can be set to have older EPG information
  still displayed in the "Schedule" menu (thanks to Jaakko Hyvätti).
- Added PDCDescriptor handling to 'libsi'.
- Implemented handling the VPS timestamps (aka "Programme Identification Label")
  for full VPS support for timers (provided the tv stations actually broadcast
  this information). The VPS time is displayed in the event info page if it exists
  and is different than the event's start time.
- Extended the SVDRP command LSTE to allow limiting the listed data to a given
  channel, the present or following events, or events at a given time (thanks to
  Thomas Heiligenmann).
- Fixed a typo in libsi/si.h (thanks to Stéphane Esté-Gracias).
- Timers can now be set to use the VPS information to control recording a programme.
  The new setup options "Recording/Use VPS" and "Recording/VPS margin", as well as
  the "VPS" option in the individual timers, can be used to control this feature
  (see MANUAL for details).
  Note that this feature will certainly need a lot of testing before it can be
  called "safe"!
- The "Schedule" and "What's on now/next?" menus now have an additional column
  which displays information on whether there is a timer defined for an event,
  whether an event has a VPS time that's different than its start time, and
  whether an event is currently running (see MANUAL under "The "Schedule" Menu"
  for details).
This commit is contained in:
Klaus Schmidinger
2004-02-29 18:00:00 +01:00
parent 3fc2965975
commit 5a4eb3f104
42 changed files with 1344 additions and 375 deletions

View File

@@ -16,3 +16,11 @@ VDR Plugin 'sky' Revision History
2004-01-04: Version 0.2.0
- Implemented automatic PID switching and channel detection
2004-02-15: Version 0.3.0
- Now using the actual channel IDs a derived from the data stream.
- Switched EPG data retrieval to http://www.bleb.org.
- Added automatic DST detection to getskyepg.pl.
- Fixed handling receivers, so that a recording on the same channel
won't interrupt an ongoing Transfer mode.

View File

@@ -28,23 +28,18 @@ control the Digibox.
In order to access the Sky channels VDR needs to know the channel number
under which each channel is stored in the Sky Digibox. These numbers are
used as 'frequency' parameters in the channels.conf definitions of the Sky
channels (see the file 'channels.conf.sky'). Since these numbers are always
less than 1000, they can be easily distinguished from normal satellite
transponder frequencies. The VPID is 160 and the APID is 80 for all Sky
channels. These are just fake PIDs, since the Kfir card always uses these
fixed PIDs. The 'Ca' parameter of the Sky channels is set to 301, which
is defined as "Videoguard, Sky Digital" in VDR's 'ca.conf' file. Again, please
note that VDR doesn't do any decrypting here, this is just to mark these
channels as "conditionally accessible" and have a way of setting the CICAM
value for the Kfir device in VDR's Setup menu.
stored in the file 'channels.conf.sky', together with the channel IDs as
derived from the actual channel data and the names under which the EPG
data for each channel can be found (see below). Copy this file to your
plugins config directory, in a subdirectory named 'sky', as in
The Sky EPG is available on the Internet at http://www.ananova.com.
/video/plugins/sky/channels.conf.sky
The Sky EPG is available on the Internet at http://www.bleb.org.
The Perl script getskyepg.pl extracts the EPG data from these pages
and sends it to VDR via an SVDRP connection. The channel numbers Sky
uses to generate the EPG pages are stored as the 'sid' parameter in
the channels.conf definitions of the Sky channels. You can keep your
EPG data up-to-date by entering a call to getskyepg.pl into your
/etc/crontab. Call 'getskyepg.pl -h' for a list of options.
and sends it to VDR via an SVDRP connection. The channel names as
used on the bleb.org pages are defined in the channels.conf.sky file.
You can keep your EPG data up-to-date by entering a call to getskyepg.pl
into your /etc/crontab. Call 'getskyepg.pl -h' for a list of options.
The getskyepg.pl script requires the programs /usr/bin/wget and /usr/bin/logger
to be installed on your system.

View File

@@ -1,4 +1,34 @@
Sky One:106:h:S28.2E:0:160:80:0:301:222
itv2:226:h:S28.2E:0:160:80:0:301:451
sci-fi:130:h:S28.2E:0:160:80:0:301:161
Paramount Comedy:127:h:S28.2E:0:160:80:0:301:185
# Sky channel definitions
#
# Syntax:
#
# ChannelID:ChannelNumber:EPGname
#
# where
#
# ChannelID is the channel ID as derived from the actual channel
# data as broadcast in the data stream (see man vdr(5)).
#
# ChannelNumber is the number of this channel as you have to
# enter it on the DigiBox remote control.
#
# EPGname is the name of the page at www.bleb.org that has EPG
# data for this channel (without the '.xml'). If no such
# page exists, 'x' is entered.
#
S28.2E-2-2027-4705:106:sky_one
S28.2E-2-2027-5104:107:sky_one_mix
S28.2E-2-2054-10240:226:itv2
S28.2E-2-2023-4905:130:scifi
S28.2E-2-2025-5904:127:paramount
S28.2E-2-2009-6201:551:discovery
S28.2E-2-2020-4809:310:sky_cinema
S28.2E-2-2007-4303:301:sky_movies1
S28.2E-2-2007-4302:302:sky_movies2
S28.2E-2-2007-4403:303:sky_movies3
S28.2E-2-2011-4402:304:sky_movies4
S28.2E-2-2011-4503:305:sky_movies5
S28.2E-2-2011-4502:306:sky_movies6
S28.2E-2-2020-4603:307:sky_movies7
S28.2E-2-2007-5502:308:sky_movies8
S28.2E-2-2020-4602:309:x

View File

@@ -1,14 +1,14 @@
#!/usr/bin/perl
# getskyepg.pl: Get EPG data from Sky's web pages
# getskyepg.pl: Get EPG data for Sky channels from the Internet
#
# Connects to a running VDR instance via SVDRP, gets the channel data
# for the Sky channels and connects to Sky's web pages to extract the
# for the Sky channels and connects to Internet web pages to extract the
# EPG data for these channels. The result is sent to VDR via SVDRP.
#
# See the README file for copyright information and how to reach the author.
#
# $Id: getskyepg.pl 1.2 2003/04/02 16:21:47 kls Exp $
# $Id: getskyepg.pl 1.3 2004/02/15 13:35:52 kls Exp $
use Getopt::Std;
use Time::Local;
@@ -16,31 +16,33 @@ use Time::Local;
$Usage = qq{
Usage: $0 [options]
Options: -d hostname destination hostname (default: localhost)
Options: -c filename channel config file name (default: channels.conf.sky)
-d hostname destination hostname (default: localhost)
-p port SVDRP port number (default: 2001)
-S source channel source (default: S28.2E)
-D days days to get EPG for (1..7, default: 2)
};
die $Usage if (!getopts("d:D:hp:S:") || $opt_h);
die $Usage if (!getopts("c:d:D:hp:S:") || $opt_h);
$Conf = $opt_c || "channels.conf.sky";
$Dest = $opt_d || "localhost";
$Port = $opt_p || 2001;
$Source = $opt_S || "S28.2E";
$Days = $opt_D || 2;
$SkyWebPage = "www.ananova.com/tv/frontpage.html";
$SkyWebPage = "www.bleb.org/tv/data/listings";
$WGET = "/usr/bin/wget -q -O-";
$LOGGER = "/usr/bin/logger -t SKYEPG";
$DST = -3600; ##XXX TODO find out whether DST is active!
$DST = -3600; # Daylight Saving Time offset
$SecsInDay = 86400;
$MaxFrequency = 1000;
$idxName = 0;
$idxFrequency = 1;
$idxSource = 3;
$idxSid = 9;
@Channels = ();
$idxSource = 0;
$idxNumber = 1;
$idxName = 2;
Error("days out of range: $Days") unless (1 <= $Days && $Days <= 7);
@@ -57,34 +59,52 @@ sub Error
sub GetChannels
{
SVDRPsend("LSTC");
my @channels = ();
for (SVDRPreceive(250)) {
my @a = split(':', substr($_, 4));
if ($a[$idxSource] eq $Source && $a[$idxFrequency] < $MaxFrequency) {
push(@channels, [@a]);
}
}
return @channels;
open(CHANNELS, $Conf) || Error("$Conf: $!");
while (<CHANNELS>) {
chomp;
next if (/^#/);
my @a = split(":");
push(@Channels, [@a]) unless ($a[$idxName] eq "x");
}
close(CHANNELS);
}
GetChannels();
sub GetPage
{
my $channel = shift;
my $day = shift;
my $url = "$SkyWebPage?c=$channel&day=day$day";
$day--;
my $url = "$SkyWebPage/$day/$channel.xml";
Log("reading $url");
my @page = split("\n", `$WGET '$url'`);
Log("received " . ($#page + 1) . " lines");
return @page;
}
sub StripWhitespace
{
my $s = shift;
$s =~ s/\s*(.*)\s*/$1/;
$s =~ s/\s+/ /g;
return $s;
}
sub Extract
{
my $s = shift;
my $t = shift;
$s =~ /<$t>([^<]*)<\/$t>/;
return StripWhitespace($1);
}
# In order to get the duration we need to buffer the last event:
$Id = "";
$Time = 0;
$Title = "";
$Episode = "";
$Descr = "";
$Subtitle = "";
$Desc = "";
sub GetEpgData
{
@@ -94,40 +114,64 @@ sub GetEpgData
$Time = 0;
for $day (1 .. $Days) {
my $dt = 0;
my $ap = "";
my @page = GetPage($channel, $day);
my $data = "";
for $line (@page) {
if ($line =~ /^<\/tr><tr /) {
# extract information:
my ($time, $title, $episode, $descr) = ($line =~ /^.*?<b>(.*?)<\/b>.*?<b>(.*?)<\/b> *(<i>.*?<\/i>)? *(.*?) *<\/small>/);
my ($h, $m, $a) = ($time =~ /([0-9]+)\.([0-9]+)(.)m/);
# handle am/pm:
$dt = $SecsInDay if ($ap eq "p" && $a eq "a");
$ap = $a;
$h += 12 if ($a eq "p" && $h < 12);
$h -= 12 if ($a eq "a" && $h == 12);
chomp($line);
if ($line =~ /<programme>/) {
$data = "";
}
elsif ($line =~ /<\/programme>/) {
my $title = Extract($data, "title");
my $subtitle = Extract($data, "subtitle");
my $desc = Extract($data, "desc");
my $start = Extract($data, "start");
# 'end' is useless, because it is sometimes missing :-(
# my $end = Extract($data, "end");
if (!$subtitle) {
# They sometimes write all info into the description, as in
# Episode: some description.
# Why don't they just fill in the data correctly?
my ($s, $d) = ($desc =~ /([^:]*)[:](.*)/);
if ($s && $d) {
$subtitle = $s;
$desc = $d;
}
}
# 'start' and 'end' as time of day isn't of much use here, since
# the page for one day contains data that actually belongs to the
# next day (after midnight). Oh well, lets reconstruct the missing
# information:
$start = "0" . $start if (length($start) < 4);
my ($h, $m) = ($start =~ /(..)(..)/);
$dt = $SecsInDay if ($h > 12);
# convert to time_t:
my @gmt = gmtime;
$gmt[0] = 0; # seconds
$gmt[1] = $m; # minutes
$gmt[2] = $h; # hours
$time = timegm(@gmt) + ($day - 1) * $SecsInDay + $dt + $DST;
$time = timegm(@gmt) + ($day - 1) * $SecsInDay + ($h < 12 ? $dt : 0);
# comensate for DST:
$time += $DST if (localtime($time))[8];
# create EPG data:
if ($Time) {
$duration = $time - $Time;
SVDRPsend("E $Id $Time $duration");
SVDRPsend("T $Title");
SVDRPsend("S $Episode");
SVDRPsend("D $Descr");
SVDRPsend("S $Subtitle");
SVDRPsend("D $Desc");
SVDRPsend("e");
$numEvents++;
}
# buffer the last event:
$Id = $time / 60 % 0xFFFF; # this gives us unique ids for every minute of over 6 weeks
$Time = $time;
($Title = $title) =~ s/<[^>]+>//g;
($Episode = $episode) =~ s/<[^>]+>//g;
($Descr = $descr) =~ s/<[^>]+>//g;
$Title = $title;
$Subtitle = $subtitle;
$Desc = $desc;
}
else {
$data .= $line;
}
}
}
@@ -137,14 +181,10 @@ sub GetEpgData
sub ProcessEpg
{
Log("getting Sky channel definitions");
my @channels = GetChannels();
Error("no Sky channels found") unless @channels;
Log("found " . ($#channels + 1) . " channels");
for (@channels) {
my $channel = @$_[$idxSid];
my $channelID = "@$_[$idxSource]-0-@$_[$idxFrequency]-$channel";
Log("processing channel @$_[0]");
for (@Channels) {
my $channel = @$_[$idxName];
my $channelID = @$_[$idxSource];
Log("processing channel $channel - $channelID");
SVDRPsend("PUTE");
SVDRPreceive(354);
GetEpgData($channel, $channelID);

View File

@@ -3,7 +3,7 @@
*
* See the README file for copyright information and how to reach the author.
*
* $Id: sky.c 1.4 2004/01/04 15:29:15 kls Exp $
* $Id: sky.c 1.6 2004/02/15 14:59:46 kls Exp $
*/
#include <sys/socket.h>
@@ -14,16 +14,53 @@
#include <vdr/plugin.h>
#include <vdr/sources.h>
static const char *VERSION = "0.2.0";
static const char *VERSION = "0.3.0";
static const char *DESCRIPTION = "Sky Digibox interface";
// --- cDigiboxDevice --------------------------------------------------------
#define DUMMYAPID 80
#define DUMMYVPID 160
class cSkyChannel : public cListObject {
public:
tChannelID channelID;
int digiboxChannelNumber;
bool Parse(const char *s);
};
bool cSkyChannel::Parse(const char *s)
{
char *id = NULL;
if (2 == sscanf(s, "%a[^:]:%d", &id, &digiboxChannelNumber))
channelID = tChannelID::FromString(id);
free(id);
return digiboxChannelNumber && channelID.Valid();
}
class cSkyChannels : public cConfig<cSkyChannel> {
public:
cSkyChannel *GetSkyChannel(const cChannel *Channel);
};
cSkyChannel *cSkyChannels::GetSkyChannel(const cChannel *Channel)
{
tChannelID ChannelID = Channel->GetChannelID();
for (cSkyChannel *sc = First(); sc; sc = Next(sc)) {
if (ChannelID == sc->channelID)
return sc;
}
return NULL;
}
cSkyChannels SkyChannels;
class cDigiboxDevice : public cDevice {
private:
int source;
int digiboxChannelNumber;
int fd_dvr;
int apid, vpid;
cTSBuffer *tsBuffer;
int fd_lirc;
void LircSend(const char *s);
@@ -47,6 +84,7 @@ cDigiboxDevice::cDigiboxDevice(void)
source = cSource::FromString("S28.2E");//XXX parameter???
digiboxChannelNumber = 0;
fd_dvr = -1;
apid = vpid = 0;
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strn0cpy(addr.sun_path, "/dev/lircd", sizeof(addr.sun_path));//XXX parameter???
@@ -93,7 +131,7 @@ void cDigiboxDevice::LircSend(int n)
bool cDigiboxDevice::SetPid(cPidHandle *Handle, int Type, bool On)
{
dsyslog("SetPid %d %d", Handle->pid, On);
//dsyslog("SetPid %d %d", Handle->pid, On);
return true;
}
@@ -122,6 +160,16 @@ bool cDigiboxDevice::GetTSPacket(uchar *&Data)
int r = tsBuffer->Read();
if (r >= 0) {
Data = tsBuffer->Get();
if (Data) {
// insert the actual PIDs:
int Pid = (((uint16_t)Data[1] & PID_MASK_HI) << 8) | Data[2];
if (Pid == DUMMYAPID)
Pid = apid;
else if (Pid == DUMMYVPID)
Pid = vpid;
Data[1] = ((Pid >> 8) & 0xFF) | (Data[1] & ~PID_MASK_HI);
Data[2] = Pid & 0xFF;
}
return true;
}
else if (FATALERRNO) {
@@ -149,9 +197,10 @@ bool cDigiboxDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool
bool hasPriority = Priority < 0 || Priority > this->Priority();
bool needsDetachReceivers = true;
if (ProvidesSource(Channel->Source()) && Channel->Ca() == 0x30) {//XXX
if (Receiving()) {
if (digiboxChannelNumber == Channel->Frequency()) {
cSkyChannel *SkyChannel = SkyChannels.GetSkyChannel(Channel);
if (SkyChannel) {
if (Receiving(true)) {
if (digiboxChannelNumber == SkyChannel->digiboxChannelNumber) {
needsDetachReceivers = false;
result = true;
}
@@ -168,16 +217,21 @@ bool cDigiboxDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool
bool cDigiboxDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
{
if (fd_lirc >= 0 && !Receiving()) { // if we are receiving the channel is already set!
digiboxChannelNumber = Channel->Frequency();
//XXX only when recording??? -> faster channel switching!
LircSend("SKY"); // makes sure the Digibox is "on"
//XXX lircprint(fd_lirc, "BACKUP");
//XXX lircprint(fd_lirc, "BACKUP");
//XXX lircprint(fd_lirc, "BACKUP");
LircSend(digiboxChannelNumber);
if (fd_lirc >= 0 && !Receiving(true)) { // if we are receiving the channel is already set!
cSkyChannel *SkyChannel = SkyChannels.GetSkyChannel(Channel);
if (SkyChannel) {
digiboxChannelNumber = SkyChannel->digiboxChannelNumber;
apid = Channel->Apid1();
vpid = Channel->Vpid();
//XXX only when recording??? -> faster channel switching!
LircSend("SKY"); // makes sure the Digibox is "on"
//XXX lircprint(fd_lirc, "BACKUP");
//XXX lircprint(fd_lirc, "BACKUP");
//XXX lircprint(fd_lirc, "BACKUP");
LircSend(digiboxChannelNumber);
}
}
return true;
return true;
}
// --- cPluginSky ------------------------------------------------------------
@@ -225,8 +279,16 @@ bool cPluginSky::ProcessArgs(int argc, char *argv[])
bool cPluginSky::Initialize(void)
{
// Initialize any background activities the plugin shall perform.
new cDigiboxDevice;
return true;
const char *ConfigDir = ConfigDirectory(Name());
if (ConfigDir) {
if (SkyChannels.Load(AddDirectory(ConfigDir, "channels.conf.sky"), true)) {
new cDigiboxDevice;
return true;
}
}
else
esyslog("ERROR: can't get config directory");
return false;
}
void cPluginSky::Housekeeping(void)