Skip to content

Commit

Permalink
ExternalRecorder: minor fixes and cleanup of side-band messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpoet committed Nov 23, 2024
1 parent a8f86b2 commit 92fb513
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 47 deletions.
1 change: 0 additions & 1 deletion mythtv/libs/libmythtv/recorders/ExternalChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ bool ExternalChannel::EnterPowerSavingMode(void)

uint ExternalChannel::GetTuneStatus(void)
{

if (!m_backgroundTuning)
return 3;

Expand Down
9 changes: 9 additions & 0 deletions mythtv/libs/libmythtv/recorders/ExternalRecorder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ void ExternalRecorder::run(void)
m_error = "Stream handler died unexpectedly.";
LOG(VB_GENERAL, LOG_ERR, LOC + m_error);
}

if (m_streamHandler->IsDamaged())
{
LOG(VB_GENERAL, LOG_INFO, LOC +
QString("Recording is damaged. Setting status to %1")
.arg(RecStatus::toString(RecStatus::Failing, kSingleRecord)));
SetRecordingStatus(RecStatus::Failing, __FILE__, __LINE__);
m_streamHandler->ClearDamaged();
}
}

StopStreaming();
Expand Down
90 changes: 74 additions & 16 deletions mythtv/libs/libmythtv/recorders/ExternalStreamHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,8 @@ void ExternalStreamHandler::run(void)
std::this_thread::sleep_for(20s);
if (!RestartStream())
{
LOG(VB_RECORD, LOG_ERR, LOC + "Failed to restart stream.");
LOG(VB_RECORD, LOG_ERR, LOC +
"Failed to restart stream.");
m_bError = true;
}
continue;
Expand Down Expand Up @@ -1073,6 +1074,7 @@ bool ExternalStreamHandler::RestartStream(void)
bool streaming = (StreamingCount() > 0);

LOG(VB_RECORD, LOG_INFO, LOC + "Restarting stream.");
m_damaged = true;

if (streaming)
StopStreaming();
Expand Down Expand Up @@ -1637,7 +1639,7 @@ bool ExternalStreamHandler::ProcessJson(const QVariantMap & vmsg,
if (!okay)
level = LOG_WARNING;
else if (cmd == "SendBytes" ||
(cmd == "TuneStatus" &&
(cmd == "TuneStatus?" &&
elements["message"] == "InProgress"))
level = LOG_DEBUG;

Expand Down Expand Up @@ -1672,8 +1674,8 @@ bool ExternalStreamHandler::ProcessJson(const QVariantMap & vmsg,

bool ExternalStreamHandler::CheckForError(void)
{
QString result;
bool err = false;
QByteArray response;
bool err = false;

QMutexLocker locker(&m_ioLock);

Expand All @@ -1692,26 +1694,82 @@ bool ExternalStreamHandler::CheckForError(void)

do
{
result = m_io->GetStatus(0ms);
if (!result.isEmpty())
response = m_io->GetStatus(0ms);
if (!response.isEmpty())
{
if (m_apiVersion > 1)
if (m_apiVersion > 2)
{
QStringList tokens = result.split(':', Qt::SkipEmptyParts);
tokens.removeFirst();
result = tokens.join(':');
for (int idx = 1; idx < tokens.size(); ++idx)
err |= tokens[idx].startsWith("ERR");
QJsonParseError parseError;
QJsonDocument doc;
QVariantMap elements;

doc = QJsonDocument::fromJson(response, &parseError);

if (parseError.error != QJsonParseError::NoError)
{
LOG(VB_GENERAL, LOG_ERR, LOC +
QString("ExternalRecorder returned invalid JSON message: %1: %2\n%3\n")
.arg(parseError.offset).arg(parseError.errorString())
.arg(QString(response)));
}
else
{
LogLevel_t level;
elements = doc.toVariant().toMap();
if (elements.find("command") != elements.end() &&
elements["command"] == "STATUS")
{
QString status = elements["status"].toString();
if (status.startsWith("err", Qt::CaseInsensitive))
{
level = LOG_ERR;
err |= true;
}
else if (status.startsWith("warn",
Qt::CaseInsensitive))
level = LOG_WARNING;
else if (status.startsWith("damage",
Qt::CaseInsensitive))
{
level = LOG_WARNING;
m_damaged |= true;
}
else
level = LOG_INFO;
LOG(VB_RECORD, level,
LOC + elements["message"].toString());
}
}
}
else
{
err |= result.startsWith("STATUS:ERR");
}
QString res = QString(response);
if (m_apiVersion == 2)
{
QStringList tokens = res.split(':', Qt::SkipEmptyParts);
tokens.removeFirst();
res = tokens.join(':');
for (int idx = 1; idx < tokens.size(); ++idx)
{
err |= tokens[idx].startsWith("ERR",
Qt::CaseInsensitive);
m_damaged |= tokens[idx].startsWith("damage",
Qt::CaseInsensitive);
}
}
else
{
err |= res.startsWith("STATUS:ERR",
Qt::CaseInsensitive);
m_damaged |= res.startsWith("STATUS:DAMAGE",
Qt::CaseInsensitive);
}

LOG(VB_RECORD, (err ? LOG_WARNING : LOG_INFO), LOC + result);
LOG(VB_RECORD, (err ? LOG_WARNING : LOG_INFO), LOC + res);
}
}
}
while (!result.isEmpty());
while (!response.isEmpty());

return err;
}
Expand Down
3 changes: 3 additions & 0 deletions mythtv/libs/libmythtv/recorders/ExternalStreamHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ class ExternalStreamHandler : public StreamHandler

QString GetDescription(void) { return m_loc; }
QString UpdateDescription(void);
bool IsDamaged(void) const { return m_damaged; }
void ClearDamaged(void) { m_damaged = false; }
bool IsAppOpen(void);
bool IsTSOpen(void);
bool HasTuner(void) const { return m_hasTuner; }
Expand Down Expand Up @@ -144,6 +146,7 @@ class ExternalStreamHandler : public StreamHandler
QByteArray m_replayBuffer;
bool m_replay {false};
bool m_xon {false};
bool m_damaged {false};

// for implementing Get & Return
static QMutex s_handlersLock;
Expand Down
18 changes: 10 additions & 8 deletions mythtv/programs/mythexternrecorder/MythExternControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,11 @@ bool Commands::SendStatus(const QString & command,

if (!command.isEmpty())
{
if (command == m_prevCmd)
if (command + response + status == m_prevStatus)
{
if (++m_repCmdCnt % 25 == 0)
{
LOG(VB_RECORD, LOG_INFO, LOC +
LOG(VB_RECORD, LOG_DEBUG, LOC +
QString("Processing '%1' --> '%2' (Repeated 25 times)")
.arg(command, QString(msgbuf)));
}
Expand All @@ -242,20 +242,22 @@ bool Commands::SendStatus(const QString & command,
{
if (m_repCmdCnt)
{
LOG(VB_RECORD, LOG_INFO,
LOC + QString("Processing '%1' (Repeated %2 times)")
.arg(m_prevCmd).arg(m_repCmdCnt % 25));
LOG(VB_RECORD, LOG_DEBUG,
LOC + QString("Processing '%1' --> '%2' (Repeated %2 times)")
.arg(m_prevMsgBuf).arg(m_repCmdCnt % 25));
m_repCmdCnt = 0;
}
LOG(VB_RECORD, LOG_INFO, LOC +
LOG(VB_RECORD, LOG_DEBUG, LOC +
QString("Processing '%1' --> '%2'")
.arg(command, QString(msgbuf)));
}
m_prevCmd = command;
m_prevStatus = command + response + status;
m_prevMsgBuf = QString(msgbuf);
}
else
{
m_prevCmd.clear();
m_prevStatus.clear();
m_prevMsgBuf.clear();
m_repCmdCnt = 0;
}

Expand Down
3 changes: 2 additions & 1 deletion mythtv/programs/mythexternrecorder/MythExternControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ class Commands : public QObject
std::thread m_thread;

size_t m_repCmdCnt { 0 };
QString m_prevCmd;
QString m_prevStatus;
QString m_prevMsgBuf;

MythExternControl* m_parent { nullptr };
int m_apiVersion { -1 };
Expand Down
66 changes: 45 additions & 21 deletions mythtv/programs/mythexternrecorder/MythExternRecApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,7 @@ bool MythExternRecApp::Open(void)

void MythExternRecApp::TerminateProcess(QProcess & proc, const QString & desc) const
{
if (proc.state() == QProcess::Running)
{
LOG(VB_RECORD, LOG_INFO, LOC +
QString("Sending SIGINT to %1(%2)").arg(desc).arg(proc.processId()));
kill(proc.processId(), SIGINT);
proc.waitForFinished(5000);
}
m_terminating = true;
if (proc.state() == QProcess::Running)
{
LOG(VB_RECORD, LOG_INFO, LOC +
Expand All @@ -348,6 +342,7 @@ void MythExternRecApp::TerminateProcess(QProcess & proc, const QString & desc) c
proc.kill();
proc.waitForFinished();
}
m_terminating = false;
}

Q_SLOT void MythExternRecApp::Close(void)
Expand Down Expand Up @@ -974,7 +969,7 @@ Q_SLOT void MythExternRecApp::StopStreaming(const QString & serial, bool silent)
if (silent)
{
emit SendMessage("StopStreaming", serial,
"Already not Streaming", "STATUS");
"Already not Streaming", "INFO");
}
else
{
Expand Down Expand Up @@ -1031,32 +1026,61 @@ Q_SLOT void MythExternRecApp::ProcStateChanged(QProcess::ProcessState newState)
if (unexpected)
{
emit Streaming(false);
MythLog("ERR Unexpected " + msg);
emit SendMessage("STATUS", "0", "Unexpected: " + msg, "ERR");
}
}

Q_SLOT void MythExternRecApp::ProcError(QProcess::ProcessError /*error */)
{
LOG(VB_RECORD, LOG_ERR, LOC + QString(": Error: %1")
.arg(m_proc.errorString()));
MythLog(m_proc.errorString());
if (m_terminating)
{
LOG(VB_RECORD, LOG_INFO, LOC + QString(": %1")
.arg(m_proc.errorString()));
emit SendMessage("STATUS", "0", m_proc.errorString(), "INFO");
}
else
{
LOG(VB_RECORD, LOG_ERR, LOC + QString(": Error: %1")
.arg(m_proc.errorString()));
emit SendMessage("STATUS", "0", m_proc.errorString(), "ERR");
}
}

Q_SLOT void MythExternRecApp::ProcReadStandardError(void)
{
QByteArray buf = m_proc.readAllStandardError();
QString msg = QString::fromUtf8(buf).trimmed();
QList<QString> msgs = msg.split('\n');
QString message;

// Log any error messages
if (!msg.isEmpty())
for (int idx=0; idx < msgs.count(); ++idx)
{
LOG(VB_RECORD, LOG_INFO, LOC + QString(">>> %1")
.arg(msg));
#if 0 // Show even long messages in mythbackend log
if (msg.size() > 79)
msg = QString("Application message: see '%1'").arg(m_logFile);
#endif
MythLog(msg);
// Log any error messages
if (!msgs[idx].isEmpty())
{
QStringList tokens = QString(msgs[idx])
.split(':', Qt::SkipEmptyParts);
tokens.removeFirst();
if (tokens.empty())
message = msgs[idx];
else
message = tokens.join(':');
if (msgs[idx].startsWith("err", Qt::CaseInsensitive))
{
LOG(VB_RECORD, LOG_ERR, LOC + QString(">>> %1").arg(msgs[idx]));
emit SendMessage("STATUS", "0", message, "ERR");
}
else if (msgs[idx].startsWith("warn", Qt::CaseInsensitive))
{
LOG(VB_RECORD, LOG_WARNING, LOC + QString(">>> %1").arg(msgs[idx]));
emit SendMessage("STATUS", "0", message, "WARN");
}
else
{
LOG(VB_RECORD, LOG_DEBUG, LOC + QString(">>> %1").arg(msgs[idx]));
emit SendMessage("STATUS", "0", message, "INFO");
}
}
}
}

Expand Down
1 change: 1 addition & 0 deletions mythtv/programs/mythexternrecorder/MythExternRecApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class MythExternRecApp : public QObject
QString replace_extra_args(const QString & var,
const QVariantMap & extra_args) const;

mutable bool m_terminating { false };
bool m_fatal { false };
QString m_fatalMsg;

Expand Down

0 comments on commit 92fb513

Please sign in to comment.