MythTV  master
recordinginfo.cpp
Go to the documentation of this file.
1 // POSIX headers
2 #include <sys/types.h>
3 
4 // C headers
5 #include <cstdlib>
6 
7 // Qt headers
8 #include <QMap>
9 
10 // MythTV headers
11 #include "recordinginfo.h"
12 #include "recordingrule.h"
13 #include "scheduledrecording.h"
14 #include "mythmiscutil.h"
15 #include "mythdate.h"
16 #include "mythcorecontext.h"
17 #include "programinfoupdater.h"
18 #include "jobqueue.h"
19 #include "mythdb.h"
20 #include "mythlogging.h"
21 
22 #define LOC QString("RecordingInfo(%1): ").arg(GetBasename())
23 
24 const QRegularExpression RecordingInfo::kReSearchTypeName { R"(\s*\(.*\)$)" };
25 const QRegularExpression RecordingInfo::kReLeadingAnd
26  { R"(^\s*AND\s*)", QRegularExpression::CaseInsensitiveOption };
27 
28 static inline QString null_to_empty(const QString &str)
29 {
30  return str.isEmpty() ? "" : str;
31 }
32 
34 // works only for integer divisors of 60
35 static const uint kUnknownProgramLength = 30;
36 
38  const QString &_title,
39  const QString &_sortTitle,
40  const QString &_subtitle,
41  const QString &_sortSubtitle,
42  const QString &_description,
43  uint _season,
44  uint _episode,
45  uint _totalepisodes,
46  const QString &_syndicatedepisode,
47  const QString &_category,
48 
49  uint _chanid,
50  const QString &_chanstr,
51  const QString &_chansign,
52  const QString &_channame,
53 
54  const QString &_recgroup,
55  const QString &_playgroup,
56 
57  const QString &_hostname,
58  const QString &_storagegroup,
59 
60  uint _year,
61  uint _partnumber,
62  uint _parttotal,
63 
64  const QString &_seriesid,
65  const QString &_programid,
66  const QString &_inetref,
67  const CategoryType _catType,
68 
69  int _recpriority,
70 
71  const QDateTime &_startts,
72  const QDateTime &_endts,
73  const QDateTime &_recstartts,
74  const QDateTime &_recendts,
75 
76  float _stars,
77  QDate _originalAirDate,
78 
79  bool _repeat,
80 
81  RecStatus::Type _oldrecstatus,
82  bool _reactivate,
83 
84  uint _recordid,
85  uint _parentid,
86  RecordingType _rectype,
87  RecordingDupInType _dupin,
88  RecordingDupMethodType _dupmethod,
89 
90  uint _sourceid,
91  uint _inputid,
92 
93  uint _findid,
94 
95  bool _commfree,
96  uint _subtitleType,
97  uint _videoproperties,
98  uint _audioproperties,
99  bool _future,
100  int _schedorder,
101  uint _mplexid,
102  uint _sgroupid,
103  const QString &_inputname) :
104  ProgramInfo(
105  _title, _sortTitle, _subtitle, _sortSubtitle,
106  _description, _season, _episode, _totalepisodes,
107  _category, _chanid, _chanstr, _chansign, _channame,
108  QString(), _recgroup, _playgroup,
109  _startts, _endts, _recstartts, _recendts,
110  _seriesid, _programid, _inetref, _inputname),
111  m_oldrecstatus(_oldrecstatus),
112  m_future(_future),
113  m_schedOrder(_schedorder),
114  m_mplexId(_mplexid),
115  m_sgroupId(_sgroupid),
116  m_desiredRecStartTs(_startts),
117  m_desiredRecEndTs(_endts)
118 {
119  m_hostname = _hostname;
120  m_storageGroup = _storagegroup;
121 
122  m_syndicatedEpisode = _syndicatedepisode;
123 
124  m_year = _year;
125  m_partNumber = _partnumber;
126  m_partTotal = _parttotal;
127  m_catType = _catType;
128 
129  m_recPriority = _recpriority;
130 
131  m_stars = clamp(_stars, 0.0F, 1.0F);
132  m_originalAirDate = _originalAirDate;
133  if (m_originalAirDate.isValid() && m_originalAirDate < QDate(1895, 12, 28))
134  m_originalAirDate = QDate();
135 
136  m_programFlags &= ~FL_REPEAT;
137  m_programFlags |= _repeat ? FL_REPEAT : 0;
138  m_programFlags &= ~FL_REACTIVATE;
139  m_programFlags |= _reactivate ? FL_REACTIVATE : 0;
140  m_programFlags &= ~FL_CHANCOMMFREE;
141  m_programFlags |= _commfree ? FL_CHANCOMMFREE : 0;
142 
143  m_recordId = _recordid;
144  m_parentId = _parentid;
145  m_recType = _rectype;
146  m_dupIn = _dupin;
147  m_dupMethod = _dupmethod;
148 
149  m_sourceId = _sourceid;
150  m_inputId = _inputid;
151  m_findId = _findid;
152 
153  m_videoProperties = _videoproperties;
154  m_audioProperties = _audioproperties;
155  m_subtitleProperties = _subtitleType;
156 
157  if (m_recStartTs >= m_recEndTs)
158  {
159  // start/end-offsets are invalid so ignore
162  }
163 
165 }
166 
168  const QString &_title,
169  const QString &_sortTitle,
170  const QString &_subtitle,
171  const QString &_sortSubtitle,
172  const QString &_description,
173  uint _season,
174  uint _episode,
175  const QString &_category,
176 
177  uint _chanid,
178  const QString &_chanstr,
179  const QString &_chansign,
180  const QString &_channame,
181 
182  const QString &_recgroup,
183  const QString &_playgroup,
184 
185  const QString &_seriesid,
186  const QString &_programid,
187  const QString &_inetref,
188 
189  int _recpriority,
190 
191  const QDateTime &_startts,
192  const QDateTime &_endts,
193  const QDateTime &_recstartts,
194  const QDateTime &_recendts,
195 
196  RecStatus::Type _recstatus,
197 
198  uint _recordid,
199  RecordingType _rectype,
200  RecordingDupInType _dupin,
201  RecordingDupMethodType _dupmethod,
202 
203  uint _findid,
204 
205  bool _commfree) :
206  ProgramInfo(
207  _title, _sortTitle, _subtitle, _sortSubtitle,
208  _description, _season, _episode, 0,
209  _category, _chanid, _chanstr, _chansign, _channame,
210  QString(), _recgroup, _playgroup,
211  _startts, _endts, _recstartts, _recendts,
212  _seriesid, _programid, _inetref, ""),
213  m_desiredRecStartTs(_startts),
214  m_desiredRecEndTs(_endts)
215 {
216  m_recPriority = _recpriority;
217 
218  m_recStatus = _recstatus,
219 
220  m_recordId = _recordid;
221  m_recType = _rectype;
222  m_dupIn = _dupin;
223  m_dupMethod = _dupmethod;
224 
225  m_findId = _findid;
226 
227  m_programFlags &= ~FL_CHANCOMMFREE;
228  m_programFlags |= _commfree ? FL_CHANCOMMFREE : 0;
229 
231 }
232 
242  uint _chanid, const QDateTime &desiredts,
243  bool genUnknown, std::chrono::hours maxHours, LoadStatus *status)
244 {
245  ProgramList schedList;
246  ProgramList progList;
247 
248  MSqlBindings bindings;
249  QString querystr = "WHERE program.chanid = :CHANID AND "
250  " program.starttime < :STARTTS1 AND "
251  " program.endtime > :STARTTS2 ";
252  bindings[":CHANID"] = QString::number(_chanid);
253  QDateTime query_startts = desiredts.addSecs(50 - desiredts.time().second());
254  bindings[":STARTTS1"] = query_startts;
255  bindings[":STARTTS2"] = query_startts;
256 
257  ::LoadFromScheduler(schedList);
258  LoadFromProgram(progList, querystr, bindings, schedList);
259 
260  if (!progList.empty())
261  {
262  ProgramInfo *pginfo = progList[0];
263 
264  if (maxHours > 0h)
265  {
266  auto maxSecs = duration_cast<std::chrono::seconds>(maxHours);
267  if (desiredts.secsTo(pginfo->GetScheduledEndTime()) > maxSecs.count())
268  {
269  pginfo->SetScheduledEndTime(desiredts.addSecs(maxSecs.count()));
270  pginfo->SetRecordingEndTime(pginfo->GetScheduledEndTime());
271  }
272  }
273 
274  *this = *pginfo;
275  if (status)
276  *status = kFoundProgram;
277  return;
278  }
279 
280  m_recStartTs = m_startTs = desiredts;
281  m_recEndTs = m_endTs = desiredts;
282  m_lastModified = desiredts;
283 
284  MSqlQuery query(MSqlQuery::InitCon());
285  query.prepare("SELECT chanid, channum, callsign, name, "
286  "commmethod, outputfilters "
287  "FROM channel "
288  "WHERE chanid = :CHANID");
289  query.bindValue(":CHANID", _chanid);
290 
291  if (!query.exec())
292  {
293  MythDB::DBError("Loading Program overlapping a datetime", query);
294  if (status)
295  *status = kNoProgram;
296  return;
297  }
298 
299  if (!query.next())
300  {
301  if (status)
302  *status = kNoProgram;
303  return;
304  }
305 
306  m_chanId = query.value(0).toUInt();
307  m_chanStr = query.value(1).toString();
308  m_chanSign = query.value(2).toString();
309  m_chanName = query.value(3).toString();
310  m_programFlags &= ~FL_CHANCOMMFREE;
311  m_programFlags |= (query.value(4).toInt() == COMM_DETECT_COMMFREE) ?
312  FL_CHANCOMMFREE : 0;
313  m_chanPlaybackFilters = query.value(5).toString();
314 
315  {
316  QMutexLocker locker(&s_staticDataLock);
317  if (s_unknownTitle.isEmpty())
318  s_unknownTitle = gCoreContext->GetSetting("UnknownTitle");
320  }
321 
322  if (!genUnknown)
323  {
324  if (status)
325  *status = kFakedZeroMinProgram;
326  return;
327  }
328 
329  // Round endtime up to the next half-hour.
330  m_endTs = QDateTime(
331  m_endTs.date(),
332  QTime(m_endTs.time().hour(),
333  m_endTs.time().minute() / kUnknownProgramLength
334  * kUnknownProgramLength), Qt::UTC);
335  m_endTs = m_endTs.addSecs(kUnknownProgramLength * 60);
336 
337  // if under a minute, bump it up to the next half hour
338  if (m_startTs.secsTo(m_endTs) < 60)
339  m_endTs = m_endTs.addSecs(kUnknownProgramLength * 60);
340 
342 
343  // Find next program starttime
344  bindings.clear();
345  QDateTime nextstart = m_startTs;
346  querystr = "WHERE program.chanid = :CHANID AND "
347  " program.starttime > :STARTTS "
348  "GROUP BY program.starttime ORDER BY program.starttime LIMIT 1 ";
349  bindings[":CHANID"] = QString::number(_chanid);
350  bindings[":STARTTS"] = desiredts.addSecs(50 - desiredts.time().second());
351 
352  LoadFromProgram(progList, querystr, bindings, schedList);
353 
354  if (!progList.empty())
355  nextstart = (*progList.begin())->GetScheduledStartTime();
356 
357  if (nextstart > m_startTs && nextstart < m_recEndTs)
358  m_recEndTs = m_endTs = nextstart;
359 
360  if (status)
361  *status = kFakedLiveTVProgram;
362 
365 
367 }
368 
371  bool ignore_non_serialized_data)
372 {
373  bool is_same =
374  ((m_chanId != 0U) && m_recStartTs.isValid() && m_startTs.isValid() &&
375  m_chanId == other.GetChanID() &&
376  m_recStartTs == other.GetRecordingStartTime() &&
377  m_startTs == other.GetScheduledStartTime());
378 
379  ProgramInfo::clone(other, ignore_non_serialized_data);
380 
381  if (!is_same)
382  {
383  delete m_record;
384  m_record = nullptr;
385  }
386 
387  if (!ignore_non_serialized_data)
388  {
391  m_future = other.m_future;
392  m_schedOrder = other.m_schedOrder;
393  m_mplexId = other.m_mplexId;
394  m_sgroupId = other.m_sgroupId;
397  }
398 
399  delete m_recordingFile;
400  m_recordingFile = nullptr;
402 }
403 
406  bool ignore_non_serialized_data)
407 {
408  bool is_same =
409  ((m_chanId != 0U) && m_recStartTs.isValid() && m_startTs.isValid() &&
410  m_chanId == other.GetChanID() &&
411  m_recStartTs == other.GetRecordingStartTime() &&
412  m_startTs == other.GetScheduledStartTime());
413 
414  ProgramInfo::clone(other, ignore_non_serialized_data);
415 
416  if (!is_same)
417  {
418  delete m_record;
419  m_record = nullptr;
420  }
421 
424  m_future = false;
425  m_schedOrder = 0;
426  m_mplexId = 0;
427  m_sgroupId = 0;
428  m_desiredRecStartTs = QDateTime();
429  m_desiredRecEndTs = QDateTime();
430 
431  delete m_recordingFile;
432  m_recordingFile = nullptr;
434 }
435 
437 {
439 
440  delete m_record;
441  m_record = nullptr;
442 
445  m_future = false;
446  m_schedOrder = 0;
447  m_mplexId = 0;
448  m_sgroupId = 0;
449  m_desiredRecStartTs = QDateTime();
450  m_desiredRecEndTs = QDateTime();
451 
452  delete m_recordingFile;
453  m_recordingFile = nullptr;
454 }
455 
456 
461 {
462  delete m_record;
463  m_record = nullptr;
464 
465  delete m_recordingFile;
466  m_recordingFile = nullptr;
467 }
468 
475 {
476  if (m_record == nullptr)
477  {
478  m_record = new RecordingRule();
479  m_record->LoadByProgram(this);
480  }
481 
482  return m_record->m_type;
483 }
484 
491 {
492  if (m_record == nullptr)
493  {
494  m_record = new RecordingRule();
495  m_record->LoadByProgram(this);
496  }
497 
498  return m_record->m_recProfile;
499 }
500 
505 {
506  if (m_record == nullptr)
507  {
508  m_record = new RecordingRule();
509  m_record->LoadByProgram(this);
510  }
511 
512  int result = 0;
513 
515  result |= JOB_TRANSCODE;
517  result |= JOB_COMMFLAG;
519  result |= JOB_METADATA;
521  result |= JOB_USERJOB1;
523  result |= JOB_USERJOB2;
525  result |= JOB_USERJOB3;
527  result |= JOB_USERJOB4;
528 
529 
530  return result;
531 }
532 
537 {
538  MSqlQuery query(MSqlQuery::InitCon());
539 
540  if (getRecordID() < 0)
541  {
542  LOG(VB_GENERAL, LOG_ERR,
543  "ProgInfo Error: ApplyRecordRecID(void) needs recordid");
544  return;
545  }
546 
547  query.prepare("UPDATE recorded "
548  "SET recordid = :RECID "
549  "WHERE chanid = :CHANID AND starttime = :START");
550 
551  if (m_recType == kOverrideRecord && m_parentId > 0)
552  query.bindValue(":RECID", m_parentId);
553  else
554  query.bindValue(":RECID", getRecordID());
555  query.bindValue(":CHANID", m_chanId);
556  query.bindValue(":START", m_recStartTs);
557 
558  if (!query.exec())
559  MythDB::DBError(LOC + "RecordID update", query);
560 }
561 
572 {
574  if (newstate == kOverrideRecord || newstate == kDontRecord)
576  m_record->m_type = newstate;
577 
578  if (save)
579  {
580  if (newstate == kNotRecording)
581  m_record->Delete();
582  else
583  m_record->Save();
584  }
585 }
586 
593 {
595  m_record->m_recPriority = newrecpriority;
596  m_record->Save();
597 }
598 
604 void RecordingInfo::ApplyRecordRecGroupChange(const QString &newrecgroup)
605 {
606  MSqlQuery query(MSqlQuery::InitCon());
607 
608  int newrecgroupid = GetRecgroupID(newrecgroup);
609 
610  // Catchall - in the event that the group doesn't exist, then to avoid
611  // breakage, we need to create it
612  if (newrecgroupid == 0)
613  {
614  query.prepare("INSERT INTO recgroups SET recgroup = :NAME, "
615  "displayname = :DISPLAYNAME");
616  query.bindValue(":NAME", newrecgroup);
617  query.bindValue(":DISPLAYNAME", newrecgroup);
618 
619  if (query.exec())
620  newrecgroupid = query.lastInsertId().toInt();
621 
622  if (newrecgroupid <= 0)
623  {
624  LOG(VB_GENERAL, LOG_ERR, QString("Could not create recording group (%1). "
625  "Does it already exist?").arg(newrecgroup));
626  return;
627  }
628  }
629 
630  LOG(VB_GENERAL, LOG_NOTICE,
631  QString("ApplyRecordRecGroupChange: %1 to %2 (%3)")
632  .arg(m_recGroup, newrecgroup, QString::number(newrecgroupid)));
633 
634  query.prepare("UPDATE recorded"
635  " SET recgroup = :RECGROUP, "
636  " recgroupid = :RECGROUPID "
637  " WHERE chanid = :CHANID"
638  " AND starttime = :START ;");
639  query.bindValue(":RECGROUP", null_to_empty(newrecgroup));
640  query.bindValue(":RECGROUPID", newrecgroupid);
641  query.bindValue(":START", m_recStartTs);
642  query.bindValue(":CHANID", m_chanId);
643 
644  if (!query.exec())
645  MythDB::DBError("RecGroup update", query);
646 
647  m_recGroup = newrecgroup; // Deprecate in favour of recgroupid
648  //recgroupid = newrecgroupid;
649 
650  SendUpdateEvent();
651 }
652 
654 {
655  MSqlQuery query(MSqlQuery::InitCon());
656 
657  QString newrecgroup;
658  if (newrecgroupid > 0)
659  {
660  newrecgroup = GetRecgroupString(newrecgroupid);
661 
662  query.prepare("UPDATE recorded"
663  " SET recgroup = :RECGROUP, "
664  " recgroupid = :RECGROUPID "
665  " WHERE chanid = :CHANID"
666  " AND starttime = :START ;");
667  query.bindValue(":RECGROUP", null_to_empty(newrecgroup));
668  query.bindValue(":RECGROUPID", newrecgroupid);
669  query.bindValue(":START", m_recStartTs);
670  query.bindValue(":CHANID", m_chanId);
671 
672  if (!query.exec())
673  MythDB::DBError("RecGroup update", query);
674 
675  m_recGroup = newrecgroup; // Deprecate in favour of recgroupid
676  //recgroupid = newrecgroupid;
677 
678  SendUpdateEvent();
679  }
680 
681  LOG(VB_GENERAL, LOG_NOTICE,
682  QString("ApplyRecordRecGroupChange: %1 to %2 (%3)")
683  .arg(m_recGroup, newrecgroup).arg(newrecgroupid));
684 }
685 
691 void RecordingInfo::ApplyRecordPlayGroupChange(const QString &newplaygroup)
692 {
693  MSqlQuery query(MSqlQuery::InitCon());
694 
695  query.prepare("UPDATE recorded"
696  " SET playgroup = :PLAYGROUP"
697  " WHERE chanid = :CHANID"
698  " AND starttime = :START ;");
699  query.bindValue(":PLAYGROUP", null_to_empty(newplaygroup));
700  query.bindValue(":START", m_recStartTs);
701  query.bindValue(":CHANID", m_chanId);
702 
703  if (!query.exec())
704  MythDB::DBError("PlayGroup update", query);
705 
706  m_playGroup = newplaygroup;
707 
708  SendUpdateEvent();
709 }
710 
716 void RecordingInfo::ApplyStorageGroupChange(const QString &newstoragegroup)
717 {
718  MSqlQuery query(MSqlQuery::InitCon());
719 
720  query.prepare("UPDATE recorded"
721  " SET storagegroup = :STORAGEGROUP"
722  " WHERE chanid = :CHANID"
723  " AND starttime = :START ;");
724  query.bindValue(":STORAGEGROUP", null_to_empty(newstoragegroup));
725  query.bindValue(":START", m_recStartTs);
726  query.bindValue(":CHANID", m_chanId);
727 
728  if (!query.exec())
729  MythDB::DBError("StorageGroup update", query);
730 
731  m_storageGroup = newstoragegroup;
732 
733  SendUpdateEvent();
734 }
735 
743 void RecordingInfo::ApplyRecordRecTitleChange(const QString &newTitle,
744  const QString &newSubtitle, const QString &newDescription)
745 {
746  MSqlQuery query(MSqlQuery::InitCon());
747  QString sql = "UPDATE recorded SET title = :TITLE, subtitle = :SUBTITLE ";
748  if (!newDescription.isNull())
749  sql += ", description = :DESCRIPTION ";
750  sql += " WHERE chanid = :CHANID AND starttime = :START ;";
751 
752  query.prepare(sql);
753  query.bindValue(":TITLE", newTitle);
754  query.bindValue(":SUBTITLE", null_to_empty(newSubtitle));
755  if (!newDescription.isNull())
756  query.bindValue(":DESCRIPTION", newDescription);
757  query.bindValue(":CHANID", m_chanId);
758  query.bindValue(":START", m_recStartTs);
759 
760  if (!query.exec())
761  MythDB::DBError("RecTitle update", query);
762 
763  m_title = newTitle;
764  m_subtitle = newSubtitle;
765  if (!newDescription.isNull())
766  m_description = newDescription;
767 
768  SendUpdateEvent();
769 }
770 
771 /* \fn RecordingInfo::ApplyTranscoderProfileChangeById(int id)
772  * \brief Sets the transcoder profile for a recording
773  * \param profileid is the 'id' field from recordingprofiles table.
774  */
776 {
777  MSqlQuery query(MSqlQuery::InitCon());
778 
779  query.prepare("UPDATE recorded "
780  "SET transcoder = :PROFILEID "
781  "WHERE chanid = :CHANID "
782  "AND starttime = :START");
783  query.bindValue(":PROFILEID", id);
784  query.bindValue(":CHANID", m_chanId);
785  query.bindValue(":START", m_recStartTs);
786 
787  if (!query.exec())
788  MythDB::DBError(LOC + "unable to update transcoder "
789  "in recorded table", query);
790 }
791 
796 {
797  if (profile == "Default") // use whatever is already in the transcoder
798  return;
799 
800  MSqlQuery query(MSqlQuery::InitCon());
801 
802  if (profile == "Autodetect")
803  {
804  query.prepare("UPDATE recorded "
805  "SET transcoder = 0 "
806  "WHERE chanid = :CHANID "
807  "AND starttime = :START");
808  query.bindValue(":CHANID", m_chanId);
809  query.bindValue(":START", m_recStartTs);
810 
811  if (!query.exec())
812  MythDB::DBError(LOC + "unable to update transcoder "
813  "in recorded table", query);
814  }
815  else
816  {
817  MSqlQuery pidquery(MSqlQuery::InitCon());
818  pidquery.prepare("SELECT r.id "
819  "FROM recordingprofiles r, profilegroups p "
820  "WHERE r.profilegroup = p.id "
821  "AND p.name = 'Transcoders' "
822  "AND r.name = :PROFILE ");
823  pidquery.bindValue(":PROFILE", profile);
824 
825  if (!pidquery.exec())
826  {
827  MythDB::DBError("ProgramInfo: unable to query transcoder "
828  "profile ID", query);
829  }
830  else if (pidquery.next())
831  {
832  query.prepare("UPDATE recorded "
833  "SET transcoder = :TRANSCODER "
834  "WHERE chanid = :CHANID "
835  "AND starttime = :START");
836  query.bindValue(":TRANSCODER", pidquery.value(0).toInt());
837  query.bindValue(":CHANID", m_chanId);
838  query.bindValue(":START", m_recStartTs);
839 
840  if (!query.exec())
841  MythDB::DBError(LOC + "unable to update transcoder "
842  "in recorded table", query);
843  }
844  else
845  {
846  LOG(VB_GENERAL, LOG_ERR,
847  "ProgramInfo: unable to query transcoder profile ID");
848  }
849  }
850 }
851 
857 {
861  AddHistory(true, true);
862 }
863 
868 {
870  if (curType == kNotRecording)
872 }
873 
878 {
880  return m_record;
881 }
882 
887 {
890  return m_recordId;
891 }
892 
894  uint chanid, const QDateTime& recstartts)
895 {
896  if (chanid < 1)
897  {
898  LOG(VB_RECORD, LOG_WARNING,
899  QString("QueryRecordedIdFromKey: Invalid chanid %1").arg(chanid));
900  return false;
901  }
902  if (!recstartts.isValid())
903  {
904  LOG(VB_RECORD, LOG_WARNING,
905  QString("QueryRecordedIdFromKey: Invalid start ts %1")
906  .arg(recstartts.toString()));
907  return false;
908  }
909 
910  MSqlQuery query(MSqlQuery::InitCon());
911  query.prepare(
912  "SELECT recordedid FROM recorded "
913  "WHERE chanid = :CHANID AND starttime = :RECSTARTTS");
914  query.bindValue(":CHANID", chanid);
915  query.bindValue(":RECSTARTTS", recstartts);
916  if (query.exec() && query.next())
917  {
918  recordedid = query.value(0).toUInt();
919  return true;
920  }
921 
922  return false;
923 }
924 
933 void RecordingInfo::StartedRecording(const QString& ext)
934 {
936 
937  if (!InsertRecording(ext))
938  return;
939 
940  LOG(VB_FILE, LOG_INFO, LOC + QString("StartedRecording: Recording to '%1'")
941  .arg(m_pathname));
942 
943 
944  MSqlQuery query(MSqlQuery::InitCon());
945 
946  query.prepare("DELETE FROM recordedseek WHERE chanid = :CHANID"
947  " AND starttime = :START;");
948  query.bindValue(":CHANID", m_chanId);
949  query.bindValue(":START", m_recStartTs);
950 
951  if (!query.exec() || !query.isActive())
952  MythDB::DBError("Clear seek info on record", query);
953 
954  query.prepare("DELETE FROM recordedmarkup WHERE chanid = :CHANID"
955  " AND starttime = :START;");
956  query.bindValue(":CHANID", m_chanId);
957  query.bindValue(":START", m_recStartTs);
958 
959  if (!query.exec() || !query.isActive())
960  MythDB::DBError("Clear markup on record", query);
961 
962  query.prepare("REPLACE INTO recordedcredits"
963  " SELECT * FROM credits"
964  " WHERE chanid = :CHANID AND starttime = :START;");
965  query.bindValue(":CHANID", m_chanId);
966  query.bindValue(":START", m_startTs);
967  if (!query.exec() || !query.isActive())
968  MythDB::DBError("Copy program credits on record", query);
969 
970  query.prepare("REPLACE INTO recordedprogram"
971  " SELECT * from program"
972  " WHERE chanid = :CHANID AND starttime = :START"
973  " AND title = :TITLE;");
974  query.bindValue(":CHANID", m_chanId);
975  query.bindValue(":START", m_startTs);
976  query.bindValue(":TITLE", m_title);
977  if (!query.exec() || !query.isActive())
978  MythDB::DBError("Copy program data on record", query);
979 
980  query.prepare("REPLACE INTO recordedrating"
981  " SELECT * from programrating"
982  " WHERE chanid = :CHANID AND starttime = :START;");
983  query.bindValue(":CHANID", m_chanId);
984  query.bindValue(":START", m_startTs);
985  if (!query.exec() || !query.isActive())
986  MythDB::DBError("Copy program ratings on record", query);
987 
988  InsertFile();
989 }
990 
991 bool RecordingInfo::InsertRecording(const QString &ext, bool force_match)
992 {
993  QString dirname = m_pathname;
994 
995 #if 1
996  if (!dirname.isEmpty())
997  {
998  LOG(VB_GENERAL, LOG_WARNING, LOC +
999  QString("InsertRecording: m_pathname was '%1'. "
1000  "This is usually blank.").arg(dirname));
1001  }
1002 #endif
1003 
1005 
1006  if (!m_record)
1007  {
1008  m_record = new RecordingRule();
1009  m_record->LoadByProgram(this);
1010  }
1011 
1012  int count = 0;
1013  while (!InsertProgram(this, m_record) && count < 50)
1014  {
1015  if (force_match)
1016  {
1017  LOG(VB_GENERAL, LOG_ERR, "Failed to insert new recording.");
1018  return false;
1019  }
1020 
1021  m_recStartTs = m_recStartTs.addSecs(1);
1023  ++count;
1024  }
1025 
1026  if (count >= 50)
1027  {
1028  LOG(VB_GENERAL, LOG_ERR, "Could not insert program");
1029  return false;
1030  }
1031 
1032  m_pathname = dirname + "/" + m_pathname;
1033 
1034  return true;
1035 }
1036 
1038  const RecordingRule *rule)
1039 {
1040  QString inputname = pg->GetInputName();
1041  int recgroupid = GetRecgroupID(pg->m_recGroup);
1042 
1043  MSqlQuery query(MSqlQuery::InitCon());
1044 
1045  if (!query.exec("LOCK TABLES recorded WRITE"))
1046  {
1047  MythDB::DBError("InsertProgram -- lock", query);
1048  return false;
1049  }
1050 
1051  query.prepare(
1052  "SELECT recordid "
1053  " FROM recorded "
1054  " WHERE chanid = :CHANID AND "
1055  " starttime = :STARTS");
1056  query.bindValue(":CHANID", pg->m_chanId);
1057  query.bindValue(":STARTS", pg->m_recStartTs);
1058 
1059  bool err = true;
1060  if (!query.exec())
1061  {
1062  MythDB::DBError("InsertProgram -- select", query);
1063  }
1064  else if (query.next())
1065  {
1066  LOG(VB_GENERAL, LOG_ERR,
1067  QString("RecordingInfo::InsertProgram(%1): ")
1068  .arg(pg->toString()) + "recording already exists...");
1069  }
1070  else
1071  {
1072  err = false;
1073  }
1074 
1075  if (err)
1076  {
1077  if (!query.exec("UNLOCK TABLES"))
1078  MythDB::DBError("InsertProgram -- unlock tables", query);
1079  return false;
1080  }
1081 
1082  query.prepare(
1083  "INSERT INTO recorded "
1084  " (chanid, starttime, endtime, title, "
1085  " subtitle, description, season, episode, "
1086  " hostname, category, recgroup, autoexpire, "
1087  " recordid, seriesid, programid, inetref, "
1088  " stars, previouslyshown, originalairdate, "
1089  " findid, transcoder, playgroup, recpriority, "
1090  " basename, progstart, progend, profile, "
1091  " duplicate, storagegroup, inputname, recgroupid) "
1092  "VALUES"
1093  " (:CHANID, :STARTS, :ENDS, :TITLE, "
1094  " :SUBTITLE, :DESC, :SEASON, :EPISODE, "
1095  " :HOSTNAME, :CATEGORY, :RECGROUP, :AUTOEXP, "
1096  " :RECORDID, :SERIESID, :PROGRAMID, :INETREF, "
1097  " :STARS, :REPEAT, :ORIGAIRDATE, "
1098  " :FINDID, :TRANSCODER, :PLAYGROUP, :RECPRIORITY, "
1099  " :BASENAME, :PROGSTART, :PROGEND, :PROFILE, "
1100  " 0, :STORGROUP, :INPUTNAME, :RECGROUPID) "
1101  );
1102 
1103  if (pg->m_recType == kOverrideRecord)
1104  query.bindValue(":RECORDID", pg->m_parentId);
1105  else
1106  query.bindValue(":RECORDID", pg->m_recordId);
1107 
1108  if (pg->m_originalAirDate.isValid())
1109  {
1110  query.bindValue(":ORIGAIRDATE", pg->m_originalAirDate);
1111  // If there is no originalairdate use "year"
1112  }
1113  else if (pg->m_year >= 1895)
1114  {
1115  query.bindValue(":ORIGAIRDATE", QDate(pg->m_year,1,1));
1116  }
1117  else
1118  {
1119  query.bindValue(":ORIGAIRDATE", "0000-00-00");
1120  }
1121 
1122  query.bindValue(":CHANID", pg->m_chanId);
1123  query.bindValue(":STARTS", pg->m_recStartTs);
1124  query.bindValue(":ENDS", pg->m_recEndTs);
1125  query.bindValue(":TITLE", pg->m_title);
1126  query.bindValue(":SUBTITLE", null_to_empty(pg->m_subtitle));
1127  query.bindValue(":DESC", null_to_empty(pg->m_description));
1128  query.bindValue(":SEASON", pg->m_season);
1129  query.bindValue(":EPISODE", pg->m_episode);
1130  query.bindValue(":HOSTNAME", pg->m_hostname);
1131  query.bindValue(":CATEGORY", null_to_empty(pg->m_category));
1132  query.bindValue(":RECGROUP", null_to_empty(pg->m_recGroup));
1133  query.bindValue(":AUTOEXP", rule->m_autoExpire);
1134  query.bindValue(":SERIESID", null_to_empty(pg->m_seriesId));
1135  query.bindValue(":PROGRAMID", null_to_empty(pg->m_programId));
1136  query.bindValue(":INETREF", null_to_empty(pg->m_inetRef));
1137  query.bindValue(":FINDID", pg->m_findId);
1138  query.bindValue(":STARS", pg->m_stars);
1139  query.bindValue(":REPEAT", pg->IsRepeat());
1140  query.bindValue(":TRANSCODER", rule->m_transcoder);
1141  query.bindValue(":PLAYGROUP", pg->m_playGroup);
1142  query.bindValue(":RECPRIORITY", rule->m_recPriority);
1143  query.bindValue(":BASENAME", pg->m_pathname);
1144  query.bindValue(":STORGROUP", null_to_empty(pg->m_storageGroup));
1145  query.bindValue(":PROGSTART", pg->m_startTs);
1146  query.bindValue(":PROGEND", pg->m_endTs);
1147  query.bindValue(":PROFILE", null_to_empty(rule->m_recProfile));
1148  query.bindValue(":INPUTNAME", inputname);
1149  query.bindValue(":RECGROUPID", recgroupid);
1150 
1151  bool ok = query.exec() && (query.numRowsAffected() > 0);
1152  if (ok)
1153  {
1154  pg->SetRecordingID(query.lastInsertId().toUInt());
1155  }
1156  bool active = query.isActive();
1157 
1158  if (!query.exec("UNLOCK TABLES"))
1159  MythDB::DBError("InsertProgram -- unlock tables", query);
1160 
1161  if (!ok && !active)
1162  {
1163  MythDB::DBError("InsertProgram -- insert", query);
1164 
1165  }
1166  else if (pg->m_recordId > 0)
1167  {
1168  query.prepare("UPDATE channel SET last_record = NOW() "
1169  "WHERE chanid = :CHANID");
1170  query.bindValue(":CHANID", pg->GetChanID());
1171  if (!query.exec())
1172  MythDB::DBError("InsertProgram -- channel last_record", query);
1173 
1174  query.prepare("UPDATE record SET last_record = NOW() "
1175  "WHERE recordid = :RECORDID");
1176  query.bindValue(":RECORDID", pg->m_recordId);
1177  if (!query.exec())
1178  MythDB::DBError("InsertProgram -- record last_record", query);
1179 
1180  if (pg->m_recType == kOverrideRecord && pg->m_parentId > 0)
1181  {
1182  query.prepare("UPDATE record SET last_record = NOW() "
1183  "WHERE recordid = :PARENTID");
1184  query.bindValue(":PARENTID", pg->m_parentId);
1185  if (!query.exec())
1186  MythDB::DBError("InsertProgram -- record last_record override",
1187  query);
1188  }
1189  }
1190 
1191  return ok;
1192 }
1193 
1195 {
1196  // File
1197  if (!GetRecordingFile())
1199  RecordingFile *recFile = GetRecordingFile();
1200  recFile->m_fileName = GetBasename();
1201  recFile->m_storageDeviceID = GetHostname();
1202  recFile->m_storageGroup = GetStorageGroup();
1203  recFile->Save();
1204 
1205  SendAddedEvent();
1206 }
1207 
1216 void RecordingInfo::FinishedRecording(bool allowReRecord)
1217 {
1218  MSqlQuery query(MSqlQuery::InitCon());
1219  query.prepare("UPDATE recorded SET endtime = :ENDTIME, "
1220  " duplicate = :DUPLICATE "
1221  "WHERE chanid = :CHANID AND "
1222  " starttime = :STARTTIME ");
1223  query.bindValue(":ENDTIME", m_recEndTs);
1224  query.bindValue(":CHANID", m_chanId);
1225  query.bindValue(":STARTTIME", m_recStartTs);
1226  query.bindValue(":DUPLICATE", !allowReRecord);
1227 
1228  if (!query.exec())
1229  MythDB::DBError("FinishedRecording update", query);
1230 
1232  if (!allowReRecord)
1233  {
1235 
1236  qint64 starttime = m_recStartTs.toSecsSinceEpoch();
1237  qint64 endtime = m_recEndTs.toSecsSinceEpoch();
1238  SaveTotalDuration(std::chrono::seconds(endtime - starttime));
1239 
1240  QString msg = "Finished recording";
1241  QString msg_subtitle = m_subtitle.isEmpty() ? "" :
1242  QString(" \"%1\"").arg(m_subtitle);
1243  QString details = QString("%1%2: channel %3")
1244  .arg(m_title, msg_subtitle, QString::number(m_chanId));
1245 
1246  LOG(VB_GENERAL, LOG_INFO, QString("%1 %2").arg(msg, details));
1247  }
1248 
1249  SendUpdateEvent();
1250 }
1251 
1257 {
1258  MSqlQuery query(MSqlQuery::InitCon());
1259  query.prepare("UPDATE recorded SET endtime = :ENDTIME "
1260  "WHERE chanid = :CHANID AND "
1261  " starttime = :STARTTIME ");
1262  query.bindValue(":ENDTIME", m_recEndTs);
1263 
1264  query.bindValue(":CHANID", m_chanId);
1265  query.bindValue(":STARTTIME", m_recStartTs);
1266 
1267  if (!query.exec())
1268  MythDB::DBError("UpdateRecordingEnd update", query);
1269 
1270  SendUpdateEvent();
1271 }
1272 
1277 {
1278  MSqlQuery result(MSqlQuery::InitCon());
1279 
1280  result.prepare("UPDATE oldrecorded SET reactivate = 1 "
1281  "WHERE station = :STATION AND "
1282  " starttime = :STARTTIME AND "
1283  " title = :TITLE;");
1284  result.bindValue(":STARTTIME", m_startTs);
1285  result.bindValue(":TITLE", m_title);
1286  result.bindValue(":STATION", m_chanSign);
1287 
1288  if (!result.exec())
1289  MythDB::DBError("ReactivateRecording", result);
1290 
1292 }
1293 
1297 void RecordingInfo::AddHistory(bool resched, bool forcedup, bool future)
1298 {
1299  bool dup = (GetRecordingStatus() == RecStatus::Recorded || forcedup);
1302  LOG(VB_SCHEDULE, LOG_INFO, QString("AddHistory: %1/%2, %3, %4, %5/%6")
1303  .arg(int(rs)).arg(int(m_oldrecstatus)).arg(future).arg(dup)
1305  if (!future)
1307  if (dup)
1308  SetReactivated(false);
1309  uint erecid = m_parentId ? m_parentId : m_recordId;
1310 
1311  MSqlQuery result(MSqlQuery::InitCon());
1312 
1313  result.prepare("REPLACE INTO oldrecorded (chanid,starttime,"
1314  "endtime,title,subtitle,description,season,episode,"
1315  "category,seriesid,programid,inetref,findid,recordid,"
1316  "station,rectype,recstatus,duplicate,reactivate,generic,"
1317  "future) "
1318  "VALUES(:CHANID,:START,:END,:TITLE,:SUBTITLE,:DESC,:SEASON,"
1319  ":EPISODE,:CATEGORY,:SERIESID,:PROGRAMID,:INETREF,"
1320  ":FINDID,:RECORDID,:STATION,:RECTYPE,:RECSTATUS,:DUPLICATE,"
1321  ":REACTIVATE,:GENERIC,:FUTURE);");
1322  result.bindValue(":CHANID", m_chanId);
1323  result.bindValue(":START", m_startTs);
1324  result.bindValue(":END", m_endTs);
1325  result.bindValue(":TITLE", m_title);
1326  result.bindValue(":SUBTITLE", null_to_empty(m_subtitle));
1327  result.bindValue(":DESC", null_to_empty(m_description));
1328  result.bindValue(":SEASON", m_season);
1329  result.bindValue(":EPISODE", m_episode);
1330  result.bindValue(":CATEGORY", null_to_empty(m_category));
1331  result.bindValue(":SERIESID", null_to_empty(m_seriesId));
1332  result.bindValue(":PROGRAMID", null_to_empty(m_programId));
1333  result.bindValue(":INETREF", null_to_empty(m_inetRef));
1334  result.bindValue(":FINDID", m_findId);
1335  result.bindValue(":RECORDID", erecid);
1336  result.bindValue(":STATION", null_to_empty(m_chanSign));
1337  result.bindValue(":RECTYPE", m_recType);
1338  result.bindValue(":RECSTATUS", rs);
1339  result.bindValue(":DUPLICATE", dup);
1340  result.bindValue(":REACTIVATE", 0);
1341  result.bindValue(":GENERIC", IsGeneric());
1342  result.bindValue(":FUTURE", future);
1343 
1344  if (!result.exec())
1345  MythDB::DBError("addHistory", result);
1346 
1347  if (dup && m_findId)
1348  {
1349  result.prepare("REPLACE INTO oldfind (recordid, findid) "
1350  "VALUES(:RECORDID,:FINDID);");
1351  result.bindValue(":RECORDID", erecid);
1352  result.bindValue(":FINDID", m_findId);
1353 
1354  if (!result.exec())
1355  MythDB::DBError("addFindHistory", result);
1356  }
1357 
1358  // The adding of an entry to oldrecorded may affect near-future
1359  // scheduling decisions, so recalculate if told
1360  if (resched)
1361  ScheduledRecording::RescheduleCheck(*this, "AddHistory");
1362 }
1363 
1368 {
1369  uint erecid = m_parentId ? m_parentId : m_recordId;
1370 
1371  MSqlQuery result(MSqlQuery::InitCon());
1372 
1373  result.prepare("DELETE FROM oldrecorded WHERE title = :TITLE AND "
1374  "starttime = :START AND station = :STATION");
1375  result.bindValue(":TITLE", m_title);
1376  result.bindValue(":START", m_recStartTs);
1377  result.bindValue(":STATION", m_chanSign);
1378 
1379  if (!result.exec())
1380  MythDB::DBError("deleteHistory", result);
1381 
1382  if (/*m_duplicate &&*/ m_findId)
1383  {
1384  result.prepare("DELETE FROM oldfind WHERE "
1385  "recordid = :RECORDID AND findid = :FINDID");
1386  result.bindValue(":RECORDID", erecid);
1387  result.bindValue(":FINDID", m_findId);
1388 
1389  if (!result.exec())
1390  MythDB::DBError("deleteFindHistory", result);
1391  }
1392 
1393  // The removal of an entry from oldrecorded may affect near-future
1394  // scheduling decisions, so recalculate
1395  ScheduledRecording::RescheduleCheck(*this, "DeleteHistory");
1396 }
1397 
1407 {
1408  uint erecid = m_parentId ? m_parentId : m_recordId;
1409  uint din = m_dupIn;
1410  uint dmeth = m_dupMethod;
1411 
1412  if (din == kDupsUnset)
1413  din = kDupsInAll;
1414  if (dmeth == kDupCheckUnset)
1415  dmeth = kDupCheckSubThenDesc;
1416 
1417  MSqlQuery result(MSqlQuery::InitCon());
1418 
1419  // Handle this specific entry in recorded.
1420  result.prepare("UPDATE recorded SET duplicate = 0 "
1421  "WHERE chanid = :CHANID "
1422  "AND starttime = :STARTTIME "
1423  "AND title = :TITLE;");
1424  result.bindValue(":STARTTIME", m_recStartTs);
1425  result.bindValue(":TITLE", m_title);
1426  result.bindValue(":CHANID", m_chanId);
1427 
1428  if (!result.exec())
1429  MythDB::DBError("forgetRecorded1", result);
1430 
1431  // Handle other matching entries in recorded.
1432  if (din & kDupsInRecorded)
1433  {
1434  result.prepare(
1435  "UPDATE recorded SET duplicate = 0 "
1436  "WHERE duplicate = 1 AND "
1437  " title = :TITLE AND "
1438  " ( "
1439  " (:PROGRAMID1 <> '' AND "
1440  " :PROGRAMID2 = recorded.programid) "
1441  " OR "
1442  " ( "
1443  " (:PROGRAMID3 = '' OR recorded.programid = '' OR "
1444  " LEFT(:PROGRAMID4, LOCATE('/', :PROGRAMID5)) <> "
1445  " LEFT(recorded.programid, "
1446  " LOCATE('/', recorded.programid))) "
1447  " AND "
1448  " (((:DUPMETHOD1 & 0x02) = 0) OR (:SUBTITLE1 <> '' "
1449  " AND :SUBTITLE2 = recorded.subtitle)) "
1450  " AND "
1451  " (((:DUPMETHOD2 & 0x04) = 0) OR (:DESCRIPTION1 <> '' "
1452  " AND :DESCRIPTION2 = recorded.description)) "
1453  " AND "
1454  " (((:DUPMETHOD3 & 0x08) = 0) OR "
1455  " (:SUBTITLE3 <> '' AND "
1456  " (:SUBTITLE4 = recorded.subtitle OR "
1457  " (recorded.subtitle = '' AND "
1458  " :SUBTITLE5 = recorded.description))) OR "
1459  " (:SUBTITLE6 = '' AND :DESCRIPTION3 <> '' AND "
1460  " (:DESCRIPTION4 = recorded.subtitle OR "
1461  " (recorded.subtitle = '' AND "
1462  " :DESCRIPTION5 = recorded.description)))) "
1463  " ) "
1464  " )" );
1465  result.bindValue(":TITLE", m_title);
1466  result.bindValue(":SUBTITLE1", null_to_empty(m_subtitle));
1467  result.bindValue(":SUBTITLE2", null_to_empty(m_subtitle));
1468  result.bindValue(":SUBTITLE3", null_to_empty(m_subtitle));
1469  result.bindValue(":SUBTITLE4", null_to_empty(m_subtitle));
1470  result.bindValue(":SUBTITLE5", null_to_empty(m_subtitle));
1471  result.bindValue(":SUBTITLE6", null_to_empty(m_subtitle));
1472  result.bindValue(":DESCRIPTION1", null_to_empty(m_description));
1473  result.bindValue(":DESCRIPTION2", null_to_empty(m_description));
1474  result.bindValue(":DESCRIPTION3", null_to_empty(m_description));
1475  result.bindValue(":DESCRIPTION4", null_to_empty(m_description));
1476  result.bindValue(":DESCRIPTION5", null_to_empty(m_description));
1477  result.bindValue(":PROGRAMID1", null_to_empty(m_programId));
1478  result.bindValue(":PROGRAMID2", null_to_empty(m_programId));
1479  result.bindValue(":PROGRAMID3", null_to_empty(m_programId));
1480  result.bindValue(":PROGRAMID4", null_to_empty(m_programId));
1481  result.bindValue(":PROGRAMID5", null_to_empty(m_programId));
1482  result.bindValue(":DUPMETHOD1", dmeth);
1483  result.bindValue(":DUPMETHOD2", dmeth);
1484  result.bindValue(":DUPMETHOD3", dmeth);
1485 
1486  if (!result.exec())
1487  MythDB::DBError("forgetRecorded2", result);
1488  }
1489 
1490  // Handle this specific entry in oldrecorded.
1491  result.prepare("UPDATE oldrecorded SET duplicate = 0 "
1492  "WHERE station = :STATION "
1493  "AND starttime = :STARTTIME "
1494  "AND title = :TITLE;");
1495  result.bindValue(":STARTTIME", m_startTs);
1496  result.bindValue(":TITLE", m_title);
1497  result.bindValue(":STATION", m_chanSign);
1498 
1499  if (!result.exec())
1500  MythDB::DBError("forgetOldRecorded1", result);
1501 
1502  // Handle other matching entries in oldrecorded.
1503  if (din & kDupsInOldRecorded)
1504  {
1505  result.prepare(
1506  "UPDATE oldrecorded SET duplicate = 0 "
1507  "WHERE duplicate = 1 AND "
1508  " title = :TITLE AND "
1509  " ( "
1510  " (:PROGRAMID1 <> '' AND "
1511  " :PROGRAMID2 = oldrecorded.programid) "
1512  " OR "
1513  " ( "
1514  " (:PROGRAMID3 = '' OR oldrecorded.programid = '' OR "
1515  " LEFT(:PROGRAMID4, LOCATE('/', :PROGRAMID5)) <> "
1516  " LEFT(oldrecorded.programid, "
1517  " LOCATE('/', oldrecorded.programid))) "
1518  " AND "
1519  " (((:DUPMETHOD1 & 0x02) = 0) OR (:SUBTITLE1 <> '' "
1520  " AND :SUBTITLE2 = oldrecorded.subtitle)) "
1521  " AND "
1522  " (((:DUPMETHOD2 & 0x04) = 0) OR (:DESCRIPTION1 <> '' "
1523  " AND :DESCRIPTION2 = oldrecorded.description)) "
1524  " AND "
1525  " (((:DUPMETHOD3 & 0x08) = 0) OR "
1526  " (:SUBTITLE3 <> '' AND "
1527  " (:SUBTITLE4 = oldrecorded.subtitle OR "
1528  " (oldrecorded.subtitle = '' AND "
1529  " :SUBTITLE5 = oldrecorded.description))) OR "
1530  " (:SUBTITLE6 = '' AND :DESCRIPTION3 <> '' AND "
1531  " (:DESCRIPTION4 = oldrecorded.subtitle OR "
1532  " (oldrecorded.subtitle = '' AND "
1533  " :DESCRIPTION5 = oldrecorded.description)))) "
1534  " ) "
1535  " )" );
1536  result.bindValue(":TITLE", m_title);
1537  result.bindValue(":SUBTITLE1", null_to_empty(m_subtitle));
1538  result.bindValue(":SUBTITLE2", null_to_empty(m_subtitle));
1539  result.bindValue(":SUBTITLE3", null_to_empty(m_subtitle));
1540  result.bindValue(":SUBTITLE4", null_to_empty(m_subtitle));
1541  result.bindValue(":SUBTITLE5", null_to_empty(m_subtitle));
1542  result.bindValue(":SUBTITLE6", null_to_empty(m_subtitle));
1543  result.bindValue(":DESCRIPTION1", null_to_empty(m_description));
1544  result.bindValue(":DESCRIPTION2", null_to_empty(m_description));
1545  result.bindValue(":DESCRIPTION3", null_to_empty(m_description));
1546  result.bindValue(":DESCRIPTION4", null_to_empty(m_description));
1547  result.bindValue(":DESCRIPTION5", null_to_empty(m_description));
1548  result.bindValue(":PROGRAMID1", null_to_empty(m_programId));
1549  result.bindValue(":PROGRAMID2", null_to_empty(m_programId));
1550  result.bindValue(":PROGRAMID3", null_to_empty(m_programId));
1551  result.bindValue(":PROGRAMID4", null_to_empty(m_programId));
1552  result.bindValue(":PROGRAMID5", null_to_empty(m_programId));
1553  result.bindValue(":DUPMETHOD1", dmeth);
1554  result.bindValue(":DUPMETHOD2", dmeth);
1555  result.bindValue(":DUPMETHOD3", dmeth);
1556 
1557  if (!result.exec())
1558  MythDB::DBError("forgetOldRecorded2", result);
1559  }
1560 
1561  // Remove any never records which aren't need anymore.
1562  result.prepare("DELETE FROM oldrecorded "
1563  "WHERE recstatus = :NEVER AND duplicate = 0");
1564  result.bindValue(":NEVER", RecStatus::NeverRecord);
1565 
1566  if (!result.exec())
1567  MythDB::DBError("forgetNeverHistory", result);
1568 
1569  // Handle matching entries in oldfind.
1570  if (m_findId)
1571  {
1572  result.prepare("DELETE FROM oldfind WHERE "
1573  "recordid = :RECORDID AND findid = :FINDID");
1574  result.bindValue(":RECORDID", erecid);
1575  result.bindValue(":FINDID", m_findId);
1576 
1577  if (!result.exec())
1578  MythDB::DBError("forgetFindHistory", result);
1579  }
1580 
1581  // The removal of an entry from oldrecorded may affect near-future
1582  // scheduling decisions, so recalculate
1583  ScheduledRecording::RescheduleCheck(*this, "ForgetHistory");
1584 }
1585 
1590 {
1591  MSqlQuery result(MSqlQuery::InitCon());
1592 
1593  result.prepare("UPDATE oldrecorded SET duplicate = 1 "
1594  "WHERE future = 0 AND duplicate = 0 "
1595  "AND title = :TITLE AND "
1596  "((programid = '' AND subtitle = :SUBTITLE"
1597  " AND description = :DESC) OR "
1598  " (programid <> '' AND programid = :PROGRAMID) OR "
1599  " (findid <> 0 AND findid = :FINDID))");
1600  result.bindValue(":TITLE", m_title);
1601  result.bindValue(":SUBTITLE", null_to_empty(m_subtitle));
1602  result.bindValue(":DESC", null_to_empty(m_description));
1603  result.bindValue(":PROGRAMID", null_to_empty(m_programId));
1604  result.bindValue(":FINDID", m_findId);
1605 
1606  if (!result.exec())
1607  MythDB::DBError("setDupHistory", result);
1608 
1609  ScheduledRecording::RescheduleCheck(*this, "SetHistory");
1610 }
1611 
1617 {
1618  str.replace("%RECID%", QString::number(getRecordID()));
1619  str.replace("%PARENTID%", QString::number(m_parentId));
1620  str.replace("%FINDID%", QString::number(m_findId));
1621  str.replace("%RECSTATUS%", QString::number(m_recStatus));
1622  str.replace("%RECTYPE%", QString::number(m_recType));
1623  str.replace("%REACTIVATE%", IsReactivated() ? "1" : "0");
1624  str.replace("%INPUTNAME%", GetInputName());
1625  str.replace("%CHANNUM%", GetChanNum());
1626 
1628 }
1629 
1633 uint RecordingInfo::GetRecgroupID(const QString& recGroup)
1634 {
1635  MSqlQuery query(MSqlQuery::InitCon());
1636 
1637  query.prepare("SELECT recgroupid FROM recgroups WHERE recgroup = :RECGROUP");
1638  query.bindValue(":RECGROUP", null_to_empty(recGroup));
1639 
1640  if (!query.exec())
1641  MythDB::DBError("RecGroup update", query);
1642 
1643  if (!query.next())
1644  return 0;
1645 
1646  return query.value(0).toUInt();
1647 }
1648 
1653 {
1654  MSqlQuery query(MSqlQuery::InitCon());
1655 
1656  query.prepare("SELECT recgroup FROM recgroups WHERE recgroupid = :RECGROUPID");
1657  query.bindValue(":RECGROUPID", recGroupID);
1658  if (!query.exec() || !query.next())
1659  {
1660  MythDB::DBError("GetRecgroupString()", query);
1661  return QString();
1662  }
1663  return query.value(0).toString();
1664 }
1665 
1667 {
1668  if (!m_recordingFile)
1669  {
1671  if (m_recordedId > 0)
1672  {
1674  m_recordingFile->Load();
1675  }
1676  }
1677 }
1678 
1679 void RecordingInfo::SaveFilesize(uint64_t fsize)
1680 {
1681  if (!GetRecordingFile())
1683  GetRecordingFile()->m_fileSize = fsize;
1684  GetRecordingFile()->Save(); // Ideally this would be called just the once when all metadata is gathered
1685 
1687 
1688  ProgramInfo::SaveFilesize(fsize); // Temporary
1689 }
1690 
1691 void RecordingInfo::SetFilesize(uint64_t fsize)
1692 {
1693  if (!GetRecordingFile())
1695  GetRecordingFile()->m_fileSize = fsize;
1697 
1698  // Make sure the old storage location is updated for now
1699  ProgramInfo::SetFilesize(fsize);
1700 }
1701 
1702 uint64_t RecordingInfo::GetFilesize(void) const
1703 {
1705  return GetRecordingFile()->m_fileSize;
1706 
1707  // Temporary fallback to reading from old storage location
1708  return ProgramInfo::GetFilesize();
1709 }
1710 
1711 
1712 /* vim: set expandtab tabstop=4 shiftwidth=4: */
RecordingInfo::ApplyRecordPlayGroupChange
void ApplyRecordPlayGroupChange(const QString &newplaygroup)
Sets the recording group, both in this RecordingInfo and in the database.
Definition: recordinginfo.cpp:691
RecordingInfo::GetRecgroupID
static uint GetRecgroupID(const QString &recGroup)
Temporary helper during transition from string to ID.
Definition: recordinginfo.cpp:1633
JOB_USERJOB3
@ JOB_USERJOB3
Definition: jobqueue.h:84
MSqlBindings
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:97
ProgramInfo::m_startTs
QDateTime m_startTs
Definition: programinfo.h:787
JOB_USERJOB4
@ JOB_USERJOB4
Definition: jobqueue.h:85
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:212
RecordingRule::LoadByProgram
bool LoadByProgram(const ProgramInfo *proginfo)
Definition: recordingrule.cpp:168
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:802
RecStatus::Type
Type
Definition: recStatus.h:16
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:124
RecordingInfo::InsertProgram
static bool InsertProgram(RecordingInfo *pg, const RecordingRule *rule)
Definition: recordinginfo.cpp:1037
RecordingInfo::m_future
bool m_future
Definition: recordinginfo.h:287
ProgramInfo::SaveFilesize
virtual void SaveFilesize(uint64_t fsize)
Sets recording file size in database, and sets "filesize" field.
Definition: programinfo.cpp:6231
RecordingRule::m_autoTranscode
bool m_autoTranscode
Definition: recordingrule.h:133
ProgramInfo::m_fileSize
uint64_t m_fileSize
Definition: programinfo.h:785
RecordingInfo::QueryRecordedIdForKey
static bool QueryRecordedIdForKey(int &recordedid, uint chanid, const QDateTime &recstartts)
Definition: recordinginfo.cpp:893
RecordingInfo::FinishedRecording
void FinishedRecording(bool allowReRecord)
If not a premature stop, adds program to history of recorded programs.
Definition: recordinginfo.cpp:1216
RecordingInfo::kReSearchTypeName
static const QRegularExpression kReSearchTypeName
Definition: recordinginfo.h:197
ProgramInfo::GetFilesize
virtual uint64_t GetFilesize(void) const
Definition: programinfo.cpp:6262
RecordingInfo::ApplyNeverRecord
void ApplyNeverRecord(void)
Set this program to never be recorded by inserting 'history' for it into the database with a status o...
Definition: recordinginfo.cpp:856
ProgramInfo::m_recEndTs
QDateTime m_recEndTs
Definition: programinfo.h:790
RecordingInfo::m_oldrecstatus
RecStatus::Type m_oldrecstatus
Definition: recordinginfo.h:285
ProgramInfo::m_catType
CategoryType m_catType
Definition: programinfo.h:783
ProgramInfo::m_inputId
uint32_t m_inputId
Definition: programinfo.h:803
ProgramInfo::m_title
QString m_title
Definition: programinfo.h:752
RecordingRule::m_autoCommFlag
bool m_autoCommFlag
Definition: recordingrule.h:132
RecordingInfo::kFoundProgram
@ kFoundProgram
Definition: recordinginfo.h:182
ProgramInfo::SetRecordingStatus
void SetRecordingStatus(RecStatus::Type status)
Definition: programinfo.h:580
ProgramInfo::m_dupMethod
uint8_t m_dupMethod
Definition: programinfo.h:817
ProgramInfo::GetHostname
QString GetHostname(void) const
Definition: programinfo.h:420
ProgramInfo::m_storageGroup
QString m_storageGroup
Definition: programinfo.h:778
ProgramInfo::GetInputName
QString GetInputName(void) const
Definition: programinfo.h:463
ProgramInfo::m_chanId
uint32_t m_chanId
Definition: programinfo.h:766
mythdb.h
ProgramInfo::m_dupIn
uint8_t m_dupIn
Definition: programinfo.h:816
RecordingRule::Save
bool Save(bool sendSig=true)
Definition: recordingrule.cpp:382
ProgramInfo::m_audioProperties
AudioPropsType m_audioProperties
Definition: programinfo.h:808
RecordingInfo::m_desiredRecEndTs
QDateTime m_desiredRecEndTs
Definition: recordinginfo.h:292
RecordingInfo::ApplyRecordStateChange
void ApplyRecordStateChange(RecordingType newstate, bool save=true)
Sets RecordingType of "record", creating "record" if it does not exist.
Definition: recordinginfo.cpp:571
ProgramInfo::m_recordId
uint32_t m_recordId
Definition: programinfo.h:799
RecStatus::NeverRecord
@ NeverRecord
Definition: recStatus.h:43
ProgramInfo::m_recStartTs
QDateTime m_recStartTs
Definition: programinfo.h:789
RecordingInfo::ApplyRecordRecID
void ApplyRecordRecID(void)
Sets recordid to match RecordingRule recordid.
Definition: recordinginfo.cpp:536
kDupCheckSubThenDesc
@ kDupCheckSubThenDesc
Definition: recordingtypes.h:64
ProgramInfo::m_description
QString m_description
Definition: programinfo.h:756
ProgramInfo::s_staticDataLock
static QMutex s_staticDataLock
Definition: programinfo.h:838
RecordingInfo
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:35
RecordingInfo::GetFilesize
uint64_t GetFilesize(void) const override
Definition: recordinginfo.cpp:1702
RecordingInfo::ForgetHistory
void ForgetHistory(void)
Forget the recording of a program so it will be recorded again.
Definition: recordinginfo.cpp:1406
ProgramInfo::clone
virtual void clone(const ProgramInfo &other, bool ignore_non_serialized_data=false)
Copies important fields from other ProgramInfo.
Definition: programinfo.cpp:839
ProgramInfo::GetChanNum
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
Definition: programinfo.h:375
RecordingInfo::SetFilesize
void SetFilesize(uint64_t fsize) override
Definition: recordinginfo.cpp:1691
MSqlQuery::lastInsertId
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:907
JOB_COMMFLAG
@ JOB_COMMFLAG
Definition: jobqueue.h:77
AutoDeleteDeque::empty
bool empty(void) const
Definition: autodeletedeque.h:66
null_to_empty
static QString null_to_empty(const QString &str)
Definition: recordinginfo.cpp:28
RecordingInfo::DeleteHistory
void DeleteHistory(void)
Deletes recording history, creating "record" it if necessary.
Definition: recordinginfo.cpp:1367
ProgramInfo::m_subtitleProperties
SubtitlePropsType m_subtitleProperties
Definition: programinfo.h:809
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:201
RecordingInfo::GetProgramRecordingStatus
RecordingType GetProgramRecordingStatus(void)
Returns the recording type for this RecordingInfo, creating "record" field if necessary.
Definition: recordinginfo.cpp:474
RecordingInfo::kReLeadingAnd
static const QRegularExpression kReLeadingAnd
Definition: recordinginfo.h:200
RecStatus::Unknown
@ Unknown
Definition: recStatus.h:32
RecordingRule
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:32
RecordingDupMethodType
RecordingDupMethodType
Definition: recordingtypes.h:57
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
ProgramInfo::m_recPriority
int32_t m_recPriority
Definition: programinfo.h:764
ProgramInfo::m_season
uint m_season
Definition: programinfo.h:757
RecordingFile
Holds information on a recording file and it's video and audio streams.
Definition: recordingfile.h:29
RecStatus::Recorded
@ Recorded
Definition: recStatus.h:29
ProgramInfo::SetScheduledStartTime
void SetScheduledStartTime(const QDateTime &dt)
Definition: programinfo.h:523
ProgramInfo::IsReactivated
bool IsReactivated(void) const
Definition: programinfo.h:489
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
ProgramInfo::GetScheduledEndTime
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:396
ProgramInfo::m_pathname
QString m_pathname
Definition: programinfo.h:775
RecordingInfo::UpdateRecordingEnd
void UpdateRecordingEnd(void)
Update information in the recorded table when the end-time of a recording is changed.
Definition: recordinginfo.cpp:1256
ProgramInfo::m_endTs
QDateTime m_endTs
Definition: programinfo.h:788
RecordingInfo::s_unknownTitle
static QString s_unknownTitle
Definition: recordinginfo.h:302
RecordingInfo::getRecordID
int getRecordID(void)
Returns a record id, creating "record" it if necessary.
Definition: recordinginfo.cpp:886
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
kDupsInAll
@ kDupsInAll
Definition: recordingtypes.h:47
ProgramInfo::GetRecordingStartTime
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:403
ProgramInfo::SendAddedEvent
void SendAddedEvent(void) const
Sends event out that the ProgramInfo should be added to lists.
Definition: programinfo.cpp:2715
RecordingInfo::m_mplexId
uint m_mplexId
Definition: recordinginfo.h:289
JOB_USERJOB2
@ JOB_USERJOB2
Definition: jobqueue.h:83
RecordingInfo::ApplyTranscoderProfileChange
void ApplyTranscoderProfileChange(const QString &profile) const
Sets the transcoder profile for a recording.
Definition: recordinginfo.cpp:795
ProgramInfo::m_sourceId
uint32_t m_sourceId
Definition: programinfo.h:802
AutoDeleteDeque::begin
iterator begin(void)
Definition: autodeletedeque.h:50
kDupsInRecorded
@ kDupsInRecorded
Definition: recordingtypes.h:45
ProgramInfo::IsRepeat
bool IsRepeat(void) const
Definition: programinfo.h:487
RecordingInfo::ApplyStorageGroupChange
void ApplyStorageGroupChange(const QString &newstoragegroup)
Sets the storage group, both in this RecordingInfo and in the database.
Definition: recordinginfo.cpp:716
RecordingInfo::GetProgramRecordingProfile
QString GetProgramRecordingProfile(void) const
Returns recording profile name that will be, or was used, for this program, creating "record" field i...
Definition: recordinginfo.cpp:490
RecordingDupInType
RecordingDupInType
Definition: recordingtypes.h:42
ProgramInfo::m_hostname
QString m_hostname
Definition: programinfo.h:777
ProgramInfo::m_chanName
QString m_chanName
Definition: programinfo.h:769
mythdate.h
ProgramInfo::SetRecordingEndTime
void SetRecordingEndTime(const QDateTime &dt)
Definition: programinfo.h:526
RecordingInfo::GetRecordingFile
RecordingFile * GetRecordingFile() const
Definition: recordinginfo.h:280
COMM_DETECT_COMMFREE
@ COMM_DETECT_COMMFREE
Definition: programtypes.h:130
ProgramInfo::GetScheduledStartTime
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:389
mythlogging.h
ProgramInfo::GetRecordingStatus
RecStatus::Type GetRecordingStatus(void) const
Definition: programinfo.h:446
RecordingInfo::m_savedrecstatus
RecStatus::Type m_savedrecstatus
Definition: recordinginfo.h:286
hardwareprofile.scan.profile
profile
Definition: scan.py:99
RecordingRule::m_autoUserJob4
bool m_autoUserJob4
Definition: recordingrule.h:137
ProgramInfo::m_recType
uint8_t m_recType
Definition: programinfo.h:815
ProgramInfo::m_category
QString m_category
Definition: programinfo.h:761
ProgramInfo::SetScheduledEndTime
void SetScheduledEndTime(const QDateTime &dt)
Definition: programinfo.h:524
RecStatus::PreviousRecording
@ PreviousRecording
Definition: recStatus.h:34
programinfoupdater.h
JOB_USERJOB1
@ JOB_USERJOB1
Definition: jobqueue.h:82
ProgramInfo::m_playGroup
QString m_playGroup
Definition: programinfo.h:773
RecordingInfo::m_desiredRecStartTs
QDateTime m_desiredRecStartTs
Definition: recordinginfo.h:291
RecordingInfo::SaveFilesize
void SaveFilesize(uint64_t fsize) override
Sets recording file size in database, and sets "filesize" field.
Definition: recordinginfo.cpp:1679
RecordingInfo::GetRecgroupString
static QString GetRecgroupString(uint recGroupID)
Temporary helper during transition from string to ID.
Definition: recordinginfo.cpp:1652
ProgramInfo::clear
virtual void clear(void)
Definition: programinfo.cpp:935
ProgramInfo::GetTitle
QString GetTitle(void) const
Definition: programinfo.h:360
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
ProgramInfo::m_seriesId
QString m_seriesId
Definition: programinfo.h:780
RecordingRule::m_autoUserJob2
bool m_autoUserJob2
Definition: recordingrule.h:135
RecordingFile::Save
bool Save()
Definition: recordingfile.cpp:55
RecordingInfo::RecordingInfo
RecordingInfo(void)
Definition: recordinginfo.h:38
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:200
kDupsInOldRecorded
@ kDupsInOldRecorded
Definition: recordingtypes.h:46
RecordingRule::m_autoExpire
bool m_autoExpire
Definition: recordingrule.h:127
RecordingInfo::GetAutoRunJobs
int GetAutoRunJobs(void) const
Returns a bitmap of which jobs are attached to this RecordingInfo.
Definition: recordinginfo.cpp:504
ProgramInfo::m_lastModified
QDateTime m_lastModified
Definition: programinfo.h:794
RecordingRule::m_recProfile
QString m_recProfile
Definition: recordingrule.h:121
ProgramInfo::m_episode
uint m_episode
Definition: programinfo.h:758
clamp
float clamp(float val, float minimum, float maximum)
Definition: mythmiscutil.h:56
kDupCheckUnset
@ kDupCheckUnset
Definition: recordingtypes.h:59
RecordingInfo::QuickRecord
void QuickRecord(void)
Create a kSingleRecord if not already scheduled.
Definition: recordinginfo.cpp:867
ProgramInfo::SaveTotalDuration
void SaveTotalDuration(std::chrono::milliseconds duration)
Store the Total Duration at frame 0 in the recordedmarkup table.
Definition: programinfo.cpp:4242
ProgramInfo::m_recGroup
QString m_recGroup
Definition: programinfo.h:772
RecordingRule::m_type
RecordingType m_type
Definition: recordingrule.h:113
ProgramInfo::toString
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
Definition: programinfo.cpp:1933
ProgramInfoUpdater::insert
void insert(uint recordedid, PIAction action, uint64_t filesize=0ULL)
Definition: programinfoupdater.cpp:10
scheduledrecording.h
ScheduledRecording::RescheduleCheck
static void RescheduleCheck(const RecordingInfo &recinfo, const QString &why)
Definition: scheduledrecording.h:23
jobqueue.h
RecordingInfo::ReactivateRecording
void ReactivateRecording(void)
Asks the scheduler to restart this recording if possible.
Definition: recordinginfo.cpp:1276
RecordingInfo::StartedRecording
void StartedRecording(const QString &ext)
Inserts this RecordingInfo into the database as an existing recording.
Definition: recordinginfo.cpp:933
ProgramInfo::m_originalAirDate
QDate m_originalAirDate
Definition: programinfo.h:793
uint
unsigned int uint
Definition: compat.h:140
ProgramInfo::SetFilesize
virtual void SetFilesize(uint64_t sz)
Definition: programinfo.cpp:6221
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
ProgramInfo::LoadFromScheduler
static QStringList LoadFromScheduler(const QString &tmptable, int recordid)
Definition: programinfo.cpp:5431
RecordingInfo::LoadStatus
LoadStatus
Definition: recordinginfo.h:180
RecordingInfo::kNoProgram
@ kNoProgram
Definition: recordinginfo.h:181
ProgramInfo::CategoryType
CategoryType
Definition: programinfo.h:75
ProgramInfo::GetStorageGroup
QString GetStorageGroup(void) const
Definition: programinfo.h:421
ProgramInfo::m_recStatus
int8_t m_recStatus
Definition: programinfo.h:814
ScheduledRecording::ReschedulePlace
static void ReschedulePlace(const QString &why)
Definition: scheduledrecording.h:33
RecordingInfo::LoadRecordingFile
void LoadRecordingFile()
Definition: recordinginfo.cpp:1666
RecordingInfo::m_sgroupId
uint m_sgroupId
Definition: recordinginfo.h:290
RecordingFile::m_fileSize
uint64_t m_fileSize
Definition: recordingfile.h:45
RecordingInfo::kFakedZeroMinProgram
@ kFakedZeroMinProgram
Definition: recordinginfo.h:184
RecordingInfo::m_schedOrder
int m_schedOrder
Definition: recordinginfo.h:288
AutoDeleteDeque< ProgramInfo * >
ProgramInfo::m_parentId
uint32_t m_parentId
Definition: programinfo.h:800
ProgramInfo::m_chanPlaybackFilters
QString m_chanPlaybackFilters
Definition: programinfo.h:770
recordinginfo.h
RecordingInfo::ApplyRecordRecPriorityChange
void ApplyRecordRecPriorityChange(int newrecpriority)
Sets recording priority of "record", creating "record" if it does not exist.
Definition: recordinginfo.cpp:592
ProgramInfo::GetChanID
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:371
kPIUpdateFileSize
@ kPIUpdateFileSize
Definition: programinfoupdater.h:22
RecordingRule::m_transcoder
int m_transcoder
Definition: recordingrule.h:131
RecordingRule::m_autoUserJob1
bool m_autoUserJob1
Definition: recordingrule.h:134
ProgramInfo::s_updater
static ProgramInfoUpdater * s_updater
Definition: programinfo.h:839
RecordingInfo::~RecordingInfo
~RecordingInfo() override
Destructor deletes "record" if it exists.
Definition: recordinginfo.cpp:460
RecordingInfo::SubstituteMatches
void SubstituteMatches(QString &str) override
Replace MATCH% vars in the specified string.
Definition: recordinginfo.cpp:1616
RecordingInfo::clone
virtual void clone(const RecordingInfo &other, bool ignore_non_serialized_data=false)
Copies important fields from other RecordingInfo.
Definition: recordinginfo.cpp:370
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
RecordingRule::m_recordID
int m_recordID
Unique Recording Rule ID.
Definition: recordingrule.h:72
ProgramInfo::m_inetRef
QString m_inetRef
Definition: programinfo.h:782
mythmiscutil.h
RecordingFile::m_recordingId
uint m_recordingId
Definition: recordingfile.h:38
ProgramInfo::m_subtitle
QString m_subtitle
Definition: programinfo.h:754
mythcorecontext.h
kOverrideRecord
@ kOverrideRecord
Definition: recordingtypes.h:28
RecordingInfo::InsertRecording
bool InsertRecording(const QString &ext, bool force_match=false)
Definition: recordinginfo.cpp:991
RecordingInfo::m_record
class RecordingRule * m_record
Definition: recordinginfo.h:295
ProgramInfo::m_syndicatedEpisode
QString m_syndicatedEpisode
Definition: programinfo.h:760
kNotRecording
@ kNotRecording
Definition: recordingtypes.h:21
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:878
JOB_METADATA
@ JOB_METADATA
Definition: jobqueue.h:78
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
ProgramInfo::m_findId
uint32_t m_findId
Definition: programinfo.h:804
RecStatus::CurrentRecording
@ CurrentRecording
Definition: recStatus.h:35
RecordingFile::m_fileName
QString m_fileName
Definition: recordingfile.h:44
LoadFromProgram
bool LoadFromProgram(ProgramList &destination, const QString &where, const QString &groupBy, const QString &orderBy, const MSqlBindings &bindings, const ProgramList &schedList)
Definition: programinfo.cpp:5566
RecordingInfo::clear
void clear(void) override
Definition: recordinginfo.cpp:436
LOC
#define LOC
Definition: recordinginfo.cpp:22
kSingleRecord
@ kSingleRecord
Definition: recordingtypes.h:22
ProgramInfo::m_chanSign
QString m_chanSign
Definition: programinfo.h:768
RecordingInfo::AddHistory
void AddHistory(bool resched=true, bool forcedup=false, bool future=false)
Adds recording history, creating "record" it if necessary.
Definition: recordinginfo.cpp:1297
ProgramInfo::SubstituteMatches
virtual void SubstituteMatches(QString &str)
Subsitute MATCH% type variable names in the given string.
Definition: programinfo.cpp:5318
RecordingInfo::ApplyTranscoderProfileChangeById
void ApplyTranscoderProfileChangeById(int id)
Definition: recordinginfo.cpp:775
kUnknownProgramLength
static const uint kUnknownProgramLength
Definition: recordinginfo.cpp:35
ProgramInfo::m_programFlags
uint32_t m_programFlags
ProgramFlag.
Definition: programinfo.h:806
ProgramInfo::m_partTotal
uint16_t m_partTotal
Definition: programinfo.h:812
ProgramInfo::m_chanStr
QString m_chanStr
Definition: programinfo.h:767
ProgramInfo::SendUpdateEvent
void SendUpdateEvent(void) const
Sends event out that the ProgramInfo should be reloaded.
Definition: programinfo.cpp:2710
RecordingInfo::kFakedLiveTVProgram
@ kFakedLiveTVProgram
Definition: recordinginfo.h:183
RecordingInfo::SetRecordingID
void SetRecordingID(uint _recordedid) override
Definition: recordinginfo.h:220
RecordingRule::Delete
bool Delete(bool sendSig=true)
Definition: recordingrule.cpp:500
RecordingRule::MakeOverride
bool MakeOverride(void)
Definition: recordingrule.cpp:360
MSqlQuery::numRowsAffected
int numRowsAffected() const
Definition: mythdbcon.h:214
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:862
ProgramInfo::m_partNumber
uint16_t m_partNumber
Definition: programinfo.h:811
RecordingInfo::ApplyRecordRecTitleChange
void ApplyRecordRecTitleChange(const QString &newTitle, const QString &newSubtitle, const QString &newDescription)
Sets the recording title, subtitle, and description both in this RecordingInfo and in the database.
Definition: recordinginfo.cpp:743
RecordingInfo::m_recordingFile
RecordingFile * m_recordingFile
Definition: recordinginfo.h:296
RecordingFile::Load
bool Load()
Definition: recordingfile.cpp:7
RecordingInfo::GetRecordingRule
RecordingRule * GetRecordingRule(void)
Returns the "record" field, creating it if necessary.
Definition: recordinginfo.cpp:877
RecordingInfo::ApplyRecordRecGroupChange
void ApplyRecordRecGroupChange(const QString &newrecgroup)
Sets the recording group, both in this RecordingInfo and in the database.
Definition: recordinginfo.cpp:604
ProgramInfo::m_programId
QString m_programId
Definition: programinfo.h:781
recordingrule.h
ProgramInfo::m_stars
float m_stars
Rating, range [0..1].
Definition: programinfo.h:792
RecordingRule::m_recPriority
int m_recPriority
Definition: recordingrule.h:109
RecordingFile::m_storageGroup
QString m_storageGroup
Definition: recordingfile.h:41
ProgramInfo::m_year
uint16_t m_year
Definition: programinfo.h:810
ProgramInfo::GetBasename
QString GetBasename(void) const
Definition: programinfo.h:343
RecordingRule::m_autoUserJob3
bool m_autoUserJob3
Definition: recordingrule.h:136
ProgramInfo::SetReactivated
void SetReactivated(bool reactivate)
Definition: programinfo.h:541
ProgramInfo::IsGeneric
bool IsGeneric(void) const
Definition: programinfo.cpp:1924
JOB_TRANSCODE
@ JOB_TRANSCODE
Definition: jobqueue.h:76
ProgramInfo::m_recordedId
uint m_recordedId
Definition: programinfo.h:819
ProgramInfo::CreateRecordBasename
QString CreateRecordBasename(const QString &ext) const
Returns a filename for a recording based on the recording channel and date.
Definition: programinfo.cpp:2390
ProgramInfo::m_videoProperties
VideoPropsType m_videoProperties
Definition: programinfo.h:807
RecordingType
RecordingType
Definition: recordingtypes.h:19
kDontRecord
@ kDontRecord
Definition: recordingtypes.h:29
RecordingRule::m_autoMetadataLookup
bool m_autoMetadataLookup
Definition: recordingrule.h:138
kDupsUnset
@ kDupsUnset
Definition: recordingtypes.h:44
RecordingFile::m_storageDeviceID
QString m_storageDeviceID
Definition: recordingfile.h:40
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:922
RecordingInfo::InsertFile
void InsertFile(void)
Definition: recordinginfo.cpp:1194
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:827
RecordingInfo::SetDupHistory
void SetDupHistory(void)
Set the duplicate flag in oldrecorded.
Definition: recordinginfo.cpp:1589