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
12 #include "libmythbase/mythdate.h"
13 #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 recordedid = :RECORDEDID");
689  query.bindValue(":RECGROUP", null_to_empty(newrecgroup));
690  query.bindValue(":RECGROUPID", newrecgroupid);
691  query.bindValue(":RECORDEDID", m_recordedId);
692 
693  if (!query.exec())
694  MythDB::DBError("RecGroup update", query);
695 
696  m_recGroup = newrecgroup; // Deprecate in favour of recgroupid
697  //recgroupid = newrecgroupid;
698 
699  SendUpdateEvent();
700 }
701 
703 {
704  MSqlQuery query(MSqlQuery::InitCon());
705 
706  QString newrecgroup;
707  if (newrecgroupid > 0)
708  {
709  newrecgroup = GetRecgroupString(newrecgroupid);
710 
711  query.prepare("UPDATE recorded"
712  " SET recgroup = :RECGROUP, "
713  " recgroupid = :RECGROUPID "
714  " WHERE chanid = :CHANID"
715  " AND starttime = :START ;");
716  query.bindValue(":RECGROUP", null_to_empty(newrecgroup));
717  query.bindValue(":RECGROUPID", newrecgroupid);
718  query.bindValue(":START", m_recStartTs);
719  query.bindValue(":CHANID", m_chanId);
720 
721  if (!query.exec())
722  MythDB::DBError("RecGroup update", query);
723 
724  m_recGroup = newrecgroup; // Deprecate in favour of recgroupid
725  //recgroupid = newrecgroupid;
726 
727  SendUpdateEvent();
728  }
729 
730  LOG(VB_GENERAL, LOG_NOTICE,
731  QString("ApplyRecordRecGroupChange: %1 to %2 (%3)")
732  .arg(m_recGroup, newrecgroup).arg(newrecgroupid));
733 }
734 
740 void RecordingInfo::ApplyRecordPlayGroupChange(const QString &newplaygroup)
741 {
742  MSqlQuery query(MSqlQuery::InitCon());
743 
744  query.prepare("UPDATE recorded"
745  " SET playgroup = :PLAYGROUP"
746  " WHERE chanid = :CHANID"
747  " AND starttime = :START ;");
748  query.bindValue(":PLAYGROUP", null_to_empty(newplaygroup));
749  query.bindValue(":START", m_recStartTs);
750  query.bindValue(":CHANID", m_chanId);
751 
752  if (!query.exec())
753  MythDB::DBError("PlayGroup update", query);
754 
755  m_playGroup = newplaygroup;
756 
757  SendUpdateEvent();
758 }
759 
765 void RecordingInfo::ApplyStorageGroupChange(const QString &newstoragegroup)
766 {
767  MSqlQuery query(MSqlQuery::InitCon());
768 
769  query.prepare("UPDATE recorded"
770  " SET storagegroup = :STORAGEGROUP"
771  " WHERE chanid = :CHANID"
772  " AND starttime = :START ;");
773  query.bindValue(":STORAGEGROUP", null_to_empty(newstoragegroup));
774  query.bindValue(":START", m_recStartTs);
775  query.bindValue(":CHANID", m_chanId);
776 
777  if (!query.exec())
778  MythDB::DBError("StorageGroup update", query);
779 
780  m_storageGroup = newstoragegroup;
781 
782  SendUpdateEvent();
783 }
784 
792 void RecordingInfo::ApplyRecordRecTitleChange(const QString &newTitle,
793  const QString &newSubtitle, const QString &newDescription)
794 {
795  MSqlQuery query(MSqlQuery::InitCon());
796  QString sql = "UPDATE recorded SET title = :TITLE, subtitle = :SUBTITLE ";
797  if (!newDescription.isNull())
798  sql += ", description = :DESCRIPTION ";
799  sql += " WHERE chanid = :CHANID AND starttime = :START ;";
800 
801  query.prepare(sql);
802  query.bindValue(":TITLE", newTitle);
803  query.bindValue(":SUBTITLE", null_to_empty(newSubtitle));
804  if (!newDescription.isNull())
805  query.bindValue(":DESCRIPTION", newDescription);
806  query.bindValue(":CHANID", m_chanId);
807  query.bindValue(":START", m_recStartTs);
808 
809  if (!query.exec())
810  MythDB::DBError("RecTitle update", query);
811 
812  m_title = newTitle;
813  m_subtitle = newSubtitle;
814  if (!newDescription.isNull())
815  m_description = newDescription;
816 
817  SendUpdateEvent();
818 }
819 
820 /* \fn RecordingInfo::ApplyTranscoderProfileChangeById(int id)
821  * \brief Sets the transcoder profile for a recording
822  * \param profileid is the 'id' field from recordingprofiles table.
823  */
825 {
826  MSqlQuery query(MSqlQuery::InitCon());
827 
828  query.prepare("UPDATE recorded "
829  "SET transcoder = :PROFILEID "
830  "WHERE chanid = :CHANID "
831  "AND starttime = :START");
832  query.bindValue(":PROFILEID", id);
833  query.bindValue(":CHANID", m_chanId);
834  query.bindValue(":START", m_recStartTs);
835 
836  if (!query.exec())
837  MythDB::DBError(LOC + "unable to update transcoder "
838  "in recorded table", query);
839 }
840 
845 {
846  if (profile == "Default") // use whatever is already in the transcoder
847  return;
848 
849  MSqlQuery query(MSqlQuery::InitCon());
850 
851  if (profile == "Autodetect")
852  {
853  query.prepare("UPDATE recorded "
854  "SET transcoder = 0 "
855  "WHERE chanid = :CHANID "
856  "AND starttime = :START");
857  query.bindValue(":CHANID", m_chanId);
858  query.bindValue(":START", m_recStartTs);
859 
860  if (!query.exec())
861  MythDB::DBError(LOC + "unable to update transcoder "
862  "in recorded table", query);
863  }
864  else
865  {
866  MSqlQuery pidquery(MSqlQuery::InitCon());
867  pidquery.prepare("SELECT r.id "
868  "FROM recordingprofiles r, profilegroups p "
869  "WHERE r.profilegroup = p.id "
870  "AND p.name = 'Transcoders' "
871  "AND r.name = :PROFILE ");
872  pidquery.bindValue(":PROFILE", profile);
873 
874  if (!pidquery.exec())
875  {
876  MythDB::DBError("ProgramInfo: unable to query transcoder "
877  "profile ID", query);
878  }
879  else if (pidquery.next())
880  {
881  query.prepare("UPDATE recorded "
882  "SET transcoder = :TRANSCODER "
883  "WHERE chanid = :CHANID "
884  "AND starttime = :START");
885  query.bindValue(":TRANSCODER", pidquery.value(0).toInt());
886  query.bindValue(":CHANID", m_chanId);
887  query.bindValue(":START", m_recStartTs);
888 
889  if (!query.exec())
890  MythDB::DBError(LOC + "unable to update transcoder "
891  "in recorded table", query);
892  }
893  else
894  {
895  LOG(VB_GENERAL, LOG_ERR,
896  "ProgramInfo: unable to query transcoder profile ID");
897  }
898  }
899 }
900 
906 {
910  AddHistory(true, true);
911 }
912 
917 {
919  if (curType == kNotRecording)
921 }
922 
927 {
929  return m_record;
930 }
931 
936 {
939  return m_recordId;
940 }
941 
943  uint chanid, const QDateTime& recstartts)
944 {
945  if (chanid < 1)
946  {
947  LOG(VB_RECORD, LOG_WARNING,
948  QString("QueryRecordedIdFromKey: Invalid chanid %1").arg(chanid));
949  return false;
950  }
951  if (!recstartts.isValid())
952  {
953  LOG(VB_RECORD, LOG_WARNING,
954  QString("QueryRecordedIdFromKey: Invalid start ts %1")
955  .arg(recstartts.toString()));
956  return false;
957  }
958 
959  MSqlQuery query(MSqlQuery::InitCon());
960  query.prepare(
961  "SELECT recordedid FROM recorded "
962  "WHERE chanid = :CHANID AND starttime = :RECSTARTTS");
963  query.bindValue(":CHANID", chanid);
964  query.bindValue(":RECSTARTTS", recstartts);
965  if (query.exec() && query.next())
966  {
967  recordedid = query.value(0).toUInt();
968  return true;
969  }
970 
971  return false;
972 }
973 
982 void RecordingInfo::StartedRecording(const QString& ext)
983 {
985 
986  if (!InsertRecording(ext))
987  return;
988 
989  LOG(VB_FILE, LOG_INFO, LOC + QString("StartedRecording: Recording to '%1'")
990  .arg(m_pathname));
991 
992 
993  MSqlQuery query(MSqlQuery::InitCon());
994 
995  query.prepare("DELETE FROM recordedseek WHERE chanid = :CHANID"
996  " AND starttime = :START;");
997  query.bindValue(":CHANID", m_chanId);
998  query.bindValue(":START", m_recStartTs);
999 
1000  if (!query.exec() || !query.isActive())
1001  MythDB::DBError("Clear seek info on record", query);
1002 
1003  query.prepare("DELETE FROM recordedmarkup WHERE chanid = :CHANID"
1004  " AND starttime = :START;");
1005  query.bindValue(":CHANID", m_chanId);
1006  query.bindValue(":START", m_recStartTs);
1007 
1008  if (!query.exec() || !query.isActive())
1009  MythDB::DBError("Clear markup on record", query);
1010 
1011  query.prepare("REPLACE INTO recordedcredits"
1012  " SELECT * FROM credits"
1013  " WHERE chanid = :CHANID AND starttime = :START;");
1014  query.bindValue(":CHANID", m_chanId);
1015  query.bindValue(":START", m_startTs);
1016  if (!query.exec() || !query.isActive())
1017  MythDB::DBError("Copy program credits on record", query);
1018 
1019  query.prepare("REPLACE INTO recordedprogram"
1020  " SELECT * from program"
1021  " WHERE chanid = :CHANID AND starttime = :START"
1022  " AND title = :TITLE;");
1023  query.bindValue(":CHANID", m_chanId);
1024  query.bindValue(":START", m_startTs);
1025  query.bindValue(":TITLE", m_title);
1026  if (!query.exec() || !query.isActive())
1027  MythDB::DBError("Copy program data on record", query);
1028 
1029  query.prepare("REPLACE INTO recordedrating"
1030  " SELECT * from programrating"
1031  " WHERE chanid = :CHANID AND starttime = :START;");
1032  query.bindValue(":CHANID", m_chanId);
1033  query.bindValue(":START", m_startTs);
1034  if (!query.exec() || !query.isActive())
1035  MythDB::DBError("Copy program ratings on record", query);
1036 
1037  InsertFile();
1038 }
1039 
1040 bool RecordingInfo::InsertRecording(const QString &ext, bool force_match)
1041 {
1042  QString dirname = m_pathname;
1043 
1044 #if 1
1045  if (!dirname.isEmpty())
1046  {
1047  LOG(VB_GENERAL, LOG_DEBUG, LOC +
1048  QString("InsertRecording: m_pathname was '%1'. "
1049  "This is usually blank.").arg(dirname));
1050  }
1051 #endif
1052 
1054 
1055  if (!m_record)
1056  {
1057  m_record = new RecordingRule();
1058  m_record->LoadByProgram(this);
1059  }
1060 
1061  int count = 0;
1062  while (!InsertProgram(this, m_record) && count < 50)
1063  {
1064  if (force_match)
1065  {
1066  LOG(VB_GENERAL, LOG_ERR, "Failed to insert new recording.");
1067  return false;
1068  }
1069 
1070  m_recStartTs = m_recStartTs.addSecs(1);
1072  ++count;
1073  }
1074 
1075  if (count >= 50)
1076  {
1077  LOG(VB_GENERAL, LOG_ERR, "Could not insert program");
1078  return false;
1079  }
1080 
1081  m_pathname = dirname + "/" + m_pathname;
1082 
1083  return true;
1084 }
1085 
1087  const RecordingRule *rule)
1088 {
1089  QString inputname = pg->GetInputName();
1090  int recgroupid = GetRecgroupID(pg->m_recGroup);
1091 
1092  MSqlQuery query(MSqlQuery::InitCon());
1093 
1094  if (!query.exec("LOCK TABLES recorded WRITE"))
1095  {
1096  MythDB::DBError("InsertProgram -- lock", query);
1097  return false;
1098  }
1099 
1100  query.prepare(
1101  "SELECT recordid "
1102  " FROM recorded "
1103  " WHERE chanid = :CHANID AND "
1104  " starttime = :STARTS");
1105  query.bindValue(":CHANID", pg->m_chanId);
1106  query.bindValue(":STARTS", pg->m_recStartTs);
1107 
1108  bool err = true;
1109  if (!query.exec())
1110  {
1111  MythDB::DBError("InsertProgram -- select", query);
1112  }
1113  else if (query.next())
1114  {
1115  LOG(VB_GENERAL, LOG_ERR,
1116  QString("RecordingInfo::InsertProgram(%1): ")
1117  .arg(pg->toString()) + "recording already exists...");
1118  }
1119  else
1120  {
1121  err = false;
1122  }
1123 
1124  if (err)
1125  {
1126  if (!query.exec("UNLOCK TABLES"))
1127  MythDB::DBError("InsertProgram -- unlock tables", query);
1128  return false;
1129  }
1130 
1131  query.prepare(
1132  "INSERT INTO recorded "
1133  " (chanid, starttime, endtime, title, "
1134  " subtitle, description, season, episode, "
1135  " hostname, category, recgroup, autoexpire, "
1136  " recordid, seriesid, programid, inetref, "
1137  " stars, previouslyshown, originalairdate, "
1138  " findid, transcoder, playgroup, recpriority, "
1139  " basename, progstart, progend, profile, "
1140  " duplicate, storagegroup, inputname, recgroupid) "
1141  "VALUES"
1142  " (:CHANID, :STARTS, :ENDS, :TITLE, "
1143  " :SUBTITLE, :DESC, :SEASON, :EPISODE, "
1144  " :HOSTNAME, :CATEGORY, :RECGROUP, :AUTOEXP, "
1145  " :RECORDID, :SERIESID, :PROGRAMID, :INETREF, "
1146  " :STARS, :REPEAT, :ORIGAIRDATE, "
1147  " :FINDID, :TRANSCODER, :PLAYGROUP, :RECPRIORITY, "
1148  " :BASENAME, :PROGSTART, :PROGEND, :PROFILE, "
1149  " 0, :STORGROUP, :INPUTNAME, :RECGROUPID) "
1150  );
1151 
1152  if (pg->m_recType == kOverrideRecord)
1153  query.bindValue(":RECORDID", pg->m_parentId);
1154  else
1155  query.bindValue(":RECORDID", pg->m_recordId);
1156 
1157  if (pg->m_originalAirDate.isValid())
1158  {
1159  query.bindValue(":ORIGAIRDATE", pg->m_originalAirDate);
1160  // If there is no originalairdate use "year"
1161  }
1162  else if (pg->m_year == pg->m_recStartTs.date().year())
1163  {
1164  query.bindValue(":ORIGAIRDATE", pg->m_recStartTs.date());
1165  }
1166  else if (pg->m_year >= 1895)
1167  {
1168  query.bindValue(":ORIGAIRDATE", QDate(pg->m_year,1,1));
1169  }
1170  else
1171  {
1172  query.bindValue(":ORIGAIRDATE", "0000-00-00");
1173  }
1174 
1175  query.bindValue(":CHANID", pg->m_chanId);
1176  query.bindValue(":STARTS", pg->m_recStartTs);
1177  query.bindValue(":ENDS", pg->m_recEndTs);
1178  query.bindValue(":TITLE", pg->m_title);
1179  query.bindValue(":SUBTITLE", null_to_empty(pg->m_subtitle));
1180  query.bindValue(":DESC", null_to_empty(pg->m_description));
1181  query.bindValue(":SEASON", pg->m_season);
1182  query.bindValue(":EPISODE", pg->m_episode);
1183  query.bindValue(":HOSTNAME", pg->m_hostname);
1184  query.bindValue(":CATEGORY", null_to_empty(pg->m_category));
1185  query.bindValue(":RECGROUP", null_to_empty(pg->m_recGroup));
1186  query.bindValue(":AUTOEXP", rule->m_autoExpire);
1187  query.bindValue(":SERIESID", null_to_empty(pg->m_seriesId));
1188  query.bindValue(":PROGRAMID", null_to_empty(pg->m_programId));
1189  query.bindValue(":INETREF", null_to_empty(pg->m_inetRef));
1190  query.bindValue(":FINDID", pg->m_findId);
1191  query.bindValue(":STARS", pg->m_stars);
1192  query.bindValue(":REPEAT", pg->IsRepeat());
1193  query.bindValue(":TRANSCODER", rule->m_transcoder);
1194  query.bindValue(":PLAYGROUP", pg->m_playGroup);
1195  query.bindValue(":RECPRIORITY", rule->m_recPriority);
1196  query.bindValue(":BASENAME", pg->m_pathname);
1197  query.bindValue(":STORGROUP", null_to_empty(pg->m_storageGroup));
1198  query.bindValue(":PROGSTART", pg->m_startTs);
1199  query.bindValue(":PROGEND", pg->m_endTs);
1200  query.bindValue(":PROFILE", null_to_empty(rule->m_recProfile));
1201  query.bindValue(":INPUTNAME", inputname);
1202  query.bindValue(":RECGROUPID", recgroupid);
1203 
1204  bool ok = query.exec() && (query.numRowsAffected() > 0);
1205  if (ok)
1206  {
1207  pg->SetRecordingID(query.lastInsertId().toUInt());
1208  }
1209  bool active = query.isActive();
1210 
1211  if (!query.exec("UNLOCK TABLES"))
1212  MythDB::DBError("InsertProgram -- unlock tables", query);
1213 
1214  if (!ok && !active)
1215  {
1216  MythDB::DBError("InsertProgram -- insert", query);
1217 
1218  }
1219  else if (pg->m_recordId > 0)
1220  {
1221  query.prepare("UPDATE channel SET last_record = NOW() "
1222  "WHERE chanid = :CHANID");
1223  query.bindValue(":CHANID", pg->GetChanID());
1224  if (!query.exec())
1225  MythDB::DBError("InsertProgram -- channel last_record", query);
1226 
1227  query.prepare("UPDATE record SET last_record = NOW() "
1228  "WHERE recordid = :RECORDID");
1229  query.bindValue(":RECORDID", pg->m_recordId);
1230  if (!query.exec())
1231  MythDB::DBError("InsertProgram -- record last_record", query);
1232 
1233  if (pg->m_recType == kOverrideRecord && pg->m_parentId > 0)
1234  {
1235  query.prepare("UPDATE record SET last_record = NOW() "
1236  "WHERE recordid = :PARENTID");
1237  query.bindValue(":PARENTID", pg->m_parentId);
1238  if (!query.exec())
1239  MythDB::DBError("InsertProgram -- record last_record override",
1240  query);
1241  }
1242  }
1243 
1244  return ok;
1245 }
1246 
1248 {
1249  // File
1250  if (!GetRecordingFile())
1252  RecordingFile *recFile = GetRecordingFile();
1253  recFile->m_fileName = GetBasename();
1254  recFile->m_storageDeviceID = GetHostname();
1255  recFile->m_storageGroup = GetStorageGroup();
1256  recFile->Save();
1257 
1258  SendAddedEvent();
1259 }
1260 
1269 void RecordingInfo::FinishedRecording(bool allowReRecord)
1270 {
1271  MSqlQuery query(MSqlQuery::InitCon());
1272  query.prepare("UPDATE recorded SET endtime = :ENDTIME, "
1273  " duplicate = :DUPLICATE "
1274  "WHERE chanid = :CHANID AND "
1275  " starttime = :STARTTIME ");
1276  query.bindValue(":ENDTIME", m_recEndTs);
1277  query.bindValue(":CHANID", m_chanId);
1278  query.bindValue(":STARTTIME", m_recStartTs);
1279  query.bindValue(":DUPLICATE", !allowReRecord);
1280 
1281  if (!query.exec())
1282  MythDB::DBError("FinishedRecording update", query);
1283 
1285  if (!allowReRecord)
1286  {
1288 
1289  qint64 starttime = m_recStartTs.toSecsSinceEpoch();
1290  qint64 endtime = m_recEndTs.toSecsSinceEpoch();
1291  SaveTotalDuration(std::chrono::seconds(endtime - starttime));
1292 
1293  QString msg = "Finished recording";
1294  QString msg_subtitle = m_subtitle.isEmpty() ? "" :
1295  QString(" \"%1\"").arg(m_subtitle);
1296  QString details = QString("%1%2: channel %3")
1297  .arg(m_title, msg_subtitle, QString::number(m_chanId));
1298 
1299  LOG(VB_GENERAL, LOG_INFO, QString("%1 %2").arg(msg, details));
1300  }
1301 
1302  SendUpdateEvent();
1303 }
1304 
1310 {
1311  MSqlQuery query(MSqlQuery::InitCon());
1312  query.prepare("UPDATE recorded SET endtime = :ENDTIME "
1313  "WHERE chanid = :CHANID AND "
1314  " starttime = :STARTTIME ");
1315  query.bindValue(":ENDTIME", m_recEndTs);
1316 
1317  query.bindValue(":CHANID", m_chanId);
1318  query.bindValue(":STARTTIME", m_recStartTs);
1319 
1320  if (!query.exec())
1321  MythDB::DBError("UpdateRecordingEnd update", query);
1322 
1323  SendUpdateEvent();
1324 }
1325 
1330 {
1331  MSqlQuery result(MSqlQuery::InitCon());
1332 
1333  result.prepare("UPDATE oldrecorded SET reactivate = 1 "
1334  "WHERE station = :STATION AND "
1335  " starttime = :STARTTIME AND "
1336  " title = :TITLE;");
1337  result.bindValue(":STARTTIME", m_startTs);
1338  result.bindValue(":TITLE", m_title);
1339  result.bindValue(":STATION", m_chanSign);
1340 
1341  if (!result.exec())
1342  MythDB::DBError("ReactivateRecording", result);
1343 
1345 }
1346 
1350 void RecordingInfo::AddHistory(bool resched, bool forcedup, bool future)
1351 {
1352  bool dup = (GetRecordingStatus() == RecStatus::Recorded || forcedup);
1355  LOG(VB_SCHEDULE, LOG_INFO, QString("AddHistory: %1/%2, %3, %4, %5/%6")
1356  .arg(int(rs)).arg(int(m_oldrecstatus)).arg(future).arg(dup)
1358  if (!future)
1360  if (dup)
1361  SetReactivated(false);
1362  uint erecid = m_parentId ? m_parentId : m_recordId;
1363 
1364  MSqlQuery result(MSqlQuery::InitCon());
1365 
1366  result.prepare("REPLACE INTO oldrecorded (chanid,starttime,"
1367  "endtime,title,subtitle,description,season,episode,"
1368  "category,seriesid,programid,inetref,findid,recordid,"
1369  "station,rectype,recstatus,duplicate,reactivate,generic,"
1370  "future) "
1371  "VALUES(:CHANID,:START,:END,:TITLE,:SUBTITLE,:DESC,:SEASON,"
1372  ":EPISODE,:CATEGORY,:SERIESID,:PROGRAMID,:INETREF,"
1373  ":FINDID,:RECORDID,:STATION,:RECTYPE,:RECSTATUS,:DUPLICATE,"
1374  ":REACTIVATE,:GENERIC,:FUTURE);");
1375  result.bindValue(":CHANID", m_chanId);
1376  result.bindValue(":START", m_startTs);
1377  result.bindValue(":END", m_endTs);
1378  result.bindValue(":TITLE", m_title);
1379  result.bindValue(":SUBTITLE", null_to_empty(m_subtitle));
1380  result.bindValue(":DESC", null_to_empty(m_description));
1381  result.bindValue(":SEASON", m_season);
1382  result.bindValue(":EPISODE", m_episode);
1383  result.bindValue(":CATEGORY", null_to_empty(m_category));
1384  result.bindValue(":SERIESID", null_to_empty(m_seriesId));
1385  result.bindValue(":PROGRAMID", null_to_empty(m_programId));
1386  result.bindValue(":INETREF", null_to_empty(m_inetRef));
1387  result.bindValue(":FINDID", m_findId);
1388  result.bindValue(":RECORDID", erecid);
1389  result.bindValue(":STATION", null_to_empty(m_chanSign));
1390  result.bindValue(":RECTYPE", m_recType);
1391  result.bindValue(":RECSTATUS", rs);
1392  result.bindValue(":DUPLICATE", dup);
1393  result.bindValue(":REACTIVATE", 0);
1394  result.bindValue(":GENERIC", IsGeneric());
1395  result.bindValue(":FUTURE", future);
1396 
1397  if (!result.exec())
1398  MythDB::DBError("addHistory", result);
1399 
1400  if (dup && m_findId)
1401  {
1402  result.prepare("REPLACE INTO oldfind (recordid, findid) "
1403  "VALUES(:RECORDID,:FINDID);");
1404  result.bindValue(":RECORDID", erecid);
1405  result.bindValue(":FINDID", m_findId);
1406 
1407  if (!result.exec())
1408  MythDB::DBError("addFindHistory", result);
1409  }
1410 
1411  // The adding of an entry to oldrecorded may affect near-future
1412  // scheduling decisions, so recalculate if told
1413  if (resched)
1414  ScheduledRecording::RescheduleCheck(*this, "AddHistory");
1415 }
1416 
1421 {
1422  uint erecid = m_parentId ? m_parentId : m_recordId;
1423 
1424  MSqlQuery result(MSqlQuery::InitCon());
1425 
1426  result.prepare("DELETE FROM oldrecorded WHERE title = :TITLE AND "
1427  "starttime = :START AND station = :STATION");
1428  result.bindValue(":TITLE", m_title);
1429  result.bindValue(":START", m_recStartTs);
1430  result.bindValue(":STATION", m_chanSign);
1431 
1432  if (!result.exec())
1433  MythDB::DBError("deleteHistory", result);
1434 
1435  if (/*m_duplicate &&*/ m_findId)
1436  {
1437  result.prepare("DELETE FROM oldfind WHERE "
1438  "recordid = :RECORDID AND findid = :FINDID");
1439  result.bindValue(":RECORDID", erecid);
1440  result.bindValue(":FINDID", m_findId);
1441 
1442  if (!result.exec())
1443  MythDB::DBError("deleteFindHistory", result);
1444  }
1445 
1446  // The removal of an entry from oldrecorded may affect near-future
1447  // scheduling decisions, so recalculate
1448  ScheduledRecording::RescheduleCheck(*this, "DeleteHistory");
1449 }
1450 
1460 {
1461  uint erecid = m_parentId ? m_parentId : m_recordId;
1462  uint din = m_dupIn;
1463  uint dmeth = m_dupMethod;
1464 
1465  if (din == kDupsUnset)
1466  din = kDupsInAll;
1467  if (dmeth == kDupCheckUnset)
1468  dmeth = kDupCheckSubThenDesc;
1469 
1470  MSqlQuery result(MSqlQuery::InitCon());
1471 
1472  // Handle this specific entry in recorded.
1473  result.prepare("UPDATE recorded SET duplicate = 0 "
1474  "WHERE chanid = :CHANID "
1475  "AND starttime = :STARTTIME "
1476  "AND title = :TITLE;");
1477  result.bindValue(":STARTTIME", m_recStartTs);
1478  result.bindValue(":TITLE", m_title);
1479  result.bindValue(":CHANID", m_chanId);
1480 
1481  if (!result.exec())
1482  MythDB::DBError("forgetRecorded1", result);
1483 
1484  // Handle other matching entries in recorded.
1485  if (din & kDupsInRecorded)
1486  {
1487  result.prepare(
1488  "UPDATE recorded SET duplicate = 0 "
1489  "WHERE duplicate = 1 AND "
1490  " title = :TITLE AND "
1491  " ( "
1492  " (:PROGRAMID1 <> '' AND "
1493  " :PROGRAMID2 = recorded.programid) "
1494  " OR "
1495  " ( "
1496  " (:PROGRAMID3 = '' OR recorded.programid = '' OR "
1497  " LEFT(:PROGRAMID4, LOCATE('/', :PROGRAMID5)) <> "
1498  " LEFT(recorded.programid, "
1499  " LOCATE('/', recorded.programid))) "
1500  " AND "
1501  " (((:DUPMETHOD1 & 0x02) = 0) OR (:SUBTITLE1 <> '' "
1502  " AND :SUBTITLE2 = recorded.subtitle)) "
1503  " AND "
1504  " (((:DUPMETHOD2 & 0x04) = 0) OR (:DESCRIPTION1 <> '' "
1505  " AND :DESCRIPTION2 = recorded.description)) "
1506  " AND "
1507  " (((:DUPMETHOD3 & 0x08) = 0) OR "
1508  " (:SUBTITLE3 <> '' AND "
1509  " (:SUBTITLE4 = recorded.subtitle OR "
1510  " (recorded.subtitle = '' AND "
1511  " :SUBTITLE5 = recorded.description))) OR "
1512  " (:SUBTITLE6 = '' AND :DESCRIPTION3 <> '' AND "
1513  " (:DESCRIPTION4 = recorded.subtitle OR "
1514  " (recorded.subtitle = '' AND "
1515  " :DESCRIPTION5 = recorded.description)))) "
1516  " ) "
1517  " )" );
1518  result.bindValue(":TITLE", m_title);
1519  result.bindValue(":SUBTITLE1", null_to_empty(m_subtitle));
1520  result.bindValue(":SUBTITLE2", null_to_empty(m_subtitle));
1521  result.bindValue(":SUBTITLE3", null_to_empty(m_subtitle));
1522  result.bindValue(":SUBTITLE4", null_to_empty(m_subtitle));
1523  result.bindValue(":SUBTITLE5", null_to_empty(m_subtitle));
1524  result.bindValue(":SUBTITLE6", null_to_empty(m_subtitle));
1525  result.bindValue(":DESCRIPTION1", null_to_empty(m_description));
1526  result.bindValue(":DESCRIPTION2", null_to_empty(m_description));
1527  result.bindValue(":DESCRIPTION3", null_to_empty(m_description));
1528  result.bindValue(":DESCRIPTION4", null_to_empty(m_description));
1529  result.bindValue(":DESCRIPTION5", null_to_empty(m_description));
1530  result.bindValue(":PROGRAMID1", null_to_empty(m_programId));
1531  result.bindValue(":PROGRAMID2", null_to_empty(m_programId));
1532  result.bindValue(":PROGRAMID3", null_to_empty(m_programId));
1533  result.bindValue(":PROGRAMID4", null_to_empty(m_programId));
1534  result.bindValue(":PROGRAMID5", null_to_empty(m_programId));
1535  result.bindValue(":DUPMETHOD1", dmeth);
1536  result.bindValue(":DUPMETHOD2", dmeth);
1537  result.bindValue(":DUPMETHOD3", dmeth);
1538 
1539  if (!result.exec())
1540  MythDB::DBError("forgetRecorded2", result);
1541  }
1542 
1543  // Handle this specific entry in oldrecorded.
1544  result.prepare("UPDATE oldrecorded SET duplicate = 0 "
1545  "WHERE station = :STATION "
1546  "AND starttime = :STARTTIME "
1547  "AND title = :TITLE;");
1548  result.bindValue(":STARTTIME", m_startTs);
1549  result.bindValue(":TITLE", m_title);
1550  result.bindValue(":STATION", m_chanSign);
1551 
1552  if (!result.exec())
1553  MythDB::DBError("forgetOldRecorded1", result);
1554 
1555  // Handle other matching entries in oldrecorded.
1556  if (din & kDupsInOldRecorded)
1557  {
1558  result.prepare(
1559  "UPDATE oldrecorded SET duplicate = 0 "
1560  "WHERE duplicate = 1 AND "
1561  " title = :TITLE AND "
1562  " ( "
1563  " (:PROGRAMID1 <> '' AND "
1564  " :PROGRAMID2 = oldrecorded.programid) "
1565  " OR "
1566  " ( "
1567  " (:PROGRAMID3 = '' OR oldrecorded.programid = '' OR "
1568  " LEFT(:PROGRAMID4, LOCATE('/', :PROGRAMID5)) <> "
1569  " LEFT(oldrecorded.programid, "
1570  " LOCATE('/', oldrecorded.programid))) "
1571  " AND "
1572  " (((:DUPMETHOD1 & 0x02) = 0) OR (:SUBTITLE1 <> '' "
1573  " AND :SUBTITLE2 = oldrecorded.subtitle)) "
1574  " AND "
1575  " (((:DUPMETHOD2 & 0x04) = 0) OR (:DESCRIPTION1 <> '' "
1576  " AND :DESCRIPTION2 = oldrecorded.description)) "
1577  " AND "
1578  " (((:DUPMETHOD3 & 0x08) = 0) OR "
1579  " (:SUBTITLE3 <> '' AND "
1580  " (:SUBTITLE4 = oldrecorded.subtitle OR "
1581  " (oldrecorded.subtitle = '' AND "
1582  " :SUBTITLE5 = oldrecorded.description))) OR "
1583  " (:SUBTITLE6 = '' AND :DESCRIPTION3 <> '' AND "
1584  " (:DESCRIPTION4 = oldrecorded.subtitle OR "
1585  " (oldrecorded.subtitle = '' AND "
1586  " :DESCRIPTION5 = oldrecorded.description)))) "
1587  " ) "
1588  " )" );
1589  result.bindValue(":TITLE", m_title);
1590  result.bindValue(":SUBTITLE1", null_to_empty(m_subtitle));
1591  result.bindValue(":SUBTITLE2", null_to_empty(m_subtitle));
1592  result.bindValue(":SUBTITLE3", null_to_empty(m_subtitle));
1593  result.bindValue(":SUBTITLE4", null_to_empty(m_subtitle));
1594  result.bindValue(":SUBTITLE5", null_to_empty(m_subtitle));
1595  result.bindValue(":SUBTITLE6", null_to_empty(m_subtitle));
1596  result.bindValue(":DESCRIPTION1", null_to_empty(m_description));
1597  result.bindValue(":DESCRIPTION2", null_to_empty(m_description));
1598  result.bindValue(":DESCRIPTION3", null_to_empty(m_description));
1599  result.bindValue(":DESCRIPTION4", null_to_empty(m_description));
1600  result.bindValue(":DESCRIPTION5", null_to_empty(m_description));
1601  result.bindValue(":PROGRAMID1", null_to_empty(m_programId));
1602  result.bindValue(":PROGRAMID2", null_to_empty(m_programId));
1603  result.bindValue(":PROGRAMID3", null_to_empty(m_programId));
1604  result.bindValue(":PROGRAMID4", null_to_empty(m_programId));
1605  result.bindValue(":PROGRAMID5", null_to_empty(m_programId));
1606  result.bindValue(":DUPMETHOD1", dmeth);
1607  result.bindValue(":DUPMETHOD2", dmeth);
1608  result.bindValue(":DUPMETHOD3", dmeth);
1609 
1610  if (!result.exec())
1611  MythDB::DBError("forgetOldRecorded2", result);
1612  }
1613 
1614  // Remove any never records which aren't need anymore.
1615  result.prepare("DELETE FROM oldrecorded "
1616  "WHERE recstatus = :NEVER AND duplicate = 0");
1617  result.bindValue(":NEVER", RecStatus::NeverRecord);
1618 
1619  if (!result.exec())
1620  MythDB::DBError("forgetNeverHistory", result);
1621 
1622  // Handle matching entries in oldfind.
1623  if (m_findId)
1624  {
1625  result.prepare("DELETE FROM oldfind WHERE "
1626  "recordid = :RECORDID AND findid = :FINDID");
1627  result.bindValue(":RECORDID", erecid);
1628  result.bindValue(":FINDID", m_findId);
1629 
1630  if (!result.exec())
1631  MythDB::DBError("forgetFindHistory", result);
1632  }
1633 
1634  // The removal of an entry from oldrecorded may affect near-future
1635  // scheduling decisions, so recalculate
1636  ScheduledRecording::RescheduleCheck(*this, "ForgetHistory");
1637 }
1638 
1643 {
1644  MSqlQuery result(MSqlQuery::InitCon());
1645 
1646  result.prepare("UPDATE oldrecorded SET duplicate = 1 "
1647  "WHERE future = 0 AND duplicate = 0 "
1648  "AND title = :TITLE AND "
1649  "((programid = '' AND subtitle = :SUBTITLE"
1650  " AND description = :DESC) OR "
1651  " (programid <> '' AND programid = :PROGRAMID) OR "
1652  " (findid <> 0 AND findid = :FINDID))");
1653  result.bindValue(":TITLE", m_title);
1654  result.bindValue(":SUBTITLE", null_to_empty(m_subtitle));
1655  result.bindValue(":DESC", null_to_empty(m_description));
1656  result.bindValue(":PROGRAMID", null_to_empty(m_programId));
1657  result.bindValue(":FINDID", m_findId);
1658 
1659  if (!result.exec())
1660  MythDB::DBError("setDupHistory", result);
1661 
1662  ScheduledRecording::RescheduleCheck(*this, "SetHistory");
1663 }
1664 
1670 {
1671  str.replace("%RECID%", QString::number(getRecordID()));
1672  str.replace("%PARENTID%", QString::number(m_parentId));
1673  str.replace("%FINDID%", QString::number(m_findId));
1674  str.replace("%RECSTATUS%", QString::number(m_recStatus));
1675  str.replace("%RECTYPE%", QString::number(m_recType));
1676  str.replace("%REACTIVATE%", IsReactivated() ? "1" : "0");
1677  str.replace("%INPUTNAME%", GetInputName());
1678  str.replace("%CHANNUM%", GetChanNum());
1679 
1681 }
1682 
1686 uint RecordingInfo::GetRecgroupID(const QString& recGroup)
1687 {
1688  MSqlQuery query(MSqlQuery::InitCon());
1689 
1690  query.prepare("SELECT recgroupid FROM recgroups WHERE recgroup = :RECGROUP");
1691  query.bindValue(":RECGROUP", null_to_empty(recGroup));
1692 
1693  if (!query.exec())
1694  MythDB::DBError("RecGroup update", query);
1695 
1696  if (!query.next())
1697  return 0;
1698 
1699  return query.value(0).toUInt();
1700 }
1701 
1706 {
1707  MSqlQuery query(MSqlQuery::InitCon());
1708 
1709  query.prepare("SELECT recgroup FROM recgroups WHERE recgroupid = :RECGROUPID");
1710  query.bindValue(":RECGROUPID", recGroupID);
1711  if (!query.exec() || !query.next())
1712  {
1713  MythDB::DBError("GetRecgroupString()", query);
1714  return {};
1715  }
1716  return query.value(0).toString();
1717 }
1718 
1720 {
1721  if (!m_recordingFile)
1722  {
1724  if (m_recordedId > 0)
1725  {
1727  m_recordingFile->Load();
1728  }
1729  }
1730 }
1731 
1732 void RecordingInfo::SaveFilesize(uint64_t fsize)
1733 {
1734  if (!GetRecordingFile())
1736  GetRecordingFile()->m_fileSize = fsize;
1737  GetRecordingFile()->Save(); // Ideally this would be called just the once when all metadata is gathered
1738 
1740 
1741  ProgramInfo::SaveFilesize(fsize); // Temporary
1742 }
1743 
1744 void RecordingInfo::SetFilesize(uint64_t fsize)
1745 {
1746  if (!GetRecordingFile())
1748  GetRecordingFile()->m_fileSize = fsize;
1750 
1751  // Make sure the old storage location is updated for now
1752  ProgramInfo::SetFilesize(fsize);
1753 }
1754 
1755 uint64_t RecordingInfo::GetFilesize(void) const
1756 {
1758  return GetRecordingFile()->m_fileSize;
1759 
1760  // Temporary fallback to reading from old storage location
1761  return ProgramInfo::GetFilesize();
1762 }
1763 
1764 
1765 /* 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:740
RecordingInfo::GetRecgroupID
static uint GetRecgroupID(const QString &recGroup)
Temporary helper during transition from string to ID.
Definition: recordinginfo.cpp:1686
JOB_USERJOB3
@ JOB_USERJOB3
Definition: jobqueue.h:86
MSqlBindings
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:100
ProgramInfo::m_startTs
QDateTime m_startTs
Definition: programinfo.h:798
JOB_USERJOB4
@ JOB_USERJOB4
Definition: jobqueue.h:87
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:215
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:813
RecStatus::Type
Type
Definition: recordingstatus.h:15
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:127
RecordingInfo::InsertProgram
static bool InsertProgram(RecordingInfo *pg, const RecordingRule *rule)
Definition: recordinginfo.cpp:1086
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:6394
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:942
RecordingInfo::FinishedRecording
void FinishedRecording(bool allowReRecord)
If not a premature stop, adds program to history of recorded programs.
Definition: recordinginfo.cpp:1269
RecordingInfo::kReSearchTypeName
static const QRegularExpression kReSearchTypeName
Definition: recordinginfo.h:197
ProgramInfo::GetFilesize
virtual uint64_t GetFilesize(void) const
Definition: programinfo.cpp:6425
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:905
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:42
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:1755
RecordingInfo::ForgetHistory
void ForgetHistory(void)
Forget the recording of a program so it will be recorded again.
Definition: recordinginfo.cpp:1459
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:1744
MSqlQuery::lastInsertId
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:936
JOB_COMMFLAG
@ JOB_COMMFLAG
Definition: jobqueue.h:79
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:1420
ProgramInfo::m_subtitleProperties
SubtitlePropsType m_subtitleProperties
Definition: programinfo.h:821
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:204
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:31
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:619
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:28
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:1309
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:935
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:2753
RecordingInfo::m_mplexId
uint m_mplexId
Definition: recordinginfo.h:291
JOB_USERJOB2
@ JOB_USERJOB2
Definition: jobqueue.h:85
RecordingInfo::ApplyTranscoderProfileChange
void ApplyTranscoderProfileChange(const QString &profile) const
Sets the transcoder profile for a recording.
Definition: recordinginfo.cpp:844
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:765
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:129
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:97
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:33
programinfoupdater.h
JOB_USERJOB1
@ JOB_USERJOB1
Definition: jobqueue.h:84
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:1732
RecordingInfo::GetRecgroupString
static QString GetRecgroupString(uint recGroupID)
Temporary helper during transition from string to ID.
Definition: recordinginfo.cpp:1705
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:551
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:226
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:916
ProgramInfo::SaveTotalDuration
void SaveTotalDuration(std::chrono::milliseconds duration)
Store the Total Duration at frame 0 in the recordedmarkup table.
Definition: programinfo.cpp:4384
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:1329
RecordingInfo::StartedRecording
void StartedRecording(const QString &ext)
Inserts this RecordingInfo into the database as an existing recording.
Definition: recordinginfo.cpp:982
ProgramInfo::m_originalAirDate
QDate m_originalAirDate
Definition: programinfo.h:804
uint
unsigned int uint
Definition: compat.h:81
ProgramInfo::SetFilesize
virtual void SetFilesize(uint64_t sz)
Definition: programinfo.cpp:6384
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:5587
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:1719
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:1669
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:1040
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:889
JOB_METADATA
@ JOB_METADATA
Definition: jobqueue.h:80
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:34
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:5722
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:1350
ProgramInfo::SubstituteMatches
virtual void SubstituteMatches(QString &str)
Subsitute MATCH% type variable names in the given string.
Definition: programinfo.cpp:5470
RecordingInfo::ApplyTranscoderProfileChangeById
void ApplyTranscoderProfileChangeById(int id)
Definition: recordinginfo.cpp:824
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:2747
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:217
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:792
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:926
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:78
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_recordedId
uint m_recordedId
Definition: programinfo.h:831
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:1247
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:838
RecordingInfo::SetDupHistory
void SetDupHistory(void)
Set the duplicate flag in oldrecorded.
Definition: recordinginfo.cpp:1642