|
MythTV
0.26-pre
|
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
1.7.6.1