00001
00002
00003
00004
00005 #include <sys/types.h>
00006 #include <signal.h>
00007 #include <unistd.h>
00008
00009
00010 #include "mythcontext.h"
00011 #include "signalmonitor.h"
00012 #include "compat.h"
00013
00014 extern "C" {
00015 #include "../libavcodec/avcodec.h"
00016 }
00017 #include "../libmyth/util.h"
00018
00019 #ifdef USING_DVB
00020 # include "dvbsignalmonitor.h"
00021 # include "dvbchannel.h"
00022 #endif
00023
00024 #ifdef USING_V4L
00025 # include "analogsignalmonitor.h"
00026 # include "channel.h"
00027 #endif
00028
00029 #ifdef USING_HDHOMERUN
00030 # include "hdhrsignalmonitor.h"
00031 # include "hdhrchannel.h"
00032 #endif
00033
00034 #ifdef USING_IPTV
00035 # include "iptvsignalmonitor.h"
00036 # include "iptvchannel.h"
00037 #endif
00038
00039 #ifdef USING_FIREWIRE
00040 # include "firewiresignalmonitor.h"
00041 # include "firewirechannel.h"
00042 #endif
00043
00044 #undef DBG_SM
00045 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \
00046 "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG);
00047
00065 void ALRMhandler(int )
00066 {
00067 cerr<<"SignalMonitor: Got SIGALRM"<<endl;
00068 signal(SIGINT, ALRMhandler);
00069 }
00070
00071 SignalMonitor *SignalMonitor::Init(QString cardtype, int db_cardnum,
00072 ChannelBase *channel)
00073 {
00074 (void) cardtype;
00075 (void) db_cardnum;
00076 (void) channel;
00077
00078 SignalMonitor *signalMonitor = NULL;
00079
00080 {
00081 QMutexLocker locker(&avcodeclock);
00082 avcodec_init();
00083 }
00084
00085 #ifdef USING_DVB
00086 if (CardUtil::IsDVBCardType(cardtype))
00087 {
00088 DVBChannel *dvbc = dynamic_cast<DVBChannel*>(channel);
00089 if (dvbc)
00090 signalMonitor = new DVBSignalMonitor(db_cardnum, dvbc);
00091 }
00092 #endif
00093
00094 #ifdef USING_V4L
00095 if ((cardtype.upper() == "V4L") ||
00096 (cardtype.upper() == "MPEG"))
00097 {
00098 Channel *chan = dynamic_cast<Channel*>(channel);
00099 if (chan)
00100 signalMonitor = new AnalogSignalMonitor(db_cardnum, chan);
00101 }
00102 #endif
00103
00104 #ifdef USING_HDHOMERUN
00105 if (cardtype.upper() == "HDHOMERUN")
00106 {
00107 HDHRChannel *hdhrc = dynamic_cast<HDHRChannel*>(channel);
00108 if (hdhrc)
00109 signalMonitor = new HDHRSignalMonitor(db_cardnum, hdhrc);
00110 }
00111 #endif
00112
00113 #ifdef USING_IPTV
00114 if (cardtype.upper() == "FREEBOX")
00115 {
00116 IPTVChannel *fbc = dynamic_cast<IPTVChannel*>(channel);
00117 if (fbc)
00118 signalMonitor = new IPTVSignalMonitor(db_cardnum, fbc);
00119 }
00120 #endif
00121
00122 #ifdef USING_FIREWIRE
00123 if (cardtype.upper() == "FIREWIRE")
00124 {
00125 FirewireChannel *fc = dynamic_cast<FirewireChannel*>(channel);
00126 if (fc)
00127 signalMonitor = new FirewireSignalMonitor(db_cardnum, fc);
00128 }
00129 #endif
00130
00131 if (!signalMonitor)
00132 {
00133 VERBOSE(VB_IMPORTANT,
00134 QString("Failed to create signal monitor in Init(%1, %2, 0x%3)")
00135 .arg(cardtype).arg(db_cardnum).arg((long)channel,0,16));
00136 }
00137
00138 return signalMonitor;
00139 }
00140
00155 SignalMonitor::SignalMonitor(int _capturecardnum, ChannelBase *_channel,
00156 uint64_t wait_for_mask, const char *name)
00157 : QObject(NULL, name), channel(_channel),
00158 capturecardnum(_capturecardnum), flags(wait_for_mask),
00159 update_rate(25), minimum_update_rate(5),
00160 running(false), exit(false),
00161 update_done(false), notify_frontend(true),
00162 signalLock (QObject::tr("Signal Lock"), "slock",
00163 1, true, 0, 1, 0),
00164 signalStrength(QObject::tr("Signal Power"), "signal",
00165 0, true, 0, 100, 0),
00166 statusLock(true)
00167 {
00168 }
00169
00173 SignalMonitor::~SignalMonitor()
00174 {
00175 Stop();
00176 }
00177
00181 void SignalMonitor::deleteLater(void)
00182 {
00183 disconnect();
00184 Stop();
00185 QObject::deleteLater();
00186 }
00187
00188 void SignalMonitor::AddFlags(uint64_t _flags)
00189 {
00190 DBG_SM("AddFlags", sm_flags_to_string(_flags));
00191 flags |= _flags;
00192 }
00193
00194 void SignalMonitor::RemoveFlags(uint64_t _flags)
00195 {
00196 DBG_SM("RemoveFlags", sm_flags_to_string(_flags));
00197 flags &= ~_flags;
00198 }
00199
00200 bool SignalMonitor::HasFlags(uint64_t _flags) const
00201 {
00202 return (flags & _flags) == _flags;
00203 }
00204
00205 bool SignalMonitor::HasAnyFlag(uint64_t _flags) const
00206 {
00207 return (flags & _flags);
00208 }
00209
00213 void SignalMonitor::Start()
00214 {
00215 DBG_SM("Start", "begin");
00216 {
00217 QMutexLocker locker(&startStopLock);
00218 if (!running)
00219 pthread_create(&monitor_thread, NULL, SpawnMonitorLoop, this);
00220 while (!running)
00221 usleep(50);
00222 }
00223 DBG_SM("Start", "end");
00224 }
00225
00229 void SignalMonitor::Stop()
00230 {
00231 DBG_SM("Stop", "begin");
00232 {
00233 QMutexLocker locker(&startStopLock);
00234 if (running)
00235 {
00236 exit = true;
00237 pthread_join(monitor_thread, NULL);
00238 }
00239 }
00240 DBG_SM("Stop", "end");
00241 }
00242
00247 void SignalMonitor::Kick()
00248 {
00249 update_done = false;
00250
00251
00252
00253 while (!update_done)
00254 usleep(50);
00255 }
00256
00271 QStringList SignalMonitor::GetStatusList(bool kick)
00272 {
00273 if (kick && running)
00274 Kick();
00275 else if (!running)
00276 UpdateValues();
00277
00278 QStringList list;
00279 statusLock.lock();
00280 list<<signalLock.GetName()<<signalLock.GetStatus();
00281 if (HasFlags(kDTVSigMon_WaitForSig))
00282 list<<signalStrength.GetName()<<signalStrength.GetStatus();
00283 statusLock.unlock();
00284
00285 return list;
00286 }
00287
00291 void SignalMonitor::MonitorLoop()
00292 {
00293
00294
00295 running = true;
00296 exit = false;
00297
00298 while (!exit)
00299 {
00300 UpdateValues();
00301
00302 if (notify_frontend && capturecardnum>=0)
00303 {
00304 QStringList slist = GetStatusList(false);
00305 MythEvent me(QString("SIGNAL %1").arg(capturecardnum), slist);
00306 gContext->dispatch(me);
00307
00308 }
00309
00310 usleep(update_rate * 1000);
00311 }
00312
00313
00314
00315
00316 if (notify_frontend && capturecardnum>=0)
00317 {
00318 QStringList slist = GetStatusList(false);
00319 MythEvent me(QString("SIGNAL %1").arg(capturecardnum), slist);
00320 gContext->dispatch(me);
00321 }
00322
00323
00324
00325 running = false;
00326 }
00327
00331 void* SignalMonitor::SpawnMonitorLoop(void* self)
00332 {
00333 ((SignalMonitor*)self)->MonitorLoop();
00334 return NULL;
00335 }
00336
00346 bool SignalMonitor::WaitForLock(int timeout)
00347 {
00348 statusLock.lock();
00349 if (-1 == timeout)
00350 timeout = signalLock.GetTimeout();
00351 statusLock.unlock();
00352 if (timeout<0)
00353 return false;
00354
00355 MythTimer t;
00356 t.start();
00357 if (running)
00358 {
00359 while (t.elapsed()<timeout && running)
00360 {
00361 Kick();
00362 statusLock.lock();
00363 bool ok = signalLock.IsGood();
00364 statusLock.unlock();
00365 if (ok)
00366 return true;
00367
00368 usleep(50);
00369 }
00370 if (!running)
00371 return WaitForLock(timeout-t.elapsed());
00372 }
00373 else
00374 {
00375 while (t.elapsed()<timeout && !running)
00376 {
00377 UpdateValues();
00378 statusLock.lock();
00379 bool ok = signalLock.IsGood();
00380 statusLock.unlock();
00381 if (ok)
00382 return true;
00383
00384 usleep(50);
00385 }
00386 if (running)
00387 return WaitForLock(timeout-t.elapsed());
00388 }
00389 return false;
00390 }