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