MythTV master
playbacksock.cpp
Go to the documentation of this file.
1// C++
2#include <utility>
3
4// Qt
5#include <QStringList>
6
7// MythTV
14#include "libmythtv/inputinfo.h"
15
16// MythBackend
17#include "mainserver.h"
18#include "playbacksock.h"
19
20#define LOC QString("PlaybackSock: ")
21#define LOC_ERR QString("PlaybackSock, Error: ")
22
24 MythSocket *lsock,
25 QString lhostname, PlaybackSockEventsMode eventsMode) :
26 ReferenceCounter("PlaybackSock"),
27 m_sock(lsock),
28 m_hostname(std::move(lhostname)),
29 m_ip(""),
30 m_eventsMode(eventsMode)
31{
32 QString localhostname = gCoreContext->GetHostName();
33 m_local = (m_hostname == localhostname);
34}
35
37{
38 m_sock->DecrRef();
39 m_sock = nullptr;
40}
41
43{
44 return (m_eventsMode != kPBSEvents_None);
45}
46
48{
49 return ((m_eventsMode == kPBSEvents_Normal) ||
51}
52
54{
55 return ((m_eventsMode == kPBSEvents_Normal) ||
57}
58
60{
62}
63
65{
66 return m_eventsMode;
67}
68
69bool PlaybackSock::ReadStringList(QStringList &list)
70{
71 m_sock->IncrRef();
72 ReferenceLocker rlocker(m_sock);
73 QMutexLocker locker(&m_sockLock);
74 if (!m_sock->IsDataAvailable())
75 {
76 LOG(VB_GENERAL, LOG_DEBUG,
77 "PlaybackSock::ReadStringList(): Data vanished !!!");
78 return false;
79 }
80 return m_sock->ReadStringList(list);
81}
82
84 QStringList &strlist, uint min_reply_length)
85{
86 bool ok = false;
87
88 m_sock->IncrRef();
89
90 {
91 QMutexLocker locker(&m_sockLock);
93
94 ok = m_sock->SendReceiveStringList(strlist);
95 while (ok && strlist[0] == "BACKEND_MESSAGE")
96 {
97 // oops, not for us
98 if (strlist.size() >= 2)
99 {
100 QString message = strlist[1];
101 strlist.pop_front();
102 strlist.pop_front();
103 MythEvent me(message, strlist);
105 }
106
107 ok = m_sock->ReadStringList(strlist);
108 }
110 }
111
112 m_sock->DecrRef();
113
114 if (!ok)
115 {
116 LOG(VB_GENERAL, LOG_ERR,
117 "PlaybackSock::SendReceiveStringList(): No response.");
118 return false;
119 }
120
121 if (min_reply_length && ((uint)strlist.size() < min_reply_length))
122 {
123 LOG(VB_GENERAL, LOG_ERR,
124 "PlaybackSock::SendReceiveStringList(): Response too short");
125 return false;
126 }
127
128 return true;
129}
130
134{
135 QStringList strlist(QString("GO_TO_SLEEP"));
136
137 return SendReceiveStringList(strlist, 1) && (strlist[0] == "OK");
138}
139
144{
145 QStringList strlist(QString("QUERY_FREE_SPACE"));
146
148 {
150 }
151 return {};
152}
153
155{
156 QStringList strlist(QString("CHECK_RECORDING"));
157 pginfo->ToStringList(strlist);
158
159 if (SendReceiveStringList(strlist, 1))
160 return strlist[0].toInt();
161
162 return 0;
163}
164
165int PlaybackSock::DeleteFile(const QString &filename, const QString &sgroup)
166{
167 QStringList strlist("DELETE_FILE");
168 strlist << filename;
169 strlist << sgroup;
170
171 if (SendReceiveStringList(strlist, 1))
172 return strlist[0].toInt();
173
174 return 0;
175}
176
178{
179 QStringList strlist(QString("STOP_RECORDING"));
180 pginfo->ToStringList(strlist);
181
182 if (SendReceiveStringList(strlist, 1))
183 return strlist[0].toInt();
184
185 return 0;
186}
187
189 bool forceMetadataDelete)
190{
191 QStringList strlist;
192
193 if (forceMetadataDelete)
194 strlist = QStringList( QString("FORCE_DELETE_RECORDING"));
195 else
196 strlist = QStringList( QString("DELETE_RECORDING"));
197
198 pginfo->ToStringList(strlist);
199
200 if (SendReceiveStringList(strlist, 1))
201 return strlist[0].toInt();
202
203 return 0;
204}
205
207 const QString &playbackhost)
208{
209 QStringList strlist(QString("FILL_PROGRAM_INFO"));
210 strlist << playbackhost;
211 pginfo.ToStringList(strlist);
212
213 if (SendReceiveStringList(strlist))
214 {
215 ProgramInfo tmp(strlist);
216 if (tmp.HasPathname() || tmp.GetChanID())
217 {
218 pginfo.clone(tmp, true);
219 return true;
220 }
221 }
222
223 return false;
224}
225
226QStringList PlaybackSock::GetSGFileList(const QString &host, const QString &groupname,
227 const QString &directory, bool fileNamesOnly)
228{
229 QStringList strlist(QString("QUERY_SG_GETFILELIST"));
230 strlist << host;
231 strlist << groupname;
232 strlist << directory;
233 strlist << QString::number(static_cast<int>(fileNamesOnly));
234
235 SendReceiveStringList(strlist);
236
237 return strlist;
238}
239
240QStringList PlaybackSock::GetSGFileQuery(const QString &host, const QString &groupname,
241 const QString &filename)
242{
243 QStringList strlist(QString("QUERY_SG_FILEQUERY"));
244 strlist << host;
245 strlist << groupname;
246 strlist << filename;
247
248 SendReceiveStringList(strlist);
249
250 return strlist;
251}
252
253QString PlaybackSock::GetFileHash(const QString& filename, const QString& storageGroup)
254{
255 QStringList strlist(QString("QUERY_FILE_HASH"));
256 strlist << filename
257 << storageGroup;
258
259 SendReceiveStringList(strlist);
260 return strlist[0];
261}
262
263QStringList PlaybackSock::GetFindFile(const QString &host, const QString &filename,
264 const QString &storageGroup, bool useRegex)
265{
266 QStringList strlist(QString("QUERY_FINDFILE"));
267 strlist << host
268 << storageGroup
269 << filename
270 << (useRegex ? "1" : "0")
271 << "0";
272
273 SendReceiveStringList(strlist);
274 return strlist;
275}
276
277QStringList PlaybackSock::GenPreviewPixmap(const QString &token,
278 const ProgramInfo *pginfo)
279{
280 QStringList strlist(QString("QUERY_GENPIXMAP2"));
281 strlist += token;
282 pginfo->ToStringList(strlist);
283
284 SendReceiveStringList(strlist);
285
286 return strlist;
287}
288
289QStringList PlaybackSock::GenPreviewPixmap(const QString &token,
290 const ProgramInfo *pginfo,
291 std::chrono::seconds time,
292 long long frame,
293 const QString &outputFile,
294 const QSize outputSize)
295{
296 QStringList strlist(QString("QUERY_GENPIXMAP2"));
297 strlist += token;
298 pginfo->ToStringList(strlist);
299 if (time != std::chrono::seconds::max())
300 {
301 strlist.push_back("s");
302 strlist.push_back(QString::number(time.count()));
303 }
304 else
305 {
306 strlist.push_back("f");
307 strlist.push_back(QString::number(frame));
308 }
309 strlist.push_back((outputFile.isEmpty()) ? "<EMPTY>" : outputFile);
310 strlist.push_back(QString::number(outputSize.width()));
311 strlist.push_back(QString::number(outputSize.height()));
312
313 SendReceiveStringList(strlist);
314
315 return strlist;
316}
317
319{
320 QStringList strlist(QString("QUERY_PIXMAP_LASTMODIFIED"));
321 pginfo->ToStringList(strlist);
322
323 SendReceiveStringList(strlist);
324
325 if (!strlist.empty() && !strlist[0].isEmpty() && (strlist[0] != "BAD"))
326 {
327 return MythDate::fromSecsSinceEpoch(strlist[0].toLongLong());
328 }
329
330 return {};
331}
332
334{
335 QStringList strlist("QUERY_CHECKFILE");
336 strlist << QString::number(0); // don't check slaves
337 pginfo->ToStringList(strlist);
338
339 if (SendReceiveStringList(strlist, 2))
340 {
341 pginfo->SetPathname(strlist[1]);
342 return strlist[0].toInt() != 0;
343 }
344
345 return false;
346}
347
348bool PlaybackSock::IsBusy(int capturecardnum, InputInfo *busy_input,
349 std::chrono::seconds time_buffer)
350{
351 QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
352
353 strlist << "IS_BUSY";
354 strlist << QString::number(time_buffer.count());
355
356 if (!SendReceiveStringList(strlist, 1))
357 {
358 LOG(VB_GENERAL, LOG_ERR, LOC + "IsBusy: " +
359 QString("QUERY_REMOTEENCODER %1").arg(capturecardnum) +
360 " gave us no response.");
361 }
362
363 bool state = false;
364
365 if (!strlist.isEmpty())
366 {
367 QStringList::const_iterator it = strlist.cbegin();
368 state = ((*it).toInt() != 0);
369
370 if (busy_input)
371 {
372 ++it;
373 if (!busy_input->FromStringList(it, strlist.cend()))
374 {
375 LOG(VB_GENERAL, LOG_ERR, LOC + "IsBusy: "
376 "Failed to parse response to " +
377 QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
378 state = false;
379 // pretend it's not busy if we can't parse response
380 }
381 }
382 }
383
384 return state;
385}
386
391int PlaybackSock::GetEncoderState(int capturecardnum)
392{
393 QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
394 strlist << "GET_STATE";
395
396 if (!SendReceiveStringList(strlist, 1))
397 {
398 LOG(VB_GENERAL, LOG_ERR, LOC + "GetEncoderState: " +
399 QString("QUERY_REMOTEENCODER %1").arg(capturecardnum) +
400 " gave us no response.");
401
402 return kState_Error;
403 }
404
405 return strlist[0].toInt();
406}
407
408long long PlaybackSock::GetMaxBitrate(int capturecardnum)
409{
410 QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
411 strlist << "GET_MAX_BITRATE";
412
413 if (SendReceiveStringList(strlist, 1))
414 return strlist[0].toLongLong();
415
416 return 20200000LL; // Peak bit rate for HD-PVR
417}
418
424{
425 QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(cardid));
426 strlist << "GET_CURRENT_RECORDING";
427
428 if (!SendReceiveStringList(strlist))
429 return nullptr;
430
431 auto *pginfo = new ProgramInfo(strlist);
432 if (!pginfo->HasPathname() && !pginfo->GetChanID())
433 {
434 delete pginfo;
435 pginfo = nullptr;
436 }
437
438 return pginfo;
439}
440
441bool PlaybackSock::EncoderIsRecording(int capturecardnum,
442 const ProgramInfo *pginfo)
443{
444 QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
445 strlist << "MATCHES_RECORDING";
446 pginfo->ToStringList(strlist);
447
448 if (SendReceiveStringList(strlist, 1))
449 return (bool) strlist[0].toInt();
450
451 return false;
452}
453
455 ProgramInfo *pginfo)
456{
457 QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
458 strlist << "START_RECORDING";
459 pginfo->ToStringList(strlist);
460
461 if (SendReceiveStringList(strlist, 3))
462 {
463 pginfo->SetRecordingID(strlist[1].toUInt());
464 pginfo->SetRecordingStartTime(
465 MythDate::fromSecsSinceEpoch(strlist[2].toLongLong()));
466 return RecStatus::Type(strlist[0].toInt());
467 }
468
469 return RecStatus::Unknown;
470}
471
473{
474 QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
475 strlist << "GET_RECORDING_STATUS";
476
477 if (!SendReceiveStringList(strlist, 1))
478 {
479 LOG(VB_GENERAL, LOG_ERR, LOC + "GetRecordingStatus: " +
480 QString("QUERY_REMOTEENCODER %1").arg(capturecardnum) +
481 " did not respond.");
482
483 return RecStatus::Unknown;
484 }
485
486 return RecStatus::Type(strlist[0].toInt());
487}
488
489void PlaybackSock::RecordPending(int capturecardnum, const ProgramInfo *pginfo,
490 std::chrono::seconds secsleft, bool hasLater)
491{
492 QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
493 strlist << "RECORD_PENDING";
494 strlist << QString::number(secsleft.count());
495 strlist << QString::number(static_cast<int>(hasLater));
496 pginfo->ToStringList(strlist);
497
498 SendReceiveStringList(strlist);
499}
500
501std::chrono::milliseconds PlaybackSock::SetSignalMonitoringRate(int capturecardnum,
502 std::chrono::milliseconds rate, int notifyFrontend)
503{
504 QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
505 strlist << "SET_SIGNAL_MONITORING_RATE";
506 strlist << QString::number(rate.count());
507 strlist << QString::number(notifyFrontend);
508
509 if (SendReceiveStringList(strlist, 1))
510 return std::chrono::milliseconds(strlist[0].toInt());
511
512 return -1ms;
513}
514
515void PlaybackSock::SetNextLiveTVDir(int capturecardnum, const QString& dir)
516{
517 QStringList strlist(QString("SET_NEXT_LIVETV_DIR %1 %2")
518 .arg(capturecardnum)
519 .arg(dir));
520
521 SendReceiveStringList(strlist);
522}
523
524void PlaybackSock::CancelNextRecording(int capturecardnum, bool cancel)
525{
526 QStringList strlist(QString("QUERY_REMOTEENCODER %1")
527 .arg(capturecardnum));
528
529 strlist << "CANCEL_NEXT_RECORDING";
530 strlist << QString::number(static_cast<int>(cancel));
531
532 SendReceiveStringList(strlist);
533}
534
535QStringList PlaybackSock::ForwardRequest(const QStringList &slist)
536{
537 QStringList strlist = slist;
538
539 if (SendReceiveStringList(strlist))
540 return strlist;
541
542 return {};
543}
544
548{
549 QStringList strlist(QString("ADD_CHILD_INPUT %1").arg(childid));
550 return SendReceiveStringList(strlist, 1) && (strlist[0] == "OK");
551}
552
553/* vim: set expandtab tabstop=4 shiftwidth=4: */
static constexpr int kLines
number of strings in the serialized stringlist
virtual bool FromStringList(QStringList::const_iterator &it, const QStringList::const_iterator &end)
Definition: inputinfo.cpp:14
QString GetHostName(void)
void dispatch(const MythEvent &event)
This class is used as a container for messages.
Definition: mythevent.h:17
Class for communcating between myth backends and frontends.
Definition: mythsocket.h:26
bool SendReceiveStringList(QStringList &list, uint min_reply_length=0, std::chrono::milliseconds timeoutMS=kLongTimeout)
Definition: mythsocket.cpp:326
bool ReadStringList(QStringList &list, std::chrono::milliseconds timeoutMS=kShortTimeout)
Definition: mythsocket.cpp:313
bool IsDataAvailable(void)
Definition: mythsocket.cpp:557
void SetReadyReadCallbackEnabled(bool enabled)
Definition: mythsocket.h:48
MythSocket * m_sock
Definition: playbacksock.h:118
QDateTime PixmapLastModified(const ProgramInfo *pginfo)
int DeleteRecording(const ProgramInfo *pginfo, bool forceMetadataDelete=false)
~PlaybackSock() override
bool IsBusy(int capturecardnum, InputInfo *busy_input=nullptr, std::chrono::seconds time_buffer=5s)
void CancelNextRecording(int capturecardnum, bool cancel)
RecStatus::Type GetRecordingStatus(int capturecardnum)
bool FillProgramInfo(ProgramInfo &pginfo, const QString &playbackhost)
bool GoToSleep(void)
Tells a slave to go to sleep.
long long GetMaxBitrate(int capturecardnum)
QStringList GenPreviewPixmap(const QString &token, const ProgramInfo *pginfo)
bool wantsNonSystemEvents(void) const
QMutex m_sockLock
Definition: playbacksock.h:129
QString m_hostname
Definition: playbacksock.h:119
bool wantsEvents(void) const
FileSystemInfoList GetDiskSpace()
Gets the total and used space in kilobytes for the host's directories.
int DeleteFile(const QString &filename, const QString &sgroup)
bool wantsOnlySystemEvents(void) const
QString GetFileHash(const QString &filename, const QString &storageGroup)
bool CheckFile(ProgramInfo *pginfo)
QStringList GetSGFileQuery(const QString &host, const QString &groupname, const QString &filename)
PlaybackSockEventsMode m_eventsMode
Definition: playbacksock.h:123
QStringList GetFindFile(const QString &host, const QString &filename, const QString &storageGroup, bool useRegex)
bool SendReceiveStringList(QStringList &strlist, uint min_reply_length=0)
ProgramInfo * GetRecording(uint cardid)
Returns the ProgramInfo being used by any current recording.
PlaybackSockEventsMode eventsMode(void) const
int CheckRecordingActive(const ProgramInfo *pginfo)
std::chrono::milliseconds SetSignalMonitoringRate(int capturecardnum, std::chrono::milliseconds rate, int notifyFrontend)
QStringList GetSGFileList(const QString &host, const QString &groupname, const QString &directory, bool fileNamesOnly)
bool EncoderIsRecording(int capturecardnum, const ProgramInfo *pginfo)
void RecordPending(int capturecardnum, const ProgramInfo *pginfo, std::chrono::seconds secsleft, bool hasLater)
int GetEncoderState(int capturecardnum)
Returns the maximum bits per second the recorder can produce.
bool ReadStringList(QStringList &list)
RecStatus::Type StartRecording(int capturecardnum, ProgramInfo *pginfo)
QStringList ForwardRequest(const QStringList &slist)
bool wantsSystemEvents(void) const
PlaybackSock(MythSocket *lsock, QString lhostname, PlaybackSockEventsMode eventsMode)
void SetNextLiveTVDir(int capturecardnum, const QString &dir)
bool AddChildInput(uint childid)
Tells a slave to add a child input.
int StopRecording(const ProgramInfo *pginfo)
Holds information on recordings and videos.
Definition: programinfo.h:68
void SetRecordingStartTime(const QDateTime &dt)
Definition: programinfo.h:530
void ToStringList(QStringList &list) const
Serializes ProgramInfo into a QStringList which can be passed over a socket.
virtual void clone(const ProgramInfo &other, bool ignore_non_serialized_data=false)
Copies important fields from other ProgramInfo.
virtual void SetRecordingID(uint _recordedid)
Definition: programinfo.h:583
void SetPathname(const QString &pn)
General purpose reference counter.
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual int IncrRef(void)
Increments reference count.
This decrements the reference on destruction.
QVector< FileSystemInfo > FileSystemInfoList
unsigned int uint
Definition: freesurround.h:24
static guint32 * tmp
Definition: goom_core.cpp:26
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MBASE_PUBLIC FileSystemInfoList FromStringList(const QStringList &list)
MBASE_PUBLIC QDateTime fromSecsSinceEpoch(int64_t seconds)
This function takes the number of seconds since the start of the epoch and returns a QDateTime with t...
Definition: mythdate.cpp:81
STL namespace.
#define LOC
PlaybackSockEventsMode
Definition: playbacksock.h:21
@ kPBSEvents_None
Definition: playbacksock.h:22
@ kPBSEvents_SystemOnly
Definition: playbacksock.h:25
@ kPBSEvents_Normal
Definition: playbacksock.h:23
@ kPBSEvents_NonSystem
Definition: playbacksock.h:24
@ kState_Error
Error State, if we ever try to enter this state errored is set.
Definition: tv.h:57