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  if (m_hostname == localhostname)
33  m_local = true;
34  else
35  m_local = false;
36 }
37 
39 {
40  m_sock->DecrRef();
41  m_sock = nullptr;
42 }
43 
44 bool PlaybackSock::wantsEvents(void) const
45 {
46  return (m_eventsMode != kPBSEvents_None);
47 }
48 
50 {
51  return ((m_eventsMode == kPBSEvents_Normal) ||
53 }
54 
56 {
57  return ((m_eventsMode == kPBSEvents_Normal) ||
59 }
60 
62 {
64 }
65 
67 {
68  return m_eventsMode;
69 }
70 
71 bool PlaybackSock::ReadStringList(QStringList &list)
72 {
73  m_sock->IncrRef();
74  ReferenceLocker rlocker(m_sock);
75  QMutexLocker locker(&m_sockLock);
76  if (!m_sock->IsDataAvailable())
77  {
78  LOG(VB_GENERAL, LOG_DEBUG,
79  "PlaybackSock::ReadStringList(): Data vanished !!!");
80  return false;
81  }
82  return m_sock->ReadStringList(list);
83 }
84 
86  QStringList &strlist, uint min_reply_length)
87 {
88  bool ok = false;
89 
90  m_sock->IncrRef();
91 
92  {
93  QMutexLocker locker(&m_sockLock);
95 
96  ok = m_sock->SendReceiveStringList(strlist);
97  while (ok && strlist[0] == "BACKEND_MESSAGE")
98  {
99  // oops, not for us
100  if (strlist.size() >= 2)
101  {
102  QString message = strlist[1];
103  strlist.pop_front();
104  strlist.pop_front();
105  MythEvent me(message, strlist);
106  gCoreContext->dispatch(me);
107  }
108 
109  ok = m_sock->ReadStringList(strlist);
110  }
112  }
113 
114  m_sock->DecrRef();
115 
116  if (!ok)
117  {
118  LOG(VB_GENERAL, LOG_ERR,
119  "PlaybackSock::SendReceiveStringList(): No response.");
120  return false;
121  }
122 
123  if (min_reply_length && ((uint)strlist.size() < min_reply_length))
124  {
125  LOG(VB_GENERAL, LOG_ERR,
126  "PlaybackSock::SendReceiveStringList(): Response too short");
127  return false;
128  }
129 
130  return true;
131 }
132 
136 {
137  QStringList strlist(QString("GO_TO_SLEEP"));
138 
139  return SendReceiveStringList(strlist, 1) && (strlist[0] == "OK");
140 }
141 
145 void PlaybackSock::GetDiskSpace(QStringList &o_strlist)
146 {
147  QStringList strlist(QString("QUERY_FREE_SPACE"));
148 
149  if (SendReceiveStringList(strlist, 8))
150  {
151  o_strlist += strlist;
152  }
153 }
154 
156 {
157  QStringList strlist(QString("CHECK_RECORDING"));
158  pginfo->ToStringList(strlist);
159 
160  if (SendReceiveStringList(strlist, 1))
161  return strlist[0].toInt();
162 
163  return 0;
164 }
165 
166 int PlaybackSock::DeleteFile(const QString &filename, const QString &sgroup)
167 {
168  QStringList strlist("DELETE_FILE");
169  strlist << filename;
170  strlist << sgroup;
171 
172  if (SendReceiveStringList(strlist, 1))
173  return strlist[0].toInt();
174 
175  return 0;
176 }
177 
179 {
180  QStringList strlist(QString("STOP_RECORDING"));
181  pginfo->ToStringList(strlist);
182 
183  if (SendReceiveStringList(strlist, 1))
184  return strlist[0].toInt();
185 
186  return 0;
187 }
188 
190  bool forceMetadataDelete)
191 {
192  QStringList strlist;
193 
194  if (forceMetadataDelete)
195  strlist = QStringList( QString("FORCE_DELETE_RECORDING"));
196  else
197  strlist = QStringList( QString("DELETE_RECORDING"));
198 
199  pginfo->ToStringList(strlist);
200 
201  if (SendReceiveStringList(strlist, 1))
202  return strlist[0].toInt();
203 
204  return 0;
205 }
206 
208  const QString &playbackhost)
209 {
210  QStringList strlist(QString("FILL_PROGRAM_INFO"));
211  strlist << playbackhost;
212  pginfo.ToStringList(strlist);
213 
214  if (SendReceiveStringList(strlist))
215  {
216  ProgramInfo tmp(strlist);
217  if (tmp.HasPathname() || tmp.GetChanID())
218  {
219  pginfo.clone(tmp, true);
220  return true;
221  }
222  }
223 
224  return false;
225 }
226 
227 QStringList PlaybackSock::GetSGFileList(QString &host, QString &groupname,
228  QString &directory, bool fileNamesOnly)
229 {
230  QStringList strlist(QString("QUERY_SG_GETFILELIST"));
231  strlist << host;
232  strlist << groupname;
233  strlist << directory;
234  strlist << QString::number(fileNamesOnly);
235 
236  SendReceiveStringList(strlist);
237 
238  return strlist;
239 }
240 
241 QStringList PlaybackSock::GetSGFileQuery(QString &host, QString &groupname,
242  QString &filename)
243 {
244  QStringList strlist(QString("QUERY_SG_FILEQUERY"));
245  strlist << host;
246  strlist << groupname;
247  strlist << filename;
248 
249  SendReceiveStringList(strlist);
250 
251  return strlist;
252 }
253 
254 QString PlaybackSock::GetFileHash(const QString& filename, const QString& storageGroup)
255 {
256  QStringList strlist(QString("QUERY_FILE_HASH"));
257  strlist << filename
258  << storageGroup;
259 
260  SendReceiveStringList(strlist);
261  return strlist[0];
262 }
263 
264 QStringList PlaybackSock::GetFindFile(const QString &host, const QString &filename,
265  const QString &storageGroup, bool useRegex)
266 {
267  QStringList strlist(QString("QUERY_FINDFILE"));
268  strlist << host
269  << storageGroup
270  << filename
271  << (useRegex ? "1" : "0")
272  << "0";
273 
274  SendReceiveStringList(strlist);
275  return strlist;
276 }
277 
278 QStringList PlaybackSock::GenPreviewPixmap(const QString &token,
279  const ProgramInfo *pginfo)
280 {
281  QStringList strlist(QString("QUERY_GENPIXMAP2"));
282  strlist += token;
283  pginfo->ToStringList(strlist);
284 
285  SendReceiveStringList(strlist);
286 
287  return strlist;
288 }
289 
290 QStringList PlaybackSock::GenPreviewPixmap(const QString &token,
291  const ProgramInfo *pginfo,
292  bool time_fmt_sec,
293  long long time,
294  const QString &outputFile,
295  const QSize &outputSize)
296 {
297  QStringList strlist(QString("QUERY_GENPIXMAP2"));
298  strlist += token;
299  pginfo->ToStringList(strlist);
300  strlist.push_back(time_fmt_sec ? "s" : "f");
301  strlist.push_back(QString::number(time));
302  strlist.push_back((outputFile.isEmpty()) ? "<EMPTY>" : outputFile);
303  strlist.push_back(QString::number(outputSize.width()));
304  strlist.push_back(QString::number(outputSize.height()));
305 
306  SendReceiveStringList(strlist);
307 
308  return strlist;
309 }
310 
312 {
313  QStringList strlist(QString("QUERY_PIXMAP_LASTMODIFIED"));
314  pginfo->ToStringList(strlist);
315 
316  SendReceiveStringList(strlist);
317 
318  if (!strlist.empty() && !strlist[0].isEmpty() && (strlist[0] != "BAD"))
319 #if QT_VERSION < QT_VERSION_CHECK(5,8,0)
320  return MythDate::fromTime_t(strlist[0].toUInt());
321 #else
322  return MythDate::fromSecsSinceEpoch(strlist[0].toLongLong());
323 #endif
324 
325  return QDateTime();
326 }
327 
329 {
330  QStringList strlist("QUERY_CHECKFILE");
331  strlist << QString::number(0); // don't check slaves
332  pginfo->ToStringList(strlist);
333 
334  if (SendReceiveStringList(strlist, 2))
335  {
336  pginfo->SetPathname(strlist[1]);
337  return strlist[0].toInt() != 0;
338  }
339 
340  return false;
341 }
342 
343 bool PlaybackSock::IsBusy(int capturecardnum, InputInfo *busy_input,
344  int time_buffer)
345 {
346  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
347 
348  strlist << "IS_BUSY";
349  strlist << QString::number(time_buffer);
350 
351  if (!SendReceiveStringList(strlist, 1))
352  {
353  LOG(VB_GENERAL, LOG_ERR, LOC + "IsBusy: " +
354  QString("QUERY_REMOTEENCODER %1").arg(capturecardnum) +
355  " gave us no response.");
356  }
357 
358  bool state = false;
359 
360  if (!strlist.isEmpty())
361  {
362  QStringList::const_iterator it = strlist.begin();
363  state = ((*it).toInt() != 0);
364 
365  if (busy_input)
366  {
367  ++it;
368  if (!busy_input->FromStringList(it, strlist.end()))
369  {
370  LOG(VB_GENERAL, LOG_ERR, LOC + "IsBusy: "
371  "Failed to parse response to " +
372  QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
373  state = false;
374  // pretend it's not busy if we can't parse response
375  }
376  }
377  }
378 
379  return state;
380 }
381 
386 int PlaybackSock::GetEncoderState(int capturecardnum)
387 {
388  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
389  strlist << "GET_STATE";
390 
391  if (!SendReceiveStringList(strlist, 1))
392  {
393  LOG(VB_GENERAL, LOG_ERR, LOC + "GetEncoderState: " +
394  QString("QUERY_REMOTEENCODER %1").arg(capturecardnum) +
395  " gave us no response.");
396 
397  return kState_Error;
398  }
399 
400  return strlist[0].toInt();
401 }
402 
403 long long PlaybackSock::GetMaxBitrate(int capturecardnum)
404 {
405  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
406  strlist << "GET_MAX_BITRATE";
407 
408  if (SendReceiveStringList(strlist, 1))
409  return strlist[0].toLongLong();
410 
411  return 20200000LL; // Peak bit rate for HD-PVR
412 }
413 
419 {
420  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(cardid));
421  strlist << "GET_CURRENT_RECORDING";
422 
423  if (!SendReceiveStringList(strlist))
424  return nullptr;
425 
426  ProgramInfo *pginfo = new ProgramInfo(strlist);
427  if (!pginfo->HasPathname() && !pginfo->GetChanID())
428  {
429  delete pginfo;
430  pginfo = nullptr;
431  }
432 
433  return pginfo;
434 }
435 
436 bool PlaybackSock::EncoderIsRecording(int capturecardnum,
437  const ProgramInfo *pginfo)
438 {
439  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
440  strlist << "MATCHES_RECORDING";
441  pginfo->ToStringList(strlist);
442 
443  if (SendReceiveStringList(strlist, 1))
444  return (bool) strlist[0].toInt();
445 
446  return false;
447 }
448 
450  ProgramInfo *pginfo)
451 {
452  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
453  strlist << "START_RECORDING";
454  pginfo->ToStringList(strlist);
455 
456  if (SendReceiveStringList(strlist, 3))
457  {
458  pginfo->SetRecordingID(strlist[1].toUInt());
459 #if QT_VERSION < QT_VERSION_CHECK(5,8,0)
460  pginfo->SetRecordingStartTime(
461  MythDate::fromTime_t(strlist[2].toUInt()));
462 #else
463  pginfo->SetRecordingStartTime(
464  MythDate::fromSecsSinceEpoch(strlist[2].toLongLong()));
465 #endif
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 
489 void PlaybackSock::RecordPending(int capturecardnum, const ProgramInfo *pginfo,
490  int secsleft, bool hasLater)
491 {
492  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
493  strlist << "RECORD_PENDING";
494  strlist << QString::number(secsleft);
495  strlist << QString::number(hasLater);
496  pginfo->ToStringList(strlist);
497 
498  SendReceiveStringList(strlist);
499 }
500 
502  int rate, int notifyFrontend)
503 {
504  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
505  strlist << "SET_SIGNAL_MONITORING_RATE";
506  strlist << QString::number(rate);
507  strlist << QString::number(notifyFrontend);
508 
509  if (SendReceiveStringList(strlist, 1))
510  return strlist[0].toInt();
511 
512  return -1;
513 }
514 
515 void 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 
524 void 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(cancel);
531 
532  SendReceiveStringList(strlist);
533 }
534 
535 QStringList PlaybackSock::ForwardRequest(const QStringList &slist)
536 {
537  QStringList strlist = slist;
538 
539  if (SendReceiveStringList(strlist))
540  return strlist;
541 
542  return QStringList();
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: */
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.
virtual ~PlaybackSock()
bool AddChildInput(uint childid)
Tells a slave to add a child input.
void SetPathname(const QString &) const
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
int DeleteFile(const QString &filename, const QString &sgroup)
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
unsigned int uint
Definition: compat.h:140
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
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:66
QString GetFileHash(const QString &filename, const QString &storageGroup)
QStringList ForwardRequest(const QStringList &)
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)
virtual bool FromStringList(QStringList::const_iterator &it, QStringList::const_iterator end)
Definition: inputinfo.cpp:13
QStringList GetSGFileList(QString &host, QString &groupname, QString &directory, bool fileNamesOnly)
RecStatus::Type StartRecording(int capturecardnum, ProgramInfo *pginfo)
bool IsDataAvailable(void) const
Definition: mythsocket.cpp:567
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)
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:563
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
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:364
QStringList GenPreviewPixmap(const QString &token, const ProgramInfo *pginfo)
void SetRecordingStartTime(const QDateTime &dt)
Definition: programinfo.h:510
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)
bool HasPathname(void) const
Definition: programinfo.h:350
#define LOC
void SetNextLiveTVDir(int capturecardnum, const QString &dir)