2004-01-04 12:30:00 +01:00
|
|
|
/*
|
|
|
|
* sdt.c: SDT section filter
|
|
|
|
*
|
|
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
|
|
* how to reach the author.
|
|
|
|
*
|
2014-01-05 10:41:46 +01:00
|
|
|
* $Id: sdt.c 3.1 2014/01/04 15:02:31 kls Exp $
|
2004-01-04 12:30:00 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "sdt.h"
|
|
|
|
#include "channels.h"
|
2004-01-05 12:08:09 +01:00
|
|
|
#include "config.h"
|
2004-01-04 12:30:00 +01:00
|
|
|
#include "libsi/section.h"
|
|
|
|
#include "libsi/descriptor.h"
|
|
|
|
|
2004-01-05 14:30:31 +01:00
|
|
|
// --- cSdtFilter ------------------------------------------------------------
|
2004-01-04 12:30:00 +01:00
|
|
|
|
2004-01-05 14:30:31 +01:00
|
|
|
cSdtFilter::cSdtFilter(cPatFilter *PatFilter)
|
|
|
|
{
|
|
|
|
patFilter = PatFilter;
|
|
|
|
Set(0x11, 0x42); // SDT
|
|
|
|
}
|
2004-01-04 12:30:00 +01:00
|
|
|
|
2004-01-05 14:30:31 +01:00
|
|
|
void cSdtFilter::SetStatus(bool On)
|
2004-01-04 12:30:00 +01:00
|
|
|
{
|
2004-01-05 14:30:31 +01:00
|
|
|
cFilter::SetStatus(On);
|
|
|
|
sectionSyncer.Reset();
|
|
|
|
}
|
2004-01-04 12:30:00 +01:00
|
|
|
|
2004-01-05 14:30:31 +01:00
|
|
|
void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
|
|
|
|
{
|
|
|
|
if (!(Source() && Transponder()))
|
|
|
|
return;
|
|
|
|
SI::SDT sdt(Data, false);
|
|
|
|
if (!sdt.CheckCRCAndParse())
|
|
|
|
return;
|
|
|
|
if (!sectionSyncer.Sync(sdt.getVersionNumber(), sdt.getSectionNumber(), sdt.getLastSectionNumber()))
|
2004-01-04 12:30:00 +01:00
|
|
|
return;
|
|
|
|
if (!Channels.Lock(true, 10))
|
|
|
|
return;
|
|
|
|
SI::SDT::Service SiSdtService;
|
2004-10-16 10:14:19 +02:00
|
|
|
for (SI::Loop::Iterator it; sdt.serviceLoop.getNext(SiSdtService, it); ) {
|
2004-01-11 15:54:37 +01:00
|
|
|
cChannel *channel = Channels.GetByChannelID(tChannelID(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId()));
|
|
|
|
if (!channel)
|
|
|
|
channel = Channels.GetByChannelID(tChannelID(Source(), 0, Transponder(), SiSdtService.getServiceId()));
|
2014-01-05 10:41:46 +01:00
|
|
|
if (channel)
|
|
|
|
channel->SetSeen();
|
2004-01-04 12:30:00 +01:00
|
|
|
|
2004-07-18 11:02:50 +02:00
|
|
|
cLinkChannels *LinkChannels = NULL;
|
2004-01-04 12:30:00 +01:00
|
|
|
SI::Descriptor *d;
|
|
|
|
for (SI::Loop::Iterator it2; (d = SiSdtService.serviceDescriptors.getNext(it2)); ) {
|
|
|
|
switch (d->getDescriptorTag()) {
|
|
|
|
case SI::ServiceDescriptorTag: {
|
|
|
|
SI::ServiceDescriptor *sd = (SI::ServiceDescriptor *)d;
|
|
|
|
switch (sd->getServiceType()) {
|
|
|
|
case 0x01: // digital television service
|
2004-01-16 15:09:22 +01:00
|
|
|
case 0x02: // digital radio sound service
|
2004-07-18 11:02:50 +02:00
|
|
|
case 0x04: // NVOD reference service
|
|
|
|
case 0x05: // NVOD time-shifted service
|
2010-05-16 14:25:58 +02:00
|
|
|
case 0x16: // digital SD television service
|
2008-04-12 13:39:12 +02:00
|
|
|
case 0x19: // digital HD television service
|
2004-01-04 12:30:00 +01:00
|
|
|
{
|
2007-06-10 13:02:43 +02:00
|
|
|
char NameBuf[Utf8BufSize(1024)];
|
|
|
|
char ShortNameBuf[Utf8BufSize(1024)];
|
|
|
|
char ProviderNameBuf[Utf8BufSize(1024)];
|
2004-06-06 14:53:21 +02:00
|
|
|
sd->serviceName.getText(NameBuf, ShortNameBuf, sizeof(NameBuf), sizeof(ShortNameBuf));
|
2004-03-07 11:13:54 +01:00
|
|
|
char *pn = compactspace(NameBuf);
|
|
|
|
char *ps = compactspace(ShortNameBuf);
|
2005-05-14 09:47:06 +02:00
|
|
|
if (!*ps && cSource::IsCable(Source())) {
|
|
|
|
// Some cable providers don't mark short channel names according to the
|
2009-12-13 11:57:44 +01:00
|
|
|
// standard, but rather go their own way and use "name>short name":
|
2005-08-27 09:29:30 +02:00
|
|
|
char *p = strchr(pn, '>'); // fix for UPC Wien
|
2005-05-14 09:47:06 +02:00
|
|
|
if (p && p > pn) {
|
|
|
|
*p++ = 0;
|
2005-08-27 09:29:30 +02:00
|
|
|
strcpy(ShortNameBuf, skipspace(p));
|
2005-05-14 09:47:06 +02:00
|
|
|
}
|
|
|
|
}
|
2009-12-24 10:49:16 +01:00
|
|
|
// Avoid ',' in short name (would cause trouble in channels.conf):
|
|
|
|
for (char *p = ShortNameBuf; *p; p++) {
|
|
|
|
if (*p == ',')
|
|
|
|
*p = '.';
|
|
|
|
}
|
2004-10-31 12:53:00 +01:00
|
|
|
sd->providerName.getText(ProviderNameBuf, sizeof(ProviderNameBuf));
|
|
|
|
char *pp = compactspace(ProviderNameBuf);
|
2004-01-11 15:54:37 +01:00
|
|
|
if (channel) {
|
|
|
|
channel->SetId(sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
|
2006-04-15 14:18:25 +02:00
|
|
|
if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3)
|
2004-10-31 12:53:00 +01:00
|
|
|
channel->SetName(pn, ps, pp);
|
2004-01-04 12:30:00 +01:00
|
|
|
// Using SiSdtService.getFreeCaMode() is no good, because some
|
|
|
|
// tv stations set this flag even for non-encrypted channels :-(
|
|
|
|
// The special value 0xFFFF was supposed to mean "unknown encryption"
|
|
|
|
// and would have been overwritten with real CA values later:
|
2004-01-11 15:54:37 +01:00
|
|
|
// channel->SetCa(SiSdtService.getFreeCaMode() ? 0xFFFF : 0);
|
2004-01-04 12:30:00 +01:00
|
|
|
}
|
2006-04-15 14:18:25 +02:00
|
|
|
else if (*pn && Setup.UpdateChannels >= 4) {
|
2004-10-31 12:53:00 +01:00
|
|
|
channel = Channels.NewChannel(Channel(), pn, ps, pp, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
|
2004-01-05 14:30:31 +01:00
|
|
|
patFilter->Trigger();
|
2004-01-04 12:30:00 +01:00
|
|
|
}
|
|
|
|
}
|
2009-12-06 12:57:45 +01:00
|
|
|
default: ;
|
2004-01-04 12:30:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
// Using the CaIdentifierDescriptor is no good, because some tv stations
|
|
|
|
// just don't use it. The actual CA values are collected in pat.c:
|
|
|
|
/*
|
|
|
|
case SI::CaIdentifierDescriptorTag: {
|
|
|
|
SI::CaIdentifierDescriptor *cid = (SI::CaIdentifierDescriptor *)d;
|
2004-01-11 15:54:37 +01:00
|
|
|
if (channel) {
|
2004-01-04 12:30:00 +01:00
|
|
|
for (SI::Loop::Iterator it; cid->identifiers.hasNext(it); )
|
2004-01-11 15:54:37 +01:00
|
|
|
channel->SetCa(cid->identifiers.getNext(it));
|
2004-01-04 12:30:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
*/
|
|
|
|
case SI::NVODReferenceDescriptorTag: {
|
|
|
|
SI::NVODReferenceDescriptor *nrd = (SI::NVODReferenceDescriptor *)d;
|
2004-10-16 10:14:19 +02:00
|
|
|
SI::NVODReferenceDescriptor::Service Service;
|
|
|
|
for (SI::Loop::Iterator it; nrd->serviceLoop.getNext(Service, it); ) {
|
2004-07-18 11:02:50 +02:00
|
|
|
cChannel *link = Channels.GetByChannelID(tChannelID(Source(), Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId()));
|
2006-04-15 14:18:25 +02:00
|
|
|
if (!link && Setup.UpdateChannels >= 4) {
|
2004-10-31 12:53:00 +01:00
|
|
|
link = Channels.NewChannel(Channel(), "NVOD", "", "", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId());
|
2004-07-18 11:02:50 +02:00
|
|
|
patFilter->Trigger();
|
|
|
|
}
|
|
|
|
if (link) {
|
|
|
|
if (!LinkChannels)
|
|
|
|
LinkChannels = new cLinkChannels;
|
|
|
|
LinkChannels->Add(new cLinkChannel(link));
|
|
|
|
}
|
2004-01-04 12:30:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default: ;
|
|
|
|
}
|
|
|
|
delete d;
|
|
|
|
}
|
2004-07-18 11:02:50 +02:00
|
|
|
if (LinkChannels) {
|
|
|
|
if (channel)
|
|
|
|
channel->SetLinkChannels(LinkChannels);
|
|
|
|
else
|
|
|
|
delete LinkChannels;
|
|
|
|
}
|
2004-01-04 12:30:00 +01:00
|
|
|
}
|
2014-01-05 10:41:46 +01:00
|
|
|
if (sdt.getSectionNumber() == sdt.getLastSectionNumber())
|
|
|
|
Channels.MarkObsoleteChannels(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId());
|
2004-01-04 12:30:00 +01:00
|
|
|
Channels.Unlock();
|
|
|
|
}
|