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
13 #include "libmythbase/mythdate.h"
14 #include "libmythbase/mythdb.h"
16 
17 #include "jobqueue.h"
18 #include "recordinginfo.h"
19 #include "recordingrule.h"
20 #include "scheduledrecording.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 = std::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 * 60LL);
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 * 60LL);
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 ";
349  bindings[":CHANID"] = QString::number(_chanid);
350  bindings[":STARTTS"] = desiredts.addSecs(50 - desiredts.time().second());
351 
352  const uint limit = 1;
353  uint count = 0;
354  LoadFromProgram(progList, querystr, bindings, schedList, 0, limit, count);
355 
356  if (!progList.empty())
357  nextstart = (*progList.begin())->GetScheduledStartTime();
358 
359  if (nextstart > m_startTs && nextstart < m_recEndTs)
360  m_recEndTs = m_endTs = nextstart;
361 
362  if (status)
363  *status = kFakedLiveTVProgram;
364 
367 
369 }
370 
373  bool ignore_non_serialized_data)
374 {
375  bool is_same =
376  ((m_chanId != 0U) && m_recStartTs.isValid() && m_startTs.isValid() &&
377  m_chanId == other.GetChanID() &&
378  m_recStartTs == other.GetRecordingStartTime() &&
379  m_startTs == other.GetScheduledStartTime());
380 
381  ProgramInfo::clone(other, ignore_non_serialized_data);
382 
383  if (!is_same)
384  {
385  delete m_record;
386  m_record = nullptr;
387  }
388 
389  if (!ignore_non_serialized_data)
390  {
393  m_future = other.m_future;
394  m_schedOrder = other.m_schedOrder;
395  m_mplexId = other.m_mplexId;
396  m_sgroupId = other.m_sgroupId;
399  }
400 
401  delete m_recordingFile;
402  m_recordingFile = nullptr;
404 }
405 
408  bool ignore_non_serialized_data)
409 {
410  bool is_same =
411  ((m_chanId != 0U) && m_recStartTs.isValid() && m_startTs.isValid() &&
412  m_chanId == other.GetChanID() &&
413  m_recStartTs == other.GetRecordingStartTime() &&
414  m_startTs == other.GetScheduledStartTime());
415 
416  ProgramInfo::clone(other, ignore_non_serialized_data);
417 
418  if (!is_same)
419  {
420  delete m_record;
421  m_record = nullptr;
422  }
423 
426  m_future = false;
427  m_schedOrder = 0;
428  m_mplexId = 0;
429  m_sgroupId = 0;
430  m_desiredRecStartTs = QDateTime();
431  m_desiredRecEndTs = QDateTime();
432 
433  delete m_recordingFile;
434  m_recordingFile = nullptr;
436 }
437 
439 {
441 
442  delete m_record;
443  m_record = nullptr;
444 
447  m_future = false;
448  m_schedOrder = 0;
449  m_mplexId = 0;
450  m_sgroupId = 0;
451  m_desiredRecStartTs = QDateTime();
452  m_desiredRecEndTs = QDateTime();
453 
454  delete m_recordingFile;
455  m_recordingFile = nullptr;
456 }
457 
458 
463 {
464  delete m_record;
465  m_record = nullptr;
466 
467  delete m_recordingFile;
468  m_recordingFile = nullptr;
469 }
470 
477 {
478  if (m_record == nullptr)
479  {
480  m_record = new RecordingRule();
481  m_record->LoadByProgram(this);
482  }
483 
484  return m_record->m_type;
485 }
486 
493 {
494  if (m_record == nullptr)
495  {
496  m_record = new RecordingRule();
497  m_record->LoadByProgram(this);
498  }
499 
500  return m_record->m_recProfile;
501 }
502 
507 {
508  if (m_record == nullptr)
509  {
510  m_record = new RecordingRule();
511  m_record->LoadByProgram(this);
512  }
513 
514  int result = 0;
515 
517  result |= JOB_TRANSCODE;
519  result |= JOB_COMMFLAG;
521  result |= JOB_METADATA;
523  result |= JOB_USERJOB1;
525  result |= JOB_USERJOB2;
527  result |= JOB_USERJOB3;
529  result |= JOB_USERJOB4;
530 
531 
532  return result;
533 }
534 
539 {
540  MSqlQuery query(MSqlQuery::InitCon());
541 
542  if (getRecordID() < 0)
543  {
544  LOG(VB_GENERAL, LOG_ERR,
545  "ProgInfo Error: ApplyRecordRecID(void) needs recordid");
546  return;
547  }
548 
549  query.prepare("UPDATE recorded "
550  "SET recordid = :RECID "
551  "WHERE chanid = :CHANID AND starttime = :START");
552 
553  if (m_recType == kOverrideRecord && m_parentId > 0)
554  query.bindValue(":RECID", m_parentId);
555  else
556  query.bindValue(":RECID", getRecordID());
557  query.bindValue(":CHANID", m_chanId);
558  query.bindValue(":START", m_recStartTs);
559 
560  if (!query.exec())
561  MythDB::DBError(LOC + "RecordID update", query);
562 }
563 
574 {
576  if (newstate == kOverrideRecord || newstate == kDontRecord)
578  m_record->m_type = newstate;
579 
580  if (save)
581  {
582  if (newstate == kNotRecording)
583  m_record->Delete();
584  else
585  m_record->Save();
586  }
587 }
588 
593 void RecordingInfo::ApplyStarsChange(float newstarsvalue)
594 {
595  MSqlQuery query(MSqlQuery::InitCon());
596 
597  query.prepare("UPDATE recorded"
598  " SET stars = :STARS"
599  " WHERE chanid = :CHANID"
600  " AND starttime = :START ;");
601  query.bindValue(":STARS", newstarsvalue);
602  query.bindValue(":START", m_recStartTs);
603  query.bindValue(":CHANID", m_chanId);
604 
605  if (!query.exec())
606  MythDB::DBError("Stars update", query);
607 
608  m_stars = newstarsvalue;
609 
610  SendUpdateEvent();
611 }
612 
618 void RecordingInfo::ApplyOriginalAirDateChange(QDate originalairdate)
619 {
620  MSqlQuery query(MSqlQuery::InitCon());
621 
622  query.prepare("UPDATE recorded"
623  " SET originalairdate = :ORIGINALAIRDATE"
624  " WHERE chanid = :CHANID"
625  " AND starttime = :START ;");
626  query.bindValue(":ORIGINALAIRDATE", originalairdate);
627  query.bindValue(":CHANID", m_chanId);
628  query.bindValue(":START", m_recStartTs);
629 
630  if (!query.exec())
631  MythDB::DBError("OriginalAirDate update", query);
632 
633  m_originalAirDate = originalairdate;
634 
635  SendUpdateEvent();
636 }
637 
644 {
646  m_record->m_recPriority = newrecpriority;
647  m_record->Save();
648 }
649 
655 void RecordingInfo::ApplyRecordRecGroupChange(const QString &newrecgroup)
656 {
657  MSqlQuery query(MSqlQuery::InitCon());
658 
659  int newrecgroupid = GetRecgroupID(newrecgroup);
660 
661  // Catchall - in the event that the group doesn't exist, then to avoid
662  // breakage, we need to create it
663  if (newrecgroupid == 0)
664  {
665  query.prepare("INSERT INTO recgroups SET recgroup = :NAME, "
666  "displayname = :DISPLAYNAME");
667  query.bindValue(":NAME", newrecgroup);
668  query.bindValue(":DISPLAYNAME", newrecgroup);
669 
670  if (query.exec())
671  newrecgroupid = query.lastInsertId().toInt();
672 
673  if (newrecgroupid <= 0)
674  {
675  LOG(VB_GENERAL, LOG_ERR, QString("Could not create recording group (%1). "
676  "Does it already exist?").arg(newrecgroup));
677  return;
678  }
679  }
680 
681  LOG(VB_GENERAL, LOG_NOTICE,
682  QString("ApplyRecordRecGroupChange: %1 to %2 (%3)")
683  .arg(m_recGroup, newrecgroup, QString::number(newrecgroupid)));
684 
685  query.prepare("UPDATE recorded"
686  " SET recgroup = :RECGROUP, "
687  " recgroupid = :RECGROUPID "
688  " WHERE chanid = :CHANID"
689  " AND starttime = :START ;");
690  query.bindValue(":RECGROUP", null_to_empty(newrecgroup));
691  query.bindValue(":RECGROUPID", newrecgroupid);
692  query.bindValue(":START", m_recStartTs);
693  query.bindValue(":CHANID", m_chanId);
694 
695  if (!query.exec())
696  MythDB::DBError("RecGroup update", query);
697 
698  m_recGroup = newrecgroup; // Deprecate in favour of recgroupid
699  //recgroupid = newrecgroupid;
700 
701  SendUpdateEvent();
702 }
703 
705 {
706  MSqlQuery query(MSqlQuery::InitCon());
707 
708  QString newrecgroup;
709  if (newrecgroupid > 0)
710  {
711  newrecgroup = GetRecgroupString(newrecgroupid);
712 
713  query.prepare("UPDATE recorded"
714  " SET recgroup = :RECGROUP, "
715  " recgroupid = :RECGROUPID "
716  " WHERE chanid = :CHANID"
717  " AND starttime = :START ;");
718  query.bindValue(":RECGROUP", null_to_empty(newrecgroup));
719  query.bindValue(":RECGROUPID", newrecgroupid);
720  query.bindValue(":START", m_recStartTs);
721  query.bindValue(":CHANID", m_chanId);
722 
723  if (!query.exec())
724  MythDB::DBError("RecGroup update", query);
725 
726  m_recGroup = newrecgroup; // Deprecate in favour of recgroupid
727  //recgroupid = newrecgroupid;
728 
729  SendUpdateEvent();
730  }
731 
732  LOG(VB_GENERAL, LOG_NOTICE,
733  QString("ApplyRecordRecGroupChange: %1 to %2 (%3)")
734  .arg(m_recGroup, newrecgroup).arg(newrecgroupid));
735 }
736 
742 void RecordingInfo::ApplyRecordPlayGroupChange(const QString &newplaygroup)
743 {
744  MSqlQuery query(MSqlQuery::InitCon());
745 
746  query.prepare("UPDATE recorded"
747  " SET playgroup = :PLAYGROUP"
748  " WHERE chanid = :CHANID"
749  " AND starttime = :START ;");
750  query.bindValue(":PLAYGROUP", null_to_empty(newplaygroup));
751  query.bindValue(":START", m_recStartTs);
752  query.bindValue(":CHANID", m_chanId);
753 
754  if (!query.exec())
755  MythDB::DBError("PlayGroup update", query);
756 
757  m_playGroup = newplaygroup;
758 
759  SendUpdateEvent();
760 }
761 
767 void RecordingInfo::ApplyStorageGroupChange(const QString &newstoragegroup)
768 {
769  MSqlQuery query(MSqlQuery::InitCon());
770 
771  query.prepare("UPDATE recorded"
772  " SET storagegroup = :STORAGEGROUP"
773  " WHERE chanid = :CHANID"
774  " AND starttime = :START ;");
775  query.bindValue(":STORAGEGROUP", null_to_empty(newstoragegroup));
776  query.bindValue(":START", m_recStartTs);
777  query.bindValue(":CHANID", m_chanId);
778 
779  if (!query.exec())
780  MythDB::DBError("StorageGroup update", query);
781 
782  m_storageGroup = newstoragegroup;
783 
784  SendUpdateEvent();
785 }
786 
794 void RecordingInfo::ApplyRecordRecTitleChange(const QString &newTitle,
795  const QString &newSubtitle, const QString &newDescription)
796 {
797  MSqlQuery query(MSqlQuery::InitCon());
798  QString sql = "UPDATE recorded SET title = :TITLE, subtitle = :SUBTITLE ";
799  if (!newDescription.isNull())
800  sql += ", description = :DESCRIPTION ";
801  sql += " WHERE chanid = :CHANID AND starttime = :START ;";
802 
803  query.prepare(sql);
804  query.bindValue(":TITLE", newTitle);
805  query.bindValue(":SUBTITLE", null_to_empty(newSubtitle));
806  if (!newDescription.isNull())
807  query.bindValue(":DESCRIPTION", newDescription);
808  query.bindValue(":CHANID", m_chanId);
809  query.bindValue(":START", m_recStartTs);
810 
811  if (!query.exec())
812  MythDB::DBError("RecTitle update", query);
813 
814  m_title = newTitle;
815  m_subtitle = newSubtitle;
816  if (!newDescription.isNull())
817  m_description = newDescription;
818 
819  SendUpdateEvent();
820 }
821 
822 /* \fn RecordingInfo::ApplyTranscoderProfileChangeById(int id)
823  * \brief Sets the transcoder profile for a recording
824  * \param profileid is the 'id' field from recordingprofiles table.
825  */
827 {
828  MSqlQuery query(MSqlQuery::InitCon());
829 
830  query.prepare("UPDATE recorded "
831  "SET transcoder = :PROFILEID "
832  "WHERE chanid = :CHANID "
833  "AND starttime = :START");
834  query.bindValue(":PROFILEID", id);
835  query.bindValue(":CHANID", m_chanId);
836  query.bindValue(":START", m_recStartTs);
837 
838  if (!query.exec())
839  MythDB::DBError(LOC + "unable to update transcoder "
840  "in recorded table", query);
841 }
842 
847 {
848  if (profile == "Default") // use whatever is already in the transcoder
849  return;
850 
851  MSqlQuery query(MSqlQuery::InitCon());
852 
853  if (profile == "Autodetect")
854  {
855  query.prepare("UPDATE recorded "
856  "SET transcoder = 0 "
857  "WHERE chanid = :CHANID "
858  "AND starttime = :START");
859  query.bindValue(":CHANID", m_chanId);
860  query.bindValue(":START", m_recStartTs);
861 
862  if (!query.exec())
863  MythDB::DBError(LOC + "unable to update transcoder "
864  "in recorded table", query);
865  }
866  else
867  {
868  MSqlQuery pidquery(MSqlQuery::InitCon());
869  pidquery.prepare("SELECT r.id "
870  "FROM recordingprofiles r, profilegroups p "
871  "WHERE r.profilegroup = p.id "
872  "AND p.name = 'Transcoders' "
873  "AND r.name = :PROFILE ");
874  pidquery.bindValue(":PROFILE", profile);
875 
876  if (!pidquery.exec())
877  {
878  MythDB::DBError("ProgramInfo: unable to query transcoder "
879  "profile ID", query);
880  }
881  else if (pidquery.next())
882  {
883  query.prepare("UPDATE recorded "
884  "SET transcoder = :TRANSCODER "
885  "WHERE chanid = :CHANID "
886  "AND starttime = :START");
887  query.bindValue(":TRANSCODER", pidquery.value(0).toInt());
888  query.bindValue(":CHANID", m_chanId);
889  query.bindValue(":START", m_recStartTs);
890 
891  if (!query.exec())
892  MythDB::DBError(LOC + "unable to update transcoder "
893  "in recorded table", query);
894  }
895  else
896  {
897  LOG(VB_GENERAL, LOG_ERR,
898  "ProgramInfo: unable to query transcoder profile ID");
899  }
900  }
901 }
902 
908 {
912  AddHistory(true, true);
913 }
914 
919 {
921  if (curType == kNotRecording)
923 }
924 
929 {
931  return m_record;
932 }
933 
938 {
941  return m_recordId;
942 }
943 
945  uint chanid, const QDateTime& recstartts)
946 {
947  if (chanid < 1)
948  {
949  LOG(VB_RECORD, LOG_WARNING,
950  QString("QueryRecordedIdFromKey: Invalid chanid %1").arg(chanid));
951  return false;
952  }
953  if (!recstartts.isValid())
954  {
955  LOG(VB_RECORD, LOG_WARNING,
956  QString("QueryRecordedIdFromKey: Invalid start ts %1")
957  .arg(recstartts.toString()));
958  return false;
959  }
960 
961  MSqlQuery query(MSqlQuery::InitCon());
962  query.prepare(
963  "SELECT recordedid FROM recorded "
964  "WHERE chanid = :CHANID AND starttime = :RECSTARTTS");
965  query.bindValue(":CHANID", chanid);
966  query.bindValue(":RECSTARTTS", recstartts);
967  if (query.exec() && query.next())
968  {
969  recordedid = query.value(0).toUInt();
970  return true;
971  }
972 
973  return false;
974 }
975 
984 void RecordingInfo::StartedRecording(const QString& ext)
985 {
987 
988  if (!InsertRecording(ext))
989  return;
990 
991  LOG(VB_FILE, LOG_INFO, LOC + QString("StartedRecording: Recording to '%1'")
992  .arg(m_pathname));
993 
994 
995  MSqlQuery query(MSqlQuery::InitCon());
996 
997  query.prepare("DELETE FROM recordedseek WHERE chanid = :CHANID"
998  " AND starttime = :START;");
999  query.bindValue(":CHANID", m_chanId);
1000  query.bindValue(":START", m_recStartTs);
1001 
1002  if (!query.exec() || !query.isActive())
1003  MythDB::DBError("Clear seek info on record", query);
1004 
1005  query.prepare("DELETE FROM recordedmarkup WHERE chanid = :CHANID"
1006  " AND starttime = :START;");
1007  query.bindValue(":CHANID", m_chanId);
1008  query.bindValue(":START", m_recStartTs);
1009 
1010  if (!query.exec() || !query.isActive())
1011  MythDB::DBError("Clear markup on record", query);
1012 
1013  query.prepare("REPLACE INTO recordedcredits"
1014  " SELECT * FROM credits"
1015  " WHERE chanid = :CHANID AND starttime = :START;");
1016  query.bindValue(":CHANID", m_chanId);
1017  query.bindValue(":START", m_startTs);
1018  if (!query.exec() || !query.isActive())
1019  MythDB::DBError("Copy program credits on record", query);
1020 
1021  query.prepare("REPLACE INTO recordedprogram"
1022  " SELECT * from program"
1023  " WHERE chanid = :CHANID AND starttime = :START"
1024  " AND title = :TITLE;");
1025  query.bindValue(":CHANID", m_chanId);
1026  query.bindValue(":START", m_startTs);
1027  query.bindValue(":TITLE", m_title);
1028  if (!query.exec() || !query.isActive())
1029  MythDB::DBError("Copy program data on record", query);
1030 
1031  query.prepare("REPLACE INTO recordedrating"
1032  " SELECT * from programrating"
1033  " WHERE chanid = :CHANID AND starttime = :START;");
1034  query.bindValue(":CHANID", m_chanId);
1035  query.bindValue(":START", m_startTs);
1036  if (!query.exec() || !query.isActive())
1037  MythDB::DBError("Copy program ratings on record", query);
1038 
1039  InsertFile();
1040 }
1041 
1042 bool RecordingInfo::InsertRecording(const QString &ext, bool force_match)
1043 {
1044  QString dirname = m_pathname;
1045 
1046 #if 1
1047  if (!dirname.isEmpty())
1048  {
1049  LOG(VB_GENERAL, LOG_DEBUG, LOC +
1050  QString("InsertRecording: m_pathname was '%1'. "
1051  "This is usually blank.").arg(dirname));
1052  }
1053 #endif
1054 
1056 
1057  if (!m_record)
1058  {
1059  m_record = new RecordingRule();
1060  m_record->LoadByProgram(this);
1061  }
1062 
1063  int count = 0;
1064  while (!InsertProgram(this, m_record) && count < 50)
1065  {
1066  if (force_match)
1067  {
1068  LOG(VB_GENERAL, LOG_ERR, "Failed to insert new recording.");
1069  return false;
1070  }
1071 
1072  m_recStartTs = m_recStartTs.addSecs(1);
1074  ++count;
1075  }
1076 
1077  if (count >= 50)
1078  {
1079  LOG(VB_GENERAL, LOG_ERR, "Could not insert program");
1080  return false;
1081  }
1082 
1083  m_pathname = dirname + "/" + m_pathname;
1084 
1085  return true;
1086 }
1087 
1089  const RecordingRule *rule)
1090 {
1091  QString inputname = pg->GetInputName();
1092  int recgroupid = GetRecgroupID(pg->m_recGroup);
1093 
1094  MSqlQuery query(MSqlQuery::InitCon());
1095 
1096  if (!query.exec("LOCK TABLES recorded WRITE"))
1097  {
1098  MythDB::DBError("InsertProgram -- lock", query);
1099  return false;
1100  }
1101 
1102  query.prepare(
1103  "SELECT recordid "
1104  " FROM recorded "
1105  " WHERE chanid = :CHANID AND "
1106  " starttime = :STARTS");
1107  query.bindValue(":CHANID", pg->m_chanId);
1108  query.bindValue(":STARTS", pg->m_recStartTs);
1109 
1110  bool err = true;
1111  if (!query.exec())
1112  {
1113  MythDB::DBError("InsertProgram -- select", query);
1114  }
1115  else if (query.next())
1116  {
1117  LOG(VB_GENERAL, LOG_ERR,
1118  QString("RecordingInfo::InsertProgram(%1): ")
1119  .arg(pg->toString()) + "recording already exists...");
1120  }
1121  else
1122  {
1123  err = false;
1124  }
1125 
1126  if (err)
1127  {
1128  if (!query.exec("UNLOCK TABLES"))
1129  MythDB::DBError("InsertProgram -- unlock tables", query);
1130  return false;
1131  }
1132 
1133  query.prepare(
1134  "INSERT INTO recorded "
1135  " (chanid, starttime, endtime, title, "
1136  " subtitle, description, season, episode, "
1137  " hostname, category, recgroup, autoexpire, "
1138  " recordid, seriesid, programid, inetref, "
1139  " stars, previouslyshown, originalairdate, "
1140  " findid, transcoder, playgroup, recpriority, "
1141  " basename, progstart, progend, profile, "
1142  " duplicate, storagegroup, inputname, recgroupid) "
1143  "VALUES"
1144  " (:CHANID, :STARTS, :ENDS, :TITLE, "
1145  " :SUBTITLE, :DESC, :SEASON, :EPISODE, "
1146  " :HOSTNAME, :CATEGORY, :RECGROUP, :AUTOEXP, "
1147  " :RECORDID, :SERIESID, :PROGRAMID, :INETREF, "
1148  " :STARS, :REPEAT, :ORIGAIRDATE, "
1149  " :FINDID, :TRANSCODER, :PLAYGROUP, :RECPRIORITY, "
1150  " :BASENAME, :PROGSTART, :PROGEND, :PROFILE, "
1151  " 0, :STORGROUP, :INPUTNAME, :RECGROUPID) "
1152  );
1153 
1154  if (pg->m_recType == kOverrideRecord)
1155  query.bindValue(":RECORDID", pg->m_parentId);
1156  else
1157  query.bindValue(":RECORDID", pg->m_recordId);
1158 
1159  if (pg->m_originalAirDate.isValid())
1160  {
1161  query.bindValue(":ORIGAIRDATE", pg->m_originalAirDate);
1162  // If there is no originalairdate use "year"
1163  }
1164  else if (pg->m_year == pg->m_recStartTs.date().year())
1165  {
1166  query.bindValue(":ORIGAIRDATE", pg->m_recStartTs.date());
1167  }
1168  else if (pg->m_year >= 1895)
1169  {
1170  query.bindValue(":ORIGAIRDATE", QDate(pg->m_year,1,1));
1171  }
1172  else
1173  {
1174  query.bindValue(":ORIGAIRDATE", "0000-00-00");
1175  }
1176 
1177  query.bindValue(":CHANID", pg->m_chanId);
1178  query.bindValue(":STARTS", pg->m_recStartTs);
1179  query.bindValue(":ENDS", pg->m_recEndTs);
1180  query.bindValue(":TITLE", pg->m_title);
1181  query.bindValue(":SUBTITLE", null_to_empty(pg->m_subtitle));
1182  query.bindValue(":DESC", null_to_empty(pg->m_description));
1183  query.bindValue(":SEASON", pg->m_season);
1184  query.bindValue(":EPISODE", pg->m_episode);
1185  query.bindValue(":HOSTNAME", pg->m_hostname);
1186  query.bindValue(":CATEGORY", null_to_empty(pg->m_category));
1187  query.bindValue(":RECGROUP", null_to_empty(pg->m_recGroup));
1188  query.bindValue(":AUTOEXP", rule->m_autoExpire);
1189  query.bindValue(":SERIESID", null_to_empty(pg->m_seriesId));
1190  query.bindValue(":PROGRAMID", null_to_empty(pg->m_programId));
1191  query.bindValue(":INETREF", null_to_empty(pg->m_inetRef));
1192  query.bindValue(":FINDID", pg->m_findId);
1193  query.bindValue(":STARS", pg->m_stars);
1194  query.bindValue(":REPEAT", pg->IsRepeat());
1195  query.bindValue(":TRANSCODER", rule->m_transcoder);
1196  query.bindValue(":PLAYGROUP", pg->m_playGroup);
1197  query.bindValue(":RECPRIORITY", rule->m_recPriority);
1198  query.bindValue(":BASENAME", pg->m_pathname);
1199  query.bindValue(":STORGROUP", null_to_empty(pg->m_storageGroup));
1200  query.bindValue(":PROGSTART", pg->m_startTs);
1201  query.bindValue(":PROGEND", pg->m_endTs);
1202  query.bindValue(":PROFILE", null_to_empty(rule->m_recProfile));
1203  query.bindValue(":INPUTNAME", inputname);
1204  query.bindValue(":RECGROUPID", recgroupid);
1205 
1206  bool ok = query.exec() && (query.numRowsAffected() > 0);
1207  if (ok)
1208  {
1209  pg->SetRecordingID(query.lastInsertId().toUInt());
1210  }
1211  bool active = query.isActive();
1212 
1213  if (!query.exec("UNLOCK TABLES"))
1214  MythDB::DBError("InsertProgram -- unlock tables", query);
1215 
1216  if (!ok && !active)
1217  {
1218  MythDB::DBError("InsertProgram -- insert", query);
1219 
1220  }
1221  else if (pg->m_recordId > 0)
1222  {
1223  query.prepare("UPDATE channel SET last_record = NOW() "
1224  "WHERE chanid = :CHANID");
1225  query.bindValue(":CHANID", pg->GetChanID());
1226  if (!query.exec())
1227  MythDB::DBError("InsertProgram -- channel last_record", query);
1228 
1229  query.prepare("UPDATE record SET last_record = NOW() "
1230  "WHERE recordid = :RECORDID");
1231  query.bindValue(":RECORDID", pg->m_recordId);
1232  if (!query.exec())
1233  MythDB::DBError("InsertProgram -- record last_record", query);
1234 
1235  if (pg->m_recType == kOverrideRecord && pg->m_parentId > 0)
1236  {
1237  query.prepare("UPDATE record SET last_record = NOW() "
1238  "WHERE recordid = :PARENTID");
1239  query.bindValue(":PARENTID", pg->m_parentId);
1240  if (!query.exec())
1241  MythDB::DBError("InsertProgram -- record last_record override",
1242  query);
1243  }
1244  }
1245 
1246  return ok;
1247 }
1248 
1250 {
1251  // File
1252  if (!GetRecordingFile())
1254  RecordingFile *recFile = GetRecordingFile();
1255  recFile->m_fileName = GetBasename();
1256  recFile->m_storageDeviceID = GetHostname();
1257  recFile->m_storageGroup = GetStorageGroup();
1258  recFile->Save();
1259 
1260  SendAddedEvent();
1261 }
1262 
1271 void RecordingInfo::FinishedRecording(bool allowReRecord)
1272 {
1273  MSqlQuery query(MSqlQuery::InitCon());
1274  query.prepare("UPDATE recorded SET endtime = :ENDTIME, "
1275  " duplicate = :DUPLICATE "
1276  "WHERE chanid = :CHANID AND "
1277  " starttime = :STARTTIME ");
1278  query.bindValue(":ENDTIME", m_recEndTs);
1279  query.bindValue(":CHANID", m_chanId);
1280  query.bindValue(":STARTTIME", m_recStartTs);
1281  query.bindValue(":DUPLICATE", !allowReRecord);
1282 
1283  if (!query.exec())
1284  MythDB::DBError("FinishedRecording update", query);
1285 
1287  if (!allowReRecord)
1288  {
1290 
1291  qint64 starttime = m_recStartTs.toSecsSinceEpoch();
1292  qint64 endtime = m_recEndTs.toSecsSinceEpoch();
1293  SaveTotalDuration(std::chrono::seconds(endtime - starttime));
1294 
1295  QString msg = "Finished recording";
1296  QString msg_subtitle = m_subtitle.isEmpty() ? "" :
1297  QString(" \"%1\"").arg(m_subtitle);
1298  QString details = QString("%1%2: channel %3")
1299  .arg(m_title, msg_subtitle, QString::number(m_chanId));
1300 
1301  LOG(VB_GENERAL, LOG_INFO, QString("%1 %2").arg(msg, details));
1302  }
1303 
1304  SendUpdateEvent();
1305 }
1306 
1312 {
1313  MSqlQuery query(MSqlQuery::InitCon());
1314  query.prepare("UPDATE recorded SET endtime = :ENDTIME "
1315  "WHERE chanid = :CHANID AND "
1316  " starttime = :STARTTIME ");
1317  query.bindValue(":ENDTIME", m_recEndTs);
1318 
1319  query.bindValue(":CHANID", m_chanId);
1320  query.bindValue(":STARTTIME", m_recStartTs);
1321 
1322  if (!query.exec())
1323  MythDB::DBError("UpdateRecordingEnd update", query);
1324 
1325  SendUpdateEvent();
1326 }
1327 
1332 {
1333  MSqlQuery result(MSqlQuery::InitCon());
1334 
1335  result.prepare("UPDATE oldrecorded SET reactivate = 1 "
1336  "WHERE station = :STATION AND "
1337  " starttime = :STARTTIME AND "
1338  " title = :TITLE;");
1339  result.bindValue(":STARTTIME", m_startTs);
1340  result.bindValue(":TITLE", m_title);
1341  result.bindValue(":STATION", m_chanSign);
1342 
1343  if (!result.exec())
1344  MythDB::DBError("ReactivateRecording", result);
1345 
1347 }
1348 
1352 void RecordingInfo::AddHistory(bool resched, bool forcedup, bool future)
1353 {
1354  bool dup = (GetRecordingStatus() == RecStatus::Recorded || forcedup);
1357  LOG(VB_SCHEDULE, LOG_INFO, QString("AddHistory: %1/%2, %3, %4, %5/%6")
1358  .arg(int(rs)).arg(int(m_oldrecstatus)).arg(future).arg(dup)
1360  if (!future)
1362  if (dup)
1363  SetReactivated(false);
1364  uint erecid = m_parentId ? m_parentId : m_recordId;
1365 
1366  MSqlQuery result(MSqlQuery::InitCon());
1367 
1368  result.prepare("REPLACE INTO oldrecorded (chanid,starttime,"
1369  "endtime,title,subtitle,description,season,episode,"
1370  "category,seriesid,programid,inetref,findid,recordid,"
1371  "station,rectype,recstatus,duplicate,reactivate,generic,"
1372  "future) "
1373  "VALUES(:CHANID,:START,:END,:TITLE,:SUBTITLE,:DESC,:SEASON,"
1374  ":EPISODE,:CATEGORY,:SERIESID,:PROGRAMID,:INETREF,"
1375  ":FINDID,:RECORDID,:STATION,:RECTYPE,:RECSTATUS,:DUPLICATE,"
1376  ":REACTIVATE,:GENERIC,:FUTURE);");
1377  result.bindValue(":CHANID", m_chanId);
1378  result.bindValue(":START", m_startTs);
1379  result.bindValue(":END", m_endTs);
1380  result.bindValue(":TITLE", m_title);
1381  result.bindValue(":SUBTITLE", null_to_empty(m_subtitle));
1382  result.bindValue(":DESC", null_to_empty(m_description));
1383  result.bindValue(":SEASON", m_season);
1384  result.bindValue(":EPISODE", m_episode);
1385  result.bindValue(":CATEGORY", null_to_empty(m_category));
1386  result.bindValue(":SERIESID", null_to_empty(m_seriesId));
1387  result.bindValue(":PROGRAMID", null_to_empty(m_programId));
1388  result.bindValue(":INETREF", null_to_empty(m_inetRef));
1389  result.bindValue(":FINDID", m_findId);
1390  result.bindValue(":RECORDID", erecid);
1391  result.bindValue(":STATION", null_to_empty(m_chanSign));
1392  result.bindValue(":RECTYPE", m_recType);
1393  result.bindValue(":RECSTATUS", rs);
1394  result.bindValue(":DUPLICATE", dup);
1395  result.bindValue(":REACTIVATE", 0);
1396  result.bindValue(":GENERIC", IsGeneric());
1397  result.bindValue(":FUTURE", future);
1398 
1399  if (!result.exec())
1400  MythDB::DBError("addHistory", result);
1401 
1402  if (dup && m_findId)
1403  {
1404  result.prepare("REPLACE INTO oldfind (recordid, findid) "
1405  "VALUES(:RECORDID,:FINDID);");
1406  result.bindValue(":RECORDID", erecid);
1407  result.bindValue(":FINDID", m_findId);
1408 
1409  if (!result.exec())
1410  MythDB::DBError("addFindHistory", result);
1411  }
1412 
1413  // The adding of an entry to oldrecorded may affect near-future
1414  // scheduling decisions, so recalculate if told
1415  if (resched)
1416  ScheduledRecording::RescheduleCheck(*this, "AddHistory");
1417 }
1418 
1423 {
1424  uint erecid = m_parentId ? m_parentId : m_recordId;
1425 
1426  MSqlQuery result(MSqlQuery::InitCon());
1427 
1428  result.prepare("DELETE FROM oldrecorded WHERE title = :TITLE AND "
1429  "starttime = :START AND station = :STATION");
1430  result.bindValue(":TITLE", m_title);
1431  result.bindValue(":START", m_recStartTs);
1432  result.bindValue(":STATION", m_chanSign);
1433 
1434  if (!result.exec())
1435  MythDB::DBError("deleteHistory", result);
1436 
1437  if (/*m_duplicate &&*/ m_findId)
1438  {
1439  result.prepare("DELETE FROM oldfind WHERE "
1440  "recordid = :RECORDID AND findid = :FINDID");
1441  result.bindValue(":RECORDID", erecid);
1442  result.bindValue(":FINDID", m_findId);
1443 
1444  if (!result.exec())
1445  MythDB::DBError("deleteFindHistory", result);
1446  }
1447 
1448  // The removal of an entry from oldrecorded may affect near-future
1449  // scheduling decisions, so recalculate
1450  ScheduledRecording::RescheduleCheck(*this, "DeleteHistory");
1451 }
1452 
1462 {
1463  uint erecid = m_parentId ? m_parentId : m_recordId;
1464  uint din = m_dupIn;
1465  uint dmeth = m_dupMethod;
1466 
1467  if (din == kDupsUnset)
1468  din = kDupsInAll;
1469  if (dmeth == kDupCheckUnset)
1470  dmeth = kDupCheckSubThenDesc;
1471 
1472  MSqlQuery result(MSqlQuery::InitCon());
1473 
1474  // Handle this specific entry in recorded.
1475  result.prepare("UPDATE recorded SET duplicate = 0 "
1476  "WHERE chanid = :CHANID "
1477  "AND starttime = :STARTTIME "
1478  "AND title = :TITLE;");
1479  result.bindValue(":STARTTIME", m_recStartTs);
1480  result.bindValue(":TITLE", m_title);
1481  result.bindValue(":CHANID", m_chanId);
1482 
1483  if (!result.exec())
1484  MythDB::DBError("forgetRecorded1", result);
1485 
1486  // Handle other matching entries in recorded.
1487  if (din & kDupsInRecorded)
1488  {
1489  result.prepare(
1490  "UPDATE recorded SET duplicate = 0 "
1491  "WHERE duplicate = 1 AND "
1492  " title = :TITLE AND "
1493  " ( "
1494  " (:PROGRAMID1 <> '' AND "
1495  " :PROGRAMID2 = recorded.programid) "
1496  " OR "
1497  " ( "
1498  " (:PROGRAMID3 = '' OR recorded.programid = '' OR "
1499  " LEFT(:PROGRAMID4, LOCATE('/', :PROGRAMID5)) <> "
1500  " LEFT(recorded.programid, "
1501  " LOCATE('/', recorded.programid))) "
1502  " AND "
1503  " (((:DUPMETHOD1 & 0x02) = 0) OR (:SUBTITLE1 <> '' "
1504  " AND :SUBTITLE2 = recorded.subtitle)) "
1505  " AND "
1506  " (((:DUPMETHOD2 & 0x04) = 0) OR (:DESCRIPTION1 <> '' "
1507  " AND :DESCRIPTION2 = recorded.description)) "
1508  " AND "
1509  " (((:DUPMETHOD3 & 0x08) = 0) OR "
1510  " (:SUBTITLE3 <> '' AND "
1511  " (:SUBTITLE4 = recorded.subtitle OR "
1512  " (recorded.subtitle = '' AND "
1513  " :SUBTITLE5 = recorded.description))) OR "
1514  " (:SUBTITLE6 = '' AND :DESCRIPTION3 <> '' AND "
1515  " (:DESCRIPTION4 = recorded.subtitle OR "
1516  " (recorded.subtitle = '' AND "
1517  " :DESCRIPTION5 = recorded.description)))) "
1518  " ) "
1519  " )" );
1520  result.bindValue(":TITLE", m_title);
1521  result.bindValue(":SUBTITLE1", null_to_empty(m_subtitle));
1522  result.bindValue(":SUBTITLE2", null_to_empty(m_subtitle));
1523  result.bindValue(":SUBTITLE3", null_to_empty(m_subtitle));
1524  result.bindValue(":SUBTITLE4", null_to_empty(m_subtitle));
1525  result.bindValue(":SUBTITLE5", null_to_empty(m_subtitle));
1526  result.bindValue(":SUBTITLE6", null_to_empty(m_subtitle));
1527  result.bindValue(":DESCRIPTION1", null_to_empty(m_description));
1528  result.bindValue(":DESCRIPTION2", null_to_empty(m_description));
1529  result.bindValue(":DESCRIPTION3", null_to_empty(m_description));
1530  result.bindValue(":DESCRIPTION4", null_to_empty(m_description));
1531  result.bindValue(":DESCRIPTION5", null_to_empty(m_description));
1532  result.bindValue(":PROGRAMID1", null_to_empty(m_programId));
1533  result.bindValue(":PROGRAMID2", null_to_empty(m_programId));
1534  result.bindValue(":PROGRAMID3", null_to_empty(m_programId));
1535  result.bindValue(":PROGRAMID4", null_to_empty(m_programId));
1536  result.bindValue(":PROGRAMID5", null_to_empty(m_programId));
1537  result.bindValue(":DUPMETHOD1", dmeth);
1538  result.bindValue(":DUPMETHOD2", dmeth);
1539  result.bindValue(":DUPMETHOD3", dmeth);
1540 
1541  if (!result.exec())
1542  MythDB::DBError("forgetRecorded2", result);
1543  }
1544 
1545  // Handle this specific entry in oldrecorded.
1546  result.prepare("UPDATE oldrecorded SET duplicate = 0 "
1547  "WHERE station = :STATION "
1548  "AND starttime = :STARTTIME "
1549  "AND title = :TITLE;");
1550  result.bindValue(":STARTTIME", m_startTs);
1551  result.bindValue(":TITLE", m_title);
1552  result.bindValue(":STATION", m_chanSign);
1553 
1554  if (!result.exec())
1555  MythDB::DBError("forgetOldRecorded1", result);
1556 
1557  // Handle other matching entries in oldrecorded.
1558  if (din & kDupsInOldRecorded)
1559  {
1560  result.prepare(
1561  "UPDATE oldrecorded SET duplicate = 0 "
1562  "WHERE duplicate = 1 AND "
1563  " title = :TITLE AND "
1564  " ( "
1565  " (:PROGRAMID1 <> '' AND "
1566  " :PROGRAMID2 = oldrecorded.programid) "
1567  " OR "
1568  " ( "
1569  " (:PROGRAMID3 = '' OR oldrecorded.programid = '' OR "
1570  " LEFT(:PROGRAMID4, LOCATE('/', :PROGRAMID5)) <> "
1571  " LEFT(oldrecorded.programid, "
1572  " LOCATE('/', oldrecorded.programid))) "
1573  " AND "
1574  " (((:DUPMETHOD1 & 0x02) = 0) OR (:SUBTITLE1 <> '' "
1575  " AND :SUBTITLE2 = oldrecorded.subtitle)) "
1576  " AND "
1577  " (((:DUPMETHOD2 & 0x04) = 0) OR (:DESCRIPTION1 <> '' "
1578  " AND :DESCRIPTION2 = oldrecorded.description)) "
1579  " AND "
1580  " (((:DUPMETHOD3 & 0x08) = 0) OR "
1581  " (:SUBTITLE3 <> '' AND "
1582  " (:SUBTITLE4 = oldrecorded.subtitle OR "
1583  " (oldrecorded.subtitle = '' AND "
1584  " :SUBTITLE5 = oldrecorded.description))) OR "
1585  " (:SUBTITLE6 = '' AND :DESCRIPTION3 <> '' AND "
1586  " (:DESCRIPTION4 = oldrecorded.subtitle OR "
1587  " (oldrecorded.subtitle = '' AND "
1588  " :DESCRIPTION5 = oldrecorded.description)))) "
1589  " ) "
1590  " )" );
1591  result.bindValue(":TITLE", m_title);
1592  result.bindValue(":SUBTITLE1", null_to_empty(m_subtitle));
1593  result.bindValue(":SUBTITLE2", null_to_empty(m_subtitle));
1594  result.bindValue(":SUBTITLE3", null_to_empty(m_subtitle));
1595  result.bindValue(":SUBTITLE4", null_to_empty(m_subtitle));
1596  result.bindValue(":SUBTITLE5", null_to_empty(m_subtitle));
1597  result.bindValue(":SUBTITLE6", null_to_empty(m_subtitle));
1598  result.bindValue(":DESCRIPTION1", null_to_empty(m_description));
1599  result.bindValue(":DESCRIPTION2", null_to_empty(m_description));
1600  result.bindValue(":DESCRIPTION3", null_to_empty(m_description));
1601  result.bindValue(":DESCRIPTION4", null_to_empty(m_description));
1602  result.bindValue(":DESCRIPTION5", null_to_empty(m_description));
1603  result.bindValue(":PROGRAMID1", null_to_empty(m_programId));
1604  result.bindValue(":PROGRAMID2", null_to_empty(m_programId));
1605  result.bindValue(":PROGRAMID3", null_to_empty(m_programId));
1606  result.bindValue(":PROGRAMID4", null_to_empty(m_programId));
1607  result.bindValue(":PROGRAMID5", null_to_empty(m_programId));
1608  result.bindValue(":DUPMETHOD1", dmeth);
1609  result.bindValue(":DUPMETHOD2", dmeth);
1610  result.bindValue(":DUPMETHOD3", dmeth);
1611 
1612  if (!result.exec())
1613  MythDB::DBError("forgetOldRecorded2", result);
1614  }
1615 
1616  // Remove any never records which aren't need anymore.
1617  result.prepare("DELETE FROM oldrecorded "
1618  "WHERE recstatus = :NEVER AND duplicate = 0");
1619  result.bindValue(":NEVER", RecStatus::NeverRecord);
1620 
1621  if (!result.exec())
1622  MythDB::DBError("forgetNeverHistory", result);
1623 
1624  // Handle matching entries in oldfind.
1625  if (m_findId)
1626  {
1627  result.prepare("DELETE FROM oldfind WHERE "
1628  "recordid = :RECORDID AND findid = :FINDID");
1629  result.bindValue(":RECORDID", erecid);
1630  result.bindValue(":FINDID", m_findId);
1631 
1632  if (!result.exec())
1633  MythDB::DBError("forgetFindHistory", result);
1634  }
1635 
1636  // The removal of an entry from oldrecorded may affect near-future
1637  // scheduling decisions, so recalculate
1638  ScheduledRecording::RescheduleCheck(*this, "ForgetHistory");
1639 }
1640 
1645 {
1646  MSqlQuery result(MSqlQuery::InitCon());
1647 
1648  result.prepare("UPDATE oldrecorded SET duplicate = 1 "
1649  "WHERE future = 0 AND duplicate = 0 "
1650  "AND title = :TITLE AND "
1651  "((programid = '' AND subtitle = :SUBTITLE"
1652  " AND description = :DESC) OR "
1653  " (programid <> '' AND programid = :PROGRAMID) OR "
1654  " (findid <> 0 AND findid = :FINDID))");
1655  result.bindValue(":TITLE", m_title);
1656  result.bindValue(":SUBTITLE", null_to_empty(m_subtitle));
1657  result.bindValue(":DESC", null_to_empty(m_description));
1658  result.bindValue(":PROGRAMID", null_to_empty(m_programId));
1659  result.bindValue(":FINDID", m_findId);
1660 
1661  if (!result.exec())
1662  MythDB::DBError("setDupHistory", result);
1663 
1664  ScheduledRecording::RescheduleCheck(*this, "SetHistory");
1665 }
1666 
1672 {
1673  str.replace("%RECID%", QString::number(getRecordID()));
1674  str.replace("%PARENTID%", QString::number(m_parentId));
1675  str.replace("%FINDID%", QString::number(m_findId));
1676  str.replace("%RECSTATUS%", QString::number(m_recStatus));
1677  str.replace("%RECTYPE%", QString::number(m_recType));
1678  str.replace("%REACTIVATE%", IsReactivated() ? "1" : "0");
1679  str.replace("%INPUTNAME%", GetInputName());
1680  str.replace("%CHANNUM%", GetChanNum());
1681 
1683 }
1684 
1688 uint RecordingInfo::GetRecgroupID(const QString& recGroup)
1689 {
1690  MSqlQuery query(MSqlQuery::InitCon());
1691 
1692  query.prepare("SELECT recgroupid FROM recgroups WHERE recgroup = :RECGROUP");
1693  query.bindValue(":RECGROUP", null_to_empty(recGroup));
1694 
1695  if (!query.exec())
1696  MythDB::DBError("RecGroup update", query);
1697 
1698  if (!query.next())
1699  return 0;
1700 
1701  return query.value(0).toUInt();
1702 }
1703 
1708 {
1709  MSqlQuery query(MSqlQuery::InitCon());
1710 
1711  query.prepare("SELECT recgroup FROM recgroups WHERE recgroupid = :RECGROUPID");
1712  query.bindValue(":RECGROUPID", recGroupID);
1713  if (!query.exec() || !query.next())
1714  {
1715  MythDB::DBError("GetRecgroupString()", query);
1716  return {};
1717  }
1718  return query.value(0).toString();
1719 }
1720 
1722 {
1723  if (!m_recordingFile)
1724  {
1726  if (m_recordedId > 0)
1727  {
1729  m_recordingFile->Load();
1730  }
1731  }
1732 }
1733 
1734 void RecordingInfo::SaveFilesize(uint64_t fsize)
1735 {
1736  if (!GetRecordingFile())
1738  GetRecordingFile()->m_fileSize = fsize;
1739  GetRecordingFile()->Save(); // Ideally this would be called just the once when all metadata is gathered
1740 
1742 
1743  ProgramInfo::SaveFilesize(fsize); // Temporary
1744 }
1745 
1746 void RecordingInfo::SetFilesize(uint64_t fsize)
1747 {
1748  if (!GetRecordingFile())
1750  GetRecordingFile()->m_fileSize = fsize;
1752 
1753  // Make sure the old storage location is updated for now
1754  ProgramInfo::SetFilesize(fsize);
1755 }
1756 
1757 uint64_t RecordingInfo::GetFilesize(void) const
1758 {
1760  return GetRecordingFile()->m_fileSize;
1761 
1762  // Temporary fallback to reading from old storage location
1763  return ProgramInfo::GetFilesize();
1764 }
1765 
1766 
1767 /* 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:742
RecordingInfo::GetRecgroupID
static uint GetRecgroupID(const QString &recGroup)
Temporary helper during transition from string to ID.
Definition: recordinginfo.cpp:1688
JOB_USERJOB3
@ JOB_USERJOB3
Definition: jobqueue.h:88
MSqlBindings
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:101
ProgramInfo::m_startTs
QDateTime m_startTs
Definition: programinfo.h:798
JOB_USERJOB4
@ JOB_USERJOB4
Definition: jobqueue.h:89
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:216
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:807
RecStatus::Type
Type
Definition: recordingstatus.h:16
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
RecordingInfo::InsertProgram
static bool InsertProgram(RecordingInfo *pg, const RecordingRule *rule)
Definition: recordinginfo.cpp:1088
RecordingInfo::m_future
bool m_future
Definition: recordinginfo.h:289
ProgramInfo::SaveFilesize
virtual void SaveFilesize(uint64_t fsize)
Sets recording file size in database, and sets "filesize" field.
Definition: programinfo.cpp:6314
RecordingRule::m_autoTranscode
bool m_autoTranscode
Definition: recordingrule.h:132
RecordingInfo::ApplyStarsChange
void ApplyStarsChange(float newstarsvalue)
Sets the stars value in the database.
Definition: recordinginfo.cpp:593
ProgramInfo::m_fileSize
uint64_t m_fileSize
Definition: programinfo.h:796
RecordingInfo::QueryRecordedIdForKey
static bool QueryRecordedIdForKey(int &recordedid, uint chanid, const QDateTime &recstartts)
Definition: recordinginfo.cpp:944
RecordingInfo::FinishedRecording
void FinishedRecording(bool allowReRecord)
If not a premature stop, adds program to history of recorded programs.
Definition: recordinginfo.cpp:1271
RecordingInfo::kReSearchTypeName
static const QRegularExpression kReSearchTypeName
Definition: recordinginfo.h:197
ProgramInfo::GetFilesize
virtual uint64_t GetFilesize(void) const
Definition: programinfo.cpp:6345
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:907
ProgramInfo::m_recEndTs
QDateTime m_recEndTs
Definition: programinfo.h:801
RecordingInfo::m_oldrecstatus
RecStatus::Type m_oldrecstatus
Definition: recordinginfo.h:287
ProgramInfo::m_catType
CategoryType m_catType
Definition: programinfo.h:794
ProgramInfo::m_inputId
uint32_t m_inputId
Definition: programinfo.h:815
ProgramInfo::m_title
QString m_title
Definition: programinfo.h:763
RecordingRule::m_autoCommFlag
bool m_autoCommFlag
Definition: recordingrule.h:131
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:829
ProgramInfo::GetHostname
QString GetHostname(void) const
Definition: programinfo.h:421
ProgramInfo::m_storageGroup
QString m_storageGroup
Definition: programinfo.h:789
ProgramInfo::GetInputName
QString GetInputName(void) const
Definition: programinfo.h:464
ProgramInfo::m_chanId
uint32_t m_chanId
Definition: programinfo.h:777
mythdb.h
ProgramInfo::m_dupIn
uint8_t m_dupIn
Definition: programinfo.h:828
RecordingRule::Save
bool Save(bool sendSig=true)
Definition: recordingrule.cpp:388
ProgramInfo::m_audioProperties
AudioPropsType m_audioProperties
Definition: programinfo.h:820
RecordingInfo::m_desiredRecEndTs
QDateTime m_desiredRecEndTs
Definition: recordinginfo.h:294
RecordingInfo::ApplyRecordStateChange
void ApplyRecordStateChange(RecordingType newstate, bool save=true)
Sets RecordingType of "record", creating "record" if it does not exist.
Definition: recordinginfo.cpp:573
ProgramInfo::m_recordId
uint32_t m_recordId
Definition: programinfo.h:811
RecStatus::NeverRecord
@ NeverRecord
Definition: recordingstatus.h:43
ProgramInfo::m_recStartTs
QDateTime m_recStartTs
Definition: programinfo.h:800
RecordingInfo::ApplyRecordRecID
void ApplyRecordRecID(void)
Sets recordid to match RecordingRule recordid.
Definition: recordinginfo.cpp:538
kDupCheckSubThenDesc
@ kDupCheckSubThenDesc
Definition: recordingtypes.h:69
ProgramInfo::m_description
QString m_description
Definition: programinfo.h:767
ProgramInfo::s_staticDataLock
static QMutex s_staticDataLock
Definition: programinfo.h:853
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:1757
RecordingInfo::ForgetHistory
void ForgetHistory(void)
Forget the recording of a program so it will be recorded again.
Definition: recordinginfo.cpp:1461
ProgramInfo::clone
virtual void clone(const ProgramInfo &other, bool ignore_non_serialized_data=false)
Copies important fields from other ProgramInfo.
Definition: programinfo.cpp:836
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:376
RecordingInfo::SetFilesize
void SetFilesize(uint64_t fsize) override
Definition: recordinginfo.cpp:1746
MSqlQuery::lastInsertId
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:912
JOB_COMMFLAG
@ JOB_COMMFLAG
Definition: jobqueue.h:81
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:1422
ProgramInfo::m_subtitleProperties
SubtitlePropsType m_subtitleProperties
Definition: programinfo.h:821
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:205
RecordingInfo::GetProgramRecordingStatus
RecordingType GetProgramRecordingStatus(void)
Returns the recording type for this RecordingInfo, creating "record" field if necessary.
Definition: recordinginfo.cpp:476
RecordingInfo::kReLeadingAnd
static const QRegularExpression kReLeadingAnd
Definition: recordinginfo.h:200
RecStatus::Unknown
@ Unknown
Definition: recordingstatus.h:32
RecordingRule
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:28
RecordingDupMethodType
RecordingDupMethodType
Definition: recordingtypes.h:62
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:608
ProgramInfo::m_recPriority
int32_t m_recPriority
Definition: programinfo.h:775
ProgramInfo::m_season
uint m_season
Definition: programinfo.h:768
RecordingFile
Holds information on a recording file and it's video and audio streams.
Definition: recordingfile.h:29
RecStatus::Recorded
@ Recorded
Definition: recordingstatus.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:39
ProgramInfo::GetScheduledEndTime
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:397
ProgramInfo::m_pathname
QString m_pathname
Definition: programinfo.h:786
RecordingInfo::UpdateRecordingEnd
void UpdateRecordingEnd(void)
Update information in the recorded table when the end-time of a recording is changed.
Definition: recordinginfo.cpp:1311
ProgramInfo::m_endTs
QDateTime m_endTs
Definition: programinfo.h:799
RecordingInfo::s_unknownTitle
static QString s_unknownTitle
Definition: recordinginfo.h:304
RecordingInfo::getRecordID
int getRecordID(void)
Returns a record id, creating "record" it if necessary.
Definition: recordinginfo.cpp:937
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
kDupsInAll
@ kDupsInAll
Definition: recordingtypes.h:50
ProgramInfo::GetRecordingStartTime
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:404
ProgramInfo::SendAddedEvent
void SendAddedEvent(void) const
Sends event out that the ProgramInfo should be added to lists.
Definition: programinfo.cpp:2761
RecordingInfo::m_mplexId
uint m_mplexId
Definition: recordinginfo.h:291
JOB_USERJOB2
@ JOB_USERJOB2
Definition: jobqueue.h:87
RecordingInfo::ApplyTranscoderProfileChange
void ApplyTranscoderProfileChange(const QString &profile) const
Sets the transcoder profile for a recording.
Definition: recordinginfo.cpp:846
ProgramInfo::m_sourceId
uint32_t m_sourceId
Definition: programinfo.h:814
AutoDeleteDeque::begin
iterator begin(void)
Definition: autodeletedeque.h:50
kDupsInRecorded
@ kDupsInRecorded
Definition: recordingtypes.h:48
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:767
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:492
RecordingDupInType
RecordingDupInType
Definition: recordingtypes.h:45
RecordingInfo::ApplyOriginalAirDateChange
void ApplyOriginalAirDateChange(QDate originalairdate)
Definition: recordinginfo.cpp:618
ProgramInfo::m_hostname
QString m_hostname
Definition: programinfo.h:788
ProgramInfo::m_chanName
QString m_chanName
Definition: programinfo.h:780
mythdate.h
ProgramInfo::SetRecordingEndTime
void SetRecordingEndTime(const QDateTime &dt)
Definition: programinfo.h:526
RecordingInfo::GetRecordingFile
RecordingFile * GetRecordingFile() const
Definition: recordinginfo.h:282
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:390
mythlogging.h
ProgramInfo::GetRecordingStatus
RecStatus::Type GetRecordingStatus(void) const
Definition: programinfo.h:447
RecordingInfo::m_savedrecstatus
RecStatus::Type m_savedrecstatus
Definition: recordinginfo.h:288
hardwareprofile.scan.profile
profile
Definition: scan.py:99
RecordingRule::m_autoUserJob4
bool m_autoUserJob4
Definition: recordingrule.h:136
ProgramInfo::m_recType
uint8_t m_recType
Definition: programinfo.h:827
ProgramInfo::m_category
QString m_category
Definition: programinfo.h:772
ProgramInfo::SetScheduledEndTime
void SetScheduledEndTime(const QDateTime &dt)
Definition: programinfo.h:524
RecStatus::PreviousRecording
@ PreviousRecording
Definition: recordingstatus.h:34
programinfoupdater.h
JOB_USERJOB1
@ JOB_USERJOB1
Definition: jobqueue.h:86
ProgramInfo::m_playGroup
QString m_playGroup
Definition: programinfo.h:784
RecordingInfo::m_desiredRecStartTs
QDateTime m_desiredRecStartTs
Definition: recordinginfo.h:293
RecordingInfo::SaveFilesize
void SaveFilesize(uint64_t fsize) override
Sets recording file size in database, and sets "filesize" field.
Definition: recordinginfo.cpp:1734
RecordingInfo::GetRecgroupString
static QString GetRecgroupString(uint recGroupID)
Temporary helper during transition from string to ID.
Definition: recordinginfo.cpp:1707
ProgramInfo::clear
virtual void clear(void)
Definition: programinfo.cpp:932
ProgramInfo::GetTitle
QString GetTitle(void) const
Definition: programinfo.h:361
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:540
ProgramInfo::m_seriesId
QString m_seriesId
Definition: programinfo.h:791
RecordingRule::m_autoUserJob2
bool m_autoUserJob2
Definition: recordingrule.h:134
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:227
kDupsInOldRecorded
@ kDupsInOldRecorded
Definition: recordingtypes.h:49
RecordingRule::m_autoExpire
bool m_autoExpire
Definition: recordingrule.h:126
RecordingInfo::GetAutoRunJobs
int GetAutoRunJobs(void) const
Returns a bitmap of which jobs are attached to this RecordingInfo.
Definition: recordinginfo.cpp:506
ProgramInfo::m_lastModified
QDateTime m_lastModified
Definition: programinfo.h:805
RecordingRule::m_recProfile
QString m_recProfile
Definition: recordingrule.h:120
ProgramInfo::m_episode
uint m_episode
Definition: programinfo.h:769
kDupCheckUnset
@ kDupCheckUnset
Definition: recordingtypes.h:64
RecordingInfo::QuickRecord
void QuickRecord(void)
Create a kSingleRecord if not already scheduled.
Definition: recordinginfo.cpp:918
ProgramInfo::SaveTotalDuration
void SaveTotalDuration(std::chrono::milliseconds duration)
Store the Total Duration at frame 0 in the recordedmarkup table.
Definition: programinfo.cpp:4315
ProgramInfo::m_recGroup
QString m_recGroup
Definition: programinfo.h:783
RecordingRule::m_type
RecordingType m_type
Definition: recordingrule.h:111
ProgramInfo::toString
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
Definition: programinfo.cpp:1934
ProgramInfoUpdater::insert
void insert(uint recordedid, PIAction action, uint64_t filesize=0ULL)
Definition: programinfoupdater.cpp:12
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:1331
RecordingInfo::StartedRecording
void StartedRecording(const QString &ext)
Inserts this RecordingInfo into the database as an existing recording.
Definition: recordinginfo.cpp:984
ProgramInfo::m_originalAirDate
QDate m_originalAirDate
Definition: programinfo.h:804
uint
unsigned int uint
Definition: compat.h:79
ProgramInfo::SetFilesize
virtual void SetFilesize(uint64_t sz)
Definition: programinfo.cpp:6304
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
ProgramInfo::LoadFromScheduler
static QStringList LoadFromScheduler(const QString &tmptable, int recordid)
Definition: programinfo.cpp:5507
RecordingInfo::LoadStatus
LoadStatus
Definition: recordinginfo.h:180
RecordingInfo::kNoProgram
@ kNoProgram
Definition: recordinginfo.h:181
ProgramInfo::CategoryType
CategoryType
Definition: programinfo.h:76
ProgramInfo::GetStorageGroup
QString GetStorageGroup(void) const
Definition: programinfo.h:422
ProgramInfo::m_recStatus
int8_t m_recStatus
Definition: programinfo.h:826
ScheduledRecording::ReschedulePlace
static void ReschedulePlace(const QString &why)
Definition: scheduledrecording.h:33
RecordingInfo::LoadRecordingFile
void LoadRecordingFile()
Definition: recordinginfo.cpp:1721
RecordingInfo::m_sgroupId
uint m_sgroupId
Definition: recordinginfo.h:292
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:290
AutoDeleteDeque< ProgramInfo * >
ProgramInfo::m_parentId
uint32_t m_parentId
Definition: programinfo.h:812
ProgramInfo::m_chanPlaybackFilters
QString m_chanPlaybackFilters
Definition: programinfo.h:781
recordinginfo.h
RecordingInfo::ApplyRecordRecPriorityChange
void ApplyRecordRecPriorityChange(int newrecpriority)
Sets recording priority of "record", creating "record" if it does not exist.
Definition: recordinginfo.cpp:643
ProgramInfo::GetChanID
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:372
kPIUpdateFileSize
@ kPIUpdateFileSize
Definition: programinfoupdater.h:22
RecordingRule::m_transcoder
int m_transcoder
Definition: recordingrule.h:130
RecordingRule::m_autoUserJob1
bool m_autoUserJob1
Definition: recordingrule.h:133
ProgramInfo::s_updater
static ProgramInfoUpdater * s_updater
Definition: programinfo.h:854
RecordingInfo::~RecordingInfo
~RecordingInfo() override
Destructor deletes "record" if it exists.
Definition: recordinginfo.cpp:462
RecordingInfo::SubstituteMatches
void SubstituteMatches(QString &str) override
Replace MATCH% vars in the specified string.
Definition: recordinginfo.cpp:1671
RecordingInfo::clone
virtual void clone(const RecordingInfo &other, bool ignore_non_serialized_data=false)
Copies important fields from other RecordingInfo.
Definition: recordinginfo.cpp:372
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
RecordingRule::m_recordID
int m_recordID
Unique Recording Rule ID.
Definition: recordingrule.h:70
ProgramInfo::m_inetRef
QString m_inetRef
Definition: programinfo.h:793
RecordingFile::m_recordingId
uint m_recordingId
Definition: recordingfile.h:38
ProgramInfo::m_subtitle
QString m_subtitle
Definition: programinfo.h:765
mythcorecontext.h
kOverrideRecord
@ kOverrideRecord
Definition: recordingtypes.h:29
RecordingInfo::InsertRecording
bool InsertRecording(const QString &ext, bool force_match=false)
Definition: recordinginfo.cpp:1042
RecordingInfo::m_record
class RecordingRule * m_record
Definition: recordinginfo.h:297
ProgramInfo::m_syndicatedEpisode
QString m_syndicatedEpisode
Definition: programinfo.h:771
kNotRecording
@ kNotRecording
Definition: recordingtypes.h:22
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:883
JOB_METADATA
@ JOB_METADATA
Definition: jobqueue.h:82
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
ProgramInfo::m_findId
uint32_t m_findId
Definition: programinfo.h:816
RecStatus::CurrentRecording
@ CurrentRecording
Definition: recordingstatus.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:5642
RecordingInfo::clear
void clear(void) override
Definition: recordinginfo.cpp:438
LOC
#define LOC
Definition: recordinginfo.cpp:22
kSingleRecord
@ kSingleRecord
Definition: recordingtypes.h:23
ProgramInfo::m_chanSign
QString m_chanSign
Definition: programinfo.h:779
RecordingInfo::AddHistory
void AddHistory(bool resched=true, bool forcedup=false, bool future=false)
Adds recording history, creating "record" it if necessary.
Definition: recordinginfo.cpp:1352
ProgramInfo::SubstituteMatches
virtual void SubstituteMatches(QString &str)
Subsitute MATCH% type variable names in the given string.
Definition: programinfo.cpp:5390
RecordingInfo::ApplyTranscoderProfileChangeById
void ApplyTranscoderProfileChangeById(int id)
Definition: recordinginfo.cpp:826
kUnknownProgramLength
static const uint kUnknownProgramLength
Definition: recordinginfo.cpp:35
ProgramInfo::m_programFlags
uint32_t m_programFlags
ProgramFlag.
Definition: programinfo.h:818
ProgramInfo::m_partTotal
uint16_t m_partTotal
Definition: programinfo.h:824
ProgramInfo::m_chanStr
QString m_chanStr
Definition: programinfo.h:778
ProgramInfo::SendUpdateEvent
void SendUpdateEvent(void) const
Sends event out that the ProgramInfo should be reloaded.
Definition: programinfo.cpp:2755
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:507
RecordingRule::MakeOverride
bool MakeOverride(void)
Definition: recordingrule.cpp:366
MSqlQuery::numRowsAffected
int numRowsAffected() const
Definition: mythdbcon.h:218
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:838
ProgramInfo::m_partNumber
uint16_t m_partNumber
Definition: programinfo.h:823
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:794
RecordingInfo::m_recordingFile
RecordingFile * m_recordingFile
Definition: recordinginfo.h:298
RecordingFile::Load
bool Load()
Definition: recordingfile.cpp:7
RecordingInfo::GetRecordingRule
RecordingRule * GetRecordingRule(void)
Returns the "record" field, creating it if necessary.
Definition: recordinginfo.cpp:928
RecordingInfo::ApplyRecordRecGroupChange
void ApplyRecordRecGroupChange(const QString &newrecgroup)
Sets the recording group, both in this RecordingInfo and in the database.
Definition: recordinginfo.cpp:655
ProgramInfo::m_programId
QString m_programId
Definition: programinfo.h:792
recordingrule.h
ProgramInfo::m_stars
float m_stars
Rating, range [0..1].
Definition: programinfo.h:803
RecordingRule::m_recPriority
int m_recPriority
Definition: recordingrule.h:107
RecordingFile::m_storageGroup
QString m_storageGroup
Definition: recordingfile.h:41
ProgramInfo::m_year
uint16_t m_year
Definition: programinfo.h:822
ProgramInfo::GetBasename
QString GetBasename(void) const
Definition: programinfo.h:344
RecordingRule::m_autoUserJob3
bool m_autoUserJob3
Definition: recordingrule.h:135
ProgramInfo::SetReactivated
void SetReactivated(bool reactivate)
Definition: programinfo.h:541
ProgramInfo::IsGeneric
bool IsGeneric(void) const
Definition: programinfo.cpp:1925
JOB_TRANSCODE
@ JOB_TRANSCODE
Definition: jobqueue.h:80
ProgramInfo::m_recordedId
uint m_recordedId
Definition: programinfo.h:831
ProgramInfo::CreateRecordBasename
QString CreateRecordBasename(const QString &ext) const
Returns a filename for a recording based on the recording channel and date.
Definition: programinfo.cpp:2392
ProgramInfo::m_videoProperties
VideoPropsType m_videoProperties
Definition: programinfo.h:819
RecordingType
RecordingType
Definition: recordingtypes.h:20
kDontRecord
@ kDontRecord
Definition: recordingtypes.h:30
RecordingRule::m_autoMetadataLookup
bool m_autoMetadataLookup
Definition: recordingrule.h:137
kDupsUnset
@ kDupsUnset
Definition: recordingtypes.h:47
RecordingFile::m_storageDeviceID
QString m_storageDeviceID
Definition: recordingfile.h:40
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:898
RecordingInfo::InsertFile
void InsertFile(void)
Definition: recordinginfo.cpp:1249
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:832
RecordingInfo::SetDupHistory
void SetDupHistory(void)
Set the duplicate flag in oldrecorded.
Definition: recordinginfo.cpp:1644