00001
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
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
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
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
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() );
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