MythTV  0.28pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
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 ((!sTitleRegEx.isEmpty() && !pInfo->GetTitle().contains(rTitleRegEx)) ||
109  (!sRecGroup.isEmpty() && sRecGroup != pInfo->GetRecordingGroup()) ||
110  (!sStorageGroup.isEmpty() && sStorageGroup != pInfo->GetStorageGroup()))
111  continue;
112 
113  if ((nAvailable < nStartIndex) ||
114  (nCount >= nMax))
115  {
116  ++nAvailable;
117  continue;
118  }
119 
120  ++nAvailable;
121  ++nCount;
122 
123  DTC::Program *pProgram = pPrograms->AddNewProgram();
124 
125  FillProgramInfo( pProgram, pInfo, true );
126  }
127 
128  // ----------------------------------------------------------------------
129 
130  pPrograms->setStartIndex ( nStartIndex );
131  pPrograms->setCount ( nCount );
132  pPrograms->setTotalAvailable( nAvailable );
133  pPrograms->setAsOf ( MythDate::current() );
134  pPrograms->setVersion ( MYTH_BINARY_VERSION );
135  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
136 
137  return pPrograms;
138 }
139 
141 //
143 
144 DTC::Program* Dvr::GetRecorded(int chanid, const QDateTime &recstarttsRaw)
145 {
146  if (chanid <= 0 || !recstarttsRaw.isValid())
147  throw QString("Channel ID or StartTime appears invalid.");
148 
149  ProgramInfo pi(chanid, recstarttsRaw.toUTC());
150 
151  DTC::Program *pProgram = new DTC::Program();
152  FillProgramInfo( pProgram, &pi, true );
153 
154  return pProgram;
155 }
156 
158 //
160 
161 bool Dvr::RemoveRecorded(int chanid, const QDateTime &recstarttsRaw,
162  bool forceDelete, bool allowRerecord)
163 {
164  return DeleteRecording(chanid, recstarttsRaw, forceDelete, allowRerecord);
165 }
166 
167 
168 bool Dvr::DeleteRecording(int chanid, const QDateTime &recstarttsRaw,
169  bool forceDelete, bool allowRerecord)
170 {
171  if (chanid <= 0 || !recstarttsRaw.isValid())
172  throw QString("Channel ID or StartTime appears invalid.");
173 
174  ProgramInfo pi(chanid, recstarttsRaw.toUTC());
175 
176  if (pi.GetChanID() && pi.HasPathname())
177  {
178  QString cmd = QString("DELETE_RECORDING %1 %2 %3 %4")
179  .arg(pi.GetChanID())
180  .arg(pi.GetRecordingStartTime(MythDate::ISODate))
181  .arg(forceDelete ? "FORCE" : "NO_FORCE")
182  .arg(allowRerecord ? "FORGET" : "NO_FORGET");
183  MythEvent me(cmd);
184 
185  gCoreContext->dispatch(me);
186  return true;
187  }
188 
189  return false;
190 }
191 
193 //
195 
196 bool Dvr::UnDeleteRecording(int chanid, const QDateTime &recstarttsRaw)
197 {
198  if (chanid <= 0 || !recstarttsRaw.isValid())
199  throw QString("Channel ID or StartTime appears invalid.");
200 
201  RecordingInfo ri(chanid, recstarttsRaw.toUTC());
202 
203  if (ri.GetChanID() && ri.HasPathname())
204  {
205  QString cmd = QString("UNDELETE_RECORDING %1 %2")
206  .arg(ri.GetChanID())
207  .arg(ri.GetRecordingStartTime(MythDate::ISODate));
208  MythEvent me(cmd);
209 
210  gCoreContext->dispatch(me);
211  return true;
212  }
213 
214  return false;
215 }
216 
218 //
220 
222  const QDateTime &recstarttsRaw,
223  bool watched)
224 {
225  if (chanid <= 0 || !recstarttsRaw.isValid())
226  return false;
227 
228  ProgramInfo pi(chanid, recstarttsRaw.toUTC());
229  pi.SaveWatched(watched);
230 
231  return true;
232 }
233 
235 //
237 
239  int nCount )
240 {
241  pginfolist_t infoList;
242 
243  if (expirer)
244  expirer->GetAllExpiring( infoList );
245 
246  // ----------------------------------------------------------------------
247  // Build Response
248  // ----------------------------------------------------------------------
249 
250  DTC::ProgramList *pPrograms = new DTC::ProgramList();
251 
252  nStartIndex = min( nStartIndex, (int)infoList.size() );
253  nCount = (nCount > 0) ? min( nCount, (int)infoList.size() ) : infoList.size();
254  int nEndIndex = min((nStartIndex + nCount), (int)infoList.size() );
255 
256  for( int n = nStartIndex; n < nEndIndex; n++)
257  {
258  ProgramInfo *pInfo = infoList[ n ];
259 
260  if (pInfo != NULL)
261  {
262  DTC::Program *pProgram = pPrograms->AddNewProgram();
263 
264  FillProgramInfo( pProgram, pInfo, true );
265 
266  delete pInfo;
267  }
268  }
269 
270  // ----------------------------------------------------------------------
271 
272  pPrograms->setStartIndex ( nStartIndex );
273  pPrograms->setCount ( nCount );
274  pPrograms->setTotalAvailable( infoList.size() );
275  pPrograms->setAsOf ( MythDate::current() );
276  pPrograms->setVersion ( MYTH_BINARY_VERSION );
277  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
278 
279  return pPrograms;
280 }
281 
283 //
285 
287 {
288 
289  DTC::EncoderList* pList = new DTC::EncoderList();
290 
291  QList<InputInfo> inputInfoList = CardUtil::GetAllInputInfo();
292  QMap<int, EncoderLink *>::Iterator iter = tvList.begin();
293 
294  for (; iter != tvList.end(); ++iter)
295  {
296  EncoderLink *elink = *iter;
297 
298  if (elink != NULL)
299  {
300  DTC::Encoder *pEncoder = pList->AddNewEncoder();
301 
302  pEncoder->setId ( elink->GetCardID() );
303  pEncoder->setState ( elink->GetState() );
304  pEncoder->setLocal ( elink->IsLocal() );
305  pEncoder->setConnected ( elink->IsConnected() );
306  pEncoder->setSleepStatus ( elink->GetSleepStatus() );
307  // pEncoder->setLowOnFreeSpace( elink->isLowOnFreeSpace());
308 
309  if (pEncoder->Local())
310  pEncoder->setHostName( gCoreContext->GetHostName() );
311  else
312  pEncoder->setHostName( elink->GetHostName() );
313 
314  QList<InputInfo>::iterator it = inputInfoList.begin();
315  for (; it < inputInfoList.end(); ++it)
316  {
317  InputInfo inputInfo = *it;
318  if (inputInfo.cardid == static_cast<uint>(elink->GetCardID()))
319  {
320  DTC::Input *input = pEncoder->AddNewInput();
321  FillInputInfo(input, inputInfo);
322  }
323  }
324 
325  switch ( pEncoder->State() )
326  {
330  {
331  ProgramInfo *pInfo = elink->GetRecording();
332 
333  if (pInfo)
334  {
335  DTC::Program *pProgram = pEncoder->Recording();
336 
337  FillProgramInfo( pProgram, pInfo, true, true );
338 
339  delete pInfo;
340  }
341 
342  break;
343  }
344 
345  default:
346  break;
347  }
348  }
349  }
350  return pList;
351 }
352 
354 //
356 
358 {
359  DTC::InputList *pList = new DTC::InputList();
360 
361  QList<InputInfo> inputInfoList = CardUtil::GetAllInputInfo();
362  QList<InputInfo>::iterator it = inputInfoList.begin();
363  for (; it < inputInfoList.end(); ++it)
364  {
365  InputInfo inputInfo = *it;
366  DTC::Input *input = pList->AddNewInput();
367  FillInputInfo(input, inputInfo);
368  }
369 
370  return pList;
371 }
372 
374 //
376 
377 QStringList Dvr::GetRecGroupList()
378 {
379  MSqlQuery query(MSqlQuery::InitCon());
380  query.prepare("SELECT recgroup FROM recgroups WHERE recgroup <> 'Deleted' "
381  "ORDER BY recgroup");
382 
383  QStringList result;
384  if (!query.exec())
385  {
386  MythDB::DBError("GetRecGroupList", query);
387  return result;
388  }
389 
390  while (query.next())
391  result << query.value(0).toString();
392 
393  return result;
394 }
395 
397 //
399 
401 {
403 }
404 
406 //
408 
410 {
411  return PlayGroup::GetNames();
412 }
413 
415 //
417 
419 {
421 
422  MSqlQuery query(MSqlQuery::InitCon());
423 
424  query.prepare("SELECT filterid, description, newruledefault "
425  "FROM recordfilter ORDER BY filterid");
426 
427  if (query.exec())
428  {
429  while (query.next())
430  {
431  DTC::RecRuleFilter* ruleFilter = filterList->AddNewRecRuleFilter();
432  ruleFilter->setId(query.value(0).toInt());
433  ruleFilter->setDescription(QObject::tr(query.value(1).toString()
434  .toUtf8().constData()));
435  }
436  }
437 
438  return filterList;
439 }
440 
442 //
444 
445 QStringList Dvr::GetTitleList(const QString& RecGroup)
446 {
447  MSqlQuery query(MSqlQuery::InitCon());
448 
449  QString querystr = "SELECT DISTINCT title FROM recorded";
450 
451  if (!RecGroup.isEmpty())
452  querystr += " WHERE recgroup = :RECGROUP";
453 
454  querystr += " ORDER BY title";
455 
456  query.prepare(querystr);
457 
458  if (!RecGroup.isEmpty())
459  query.bindValue(":RECGROUP", RecGroup);
460 
461  QStringList result;
462  if (!query.exec())
463  {
464  MythDB::DBError("GetTitleList recorded", query);
465  return result;
466  }
467 
468  while (query.next())
469  result << query.value(0).toString();
470 
471  return result;
472 }
473 
475 //
477 
479 {
480  MSqlQuery query(MSqlQuery::InitCon());
481 
482  QString querystr = QString(
483  "SELECT title, inetref, count(title) as count "
484  " FROM recorded "
485  " WHERE inetref <> '' "
486  " GROUP BY title, inetref "
487  " ORDER BY title");
488 
489  query.prepare(querystr);
490 
491  DTC::TitleInfoList *pTitleInfos = new DTC::TitleInfoList();
492  if (!query.exec())
493  {
494  MythDB::DBError("GetTitleList recorded", query);
495  return pTitleInfos;
496  }
497 
498  while (query.next())
499  {
500  DTC::TitleInfo *pTitleInfo = pTitleInfos->AddNewTitleInfo();
501 
502  pTitleInfo->setTitle(query.value(0).toString());
503  pTitleInfo->setInetref(query.value(1).toString());
504  pTitleInfo->setCount(query.value(2).toInt());
505  }
506 
507  return pTitleInfos;
508 }
509 
511 //
513 
515  int nCount,
516  bool bShowAll,
517  int nRecordId,
518  int nRecStatus )
519 {
520  RecordingList recordingList;
521  RecordingList tmpList;
522  bool hasConflicts;
523 
524  if (nRecordId <= 0)
525  nRecordId = -1;
526 
527  LoadFromScheduler(tmpList, hasConflicts, "", nRecordId);
528 
529  // Sort the upcoming into only those which will record
530  RecordingList::iterator it = tmpList.begin();
531  for(; it < tmpList.end(); ++it)
532  {
533  if ((nRecStatus != 0) &&
534  ((*it)->GetRecordingStatus() != nRecStatus))
535  continue;
536 
537  if (!bShowAll && ((((*it)->GetRecordingStatus() >= rsTuning) &&
538  ((*it)->GetRecordingStatus() <= rsWillRecord)) ||
539  ((*it)->GetRecordingStatus() == rsConflict)) &&
540  ((*it)->GetRecordingEndTime() > MythDate::current()))
541  {
542  recordingList.push_back(new RecordingInfo(**it));
543  }
544  else if (bShowAll &&
545  ((*it)->GetRecordingEndTime() > MythDate::current()))
546  {
547  recordingList.push_back(new RecordingInfo(**it));
548  }
549  }
550 
551  // ----------------------------------------------------------------------
552  // Build Response
553  // ----------------------------------------------------------------------
554 
555  DTC::ProgramList *pPrograms = new DTC::ProgramList();
556 
557  nStartIndex = min( nStartIndex, (int)recordingList.size() );
558  nCount = (nCount > 0) ? min( nCount, (int)recordingList.size() ) : recordingList.size();
559  int nEndIndex = min((nStartIndex + nCount), (int)recordingList.size() );
560 
561  for( int n = nStartIndex; n < nEndIndex; n++)
562  {
563  ProgramInfo *pInfo = recordingList[ n ];
564 
565  DTC::Program *pProgram = pPrograms->AddNewProgram();
566 
567  FillProgramInfo( pProgram, pInfo, true );
568  }
569 
570  // ----------------------------------------------------------------------
571 
572  pPrograms->setStartIndex ( nStartIndex );
573  pPrograms->setCount ( nCount );
574  pPrograms->setTotalAvailable( recordingList.size() );
575  pPrograms->setAsOf ( MythDate::current() );
576  pPrograms->setVersion ( MYTH_BINARY_VERSION );
577  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
578 
579  return pPrograms;
580 }
581 
583 //
585 
587  int nCount,
588  int nRecordId )
589 {
590  RecordingList recordingList;
591  RecordingList tmpList;
592  bool hasConflicts;
593 
594  if (nRecordId <= 0)
595  nRecordId = -1;
596 
597  LoadFromScheduler(tmpList, hasConflicts, "", nRecordId);
598 
599  // Sort the upcoming into only those which are conflicts
600  RecordingList::iterator it = tmpList.begin();
601  for(; it < tmpList.end(); ++it)
602  {
603  if (((*it)->GetRecordingStatus() == rsConflict) &&
604  ((*it)->GetRecordingStartTime() >= MythDate::current()))
605  {
606  recordingList.push_back(new RecordingInfo(**it));
607  }
608  }
609 
610  // ----------------------------------------------------------------------
611  // Build Response
612  // ----------------------------------------------------------------------
613 
614  DTC::ProgramList *pPrograms = new DTC::ProgramList();
615 
616  nStartIndex = min( nStartIndex, (int)recordingList.size() );
617  nCount = (nCount > 0) ? min( nCount, (int)recordingList.size() ) : recordingList.size();
618  int nEndIndex = min((nStartIndex + nCount), (int)recordingList.size() );
619 
620  for( int n = nStartIndex; n < nEndIndex; n++)
621  {
622  ProgramInfo *pInfo = recordingList[ n ];
623 
624  DTC::Program *pProgram = pPrograms->AddNewProgram();
625 
626  FillProgramInfo( pProgram, pInfo, true );
627  }
628 
629  // ----------------------------------------------------------------------
630 
631  pPrograms->setStartIndex ( nStartIndex );
632  pPrograms->setCount ( nCount );
633  pPrograms->setTotalAvailable( recordingList.size() );
634  pPrograms->setAsOf ( MythDate::current() );
635  pPrograms->setVersion ( MYTH_BINARY_VERSION );
636  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
637 
638  return pPrograms;
639 }
640 
642  QString sTitle,
643  QString sSubtitle,
644  QString sDescription,
645  QString sCategory,
646  QDateTime recstarttsRaw,
647  QDateTime recendtsRaw,
648  QString sSeriesId,
649  QString sProgramId,
650  int nChanId,
651  QString sStation,
652  int nFindDay,
653  QTime tFindTime,
654  int nParentId,
655  bool bInactive,
656  uint nSeason,
657  uint nEpisode,
658  QString sInetref,
659  QString sType,
660  QString sSearchType,
661  int nRecPriority,
662  uint nPreferredInput,
663  int nStartOffset,
664  int nEndOffset,
665  QString sDupMethod,
666  QString sDupIn,
667  uint nFilter,
668  QString sRecProfile,
669  QString sRecGroup,
670  QString sStorageGroup,
671  QString sPlayGroup,
672  bool bAutoExpire,
673  int nMaxEpisodes,
674  bool bMaxNewest,
675  bool bAutoCommflag,
676  bool bAutoTranscode,
677  bool bAutoMetaLookup,
678  bool bAutoUserJob1,
679  bool bAutoUserJob2,
680  bool bAutoUserJob3,
681  bool bAutoUserJob4,
682  int nTranscoder)
683 {
684  QDateTime recstartts = recstarttsRaw.toUTC();
685  QDateTime recendts = recendtsRaw.toUTC();
686  RecordingRule rule;
687  rule.LoadTemplate("Default");
688 
689  if (sType.isEmpty())
690  sType = "single";
691 
692  if (sSearchType.isEmpty())
693  sSearchType = "none";
694 
695  if (sDupMethod.isEmpty())
696  sDupMethod = "subtitleanddescription";
697 
698  if (sDupIn.isEmpty())
699  sDupIn = "all";
700 
701  rule.m_title = sTitle;
702  rule.m_subtitle = sSubtitle;
703  rule.m_description = sDescription;
704 
705  rule.m_startdate = recstartts.date();
706  rule.m_starttime = recstartts.time();
707  rule.m_enddate = recendts.date();
708  rule.m_endtime = recendts.time();
709 
710  rule.m_type = recTypeFromString(sType);
711  rule.m_searchType = searchTypeFromString(sSearchType);
712  rule.m_dupMethod = dupMethodFromString(sDupMethod);
713  rule.m_dupIn = dupInFromString(sDupIn);
714 
715  if (sRecProfile.isEmpty())
716  sRecProfile = "Default";
717 
718  if (sRecGroup.isEmpty())
719  sRecGroup = "Default";
720 
721  if (sStorageGroup.isEmpty())
722  sStorageGroup = "Default";
723 
724  if (sPlayGroup.isEmpty())
725  sPlayGroup = "Default";
726 
727  rule.m_category = sCategory;
728  rule.m_seriesid = sSeriesId;
729  rule.m_programid = sProgramId;
730 
731  rule.m_channelid = nChanId;
732  rule.m_station = sStation;
733 
734  rule.m_findday = nFindDay;
735  rule.m_findtime = tFindTime;
736 
737  rule.m_recProfile = sRecProfile;
738  rule.m_recGroupID = RecordingInfo::GetRecgroupID(sRecGroup) > 0 ? RecordingInfo::GetRecgroupID(sRecGroup) :
740  rule.m_storageGroup = sStorageGroup;
741  rule.m_playGroup = sPlayGroup;
742 
743  rule.m_parentRecID = nParentId;
744  rule.m_isInactive = bInactive;
745 
746  rule.m_season = nSeason;
747  rule.m_episode = nEpisode;
748  rule.m_inetref = sInetref;
749 
750  rule.m_recPriority = nRecPriority;
751  rule.m_prefInput = nPreferredInput;
752  rule.m_startOffset = nStartOffset;
753  rule.m_endOffset = nEndOffset;
754  rule.m_filter = nFilter;
755 
756  rule.m_autoExpire = bAutoExpire;
757  rule.m_maxEpisodes = nMaxEpisodes;
758  rule.m_maxNewest = bMaxNewest;
759 
760  rule.m_autoCommFlag = bAutoCommflag;
761  rule.m_autoTranscode = bAutoTranscode;
762  rule.m_autoMetadataLookup = bAutoMetaLookup;
763 
764  rule.m_autoUserJob1 = bAutoUserJob1;
765  rule.m_autoUserJob2 = bAutoUserJob2;
766  rule.m_autoUserJob3 = bAutoUserJob3;
767  rule.m_autoUserJob4 = bAutoUserJob4;
768 
769  rule.m_transcoder = nTranscoder;
770 
771  QString msg;
772  if (!rule.IsValid(msg))
773  throw msg;
774 
775  rule.Save();
776 
777  uint recid = rule.m_recordID;
778 
779  return recid;
780 }
781 
783  QString sTitle,
784  QString sSubtitle,
785  QString sDescription,
786  QString sCategory,
787  QDateTime dStartTimeRaw,
788  QDateTime dEndTimeRaw,
789  QString sSeriesId,
790  QString sProgramId,
791  int nChanId,
792  QString sStation,
793  int nFindDay,
794  QTime tFindTime,
795  bool bInactive,
796  uint nSeason,
797  uint nEpisode,
798  QString sInetref,
799  QString sType,
800  QString sSearchType,
801  int nRecPriority,
802  uint nPreferredInput,
803  int nStartOffset,
804  int nEndOffset,
805  QString sDupMethod,
806  QString sDupIn,
807  uint nFilter,
808  QString sRecProfile,
809  QString sRecGroup,
810  QString sStorageGroup,
811  QString sPlayGroup,
812  bool bAutoExpire,
813  int nMaxEpisodes,
814  bool bMaxNewest,
815  bool bAutoCommflag,
816  bool bAutoTranscode,
817  bool bAutoMetaLookup,
818  bool bAutoUserJob1,
819  bool bAutoUserJob2,
820  bool bAutoUserJob3,
821  bool bAutoUserJob4,
822  int nTranscoder)
823 {
824  if (nRecordId <= 0 )
825  throw QString("Record ID is invalid.");
826 
827  RecordingRule pRule;
828  pRule.m_recordID = nRecordId;
829  pRule.Load();
830 
831  if (!pRule.IsLoaded())
832  throw QString("Record ID does not exist.");
833 
834  QDateTime recstartts = dStartTimeRaw.toUTC();
835  QDateTime recendts = dEndTimeRaw.toUTC();
836 
837  pRule.m_isInactive = bInactive;
838  if (sType.isEmpty())
839  sType = "single";
840 
841  if (sSearchType.isEmpty())
842  sSearchType = "none";
843 
844  if (sDupMethod.isEmpty())
845  sDupMethod = "subtitleanddescription";
846 
847  if (sDupIn.isEmpty())
848  sDupIn = "all";
849 
850  pRule.m_type = recTypeFromString(sType);
851  pRule.m_searchType = searchTypeFromString(sSearchType);
852  pRule.m_dupMethod = dupMethodFromString(sDupMethod);
853  pRule.m_dupIn = dupInFromString(sDupIn);
854 
855  if (sRecProfile.isEmpty())
856  sRecProfile = "Default";
857 
858  if (sRecGroup.isEmpty())
859  sRecGroup = "Default";
860 
861  if (sStorageGroup.isEmpty())
862  sStorageGroup = "Default";
863 
864  if (sPlayGroup.isEmpty())
865  sPlayGroup = "Default";
866 
867  if (!sTitle.isEmpty())
868  pRule.m_title = sTitle;
869 
870  if (!sSubtitle.isEmpty())
871  pRule.m_subtitle = sSubtitle;
872 
873  if(!sDescription.isEmpty())
874  pRule.m_description = sDescription;
875 
876  if (!sCategory.isEmpty())
877  pRule.m_category = sCategory;
878 
879  if (!sSeriesId.isEmpty())
880  pRule.m_seriesid = sSeriesId;
881 
882  if (!sProgramId.isEmpty())
883  pRule.m_programid = sProgramId;
884 
885  if (nChanId)
886  pRule.m_channelid = nChanId;
887  if (!sStation.isEmpty())
888  pRule.m_station = sStation;
889 
890  pRule.m_startdate = recstartts.date();
891  pRule.m_starttime = recstartts.time();
892  pRule.m_enddate = recendts.date();
893  pRule.m_endtime = recendts.time();
894 
895  pRule.m_findday = nFindDay;
896  pRule.m_findtime = tFindTime;
897 
898  pRule.m_recProfile = sRecProfile;
899  pRule.m_recGroupID = RecordingInfo::GetRecgroupID(sRecGroup) > 0 ? RecordingInfo::GetRecgroupID(sRecGroup) :
901  pRule.m_storageGroup = sStorageGroup;
902  pRule.m_playGroup = sPlayGroup;
903 
904  pRule.m_isInactive = bInactive;
905 
906  pRule.m_season = nSeason;
907  pRule.m_episode = nEpisode;
908  pRule.m_inetref = sInetref;
909 
910  pRule.m_recPriority = nRecPriority;
911  pRule.m_prefInput = nPreferredInput;
912  pRule.m_startOffset = nStartOffset;
913  pRule.m_endOffset = nEndOffset;
914  pRule.m_filter = nFilter;
915 
916  pRule.m_autoExpire = bAutoExpire;
917  pRule.m_maxEpisodes = nMaxEpisodes;
918  pRule.m_maxNewest = bMaxNewest;
919 
920  pRule.m_autoCommFlag = bAutoCommflag;
921  pRule.m_autoTranscode = bAutoTranscode;
922  pRule.m_autoMetadataLookup = bAutoMetaLookup;
923 
924  pRule.m_autoUserJob1 = bAutoUserJob1;
925  pRule.m_autoUserJob2 = bAutoUserJob2;
926  pRule.m_autoUserJob3 = bAutoUserJob3;
927  pRule.m_autoUserJob4 = bAutoUserJob4;
928 
929  pRule.m_transcoder = nTranscoder;
930 
931  QString msg;
932  if (!pRule.IsValid(msg))
933  throw msg;
934 
935  pRule.Save();
936 
937  return true;
938 }
939 
940 bool Dvr::RemoveRecordSchedule ( uint nRecordId )
941 {
942  bool bResult = false;
943 
944  if (nRecordId <= 0 )
945  throw QString("Record ID does not exist.");
946 
947  RecordingRule pRule;
948  pRule.m_recordID = nRecordId;
949 
950  bResult = pRule.Delete();
951 
952  return bResult;
953 }
954 
955 bool Dvr::AddDontRecordSchedule(int nChanId, const QDateTime &dStartTime,
956  bool bNeverRecord)
957 {
958  bool bResult = true;
959 
960  if (nChanId <= 0 || !dStartTime.isValid())
961  throw QString("Program does not exist.");
962 
963  ProgramInfo *pi = LoadProgramFromProgram(nChanId, dStartTime.toUTC());
964 
965  if (!pi)
966  throw QString("Program does not exist.");
967 
968  // Why RecordingInfo instead of ProgramInfo? Good question ...
969  RecordingInfo recInfo = RecordingInfo(*pi);
970 
971  delete pi;
972 
973  if (bNeverRecord)
974  {
975  recInfo.ApplyNeverRecord();
976  }
977  else
979 
980  return bResult;
981 }
982 
984  int nCount,
985  const QString &Sort,
986  bool Descending )
987 {
988  Scheduler::SchedSortColumn sortingColumn;
989  if (Sort.toLower() == "lastrecorded")
990  sortingColumn = Scheduler::kSortLastRecorded;
991  else if (Sort.toLower() == "title")
992  sortingColumn = Scheduler::kSortTitle;
993  else if (Sort.toLower() == "priority")
994  sortingColumn = Scheduler::kSortPriority;
995  else if (Sort.toLower() == "type")
996  sortingColumn = Scheduler::kSortType;
997 
998  RecList recList;
999  Scheduler::GetAllScheduled(recList, sortingColumn, !Descending);
1000 
1001  // ----------------------------------------------------------------------
1002  // Build Response
1003  // ----------------------------------------------------------------------
1004 
1005  DTC::RecRuleList *pRecRules = new DTC::RecRuleList();
1006 
1007  nStartIndex = min( nStartIndex, (int)recList.size() );
1008  nCount = (nCount > 0) ? min( nCount, (int)recList.size() ) : recList.size();
1009  int nEndIndex = min((nStartIndex + nCount), (int)recList.size() );
1010 
1011  for( int n = nStartIndex; n < nEndIndex; n++)
1012  {
1013  RecordingInfo *info = recList[n];
1014 
1015  if (info != NULL)
1016  {
1017  DTC::RecRule *pRecRule = pRecRules->AddNewRecRule();
1018 
1019  FillRecRuleInfo( pRecRule, info->GetRecordingRule() );
1020  }
1021  }
1022 
1023  // ----------------------------------------------------------------------
1024 
1025  pRecRules->setStartIndex ( nStartIndex );
1026  pRecRules->setCount ( nCount );
1027  pRecRules->setTotalAvailable( recList.size() );
1028  pRecRules->setAsOf ( MythDate::current() );
1029  pRecRules->setVersion ( MYTH_BINARY_VERSION );
1030  pRecRules->setProtoVer ( MYTH_PROTO_VERSION );
1031 
1032  while (!recList.empty())
1033  {
1034  delete recList.back();
1035  recList.pop_back();
1036  }
1037 
1038  return pRecRules;
1039 }
1040 
1042  QString sTemplate,
1043  int nChanId,
1044  QDateTime dStartTimeRaw,
1045  bool bMakeOverride )
1046 {
1047  RecordingRule rule;
1048  QDateTime dStartTime = dStartTimeRaw.toUTC();
1049 
1050  if (nRecordId > 0)
1051  {
1052  rule.m_recordID = nRecordId;
1053  if (!rule.Load())
1054  throw QString("Record ID does not exist.");
1055  }
1056  else if (!sTemplate.isEmpty())
1057  {
1058  if (!rule.LoadTemplate(sTemplate))
1059  throw QString("Template does not exist.");
1060  }
1061  else if (nChanId > 0 && dStartTime.isValid())
1062  {
1064  RecordingInfo info(nChanId, dStartTime, false, 0, &status);
1065  if (status != RecordingInfo::kFoundProgram)
1066  throw QString("Program does not exist.");
1067  RecordingRule *pRule = info.GetRecordingRule();
1068  if (bMakeOverride && rule.m_type != kSingleRecord &&
1069  rule.m_type != kOverrideRecord && rule.m_type != kDontRecord)
1070  pRule->MakeOverride();
1071  rule = *pRule;
1072  }
1073  else
1074  {
1075  throw QString("Invalid request.");
1076  }
1077 
1078  DTC::RecRule *pRecRule = new DTC::RecRule();
1079  FillRecRuleInfo( pRecRule, &rule );
1080 
1081  return pRecRule;
1082 }
1083 
1085 {
1086  bool bResult = false;
1087 
1088  if (nRecordId <= 0 )
1089  throw QString("Record ID appears invalid.");
1090 
1091  RecordingRule pRule;
1092  pRule.m_recordID = nRecordId;
1093  pRule.Load();
1094 
1095  if (pRule.IsLoaded())
1096  {
1097  pRule.m_isInactive = false;
1098  pRule.Save();
1099  bResult = true;
1100  }
1101 
1102  return bResult;
1103 }
1104 
1106 {
1107  bool bResult = false;
1108 
1109  if (nRecordId <= 0 )
1110  throw QString("Record ID appears invalid.");
1111 
1112  RecordingRule pRule;
1113  pRule.m_recordID = nRecordId;
1114  pRule.Load();
1115 
1116  if (pRule.IsLoaded())
1117  {
1118  pRule.m_isInactive = true;
1119  pRule.Save();
1120  bResult = true;
1121  }
1122 
1123  return bResult;
1124 }
1125 
1126 QString Dvr::RecStatusToString(int RecStatus)
1127 {
1128  RecStatusType type = static_cast<RecStatusType>(RecStatus);
1129  return toString(type);
1130 }
1131 
1132 QString Dvr::RecStatusToDescription(int RecStatus, int recType,
1133  const QDateTime &StartTime)
1134 {
1135  //if (!StartTime.isValid())
1136  // throw QString("StartTime appears invalid.");
1137  RecStatusType rsType = static_cast<RecStatusType>(RecStatus);
1138  RecordingType recordingType = static_cast<RecordingType>(recType);
1139  return toDescription(rsType, recordingType, StartTime);
1140 }
1141 
1142 QString Dvr::RecTypeToString(QString recType)
1143 {
1144  // RecordingType type = static_cast<RecordingType>(recType);
1145  return toString(recTypeFromString(recType));
1146 }
1147 
1148 QString Dvr::RecTypeToDescription(QString recType)
1149 {
1150  // RecordingType type = static_cast<RecordingType>(recType);
1151  return toDescription(recTypeFromString(recType));
1152 }
1153 
1154 QString Dvr::DupInToString(QString DupIn)
1155 {
1156  // RecordingDupInType type= static_cast<RecordingDupInType>(DupIn);
1157  // return toString(type);
1158  return toString(dupInFromString(DupIn));
1159 }
1160 
1161 QString Dvr::DupInToDescription(QString DupIn)
1162 {
1163  // RecordingDupInType type= static_cast<RecordingDupInType>(DupIn);
1164  //return toDescription(type);
1165  return toDescription(dupInFromString(DupIn));
1166 }
1167 
1168 QString Dvr::DupMethodToString(QString DupMethod)
1169 {
1170  // RecordingDupMethodType method = static_cast<RecordingDupMethodType>(DupMethod);
1171  return toString(dupMethodFromString(DupMethod));
1172 }
1173 
1174 QString Dvr::DupMethodToDescription(QString DupMethod)
1175 {
1176  // RecordingDupMethodType method = static_cast<RecordingDupMethodType>(DupMethod);
1177  return toDescription(dupMethodFromString(DupMethod));
1178 }
QString RecStatusToString(int RecStatus)
Definition: dvr.cpp:1126
QString m_subtitle
Definition: recordingrule.h:76
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:765
MythScheduler * GetScheduler(void)
DTC::ProgramList * GetConflictList(int StartIndex, int Count, int RecordId)
Definition: dvr.cpp:586
Program * AddNewProgram()
Definition: programList.h:86
void bindValue(const QString &placeholder, const QVariant &val)
Definition: mythdbcon.cpp:857
AutoExpire * expirer
QString m_programid
Definition: recordingrule.h:88
DTC::RecRuleFilterList * GetRecRuleFilterList()
Definition: dvr.cpp:418
DTC::TitleInfoList * GetTitleInfoList()
Definition: dvr.cpp:478
SchedSortColumn
Definition: scheduler.h:69
ProgramInfo * LoadProgramFromProgram(const uint chanid, const QDateTime &starttime)
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
Definition: tv.h:67
void push_back(T info)
void FillProgramInfo(DTC::Program *pProgram, ProgramInfo *pInfo, bool bIncChannel, bool bDetails, bool bIncCast)
Definition: serviceUtil.cpp:43
bool Delete(bool sendSig=true)
bool IsLoaded() const
Definition: recordingrule.h:55
RecSearchType searchTypeFromString(QString type)
QString toString(MarkTypes type)
QStringList GetPlayGroupList()
Definition: dvr.cpp:409
QString toDescription(RecStatusType recstatus, RecordingType rectype, const QDateTime &recstartts)
Converts "recstatus" into a long human readable description.
QVariant value(int i) const
Definition: mythdbcon.h:182
bool UnDeleteRecording(int ChanId, const QDateTime &StartTime)
Definition: dvr.cpp:196
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
RecordingType recTypeFromString(QString type)
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:32
QString DupMethodToDescription(QString DupMethod)
Definition: dvr.cpp:1174
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:84
unsigned int uint
Definition: compat.h:135
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QString DupInToString(QString DupIn)
Definition: dvr.cpp:1154
GLint GLenum GLsizei GLint GLenum GLenum type
AutoDeleteDeque< ProgramInfo * > ProgramList
Definition: programinfo.h:35
RecordingType m_type
Definition: recordingrule.h:99
RecordingDupMethodType m_dupMethod
DTC::RecRuleList * GetRecordScheduleList(int StartIndex, int Count, const QString &Sort, bool Descending)
Definition: dvr.cpp:983
DTC::ProgramList * GetExpiringList(int StartIndex, int Count)
Definition: dvr.cpp:238
uint cardid
card id associated with input
Definition: inputinfo.h:73
static uint GetRecgroupID(const QString &recGroup)
Temporary helper during transition from string to ID.
iterator begin(void)
size_t size(void) const
deque< RecordingInfo * > RecList
Definition: mythscheduler.h:12
bool UpdateRecordedWatchedStatus(int ChanId, const QDateTime &StartTime, bool Watched)
Definition: dvr.cpp:221
QStringList GetRecStorageGroupList()
Definition: dvr.cpp:400
bool Save(bool sendSig=true)
RecordingDupMethodType dupMethodFromString(QString type)
Holds information on recordings and videos.
Definition: programinfo.h:72
void ApplyRecordStateChange(RecordingType newstate, bool save=true)
Sets RecordingType of "record", creating "record" if it does not exist.
Recording Only is a TVRec only state for when we are recording a program, but there is no one current...
Definition: tv.h:88
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:1655
static QMap< QString, uint32_t > QueryInUseMap(void)
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
QString DupMethodToString(QString DupMethod)
Definition: dvr.cpp:1168
Input * AddNewInput()
Definition: inputList.h:59
if[["$1"==""]]
Definition: create_test.sh:7
QString m_description
Definition: recordingrule.h:77
bool DeleteRecording(int ChanId, const QDateTime &StartTime, bool ForceDelete, bool AllowRerecord)
Definition: dvr.cpp:168
DTC::Program * GetRecorded(int ChanId, const QDateTime &StartTime)
Definition: dvr.cpp:144
QString RecStatusToDescription(int RecStatus, int RecType, const QDateTime &StartTime)
Definition: dvr.cpp:1132
QString RecTypeToString(QString RecType)
Definition: dvr.cpp:1142
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:529
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:31
static QList< InputInfo > GetAllInputInfo()
Definition: cardutil.cpp:1205
void GetAllExpiring(QStringList &strList)
Gets the full list of programs that can expire in expiration order.
Definition: autoexpire.cpp:841
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:1148
void dispatch(const MythEvent &event)
QString m_inetref
Definition: recordingrule.h:89
DTC::RecRule * GetRecordSchedule(uint RecordId, QString Template, int ChanId, QDateTime StartTime, bool MakeOverride)
Definition: dvr.cpp:1041
bool AddDontRecordSchedule(int ChanId, const QDateTime &StartTime, bool NeverRecord)
Definition: dvr.cpp:955
Encoder * AddNewEncoder()
Definition: encoderList.h:59
DTC::ProgramList * GetUpcomingList(int StartIndex, int Count, bool ShowAll, int RecordId, int RecStatus)
Definition: dvr.cpp:514
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:790
RecRule * AddNewRecRule()
Definition: recRuleList.h:72
QString GetRecordingGroup(void) const
Definition: programinfo.h:398
QString m_title
Recording rule is enabled?
Definition: recordingrule.h:75
bool RemoveRecorded(int ChanId, const QDateTime &StartTime, bool ForceDelete, bool AllowRerecord)
Definition: dvr.cpp:161
Used to expire recordings to make space for new recordings.
Definition: autoexpire.h:62
void ApplyNeverRecord(void)
Set this program to never be recorded by inserting 'history' for it into the database with a status o...
QString DupInToDescription(QString DupIn)
Definition: dvr.cpp:1161
iterator end(void)
static QMap< QString, bool > QueryJobsRunning(int type)
QString m_recProfile
bool LoadFromScheduler(AutoDeleteDeque< TYPE * > &destination, bool &hasConflicts, QString altTable="", int recordid=-1)
Definition: programinfo.h:792
void SaveWatched(bool watchedFlag)
Set "watched" field in recorded/videometadata to "watchedFlag".
DTC::EncoderList * GetEncoderList()
Definition: dvr.cpp:286
static QStringList GetNames(void)
Definition: playgroup.cpp:173
virtual QMap< QString, ProgramInfo * > GetRecording(void) const =0
bool RemoveRecordSchedule(uint RecordId)
Definition: dvr.cpp:940
bool Load(bool asTemplate=false)
unsigned m_filter
QString GetStorageGroup(void) const
Definition: programinfo.h:401
QString m_category
Definition: recordingrule.h:80
bool LoadFromRecorded(ProgramList &destination, bool possiblyInProgressRecordingsOnly, const QMap< QString, uint32_t > &inUseMap, const QMap< QString, bool > &isJobRunning, const QMap< QString, ProgramInfo * > &recMap, int sort)
bool LoadTemplate(QString category, QString categoryType="Default")
enum RecStatusTypes RecStatusType
DTC::InputList * GetInputList()
Definition: dvr.cpp:357
DTC::ProgramList * GetRecordedList(bool Descending, int StartIndex, int Count, const QString &TitleRegEx, const QString &RecGroup, const QString &StorageGroup)
Definition: dvr.cpp:62
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:597
vector< ProgramInfo * > pginfolist_t
Definition: autoexpire.h:23
QStringList GetRecGroupList()
Definition: dvr.cpp:377
RecordingDupInType dupInFromString(QString type)
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:181
void FillInputInfo(DTC::Input *input, InputInfo inputInfo)
bool MakeOverride(void)
bool DisableRecordSchedule(uint RecordId)
Definition: dvr.cpp:1105
List::iterator iterator
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:782
Default UTC.
Definition: mythdate.h:14
bool EnableRecordSchedule(uint RecordId)
Definition: dvr.cpp:1084
QStringList GetTitleList(const QString &RecGroup)
Definition: dvr.cpp:445
QString GetTitle(void) const
Definition: programinfo.h:342
RecSearchType m_searchType
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:641
bool IsValid(QString &text)