MythTV  0.27pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
dvr.cpp
Go to the documentation of this file.
1 
2 // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 
42 #include "serviceUtil.h"
43 #include <mythscheduler.h>
44 
45 extern QMap<int, EncoderLink *> tvList;
46 extern AutoExpire *expirer;
47 
49 //
51 
53  int nStartIndex,
54  int nCount )
55 {
56  return GetFilteredRecordedList( bDescending, nStartIndex, nCount,
57  QString(), QString(), QString() );
58 }
59 
61  int nStartIndex,
62  int nCount,
63  const QString &sTitleRegEx,
64  const QString &sRecGroup,
65  const QString &sStorageGroup )
66 {
67  QMap< QString, ProgramInfo* > recMap;
68 
70  recMap = gCoreContext->GetScheduler()->GetRecording();
71 
72  QMap< QString, uint32_t > inUseMap = ProgramInfo::QueryInUseMap();
73  QMap< QString, bool > isJobRunning= ProgramInfo::QueryJobsRunning(JOB_COMMFLAG);
74 
75  ProgramList progList;
76 
77  int desc = 0;
78  if (bDescending)
79  desc = -1;
80 
81  LoadFromRecorded( progList, false, inUseMap, isJobRunning, recMap, desc );
82 
83  QMap< QString, ProgramInfo* >::iterator mit = recMap.begin();
84 
85  for (; mit != recMap.end(); mit = recMap.erase(mit))
86  delete *mit;
87 
88  // ----------------------------------------------------------------------
89  // Build Response
90  // ----------------------------------------------------------------------
91 
92  DTC::ProgramList *pPrograms = new DTC::ProgramList();
93  int nAvailable = 0;
94 
95  if ((sTitleRegEx.isEmpty()) &&
96  (sRecGroup.isEmpty()) &&
97  (sStorageGroup.isEmpty()))
98  {
99  nStartIndex = min( nStartIndex, (int)progList.size() );
100  nCount = (nCount > 0) ? min( nCount, (int)progList.size() ) : progList.size();
101  int nEndIndex = min((nStartIndex + nCount), (int)progList.size() );
102  nCount = nEndIndex - nStartIndex;
103 
104  nAvailable = progList.size();
105 
106  for( int n = nStartIndex; n < nEndIndex; n++)
107  {
108  ProgramInfo *pInfo = progList[ n ];
109  if (pInfo->GetRecordingGroup() != "Deleted")
110  {
111  DTC::Program *pProgram = pPrograms->AddNewProgram();
112 
113  FillProgramInfo( pProgram, pInfo, true );
114  }
115  }
116  }
117  else
118  {
119  int nMax = nCount;
120 
121  nAvailable = 0;
122  nCount = 0;
123 
124  QRegExp rTitleRegEx = QRegExp(sTitleRegEx, Qt::CaseInsensitive);
125 
126  for( unsigned int n = 0; n < progList.size(); n++)
127  {
128  ProgramInfo *pInfo = progList[ n ];
129 
130  if ((!sTitleRegEx.isEmpty() && !pInfo->GetTitle().contains(rTitleRegEx)) ||
131  (!sRecGroup.isEmpty() && sRecGroup != pInfo->GetRecordingGroup()) ||
132  (!sStorageGroup.isEmpty() && sStorageGroup != pInfo->GetStorageGroup()))
133  continue;
134 
135  ++nAvailable;
136 
137  if ((nAvailable < nStartIndex) ||
138  (nCount >= nMax))
139  continue;
140 
141  ++nCount;
142 
143  DTC::Program *pProgram = pPrograms->AddNewProgram();
144 
145  FillProgramInfo( pProgram, pInfo, true );
146  }
147  }
148 
149  // ----------------------------------------------------------------------
150 
151  pPrograms->setStartIndex ( nStartIndex );
152  pPrograms->setCount ( nCount );
153  pPrograms->setTotalAvailable( nAvailable );
154  pPrograms->setAsOf ( MythDate::current() );
155  pPrograms->setVersion ( MYTH_BINARY_VERSION );
156  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
157 
158  return pPrograms;
159 }
160 
162 //
164 
165 DTC::Program* Dvr::GetRecorded(int chanid, const QDateTime &recstarttsRaw)
166 {
167  if (chanid <= 0 || !recstarttsRaw.isValid())
168  throw QString("Channel ID or StartTime appears invalid.");
169 
170  ProgramInfo pi(chanid, recstarttsRaw.toUTC());
171 
172  DTC::Program *pProgram = new DTC::Program();
173  FillProgramInfo( pProgram, &pi, true );
174 
175  return pProgram;
176 }
177 
179 //
181 
182 bool Dvr::RemoveRecorded(int chanid, const QDateTime &recstarttsRaw)
183 {
184  if (chanid <= 0 || !recstarttsRaw.isValid())
185  throw QString("Channel ID or StartTime appears invalid.");
186 
187  ProgramInfo pi(chanid, recstarttsRaw.toUTC());
188 
189  if (pi.GetChanID() && pi.HasPathname())
190  {
191  QString cmd = QString("DELETE_RECORDING %1 %2")
192  .arg(pi.GetChanID())
193  .arg(pi.GetRecordingStartTime(MythDate::ISODate));
194  MythEvent me(cmd);
195 
196  gCoreContext->dispatch(me);
197  return true;
198  }
199 
200  return false;
201 }
202 
204 //
206 
208  int nCount )
209 {
210  pginfolist_t infoList;
211 
212  if (expirer)
213  expirer->GetAllExpiring( infoList );
214 
215  // ----------------------------------------------------------------------
216  // Build Response
217  // ----------------------------------------------------------------------
218 
219  DTC::ProgramList *pPrograms = new DTC::ProgramList();
220 
221  nStartIndex = min( nStartIndex, (int)infoList.size() );
222  nCount = (nCount > 0) ? min( nCount, (int)infoList.size() ) : infoList.size();
223  int nEndIndex = min((nStartIndex + nCount), (int)infoList.size() );
224 
225  for( int n = nStartIndex; n < nEndIndex; n++)
226  {
227  ProgramInfo *pInfo = infoList[ n ];
228 
229  if (pInfo != NULL)
230  {
231  DTC::Program *pProgram = pPrograms->AddNewProgram();
232 
233  FillProgramInfo( pProgram, pInfo, true );
234 
235  delete pInfo;
236  }
237  }
238 
239  // ----------------------------------------------------------------------
240 
241  pPrograms->setStartIndex ( nStartIndex );
242  pPrograms->setCount ( nCount );
243  pPrograms->setTotalAvailable( infoList.size() );
244  pPrograms->setAsOf ( MythDate::current() );
245  pPrograms->setVersion ( MYTH_BINARY_VERSION );
246  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
247 
248  return pPrograms;
249 }
250 
252 //
254 
256 {
257  DTC::EncoderList* pList = new DTC::EncoderList();
258 
259  QMap<int, EncoderLink *>::Iterator iter = tvList.begin();
260 
261  for (; iter != tvList.end(); ++iter)
262  {
263  EncoderLink *elink = *iter;
264 
265  if (elink != NULL)
266  {
267  DTC::Encoder *pEncoder = pList->AddNewEncoder();
268 
269  pEncoder->setId ( elink->GetCardID() );
270  pEncoder->setState ( elink->GetState() );
271  pEncoder->setLocal ( elink->IsLocal() );
272  pEncoder->setConnected ( elink->IsConnected() );
273  pEncoder->setSleepStatus ( elink->GetSleepStatus() );
274  // pEncoder->setLowOnFreeSpace( elink->isLowOnFreeSpace());
275 
276  if (pEncoder->Local())
277  pEncoder->setHostName( gCoreContext->GetHostName() );
278  else
279  pEncoder->setHostName( elink->GetHostName() );
280 
281  switch ( pEncoder->State() )
282  {
286  {
287  ProgramInfo *pInfo = elink->GetRecording();
288 
289  if (pInfo)
290  {
291  DTC::Program *pProgram = pEncoder->Recording();
292 
293  FillProgramInfo( pProgram, pInfo, true, true );
294 
295  delete pInfo;
296  }
297 
298  break;
299  }
300 
301  default:
302  break;
303  }
304  }
305  }
306  return pList;
307 }
308 
310 //
312 
313 QStringList Dvr::GetRecGroupList()
314 {
315  MSqlQuery query(MSqlQuery::InitCon());
316 
317  QString querystr = QString("SELECT DISTINCT recgroup FROM record");
318 
319  query.prepare(querystr);
320 
321  QStringList result;
322  if (!query.exec())
323  {
324  MythDB::DBError("GetRecGroupList record", query);
325  return result;
326  }
327 
328  while (query.next())
329  result << query.value(0).toString();
330 
331  querystr = QString("SELECT DISTINCT recgroup FROM recorded");
332 
333  query.prepare(querystr);
334 
335  if (!query.exec())
336  {
337  MythDB::DBError("GetRecGroupList recorded", query);
338  return result;
339  }
340 
341  while (query.next())
342  {
343  QString value = query.value(0).toString();
344 
345  if (!result.contains(value))
346  result << value;
347  }
348 
349  result.sort();
350 
351  return result;
352 }
353 
355 //
357 
358 QStringList Dvr::GetTitleList()
359 {
360  MSqlQuery query(MSqlQuery::InitCon());
361 
362  QString querystr = QString("SELECT DISTINCT title FROM recorded");
363 
364  query.prepare(querystr);
365 
366  QStringList result;
367  if (!query.exec())
368  {
369  MythDB::DBError("GetTitleList recorded", query);
370  return result;
371  }
372 
373  while (query.next())
374  result << query.value(0).toString();
375 
376  result.sort();
377 
378  return result;
379 }
380 
382 //
384 
386  int nCount,
387  bool bShowAll )
388 {
389  RecordingList recordingList;
390  RecordingList tmpList;
391  bool hasConflicts;
392  LoadFromScheduler(tmpList, hasConflicts);
393 
394  // Sort the upcoming into only those which will record
395  RecordingList::iterator it = tmpList.begin();
396  for(; it < tmpList.end(); ++it)
397  {
398  if (!bShowAll && ((*it)->GetRecordingStatus() <= rsWillRecord) &&
399  ((*it)->GetRecordingStartTime() >= MythDate::current()))
400  {
401  recordingList.push_back(new RecordingInfo(**it));
402  }
403  else if (bShowAll &&
404  ((*it)->GetRecordingStartTime() >= MythDate::current()))
405  {
406  recordingList.push_back(new RecordingInfo(**it));
407  }
408  }
409 
410  // ----------------------------------------------------------------------
411  // Build Response
412  // ----------------------------------------------------------------------
413 
414  DTC::ProgramList *pPrograms = new DTC::ProgramList();
415 
416  nStartIndex = min( nStartIndex, (int)recordingList.size() );
417  nCount = (nCount > 0) ? min( nCount, (int)recordingList.size() ) : recordingList.size();
418  int nEndIndex = min((nStartIndex + nCount), (int)recordingList.size() );
419 
420  for( int n = nStartIndex; n < nEndIndex; n++)
421  {
422  ProgramInfo *pInfo = recordingList[ n ];
423 
424  DTC::Program *pProgram = pPrograms->AddNewProgram();
425 
426  FillProgramInfo( pProgram, pInfo, true );
427  }
428 
429  // ----------------------------------------------------------------------
430 
431  pPrograms->setStartIndex ( nStartIndex );
432  pPrograms->setCount ( nCount );
433  pPrograms->setTotalAvailable( recordingList.size() );
434  pPrograms->setAsOf ( MythDate::current() );
435  pPrograms->setVersion ( MYTH_BINARY_VERSION );
436  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
437 
438  return pPrograms;
439 }
440 
442 //
444 
446  int nCount )
447 {
448  RecordingList recordingList;
449  RecordingList tmpList;
450  bool hasConflicts;
451  LoadFromScheduler(tmpList, hasConflicts);
452 
453  // Sort the upcoming into only those which are conflicts
454  RecordingList::iterator it = tmpList.begin();
455  for(; it < tmpList.end(); ++it)
456  {
457  if (((*it)->GetRecordingStatus() == rsConflict) &&
458  ((*it)->GetRecordingStartTime() >= MythDate::current()))
459  {
460  recordingList.push_back(new RecordingInfo(**it));
461  }
462  }
463 
464  // ----------------------------------------------------------------------
465  // Build Response
466  // ----------------------------------------------------------------------
467 
468  DTC::ProgramList *pPrograms = new DTC::ProgramList();
469 
470  nStartIndex = min( nStartIndex, (int)recordingList.size() );
471  nCount = (nCount > 0) ? min( nCount, (int)recordingList.size() ) : recordingList.size();
472  int nEndIndex = min((nStartIndex + nCount), (int)recordingList.size() );
473 
474  for( int n = nStartIndex; n < nEndIndex; n++)
475  {
476  ProgramInfo *pInfo = recordingList[ n ];
477 
478  DTC::Program *pProgram = pPrograms->AddNewProgram();
479 
480  FillProgramInfo( pProgram, pInfo, true );
481  }
482 
483  // ----------------------------------------------------------------------
484 
485  pPrograms->setStartIndex ( nStartIndex );
486  pPrograms->setCount ( nCount );
487  pPrograms->setTotalAvailable( recordingList.size() );
488  pPrograms->setAsOf ( MythDate::current() );
489  pPrograms->setVersion ( MYTH_BINARY_VERSION );
490  pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
491 
492  return pPrograms;
493 }
494 
496  QString sTitle,
497  QString sSubtitle,
498  QString sDescription,
499  QString sCategory,
500  QDateTime recstarttsRaw,
501  QDateTime recendtsRaw,
502  QString sSeriesId,
503  QString sProgramId,
504  int nChanId,
505  QString sStation,
506  int nFindDay,
507  QTime tFindTime,
508  int nParentId,
509  bool bInactive,
510  uint nSeason,
511  uint nEpisode,
512  QString sInetref,
513  QString sType,
514  QString sSearchType,
515  int nRecPriority,
516  uint nPreferredInput,
517  int nStartOffset,
518  int nEndOffset,
519  QString sDupMethod,
520  QString sDupIn,
521  uint nFilter,
522  QString sRecProfile,
523  QString sRecGroup,
524  QString sStorageGroup,
525  QString sPlayGroup,
526  bool bAutoExpire,
527  int nMaxEpisodes,
528  bool bMaxNewest,
529  bool bAutoCommflag,
530  bool bAutoTranscode,
531  bool bAutoMetaLookup,
532  bool bAutoUserJob1,
533  bool bAutoUserJob2,
534  bool bAutoUserJob3,
535  bool bAutoUserJob4,
536  int nTranscoder)
537 {
538  QDateTime recstartts = recstarttsRaw.toUTC();
539  QDateTime recendts = recendtsRaw.toUTC();
540  RecordingRule rule;
541  rule.LoadTemplate("Default");
542 
543  if (sType.isEmpty())
544  sType = "single";
545 
546  if (sSearchType.isEmpty())
547  sSearchType = "none";
548 
549  if (sDupMethod.isEmpty())
550  sDupMethod = "subtitleanddescription";
551 
552  if (sDupIn.isEmpty())
553  sDupIn = "all";
554 
555  rule.m_title = sTitle;
556  rule.m_subtitle = sSubtitle;
557  rule.m_description = sDescription;
558 
559  rule.m_type = recTypeFromString(sType);
560  rule.m_searchType = searchTypeFromString(sSearchType);
561  rule.m_dupMethod = dupMethodFromString(sDupMethod);
562  rule.m_dupIn = dupInFromString(sDupIn);
563 
564  if (sRecProfile.isEmpty())
565  sRecProfile = "Default";
566 
567  if (sRecGroup.isEmpty())
568  sRecGroup = "Default";
569 
570  if (sStorageGroup.isEmpty())
571  sStorageGroup = "Default";
572 
573  if (sPlayGroup.isEmpty())
574  sPlayGroup = "Default";
575 
576  rule.m_category = sCategory;
577  rule.m_seriesid = sSeriesId;
578  rule.m_programid = sProgramId;
579 
580  rule.m_station = sStation;
581 
582  rule.m_findday = nFindDay;
583  rule.m_findtime = tFindTime;
584 
585  rule.m_recProfile = sRecProfile;
586  rule.m_recGroup = sRecGroup;
587  rule.m_storageGroup = sStorageGroup;
588  rule.m_playGroup = sPlayGroup;
589 
590  rule.m_parentRecID = nParentId;
591  rule.m_isInactive = bInactive;
592 
593  rule.m_season = nSeason;
594  rule.m_episode = nEpisode;
595  rule.m_inetref = sInetref;
596 
597  rule.m_recPriority = nRecPriority;
598  rule.m_prefInput = nPreferredInput;
599  rule.m_startOffset = nStartOffset;
600  rule.m_endOffset = nEndOffset;
601  rule.m_filter = nFilter;
602 
603  rule.m_autoExpire = bAutoExpire;
604  rule.m_maxEpisodes = nMaxEpisodes;
605  rule.m_maxNewest = bMaxNewest;
606 
607  rule.m_autoCommFlag = bAutoCommflag;
608  rule.m_autoTranscode = bAutoTranscode;
609  rule.m_autoMetadataLookup = bAutoMetaLookup;
610 
611  rule.m_autoUserJob1 = bAutoUserJob1;
612  rule.m_autoUserJob2 = bAutoUserJob2;
613  rule.m_autoUserJob3 = bAutoUserJob3;
614  rule.m_autoUserJob4 = bAutoUserJob4;
615 
616  rule.m_transcoder = nTranscoder;
617 
618  QString msg;
619  if (!rule.IsValid(msg))
620  throw msg;
621 
622  rule.Save();
623 
624  int recid = rule.m_recordID;
625 
626  return recid;
627 }
628 
629 bool Dvr::UpdateRecordSchedule ( int nRecordId,
630  QString sTitle,
631  QString sSubtitle,
632  QString sDescription,
633  QString sCategory,
634  QDateTime dStartTimeRaw,
635  QDateTime dEndTimeRaw,
636  QString sSeriesId,
637  QString sProgramId,
638  int nChanId,
639  QString sStation,
640  int nFindDay,
641  QTime tFindTime,
642  bool bInactive,
643  uint nSeason,
644  uint nEpisode,
645  QString sInetref,
646  QString sType,
647  QString sSearchType,
648  int nRecPriority,
649  uint nPreferredInput,
650  int nStartOffset,
651  int nEndOffset,
652  QString sDupMethod,
653  QString sDupIn,
654  uint nFilter,
655  QString sRecProfile,
656  QString sRecGroup,
657  QString sStorageGroup,
658  QString sPlayGroup,
659  bool bAutoExpire,
660  int nMaxEpisodes,
661  bool bMaxNewest,
662  bool bAutoCommflag,
663  bool bAutoTranscode,
664  bool bAutoMetaLookup,
665  bool bAutoUserJob1,
666  bool bAutoUserJob2,
667  bool bAutoUserJob3,
668  bool bAutoUserJob4,
669  int nTranscoder)
670 {
671  if (nRecordId <= 0 )
672  throw QString("Record ID is invalid.");
673 
674  RecordingRule pRule;
675  pRule.m_recordID = nRecordId;
676  pRule.Load();
677 
678  if (!pRule.IsLoaded())
679  throw QString("Record ID does not exist.");
680 
681  QDateTime recstartts = dStartTimeRaw.toUTC();
682  QDateTime recendts = dEndTimeRaw.toUTC();
683 
684  pRule.m_isInactive = bInactive;
685  if (sType.isEmpty())
686  sType = "single";
687 
688  if (sSearchType.isEmpty())
689  sSearchType = "none";
690 
691  if (sDupMethod.isEmpty())
692  sDupMethod = "subtitleanddescription";
693 
694  if (sDupIn.isEmpty())
695  sDupIn = "all";
696 
697  pRule.m_type = recTypeFromString(sType);
698  pRule.m_searchType = searchTypeFromString(sSearchType);
699  pRule.m_dupMethod = dupMethodFromString(sDupMethod);
700  pRule.m_dupIn = dupInFromString(sDupIn);
701 
702  if (sRecProfile.isEmpty())
703  sRecProfile = "Default";
704 
705  if (sRecGroup.isEmpty())
706  sRecGroup = "Default";
707 
708  if (sStorageGroup.isEmpty())
709  sStorageGroup = "Default";
710 
711  if (sPlayGroup.isEmpty())
712  sPlayGroup = "Default";
713 
714  if (!sTitle.isEmpty())
715  pRule.m_title = sTitle;
716 
717  if (!sSubtitle.isEmpty())
718  pRule.m_subtitle = sSubtitle;
719 
720  if(!sDescription.isEmpty())
721  pRule.m_description = sDescription;
722 
723  if (!sCategory.isEmpty())
724  pRule.m_category = sCategory;
725 
726  if (!sSeriesId.isEmpty())
727  pRule.m_seriesid = sSeriesId;
728 
729  if (!sProgramId.isEmpty())
730  pRule.m_programid = sProgramId;
731 
732  if (!sStation.isEmpty())
733  pRule.m_station = sStation;
734 
735  pRule.m_startdate = recstartts.date();
736  pRule.m_starttime = recstartts.time();
737 
738  pRule.m_enddate = recendts.date();
739  pRule.m_endtime = recendts.time();
740 
741  pRule.m_findday = nFindDay;
742  pRule.m_findtime = tFindTime;
743 
744  pRule.m_recProfile = sRecProfile;
745  pRule.m_recGroup = sRecGroup;
746  pRule.m_storageGroup = sStorageGroup;
747  pRule.m_playGroup = sPlayGroup;
748 
749  pRule.m_isInactive = bInactive;
750 
751  pRule.m_season = nSeason;
752  pRule.m_episode = nEpisode;
753  pRule.m_inetref = sInetref;
754 
755  pRule.m_recPriority = nRecPriority;
756  pRule.m_prefInput = nPreferredInput;
757  pRule.m_startOffset = nStartOffset;
758  pRule.m_endOffset = nEndOffset;
759  pRule.m_filter = nFilter;
760 
761  pRule.m_autoExpire = bAutoExpire;
762  pRule.m_maxEpisodes = nMaxEpisodes;
763  pRule.m_maxNewest = bMaxNewest;
764 
765  pRule.m_autoCommFlag = bAutoCommflag;
766  pRule.m_autoTranscode = bAutoTranscode;
767  pRule.m_autoMetadataLookup = bAutoMetaLookup;
768 
769  pRule.m_autoUserJob1 = bAutoUserJob1;
770  pRule.m_autoUserJob2 = bAutoUserJob2;
771  pRule.m_autoUserJob3 = bAutoUserJob3;
772  pRule.m_autoUserJob4 = bAutoUserJob4;
773 
774  pRule.m_transcoder = nTranscoder;
775 
776  QString msg;
777  if (!pRule.IsValid(msg))
778  throw msg;
779 
780  pRule.Save();
781 
782  return true;
783 }
784 
785 bool Dvr::RemoveRecordSchedule ( uint nRecordId )
786 {
787  bool bResult = false;
788 
789  if (nRecordId <= 0 )
790  throw QString("Record ID does not exist.");
791 
792  RecordingRule pRule;
793  pRule.m_recordID = nRecordId;
794 
795  bResult = pRule.Delete();
796 
797  return bResult;
798 }
799 
801  int nCount )
802 {
803  RecList recList;
805 
806  // ----------------------------------------------------------------------
807  // Build Response
808  // ----------------------------------------------------------------------
809 
810  DTC::RecRuleList *pRecRules = new DTC::RecRuleList();
811 
812  nStartIndex = min( nStartIndex, (int)recList.size() );
813  nCount = (nCount > 0) ? min( nCount, (int)recList.size() ) : recList.size();
814  int nEndIndex = min((nStartIndex + nCount), (int)recList.size() );
815 
816  for( int n = nStartIndex; n < nEndIndex; n++)
817  {
818  RecordingInfo *info = recList[n];
819 
820  if (info != NULL)
821  {
822  DTC::RecRule *pRecRule = pRecRules->AddNewRecRule();
823 
824  FillRecRuleInfo( pRecRule, info->GetRecordingRule() );
825  }
826  }
827 
828  // ----------------------------------------------------------------------
829 
830  pRecRules->setStartIndex ( nStartIndex );
831  pRecRules->setCount ( nCount );
832  pRecRules->setTotalAvailable( recList.size() );
833  pRecRules->setAsOf ( MythDate::current() );
834  pRecRules->setVersion ( MYTH_BINARY_VERSION );
835  pRecRules->setProtoVer ( MYTH_PROTO_VERSION );
836 
837  while (!recList.empty())
838  {
839  delete recList.back();
840  recList.pop_back();
841  }
842 
843  return pRecRules;
844 }
845 
847  QString sTemplate,
848  int nChanId,
849  QDateTime dStartTimeRaw,
850  bool bMakeOverride )
851 {
852  if (nRecordId < 0 )
853  throw QString("Record ID is invalid.");
854 
855  RecordingRule rule;
856 
857  if (nRecordId > 0)
858  {
859  rule.m_recordID = nRecordId;
860  if (!rule.Load())
861  throw QString("Record ID does not exist.");
862  }
863  else if (!sTemplate.isEmpty())
864  {
865  if (!rule.LoadTemplate(sTemplate))
866  throw QString("Template does not exist.");
867  }
868  else if (nChanId > 0 && dStartTimeRaw.isValid())
869  {
871  RecordingInfo info(nChanId, dStartTimeRaw, false, 0, &status);
872  if (status != RecordingInfo::kFoundProgram)
873  throw QString("Program does not exist.");
874  RecordingRule *pRule = info.GetRecordingRule();
875  if (bMakeOverride && rule.m_type != kSingleRecord &&
876  rule.m_type != kOverrideRecord && rule.m_type != kDontRecord)
877  pRule->MakeOverride();
878  rule = *pRule;
879  }
880  else
881  {
882  throw QString("Invalid request.");
883  }
884 
885  DTC::RecRule *pRecRule = new DTC::RecRule();
886  FillRecRuleInfo( pRecRule, &rule );
887 
888  return pRecRule;
889 }
890 
891 bool Dvr::EnableRecordSchedule ( uint nRecordId )
892 {
893  bool bResult = false;
894 
895  if (nRecordId <= 0 )
896  throw QString("Record ID appears invalid.");
897 
898  RecordingRule pRule;
899  pRule.m_recordID = nRecordId;
900  pRule.Load();
901 
902  if (pRule.IsLoaded())
903  {
904  pRule.m_isInactive = false;
905  pRule.Save();
906  bResult = true;
907  }
908 
909  return bResult;
910 }
911 
913 {
914  bool bResult = false;
915 
916  if (nRecordId <= 0 )
917  throw QString("Record ID appears invalid.");
918 
919  RecordingRule pRule;
920  pRule.m_recordID = nRecordId;
921  pRule.Load();
922 
923  if (pRule.IsLoaded())
924  {
925  pRule.m_isInactive = true;
926  pRule.Save();
927  bResult = true;
928  }
929 
930  return bResult;
931 }
932