diff options
| -rw-r--r-- | HISTORY | 6 | ||||
| -rw-r--r-- | README.developer | 4 | ||||
| -rw-r--r-- | channels.c | 83 | ||||
| -rw-r--r-- | channels.h | 22 | ||||
| -rw-r--r-- | eit.c | 36 | 
5 files changed, 141 insertions, 10 deletions
| @@ -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. @@ -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); @@ -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<cLinkChannel> { +  }; +  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<cChannel> { @@ -8,7 +8,7 @@   * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.   * Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.   * - * $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);        }  } | 
