MythTV  0.26-pre
dtvmultiplex.cpp
Go to the documentation of this file.
00001 // MythTV headers
00002 #include "dtvmultiplex.h"
00003 #include "mythdb.h"
00004 #include "mythlogging.h"
00005 #include "mpeg/dvbdescriptors.h"
00006 
00007 #define LOC      QString("DTVMux: ")
00008 
00009 DTVMultiplex::DTVMultiplex(const DTVMultiplex &other) :
00010     frequency(other.frequency),
00011     symbolrate(other.symbolrate),
00012     inversion(other.inversion),
00013     bandwidth(other.bandwidth),
00014     hp_code_rate(other.hp_code_rate),
00015     lp_code_rate(other.lp_code_rate),
00016     modulation(other.modulation),
00017     trans_mode(other.trans_mode),
00018     guard_interval(other.guard_interval),
00019     hierarchy(other.hierarchy),
00020     polarity(other.polarity),
00021     fec(other.fec),
00022     mod_sys(other.mod_sys),
00023     rolloff(other.rolloff),
00024     mplex(other.mplex),
00025     sistandard(other.sistandard)
00026 {
00027 }
00028 
00029 DTVMultiplex &DTVMultiplex::operator=(const DTVMultiplex &other)
00030 {
00031     frequency      = other.frequency;
00032     symbolrate     = other.symbolrate;
00033     inversion      = other.inversion;
00034     bandwidth      = other.bandwidth;
00035     hp_code_rate   = other.hp_code_rate;
00036     lp_code_rate   = other.lp_code_rate;
00037     modulation     = other.modulation;
00038     trans_mode     = other.trans_mode;
00039     guard_interval = other.guard_interval;
00040     hierarchy      = other.hierarchy;
00041     polarity       = other.polarity;
00042     fec            = other.fec;
00043     mod_sys        = other.mod_sys;
00044     rolloff        = other.rolloff;
00045     mplex          = other.mplex;
00046     sistandard     = other.sistandard;
00047     return *this;
00048 }
00049 
00050 bool DTVMultiplex::operator==(const DTVMultiplex &m) const
00051 {
00052     return ((frequency == m.frequency) &&
00053             (modulation == m.modulation) &&
00054             (inversion == m.inversion) &&
00055             (bandwidth == m.bandwidth) &&
00056             (hp_code_rate == m.hp_code_rate) &&
00057             (lp_code_rate == m.lp_code_rate) &&
00058             (trans_mode == m.trans_mode) &&
00059             (guard_interval == m.guard_interval) &&
00060             (fec == m.fec) &&
00061             (mod_sys  == m.mod_sys)  &&
00062             (rolloff  == m.rolloff)  &&
00063             (polarity == m.polarity) &&
00064             (hierarchy == m.hierarchy));
00065 }
00066 
00068 // Gets
00069 
00070 QString DTVMultiplex::toString() const
00071 {
00072     QString ret = QString("%1 %2 %3 ")
00073         .arg(frequency).arg(modulation.toString()).arg(inversion.toString());
00074 
00075     ret += QString("%1 %2 %3 %4 %5 %6 %7")
00076         .arg(hp_code_rate.toString()).arg(lp_code_rate.toString())
00077         .arg(bandwidth.toString()).arg(trans_mode.toString())
00078         .arg(guard_interval.toString()).arg(hierarchy.toString())
00079         .arg(polarity.toString());
00080     ret += QString(" fec: %1 msys: %2 rolloff: %3")
00081         .arg(fec.toString()).arg(mod_sys.toString()).arg(rolloff.toString());
00082 
00083     return ret;
00084 }
00085 
00086 bool DTVMultiplex::IsEqual(DTVTunerType type, const DTVMultiplex &other,
00087                            uint freq_range, bool fuzzy) const
00088 {
00089     if ((frequency + freq_range  < other.frequency             ) ||
00090         (frequency               > other.frequency + freq_range))
00091     {
00092         return false;
00093     }
00094 
00095     if (DTVTunerType::kTunerTypeDVBC == type)
00096     {
00097         if (fuzzy)
00098             return
00099                 inversion.IsCompatible(other.inversion)   &&
00100                 (symbolrate == other.symbolrate)          &&
00101                 fec.IsCompatible(other.fec)               &&
00102                 modulation.IsCompatible(other.modulation);
00103         return
00104             (inversion  == other.inversion)  &&
00105             (symbolrate == other.symbolrate) &&
00106             (fec        == other.fec)        &&
00107             (modulation == other.modulation);
00108     }
00109 
00110     if (DTVTunerType::kTunerTypeDVBT == type)
00111     {
00112         if (fuzzy)
00113             return
00114                 inversion.IsCompatible(other.inversion)           &&
00115                 bandwidth.IsCompatible(other.bandwidth)           &&
00116                 hp_code_rate.IsCompatible(other.hp_code_rate)     &&
00117                 lp_code_rate.IsCompatible(other.lp_code_rate)     &&
00118                 modulation.IsCompatible(other.modulation)         &&
00119                 guard_interval.IsCompatible(other.guard_interval) &&
00120                 trans_mode.IsCompatible(other.trans_mode)         &&
00121                 hierarchy.IsCompatible(other.hierarchy);
00122         return
00123             (inversion      == other.inversion)      &&
00124             (bandwidth      == other.bandwidth)      &&
00125             (hp_code_rate   == other.hp_code_rate)   &&
00126             (lp_code_rate   == other.lp_code_rate)   &&
00127             (modulation     == other.modulation)     &&
00128             (guard_interval == other.guard_interval) &&
00129             (trans_mode     == other.trans_mode)     &&
00130             (hierarchy      == other.hierarchy);
00131     }
00132 
00133     if (DTVTunerType::kTunerTypeATSC == type)
00134     {
00135         if (fuzzy)
00136             modulation.IsCompatible(other.modulation);
00137         return (modulation == other.modulation);
00138     }
00139 
00140     if ((DTVTunerType::kTunerTypeDVBS1 == type) ||
00141         (DTVTunerType::kTunerTypeDVBS2 == type))
00142     {
00143         bool ret =
00144             (symbolrate == other.symbolrate)        &&
00145             (polarity   == other.polarity)          &&
00146             (mod_sys    == other.mod_sys);
00147 
00148         if (fuzzy)
00149             return ret &&
00150                 inversion.IsCompatible(other.inversion) &&
00151                 fec.IsCompatible(other.fec)             &&
00152                 rolloff.IsCompatible(other.rolloff);
00153         return ret &&
00154             (inversion  == other.inversion)  &&
00155             (fec        == other.fec)        &&
00156             (rolloff    == other.rolloff);
00157     }
00158 
00159     return false;
00160 }
00161 
00163 // Parsers
00164 
00165 bool DTVMultiplex::ParseATSC(const QString &_frequency,
00166                              const QString &_modulation)
00167 {
00168     bool ok = true;
00169     frequency = _frequency.toULongLong(&ok);
00170     if (!ok)
00171     {
00172         LOG(VB_GENERAL, LOG_ERR, LOC +
00173             QString("Failed to parse ATSC frequency %1").arg(_frequency));
00174         return false;
00175     }
00176 
00177     ok = modulation.Parse(_modulation);
00178     if (!ok)
00179     {
00180         LOG(VB_GENERAL, LOG_ERR, LOC +
00181             QString("Failed to parse ATSC modulation %1").arg(_modulation));
00182     }
00183     return ok;
00184 }
00185 
00186 bool DTVMultiplex::ParseDVB_T(
00187     const QString &_frequency,   const QString &_inversion,
00188     const QString &_bandwidth,   const QString &_coderate_hp,
00189     const QString &_coderate_lp, const QString &_modulation,
00190     const QString &_trans_mode,  const QString &_guard_interval,
00191     const QString &_hierarchy)
00192 {
00193     bool ok = inversion.Parse(_inversion);
00194     if (!ok)
00195     {
00196         LOG(VB_GENERAL, LOG_WARNING, LOC +
00197             "Invalid inversion, falling back to 'auto'.");
00198         ok = true;
00199     }
00200 
00201     ok &= bandwidth.Parse(_bandwidth);
00202     ok &= hp_code_rate.Parse(_coderate_hp);
00203     ok &= lp_code_rate.Parse(_coderate_lp);
00204     ok &= modulation.Parse(_modulation);
00205     ok &= trans_mode.Parse(_trans_mode);
00206     ok &= hierarchy.Parse(_hierarchy);
00207     ok &= guard_interval.Parse(_guard_interval);
00208     if (ok)
00209         frequency = _frequency.toInt(&ok);
00210 
00211     return ok;
00212 }
00213 
00214 bool DTVMultiplex::ParseDVB_S_and_C(
00215     const QString &_frequency,   const QString &_inversion,
00216     const QString &_symbol_rate, const QString &_fec_inner,
00217     const QString &_modulation,  const QString &_polarity)
00218 {
00219     bool ok = inversion.Parse(_inversion);
00220     if (!ok)
00221     {
00222         LOG(VB_GENERAL, LOG_WARNING, LOC +
00223             "Invalid inversion, falling back to 'auto'");
00224 
00225         ok = true;
00226     }
00227 
00228     symbolrate = _symbol_rate.toInt();
00229     if (!symbolrate)
00230     {
00231         LOG(VB_GENERAL, LOG_ERR, LOC + "Invalid symbol rate " +
00232             QString("parameter '%1', aborting.").arg(_symbol_rate));
00233 
00234         return false;
00235     }
00236 
00237     ok &= fec.Parse(_fec_inner);
00238     ok &= modulation.Parse(_modulation);
00239 
00240     if (!_polarity.isEmpty())
00241         polarity.Parse(_polarity.toLower());
00242 
00243     if (ok)
00244         frequency = _frequency.toInt(&ok);
00245 
00246     return ok;
00247 }
00248 
00249 bool DTVMultiplex::ParseDVB_S2(
00250     const QString &_frequency,   const QString &_inversion,
00251     const QString &_symbol_rate, const QString &_fec_inner,
00252     const QString &_modulation,  const QString &_polarity,
00253     const QString &_mod_sys,     const QString &_rolloff)
00254 {
00255     bool ok = ParseDVB_S_and_C(_frequency, _inversion, _symbol_rate,
00256                                _fec_inner, _modulation, _polarity);
00257 
00258     if (!mod_sys.Parse(_mod_sys))
00259     {
00260         LOG(VB_GENERAL, LOG_ERR, LOC + "Invalid S2 modulation system " +
00261                 QString("parameter '%1', aborting.").arg(_mod_sys));
00262         return false;
00263     }
00264 
00265     // For #10153, guess at modulation system based on modulation
00266     if (DTVModulationSystem::kModulationSystem_UNDEFINED == mod_sys)
00267     {
00268         mod_sys = (DTVModulation::kModulationQPSK == modulation) ?
00269             DTVModulationSystem::kModulationSystem_DVBS : 
00270             DTVModulationSystem::kModulationSystem_DVBS2;
00271     }
00272     
00273     if ((DTVModulationSystem::kModulationSystem_DVBS  != mod_sys) &&
00274         (DTVModulationSystem::kModulationSystem_DVBS2 != mod_sys))
00275     {
00276         LOG(VB_GENERAL, LOG_ERR, LOC + "Unsupported S2 modulation system " +
00277             QString("parameter '%1', aborting.").arg(_mod_sys));
00278         return false;
00279     }
00280 
00281     if (!_rolloff.isEmpty())
00282         ok &= rolloff.Parse(_rolloff);
00283 
00284     return ok;
00285 }
00286 
00287 bool DTVMultiplex::ParseTuningParams(
00288     DTVTunerType type,
00289     QString _frequency,    QString _inversion,      QString _symbolrate,
00290     QString _fec,          QString _polarity,
00291     QString _hp_code_rate, QString _lp_code_rate,   QString _ofdm_modulation,
00292     QString _trans_mode,   QString _guard_interval, QString _hierarchy,
00293     QString _modulation,   QString _bandwidth,
00294     QString _mod_sys,      QString _rolloff)
00295 {
00296     if (DTVTunerType::kTunerTypeDVBT == type)
00297     {
00298         return ParseDVB_T(
00299             _frequency,       _inversion,       _bandwidth,    _hp_code_rate,
00300             _lp_code_rate,    _ofdm_modulation, _trans_mode,   _guard_interval,
00301             _hierarchy);
00302     }
00303 
00304     if ((DTVTunerType::kTunerTypeDVBS1 == type) ||
00305         (DTVTunerType::kTunerTypeDVBC  == type))
00306     {
00307         return ParseDVB_S_and_C(
00308             _frequency,       _inversion,     _symbolrate,
00309             _fec,             _modulation,    _polarity);
00310     }
00311 
00312     if (DTVTunerType::kTunerTypeDVBS2 == type)
00313     {
00314         return ParseDVB_S2(
00315             _frequency,       _inversion,     _symbolrate,
00316             _fec,             _modulation,    _polarity,
00317             _mod_sys,         _rolloff);
00318     }
00319 
00320     if (DTVTunerType::kTunerTypeATSC == type)
00321         return ParseATSC(_frequency, _modulation);
00322 
00323     LOG(VB_GENERAL, LOG_ERR, LOC + "ParseTuningParams -- Unknown tuner type");
00324 
00325     return false;
00326 }
00327 
00328 bool DTVMultiplex::FillFromDB(DTVTunerType type, uint mplexid)
00329 {
00330     Clear();
00331 
00332     MSqlQuery query(MSqlQuery::InitCon());
00333     query.prepare(
00334         "SELECT frequency,         inversion,      symbolrate, "
00335         "       fec,               polarity, "
00336         "       hp_code_rate,      lp_code_rate,   constellation, "
00337         "       transmission_mode, guard_interval, hierarchy, "
00338         "       modulation,        bandwidth,      sistandard, "
00339         "       mod_sys,           rolloff "
00340         "FROM dtv_multiplex "
00341         "WHERE dtv_multiplex.mplexid = :MPLEXID");
00342     query.bindValue(":MPLEXID", mplexid);
00343 
00344     if (!query.exec())
00345     {
00346         MythDB::DBError("DVBTuning::FillFromDB", query);
00347         return false;
00348     }
00349 
00350     if (!query.next())
00351     {
00352         LOG(VB_GENERAL, LOG_ERR, LOC +
00353             QString("Could not find tuning parameters for mplex %1")
00354                 .arg(mplexid));
00355 
00356         return false;
00357     }
00358 
00359     mplex = mplexid;
00360     sistandard = query.value(13).toString();
00361 
00362     // Parse the query into our DVBTuning class
00363     return ParseTuningParams(
00364         type,
00365         query.value(0).toString(),  query.value(1).toString(),
00366         query.value(2).toString(),  query.value(3).toString(),
00367         query.value(4).toString(),  query.value(5).toString(),
00368         query.value(6).toString(),  query.value(7).toString(),
00369         query.value(8).toString(),  query.value(9).toString(),
00370         query.value(10).toString(), query.value(11).toString(),
00371         query.value(12).toString(), query.value(14).toString(),
00372         query.value(15).toString());
00373 }
00374 
00375 
00376 bool DTVMultiplex::FillFromDeliverySystemDesc(DTVTunerType type,
00377                                               const MPEGDescriptor &desc)
00378 {
00379     uint tag = desc.DescriptorTag();
00380     sistandard = "dvb";
00381 
00382     switch (tag)
00383     {
00384         case DescriptorID::terrestrial_delivery_system:
00385         {
00386             if (type != DTVTunerType::kTunerTypeDVBT)
00387                 break;
00388 
00389             const TerrestrialDeliverySystemDescriptor cd(desc);
00390 
00391             return ParseDVB_T(
00392                 QString().number(cd.FrequencyHz()), "auto",
00393                 cd.BandwidthString(),               cd.CodeRateHPString(),
00394                 cd.CodeRateLPString(),              cd.ConstellationString(),
00395                 cd.TransmissionModeString(),        cd.GuardIntervalString(),
00396                 cd.HierarchyString());
00397         }
00398         case DescriptorID::satellite_delivery_system:
00399         {
00400             const SatelliteDeliverySystemDescriptor cd(desc);
00401 
00402             if (type == DTVTunerType::kTunerTypeDVBS1)
00403             {
00404                 if (cd.ModulationSystem())
00405                 {
00406                     LOG(VB_CHANSCAN, LOG_NOTICE, LOC +
00407                         "Ignoring DVB-S2 transponder with DVB-S card");
00408                     return false;
00409                 }
00410 
00411                 return ParseDVB_S_and_C(
00412                     QString().number(cd.FrequencyHz()),  "auto",
00413                     QString().number(cd.SymbolRateHz()), cd.FECInnerString(),
00414                     cd.ModulationString(),
00415                     cd.PolarizationString());
00416             }
00417 
00418             if (type == DTVTunerType::kTunerTypeDVBS2)
00419             {
00420                 return ParseDVB_S2(
00421                     QString().number(cd.FrequencyHz()),  "auto",
00422                     QString().number(cd.SymbolRateHz()), cd.FECInnerString(),
00423                     cd.ModulationString(),
00424                     cd.PolarizationString(),
00425                     cd.ModulationSystemString(),         cd.RollOffString());
00426             }
00427 
00428             break;
00429         }
00430         case DescriptorID::cable_delivery_system:
00431         {
00432             if (type != DTVTunerType::kTunerTypeDVBC)
00433                 break;
00434 
00435             const CableDeliverySystemDescriptor cd(desc);
00436 
00437             return ParseDVB_S_and_C(
00438                     QString().number(cd.FrequencyHz()),  "auto",
00439                     QString().number(cd.SymbolRateHz()), cd.FECInnerString(),
00440                     cd.ModulationString(),               QString());
00441         }
00442         default:
00443             LOG(VB_CHANSCAN, LOG_ERR, LOC +
00444                 "unknown delivery system descriptor");
00445             return false;
00446     }
00447 
00448     LOG(VB_CHANSCAN, LOG_ERR, LOC +
00449         QString("Tuner type %1 does not match delivery system")
00450             .arg(type.toString()));
00451     return false;
00452 }
00453 
00454 
00457 
00458 bool ScanDTVTransport::FillFromDB(DTVTunerType type, uint mplexid)
00459 {
00460     if (!DTVMultiplex::FillFromDB(type, mplexid))
00461         return false;
00462 
00463     MSqlQuery query(MSqlQuery::InitCon());
00464     query.prepare(
00465         "SELECT c.mplexid,       c.sourceid,        c.chanid,          "
00466         "       c.callsign,      c.name,            c.channum,         "
00467         "       c.serviceid,     c.atsc_major_chan, c.atsc_minor_chan, "
00468         "       c.useonairguide, c.visible,         c.freqid,          "
00469         "       c.icon,          c.tvformat,        c.xmltvid,         "
00470         "       d.transportid,   d.networkid,       c.default_authority "
00471         "FROM channel AS c, dtv_multiplex AS d "
00472         "WHERE c.mplexid = :MPLEXID AND"
00473         "      c.mplexid = d.mplexid");
00474     query.bindValue(":MPLEXID", mplexid);
00475 
00476     if (!query.exec())
00477     {
00478         MythDB::DBError("ScanDTVTransport::FillFromDB", query);
00479         return false;
00480     }
00481 
00482     while (query.next())
00483     {
00484         ChannelInsertInfo chan(
00485             query.value(0).toUInt(),     query.value(1).toUInt(),
00486             query.value(2).toUInt(),     query.value(3).toString(),
00487             query.value(4).toString(),   query.value(5).toString(),
00488             query.value(6).toUInt(),
00489             query.value(7).toUInt(),     query.value(8).toUInt(),
00490             query.value(9).toUInt(),    !query.value(10).toUInt(),
00491             false,
00492             query.value(11).toString(),  query.value(12).toString(),
00493             query.value(13).toString(),  query.value(14).toString(),
00494             0, 0, 0,
00495             query.value(15).toUInt(),    query.value(16).toUInt(),
00496             0,
00497             QString::null,
00498             false, false, false, false,
00499             false, false, false, false,
00500             false, false, false, 0,
00501             query.value(17).toString() /* default_authority */);
00502 
00503         channels.push_back(chan);
00504     }
00505 
00506     return true;
00507 }
00508 
00509 uint ScanDTVTransport::SaveScan(uint scanid) const
00510 {
00511     uint transportid = 0;
00512 
00513     MSqlQuery query(MSqlQuery::InitCon());
00514     query.prepare(
00515         "INSERT INTO channelscan_dtv_multiplex "
00516         " (  scanid, "
00517         "    mplexid,            frequency,       inversion,  "
00518         "    symbolrate,         fec,             polarity,   "
00519         "    hp_code_rate,       lp_code_rate,    modulation, "
00520         "    transmission_mode,  guard_interval,  hierarchy,  "
00521         "    mod_sys,            rolloff,                     "
00522         "    bandwidth,          sistandard,      tuner_type  "
00523         " ) "
00524         "VALUES "
00525         " ( :SCANID, "
00526         "   :MPLEXID,           :FREQUENCY,      :INVERSION,  "
00527         "   :SYMBOLRATE,        :FEC,            :POLARITY,   "
00528         "   :HP_CODE_RATE,      :LP_CODE_RATE,   :MODULATION, "
00529         "   :TRANSMISSION_MODE, :GUARD_INTERVAL, :HIERARCHY,  "
00530         "   :MOD_SYS,           :ROLLOFF,                     "
00531         "   :BANDWIDTH,         :SISTANDARD,     :TUNER_TYPE  "
00532         " );");
00533 
00534     query.bindValue(":SCANID", scanid);
00535     query.bindValue(":MPLEXID", mplex);
00536     query.bindValue(":FREQUENCY", QString::number(frequency));
00537     query.bindValue(":INVERSION", inversion.toString());
00538     query.bindValue(":SYMBOLRATE", QString::number(symbolrate));
00539     query.bindValue(":FEC", fec.toString());
00540     query.bindValue(":POLARITY", polarity.toString());
00541     query.bindValue(":HP_CODE_RATE", hp_code_rate.toString());
00542     query.bindValue(":LP_CODE_RATE", lp_code_rate.toString());
00543     query.bindValue(":MODULATION", modulation.toString());
00544     query.bindValue(":TRANSMISSION_MODE", trans_mode.toString());
00545     query.bindValue(":GUARD_INTERVAL", guard_interval.toString());
00546     query.bindValue(":HIERARCHY", hierarchy.toString());
00547     query.bindValue(":MOD_SYS", mod_sys.toString());
00548     query.bindValue(":ROLLOFF", rolloff.toString());
00549     query.bindValue(":BANDWIDTH", bandwidth.toString());
00550     query.bindValue(":SISTANDARD", sistandard);
00551     query.bindValue(":TUNER_TYPE", (uint)tuner_type);
00552 
00553     if (!query.exec())
00554     {
00555         MythDB::DBError("ScanDTVTransport::SaveScan 1", query);
00556         return transportid;
00557     }
00558 
00559     query.prepare("SELECT MAX(transportid) FROM channelscan_dtv_multiplex");
00560     if (!query.exec())
00561         MythDB::DBError("ScanDTVTransport::SaveScan 2", query);
00562     else if (query.next())
00563         transportid = query.value(0).toUInt();
00564 
00565     if (!transportid)
00566         return transportid;
00567 
00568     for (uint i = 0; i < channels.size(); i++)
00569         channels[i].SaveScan(scanid, transportid);
00570 
00571     return transportid;
00572 }
00573 
00574 bool ScanDTVTransport::ParseTuningParams(
00575     DTVTunerType type,
00576     QString _frequency,    QString _inversion,      QString _symbolrate,
00577     QString _fec,          QString _polarity,
00578     QString _hp_code_rate, QString _lp_code_rate,   QString _ofdm_modulation,
00579     QString _trans_mode,   QString _guard_interval, QString _hierarchy,
00580     QString _modulation,   QString _bandwidth,      QString _mod_sys,
00581     QString _rolloff)
00582 {
00583     tuner_type = type;
00584 
00585     return DTVMultiplex::ParseTuningParams(
00586         type,
00587         _frequency,     _inversion,       _symbolrate,
00588         _fec,           _polarity,
00589         _hp_code_rate,  _lp_code_rate,    _ofdm_modulation,
00590         _trans_mode,    _guard_interval,  _hierarchy,
00591         _modulation,    _bandwidth,       _mod_sys,
00592         _rolloff);
00593 }
00594 
00595 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends