--- ./nit.c	2015/02/04 09:13:54	4.0
+++ ./nit.c	2015/03/16 15:22:47
@@ -19,19 +19,22 @@
 #define DVB_SYSTEM_1 0 // see also dvbdevice.c
 #define DVB_SYSTEM_2 1
 
+#define MAXNETWORKNAME Utf8BufSize(256)
+
+// Set to 'true' for debug output:
+static bool DebugNit = true;//XXX false;
+
+#define dbgnit(a...) if (DebugNit) fprintf(stderr, a)
+
 cNitFilter::cNitFilter(cSdtFilter *SdtFilter)
 {
   sdtFilter = SdtFilter;
-  numNits = 0;
-  networkId = 0;
-  Set(0x10, 0x40);  // NIT
+  Set(0x10, SI::TableIdNIT);
 }
 
 void cNitFilter::SetStatus(bool On)
 {
   cFilter::SetStatus(On);
-  numNits = 0;
-  networkId = 0;
   sectionSyncer.Reset();
 }
 
@@ -40,63 +43,28 @@
   SI::NIT nit(Data, false);
   if (!nit.CheckCRCAndParse())
      return;
-  // Some broadcasters send more than one NIT, with no apparent way of telling which
-  // one is the right one to use. This is an attempt to find the NIT that contains
-  // the transponder it was transmitted on and use only that one:
-  int ThisNIT = -1;
-  if (!networkId) {
-     for (int i = 0; i < numNits; i++) {
-         if (nits[i].networkId == nit.getNetworkId()) {
-            if (nit.getSectionNumber() == 0) {
-               // all NITs have passed by
-               for (int j = 0; j < numNits; j++) {
-                   if (nits[j].hasTransponder) {
-                      networkId = nits[j].networkId;
-                      //printf("taking NIT with network ID %d\n", networkId);
-                      //XXX what if more than one NIT contains this transponder???
-                      break;
-                      }
-                   }
-               if (!networkId) {
-                  //printf("none of the NITs contains transponder %d\n", Transponder());
-                  return;
-                  }
-               }
-            else {
-               ThisNIT = i;
-               break;
-               }
-            }
-         }
-     if (!networkId && ThisNIT < 0 && numNits < MAXNITS) {
-        if (nit.getSectionNumber() == 0) {
-           *nits[numNits].name = 0;
-           SI::Descriptor *d;
-           for (SI::Loop::Iterator it; (d = nit.commonDescriptors.getNext(it)); ) {
-               switch (d->getDescriptorTag()) {
-                 case SI::NetworkNameDescriptorTag: {
-                      SI::NetworkNameDescriptor *nnd = (SI::NetworkNameDescriptor *)d;
-                      nnd->name.getText(nits[numNits].name, MAXNETWORKNAME);
-                      }
-                      break;
-                 default: ;
-                 }
-               delete d;
-               }
-           nits[numNits].networkId = nit.getNetworkId();
-           nits[numNits].hasTransponder = false;
-           //printf("NIT[%d] %5d '%s'\n", numNits, nits[numNits].networkId, nits[numNits].name);
-           ThisNIT = numNits;
-           numNits++;
+  if (!sectionSyncer.Sync(nit.getVersionNumber(), nit.getSectionNumber(), nit.getLastSectionNumber()))
+     return;
+  if (DebugNit) {
+     char NetworkName[MAXNETWORKNAME] = "";
+     SI::Descriptor *d;
+     for (SI::Loop::Iterator it; (d = nit.commonDescriptors.getNext(it)); ) {
+         switch (d->getDescriptorTag()) {
+           case SI::NetworkNameDescriptorTag: {
+                SI::NetworkNameDescriptor *nnd = (SI::NetworkNameDescriptor *)d;
+                nnd->name.getText(NetworkName, MAXNETWORKNAME);
+                }
+                break;
+           default: ;
            }
-        }
+         delete d;
+         }
+     dbgnit("NIT: %02X %2d %2d %2d %s %d %d '%s'\n", Tid, nit.getVersionNumber(), nit.getSectionNumber(), nit.getLastSectionNumber(), *cSource::ToString(Source()), nit.getNetworkId(), Transponder(), NetworkName);
      }
-  else if (networkId != nit.getNetworkId())
-     return; // ignore all other NITs
-  else if (!sectionSyncer.Sync(nit.getVersionNumber(), nit.getSectionNumber(), nit.getLastSectionNumber()))
-     return;
-  if (!Channels.Lock(true, 10))
+  if (!Channels.Lock(true, 10)) {
+     sectionSyncer.Reset(); // let's not miss any section of the NIT
      return;
+     }
   SI::NIT::TransportStream ts;
   for (SI::Loop::Iterator it; nit.transportStreamLoop.getNext(ts, it); ) {
       SI::Descriptor *d;
@@ -118,6 +86,7 @@
                   default: ;
                   }
                 Frequencies[n++] = f;
+                dbgnit("    Frequencies[%d] = %d\n", n - 1, f);
                 }
             }
          else
@@ -142,16 +111,7 @@
                  static int RollOffs[] = { ROLLOFF_35, ROLLOFF_25, ROLLOFF_20, ROLLOFF_AUTO };
                  dtp.SetRollOff(sd->getModulationSystem() ? RollOffs[sd->getRollOff()] : ROLLOFF_AUTO);
                  int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
-                 if (ThisNIT >= 0) {
-                    for (int n = 0; n < NumFrequencies; n++) {
-                        if (ISTRANSPONDER(cChannel::Transponder(Frequencies[n], dtp.Polarization()), Transponder())) {
-                           nits[ThisNIT].hasTransponder = true;
-                           //printf("has transponder %d\n", Transponder());
-                           break;
-                           }
-                        }
-                    break;
-                    }
+                 dbgnit("    %s %d %c %d %d\n", *cSource::ToString(Source), Frequency, Polarizations[sd->getPolarization()], SymbolRate, cChannel::Transponder(Frequency, Polarizations[sd->getPolarization()]));
                  if (Setup.UpdateChannels >= 5) {
                     bool found = false;
                     bool forceTransponderUpdate = false;
@@ -184,7 +144,8 @@
                            }
                        }
                     }
-                 sdtFilter->Trigger(Source);
+                 if (ISTRANSPONDER(cChannel::Transponder(Frequency, dtp.Polarization()), Transponder()))
+                    sdtFilter->Trigger(Source);
                  }
                  break;
             case SI::S2SatelliteDeliverySystemDescriptorTag: {
@@ -213,16 +174,7 @@
                  static int Modulations[] = { QPSK, QAM_16, QAM_32, QAM_64, QAM_128, QAM_256, QAM_AUTO };
                  dtp.SetModulation(Modulations[min(sd->getModulation(), 6)]);
                  int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
-                 if (ThisNIT >= 0) {
-                    for (int n = 0; n < NumFrequencies; n++) {
-                        if (ISTRANSPONDER(Frequencies[n] / 1000, Transponder())) {
-                           nits[ThisNIT].hasTransponder = true;
-                           //printf("has transponder %d\n", Transponder());
-                           break;
-                           }
-                        }
-                    break;
-                    }
+                 dbgnit("    %s %d %d %d %d\n", *cSource::ToString(Source), Frequency, CodeRates[sd->getFecInner()], Modulations[min(sd->getModulation(), 6)], SymbolRate);
                  if (Setup.UpdateChannels >= 5) {
                     bool found = false;
                     bool forceTransponderUpdate = false;
@@ -255,7 +207,8 @@
                            }
                        }
                     }
-                 sdtFilter->Trigger(Source);
+                 if (ISTRANSPONDER(Frequency / 1000, Transponder()))
+                    sdtFilter->Trigger(Source);
                  }
                  break;
             case SI::TerrestrialDeliverySystemDescriptorTag: {
@@ -277,16 +230,7 @@
                  dtp.SetGuard(GuardIntervals[sd->getGuardInterval()]);
                  static int TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_4K, TRANSMISSION_MODE_AUTO };
                  dtp.SetTransmission(TransmissionModes[sd->getTransmissionMode()]);
-                 if (ThisNIT >= 0) {
-                    for (int n = 0; n < NumFrequencies; n++) {
-                        if (ISTRANSPONDER(Frequencies[n] / 1000000, Transponder())) {
-                           nits[ThisNIT].hasTransponder = true;
-                           //printf("has transponder %d\n", Transponder());
-                           break;
-                           }
-                        }
-                    break;
-                    }
+                 dbgnit("    %s %d %d %d %d %d %d %d %d\n", *cSource::ToString(Source), Frequency, Bandwidths[sd->getBandwidth()], Constellations[sd->getConstellation()], Hierarchies[sd->getHierarchy()], CodeRates[sd->getCodeRateHP()], CodeRates[sd->getCodeRateLP()], GuardIntervals[sd->getGuardInterval()], TransmissionModes[sd->getTransmissionMode()]);
                  if (Setup.UpdateChannels >= 5) {
                     bool found = false;
                     bool forceTransponderUpdate = false;
@@ -319,7 +263,8 @@
                            }
                        }
                     }
-                 sdtFilter->Trigger(Source);
+                 if (ISTRANSPONDER(Frequency / 1000000, Transponder()))
+                    sdtFilter->Trigger(Source);
                  }
                  break;
             case SI::ExtensionDescriptorTag: {
--- ./nit.h	2014/03/10 14:12:05	4.0
+++ ./nit.h	2015/03/16 12:41:38
@@ -13,24 +13,10 @@
 #include "filter.h"
 #include "sdt.h"
 
-#define MAXNITS 16
-#define MAXNETWORKNAME Utf8BufSize(256)
-
 class cNitFilter : public cFilter {
 private:
-
-  class cNit {
-  public:
-    u_short networkId;
-    char name[MAXNETWORKNAME];
-    bool hasTransponder;
-    };
-
   cSectionSyncer sectionSyncer;
   cSdtFilter *sdtFilter;
-  cNit nits[MAXNITS];
-  u_short networkId;
-  int numNits;
 protected:
   virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
 public:
--- ./sdt.c	2015/01/04 14:33:35	4.0
+++ ./sdt.c	2015/03/16 15:22:56
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: sdt.c 4.0 2015/01/04 14:33:35 kls Exp $
+ * $Id: sdt.c 4.2 2015/03/14 12:51:42 kls Exp kls $
  */
 
 #include "sdt.h"
@@ -13,6 +13,11 @@
 #include "libsi/section.h"
 #include "libsi/descriptor.h"
 
+// Set to 'true' for debug output:
+static bool DebugSdt = true;//XXX false;
+
+#define dbgsdt(a...) if (DebugSdt) fprintf(stderr, a)
+
 // --- cSdtFilter ------------------------------------------------------------
 
 cSdtFilter::cSdtFilter(cPatFilter *PatFilter)
@@ -47,8 +52,11 @@
      return;
   if (!sectionSyncer.Sync(sdt.getVersionNumber(), sdt.getSectionNumber(), sdt.getLastSectionNumber()))
      return;
-  if (!Channels.Lock(true, 10))
+  if (!Channels.Lock(true, 10)) {
+     sectionSyncer.Reset(); // let's not miss any section of the SDT
      return;
+     }
+  dbgsdt("SDT: %2d %2d %2d %s %d\n", sdt.getVersionNumber(), sdt.getSectionNumber(), sdt.getLastSectionNumber(), *cSource::ToString(source), Transponder());
   SI::SDT::Service SiSdtService;
   for (SI::Loop::Iterator it; sdt.serviceLoop.getNext(SiSdtService, it); ) {
       cChannel *channel = Channels.GetByChannelID(tChannelID(source, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId()));
@@ -104,7 +112,9 @@
                            // channel->SetCa(SiSdtService.getFreeCaMode() ? 0xFFFF : 0);
                            }
                         else if (*pn && Setup.UpdateChannels >= 4) {
+                           dbgsdt("    %5d %5d %5d %s/%s %d %s\n", sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId(), *cSource::ToString(Channel()->Source()), *cSource::ToString(source), Channel()->Transponder(), pn);
                            channel = Channels.NewChannel(Channel(), pn, ps, pp, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
+                           channel->SetSource(source); // in case this comes from a satellite with a slightly different position
                            patFilter->Trigger(SiSdtService.getServiceId());
                            }
                         }
@@ -153,8 +163,11 @@
          }
       }
   if (sdt.getSectionNumber() == sdt.getLastSectionNumber()) {
-     if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3)
-        Channels.MarkObsoleteChannels(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId());
+     if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3) {
+        Channels.MarkObsoleteChannels(source, sdt.getOriginalNetworkId(), sdt.getTransportStreamId());
+        if (source != Source())
+           Channels.MarkObsoleteChannels(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId());
+        }
      }
   Channels.Unlock();
 }
--- channels.c	2015/02/01 13:47:05	4.0
+++ channels.c	2015/03/13 11:34:28
@@ -229,6 +229,18 @@
   return true;
 }
 
+void cChannel::SetSource(int Source)
+{
+  if (source != Source) {
+     if (Number()) {
+        dsyslog("changing source of channel %d (%s) from %s to %s", Number(), name, *cSource::ToString(source), *cSource::ToString(Source));
+        modification |= CHANNELMOD_TRANSP;
+        Channels.SetModified();
+        }
+     source = Source;
+     }
+}
+
 void cChannel::SetId(int Nid, int Tid, int Sid, int Rid)
 {
   if (nid != Nid || tid != Tid || sid != Sid || rid != Rid) {
--- channels.h	2015/02/01 13:30:26	4.0
+++ channels.h	2015/03/13 11:20:50
@@ -193,6 +193,7 @@
   time_t Seen(void) { return seen; }
   void CopyTransponderData(const cChannel *Channel);
   bool SetTransponderData(int Source, int Frequency, int Srate, const char *Parameters, bool Quiet = false);
+  void SetSource(int Source);
   void SetId(int Nid, int Tid, int Sid, int Rid = 0);
   void SetLcn(int Lcn);
   void SetName(const char *Name, const char *ShortName, const char *Provider);
