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