MythTV  master
tvremoteutil.cpp
Go to the documentation of this file.
1 #include <chrono> // for milliseconds
2 #include <thread> // for sleep_for
3 
7 
8 #include "cardutil.h"
9 #include "inputinfo.h"
10 #include "remoteencoder.h"
11 #include "tv_rec.h"
12 #include "tvremoteutil.h"
13 
15 {
16  if (gCoreContext->IsBackend())
17  {
18  const TVRec *rec = TVRec::GetTVRec(inputid);
19  if (rec)
20  return rec->GetFlags();
21  return 0;
22  }
23 
24  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(inputid));
25  strlist << "GET_FLAGS";
26  if (!gCoreContext->SendReceiveStringList(strlist) || strlist.empty())
27  return 0;
28 
29  return strlist[0].toInt();
30 }
31 
33 {
34  if (gCoreContext->IsBackend())
35  {
36  const TVRec *rec = TVRec::GetTVRec(inputid);
37  if (rec)
38  return rec->GetState();
39  return kState_ChangingState;
40  }
41 
42  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(inputid));
43  strlist << "GET_STATE";
44  if (!gCoreContext->SendReceiveStringList(strlist) || strlist.empty())
45  return kState_ChangingState;
46 
47  return strlist[0].toInt();
48 }
49 
50 
51 bool RemoteRecordPending(uint inputid, const ProgramInfo *pginfo,
52  std::chrono::seconds secsleft, bool hasLater)
53 {
54  if (gCoreContext->IsBackend())
55  {
56  TVRec *rec = TVRec::GetTVRec(inputid);
57  if (rec)
58  {
59  rec->RecordPending(pginfo, secsleft, hasLater);
60  return true;
61  }
62  return false;
63  }
64 
65  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(inputid));
66  strlist << "RECORD_PENDING";
67  strlist << QString::number(secsleft.count());
68  strlist << QString::number(static_cast<int>(hasLater));
69  pginfo->ToStringList(strlist);
70 
71  if (!gCoreContext->SendReceiveStringList(strlist) || strlist.empty())
72  return false;
73 
74  return strlist[0].toUpper() == "OK";
75 }
76 
77 bool RemoteStopLiveTV(uint inputid)
78 {
79  if (gCoreContext->IsBackend())
80  {
81  TVRec *rec = TVRec::GetTVRec(inputid);
82  if (rec)
83  {
84  rec->StopLiveTV();
85  return true;
86  }
87  return false;
88  }
89 
90  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(inputid));
91  strlist << "STOP_LIVETV";
92 
93  if (!gCoreContext->SendReceiveStringList(strlist) || strlist.empty())
94  return false;
95 
96  return strlist[0].toUpper() == "OK";
97 }
98 
100 {
101  if (gCoreContext->IsBackend())
102  {
103  TVRec *rec = TVRec::GetTVRec(inputid);
104  if (rec)
105  {
106  rec->StopRecording();
107  return true;
108  }
109  return false;
110  }
111 
112  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(inputid));
113  strlist << "STOP_RECORDING";
114 
115  if (!gCoreContext->SendReceiveStringList(strlist) || strlist.empty())
116  return false;
117 
118  return strlist[0].toUpper() == "OK";
119 }
120 
121 void RemoteStopRecording(const ProgramInfo *pginfo)
122 {
123  QStringList strlist(QString("STOP_RECORDING"));
124  pginfo->ToStringList(strlist);
125 
127 }
128 
129 void RemoteCancelNextRecording(uint inputid, bool cancel)
130 {
131  QStringList strlist(QString("QUERY_RECORDER %1").arg(inputid));
132  strlist << "CANCEL_NEXT_RECORDING";
133  strlist << QString::number((cancel) ? 1 : 0);
134 
136 }
137 
138 std::vector<InputInfo> RemoteRequestFreeInputInfo(uint excluded_input)
139 {
140  LOG(VB_CHANNEL, LOG_INFO,
141  QString("RemoteRequestFreeInputInfo excluding input %1")
142  .arg(excluded_input));
143 
144  std::vector<InputInfo> inputs;
145 
146  QStringList strlist(QString("GET_FREE_INPUT_INFO %1")
147  .arg(excluded_input));
148  if (!gCoreContext->SendReceiveStringList(strlist))
149  return inputs;
150 
151  QStringList::const_iterator it = strlist.cbegin();
152  while (it != strlist.cend())
153  {
154  InputInfo info;
155  if (!info.FromStringList(it, strlist.cend()))
156  break;
157  inputs.push_back(info);
158  LOG(VB_CHANNEL, LOG_INFO,
159  QString("RemoteRequestFreeInputInfo got input %1 (%2/%3)")
160  .arg(info.m_inputId).arg(info.m_chanId).arg(info.m_mplexId));
161  }
162 
163  LOG(VB_CHANNEL, LOG_INFO,
164  QString("RemoteRequestFreeInputInfo got %1 inputs")
165  .arg(inputs.size()));
166  return inputs;
167 }
168 
170 {
171  LOG(VB_CHANNEL, LOG_INFO, QString("RemoteGetFreeRecorderCount"));
172 
173  std::vector<InputInfo> inputs =
175 
176  LOG(VB_CHANNEL, LOG_INFO, QString("RemoteGetFreeRecorderCount got %1")
177  .arg(inputs.size()));
178  return inputs.size();
179 }
180 
182 {
183  LOG(VB_CHANNEL, LOG_INFO,
184  QString("RemoteRequestNextFreeRecorder after input %1)")
185  .arg(inputid));
186 
187  std::vector<InputInfo> inputs =
189 
190  if (inputs.empty())
191  {
192  LOG(VB_CHANNEL, LOG_INFO,
193  QString("RemoteRequestNextFreeRecorder got no input (after input %1)")
194  .arg(inputid));
195  return nullptr;
196  }
197 
198  size_t i = 0;
199  for ( ; i < inputs.size(); ++i)
200  if (inputs[i].m_inputId == (uint)inputid)
201  break;
202 
203  if (i >= inputs.size())
204  {
205  // We should always find the referenced input. If we don't,
206  // just return the first one.
207  i = 0;
208  }
209  else
210  {
211  // Try to find the next input with a different name. If one
212  // doesn't exist, just return the current one.
213  size_t j = i;
214  do
215  {
216  i = (i + 1) % inputs.size();
217  }
218  while (i != j && inputs[i].m_displayName == inputs[j].m_displayName);
219  }
220 
221  LOG(VB_CHANNEL, LOG_INFO,
222  QString("RemoteRequestNextFreeRecorder got input %1")
223  .arg(inputs[i].m_inputId));
224 
225  return RemoteGetExistingRecorder(inputs[i].m_inputId);
226 }
227 
228 std::vector<uint> RemoteRequestFreeRecorderList(uint excluded_input)
229 {
230  LOG(VB_CHANNEL, LOG_INFO,
231  QString("RemoteRequestFreeRecorderList excluding input %1")
232  .arg(excluded_input));
233 
234  std::vector<InputInfo> inputs =
235  RemoteRequestFreeInputInfo(excluded_input);
236 
237  std::vector<uint> inputids;
238  std::transform(inputs.cbegin(), inputs.cend(), std::back_inserter(inputids),
239  [](const auto & input){ return input.m_inputId; } );
240 
241  LOG(VB_CHANNEL, LOG_INFO,
242  QString("RemoteRequestFreeRecorderList got inputs"));
243  return inputids;
244 }
245 
246 std::vector<uint> RemoteRequestFreeInputList(uint excluded_input)
247 {
248  LOG(VB_CHANNEL, LOG_INFO,
249  QString("RemoteRequestFreeInputList excluding input %1")
250  .arg(excluded_input));
251 
252  std::vector<InputInfo> inputs =
253  RemoteRequestFreeInputInfo(excluded_input);
254 
255  std::vector<uint> inputids;
256  std::transform(inputs.cbegin(), inputs.cend(), std::back_inserter(inputids),
257  [](const auto & input){ return input.m_inputId; } );
258 
259  LOG(VB_CHANNEL, LOG_INFO,
260  QString("RemoteRequestFreeInputList got inputs"));
261  return inputids;
262 }
263 
265 (const QStringList &qualifiedRecorders, uint excluded_input)
266 {
267  LOG(VB_CHANNEL, LOG_INFO,
268  QString("RemoteRequestFreeRecorderFromList excluding input %1")
269  .arg(excluded_input));
270 
271  std::vector<InputInfo> inputs =
272  RemoteRequestFreeInputInfo(excluded_input);
273 
274  for (const auto & recorder : std::as_const(qualifiedRecorders))
275  {
276  uint inputid = recorder.toUInt();
277  auto sameinput = [inputid](const auto & input){ return input.m_inputId == inputid; };
278  if (std::any_of(inputs.cbegin(), inputs.cend(), sameinput))
279  {
280  LOG(VB_CHANNEL, LOG_INFO,
281  QString("RemoteRequestFreeRecorderFromList got input %1")
282  .arg(inputid));
283  return RemoteGetExistingRecorder(inputid);
284  }
285  }
286 
287  LOG(VB_CHANNEL, LOG_INFO,
288  QString("RemoteRequestFreeRecorderFromList got no input"));
289  return nullptr;
290 }
291 
293 {
294  LOG(VB_CHANNEL, LOG_INFO,
295  QString("RemoteRequestRecorder entered"));
296 
297  std::vector<InputInfo> inputs =
299 
300  if (inputs.empty())
301  {
302  LOG(VB_CHANNEL, LOG_INFO,
303  QString("RemoteRequestRecorder got no input"));
304  return nullptr;
305  }
306 
307  LOG(VB_CHANNEL, LOG_INFO,
308  QString("RemoteRequestRecorder got input %1")
309  .arg(inputs[0].m_inputId));
310  return RemoteGetExistingRecorder(inputs[0].m_inputId);
311 }
312 
314 {
315  LOG(VB_CHANNEL, LOG_INFO,
316  QString("RemoteGetExistingRecorder program %1")
317  .arg(pginfo->GetTitle()));
318 
319  QStringList strlist( "GET_RECORDER_NUM" );
320  pginfo->ToStringList(strlist);
321 
322  if (!gCoreContext->SendReceiveStringList(strlist))
323  {
324  LOG(VB_CHANNEL, LOG_INFO,
325  QString("RemoteGetExistingRecorder got no input"));
326  return nullptr;
327  }
328 
329  int num = strlist[0].toInt();
330  QString hostname = strlist[1];
331  int port = strlist[2].toInt();
332 
333  LOG(VB_CHANNEL, LOG_INFO,
334  QString("RemoteGetExistingRecorder got input %1").arg(num));
335  return new RemoteEncoder(num, hostname, port);
336 }
337 
339 {
340  LOG(VB_CHANNEL, LOG_INFO,
341  QString("RemoteGetExistingRecorder input %1")
342  .arg(recordernum));
343 
344  QStringList strlist( "GET_RECORDER_FROM_NUM" );
345  strlist << QString("%1").arg(recordernum);
346 
347  if (!gCoreContext->SendReceiveStringList(strlist))
348  {
349  LOG(VB_CHANNEL, LOG_INFO,
350  QString("RemoteGetExistingRecorder got no input"));
351  return nullptr;
352  }
353 
354  QString hostname = strlist[0];
355  int port = strlist[1].toInt();
356 
357  LOG(VB_CHANNEL, LOG_INFO,
358  QString("RemoteGetExistingRecorder got input %1")
359  .arg(recordernum));
360  return new RemoteEncoder(recordernum, hostname, port);
361 }
362 
363 bool RemoteIsBusy(uint inputid, InputInfo &busy_input)
364 {
365 #if 0
366  LOG(VB_GENERAL, LOG_DEBUG, QString("RemoteIsBusy(%1) %2")
367  .arg(inputid).arg(gCoreContext->IsBackend() ? "be" : "fe"));
368 #endif
369 
370  busy_input.Clear();
371 
372  if (gCoreContext->IsBackend())
373  {
374  const TVRec *rec = TVRec::GetTVRec(inputid);
375  if (rec)
376  return rec->IsBusy(&busy_input);
377 
378  // Note this value is intentionally different than the
379  // non-backend, error value below. There is a small
380  // window when adding an input where an input can exist in
381  // the database, but not yet have a TVRec. In such cases,
382  // we don't want it to be considered busy and block other
383  // actions.
384  return false;
385  }
386 
387  QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(inputid));
388  strlist << "IS_BUSY";
389  if (!gCoreContext->SendReceiveStringList(strlist) || strlist.empty())
390  return true;
391 
392  QStringList::const_iterator it = strlist.cbegin();
393  bool state = (*it).toInt() != 0;
394  ++it;
395  if (!busy_input.FromStringList(it, strlist.cend()))
396  state = true; // if there was an error pretend that the input is busy.
397 
398  return state;
399 }
400 
402  std::vector<TunerStatus> *tunerList, bool list_inactive)
403 {
404  bool isRecording = false;
405  std::vector<uint> inputlist = CardUtil::GetInputList();
406 
407  if (tunerList)
408  tunerList->clear();
409 
410  for (uint inputid : inputlist)
411  {
412  int state = kState_ChangingState;
413  QString channelName = "";
414  QString title = "";
415  QString subtitle = "";
416  QDateTime dtStart = QDateTime();
417  QDateTime dtEnd = QDateTime();
418  QStringList strlist;
419 
420  QString cmd = QString("QUERY_REMOTEENCODER %1").arg(inputid);
421 
422  while (state == kState_ChangingState)
423  {
424  strlist = QStringList(cmd);
425  strlist << "GET_STATE";
427 
428  if (strlist.empty())
429  break;
430 
431  state = strlist[0].toInt();
432  if (kState_ChangingState == state)
433  std::this_thread::sleep_for(5ms);
434  }
435 
436  if (kState_RecordingOnly == state || kState_WatchingRecording == state)
437  {
438  isRecording = true;
439 
440  if (!tunerList)
441  break;
442 
443  strlist = QStringList(QString("QUERY_RECORDER %1").arg(inputid));
444  strlist << "GET_RECORDING";
446 
447  ProgramInfo progInfo(strlist);
448 
449  title = progInfo.GetTitle();
450  subtitle = progInfo.GetSubtitle();
451  channelName = progInfo.GetChannelName();
452  dtStart = progInfo.GetScheduledStartTime();
453  dtEnd = progInfo.GetScheduledEndTime();
454  }
455  else if (!list_inactive)
456  {
457  continue;
458  }
459 
460  if (tunerList)
461  {
462  TunerStatus tuner;
463  tuner.id = inputid;
464  tuner.isRecording = ((kState_RecordingOnly == state) ||
465  (kState_WatchingRecording == state));
466  tuner.channame = channelName;
467  tuner.title = (kState_ChangingState == state) ?
468  QObject::tr("Error querying recorder state") : title;
469  tuner.subtitle = subtitle;
470  tuner.startTime = dtStart;
471  tuner.endTime = dtEnd;
472  tunerList->push_back(tuner);
473  }
474  }
475 
476  return isRecording;
477 }
478 
479 /* vim: set expandtab tabstop=4 shiftwidth=4: */
TVRec::RecordPending
void RecordPending(const ProgramInfo *rcinfo, std::chrono::seconds secsleft, bool hasLater)
Tells TVRec "rcinfo" is the next pending recording.
Definition: tv_rec.cpp:312
RemoteGetExistingRecorder
RemoteEncoder * RemoteGetExistingRecorder(const ProgramInfo *pginfo)
Definition: tvremoteutil.cpp:313
RemoteRequestRecorder
RemoteEncoder * RemoteRequestRecorder(void)
Definition: tvremoteutil.cpp:292
MythCoreContext::SendReceiveStringList
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
Send a message to the backend and wait for a response.
Definition: mythcorecontext.cpp:1381
RemoteGetState
uint RemoteGetState(uint inputid)
Definition: tvremoteutil.cpp:32
TunerStatus::title
QString title
Definition: tvremoteutil.h:22
TVRec::IsBusy
bool IsBusy(InputInfo *busy_input=nullptr, std::chrono::seconds time_buffer=5s) const
Returns true if the recorder is busy, or will be within the next time_buffer seconds.
Definition: tv_rec.cpp:2541
ProgramInfo::GetChannelName
QString GetChannelName(void) const
This is the channel name in the local market, i.e.
Definition: programinfo.h:387
RemoteGetFreeRecorderCount
int RemoteGetFreeRecorderCount(void)
Definition: tvremoteutil.cpp:169
TVRec::StopRecording
void StopRecording(bool killFile=false)
Changes from a recording state to kState_None.
Definition: tv_rec.cpp:748
TunerStatus::endTime
QDateTime endTime
Definition: tvremoteutil.h:25
ProgramInfo::GetScheduledEndTime
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:398
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
RemoteGetFlags
uint RemoteGetFlags(uint inputid)
Definition: tvremoteutil.cpp:14
RemoteStopLiveTV
bool RemoteStopLiveTV(uint inputid)
Definition: tvremoteutil.cpp:77
RemoteEncoder
Definition: remoteencoder.h:24
TunerStatus::channame
QString channame
Definition: tvremoteutil.h:21
TunerStatus
recording status stuff
Definition: tvremoteutil.h:16
programinfo.h
RemoteRequestFreeInputList
std::vector< uint > RemoteRequestFreeInputList(uint excluded_input)
Definition: tvremoteutil.cpp:246
ProgramInfo::GetScheduledStartTime
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:391
mythlogging.h
CardUtil::GetInputList
static std::vector< uint > GetInputList(void)
Definition: cardutil.cpp:2901
RemoteStopRecording
bool RemoteStopRecording(uint inputid)
Definition: tvremoteutil.cpp:99
RemoteRequestFreeInputInfo
std::vector< InputInfo > RemoteRequestFreeInputInfo(uint excluded_input)
Definition: tvremoteutil.cpp:138
RemoteIsBusy
bool RemoteIsBusy(uint inputid, InputInfo &busy_input)
Definition: tvremoteutil.cpp:363
ProgramInfo::GetTitle
QString GetTitle(void) const
Definition: programinfo.h:362
isRecording
static bool isRecording()
Definition: mythshutdown.cpp:228
recorder
RemoteEncoder * recorder
Definition: mythcommflag.cpp:67
kState_ChangingState
@ kState_ChangingState
This is a placeholder state which we never actually enter, but is returned by GetState() when we are ...
Definition: tv.h:92
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
InputInfo::Clear
virtual void Clear(void)
Definition: inputinfo.cpp:6
kState_WatchingRecording
@ kState_WatchingRecording
Watching Recording is the state for when we are watching an in progress recording,...
Definition: tv.h:83
tvremoteutil.h
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
RemoteGetRecordingStatus
bool RemoteGetRecordingStatus(std::vector< TunerStatus > *tunerList, bool list_inactive)
Definition: tvremoteutil.cpp:401
ProgramInfo::ToStringList
void ToStringList(QStringList &list) const
Serializes ProgramInfo into a QStringList which can be passed over a socket.
Definition: programinfo.cpp:1276
mythcorecontext.h
MythCoreContext::IsBackend
bool IsBackend(void) const
is this process a backend process
Definition: mythcorecontext.cpp:650
cardutil.h
RemoteRequestFreeRecorderFromList
RemoteEncoder * RemoteRequestFreeRecorderFromList(const QStringList &qualifiedRecorders, uint excluded_input)
Definition: tvremoteutil.cpp:265
TVRec
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:142
TunerStatus::id
uint id
Definition: tvremoteutil.h:19
TVRec::GetState
TVState GetState(void) const
Returns the TVState of the recorder.
Definition: tv_rec.cpp:264
tv_rec.h
RemoteCancelNextRecording
void RemoteCancelNextRecording(uint inputid, bool cancel)
Definition: tvremoteutil.cpp:129
RemoteRecordPending
bool RemoteRecordPending(uint inputid, const ProgramInfo *pginfo, std::chrono::seconds secsleft, bool hasLater)
Definition: tvremoteutil.cpp:51
inputinfo.h
InputInfo
Definition: inputinfo.h:14
TunerStatus::startTime
QDateTime startTime
Definition: tvremoteutil.h:24
remoteencoder.h
kState_RecordingOnly
@ kState_RecordingOnly
Recording Only is a TVRec only state for when we are recording a program, but there is no one current...
Definition: tv.h:87
TVRec::GetFlags
uint GetFlags(void) const
Definition: tv_rec.h:245
azlyrics.info
dictionary info
Definition: azlyrics.py:7
musicbrainzngs.caa.hostname
string hostname
Definition: caa.py:17
RemoteRequestFreeRecorderList
std::vector< uint > RemoteRequestFreeRecorderList(uint excluded_input)
Definition: tvremoteutil.cpp:228
TunerStatus::isRecording
bool isRecording
Definition: tvremoteutil.h:20
TVRec::StopLiveTV
void StopLiveTV(void)
Tells TVRec to stop a "Live TV" recorder.
Definition: tv_rec.cpp:2934
TunerStatus::subtitle
QString subtitle
Definition: tvremoteutil.h:23
TVRec::GetTVRec
static TVRec * GetTVRec(uint inputid)
Definition: tv_rec.cpp:4896
uint
unsigned int uint
Definition: freesurround.h:24
RemoteRequestNextFreeRecorder
RemoteEncoder * RemoteRequestNextFreeRecorder(int inputid)
Definition: tvremoteutil.cpp:181
ProgramInfo::GetSubtitle
QString GetSubtitle(void) const
Definition: programinfo.h:364
InputInfo::FromStringList
virtual bool FromStringList(QStringList::const_iterator &it, const QStringList::const_iterator &end)
Definition: inputinfo.cpp:14