File indexing completed on 2024-05-12 04:52:17

0001 /*
0002  * dvbscan.cpp
0003  *
0004  * Copyright (C) 2008-2011 Christoph Pfister <christophpfister@gmail.com>
0005  *
0006  * This program is free software; you can redistribute it and/or modify
0007  * it under the terms of the GNU General Public License as published by
0008  * the Free Software Foundation; either version 2 of the License, or
0009  * (at your option) any later version.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  * GNU General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU General Public License along
0017  * with this program; if not, write to the Free Software Foundation, Inc.,
0018  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
0019  */
0020 
0021 #include "../log.h"
0022 
0023 #include <QBitArray>
0024 #include <QVector>
0025 #include <stdint.h>
0026 
0027 #include "dvbdevice.h"
0028 #include "dvbscan.h"
0029 #include "dvbsi.h"
0030 
0031 class DvbPatEntry
0032 {
0033 public:
0034     DvbPatEntry(int programNumber_, int pid_) : programNumber(programNumber_), pid(pid_) { }
0035     ~DvbPatEntry() { }
0036 
0037     int programNumber;
0038     int pid;
0039 };
0040 
0041 Q_DECLARE_TYPEINFO(DvbPatEntry, Q_MOVABLE_TYPE);
0042 
0043 class DvbSdtEntry
0044 {
0045 public:
0046     DvbSdtEntry(int serviceId_, int networkId_, bool scrambled_) : serviceId(serviceId_),
0047         networkId(networkId_), scrambled(scrambled_) { }
0048     ~DvbSdtEntry() { }
0049 
0050     int serviceId;
0051     int networkId;
0052     bool scrambled;
0053     QString name;
0054     QString provider;
0055 };
0056 
0057 class DvbScanFilter : public DvbSectionFilter, QObject
0058 {
0059 public:
0060     DvbScanFilter(DvbScan *scan_, bool useOtherNit_) : scan(scan_), pid(-1), useOtherNit(useOtherNit_) { }
0061 
0062     ~DvbScanFilter()
0063     {
0064         stopFilter();
0065     }
0066 
0067     bool isActive() const
0068     {
0069         return (pid != -1);
0070     }
0071 
0072     bool startFilter(int pid_, DvbScan::FilterType type_);
0073     void stopFilter();
0074 
0075 private:
0076     struct sectCheck {
0077         int id;
0078         QBitArray check;
0079     };
0080 
0081     bool checkMultipleSection(const DvbStandardSection &section);
0082     bool isFinished();
0083     void processSection(const char *data, int size) override;
0084     void timerEvent(QTimerEvent *) override;
0085 
0086     DvbScan *scan;
0087 
0088     int pid;
0089     DvbScan::FilterType type;
0090     QVector<sectCheck> multipleSections;
0091     int timerId;
0092     bool useOtherNit;
0093 };
0094 
0095 bool DvbScanFilter::startFilter(int pid_, DvbScan::FilterType type_)
0096 {
0097     Q_ASSERT(pid == -1);
0098 
0099     pid = pid_;
0100     type = type_;
0101     multipleSections.clear();
0102 
0103     if (!scan->device->addSectionFilter(pid, this)) {
0104         pid = -1;
0105         return false;
0106     }
0107 
0108     // FIXME check timings
0109     if (type != DvbScan::NitFilter) {
0110         timerId = startTimer(5000);
0111     } else {
0112         timerId = startTimer(20000);
0113     }
0114 
0115     return true;
0116 }
0117 
0118 void DvbScanFilter::stopFilter()
0119 {
0120     if (pid != -1) {
0121         killTimer(timerId);
0122         scan->device->removeSectionFilter(pid, this);
0123         multipleSections.clear();
0124 
0125         pid = -1;
0126     }
0127 }
0128 
0129 bool DvbScanFilter::checkMultipleSection(const DvbStandardSection &section)
0130 {
0131     int sectionCount = section.lastSectionNumber() + 1;
0132     int tableNumber = -1;
0133     int id = section.tableId() << 16 | section.tableIdExtension();
0134 
0135     for (int i = 0; i < multipleSections.size(); i++) {
0136         if (multipleSections.at(i).id == id) {
0137             tableNumber = i;
0138             break;
0139         }
0140     }
0141     if (tableNumber < 0) {
0142         tableNumber = multipleSections.size();
0143         multipleSections.resize(tableNumber + 1);
0144         multipleSections[tableNumber].id = id;
0145         multipleSections[tableNumber].check.resize(sectionCount);
0146     }
0147 
0148     if (section.sectionNumber() >= sectionCount) {
0149         qCWarning(logDvb, "Current section is bigger than the last one");
0150         sectionCount = section.sectionNumber() + 1;
0151     }
0152 
0153     QBitArray *check = &multipleSections[tableNumber].check;
0154 
0155     if (check->isEmpty()) {
0156         check->resize(sectionCount);
0157     } else {
0158         if (check->size() != sectionCount) {
0159             qCWarning(logDvb, "Inconsistent number of sections");
0160 
0161             if (check->size() < sectionCount)
0162                 check->resize(sectionCount);
0163         }
0164     }
0165 
0166     if (check->testBit(section.sectionNumber())) {
0167         return false;
0168     }
0169 
0170     check->setBit(section.sectionNumber());
0171     return true;
0172 }
0173 
0174 bool DvbScanFilter::isFinished()
0175 {
0176     for (int i = 0; i < multipleSections.size(); i++) {
0177         if (multipleSections[i].check.count(false) != 0)
0178             return false;
0179     }
0180     return true;
0181 }
0182 
0183 void DvbScanFilter::processSection(const char *data, int size)
0184 {
0185     switch (type) {
0186     case DvbScan::PatFilter: {
0187         DvbPatSection patSection(data, size);
0188 
0189         if (!patSection.isValid() || (patSection.tableId() != 0x0)) {
0190             return;
0191         }
0192 
0193         if (!checkMultipleSection(patSection)) {
0194             // already read this part
0195             return;
0196         }
0197 
0198         scan->processPat(patSection);
0199         break;
0200         }
0201     case DvbScan::PmtFilter: {
0202         DvbPmtSection pmtSection(data, size);
0203 
0204         if (!pmtSection.isValid() || (pmtSection.tableId() != 0x2)) {
0205             return;
0206         }
0207 
0208         if (!checkMultipleSection(pmtSection)) {
0209             // already read this part
0210             return;
0211         }
0212 
0213         scan->processPmt(pmtSection, pid);
0214         break;
0215         }
0216     case DvbScan::SdtFilter: {
0217         // FIXME: should we also handle other SDT table?
0218 
0219         DvbSdtSection sdtSection(data, size);
0220 
0221 
0222         if (!sdtSection.isValid() || (sdtSection.tableId() != 0x42)) {
0223             // there are also other tables in the SDT
0224             return;
0225         }
0226 
0227         if (!checkMultipleSection(sdtSection)) {
0228             // already read this part
0229             return;
0230         }
0231 
0232         scan->processSdt(sdtSection);
0233         break;
0234         }
0235     case DvbScan::VctFilter: {
0236         AtscVctSection vctSection(data, size);
0237 
0238         if (!vctSection.isValid() ||
0239             ((vctSection.tableId() != 0xc8) && (vctSection.tableId() != 0xc9))) {
0240             // there are also other tables in the VCT
0241             return;
0242         }
0243 
0244         if (!checkMultipleSection(vctSection)) {
0245             // already read this part
0246             return;
0247         }
0248 
0249         scan->processVct(vctSection);
0250         break;
0251         }
0252     case DvbScan::NitFilter: {
0253         DvbNitSection nitSection(data, size);
0254 
0255 
0256         if (!nitSection.isValid())
0257             return;
0258 
0259         if (!((nitSection.tableId() == 0x40) || (useOtherNit && (nitSection.tableId() == 0x41))))
0260             return;
0261 
0262         qCDebug(logDvb, "Handling NIT table ID 0x%02x, extension 0x%04x", nitSection.tableId(), nitSection.tableIdExtension());
0263 
0264         if (!checkMultipleSection(nitSection)) {
0265             // already read this part
0266             return;
0267         }
0268 
0269         scan->processNit(nitSection);
0270         break;
0271         }
0272     }
0273 
0274     if (isFinished())
0275         scan->filterFinished(this);
0276 }
0277 
0278 void DvbScanFilter::timerEvent(QTimerEvent *)
0279 {
0280     qCWarning(logDvb, "Timeout while reading section; type = %d, PID = %d", type, pid);
0281     scan->filterFinished(this);
0282 }
0283 
0284 DvbScan::DvbScan(DvbDevice *device_, const QString &source_, const DvbTransponder &transponder_, bool useOtherNit_) :
0285     device(device_), source(source_), transponder(transponder_), isLive(true), isAuto(false), useOtherNit(useOtherNit_),
0286     transponderIndex(-1), state(ScanPat), patIndex(0), activeFilters(0)
0287 {
0288     qCDebug(logDvb, "Use other NIT is %s", useOtherNit ? "enabled" : "disabled");
0289 }
0290 
0291 DvbScan::DvbScan(DvbDevice *device_, const QString &source_,
0292     const QList<DvbTransponder> &transponders_, bool useOtherNit_) : device(device_), source(source_),
0293     isLive(false), isAuto(false), useOtherNit(useOtherNit_), transponders(transponders_), transponderIndex(0),
0294     state(ScanTune), patIndex(0), activeFilters(0)
0295 {
0296     qCDebug(logDvb, "Use other NIT is %s", useOtherNit ? "enabled" : "disabled");
0297 }
0298 
0299 DvbScan::DvbScan(DvbDevice *device_, const QString &source_, const QString &autoScanSource, bool useOtherNit_) :
0300     device(device_), source(source_), isLive(false), isAuto(true), useOtherNit(useOtherNit_), transponderIndex(0),
0301     state(ScanTune), patIndex(0), activeFilters(0)
0302 {
0303     qCDebug(logDvb, "Use other NIT is %s", useOtherNit ? "enabled" : "disabled");
0304 
0305     // Seek for DVB-T transponders
0306 
0307     if ((autoScanSource == QLatin1String("AUTO-T-Normal")) ||
0308         (autoScanSource == QLatin1String("AUTO-T-Offsets")) ||
0309         (autoScanSource == QLatin1String("AUTO-T2-Normal")) ||
0310         (autoScanSource == QLatin1String("AUTO-T2-Offsets"))) {
0311         bool offsets = (autoScanSource == QLatin1String("AUTO-T-Offsets")) || (autoScanSource == QLatin1String("AUTO-T2-Offsets"));
0312 
0313         for (int frequency = 177500000; frequency <= 226500000; frequency += 7000000) {
0314             DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
0315             DvbTTransponder *dvbTTransponder = currentTransponder.as<DvbTTransponder>();
0316             dvbTTransponder->frequency = frequency;
0317             dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth7MHz;
0318             dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
0319             dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
0320             dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
0321             dvbTTransponder->transmissionMode = DvbTTransponder::TransmissionModeAuto;
0322             dvbTTransponder->guardInterval = DvbTTransponder::GuardIntervalAuto;
0323             dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
0324             transponders.append(currentTransponder);
0325         }
0326 
0327         for (int frequency = 474000000; frequency <= 858000000; frequency += 8000000) {
0328             for (int i = 0; i < 3; ++i) {
0329                 if ((i != 0) && (!offsets)) {
0330                     break;
0331                 }
0332 
0333                 int offset = 0;
0334 
0335                 if (i == 1) {
0336                     offset = -167000;
0337                 } else if (i == 2) {
0338                     offset = 167000;
0339                 }
0340 
0341                 DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
0342                 DvbTTransponder *dvbTTransponder =
0343                     currentTransponder.as<DvbTTransponder>();
0344                 dvbTTransponder->frequency = frequency + offset;
0345                 dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth8MHz;
0346                 dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
0347                 dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
0348                 dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
0349                 dvbTTransponder->transmissionMode =
0350                     DvbTTransponder::TransmissionModeAuto;
0351                 dvbTTransponder->guardInterval =
0352                     DvbTTransponder::GuardIntervalAuto;
0353                 dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
0354                 transponders.append(currentTransponder);
0355             }
0356         }
0357     } else if ((autoScanSource == QLatin1String("AUTO-T-Australia")) ||
0358            (autoScanSource == QLatin1String("AUTO-T2-Australia"))) {
0359         for (int frequency = 177500000; frequency <= 226500000; frequency += 7000000) {
0360             for (int i = 0; i < 2; ++i) {
0361                 int offset = 0;
0362 
0363                 if (i == 1) {
0364                     offset = 125000;
0365                 }
0366 
0367                 DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
0368                 DvbTTransponder *dvbTTransponder =
0369                     currentTransponder.as<DvbTTransponder>();
0370                 dvbTTransponder->frequency = frequency + offset;
0371                 dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth7MHz;
0372                 dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
0373                 dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
0374                 dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
0375                 dvbTTransponder->transmissionMode =
0376                     DvbTTransponder::TransmissionModeAuto;
0377                 dvbTTransponder->guardInterval =
0378                     DvbTTransponder::GuardIntervalAuto;
0379                 dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
0380                 transponders.append(currentTransponder);
0381             }
0382         }
0383 
0384         for (int frequency = 529500000; frequency <= 816500000; frequency += 7000000) {
0385             for (int i = 0; i < 2; ++i) {
0386                 int offset = 0;
0387 
0388                 if (i == 1) {
0389                     offset = 125000;
0390                 }
0391 
0392                 DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
0393                 DvbTTransponder *dvbTTransponder =
0394                     currentTransponder.as<DvbTTransponder>();
0395                 dvbTTransponder->frequency = frequency + offset;
0396                 dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth7MHz;
0397                 dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
0398                 dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
0399                 dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
0400                 dvbTTransponder->transmissionMode =
0401                     DvbTTransponder::TransmissionModeAuto;
0402                 dvbTTransponder->guardInterval =
0403                     DvbTTransponder::GuardIntervalAuto;
0404                 dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
0405                 transponders.append(currentTransponder);
0406             }
0407         }
0408     } else if ((autoScanSource == QLatin1String("AUTO-T-Italy")) ||
0409            (autoScanSource == QLatin1String("AUTO-T2-Italy"))) {
0410         static const int italyVhf[] = { 177500000, 186000000, 194500000, 203500000,
0411                         212500000, 219500000, 226500000 };
0412 
0413         for (unsigned i = 0; i < (sizeof(italyVhf) / sizeof(italyVhf[0])); ++i) {
0414             for (int j = 0; j < 2; ++j) {
0415                 DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
0416                 DvbTTransponder *dvbTTransponder =
0417                     currentTransponder.as<DvbTTransponder>();
0418                 dvbTTransponder->frequency = italyVhf[i];
0419                 dvbTTransponder->bandwidth = ((j == 0) ?
0420                     DvbTTransponder::Bandwidth7MHz :
0421                     DvbTTransponder::Bandwidth8MHz);
0422                 dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
0423                 dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
0424                 dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
0425                 dvbTTransponder->transmissionMode =
0426                     DvbTTransponder::TransmissionModeAuto;
0427                 dvbTTransponder->guardInterval =
0428                     DvbTTransponder::GuardIntervalAuto;
0429                 dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
0430                 transponders.append(currentTransponder);
0431             }
0432         }
0433 
0434         for (int frequency = 474000000; frequency <= 858000000; frequency += 8000000) {
0435             DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
0436             DvbTTransponder *dvbTTransponder =
0437                 currentTransponder.as<DvbTTransponder>();
0438             dvbTTransponder->frequency = frequency;
0439             dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth8MHz;
0440             dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
0441             dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
0442             dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
0443             dvbTTransponder->transmissionMode = DvbTTransponder::TransmissionModeAuto;
0444             dvbTTransponder->guardInterval = DvbTTransponder::GuardIntervalAuto;
0445             dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
0446             transponders.append(currentTransponder);
0447         }
0448     } else if ((autoScanSource == QLatin1String("AUTO-T-Taiwan"))||
0449            (autoScanSource == QLatin1String("AUTO-T2-Taiwan"))) {
0450         for (int frequency = 527000000; frequency <= 599000000; frequency += 6000000) {
0451             DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
0452             DvbTTransponder *dvbTTransponder =
0453                 currentTransponder.as<DvbTTransponder>();
0454             dvbTTransponder->frequency = frequency;
0455             dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth6MHz;
0456             dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
0457             dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
0458             dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
0459             dvbTTransponder->transmissionMode = DvbTTransponder::TransmissionModeAuto;
0460             dvbTTransponder->guardInterval = DvbTTransponder::GuardIntervalAuto;
0461             dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
0462             transponders.append(currentTransponder);
0463         }
0464     }
0465 
0466     // Seek for DVB-T2 transponders
0467 
0468     if ((autoScanSource == QLatin1String("AUTO-T2-Normal")) ||
0469            (autoScanSource == QLatin1String("AUTO-T2-Offsets"))) {
0470         bool offsets = (autoScanSource == QLatin1String("AUTO-T2-Offsets"));
0471 
0472         for (int frequency = 177500000; frequency <= 226500000; frequency += 7000000) {
0473             DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
0474             DvbT2Transponder *dvbT2Transponder = currentTransponder.as<DvbT2Transponder>();
0475             dvbT2Transponder->frequency = frequency;
0476             dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth7MHz;
0477             dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
0478             dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
0479             dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
0480             dvbT2Transponder->transmissionMode = DvbT2Transponder::TransmissionModeAuto;
0481             dvbT2Transponder->guardInterval = DvbT2Transponder::GuardIntervalAuto;
0482             dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
0483             dvbT2Transponder->streamId = 0;
0484             transponders.append(currentTransponder);
0485         }
0486 
0487         for (int frequency = 474000000; frequency <= 858000000; frequency += 8000000) {
0488             for (int i = 0; i < 3; ++i) {
0489                 if ((i != 0) && (!offsets)) {
0490                     break;
0491                 }
0492 
0493                 int offset = 0;
0494 
0495                 if (i == 1) {
0496                     offset = -167000;
0497                 } else if (i == 2) {
0498                     offset = 167000;
0499                 }
0500 
0501                 DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
0502                 DvbT2Transponder *dvbT2Transponder = currentTransponder.as<DvbT2Transponder>();
0503                 dvbT2Transponder->frequency = frequency + offset;
0504                 dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth8MHz;
0505                 dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
0506                 dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
0507                 dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
0508                 dvbT2Transponder->transmissionMode = DvbT2Transponder::TransmissionModeAuto;
0509                 dvbT2Transponder->guardInterval = DvbT2Transponder::GuardIntervalAuto;
0510                 dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
0511                 dvbT2Transponder->streamId = 0;
0512                 transponders.append(currentTransponder);
0513             }
0514         }
0515     } else if (autoScanSource == QLatin1String("AUTO-T2-Australia")) {
0516         for (int frequency = 177500000; frequency <= 226500000; frequency += 7000000) {
0517             for (int i = 0; i < 2; ++i) {
0518                 int offset = 0;
0519 
0520                 if (i == 1) {
0521                     offset = 125000;
0522                 }
0523 
0524                 DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
0525                 DvbT2Transponder *dvbT2Transponder =
0526                     currentTransponder.as<DvbT2Transponder>();
0527                 dvbT2Transponder->frequency = frequency + offset;
0528                 dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth7MHz;
0529                 dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
0530                 dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
0531                 dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
0532                 dvbT2Transponder->transmissionMode =
0533                     DvbT2Transponder::TransmissionModeAuto;
0534                 dvbT2Transponder->guardInterval =
0535                     DvbT2Transponder::GuardIntervalAuto;
0536                 dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
0537                 dvbT2Transponder->streamId = 0;
0538                 transponders.append(currentTransponder);
0539             }
0540         }
0541 
0542         for (int frequency = 529500000; frequency <= 816500000; frequency += 7000000) {
0543             for (int i = 0; i < 2; ++i) {
0544                 int offset = 0;
0545 
0546                 if (i == 1) {
0547                     offset = 125000;
0548                 }
0549 
0550                 DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
0551                 DvbT2Transponder *dvbT2Transponder =
0552                     currentTransponder.as<DvbT2Transponder>();
0553                 dvbT2Transponder->frequency = frequency + offset;
0554                 dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth7MHz;
0555                 dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
0556                 dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
0557                 dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
0558                 dvbT2Transponder->transmissionMode =
0559                     DvbT2Transponder::TransmissionModeAuto;
0560                 dvbT2Transponder->guardInterval =
0561                     DvbT2Transponder::GuardIntervalAuto;
0562                 dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
0563                 dvbT2Transponder->streamId = 0;
0564                 transponders.append(currentTransponder);
0565             }
0566         }
0567     } else if (autoScanSource == QLatin1String("AUTO-T2-Italy")) {
0568         static const int italyVhf[] = { 177500000, 186000000, 194500000, 203500000,
0569                         212500000, 219500000, 226500000 };
0570 
0571         for (unsigned i = 0; i < (sizeof(italyVhf) / sizeof(italyVhf[0])); ++i) {
0572             for (int j = 0; j < 2; ++j) {
0573                 DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
0574                 DvbT2Transponder *dvbT2Transponder =
0575                     currentTransponder.as<DvbT2Transponder>();
0576                 dvbT2Transponder->frequency = italyVhf[i];
0577                 dvbT2Transponder->bandwidth = ((j == 0) ?
0578                     DvbT2Transponder::Bandwidth7MHz :
0579                     DvbT2Transponder::Bandwidth8MHz);
0580                 dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
0581                 dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
0582                 dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
0583                 dvbT2Transponder->transmissionMode =
0584                     DvbT2Transponder::TransmissionModeAuto;
0585                 dvbT2Transponder->guardInterval =
0586                     DvbT2Transponder::GuardIntervalAuto;
0587                 dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
0588                 dvbT2Transponder->streamId = 0;
0589                 transponders.append(currentTransponder);
0590             }
0591         }
0592 
0593         for (int frequency = 474000000; frequency <= 858000000; frequency += 8000000) {
0594             DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
0595             DvbT2Transponder *dvbT2Transponder =
0596                 currentTransponder.as<DvbT2Transponder>();
0597             dvbT2Transponder->frequency = frequency;
0598             dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth8MHz;
0599             dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
0600             dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
0601             dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
0602             dvbT2Transponder->transmissionMode = DvbT2Transponder::TransmissionModeAuto;
0603             dvbT2Transponder->guardInterval = DvbT2Transponder::GuardIntervalAuto;
0604             dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
0605             dvbT2Transponder->streamId = 0;
0606             transponders.append(currentTransponder);
0607         }
0608     } else if (autoScanSource == QLatin1String("AUTO-T2-Taiwan")) {
0609         for (int frequency = 527000000; frequency <= 599000000; frequency += 6000000) {
0610             DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
0611             DvbT2Transponder *dvbT2Transponder =
0612                 currentTransponder.as<DvbT2Transponder>();
0613             dvbT2Transponder->frequency = frequency;
0614             dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth6MHz;
0615             dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
0616             dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
0617             dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
0618             dvbT2Transponder->transmissionMode = DvbT2Transponder::TransmissionModeAuto;
0619             dvbT2Transponder->guardInterval = DvbT2Transponder::GuardIntervalAuto;
0620             dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
0621             dvbT2Transponder->streamId = 0;
0622             transponders.append(currentTransponder);
0623         }
0624     }
0625 
0626     // Seek for ISDB-T transponders
0627 
0628     if (autoScanSource == QLatin1String("AUTO-UHF-6MHz")) {
0629         for (int frequency = 473142857; frequency <= 803142857; frequency += 6000000) {
0630             DvbTransponder currentTransponder(DvbTransponderBase::IsdbT);
0631             IsdbTTransponder *isdbTTransponder =
0632                 currentTransponder.as<IsdbTTransponder>();
0633             isdbTTransponder->frequency = frequency;
0634             isdbTTransponder->bandwidth = IsdbTTransponder::Bandwidth6MHz;
0635             isdbTTransponder->transmissionMode = IsdbTTransponder::TransmissionModeAuto;
0636             isdbTTransponder->guardInterval = IsdbTTransponder::GuardIntervalAuto;
0637             isdbTTransponder->partialReception = IsdbTTransponder::PR_AUTO;
0638             isdbTTransponder->soundBroadcasting = IsdbTTransponder::SB_disabled;
0639             for (int i = 0; i < 3; i++) {
0640                 isdbTTransponder->layerEnabled[i] = true;
0641                 isdbTTransponder->modulation[i] = IsdbTTransponder::ModulationAuto;
0642                 isdbTTransponder->fecRate[i] = IsdbTTransponder::FecAuto;
0643                 isdbTTransponder->interleaving[i] = IsdbTTransponder::I_AUTO;
0644                 isdbTTransponder->segmentCount[i] = 15;
0645             }
0646             transponders.append(currentTransponder);
0647         }
0648     }
0649 }
0650 
0651 DvbScan::~DvbScan()
0652 {
0653     qDeleteAll(filters);
0654 }
0655 
0656 void DvbScan::start()
0657 {
0658     connect(device, SIGNAL(stateChanged()), this, SLOT(deviceStateChanged()));
0659     updateState();
0660 }
0661 
0662 void DvbScan::deviceStateChanged()
0663 {
0664     if (device->getDeviceState() == DvbDevice::DeviceReleased) {
0665         qCWarning(logDvb, "Device was released. Stopping scan");
0666         emit scanFinished();
0667         return;
0668     }
0669 
0670     if (state == ScanTuning) {
0671         updateState();
0672     }
0673 }
0674 
0675 bool DvbScan::startFilter(int pid, FilterType type)
0676 {
0677     if (activeFilters != filters.size()) {
0678         foreach (DvbScanFilter *filter, filters) {
0679             if (!filter->isActive()) {
0680                 if (!filter->startFilter(pid, type)) {
0681                     return false;
0682                 }
0683 
0684                 ++activeFilters;
0685                 return true;
0686             }
0687         }
0688 
0689         Q_ASSERT(false);
0690     } else if (activeFilters < 10) {
0691         DvbScanFilter *filter = new DvbScanFilter(this, useOtherNit);
0692 
0693         if (!filter->startFilter(pid, type)) {
0694             delete filter;
0695             return false;
0696         }
0697 
0698         filters.append(filter);
0699         ++activeFilters;
0700         return true;
0701     }
0702 
0703     return false;
0704 }
0705 
0706 void DvbScan::updateState()
0707 {
0708     while (true) {
0709         switch (state) {
0710         case ScanPat: {
0711             if (!startFilter(0x0, PatFilter)) {
0712                 return;
0713             }
0714 
0715             snr = device->getSnr(scale);
0716 
0717             state = ScanNit;
0718             }
0719             // fall through
0720         case ScanNit: {
0721             if (!isLive && !isAuto &&
0722                 (transponder.getTransmissionType() != DvbTransponderBase::Atsc)) {
0723                 if (!startFilter(0x10, NitFilter)) {
0724                     return;
0725                 }
0726             }
0727 
0728             state = ScanSdt;
0729             }
0730             // fall through
0731         case ScanSdt: {
0732             if (transponder.getTransmissionType() != DvbTransponderBase::Atsc) {
0733                 if (!startFilter(0x11, SdtFilter)) {
0734                     return;
0735                 }
0736             } else {
0737                 if (!startFilter(0x1ffb, VctFilter)) {
0738                     return;
0739                 }
0740             }
0741 
0742             state = ScanPmt;
0743             }
0744             // fall through
0745         case ScanPmt: {
0746             while (patIndex < patEntries.size()) {
0747                 if (!startFilter(patEntries.at(patIndex).pid, PmtFilter)) {
0748                     return;
0749                 }
0750 
0751                 ++patIndex;
0752             }
0753 
0754             if (activeFilters != 0) {
0755                 return;
0756             }
0757 
0758             for (int i = 0; i < channels.size(); ++i) {
0759                 DvbPreviewChannel &channel = channels[i];
0760 
0761                 foreach (const DvbSdtEntry &sdtEntry, sdtEntries) {
0762                     if (channel.serviceId == sdtEntry.serviceId) {
0763                         channel.name = sdtEntry.name;
0764                         channel.networkId = sdtEntry.networkId;
0765                         channel.isScrambled = sdtEntry.scrambled;
0766                         channel.provider = sdtEntry.provider;
0767                         break;
0768                     }
0769                 }
0770 
0771                 if (channel.name.isEmpty()) {
0772                     channel.name = QString(QLatin1String("#0 %1:%2")).
0773                                arg(channel.transportStreamId).
0774                                arg(channel.serviceId);
0775                 }
0776                 qCDebug(logDvb, "Found channel %s", qPrintable(channel.name));
0777             }
0778 
0779             if (!channels.isEmpty()) {
0780                 emit foundChannels(channels);
0781             }
0782 
0783             if (isLive) {
0784                 qCInfo(logDvb, "Scanning while live stream. Can't change the transponder");
0785                 emit scanFinished();
0786                 return;
0787             }
0788 
0789             patEntries.clear();
0790             patIndex = 0;
0791             sdtEntries.clear();
0792             channels.clear();
0793 
0794             state = ScanTune;
0795             }
0796             // fall through
0797         case ScanTune: {
0798             if (transponders.size() > 0) {
0799                 emit scanProgress((100 * transponderIndex) / transponders.size());
0800             }
0801 
0802             qCDebug(logDvb, "Transponder %d/%d", transponderIndex, transponders.size());
0803             if (transponderIndex >= transponders.size()) {
0804                 emit scanFinished();
0805                 return;
0806             }
0807 
0808             transponder = transponders.at(transponderIndex);
0809             ++transponderIndex;
0810 
0811             state = ScanTuning;
0812 
0813             if (!isAuto) {
0814                 device->tune(transponder);
0815             } else {
0816                 device->autoTune(transponder);
0817             }
0818 
0819             return;
0820             }
0821 
0822         case ScanTuning: {
0823             switch (device->getDeviceState()) {
0824             case DvbDevice::DeviceIdle:
0825                 state = ScanTune;
0826                 break;
0827 
0828             case DvbDevice::DeviceTuned:
0829                 if (isAuto) {
0830                     transponders[transponderIndex - 1] =
0831                         device->getAutoTransponder();
0832                 }
0833 
0834                 state = ScanPat;
0835                 break;
0836 
0837             default:
0838                 return;
0839             }
0840 
0841             break;
0842             }
0843         }
0844     }
0845 }
0846 
0847 void DvbScan::processPat(const DvbPatSection &section)
0848 {
0849     transportStreamId = section.transportStreamId();
0850 
0851     for (DvbPatSectionEntry entry = section.entries(); entry.isValid(); entry.advance()) {
0852         if (entry.programNumber() != 0x0) {
0853             // skip 0x0 which has a special meaning
0854             patEntries.append(DvbPatEntry(entry.programNumber(), entry.pid()));
0855 
0856             qCDebug(logDvb, "New PAT entry: pid %d, program %d", entry.pid(), entry.programNumber());
0857         }
0858     }
0859 }
0860 
0861 void DvbScan::processPmt(const DvbPmtSection &section, int pid)
0862 {
0863     DvbPreviewChannel channel;
0864 
0865     DvbPmtParser parser(section);
0866     channel.hasVideo = (parser.videoPid >= 0);
0867 
0868     if (!parser.audioPids.isEmpty()) {
0869         channel.audioPid = parser.audioPids.at(0).first;
0870     }
0871 
0872     if (channel.hasVideo || (channel.audioPid >= 0)) {
0873         channel.source = source;
0874         channel.transponder = transponder;
0875         channel.transportStreamId = transportStreamId;
0876         channel.pmtPid = pid;
0877         channel.pmtSectionData = section.toByteArray();
0878         channel.serviceId = section.programNumber();
0879         switch (scale) {
0880         case DvbBackendDevice::dBuV:
0881         case DvbBackendDevice::NotSupported: {
0882             channel.snr = "";
0883             break;
0884         }
0885         case DvbBackendDevice::Percentage: {
0886             channel.snr = QString::number(snr, 'f', 0) + '%';
0887             break;
0888         }
0889         case DvbBackendDevice::Decibel: {
0890             channel.snr = QString::number(snr, 'f', 2) + " dB";
0891             break;
0892         }
0893         };
0894         channels.append(channel);
0895 
0896         qCDebug(logDvb, "New channel: PID %d, service ID %d", pid, section.programNumber());
0897     }
0898 }
0899 
0900 void DvbScan::processSdt(const DvbSdtSection &section)
0901 {
0902     for (DvbSdtSectionEntry entry = section.entries(); entry.isValid(); entry.advance()) {
0903         DvbSdtEntry sdtEntry(entry.serviceId(), section.originalNetworkId(),
0904                      entry.isScrambled());
0905 
0906         for (DvbDescriptor descriptor = entry.descriptors(); descriptor.isValid();
0907              descriptor.advance()) {
0908             if (descriptor.descriptorTag() != 0x48) {
0909                 continue;
0910             }
0911 
0912             DvbServiceDescriptor serviceDescriptor(descriptor);
0913 
0914             if (!serviceDescriptor.isValid()) {
0915                 continue;
0916             }
0917 
0918             sdtEntry.name = serviceDescriptor.serviceName();
0919             sdtEntry.provider = serviceDescriptor.providerName();
0920 
0921             qCDebug(logDvb, "New SDT entry: service ID 0x%04x, name '%s', provider '%s'", entry.serviceId(), qPrintable(sdtEntry.name), qPrintable(sdtEntry.provider));
0922             sdtEntries.append(sdtEntry);
0923         }
0924     }
0925 }
0926 
0927 void DvbScan::processVct(const AtscVctSection &section)
0928 {
0929     AtscVctSectionEntry entry = section.entries();
0930     int entryCount = section.entryCount();
0931 
0932     for (int i = 0; i < entryCount && (entry.isValid()); i++) {
0933         QString majorminor = QString(QLatin1String("%1-%2 ")).
0934             arg(entry.majorNumber(), 3, 10, QLatin1Char('0')).arg(entry.minorNumber());
0935 
0936         DvbSdtEntry sdtEntry(entry.programNumber(), entry.sourceId(), entry.isScrambled());
0937 
0938         // Each VCT section has it's own list of descriptors
0939         // See A/65C table 6.25a for the list of descriptors
0940         for (DvbDescriptor descriptor = entry.descriptors(); descriptor.isValid();
0941              descriptor.advance()) {
0942             if (descriptor.descriptorTag() == 0xa0) {
0943                 // Extended Channel Name Descriptor
0944                 AtscChannelNameDescriptor nameDescriptor(descriptor);
0945                 if (!nameDescriptor.isValid()) {
0946                     continue;
0947                 }
0948                 sdtEntry.name = majorminor + nameDescriptor.name();
0949             }
0950         }
0951 
0952         if (sdtEntry.name.isEmpty()) {
0953             // Extended Channel name not available, fall back
0954             // to the short name
0955             QChar shortName[] = { entry.shortName1(),
0956                         entry.shortName2(),
0957                         entry.shortName3(),
0958                         entry.shortName4(),
0959                         entry.shortName5(),
0960                         entry.shortName6(),
0961                         entry.shortName7(), 0 };
0962             int nameLength = 0;
0963             while (shortName[nameLength] != 0) {
0964                 ++nameLength;
0965             }
0966             sdtEntry.name = majorminor + QString(shortName, nameLength);
0967         }
0968 
0969         qCDebug(logDvb, "New SDT entry: name %s", qPrintable(sdtEntry.name));
0970         sdtEntries.append(sdtEntry);
0971 
0972         if (i < entryCount - 1)
0973             entry.advance();
0974     }
0975 }
0976 
0977 void DvbScan::processNit(const DvbNitSection &section)
0978 {
0979     for (DvbNitSectionEntry entry = section.entries(); entry.isValid(); entry.advance()) {
0980         for (DvbDescriptor descriptor = entry.descriptors(); descriptor.isValid();
0981              descriptor.advance()) {
0982             processNitDescriptor(descriptor);
0983         }
0984     }
0985 }
0986 
0987 static DvbCTransponder::Modulation extractDvbCModulation(const DvbCableDescriptor &descriptor)
0988 {
0989     switch (descriptor.modulation()) {
0990     case 1:
0991         return DvbCTransponder::Qam16;
0992     case 2:
0993         return DvbCTransponder::Qam32;
0994     case 3:
0995         return DvbCTransponder::Qam64;
0996     case 4:
0997         return DvbCTransponder::Qam128;
0998     case 5:
0999         return DvbCTransponder::Qam256;
1000     default:
1001         return DvbCTransponder::ModulationAuto;
1002     }
1003 }
1004 
1005 static DvbCTransponder::FecRate extractDvbCFecRate(const DvbCableDescriptor &descriptor)
1006 {
1007     switch (descriptor.fecRate()) {
1008     case 1:
1009         return DvbTransponderBase::Fec1_2;
1010     case 2:
1011         return DvbTransponderBase::Fec2_3;
1012     case 3:
1013         return DvbTransponderBase::Fec3_4;
1014     case 4:
1015         return DvbTransponderBase::Fec5_6;
1016     case 5:
1017         return DvbTransponderBase::Fec7_8;
1018     case 6:
1019         return DvbTransponderBase::Fec8_9;
1020     case 7:
1021         return DvbTransponderBase::Fec3_5;
1022     case 8:
1023         return DvbTransponderBase::Fec4_5;
1024     case 9:
1025         return DvbTransponderBase::Fec9_10;
1026     case 15:
1027         return DvbTransponderBase::FecNone;
1028     default:
1029         return DvbTransponderBase::FecAuto;
1030     }
1031 }
1032 
1033 static DvbSTransponder::Polarization extractDvbSPolarization(
1034     const DvbSatelliteDescriptor &descriptor)
1035 {
1036     switch (descriptor.polarization()) {
1037     case 0:
1038         return DvbSTransponder::Horizontal;
1039     case 1:
1040         return DvbSTransponder::Vertical;
1041     case 2:
1042         return DvbSTransponder::CircularLeft;
1043     default:
1044         return DvbSTransponder::CircularRight;
1045     }
1046 }
1047 
1048 static DvbSTransponder::FecRate extractDvbSFecRate(const DvbSatelliteDescriptor &descriptor)
1049 {
1050     switch (descriptor.fecRate()) {
1051     case 1:
1052         return DvbTransponderBase::Fec1_2;
1053     case 2:
1054         return DvbTransponderBase::Fec2_3;
1055     case 3:
1056         return DvbTransponderBase::Fec3_4;
1057     case 4:
1058         return DvbTransponderBase::Fec5_6;
1059     case 5:
1060         return DvbTransponderBase::Fec7_8;
1061     case 6:
1062         return DvbTransponderBase::Fec8_9;
1063     case 7:
1064         return DvbTransponderBase::Fec3_5;
1065     case 8:
1066         return DvbTransponderBase::Fec4_5;
1067     case 9:
1068         return DvbTransponderBase::Fec9_10;
1069     default:
1070         return DvbTransponderBase::FecAuto;
1071     }
1072 }
1073 
1074 static DvbS2Transponder::Modulation extractDvbS2Modulation(
1075     const DvbSatelliteDescriptor &descriptor)
1076 {
1077     switch (descriptor.modulation()) {
1078     case 1:
1079         return DvbS2Transponder::Qpsk;
1080     case 2:
1081         return DvbS2Transponder::Psk8;
1082     default:
1083         return DvbS2Transponder::ModulationAuto;
1084     }
1085 }
1086 
1087 static DvbS2Transponder::RollOff extractDvbS2RollOff(const DvbSatelliteDescriptor &descriptor)
1088 {
1089     switch (descriptor.rollOff()) {
1090     case 0:
1091         return DvbS2Transponder::RollOff35;
1092     case 1:
1093         return DvbS2Transponder::RollOff25;
1094     case 2:
1095         return DvbS2Transponder::RollOff20;
1096     default:
1097         return DvbS2Transponder::RollOffAuto;
1098     }
1099 }
1100 
1101 static DvbTTransponder::Bandwidth extractDvbTBandwidth(const DvbTerrestrialDescriptor &descriptor)
1102 {
1103     switch (descriptor.bandwidth()) {
1104     case 0:
1105         return DvbTTransponder::Bandwidth8MHz;
1106     case 1:
1107         return DvbTTransponder::Bandwidth7MHz;
1108     case 2:
1109         return DvbTTransponder::Bandwidth6MHz;
1110     case 3:
1111         return DvbTTransponder::Bandwidth5MHz;
1112     default:
1113         return DvbTTransponder::BandwidthAuto;
1114     }
1115 }
1116 
1117 static DvbTTransponder::Modulation extractDvbTModulation(
1118     const DvbTerrestrialDescriptor &descriptor)
1119 {
1120     switch (descriptor.constellation()) {
1121     case 0:
1122         return DvbTTransponder::Qpsk;
1123     case 1:
1124         return DvbTTransponder::Qam16;
1125     case 2:
1126         return DvbTTransponder::Qam64;
1127     default:
1128         return DvbTTransponder::ModulationAuto;
1129     }
1130 }
1131 
1132 static DvbTTransponder::FecRate extractDvbTFecRateHigh(const DvbTerrestrialDescriptor &descriptor)
1133 {
1134     switch (descriptor.fecRateHigh()) {
1135     case 0:
1136         return DvbTTransponder::Fec1_2;
1137     case 1:
1138         return DvbTTransponder::Fec2_3;
1139     case 2:
1140         return DvbTTransponder::Fec3_4;
1141     case 3:
1142         return DvbTTransponder::Fec5_6;
1143     case 4:
1144         return DvbTTransponder::Fec7_8;
1145     default:
1146         return DvbTTransponder::FecAuto;
1147     }
1148 }
1149 
1150 static DvbTTransponder::FecRate extractDvbTFecRateLow(const DvbTerrestrialDescriptor &descriptor)
1151 {
1152     switch (descriptor.fecRateLow()) {
1153     case 0:
1154         return DvbTTransponder::Fec1_2;
1155     case 1:
1156         return DvbTTransponder::Fec2_3;
1157     case 2:
1158         return DvbTTransponder::Fec3_4;
1159     case 3:
1160         return DvbTTransponder::Fec5_6;
1161     case 4:
1162         return DvbTTransponder::Fec7_8;
1163     default:
1164         return DvbTTransponder::FecAuto;
1165     }
1166 }
1167 
1168 static DvbTTransponder::TransmissionMode extractDvbTTransmissionMode(
1169     const DvbTerrestrialDescriptor &descriptor)
1170 {
1171     switch (descriptor.transmissionMode()) {
1172     case 0:
1173         return DvbTTransponder::TransmissionMode2k;
1174     case 1:
1175         return DvbTTransponder::TransmissionMode8k;
1176     case 2:
1177         return DvbTTransponder::TransmissionMode4k;
1178     default:
1179         return DvbTTransponder::TransmissionModeAuto;
1180     }
1181 }
1182 
1183 static DvbTTransponder::GuardInterval extractDvbTGuardInterval(
1184     const DvbTerrestrialDescriptor &descriptor)
1185 {
1186     switch (descriptor.guardInterval()) {
1187     case 0:
1188         return DvbTTransponder::GuardInterval1_32;
1189     case 1:
1190         return DvbTTransponder::GuardInterval1_16;
1191     case 2:
1192         return DvbTTransponder::GuardInterval1_8;
1193     default:
1194         return DvbTTransponder::GuardInterval1_4;
1195     }
1196 }
1197 
1198 static DvbTTransponder::Hierarchy extractDvbTHierarchy(const DvbTerrestrialDescriptor &descriptor)
1199 {
1200     switch (descriptor.hierarchy() & 0x3) {
1201     case 0:
1202         return DvbTTransponder::HierarchyNone;
1203     case 1:
1204         return DvbTTransponder::Hierarchy1;
1205     case 2:
1206         return DvbTTransponder::Hierarchy2;
1207     default:
1208         return DvbTTransponder::Hierarchy4;
1209     }
1210 }
1211 
1212 // FIXME: Implement DvbT2Descriptor
1213 
1214 void DvbScan::processNitDescriptor(const DvbDescriptor &descriptor)
1215 {
1216     DvbTransponder newTransponder(transponder.getTransmissionType());
1217 
1218     switch (transponder.getTransmissionType()) {
1219     case DvbTransponderBase::Invalid:
1220         qCWarning(logDvb, "Invalid transponder type");
1221         return;
1222     case DvbTransponderBase::DvbC: {
1223         if (descriptor.descriptorTag() != 0x44) {
1224             return;
1225         }
1226 
1227         DvbCableDescriptor cableDescriptor(descriptor);
1228 
1229         if (!cableDescriptor.isValid()) {
1230             return;
1231         }
1232 
1233         newTransponder = DvbTransponder(DvbTransponderBase::DvbC);
1234         DvbCTransponder *dvbCTransponder = newTransponder.as<DvbCTransponder>();
1235         dvbCTransponder->frequency =
1236             DvbDescriptor::bcdToInt(cableDescriptor.frequency(), 100);
1237         dvbCTransponder->symbolRate =
1238             DvbDescriptor::bcdToInt(cableDescriptor.symbolRate(), 100);
1239         dvbCTransponder->modulation = extractDvbCModulation(cableDescriptor);
1240         dvbCTransponder->fecRate = extractDvbCFecRate(cableDescriptor);
1241 
1242         qCDebug(logDvb, "Added transponder: %.2f MHz", dvbCTransponder->frequency / 1000000.);
1243         break;
1244         }
1245     case DvbTransponderBase::DvbS:
1246     case DvbTransponderBase::DvbS2: {
1247         if (descriptor.descriptorTag() != 0x43) {
1248             return;
1249         }
1250 
1251         DvbSatelliteDescriptor satelliteDescriptor(descriptor);
1252 
1253         if (!satelliteDescriptor.isValid()) {
1254             return;
1255         }
1256 
1257         DvbSTransponder *dvbSTransponder;
1258 
1259         if (!satelliteDescriptor.isDvbS2()) {
1260             newTransponder = DvbTransponder(DvbTransponderBase::DvbS);
1261             dvbSTransponder = newTransponder.as<DvbSTransponder>();
1262         } else {
1263             if ((device->getTransmissionTypes() & DvbDevice::DvbS2) == 0) {
1264                 return;
1265             }
1266 
1267             newTransponder = DvbTransponder(DvbTransponderBase::DvbS2);
1268             DvbS2Transponder *dvbS2Transponder = newTransponder.as<DvbS2Transponder>();
1269             dvbS2Transponder->modulation = extractDvbS2Modulation(satelliteDescriptor);
1270             dvbS2Transponder->rollOff = extractDvbS2RollOff(satelliteDescriptor);
1271             dvbSTransponder = dvbS2Transponder;
1272         }
1273 
1274         dvbSTransponder->frequency =
1275             DvbDescriptor::bcdToInt(satelliteDescriptor.frequency(), 10);
1276         dvbSTransponder->polarization = extractDvbSPolarization(satelliteDescriptor);
1277         dvbSTransponder->symbolRate =
1278             DvbDescriptor::bcdToInt(satelliteDescriptor.symbolRate(), 100);
1279         dvbSTransponder->fecRate = extractDvbSFecRate(satelliteDescriptor);
1280 
1281         qCDebug(logDvb, "Added transponder: %.2f MHz", dvbSTransponder->frequency / 1000000.);
1282         break;
1283         }
1284     case DvbTransponderBase::DvbT2:
1285         // FIXME: Implement T2_delivery_system_descriptor
1286         // descriptor 0x7f, extension descriptor 0x04  or use libdvbv5
1287 
1288     case DvbTransponderBase::DvbT: {
1289         if (descriptor.descriptorTag() != 0x5a) {
1290             return;
1291         }
1292 
1293         DvbTerrestrialDescriptor terrestrialDescriptor(descriptor);
1294 
1295         if (!terrestrialDescriptor.isValid()) {
1296             return;
1297         }
1298 
1299         newTransponder = DvbTransponder(DvbTransponderBase::DvbT);
1300         DvbTTransponder *dvbTTransponder = newTransponder.as<DvbTTransponder>();
1301         dvbTTransponder->frequency = terrestrialDescriptor.frequency() * 10;
1302         dvbTTransponder->bandwidth = extractDvbTBandwidth(terrestrialDescriptor);
1303         dvbTTransponder->modulation = extractDvbTModulation(terrestrialDescriptor);
1304         dvbTTransponder->fecRateHigh = extractDvbTFecRateHigh(terrestrialDescriptor);
1305         dvbTTransponder->fecRateLow = extractDvbTFecRateLow(terrestrialDescriptor);
1306         dvbTTransponder->transmissionMode =
1307             extractDvbTTransmissionMode(terrestrialDescriptor);
1308         dvbTTransponder->guardInterval = extractDvbTGuardInterval(terrestrialDescriptor);
1309         dvbTTransponder->hierarchy = extractDvbTHierarchy(terrestrialDescriptor);
1310 
1311         if (dvbTTransponder->hierarchy == DvbTTransponder::HierarchyNone) {
1312             dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
1313         }
1314 
1315         qCDebug(logDvb, "Added transponder: %.2f MHz", dvbTTransponder->frequency / 1000000.);
1316         break;
1317         }
1318     case DvbTransponderBase::Atsc:
1319         return;
1320     case DvbTransponderBase::IsdbT:
1321         if (descriptor.descriptorTag() != 0xfa) {
1322             return;
1323         }
1324 
1325         IsdbTerrestrialDescriptor IsdbTDescriptor(descriptor);
1326 
1327         if (!IsdbTDescriptor.isValid()) {
1328             return;
1329         }
1330 
1331         for (int i = 0; i < IsdbTDescriptor.frequencyLength(); i++) {
1332             newTransponder = DvbTransponder(DvbTransponderBase::IsdbT);
1333             IsdbTTransponder *isdbTTransponder = newTransponder.as<IsdbTTransponder>();
1334 
1335             isdbTTransponder->frequency =
1336                 (uint32_t)((((uint64_t)IsdbTDescriptor.frequency(i)) * 1000000ul) / 7);
1337             isdbTTransponder->bandwidth = IsdbTTransponder::Bandwidth6MHz;
1338             isdbTTransponder->transmissionMode = IsdbTTransponder::TransmissionModeAuto;
1339             isdbTTransponder->guardInterval = IsdbTTransponder::GuardIntervalAuto;
1340             isdbTTransponder->partialReception = IsdbTTransponder::PR_AUTO;
1341             isdbTTransponder->soundBroadcasting = IsdbTTransponder::SB_disabled;
1342             for (int i = 0; i < 3; i++) {
1343                 isdbTTransponder->layerEnabled[i] = true;
1344                 isdbTTransponder->modulation[i] = IsdbTTransponder::ModulationAuto;
1345                 isdbTTransponder->fecRate[i] = IsdbTTransponder::FecAuto;
1346                 isdbTTransponder->interleaving[i] = IsdbTTransponder::I_AUTO;
1347                 isdbTTransponder->segmentCount[i] = 15;
1348             }
1349 
1350             bool duplicate = false;
1351 
1352             foreach (const DvbTransponder &existingTransponder, transponders) {
1353                 if (existingTransponder.corresponds(newTransponder)) {
1354                     duplicate = true;
1355                     break;
1356                 }
1357             }
1358             if (duplicate)
1359                 continue;
1360 
1361             transponders.append(newTransponder);
1362             qCDebug(logDvb, "Added transponder: %.2f MHz", isdbTTransponder->frequency / 1000000.);
1363         }
1364         return;
1365     }
1366 
1367 
1368     // New transponder was found. Add it
1369     foreach (const DvbTransponder &existingTransponder, transponders) {
1370         if (existingTransponder.corresponds(newTransponder))
1371             return;
1372     }
1373 
1374     transponders.append(newTransponder);
1375 }
1376 
1377 void DvbScan::filterFinished(DvbScanFilter *filter)
1378 {
1379     filter->stopFilter();
1380     --activeFilters;
1381     updateState();
1382 }
1383 
1384 #include "moc_dvbscan.cpp"