|
MythTV
0.26-pre
|
00001 // -*- Mode: c++ -*- 00002 // Copyright (c) 2005, Daniel Thor Kristjansson 00003 00004 // C headers 00005 #include <sys/types.h> 00006 #include <signal.h> 00007 #include <unistd.h> 00008 00009 // MythTV headers 00010 #include "scriptsignalmonitor.h" 00011 #include "signalmonitor.h" 00012 #include "mythcontext.h" 00013 #include "compat.h" 00014 #include "mythlogging.h" 00015 #include "tv_rec.h" 00016 00017 extern "C" { 00018 #include "libavcodec/avcodec.h" 00019 } 00020 #include "mythmiscutil.h" 00021 00022 #ifdef USING_DVB 00023 # include "dvbsignalmonitor.h" 00024 # include "dvbchannel.h" 00025 #endif 00026 00027 #ifdef USING_V4L2 00028 # include "analogsignalmonitor.h" 00029 # include "v4lchannel.h" 00030 #endif 00031 00032 #ifdef USING_HDHOMERUN 00033 # include "hdhrsignalmonitor.h" 00034 # include "hdhrchannel.h" 00035 #endif 00036 00037 #ifdef USING_IPTV 00038 # include "iptvsignalmonitor.h" 00039 # include "iptvchannel.h" 00040 #endif 00041 00042 #ifdef USING_FIREWIRE 00043 # include "firewiresignalmonitor.h" 00044 # include "firewirechannel.h" 00045 #endif 00046 00047 #ifdef USING_ASI 00048 # include "asisignalmonitor.h" 00049 # include "asichannel.h" 00050 #endif 00051 00052 #ifdef USING_CETON 00053 # include "cetonsignalmonitor.h" 00054 # include "cetonchannel.h" 00055 #endif 00056 00057 #undef DBG_SM 00058 #define DBG_SM(FUNC, MSG) LOG(VB_CHANNEL, LOG_DEBUG, \ 00059 QString("SM(%1)::%2: %3").arg(channel->GetDevice()).arg(FUNC).arg(MSG)) 00060 00078 static void ALRMhandler(int /*sig*/) 00079 { 00080 LOG(VB_GENERAL, LOG_NOTICE, "SignalMonitor: Got SIGALRM"); 00081 signal(SIGINT, ALRMhandler); 00082 } 00083 00084 SignalMonitor *SignalMonitor::Init(QString cardtype, int db_cardnum, 00085 ChannelBase *channel) 00086 { 00087 (void) cardtype; 00088 (void) db_cardnum; 00089 (void) channel; 00090 00091 SignalMonitor *signalMonitor = NULL; 00092 00093 { 00094 QMutexLocker locker(avcodeclock); 00095 #if 0 00096 avcodec_register_all(); 00097 #endif 00098 } 00099 00100 #ifdef USING_DVB 00101 if (CardUtil::IsDVBCardType(cardtype)) 00102 { 00103 DVBChannel *dvbc = dynamic_cast<DVBChannel*>(channel); 00104 if (dvbc) 00105 signalMonitor = new DVBSignalMonitor(db_cardnum, dvbc); 00106 } 00107 #endif 00108 00109 #ifdef USING_V4L2 00110 if ((cardtype.toUpper() == "HDPVR")) 00111 { 00112 V4LChannel *chan = dynamic_cast<V4LChannel*>(channel); 00113 if (chan) 00114 signalMonitor = new AnalogSignalMonitor(db_cardnum, chan); 00115 } 00116 #endif 00117 00118 #ifdef USING_HDHOMERUN 00119 if (cardtype.toUpper() == "HDHOMERUN") 00120 { 00121 HDHRChannel *hdhrc = dynamic_cast<HDHRChannel*>(channel); 00122 if (hdhrc) 00123 signalMonitor = new HDHRSignalMonitor(db_cardnum, hdhrc); 00124 } 00125 #endif 00126 00127 #ifdef USING_CETON 00128 if (cardtype.toUpper() == "CETON") 00129 { 00130 CetonChannel *cetonchan = dynamic_cast<CetonChannel*>(channel); 00131 if (cetonchan) 00132 signalMonitor = new CetonSignalMonitor(db_cardnum, cetonchan); 00133 } 00134 #endif 00135 00136 #ifdef USING_IPTV 00137 if (cardtype.toUpper() == "FREEBOX") 00138 { 00139 IPTVChannel *fbc = dynamic_cast<IPTVChannel*>(channel); 00140 if (fbc) 00141 signalMonitor = new IPTVSignalMonitor(db_cardnum, fbc); 00142 } 00143 #endif 00144 00145 #ifdef USING_FIREWIRE 00146 if (cardtype.toUpper() == "FIREWIRE") 00147 { 00148 FirewireChannel *fc = dynamic_cast<FirewireChannel*>(channel); 00149 if (fc) 00150 signalMonitor = new FirewireSignalMonitor(db_cardnum, fc); 00151 } 00152 #endif 00153 00154 #ifdef USING_ASI 00155 if (cardtype.toUpper() == "ASI") 00156 { 00157 ASIChannel *fc = dynamic_cast<ASIChannel*>(channel); 00158 if (fc) 00159 signalMonitor = new ASISignalMonitor(db_cardnum, fc); 00160 } 00161 #endif 00162 00163 if (!signalMonitor && channel) 00164 { 00165 signalMonitor = new ScriptSignalMonitor(db_cardnum, channel); 00166 } 00167 00168 if (!signalMonitor) 00169 { 00170 LOG(VB_GENERAL, LOG_ERR, 00171 QString("Failed to create signal monitor in Init(%1, %2, 0x%3)") 00172 .arg(cardtype).arg(db_cardnum).arg((long)channel,0,16)); 00173 } 00174 00175 return signalMonitor; 00176 } 00177 00191 SignalMonitor::SignalMonitor(int _capturecardnum, ChannelBase *_channel, 00192 uint64_t wait_for_mask) 00193 : MThread("SignalMonitor"), 00194 channel(_channel), pParent(NULL), 00195 capturecardnum(_capturecardnum), flags(wait_for_mask), 00196 update_rate(25), minimum_update_rate(5), 00197 update_done(false), notify_frontend(true), 00198 tablemon(false), eit_scan(false), 00199 signalLock (QObject::tr("Signal Lock"), "slock", 00200 1, true, 0, 1, 0), 00201 signalStrength(QObject::tr("Signal Power"), "signal", 00202 0, true, 0, 100, 0), 00203 scriptStatus (QObject::tr("Script Status"), "script", 00204 3, true, 0, 3, 0), 00205 running(false), exit(false), 00206 statusLock(QMutex::Recursive) 00207 { 00208 if (!channel->IsExternalChannelChangeSupported()) 00209 { 00210 scriptStatus.SetValue(3); 00211 } 00212 } 00213 00217 SignalMonitor::~SignalMonitor() 00218 { 00219 Stop(); 00220 wait(); 00221 } 00222 00223 void SignalMonitor::AddFlags(uint64_t _flags) 00224 { 00225 DBG_SM("AddFlags", sm_flags_to_string(_flags)); 00226 flags |= _flags; 00227 } 00228 00229 void SignalMonitor::RemoveFlags(uint64_t _flags) 00230 { 00231 DBG_SM("RemoveFlags", sm_flags_to_string(_flags)); 00232 flags &= ~_flags; 00233 } 00234 00235 bool SignalMonitor::HasFlags(uint64_t _flags) const 00236 { 00237 return (flags & _flags) == _flags; 00238 } 00239 00240 bool SignalMonitor::HasAnyFlag(uint64_t _flags) const 00241 { 00242 return (flags & _flags); 00243 } 00244 00248 void SignalMonitor::Start() 00249 { 00250 DBG_SM("Start", "begin"); 00251 { 00252 QMutexLocker locker(&startStopLock); 00253 exit = false; 00254 start(); 00255 while (!running) 00256 startStopWait.wait(locker.mutex()); 00257 } 00258 DBG_SM("Start", "end"); 00259 } 00260 00264 void SignalMonitor::Stop() 00265 { 00266 DBG_SM("Stop", "begin"); 00267 00268 QMutexLocker locker(&startStopLock); 00269 exit = true; 00270 if (running) 00271 { 00272 locker.unlock(); 00273 wait(); 00274 } 00275 00276 DBG_SM("Stop", "end"); 00277 } 00278 00288 QStringList SignalMonitor::GetStatusList(void) const 00289 { 00290 QStringList list; 00291 statusLock.lock(); 00292 list<<scriptStatus.GetName()<<scriptStatus.GetStatus(); 00293 list<<signalLock.GetName()<<signalLock.GetStatus(); 00294 if (HasFlags(kSigMon_WaitForSig)) 00295 list<<signalStrength.GetName()<<signalStrength.GetStatus(); 00296 statusLock.unlock(); 00297 00298 return list; 00299 } 00300 00302 void SignalMonitor::run(void) 00303 { 00304 RunProlog(); 00305 00306 QMutexLocker locker(&startStopLock); 00307 running = true; 00308 startStopWait.wakeAll(); 00309 00310 while (!exit) 00311 { 00312 locker.unlock(); 00313 00314 UpdateValues(); 00315 00316 if (notify_frontend && capturecardnum>=0) 00317 { 00318 QStringList slist = GetStatusList(); 00319 MythEvent me(QString("SIGNAL %1").arg(capturecardnum), slist); 00320 gCoreContext->dispatch(me); 00321 } 00322 00323 locker.relock(); 00324 startStopWait.wait(locker.mutex(), update_rate); 00325 } 00326 00327 // We need to send a last informational message because a 00328 // signal update may have come in while we were sleeping 00329 // if we are using the multithreaded dtvsignalmonitor. 00330 locker.unlock(); 00331 if (notify_frontend && capturecardnum>=0) 00332 { 00333 QStringList slist = GetStatusList(); 00334 MythEvent me(QString("SIGNAL %1").arg(capturecardnum), slist); 00335 gCoreContext->dispatch(me); 00336 } 00337 locker.relock(); 00338 00339 running = false; 00340 startStopWait.wakeAll(); 00341 00342 RunEpilog(); 00343 } 00344 00345 void SignalMonitor::AddListener(SignalMonitorListener *listener) 00346 { 00347 QMutexLocker locker(&listenerLock); 00348 for (uint i = 0; i < listeners.size(); i++) 00349 { 00350 if (listeners[i] == listener) 00351 return; 00352 } 00353 listeners.push_back(listener); 00354 } 00355 00356 void SignalMonitor::RemoveListener(SignalMonitorListener *listener) 00357 { 00358 QMutexLocker locker(&listenerLock); 00359 00360 vector<SignalMonitorListener*> new_listeners; 00361 for (uint i = 0; i < listeners.size(); i++) 00362 { 00363 if (listeners[i] != listener) 00364 new_listeners.push_back(listeners[i]); 00365 } 00366 00367 listeners = new_listeners; 00368 } 00369 00370 void SignalMonitor::SendMessage( 00371 SignalMonitorMessageType type, const SignalMonitorValue &value) 00372 { 00373 statusLock.lock(); 00374 SignalMonitorValue val = value; 00375 statusLock.unlock(); 00376 00377 QMutexLocker locker(&listenerLock); 00378 for (uint i = 0; i < listeners.size(); i++) 00379 { 00380 SignalMonitorListener *listener = listeners[i]; 00381 DVBSignalMonitorListener *dvblistener = 00382 dynamic_cast<DVBSignalMonitorListener*>(listener); 00383 00384 switch (type) 00385 { 00386 case kStatusSignalLock: 00387 listener->StatusSignalLock(val); 00388 break; 00389 case kAllGood: 00390 listener->AllGood(); 00391 break; 00392 case kStatusSignalStrength: 00393 listener->StatusSignalStrength(val); 00394 break; 00395 case kStatusChannelTuned: 00396 listener->StatusChannelTuned(val); 00397 break; 00398 case kStatusSignalToNoise: 00399 if (dvblistener) 00400 dvblistener->StatusSignalToNoise(val); 00401 break; 00402 case kStatusBitErrorRate: 00403 if (dvblistener) 00404 dvblistener->StatusBitErrorRate(val); 00405 break; 00406 case kStatusUncorrectedBlocks: 00407 if (dvblistener) 00408 dvblistener->StatusUncorrectedBlocks(val); 00409 break; 00410 case kStatusRotorPosition: 00411 if (dvblistener) 00412 dvblistener->StatusRotorPosition(val); 00413 break; 00414 } 00415 } 00416 } 00417 00418 void SignalMonitor::UpdateValues(void) 00419 { 00420 QMutexLocker locker(&statusLock); 00421 if (channel->IsExternalChannelChangeSupported() && 00422 (scriptStatus.GetValue() < 2)) 00423 { 00424 scriptStatus.SetValue(channel->GetScriptStatus()); 00425 } 00426 } 00427 00428 void SignalMonitor::SendMessageAllGood(void) 00429 { 00430 QMutexLocker locker(&listenerLock); 00431 for (uint i = 0; i < listeners.size(); i++) 00432 listeners[i]->AllGood(); 00433 } 00434 00435 void SignalMonitor::EmitStatus(void) 00436 { 00437 SendMessage(kStatusChannelTuned, scriptStatus); 00438 SendMessage(kStatusSignalLock, signalLock); 00439 if (HasFlags(kSigMon_WaitForSig)) 00440 SendMessage(kStatusSignalStrength, signalStrength); 00441 }
1.7.6.1