MythTV  master
signalmonitor.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 // Copyright (c) 2005, Daniel Thor Kristjansson
3 
4 // C headers
5 #include <csignal>
6 #include <sys/types.h>
7 #include <unistd.h>
8 
9 // MythTV headers
10 #include "scriptsignalmonitor.h"
11 #include "signalmonitor.h"
12 #include "mythcontext.h"
13 #include "compat.h"
14 #include "mythlogging.h"
15 #include "tv_rec.h"
16 
17 extern "C" {
18 #include "libavcodec/avcodec.h"
19 }
20 #include "mythdate.h"
21 
22 #ifdef USING_DVB
23 # include "dvbsignalmonitor.h"
24 # include "dvbchannel.h"
25 #endif
26 
27 #ifdef USING_V4L2
28 // Old
29 # include "analogsignalmonitor.h"
30 // New
31 # include "v4l2encsignalmonitor.h"
32 # include "v4lchannel.h"
33 #endif
34 
35 #ifdef USING_HDHOMERUN
36 # include "hdhrsignalmonitor.h"
37 # include "hdhrchannel.h"
38 #endif
39 
40 #ifdef USING_SATIP
41 # include "satipsignalmonitor.h"
42 # include "satipchannel.h"
43 #endif
44 
45 #ifdef USING_IPTV
46 # include "iptvsignalmonitor.h"
47 # include "iptvchannel.h"
48 #endif
49 
50 #ifdef USING_FIREWIRE
51 # include "firewiresignalmonitor.h"
52 # include "firewirechannel.h"
53 #endif
54 
55 #ifdef USING_ASI
56 # include "asisignalmonitor.h"
57 # include "asichannel.h"
58 #endif
59 
60 #ifdef USING_CETON
61 # include "cetonsignalmonitor.h"
62 # include "cetonchannel.h"
63 #endif
64 
65 #include "ExternalSignalMonitor.h"
66 #include "ExternalChannel.h"
67 
68 #undef DBG_SM
69 #define DBG_SM(FUNC, MSG) LOG(VB_CHANNEL, LOG_DEBUG, \
70  QString("SigMon[%1](%2)::%3: %4").arg(m_inputid) \
71  .arg(m_channel->GetDevice()).arg(FUNC).arg(MSG))
72 
90 SignalMonitor *SignalMonitor::Init(const QString& cardtype, int db_cardnum,
92  bool release_stream)
93 {
94  (void) cardtype;
95  (void) db_cardnum;
96  (void) channel;
97 
98  SignalMonitor *signalMonitor = nullptr;
99 
100  if (cardtype == "GuaranteedToFail")
101  {
102  // This lets all the conditionally compiled tests be set up as
103  // 'else if' statements
104  }
105 #ifdef USING_DVB
106  else if (CardUtil::IsDVBInputType(cardtype))
107  {
108  auto *dvbc = dynamic_cast<DVBChannel*>(channel);
109  if (dvbc)
110  signalMonitor = new DVBSignalMonitor(db_cardnum, dvbc,
111  release_stream);
112  }
113 #endif
114 
115 #ifdef USING_V4L2
116  else if ((cardtype.toUpper() == "HDPVR"))
117  {
118  auto *chan = dynamic_cast<V4LChannel*>(channel);
119  if (chan)
120  signalMonitor = new AnalogSignalMonitor(db_cardnum, chan,
121  release_stream);
122  }
123  else if (cardtype.toUpper() == "V4L2ENC")
124  {
125  auto *chan = dynamic_cast<V4LChannel*>(channel);
126  if (chan)
127  signalMonitor = new V4L2encSignalMonitor(db_cardnum, chan,
128  release_stream);
129  }
130 #endif
131 
132 #ifdef USING_HDHOMERUN
133  else if (cardtype.toUpper() == "HDHOMERUN")
134  {
135  auto *hdhrc = dynamic_cast<HDHRChannel*>(channel);
136  if (hdhrc)
137  signalMonitor = new HDHRSignalMonitor(db_cardnum, hdhrc,
138  release_stream);
139  }
140 #endif
141 
142 #ifdef USING_SATIP
143  else if (cardtype.toUpper() == "SATIP")
144  {
145  auto *satipchan = dynamic_cast<SatIPChannel*>(channel);
146  if (satipchan)
147  signalMonitor = new SatIPSignalMonitor(db_cardnum, satipchan);
148  }
149 #endif
150 
151 #ifdef USING_CETON
152  else if (cardtype.toUpper() == "CETON")
153  {
154  auto *cetonchan = dynamic_cast<CetonChannel*>(channel);
155  if (cetonchan)
156  signalMonitor = new CetonSignalMonitor(db_cardnum, cetonchan,
157  release_stream);
158  }
159 #endif
160 
161 #ifdef USING_IPTV
162  else if (cardtype.toUpper() == "FREEBOX")
163  {
164  auto *fbc = dynamic_cast<IPTVChannel*>(channel);
165  if (fbc)
166  signalMonitor = new IPTVSignalMonitor(db_cardnum, fbc,
167  release_stream);
168  }
169 #endif
170 
171 #ifdef USING_VBOX
172  else if (cardtype.toUpper() == "VBOX")
173  {
174  auto *fbc = dynamic_cast<IPTVChannel*>(channel);
175  if (fbc)
176  signalMonitor = new IPTVSignalMonitor(db_cardnum, fbc,
177  release_stream);
178  }
179 #endif
180 
181 #ifdef USING_FIREWIRE
182  else if (cardtype.toUpper() == "FIREWIRE")
183  {
184  auto *fc = dynamic_cast<FirewireChannel*>(channel);
185  if (fc)
186  signalMonitor = new FirewireSignalMonitor(db_cardnum, fc,
187  release_stream);
188  }
189 #endif
190 
191 #ifdef USING_ASI
192  else if (cardtype.toUpper() == "ASI")
193  {
194  auto *fc = dynamic_cast<ASIChannel*>(channel);
195  if (fc)
196  signalMonitor = new ASISignalMonitor(db_cardnum, fc,
197  release_stream);
198  }
199 #endif
200 
201  else if (cardtype.toUpper() == "EXTERNAL")
202  {
203  auto *fc = dynamic_cast<ExternalChannel*>(channel);
204  if (fc)
205  signalMonitor = new ExternalSignalMonitor(db_cardnum, fc,
206  release_stream);
207  }
208 
209  if (!signalMonitor && channel)
210  {
211  signalMonitor = new ScriptSignalMonitor(db_cardnum, channel,
212  release_stream);
213  }
214 
215  if (!signalMonitor)
216  {
217  LOG(VB_GENERAL, LOG_ERR,
218  QString("Failed to create signal monitor in Init(%1, %2, 0x%3)")
219  .arg(cardtype).arg(db_cardnum).arg((long)channel,0,16));
220  }
221 
222  return signalMonitor;
223 }
224 
238  bool _release_stream, uint64_t wait_for_mask)
239  : MThread("SignalMonitor"),
240  m_channel(_channel),
241  m_inputid(_inputid), m_flags(wait_for_mask),
242  m_releaseStream(_release_stream),
243  m_signalLock (QCoreApplication::translate("(Common)", "Signal Lock"),
244  "slock", 1, true, 0, 1, 0),
245  m_signalStrength(QCoreApplication::translate("(Common)", "Signal Power"),
246  "signal", 0, true, 0, 100, 0),
247  m_scriptStatus (QCoreApplication::translate("(Common)", "Script Status"),
248  "script", 3, true, 0, 3, 0)
249 {
251  {
253  }
254 }
255 
260 {
262  wait();
263 }
264 
265 void SignalMonitor::AddFlags(uint64_t _flags)
266 {
267  DBG_SM("AddFlags", sm_flags_to_string(_flags));
268  m_flags |= _flags;
269 }
270 
271 void SignalMonitor::RemoveFlags(uint64_t _flags)
272 {
273  DBG_SM("RemoveFlags", sm_flags_to_string(_flags));
274  m_flags &= ~_flags;
275 }
276 
277 bool SignalMonitor::HasFlags(uint64_t _flags) const
278 {
279  return (m_flags & _flags) == _flags;
280 }
281 
282 bool SignalMonitor::HasAnyFlag(uint64_t _flags) const
283 {
284  return (m_flags & _flags) != 0U;
285 }
286 
291 {
292  DBG_SM("Start", "begin");
293  {
294  QMutexLocker locker(&m_startStopLock);
295  m_exit = false;
296  start();
297  while (!m_running)
298  m_startStopWait.wait(locker.mutex());
299  }
300  DBG_SM("Start", "end");
301 }
302 
307 {
308  DBG_SM("Stop", "begin");
309 
310  QMutexLocker locker(&m_startStopLock);
311  m_exit = true;
312  if (m_running)
313  {
314  locker.unlock();
315  wait();
316  }
317 
318  DBG_SM("Stop", "end");
319 }
320 
330 QStringList SignalMonitor::GetStatusList(void) const
331 {
332  QStringList list;
333  m_statusLock.lock();
338  m_statusLock.unlock();
339 
340  return list;
341 }
342 
345 {
346  RunProlog();
347 
348  QMutexLocker locker(&m_startStopLock);
349  m_running = true;
350  m_startStopWait.wakeAll();
351 
352  while (!m_exit)
353  {
354  locker.unlock();
355 
356  UpdateValues();
357 
358  if (m_notifyFrontend && m_inputid>=0)
359  {
360  QStringList slist = GetStatusList();
361  MythEvent me(QString("SIGNAL %1").arg(m_inputid), slist);
362  gCoreContext->dispatch(me);
363  }
364 
365  locker.relock();
366  m_startStopWait.wait(locker.mutex(), m_updateRate);
367  }
368 
369  // We need to send a last informational message because a
370  // signal update may have come in while we were sleeping
371  // if we are using the multithreaded dtvsignalmonitor.
372  locker.unlock();
373  if (m_notifyFrontend && m_inputid>=0)
374  {
375  QStringList slist = GetStatusList();
376  MythEvent me(QString("SIGNAL %1").arg(m_inputid), slist);
377  gCoreContext->dispatch(me);
378  }
379  locker.relock();
380 
381  m_running = false;
382  m_startStopWait.wakeAll();
383 
384  RunEpilog();
385 }
386 
388 {
389  QMutexLocker locker(&m_listenerLock);
390  for (auto & entry : m_listeners)
391  {
392  if (entry == listener)
393  return;
394  }
395  m_listeners.push_back(listener);
396 }
397 
399 {
400  QMutexLocker locker(&m_listenerLock);
401 
402  std::vector<SignalMonitorListener*> new_listeners;
403  for (auto & entry : m_listeners)
404  {
405  if (entry != listener)
406  new_listeners.push_back(entry);
407  }
408 
409  m_listeners = new_listeners;
410 }
411 
414 {
415  m_statusLock.lock();
416  const SignalMonitorValue& val = value;
417  m_statusLock.unlock();
418 
419  QMutexLocker locker(&m_listenerLock);
420  for (auto *listener : m_listeners)
421  {
422  auto *dvblistener = dynamic_cast<DVBSignalMonitorListener*>(listener);
423 
424  switch (type)
425  {
426  case kStatusSignalLock:
427  listener->StatusSignalLock(val);
428  break;
429  case kAllGood:
430  listener->AllGood();
431  break;
433  listener->StatusSignalStrength(val);
434  break;
435  case kStatusChannelTuned:
436  listener->StatusChannelTuned(val);
437  break;
439  if (dvblistener)
440  dvblistener->StatusSignalToNoise(val);
441  break;
442  case kStatusBitErrorRate:
443  if (dvblistener)
444  dvblistener->StatusBitErrorRate(val);
445  break;
447  if (dvblistener)
448  dvblistener->StatusUncorrectedBlocks(val);
449  break;
451  if (dvblistener)
452  dvblistener->StatusRotorPosition(val);
453  break;
454  }
455  }
456 }
457 
459 {
460  QMutexLocker locker(&m_statusLock);
461  if (m_scriptStatus.GetValue() < 2)
462  {
464  }
465 }
466 
468 {
469  QMutexLocker locker(&m_listenerLock);
470  for (auto & entry : m_listeners)
471  entry->AllGood();
472 }
473 
475 {
480 }
SatIPSignalMonitor
Definition: satipsignalmonitor.h:12
hdhrsignalmonitor.h
channel
QDomElement channel
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:501
SignalMonitor::m_flags
volatile uint64_t m_flags
Definition: signalmonitor.h:205
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:288
analogsignalmonitor.h
SignalMonitorValue::SetValue
void SetValue(int _value)
Definition: signalmonitorvalue.h:74
kStatusSignalStrength
@ kStatusSignalStrength
Definition: signalmonitorlistener.h:14
SignalMonitorValue::GetStatus
QString GetStatus() const
Returns a signal monitor value as one long string.
Definition: signalmonitorvalue.h:32
FirewireSignalMonitor
Definition: firewiresignalmonitor.h:34
SignalMonitor::m_updateRate
int m_updateRate
Definition: signalmonitor.h:207
SignalMonitor::m_channel
ChannelBase * m_channel
Definition: signalmonitor.h:202
firewirechannel.h
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:17
DVBSignalMonitor
Definition: dvbsignalmonitor.h:18
SignalMonitor::SendMessage
void SendMessage(SignalMonitorMessageType type, const SignalMonitorValue &val)
Definition: signalmonitor.cpp:412
SignalMonitor::m_exit
volatile bool m_exit
Definition: signalmonitor.h:226
arg
arg(title).arg(filename).arg(doDelete))
signalmonitor.h
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MThread::RunProlog
void RunProlog(void)
Sets up a thread, call this if you reimplement run().
Definition: mthread.cpp:198
iptvsignalmonitor.h
CetonChannel
Definition: cetonchannel.h:23
SignalMonitor::m_running
volatile bool m_running
Definition: signalmonitor.h:225
ExternalSignalMonitor.h
SignalMonitorValue::GetName
QString GetName(void) const
Returns the long name of this value.
Definition: signalmonitorvalue.cpp:81
satipchannel.h
SignalMonitorListener
Definition: signalmonitorlistener.h:22
SignalMonitor::HasAnyFlag
bool HasAnyFlag(uint64_t _flags) const
Definition: signalmonitor.cpp:282
SignalMonitor::AddFlags
virtual void AddFlags(uint64_t _flags)
Definition: signalmonitor.cpp:265
dvbchannel.h
true
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
SignalMonitor::kSigMon_WaitForSig
static const uint64_t kSigMon_WaitForSig
Definition: signalmonitor.h:186
HDHRChannel
Definition: hdhrchannel.h:21
SignalMonitor::m_startStopLock
QMutex m_startStopLock
Definition: signalmonitor.h:223
SignalMonitor::m_scriptStatus
SignalMonitorValue m_scriptStatus
Definition: signalmonitor.h:219
scriptsignalmonitor.h
SatIPChannel
Definition: satipchannel.h:13
v4l2encsignalmonitor.h
mythdate.h
SignalMonitorValue::GetValue
int GetValue() const
Returns the value.
Definition: signalmonitorvalue.h:40
ScriptSignalMonitor
Definition: scriptsignalmonitor.h:10
cetonchannel.h
SignalMonitor::RemoveFlags
virtual void RemoveFlags(uint64_t _flags)
Definition: signalmonitor.cpp:271
dvbsignalmonitor.h
kStatusSignalLock
@ kStatusSignalLock
Definition: signalmonitorlistener.h:13
SignalMonitor::m_signalStrength
SignalMonitorValue m_signalStrength
Definition: signalmonitor.h:218
mythlogging.h
SignalMonitor::m_inputid
int m_inputid
Definition: signalmonitor.h:204
ChannelBase
Abstract class providing a generic interface to tuning hardware.
Definition: channelbase.h:32
cetonsignalmonitor.h
SignalMonitor::m_notifyFrontend
bool m_notifyFrontend
Definition: signalmonitor.h:210
AnalogSignalMonitor
Definition: analogsignalmonitor.h:13
sm_flags_to_string
QString sm_flags_to_string(uint64_t flags)
Definition: signalmonitor.h:232
V4L2encSignalMonitor
Definition: v4l2encsignalmonitor.h:17
SignalMonitor::m_signalLock
SignalMonitorValue m_signalLock
Definition: signalmonitor.h:217
SignalMonitor::run
void run(void) override
Basic signal monitoring loop.
Definition: signalmonitor.cpp:344
SignalMonitor::SendMessageAllGood
void SendMessageAllGood(void)
Definition: signalmonitor.cpp:467
FirewireChannel
FirewireChannel Copyright (c) 2005 by Jim Westfall and Dave Abrahams Distributed as part of MythTV un...
Definition: firewirechannel.h:15
compat.h
kStatusBitErrorRate
@ kStatusBitErrorRate
Definition: signalmonitorlistener.h:16
v4lchannel.h
SignalMonitor::~SignalMonitor
~SignalMonitor() override
Stops monitoring thread.
Definition: signalmonitor.cpp:259
SignalMonitor::EmitStatus
virtual void EmitStatus(void)
Definition: signalmonitor.cpp:474
SignalMonitor::UpdateValues
virtual void UpdateValues(void)
This should be overridden to actually do signal monitoring.
Definition: signalmonitor.cpp:458
ChannelBase::IsExternalChannelChangeInUse
virtual bool IsExternalChannelChangeInUse(void)
Definition: channelbase.cpp:841
satipsignalmonitor.h
IPTVChannel
Definition: iptvchannel.h:25
MThread::RunEpilog
void RunEpilog(void)
Cleans up a thread's resources, call this if you reimplement run().
Definition: mthread.cpp:211
SignalMonitorValue
Definition: signalmonitorvalue.h:14
kStatusRotorPosition
@ kStatusRotorPosition
Definition: signalmonitorlistener.h:18
HDHRSignalMonitor
Definition: hdhrsignalmonitor.h:14
asisignalmonitor.h
CardUtil::IsDVBInputType
static bool IsDVBInputType(const QString &inputType)
Returns true iff the input_type is one of the DVB types.
Definition: cardutil.cpp:982
ExternalChannel
-*- Mode: c++ -*-
Definition: ExternalChannel.h:18
SignalMonitor::m_startStopWait
QWaitCondition m_startStopWait
Definition: signalmonitor.h:224
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
ExternalSignalMonitor
Definition: ExternalSignalMonitor.h:16
ASISignalMonitor
Definition: asisignalmonitor.h:14
SignalMonitor
Signal monitoring base class.
Definition: signalmonitor.h:32
asichannel.h
kStatusSignalToNoise
@ kStatusSignalToNoise
Definition: signalmonitorlistener.h:15
SignalMonitor::Init
static SignalMonitor * Init(const QString &cardtype, int db_cardnum, ChannelBase *channel, bool release_stream)
Definition: signalmonitor.cpp:90
kAllGood
@ kAllGood
Definition: signalmonitorlistener.h:11
iptvchannel.h
CetonSignalMonitor
Definition: cetonsignalmonitor.h:19
ChannelBase::GetScriptStatus
uint GetScriptStatus(bool holding_lock=false)
Definition: channelbase.cpp:428
DVBChannel
Provides interface to the tuning hardware when using DVB drivers.
Definition: dvbchannel.h:30
SignalMonitor::HasFlags
bool HasFlags(uint64_t _flags) const
Definition: signalmonitor.cpp:277
ASIChannel
-*- Mode: c++ -*-
Definition: asichannel.h:15
SignalMonitor::AddListener
void AddListener(SignalMonitorListener *listener)
Definition: signalmonitor.cpp:387
SignalMonitor::RemoveListener
void RemoveListener(SignalMonitorListener *listener)
Definition: signalmonitor.cpp:398
SignalMonitorMessageType
SignalMonitorMessageType
Definition: signalmonitorlistener.h:10
ExternalChannel.h
SignalMonitor::m_statusLock
QMutex m_statusLock
Definition: signalmonitor.h:228
DVBSignalMonitorListener
Definition: signalmonitorlistener.h:58
kStatusUncorrectedBlocks
@ kStatusUncorrectedBlocks
Definition: signalmonitorlistener.h:17
mythcontext.h
MThread
This is a wrapper around QThread that does several additional things.
Definition: mthread.h:49
tv_rec.h
SignalMonitor::Start
virtual void Start()
Start signal monitoring thread.
Definition: signalmonitor.cpp:290
firewiresignalmonitor.h
SignalMonitor::m_listeners
std::vector< SignalMonitorListener * > m_listeners
Definition: signalmonitor.h:221
SignalMonitor::GetStatusList
virtual QStringList GetStatusList(void) const
Returns QStringList containing all signals and their current values.
Definition: signalmonitor.cpp:330
SignalMonitor::m_listenerLock
QMutex m_listenerLock
Definition: signalmonitor.h:229
DBG_SM
#define DBG_SM(FUNC, MSG)
Definition: signalmonitor.cpp:69
MThread::wait
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:305
SignalMonitor::Stop
virtual void Stop()
Stop signal monitoring thread.
Definition: signalmonitor.cpp:306
kStatusChannelTuned
@ kStatusChannelTuned
Definition: signalmonitorlistener.h:12
hdhrchannel.h
IPTVSignalMonitor
Definition: iptvsignalmonitor.h:12
V4LChannel
Implements tuning for TV cards using the V4L driver API, both versions 1 and 2.
Definition: v4lchannel.h:31
MythCoreContext::dispatch
void dispatch(const MythEvent &event)
Definition: mythcorecontext.cpp:1734
SignalMonitor::SignalMonitor
SignalMonitor(int, ChannelBase *, uint64_t, bool)=delete