MythTV  master
v2dvr.cpp
Go to the documentation of this file.
1 // Program Name: v2dvr.cpp
3 // Created : Mar. 7, 2011
4 //
5 // Copyright (c) 2011 David Blain <dblain@mythtv.org>
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //
25 
26 // MythTV
30 #include "libmythbase/mythversion.h"
33 #include "libmythtv/cardutil.h"
34 #include "libmythtv/channelutil.h"
35 #include "libmythtv/jobqueue.h"
36 #include "libmythtv/playgroup.h"
37 #include "libmythtv/programdata.h"
38 #include "libmythtv/tv_rec.h"
39 
40 // MythBackend
41 #include "autoexpire.h"
42 #include "backendcontext.h"
43 #include "encoderlink.h"
44 #include "scheduler.h"
45 #include "v2dvr.h"
46 #include "v2serviceUtil.h"
47 #include "v2titleInfoList.h"
48 
49 // This will be initialised in a thread safe manner on first use
51  (DVR_HANDLE, V2Dvr::staticMetaObject, &V2Dvr::RegisterCustomTypes))
52 
54 {
55  qRegisterMetaType<V2ProgramList*>("V2ProgramList");
56  qRegisterMetaType<V2Program*>("V2Program");
57  qRegisterMetaType<V2CutList*>("V2CutList");
58  qRegisterMetaType<V2Cutting*>("V2Cutting");
59  qRegisterMetaType<V2MarkupList*>("V2MarkupList");
60  qRegisterMetaType<V2Markup*>("V2Markup");
61  qRegisterMetaType<V2EncoderList*>("V2EncoderList");
62  qRegisterMetaType<V2Encoder*>("V2Encoder");
63  qRegisterMetaType<V2InputList*>("V2InputList");
64  qRegisterMetaType<V2Input*>("V2Input");
65  qRegisterMetaType<V2RecRuleFilterList*>("V2RecRuleFilterList");
66  qRegisterMetaType<V2RecRuleFilter*>("V2RecRuleFilter");
67  qRegisterMetaType<V2TitleInfoList*>("V2TitleInfoList");
68  qRegisterMetaType<V2TitleInfo*>("V2TitleInfo");
69  qRegisterMetaType<V2RecRule*>("V2RecRule");
70  qRegisterMetaType<V2RecRuleList*>("V2RecRuleList");
71  qRegisterMetaType<V2ChannelInfo*>("V2ChannelInfo");
72  qRegisterMetaType<V2RecordingInfo*>("V2RecordingInfo");
73  qRegisterMetaType<V2ArtworkInfoList*>("V2ArtworkInfoList");
74  qRegisterMetaType<V2ArtworkInfo*>("V2ArtworkInfo");
75  qRegisterMetaType<V2CastMemberList*>("V2CastMemberList");
76  qRegisterMetaType<V2CastMember*>("V2CastMember");
77 }
78 
80  : MythHTTPService(s_service)
81 {
82 }
83 
85  int nCount )
86 {
87  pginfolist_t infoList;
88 
89  if (gExpirer)
90  gExpirer->GetAllExpiring( infoList );
91 
92  // ----------------------------------------------------------------------
93  // Build Response
94  // ----------------------------------------------------------------------
95 
96  auto *pPrograms = new V2ProgramList();
97 
98  nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (int)infoList.size() ) : 0;
99  nCount = (nCount > 0) ? std::min( nCount, (int)infoList.size() ) : infoList.size();
100  int nEndIndex = std::min((nStartIndex + nCount), (int)infoList.size() );
101 
102  for( int n = nStartIndex; n < nEndIndex; n++)
103  {
104  ProgramInfo *pInfo = infoList[ n ];
105 
106  if (pInfo != nullptr)
107  {
108  V2Program *pProgram = pPrograms->AddNewProgram();
109 
110  V2FillProgramInfo( pProgram, pInfo, true );
111 
112  delete pInfo;
113  }
114  }
115 
116  // ----------------------------------------------------------------------
117 
118  pPrograms->setStartIndex ( nStartIndex );
119  pPrograms->setCount ( nCount );
120  pPrograms->setTotalAvailable( infoList.size() );
121  pPrograms->setAsOf ( MythDate::current() );
122  pPrograms->setVersion ( MYTH_BINARY_VERSION );
123  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
124 
125  return pPrograms;
126 }
127 
129  int nStartIndex,
130  int nCount,
131  const QString &sTitleRegEx,
132  const QString &sRecGroup,
133  const QString &sStorageGroup,
134  const QString &sCategory,
135  const QString &sSort,
136  bool bIgnoreLiveTV,
137  bool bIgnoreDeleted,
138  bool bIncChannel,
139  bool bDetails,
140  bool bIncCast,
141  bool bIncArtWork,
142  bool bIncRecording
143  )
144 {
145  if (!HAS_PARAMv2("IncChannel"))
146  bIncChannel = true;
147 
148  if (!HAS_PARAMv2("Details"))
149  bDetails = true;
150 
151  if (!HAS_PARAMv2("IncCast"))
152  bIncCast = true;
153 
154  if (!HAS_PARAMv2("IncArtwork"))
155  bIncArtWork = true;
156 
157  if (!HAS_PARAMv2("IncRecording"))
158  bIncRecording = true;
159 
160  QMap< QString, ProgramInfo* > recMap;
161 
162  if (gCoreContext->GetScheduler())
163  recMap = gCoreContext->GetScheduler()->GetRecording();
164 
165  QMap< QString, uint32_t > inUseMap = ProgramInfo::QueryInUseMap();
166  QMap< QString, bool > isJobRunning= ProgramInfo::QueryJobsRunning(JOB_COMMFLAG);
167 
168  ProgramList progList;
169 
170  int desc = 1;
171  if (bDescending)
172  desc = -1;
173 
174  if (bIgnoreLiveTV && (sRecGroup == "LiveTV"))
175  {
176  bIgnoreLiveTV = false;
177  LOG(VB_GENERAL, LOG_ERR, QString("Setting Ignore%1=false because RecGroup=%1")
178  .arg(sRecGroup));
179  }
180 
181  if (bIgnoreDeleted && (sRecGroup == "Deleted"))
182  {
183  bIgnoreDeleted = false;
184  LOG(VB_GENERAL, LOG_ERR, QString("Setting Ignore%1=false because RecGroup=%1")
185  .arg(sRecGroup));
186  }
187 
188  LoadFromRecorded( progList, false, inUseMap, isJobRunning, recMap, desc,
189  sSort, bIgnoreLiveTV, bIgnoreDeleted );
190 
191  QMap< QString, ProgramInfo* >::iterator mit = recMap.begin();
192 
193  for (; mit != recMap.end(); mit = recMap.erase(mit))
194  delete *mit;
195 
196  // ----------------------------------------------------------------------
197  // Build Response
198  // ----------------------------------------------------------------------
199 
200  auto *pPrograms = new V2ProgramList();
201 
202  int nAvailable = 0;
203 
204  int nMax = (nCount > 0) ? nCount : progList.size();
205 
206  nAvailable = 0;
207  nCount = 0;
208 
209  QRegularExpression rTitleRegEx
210  { sTitleRegEx, QRegularExpression::CaseInsensitiveOption };
211 
212  for (auto *pInfo : progList)
213  {
214  if (pInfo->IsDeletePending() ||
215  (!sTitleRegEx.isEmpty() && !pInfo->GetTitle().contains(rTitleRegEx)) ||
216  (!sRecGroup.isEmpty() && sRecGroup != pInfo->GetRecordingGroup()) ||
217  (!sStorageGroup.isEmpty() && sStorageGroup != pInfo->GetStorageGroup()) ||
218  (!sCategory.isEmpty() && sCategory != pInfo->GetCategory()))
219  continue;
220 
221  if ((nAvailable < nStartIndex) ||
222  (nCount >= nMax))
223  {
224  ++nAvailable;
225  continue;
226  }
227 
228  ++nAvailable;
229  ++nCount;
230 
231  V2Program *pProgram = pPrograms->AddNewProgram();
232  V2FillProgramInfo( pProgram, pInfo, bIncChannel, bDetails, bIncCast, bIncArtWork, bIncRecording );
233  }
234 
235  // ----------------------------------------------------------------------
236 
237  pPrograms->setStartIndex ( nStartIndex );
238  pPrograms->setCount ( nCount );
239  pPrograms->setTotalAvailable( nAvailable );
240  pPrograms->setAsOf ( MythDate::current() );
241  pPrograms->setVersion ( MYTH_BINARY_VERSION );
242  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
243 
244  return pPrograms;
245 }
246 
248 //
250 
252  int nStartIndex,
253  int nCount,
254  const QDateTime &sStartTime,
255  const QDateTime &sEndTime,
256  const QString &sTitle,
257  const QString &sSeriesId,
258  int nRecordId,
259  const QString &sSort)
260 {
261  if (!sStartTime.isNull() && !sStartTime.isValid())
262  throw QString("StartTime is invalid");
263 
264  if (!sEndTime.isNull() && !sEndTime.isValid())
265  throw QString("EndTime is invalid");
266 
267  const QDateTime& dtStartTime = sStartTime;
268  const QDateTime& dtEndTime = sEndTime;
269 
270  if (!sEndTime.isNull() && dtEndTime < dtStartTime)
271  throw QString("EndTime is before StartTime");
272 
273  // ----------------------------------------------------------------------
274  // Build SQL statement for Program Listing
275  // ----------------------------------------------------------------------
276 
277  ProgramList progList;
278  MSqlBindings bindings;
279  QString sSQL;
280 
281  if (!dtStartTime.isNull())
282  {
283  sSQL += " AND endtime >= :StartDate ";
284  bindings[":StartDate"] = dtStartTime;
285  }
286 
287  if (!dtEndTime.isNull())
288  {
289  sSQL += " AND starttime <= :EndDate ";
290  bindings[":EndDate"] = dtEndTime;
291  }
292 
293  QStringList clause;
294 
295  if (nRecordId > 0)
296  {
297  clause << "recordid = :RecordId";
298  bindings[":RecordId"] = nRecordId;
299  }
300 
301  if (!sTitle.isEmpty())
302  {
303  clause << "title = :Title";
304  bindings[":Title"] = sTitle;
305  }
306 
307  if (!sSeriesId.isEmpty())
308  {
309  clause << "seriesid = :SeriesId";
310  bindings[":SeriesId"] = sSeriesId;
311  }
312 
313  if (!clause.isEmpty())
314  {
315  sSQL += QString(" AND (%1) ").arg(clause.join(" OR "));
316  }
317 
318  if (sSort == "starttime")
319  sSQL += "ORDER BY starttime "; // NOLINT(bugprone-branch-clone)
320  else if (sSort == "title")
321  sSQL += "ORDER BY title ";
322  else
323  sSQL += "ORDER BY starttime ";
324 
325  if (bDescending)
326  sSQL += "DESC ";
327  else
328  sSQL += "ASC ";
329 
330  uint nTotalAvailable = (nStartIndex == 0) ? 1 : 0;
331  LoadFromOldRecorded( progList, sSQL, bindings,
332  (uint)nStartIndex, (uint)nCount, nTotalAvailable );
333 
334  // ----------------------------------------------------------------------
335  // Build Response
336  // ----------------------------------------------------------------------
337 
338  auto *pPrograms = new V2ProgramList();
339 
340  nCount = (int)progList.size();
341  int nEndIndex = (int)progList.size();
342 
343  for( int n = 0; n < nEndIndex; n++)
344  {
345  ProgramInfo *pInfo = progList[ n ];
346 
347  V2Program *pProgram = pPrograms->AddNewProgram();
348 
349  V2FillProgramInfo( pProgram, pInfo, true );
350  }
351 
352  // ----------------------------------------------------------------------
353 
354  pPrograms->setStartIndex ( nStartIndex );
355  pPrograms->setCount ( nCount );
356  pPrograms->setTotalAvailable( nTotalAvailable );
357  pPrograms->setAsOf ( MythDate::current() );
358  pPrograms->setVersion ( MYTH_BINARY_VERSION );
359  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
360 
361  return pPrograms;
362 }
363 
365 //
367 
369  int chanid, const QDateTime &StartTime)
370 {
371  if ((RecordedId <= 0) &&
372  (chanid <= 0 || !StartTime.isValid()))
373  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
374 
375  // TODO Should use RecordingInfo
376  ProgramInfo pi;
377  if (RecordedId > 0)
378  pi = ProgramInfo(RecordedId);
379  else
380  pi = ProgramInfo(chanid, StartTime.toUTC());
381 
382  auto *pProgram = new V2Program();
383  V2FillProgramInfo( pProgram, &pi, true );
384 
385  return pProgram;
386 }
387 
389 //
391 
392 bool V2Dvr::AddRecordedCredits(int RecordedId, const QString & Cast)
393 {
394  QJsonDocument jsonDoc = QJsonDocument::fromJson(Cast.toUtf8());
395  // Verify the corresponding recording exists
396  RecordingInfo ri(RecordedId);
397  if (!ri.HasPathname())
398  throw QString("AddRecordedCredits: recordedid %1 does "
399  "not exist.").arg(RecordedId);
400 
401  DBCredits* credits = V2jsonCastToCredits(jsonDoc.object());
402  if (credits == nullptr)
403  throw QString("AddRecordedCredits: Failed to parse cast from json.");
404 
405  MSqlQuery query(MSqlQuery::InitCon());
406  for (auto & person : *credits)
407  {
408  if (!person.InsertDB(query, ri.GetChanID(),
409  ri.GetScheduledStartTime(), true))
410  throw QString("AddRecordedCredits: Failed to add credit "
411  "%1 to DB").arg(person.toString());
412  }
413 
414  return true;
415 }
416 
418 //
420 
421 int V2Dvr::AddRecordedProgram(const QString &Program)
422 {
423  QJsonDocument doc = QJsonDocument::fromJson(Program.toUtf8());
424  QJsonObject program = doc.object();
425  QJsonObject channel = program["Channel"].toObject();
426  QJsonObject recording = program["Recording"].toObject();
427  QJsonObject cast = program["Cast"].toObject();
428 
429  auto *pi = new ProgInfo();
430  int chanid = channel.value("ChanId").toVariant().toString().toUInt();
431 
432  QString hostname = program["HostName"].toString("");
433 
434  if (ChannelUtil::GetChanNum(chanid).isEmpty())
435  throw QString("AddRecordedProgram: chanid %1 does "
436  "not exist.").arg(chanid);
437 
438  pi->m_title = program.value("Title").toString("");
439  pi->m_subtitle = program.value("SubTitle").toString("");
440  pi->m_description = program.value("Description").toString("");
441  pi->m_category = program.value("Category").toString("");
442  pi->m_starttime = QDateTime::fromString(program.value("StartTime")
443  .toString(""), Qt::ISODate);
444  pi->m_endtime = QDateTime::fromString(program.value("EndTime")
445  .toString(""), Qt::ISODate);
446  pi->m_originalairdate = QDate::fromString(program.value("Airdate").toString(),
447  Qt::ISODate);
448  pi->m_airdate = pi->m_originalairdate.year();
449  pi->m_partnumber = program.value("PartNumber").toString("0").toUInt();
450  pi->m_parttotal = program.value("PartTotal").toString("0").toUInt();
451  pi->m_syndicatedepisodenumber = "";
452  pi->m_subtitleType = ProgramInfo::SubtitleTypesFromNames
453  (program.value("SubPropNames").toString(""));
454  pi->m_audioProps = ProgramInfo::AudioPropertiesFromNames
455  (program.value("AudioPropNames").toString(""));
456  pi->m_videoProps = ProgramInfo::VideoPropertiesFromNames
457  (program.value("VideoPropNames").toString(""));
458  pi->m_stars = program.value("Stars").toVariant().toString().toFloat();
459  pi->m_categoryType = string_to_myth_category_type(program.value("CatType").toString(""));
460  pi->m_seriesId = program.value("SeriesId").toString("");
461  pi->m_programId = program.value("ProgramId").toString("");
462  pi->m_inetref = program.value("Inetref").toString("");
463  pi->m_previouslyshown = false;
464  pi->m_listingsource = 0;
465 // pi->m_ratings =
466 // pi->m_genres =
467  pi->m_season = program.value("Season").toVariant()
468  .toString().toUInt();
469  pi->m_episode = program.value("Episode").toVariant()
470  .toString().toUInt();
471  pi->m_totalepisodes = program.value("TotalEpisodes").toVariant()
472  .toString().toUInt();
473 
474  pi->m_channel = channel.value("ChannelName").toString("");
475 
476  pi->m_startts = recording.value("StartTs").toString("");
477  pi->m_endts = recording.value("EndTs").toString("");
478  QDateTime recstartts = QDateTime::fromString(pi->m_startts, Qt::ISODate);
479  QDateTime recendts = QDateTime::fromString(pi->m_endts, Qt::ISODate);
480 
481  pi->m_title_pronounce = "";
482  pi->m_credits = V2jsonCastToCredits(cast);
483  pi->m_showtype = "";
484  pi->m_colorcode = "";
485  pi->m_clumpidx = "";
486  pi->m_clumpmax = "";
487 
488  // pi->m_ratings =
489 
490  /* Create a recordedprogram DB entry. */
491  MSqlQuery query(MSqlQuery::InitCon());
492  if (!pi->InsertDB(query, chanid, true))
493  {
494  throw QString("AddRecordedProgram: "
495  "Failed to add recordedprogram entry.");
496  }
497 
498  /* Create recorded DB entry */
499  RecordingInfo ri(pi->m_title, pi->m_title,
500  pi->m_subtitle, pi->m_subtitle,
501  pi->m_description,
502  pi->m_season, pi->m_episode,
503  pi->m_totalepisodes,
504  pi->m_syndicatedepisodenumber,
505  pi->m_category,
506  chanid,
507  channel.value("ChanNum").toString("0"),
508  channel.value("CallSign").toString(""),
509  pi->m_channel,
510  recording.value("RecGroup").toString(""),
511  recording.value("PlayGroup").toString(""),
512  hostname,
513  recording.value("StorageGroup").toString(""),
514  pi->m_airdate,
515  pi->m_partnumber,
516  pi->m_parttotal,
517  pi->m_seriesId,
518  pi->m_programId,
519  pi->m_inetref,
520  pi->m_categoryType,
521  recording.value("Priority").toString("0").toInt(),
522  pi->m_starttime,
523  pi->m_endtime,
524  recstartts,
525  recendts,
526  pi->m_stars,
527  pi->m_originalairdate,
528  program.value("Repeat").toString("false").toLower() == "true",
529  static_cast<RecStatus::Type>(recording.value("Status").toInt()),
530  false, // reactivate
531  recording.value("RecordedId").toString("0").toInt(),
532  0, // parentid
533  static_cast<RecordingType>(recording.value("RecType").toInt()),
534  static_cast<RecordingDupInType>(recording.value("DupInType").toInt()),
535  static_cast<RecordingDupMethodType>(recording.value("DupMethod").toInt()),
536  channel.value("SourceId").toVariant().toString().toUInt(),
537  channel.value("InputId").toVariant().toString().toUInt(),
538  0, // findid
539  channel.value("CommFree").toBool(),
540  pi->m_subtitleType,
541  pi->m_videoProps,
542  pi->m_audioProps,
543  false, // future
544  0, // schedorder
545  0, // mplexid
546  0, // sgroupid,
547  recording.value("EncoderName").toString(""));
548 
549  ri.ProgramFlagsFromNames(program.value("ProgramFlagNames").toString(""));
550 
551  QString filename = program.value("FileName").toString("");
552  QString ext("");
553  int idx = filename.lastIndexOf('.');
554  if (idx > 0)
555  ext = filename.right(filename.size() - idx - 1);
556  // Inserts this RecordingInfo into the database as an existing recording
557  if (!ri.InsertRecording(ext, true))
558  throw QString("Failed to create RecordingInfo database entry. "
559  "Non unique starttime?");
560 
561  ri.InsertFile();
562 
565  ri.SavePreserve(ri.IsPreserved());
568  ri.SaveWatched(ri.IsWatched());
569  // TODO: Cutlist
570 
572  ri.SendUpdateEvent();
573 
574  return ri.GetRecordingID();
575 }
576 
578 //
580 
581 bool V2Dvr::RemoveRecorded(int RecordedId,
582  int chanid, const QDateTime &StartTime,
583  bool forceDelete, bool allowRerecord)
584 {
585  return DeleteRecording(RecordedId, chanid, StartTime, forceDelete,
586  allowRerecord);
587 }
588 
589 
590 bool V2Dvr::DeleteRecording(int RecordedId,
591  int chanid, const QDateTime &StartTime,
592  bool forceDelete, bool allowRerecord)
593 {
594  if ((RecordedId <= 0) &&
595  (chanid <= 0 || !StartTime.isValid()))
596  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
597 
598  // TODO Should use RecordingInfo
599  ProgramInfo pi;
600  if (RecordedId > 0)
601  pi = ProgramInfo(RecordedId);
602  else
603  pi = ProgramInfo(chanid, StartTime.toUTC());
604 
605  if (pi.GetChanID() && pi.HasPathname())
606  {
607  QString cmd = QString("DELETE_RECORDING %1 %2 %3 %4")
608  .arg(QString::number(pi.GetChanID()),
610  forceDelete ? "FORCE" : "NO_FORCE",
611  allowRerecord ? "FORGET" : "NO_FORGET");
612  MythEvent me(cmd);
613 
614  gCoreContext->dispatch(me);
615  return true;
616  }
617 
618  return false;
619 }
620 
622 //
624 
625 bool V2Dvr::UnDeleteRecording(int RecordedId,
626  int chanid, const QDateTime &StartTime)
627 {
628  if ((RecordedId <= 0) &&
629  (chanid <= 0 || !StartTime.isValid()))
630  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
631 
632  RecordingInfo ri;
633  if (RecordedId > 0)
634  ri = RecordingInfo(RecordedId);
635  else
636  ri = RecordingInfo(chanid, StartTime.toUTC());
637 
638  if (ri.GetChanID() && ri.HasPathname())
639  {
640  QString cmd = QString("UNDELETE_RECORDING %1 %2")
641  .arg(ri.GetChanID())
643  MythEvent me(cmd);
644 
645  gCoreContext->dispatch(me);
646  return true;
647  }
648 
649  return false;
650 }
651 
653 //
655 
656 bool V2Dvr::StopRecording(int RecordedId)
657 {
658  if (RecordedId <= 0)
659  throw QString("RecordedId param is invalid.");
660 
661  RecordingInfo ri = RecordingInfo(RecordedId);
662 
663  if (ri.GetChanID())
664  {
665  QString cmd = QString("STOP_RECORDING %1 %2")
666  .arg(ri.GetChanID())
668  MythEvent me(cmd);
669 
670  gCoreContext->dispatch(me);
671  return true;
672  }
673  throw QString("RecordedId %1 not found").arg(RecordedId);
674 
675  return false;
676 }
677 
679 //
681 
682 bool V2Dvr::ReactivateRecording(int RecordedId,
683  int chanid, const QDateTime &StartTime)
684 {
685  if ((RecordedId <= 0) &&
686  (chanid <= 0 || !StartTime.isValid()))
687  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
688 
689  RecordingInfo ri;
690  if (RecordedId > 0)
691  ri = RecordingInfo(RecordedId);
692  else
693  ri = RecordingInfo(chanid, StartTime.toUTC());
694 
695  if (ri.GetChanID() && ri.HasPathname())
696  {
697  ri.ReactivateRecording();
698  return true;
699  }
700 
701  return false;
702 }
703 
705 //
707 
709 {
710  ScheduledRecording::RescheduleMatch(0, 0, 0, QDateTime(),
711  "RescheduleRecordings");
712  return true;
713 }
714 
716 //
718 
719 bool V2Dvr::AllowReRecord ( int RecordedId )
720 {
721  if (RecordedId <= 0)
722  throw QString("RecordedId param is invalid.");
723 
724  RecordingInfo ri = RecordingInfo(RecordedId);
725 
726  if (!ri.GetChanID())
727  throw QString("RecordedId %1 not found").arg(RecordedId);
728 
729  ri.ForgetHistory();
730 
731  return true;
732 }
733 
735 //
737 
739  int chanid,
740  const QDateTime &StartTime,
741  bool watched)
742 {
743  LOG(VB_GENERAL, LOG_WARNING, "Deprecated, use Dvr/UpdateRecordedMetadata.");
744 
745  if ((RecordedId <= 0) &&
746  (chanid <= 0 || !StartTime.isValid()))
747  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
748 
749  // TODO Should use RecordingInfo
750  ProgramInfo pi;
751  if (RecordedId > 0)
752  pi = ProgramInfo(RecordedId);
753  else
754  pi = ProgramInfo(chanid, StartTime.toUTC());
755 
756  if (pi.GetChanID() && pi.HasPathname())
757  {
758  pi.SaveWatched(watched);
759  return true;
760  }
761 
762  return false;
763 }
764 
766 //
768 
769 long V2Dvr::GetSavedBookmark( int RecordedId,
770  int chanid,
771  const QDateTime &StartTime,
772  const QString &offsettype )
773 {
774  if ((RecordedId <= 0) &&
775  (chanid <= 0 || !StartTime.isValid()))
776  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
777 
778  RecordingInfo ri;
779  if (RecordedId > 0)
780  ri = RecordingInfo(RecordedId);
781  else
782  ri = RecordingInfo(chanid, StartTime.toUTC());
783  uint64_t offset = 0;
784  bool isend=true;
785  uint64_t position = ri.QueryBookmark();
786  // if no bookmark return 0
787  if (position == 0)
788  return 0;
789  if (offsettype.toLower() == "position"){
790  // if bookmark cannot be converted to a keyframe we will
791  // just return the actual frame saved as the bookmark
792  if (ri.QueryKeyFramePosition(&offset, position, isend))
793  return offset;
794  }
795  if (offsettype.toLower() == "duration"){
796  if (ri.QueryKeyFrameDuration(&offset, position, isend))
797  return offset;
798  // If bookmark cannot be converted to a duration return -1
799  return -1;
800  }
801  return position;
802 }
803 
805 // Get last play position
806 // Providing -1 for the RecordedId will return response of -1.
807 // This is a way to check if this api, and the other LastPlayPos APIs,
808 // are supported
810 
811 long V2Dvr::GetLastPlayPos( int RecordedId,
812  int chanid,
813  const QDateTime &StartTime,
814  const QString &offsettype )
815 {
816  if (RecordedId == -1)
817  return -1;
818 
819  if ((RecordedId <= 0) &&
820  (chanid <= 0 || !StartTime.isValid()))
821  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
822 
823  RecordingInfo ri;
824  if (RecordedId > 0)
825  ri = RecordingInfo(RecordedId);
826  else
827  ri = RecordingInfo(chanid, StartTime.toUTC());
828  uint64_t offset = 0;
829  bool isend=true;
830  uint64_t position = ri.QueryLastPlayPos();
831  // if no bookmark return 0
832  if (position == 0)
833  return 0;
834  if (offsettype.toLower() == "position"){
835  // if bookmark cannot be converted to a keyframe we will
836  // just return the actual frame saved as the bookmark
837  if (ri.QueryKeyFramePosition(&offset, position, isend))
838  return offset;
839  }
840  if (offsettype.toLower() == "duration"){
841  if (ri.QueryKeyFrameDuration(&offset, position, isend))
842  return offset;
843  // If bookmark cannot be converted to a duration return -1
844  return -1;
845  }
846  return position;
847 }
848 
850 //
852 
853 bool V2Dvr::SetSavedBookmark( int RecordedId,
854  int chanid,
855  const QDateTime &StartTime,
856  const QString &offsettype,
857  long Offset )
858 {
859  LOG(VB_GENERAL, LOG_WARNING, "Deprecated, use Dvr/UpdateRecordedMetadata.");
860 
861  if ((RecordedId <= 0) &&
862  (chanid <= 0 || !StartTime.isValid()))
863  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
864 
865  if (Offset < 0)
866  throw QString("Offset must be >= 0.");
867 
868  RecordingInfo ri;
869  if (RecordedId > 0)
870  ri = RecordingInfo(RecordedId);
871  else
872  ri = RecordingInfo(chanid, StartTime.toUTC());
873  uint64_t position = 0;
874  bool isend=true;
875  if (offsettype.toLower() == "position"){
876  if (!ri.QueryPositionKeyFrame(&position, Offset, isend))
877  return false;
878  }
879  else if (offsettype.toLower() == "duration"){
880  if (!ri.QueryDurationKeyFrame(&position, Offset, isend))
881  return false;
882  }
883  else
884  position = Offset;
885  ri.SaveBookmark(position);
886  return true;
887 }
888 
890 // Set last Play Position. Check if this is supported by first calling
891 // Get Last Play Position with -1.
893 
894 bool V2Dvr::SetLastPlayPos( int RecordedId,
895  int chanid,
896  const QDateTime &StartTime,
897  const QString &offsettype,
898  long Offset )
899 {
900  if ((RecordedId <= 0) &&
901  (chanid <= 0 || !StartTime.isValid()))
902  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
903 
904  if (Offset < 0)
905  throw QString("Offset must be >= 0.");
906 
907  RecordingInfo ri;
908  if (RecordedId > 0)
909  ri = RecordingInfo(RecordedId);
910  else
911  ri = RecordingInfo(chanid, StartTime.toUTC());
912  uint64_t position = 0;
913  bool isend=true;
914  if (offsettype.toLower() == "position"){
915  if (!ri.QueryPositionKeyFrame(&position, Offset, isend))
916  return false;
917  }
918  else if (offsettype.toLower() == "duration"){
919  if (!ri.QueryDurationKeyFrame(&position, Offset, isend))
920  return false;
921  }
922  else
923  position = Offset;
924  ri.SaveLastPlayPos(position);
925  return true;
926 }
927 
929  int chanid,
930  const QDateTime &StartTime,
931  const QString &offsettype )
932 {
933  int marktype = 0;
934  if ((RecordedId <= 0) &&
935  (chanid <= 0 || !StartTime.isValid()))
936  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
937 
938  RecordingInfo ri;
939  if (RecordedId > 0)
940  ri = RecordingInfo(RecordedId);
941  else
942  ri = RecordingInfo(chanid, StartTime.toUTC());
943 
944  auto* pCutList = new V2CutList();
945  if (offsettype.toLower() == "position")
946  marktype = 1;
947  else if (offsettype.toLower() == "duration")
948  marktype = 2;
949  else
950  marktype = 0;
951 
952  V2FillCutList(pCutList, &ri, marktype);
953 
954  return pCutList;
955 }
956 
958 //
960 
962  int chanid,
963  const QDateTime &StartTime,
964  const QString &offsettype )
965 {
966  int marktype = 0;
967  if ((RecordedId <= 0) &&
968  (chanid <= 0 || !StartTime.isValid()))
969  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
970 
971  RecordingInfo ri;
972  if (RecordedId > 0)
973  ri = RecordingInfo(RecordedId);
974  else
975  ri = RecordingInfo(chanid, StartTime.toUTC());
976 
977  auto* pCutList = new V2CutList();
978  if (offsettype.toLower() == "position")
979  marktype = 1;
980  else if (offsettype.toLower() == "duration")
981  marktype = 2;
982  else
983  marktype = 0;
984 
985  V2FillCommBreak(pCutList, &ri, marktype);
986 
987  return pCutList;
988 }
989 
991 //
993 
995  const QString &offsettype )
996 {
997  MarkTypes marktype = MARK_UNSET;
998  if (RecordedId <= 0)
999  throw QString("Recorded ID appears invalid.");
1000 
1001  RecordingInfo ri;
1002  ri = RecordingInfo(RecordedId);
1003 
1004  auto* pCutList = new V2CutList();
1005  if (offsettype.toLower() == "bytes")
1006  marktype = MARK_GOP_BYFRAME;
1007  else if (offsettype.toLower() == "duration")
1008  marktype = MARK_DURATION_MS;
1009  else
1010  {
1011  delete pCutList;
1012  throw QString("Type must be 'BYTES' or 'DURATION'.");
1013  }
1014 
1015  V2FillSeek(pCutList, &ri, marktype);
1016 
1017  return pCutList;
1018 }
1019 
1021 //
1023 
1025 {
1026  RecordingInfo ri;
1027  ri = RecordingInfo(RecordedId);
1028 
1029  if (!ri.HasPathname())
1030  throw QString("Invalid RecordedId %1").arg(RecordedId);
1031 
1032  QVector<ProgramInfo::MarkupEntry> mapMark;
1033  QVector<ProgramInfo::MarkupEntry> mapSeek;
1034 
1035  ri.QueryMarkup(mapMark, mapSeek);
1036 
1037  auto* pMarkupList = new V2MarkupList();
1038  for (const auto& entry : qAsConst(mapMark))
1039  {
1040  V2Markup *pMarkup = pMarkupList->AddNewMarkup();
1041  QString typestr = toString(static_cast<MarkTypes>(entry.type));
1042  pMarkup->setType(typestr);
1043  pMarkup->setFrame(entry.frame);
1044  if (entry.isDataNull)
1045  pMarkup->setData("NULL");
1046  else
1047  pMarkup->setData(QString::number(entry.data));
1048  }
1049  for (const auto& entry : qAsConst(mapSeek))
1050  {
1051  V2Markup *pSeek = pMarkupList->AddNewSeek();
1052  QString typestr = toString(static_cast<MarkTypes>(entry.type));
1053  pSeek->setType(typestr);
1054  pSeek->setFrame(entry.frame);
1055  if (entry.isDataNull)
1056  pSeek->setData("NULL");
1057  else
1058  pSeek->setData(QString::number(entry.data));
1059  }
1060 
1061 
1062  return pMarkupList;
1063 }
1064 
1066 //
1068 
1069 bool V2Dvr::SetRecordedMarkup(int RecordedId, const QString &MarkupList)
1070 {
1071  RecordingInfo ri;
1072  ri = RecordingInfo(RecordedId);
1073 
1074  if (!ri.HasPathname())
1075  throw QString("Invalid RecordedId %1").arg(RecordedId);
1076 
1077  QVector<ProgramInfo::MarkupEntry> mapMark;
1078  QVector<ProgramInfo::MarkupEntry> mapSeek;
1079 
1080  QJsonDocument doc = QJsonDocument::fromJson(MarkupList.toUtf8());
1081  QJsonObject markuplist = doc.object();
1082 
1083  QJsonArray marks = markuplist["Mark"].toArray();
1084  for (const auto & m : marks)
1085  {
1086  QJsonObject markup = m.toObject();
1088 
1089  QString typestr = markup.value("Type").toString("");
1090  entry.type = markTypeFromString(typestr);
1091  entry.frame = markup.value("Frame").toVariant()
1092  .toString().toLongLong();
1093  QString data = markup.value("Data").toString("NULL");
1094  entry.isDataNull = (data == "NULL");
1095  if (!entry.isDataNull)
1096  entry.data = data.toLongLong();
1097 
1098  mapMark.append(entry);
1099  }
1100 
1101  QJsonArray seeks = markuplist["Seek"].toArray();
1102  for (const auto & m : seeks)
1103  {
1104  QJsonObject markup = m.toObject();
1106 
1107  QString typestr = markup.value("Type").toString("");
1108  entry.type = markTypeFromString(typestr);
1109  entry.frame = markup.value("Frame").toVariant().toString().toLongLong();
1110  QString data = markup.value("Data").toString("NULL");
1111  entry.isDataNull = (data == "NULL");
1112  if (!entry.isDataNull)
1113  entry.data = data.toLongLong();
1114 
1115  mapSeek.append(entry);
1116  }
1117 
1118  ri.SaveMarkup(mapMark, mapSeek);
1119 
1120  return true;
1121 }
1122 
1124 //
1126 
1128 {
1129  auto* pList = new V2EncoderList();
1130  FillEncoderList(pList->GetEncoders(), pList);
1131  return pList;
1132 }
1133 
1135 //
1137 
1139 {
1140  auto *pList = new V2InputList();
1141 
1142  QList<InputInfo> inputInfoList = CardUtil::GetAllInputInfo();
1143  for (const auto & inputInfo : qAsConst(inputInfoList))
1144  {
1145  V2Input *input = pList->AddNewInput();
1146  V2FillInputInfo(input, inputInfo);
1147  }
1148 
1149  return pList;
1150 }
1151 
1153 //
1155 
1157 {
1158  MSqlQuery query(MSqlQuery::InitCon());
1159  query.prepare("SELECT recgroup FROM recgroups WHERE recgroup <> 'Deleted' "
1160  "ORDER BY recgroup");
1161 
1162  QStringList result;
1163  if (!query.exec())
1164  {
1165  MythDB::DBError("GetRecGroupList", query);
1166  return result;
1167  }
1168 
1169  while (query.next())
1170  result << query.value(0).toString();
1171 
1172  return result;
1173 }
1174 
1176 //
1178 
1179 QStringList V2Dvr::GetProgramCategories( bool OnlyRecorded )
1180 {
1181  MSqlQuery query(MSqlQuery::InitCon());
1182 
1183  if (OnlyRecorded)
1184  query.prepare("SELECT DISTINCT category FROM recorded ORDER BY category");
1185  else
1186  query.prepare("SELECT DISTINCT category FROM program ORDER BY category");
1187 
1188  QStringList result;
1189  if (!query.exec())
1190  {
1191  MythDB::DBError("GetProgramCategories", query);
1192  return result;
1193  }
1194 
1195  while (query.next())
1196  result << query.value(0).toString();
1197 
1198  return result;
1199 }
1200 
1202 //
1204 
1206 {
1208 }
1209 
1211 //
1213 
1215 {
1216  return PlayGroup::GetNames();
1217 }
1218 
1220 //
1222 
1224 {
1225  auto* filterList = new V2RecRuleFilterList();
1226 
1227  MSqlQuery query(MSqlQuery::InitCon());
1228 
1229  query.prepare("SELECT filterid, description, newruledefault "
1230  "FROM recordfilter ORDER BY filterid");
1231 
1232  if (query.exec())
1233  {
1234  while (query.next())
1235  {
1236  V2RecRuleFilter* ruleFilter = filterList->AddNewRecRuleFilter();
1237  ruleFilter->setId(query.value(0).toInt());
1238  ruleFilter->setDescription(QObject::tr(query.value(1).toString()
1239  .toUtf8().constData()));
1240  }
1241  }
1242 
1243  return filterList;
1244 }
1245 
1247 //
1249 
1250 QStringList V2Dvr::GetTitleList(const QString& RecGroup)
1251 {
1252  MSqlQuery query(MSqlQuery::InitCon());
1253 
1254  QString querystr = "SELECT DISTINCT title FROM recorded "
1255  "WHERE deletepending = 0";
1256 
1257  if (!RecGroup.isEmpty())
1258  querystr += " AND recgroup = :RECGROUP";
1259  else
1260  querystr += " AND recgroup != 'Deleted'";
1261 
1262  querystr += " ORDER BY title";
1263 
1264  query.prepare(querystr);
1265 
1266  if (!RecGroup.isEmpty())
1267  query.bindValue(":RECGROUP", RecGroup);
1268 
1269  QStringList result;
1270  if (!query.exec())
1271  {
1272  MythDB::DBError("GetTitleList recorded", query);
1273  return result;
1274  }
1275 
1276  while (query.next())
1277  result << query.value(0).toString();
1278 
1279  return result;
1280 }
1281 
1283 //
1285 
1287 {
1288  MSqlQuery query(MSqlQuery::InitCon());
1289 
1290  QString querystr = QString(
1291  "SELECT title, inetref, count(title) as count "
1292  " FROM recorded AS r "
1293  " JOIN recgroups AS g ON r.recgroupid = g.recgroupid "
1294  " WHERE g.recgroup NOT IN ('Deleted', 'LiveTV') "
1295  " AND r.deletepending = 0 "
1296  " GROUP BY title, inetref "
1297  " ORDER BY title");
1298 
1299  query.prepare(querystr);
1300 
1301  auto *pTitleInfos = new V2TitleInfoList();
1302  if (!query.exec())
1303  {
1304  MythDB::DBError("GetTitleList recorded", query);
1305  return pTitleInfos;
1306  }
1307 
1308  while (query.next())
1309  {
1310  V2TitleInfo *pTitleInfo = pTitleInfos->AddNewTitleInfo();
1311 
1312  pTitleInfo->setTitle(query.value(0).toString());
1313  pTitleInfo->setInetref(query.value(1).toString());
1314  pTitleInfo->setCount(query.value(2).toInt());
1315  }
1316 
1317  return pTitleInfos;
1318 }
1319 
1320 
1322  int nCount,
1323  int nRecordId )
1324 {
1325  auto *pPrograms = new V2ProgramList();
1326  int size = FillUpcomingList(pPrograms->GetPrograms(), pPrograms,
1327  nStartIndex,
1328  nCount,
1329  true, // bShowAll,
1330  nRecordId,
1331  RecStatus::Conflict); // nRecStatus );
1332 
1333  pPrograms->setStartIndex ( nStartIndex );
1334  pPrograms->setCount ( nCount );
1335  pPrograms->setTotalAvailable( size );
1336  pPrograms->setAsOf ( MythDate::current() );
1337  pPrograms->setVersion ( MYTH_BINARY_VERSION );
1338  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1339 
1340  return pPrograms;
1341 }
1342 
1344  int nCount,
1345  bool bShowAll,
1346  int nRecordId,
1347  const QString & RecStatus )
1348 {
1349  int nRecStatus = 0;
1350  if (!RecStatus.isEmpty())
1351  {
1352  // Handle enum name
1353  QMetaEnum meta = QMetaEnum::fromType<RecStatus::Type>();
1354  bool ok {false};
1355  nRecStatus = meta.keyToValue(RecStatus.toLocal8Bit(), &ok);
1356  // if enum name not valid try for int nRecStatus
1357  if (!ok)
1358  nRecStatus = RecStatus.toInt(&ok);
1359  // if still not valid use 99999 to trigger an "unknown" response
1360  if (!ok)
1361  nRecStatus = 99999;
1362  }
1363  auto *pPrograms = new V2ProgramList();
1364  int size = FillUpcomingList(pPrograms->GetPrograms(), pPrograms,
1365  nStartIndex,
1366  nCount,
1367  bShowAll,
1368  nRecordId,
1369  nRecStatus );
1370 
1371  pPrograms->setStartIndex ( nStartIndex );
1372  pPrograms->setCount ( nCount );
1373  pPrograms->setTotalAvailable( size );
1374  pPrograms->setAsOf ( MythDate::current() );
1375  pPrograms->setVersion ( MYTH_BINARY_VERSION );
1376  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1377 
1378  return pPrograms;
1379 }
1380 
1382  const QString& sTitle,
1383  const QString& sSubtitle,
1384  const QString& sDescription,
1385  const QString& sCategory,
1386  const QDateTime& StartTime,
1387  const QDateTime& EndTime,
1388  const QString& sSeriesId,
1389  const QString& sProgramId,
1390  int nChanId,
1391  const QString& sStation,
1392  int nFindDay,
1393  QTime tFindTime,
1394  int nParentId,
1395  bool bInactive,
1396  uint nSeason,
1397  uint nEpisode,
1398  const QString& sInetref,
1399  QString sType,
1400  QString sSearchType,
1401  int nRecPriority,
1402  uint nPreferredInput,
1403  int nStartOffset,
1404  int nEndOffset,
1405  const QDateTime& LastRecorded,
1406  QString sDupMethod,
1407  QString sDupIn,
1408  bool bNewEpisOnly,
1409  uint nFilter,
1410  QString sRecProfile,
1411  QString sRecGroup,
1412  QString sStorageGroup,
1413  QString sPlayGroup,
1414  bool bAutoExpire,
1415  int nMaxEpisodes,
1416  bool bMaxNewest,
1417  bool bAutoCommflag,
1418  bool bAutoTranscode,
1419  bool bAutoMetaLookup,
1420  bool bAutoUserJob1,
1421  bool bAutoUserJob2,
1422  bool bAutoUserJob3,
1423  bool bAutoUserJob4,
1424  int nTranscoder,
1425  const QString& AutoExtend)
1426 {
1427  QDateTime recstartts = StartTime.toUTC();
1428  QDateTime recendts = EndTime.toUTC();
1429  QDateTime lastrects = LastRecorded.toUTC();
1430  RecordingRule rule;
1431  rule.LoadTemplate("Default");
1432 
1433  if (sType.isEmpty())
1434  sType = "single";
1435 
1436  if (sSearchType.isEmpty())
1437  sSearchType = "none";
1438 
1439  if (sDupMethod.isEmpty())
1440  sDupMethod = "subtitleanddescription";
1441 
1442  if (sDupIn.isEmpty())
1443  sDupIn = "all";
1444 
1445  rule.m_title = sTitle;
1446  rule.m_subtitle = sSubtitle;
1447  rule.m_description = sDescription;
1448 
1449  rule.m_startdate = recstartts.date();
1450  rule.m_starttime = recstartts.time();
1451  rule.m_enddate = recendts.date();
1452  rule.m_endtime = recendts.time();
1453 
1454  rule.m_type = recTypeFromString(sType);
1455  rule.m_searchType = searchTypeFromString(sSearchType);
1456  if (rule.m_searchType == kManualSearch)
1457  rule.m_dupMethod = kDupCheckNone;
1458  else
1459  rule.m_dupMethod = dupMethodFromString(sDupMethod);
1460  rule.m_dupIn = dupInFromStringAndBool(sDupIn, bNewEpisOnly);
1461 
1462  if (sRecProfile.isEmpty())
1463  sRecProfile = "Default";
1464 
1465  if (sRecGroup.isEmpty())
1466  sRecGroup = "Default";
1467 
1468  if (sStorageGroup.isEmpty())
1469  sStorageGroup = "Default";
1470 
1471  if (sPlayGroup.isEmpty())
1472  sPlayGroup = "Default";
1473 
1474  rule.m_category = sCategory;
1475  rule.m_seriesid = sSeriesId;
1476  rule.m_programid = sProgramId;
1477 
1478  rule.m_channelid = nChanId;
1479  rule.m_station = sStation;
1480 
1481  rule.m_findday = nFindDay;
1482  rule.m_findtime = tFindTime;
1483 
1484  rule.m_recProfile = sRecProfile;
1485  rule.m_recGroupID = RecordingInfo::GetRecgroupID(sRecGroup);
1486  if (rule.m_recGroupID == 0)
1487  {
1488  rule.m_recGroupID = V2CreateRecordingGroup(sRecGroup);
1489  if (rule.m_recGroupID <= 0)
1491  }
1492  rule.m_storageGroup = sStorageGroup;
1493  rule.m_playGroup = sPlayGroup;
1494 
1495  rule.m_parentRecID = nParentId;
1496  rule.m_isInactive = bInactive;
1497 
1498  rule.m_season = nSeason;
1499  rule.m_episode = nEpisode;
1500  rule.m_inetref = sInetref;
1501 
1502  rule.m_recPriority = nRecPriority;
1503  rule.m_prefInput = nPreferredInput;
1504  rule.m_startOffset = nStartOffset;
1505  rule.m_endOffset = nEndOffset;
1506  rule.m_filter = nFilter;
1507 
1508  rule.m_autoExpire = bAutoExpire;
1509  rule.m_maxEpisodes = nMaxEpisodes;
1510  rule.m_maxNewest = bMaxNewest;
1511 
1512  rule.m_autoCommFlag = bAutoCommflag;
1513  rule.m_autoTranscode = bAutoTranscode;
1514  rule.m_autoMetadataLookup = bAutoMetaLookup;
1515 
1516  rule.m_autoUserJob1 = bAutoUserJob1;
1517  rule.m_autoUserJob2 = bAutoUserJob2;
1518  rule.m_autoUserJob3 = bAutoUserJob3;
1519  rule.m_autoUserJob4 = bAutoUserJob4;
1520 
1521  rule.m_transcoder = nTranscoder;
1522  rule.m_autoExtend = autoExtendTypeFromString(AutoExtend);
1523 
1524  rule.m_lastRecorded = lastrects;
1525 
1526  QString msg;
1527  if (!rule.IsValid(msg))
1528  throw QString(msg);
1529 
1530  rule.Save();
1531 
1532  uint recid = rule.m_recordID;
1533 
1534  return recid;
1535 }
1536 
1538  const QString& sTitle,
1539  const QString& sSubtitle,
1540  const QString& sDescription,
1541  const QString& sCategory,
1542  const QDateTime& StartTime,
1543  const QDateTime& EndTime,
1544  const QString& sSeriesId,
1545  const QString& sProgramId,
1546  int nChanId,
1547  const QString& sStation,
1548  int nFindDay,
1549  QTime tFindTime,
1550  bool bInactive,
1551  uint nSeason,
1552  uint nEpisode,
1553  const QString& sInetref,
1554  QString sType,
1555  QString sSearchType,
1556  int nRecPriority,
1557  uint nPreferredInput,
1558  int nStartOffset,
1559  int nEndOffset,
1560  QString sDupMethod,
1561  QString sDupIn,
1562  bool bNewEpisOnly,
1563  uint nFilter,
1564  QString sRecProfile,
1565  QString sRecGroup,
1566  QString sStorageGroup,
1567  QString sPlayGroup,
1568  bool bAutoExpire,
1569  int nMaxEpisodes,
1570  bool bMaxNewest,
1571  bool bAutoCommflag,
1572  bool bAutoTranscode,
1573  bool bAutoMetaLookup,
1574  bool bAutoUserJob1,
1575  bool bAutoUserJob2,
1576  bool bAutoUserJob3,
1577  bool bAutoUserJob4,
1578  int nTranscoder,
1579  const QString& AutoExtend)
1580 {
1581  if (nRecordId == 0 )
1582  throw QString("Record ID is invalid.");
1583 
1584  RecordingRule pRule;
1585  pRule.m_recordID = nRecordId;
1586  pRule.Load();
1587 
1588  if (!pRule.IsLoaded())
1589  throw QString("Record ID does not exist.");
1590 
1591  QDateTime recstartts = StartTime.toUTC();
1592  QDateTime recendts = EndTime.toUTC();
1593 
1594  pRule.m_isInactive = bInactive;
1595  if (sType.isEmpty())
1596  sType = "single";
1597 
1598  if (sSearchType.isEmpty())
1599  sSearchType = "none";
1600 
1601  if (sDupMethod.isEmpty())
1602  sDupMethod = "subtitleanddescription";
1603 
1604  if (sDupIn.isEmpty())
1605  sDupIn = "all";
1606 
1607  pRule.m_type = recTypeFromString(sType);
1608  pRule.m_searchType = searchTypeFromString(sSearchType);
1609  if (pRule.m_searchType == kManualSearch)
1610  pRule.m_dupMethod = kDupCheckNone;
1611  else
1612  pRule.m_dupMethod = dupMethodFromString(sDupMethod);
1613  pRule.m_dupIn = dupInFromStringAndBool(sDupIn, bNewEpisOnly);
1614 
1615  if (sRecProfile.isEmpty())
1616  sRecProfile = "Default";
1617 
1618  if (sRecGroup.isEmpty())
1619  sRecGroup = "Default";
1620 
1621  if (sStorageGroup.isEmpty())
1622  sStorageGroup = "Default";
1623 
1624  if (sPlayGroup.isEmpty())
1625  sPlayGroup = "Default";
1626 
1627  if (!sTitle.isEmpty())
1628  pRule.m_title = sTitle;
1629 
1630  if (!sSubtitle.isEmpty())
1631  pRule.m_subtitle = sSubtitle;
1632 
1633  if(!sDescription.isEmpty())
1634  pRule.m_description = sDescription;
1635 
1636  if (!sCategory.isEmpty())
1637  pRule.m_category = sCategory;
1638 
1639  if (!sSeriesId.isEmpty())
1640  pRule.m_seriesid = sSeriesId;
1641 
1642  if (!sProgramId.isEmpty())
1643  pRule.m_programid = sProgramId;
1644 
1645  if (nChanId)
1646  pRule.m_channelid = nChanId;
1647  if (!sStation.isEmpty())
1648  pRule.m_station = sStation;
1649 
1650  pRule.m_startdate = recstartts.date();
1651  pRule.m_starttime = recstartts.time();
1652  pRule.m_enddate = recendts.date();
1653  pRule.m_endtime = recendts.time();
1654 
1655  pRule.m_findday = nFindDay;
1656  pRule.m_findtime = tFindTime;
1657 
1658  pRule.m_recProfile = sRecProfile;
1659  pRule.m_recGroupID = RecordingInfo::GetRecgroupID(sRecGroup);
1660  if (pRule.m_recGroupID == 0)
1661  {
1662  pRule.m_recGroupID = V2CreateRecordingGroup(sRecGroup);
1663  if (pRule.m_recGroupID <= 0)
1665  }
1666  pRule.m_storageGroup = sStorageGroup;
1667  pRule.m_playGroup = sPlayGroup;
1668 
1669  pRule.m_isInactive = bInactive;
1670 
1671  pRule.m_season = nSeason;
1672  pRule.m_episode = nEpisode;
1673  pRule.m_inetref = sInetref;
1674 
1675  pRule.m_recPriority = nRecPriority;
1676  pRule.m_prefInput = nPreferredInput;
1677  pRule.m_startOffset = nStartOffset;
1678  pRule.m_endOffset = nEndOffset;
1679  pRule.m_filter = nFilter;
1680 
1681  pRule.m_autoExpire = bAutoExpire;
1682  pRule.m_maxEpisodes = nMaxEpisodes;
1683  pRule.m_maxNewest = bMaxNewest;
1684 
1685  pRule.m_autoCommFlag = bAutoCommflag;
1686  pRule.m_autoTranscode = bAutoTranscode;
1687  pRule.m_autoMetadataLookup = bAutoMetaLookup;
1688 
1689  pRule.m_autoUserJob1 = bAutoUserJob1;
1690  pRule.m_autoUserJob2 = bAutoUserJob2;
1691  pRule.m_autoUserJob3 = bAutoUserJob3;
1692  pRule.m_autoUserJob4 = bAutoUserJob4;
1693 
1694  pRule.m_transcoder = nTranscoder;
1695 
1696  if (!AutoExtend.isEmpty())
1697  pRule.m_autoExtend = autoExtendTypeFromString(AutoExtend);
1698 
1699  QString msg;
1700  if (!pRule.IsValid(msg))
1701  throw QString(msg);
1702 
1703  bool bResult = pRule.Save();
1704 
1705  return bResult;
1706 }
1707 
1709 {
1710  bool bResult = false;
1711 
1712  if (nRecordId == 0 )
1713  throw QString("Record ID does not exist.");
1714 
1715  RecordingRule pRule;
1716  pRule.m_recordID = nRecordId;
1717 
1718  bResult = pRule.Delete();
1719 
1720  return bResult;
1721 }
1722 
1723 bool V2Dvr::AddDontRecordSchedule(int nChanId, const QDateTime &dStartTime,
1724  bool bNeverRecord)
1725 {
1726  bool bResult = true;
1727 
1728  if (nChanId <= 0 || !dStartTime.isValid())
1729  throw QString("Program does not exist.");
1730 
1731  ProgramInfo *pi = LoadProgramFromProgram(nChanId, dStartTime.toUTC());
1732 
1733  if (!pi)
1734  throw QString("Program does not exist.");
1735 
1736  // Why RecordingInfo instead of ProgramInfo? Good question ...
1737  RecordingInfo recInfo = RecordingInfo(*pi);
1738 
1739  delete pi;
1740 
1741  if (bNeverRecord)
1742  {
1743  recInfo.ApplyNeverRecord();
1744  }
1745  else
1747 
1748  return bResult;
1749 }
1750 
1752  int nCount,
1753  const QString &Sort,
1754  bool Descending )
1755 {
1757  if (Sort.toLower() == "lastrecorded")
1758  sortingColumn = Scheduler::kSortLastRecorded;
1759  else if (Sort.toLower() == "nextrecording")
1760  sortingColumn = Scheduler::kSortNextRecording;
1761  else if (Sort.toLower() == "title")
1762  sortingColumn = Scheduler::kSortTitle; // NOLINT(bugprone-branch-clone)
1763  else if (Sort.toLower() == "priority")
1764  sortingColumn = Scheduler::kSortPriority;
1765  else if (Sort.toLower() == "type")
1766  sortingColumn = Scheduler::kSortType;
1767  else
1768  sortingColumn = Scheduler::kSortTitle;
1769 
1770  RecList recList;
1771  Scheduler::GetAllScheduled(recList, sortingColumn, !Descending);
1772 
1773  // ----------------------------------------------------------------------
1774  // Build Response
1775  // ----------------------------------------------------------------------
1776 
1777  auto *pRecRules = new V2RecRuleList();
1778 
1779  nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (int)recList.size() ) : 0;
1780  nCount = (nCount > 0) ? std::min( nCount, (int)recList.size() ) : recList.size();
1781  int nEndIndex = std::min((nStartIndex + nCount), (int)recList.size() );
1782 
1783  for( int n = nStartIndex; n < nEndIndex; n++)
1784  {
1785  RecordingInfo *info = recList[n];
1786 
1787  if (info != nullptr)
1788  {
1789  V2RecRule *pRecRule = pRecRules->AddNewRecRule();
1790 
1791  V2FillRecRuleInfo( pRecRule, info->GetRecordingRule() );
1792  }
1793  }
1794 
1795  // ----------------------------------------------------------------------
1796 
1797  pRecRules->setStartIndex ( nStartIndex );
1798  pRecRules->setCount ( nCount );
1799  pRecRules->setTotalAvailable( recList.size() );
1800  pRecRules->setAsOf ( MythDate::current() );
1801  pRecRules->setVersion ( MYTH_BINARY_VERSION );
1802  pRecRules->setProtoVer ( MYTH_PROTO_VERSION );
1803 
1804  while (!recList.empty())
1805  {
1806  delete recList.back();
1807  recList.pop_back();
1808  }
1809 
1810  return pRecRules;
1811 }
1812 
1814  const QString& sTemplate,
1815  int nRecordedId,
1816  int nChanId,
1817  const QDateTime& StartTime,
1818  bool bMakeOverride )
1819 {
1820  RecordingRule rule;
1821  QDateTime dStartTime = StartTime.toUTC();
1822 
1823  if (nRecordId > 0)
1824  {
1825  rule.m_recordID = nRecordId;
1826  if (!rule.Load())
1827  throw QString("Record ID does not exist.");
1828  }
1829  else if (!sTemplate.isEmpty())
1830  {
1831  if (!rule.LoadTemplate(sTemplate))
1832  throw QString("Template does not exist.");
1833  }
1834  else if (nRecordedId > 0) // Loads from the Recorded/Recorded Program Table
1835  {
1836  // Despite the use of ProgramInfo, this only applies to Recordings.
1837  ProgramInfo recInfo(nRecordedId);
1838  if (!rule.LoadByProgram(&recInfo))
1839  throw QString("Recording does not exist");
1840  }
1841  else if (nChanId > 0 && dStartTime.isValid()) // Loads from Program Table, should NOT be used with recordings
1842  {
1843  // Despite the use of RecordingInfo, this only applies to programs in the
1844  // present or future, not to recordings? Confused yet?
1846  RecordingInfo info(nChanId, dStartTime, false, 0h, &status);
1847  if (status != RecordingInfo::kFoundProgram)
1848  throw QString("Program does not exist.");
1849  RecordingRule *pRule = info.GetRecordingRule();
1850  if (bMakeOverride && rule.m_type != kSingleRecord &&
1851  rule.m_type != kOverrideRecord && rule.m_type != kDontRecord)
1852  pRule->MakeOverride();
1853  rule = *pRule;
1854  }
1855  else
1856  {
1857  throw QString("Invalid request.");
1858  }
1859 
1860  auto *pRecRule = new V2RecRule();
1861  V2FillRecRuleInfo( pRecRule, &rule );
1862 
1863  return pRecRule;
1864 }
1865 
1867 {
1868  bool bResult = false;
1869 
1870  if (nRecordId == 0 )
1871  throw QString("Record ID appears invalid.");
1872 
1873  RecordingRule pRule;
1874  pRule.m_recordID = nRecordId;
1875  pRule.Load();
1876 
1877  if (pRule.IsLoaded())
1878  {
1879  pRule.m_isInactive = false;
1880  bResult = pRule.Save();
1881  }
1882 
1883  return bResult;
1884 }
1885 
1887 {
1888  bool bResult = false;
1889 
1890  if (nRecordId == 0 )
1891  throw QString("Record ID appears invalid.");
1892 
1893  RecordingRule pRule;
1894  pRule.m_recordID = nRecordId;
1895  pRule.Load();
1896 
1897  if (pRule.IsLoaded())
1898  {
1899  pRule.m_isInactive = true;
1900  bResult = pRule.Save();
1901  }
1902 
1903  return bResult;
1904 }
1905 
1906 int V2Dvr::RecordedIdForKey(int chanid, const QDateTime &StartTime)
1907 {
1908  int recordedid = 0;
1909 
1910  if (!RecordingInfo::QueryRecordedIdForKey(recordedid, chanid,
1911  StartTime))
1912  return -1;
1913 
1914  return recordedid;
1915 }
1916 
1917 int V2Dvr::RecordedIdForPathname(const QString & pathname)
1918 {
1919  uint recordedid = 0;
1920 
1921  if (!ProgramInfo::QueryRecordedIdFromPathname(pathname, recordedid))
1922  return -1;
1923 
1924  return recordedid;
1925 }
1926 
1927 QString V2Dvr::RecStatusToString(const QString & RecStatus)
1928 {
1929  // Handle enum name
1930  QMetaEnum meta = QMetaEnum::fromType<RecStatus::Type>();
1931  bool ok {false};
1932  int value = meta.keyToValue(RecStatus.toLocal8Bit(), &ok);
1933  // if enum name not valid try for int value
1934  if (!ok)
1935  value = RecStatus.toInt(&ok);
1936  // if still not valid use 0 to trigger an "unknown" response
1937  if (!ok)
1938  value = 0;
1939  auto type = static_cast<RecStatus::Type>(value);
1940  return RecStatus::toString(type);
1941 }
1942 
1943 QString V2Dvr::RecStatusToDescription(const QString & RecStatus, int recType,
1944  const QDateTime &StartTime)
1945 {
1946  // Handle enum name
1947  QMetaEnum meta = QMetaEnum::fromType<RecStatus::Type>();
1948  bool ok {false};
1949  int value = meta.keyToValue(RecStatus.toLocal8Bit(), &ok);
1950  // if enum name not valid try for int value
1951  if (!ok)
1952  value = RecStatus.toInt(&ok);
1953  // if still not valid use 0 to trigger an "unknown" response
1954  if (!ok)
1955  value = 0;
1956  auto recstatusType = static_cast<RecStatus::Type>(value);
1957  auto recordingType = static_cast<RecordingType>(recType);
1958  return RecStatus::toDescription(recstatusType, recordingType, StartTime);
1959 }
1960 
1961 QString V2Dvr::RecTypeToString(const QString& recType)
1962 {
1963  bool ok = false;
1964  auto enumType = static_cast<RecordingType>(recType.toInt(&ok, 10));
1965  if (ok)
1966  return toString(enumType);
1967  // RecordingType type = static_cast<RecordingType>(recType);
1968  return toString(recTypeFromString(recType));
1969 }
1970 
1971 QString V2Dvr::RecTypeToDescription(const QString& recType)
1972 {
1973  bool ok = false;
1974  auto enumType = static_cast<RecordingType>(recType.toInt(&ok, 10));
1975  if (ok)
1976  return toDescription(enumType);
1977  // RecordingType type = static_cast<RecordingType>(recType);
1978  return toDescription(recTypeFromString(recType));
1979 }
1980 
1981 QString V2Dvr::DupInToString(const QString& DupIn)
1982 {
1983  // RecordingDupInType type= static_cast<RecordingDupInType>(DupIn);
1984  // return toString(type);
1985  return toString(dupInFromString(DupIn));
1986 }
1987 
1988 QString V2Dvr::DupInToDescription(const QString& DupIn)
1989 {
1990  // RecordingDupInType type= static_cast<RecordingDupInType>(DupIn);
1991  //return toDescription(type);
1992  return toDescription(dupInFromString(DupIn));
1993 }
1994 
1995 QString V2Dvr::DupMethodToString(const QString& DupMethod)
1996 {
1997  // RecordingDupMethodType method = static_cast<RecordingDupMethodType>(DupMethod);
1998  return toString(dupMethodFromString(DupMethod));
1999 }
2000 
2001 QString V2Dvr::DupMethodToDescription(const QString& DupMethod)
2002 {
2003  // RecordingDupMethodType method = static_cast<RecordingDupMethodType>(DupMethod);
2004  return toDescription(dupMethodFromString(DupMethod));
2005 }
2006 
2008 //
2010 
2011 int V2Dvr::ManageJobQueue( const QString &sAction,
2012  const QString &sJobName,
2013  int nJobId,
2014  int nRecordedId,
2015  QDateTime JobStartTime,
2016  QString sRemoteHost,
2017  QString sJobArgs )
2018 {
2019  int nReturn = -1;
2020 
2021  if (!HAS_PARAMv2("JobName") ||
2022  !HAS_PARAMv2("RecordedId") )
2023  {
2024  LOG(VB_GENERAL, LOG_ERR, "JobName and RecordedId are required.");
2025  return nReturn;
2026  }
2027 
2028  if (sRemoteHost.isEmpty())
2029  sRemoteHost = gCoreContext->GetHostName();
2030 
2031  int jobType = JobQueue::GetJobTypeFromName(sJobName);
2032 
2033  if (jobType == JOB_NONE)
2034  return nReturn;
2035 
2036  RecordingInfo ri = RecordingInfo(nRecordedId);
2037 
2038  if (!ri.GetChanID())
2039  return nReturn;
2040 
2041  if ( sAction == "Remove")
2042  {
2043  if (!HAS_PARAMv2("JobId") || nJobId < 0)
2044  {
2045  LOG(VB_GENERAL, LOG_ERR, "For Remove, a valid JobId is required.");
2046  return nReturn;
2047  }
2048 
2049  if (!JobQueue::SafeDeleteJob(nJobId, jobType, ri.GetChanID(),
2050  ri.GetRecordingStartTime()))
2051  return nReturn;
2052 
2053  return nJobId;
2054  }
2055 
2056  if ( sAction != "Add")
2057  {
2058  LOG(VB_GENERAL, LOG_ERR, QString("Illegal Action name '%1'. Use: Add, "
2059  "or Remove").arg(sAction));
2060  return nReturn;
2061  }
2062 
2063  if (((jobType & JOB_USERJOB) != 0) &&
2064  gCoreContext->GetSetting(sJobName, "").isEmpty())
2065  {
2066  LOG(VB_GENERAL, LOG_ERR, QString("%1 hasn't been defined.")
2067  .arg(sJobName));
2068  return nReturn;
2069  }
2070 
2071  if (!gCoreContext->GetBoolSettingOnHost(QString("JobAllow%1").arg(sJobName),
2072  sRemoteHost, false))
2073  {
2074  LOG(VB_GENERAL, LOG_ERR, QString("%1 hasn't been allowed on host %2.")
2075  .arg(sJobName, sRemoteHost));
2076  return nReturn;
2077  }
2078 
2079  if (!JobStartTime.isValid())
2080  JobStartTime = QDateTime::currentDateTime();
2081 
2082  if (!JobQueue::InJobRunWindow(JobStartTime))
2083  return nReturn;
2084 
2085  if (sJobArgs.isNull())
2086  sJobArgs = "";
2087 
2088  bool bReturn = JobQueue::QueueJob(jobType,
2089  ri.GetChanID(),
2090  ri.GetRecordingStartTime(),
2091  sJobArgs,
2092  QString("Dvr/ManageJobQueue"), // comment col.
2093  sRemoteHost,
2094  JOB_NO_FLAGS,
2095  JOB_QUEUED,
2096  JobStartTime.toUTC());
2097 
2098  if (!bReturn)
2099  {
2100  LOG(VB_GENERAL, LOG_ERR, QString("%1 job wasn't queued because of a "
2101  "database error or because it was "
2102  "already running/stopping etc.")
2103  .arg(sJobName));
2104 
2105  return nReturn;
2106  }
2107 
2108  return JobQueue::GetJobID(jobType, ri.GetChanID(),
2109  ri.GetRecordingStartTime());
2110 }
2111 
2113 //
2115 
2117  bool AutoExpire,
2118  long BookmarkOffset,
2119  const QString &BookmarkOffsetType,
2120  bool Damaged,
2121  const QString &Description,
2122  uint Episode,
2123  const QString &Inetref,
2124  QDate OriginalAirDate,
2125  bool Preserve,
2126  uint Season,
2127  uint Stars,
2128  const QString &SubTitle,
2129  const QString &Title,
2130  bool Watched,
2131  const QString &RecGroup )
2132 
2133 {
2134  if (m_request->m_queries.size() < 2 || !HAS_PARAMv2("RecordedId"))
2135  {
2136  LOG(VB_GENERAL, LOG_ERR, "No RecordedId, or no parameters to change.");
2137  return false;
2138  }
2139 
2140  auto pi = ProgramInfo(RecordedId);
2141  auto ri = RecordingInfo(RecordedId);
2142 
2143  if (!ri.GetChanID())
2144  return false;
2145 
2146  if (HAS_PARAMv2("AutoExpire"))
2147  pi.SaveAutoExpire(AutoExpire ? kNormalAutoExpire :
2148  kDisableAutoExpire, false);
2149 
2150  if (HAS_PARAMv2("BookmarkOffset"))
2151  {
2152  uint64_t position =0;
2153 
2154  if (BookmarkOffsetType.toLower() == "position")
2155  {
2156  if (!ri.QueryPositionKeyFrame(&position, BookmarkOffset, true))
2157  return false;
2158  }
2159  else if (BookmarkOffsetType.toLower() == "duration")
2160  {
2161  if (!ri.QueryDurationKeyFrame(&position, BookmarkOffset, true))
2162  return false;
2163  }
2164  else
2165  position = BookmarkOffset;
2166 
2167  ri.SaveBookmark(position);
2168  }
2169 
2170  if (HAS_PARAMv2("Damaged"))
2171  pi.SaveVideoProperties(VID_DAMAGED, Damaged ? VID_DAMAGED : 0);
2172 
2173  if (HAS_PARAMv2("Description") ||
2174  HAS_PARAMv2("SubTitle") ||
2175  HAS_PARAMv2("Title"))
2176  {
2177 
2178  QString tmp_description;
2179  QString tmp_subtitle;
2180  QString tmp_title;
2181 
2182  if (HAS_PARAMv2("Description"))
2183  tmp_description = Description;
2184  else
2185  tmp_description = ri.GetDescription();
2186 
2187  if (HAS_PARAMv2("SubTitle"))
2188  tmp_subtitle = SubTitle;
2189  else
2190  tmp_subtitle = ri.GetSubtitle();
2191 
2192  if (HAS_PARAMv2("Title"))
2193  tmp_title = Title;
2194  else
2195  tmp_title = ri.GetTitle();
2196 
2197  ri.ApplyRecordRecTitleChange(tmp_title, tmp_subtitle, tmp_description);
2198  }
2199 
2200  if (HAS_PARAMv2("Episode") ||
2201  HAS_PARAMv2("Season"))
2202  {
2203  int tmp_episode = 0;
2204  int tmp_season = 0;
2205 
2206  if (HAS_PARAMv2("Episode"))
2207  tmp_episode = Episode;
2208  else
2209  tmp_episode = ri.GetEpisode();
2210 
2211  if (HAS_PARAMv2("Season"))
2212  tmp_season = Season;
2213  else
2214  tmp_season = ri.GetSeason();
2215 
2216  pi.SaveSeasonEpisode(tmp_season, tmp_episode);
2217  }
2218 
2219  if (HAS_PARAMv2("Inetref"))
2220  pi.SaveInetRef(Inetref);
2221 
2222  if (HAS_PARAMv2("OriginalAirDate"))
2223  {
2224  // OriginalAirDate can be set to null by submitting value 'null' in json
2225  if (!OriginalAirDate.isValid() && !OriginalAirDate.isNull())
2226  {
2227  LOG(VB_GENERAL, LOG_ERR, "Need valid OriginalAirDate yyyy-mm-dd.");
2228  return false;
2229  }
2230  ri.ApplyOriginalAirDateChange(OriginalAirDate);
2231  }
2232 
2233  if (HAS_PARAMv2("Preserve"))
2234  pi.SavePreserve(Preserve);
2235 
2236  if (HAS_PARAMv2("Stars"))
2237  {
2238  if (Stars > 10)
2239  {
2240  LOG(VB_GENERAL, LOG_ERR, "Recording stars can be 0 to 10.");
2241  return false;
2242  }
2243  ri.ApplyStarsChange(Stars * 0.1);
2244  }
2245 
2246  if (HAS_PARAMv2("Watched"))
2247  pi.SaveWatched(Watched);
2248 
2249  if (HAS_PARAMv2("RecGroup"))
2250  ri.ApplyRecordRecGroupChange(RecGroup);
2251 
2252  return true;
2253 }
MythHTTPService::HAS_PARAMv2
bool HAS_PARAMv2(const QString &p)
Definition: mythhttpservice.h:36
StorageGroup::getRecordingsGroups
static QStringList getRecordingsGroups(void)
Definition: storagegroup.cpp:789
RecordingInfo::GetRecgroupID
static uint GetRecgroupID(const QString &recGroup)
Temporary helper during transition from string to ID.
Definition: recordinginfo.cpp:1686
RecordingRule::m_channelid
int m_channelid
callsign?
Definition: recordingrule.h:99
V2Dvr::AllowReRecord
static bool AllowReRecord(int RecordedId)
Definition: v2dvr.cpp:719
MSqlBindings
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:101
RecordingRule::LoadByProgram
bool LoadByProgram(const ProgramInfo *proginfo)
Definition: recordingrule.cpp:168
Scheduler::kSortNextRecording
@ kSortNextRecording
Definition: scheduler.h:86
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:811
RecStatus::Type
Type
Definition: recordingstatus.h:16
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
RecordingRule::m_autoTranscode
bool m_autoTranscode
Definition: recordingrule.h:132
RecordingRule::m_enddate
QDate m_enddate
Definition: recordingrule.h:90
RecordingInfo::kDefaultRecGroup
@ kDefaultRecGroup
Definition: recordinginfo.h:191
RecordingRule::m_playGroup
QString m_playGroup
Definition: recordingrule.h:122
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:84
RecordingRule::m_seriesid
QString m_seriesid
Definition: recordingrule.h:84
RecordingRule::m_parentRecID
int m_parentRecID
Definition: recordingrule.h:71
COMM_FLAG_NOT_FLAGGED
@ COMM_FLAG_NOT_FLAGGED
Definition: programtypes.h:122
RecordingInfo::QueryRecordedIdForKey
static bool QueryRecordedIdForKey(int &recordedid, uint chanid, const QDateTime &recstartts)
Definition: recordinginfo.cpp:942
V2Dvr::UpdateRecordedMetadata
bool UpdateRecordedMetadata(uint RecordedId, bool AutoExpire, long BookmarkOffset, const QString &BookmarkOffsetType, bool Damaged, const QString &Description, uint Episode, const QString &Inetref, QDate OriginalAirDate, bool Preserve, uint Season, uint Stars, const QString &SubTitle, const QString &Title, bool Watched, const QString &RecGroup)
Definition: v2dvr.cpp:2116
V2InputList
Definition: v2inputList.h:20
V2Dvr::GetRecordedSeek
static V2CutList * GetRecordedSeek(int RecordedId, const QString &OffsetType)
Definition: v2dvr.cpp:994
RecordingInfo::ApplyNeverRecord
void ApplyNeverRecord(void)
Set this program to never be recorded by inserting 'history' for it into the database with a status o...
Definition: recordinginfo.cpp:905
V2Dvr::RecordedIdForPathname
static int RecordedIdForPathname(const QString &Pathname)
Definition: v2dvr.cpp:1917
backendcontext.h
V2Dvr::GetPlayGroupList
static QStringList GetPlayGroupList()
Definition: v2dvr.cpp:1214
V2FillProgramInfo
void V2FillProgramInfo(V2Program *pProgram, ProgramInfo *pInfo, bool bIncChannel, bool bDetails, bool bIncCast, bool bIncArtwork, bool bIncRecording)
Definition: v2serviceUtil.cpp:33
RecordingRule::m_description
QString m_description
Definition: recordingrule.h:81
RecordingRule::m_autoCommFlag
bool m_autoCommFlag
Definition: recordingrule.h:131
RecordingRule::m_inetref
QString m_inetref
Definition: recordingrule.h:87
RecordingInfo::kFoundProgram
@ kFoundProgram
Definition: recordinginfo.h:182
ProgramInfo::SaveBookmark
void SaveBookmark(uint64_t frame)
Clears any existing bookmark in DB and if frame is greater than 0 sets a new bookmark.
Definition: programinfo.cpp:2677
ProgramInfo::SetRecordingStatus
void SetRecordingStatus(RecStatus::Type status)
Definition: programinfo.h:580
MythCoreContext::GetScheduler
MythScheduler * GetScheduler(void)
Definition: mythcorecontext.cpp:1874
V2Dvr::GetRecordSchedule
static V2RecRule * GetRecordSchedule(uint RecordId, const QString &Template, int RecordedId, int ChanId, const QDateTime &StartTime, bool MakeOverride)
Definition: v2dvr.cpp:1813
RecordingRule::m_maxNewest
bool m_maxNewest
Definition: recordingrule.h:127
LoadProgramFromProgram
ProgramInfo * LoadProgramFromProgram(const uint chanid, const QDateTime &starttime)
Definition: programinfo.cpp:5794
RecordingRule::m_category
QString m_category
Definition: recordingrule.h:82
RecordingRule::Save
bool Save(bool sendSig=true)
Definition: recordingrule.cpp:388
JobQueue::QueueJob
static bool QueueJob(int jobType, uint chanid, const QDateTime &recstartts, const QString &args="", const QString &comment="", QString host="", int flags=0, int status=JOB_QUEUED, QDateTime schedruntime=QDateTime())
Definition: jobqueue.cpp:513
RecordingRule::m_starttime
QTime m_starttime
Definition: recordingrule.h:91
RecordingInfo::ApplyRecordStateChange
void ApplyRecordStateChange(RecordingType newstate, bool save=true)
Sets RecordingType of "record", creating "record" if it does not exist.
Definition: recordinginfo.cpp:573
Scheduler::kSortPriority
@ kSortPriority
Definition: scheduler.h:87
FillUpcomingList
int FillUpcomingList(QVariantList &list, QObject *parent, int &nStartIndex, int &nCount, bool bShowAll, int nRecordId, int nRecStatus)
Definition: v2serviceUtil.cpp:763
searchTypeFromString
RecSearchType searchTypeFromString(const QString &type)
Definition: recordingtypes.cpp:329
V2Dvr::GetRecordedList
V2ProgramList * GetRecordedList(bool Descending, int StartIndex, int Count, const QString &TitleRegEx, const QString &RecGroup, const QString &StorageGroup, const QString &Category, const QString &Sort, bool IgnoreLiveTV, bool IgnoreDeleted, bool IncChannel, bool Details, bool IncCast, bool IncArtWork, bool IncRecording)
Definition: v2dvr.cpp:128
V2FillCommBreak
void V2FillCommBreak(V2CutList *pCutList, ProgramInfo *rInfo, int marktype)
Definition: v2serviceUtil.cpp:636
dupInFromString
RecordingDupInType dupInFromString(const QString &type)
Definition: recordingtypes.cpp:216
V2Dvr::DeleteRecording
static bool DeleteRecording(int RecordedId, int ChanId, const QDateTime &StartTime, bool ForceDelete, bool AllowRerecord)
Definition: v2dvr.cpp:590
Scheduler::GetAllScheduled
static void GetAllScheduled(QStringList &strList, SchedSortColumn sortBy=kSortTitle, bool ascending=true)
Returns all scheduled programs serialized into a QStringList.
Definition: scheduler.cpp:1843
RecordingInfo
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:35
gExpirer
AutoExpire * gExpirer
Definition: backendcontext.cpp:8
RecordingInfo::ForgetHistory
void ForgetHistory(void)
Forget the recording of a program so it will be recorded again.
Definition: recordinginfo.cpp:1459
ProgramInfo::QueryMarkup
void QueryMarkup(QVector< MarkupEntry > &mapMark, QVector< MarkupEntry > &mapSeek) const
Definition: programinfo.cpp:4562
programdata.h
ProgramInfo::GetRecordingID
uint GetRecordingID(void) const
Definition: programinfo.h:446
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
RecordingRule::m_title
QString m_title
Definition: recordingrule.h:77
JOB_COMMFLAG
@ JOB_COMMFLAG
Definition: jobqueue.h:81
ProgramInfo::QueryJobsRunning
static QMap< QString, bool > QueryJobsRunning(int type)
Definition: programinfo.cpp:5479
ProgramInfo::QueryPositionKeyFrame
bool QueryPositionKeyFrame(uint64_t *keyframe, uint64_t position, bool backwards) const
Definition: programinfo.cpp:4190
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:205
AutoExpire
Used to expire recordings to make space for new recordings.
Definition: autoexpire.h:60
JOB_NONE
@ JOB_NONE
Definition: jobqueue.h:77
V2ProgramList
Definition: v2programList.h:22
RecordingRule
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:28
JobQueue::SafeDeleteJob
static bool SafeDeleteJob(int jobID, int jobType, int chanid, const QDateTime &recstartts)
Definition: jobqueue.cpp:876
RecordingDupMethodType
RecordingDupMethodType
Definition: recordingtypes.h:62
RecordingRule::m_endOffset
int m_endOffset
Definition: recordingrule.h:110
mythhttpmetaservice.h
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:617
V2Dvr::DupInToString
static QString DupInToString(const QString &DupIn)
Definition: v2dvr.cpp:1981
ProgramInfo::SaveCommFlagged
void SaveCommFlagged(CommFlagStatus flag)
Set "commflagged" field in "recorded" table to "flag".
Definition: programinfo.cpp:3341
RecStatus::Recorded
@ Recorded
Definition: recordingstatus.h:29
V2Dvr::AddRecordSchedule
static uint AddRecordSchedule(const QString &Title, const QString &Subtitle, const QString &Description, const QString &Category, const QDateTime &StartTime, const QDateTime &EndTime, const QString &SeriesId, const QString &ProgramId, int ChanId, const QString &Station, int FindDay, QTime FindTime, int ParentId, bool Inactive, uint Season, uint Episode, const QString &Inetref, QString Type, QString SearchType, int RecPriority, uint PreferredInput, int StartOffset, int EndOffset, const QDateTime &LastRecorded, QString DupMethod, QString DupIn, bool NewEpisOnly, uint Filter, QString RecProfile, QString RecGroup, QString StorageGroup, QString PlayGroup, bool AutoExpire, int MaxEpisodes, bool MaxNewest, bool AutoCommflag, bool AutoTranscode, bool AutoMetaLookup, bool AutoUserJob1, bool AutoUserJob2, bool AutoUserJob3, bool AutoUserJob4, int Transcoder, const QString &AutoExtend)
Definition: v2dvr.cpp:1381
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
playgroup.h
V2Dvr::GetRecRuleFilterList
static V2RecRuleFilterList * GetRecRuleFilterList()
Definition: v2dvr.cpp:1223
DVR_HANDLE
#define DVR_HANDLE
Definition: v2dvr.h:40
ProgramInfo::QueryKeyFrameDuration
bool QueryKeyFrameDuration(uint64_t *duration, uint64_t keyframe, bool backwards) const
Definition: programinfo.cpp:4217
LoadFromRecorded
bool LoadFromRecorded(ProgramList &destination, bool possiblyInProgressRecordingsOnly, const QMap< QString, uint32_t > &inUseMap, const QMap< QString, bool > &isJobRunning, const QMap< QString, ProgramInfo * > &recMap, int sort, const QString &sortBy, bool ignoreLiveTV, bool ignoreDeleted)
Definition: programinfo.cpp:5996
AutoExpire::GetAllExpiring
void GetAllExpiring(QStringList &strList)
Gets the full list of programs that can expire in expiration order.
Definition: autoexpire.cpp:834
V2EncoderList
Definition: v2encoderList.h:20
RecordingRule::IsLoaded
bool IsLoaded() const
Definition: recordingrule.h:55
V2Dvr::RecTypeToDescription
static QString RecTypeToDescription(const QString &RecType)
Definition: v2dvr.cpp:1971
V2Dvr::GetSavedBookmark
static long GetSavedBookmark(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType)
Definition: v2dvr.cpp:769
V2Dvr::SetSavedBookmark
static bool SetSavedBookmark(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType, long Offset)
Definition: v2dvr.cpp:853
RecordingRule::m_dupIn
RecordingDupInType m_dupIn
Definition: recordingrule.h:114
RecordingRule::m_isInactive
bool m_isInactive
Recording rule is enabled?
Definition: recordingrule.h:74
v2dvr.h
RecordingRule::m_season
uint m_season
Definition: recordingrule.h:94
scheduler.h
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
V2Dvr::GetProgramCategories
static QStringList GetProgramCategories(bool OnlyRecorded)
Definition: v2dvr.cpp:1179
ProgramInfo::GetRecordingStartTime
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:404
ProgramInfo::IsWatched
bool IsWatched(void) const
Definition: programinfo.h:482
V2Dvr::GetConflictList
static V2ProgramList * GetConflictList(int StartIndex, int Count, int RecordId)
Definition: v2dvr.cpp:1321
DBCredits
std::vector< DBPerson > DBCredits
Definition: programdata.h:73
RecStatus::toString
static QString toString(RecStatus::Type recstatus, uint id)
Converts "recstatus" into a short (unreadable) string.
Definition: recordingstatus.cpp:40
JobQueue::InJobRunWindow
static bool InJobRunWindow(QDateTime jobstarttsRaw)
Definition: jobqueue.cpp:1653
ProgramInfo::IsPreserved
bool IsPreserved(void) const
Definition: programinfo.h:484
string_to_myth_category_type
ProgramInfo::CategoryType string_to_myth_category_type(const QString &category_type)
Definition: programinfo.cpp:137
ProgramInfo::QueryBookmark
uint64_t QueryBookmark(void) const
Gets any bookmark position in database, unless the ignore bookmark flag is set.
Definition: programinfo.cpp:2801
PlayGroup::GetNames
static QStringList GetNames(void)
Definition: playgroup.cpp:206
COMM_FLAG_DONE
@ COMM_FLAG_DONE
Definition: programtypes.h:123
V2Dvr::EnableRecordSchedule
static bool EnableRecordSchedule(uint RecordId)
Definition: v2dvr.cpp:1866
MythScheduler::GetRecording
virtual QMap< QString, ProgramInfo * > GetRecording(void) const =0
RecordingRule::Load
bool Load(bool asTemplate=false)
Load a single rule from the recorded table.
Definition: recordingrule.cpp:56
V2Dvr::RecStatusToDescription
static QString RecStatusToDescription(const QString &RecStatus, int RecType, const QDateTime &StartTime)
Definition: v2dvr.cpp:1943
RecordingRule::m_startOffset
int m_startOffset
Definition: recordingrule.h:109
kDisableAutoExpire
@ kDisableAutoExpire
Definition: programtypes.h:195
RecordingDupInType
RecordingDupInType
Definition: recordingtypes.h:45
V2Dvr::DisableRecordSchedule
static bool DisableRecordSchedule(uint RecordId)
Definition: v2dvr.cpp:1886
V2FillInputInfo
void V2FillInputInfo(V2Input *input, const InputInfo &inputInfo)
Definition: v2serviceUtil.cpp:505
V2Dvr::RegisterCustomTypes
static void RegisterCustomTypes()
RecordingRule::m_episode
uint m_episode
Definition: recordingrule.h:95
autoexpire.h
ProgramInfo::MarkupEntry::type
int type
Definition: programinfo.h:694
V2Dvr::AddDontRecordSchedule
static bool AddDontRecordSchedule(int ChanId, const QDateTime &StartTime, bool NeverRecord)
Definition: v2dvr.cpp:1723
V2Dvr::UnDeleteRecording
static bool UnDeleteRecording(int RecordedId, int ChanId, const QDateTime &StartTime)
Definition: v2dvr.cpp:625
programinfo.h
CardUtil::GetAllInputInfo
static QList< InputInfo > GetAllInputInfo()
Definition: cardutil.cpp:1730
ProgramInfo::GetScheduledStartTime
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:390
ProgramInfo::QueryRecordedIdFromPathname
static bool QueryRecordedIdFromPathname(const QString &pathname, uint &recordedid)
Definition: programinfo.cpp:1233
RecordingRule::IsValid
bool IsValid(QString &msg) const
Definition: recordingrule.cpp:855
kNormalAutoExpire
@ kNormalAutoExpire
Definition: programtypes.h:196
v2serviceUtil.h
v2titleInfoList.h
RecordingRule::m_autoUserJob4
bool m_autoUserJob4
Definition: recordingrule.h:136
V2FillRecRuleInfo
void V2FillRecRuleInfo(V2RecRule *pRecRule, RecordingRule *pRule)
Definition: v2serviceUtil.cpp:253
Scheduler::kSortType
@ kSortType
Definition: scheduler.h:87
MARK_DURATION_MS
@ MARK_DURATION_MS
Definition: programtypes.h:75
ProgramInfo::MarkupEntry::data
uint64_t data
Definition: programinfo.h:696
RecStatus::toDescription
static QString toDescription(Type recstatus, RecordingType rectype, const QDateTime &recstartts)
Converts "recstatus" into a long human readable description.
Definition: recordingstatus.cpp:188
FillEncoderList
void FillEncoderList(QVariantList &list, QObject *parent)
Definition: v2serviceUtil.cpp:700
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:549
RecordingRule::m_autoUserJob2
bool m_autoUserJob2
Definition: recordingrule.h:134
V2Dvr::GetRecorded
static V2Program * GetRecorded(int RecordedId, int ChanId, const QDateTime &StartTime)
Definition: v2dvr.cpp:368
V2Dvr::RecStatusToString
static QString RecStatusToString(const QString &RecStatus)
Definition: v2dvr.cpp:1927
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
Scheduler::kSortLastRecorded
@ kSortLastRecorded
Definition: scheduler.h:86
V2FillSeek
void V2FillSeek(V2CutList *pCutList, RecordingInfo *rInfo, MarkTypes marktype)
Definition: v2serviceUtil.cpp:682
RecordingRule::m_findtime
QTime m_findtime
Time for timeslot rules.
Definition: recordingrule.h:101
dupMethodFromString
RecordingDupMethodType dupMethodFromString(const QString &type)
Definition: recordingtypes.cpp:293
RecordingRule::m_lastRecorded
QDateTime m_lastRecorded
Definition: recordingrule.h:143
RecordingRule::m_autoExpire
bool m_autoExpire
Definition: recordingrule.h:126
markTypeFromString
MarkTypes markTypeFromString(const QString &str)
Definition: programtypes.cpp:68
RecordingRule::m_recProfile
QString m_recProfile
Definition: recordingrule.h:120
V2Dvr::UpdateRecordedWatchedStatus
static bool UpdateRecordedWatchedStatus(int RecordedId, int ChanId, const QDateTime &StartTime, bool Watched)
Definition: v2dvr.cpp:738
V2RecRuleFilterList
Definition: v2recRuleFilterList.h:12
RecordingRule::m_searchType
RecSearchType m_searchType
Definition: recordingrule.h:112
pginfolist_t
std::vector< ProgramInfo * > pginfolist_t
Definition: autoexpire.h:24
recTypeFromString
RecordingType recTypeFromString(const QString &type)
Definition: recordingtypes.cpp:101
RecordingRule::m_type
RecordingType m_type
Definition: recordingrule.h:111
Scheduler::kSortTitle
@ kSortTitle
Definition: scheduler.h:86
RecStatus::Conflict
@ Conflict
Definition: recordingstatus.h:39
V2Dvr::GetRecordScheduleList
static V2RecRuleList * GetRecordScheduleList(int StartIndex, int Count, const QString &Sort, bool Descending)
Definition: v2dvr.cpp:1751
RecordingRule::m_subtitle
QString m_subtitle
Definition: recordingrule.h:79
dupInFromStringAndBool
RecordingDupInType dupInFromStringAndBool(const QString &type, bool newEpisodesOnly)
Definition: recordingtypes.cpp:229
ProgramInfo::MarkupEntry
Definition: programinfo.h:692
V2CutList
Definition: v2cutList.h:21
storagegroup.h
V2Dvr::GetRecStorageGroupList
static QStringList GetRecStorageGroupList()
Definition: v2dvr.cpp:1205
V2Dvr::SetLastPlayPos
static bool SetLastPlayPos(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType, long Offset)
Definition: v2dvr.cpp:894
V2Dvr::GetRecordedMarkup
static V2MarkupList * GetRecordedMarkup(int RecordedId)
Definition: v2dvr.cpp:1024
jobqueue.h
RecordingRule::m_findday
int m_findday
Day of the week for once per week etc.
Definition: recordingrule.h:104
Scheduler::SchedSortColumn
SchedSortColumn
Definition: scheduler.h:86
RecordingRule::m_filter
unsigned m_filter
Definition: recordingrule.h:115
RecordingInfo::ReactivateRecording
void ReactivateRecording(void)
Asks the scheduler to restart this recording if possible.
Definition: recordinginfo.cpp:1329
V2Dvr::GetExpiringList
static V2ProgramList * GetExpiringList(int StartIndex, int Count)
Definition: v2dvr.cpp:84
kManualSearch
@ kManualSearch
Definition: recordingtypes.h:85
uint
unsigned int uint
Definition: compat.h:81
ProgramInfo::ProgramFlagsFromNames
void ProgramFlagsFromNames(const QString &names)
Definition: programinfo.cpp:1534
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
V2Dvr::DupMethodToString
static QString DupMethodToString(const QString &DupMethod)
Definition: v2dvr.cpp:1995
toDescription
QString toDescription(RecordingType rectype)
Converts "rectype" into a human readable description.
Definition: recordingtypes.cpp:50
RecordingInfo::LoadStatus
LoadStatus
Definition: recordinginfo.h:180
RecordingInfo::kNoProgram
@ kNoProgram
Definition: recordinginfo.h:181
V2CreateRecordingGroup
int V2CreateRecordingGroup(const QString &groupName)
Definition: v2serviceUtil.cpp:859
MythHTTPService
Definition: mythhttpservice.h:19
V2Dvr::UpdateRecordSchedule
static bool UpdateRecordSchedule(uint RecordId, const QString &Title, const QString &Subtitle, const QString &Description, const QString &Category, const QDateTime &StartTime, const QDateTime &EndTime, const QString &SeriesId, const QString &ProgramId, int ChanId, const QString &Station, int FindDay, QTime FindTime, bool Inactive, uint Season, uint Episode, const QString &Inetref, QString Type, QString SearchType, int RecPriority, uint PreferredInput, int StartOffset, int EndOffset, QString DupMethod, QString DupIn, bool NewEpisOnly, uint Filter, QString RecProfile, QString RecGroup, QString StorageGroup, QString PlayGroup, bool AutoExpire, int MaxEpisodes, bool MaxNewest, bool AutoCommflag, bool AutoTranscode, bool AutoMetaLookup, bool AutoUserJob1, bool AutoUserJob2, bool AutoUserJob3, bool AutoUserJob4, int Transcoder, const QString &AutoExtend)
Definition: v2dvr.cpp:1537
RecordingRule::m_maxEpisodes
int m_maxEpisodes
Definition: recordingrule.h:125
ProgramInfo::AudioPropertiesFromNames
static uint AudioPropertiesFromNames(const QString &names)
Definition: programinfo.cpp:1529
Stars
@ Stars
Definition: synaesthesia.h:26
RecordingRule::m_programid
QString m_programid
Definition: recordingrule.h:85
ProgramInfo::SaveAutoExpire
void SaveAutoExpire(AutoExpireType autoExpire, bool updateDelete=false)
Set "autoexpire" field in "recorded" table to "autoExpire".
Definition: programinfo.cpp:3394
channelutil.h
V2Dvr::GetOldRecordedList
static V2ProgramList * GetOldRecordedList(bool Descending, int StartIndex, int Count, const QDateTime &StartTime, const QDateTime &EndTime, const QString &Title, const QString &SeriesId, int RecordId, const QString &Sort)
Definition: v2dvr.cpp:251
V2Dvr::RemoveRecordSchedule
static bool RemoveRecordSchedule(uint RecordId)
Definition: v2dvr.cpp:1708
ProgramInfo::SubtitleTypesFromNames
static uint SubtitleTypesFromNames(const QString &names)
Definition: programinfo.cpp:1519
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:34
RecordingRule::m_recGroupID
uint m_recGroupID
Definition: recordingrule.h:123
RecordingRule::m_endtime
QTime m_endtime
Definition: recordingrule.h:92
AutoDeleteDeque< ProgramInfo * >
V2Dvr::RescheduleRecordings
static bool RescheduleRecordings(void)
Definition: v2dvr.cpp:708
V2Dvr::GetTitleList
static QStringList GetTitleList(const QString &RecGroup)
Definition: v2dvr.cpp:1250
RecordingRule::m_storageGroup
QString m_storageGroup
Definition: recordingrule.h:121
ProgramInfo::GetChanID
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:372
RecordingRule::m_transcoder
int m_transcoder
Definition: recordingrule.h:130
RecordingRule::m_autoUserJob1
bool m_autoUserJob1
Definition: recordingrule.h:133
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
RecordingRule::LoadTemplate
bool LoadTemplate(const QString &title, const QString &category="Default", const QString &categoryType="Default")
Definition: recordingrule.cpp:274
RecordingRule::m_recordID
int m_recordID
Unique Recording Rule ID.
Definition: recordingrule.h:70
ProgramInfo::QueryKeyFramePosition
bool QueryKeyFramePosition(uint64_t *position, uint64_t keyframe, bool backwards) const
Definition: programinfo.cpp:4199
V2Dvr::ReactivateRecording
static bool ReactivateRecording(int RecordedId, int ChanId, const QDateTime &StartTime)
Definition: v2dvr.cpp:682
V2Dvr::RecTypeToString
static QString RecTypeToString(const QString &RecType)
Definition: v2dvr.cpp:1961
mythscheduler.h
mythcorecontext.h
V2Dvr::GetLastPlayPos
static long GetLastPlayPos(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType)
Definition: v2dvr.cpp:811
JobQueue::GetJobTypeFromName
static int GetJobTypeFromName(const QString &name)
Definition: jobqueue.cpp:703
cardutil.h
kOverrideRecord
@ kOverrideRecord
Definition: recordingtypes.h:29
MARK_GOP_BYFRAME
@ MARK_GOP_BYFRAME
Definition: programtypes.h:65
RecordingInfo::InsertRecording
bool InsertRecording(const QString &ext, bool force_match=false)
Definition: recordinginfo.cpp:1040
RecordingRule::m_dupMethod
RecordingDupMethodType m_dupMethod
Definition: recordingrule.h:113
autoExtendTypeFromString
AutoExtendType autoExtendTypeFromString(const QString &type)
Definition: recordingtypes.cpp:383
ProgramInfo::IsCommercialFlagged
bool IsCommercialFlagged(void) const
Definition: programinfo.h:478
V2Dvr::AddRecordedCredits
static bool AddRecordedCredits(int RecordedId, const QString &Cast)
Definition: v2dvr.cpp:392
JobQueue::GetJobID
static int GetJobID(int jobType, uint chanid, const QDateTime &recstartts)
Definition: jobqueue.cpp:643
V2Dvr::StopRecording
static bool StopRecording(int RecordedId)
Definition: v2dvr.cpp:656
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:887
kDupCheckNone
@ kDupCheckNone
Definition: recordingtypes.h:65
MarkTypes
MarkTypes
Definition: programtypes.h:48
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
ProgInfo
Definition: programdata.h:226
V2FillCutList
void V2FillCutList(V2CutList *pCutList, ProgramInfo *rInfo, int marktype)
Definition: v2serviceUtil.cpp:594
kSingleRecord
@ kSingleRecord
Definition: recordingtypes.h:23
V2Dvr::GetEncoderList
static V2EncoderList * GetEncoderList()
Definition: v2dvr.cpp:1127
V2Dvr::GetTitleInfoList
static V2TitleInfoList * GetTitleInfoList()
Definition: v2dvr.cpp:1286
ProgramInfo::QueryInUseMap
static QMap< QString, uint32_t > QueryInUseMap(void)
Definition: programinfo.cpp:5443
V2Markup
Definition: v2markup.h:21
ProgramInfo::SaveWatched
void SaveWatched(bool watchedFlag)
Set "watched" field in recorded/videometadata to "watchedFlag".
Definition: programinfo.cpp:3052
V2Dvr::DupInToDescription
static QString DupInToDescription(const QString &DupIn)
Definition: v2dvr.cpp:1988
RecList
std::deque< RecordingInfo * > RecList
Definition: mythscheduler.h:12
ProgramInfo::IsAutoExpirable
bool IsAutoExpirable(void) const
Definition: programinfo.h:483
V2Program
Definition: v2programAndChannel.h:105
RecordingRule::m_autoExtend
AutoExtendType m_autoExtend
Definition: recordingrule.h:116
V2Dvr::GetInputList
static V2InputList * GetInputList()
Definition: v2dvr.cpp:1138
marks
static const std::array< const mark, 16 > marks
Definition: lang.cpp:23
ProgramInfo::SendUpdateEvent
void SendUpdateEvent(void) const
Sends event out that the ProgramInfo should be reloaded.
Definition: programinfo.cpp:2755
tv_rec.h
ProgramInfo::SavePreserve
void SavePreserve(bool preserveEpisode)
Set "preserve" field in "recorded" table to "preserveEpisode".
Definition: programinfo.cpp:3367
ProgramInfo::MarkupEntry::isDataNull
bool isDataNull
Definition: programinfo.h:697
V2Dvr::DupMethodToDescription
static QString DupMethodToDescription(const QString &DupMethod)
Definition: v2dvr.cpp:2001
RecStatus
Definition: recordingstatus.h:11
V2Dvr::GetRecGroupList
static QStringList GetRecGroupList()
Definition: v2dvr.cpp:1156
V2Dvr::RecordedIdForKey
static int RecordedIdForKey(int ChanId, const QDateTime &StartTime)
Definition: v2dvr.cpp:1906
JOB_NO_FLAGS
@ JOB_NO_FLAGS
Definition: jobqueue.h:61
LoadFromOldRecorded
bool LoadFromOldRecorded(ProgramList &destination, const QString &sql, const MSqlBindings &bindings)
Definition: programinfo.cpp:5830
RecordingRule::Delete
bool Delete(bool sendSig=true)
Definition: recordingrule.cpp:507
V2Dvr::GetRecordedCommBreak
static V2CutList * GetRecordedCommBreak(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType)
Definition: v2dvr.cpp:961
RecordingRule::MakeOverride
bool MakeOverride(void)
Definition: recordingrule.cpp:366
MARK_UNSET
@ MARK_UNSET
Definition: programtypes.h:51
ProgramInfo::MarkupEntry::frame
uint64_t frame
Definition: programinfo.h:695
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:837
ProgramInfo::SaveMarkup
void SaveMarkup(const QVector< MarkupEntry > &mapMark, const QVector< MarkupEntry > &mapSeek) const
Definition: programinfo.cpp:4643
V2Dvr::GetUpcomingList
static V2ProgramList * GetUpcomingList(int StartIndex, int Count, bool ShowAll, int RecordId, const QString &RecStatus)
Definition: v2dvr.cpp:1343
MythHTTPService::m_request
HTTPRequest2 m_request
Definition: mythhttpservice.h:35
ProgramInfo::QueryLastPlayPos
uint64_t QueryLastPlayPos(void) const
Gets any lastplaypos position in database, unless the ignore lastplaypos flag is set.
Definition: programinfo.cpp:2828
MythCoreContext::GetBoolSettingOnHost
bool GetBoolSettingOnHost(const QString &key, const QString &host, bool defaultval=false)
Definition: mythcorecontext.cpp:934
musicbrainzngs.caa.hostname
string hostname
Definition: caa.py:17
V2RecRuleFilter
Definition: v2recRuleFilter.h:12
V2Dvr::GetRecordedCutList
static V2CutList * GetRecordedCutList(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType)
Definition: v2dvr.cpp:928
RecordingRule::m_station
QString m_station
Definition: recordingrule.h:98
ChannelUtil::GetChanNum
static QString GetChanNum(int chan_id)
Returns the channel-number string of the given channel.
Definition: channelutil.cpp:775
RecordingInfo::GetRecordingRule
RecordingRule * GetRecordingRule(void)
Returns the "record" field, creating it if necessary.
Definition: recordinginfo.cpp:926
V2RecRuleList
Definition: v2recRuleList.h:11
ProgramInfo::QueryDurationKeyFrame
bool QueryDurationKeyFrame(uint64_t *keyframe, uint64_t duration, bool backwards) const
Definition: programinfo.cpp:4208
RecordingRule::m_recPriority
int m_recPriority
Definition: recordingrule.h:107
build_compdb.filename
filename
Definition: build_compdb.py:21
RecordingRule::m_autoUserJob3
bool m_autoUserJob3
Definition: recordingrule.h:135
V2MarkupList
Definition: v2markupList.h:21
V2Dvr::RemoveRecorded
static bool RemoveRecorded(int RecordedId, int ChanId, const QDateTime &StartTime, bool ForceDelete, bool AllowRerecord)
Definition: v2dvr.cpp:581
Q_GLOBAL_STATIC_WITH_ARGS
Q_GLOBAL_STATIC_WITH_ARGS(MythHTTPMetaService, s_service,(DVR_HANDLE, V2Dvr::staticMetaObject, &V2Dvr::RegisterCustomTypes)) void V2Dvr
Definition: v2dvr.cpp:50
V2TitleInfoList
Definition: v2titleInfoList.h:20
ScheduledRecording::RescheduleMatch
static void RescheduleMatch(uint recordid, uint sourceid, uint mplexid, const QDateTime &maxstarttime, const QString &why)
Definition: scheduledrecording.h:17
MythCoreContext::dispatch
void dispatch(const MythEvent &event)
Definition: mythcorecontext.cpp:1722
RecordingType
RecordingType
Definition: recordingtypes.h:20
V2TitleInfo
Definition: v2titleInfo.h:20
V2Input
Definition: v2input.h:20
kDontRecord
@ kDontRecord
Definition: recordingtypes.h:30
MythHTTPMetaService
Definition: mythhttpmetaservice.h:10
RecordingRule::m_startdate
QDate m_startdate
Definition: recordingrule.h:89
RecordingRule::m_autoMetadataLookup
bool m_autoMetadataLookup
Definition: recordingrule.h:137
V2Dvr::AddRecordedProgram
static int AddRecordedProgram(const QString &Program)
Definition: v2dvr.cpp:421
ProgramInfo::HasPathname
bool HasPathname(void) const
Definition: programinfo.h:358
ProgramInfo::VideoPropertiesFromNames
static uint VideoPropertiesFromNames(const QString &names)
Definition: programinfo.cpp:1524
V2Dvr::ManageJobQueue
int ManageJobQueue(const QString &Action, const QString &JobName, int JobId, int RecordedId, QDateTime JobStartTime, QString RemoteHost, QString JobArgs)
Definition: v2dvr.cpp:2011
AutoDeleteDeque::size
size_t size(void) const
Definition: autodeletedeque.h:67
RecordingRule::m_prefInput
int m_prefInput
Definition: recordingrule.h:108
ProgramInfo::SaveLastPlayPos
void SaveLastPlayPos(uint64_t frame)
TODO Move to RecordingInfo.
Definition: programinfo.cpp:2714
V2jsonCastToCredits
DBCredits * V2jsonCastToCredits(const QJsonObject &cast)
Definition: v2serviceUtil.cpp:879
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:897
RecordingInfo::InsertFile
void InsertFile(void)
Definition: recordinginfo.cpp:1247
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:836
V2RecRule
Definition: v2recRule.h:12
JOB_USERJOB
@ JOB_USERJOB
Definition: jobqueue.h:85
V2Dvr::V2Dvr
V2Dvr()
Definition: v2dvr.cpp:79
V2Dvr::SetRecordedMarkup
static bool SetRecordedMarkup(int RecordedId, const QString &MarkupList)
Definition: v2dvr.cpp:1069