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