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