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