void DTVConfParser::AddChannel(const DTVMultiplex &mux, DTVChannelInfo &chan) { for (uint i = 0; i < channels.size(); i++) { if (channels[i] == mux) { channels[i].channels.push_back(chan); VERBOSE(VB_IMPORTANT, "Imported channel: "<<chan.toString() <<" on "<<mux.toString()); return; } } channels.push_back(mux); channels.back().channels.push_back(chan); VERBOSE(VB_IMPORTANT, "Imported channel: "<<chan.toString() <<" on "<<mux.toString()); }
/** * \brief Tunes the card to a frequency but does not deal with PIDs. * * This is used by DVB Channel Scanner, the EIT Parser, and by TVRec. * * \param tuning Info on transport to tune to * \param inputid Optional, forces specific input (for DiSEqC) * \param force_reset If true, frequency tuning is done * even if it should not be needed. * \param same_input Optional, doesn't change input (for retuning). * \return true on success, false on failure */ bool DVBChannel::Tune(const DTVMultiplex &tuning, uint inputid, bool force_reset, bool same_input) { QMutexLocker lock(&tune_lock); QMutexLocker locker(&hw_lock); DVBChannel *master = GetMasterLock(); if (master != this) { LOG(VB_CHANNEL, LOG_INFO, LOC + "tuning on slave channel"); SetSIStandard(tuning.sistandard); bool ok = master->Tune(tuning, inputid, force_reset, false); ReturnMasterLock(master); return ok; } ReturnMasterLock(master); // if we're the master we don't need this lock.. int intermediate_freq = 0; bool can_fec_auto = false; bool reset = (force_reset || first_tune); if (tunerType.IsDiSEqCSupported() && !diseqc_tree) { LOG(VB_GENERAL, LOG_ERR, LOC + "DVB-S needs device tree for LNB handling"); return false; } desired_tuning = tuning; if (fd_frontend < 0) { LOG(VB_GENERAL, LOG_ERR, LOC + "Tune(): Card not open!"); return false; } // Remove any events in queue before tuning. drain_dvb_events(fd_frontend); // send DVB-S setup if (diseqc_tree) { // configure for new input if (!same_input) diseqc_settings.Load(inputid); // execute diseqc commands if (!diseqc_tree->Execute(diseqc_settings, tuning)) { LOG(VB_GENERAL, LOG_ERR, LOC + "Tune(): Failed to setup DiSEqC devices"); return false; } // retrieve actual intermediate frequency DiSEqCDevLNB *lnb = diseqc_tree->FindLNB(diseqc_settings); if (!lnb) { LOG(VB_GENERAL, LOG_ERR, LOC + "Tune(): No LNB for this configuration"); return false; } if (lnb->GetDeviceID() != last_lnb_dev_id) { last_lnb_dev_id = lnb->GetDeviceID(); // make sure we tune to frequency, if the lnb has changed reset = first_tune = true; } intermediate_freq = lnb->GetIntermediateFrequency( diseqc_settings, tuning); // if card can auto-FEC, use it -- sometimes NITs are inaccurate if (capabilities & FE_CAN_FEC_AUTO) can_fec_auto = true; // Check DVB-S intermediate frequency here since it requires a fully // initialized diseqc tree CheckFrequency(intermediate_freq); } LOG(VB_CHANNEL, LOG_INFO, LOC + "Old Params: " + prev_tuning.toString() + "\n\t\t\t" + LOC + "New Params: " + tuning.toString()); // DVB-S is in kHz, other DVB is in Hz bool is_dvbs = ((DTVTunerType::kTunerTypeDVBS1 == tunerType) || (DTVTunerType::kTunerTypeDVBS2 == tunerType)); int freq_mult = (is_dvbs) ? 1 : 1000; QString suffix = (is_dvbs) ? "kHz" : "Hz"; if (reset || !prev_tuning.IsEqual(tunerType, tuning, 500 * freq_mult)) { LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Tune(): Tuning to %1%2") .arg(intermediate_freq ? intermediate_freq : tuning.frequency) .arg(suffix)); #if DVB_API_VERSION >=5 if (DTVTunerType::kTunerTypeDVBS2 == tunerType) { struct dtv_property p_clear; struct dtv_properties cmdseq_clear; p_clear.cmd = DTV_CLEAR; cmdseq_clear.num = 1; cmdseq_clear.props = &p_clear; if ((ioctl(fd_frontend, FE_SET_PROPERTY, &cmdseq_clear)) < 0) { LOG(VB_GENERAL, LOG_ERR, LOC + "Tune(): Clearing DTV properties cache failed." + ENO); return false; } struct dtv_properties *cmds = dtvmultiplex_to_dtvproperties( tunerType, tuning, intermediate_freq, can_fec_auto); if (!cmds) { LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to convert DTVMultiplex to DTV_PROPERTY sequence"); return false; } if (VERBOSE_LEVEL_CHECK(VB_CHANNEL, LOG_DEBUG)) { for (uint i = 0; i < cmds->num; i++) { LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("prop %1: cmd = %2, data %3") .arg(i).arg(cmds->props[i].cmd) .arg(cmds->props[i].u.data)); } } int res = ioctl(fd_frontend, FE_SET_PROPERTY, cmds); free(cmds->props); free(cmds); if (res < 0) { LOG(VB_GENERAL, LOG_ERR, LOC + "Tune(): Setting Frontend tuning parameters failed." + ENO); return false; } } else #endif { struct dvb_frontend_parameters params = dtvmultiplex_to_dvbparams( tunerType, tuning, intermediate_freq, can_fec_auto); if (ioctl(fd_frontend, FE_SET_FRONTEND, ¶ms) < 0) { LOG(VB_GENERAL, LOG_ERR, LOC + "Tune(): Setting Frontend tuning parameters failed." + ENO); return false; } } // Extra delay to add for broken DVB drivers if (tuning_delay) usleep(tuning_delay * 1000); wait_for_backend(fd_frontend, 5 /* msec */); prev_tuning = tuning; first_tune = false; } SetSIStandard(tuning.sistandard); LOG(VB_CHANNEL, LOG_INFO, LOC + "Tune(): Frequency tuning successful."); return true; }
void DVBChannel::CheckOptions(DTVMultiplex &tuning) const { if ((tuning.inversion == DTVInversion::kInversionAuto) && !(capabilities & FE_CAN_INVERSION_AUTO)) { LOG(VB_GENERAL, LOG_WARNING, LOC + "'Auto' inversion parameter unsupported by this driver, " "falling back to 'off'."); tuning.inversion = DTVInversion::kInversionOff; } // DVB-S needs a fully initialized diseqc tree and is checked later in Tune if (!diseqc_tree) CheckFrequency(tuning.frequency); if (tunerType.IsFECVariable() && symbol_rate_minimum && symbol_rate_maximum && (symbol_rate_minimum <= symbol_rate_maximum) && (tuning.symbolrate < symbol_rate_minimum || tuning.symbolrate > symbol_rate_maximum)) { LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Symbol Rate setting (%1) is out of range (min/max:%2/%3)") .arg(tuning.symbolrate) .arg(symbol_rate_minimum).arg(symbol_rate_maximum)); } if (tunerType.IsFECVariable() && !CheckCodeRate(tuning.fec)) { LOG(VB_GENERAL, LOG_WARNING, LOC + "Selected fec_inner parameter unsupported by this driver."); } if (tunerType.IsModulationVariable() && !CheckModulation(tuning.modulation)) { LOG(VB_GENERAL, LOG_WARNING, LOC + "Selected modulation parameter unsupported by this driver."); } if (DTVTunerType::kTunerTypeDVBT != tunerType) { LOG(VB_CHANNEL, LOG_INFO, LOC + tuning.toString()); return; } // Check OFDM Tuning params if (!CheckCodeRate(tuning.hp_code_rate)) { LOG(VB_GENERAL, LOG_WARNING, LOC + "Selected code_rate_hp parameter unsupported by this driver."); } if (!CheckCodeRate(tuning.lp_code_rate)) { LOG(VB_GENERAL, LOG_WARNING, LOC + "Selected code_rate_lp parameter unsupported by this driver."); } if ((tuning.bandwidth == DTVBandwidth::kBandwidthAuto) && !(capabilities & FE_CAN_BANDWIDTH_AUTO)) { LOG(VB_GENERAL, LOG_WARNING, LOC + "'Auto' bandwidth parameter unsupported by this driver."); } if ((tuning.trans_mode == DTVTransmitMode::kTransmissionModeAuto) && !(capabilities & FE_CAN_TRANSMISSION_MODE_AUTO)) { LOG(VB_GENERAL, LOG_WARNING, LOC + "'Auto' transmission_mode parameter unsupported by this driver."); } if ((tuning.guard_interval == DTVGuardInterval::kGuardIntervalAuto) && !(capabilities & FE_CAN_GUARD_INTERVAL_AUTO)) { LOG(VB_GENERAL, LOG_WARNING, LOC + "'Auto' guard_interval parameter unsupported by this driver."); } if ((tuning.hierarchy == DTVHierarchy::kHierarchyAuto) && !(capabilities & FE_CAN_HIERARCHY_AUTO)) { LOG(VB_GENERAL, LOG_WARNING, LOC + "'Auto' hierarchy parameter unsupported by this driver. "); } if (!CheckModulation(tuning.modulation)) { LOG(VB_GENERAL, LOG_WARNING, LOC + "Selected modulation parameter unsupported by this driver."); } LOG(VB_CHANNEL, LOG_INFO, LOC + tuning.toString()); }