MythTV master
ExternalSignalMonitor.cpp
Go to the documentation of this file.
1// -*- Mode: c++ -*-
2
3#include <cerrno>
4#include <cstring>
5
6#include <QtGlobal>
7#if QT_VERSION >= QT_VERSION_CHECK(6,5,0)
8#include <QtSystemDetection>
9#endif
10
11#include <fcntl.h>
12#include <unistd.h>
13#ifndef Q_OS_WINDOWS
14#include <sys/select.h>
15#endif
16
19
20#include "ExternalChannel.h"
21#include "ExternalRecorder.h"
24#include "mpeg/atscstreamdata.h"
25#include "mpeg/atsctables.h"
26#include "mpeg/mpegtables.h"
27
28#define LOC QString("ExternSigMon[%1](%2): ").arg(m_inputid).arg(m_loc)
29
45 ExternalChannel *_channel,
46 bool _release_stream,
47 uint64_t _flags)
48 : DTVSignalMonitor(db_cardnum, _channel, _release_stream, _flags)
49{
50 LOG(VB_CHANNEL, LOG_INFO, LOC + "ctor");
55 {
56 LOG(VB_GENERAL, LOG_ERR, LOC + "Open failed");
59 }
60 else
61 {
63 }
64
66 if (channel && channel->IsBackgroundTuning())
68}
69
74{
75 LOG(VB_CHANNEL, LOG_INFO, LOC + "dtor");
79}
80
85{
86 LOG(VB_CHANNEL, LOG_INFO, LOC + "Stop() -- begin");
87
89 if (GetStreamData())
90 {
93 }
95
96 LOG(VB_CHANNEL, LOG_INFO, LOC + "Stop() -- end");
97}
98
106{
107 if (!m_running || m_exit)
108 return;
109
111 if (channel == nullptr)
112 return;
113
114 if (channel->IsExternalChannelChangeInUse())
115 {
117
118 QMutexLocker locker(&m_statusLock);
119 if (!m_scriptStatus.IsGood())
120 return;
121 }
122
123 if (channel->IsBackgroundTuning())
124 {
125 QMutexLocker locker(&m_statusLock);
126 if (m_scriptStatus.GetValue() < 2)
128
129 if (!m_scriptStatus.IsGood())
130 return;
131 }
132
134 {
136 {
137 m_error = QObject::tr("Error: stream handler died");
138 LOG(VB_CHANNEL, LOG_ERR, LOC + m_error);
139 m_updateDone = true;
140 return;
141 }
142
143 EmitStatus();
144 if (IsAllGood())
146
147 m_updateDone = true;
148 return;
149 }
150
152
153 int strength = GetSignalStrengthPercent();
154 bool is_locked = HasLock();
155
156 // Set SignalMonitorValues
157 {
158 QMutexLocker locker(&m_statusLock);
159 m_signalStrength.SetValue(strength);
160 m_signalLock.SetValue(static_cast<int>(is_locked));
161 }
162
163 EmitStatus();
164 if (IsAllGood())
166
167 // Start table monitoring if we are waiting on any table
168 // and we have a lock.
169 if (is_locked && GetStreamData() &&
173 {
175 {
179 }
180 }
181
182 m_updateDone = true;
183}
184
186{
187 QString result;
188
189 m_streamHandler->ProcessCommand("HasLock?", result);
190 if (result.startsWith("OK:"))
191 {
192 return result.mid(3, 3) == "Yes";
193 }
194 LOG(VB_CHANNEL, LOG_ERR, LOC + QString
195 ("HasLock: invalid response '%1'").arg(result));
196 if (!result.startsWith("WARN"))
197 m_error = QString("HasLock: invalid response '%1'").arg(result);
198 return false;
199}
200
202{
203 QString result;
204
205 m_streamHandler->ProcessCommand("SignalStrengthPercent?", result);
206 if (result.startsWith("OK:"))
207 {
208 bool ok = false;
209#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
210 int percent = result.midRef(3).toInt(&ok);
211#else
212 int percent = QStringView(result).mid(3).toInt(&ok);
213#endif
214 if (!ok)
215 {
216 LOG(VB_CHANNEL, LOG_ERR, LOC + QString
217 ("GetSignalStrengthPercent: invalid response '%1'")
218 .arg(result));
219 return -1;
220 }
221 return percent;
222 }
223 LOG(VB_CHANNEL, LOG_ERR, LOC + QString
224 ("GetSignalStrengthPercent: invalid response '%1'").arg(result));
225 if (!result.startsWith("WARN"))
226 m_error = QString("GetSignalStrengthPercent: invalid response '%1'")
227 .arg(result);
228 return -1;
229}
230
232{
233 QString result;
234
235 m_streamHandler->ProcessCommand("LockTimeout?", result, 10s);
236 if (result.startsWith("OK:"))
237 {
238 bool ok = false;
239 auto timeout = std::chrono::seconds(result.mid(3).toInt(&ok));
240 if (!ok)
241 {
242 LOG(VB_CHANNEL, LOG_ERR, LOC + QString
243 ("GetLockTimeout: invalid response '%1'")
244 .arg(result));
245 return -1s;
246 }
247 return timeout;
248 }
249 LOG(VB_CHANNEL, LOG_ERR, LOC + QString
250 ("GetLockTimeout: invalid response '%1'").arg(result));
251 if (!result.startsWith("WARN"))
252 m_error = QString("GetLockTimeout: invalid response '%1'").arg(result);
253 return -1s;
254}
#define LOC
Overall structure.
virtual bool IsExternalChannelChangeInUse(void)
virtual int GetInputID(void) const
Definition: channelbase.h:67
int GetMajorID(void)
virtual QString GetDevice(void) const
Returns String representing device, useful for debugging.
Definition: channelbase.h:78
This class is intended to detect the presence of needed tables.
bool IsAllGood(void) const override
void AddFlags(uint64_t _flags) override
MPEGStreamData * GetStreamData()
Returns the MPEG stream data if it exists.
-*- Mode: c++ -*-
bool IsBackgroundTuning(void) const
uint GetTuneStatus(void)
ExternalChannel * GetExternalChannel(void)
void UpdateValues(void) override
Fills in frontend stats and emits status Qt signals.
ExternalStreamHandler * m_streamHandler
std::chrono::seconds GetLockTimeout(void)
void Stop(void) override
Stop signal monitoring and table monitoring threads.
~ExternalSignalMonitor() override
Stops signal monitoring and table monitoring threads.
std::chrono::milliseconds m_lockTimeout
static ExternalStreamHandler * Get(const QString &devname, int inputid, int majorid)
bool StartStreaming(bool recording)
bool ProcessCommand(const QString &cmd, QString &result, std::chrono::milliseconds timeout=4s, uint retry_cnt=3)
static void Return(ExternalStreamHandler *&ref, int inputid)
int GetValue() const
Returns the value.
bool IsGood() const
Returns true if the value is equal to the threshold, or on the right side of the threshold (depends o...
void SetValue(int _value)
static const uint64_t kDTVSigMon_WaitForVCT
QRecursiveMutex m_statusLock
volatile bool m_exit
void SendMessageAllGood(void)
SignalMonitorValue m_signalLock
static const uint64_t kDTVSigMon_WaitForNIT
SignalMonitorValue m_scriptStatus
static const uint64_t kDTVSigMon_WaitForSDT
virtual void Stop()
Stop signal monitoring thread.
volatile bool m_running
ChannelBase * m_channel
static const uint64_t kDTVSigMon_WaitForPMT
virtual void EmitStatus(void)
static const uint64_t kSigMon_WaitForSig
static const uint64_t kDTVSigMon_WaitForPAT
static const uint64_t kDTVSigMon_WaitForMGT
virtual void UpdateValues(void)
This should be overridden to actually do signal monitoring.
SignalMonitorValue m_signalStrength
bool HasAnyFlag(uint64_t _flags) const
bool HasError(void) const
Definition: streamhandler.h:67
bool IsRunning(void) const
virtual void RemoveListener(MPEGStreamData *data)
virtual void AddListener(MPEGStreamData *data, bool allow_section_reader=false, bool needs_buffering=false, const QString &output_file=QString())
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39