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 §ion); 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 §ion) 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 §ion) 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 §ion, 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 §ion) 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 §ion) 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 §ion) 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"