summaryrefslogtreecommitdiff
path: root/sdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'sdt.c')
-rw-r--r--sdt.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/sdt.c b/sdt.c
new file mode 100644
index 00000000..a4e91b80
--- /dev/null
+++ b/sdt.c
@@ -0,0 +1,146 @@
+/*
+ * sdt.c: SDT section filter
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id: sdt.c 1.1 2004/01/04 11:54:42 kls Exp $
+ */
+
+#include "sdt.h"
+#include "channels.h"
+#include "libsi/section.h"
+#include "libsi/descriptor.h"
+
+// --- cSDT ------------------------------------------------------------------
+
+class cSDT : public SI::SDT {
+public:
+ cSDT(int Source, int Transponder, uchar &lastSdtVersion, cPatFilter *PatFilter, const u_char *Data);
+ };
+
+cSDT::cSDT(int Source, int Transponder, uchar &lastSdtVersion, cPatFilter *PatFilter, const u_char *Data)
+:SI::SDT(Data, false)
+{
+ if (!CheckCRCAndParse())
+ return;
+
+ if (getVersionNumber() == lastSdtVersion)
+ return;
+
+ if (!Channels.Lock(true, 10))
+ return;
+
+ lastSdtVersion = getVersionNumber();
+
+ SI::SDT::Service SiSdtService;
+ for (SI::Loop::Iterator it; serviceLoop.hasNext(it); ) {
+ SiSdtService = serviceLoop.getNext(it);
+
+ cChannel *Channel = Channels.GetByChannelID(tChannelID(Source, getOriginalNetworkId(), getTransportStreamId(), SiSdtService.getServiceId()));
+ if (!Channel)
+ Channel = Channels.GetByChannelID(tChannelID(Source, 0, Transponder, SiSdtService.getServiceId()));
+
+ 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
+ //XXX TODO case 0x02: // digital radio sound service
+ //XXX TODO case 0x04: // NVOD reference service
+ //XXX TODO case 0x05: // NVOD time-shifted service
+ {
+ char buffer[1024];
+ char *p = sd->serviceName.getText(buffer);
+ char NameBuf[1024];
+ char ShortNameBuf[1024];
+ char *pn = NameBuf;
+ char *ps = ShortNameBuf;
+ int IsShortName = 0;
+ while (*p) {
+ if ((uchar)*p == 0x86)
+ IsShortName++;
+ else if ((uchar)*p == 0x87)
+ IsShortName--;
+ else {
+ *pn++ = *p;
+ if (IsShortName)
+ *ps++ = *p;
+ }
+ p++;
+ }
+ *pn = *ps = 0;
+ pn = NameBuf;
+ if (*NameBuf && *ShortNameBuf) {
+ *ps++ = ',';
+ strcpy(ps, NameBuf);
+ pn = ShortNameBuf;
+ }
+ if (Channel) {
+ Channel->SetId(getOriginalNetworkId(), getTransportStreamId(), SiSdtService.getServiceId());
+ Channel->SetName(pn);
+ // 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:
+ // Channel->SetCa(SiSdtService.getFreeCaMode() ? 0xFFFF : 0);
+ }
+ else if (*pn) {
+ Channel = Channels.NewChannel(Source, Transponder, pn, getOriginalNetworkId(), getTransportStreamId(), SiSdtService.getServiceId());
+ PatFilter->Trigger();
+ }
+ }
+ }
+ }
+ 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;
+ if (Channel) {
+ for (SI::Loop::Iterator it; cid->identifiers.hasNext(it); )
+ Channel->SetCa(cid->identifiers.getNext(it));
+ }
+ }
+ break;
+ */
+ case SI::NVODReferenceDescriptorTag: {
+ SI::NVODReferenceDescriptor *nrd = (SI::NVODReferenceDescriptor *)d;
+ for (SI::Loop::Iterator it; nrd->serviceLoop.hasNext(it); ) {
+ SI::NVODReferenceDescriptor::Service Service = nrd->serviceLoop.getNext(it);
+ //printf(" %04X-%04X-%04X\n", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId());//XXX TODO
+ }
+ }
+ break;
+ default: ;
+ }
+ delete d;
+ }
+ }
+ Channels.Unlock();
+}
+
+
+// --- cSdtFilter ------------------------------------------------------------
+
+cSdtFilter::cSdtFilter(cPatFilter *PatFilter)
+{
+ lastSdtVersion = 0xFF;
+ patFilter = PatFilter;
+ Set(0x11, 0x42); // SDT
+}
+
+void cSdtFilter::SetStatus(bool On)
+{
+ cFilter::SetStatus(On);
+ lastSdtVersion = 0xFF;
+}
+
+void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
+{
+ if (Source() && Transponder())
+ cSDT SDT(Source(), Transponder(), lastSdtVersion, patFilter, Data);
+}