11 #include <QCoreApplication>
20 #include "libmythbase/mythversion.h"
27 static constexpr
const char*
VERSION {
"1.0.0" };
28 #define LOC QString("File(%1): ").arg(m_fileName)
31 int data_rate,
bool loopinput) :
32 m_parent(parent), m_fileName(
std::move(fname)),
33 m_loop(loopinput), m_dataRate(data_rate)
35 setObjectName(
"Streamer");
42 LOG(VB_RECORD, LOG_INFO,
LOC +
"Streamer::dtor -- begin");
44 LOG(VB_RECORD, LOG_INFO,
LOC +
"Streamer::dtor -- end");
52 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"Failed to open '%1' - ")
59 LOG(VB_RECORD, LOG_INFO,
LOC +
"Streamer::Close -- begin");
67 LOG(VB_RECORD, LOG_INFO,
LOC +
"Streamer::Close -- end");
75 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"SendBytes -- start");
79 LOG(VB_GENERAL, LOG_ERR,
LOC +
"SendBytes -- file not open");
99 read_sz = std::min(rate, read_sz);
104 QByteArray buffer =
m_file->read(read_sz);
106 pkt_size = buffer.size();
113 LOG(VB_RECORD, LOG_WARNING,
LOC +
114 QString(
"SendBytes -- Overflow: %1 > %2, "
115 "dropping first %3 bytes.")
126 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"SendBytes -- Buffer is empty.");
131 LOG(VB_RECORD, LOG_DEBUG,
LOC +
132 QString(
"SendBytes -- Read %1 from file. %2 bytes buffered")
133 .arg(pkt_size).arg(buf_size));
136 if (write_len > buf_size)
137 write_len = buf_size;
138 LOG(VB_RECORD, LOG_DEBUG,
LOC +
139 QString(
"SendBytes -- writing %1 bytes").arg(write_len));
143 LOG(VB_RECORD, LOG_DEBUG,
LOC +
144 QString(
"SendBytes -- wrote %1 bytes").arg(wrote));
146 if (wrote < buf_size)
149 LOG(VB_RECORD, LOG_WARNING,
LOC +
150 QString(
"%1 bytes unwritten").arg(
m_buffer.size()));
155 LOG(VB_RECORD, LOG_DEBUG,
LOC +
"SendBytes -- end");
161 setObjectName(
"Command");
166 QByteArray buf = status.toLatin1() +
'\n';
167 int len =
write(2, buf.constData(), buf.size());
168 if (len != buf.size())
170 LOG(VB_RECORD, LOG_ERR,
LOC +
171 QString(
"Status -- Wrote %1 of %2 bytes of status '%3'")
172 .arg(len).arg(status.size()).arg(status));
175 LOG(VB_RECORD, LOG_DEBUG,
"Status: " + status);
181 LOG(VB_RECORD, LOG_DEBUG,
LOC + cmd);
183 if (cmd.startsWith(
"Version?"))
188 if (cmd.startsWith(
"APIVersion?"))
193 if (cmd.startsWith(
"APIVersion:1"))
195 QString reply = (
API_VERSION == 1) ?
"OK:Yes":
"OK:No";
199 if (cmd.startsWith(
"HasLock?"))
204 if (cmd.startsWith(
"SignalStrengthPercent"))
209 if (cmd.startsWith(
"LockTimeout"))
214 if (cmd.startsWith(
"HasTuner?"))
219 if (cmd.startsWith(
"HasPictureAttributes?"))
228 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"%1 failed - not initialized!")
233 if (cmd.startsWith(
"SendBytes"))
238 LOG(VB_RECORD, LOG_ERR,
LOC +
"SendBytes - file not open.");
242 if (
m_eof.loadAcquire() != 0)
252 else if (cmd.startsWith(
"XON"))
256 else if (cmd.startsWith(
"XOFF"))
260 else if (cmd.startsWith(
"TuneChannel"))
269 else if (cmd.startsWith(
"IsOpen?"))
277 else if (cmd.startsWith(
"CloseRecorder"))
283 else if (cmd.startsWith(
"FlowControl?"))
287 else if (cmd.startsWith(
"BlockSize"))
292 else if (cmd.startsWith(
"StartStreaming"))
296 else if (cmd.startsWith(
"StopStreaming"))
305 send_status(QString(
"ERR:Unknown command '%1'").arg(cmd));
306 LOG(VB_RECORD, LOG_ERR,
LOC + QString(
"Unknown command '%1'")
318 std::array<struct pollfd,2> polls {};
321 polls[0].events = POLLIN | POLLPRI;
322 polls[0].revents = 0;
327 auto *streamThread =
new QThread(
this);
330 connect(streamThread, &QThread::finished,
336 streamThread->start();
339 input.open(stdin, QIODevice::ReadOnly);
340 QTextStream qtin(&input);
342 LOG(VB_RECORD, LOG_INFO,
LOC +
"Listening for commands");
346 int ret = poll(polls.data(), poll_cnt,
m_timeout);
348 if (polls[0].revents & POLLHUP)
350 LOG(VB_RECORD, LOG_ERR,
LOC +
"poll eof (POLLHUP)");
353 if (polls[0].revents & POLLNVAL)
355 LOG(VB_RECORD, LOG_ERR,
LOC +
"poll error");
359 if (polls[0].revents & POLLIN)
363 cmd = qtin.readLine();
366 streamThread->quit();
367 streamThread->wait();
369 streamThread =
nullptr;
376 if ((EOVERFLOW == errno))
378 LOG(VB_RECORD, LOG_ERR,
LOC +
"command overflow.");
382 if ((EAGAIN == errno) || (EINTR == errno))
384 LOG(VB_RECORD, LOG_ERR,
LOC +
"retry command read.");
388 LOG(VB_RECORD, LOG_ERR,
LOC +
"unknown error reading command.");
397 int main(
int argc,
char *argv[])
422 QCoreApplication a(argc, argv);
423 QCoreApplication::setApplicationName(
"mythfilerecorder");