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

0001 /*
0002  * dvbtransponder.cpp
0003  *
0004  * Copyright (C) 2007-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 <QDataStream>
0022 #include <QTextStream>
0023 #include <stdint.h>
0024 
0025 #include "dvbtransponder.h"
0026 
0027 static const char *enumToLinuxtv(DvbTransponderBase::FecRate fecRate)
0028 {
0029     switch (fecRate) {
0030     case DvbTransponderBase::FecNone: return "NONE";
0031     case DvbTransponderBase::Fec1_2: return "1/2";
0032     case DvbTransponderBase::Fec1_3: return "1/3";
0033     case DvbTransponderBase::Fec1_4: return "1/4";
0034     case DvbTransponderBase::Fec2_3: return "2/3";
0035     case DvbTransponderBase::Fec2_5: return "2/5";
0036     case DvbTransponderBase::Fec3_4: return "3/4";
0037     case DvbTransponderBase::Fec3_5: return "3/5";
0038     case DvbTransponderBase::Fec4_5: return "4/5";
0039     case DvbTransponderBase::Fec5_6: return "5/6";
0040     case DvbTransponderBase::Fec6_7: return "6/7";
0041     case DvbTransponderBase::Fec7_8: return "7/8";
0042     case DvbTransponderBase::Fec8_9: return "8/9";
0043     case DvbTransponderBase::Fec9_10: return "9/10";
0044     case DvbTransponderBase::FecAuto: return "AUTO";
0045     }
0046 
0047     return NULL;
0048 }
0049 
0050 static const char *enumToLinuxtv(DvbCTransponder::Modulation modulation)
0051 {
0052     switch (modulation) {
0053     case DvbCTransponder::Qam16: return "QAM16";
0054     case DvbCTransponder::Qam32: return "QAM32";
0055     case DvbCTransponder::Qam64: return "QAM64";
0056     case DvbCTransponder::Qam128: return "QAM128";
0057     case DvbCTransponder::Qam256: return "QAM256";
0058     case DvbCTransponder::ModulationAuto: return "AUTO";
0059     }
0060 
0061     return NULL;
0062 }
0063 
0064 static const char *enumToLinuxtv(DvbSTransponder::Polarization polarization)
0065 {
0066     switch (polarization) {
0067     case DvbSTransponder::Horizontal: return "H";
0068     case DvbSTransponder::Vertical: return "V";
0069     case DvbSTransponder::CircularLeft: return "L";
0070     case DvbSTransponder::CircularRight: return "R";
0071     case DvbSTransponder::Off: return "-";
0072     }
0073 
0074     return NULL;
0075 }
0076 
0077 static const char *enumToLinuxtv(DvbS2Transponder::Modulation modulation)
0078 {
0079     switch (modulation) {
0080     case DvbS2Transponder::Qpsk: return "QPSK";
0081     case DvbS2Transponder::Psk8: return "8PSK";
0082     case DvbS2Transponder::Apsk16: return "16APSK";
0083     case DvbS2Transponder::Apsk32: return "32APSK";
0084     case DvbS2Transponder::ModulationAuto: return "AUTO";
0085     }
0086 
0087     return NULL;
0088 }
0089 
0090 static const char *enumToLinuxtv(DvbS2Transponder::RollOff rollOff)
0091 {
0092     switch (rollOff) {
0093     case DvbS2Transponder::RollOff20: return "20";
0094     case DvbS2Transponder::RollOff25: return "25";
0095     case DvbS2Transponder::RollOff35: return "35";
0096     case DvbS2Transponder::RollOffAuto: return "AUTO";
0097     }
0098 
0099     return NULL;
0100 }
0101 
0102 static const char *enumToLinuxtv(DvbTTransponder::Bandwidth bandwidth)
0103 {
0104     switch (bandwidth) {
0105     case DvbTTransponder::Bandwidth5MHz: return "5MHz";
0106     case DvbTTransponder::Bandwidth6MHz: return "6MHz";
0107     case DvbTTransponder::Bandwidth7MHz: return "7MHz";
0108     case DvbTTransponder::Bandwidth8MHz: return "8MHz";
0109     case DvbTTransponder::BandwidthAuto: return "AUTO";
0110     }
0111 
0112     return NULL;
0113 }
0114 
0115 static const char *enumToLinuxtv(DvbTTransponder::Modulation modulation)
0116 {
0117     switch (modulation) {
0118     case DvbTTransponder::Qpsk: return "QPSK";
0119     case DvbTTransponder::Qam16: return "QAM16";
0120     case DvbTTransponder::Qam64: return "QAM64";
0121     case DvbTTransponder::ModulationAuto: return "AUTO";
0122     }
0123 
0124     return NULL;
0125 }
0126 
0127 static const char *enumToLinuxtv(DvbTTransponder::TransmissionMode transmissionMode)
0128 {
0129     switch (transmissionMode) {
0130     case DvbTTransponder::TransmissionMode2k: return "2k";
0131     case DvbTTransponder::TransmissionMode4k: return "4k";
0132     case DvbTTransponder::TransmissionMode8k: return "8k";
0133     case DvbTTransponder::TransmissionModeAuto: return "AUTO";
0134     }
0135 
0136     return NULL;
0137 }
0138 
0139 static const char *enumToLinuxtv(DvbTTransponder::GuardInterval guardInterval)
0140 {
0141     switch (guardInterval) {
0142     case DvbTTransponder::GuardInterval1_4: return "1/4";
0143     case DvbTTransponder::GuardInterval1_8: return "1/8";
0144     case DvbTTransponder::GuardInterval1_16: return "1/16";
0145     case DvbTTransponder::GuardInterval1_32: return "1/32";
0146     case DvbTTransponder::GuardIntervalAuto: return "AUTO";
0147     }
0148 
0149     return NULL;
0150 }
0151 
0152 static const char *enumToLinuxtv(DvbTTransponder::Hierarchy hierarchy)
0153 {
0154     switch (hierarchy) {
0155     case DvbTTransponder::HierarchyNone: return "NONE";
0156     case DvbTTransponder::Hierarchy1: return "1";
0157     case DvbTTransponder::Hierarchy2: return "2";
0158     case DvbTTransponder::Hierarchy4: return "4";
0159     case DvbTTransponder::HierarchyAuto: return "AUTO";
0160     }
0161 
0162     return NULL;
0163 }
0164 
0165 static const char *enumToLinuxtv(DvbT2Transponder::Bandwidth bandwidth)
0166 {
0167     switch (bandwidth) {
0168     case DvbT2Transponder::Bandwidth1_7MHz: return "1.7MHz";
0169     case DvbT2Transponder::Bandwidth5MHz: return "5MHz";
0170     case DvbT2Transponder::Bandwidth6MHz: return "6MHz";
0171     case DvbT2Transponder::Bandwidth7MHz: return "7MHz";
0172     case DvbT2Transponder::Bandwidth8MHz: return "8MHz";
0173     case DvbT2Transponder::Bandwidth10MHz: return "10MHz";
0174     case DvbT2Transponder::BandwidthAuto: return "AUTO";
0175     }
0176 
0177     return NULL;
0178 }
0179 
0180 static const char *enumToLinuxtv(DvbT2Transponder::Modulation modulation)
0181 {
0182     switch (modulation) {
0183     case DvbT2Transponder::Qpsk: return "QPSK";
0184     case DvbT2Transponder::Qam16: return "QAM16";
0185     case DvbT2Transponder::Qam64: return "QAM64";
0186     case DvbT2Transponder::Qam256: return "QAM256";
0187     case DvbT2Transponder::ModulationAuto: return "AUTO";
0188     }
0189 
0190     return NULL;
0191 }
0192 
0193 static const char *enumToLinuxtv(DvbT2Transponder::TransmissionMode transmissionMode)
0194 {
0195     switch (transmissionMode) {
0196     case DvbT2Transponder::TransmissionMode1k: return "1k";
0197     case DvbT2Transponder::TransmissionMode2k: return "2k";
0198     case DvbT2Transponder::TransmissionMode4k: return "4k";
0199     case DvbT2Transponder::TransmissionMode8k: return "8k";
0200     case DvbT2Transponder::TransmissionMode16k: return "16k";
0201     case DvbT2Transponder::TransmissionMode32k: return "32k";
0202     case DvbT2Transponder::TransmissionModeAuto: return "AUTO";
0203     }
0204 
0205     return NULL;
0206 }
0207 
0208 static const char *enumToLinuxtv(DvbT2Transponder::GuardInterval guardInterval)
0209 {
0210     switch (guardInterval) {
0211     case DvbT2Transponder::GuardInterval1_4:    return "1/4";
0212     case DvbT2Transponder::GuardInterval19_128: return "19/128";
0213     case DvbT2Transponder::GuardInterval1_8:    return "1/8";
0214     case DvbT2Transponder::GuardInterval19_256: return "19/256";
0215     case DvbT2Transponder::GuardInterval1_16:   return "1/16";
0216     case DvbT2Transponder::GuardInterval1_32:   return "1/32";
0217     case DvbT2Transponder::GuardInterval1_128:  return "1/128";
0218     case DvbT2Transponder::GuardIntervalAuto:   return "AUTO";
0219     }
0220 
0221     return NULL;
0222 }
0223 
0224 static const char *enumToLinuxtv(DvbT2Transponder::Hierarchy hierarchy)
0225 {
0226     switch (hierarchy) {
0227     case DvbT2Transponder::HierarchyNone: return "NONE";
0228     case DvbT2Transponder::Hierarchy1: return "1";
0229     case DvbT2Transponder::Hierarchy2: return "2";
0230     case DvbT2Transponder::Hierarchy4: return "4";
0231     case DvbT2Transponder::HierarchyAuto: return "AUTO";
0232     }
0233 
0234     return NULL;
0235 }
0236 
0237 static const char *enumToLinuxtv(IsdbTTransponder::Bandwidth bandwidth)
0238 {
0239     switch (bandwidth) {
0240     case IsdbTTransponder::Bandwidth6MHz: return "6MHz";
0241     case IsdbTTransponder::Bandwidth7MHz: return "7MHz";
0242     case IsdbTTransponder::Bandwidth8MHz: return "8MHz";
0243     }
0244 
0245     return NULL;
0246 }
0247 
0248 static const char *enumToLinuxtv(IsdbTTransponder::Modulation modulation)
0249 {
0250     switch (modulation) {
0251     case IsdbTTransponder::Qpsk: return "QPSK";
0252     case IsdbTTransponder::Dqpsk: return "DQPSK";
0253     case IsdbTTransponder::Qam16: return "QAM16";
0254     case IsdbTTransponder::Qam64: return "QAM64";
0255     case IsdbTTransponder::ModulationAuto: return "AUTO";
0256     }
0257 
0258     return NULL;
0259 }
0260 
0261 static const char *enumToLinuxtv(IsdbTTransponder::TransmissionMode transmissionMode)
0262 {
0263     switch (transmissionMode) {
0264     case IsdbTTransponder::TransmissionMode2k: return "2k";
0265     case IsdbTTransponder::TransmissionMode4k: return "4k";
0266     case IsdbTTransponder::TransmissionMode8k: return "8k";
0267     case IsdbTTransponder::TransmissionModeAuto: return "AUTO";
0268     }
0269 
0270     return NULL;
0271 }
0272 
0273 static const char *enumToLinuxtv(IsdbTTransponder::GuardInterval guardInterval)
0274 {
0275     switch (guardInterval) {
0276     case IsdbTTransponder::GuardInterval1_4: return "1/4";
0277     case IsdbTTransponder::GuardInterval1_8: return "1/8";
0278     case IsdbTTransponder::GuardInterval1_16: return "1/16";
0279     case IsdbTTransponder::GuardInterval1_32: return "1/32";
0280     case IsdbTTransponder::GuardIntervalAuto: return "AUTO";
0281     }
0282 
0283     return NULL;
0284 }
0285 
0286 static const char *enumToLinuxtv(IsdbTTransponder::Interleaving interleaving)
0287 {
0288     switch (interleaving) {
0289     case IsdbTTransponder::I_0: return "0";
0290     case IsdbTTransponder::I_1: return "1";
0291     case IsdbTTransponder::I_2: return "2";
0292     case IsdbTTransponder::I_4: return "4";
0293     case IsdbTTransponder::I_8: return "8";
0294     case IsdbTTransponder::I_16: return "16";
0295     case IsdbTTransponder::I_AUTO: return "AUTO";
0296     }
0297 
0298     return NULL;
0299 }
0300 
0301 static const char *enumToLinuxtv(IsdbTTransponder::PartialReception partialReception)
0302 {
0303     switch (partialReception) {
0304     case IsdbTTransponder::PR_disabled: return "0";
0305     case IsdbTTransponder::PR_enabled: return "1";
0306     case IsdbTTransponder::PR_AUTO: return "AUTO";
0307     }
0308 
0309     return NULL;
0310 }
0311 
0312 static const char *enumToLinuxtv(IsdbTTransponder::SoundBroadcasting soundBroadcasting)
0313 {
0314     switch (soundBroadcasting) {
0315     case IsdbTTransponder::SB_disabled: return "0";
0316     case IsdbTTransponder::SB_enabled: return "1";
0317     case IsdbTTransponder::SB_AUTO: return "AUTO";
0318     }
0319 
0320     return NULL;
0321 }
0322 
0323 static const char *enumToLinuxtv(AtscTransponder::Modulation modulation)
0324 {
0325     switch (modulation) {
0326     case AtscTransponder::Qam64: return "QAM64";
0327     case AtscTransponder::Qam256: return "QAM256";
0328     case AtscTransponder::Vsb8: return "8VSB";
0329     case AtscTransponder::Vsb16: return "16VSB";
0330     case AtscTransponder::ModulationAuto: return "AUTO";
0331     }
0332 
0333     return NULL;
0334 }
0335 
0336 template<class T> static T readEnum(QDataStream &stream)
0337 {
0338     int intValue;
0339     stream >> intValue;
0340     T value = static_cast<T>(intValue);
0341 
0342     if ((value != intValue) || (enumToLinuxtv(value) == NULL)) {
0343         stream.setStatus(QDataStream::ReadCorruptData);
0344     }
0345 
0346     return value;
0347 }
0348 
0349 class DvbChannelStringReader
0350 {
0351 public:
0352     explicit DvbChannelStringReader(const QString &string_) : string(string_)
0353     {
0354         stream.setString(&string);
0355         stream.setIntegerBase(10);
0356     }
0357 
0358     ~DvbChannelStringReader() { }
0359 
0360     bool isValid() const
0361     {
0362         return (stream.status() == QTextStream::Ok);
0363     }
0364 
0365     void readInt(int &value)
0366     {
0367         stream >> value;
0368     }
0369 
0370     template<class T> T readEnum()
0371     {
0372         QString token;
0373         stream >> token;
0374 
0375         for (int i = 0;; ++i) {
0376             T value = static_cast<T>(i);
0377 
0378             if (value != i) {
0379                 break;
0380             }
0381 
0382             const char *entry = enumToLinuxtv(value);
0383 
0384             if (entry == NULL) {
0385                 break;
0386             }
0387 
0388             if (token == QLatin1String(entry)) {
0389                 return value;
0390             }
0391         }
0392 
0393         stream.setStatus(QTextStream::ReadCorruptData);
0394         return T();
0395     }
0396 
0397     void checkChar(const QChar &value)
0398     {
0399         QString token;
0400         stream >> token;
0401 
0402         if (token != value) {
0403             stream.setStatus(QTextStream::ReadCorruptData);
0404         }
0405     }
0406 
0407     void checkString(const QString &value)
0408     {
0409         QString token;
0410         stream >> token;
0411 
0412         if (token != value) {
0413             stream.setStatus(QTextStream::ReadCorruptData);
0414         }
0415     }
0416 
0417 private:
0418     QString string;
0419     QTextStream stream;
0420 };
0421 
0422 class DvbChannelStringWriter
0423 {
0424 public:
0425     DvbChannelStringWriter()
0426     {
0427         stream.setString(&string);
0428     }
0429 
0430     ~DvbChannelStringWriter() { }
0431 
0432     QString getString()
0433     {
0434         string.chop(1);
0435         return string;
0436     }
0437 
0438     void writeInt(int value)
0439     {
0440         stream << value << ' ';
0441     }
0442 
0443     template<class T> void writeEnum(T value)
0444     {
0445         stream << enumToLinuxtv(value) << ' ';
0446     }
0447 
0448     void writeChar(const QChar &value)
0449     {
0450         stream << value << ' ';
0451     }
0452 
0453     void writeString(const QString &value)
0454     {
0455         stream << value << ' ';
0456     }
0457 
0458 private:
0459     QString string;
0460     QTextStream stream;
0461 };
0462 
0463 void DvbCTransponder::readTransponder(QDataStream &stream)
0464 {
0465     stream >> frequency;
0466     stream >> symbolRate;
0467     modulation = readEnum<Modulation>(stream);
0468     fecRate = readEnum<FecRate>(stream);
0469 }
0470 
0471 bool DvbCTransponder::fromString(const QString &string)
0472 {
0473     DvbChannelStringReader reader(string);
0474     reader.checkChar(QLatin1Char('C'));
0475     reader.readInt(frequency);
0476     reader.readInt(symbolRate);
0477     fecRate = reader.readEnum<FecRate>();
0478     modulation = reader.readEnum<Modulation>();
0479     return reader.isValid();
0480 }
0481 
0482 QString DvbCTransponder::toString() const
0483 {
0484     DvbChannelStringWriter writer;
0485     writer.writeChar(QLatin1Char('C'));
0486     writer.writeInt(frequency);
0487     writer.writeInt(symbolRate);
0488     writer.writeEnum(fecRate);
0489     writer.writeEnum(modulation);
0490     return writer.getString();
0491 }
0492 
0493 bool DvbCTransponder::corresponds(const DvbTransponder &transponder) const
0494 {
0495     const DvbCTransponder *dvbCTransponder = transponder.as<DvbCTransponder>();
0496 
0497     return ((dvbCTransponder != NULL) &&
0498         (qAbs(dvbCTransponder->frequency - frequency) <= 2000000));
0499 }
0500 
0501 void DvbSTransponder::readTransponder(QDataStream &stream)
0502 {
0503     polarization = readEnum<Polarization>(stream);
0504     stream >> frequency;
0505     stream >> symbolRate;
0506     fecRate = readEnum<FecRate>(stream);
0507 }
0508 
0509 bool DvbSTransponder::fromString(const QString &string)
0510 {
0511     DvbChannelStringReader reader(string);
0512     reader.checkChar(QLatin1Char('S'));
0513     reader.readInt(frequency);
0514     polarization = reader.readEnum<Polarization>();
0515     reader.readInt(symbolRate);
0516     fecRate = reader.readEnum<FecRate>();
0517     return reader.isValid();
0518 }
0519 
0520 QString DvbSTransponder::toString() const
0521 {
0522     DvbChannelStringWriter writer;
0523     writer.writeChar(QLatin1Char('S'));
0524     writer.writeInt(frequency);
0525     writer.writeEnum(polarization);
0526     writer.writeInt(symbolRate);
0527     writer.writeEnum(fecRate);
0528     return writer.getString();
0529 }
0530 
0531 bool DvbSTransponder::corresponds(const DvbTransponder &transponder) const
0532 {
0533     const DvbSTransponder *dvbSTransponder = transponder.as<DvbSTransponder>();
0534 
0535     return ((dvbSTransponder != NULL) &&
0536         (dvbSTransponder->polarization == polarization) &&
0537         (qAbs(dvbSTransponder->frequency - frequency) <= 2000));
0538 }
0539 
0540 void DvbS2Transponder::readTransponder(QDataStream &stream)
0541 {
0542     polarization = readEnum<Polarization>(stream);
0543     stream >> frequency;
0544     stream >> symbolRate;
0545     fecRate = readEnum<FecRate>(stream);
0546     modulation = readEnum<Modulation>(stream);
0547     rollOff = readEnum<RollOff>(stream);
0548 }
0549 
0550 bool DvbS2Transponder::fromString(const QString &string)
0551 {
0552     DvbChannelStringReader reader(string);
0553     reader.checkString(QLatin1String("S2"));
0554     reader.readInt(frequency);
0555     polarization = reader.readEnum<Polarization>();
0556     reader.readInt(symbolRate);
0557     fecRate = reader.readEnum<FecRate>();
0558     rollOff = reader.readEnum<RollOff>();
0559     modulation = reader.readEnum<Modulation>();
0560     return reader.isValid();
0561 }
0562 
0563 QString DvbS2Transponder::toString() const
0564 {
0565     DvbChannelStringWriter writer;
0566     writer.writeString(QLatin1String("S2"));
0567     writer.writeInt(frequency);
0568     writer.writeEnum(polarization);
0569     writer.writeInt(symbolRate);
0570     writer.writeEnum(fecRate);
0571     writer.writeEnum(rollOff);
0572     writer.writeEnum(modulation);
0573     return writer.getString();
0574 }
0575 
0576 bool DvbS2Transponder::corresponds(const DvbTransponder &transponder) const
0577 {
0578     const DvbS2Transponder *dvbS2Transponder = transponder.as<DvbS2Transponder>();
0579 
0580     return ((dvbS2Transponder != NULL) &&
0581         (dvbS2Transponder->polarization == polarization) &&
0582         (qAbs(dvbS2Transponder->frequency - frequency) <= 2000));
0583 }
0584 
0585 void DvbTTransponder::readTransponder(QDataStream &stream)
0586 {
0587     stream >> frequency;
0588     bandwidth = readEnum<Bandwidth>(stream);
0589     modulation = readEnum<Modulation>(stream);
0590     fecRateHigh = readEnum<FecRate>(stream);
0591     fecRateLow = readEnum<FecRate>(stream);
0592     transmissionMode = readEnum<TransmissionMode>(stream);
0593     guardInterval = readEnum<GuardInterval>(stream);
0594     hierarchy = readEnum<Hierarchy>(stream);
0595 }
0596 
0597 bool DvbTTransponder::fromString(const QString &string)
0598 {
0599     DvbChannelStringReader reader(string);
0600     reader.checkChar(QLatin1Char('T'));
0601     reader.readInt(frequency);
0602     bandwidth = reader.readEnum<Bandwidth>();
0603     fecRateHigh = reader.readEnum<FecRate>();
0604     fecRateLow = reader.readEnum<FecRate>();
0605     modulation = reader.readEnum<Modulation>();
0606     transmissionMode = reader.readEnum<TransmissionMode>();
0607     guardInterval = reader.readEnum<GuardInterval>();
0608     hierarchy = reader.readEnum<Hierarchy>();
0609     return reader.isValid();
0610 }
0611 
0612 QString DvbTTransponder::toString() const
0613 {
0614     DvbChannelStringWriter writer;
0615     writer.writeChar(QLatin1Char('T'));
0616     writer.writeInt(frequency);
0617     writer.writeEnum(bandwidth);
0618     writer.writeEnum(fecRateHigh);
0619     writer.writeEnum(fecRateLow);
0620     writer.writeEnum(modulation);
0621     writer.writeEnum(transmissionMode);
0622     writer.writeEnum(guardInterval);
0623     writer.writeEnum(hierarchy);
0624     return writer.getString();
0625 }
0626 
0627 bool DvbTTransponder::corresponds(const DvbTransponder &transponder) const
0628 {
0629     const DvbTTransponder *dvbTTransponder = transponder.as<DvbTTransponder>();
0630 
0631     return ((dvbTTransponder != NULL) &&
0632         (qAbs(dvbTTransponder->frequency - frequency) <= 2000000));
0633 }
0634 
0635 void DvbT2Transponder::readTransponder(QDataStream &stream)
0636 {
0637     stream >> frequency;
0638     bandwidth = readEnum<Bandwidth>(stream);
0639     modulation = readEnum<Modulation>(stream);
0640     fecRateHigh = readEnum<FecRate>(stream);
0641     fecRateLow = readEnum<FecRate>(stream);
0642     transmissionMode = readEnum<TransmissionMode>(stream);
0643     guardInterval = readEnum<GuardInterval>(stream);
0644     hierarchy = readEnum<Hierarchy>(stream);
0645     stream >> streamId;
0646 }
0647 
0648 bool DvbT2Transponder::fromString(const QString &string)
0649 {
0650     DvbChannelStringReader reader(string);
0651     reader.checkString(QLatin1String("T2"));
0652     reader.readInt(frequency);
0653     bandwidth = reader.readEnum<Bandwidth>();
0654     fecRateHigh = reader.readEnum<FecRate>();
0655     fecRateLow = reader.readEnum<FecRate>();
0656     modulation = reader.readEnum<Modulation>();
0657     transmissionMode = reader.readEnum<TransmissionMode>();
0658     guardInterval = reader.readEnum<GuardInterval>();
0659     hierarchy = reader.readEnum<Hierarchy>();
0660     reader.readInt(streamId);
0661     return reader.isValid();
0662 }
0663 
0664 QString DvbT2Transponder::toString() const
0665 {
0666     DvbChannelStringWriter writer;
0667     writer.writeString(QLatin1String("T2"));
0668     writer.writeInt(frequency);
0669     writer.writeEnum(bandwidth);
0670     writer.writeEnum(fecRateHigh);
0671     writer.writeEnum(fecRateLow);
0672     writer.writeEnum(modulation);
0673     writer.writeEnum(transmissionMode);
0674     writer.writeEnum(guardInterval);
0675     writer.writeEnum(hierarchy);
0676     writer.writeInt(streamId);
0677     return writer.getString();
0678 }
0679 
0680 bool DvbT2Transponder::corresponds(const DvbTransponder &transponder) const
0681 {
0682     const DvbT2Transponder *dvbT2Transponder = transponder.as<DvbT2Transponder>();
0683 
0684     return ((dvbT2Transponder != NULL) &&
0685         (qAbs(dvbT2Transponder->frequency - frequency) <= 2000000) &&
0686         (dvbT2Transponder->streamId == streamId));
0687 }
0688 
0689 void AtscTransponder::readTransponder(QDataStream &stream)
0690 {
0691     stream >> frequency;
0692     modulation = readEnum<Modulation>(stream);
0693 }
0694 
0695 bool AtscTransponder::fromString(const QString &string)
0696 {
0697     DvbChannelStringReader reader(string);
0698     reader.checkChar(QLatin1Char('A'));
0699     reader.readInt(frequency);
0700     modulation = reader.readEnum<Modulation>();
0701     return reader.isValid();
0702 }
0703 
0704 QString AtscTransponder::toString() const
0705 {
0706     DvbChannelStringWriter writer;
0707     writer.writeChar(QLatin1Char('A'));
0708     writer.writeInt(frequency);
0709     writer.writeEnum(modulation);
0710     return writer.getString();
0711 }
0712 
0713 bool AtscTransponder::corresponds(const DvbTransponder &transponder) const
0714 {
0715     const AtscTransponder *atscTransponder = transponder.as<AtscTransponder>();
0716 
0717     return ((atscTransponder != NULL) &&
0718         (qAbs(atscTransponder->frequency - frequency) <= 2000000));
0719 }
0720 
0721 void IsdbTTransponder::readTransponder(QDataStream &stream)
0722 {
0723     int layers;
0724     stream >> frequency;
0725     bandwidth = readEnum<Bandwidth>(stream);
0726     transmissionMode = readEnum<TransmissionMode>(stream);
0727     guardInterval = readEnum<GuardInterval>(stream);
0728     partialReception = readEnum<PartialReception>(stream);
0729     soundBroadcasting = readEnum<SoundBroadcasting>(stream);
0730     stream >> subChannelId;
0731     stream >> sbSegmentCount;
0732     stream >> subChannelId;
0733 
0734     stream >> layers;
0735     for (int i = 0; i < 3; i ++) {
0736         if ((1 << i) & layers)
0737             layerEnabled[i] = true;
0738         else
0739             layerEnabled[i] = false;
0740 
0741         modulation[i] = readEnum<Modulation>(stream);
0742         fecRate[i] = readEnum<FecRate>(stream);
0743         stream >> segmentCount[i];
0744         interleaving[i] = readEnum<Interleaving>(stream);
0745     }
0746 
0747     // Sanity check: if no labels are enabled, enable them all
0748     if (!(layers & 7)) {
0749         layers = 7;
0750         for (int i = 0; i < 3; i ++) {
0751             layerEnabled[i] = true;
0752             modulation[i] = IsdbTTransponder::ModulationAuto;
0753             fecRate[i] = IsdbTTransponder::FecAuto;
0754             interleaving[i] = IsdbTTransponder::I_AUTO;
0755             segmentCount[i] = 15;
0756         }
0757     }
0758 }
0759 
0760 bool IsdbTTransponder::fromString(const QString &string)
0761 {
0762     int layers;
0763     DvbChannelStringReader reader(string);
0764     reader.checkChar(QLatin1Char('I'));
0765     reader.readInt(frequency);
0766     bandwidth = reader.readEnum<Bandwidth>();
0767     transmissionMode = reader.readEnum<TransmissionMode>();
0768     guardInterval = reader.readEnum<GuardInterval>();
0769     partialReception = reader.readEnum<PartialReception>();
0770     soundBroadcasting = reader.readEnum<SoundBroadcasting>();
0771     reader.readInt(subChannelId);
0772     reader.readInt(sbSegmentCount);
0773     reader.readInt(subChannelId);
0774 
0775     reader.readInt(layers);
0776     for (int i = 0; i < 3; i ++) {
0777         if ((1 << i) & layers)
0778             layerEnabled[i] = true;
0779         else
0780             layerEnabled[i] = false;
0781 
0782         modulation[i] = reader.readEnum<Modulation>();
0783         fecRate[i] = reader.readEnum<FecRate>();
0784         reader.readInt(segmentCount[i]);
0785         interleaving[i] = reader.readEnum<Interleaving>();
0786     }
0787 
0788     // Sanity check: if no labels are enabled, enable them all
0789     if (!(layers & 7)) {
0790         layers = 7;
0791         for (int i = 0; i < 3; i ++) {
0792             layerEnabled[i] = true;
0793             modulation[i] = IsdbTTransponder::ModulationAuto;
0794             fecRate[i] = IsdbTTransponder::FecAuto;
0795             interleaving[i] = IsdbTTransponder::I_AUTO;
0796             segmentCount[i] = 15;
0797         }
0798     }
0799 
0800     return reader.isValid();
0801 }
0802 
0803 QString IsdbTTransponder::toString() const
0804 {
0805     int layers = 0;
0806     DvbChannelStringWriter writer;
0807     writer.writeChar(QLatin1Char('I'));
0808     writer.writeInt(frequency);
0809     writer.writeEnum(bandwidth);
0810     writer.writeEnum(transmissionMode);
0811     writer.writeEnum(guardInterval);
0812     writer.writeEnum(partialReception);
0813     writer.writeEnum(soundBroadcasting);
0814     writer.writeInt(subChannelId);
0815     writer.writeInt(sbSegmentCount);
0816     writer.writeInt(subChannelId);
0817 
0818     for (int i = 0; i < 3; i ++) {
0819         if (layerEnabled[i])
0820             layers |= 1 << i;
0821     }
0822     writer.writeInt(layers);
0823 
0824     for (int i = 0; i < 3; i ++) {
0825         writer.writeEnum(modulation[i]);
0826         writer.writeEnum(fecRate[i]);
0827         writer.writeInt(segmentCount[i]);
0828         writer.writeEnum(interleaving[i]);
0829     }
0830 
0831     return writer.getString();
0832 }
0833 
0834 bool IsdbTTransponder::corresponds(const DvbTransponder &transponder) const
0835 {
0836     const IsdbTTransponder *dvbTTransponder = transponder.as<IsdbTTransponder>();
0837 
0838     return ((dvbTTransponder != NULL) &&
0839         (qAbs(dvbTTransponder->frequency - frequency) <= 2000000));
0840 }
0841 
0842 bool DvbTransponder::corresponds(const DvbTransponder &transponder) const
0843 {
0844     switch (data.transmissionType) {
0845     case DvbTransponderBase::Invalid:
0846         break;
0847     case DvbTransponderBase::DvbC:
0848         return as<DvbCTransponder>()->corresponds(transponder);
0849     case DvbTransponderBase::DvbS:
0850         return as<DvbSTransponder>()->corresponds(transponder);
0851     case DvbTransponderBase::DvbS2:
0852         return as<DvbS2Transponder>()->corresponds(transponder);
0853     case DvbTransponderBase::DvbT:
0854         return as<DvbTTransponder>()->corresponds(transponder);
0855     case DvbTransponderBase::DvbT2:
0856         return as<DvbT2Transponder>()->corresponds(transponder);
0857     case DvbTransponderBase::Atsc:
0858         return as<AtscTransponder>()->corresponds(transponder);
0859     case DvbTransponderBase::IsdbT:
0860         return as<IsdbTTransponder>()->corresponds(transponder);
0861     }
0862 
0863     return false;
0864 }
0865 
0866 QString DvbTransponder::toString() const
0867 {
0868     switch (data.transmissionType) {
0869     case DvbTransponderBase::Invalid:
0870         break;
0871     case DvbTransponderBase::DvbC:
0872         return as<DvbCTransponder>()->toString();
0873     case DvbTransponderBase::DvbS:
0874         return as<DvbSTransponder>()->toString();
0875     case DvbTransponderBase::DvbS2:
0876         return as<DvbS2Transponder>()->toString();
0877     case DvbTransponderBase::DvbT:
0878         return as<DvbTTransponder>()->toString();
0879     case DvbTransponderBase::DvbT2:
0880         return as<DvbT2Transponder>()->toString();
0881     case DvbTransponderBase::Atsc:
0882         return as<AtscTransponder>()->toString();
0883     case DvbTransponderBase::IsdbT:
0884         return as<IsdbTTransponder>()->toString();
0885     }
0886 
0887     return QString();
0888 }
0889 
0890 int DvbTransponder::frequency()
0891 {
0892     switch (data.transmissionType) {
0893     case DvbTransponderBase::Invalid:
0894         return 0;
0895     case DvbTransponderBase::DvbC:
0896         return as<DvbCTransponder>()->frequency;
0897     case DvbTransponderBase::DvbS:
0898         return as<DvbSTransponder>()->frequency;
0899     case DvbTransponderBase::DvbS2:
0900         return as<DvbS2Transponder>()->frequency;
0901     case DvbTransponderBase::DvbT:
0902         return as<DvbTTransponder>()->frequency;
0903     case DvbTransponderBase::DvbT2:
0904         return as<DvbT2Transponder>()->frequency;
0905     case DvbTransponderBase::Atsc:
0906         return as<AtscTransponder>()->frequency;
0907     case DvbTransponderBase::IsdbT:
0908         return as<IsdbTTransponder>()->frequency;
0909     }
0910 
0911     return 0;
0912 }
0913 
0914 DvbTransponder DvbTransponder::fromString(const QString &string)
0915 {
0916     if (string.size() >= 2) {
0917         switch (string.at(0).unicode()) {
0918         case 'C': {
0919             DvbTransponder transponder(DvbTransponderBase::DvbC);
0920 
0921             if (transponder.as<DvbCTransponder>()->fromString(string)) {
0922                 return transponder;
0923             }
0924 
0925             break;
0926             }
0927         case 'S':
0928             if (string.at(1) != QLatin1Char('2')) {
0929                 DvbTransponder transponder(DvbTransponderBase::DvbS);
0930 
0931                 if (transponder.as<DvbSTransponder>()->fromString(string)) {
0932                     return transponder;
0933                 }
0934             } else {
0935                 DvbTransponder transponder(DvbTransponderBase::DvbS2);
0936 
0937                 if (transponder.as<DvbS2Transponder>()->fromString(string)) {
0938                     return transponder;
0939                 }
0940             }
0941 
0942             break;
0943         case 'T': {
0944             if (string.at(1) != QLatin1Char('2')) {
0945                 DvbTransponder transponder(DvbTransponderBase::DvbT);
0946 
0947                 if (transponder.as<DvbTTransponder>()->fromString(string)) {
0948                     return transponder;
0949                 }
0950 
0951                 break;
0952             } else {
0953                 DvbTransponder transponder(DvbTransponderBase::DvbT2);
0954 
0955                 if (transponder.as<DvbT2Transponder>()->fromString(string)) {
0956                     return transponder;
0957                 }
0958 
0959                 break;
0960             }
0961             }
0962         case 'A': {
0963             DvbTransponder transponder(DvbTransponderBase::Atsc);
0964 
0965             if (transponder.as<AtscTransponder>()->fromString(string)) {
0966                 return transponder;
0967             }
0968 
0969             break;
0970             }
0971         case 'I': {
0972             DvbTransponder transponder(DvbTransponderBase::IsdbT);
0973 
0974             if (transponder.as<IsdbTTransponder>()->fromString(string)) {
0975                 return transponder;
0976             }
0977 
0978             break;
0979             }
0980         }
0981     }
0982 
0983     return DvbTransponder();
0984 }