MythTV  master
ExternalSignalMonitor.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 
3 #include <cerrno>
4 #include <cstring>
5 
6 #include <fcntl.h>
7 #include <unistd.h>
8 #if !defined(USING_MINGW) && !defined(_WIN32)
9 #include <sys/select.h>
10 #endif
11 
12 #include "mythlogging.h"
13 #include "mythdbcon.h"
14 #include "ExternalSignalMonitor.h"
15 #include "atscstreamdata.h"
16 #include "mpegtables.h"
17 #include "atsctables.h"
18 
19 #include "ExternalChannel.h"
20 #include "ExternalRecorder.h"
21 #include "ExternalStreamHandler.h"
22 
23 #define LOC QString("ExternSigMon[%1](%2): ") \
24  .arg(m_inputid).arg(static_cast<ExternalChannel *>(m_channel)->GetDescription())
25 
41  ExternalChannel *_channel,
42  bool _release_stream,
43  uint64_t _flags)
44  : DTVSignalMonitor(db_cardnum, _channel, _flags, _release_stream)
45 {
46  QString result;
47 
48  LOG(VB_CHANNEL, LOG_INFO, LOC + "ctor");
53  LOG(VB_GENERAL, LOG_ERR, LOC + "Open failed");
54  else
55  m_lock_timeout = GetLockTimeout() * 1000;
56 }
57 
62 {
63  LOG(VB_CHANNEL, LOG_INFO, LOC + "dtor");
66 }
67 
72 {
73  QString result;
74 
75  LOG(VB_CHANNEL, LOG_INFO, LOC + "Stop() -- begin");
76 
78  if (GetStreamData())
79  {
82  }
84 
85  LOG(VB_CHANNEL, LOG_INFO, LOC + "Stop() -- end");
86 }
87 
95 {
96  if (!m_running || m_exit)
97  return;
98 
99  if (GetExternalChannel()->IsExternalChannelChangeInUse())
100  {
102 
103  QMutexLocker locker(&m_statusLock);
104  if (!m_scriptStatus.IsGood())
105  return;
106  }
107 
109  {
110  if (!m_stream_handler->IsRunning())
111  {
112  m_error = QObject::tr("Error: stream handler died");
113  LOG(VB_CHANNEL, LOG_ERR, LOC + m_error);
114  m_update_done = true;
115  return;
116  }
117 
118  EmitStatus();
119  if (IsAllGood())
121 
122  m_update_done = true;
123  return;
124  }
125 
127 
128  int strength = GetSignalStrengthPercent();
129  bool is_locked = HasLock();
130 
131  // Set SignalMonitorValues
132  {
133  QMutexLocker locker(&m_statusLock);
134  m_signalStrength.SetValue(strength);
135  m_signalLock.SetValue(is_locked);
136  }
137 
138  EmitStatus();
139  if (IsAllGood())
141 
142  // Start table monitoring if we are waiting on any table
143  // and we have a lock.
144  if (is_locked && GetStreamData() &&
148  {
150  {
154  }
155  }
156 
157  m_update_done = true;
158 }
159 
161 {
162  QString result;
163 
164  m_stream_handler->ProcessCommand("HasLock?", result);
165  if (result.startsWith("OK:"))
166  {
167  return result.mid(3, 3) == "Yes";
168  }
169  LOG(VB_CHANNEL, LOG_ERR, LOC + QString
170  ("HasLock: invalid response '%1'").arg(result));
171  if (!result.startsWith("WARN"))
172  m_error = QString("HasLock: invalid response '%1'").arg(result);
173  return false;
174 }
175 
177 {
178  QString result;
179 
180  m_stream_handler->ProcessCommand("SignalStrengthPercent?", result);
181  if (result.startsWith("OK:"))
182  {
183  bool ok;
184  int percent = result.mid(3).toInt(&ok);
185  if (!ok)
186  {
187  LOG(VB_CHANNEL, LOG_ERR, LOC + QString
188  ("GetSignalStrengthPercent: invalid response '%1'")
189  .arg(result));
190  return -1;
191  }
192  return percent;
193  }
194  LOG(VB_CHANNEL, LOG_ERR, LOC + QString
195  ("GetSignalStrengthPercent: invalid response '%1'").arg(result));
196  if (!result.startsWith("WARN"))
197  m_error = QString("GetSignalStrengthPercent: invalid response '%1'")
198  .arg(result);
199  return -1;
200 }
201 
203 {
204  QString result;
205 
206  m_stream_handler->ProcessCommand("LockTimeout?", result, 10000);
207  if (result.startsWith("OK:"))
208  {
209  bool ok;
210  int timeout = result.mid(3).toInt(&ok);
211  if (!ok)
212  {
213  LOG(VB_CHANNEL, LOG_ERR, LOC + QString
214  ("GetLockTimeout: invalid response '%1'")
215  .arg(result));
216  return -1;
217  }
218  return timeout;
219  }
220  LOG(VB_CHANNEL, LOG_ERR, LOC + QString
221  ("GetLockTimeout: invalid response '%1'").arg(result));
222  if (!result.startsWith("WARN"))
223  m_error = QString("GetLockTimeout: invalid response '%1'").arg(result);
224  return -1;
225 }
SignalMonitorValue m_scriptStatus
QMutex m_statusLock
void UpdateValues(void) override
Fills in frontend stats and emits status Qt signals.
static const uint64_t kDTVSigMon_WaitForPMT
static const uint64_t kDTVSigMon_WaitForPAT
bool HasAnyFlag(uint64_t _flags) const
virtual void RemoveListener(MPEGStreamData *data)
bool HasError(void) const
Definition: streamhandler.h:64
static const uint64_t kDTVSigMon_WaitForVCT
static const uint64_t kDTVSigMon_WaitForMGT
void SetValue(int _value)
static const uint64_t kDTVSigMon_WaitForNIT
Overall structure.
virtual void Stop()
Stop signal monitoring thread.
static const uint64_t kSigMon_WaitForSig
virtual void AddListener(MPEGStreamData *data, bool allow_section_reader=false, bool needs_buffering=false, QString output_file=QString())
ChannelBase * m_channel
ExternalChannel * GetExternalChannel(void)
volatile bool m_exit
ExternalStreamHandler * m_stream_handler
void Stop(void) override
Stop signal monitoring and table monitoring threads.
MPEGStreamData * GetStreamData()
Returns the MPEG stream data if it exists.
void SendMessageAllGood(void)
volatile bool m_running
virtual ~ExternalSignalMonitor()
Stops signal monitoring and table monitoring threads.
static ExternalStreamHandler * Get(const QString &devname, int inputid, int majorid)
This class is intended to detect the presence of needed tables.
#define LOC
virtual QString GetDevice(void) const
Returns String representing device, useful for debugging.
Definition: channelbase.h:78
void AddFlags(uint64_t _flags) override
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
bool ProcessCommand(const QString &cmd, QString &result, int timeout=4000, uint retry_cnt=3)
bool IsAllGood(void) const override
SignalMonitorValue m_signalStrength
static const uint64_t kDTVSigMon_WaitForSDT
virtual int GetInputID(void) const
Definition: channelbase.h:67
bool IsGood() const
Returns true if the value is equal to the threshold, or on the right side of the threshold (depends o...
SignalMonitorValue m_signalLock
bool IsRunning(void) const
static void Return(ExternalStreamHandler *&ref, int inputid)
int GetMajorID(void)
virtual void EmitStatus(void)
virtual void UpdateValues(void)
This should be overridden to actually do signal monitoring.