vdr  2.0.2
sdt.c
Go to the documentation of this file.
1 /*
2  * sdt.c: SDT section filter
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: sdt.c 2.5 2010/05/16 14:23:21 kls Exp $
8  */
9 
10 #include "sdt.h"
11 #include "channels.h"
12 #include "config.h"
13 #include "libsi/section.h"
14 #include "libsi/descriptor.h"
15 
16 // --- cSdtFilter ------------------------------------------------------------
17 
19 {
20  patFilter = PatFilter;
21  Set(0x11, 0x42); // SDT
22 }
23 
24 void cSdtFilter::SetStatus(bool On)
25 {
28 }
29 
30 void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
31 {
32  if (!(Source() && Transponder()))
33  return;
34  SI::SDT sdt(Data, false);
35  if (!sdt.CheckCRCAndParse())
36  return;
38  return;
39  if (!Channels.Lock(true, 10))
40  return;
41  SI::SDT::Service SiSdtService;
42  for (SI::Loop::Iterator it; sdt.serviceLoop.getNext(SiSdtService, it); ) {
44  if (!channel)
45  channel = Channels.GetByChannelID(tChannelID(Source(), 0, Transponder(), SiSdtService.getServiceId()));
46 
47  cLinkChannels *LinkChannels = NULL;
48  SI::Descriptor *d;
49  for (SI::Loop::Iterator it2; (d = SiSdtService.serviceDescriptors.getNext(it2)); ) {
50  switch (d->getDescriptorTag()) {
53  switch (sd->getServiceType()) {
54  case 0x01: // digital television service
55  case 0x02: // digital radio sound service
56  case 0x04: // NVOD reference service
57  case 0x05: // NVOD time-shifted service
58  case 0x16: // digital SD television service
59  case 0x19: // digital HD television service
60  {
61  char NameBuf[Utf8BufSize(1024)];
62  char ShortNameBuf[Utf8BufSize(1024)];
63  char ProviderNameBuf[Utf8BufSize(1024)];
64  sd->serviceName.getText(NameBuf, ShortNameBuf, sizeof(NameBuf), sizeof(ShortNameBuf));
65  char *pn = compactspace(NameBuf);
66  char *ps = compactspace(ShortNameBuf);
67  if (!*ps && cSource::IsCable(Source())) {
68  // Some cable providers don't mark short channel names according to the
69  // standard, but rather go their own way and use "name>short name":
70  char *p = strchr(pn, '>'); // fix for UPC Wien
71  if (p && p > pn) {
72  *p++ = 0;
73  strcpy(ShortNameBuf, skipspace(p));
74  }
75  }
76  // Avoid ',' in short name (would cause trouble in channels.conf):
77  for (char *p = ShortNameBuf; *p; p++) {
78  if (*p == ',')
79  *p = '.';
80  }
81  sd->providerName.getText(ProviderNameBuf, sizeof(ProviderNameBuf));
82  char *pp = compactspace(ProviderNameBuf);
83  if (channel) {
84  channel->SetId(sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
85  if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3)
86  channel->SetName(pn, ps, pp);
87  // Using SiSdtService.getFreeCaMode() is no good, because some
88  // tv stations set this flag even for non-encrypted channels :-(
89  // The special value 0xFFFF was supposed to mean "unknown encryption"
90  // and would have been overwritten with real CA values later:
91  // channel->SetCa(SiSdtService.getFreeCaMode() ? 0xFFFF : 0);
92  }
93  else if (*pn && Setup.UpdateChannels >= 4) {
94  channel = Channels.NewChannel(Channel(), pn, ps, pp, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
95  patFilter->Trigger();
96  }
97  }
98  default: ;
99  }
100  }
101  break;
102  // Using the CaIdentifierDescriptor is no good, because some tv stations
103  // just don't use it. The actual CA values are collected in pat.c:
104  /*
105  case SI::CaIdentifierDescriptorTag: {
106  SI::CaIdentifierDescriptor *cid = (SI::CaIdentifierDescriptor *)d;
107  if (channel) {
108  for (SI::Loop::Iterator it; cid->identifiers.hasNext(it); )
109  channel->SetCa(cid->identifiers.getNext(it));
110  }
111  }
112  break;
113  */
117  for (SI::Loop::Iterator it; nrd->serviceLoop.getNext(Service, it); ) {
119  if (!link && Setup.UpdateChannels >= 4) {
120  link = Channels.NewChannel(Channel(), "NVOD", "", "", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId());
121  patFilter->Trigger();
122  }
123  if (link) {
124  if (!LinkChannels)
125  LinkChannels = new cLinkChannels;
126  LinkChannels->Add(new cLinkChannel(link));
127  }
128  }
129  }
130  break;
131  default: ;
132  }
133  delete d;
134  }
135  if (LinkChannels) {
136  if (channel)
137  channel->SetLinkChannels(LinkChannels);
138  else
139  delete LinkChannels;
140  }
141  }
142  Channels.Unlock();
143 }
144