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([[maybe_unused]] const QString& cardtype,
92  [[maybe_unused]] int db_cardnum,
93  [[maybe_unused]] ChannelBase *channel,
94  bool release_stream)
95 {
96  SignalMonitor *signalMonitor = nullptr;
97 
98  if (cardtype == "GuaranteedToFail")
99  {
100  // This lets all the conditionally compiled tests be set up as
101  // 'else if' statements
102  }
103 #ifdef USING_DVB
104  else if (CardUtil::IsDVBInputType(cardtype))
105  {
106  auto *dvbc = dynamic_cast<DVBChannel*>(channel);
107  if (dvbc)
108  signalMonitor = new DVBSignalMonitor(db_cardnum, dvbc,
109  release_stream);
110  }
111 #endif
112 
113 #ifdef USING_V4L2
114  else if ((cardtype.toUpper() == "HDPVR"))
115  {
116  auto *chan = dynamic_cast<V4LChannel*>(channel);
117  if (chan)
118  signalMonitor = new AnalogSignalMonitor(db_cardnum, chan,
119  release_stream);
120  }
121  else if (cardtype.toUpper() == "V4L2ENC")
122  {
123  auto *chan = dynamic_cast<V4LChannel*>(channel);
124  if (chan)
125  signalMonitor = new V4L2encSignalMonitor(db_cardnum, chan,
126  release_stream);
127  }
128 #endif
129 
130 #ifdef USING_HDHOMERUN
131  else if (cardtype.toUpper() == "HDHOMERUN")
132  {
133  auto *hdhrc = dynamic_cast<HDHRChannel*>(channel);
134  if (hdhrc)
135  signalMonitor = new HDHRSignalMonitor(db_cardnum, hdhrc,
136  release_stream);
137  }
138 #endif
139 
140 #ifdef USING_SATIP
141  else if (cardtype.toUpper() == "SATIP")
142  {
143  auto *satipchan = dynamic_cast<SatIPChannel*>(channel);
144  if (satipchan)
145  signalMonitor = new SatIPSignalMonitor(db_cardnum, satipchan, release_stream);
146  }
147 #endif
148 
149 #ifdef USING_CETON
150  else if (cardtype.toUpper() == "CETON")
151  {
152  auto *cetonchan = dynamic_cast<CetonChannel*>(channel);
153  if (cetonchan)
154  signalMonitor = new CetonSignalMonitor(db_cardnum, cetonchan,
155  release_stream);
156  }
157 #endif
158 
159 #ifdef USING_IPTV
160  else if (cardtype.toUpper() == "FREEBOX")
161  {
162  auto *fbc = dynamic_cast<IPTVChannel*>(channel);
163  if (fbc)
164  signalMonitor = new IPTVSignalMonitor(db_cardnum, fbc,
165  release_stream);
166  }
167 #endif
168 
169 #ifdef USING_VBOX
170  else if (cardtype.toUpper() == "VBOX")
171  {
172  auto *fbc = dynamic_cast<IPTVChannel*>(channel);
173  if (fbc)
174  signalMonitor = new IPTVSignalMonitor(db_cardnum, fbc,
175  release_stream);
176  }
177 #endif
178 
179 #ifdef USING_FIREWIRE
180  else if (cardtype.toUpper() == "FIREWIRE")
181  {
182  auto *fc = dynamic_cast<FirewireChannel*>(channel);
183  if (fc)
184  signalMonitor = new FirewireSignalMonitor(db_cardnum, fc,
185  release_stream);
186  }
187 #endif
188 
189 #ifdef USING_ASI
190  else if (cardtype.toUpper() == "ASI")
191  {
192  auto *fc = dynamic_cast<ASIChannel*>(channel);
193  if (fc)
194  signalMonitor = new ASISignalMonitor(db_cardnum, fc,
195  release_stream);
196  }
197 #endif
198 
199  else if (cardtype.toUpper() == "EXTERNAL")
200  {
201  auto *fc = dynamic_cast<ExternalChannel*>(channel);
202  if (fc)
203  signalMonitor = new ExternalSignalMonitor(db_cardnum, fc,
204  release_stream);
205  }
206 
207  if (!signalMonitor && channel)
208  {
209  signalMonitor = new ScriptSignalMonitor(db_cardnum, channel,
210  release_stream);
211  }
212 
213  if (!signalMonitor)
214  {
215  LOG(VB_GENERAL, LOG_ERR,
216  QString("Failed to create signal monitor in Init(%1, %2, 0x%3)")
217  .arg(cardtype).arg(db_cardnum).arg((uintptr_t)channel,0,16));
218  }
219 
220  return signalMonitor;
221 }
222 
236  bool _release_stream, uint64_t wait_for_mask)
237  : MThread("SignalMonitor"),
238  m_channel(_channel),
239  m_inputid(_inputid), m_flags(wait_for_mask),
240  m_releaseStream(_release_stream),
241  m_signalLock (QCoreApplication::translate("(Common)", "Signal Lock"),
242  "slock", 1, true, 0, 1, 0ms),
243  m_signalStrength(QCoreApplication::translate("(Common)", "Signal Power"),
244  "signal", 0, true, 0, 100, 0ms),
245  m_scriptStatus (QCoreApplication::translate("(Common)", "Script Status"),
246  "script", 3, true, 0, 3, 0ms)
247 {
249  {
251  }
252 }
253 
258 {
260  wait();
261 }
262 
263 void SignalMonitor::AddFlags(uint64_t _flags)
264 {
265  DBG_SM("AddFlags", sm_flags_to_string(_flags));
266  m_flags |= _flags;
267 }
268 
269 void SignalMonitor::RemoveFlags(uint64_t _flags)
270 {
271  DBG_SM("RemoveFlags", sm_flags_to_string(_flags));
272  m_flags &= ~_flags;
273 }
274 
275 bool SignalMonitor::HasFlags(uint64_t _flags) const
276 {
277  return (m_flags & _flags) == _flags;
278 }
279 
280 bool SignalMonitor::HasAnyFlag(uint64_t _flags) const
281 {
282  return (m_flags & _flags) != 0U;
283 }
284 
289 {
290  DBG_SM("Start", "begin");
291  {
292  QMutexLocker locker(&m_startStopLock);
293  m_exit = false;
294  start();
295  while (!m_running)
296  m_startStopWait.wait(locker.mutex());
297  }
298  DBG_SM("Start", "end");
299 }
300 
305 {
306  DBG_SM("Stop", "begin");
307 
308  QMutexLocker locker(&m_startStopLock);
309  m_exit = true;
310  if (m_running)
311  {
312  locker.unlock();
313  wait();
314  }
315 
316  DBG_SM("Stop", "end");
317 }
318 
328 QStringList SignalMonitor::GetStatusList(void) const
329 {
330  QStringList list;
331  m_statusLock.lock();
336  m_statusLock.unlock();
337 
338  return list;
339 }
340 
343 {
344  RunProlog();
345 
346  QMutexLocker locker(&m_startStopLock);
347  m_running = true;
348  m_startStopWait.wakeAll();
349 
350  while (!m_exit)
351  {
352  locker.unlock();
353 
354  UpdateValues();
355 
356  if (m_notifyFrontend && m_inputid>=0)
357  {
358  QStringList slist = GetStatusList();
359  MythEvent me(QString("SIGNAL %1").arg(m_inputid), slist);
360  gCoreContext->dispatch(me);
361  }
362 
363  locker.relock();
364  m_startStopWait.wait(locker.mutex(), m_updateRate.count());
365  }
366 
367  // We need to send a last informational message because a
368  // signal update may have come in while we were sleeping
369  // if we are using the multithreaded dtvsignalmonitor.
370  locker.unlock();
371  if (m_notifyFrontend && m_inputid>=0)
372  {
373  QStringList slist = GetStatusList();
374  MythEvent me(QString("SIGNAL %1").arg(m_inputid), slist);
375  gCoreContext->dispatch(me);
376  }
377  locker.relock();
378 
379  m_running = false;
380  m_startStopWait.wakeAll();
381 
382  RunEpilog();
383 }
384 
386 {
387  QMutexLocker locker(&m_listenerLock);
388  for (auto & entry : m_listeners)
389  {
390  if (entry == listener)
391  return;
392  }
393  m_listeners.push_back(listener);
394 }
395 
397 {
398  QMutexLocker locker(&m_listenerLock);
399 
400  std::vector<SignalMonitorListener*> new_listeners;
401  for (auto & entry : m_listeners)
402  {
403  if (entry != listener)
404  new_listeners.push_back(entry);
405  }
406 
407  m_listeners = new_listeners;
408 }
409 
412 {
413  m_statusLock.lock();
414  const SignalMonitorValue& val = value;
415  m_statusLock.unlock();
416 
417  QMutexLocker locker(&m_listenerLock);
418  for (auto *listener : m_listeners)
419  {
420  auto *dvblistener = dynamic_cast<DVBSignalMonitorListener*>(listener);
421 
422  switch (type)
423  {
424  case kStatusSignalLock:
425  listener->StatusSignalLock(val);
426  break;
427  case kAllGood:
428  listener->AllGood();
429  break;
431  listener->StatusSignalStrength(val);
432  break;
433  case kStatusChannelTuned:
434  listener->StatusChannelTuned(val);
435  break;
437  if (dvblistener)
438  dvblistener->StatusSignalToNoise(val);
439  break;
440  case kStatusBitErrorRate:
441  if (dvblistener)
442  dvblistener->StatusBitErrorRate(val);
443  break;
445  if (dvblistener)
446  dvblistener->StatusUncorrectedBlocks(val);
447  break;
449  if (dvblistener)
450  dvblistener->StatusRotorPosition(val);
451  break;
452  }
453  }
454 }
455 
457 {
458  QMutexLocker locker(&m_statusLock);
459  if (m_scriptStatus.GetValue() < 2)
460  {
462  }
463 }
464 
466 {
467  QMutexLocker locker(&m_listenerLock);
468  for (auto & entry : m_listeners)
469  entry->AllGood();
470 }
471 
473 {
478 }
SatIPSignalMonitor
Definition: satipsignalmonitor.h:11
hdhrsignalmonitor.h
SignalMonitor::m_flags
volatile uint64_t m_flags
Definition: signalmonitor.h:204
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:201
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:410
SignalMonitor::m_exit
volatile bool m_exit
Definition: signalmonitor.h:225
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:224
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:280
SignalMonitor::AddFlags
virtual void AddFlags(uint64_t _flags)
Definition: signalmonitor.cpp:263
dvbchannel.h
true
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:95
SignalMonitor::kSigMon_WaitForSig
static const uint64_t kSigMon_WaitForSig
Definition: signalmonitor.h:185
HDHRChannel
Definition: hdhrchannel.h:20
SignalMonitor::m_startStopLock
QMutex m_startStopLock
Definition: signalmonitor.h:222
SignalMonitor::m_statusLock
QRecursiveMutex m_statusLock
Definition: signalmonitor.h:227
SignalMonitor::m_scriptStatus
SignalMonitorValue m_scriptStatus
Definition: signalmonitor.h:218
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:269
dvbsignalmonitor.h
kStatusSignalLock
@ kStatusSignalLock
Definition: signalmonitorlistener.h:13
SignalMonitor::m_signalStrength
SignalMonitorValue m_signalStrength
Definition: signalmonitor.h:217
mythlogging.h
SignalMonitor::m_inputid
int m_inputid
Definition: signalmonitor.h:203
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:209
AnalogSignalMonitor
Definition: analogsignalmonitor.h:12
sm_flags_to_string
QString sm_flags_to_string(uint64_t flags)
Definition: signalmonitor.h:231
V4L2encSignalMonitor
Definition: v4l2encsignalmonitor.h:16
SignalMonitor::m_signalLock
SignalMonitorValue m_signalLock
Definition: signalmonitor.h:216
SignalMonitor::m_updateRate
std::chrono::milliseconds m_updateRate
Definition: signalmonitor.h:206
SignalMonitor::run
void run(void) override
Basic signal monitoring loop.
Definition: signalmonitor.cpp:342
SignalMonitor::SendMessageAllGood
void SendMessageAllGood(void)
Definition: signalmonitor.cpp:465
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:257
SignalMonitor::EmitStatus
virtual void EmitStatus(void)
Definition: signalmonitor.cpp:472
SignalMonitor::UpdateValues
virtual void UpdateValues(void)
This should be overridden to actually do signal monitoring.
Definition: signalmonitor.cpp:456
ChannelBase::IsExternalChannelChangeInUse
virtual bool IsExternalChannelChangeInUse(void)
Definition: channelbase.cpp:836
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:1028
ExternalChannel
-*- Mode: c++ -*-
Definition: ExternalChannel.h:20
SignalMonitor::m_startStopWait
QWaitCondition m_startStopWait
Definition: signalmonitor.h:223
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
ExternalSignalMonitor
Definition: ExternalSignalMonitor.h:19
ASISignalMonitor
Definition: asisignalmonitor.h:13
SignalMonitor
Signal monitoring base class.
Definition: signalmonitor.h:30
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:429
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:275
ASIChannel
-*- Mode: c++ -*-
Definition: asichannel.h:14
SignalMonitor::AddListener
void AddListener(SignalMonitorListener *listener)
Definition: signalmonitor.cpp:385
SignalMonitor::RemoveListener
void RemoveListener(SignalMonitorListener *listener)
Definition: signalmonitor.cpp:396
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:288
firewiresignalmonitor.h
SignalMonitor::m_listeners
std::vector< SignalMonitorListener * > m_listeners
Definition: signalmonitor.h:220
SignalMonitor::GetStatusList
virtual QStringList GetStatusList(void) const
Returns QStringList containing all signals and their current values.
Definition: signalmonitor.cpp:328
SignalMonitor::m_listenerLock
QMutex m_listenerLock
Definition: signalmonitor.h:228
DBG_SM
#define DBG_SM(FUNC, MSG)
Definition: signalmonitor.cpp:70
SignalMonitor::Stop
virtual void Stop()
Stop signal monitoring thread.
Definition: signalmonitor.cpp:304
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:1719
SignalMonitor::SignalMonitor
SignalMonitor(int, ChannelBase *, uint64_t, bool)=delete