00001
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
00044
00045
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
00058 int wait = 3000;
00059 int threshold = 0;
00060
00061 signalLock.SetTimeout(wait);
00062 signalStrength.SetTimeout(wait);
00063 signalStrength.SetThreshold(threshold);
00064
00065
00066
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
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
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
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
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
00269 {
00270 QMutexLocker locker(&statusLock);
00271
00272
00273
00274
00275
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
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
00303
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
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 }