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_IPTV
41 # include "iptvsignalmonitor.h"
42 # include "iptvchannel.h"
43 #endif
44 
45 #ifdef USING_FIREWIRE
46 # include "firewiresignalmonitor.h"
47 # include "firewirechannel.h"
48 #endif
49 
50 #ifdef USING_ASI
51 # include "asisignalmonitor.h"
52 # include "asichannel.h"
53 #endif
54 
55 #ifdef USING_CETON
56 # include "cetonsignalmonitor.h"
57 # include "cetonchannel.h"
58 #endif
59 
60 #include "ExternalSignalMonitor.h"
61 #include "ExternalChannel.h"
62 
63 #undef DBG_SM
64 #define DBG_SM(FUNC, MSG) LOG(VB_CHANNEL, LOG_DEBUG, \
65  QString("SigMon[%1](%2)::%3: %4").arg(m_inputid) \
66  .arg(m_channel->GetDevice()).arg(FUNC).arg(MSG))
67 
85 SignalMonitor *SignalMonitor::Init(const QString& cardtype, int db_cardnum,
87  bool release_stream)
88 {
89  (void) cardtype;
90  (void) db_cardnum;
91  (void) channel;
92 
93  SignalMonitor *signalMonitor = nullptr;
94 
95  if (cardtype == "GuaranteedToFail")
96  {
97  // This lets all the conditionally compiled tests be set up as
98  // 'else if' statements
99  }
100 #ifdef USING_DVB
101  else if (CardUtil::IsDVBInputType(cardtype))
102  {
103  auto *dvbc = dynamic_cast<DVBChannel*>(channel);
104  if (dvbc)
105  signalMonitor = new DVBSignalMonitor(db_cardnum, dvbc,
106  release_stream);
107  }
108 #endif
109 
110 #ifdef USING_V4L2
111  else if ((cardtype.toUpper() == "HDPVR"))
112  {
113  auto *chan = dynamic_cast<V4LChannel*>(channel);
114  if (chan)
115  signalMonitor = new AnalogSignalMonitor(db_cardnum, chan,
116  release_stream);
117  }
118  else if (cardtype.toUpper() == "V4L2ENC")
119  {
120  auto *chan = dynamic_cast<V4LChannel*>(channel);
121  if (chan)
122  signalMonitor = new V4L2encSignalMonitor(db_cardnum, chan,
123  release_stream);
124  }
125 #endif
126 
127 #ifdef USING_HDHOMERUN
128  else if (cardtype.toUpper() == "HDHOMERUN")
129  {
130  auto *hdhrc = dynamic_cast<HDHRChannel*>(channel);
131  if (hdhrc)
132  signalMonitor = new HDHRSignalMonitor(db_cardnum, hdhrc,
133  release_stream);
134  }
135 #endif
136 
137 #ifdef USING_CETON
138  else if (cardtype.toUpper() == "CETON")
139  {
140  auto *cetonchan = dynamic_cast<CetonChannel*>(channel);
141  if (cetonchan)
142  signalMonitor = new CetonSignalMonitor(db_cardnum, cetonchan,
143  release_stream);
144  }
145 #endif
146 
147 #ifdef USING_IPTV
148  else if (cardtype.toUpper() == "FREEBOX")
149  {
150  auto *fbc = dynamic_cast<IPTVChannel*>(channel);
151  if (fbc)
152  signalMonitor = new IPTVSignalMonitor(db_cardnum, fbc,
153  release_stream);
154  }
155 #endif
156 
157 #ifdef USING_VBOX
158  else if (cardtype.toUpper() == "VBOX")
159  {
160  auto *fbc = dynamic_cast<IPTVChannel*>(channel);
161  if (fbc)
162  signalMonitor = new IPTVSignalMonitor(db_cardnum, fbc,
163  release_stream);
164  }
165 #endif
166 
167 #ifdef USING_FIREWIRE
168  else if (cardtype.toUpper() == "FIREWIRE")
169  {
170  auto *fc = dynamic_cast<FirewireChannel*>(channel);
171  if (fc)
172  signalMonitor = new FirewireSignalMonitor(db_cardnum, fc,
173  release_stream);
174  }
175 #endif
176 
177 #ifdef USING_ASI
178  else if (cardtype.toUpper() == "ASI")
179  {
180  auto *fc = dynamic_cast<ASIChannel*>(channel);
181  if (fc)
182  signalMonitor = new ASISignalMonitor(db_cardnum, fc,
183  release_stream);
184  }
185 #endif
186 
187  else if (cardtype.toUpper() == "EXTERNAL")
188  {
189  auto *fc = dynamic_cast<ExternalChannel*>(channel);
190  if (fc)
191  signalMonitor = new ExternalSignalMonitor(db_cardnum, fc,
192  release_stream);
193  }
194 
195  if (!signalMonitor && channel)
196  {
197  signalMonitor = new ScriptSignalMonitor(db_cardnum, channel,
198  release_stream);
199  }
200 
201  if (!signalMonitor)
202  {
203  LOG(VB_GENERAL, LOG_ERR,
204  QString("Failed to create signal monitor in Init(%1, %2, 0x%3)")
205  .arg(cardtype).arg(db_cardnum).arg((long)channel,0,16));
206  }
207 
208  return signalMonitor;
209 }
210 
224  bool _release_stream, uint64_t wait_for_mask)
225  : MThread("SignalMonitor"),
226  m_channel(_channel),
227  m_inputid(_inputid), m_flags(wait_for_mask),
228  m_release_stream(_release_stream),
229  m_signalLock (QCoreApplication::translate("(Common)", "Signal Lock"),
230  "slock", 1, true, 0, 1, 0),
231  m_signalStrength(QCoreApplication::translate("(Common)", "Signal Power"),
232  "signal", 0, true, 0, 100, 0),
233  m_scriptStatus (QCoreApplication::translate("(Common)", "Script Status"),
234  "script", 3, true, 0, 3, 0)
235 {
237  {
239  }
240 }
241 
246 {
248  wait();
249 }
250 
251 void SignalMonitor::AddFlags(uint64_t _flags)
252 {
253  DBG_SM("AddFlags", sm_flags_to_string(_flags));
254  m_flags |= _flags;
255 }
256 
257 void SignalMonitor::RemoveFlags(uint64_t _flags)
258 {
259  DBG_SM("RemoveFlags", sm_flags_to_string(_flags));
260  m_flags &= ~_flags;
261 }
262 
263 bool SignalMonitor::HasFlags(uint64_t _flags) const
264 {
265  return (m_flags & _flags) == _flags;
266 }
267 
268 bool SignalMonitor::HasAnyFlag(uint64_t _flags) const
269 {
270  return (m_flags & _flags) != 0U;
271 }
272 
277 {
278  DBG_SM("Start", "begin");
279  {
280  QMutexLocker locker(&m_startStopLock);
281  m_exit = false;
282  start();
283  while (!m_running)
284  m_startStopWait.wait(locker.mutex());
285  }
286  DBG_SM("Start", "end");
287 }
288 
293 {
294  DBG_SM("Stop", "begin");
295 
296  QMutexLocker locker(&m_startStopLock);
297  m_exit = true;
298  if (m_running)
299  {
300  locker.unlock();
301  wait();
302  }
303 
304  DBG_SM("Stop", "end");
305 }
306 
316 QStringList SignalMonitor::GetStatusList(void) const
317 {
318  QStringList list;
319  m_statusLock.lock();
324  m_statusLock.unlock();
325 
326  return list;
327 }
328 
331 {
332  RunProlog();
333 
334  QMutexLocker locker(&m_startStopLock);
335  m_running = true;
336  m_startStopWait.wakeAll();
337 
338  while (!m_exit)
339  {
340  locker.unlock();
341 
342  UpdateValues();
343 
344  if (m_notify_frontend && m_inputid>=0)
345  {
346  QStringList slist = GetStatusList();
347  MythEvent me(QString("SIGNAL %1").arg(m_inputid), slist);
348  gCoreContext->dispatch(me);
349  }
350 
351  locker.relock();
352  m_startStopWait.wait(locker.mutex(), m_update_rate);
353  }
354 
355  // We need to send a last informational message because a
356  // signal update may have come in while we were sleeping
357  // if we are using the multithreaded dtvsignalmonitor.
358  locker.unlock();
359  if (m_notify_frontend && m_inputid>=0)
360  {
361  QStringList slist = GetStatusList();
362  MythEvent me(QString("SIGNAL %1").arg(m_inputid), slist);
363  gCoreContext->dispatch(me);
364  }
365  locker.relock();
366 
367  m_running = false;
368  m_startStopWait.wakeAll();
369 
370  RunEpilog();
371 }
372 
374 {
375  QMutexLocker locker(&m_listenerLock);
376  for (auto & entry : m_listeners)
377  {
378  if (entry == listener)
379  return;
380  }
381  m_listeners.push_back(listener);
382 }
383 
385 {
386  QMutexLocker locker(&m_listenerLock);
387 
388  vector<SignalMonitorListener*> new_listeners;
389  for (auto & entry : m_listeners)
390  {
391  if (entry != listener)
392  new_listeners.push_back(entry);
393  }
394 
395  m_listeners = new_listeners;
396 }
397 
400 {
401  m_statusLock.lock();
402  const SignalMonitorValue& val = value;
403  m_statusLock.unlock();
404 
405  QMutexLocker locker(&m_listenerLock);
406  for (auto *listener : m_listeners)
407  {
408  auto *dvblistener = dynamic_cast<DVBSignalMonitorListener*>(listener);
409 
410  switch (type)
411  {
412  case kStatusSignalLock:
413  listener->StatusSignalLock(val);
414  break;
415  case kAllGood:
416  listener->AllGood();
417  break;
419  listener->StatusSignalStrength(val);
420  break;
421  case kStatusChannelTuned:
422  listener->StatusChannelTuned(val);
423  break;
425  if (dvblistener)
426  dvblistener->StatusSignalToNoise(val);
427  break;
428  case kStatusBitErrorRate:
429  if (dvblistener)
430  dvblistener->StatusBitErrorRate(val);
431  break;
433  if (dvblistener)
434  dvblistener->StatusUncorrectedBlocks(val);
435  break;
437  if (dvblistener)
438  dvblistener->StatusRotorPosition(val);
439  break;
440  }
441  }
442 }
443 
445 {
446  QMutexLocker locker(&m_statusLock);
447  if (m_scriptStatus.GetValue() < 2)
448  {
450  }
451 }
452 
454 {
455  QMutexLocker locker(&m_listenerLock);
456  for (auto & entry : m_listeners)
457  entry->AllGood();
458 }
459 
461 {
466 }
hdhrsignalmonitor.h
channel
QDomElement channel
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:498
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:292
analogsignalmonitor.h
SignalMonitorValue::SetValue
void SetValue(int _value)
Definition: signalmonitorvalue.h:75
kStatusSignalStrength
@ kStatusSignalStrength
Definition: signalmonitorlistener.h:14
SignalMonitorValue::GetStatus
QString GetStatus() const
Returns a signal monitor value as one long string.
Definition: signalmonitorvalue.h:33
FirewireSignalMonitor
Definition: firewiresignalmonitor.h:34
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:398
SignalMonitor::m_exit
volatile bool m_exit
Definition: signalmonitor.h:227
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:202
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
SignalMonitorListener
Definition: signalmonitorlistener.h:21
SignalMonitor::HasAnyFlag
bool HasAnyFlag(uint64_t _flags) const
Definition: signalmonitor.cpp:268
SignalMonitor::AddFlags
virtual void AddFlags(uint64_t _flags)
Definition: signalmonitor.cpp:251
dvbchannel.h
true
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:91
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_scriptStatus
SignalMonitorValue m_scriptStatus
Definition: signalmonitor.h:220
scriptsignalmonitor.h
v4l2encsignalmonitor.h
mythdate.h
SignalMonitorValue::GetValue
int GetValue() const
Returns the value.
Definition: signalmonitorvalue.h:41
ScriptSignalMonitor
Definition: scriptsignalmonitor.h:9
cetonchannel.h
SignalMonitor::RemoveFlags
virtual void RemoveFlags(uint64_t _flags)
Definition: signalmonitor.cpp:257
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
AnalogSignalMonitor
Definition: analogsignalmonitor.h:12
sm_flags_to_string
QString sm_flags_to_string(uint64_t flags)
Definition: signalmonitor.h:233
V4L2encSignalMonitor
Definition: v4l2encsignalmonitor.h:16
SignalMonitor::m_signalLock
SignalMonitorValue m_signalLock
Definition: signalmonitor.h:218
SignalMonitor::run
void run(void) override
Basic signal monitoring loop.
Definition: signalmonitor.cpp:330
SignalMonitor::SendMessageAllGood
void SendMessageAllGood(void)
Definition: signalmonitor.cpp:453
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:245
SignalMonitor::EmitStatus
virtual void EmitStatus(void)
Definition: signalmonitor.cpp:460
SignalMonitor::UpdateValues
virtual void UpdateValues(void)
This should be overridden to actually do signal monitoring.
Definition: signalmonitor.cpp:444
ChannelBase::IsExternalChannelChangeInUse
virtual bool IsExternalChannelChangeInUse(void)
Definition: channelbase.cpp:834
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:215
SignalMonitorValue
Definition: signalmonitorvalue.h:14
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:978
ExternalChannel
Definition: ExternalChannel.h:18
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:57
ExternalSignalMonitor
Definition: ExternalSignalMonitor.h:15
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:85
kAllGood
@ kAllGood
Definition: signalmonitorlistener.h:11
iptvchannel.h
CetonSignalMonitor
Definition: cetonsignalmonitor.h:18
ChannelBase::GetScriptStatus
uint GetScriptStatus(bool holding_lock=false)
Definition: channelbase.cpp:427
DVBChannel
Provides interface to the tuning hardware when using DVB drivers.
Definition: dvbchannel.h:29
SignalMonitor::HasFlags
bool HasFlags(uint64_t _flags) const
Definition: signalmonitor.cpp:263
ASIChannel
Definition: asichannel.h:15
SignalMonitor::AddListener
void AddListener(SignalMonitorListener *listener)
Definition: signalmonitor.cpp:373
SignalMonitor::RemoveListener
void RemoveListener(SignalMonitorListener *listener)
Definition: signalmonitor.cpp:384
SignalMonitorMessageType
SignalMonitorMessageType
Definition: signalmonitorlistener.h:10
ExternalChannel.h
SignalMonitor::m_statusLock
QMutex m_statusLock
Definition: signalmonitor.h:229
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:276
firewiresignalmonitor.h
SignalMonitor::GetStatusList
virtual QStringList GetStatusList(void) const
Returns QStringList containing all signals and their current values.
Definition: signalmonitor.cpp:316
SignalMonitor::m_listenerLock
QMutex m_listenerLock
Definition: signalmonitor.h:230
SignalMonitor::m_notify_frontend
bool m_notify_frontend
Definition: signalmonitor.h:211
DBG_SM
#define DBG_SM(FUNC, MSG)
Definition: signalmonitor.cpp:64
MThread::wait
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:309
SignalMonitor::Stop
virtual void Stop()
Stop signal monitoring thread.
Definition: signalmonitor.cpp:292
kStatusChannelTuned
@ kStatusChannelTuned
Definition: signalmonitorlistener.h:12
hdhrchannel.h
SignalMonitor::m_update_rate
int m_update_rate
Definition: signalmonitor.h:208
IPTVSignalMonitor
Definition: iptvsignalmonitor.h:11
V4LChannel
Implements tuning for TV cards using the V4L driver API, both versions 1 and 2.
Definition: v4lchannel.h:36
MythCoreContext::dispatch
void dispatch(const MythEvent &event)
Definition: mythcorecontext.cpp:1733
SignalMonitor::SignalMonitor
SignalMonitor(int, ChannelBase *, uint64_t, bool)=delete
SignalMonitor::m_listeners
vector< SignalMonitorListener * > m_listeners
Definition: signalmonitor.h:222