|
MythTV
0.26-pre
|
00001 // -*- Mode: c++ -*- 00002 00003 #include <cerrno> 00004 #include <cstring> 00005 #include <cmath> 00006 00007 #include <unistd.h> 00008 00009 #include "mythcontext.h" 00010 #include "mythdbcon.h" 00011 #include "dvbsignalmonitor.h" 00012 #include "dvbchannel.h" 00013 #include "dvbstreamdata.h" 00014 #include "atscstreamdata.h" 00015 #include "mpegtables.h" 00016 #include "atsctables.h" 00017 #include "cardutil.h" 00018 00019 #include "dvbtypes.h" 00020 #include "dvbchannel.h" 00021 #include "dvbrecorder.h" 00022 #include "dvbstreamhandler.h" 00023 00024 #define LOC QString("DVBSM(%1): ").arg(channel->GetDevice()) 00025 00040 DVBSignalMonitor::DVBSignalMonitor(int db_cardnum, DVBChannel* _channel, 00041 uint64_t _flags) 00042 : DTVSignalMonitor(db_cardnum, _channel, _flags), 00043 // This snr setup is incorrect for API 3.x but works better 00044 // than int16_t range in practice, however this is correct 00045 // for the 4.0 DVB API which uses a uint16_t for the snr 00046 signalToNoise (QObject::tr("Signal To Noise"), "snr", 00047 0, true, 0, 65535, 0), 00048 bitErrorRate (QObject::tr("Bit Error Rate"), "ber", 00049 65535, false, 0, 65535, 0), 00050 uncorrectedBlocks(QObject::tr("Uncorrected Blocks"), "ucb", 00051 65535, false, 0, 65535, 0), 00052 rotorPosition (QObject::tr("Rotor Progress"), "pos", 00053 100, true, 0, 100, 0), 00054 streamHandlerStarted(false), 00055 streamHandler(NULL) 00056 { 00057 // These two values should probably come from the database... 00058 int wait = 3000; // timeout when waiting on signal 00059 int threshold = 0; // signal strength threshold 00060 00061 signalLock.SetTimeout(wait); 00062 signalStrength.SetTimeout(wait); 00063 signalStrength.SetThreshold(threshold); 00064 00065 // This is incorrect for API 3.x but works better than int16_t range 00066 // in practice, however this is correct for the 4.0 DVB API 00067 signalStrength.SetRange(0, 65535); 00068 00069 bool ok; 00070 _channel->HasLock(&ok); 00071 if (!ok) 00072 LOG(VB_GENERAL, LOG_ERR, LOC + "Cannot read DVB status" + ENO); 00073 00074 uint64_t rmflags = 0; 00075 00076 #define DVB_IO(FLAG, METHOD, MSG) \ 00077 do { if (HasFlags(FLAG)) { bool ok; _channel->METHOD(&ok); \ 00078 if (!ok) { \ 00079 LOG(VB_GENERAL, LOG_WARNING, LOC+"Cannot "+MSG+ENO); \ 00080 rmflags |= FLAG; } \ 00081 else { \ 00082 LOG(VB_CHANNEL, LOG_INFO, LOC + "Can " + MSG); } } } while (false) 00083 00084 DVB_IO(kSigMon_WaitForSig, GetSignalStrength, 00085 "measure Signal Strength"); 00086 DVB_IO(kDVBSigMon_WaitForSNR, GetSNR, 00087 "measure S/N"); 00088 DVB_IO(kDVBSigMon_WaitForBER, GetBitErrorRate, 00089 "measure Bit Error Rate"); 00090 DVB_IO(kDVBSigMon_WaitForUB, GetUncorrectedBlockCount, 00091 "count Uncorrected Blocks"); 00092 00093 #undef DVB_IO 00094 00095 RemoveFlags(rmflags); 00096 00097 LOG(VB_CHANNEL, LOG_INFO, LOC + "DVBSignalMonitor::ctor " + 00098 QString("initial flags %1").arg(sm_flags_to_string(flags))); 00099 00100 minimum_update_rate = _channel->GetMinSignalMonitorDelay(); 00101 if (minimum_update_rate > 30) 00102 usleep(minimum_update_rate * 1000); 00103 00104 streamHandler = DVBStreamHandler::Get(_channel->GetCardNum()); 00105 } 00106 00110 DVBSignalMonitor::~DVBSignalMonitor() 00111 { 00112 Stop(); 00113 DVBStreamHandler::Return(streamHandler); 00114 } 00115 00116 // documented in dtvsignalmonitor.h 00117 void DVBSignalMonitor::SetRotorTarget(float target) 00118 { 00119 QMutexLocker locker(&statusLock); 00120 rotorPosition.SetThreshold((int)roundf(100 * target)); 00121 } 00122 00123 void DVBSignalMonitor::GetRotorStatus(bool &was_moving, bool &is_moving) 00124 { 00125 DVBChannel *dvbchannel = GetDVBChannel(); 00126 if (!dvbchannel) 00127 return; 00128 00129 const DiSEqCDevRotor *rotor = dvbchannel->GetRotor(); 00130 if (!rotor) 00131 return; 00132 00133 QMutexLocker locker(&statusLock); 00134 was_moving = rotorPosition.GetValue() < 100; 00135 int pos = (int)truncf(rotor->GetProgress() * 100); 00136 rotorPosition.SetValue(pos); 00137 is_moving = rotorPosition.GetValue() < 100; 00138 } 00139 00143 void DVBSignalMonitor::Stop(void) 00144 { 00145 LOG(VB_CHANNEL, LOG_INFO, LOC + "Stop() -- begin"); 00146 SignalMonitor::Stop(); 00147 if (GetStreamData()) 00148 streamHandler->RemoveListener(GetStreamData()); 00149 streamHandlerStarted = false; 00150 streamHandler->SetRetuneAllowed(false, NULL, NULL); 00151 LOG(VB_CHANNEL, LOG_INFO, LOC + "Stop() -- end"); 00152 } 00153 00154 QStringList DVBSignalMonitor::GetStatusList(void) const 00155 { 00156 QStringList list = DTVSignalMonitor::GetStatusList(); 00157 statusLock.lock(); 00158 if (HasFlags(kDVBSigMon_WaitForSNR)) 00159 list<<signalToNoise.GetName()<<signalToNoise.GetStatus(); 00160 if (HasFlags(kDVBSigMon_WaitForBER)) 00161 list<<bitErrorRate.GetName()<<bitErrorRate.GetStatus(); 00162 if (HasFlags(kDVBSigMon_WaitForUB)) 00163 list<<uncorrectedBlocks.GetName()<<uncorrectedBlocks.GetStatus(); 00164 if (HasFlags(kDVBSigMon_WaitForPos)) 00165 list<<rotorPosition.GetName()<<rotorPosition.GetStatus(); 00166 statusLock.unlock(); 00167 return list; 00168 } 00169 00170 void DVBSignalMonitor::HandlePMT(uint program_num, const ProgramMapTable *pmt) 00171 { 00172 DTVSignalMonitor::HandlePMT(program_num, pmt); 00173 00174 if (pmt->ProgramNumber() == (uint)programNumber) 00175 { 00176 DVBChannel *dvbchannel = GetDVBChannel(); 00177 if (dvbchannel) 00178 dvbchannel->SetPMT(pmt); 00179 } 00180 } 00181 00182 void DVBSignalMonitor::HandleSTT(const SystemTimeTable *stt) 00183 { 00184 DTVSignalMonitor::HandleSTT(stt); 00185 DVBChannel *dvbchannel = GetDVBChannel(); 00186 if (dvbchannel) 00187 dvbchannel->SetTimeOffset(GetStreamData()->TimeOffset()); 00188 } 00189 00190 void DVBSignalMonitor::HandleTDT(const TimeDateTable *tdt) 00191 { 00192 DTVSignalMonitor::HandleTDT(tdt); 00193 DVBChannel *dvbchannel = GetDVBChannel(); 00194 if (dvbchannel) 00195 dvbchannel->SetTimeOffset(GetStreamData()->TimeOffset()); 00196 } 00197 00198 DVBChannel *DVBSignalMonitor::GetDVBChannel(void) 00199 { 00200 return dynamic_cast<DVBChannel*>(channel); 00201 } 00202 00209 void DVBSignalMonitor::UpdateValues(void) 00210 { 00211 if (!running || exit) 00212 return; 00213 00214 if (streamHandlerStarted) 00215 { 00216 if (!streamHandler->IsRunning()) 00217 { 00218 error = QObject::tr("Error: stream handler died"); 00219 update_done = true; 00220 return; 00221 } 00222 00223 EmitStatus(); 00224 if (IsAllGood()) 00225 SendMessageAllGood(); 00226 00227 // TODO dtv signals... 00228 00229 update_done = true; 00230 return; 00231 } 00232 00233 AddFlags(kSigMon_WaitForSig); 00234 00235 DVBChannel *dvbchannel = GetDVBChannel(); 00236 if (!dvbchannel) 00237 return; 00238 00239 // Handle retuning after rotor has turned 00240 if (HasFlags(SignalMonitor::kDVBSigMon_WaitForPos)) 00241 { 00242 if (dvbchannel->GetRotor()) 00243 { 00244 if (!streamHandler->IsRetuneAllowed()) 00245 streamHandler->SetRetuneAllowed(true, this, dvbchannel); 00246 streamHandler->RetuneMonitor(); 00247 } 00248 else 00249 RemoveFlags(SignalMonitor::kDVBSigMon_WaitForPos); 00250 } 00251 00252 bool wasLocked = false, isLocked = false; 00253 uint sig = 0, snr = 0, ber = 0, ublocks = 0; 00254 00255 // Get info from card 00256 bool has_lock = dvbchannel->HasLock(); 00257 if (HasFlags(kSigMon_WaitForSig)) 00258 sig = (uint) (dvbchannel->GetSignalStrength() * 65535); 00259 if (HasFlags(kDVBSigMon_WaitForSNR)) 00260 snr = (uint) (dvbchannel->GetSNR() * 65535); 00261 if (HasFlags(kDVBSigMon_WaitForBER)) 00262 ber = (uint) dvbchannel->GetBitErrorRate(); 00263 if (HasFlags(kDVBSigMon_WaitForUB)) 00264 ublocks = (uint) dvbchannel->GetUncorrectedBlockCount(); 00265 00266 has_lock |= streamHandler->IsRunning(); 00267 00268 // Set SignalMonitorValues from info from card. 00269 { 00270 QMutexLocker locker(&statusLock); 00271 00272 // BER and UB are actually uint32 values, but we 00273 // clamp them at 64K. This is because these values 00274 // are acutally cumulative, but we don't try to 00275 // normalize these to a time period. 00276 00277 wasLocked = signalLock.IsGood(); 00278 signalLock.SetValue((has_lock) ? 1 : 0); 00279 isLocked = signalLock.IsGood(); 00280 00281 if (HasFlags(kSigMon_WaitForSig)) 00282 signalStrength.SetValue(sig); 00283 if (HasFlags(kDVBSigMon_WaitForSNR)) 00284 signalToNoise.SetValue(snr); 00285 if (HasFlags(kDVBSigMon_WaitForBER)) 00286 bitErrorRate.SetValue(ber); 00287 if (HasFlags(kDVBSigMon_WaitForUB)) 00288 uncorrectedBlocks.SetValue(ublocks); 00289 } 00290 00291 // Debug output 00292 if (wasLocked != isLocked) 00293 { 00294 LOG(VB_CHANNEL, LOG_INFO, LOC + "UpdateValues -- Signal " + 00295 (isLocked ? "Locked" : "Lost")); 00296 } 00297 00298 EmitStatus(); 00299 if (IsAllGood()) 00300 SendMessageAllGood(); 00301 00302 // Start table monitoring if we are waiting on any table 00303 // and we have a lock. 00304 if (isLocked && GetStreamData() && 00305 (!HasFlags(kDVBSigMon_WaitForPos) || rotorPosition.IsGood()) && 00306 HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT | 00307 kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT | 00308 kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT)) 00309 { 00310 GetStreamData()->AddListeningPID(MPEG_PAT_PID); 00311 streamHandler->AddListener(GetStreamData(), true, false); 00312 streamHandlerStarted = true; 00313 } 00314 00315 update_done = true; 00316 } 00317 00321 void DVBSignalMonitor::EmitStatus(void) 00322 { 00323 // Emit signals.. 00324 DTVSignalMonitor::EmitStatus(); 00325 if (HasFlags(kDVBSigMon_WaitForSNR)) 00326 SendMessage(kStatusSignalToNoise, signalToNoise); 00327 if (HasFlags(kDVBSigMon_WaitForBER)) 00328 SendMessage(kStatusBitErrorRate, bitErrorRate); 00329 if (HasFlags(kDVBSigMon_WaitForUB)) 00330 SendMessage(kStatusUncorrectedBlocks, uncorrectedBlocks); 00331 if (HasFlags(kDVBSigMon_WaitForPos)) 00332 SendMessage(kStatusRotorPosition, rotorPosition); 00333 }
1.7.6.1