From da3c91f01bab52add46a3de24d20b760dfaf9708 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 8 Feb 2004 11:05:22 +0100 Subject: [PATCH] Now handling "linked services" --- HISTORY | 6 +++- README.developer | 4 +-- channels.c | 83 +++++++++++++++++++++++++++++++++++++++++++++--- channels.h | 22 +++++++++++-- eit.c | 36 ++++++++++++++++++++- 5 files changed, 141 insertions(+), 10 deletions(-) diff --git a/HISTORY b/HISTORY index d6a8284a..dde28ea6 100644 --- a/HISTORY +++ b/HISTORY @@ -2627,10 +2627,14 @@ Video Disk Recorder Revision History - Added a call to cStatus::MsgOsdCurrentItem() to cMenuEditItem::SetValue() (thanks to Martin Hammerschmid). -2004-01-31: Version 1.3.4 +2004-02-08: Version 1.3.4 - Fixed handling language codes in case there is no audio or Dolby PID. - Fixed handling CA ids (was broken in 1.3.4). - Fixed the SVDRP command 'STAT DISK' to avoid a 'division by 0' in case the disk is full (thanks to Jens Rosenboom). - Fixed handling bitmap indexes for 256 color mode (thanks to Andreas Regel). +- Now handling "linked services" (based on the 'autopid' patch from Andreas + Schultz). Linked channels are detected and added to 'channels.conf', but + currently they are not yet presented to the user other than being in the + normal channel list (this will come later). diff --git a/README.developer b/README.developer index d079d637..4fe75c81 100644 --- a/README.developer +++ b/README.developer @@ -30,7 +30,7 @@ Here's a list of the highlights - and what _not_ to expect yet to have them start at some high number. - Improved CAM support. Channels with conditional access now automatically use the device that contains the proper CAM. -- No NVOD or "linked services" support yet. +- No NVOD support yet. Note that this is currently work in progress, so there may be some areas that don't work as smooth as expected, yet. @@ -47,7 +47,7 @@ Known issues: EURO1080:12168:v:S19.2E:27500:308:256:0:FF:21100:1:1088:0 - in your 'channels.conf' file. Note the Ca parameter 'F' (255 in hex), + in your 'channels.conf' file. Note the Ca parameter 'FF' (255 in hex), which gives this channel a non-existent Ca mode, so that it won't be tuned to at all. If you really want to tune to this channel for tests, do it on your own risk. diff --git a/channels.c b/channels.c index 4b3930d4..b5bd9bd4 100644 --- a/channels.c +++ b/channels.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: channels.c 1.22 2004/01/26 16:28:35 kls Exp $ + * $Id: channels.c 1.23 2004/02/08 11:05:22 kls Exp $ */ #include "channels.h" @@ -169,11 +169,13 @@ cChannel::cChannel(void) guard = GUARD_INTERVAL_AUTO; hierarchy = HIERARCHY_AUTO; modification = CHANNELMOD_NONE; + linkChannels = NULL; + refChannel = NULL; } -cChannel::cChannel(const cChannel *Channel) +cChannel::cChannel(const cChannel &Channel) { - *this = *Channel; + *this = Channel; *name = 0; vpid = 0; ppid = 0; @@ -188,6 +190,28 @@ cChannel::cChannel(const cChannel *Channel) number = 0; groupSep = false; modification = CHANNELMOD_NONE; + linkChannels = NULL; + refChannel = NULL; +} + +cChannel::~cChannel() +{ + delete linkChannels; + linkChannels = NULL; // more than one channel can link to this one, so we need the following loop + for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) { + if (Channel->linkChannels) { + for (cLinkChannel *lc = Channel->linkChannels->First(); lc; lc = Channel->linkChannels->Next(lc)) { + if (lc->Channel() == this) { + Channel->linkChannels->Del(lc); + break; + } + } + if (Channel->linkChannels->Count() == 0) { + delete Channel->linkChannels; + Channel->linkChannels = NULL; + } + } + } } cChannel& cChannel::operator= (const cChannel &Channel) @@ -397,6 +421,57 @@ void cChannel::SetCaDescriptors(int Level) } } +void cChannel::SetLinkChannels(cLinkChannels *LinkChannels) +{ + if (!linkChannels && !LinkChannels) + return; + if (linkChannels && LinkChannels) { + cLinkChannel *lca = linkChannels->First(); + cLinkChannel *lcb = LinkChannels->First(); + while (lca && lcb) { + if (lca->Channel() != lcb->Channel()) { + lca = NULL; + break; + } + lca = linkChannels->Next(lca); + lcb = LinkChannels->Next(lcb); + } + if (!lca && !lcb) { + delete LinkChannels; + return; // linkage has not changed + } + } + char buffer[((linkChannels ? linkChannels->Count() : 0) + (LinkChannels ? LinkChannels->Count() : 0)) * 6 + 256]; // 6: 5 digit channel number plus blank, 256: other texts (see below) plus reserve + char *q = buffer; + q += sprintf(q, "linking channel %d from", Number()); + if (linkChannels) { + for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) { + lc->Channel()->SetRefChannel(NULL); + q += sprintf(q, " %d", lc->Channel()->Number()); + } + delete linkChannels; + } + else + q += sprintf(q, " none"); + q += sprintf(q, " to"); + linkChannels = LinkChannels; + if (linkChannels) { + for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) { + lc->Channel()->SetRefChannel(this); + q += sprintf(q, " %d", lc->Channel()->Number()); + //dsyslog("link %4d -> %4d: %s", Number(), lc->Channel()->Number(), lc->Channel()->Name()); + } + } + else + q += sprintf(q, " none"); + dsyslog(buffer); +} + +void cChannel::SetRefChannel(cChannel *RefChannel) +{ + refChannel = RefChannel; +} + static int PrintParameter(char *p, char Name, int Value) { return Value >= 0 && Value != 999 ? sprintf(p, "%c%d", Name, Value) : 0; @@ -776,7 +851,7 @@ cChannel *cChannels::NewChannel(const cChannel *Transponder, const char *Name, i { if (Transponder) { dsyslog("creating new channel '%s' on %s transponder %d with id %d-%d-%d-%d", Name, cSource::ToString(Transponder->Source()), Transponder->Transponder(), Nid, Tid, Sid, Rid); - cChannel *NewChannel = new cChannel(Transponder); + cChannel *NewChannel = new cChannel(*Transponder); Add(NewChannel); ReNumber(); NewChannel->SetId(Nid, Tid, Sid, Rid, false); diff --git a/channels.h b/channels.h index 532a1121..fa55d951 100644 --- a/channels.h +++ b/channels.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: channels.h 1.13 2004/01/25 15:31:16 kls Exp $ + * $Id: channels.h 1.14 2004/02/07 22:04:26 kls Exp $ */ #ifndef __CHANNELS_H @@ -66,6 +66,19 @@ public: static const tChannelID InvalidID; }; +class cChannel; + +class cLinkChannel : public cListObject { +private: + cChannel *channel; +public: + cLinkChannel(cChannel *Channel) { channel = Channel; } + cChannel *Channel(void) { return channel; } + }; + +class cLinkChannels : public cList { + }; + class cChannel : public cListObject { friend class cMenuEditChannel; private: @@ -102,11 +115,14 @@ private: int hierarchy; int __EndData__; int modification; + cLinkChannels *linkChannels; + cChannel *refChannel; const char *ParametersToString(void); bool StringToParameters(const char *s); public: cChannel(void); - cChannel(const cChannel *Channel); + cChannel(const cChannel &Channel); + ~cChannel(); cChannel& operator= (const cChannel &Channel); const char *ToText(void); bool Parse(const char *s, bool AllowNonUniqueID = false); @@ -153,6 +169,8 @@ public: void SetPids(int Vpid, int Ppid, int *Apids, char ALangs[][4], int *Dpids, char DLangs[][4], int Tpid); void SetCaIds(const int *CaIds); // list must be zero-terminated void SetCaDescriptors(int Level); + void SetLinkChannels(cLinkChannels *LinkChannels); + void SetRefChannel(cChannel *RefChannel); }; class cChannels : public cRwLock, public cConfig { diff --git a/eit.c b/eit.c index d71cad82..c24a3d0a 100644 --- a/eit.c +++ b/eit.c @@ -8,7 +8,7 @@ * Robert Schneider and Rolf Hakenes . * Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg . * - * $Id: eit.c 1.85 2004/01/09 15:44:43 kls Exp $ + * $Id: eit.c 1.86 2004/02/08 10:26:54 kls Exp $ */ #include "eit.h" @@ -95,6 +95,7 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data) SI::Descriptor *d; SI::ExtendedEventDescriptors *ExtendedEventDescriptors = NULL; SI::ShortEventDescriptor *ShortEventDescriptor = NULL; + cLinkChannels *LinkChannels = NULL; for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext(it2)); ) { switch (d->getDescriptorTag()) { case SI::ExtendedEventDescriptorTag: { @@ -138,6 +139,36 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data) pEvent->SetDescription(rEvent->Description()); } break; + case SI::LinkageDescriptorTag: { + SI::LinkageDescriptor *ld = (SI::LinkageDescriptor *)d; + tChannelID linkID(Source, ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId()); + if (ld->getLinkageType() == 0xB0) { // Premiere World + time_t now = time(NULL); + bool hit = SiEitEvent.getStartTime() <= now && now < SiEitEvent.getStartTime() + SiEitEvent.getDuration(); + if (hit) { + cChannel *link = Channels.GetByChannelID(linkID); + if (link != channel) { // only link to other channels, not the same one + char linkName[ld->privateData.getLength() + 1]; + strn0cpy(linkName, (const char *)ld->privateData.getData(), sizeof(linkName)); + //fprintf(stderr, "Linkage %s %4d %4d %5d %5d %5d %5d %02X '%s'\n", hit ? "*" : "", channel->Number(), link ? link->Number() : -1, SiEitEvent.getEventId(), ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId(), ld->getLinkageType(), linkName);//XXX + if (link) { + if (Setup.UpdateChannels >= 1) + link->SetName(linkName); + } + else if (Setup.UpdateChannels >= 3) { + link = Channels.NewChannel(channel, linkName, ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId()); + //XXX patFilter->Trigger(); + } + if (link) { + if (!LinkChannels) + LinkChannels = new cLinkChannels; + LinkChannels->Add(new cLinkChannel(link)); + } + } + } + } + } + break; default: ; } delete d; @@ -167,6 +198,9 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data) else if (SiEitEvent.getRunningStatus() == SI::RunningStatusStartsInAFewSeconds) pSchedule->SetFollowingEvent(pEvent); } + + if (LinkChannels) + channel->SetLinkChannels(LinkChannels); } }