1 /*
2  * dvbtransponder.cpp
3  *
4  * Copyright (C) 2007-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 <QDataStream>
22 #include <QTextStream>
23 #include <stdint.h>
24 
25 #include "dvbtransponder.h"
26 
enumToLinuxtv(DvbTransponderBase::FecRate fecRate)27 static const char *enumToLinuxtv(DvbTransponderBase::FecRate fecRate)
28 {
29 	switch (fecRate) {
30 	case DvbTransponderBase::FecNone: return "NONE";
31 	case DvbTransponderBase::Fec1_2: return "1/2";
32 	case DvbTransponderBase::Fec1_3: return "1/3";
33 	case DvbTransponderBase::Fec1_4: return "1/4";
34 	case DvbTransponderBase::Fec2_3: return "2/3";
35 	case DvbTransponderBase::Fec2_5: return "2/5";
36 	case DvbTransponderBase::Fec3_4: return "3/4";
37 	case DvbTransponderBase::Fec3_5: return "3/5";
38 	case DvbTransponderBase::Fec4_5: return "4/5";
39 	case DvbTransponderBase::Fec5_6: return "5/6";
40 	case DvbTransponderBase::Fec6_7: return "6/7";
41 	case DvbTransponderBase::Fec7_8: return "7/8";
42 	case DvbTransponderBase::Fec8_9: return "8/9";
43 	case DvbTransponderBase::Fec9_10: return "9/10";
44 	case DvbTransponderBase::FecAuto: return "AUTO";
45 	}
46 
47 	return NULL;
48 }
49 
enumToLinuxtv(DvbCTransponder::Modulation modulation)50 static const char *enumToLinuxtv(DvbCTransponder::Modulation modulation)
51 {
52 	switch (modulation) {
53 	case DvbCTransponder::Qam16: return "QAM16";
54 	case DvbCTransponder::Qam32: return "QAM32";
55 	case DvbCTransponder::Qam64: return "QAM64";
56 	case DvbCTransponder::Qam128: return "QAM128";
57 	case DvbCTransponder::Qam256: return "QAM256";
58 	case DvbCTransponder::ModulationAuto: return "AUTO";
59 	}
60 
61 	return NULL;
62 }
63 
enumToLinuxtv(DvbSTransponder::Polarization polarization)64 static const char *enumToLinuxtv(DvbSTransponder::Polarization polarization)
65 {
66 	switch (polarization) {
67 	case DvbSTransponder::Horizontal: return "H";
68 	case DvbSTransponder::Vertical: return "V";
69 	case DvbSTransponder::CircularLeft: return "L";
70 	case DvbSTransponder::CircularRight: return "R";
71 	case DvbSTransponder::Off: return "-";
72 	}
73 
74 	return NULL;
75 }
76 
enumToLinuxtv(DvbS2Transponder::Modulation modulation)77 static const char *enumToLinuxtv(DvbS2Transponder::Modulation modulation)
78 {
79 	switch (modulation) {
80 	case DvbS2Transponder::Qpsk: return "QPSK";
81 	case DvbS2Transponder::Psk8: return "8PSK";
82 	case DvbS2Transponder::Apsk16: return "16APSK";
83 	case DvbS2Transponder::Apsk32: return "32APSK";
84 	case DvbS2Transponder::ModulationAuto: return "AUTO";
85 	}
86 
87 	return NULL;
88 }
89 
enumToLinuxtv(DvbS2Transponder::RollOff rollOff)90 static const char *enumToLinuxtv(DvbS2Transponder::RollOff rollOff)
91 {
92 	switch (rollOff) {
93 	case DvbS2Transponder::RollOff20: return "20";
94 	case DvbS2Transponder::RollOff25: return "25";
95 	case DvbS2Transponder::RollOff35: return "35";
96 	case DvbS2Transponder::RollOffAuto: return "AUTO";
97 	}
98 
99 	return NULL;
100 }
101 
enumToLinuxtv(DvbTTransponder::Bandwidth bandwidth)102 static const char *enumToLinuxtv(DvbTTransponder::Bandwidth bandwidth)
103 {
104 	switch (bandwidth) {
105 	case DvbTTransponder::Bandwidth5MHz: return "5MHz";
106 	case DvbTTransponder::Bandwidth6MHz: return "6MHz";
107 	case DvbTTransponder::Bandwidth7MHz: return "7MHz";
108 	case DvbTTransponder::Bandwidth8MHz: return "8MHz";
109 	case DvbTTransponder::BandwidthAuto: return "AUTO";
110 	}
111 
112 	return NULL;
113 }
114 
enumToLinuxtv(DvbTTransponder::Modulation modulation)115 static const char *enumToLinuxtv(DvbTTransponder::Modulation modulation)
116 {
117 	switch (modulation) {
118 	case DvbTTransponder::Qpsk: return "QPSK";
119 	case DvbTTransponder::Qam16: return "QAM16";
120 	case DvbTTransponder::Qam64: return "QAM64";
121 	case DvbTTransponder::ModulationAuto: return "AUTO";
122 	}
123 
124 	return NULL;
125 }
126 
enumToLinuxtv(DvbTTransponder::TransmissionMode transmissionMode)127 static const char *enumToLinuxtv(DvbTTransponder::TransmissionMode transmissionMode)
128 {
129 	switch (transmissionMode) {
130 	case DvbTTransponder::TransmissionMode2k: return "2k";
131 	case DvbTTransponder::TransmissionMode4k: return "4k";
132 	case DvbTTransponder::TransmissionMode8k: return "8k";
133 	case DvbTTransponder::TransmissionModeAuto: return "AUTO";
134 	}
135 
136 	return NULL;
137 }
138 
enumToLinuxtv(DvbTTransponder::GuardInterval guardInterval)139 static const char *enumToLinuxtv(DvbTTransponder::GuardInterval guardInterval)
140 {
141 	switch (guardInterval) {
142 	case DvbTTransponder::GuardInterval1_4: return "1/4";
143 	case DvbTTransponder::GuardInterval1_8: return "1/8";
144 	case DvbTTransponder::GuardInterval1_16: return "1/16";
145 	case DvbTTransponder::GuardInterval1_32: return "1/32";
146 	case DvbTTransponder::GuardIntervalAuto: return "AUTO";
147 	}
148 
149 	return NULL;
150 }
151 
enumToLinuxtv(DvbTTransponder::Hierarchy hierarchy)152 static const char *enumToLinuxtv(DvbTTransponder::Hierarchy hierarchy)
153 {
154 	switch (hierarchy) {
155 	case DvbTTransponder::HierarchyNone: return "NONE";
156 	case DvbTTransponder::Hierarchy1: return "1";
157 	case DvbTTransponder::Hierarchy2: return "2";
158 	case DvbTTransponder::Hierarchy4: return "4";
159 	case DvbTTransponder::HierarchyAuto: return "AUTO";
160 	}
161 
162 	return NULL;
163 }
164 
enumToLinuxtv(DvbT2Transponder::Bandwidth bandwidth)165 static const char *enumToLinuxtv(DvbT2Transponder::Bandwidth bandwidth)
166 {
167 	switch (bandwidth) {
168 	case DvbT2Transponder::Bandwidth1_7MHz: return "1.7MHz";
169 	case DvbT2Transponder::Bandwidth5MHz: return "5MHz";
170 	case DvbT2Transponder::Bandwidth6MHz: return "6MHz";
171 	case DvbT2Transponder::Bandwidth7MHz: return "7MHz";
172 	case DvbT2Transponder::Bandwidth8MHz: return "8MHz";
173 	case DvbT2Transponder::Bandwidth10MHz: return "10MHz";
174 	case DvbT2Transponder::BandwidthAuto: return "AUTO";
175 	}
176 
177 	return NULL;
178 }
179 
enumToLinuxtv(DvbT2Transponder::Modulation modulation)180 static const char *enumToLinuxtv(DvbT2Transponder::Modulation modulation)
181 {
182 	switch (modulation) {
183 	case DvbT2Transponder::Qpsk: return "QPSK";
184 	case DvbT2Transponder::Qam16: return "QAM16";
185 	case DvbT2Transponder::Qam64: return "QAM64";
186 	case DvbT2Transponder::Qam256: return "QAM256";
187 	case DvbT2Transponder::ModulationAuto: return "AUTO";
188 	}
189 
190 	return NULL;
191 }
192 
enumToLinuxtv(DvbT2Transponder::TransmissionMode transmissionMode)193 static const char *enumToLinuxtv(DvbT2Transponder::TransmissionMode transmissionMode)
194 {
195 	switch (transmissionMode) {
196 	case DvbT2Transponder::TransmissionMode1k: return "1k";
197 	case DvbT2Transponder::TransmissionMode2k: return "2k";
198 	case DvbT2Transponder::TransmissionMode4k: return "4k";
199 	case DvbT2Transponder::TransmissionMode8k: return "8k";
200 	case DvbT2Transponder::TransmissionMode16k: return "16k";
201 	case DvbT2Transponder::TransmissionMode32k: return "32k";
202 	case DvbT2Transponder::TransmissionModeAuto: return "AUTO";
203 	}
204 
205 	return NULL;
206 }
207 
enumToLinuxtv(DvbT2Transponder::GuardInterval guardInterval)208 static const char *enumToLinuxtv(DvbT2Transponder::GuardInterval guardInterval)
209 {
210 	switch (guardInterval) {
211 	case DvbT2Transponder::GuardInterval1_4:	return "1/4";
212 	case DvbT2Transponder::GuardInterval19_128:	return "19/128";
213 	case DvbT2Transponder::GuardInterval1_8:	return "1/8";
214 	case DvbT2Transponder::GuardInterval19_256:	return "19/256";
215 	case DvbT2Transponder::GuardInterval1_16:	return "1/16";
216 	case DvbT2Transponder::GuardInterval1_32:	return "1/32";
217 	case DvbT2Transponder::GuardInterval1_128:	return "1/128";
218 	case DvbT2Transponder::GuardIntervalAuto:	return "AUTO";
219 	}
220 
221 	return NULL;
222 }
223 
enumToLinuxtv(DvbT2Transponder::Hierarchy hierarchy)224 static const char *enumToLinuxtv(DvbT2Transponder::Hierarchy hierarchy)
225 {
226 	switch (hierarchy) {
227 	case DvbT2Transponder::HierarchyNone: return "NONE";
228 	case DvbT2Transponder::Hierarchy1: return "1";
229 	case DvbT2Transponder::Hierarchy2: return "2";
230 	case DvbT2Transponder::Hierarchy4: return "4";
231 	case DvbT2Transponder::HierarchyAuto: return "AUTO";
232 	}
233 
234 	return NULL;
235 }
236 
enumToLinuxtv(IsdbTTransponder::Bandwidth bandwidth)237 static const char *enumToLinuxtv(IsdbTTransponder::Bandwidth bandwidth)
238 {
239 	switch (bandwidth) {
240 	case IsdbTTransponder::Bandwidth6MHz: return "6MHz";
241 	case IsdbTTransponder::Bandwidth7MHz: return "7MHz";
242 	case IsdbTTransponder::Bandwidth8MHz: return "8MHz";
243 	}
244 
245 	return NULL;
246 }
247 
enumToLinuxtv(IsdbTTransponder::Modulation modulation)248 static const char *enumToLinuxtv(IsdbTTransponder::Modulation modulation)
249 {
250 	switch (modulation) {
251 	case IsdbTTransponder::Qpsk: return "QPSK";
252 	case IsdbTTransponder::Dqpsk: return "DQPSK";
253 	case IsdbTTransponder::Qam16: return "QAM16";
254 	case IsdbTTransponder::Qam64: return "QAM64";
255 	case IsdbTTransponder::ModulationAuto: return "AUTO";
256 	}
257 
258 	return NULL;
259 }
260 
enumToLinuxtv(IsdbTTransponder::TransmissionMode transmissionMode)261 static const char *enumToLinuxtv(IsdbTTransponder::TransmissionMode transmissionMode)
262 {
263 	switch (transmissionMode) {
264 	case IsdbTTransponder::TransmissionMode2k: return "2k";
265 	case IsdbTTransponder::TransmissionMode4k: return "4k";
266 	case IsdbTTransponder::TransmissionMode8k: return "8k";
267 	case IsdbTTransponder::TransmissionModeAuto: return "AUTO";
268 	}
269 
270 	return NULL;
271 }
272 
enumToLinuxtv(IsdbTTransponder::GuardInterval guardInterval)273 static const char *enumToLinuxtv(IsdbTTransponder::GuardInterval guardInterval)
274 {
275 	switch (guardInterval) {
276 	case IsdbTTransponder::GuardInterval1_4: return "1/4";
277 	case IsdbTTransponder::GuardInterval1_8: return "1/8";
278 	case IsdbTTransponder::GuardInterval1_16: return "1/16";
279 	case IsdbTTransponder::GuardInterval1_32: return "1/32";
280 	case IsdbTTransponder::GuardIntervalAuto: return "AUTO";
281 	}
282 
283 	return NULL;
284 }
285 
enumToLinuxtv(IsdbTTransponder::Interleaving interleaving)286 static const char *enumToLinuxtv(IsdbTTransponder::Interleaving interleaving)
287 {
288 	switch (interleaving) {
289 	case IsdbTTransponder::I_0: return "0";
290 	case IsdbTTransponder::I_1: return "1";
291 	case IsdbTTransponder::I_2: return "2";
292 	case IsdbTTransponder::I_4: return "4";
293 	case IsdbTTransponder::I_8: return "8";
294 	case IsdbTTransponder::I_16: return "16";
295 	case IsdbTTransponder::I_AUTO: return "AUTO";
296 	}
297 
298 	return NULL;
299 }
300 
enumToLinuxtv(IsdbTTransponder::PartialReception partialReception)301 static const char *enumToLinuxtv(IsdbTTransponder::PartialReception partialReception)
302 {
303 	switch (partialReception) {
304 	case IsdbTTransponder::PR_disabled: return "0";
305 	case IsdbTTransponder::PR_enabled: return "1";
306 	case IsdbTTransponder::PR_AUTO: return "AUTO";
307 	}
308 
309 	return NULL;
310 }
311 
enumToLinuxtv(IsdbTTransponder::SoundBroadcasting soundBroadcasting)312 static const char *enumToLinuxtv(IsdbTTransponder::SoundBroadcasting soundBroadcasting)
313 {
314 	switch (soundBroadcasting) {
315 	case IsdbTTransponder::SB_disabled: return "0";
316 	case IsdbTTransponder::SB_enabled: return "1";
317 	case IsdbTTransponder::SB_AUTO: return "AUTO";
318 	}
319 
320 	return NULL;
321 }
322 
enumToLinuxtv(AtscTransponder::Modulation modulation)323 static const char *enumToLinuxtv(AtscTransponder::Modulation modulation)
324 {
325 	switch (modulation) {
326 	case AtscTransponder::Qam64: return "QAM64";
327 	case AtscTransponder::Qam256: return "QAM256";
328 	case AtscTransponder::Vsb8: return "8VSB";
329 	case AtscTransponder::Vsb16: return "16VSB";
330 	case AtscTransponder::ModulationAuto: return "AUTO";
331 	}
332 
333 	return NULL;
334 }
335 
readEnum(QDataStream & stream)336 template<class T> static T readEnum(QDataStream &stream)
337 {
338 	int intValue;
339 	stream >> intValue;
340 	T value = static_cast<T>(intValue);
341 
342 	if ((value != intValue) || (enumToLinuxtv(value) == NULL)) {
343 		stream.setStatus(QDataStream::ReadCorruptData);
344 	}
345 
346 	return value;
347 }
348 
349 class DvbChannelStringReader
350 {
351 public:
DvbChannelStringReader(const QString & string_)352 	explicit DvbChannelStringReader(const QString &string_) : string(string_)
353 	{
354 		stream.setString(&string);
355 		stream.setIntegerBase(10);
356 	}
357 
~DvbChannelStringReader()358 	~DvbChannelStringReader() { }
359 
isValid() const360 	bool isValid() const
361 	{
362 		return (stream.status() == QTextStream::Ok);
363 	}
364 
readInt(int & value)365 	void readInt(int &value)
366 	{
367 		stream >> value;
368 	}
369 
readEnum()370 	template<class T> T readEnum()
371 	{
372 		QString token;
373 		stream >> token;
374 
375 		for (int i = 0;; ++i) {
376 			T value = static_cast<T>(i);
377 
378 			if (value != i) {
379 				break;
380 			}
381 
382 			const char *entry = enumToLinuxtv(value);
383 
384 			if (entry == NULL) {
385 				break;
386 			}
387 
388 			if (token == QLatin1String(entry)) {
389 				return value;
390 			}
391 		}
392 
393 		stream.setStatus(QTextStream::ReadCorruptData);
394 		return T();
395 	}
396 
checkChar(const QChar & value)397 	void checkChar(const QChar &value)
398 	{
399 		QString token;
400 		stream >> token;
401 
402 		if (token != value) {
403 			stream.setStatus(QTextStream::ReadCorruptData);
404 		}
405 	}
406 
checkString(const QString & value)407 	void checkString(const QString &value)
408 	{
409 		QString token;
410 		stream >> token;
411 
412 		if (token != value) {
413 			stream.setStatus(QTextStream::ReadCorruptData);
414 		}
415 	}
416 
417 private:
418 	QString string;
419 	QTextStream stream;
420 };
421 
422 class DvbChannelStringWriter
423 {
424 public:
DvbChannelStringWriter()425 	DvbChannelStringWriter()
426 	{
427 		stream.setString(&string);
428 	}
429 
~DvbChannelStringWriter()430 	~DvbChannelStringWriter() { }
431 
getString()432 	QString getString()
433 	{
434 		string.chop(1);
435 		return string;
436 	}
437 
writeInt(int value)438 	void writeInt(int value)
439 	{
440 		stream << value << ' ';
441 	}
442 
writeEnum(T value)443 	template<class T> void writeEnum(T value)
444 	{
445 		stream << enumToLinuxtv(value) << ' ';
446 	}
447 
writeChar(const QChar & value)448 	void writeChar(const QChar &value)
449 	{
450 		stream << value << ' ';
451 	}
452 
writeString(const QString & value)453 	void writeString(const QString &value)
454 	{
455 		stream << value << ' ';
456 	}
457 
458 private:
459 	QString string;
460 	QTextStream stream;
461 };
462 
readTransponder(QDataStream & stream)463 void DvbCTransponder::readTransponder(QDataStream &stream)
464 {
465 	stream >> frequency;
466 	stream >> symbolRate;
467 	modulation = readEnum<Modulation>(stream);
468 	fecRate = readEnum<FecRate>(stream);
469 }
470 
fromString(const QString & string)471 bool DvbCTransponder::fromString(const QString &string)
472 {
473 	DvbChannelStringReader reader(string);
474 	reader.checkChar(QLatin1Char('C'));
475 	reader.readInt(frequency);
476 	reader.readInt(symbolRate);
477 	fecRate = reader.readEnum<FecRate>();
478 	modulation = reader.readEnum<Modulation>();
479 	return reader.isValid();
480 }
481 
toString() const482 QString DvbCTransponder::toString() const
483 {
484 	DvbChannelStringWriter writer;
485 	writer.writeChar(QLatin1Char('C'));
486 	writer.writeInt(frequency);
487 	writer.writeInt(symbolRate);
488 	writer.writeEnum(fecRate);
489 	writer.writeEnum(modulation);
490 	return writer.getString();
491 }
492 
corresponds(const DvbTransponder & transponder) const493 bool DvbCTransponder::corresponds(const DvbTransponder &transponder) const
494 {
495 	const DvbCTransponder *dvbCTransponder = transponder.as<DvbCTransponder>();
496 
497 	return ((dvbCTransponder != NULL) &&
498 		(qAbs(dvbCTransponder->frequency - frequency) <= 2000000));
499 }
500 
readTransponder(QDataStream & stream)501 void DvbSTransponder::readTransponder(QDataStream &stream)
502 {
503 	polarization = readEnum<Polarization>(stream);
504 	stream >> frequency;
505 	stream >> symbolRate;
506 	fecRate = readEnum<FecRate>(stream);
507 }
508 
fromString(const QString & string)509 bool DvbSTransponder::fromString(const QString &string)
510 {
511 	DvbChannelStringReader reader(string);
512 	reader.checkChar(QLatin1Char('S'));
513 	reader.readInt(frequency);
514 	polarization = reader.readEnum<Polarization>();
515 	reader.readInt(symbolRate);
516 	fecRate = reader.readEnum<FecRate>();
517 	return reader.isValid();
518 }
519 
toString() const520 QString DvbSTransponder::toString() const
521 {
522 	DvbChannelStringWriter writer;
523 	writer.writeChar(QLatin1Char('S'));
524 	writer.writeInt(frequency);
525 	writer.writeEnum(polarization);
526 	writer.writeInt(symbolRate);
527 	writer.writeEnum(fecRate);
528 	return writer.getString();
529 }
530 
corresponds(const DvbTransponder & transponder) const531 bool DvbSTransponder::corresponds(const DvbTransponder &transponder) const
532 {
533 	const DvbSTransponder *dvbSTransponder = transponder.as<DvbSTransponder>();
534 
535 	return ((dvbSTransponder != NULL) &&
536 		(dvbSTransponder->polarization == polarization) &&
537 		(qAbs(dvbSTransponder->frequency - frequency) <= 2000));
538 }
539 
readTransponder(QDataStream & stream)540 void DvbS2Transponder::readTransponder(QDataStream &stream)
541 {
542 	polarization = readEnum<Polarization>(stream);
543 	stream >> frequency;
544 	stream >> symbolRate;
545 	fecRate = readEnum<FecRate>(stream);
546 	modulation = readEnum<Modulation>(stream);
547 	rollOff = readEnum<RollOff>(stream);
548 }
549 
fromString(const QString & string)550 bool DvbS2Transponder::fromString(const QString &string)
551 {
552 	DvbChannelStringReader reader(string);
553 	reader.checkString(QLatin1String("S2"));
554 	reader.readInt(frequency);
555 	polarization = reader.readEnum<Polarization>();
556 	reader.readInt(symbolRate);
557 	fecRate = reader.readEnum<FecRate>();
558 	rollOff = reader.readEnum<RollOff>();
559 	modulation = reader.readEnum<Modulation>();
560 	return reader.isValid();
561 }
562 
toString() const563 QString DvbS2Transponder::toString() const
564 {
565 	DvbChannelStringWriter writer;
566 	writer.writeString(QLatin1String("S2"));
567 	writer.writeInt(frequency);
568 	writer.writeEnum(polarization);
569 	writer.writeInt(symbolRate);
570 	writer.writeEnum(fecRate);
571 	writer.writeEnum(rollOff);
572 	writer.writeEnum(modulation);
573 	return writer.getString();
574 }
575 
corresponds(const DvbTransponder & transponder) const576 bool DvbS2Transponder::corresponds(const DvbTransponder &transponder) const
577 {
578 	const DvbS2Transponder *dvbS2Transponder = transponder.as<DvbS2Transponder>();
579 
580 	return ((dvbS2Transponder != NULL) &&
581 		(dvbS2Transponder->polarization == polarization) &&
582 		(qAbs(dvbS2Transponder->frequency - frequency) <= 2000));
583 }
584 
readTransponder(QDataStream & stream)585 void DvbTTransponder::readTransponder(QDataStream &stream)
586 {
587 	stream >> frequency;
588 	bandwidth = readEnum<Bandwidth>(stream);
589 	modulation = readEnum<Modulation>(stream);
590 	fecRateHigh = readEnum<FecRate>(stream);
591 	fecRateLow = readEnum<FecRate>(stream);
592 	transmissionMode = readEnum<TransmissionMode>(stream);
593 	guardInterval = readEnum<GuardInterval>(stream);
594 	hierarchy = readEnum<Hierarchy>(stream);
595 }
596 
fromString(const QString & string)597 bool DvbTTransponder::fromString(const QString &string)
598 {
599 	DvbChannelStringReader reader(string);
600 	reader.checkChar(QLatin1Char('T'));
601 	reader.readInt(frequency);
602 	bandwidth = reader.readEnum<Bandwidth>();
603 	fecRateHigh = reader.readEnum<FecRate>();
604 	fecRateLow = reader.readEnum<FecRate>();
605 	modulation = reader.readEnum<Modulation>();
606 	transmissionMode = reader.readEnum<TransmissionMode>();
607 	guardInterval = reader.readEnum<GuardInterval>();
608 	hierarchy = reader.readEnum<Hierarchy>();
609 	return reader.isValid();
610 }
611 
toString() const612 QString DvbTTransponder::toString() const
613 {
614 	DvbChannelStringWriter writer;
615 	writer.writeChar(QLatin1Char('T'));
616 	writer.writeInt(frequency);
617 	writer.writeEnum(bandwidth);
618 	writer.writeEnum(fecRateHigh);
619 	writer.writeEnum(fecRateLow);
620 	writer.writeEnum(modulation);
621 	writer.writeEnum(transmissionMode);
622 	writer.writeEnum(guardInterval);
623 	writer.writeEnum(hierarchy);
624 	return writer.getString();
625 }
626 
corresponds(const DvbTransponder & transponder) const627 bool DvbTTransponder::corresponds(const DvbTransponder &transponder) const
628 {
629 	const DvbTTransponder *dvbTTransponder = transponder.as<DvbTTransponder>();
630 
631 	return ((dvbTTransponder != NULL) &&
632 		(qAbs(dvbTTransponder->frequency - frequency) <= 2000000));
633 }
634 
readTransponder(QDataStream & stream)635 void DvbT2Transponder::readTransponder(QDataStream &stream)
636 {
637 	stream >> frequency;
638 	bandwidth = readEnum<Bandwidth>(stream);
639 	modulation = readEnum<Modulation>(stream);
640 	fecRateHigh = readEnum<FecRate>(stream);
641 	fecRateLow = readEnum<FecRate>(stream);
642 	transmissionMode = readEnum<TransmissionMode>(stream);
643 	guardInterval = readEnum<GuardInterval>(stream);
644 	hierarchy = readEnum<Hierarchy>(stream);
645 	stream >> streamId;
646 }
647 
fromString(const QString & string)648 bool DvbT2Transponder::fromString(const QString &string)
649 {
650 	DvbChannelStringReader reader(string);
651 	reader.checkString(QLatin1String("T2"));
652 	reader.readInt(frequency);
653 	bandwidth = reader.readEnum<Bandwidth>();
654 	fecRateHigh = reader.readEnum<FecRate>();
655 	fecRateLow = reader.readEnum<FecRate>();
656 	modulation = reader.readEnum<Modulation>();
657 	transmissionMode = reader.readEnum<TransmissionMode>();
658 	guardInterval = reader.readEnum<GuardInterval>();
659 	hierarchy = reader.readEnum<Hierarchy>();
660 	reader.readInt(streamId);
661 	return reader.isValid();
662 }
663 
toString() const664 QString DvbT2Transponder::toString() const
665 {
666 	DvbChannelStringWriter writer;
667 	writer.writeString(QLatin1String("T2"));
668 	writer.writeInt(frequency);
669 	writer.writeEnum(bandwidth);
670 	writer.writeEnum(fecRateHigh);
671 	writer.writeEnum(fecRateLow);
672 	writer.writeEnum(modulation);
673 	writer.writeEnum(transmissionMode);
674 	writer.writeEnum(guardInterval);
675 	writer.writeEnum(hierarchy);
676 	writer.writeInt(streamId);
677 	return writer.getString();
678 }
679 
corresponds(const DvbTransponder & transponder) const680 bool DvbT2Transponder::corresponds(const DvbTransponder &transponder) const
681 {
682 	const DvbT2Transponder *dvbT2Transponder = transponder.as<DvbT2Transponder>();
683 
684 	return ((dvbT2Transponder != NULL) &&
685 		(qAbs(dvbT2Transponder->frequency - frequency) <= 2000000) &&
686 		(dvbT2Transponder->streamId == streamId));
687 }
688 
readTransponder(QDataStream & stream)689 void AtscTransponder::readTransponder(QDataStream &stream)
690 {
691 	stream >> frequency;
692 	modulation = readEnum<Modulation>(stream);
693 }
694 
fromString(const QString & string)695 bool AtscTransponder::fromString(const QString &string)
696 {
697 	DvbChannelStringReader reader(string);
698 	reader.checkChar(QLatin1Char('A'));
699 	reader.readInt(frequency);
700 	modulation = reader.readEnum<Modulation>();
701 	return reader.isValid();
702 }
703 
toString() const704 QString AtscTransponder::toString() const
705 {
706 	DvbChannelStringWriter writer;
707 	writer.writeChar(QLatin1Char('A'));
708 	writer.writeInt(frequency);
709 	writer.writeEnum(modulation);
710 	return writer.getString();
711 }
712 
corresponds(const DvbTransponder & transponder) const713 bool AtscTransponder::corresponds(const DvbTransponder &transponder) const
714 {
715 	const AtscTransponder *atscTransponder = transponder.as<AtscTransponder>();
716 
717 	return ((atscTransponder != NULL) &&
718 		(qAbs(atscTransponder->frequency - frequency) <= 2000000));
719 }
720 
readTransponder(QDataStream & stream)721 void IsdbTTransponder::readTransponder(QDataStream &stream)
722 {
723 	int layers;
724 	stream >> frequency;
725 	bandwidth = readEnum<Bandwidth>(stream);
726 	transmissionMode = readEnum<TransmissionMode>(stream);
727 	guardInterval = readEnum<GuardInterval>(stream);
728 	partialReception = readEnum<PartialReception>(stream);
729 	soundBroadcasting = readEnum<SoundBroadcasting>(stream);
730 	stream >> subChannelId;
731 	stream >> sbSegmentCount;
732 	stream >> subChannelId;
733 
734 	stream >> layers;
735 	for (int i = 0; i < 3; i ++) {
736 		if ((1 << i) & layers)
737 			layerEnabled[i] = true;
738 		else
739 			layerEnabled[i] = false;
740 
741 		modulation[i] = readEnum<Modulation>(stream);
742 		fecRate[i] = readEnum<FecRate>(stream);
743 		stream >> segmentCount[i];
744 		interleaving[i] = readEnum<Interleaving>(stream);
745 	}
746 
747 	// Sanity check: if no labels are enabled, enable them all
748 	if (!(layers & 7)) {
749 		layers = 7;
750 		for (int i = 0; i < 3; i ++) {
751 			layerEnabled[i] = true;
752 			modulation[i] = IsdbTTransponder::ModulationAuto;
753 			fecRate[i] = IsdbTTransponder::FecAuto;
754 			interleaving[i] = IsdbTTransponder::I_AUTO;
755 			segmentCount[i] = 15;
756 		}
757 	}
758 }
759 
fromString(const QString & string)760 bool IsdbTTransponder::fromString(const QString &string)
761 {
762 	int layers;
763 	DvbChannelStringReader reader(string);
764 	reader.checkChar(QLatin1Char('I'));
765 	reader.readInt(frequency);
766 	bandwidth = reader.readEnum<Bandwidth>();
767 	transmissionMode = reader.readEnum<TransmissionMode>();
768 	guardInterval = reader.readEnum<GuardInterval>();
769 	partialReception = reader.readEnum<PartialReception>();
770 	soundBroadcasting = reader.readEnum<SoundBroadcasting>();
771 	reader.readInt(subChannelId);
772 	reader.readInt(sbSegmentCount);
773 	reader.readInt(subChannelId);
774 
775 	reader.readInt(layers);
776 	for (int i = 0; i < 3; i ++) {
777 		if ((1 << i) & layers)
778 			layerEnabled[i] = true;
779 		else
780 			layerEnabled[i] = false;
781 
782 		modulation[i] = reader.readEnum<Modulation>();
783 		fecRate[i] = reader.readEnum<FecRate>();
784 		reader.readInt(segmentCount[i]);
785 		interleaving[i] = reader.readEnum<Interleaving>();
786 	}
787 
788 	// Sanity check: if no labels are enabled, enable them all
789 	if (!(layers & 7)) {
790 		layers = 7;
791 		for (int i = 0; i < 3; i ++) {
792 			layerEnabled[i] = true;
793 			modulation[i] = IsdbTTransponder::ModulationAuto;
794 			fecRate[i] = IsdbTTransponder::FecAuto;
795 			interleaving[i] = IsdbTTransponder::I_AUTO;
796 			segmentCount[i] = 15;
797 		}
798 	}
799 
800 	return reader.isValid();
801 }
802 
toString() const803 QString IsdbTTransponder::toString() const
804 {
805 	int layers = 0;
806 	DvbChannelStringWriter writer;
807 	writer.writeChar(QLatin1Char('I'));
808 	writer.writeInt(frequency);
809 	writer.writeEnum(bandwidth);
810 	writer.writeEnum(transmissionMode);
811 	writer.writeEnum(guardInterval);
812 	writer.writeEnum(partialReception);
813 	writer.writeEnum(soundBroadcasting);
814 	writer.writeInt(subChannelId);
815 	writer.writeInt(sbSegmentCount);
816 	writer.writeInt(subChannelId);
817 
818 	for (int i = 0; i < 3; i ++) {
819 		if (layerEnabled[i])
820 			layers |= 1 << i;
821 	}
822 	writer.writeInt(layers);
823 
824 	for (int i = 0; i < 3; i ++) {
825 		writer.writeEnum(modulation[i]);
826 		writer.writeEnum(fecRate[i]);
827 		writer.writeInt(segmentCount[i]);
828 		writer.writeEnum(interleaving[i]);
829 	}
830 
831 	return writer.getString();
832 }
833 
corresponds(const DvbTransponder & transponder) const834 bool IsdbTTransponder::corresponds(const DvbTransponder &transponder) const
835 {
836 	const IsdbTTransponder *dvbTTransponder = transponder.as<IsdbTTransponder>();
837 
838 	return ((dvbTTransponder != NULL) &&
839 		(qAbs(dvbTTransponder->frequency - frequency) <= 2000000));
840 }
841 
corresponds(const DvbTransponder & transponder) const842 bool DvbTransponder::corresponds(const DvbTransponder &transponder) const
843 {
844 	switch (data.transmissionType) {
845 	case DvbTransponderBase::Invalid:
846 		break;
847 	case DvbTransponderBase::DvbC:
848 		return as<DvbCTransponder>()->corresponds(transponder);
849 	case DvbTransponderBase::DvbS:
850 		return as<DvbSTransponder>()->corresponds(transponder);
851 	case DvbTransponderBase::DvbS2:
852 		return as<DvbS2Transponder>()->corresponds(transponder);
853 	case DvbTransponderBase::DvbT:
854 		return as<DvbTTransponder>()->corresponds(transponder);
855 	case DvbTransponderBase::DvbT2:
856 		return as<DvbT2Transponder>()->corresponds(transponder);
857 	case DvbTransponderBase::Atsc:
858 		return as<AtscTransponder>()->corresponds(transponder);
859 	case DvbTransponderBase::IsdbT:
860 		return as<IsdbTTransponder>()->corresponds(transponder);
861 	}
862 
863 	return false;
864 }
865 
toString() const866 QString DvbTransponder::toString() const
867 {
868 	switch (data.transmissionType) {
869 	case DvbTransponderBase::Invalid:
870 		break;
871 	case DvbTransponderBase::DvbC:
872 		return as<DvbCTransponder>()->toString();
873 	case DvbTransponderBase::DvbS:
874 		return as<DvbSTransponder>()->toString();
875 	case DvbTransponderBase::DvbS2:
876 		return as<DvbS2Transponder>()->toString();
877 	case DvbTransponderBase::DvbT:
878 		return as<DvbTTransponder>()->toString();
879 	case DvbTransponderBase::DvbT2:
880 		return as<DvbT2Transponder>()->toString();
881 	case DvbTransponderBase::Atsc:
882 		return as<AtscTransponder>()->toString();
883 	case DvbTransponderBase::IsdbT:
884 		return as<IsdbTTransponder>()->toString();
885 	}
886 
887 	return QString();
888 }
889 
frequency()890 int DvbTransponder::frequency()
891 {
892 	switch (data.transmissionType) {
893 	case DvbTransponderBase::Invalid:
894 		return 0;
895 	case DvbTransponderBase::DvbC:
896 		return as<DvbCTransponder>()->frequency;
897 	case DvbTransponderBase::DvbS:
898 		return as<DvbSTransponder>()->frequency;
899 	case DvbTransponderBase::DvbS2:
900 		return as<DvbS2Transponder>()->frequency;
901 	case DvbTransponderBase::DvbT:
902 		return as<DvbTTransponder>()->frequency;
903 	case DvbTransponderBase::DvbT2:
904 		return as<DvbT2Transponder>()->frequency;
905 	case DvbTransponderBase::Atsc:
906 		return as<AtscTransponder>()->frequency;
907 	case DvbTransponderBase::IsdbT:
908 		return as<IsdbTTransponder>()->frequency;
909 	}
910 
911 	return 0;
912 }
913 
fromString(const QString & string)914 DvbTransponder DvbTransponder::fromString(const QString &string)
915 {
916 	if (string.size() >= 2) {
917 		switch (string.at(0).unicode()) {
918 		case 'C': {
919 			DvbTransponder transponder(DvbTransponderBase::DvbC);
920 
921 			if (transponder.as<DvbCTransponder>()->fromString(string)) {
922 				return transponder;
923 			}
924 
925 			break;
926 		    }
927 		case 'S':
928 			if (string.at(1) != QLatin1Char('2')) {
929 				DvbTransponder transponder(DvbTransponderBase::DvbS);
930 
931 				if (transponder.as<DvbSTransponder>()->fromString(string)) {
932 					return transponder;
933 				}
934 			} else {
935 				DvbTransponder transponder(DvbTransponderBase::DvbS2);
936 
937 				if (transponder.as<DvbS2Transponder>()->fromString(string)) {
938 					return transponder;
939 				}
940 			}
941 
942 			break;
943 		case 'T': {
944 			if (string.at(1) != QLatin1Char('2')) {
945 				DvbTransponder transponder(DvbTransponderBase::DvbT);
946 
947 				if (transponder.as<DvbTTransponder>()->fromString(string)) {
948 					return transponder;
949 				}
950 
951 				break;
952 			} else {
953 				DvbTransponder transponder(DvbTransponderBase::DvbT2);
954 
955 				if (transponder.as<DvbT2Transponder>()->fromString(string)) {
956 					return transponder;
957 				}
958 
959 				break;
960 			}
961 		    }
962 		case 'A': {
963 			DvbTransponder transponder(DvbTransponderBase::Atsc);
964 
965 			if (transponder.as<AtscTransponder>()->fromString(string)) {
966 				return transponder;
967 			}
968 
969 			break;
970 		    }
971 		case 'I': {
972 			DvbTransponder transponder(DvbTransponderBase::IsdbT);
973 
974 			if (transponder.as<IsdbTTransponder>()->fromString(string)) {
975 				return transponder;
976 			}
977 
978 			break;
979 		    }
980 		}
981 	}
982 
983 	return DvbTransponder();
984 }
985