summaryrefslogtreecommitdiff
path: root/PLUGINS/src/sky
diff options
context:
space:
mode:
Diffstat (limited to 'PLUGINS/src/sky')
-rw-r--r--PLUGINS/src/sky/HISTORY8
-rw-r--r--PLUGINS/src/sky/README29
-rw-r--r--PLUGINS/src/sky/channels.conf.sky38
-rwxr-xr-xPLUGINS/src/sky/getskyepg.pl136
-rw-r--r--PLUGINS/src/sky/sky.c96
5 files changed, 221 insertions, 86 deletions
diff --git a/PLUGINS/src/sky/HISTORY b/PLUGINS/src/sky/HISTORY
index d3da71e..c1c5f98 100644
--- a/PLUGINS/src/sky/HISTORY
+++ b/PLUGINS/src/sky/HISTORY
@@ -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.
diff --git a/PLUGINS/src/sky/README b/PLUGINS/src/sky/README
index bd089cc..185a98b 100644
--- a/PLUGINS/src/sky/README
+++ b/PLUGINS/src/sky/README
@@ -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.
-
-The Sky EPG is available on the Internet at http://www.ananova.com.
+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
+
+/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.
diff --git a/PLUGINS/src/sky/channels.conf.sky b/PLUGINS/src/sky/channels.conf.sky
index f4a437b..ba262f8 100644
--- a/PLUGINS/src/sky/channels.conf.sky
+++ b/PLUGINS/src/sky/channels.conf.sky
@@ -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
diff --git a/PLUGINS/src/sky/getskyepg.pl b/PLUGINS/src/sky/getskyepg.pl
index 46c2d7f..77768ad 100755
--- a/PLUGINS/src/sky/getskyepg.pl
+++ b/PLUGINS/src/sky/getskyepg.pl
@@ -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);
diff --git a/PLUGINS/src/sky/sky.c b/PLUGINS/src/sky/sky.c
index 750d778..6196eef 100644
--- a/PLUGINS/src/sky/sky.c
+++ b/PLUGINS/src/sky/sky.c
@@ -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)