1 /*
2 * dvbscan.cpp
3 *
4 * Copyright (C) 2008-2011 Christoph Pfister <christophpfister@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "../log.h"
22
23 #include <QBitArray>
24 #include <QVector>
25 #include <stdint.h>
26
27 #include "dvbdevice.h"
28 #include "dvbscan.h"
29 #include "dvbsi.h"
30
31 class DvbPatEntry
32 {
33 public:
DvbPatEntry(int programNumber_,int pid_)34 DvbPatEntry(int programNumber_, int pid_) : programNumber(programNumber_), pid(pid_) { }
~DvbPatEntry()35 ~DvbPatEntry() { }
36
37 int programNumber;
38 int pid;
39 };
40
41 Q_DECLARE_TYPEINFO(DvbPatEntry, Q_MOVABLE_TYPE);
42
43 class DvbSdtEntry
44 {
45 public:
DvbSdtEntry(int serviceId_,int networkId_,bool scrambled_)46 DvbSdtEntry(int serviceId_, int networkId_, bool scrambled_) : serviceId(serviceId_),
47 networkId(networkId_), scrambled(scrambled_) { }
~DvbSdtEntry()48 ~DvbSdtEntry() { }
49
50 int serviceId;
51 int networkId;
52 bool scrambled;
53 QString name;
54 QString provider;
55 };
56
57 class DvbScanFilter : public DvbSectionFilter, QObject
58 {
59 public:
DvbScanFilter(DvbScan * scan_,bool useOtherNit_)60 DvbScanFilter(DvbScan *scan_, bool useOtherNit_) : scan(scan_), pid(-1), useOtherNit(useOtherNit_) { }
61
~DvbScanFilter()62 ~DvbScanFilter()
63 {
64 stopFilter();
65 }
66
isActive() const67 bool isActive() const
68 {
69 return (pid != -1);
70 }
71
72 bool startFilter(int pid_, DvbScan::FilterType type_);
73 void stopFilter();
74
75 private:
76 struct sectCheck {
77 int id;
78 QBitArray check;
79 };
80
81 bool checkMultipleSection(const DvbStandardSection §ion);
82 bool isFinished();
83 void processSection(const char *data, int size);
84 void timerEvent(QTimerEvent *);
85
86 DvbScan *scan;
87
88 int pid;
89 DvbScan::FilterType type;
90 QVector<sectCheck> multipleSections;
91 int timerId;
92 bool useOtherNit;
93 };
94
startFilter(int pid_,DvbScan::FilterType type_)95 bool DvbScanFilter::startFilter(int pid_, DvbScan::FilterType type_)
96 {
97 Q_ASSERT(pid == -1);
98
99 pid = pid_;
100 type = type_;
101 multipleSections.clear();
102
103 if (!scan->device->addSectionFilter(pid, this)) {
104 pid = -1;
105 return false;
106 }
107
108 // FIXME check timings
109 if (type != DvbScan::NitFilter) {
110 timerId = startTimer(5000);
111 } else {
112 timerId = startTimer(20000);
113 }
114
115 return true;
116 }
117
stopFilter()118 void DvbScanFilter::stopFilter()
119 {
120 if (pid != -1) {
121 killTimer(timerId);
122 scan->device->removeSectionFilter(pid, this);
123 multipleSections.clear();
124
125 pid = -1;
126 }
127 }
128
checkMultipleSection(const DvbStandardSection & section)129 bool DvbScanFilter::checkMultipleSection(const DvbStandardSection §ion)
130 {
131 int sectionCount = section.lastSectionNumber() + 1;
132 int tableNumber = -1;
133 int id = section.tableId() << 16 | section.tableIdExtension();
134
135 for (int i = 0; i < multipleSections.size(); i++) {
136 if (multipleSections.at(i).id == id) {
137 tableNumber = i;
138 break;
139 }
140 }
141 if (tableNumber < 0) {
142 tableNumber = multipleSections.size();
143 multipleSections.resize(tableNumber + 1);
144 multipleSections[tableNumber].id = id;
145 multipleSections[tableNumber].check.resize(sectionCount);
146 }
147
148 if (section.sectionNumber() >= sectionCount) {
149 qCWarning(logDvb, "Current section is bigger than the last one");
150 sectionCount = section.sectionNumber() + 1;
151 }
152
153 QBitArray *check = &multipleSections[tableNumber].check;
154
155 if (check->isEmpty()) {
156 check->resize(sectionCount);
157 } else {
158 if (check->size() != sectionCount) {
159 qCWarning(logDvb, "Inconsistent number of sections");
160
161 if (check->size() < sectionCount)
162 check->resize(sectionCount);
163 }
164 }
165
166 if (check->testBit(section.sectionNumber())) {
167 return false;
168 }
169
170 check->setBit(section.sectionNumber());
171 return true;
172 }
173
isFinished()174 bool DvbScanFilter::isFinished()
175 {
176 for (int i = 0; i < multipleSections.size(); i++) {
177 if (multipleSections[i].check.count(false) != 0)
178 return false;
179 }
180 return true;
181 }
182
processSection(const char * data,int size)183 void DvbScanFilter::processSection(const char *data, int size)
184 {
185 switch (type) {
186 case DvbScan::PatFilter: {
187 DvbPatSection patSection(data, size);
188
189 if (!patSection.isValid() || (patSection.tableId() != 0x0)) {
190 return;
191 }
192
193 if (!checkMultipleSection(patSection)) {
194 // already read this part
195 return;
196 }
197
198 scan->processPat(patSection);
199 break;
200 }
201 case DvbScan::PmtFilter: {
202 DvbPmtSection pmtSection(data, size);
203
204 if (!pmtSection.isValid() || (pmtSection.tableId() != 0x2)) {
205 return;
206 }
207
208 if (!checkMultipleSection(pmtSection)) {
209 // already read this part
210 return;
211 }
212
213 scan->processPmt(pmtSection, pid);
214 break;
215 }
216 case DvbScan::SdtFilter: {
217 // FIXME: should we also handle other SDT table?
218
219 DvbSdtSection sdtSection(data, size);
220
221
222 if (!sdtSection.isValid() || (sdtSection.tableId() != 0x42)) {
223 // there are also other tables in the SDT
224 return;
225 }
226
227 if (!checkMultipleSection(sdtSection)) {
228 // already read this part
229 return;
230 }
231
232 scan->processSdt(sdtSection);
233 break;
234 }
235 case DvbScan::VctFilter: {
236 AtscVctSection vctSection(data, size);
237
238 if (!vctSection.isValid() ||
239 ((vctSection.tableId() != 0xc8) && (vctSection.tableId() != 0xc9))) {
240 // there are also other tables in the VCT
241 return;
242 }
243
244 if (!checkMultipleSection(vctSection)) {
245 // already read this part
246 return;
247 }
248
249 scan->processVct(vctSection);
250 break;
251 }
252 case DvbScan::NitFilter: {
253 DvbNitSection nitSection(data, size);
254
255
256 if (!nitSection.isValid())
257 return;
258
259 if (!((nitSection.tableId() == 0x40) || (useOtherNit && (nitSection.tableId() == 0x41))))
260 return;
261
262 qCDebug(logDvb, "Handling NIT table ID 0x%02x, extension 0x%04x", nitSection.tableId(), nitSection.tableIdExtension());
263
264 if (!checkMultipleSection(nitSection)) {
265 // already read this part
266 return;
267 }
268
269 scan->processNit(nitSection);
270 break;
271 }
272 }
273
274 if (isFinished())
275 scan->filterFinished(this);
276 }
277
timerEvent(QTimerEvent *)278 void DvbScanFilter::timerEvent(QTimerEvent *)
279 {
280 qCWarning(logDvb, "Timeout while reading section; type = %d, PID = %d", type, pid);
281 scan->filterFinished(this);
282 }
283
DvbScan(DvbDevice * device_,const QString & source_,const DvbTransponder & transponder_,bool useOtherNit_)284 DvbScan::DvbScan(DvbDevice *device_, const QString &source_, const DvbTransponder &transponder_, bool useOtherNit_) :
285 device(device_), source(source_), transponder(transponder_), isLive(true), isAuto(false), useOtherNit(useOtherNit_),
286 transponderIndex(-1), state(ScanPat), patIndex(0), activeFilters(0)
287 {
288 qCDebug(logDvb, "Use other NIT is %s", useOtherNit ? "enabled" : "disabled");
289 }
290
DvbScan(DvbDevice * device_,const QString & source_,const QList<DvbTransponder> & transponders_,bool useOtherNit_)291 DvbScan::DvbScan(DvbDevice *device_, const QString &source_,
292 const QList<DvbTransponder> &transponders_, bool useOtherNit_) : device(device_), source(source_),
293 isLive(false), isAuto(false), useOtherNit(useOtherNit_), transponders(transponders_), transponderIndex(0),
294 state(ScanTune), patIndex(0), activeFilters(0)
295 {
296 qCDebug(logDvb, "Use other NIT is %s", useOtherNit ? "enabled" : "disabled");
297 }
298
DvbScan(DvbDevice * device_,const QString & source_,const QString & autoScanSource,bool useOtherNit_)299 DvbScan::DvbScan(DvbDevice *device_, const QString &source_, const QString &autoScanSource, bool useOtherNit_) :
300 device(device_), source(source_), isLive(false), isAuto(true), useOtherNit(useOtherNit_), transponderIndex(0),
301 state(ScanTune), patIndex(0), activeFilters(0)
302 {
303 qCDebug(logDvb, "Use other NIT is %s", useOtherNit ? "enabled" : "disabled");
304
305 // Seek for DVB-T transponders
306
307 if ((autoScanSource == QLatin1String("AUTO-T-Normal")) ||
308 (autoScanSource == QLatin1String("AUTO-T-Offsets")) ||
309 (autoScanSource == QLatin1String("AUTO-T2-Normal")) ||
310 (autoScanSource == QLatin1String("AUTO-T2-Offsets"))) {
311 bool offsets = (autoScanSource == QLatin1String("AUTO-T-Offsets")) || (autoScanSource == QLatin1String("AUTO-T2-Offsets"));
312
313 for (int frequency = 177500000; frequency <= 226500000; frequency += 7000000) {
314 DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
315 DvbTTransponder *dvbTTransponder = currentTransponder.as<DvbTTransponder>();
316 dvbTTransponder->frequency = frequency;
317 dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth7MHz;
318 dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
319 dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
320 dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
321 dvbTTransponder->transmissionMode = DvbTTransponder::TransmissionModeAuto;
322 dvbTTransponder->guardInterval = DvbTTransponder::GuardIntervalAuto;
323 dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
324 transponders.append(currentTransponder);
325 }
326
327 for (int frequency = 474000000; frequency <= 858000000; frequency += 8000000) {
328 for (int i = 0; i < 3; ++i) {
329 if ((i != 0) && (!offsets)) {
330 break;
331 }
332
333 int offset = 0;
334
335 if (i == 1) {
336 offset = -167000;
337 } else if (i == 2) {
338 offset = 167000;
339 }
340
341 DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
342 DvbTTransponder *dvbTTransponder =
343 currentTransponder.as<DvbTTransponder>();
344 dvbTTransponder->frequency = frequency + offset;
345 dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth8MHz;
346 dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
347 dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
348 dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
349 dvbTTransponder->transmissionMode =
350 DvbTTransponder::TransmissionModeAuto;
351 dvbTTransponder->guardInterval =
352 DvbTTransponder::GuardIntervalAuto;
353 dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
354 transponders.append(currentTransponder);
355 }
356 }
357 } else if ((autoScanSource == QLatin1String("AUTO-T-Australia")) ||
358 (autoScanSource == QLatin1String("AUTO-T2-Australia"))) {
359 for (int frequency = 177500000; frequency <= 226500000; frequency += 7000000) {
360 for (int i = 0; i < 2; ++i) {
361 int offset = 0;
362
363 if (i == 1) {
364 offset = 125000;
365 }
366
367 DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
368 DvbTTransponder *dvbTTransponder =
369 currentTransponder.as<DvbTTransponder>();
370 dvbTTransponder->frequency = frequency + offset;
371 dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth7MHz;
372 dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
373 dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
374 dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
375 dvbTTransponder->transmissionMode =
376 DvbTTransponder::TransmissionModeAuto;
377 dvbTTransponder->guardInterval =
378 DvbTTransponder::GuardIntervalAuto;
379 dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
380 transponders.append(currentTransponder);
381 }
382 }
383
384 for (int frequency = 529500000; frequency <= 816500000; frequency += 7000000) {
385 for (int i = 0; i < 2; ++i) {
386 int offset = 0;
387
388 if (i == 1) {
389 offset = 125000;
390 }
391
392 DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
393 DvbTTransponder *dvbTTransponder =
394 currentTransponder.as<DvbTTransponder>();
395 dvbTTransponder->frequency = frequency + offset;
396 dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth7MHz;
397 dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
398 dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
399 dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
400 dvbTTransponder->transmissionMode =
401 DvbTTransponder::TransmissionModeAuto;
402 dvbTTransponder->guardInterval =
403 DvbTTransponder::GuardIntervalAuto;
404 dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
405 transponders.append(currentTransponder);
406 }
407 }
408 } else if ((autoScanSource == QLatin1String("AUTO-T-Italy")) ||
409 (autoScanSource == QLatin1String("AUTO-T2-Italy"))) {
410 static const int italyVhf[] = { 177500000, 186000000, 194500000, 203500000,
411 212500000, 219500000, 226500000 };
412
413 for (unsigned i = 0; i < (sizeof(italyVhf) / sizeof(italyVhf[0])); ++i) {
414 for (int j = 0; j < 2; ++j) {
415 DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
416 DvbTTransponder *dvbTTransponder =
417 currentTransponder.as<DvbTTransponder>();
418 dvbTTransponder->frequency = italyVhf[i];
419 dvbTTransponder->bandwidth = ((j == 0) ?
420 DvbTTransponder::Bandwidth7MHz :
421 DvbTTransponder::Bandwidth8MHz);
422 dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
423 dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
424 dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
425 dvbTTransponder->transmissionMode =
426 DvbTTransponder::TransmissionModeAuto;
427 dvbTTransponder->guardInterval =
428 DvbTTransponder::GuardIntervalAuto;
429 dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
430 transponders.append(currentTransponder);
431 }
432 }
433
434 for (int frequency = 474000000; frequency <= 858000000; frequency += 8000000) {
435 DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
436 DvbTTransponder *dvbTTransponder =
437 currentTransponder.as<DvbTTransponder>();
438 dvbTTransponder->frequency = frequency;
439 dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth8MHz;
440 dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
441 dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
442 dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
443 dvbTTransponder->transmissionMode = DvbTTransponder::TransmissionModeAuto;
444 dvbTTransponder->guardInterval = DvbTTransponder::GuardIntervalAuto;
445 dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
446 transponders.append(currentTransponder);
447 }
448 } else if ((autoScanSource == QLatin1String("AUTO-T-Taiwan"))||
449 (autoScanSource == QLatin1String("AUTO-T2-Taiwan"))) {
450 for (int frequency = 527000000; frequency <= 599000000; frequency += 6000000) {
451 DvbTransponder currentTransponder(DvbTransponderBase::DvbT);
452 DvbTTransponder *dvbTTransponder =
453 currentTransponder.as<DvbTTransponder>();
454 dvbTTransponder->frequency = frequency;
455 dvbTTransponder->bandwidth = DvbTTransponder::Bandwidth6MHz;
456 dvbTTransponder->modulation = DvbTTransponder::ModulationAuto;
457 dvbTTransponder->fecRateHigh = DvbTTransponder::FecAuto;
458 dvbTTransponder->fecRateLow = DvbTTransponder::FecNone;
459 dvbTTransponder->transmissionMode = DvbTTransponder::TransmissionModeAuto;
460 dvbTTransponder->guardInterval = DvbTTransponder::GuardIntervalAuto;
461 dvbTTransponder->hierarchy = DvbTTransponder::HierarchyNone;
462 transponders.append(currentTransponder);
463 }
464 }
465
466 // Seek for DVB-T2 transponders
467
468 if ((autoScanSource == QLatin1String("AUTO-T2-Normal")) ||
469 (autoScanSource == QLatin1String("AUTO-T2-Offsets"))) {
470 bool offsets = (autoScanSource == QLatin1String("AUTO-T2-Offsets"));
471
472 for (int frequency = 177500000; frequency <= 226500000; frequency += 7000000) {
473 DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
474 DvbT2Transponder *dvbT2Transponder = currentTransponder.as<DvbT2Transponder>();
475 dvbT2Transponder->frequency = frequency;
476 dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth7MHz;
477 dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
478 dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
479 dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
480 dvbT2Transponder->transmissionMode = DvbT2Transponder::TransmissionModeAuto;
481 dvbT2Transponder->guardInterval = DvbT2Transponder::GuardIntervalAuto;
482 dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
483 dvbT2Transponder->streamId = 0;
484 transponders.append(currentTransponder);
485 }
486
487 for (int frequency = 474000000; frequency <= 858000000; frequency += 8000000) {
488 for (int i = 0; i < 3; ++i) {
489 if ((i != 0) && (!offsets)) {
490 break;
491 }
492
493 int offset = 0;
494
495 if (i == 1) {
496 offset = -167000;
497 } else if (i == 2) {
498 offset = 167000;
499 }
500
501 DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
502 DvbT2Transponder *dvbT2Transponder = currentTransponder.as<DvbT2Transponder>();
503 dvbT2Transponder->frequency = frequency + offset;
504 dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth8MHz;
505 dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
506 dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
507 dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
508 dvbT2Transponder->transmissionMode = DvbT2Transponder::TransmissionModeAuto;
509 dvbT2Transponder->guardInterval = DvbT2Transponder::GuardIntervalAuto;
510 dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
511 dvbT2Transponder->streamId = 0;
512 transponders.append(currentTransponder);
513 }
514 }
515 } else if (autoScanSource == QLatin1String("AUTO-T2-Australia")) {
516 for (int frequency = 177500000; frequency <= 226500000; frequency += 7000000) {
517 for (int i = 0; i < 2; ++i) {
518 int offset = 0;
519
520 if (i == 1) {
521 offset = 125000;
522 }
523
524 DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
525 DvbT2Transponder *dvbT2Transponder =
526 currentTransponder.as<DvbT2Transponder>();
527 dvbT2Transponder->frequency = frequency + offset;
528 dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth7MHz;
529 dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
530 dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
531 dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
532 dvbT2Transponder->transmissionMode =
533 DvbT2Transponder::TransmissionModeAuto;
534 dvbT2Transponder->guardInterval =
535 DvbT2Transponder::GuardIntervalAuto;
536 dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
537 dvbT2Transponder->streamId = 0;
538 transponders.append(currentTransponder);
539 }
540 }
541
542 for (int frequency = 529500000; frequency <= 816500000; frequency += 7000000) {
543 for (int i = 0; i < 2; ++i) {
544 int offset = 0;
545
546 if (i == 1) {
547 offset = 125000;
548 }
549
550 DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
551 DvbT2Transponder *dvbT2Transponder =
552 currentTransponder.as<DvbT2Transponder>();
553 dvbT2Transponder->frequency = frequency + offset;
554 dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth7MHz;
555 dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
556 dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
557 dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
558 dvbT2Transponder->transmissionMode =
559 DvbT2Transponder::TransmissionModeAuto;
560 dvbT2Transponder->guardInterval =
561 DvbT2Transponder::GuardIntervalAuto;
562 dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
563 dvbT2Transponder->streamId = 0;
564 transponders.append(currentTransponder);
565 }
566 }
567 } else if (autoScanSource == QLatin1String("AUTO-T2-Italy")) {
568 static const int italyVhf[] = { 177500000, 186000000, 194500000, 203500000,
569 212500000, 219500000, 226500000 };
570
571 for (unsigned i = 0; i < (sizeof(italyVhf) / sizeof(italyVhf[0])); ++i) {
572 for (int j = 0; j < 2; ++j) {
573 DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
574 DvbT2Transponder *dvbT2Transponder =
575 currentTransponder.as<DvbT2Transponder>();
576 dvbT2Transponder->frequency = italyVhf[i];
577 dvbT2Transponder->bandwidth = ((j == 0) ?
578 DvbT2Transponder::Bandwidth7MHz :
579 DvbT2Transponder::Bandwidth8MHz);
580 dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
581 dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
582 dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
583 dvbT2Transponder->transmissionMode =
584 DvbT2Transponder::TransmissionModeAuto;
585 dvbT2Transponder->guardInterval =
586 DvbT2Transponder::GuardIntervalAuto;
587 dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
588 dvbT2Transponder->streamId = 0;
589 transponders.append(currentTransponder);
590 }
591 }
592
593 for (int frequency = 474000000; frequency <= 858000000; frequency += 8000000) {
594 DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
595 DvbT2Transponder *dvbT2Transponder =
596 currentTransponder.as<DvbT2Transponder>();
597 dvbT2Transponder->frequency = frequency;
598 dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth8MHz;
599 dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
600 dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
601 dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
602 dvbT2Transponder->transmissionMode = DvbT2Transponder::TransmissionModeAuto;
603 dvbT2Transponder->guardInterval = DvbT2Transponder::GuardIntervalAuto;
604 dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
605 dvbT2Transponder->streamId = 0;
606 transponders.append(currentTransponder);
607 }
608 } else if (autoScanSource == QLatin1String("AUTO-T2-Taiwan")) {
609 for (int frequency = 527000000; frequency <= 599000000; frequency += 6000000) {
610 DvbTransponder currentTransponder(DvbTransponderBase::DvbT2);
611 DvbT2Transponder *dvbT2Transponder =
612 currentTransponder.as<DvbT2Transponder>();
613 dvbT2Transponder->frequency = frequency;
614 dvbT2Transponder->bandwidth = DvbT2Transponder::Bandwidth6MHz;
615 dvbT2Transponder->modulation = DvbT2Transponder::ModulationAuto;
616 dvbT2Transponder->fecRateHigh = DvbT2Transponder::FecAuto;
617 dvbT2Transponder->fecRateLow = DvbT2Transponder::FecNone;
618 dvbT2Transponder->transmissionMode = DvbT2Transponder::TransmissionModeAuto;
619 dvbT2Transponder->guardInterval = DvbT2Transponder::GuardIntervalAuto;
620 dvbT2Transponder->hierarchy = DvbT2Transponder::HierarchyNone;
621 dvbT2Transponder->streamId = 0;
622 transponders.append(currentTransponder);
623 }
624 }
625
626 // Seek for ISDB-T transponders
627
628 if (autoScanSource == QLatin1String("AUTO-UHF-6MHz")) {
629 for (int frequency = 473142857; frequency <= 803142857; frequency += 6000000) {
630 DvbTransponder currentTransponder(DvbTransponderBase::IsdbT);
631 IsdbTTransponder *isdbTTransponder =
632 currentTransponder.as<IsdbTTransponder>();
633 isdbTTransponder->frequency = frequency;
634 isdbTTransponder->bandwidth = IsdbTTransponder::Bandwidth6MHz;
635 isdbTTransponder->transmissionMode = IsdbTTransponder::TransmissionModeAuto;
636 isdbTTransponder->guardInterval = IsdbTTransponder::GuardIntervalAuto;
637 isdbTTransponder->partialReception = IsdbTTransponder::PR_AUTO;
638 isdbTTransponder->soundBroadcasting = IsdbTTransponder::SB_disabled;
639 for (int i = 0; i < 3; i++) {
640 isdbTTransponder->layerEnabled[i] = true;
641 isdbTTransponder->modulation[i] = IsdbTTransponder::ModulationAuto;
642 isdbTTransponder->fecRate[i] = IsdbTTransponder::FecAuto;
643 isdbTTransponder->interleaving[i] = IsdbTTransponder::I_AUTO;
644 isdbTTransponder->segmentCount[i] = 15;
645 }
646 transponders.append(currentTransponder);
647 }
648 }
649 }
650
~DvbScan()651 DvbScan::~DvbScan()
652 {
653 qDeleteAll(filters);
654 }
655
start()656 void DvbScan::start()
657 {
658 connect(device, SIGNAL(stateChanged()), this, SLOT(deviceStateChanged()));
659 updateState();
660 }
661
deviceStateChanged()662 void DvbScan::deviceStateChanged()
663 {
664 if (device->getDeviceState() == DvbDevice::DeviceReleased) {
665 qCWarning(logDvb, "Device was released. Stopping scan");
666 emit scanFinished();
667 return;
668 }
669
670 if (state == ScanTuning) {
671 updateState();
672 }
673 }
674
startFilter(int pid,FilterType type)675 bool DvbScan::startFilter(int pid, FilterType type)
676 {
677 if (activeFilters != filters.size()) {
678 foreach (DvbScanFilter *filter, filters) {
679 if (!filter->isActive()) {
680 if (!filter->startFilter(pid, type)) {
681 return false;
682 }
683
684 ++activeFilters;
685 return true;
686 }
687 }
688
689 Q_ASSERT(false);
690 } else if (activeFilters < 10) {
691 DvbScanFilter *filter = new DvbScanFilter(this, useOtherNit);
692
693 if (!filter->startFilter(pid, type)) {
694 delete filter;
695 return false;
696 }
697
698 filters.append(filter);
699 ++activeFilters;
700 return true;
701 }
702
703 return false;
704 }
705
updateState()706 void DvbScan::updateState()
707 {
708 while (true) {
709 switch (state) {
710 case ScanPat: {
711 if (!startFilter(0x0, PatFilter)) {
712 return;
713 }
714
715 snr = device->getSnr(scale);
716
717 state = ScanNit;
718 }
719 // fall through
720 case ScanNit: {
721 if (!isLive && !isAuto &&
722 (transponder.getTransmissionType() != DvbTransponderBase::Atsc)) {
723 if (!startFilter(0x10, NitFilter)) {
724 return;
725 }
726 }
727
728 state = ScanSdt;
729 }
730 // fall through
731 case ScanSdt: {
732 if (transponder.getTransmissionType() != DvbTransponderBase::Atsc) {
733 if (!startFilter(0x11, SdtFilter)) {
734 return;
735 }
736 } else {
737 if (!startFilter(0x1ffb, VctFilter)) {
738 return;
739 }
740 }
741
742 state = ScanPmt;
743 }
744 // fall through
745 case ScanPmt: {
746 while (patIndex < patEntries.size()) {
747 if (!startFilter(patEntries.at(patIndex).pid, PmtFilter)) {
748 return;
749 }
750
751 ++patIndex;
752 }
753
754 if (activeFilters != 0) {
755 return;
756 }
757
758 for (int i = 0; i < channels.size(); ++i) {
759 DvbPreviewChannel &channel = channels[i];
760
761 foreach (const DvbSdtEntry &sdtEntry, sdtEntries) {
762 if (channel.serviceId == sdtEntry.serviceId) {
763 channel.name = sdtEntry.name;
764 channel.networkId = sdtEntry.networkId;
765 channel.isScrambled = sdtEntry.scrambled;
766 channel.provider = sdtEntry.provider;
767 break;
768 }
769 }
770
771 if (channel.name.isEmpty()) {
772 channel.name = QString(QLatin1String("#0 %1:%2")).
773 arg(channel.transportStreamId).
774 arg(channel.serviceId);
775 }
776 qCDebug(logDvb, "Found channel %s", qPrintable(channel.name));
777 }
778
779 if (!channels.isEmpty()) {
780 emit foundChannels(channels);
781 }
782
783 if (isLive) {
784 qCInfo(logDvb, "Scanning while live stream. Can't change the transponder");
785 emit scanFinished();
786 return;
787 }
788
789 patEntries.clear();
790 patIndex = 0;
791 sdtEntries.clear();
792 channels.clear();
793
794 state = ScanTune;
795 }
796 // fall through
797 case ScanTune: {
798 if (transponders.size() > 0) {
799 emit scanProgress((100 * transponderIndex) / transponders.size());
800 }
801
802 qCDebug(logDvb, "Transponder %d/%d", transponderIndex, transponders.size());
803 if (transponderIndex >= transponders.size()) {
804 emit scanFinished();
805 return;
806 }
807
808 transponder = transponders.at(transponderIndex);
809 ++transponderIndex;
810
811 state = ScanTuning;
812
813 if (!isAuto) {
814 device->tune(transponder);
815 } else {
816 device->autoTune(transponder);
817 }
818
819 return;
820 }
821
822 case ScanTuning: {
823 switch (device->getDeviceState()) {
824 case DvbDevice::DeviceIdle:
825 state = ScanTune;
826 break;
827
828 case DvbDevice::DeviceTuned:
829 if (isAuto) {
830 transponders[transponderIndex - 1] =
831 device->getAutoTransponder();
832 }
833
834 state = ScanPat;
835 break;
836
837 default:
838 return;
839 }
840
841 break;
842 }
843 }
844 }
845 }
846
processPat(const DvbPatSection & section)847 void DvbScan::processPat(const DvbPatSection §ion)
848 {
849 transportStreamId = section.transportStreamId();
850
851 for (DvbPatSectionEntry entry = section.entries(); entry.isValid(); entry.advance()) {
852 if (entry.programNumber() != 0x0) {
853 // skip 0x0 which has a special meaning
854 patEntries.append(DvbPatEntry(entry.programNumber(), entry.pid()));
855
856 qCDebug(logDvb, "New PAT entry: pid %d, program %d", entry.pid(), entry.programNumber());
857 }
858 }
859 }
860
processPmt(const DvbPmtSection & section,int pid)861 void DvbScan::processPmt(const DvbPmtSection §ion, int pid)
862 {
863 DvbPreviewChannel channel;
864
865 DvbPmtParser parser(section);
866 channel.hasVideo = (parser.videoPid >= 0);
867
868 if (!parser.audioPids.isEmpty()) {
869 channel.audioPid = parser.audioPids.at(0).first;
870 }
871
872 if (channel.hasVideo || (channel.audioPid >= 0)) {
873 channel.source = source;
874 channel.transponder = transponder;
875 channel.transportStreamId = transportStreamId;
876 channel.pmtPid = pid;
877 channel.pmtSectionData = section.toByteArray();
878 channel.serviceId = section.programNumber();
879 switch (scale) {
880 case DvbBackendDevice::dBuV:
881 case DvbBackendDevice::NotSupported: {
882 channel.snr = "";
883 break;
884 }
885 case DvbBackendDevice::Percentage: {
886 channel.snr = QString::number(snr, 'f', 0) + '%';
887 break;
888 }
889 case DvbBackendDevice::Decibel: {
890 channel.snr = QString::number(snr, 'f', 2) + " dB";
891 break;
892 }
893 };
894 channels.append(channel);
895
896 qCDebug(logDvb, "New channel: PID %d, service ID %d", pid, section.programNumber());
897 }
898 }
899
processSdt(const DvbSdtSection & section)900 void DvbScan::processSdt(const DvbSdtSection §ion)
901 {
902 for (DvbSdtSectionEntry entry = section.entries(); entry.isValid(); entry.advance()) {
903 DvbSdtEntry sdtEntry(entry.serviceId(), section.originalNetworkId(),
904 entry.isScrambled());
905
906 for (DvbDescriptor descriptor = entry.descriptors(); descriptor.isValid();
907 descriptor.advance()) {
908 if (descriptor.descriptorTag() != 0x48) {
909 continue;
910 }
911
912 DvbServiceDescriptor serviceDescriptor(descriptor);
913
914 if (!serviceDescriptor.isValid()) {
915 continue;
916 }
917
918 sdtEntry.name = serviceDescriptor.serviceName();
919 sdtEntry.provider = serviceDescriptor.providerName();
920
921 qCDebug(logDvb, "New SDT entry: service ID 0x%04x, name '%s', provider '%s'", entry.serviceId(), qPrintable(sdtEntry.name), qPrintable(sdtEntry.provider));
922 sdtEntries.append(sdtEntry);
923 }
924 }
925 }
926
processVct(const AtscVctSection & section)927 void DvbScan::processVct(const AtscVctSection §ion)
928 {
929 AtscVctSectionEntry entry = section.entries();
930 int entryCount = section.entryCount();
931
932 for (int i = 0; i < entryCount && (entry.isValid()); i++) {
933 QString majorminor = QString(QLatin1String("%1-%2 ")).
934 arg(entry.majorNumber(), 3, 10, QLatin1Char('0')).arg(entry.minorNumber());
935
936 DvbSdtEntry sdtEntry(entry.programNumber(), entry.sourceId(), entry.isScrambled());
937
938 // Each VCT section has it's own list of descriptors
939 // See A/65C table 6.25a for the list of descriptors
940 for (DvbDescriptor descriptor = entry.descriptors(); descriptor.isValid();
941 descriptor.advance()) {
942 if (descriptor.descriptorTag() == 0xa0) {
943 // Extended Channel Name Descriptor
944 AtscChannelNameDescriptor nameDescriptor(descriptor);
945 if (!nameDescriptor.isValid()) {
946 continue;
947 }
948 sdtEntry.name = majorminor + nameDescriptor.name();
949 }
950 }
951
952 if (sdtEntry.name.isEmpty()) {
953 // Extended Channel name not available, fall back
954 // to the short name
955 QChar shortName[] = { entry.shortName1(),
956 entry.shortName2(),
957 entry.shortName3(),
958 entry.shortName4(),
959 entry.shortName5(),
960 entry.shortName6(),
961 entry.shortName7(), 0 };
962 int nameLength = 0;
963 while (shortName[nameLength] != 0) {
964 ++nameLength;
965 }
966 sdtEntry.name = majorminor + QString(shortName, nameLength);
967 }
968
969 qCDebug(logDvb, "New SDT entry: name %s", qPrintable(sdtEntry.name));
970 sdtEntries.append(sdtEntry);
971
972 if (i < entryCount - 1)
973 entry.advance();
974 }
975 }
976
processNit(const DvbNitSection & section)977 void DvbScan::processNit(const DvbNitSection §ion)
978 {
979 for (DvbNitSectionEntry entry = section.entries(); entry.isValid(); entry.advance()) {
980 for (DvbDescriptor descriptor = entry.descriptors(); descriptor.isValid();
981 descriptor.advance()) {
982 processNitDescriptor(descriptor);
983 }
984 }
985 }
986
extractDvbCModulation(const DvbCableDescriptor & descriptor)987 static DvbCTransponder::Modulation extractDvbCModulation(const DvbCableDescriptor &descriptor)
988 {
989 switch (descriptor.modulation()) {
990 case 1:
991 return DvbCTransponder::Qam16;
992 case 2:
993 return DvbCTransponder::Qam32;
994 case 3:
995 return DvbCTransponder::Qam64;
996 case 4:
997 return DvbCTransponder::Qam128;
998 case 5:
999 return DvbCTransponder::Qam256;
1000 default:
1001 return DvbCTransponder::ModulationAuto;
1002 }
1003 }
1004
extractDvbCFecRate(const DvbCableDescriptor & descriptor)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
extractDvbSPolarization(const DvbSatelliteDescriptor & descriptor)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
extractDvbSFecRate(const DvbSatelliteDescriptor & descriptor)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
extractDvbS2Modulation(const DvbSatelliteDescriptor & descriptor)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
extractDvbS2RollOff(const DvbSatelliteDescriptor & descriptor)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
extractDvbTBandwidth(const DvbTerrestrialDescriptor & descriptor)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
extractDvbTModulation(const DvbTerrestrialDescriptor & descriptor)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
extractDvbTFecRateHigh(const DvbTerrestrialDescriptor & descriptor)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
extractDvbTFecRateLow(const DvbTerrestrialDescriptor & descriptor)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
extractDvbTTransmissionMode(const DvbTerrestrialDescriptor & descriptor)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
extractDvbTGuardInterval(const DvbTerrestrialDescriptor & descriptor)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
extractDvbTHierarchy(const DvbTerrestrialDescriptor & descriptor)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
processNitDescriptor(const DvbDescriptor & descriptor)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
filterFinished(DvbScanFilter * filter)1377 void DvbScan::filterFinished(DvbScanFilter *filter)
1378 {
1379 filter->stopFilter();
1380 --activeFilters;
1381 updateState();
1382 }
1383