MythTV  master
dvr.cpp
Go to the documentation of this file.
1 // Program Name: dvr.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 #include <QMap>
27 #include <QRegExp>
28 
29 #include "dvr.h"
30 
31 #include "compat.h"
32 #include "mythversion.h"
33 #include "mythcorecontext.h"
34 #include "mythevent.h"
35 #include "scheduler.h"
36 #include "autoexpire.h"
37 #include "jobqueue.h"
38 #include "encoderlink.h"
39 #include "remoteutil.h"
40 #include "mythdate.h"
41 #include "recordinginfo.h"
42 #include "cardutil.h"
43 #include "inputinfo.h"
44 #include "programtypes.h"
45 #include "recordingtypes.h"
46 
47 #include "serviceUtil.h"
48 #include "mythscheduler.h"
49 #include "storagegroup.h"
50 #include "playgroup.h"
51 #include "recordingprofile.h"
52 
53 #include "scheduler.h"
54 #include "tv_rec.h"
55 
56 extern QMap<int, EncoderLink *> tvList;
57 extern AutoExpire *expirer;
58 
60 //
62 
64  int nStartIndex,
65  int nCount,
66  const QString &sTitleRegEx,
67  const QString &sRecGroup,
68  const QString &sStorageGroup,
69  const QString &sCategory,
70  const QString &sSort
71  )
72 {
73  QMap< QString, ProgramInfo* > recMap;
74 
76  recMap = gCoreContext->GetScheduler()->GetRecording();
77 
78  QMap< QString, uint32_t > inUseMap = ProgramInfo::QueryInUseMap();
79  QMap< QString, bool > isJobRunning= ProgramInfo::QueryJobsRunning(JOB_COMMFLAG);
80 
81  ProgramList progList;
82 
83  int desc = 1;
84  if (bDescending)
85  desc = -1;
86 
87  LoadFromRecorded( progList, false, inUseMap, isJobRunning, recMap, desc, sSort );
88 
89  QMap< QString, ProgramInfo* >::iterator mit = recMap.begin();
90 
91  for (; mit != recMap.end(); mit = recMap.erase(mit))
92  delete *mit;
93 
94  // ----------------------------------------------------------------------
95  // Build Response
96  // ----------------------------------------------------------------------
97 
98  DTC::ProgramList *pPrograms = new DTC::ProgramList();
99  int nAvailable = 0;
100 
101  int nMax = (nCount > 0) ? nCount : progList.size();
102 
103  nAvailable = 0;
104  nCount = 0;
105 
106  QRegExp rTitleRegEx = QRegExp(sTitleRegEx, Qt::CaseInsensitive);
107 
108  for( unsigned int n = 0; n < progList.size(); n++)
109  {
110  ProgramInfo *pInfo = progList[ n ];
111 
112  if (pInfo->IsDeletePending() ||
113  (!sTitleRegEx.isEmpty() && !pInfo->GetTitle().contains(rTitleRegEx)) ||
114  (!sRecGroup.isEmpty() && sRecGroup != pInfo->GetRecordingGroup()) ||
115  (!sStorageGroup.isEmpty() && sStorageGroup != pInfo->GetStorageGroup()) ||
116  (!sCategory.isEmpty() && sCategory != pInfo->GetCategory()))
117  continue;
118 
119  if ((nAvailable < nStartIndex) ||
120  (nCount >= nMax))
121  {
122  ++nAvailable;
123  continue;
124  }
125 
126  ++nAvailable;
127  ++nCount;
128 
129  DTC::Program *pProgram = pPrograms->AddNewProgram();
130 
131  FillProgramInfo( pProgram, pInfo, true );
132  }
133 
134  // ----------------------------------------------------------------------
135 
136  pPrograms->setStartIndex ( nStartIndex );
137  pPrograms->setCount ( nCount );
138  pPrograms->setTotalAvailable( nAvailable );
139  pPrograms->setAsOf ( MythDate::current() );
140  pPrograms->setVersion ( MYTH_BINARY_VERSION );
141  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
142 
143  return pPrograms;
144 }
145 
147 //
149 
151  int nStartIndex,
152  int nCount,
153  const QDateTime &sStartTime,
154  const QDateTime &sEndTime,
155  const QString &sTitle,
156  const QString &sSeriesId,
157  int nRecordId,
158  const QString &sSort)
159 {
160  if (!sStartTime.isNull() && !sStartTime.isValid())
161  throw QString("StartTime is invalid");
162 
163  if (!sEndTime.isNull() && !sEndTime.isValid())
164  throw QString("EndTime is invalid");
165 
166  QDateTime dtStartTime = sStartTime;
167  QDateTime dtEndTime = sEndTime;
168 
169  if (!sEndTime.isNull() && dtEndTime < dtStartTime)
170  throw QString("EndTime is before StartTime");
171 
172  // ----------------------------------------------------------------------
173  // Build SQL statement for Program Listing
174  // ----------------------------------------------------------------------
175 
176  ProgramList progList;
177  MSqlBindings bindings;
178  QString sSQL;
179 
180  if (!dtStartTime.isNull())
181  {
182  sSQL += " AND endtime >= :StartDate ";
183  bindings[":StartDate"] = dtStartTime;
184  }
185 
186  if (!dtEndTime.isNull())
187  {
188  sSQL += " AND starttime <= :EndDate ";
189  bindings[":EndDate"] = dtEndTime;
190  }
191 
192  QStringList clause;
193 
194  if (nRecordId > 0)
195  {
196  clause << "recordid = :RecordId";
197  bindings[":RecordId"] = nRecordId;
198  }
199 
200  if (!sTitle.isEmpty())
201  {
202  clause << "title = :Title";
203  bindings[":Title"] = sTitle;
204  }
205 
206  if (!sSeriesId.isEmpty())
207  {
208  clause << "seriesid = :SeriesId";
209  bindings[":SeriesId"] = sSeriesId;
210  }
211 
212  if (!clause.isEmpty())
213  {
214  sSQL += QString(" AND (%1) ").arg(clause.join(" OR "));
215  }
216 
217  if (sSort == "starttime")
218  sSQL += "ORDER BY starttime ";
219  else if (sSort == "title")
220  sSQL += "ORDER BY title ";
221  else
222  sSQL += "ORDER BY starttime ";
223 
224  if (bDescending)
225  sSQL += "DESC ";
226  else
227  sSQL += "ASC ";
228 
229  uint nTotalAvailable = (nStartIndex == 0) ? 1 : 0;
230  LoadFromOldRecorded( progList, sSQL, bindings,
231  (uint)nStartIndex, (uint)nCount, nTotalAvailable );
232 
233  // ----------------------------------------------------------------------
234  // Build Response
235  // ----------------------------------------------------------------------
236 
237  DTC::ProgramList *pPrograms = new DTC::ProgramList();
238 
239  nCount = (int)progList.size();
240  int nEndIndex = (int)progList.size();
241 
242  for( int n = 0; n < nEndIndex; n++)
243  {
244  ProgramInfo *pInfo = progList[ n ];
245 
246  DTC::Program *pProgram = pPrograms->AddNewProgram();
247 
248  FillProgramInfo( pProgram, pInfo, true );
249  }
250 
251  // ----------------------------------------------------------------------
252 
253  pPrograms->setStartIndex ( nStartIndex );
254  pPrograms->setCount ( nCount );
255  pPrograms->setTotalAvailable( nTotalAvailable );
256  pPrograms->setAsOf ( MythDate::current() );
257  pPrograms->setVersion ( MYTH_BINARY_VERSION );
258  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
259 
260  return pPrograms;
261 }
262 
264 //
266 
268  int chanid, const QDateTime &recstarttsRaw)
269 {
270  if ((RecordedId <= 0) &&
271  (chanid <= 0 || !recstarttsRaw.isValid()))
272  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
273 
274  // TODO Should use RecordingInfo
275  ProgramInfo pi;
276  if (RecordedId > 0)
277  pi = ProgramInfo(RecordedId);
278  else
279  pi = ProgramInfo(chanid, recstarttsRaw.toUTC());
280 
281  DTC::Program *pProgram = new DTC::Program();
282  FillProgramInfo( pProgram, &pi, true );
283 
284  return pProgram;
285 }
286 
288 //
290 
291 bool Dvr::RemoveRecorded(int RecordedId,
292  int chanid, const QDateTime &recstarttsRaw,
293  bool forceDelete, bool allowRerecord)
294 {
295  return DeleteRecording(RecordedId, chanid, recstarttsRaw, forceDelete,
296  allowRerecord);
297 }
298 
299 
300 bool Dvr::DeleteRecording(int RecordedId,
301  int chanid, const QDateTime &recstarttsRaw,
302  bool forceDelete, bool allowRerecord)
303 {
304  if ((RecordedId <= 0) &&
305  (chanid <= 0 || !recstarttsRaw.isValid()))
306  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
307 
308  // TODO Should use RecordingInfo
309  ProgramInfo pi;
310  if (RecordedId > 0)
311  pi = ProgramInfo(RecordedId);
312  else
313  pi = ProgramInfo(chanid, recstarttsRaw.toUTC());
314 
315  if (pi.GetChanID() && pi.HasPathname())
316  {
317  QString cmd = QString("DELETE_RECORDING %1 %2 %3 %4")
318  .arg(pi.GetChanID())
320  .arg(forceDelete ? "FORCE" : "NO_FORCE")
321  .arg(allowRerecord ? "FORGET" : "NO_FORGET");
322  MythEvent me(cmd);
323 
324  gCoreContext->dispatch(me);
325  return true;
326  }
327 
328  return false;
329 }
330 
332 //
334 
335 bool Dvr::UnDeleteRecording(int RecordedId,
336  int chanid, const QDateTime &recstarttsRaw)
337 {
338  if ((RecordedId <= 0) &&
339  (chanid <= 0 || !recstarttsRaw.isValid()))
340  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
341 
342  RecordingInfo ri;
343  if (RecordedId > 0)
344  ri = RecordingInfo(RecordedId);
345  else
346  ri = RecordingInfo(chanid, recstarttsRaw.toUTC());
347 
348  if (ri.GetChanID() && ri.HasPathname())
349  {
350  QString cmd = QString("UNDELETE_RECORDING %1 %2")
351  .arg(ri.GetChanID())
353  MythEvent me(cmd);
354 
355  gCoreContext->dispatch(me);
356  return true;
357  }
358 
359  return false;
360 }
361 
363 //
365 
366 bool Dvr::StopRecording(int RecordedId)
367 {
368  if (RecordedId <= 0)
369  throw QString("RecordedId param is invalid.");
370 
371  RecordingInfo ri = RecordingInfo(RecordedId);
372 
373  if (ri.GetChanID())
374  {
375  QString cmd = QString("STOP_RECORDING %1 %2")
376  .arg(ri.GetChanID())
378  MythEvent me(cmd);
379 
380  gCoreContext->dispatch(me);
381  return true;
382  }
383  else
384  throw QString("RecordedId %1 not found").arg(RecordedId);
385 
386  return false;
387 }
388 
390 //
392 
393 bool Dvr::ReactivateRecording(int RecordedId)
394 {
395  if (RecordedId <= 0)
396  throw QString("RecordedId param is invalid.");
397 
398  RecordingInfo ri = RecordingInfo(RecordedId);
399 
400  ri.ReactivateRecording();
401 
402  return true;
403 }
404 
406 //
408 
410 {
411  QString cmd = QString("RESCHEDULE_RECORDINGS");
412  MythEvent me(cmd);
413 
414  gCoreContext->dispatch(me);
415  return true;
416 }
417 
419 //
421 
422 bool Dvr::UpdateRecordedWatchedStatus ( int RecordedId,
423  int chanid,
424  const QDateTime &recstarttsRaw,
425  bool watched)
426 {
427  if ((RecordedId <= 0) &&
428  (chanid <= 0 || !recstarttsRaw.isValid()))
429  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
430 
431  // TODO Should use RecordingInfo
432  ProgramInfo pi;
433  if (RecordedId > 0)
434  pi = ProgramInfo(RecordedId);
435  else
436  pi = ProgramInfo(chanid, recstarttsRaw.toUTC());
437 
438  if (pi.GetChanID() && pi.HasPathname())
439  {
440  pi.SaveWatched(watched);
441  return true;
442  }
443 
444  return false;
445 }
446 
448 //
450 
451 long Dvr::GetSavedBookmark( int RecordedId,
452  int chanid,
453  const QDateTime &recstarttsRaw,
454  const QString &offsettype )
455 {
456  if ((RecordedId <= 0) &&
457  (chanid <= 0 || !recstarttsRaw.isValid()))
458  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
459 
460  RecordingInfo ri;
461  if (RecordedId > 0)
462  ri = RecordingInfo(RecordedId);
463  else
464  ri = RecordingInfo(chanid, recstarttsRaw.toUTC());
465  uint64_t offset;
466  bool isend=true;
467  uint64_t position = ri.QueryBookmark();
468  if (offsettype.toLower() == "position"){
469  ri.QueryKeyFramePosition(&offset, position, isend);
470  return offset;
471  }
472  else if (offsettype.toLower() == "duration"){
473  ri.QueryKeyFrameDuration(&offset, position, isend);
474  return offset;
475  }
476  else
477  return position;
478 }
479 
481 //
483 
484 bool Dvr::SetSavedBookmark( int RecordedId,
485  int chanid,
486  const QDateTime &recstarttsRaw,
487  const QString &offsettype,
488  long Offset )
489 {
490  if ((RecordedId <= 0) &&
491  (chanid <= 0 || !recstarttsRaw.isValid()))
492  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
493 
494  if (Offset < 0)
495  throw QString("Offset must be >= 0.");
496 
497  RecordingInfo ri;
498  if (RecordedId > 0)
499  ri = RecordingInfo(RecordedId);
500  else
501  ri = RecordingInfo(chanid, recstarttsRaw.toUTC());
502  uint64_t position;
503  bool isend=true;
504  if (offsettype.toLower() == "position"){
505  if (!ri.QueryPositionKeyFrame(&position, Offset, isend))
506  return false;
507  }
508  else if (offsettype.toLower() == "duration"){
509  if (!ri.QueryDurationKeyFrame(&position, Offset, isend))
510  return false;
511  }
512  else
513  position = Offset;
514  ri.SaveBookmark(position);
515  return true;
516 }
517 
519 //
521 
523  int chanid,
524  const QDateTime &recstarttsRaw,
525  const QString &offsettype )
526 {
527  int marktype;
528  if ((RecordedId <= 0) &&
529  (chanid <= 0 || !recstarttsRaw.isValid()))
530  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
531 
532  RecordingInfo ri;
533  if (RecordedId > 0)
534  ri = RecordingInfo(RecordedId);
535  else
536  ri = RecordingInfo(chanid, recstarttsRaw.toUTC());
537 
538  DTC::CutList* pCutList = new DTC::CutList();
539  if (offsettype == "Position")
540  marktype = 1;
541  else if (offsettype == "Duration")
542  marktype = 2;
543  else
544  marktype = 0;
545 
546  FillCutList(pCutList, &ri, marktype);
547 
548  return pCutList;
549 }
550 
552 //
554 
556  int chanid,
557  const QDateTime &recstarttsRaw,
558  const QString &offsettype )
559 {
560  int marktype;
561  if ((RecordedId <= 0) &&
562  (chanid <= 0 || !recstarttsRaw.isValid()))
563  throw QString("Recorded ID or Channel ID and StartTime appears invalid.");
564 
565  RecordingInfo ri;
566  if (RecordedId > 0)
567  ri = RecordingInfo(RecordedId);
568  else
569  ri = RecordingInfo(chanid, recstarttsRaw.toUTC());
570 
571  DTC::CutList* pCutList = new DTC::CutList();
572  if (offsettype == "Position")
573  marktype = 1;
574  else if (offsettype == "Duration")
575  marktype = 2;
576  else
577  marktype = 0;
578 
579  FillCommBreak(pCutList, &ri, marktype);
580 
581  return pCutList;
582 }
583 
585 //
587 
589  const QString &offsettype )
590 {
591  MarkTypes marktype;
592  if (RecordedId <= 0)
593  throw QString("Recorded ID appears invalid.");
594 
595  RecordingInfo ri;
596  ri = RecordingInfo(RecordedId);
597 
598  DTC::CutList* pCutList = new DTC::CutList();
599  if (offsettype == "BYTES")
600  marktype = MARK_GOP_BYFRAME;
601  else if (offsettype == "DURATION")
602  marktype = MARK_DURATION_MS;
603  else
604  {
605  delete pCutList;
606  throw QString("Type must be 'BYTES' or 'DURATION'.");
607  }
608 
609  FillSeek(pCutList, &ri, marktype);
610 
611  return pCutList;
612 }
613 
615 //
617 
619  int nCount )
620 {
621  pginfolist_t infoList;
622 
623  if (expirer)
624  expirer->GetAllExpiring( infoList );
625 
626  // ----------------------------------------------------------------------
627  // Build Response
628  // ----------------------------------------------------------------------
629 
630  DTC::ProgramList *pPrograms = new DTC::ProgramList();
631 
632  nStartIndex = (nStartIndex > 0) ? min( nStartIndex, (int)infoList.size() ) : 0;
633  nCount = (nCount > 0) ? min( nCount, (int)infoList.size() ) : infoList.size();
634  int nEndIndex = min((nStartIndex + nCount), (int)infoList.size() );
635 
636  for( int n = nStartIndex; n < nEndIndex; n++)
637  {
638  ProgramInfo *pInfo = infoList[ n ];
639 
640  if (pInfo != NULL)
641  {
642  DTC::Program *pProgram = pPrograms->AddNewProgram();
643 
644  FillProgramInfo( pProgram, pInfo, true );
645 
646  delete pInfo;
647  }
648  }
649 
650  // ----------------------------------------------------------------------
651 
652  pPrograms->setStartIndex ( nStartIndex );
653  pPrograms->setCount ( nCount );
654  pPrograms->setTotalAvailable( infoList.size() );
655  pPrograms->setAsOf ( MythDate::current() );
656  pPrograms->setVersion ( MYTH_BINARY_VERSION );
657  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
658 
659  return pPrograms;
660 }
661 
663 //
665 
667 {
668  DTC::EncoderList* pList = new DTC::EncoderList();
669 
670  QReadLocker tvlocker(&TVRec::inputsLock);
671  QList<InputInfo> inputInfoList = CardUtil::GetAllInputInfo();
672  QMap<int, EncoderLink *>::Iterator iter = tvList.begin();
673 
674  for (; iter != tvList.end(); ++iter)
675  {
676  EncoderLink *elink = *iter;
677 
678  if (elink != NULL)
679  {
680  DTC::Encoder *pEncoder = pList->AddNewEncoder();
681 
682  pEncoder->setId ( elink->GetInputID() );
683  pEncoder->setState ( elink->GetState() );
684  pEncoder->setLocal ( elink->IsLocal() );
685  pEncoder->setConnected ( elink->IsConnected() );
686  pEncoder->setSleepStatus ( elink->GetSleepStatus() );
687  // pEncoder->setLowOnFreeSpace( elink->isLowOnFreeSpace());
688 
689  if (pEncoder->Local())
690  pEncoder->setHostName( gCoreContext->GetHostName() );
691  else
692  pEncoder->setHostName( elink->GetHostName() );
693 
694  QList<InputInfo>::iterator it = inputInfoList.begin();
695  for (; it < inputInfoList.end(); ++it)
696  {
697  InputInfo inputInfo = *it;
698  if (inputInfo.inputid == static_cast<uint>(elink->GetInputID()))
699  {
700  DTC::Input *input = pEncoder->AddNewInput();
701  FillInputInfo(input, inputInfo);
702  }
703  }
704 
705  switch ( pEncoder->State() )
706  {
710  {
711  ProgramInfo *pInfo = elink->GetRecording();
712 
713  if (pInfo)
714  {
715  DTC::Program *pProgram = pEncoder->Recording();
716 
717  FillProgramInfo( pProgram, pInfo, true, true );
718 
719  delete pInfo;
720  }
721 
722  break;
723  }
724 
725  default:
726  break;
727  }
728  }
729  }
730  return pList;
731 }
732 
734 //
736 
738 {
739  DTC::InputList *pList = new DTC::InputList();
740 
741  QList<InputInfo> inputInfoList = CardUtil::GetAllInputInfo();
742  QList<InputInfo>::iterator it = inputInfoList.begin();
743  for (; it < inputInfoList.end(); ++it)
744  {
745  InputInfo inputInfo = *it;
746  DTC::Input *input = pList->AddNewInput();
747  FillInputInfo(input, inputInfo);
748  }
749 
750  return pList;
751 }
752 
754 //
756 
757 QStringList Dvr::GetRecGroupList()
758 {
759  MSqlQuery query(MSqlQuery::InitCon());
760  query.prepare("SELECT recgroup FROM recgroups WHERE recgroup <> 'Deleted' "
761  "ORDER BY recgroup");
762 
763  QStringList result;
764  if (!query.exec())
765  {
766  MythDB::DBError("GetRecGroupList", query);
767  return result;
768  }
769 
770  while (query.next())
771  result << query.value(0).toString();
772 
773  return result;
774 }
775 
777 //
779 
780 QStringList Dvr::GetProgramCategories( bool OnlyRecorded )
781 {
782  MSqlQuery query(MSqlQuery::InitCon());
783 
784  if (OnlyRecorded)
785  query.prepare("SELECT DISTINCT category FROM recorded ORDER BY category");
786  else
787  query.prepare("SELECT DISTINCT category FROM program ORDER BY category");
788 
789  QStringList result;
790  if (!query.exec())
791  {
792  MythDB::DBError("GetProgramCategories", query);
793  return result;
794  }
795 
796  while (query.next())
797  result << query.value(0).toString();
798 
799  return result;
800 }
801 
803 //
805 
807 {
809 }
810 
812 //
814 
816 {
817  return PlayGroup::GetNames();
818 }
819 
821 //
823 
825 {
827 
828  MSqlQuery query(MSqlQuery::InitCon());
829 
830  query.prepare("SELECT filterid, description, newruledefault "
831  "FROM recordfilter ORDER BY filterid");
832 
833  if (query.exec())
834  {
835  while (query.next())
836  {
837  DTC::RecRuleFilter* ruleFilter = filterList->AddNewRecRuleFilter();
838  ruleFilter->setId(query.value(0).toInt());
839  ruleFilter->setDescription(QObject::tr(query.value(1).toString()
840  .toUtf8().constData()));
841  }
842  }
843 
844  return filterList;
845 }
846 
848 //
850 
851 QStringList Dvr::GetTitleList(const QString& RecGroup)
852 {
853  MSqlQuery query(MSqlQuery::InitCon());
854 
855  QString querystr = "SELECT DISTINCT title FROM recorded "
856  "WHERE deletepending = 0";
857 
858  if (!RecGroup.isEmpty())
859  querystr += " AND recgroup = :RECGROUP";
860  else
861  querystr += " AND recgroup != 'Deleted'";
862 
863  querystr += " ORDER BY title";
864 
865  query.prepare(querystr);
866 
867  if (!RecGroup.isEmpty())
868  query.bindValue(":RECGROUP", RecGroup);
869 
870  QStringList result;
871  if (!query.exec())
872  {
873  MythDB::DBError("GetTitleList recorded", query);
874  return result;
875  }
876 
877  while (query.next())
878  result << query.value(0).toString();
879 
880  return result;
881 }
882 
884 //
886 
888 {
889  MSqlQuery query(MSqlQuery::InitCon());
890 
891  QString querystr = QString(
892  "SELECT title, inetref, count(title) as count "
893  " FROM recorded AS r "
894  " JOIN recgroups AS g ON r.recgroupid = g.recgroupid "
895  " WHERE g.recgroup NOT IN ('Deleted', 'LiveTV') "
896  " AND r.deletepending = 0 "
897  " GROUP BY title, inetref "
898  " ORDER BY title");
899 
900  query.prepare(querystr);
901 
902  DTC::TitleInfoList *pTitleInfos = new DTC::TitleInfoList();
903  if (!query.exec())
904  {
905  MythDB::DBError("GetTitleList recorded", query);
906  return pTitleInfos;
907  }
908 
909  while (query.next())
910  {
911  DTC::TitleInfo *pTitleInfo = pTitleInfos->AddNewTitleInfo();
912 
913  pTitleInfo->setTitle(query.value(0).toString());
914  pTitleInfo->setInetref(query.value(1).toString());
915  pTitleInfo->setCount(query.value(2).toInt());
916  }
917 
918  return pTitleInfos;
919 }
920 
922 //
924 
926  int nCount,
927  bool bShowAll,
928  int nRecordId,
929  int nRecStatus )
930 {
931  RecordingList recordingList; // Auto-delete deque
932  RecList tmpList; // Standard deque, objects must be deleted
933 
934  if (nRecordId <= 0)
935  nRecordId = -1;
936 
937  // NOTE: Fetching this information directly from the schedule is
938  // significantly faster than using ProgramInfo::LoadFromScheduler()
939  Scheduler *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
940  if (scheduler)
941  scheduler->GetAllPending(tmpList, nRecordId);
942 
943  // Sort the upcoming into only those which will record
944  RecList::iterator it = tmpList.begin();
945  for(; it < tmpList.end(); ++it)
946  {
947  if ((nRecStatus != 0) &&
948  ((*it)->GetRecordingStatus() != nRecStatus))
949  {
950  delete *it;
951  *it = NULL;
952  continue;
953  }
954 
955  if (!bShowAll && ((((*it)->GetRecordingStatus() >= RecStatus::Pending) &&
956  ((*it)->GetRecordingStatus() <= RecStatus::WillRecord)) ||
957  ((*it)->GetRecordingStatus() == RecStatus::Recorded) ||
958  ((*it)->GetRecordingStatus() == RecStatus::Conflict)) &&
959  ((*it)->GetRecordingEndTime() > MythDate::current()))
960  {
961  recordingList.push_back(new RecordingInfo(**it));
962  }
963  else if (bShowAll &&
964  ((*it)->GetRecordingEndTime() > MythDate::current()))
965  {
966  recordingList.push_back(new RecordingInfo(**it));
967  }
968 
969  delete *it;
970  *it = NULL;
971  }
972 
973  // ----------------------------------------------------------------------
974  // Build Response
975  // ----------------------------------------------------------------------
976 
977  DTC::ProgramList *pPrograms = new DTC::ProgramList();
978 
979  nStartIndex = (nStartIndex > 0) ? min( nStartIndex, (int)recordingList.size() ) : 0;
980  nCount = (nCount > 0) ? min( nCount, (int)recordingList.size() ) : recordingList.size();
981  int nEndIndex = min((nStartIndex + nCount), (int)recordingList.size() );
982 
983  for( int n = nStartIndex; n < nEndIndex; n++)
984  {
985  ProgramInfo *pInfo = recordingList[ n ];
986 
987  DTC::Program *pProgram = pPrograms->AddNewProgram();
988 
989  FillProgramInfo( pProgram, pInfo, true );
990  }
991 
992  // ----------------------------------------------------------------------
993 
994  pPrograms->setStartIndex ( nStartIndex );
995  pPrograms->setCount ( nCount );
996  pPrograms->setTotalAvailable( recordingList.size() );
997  pPrograms->setAsOf ( MythDate::current() );
998  pPrograms->setVersion ( MYTH_BINARY_VERSION );
999  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1000 
1001  return pPrograms;
1002 }
1003 
1005 //
1007 
1009  int nCount,
1010  int nRecordId )
1011 {
1012  RecordingList recordingList; // Auto-delete deque
1013  RecList tmpList; // Standard deque, objects must be deleted
1014 
1015  if (nRecordId <= 0)
1016  nRecordId = -1;
1017 
1018  // NOTE: Fetching this information directly from the schedule is
1019  // significantly faster than using ProgramInfo::LoadFromScheduler()
1020  Scheduler *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
1021  if (scheduler)
1022  scheduler->GetAllPending(tmpList, nRecordId);
1023 
1024  // Sort the upcoming into only those which are conflicts
1025  RecList::iterator it = tmpList.begin();
1026  for(; it < tmpList.end(); ++it)
1027  {
1028  if (((*it)->GetRecordingStatus() == RecStatus::Conflict) &&
1029  ((*it)->GetRecordingStartTime() >= MythDate::current()))
1030  {
1031  recordingList.push_back(new RecordingInfo(**it));
1032  }
1033  delete *it;
1034  *it = NULL;
1035  }
1036 
1037  // ----------------------------------------------------------------------
1038  // Build Response
1039  // ----------------------------------------------------------------------
1040 
1041  DTC::ProgramList *pPrograms = new DTC::ProgramList();
1042 
1043  nStartIndex = (nStartIndex > 0) ? min( nStartIndex, (int)recordingList.size() ) : 0;
1044  nCount = (nCount > 0) ? min( nCount, (int)recordingList.size() ) : recordingList.size();
1045  int nEndIndex = min((nStartIndex + nCount), (int)recordingList.size() );
1046 
1047  for( int n = nStartIndex; n < nEndIndex; n++)
1048  {
1049  ProgramInfo *pInfo = recordingList[ n ];
1050 
1051  DTC::Program *pProgram = pPrograms->AddNewProgram();
1052 
1053  FillProgramInfo( pProgram, pInfo, true );
1054  }
1055 
1056  // ----------------------------------------------------------------------
1057 
1058  pPrograms->setStartIndex ( nStartIndex );
1059  pPrograms->setCount ( nCount );
1060  pPrograms->setTotalAvailable( recordingList.size() );
1061  pPrograms->setAsOf ( MythDate::current() );
1062  pPrograms->setVersion ( MYTH_BINARY_VERSION );
1063  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1064 
1065  return pPrograms;
1066 }
1067 
1069  QString sTitle,
1070  QString sSubtitle,
1071  QString sDescription,
1072  QString sCategory,
1073  QDateTime recstarttsRaw,
1074  QDateTime recendtsRaw,
1075  QString sSeriesId,
1076  QString sProgramId,
1077  int nChanId,
1078  QString sStation,
1079  int nFindDay,
1080  QTime tFindTime,
1081  int nParentId,
1082  bool bInactive,
1083  uint nSeason,
1084  uint nEpisode,
1085  QString sInetref,
1086  QString sType,
1087  QString sSearchType,
1088  int nRecPriority,
1089  uint nPreferredInput,
1090  int nStartOffset,
1091  int nEndOffset,
1092  QString sDupMethod,
1093  QString sDupIn,
1094  uint nFilter,
1095  QString sRecProfile,
1096  QString sRecGroup,
1097  QString sStorageGroup,
1098  QString sPlayGroup,
1099  bool bAutoExpire,
1100  int nMaxEpisodes,
1101  bool bMaxNewest,
1102  bool bAutoCommflag,
1103  bool bAutoTranscode,
1104  bool bAutoMetaLookup,
1105  bool bAutoUserJob1,
1106  bool bAutoUserJob2,
1107  bool bAutoUserJob3,
1108  bool bAutoUserJob4,
1109  int nTranscoder)
1110 {
1111  QDateTime recstartts = recstarttsRaw.toUTC();
1112  QDateTime recendts = recendtsRaw.toUTC();
1113  RecordingRule rule;
1114  rule.LoadTemplate("Default");
1115 
1116  if (sType.isEmpty())
1117  sType = "single";
1118 
1119  if (sSearchType.isEmpty())
1120  sSearchType = "none";
1121 
1122  if (sDupMethod.isEmpty())
1123  sDupMethod = "subtitleanddescription";
1124 
1125  if (sDupIn.isEmpty())
1126  sDupIn = "all";
1127 
1128  rule.m_title = sTitle;
1129  rule.m_subtitle = sSubtitle;
1130  rule.m_description = sDescription;
1131 
1132  rule.m_startdate = recstartts.date();
1133  rule.m_starttime = recstartts.time();
1134  rule.m_enddate = recendts.date();
1135  rule.m_endtime = recendts.time();
1136 
1137  rule.m_type = recTypeFromString(sType);
1138  rule.m_searchType = searchTypeFromString(sSearchType);
1139  rule.m_dupMethod = dupMethodFromString(sDupMethod);
1140  rule.m_dupIn = dupInFromString(sDupIn);
1141 
1142  if (sRecProfile.isEmpty())
1143  sRecProfile = "Default";
1144 
1145  if (sRecGroup.isEmpty())
1146  sRecGroup = "Default";
1147 
1148  if (sStorageGroup.isEmpty())
1149  sStorageGroup = "Default";
1150 
1151  if (sPlayGroup.isEmpty())
1152  sPlayGroup = "Default";
1153 
1154  rule.m_category = sCategory;
1155  rule.m_seriesid = sSeriesId;
1156  rule.m_programid = sProgramId;
1157 
1158  rule.m_channelid = nChanId;
1159  rule.m_station = sStation;
1160 
1161  rule.m_findday = nFindDay;
1162  rule.m_findtime = tFindTime;
1163 
1164  rule.m_recProfile = sRecProfile;
1165  rule.m_recGroupID = RecordingInfo::GetRecgroupID(sRecGroup);
1166  if (rule.m_recGroupID == 0)
1168  rule.m_storageGroup = sStorageGroup;
1169  rule.m_playGroup = sPlayGroup;
1170 
1171  rule.m_parentRecID = nParentId;
1172  rule.m_isInactive = bInactive;
1173 
1174  rule.m_season = nSeason;
1175  rule.m_episode = nEpisode;
1176  rule.m_inetref = sInetref;
1177 
1178  rule.m_recPriority = nRecPriority;
1179  rule.m_prefInput = nPreferredInput;
1180  rule.m_startOffset = nStartOffset;
1181  rule.m_endOffset = nEndOffset;
1182  rule.m_filter = nFilter;
1183 
1184  rule.m_autoExpire = bAutoExpire;
1185  rule.m_maxEpisodes = nMaxEpisodes;
1186  rule.m_maxNewest = bMaxNewest;
1187 
1188  rule.m_autoCommFlag = bAutoCommflag;
1189  rule.m_autoTranscode = bAutoTranscode;
1190  rule.m_autoMetadataLookup = bAutoMetaLookup;
1191 
1192  rule.m_autoUserJob1 = bAutoUserJob1;
1193  rule.m_autoUserJob2 = bAutoUserJob2;
1194  rule.m_autoUserJob3 = bAutoUserJob3;
1195  rule.m_autoUserJob4 = bAutoUserJob4;
1196 
1197  rule.m_transcoder = nTranscoder;
1198 
1199  QString msg;
1200  if (!rule.IsValid(msg))
1201  throw msg;
1202 
1203  rule.Save();
1204 
1205  uint recid = rule.m_recordID;
1206 
1207  return recid;
1208 }
1209 
1211  QString sTitle,
1212  QString sSubtitle,
1213  QString sDescription,
1214  QString sCategory,
1215  QDateTime dStartTimeRaw,
1216  QDateTime dEndTimeRaw,
1217  QString sSeriesId,
1218  QString sProgramId,
1219  int nChanId,
1220  QString sStation,
1221  int nFindDay,
1222  QTime tFindTime,
1223  bool bInactive,
1224  uint nSeason,
1225  uint nEpisode,
1226  QString sInetref,
1227  QString sType,
1228  QString sSearchType,
1229  int nRecPriority,
1230  uint nPreferredInput,
1231  int nStartOffset,
1232  int nEndOffset,
1233  QString sDupMethod,
1234  QString sDupIn,
1235  uint nFilter,
1236  QString sRecProfile,
1237  QString sRecGroup,
1238  QString sStorageGroup,
1239  QString sPlayGroup,
1240  bool bAutoExpire,
1241  int nMaxEpisodes,
1242  bool bMaxNewest,
1243  bool bAutoCommflag,
1244  bool bAutoTranscode,
1245  bool bAutoMetaLookup,
1246  bool bAutoUserJob1,
1247  bool bAutoUserJob2,
1248  bool bAutoUserJob3,
1249  bool bAutoUserJob4,
1250  int nTranscoder)
1251 {
1252  if (nRecordId <= 0 )
1253  throw QString("Record ID is invalid.");
1254 
1255  RecordingRule pRule;
1256  pRule.m_recordID = nRecordId;
1257  pRule.Load();
1258 
1259  if (!pRule.IsLoaded())
1260  throw QString("Record ID does not exist.");
1261 
1262  QDateTime recstartts = dStartTimeRaw.toUTC();
1263  QDateTime recendts = dEndTimeRaw.toUTC();
1264 
1265  pRule.m_isInactive = bInactive;
1266  if (sType.isEmpty())
1267  sType = "single";
1268 
1269  if (sSearchType.isEmpty())
1270  sSearchType = "none";
1271 
1272  if (sDupMethod.isEmpty())
1273  sDupMethod = "subtitleanddescription";
1274 
1275  if (sDupIn.isEmpty())
1276  sDupIn = "all";
1277 
1278  pRule.m_type = recTypeFromString(sType);
1279  pRule.m_searchType = searchTypeFromString(sSearchType);
1280  pRule.m_dupMethod = dupMethodFromString(sDupMethod);
1281  pRule.m_dupIn = dupInFromString(sDupIn);
1282 
1283  if (sRecProfile.isEmpty())
1284  sRecProfile = "Default";
1285 
1286  if (sRecGroup.isEmpty())
1287  sRecGroup = "Default";
1288 
1289  if (sStorageGroup.isEmpty())
1290  sStorageGroup = "Default";
1291 
1292  if (sPlayGroup.isEmpty())
1293  sPlayGroup = "Default";
1294 
1295  if (!sTitle.isEmpty())
1296  pRule.m_title = sTitle;
1297 
1298  if (!sSubtitle.isEmpty())
1299  pRule.m_subtitle = sSubtitle;
1300 
1301  if(!sDescription.isEmpty())
1302  pRule.m_description = sDescription;
1303 
1304  if (!sCategory.isEmpty())
1305  pRule.m_category = sCategory;
1306 
1307  if (!sSeriesId.isEmpty())
1308  pRule.m_seriesid = sSeriesId;
1309 
1310  if (!sProgramId.isEmpty())
1311  pRule.m_programid = sProgramId;
1312 
1313  if (nChanId)
1314  pRule.m_channelid = nChanId;
1315  if (!sStation.isEmpty())
1316  pRule.m_station = sStation;
1317 
1318  pRule.m_startdate = recstartts.date();
1319  pRule.m_starttime = recstartts.time();
1320  pRule.m_enddate = recendts.date();
1321  pRule.m_endtime = recendts.time();
1322 
1323  pRule.m_findday = nFindDay;
1324  pRule.m_findtime = tFindTime;
1325 
1326  pRule.m_recProfile = sRecProfile;
1327  pRule.m_recGroupID = RecordingInfo::GetRecgroupID(sRecGroup);
1328  if (pRule.m_recGroupID == 0)
1330  pRule.m_storageGroup = sStorageGroup;
1331  pRule.m_playGroup = sPlayGroup;
1332 
1333  pRule.m_isInactive = bInactive;
1334 
1335  pRule.m_season = nSeason;
1336  pRule.m_episode = nEpisode;
1337  pRule.m_inetref = sInetref;
1338 
1339  pRule.m_recPriority = nRecPriority;
1340  pRule.m_prefInput = nPreferredInput;
1341  pRule.m_startOffset = nStartOffset;
1342  pRule.m_endOffset = nEndOffset;
1343  pRule.m_filter = nFilter;
1344 
1345  pRule.m_autoExpire = bAutoExpire;
1346  pRule.m_maxEpisodes = nMaxEpisodes;
1347  pRule.m_maxNewest = bMaxNewest;
1348 
1349  pRule.m_autoCommFlag = bAutoCommflag;
1350  pRule.m_autoTranscode = bAutoTranscode;
1351  pRule.m_autoMetadataLookup = bAutoMetaLookup;
1352 
1353  pRule.m_autoUserJob1 = bAutoUserJob1;
1354  pRule.m_autoUserJob2 = bAutoUserJob2;
1355  pRule.m_autoUserJob3 = bAutoUserJob3;
1356  pRule.m_autoUserJob4 = bAutoUserJob4;
1357 
1358  pRule.m_transcoder = nTranscoder;
1359 
1360  QString msg;
1361  if (!pRule.IsValid(msg))
1362  throw msg;
1363 
1364  bool bResult = pRule.Save();
1365 
1366  return bResult;
1367 }
1368 
1370 {
1371  bool bResult = false;
1372 
1373  if (nRecordId <= 0 )
1374  throw QString("Record ID does not exist.");
1375 
1376  RecordingRule pRule;
1377  pRule.m_recordID = nRecordId;
1378 
1379  bResult = pRule.Delete();
1380 
1381  return bResult;
1382 }
1383 
1384 bool Dvr::AddDontRecordSchedule(int nChanId, const QDateTime &dStartTime,
1385  bool bNeverRecord)
1386 {
1387  bool bResult = true;
1388 
1389  if (nChanId <= 0 || !dStartTime.isValid())
1390  throw QString("Program does not exist.");
1391 
1392  ProgramInfo *pi = LoadProgramFromProgram(nChanId, dStartTime.toUTC());
1393 
1394  if (!pi)
1395  throw QString("Program does not exist.");
1396 
1397  // Why RecordingInfo instead of ProgramInfo? Good question ...
1398  RecordingInfo recInfo = RecordingInfo(*pi);
1399 
1400  delete pi;
1401 
1402  if (bNeverRecord)
1403  {
1404  recInfo.ApplyNeverRecord();
1405  }
1406  else
1408 
1409  return bResult;
1410 }
1411 
1413  int nCount,
1414  const QString &Sort,
1415  bool Descending )
1416 {
1417  Scheduler::SchedSortColumn sortingColumn;
1418  if (Sort.toLower() == "lastrecorded")
1419  sortingColumn = Scheduler::kSortLastRecorded;
1420  else if (Sort.toLower() == "nextrecording")
1421  sortingColumn = Scheduler::kSortNextRecording;
1422  else if (Sort.toLower() == "title")
1423  sortingColumn = Scheduler::kSortTitle;
1424  else if (Sort.toLower() == "priority")
1425  sortingColumn = Scheduler::kSortPriority;
1426  else if (Sort.toLower() == "type")
1427  sortingColumn = Scheduler::kSortType;
1428  else
1429  sortingColumn = Scheduler::kSortTitle;
1430 
1431  RecList recList;
1432  Scheduler::GetAllScheduled(recList, sortingColumn, !Descending);
1433 
1434  // ----------------------------------------------------------------------
1435  // Build Response
1436  // ----------------------------------------------------------------------
1437 
1438  DTC::RecRuleList *pRecRules = new DTC::RecRuleList();
1439 
1440  nStartIndex = (nStartIndex > 0) ? min( nStartIndex, (int)recList.size() ) : 0;
1441  nCount = (nCount > 0) ? min( nCount, (int)recList.size() ) : recList.size();
1442  int nEndIndex = min((nStartIndex + nCount), (int)recList.size() );
1443 
1444  for( int n = nStartIndex; n < nEndIndex; n++)
1445  {
1446  RecordingInfo *info = recList[n];
1447 
1448  if (info != NULL)
1449  {
1450  DTC::RecRule *pRecRule = pRecRules->AddNewRecRule();
1451 
1452  FillRecRuleInfo( pRecRule, info->GetRecordingRule() );
1453  }
1454  }
1455 
1456  // ----------------------------------------------------------------------
1457 
1458  pRecRules->setStartIndex ( nStartIndex );
1459  pRecRules->setCount ( nCount );
1460  pRecRules->setTotalAvailable( recList.size() );
1461  pRecRules->setAsOf ( MythDate::current() );
1462  pRecRules->setVersion ( MYTH_BINARY_VERSION );
1463  pRecRules->setProtoVer ( MYTH_PROTO_VERSION );
1464 
1465  while (!recList.empty())
1466  {
1467  delete recList.back();
1468  recList.pop_back();
1469  }
1470 
1471  return pRecRules;
1472 }
1473 
1475  QString sTemplate,
1476  int nRecordedId,
1477  int nChanId,
1478  QDateTime dStartTimeRaw,
1479  bool bMakeOverride )
1480 {
1481  RecordingRule rule;
1482  QDateTime dStartTime = dStartTimeRaw.toUTC();
1483 
1484  if (nRecordId > 0)
1485  {
1486  rule.m_recordID = nRecordId;
1487  if (!rule.Load())
1488  throw QString("Record ID does not exist.");
1489  }
1490  else if (!sTemplate.isEmpty())
1491  {
1492  if (!rule.LoadTemplate(sTemplate))
1493  throw QString("Template does not exist.");
1494  }
1495  else if (nRecordedId > 0) // Loads from the Recorded/Recorded Program Table
1496  {
1497  // Despite the use of ProgramInfo, this only applies to Recordings.
1498  ProgramInfo recInfo(nRecordedId);
1499  if (!rule.LoadByProgram(&recInfo))
1500  throw QString("Recording does not exist");
1501  }
1502  else if (nChanId > 0 && dStartTime.isValid()) // Loads from Program Table, should NOT be used with recordings
1503  {
1504  // Despite the use of RecordingInfo, this only applies to programs in the
1505  // present or future, not to recordings? Confused yet?
1507  RecordingInfo info(nChanId, dStartTime, false, 0, &status);
1508  if (status != RecordingInfo::kFoundProgram)
1509  throw QString("Program does not exist.");
1510  RecordingRule *pRule = info.GetRecordingRule();
1511  if (bMakeOverride && rule.m_type != kSingleRecord &&
1512  rule.m_type != kOverrideRecord && rule.m_type != kDontRecord)
1513  pRule->MakeOverride();
1514  rule = *pRule;
1515  }
1516  else
1517  {
1518  throw QString("Invalid request.");
1519  }
1520 
1521  DTC::RecRule *pRecRule = new DTC::RecRule();
1522  FillRecRuleInfo( pRecRule, &rule );
1523 
1524  return pRecRule;
1525 }
1526 
1528 {
1529  bool bResult = false;
1530 
1531  if (nRecordId <= 0 )
1532  throw QString("Record ID appears invalid.");
1533 
1534  RecordingRule pRule;
1535  pRule.m_recordID = nRecordId;
1536  pRule.Load();
1537 
1538  if (pRule.IsLoaded())
1539  {
1540  pRule.m_isInactive = false;
1541  bResult = pRule.Save();
1542  }
1543 
1544  return bResult;
1545 }
1546 
1548 {
1549  bool bResult = false;
1550 
1551  if (nRecordId <= 0 )
1552  throw QString("Record ID appears invalid.");
1553 
1554  RecordingRule pRule;
1555  pRule.m_recordID = nRecordId;
1556  pRule.Load();
1557 
1558  if (pRule.IsLoaded())
1559  {
1560  pRule.m_isInactive = true;
1561  bResult = pRule.Save();
1562  }
1563 
1564  return bResult;
1565 }
1566 
1567 int Dvr::RecordedIdForPathname(const QString & pathname)
1568 {
1569  uint recordedid;
1570 
1571  if (!ProgramInfo::QueryRecordedIdFromPathname(pathname, recordedid))
1572  return -1;
1573 
1574  return recordedid;
1575 }
1576 
1578 {
1579  RecStatus::Type type = static_cast<RecStatus::Type>(RecStatus);
1580  return RecStatus::toString(type);
1581 }
1582 
1583 QString Dvr::RecStatusToDescription(int RecStatus, int recType,
1584  const QDateTime &StartTime)
1585 {
1586  //if (!StartTime.isValid())
1587  // throw QString("StartTime appears invalid.");
1588  RecStatus::Type rsType = static_cast<RecStatus::Type>(RecStatus);
1589  RecordingType recordingType = static_cast<RecordingType>(recType);
1590  return RecStatus::toDescription(rsType, recordingType, StartTime);
1591 }
1592 
1593 QString Dvr::RecTypeToString(QString recType)
1594 {
1595  bool ok;
1596  RecordingType enumType = static_cast<RecordingType>(recType.toInt(&ok, 10));
1597  if (ok)
1598  return toString(enumType);
1599  // RecordingType type = static_cast<RecordingType>(recType);
1600  return toString(recTypeFromString(recType));
1601 }
1602 
1603 QString Dvr::RecTypeToDescription(QString recType)
1604 {
1605  bool ok;
1606  RecordingType enumType = static_cast<RecordingType>(recType.toInt(&ok, 10));
1607  if (ok)
1608  return toDescription(enumType);
1609  // RecordingType type = static_cast<RecordingType>(recType);
1610  return toDescription(recTypeFromString(recType));
1611 }
1612 
1613 QString Dvr::DupInToString(QString DupIn)
1614 {
1615  // RecordingDupInType type= static_cast<RecordingDupInType>(DupIn);
1616  // return toString(type);
1617  return toString(dupInFromString(DupIn));
1618 }
1619 
1620 QString Dvr::DupInToDescription(QString DupIn)
1621 {
1622  // RecordingDupInType type= static_cast<RecordingDupInType>(DupIn);
1623  //return toDescription(type);
1624  return toDescription(dupInFromString(DupIn));
1625 }
1626 
1627 QString Dvr::DupMethodToString(QString DupMethod)
1628 {
1629  // RecordingDupMethodType method = static_cast<RecordingDupMethodType>(DupMethod);
1630  return toString(dupMethodFromString(DupMethod));
1631 }
1632 
1633 QString Dvr::DupMethodToDescription(QString DupMethod)
1634 {
1635  // RecordingDupMethodType method = static_cast<RecordingDupMethodType>(DupMethod);
1636  return toDescription(dupMethodFromString(DupMethod));
1637 }
QString RecStatusToString(int RecStatus)
Definition: dvr.cpp:1577
QString m_subtitle
Definition: recordingrule.h:76
bool DeleteRecording(int RecordedId, int ChanId, const QDateTime &StartTime, bool ForceDelete, bool AllowRerecord)
Definition: dvr.cpp:300
QTime m_findtime
Day of the week for once per week etc.
Definition: recordingrule.h:95
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:810
MythScheduler * GetScheduler(void)
DTC::ProgramList * GetConflictList(int StartIndex, int Count, int RecordId)
Definition: dvr.cpp:1008
QStringList GetProgramCategories(bool OnlyRecorded)
Definition: dvr.cpp:780
Program * AddNewProgram()
Definition: programList.h:79
void bindValue(const QString &placeholder, const QVariant &val)
Definition: mythdbcon.cpp:915
AutoExpire * expirer
void ReactivateRecording(void)
Asks the scheduler to restart this recording if possible.
QString m_programid
Definition: recordingrule.h:88
DTC::RecRuleFilterList * GetRecRuleFilterList()
Definition: dvr.cpp:824
DTC::TitleInfoList * GetTitleInfoList()
Definition: dvr.cpp:887
SchedSortColumn
Definition: scheduler.h:91
ProgramInfo * LoadProgramFromProgram(const uint chanid, const QDateTime &starttime)
bool StopRecording(int RecordedId)
Definition: dvr.cpp:366
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
Definition: tv.h:63
void push_back(T info)
bool UpdateRecordedWatchedStatus(int RecordedId, int ChanId, const QDateTime &StartTime, bool Watched)
Definition: dvr.cpp:422
QString toDescription(RecordingType rectype)
Converts "rectype" into a human readable description.
bool LoadByProgram(const ProgramInfo *proginfo)
void FillProgramInfo(DTC::Program *pProgram, ProgramInfo *pInfo, bool bIncChannel, bool bDetails, bool bIncCast)
Definition: serviceUtil.cpp:44
bool Delete(bool sendSig=true)
RecSearchType searchTypeFromString(QString type)
QString toString(MarkTypes type)
QStringList GetPlayGroupList()
Definition: dvr.cpp:815
DTC::CutList * GetRecordedCutList(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType)
Definition: dvr.cpp:522
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
void FillRecRuleInfo(DTC::RecRule *pRecRule, RecordingRule *pRule)
RecordingRule * GetRecordingRule(void)
Returns the "record" field, creating it if necessary.
TitleInfo * AddNewTitleInfo()
Definition: titleInfoList.h:52
QString GetTitle(void) const
Definition: programinfo.h:344
RecordingType recTypeFromString(QString type)
static QString toDescription(Type, RecordingType, const QDateTime &recstartts)
Converts "recstatus" into a long human readable description.
Definition: recStatus.cpp:195
QString m_storageGroup
static QStringList getRecordingsGroups(void)
QString m_station
Definition: recordingrule.h:93
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:34
QString DupMethodToDescription(QString DupMethod)
Definition: dvr.cpp:1633
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)
Watching Recording is the state for when we are watching an in progress recording, but the user does not have control over the channel and recorder to use.
Definition: tv.h:80
unsigned int uint
Definition: compat.h:136
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QString DupInToString(QString DupIn)
Definition: dvr.cpp:1613
AutoDeleteDeque< ProgramInfo * > ProgramList
Definition: programinfo.h:29
size_t size(void) const
DTC::CutList * GetRecordedCommBreak(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType)
Definition: dvr.cpp:555
RecordingType m_type
Definition: recordingrule.h:99
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
RecordingDupMethodType m_dupMethod
static QReadWriteLock inputsLock
Definition: tv_rec.h:429
DTC::RecRuleList * GetRecordScheduleList(int StartIndex, int Count, const QString &Sort, bool Descending)
Definition: dvr.cpp:1412
int RecordedIdForPathname(const QString &Filename)
Definition: dvr.cpp:1567
bool RescheduleRecordings(void)
Definition: dvr.cpp:409
DTC::ProgramList * GetExpiringList(int StartIndex, int Count)
Definition: dvr.cpp:618
bool SetSavedBookmark(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType, long Offset)
Definition: dvr.cpp:484
static uint GetRecgroupID(const QString &recGroup)
Temporary helper during transition from string to ID.
QString GetStorageGroup(void) const
Definition: programinfo.h:403
QVariant value(int i) const
Definition: mythdbcon.h:182
QStringList GetRecStorageGroupList()
Definition: dvr.cpp:806
bool Save(bool sendSig=true)
MarkTypes
Definition: programtypes.h:50
RecordingDupMethodType dupMethodFromString(QString type)
Holds information on recordings and videos.
Definition: programinfo.h:66
void ApplyRecordStateChange(RecordingType newstate, bool save=true)
Sets RecordingType of "record", creating "record" if it does not exist.
bool RemoveRecorded(int RecordedId, int ChanId, const QDateTime &StartTime, bool ForceDelete, bool AllowRerecord)
Definition: dvr.cpp:291
voidpf uLong offset
Definition: ioapi.h:142
Recording Only is a TVRec only state for when we are recording a program, but there is no one current...
Definition: tv.h:84
This class is used as a container for messages.
Definition: mythevent.h:15
RecRuleFilter * AddNewRecRuleFilter()
static void GetAllScheduled(QStringList &strList, SchedSortColumn sortBy=kSortTitle, bool ascending=true)
Returns all scheduled programs serialized into a QStringList.
Definition: scheduler.cpp:1873
static QMap< QString, uint32_t > QueryInUseMap(void)
DTC::CutList * GetRecordedSeek(int RecordedId, const QString &OffsetType)
Definition: dvr.cpp:588
bool m_autoMetadataLookup
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
int m_findday
callsign?
Definition: recordingrule.h:94
QMap< int, EncoderLink * > tvList
QString m_playGroup
void FillCutList(DTC::CutList *pCutList, RecordingInfo *rInfo, int marktype)
static QString toString(Type, uint id)
Converts "recstatus" into a short (unreadable) string.
Definition: recStatus.cpp:39
QString DupMethodToString(QString DupMethod)
Definition: dvr.cpp:1627
long GetSavedBookmark(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType)
Definition: dvr.cpp:451
Input * AddNewInput()
Definition: inputList.h:52
bool ReactivateRecording(int RecordedId)
Definition: dvr.cpp:393
#define MYTH_PROTO_VERSION
Increment this whenever the MythTV network protocol changes.
Definition: mythversion.h:48
QString GetRecordingGroup(void) const
Definition: programinfo.h:400
QString m_description
Definition: recordingrule.h:77
void SaveBookmark(uint64_t frame)
TODO Move to RecordingInfo.
QString RecStatusToDescription(int RecStatus, int RecType, const QDateTime &StartTime)
Definition: dvr.cpp:1583
QString RecTypeToString(QString RecType)
Definition: dvr.cpp:1593
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:555
bool IsDeletePending(void) const
Definition: programinfo.h:470
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:31
static QList< InputInfo > GetAllInputInfo()
Definition: cardutil.cpp:1177
bool QueryDurationKeyFrame(uint64_t *, uint64_t duration, bool backwards) const
uint64_t QueryBookmark(void) const
Gets any bookmark position in database, unless the ignore bookmark flag is set.
void GetAllExpiring(QStringList &strList)
Gets the full list of programs that can expire in expiration order.
Definition: autoexpire.cpp:842
uint inputid
unique key in DB for this input
Definition: inputinfo.h:71
QString m_seriesid
Definition: recordingrule.h:87
int m_parentRecID
Unique Recording Rule ID.
Definition: recordingrule.h:70
RecordingDupInType m_dupIn
QString RecTypeToDescription(QString RecType)
Definition: dvr.cpp:1603
void dispatch(const MythEvent &event)
DTC::ProgramList * GetRecordedList(bool Descending, int StartIndex, int Count, const QString &TitleRegEx, const QString &RecGroup, const QString &StorageGroup, const QString &Category, const QString &Sort)
Definition: dvr.cpp:63
QString m_inetref
Definition: recordingrule.h:89
bool QueryKeyFramePosition(uint64_t *, uint64_t keyframe, bool backwards) const
void FillSeek(DTC::CutList *pCutList, RecordingInfo *rInfo, MarkTypes marktype)
static bool QueryRecordedIdFromPathname(const QString &pathname, uint &recordedid)
bool AddDontRecordSchedule(int ChanId, const QDateTime &StartTime, bool NeverRecord)
Definition: dvr.cpp:1384
Encoder * AddNewEncoder()
Definition: encoderList.h:52
DTC::ProgramList * GetUpcomingList(int StartIndex, int Count, bool ShowAll, int RecordId, int RecStatus)
Definition: dvr.cpp:925
void FillCommBreak(DTC::CutList *pCutList, RecordingInfo *rInfo, int marktype)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:835
RecRule * AddNewRecRule()
Definition: recRuleList.h:65
bool IsLoaded() const
Definition: recordingrule.h:55
DTC::RecRule * GetRecordSchedule(uint RecordId, QString Template, int nRecordedId, int ChanId, QDateTime StartTime, bool MakeOverride)
Definition: dvr.cpp:1474
bool UnDeleteRecording(int RecordedId, int ChanId, const QDateTime &StartTime)
Definition: dvr.cpp:335
QString m_title
Recording rule is enabled?
Definition: recordingrule.h:75
Used to expire recordings to make space for new recordings.
Definition: autoexpire.h:62
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:353
void ApplyNeverRecord(void)
Set this program to never be recorded by inserting &#39;history&#39; for it into the database with a status o...
QString DupInToDescription(QString DupIn)
Definition: dvr.cpp:1620
DTC::Program * GetRecorded(int RecordedId, int ChanId, const QDateTime &StartTime)
Definition: dvr.cpp:267
static QMap< QString, bool > QueryJobsRunning(int type)
QString m_recProfile
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:16
void SaveWatched(bool watchedFlag)
Set "watched" field in recorded/videometadata to "watchedFlag".
DTC::EncoderList * GetEncoderList()
Definition: dvr.cpp:666
static QStringList GetNames(void)
Definition: playgroup.cpp:206
virtual QMap< QString, ProgramInfo * > GetRecording(void) const =0
bool RemoveRecordSchedule(uint RecordId)
Definition: dvr.cpp:1369
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:385
bool LoadFromOldRecorded(ProgramList &destination, const QString &sql, const MSqlBindings &bindings)
bool Load(bool asTemplate=false)
unsigned m_filter
QString m_category
Definition: recordingrule.h:80
bool LoadTemplate(QString category, QString categoryType="Default")
DTC::InputList * GetInputList()
Definition: dvr.cpp:737
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:98
std::deque< RecordingInfo * > RecList
Definition: mythscheduler.h:10
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:623
vector< ProgramInfo * > pginfolist_t
Definition: autoexpire.h:24
QStringList GetRecGroupList()
Definition: dvr.cpp:757
RecordingDupInType dupInFromString(QString type)
QString GetCategory(void) const
Definition: programinfo.h:350
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:181
bool QueryPositionKeyFrame(uint64_t *, uint64_t position, bool backwards) const
void FillInputInfo(DTC::Input *input, InputInfo inputInfo)
bool MakeOverride(void)
bool DisableRecordSchedule(uint RecordId)
Definition: dvr.cpp:1547
QString GetHostName(void)
bool UpdateRecordSchedule(uint RecordId, QString Title, QString Subtitle, QString Description, QString Category, QDateTime StartTime, QDateTime EndTime, QString SeriesId, QString ProgramId, int ChanId, QString Station, int FindDay, QTime FindTime, bool Inactive, uint Season, uint Episode, QString Inetref, QString Type, QString SearchType, int RecPriority, uint PreferredInput, int StartOffset, int EndOffset, QString DupMethod, QString DupIn, 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)
Definition: dvr.cpp:1210
bool GetAllPending(RecList &retList, int recRuleId=0) const
Definition: scheduler.cpp:1778
DTC::ProgramList * 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: dvr.cpp:150
Default UTC.
Definition: mythdate.h:14
bool HasPathname(void) const
Definition: programinfo.h:341
bool EnableRecordSchedule(uint RecordId)
Definition: dvr.cpp:1527
QStringList GetTitleList(const QString &RecGroup)
Definition: dvr.cpp:851
RecSearchType m_searchType
bool QueryKeyFrameDuration(uint64_t *, uint64_t keyframe, bool backwards) const
uint AddRecordSchedule(QString Title, QString Subtitle, QString Description, QString Category, QDateTime StartTime, QDateTime EndTime, QString SeriesId, QString ProgramId, int ChanId, QString Station, int FindDay, QTime FindTime, int ParentId, bool Inactive, uint Season, uint Episode, QString Inetref, QString Type, QString SearchType, int RecPriority, uint PreferredInput, int StartOffset, int EndOffset, QString DupMethod, QString DupIn, 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)
Definition: dvr.cpp:1068
bool IsValid(QString &text)