MythTV  master
livetvchain.cpp
Go to the documentation of this file.
1 #include "libmyth/mythcontext.h"
2 #include "libmythbase/mythdb.h"
6 
7 #include "livetvchain.h"
8 #include "cardutil.h"
9 
10 #define LOC QString("LiveTVChain(%1): ").arg(m_id)
11 
12 static inline void clear(LiveTVChainEntry &entry)
13 {
14  entry.chanid = 0;
15  entry.starttime.setSecsSinceEpoch(0);
16  entry.endtime = QDateTime();
17  entry.discontinuity = true;
18  entry.hostprefix = QString();
19  entry.inputtype = QString();
20  entry.channum = QString();
21  entry.inputname = QString();
22 }
23 
28 {
30  LOG(VB_GENERAL, LOG_DEBUG, LOC + "ctor");
31 }
32 
34 {
35  LOG(VB_GENERAL, LOG_DEBUG, LOC + "dtor");
36 }
37 
38 QString LiveTVChain::InitializeNewChain(const QString &seed)
39 {
40  QDateTime curdt = MythDate::current();
41  m_id = QString("live-%1-%2").arg(seed, curdt.toString(Qt::ISODate));
42  return m_id;
43 }
44 
45 void LiveTVChain::SetHostPrefix(const QString &prefix)
46 {
48 }
49 
50 void LiveTVChain::SetInputType(const QString &type)
51 {
52  m_inputType = type;
53 }
54 
55 void LiveTVChain::LoadFromExistingChain(const QString &id)
56 {
57  m_id = id;
58  ReloadAll();
59 }
60 
61 void LiveTVChain::AppendNewProgram(ProgramInfo *pginfo, const QString& channum,
62  const QString& inputname, bool discont)
63 {
64  QMutexLocker lock(&m_lock);
65 
66  LiveTVChainEntry newent;
67  newent.chanid = pginfo->GetChanID();
68  newent.starttime = pginfo->GetRecordingStartTime();
69  newent.endtime = pginfo->GetRecordingEndTime();
70  newent.discontinuity = discont;
71  newent.hostprefix = m_hostPrefix;
72  newent.inputtype = m_inputType;
73  newent.channum = channum;
74  newent.inputname = inputname;
75 
76  m_chain.append(newent);
77 
79  query.prepare("INSERT INTO tvchain (chanid, starttime, endtime, chainid,"
80  " chainpos, discontinuity, watching, hostprefix, cardtype, "
81  " channame, input) "
82  "VALUES(:CHANID, :START, :END, :CHAINID, :CHAINPOS, "
83  " :DISCONT, :WATCHING, :PREFIX, :INPUTTYPE, :CHANNAME, "
84  " :INPUT );");
85  query.bindValue(":CHANID", pginfo->GetChanID());
86  query.bindValue(":START", pginfo->GetRecordingStartTime());
87  query.bindValue(":END", pginfo->GetRecordingEndTime());
88  query.bindValueNoNull(":CHAINID", m_id);
89  query.bindValue(":CHAINPOS", m_maxPos);
90  query.bindValue(":DISCONT", discont);
91  query.bindValue(":WATCHING", 0);
92  query.bindValue(":PREFIX", m_hostPrefix);
93  query.bindValue(":INPUTTYPE", m_inputType);
94  query.bindValue(":CHANNAME", channum);
95  query.bindValue(":INPUT", inputname);
96 
97  if (!query.exec() || !query.isActive())
98  MythDB::DBError("Chain: AppendNewProgram", query);
99  else
100  {
101  LOG(VB_RECORD, LOG_INFO, QString("Chain: Appended@%3 '%1_%2'")
102  .arg(newent.chanid)
104  .arg(m_maxPos));
105  }
106 
107  m_maxPos++;
108  BroadcastUpdate();
109 }
110 
112 {
113  QMutexLocker lock(&m_lock);
114 
115  MSqlQuery query(MSqlQuery::InitCon());
116  query.prepare("UPDATE tvchain SET endtime = :END "
117  "WHERE chanid = :CHANID AND starttime = :START ;");
118  query.bindValue(":END", pginfo->GetRecordingEndTime());
119  query.bindValue(":CHANID", pginfo->GetChanID());
120  query.bindValue(":START", pginfo->GetRecordingStartTime());
121 
122  if (!query.exec() || !query.isActive())
123  MythDB::DBError("Chain: FinishedRecording", query);
124  else
125  {
126  LOG(VB_RECORD, LOG_INFO,
127  QString("Chain: Updated endtime for '%1_%2' to %3")
128  .arg(QString::number(pginfo->GetChanID()),
131  }
132 
133  QList<LiveTVChainEntry>::iterator it;
134  for (it = m_chain.begin(); it != m_chain.end(); ++it)
135  {
136  if ((*it).chanid == pginfo->GetChanID() &&
137  (*it).starttime == pginfo->GetRecordingStartTime())
138  {
139  (*it).endtime = pginfo->GetRecordingEndTime();
140  }
141  }
142  BroadcastUpdate();
143 }
144 
146 {
147  QMutexLocker lock(&m_lock);
148 
149  for (auto it = m_chain.begin(); it != m_chain.end(); ++it)
150  {
151  if ((*it).chanid == pginfo->GetChanID() &&
152  (*it).starttime == pginfo->GetRecordingStartTime())
153  {
154  auto del = it;
155  ++it;
156 
157  MSqlQuery query(MSqlQuery::InitCon());
158  if (it != m_chain.end())
159  {
160  (*it).discontinuity = true;
161  query.prepare("UPDATE tvchain SET discontinuity = :DISCONT "
162  "WHERE chanid = :CHANID AND starttime = :START "
163  "AND chainid = :CHAINID ;");
164  query.bindValue(":CHANID", (*it).chanid);
165  query.bindValue(":START", (*it).starttime);
166  query.bindValue(":CHAINID", m_id);
167  query.bindValue(":DISCONT", (*it).discontinuity);
168  if (!query.exec())
169  MythDB::DBError("LiveTVChain::DeleteProgram -- "
170  "discontinuity", query);
171  }
172 
173  query.prepare("DELETE FROM tvchain WHERE chanid = :CHANID "
174  "AND starttime = :START AND chainid = :CHAINID ;");
175  query.bindValue(":CHANID", (*del).chanid);
176  query.bindValue(":START", (*del).starttime);
177  query.bindValue(":CHAINID", m_id);
178  if (!query.exec())
179  MythDB::DBError("LiveTVChain::DeleteProgram -- delete", query);
180 
181  m_chain.erase(del);
182 
183  BroadcastUpdate();
184  break;
185  }
186  }
187 }
188 
190 {
191  QString message = QString("LIVETV_CHAIN UPDATE %1").arg(m_id);
192  MythEvent me(message, entriesToStringList());
193  gCoreContext->dispatch(me);
194 }
195 
197 {
198  QMutexLocker lock(&m_lock);
199 
200  m_chain.clear();
201 
202  MSqlQuery query(MSqlQuery::InitCon());
203  query.prepare("DELETE FROM tvchain WHERE chainid = :CHAINID ;");
204  query.bindValue(":CHAINID", m_id);
205 
206  if (!query.exec())
207  MythDB::DBError("LiveTVChain::DestroyChain", query);
208 }
209 
210 void LiveTVChain::ReloadAll(const QStringList &data)
211 {
212  QMutexLocker lock(&m_lock);
213 
214  int prev_size = m_chain.size();
215  if (data.isEmpty() || !entriesFromStringList(data))
216  {
217  m_chain.clear();
218 
219  MSqlQuery query(MSqlQuery::InitCon());
220  query.prepare("SELECT chanid, starttime, endtime, discontinuity, "
221  "chainpos, hostprefix, cardtype, channame, input "
222  "FROM tvchain "
223  "WHERE chainid = :CHAINID ORDER BY chainpos;");
224  query.bindValue(":CHAINID", m_id);
225 
226  if (query.exec() && query.isActive() && query.size() > 0)
227  {
228  while (query.next())
229  {
230  LiveTVChainEntry entry;
231  entry.chanid = query.value(0).toUInt();
232  entry.starttime =
233  MythDate::as_utc(query.value(1).toDateTime());
234  entry.endtime =
235  MythDate::as_utc(query.value(2).toDateTime());
236  entry.discontinuity = query.value(3).toBool();
237  entry.hostprefix = query.value(5).toString();
238  entry.inputtype = query.value(6).toString();
239  entry.channum = query.value(7).toString();
240  entry.inputname = query.value(8).toString();
241 
242  m_maxPos = query.value(4).toInt() + 1;
243 
244  m_chain.append(entry);
245  }
246  }
247  }
248 
250  if (m_curPos < 0)
251  m_curPos = 0;
252 
253  if (m_switchId >= 0)
255 
256  if (prev_size > m_chain.size())
257  {
258  LOG(VB_PLAYBACK, LOG_INFO, LOC +
259  QString("ReloadAll(): Removed %1 recording(s)")
260  .arg(prev_size - m_chain.size()));
261  LOG(VB_PLAYBACK, LOG_INFO, LOC + toString());
262  }
263  else if (prev_size < m_chain.size())
264  {
265  LOG(VB_PLAYBACK, LOG_INFO, LOC +
266  QString("ReloadAll(): Added %1 recording(s)")
267  .arg(m_chain.size() - prev_size));
268  LOG(VB_PLAYBACK, LOG_INFO, LOC + toString());
269  }
270 }
271 
272 void LiveTVChain::GetEntryAt(int at, LiveTVChainEntry &entry) const
273 {
274  QMutexLocker lock(&m_lock);
275 
276  int size = m_chain.count();
277  int new_at = (size && (at < 0 || at >= size)) ? size - 1 : at;
278 
279  if (size && new_at >= 0 && new_at < size)
280  entry = m_chain[new_at];
281  else
282  {
283  LOG(VB_GENERAL, LOG_ERR, QString("GetEntryAt(%1) failed.").arg(at));
284  if (at == -1)
285  {
286  LOG(VB_GENERAL, LOG_ERR, "It appears that your backend may "
287  "be misconfigured. Check your backend logs to determine "
288  "whether your inputs, lineups, channels, or storage "
289  "configuration are reporting errors. This issue is commonly "
290  "caused by failing to complete all setup steps properly. You "
291  "may wish to review the documentation for mythtv-setup.");
292  }
293  clear(entry);
294  }
295 }
296 
298 {
299  auto *pginfo = new ProgramInfo(entry.chanid, entry.starttime);
300 
301  if (pginfo->GetChanID())
302  {
303  pginfo->SetPathname(entry.hostprefix + pginfo->GetBasename());
304  return pginfo;
305  }
306 
307  LOG(VB_GENERAL, LOG_ERR,
308  QString("EntryToProgram(%1@%2) failed to get pginfo")
309  .arg(entry.chanid).arg(entry.starttime.toString(Qt::ISODate)));
310  delete pginfo;
311  return nullptr;
312 }
313 
322 {
323  LiveTVChainEntry entry;
324  GetEntryAt(at, entry);
325 
326  return EntryToProgram(entry);
327 }
328 
332 int LiveTVChain::ProgramIsAt(uint chanid, const QDateTime &starttime) const
333 {
334  QMutexLocker lock(&m_lock);
335 
336  int count = 0;
337  QList<LiveTVChainEntry>::const_iterator it;
338  for (it = m_chain.begin(); it != m_chain.end(); ++it, ++count)
339  {
340  if ((*it).chanid == chanid &&
341  (*it).starttime == starttime)
342  {
343  return count;
344  }
345  }
346 
347  return -1;
348 }
349 
353 int LiveTVChain::ProgramIsAt(const ProgramInfo &pginfo) const
354 {
355  return ProgramIsAt(pginfo.GetChanID(), pginfo.GetRecordingStartTime());
356 }
357 
361 std::chrono::seconds LiveTVChain::GetLengthAtCurPos(void)
362 {
363  return GetLengthAtPos(m_curPos);
364 }
365 
369 std::chrono::seconds LiveTVChain::GetLengthAtPos(int pos)
370 {
371  QMutexLocker lock(&m_lock);
372 
373  LiveTVChainEntry entry = m_chain[pos];
374  if (pos == (m_chain.count() - 1))
375  {
376  // We're on live program, it hasn't ended. Use current time as end time
377  return MythDate::secsInPast(entry.starttime);
378  }
379 
380  // use begin time from the following program, as it's certain to be right
381  // the end time is set as per the EPG, but should playback be interrupted
382  // such as a channel change, the end value wouldn't have reflected the actual
383  // duration of the program
384  LiveTVChainEntry nextentry = m_chain[pos+1];
385  return std::chrono::seconds(entry.starttime.secsTo(nextentry.starttime));
386 }
387 
388 int LiveTVChain::TotalSize(void) const
389 {
390  return m_chain.count();
391 }
392 
394 {
395  QMutexLocker lock(&m_lock);
396 
397  m_curChanId = pginfo.GetChanID();
399 
400  m_curPos = ProgramIsAt(pginfo);
401  if (m_curPos < 0)
402  m_curPos = 0;
403  m_switchId = -1;
404 }
405 
406 bool LiveTVChain::HasNext(void) const
407 {
408  return (m_chain.count() - 1 > m_curPos);
409 }
410 
412 {
413  QMutexLocker lock(&m_lock);
414 
415  m_switchId = -1;
416  m_jumpPos = std::chrono::seconds::max();
417 }
418 
429 ProgramInfo *LiveTVChain::GetSwitchProgram(bool &discont, bool &newtype,
430  int &newid)
431 {
432  ReloadAll();
433  QMutexLocker lock(&m_lock);
434 
435  int id = m_switchId;
437  discont, newtype);
438  if (pginfo)
439  {
440  newid = id;
441  }
442  ClearSwitch();
443 
444  return pginfo;
445 }
446 
447 ProgramInfo *LiveTVChain::DoGetNextProgram(bool up, int curpos, int &newid,
448  bool &discont, bool &newtype)
449 {
450  LiveTVChainEntry oldentry;
451  LiveTVChainEntry entry;
452  ProgramInfo *pginfo = nullptr;
453 
454  GetEntryAt(curpos, oldentry);
455 
456  if (newid < 0 || curpos == newid)
457  {
458  // already on the program
459  entry = oldentry;
460  pginfo = EntryToProgram(entry);
461  newid = curpos;
462  }
463  else
464  {
465  // try to find recordings during first pass
466  // we'll skip dummy and empty recordings
467  while (!pginfo && newid < m_chain.count() && newid >= 0)
468  {
469  GetEntryAt(newid, entry);
470 
471  bool at_last_entry =
472  ((newid > curpos) &&
473  (newid == m_chain.count()-1)) ||
474  ((newid <= curpos) && (newid == 0));
475 
476  // Skip dummy recordings, if possible.
477  if (at_last_entry || (entry.inputtype != "DUMMY"))
478  pginfo = EntryToProgram(entry);
479 
480  // Skip empty recordings, if possible
481  if (pginfo && (0 == pginfo->GetFilesize()) &&
482  newid < m_chain.count()-1)
483  {
484  LOG(VB_GENERAL, LOG_WARNING,
485  QString("Skipping empty program %1")
486  .arg(pginfo->MakeUniqueKey()));
487  delete pginfo;
488  pginfo = nullptr;
489  }
490 
491  if (!pginfo)
492  {
493  newid += up ? 1 : -1;
494  }
495  }
496 
497  if (!pginfo)
498  {
499  // didn't find in first pass, now get back to the next good one
500  // as this is the one we will use
501  do
502  {
503  newid += up ? -1 : 1;
504 
505  GetEntryAt(newid, entry);
506 
507  bool at_last_entry =
508  ((newid > curpos) &&
509  (newid == m_chain.count()-1)) ||
510  ((newid <= curpos) && (newid == 0));
511 
512  // Skip dummy recordings, if possible.
513  if (at_last_entry || (entry.inputtype != "DUMMY"))
514  pginfo = EntryToProgram(entry);
515 
516  // Skip empty recordings, if possible
517  if (pginfo && (0 == pginfo->GetFilesize()) &&
518  newid < m_chain.count()-1)
519  {
520  LOG(VB_GENERAL, LOG_WARNING,
521  QString("Skipping empty program %1")
522  .arg(pginfo->MakeUniqueKey()));
523  delete pginfo;
524  pginfo = nullptr;
525  }
526  }
527  while (!pginfo && newid < m_chain.count() && newid >= 0);
528 
529  if (!pginfo)
530  {
531  // still not found so abort (will never happen once playback has started)
532  return nullptr;
533  }
534  }
535  }
536 
537  discont = true;
538  if (curpos == newid - 1)
539  discont = entry.discontinuity;
540 
541  newtype = (oldentry.inputtype != entry.inputtype);
542 
543  // Some inputs can change their streams dramatically on a channel change...
544  if (discont)
546 
547  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
548  QString("DoGetNextProgram: %1 -> ").arg(newid) + pginfo->toString());
549 
550  return pginfo;
551 }
552 
558 {
559  QMutexLocker lock(&m_lock);
560 
561  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("SwitchTo(%1)").arg(num));
562 
563  int size = m_chain.count();
564  if ((num < 0) || (num >= size))
565  num = size - 1;
566 
567  if (m_curPos != num)
568  {
569  m_switchId = num;
571  }
572  else
573  LOG(VB_GENERAL, LOG_ERR, LOC + "SwitchTo() not switching to current");
574 
575  if (VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_DEBUG))
576  {
578  GetEntryAt(num, e);
579  QString msg = QString("%1_%2")
580  .arg(e.chanid)
582  LOG(VB_PLAYBACK, LOG_DEBUG,
583  LOC + QString("Entry@%1: '%2')").arg(num).arg(msg));
584  }
585 }
586 
593 {
594 #if 0
595  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "SwitchToNext("<<(up?"up":"down")<<")");
596 #endif
597  if (up && HasNext())
598  SwitchTo(m_curPos + 1);
599  else if (!up && HasPrev())
600  SwitchTo(m_curPos - 1);
601 }
602 
603 void LiveTVChain::JumpTo(int num, std::chrono::seconds pos)
604 {
605  m_jumpPos = pos;
606  SwitchTo(num);
607 }
608 
617 void LiveTVChain::JumpToNext(bool up, std::chrono::seconds pos)
618 {
619  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("JumpToNext: %1 -> %2").arg(up).arg(pos.count()));
620  if (pos >= 0s)
621  {
622  m_jumpPos = pos;
623  SwitchToNext(up);
624  }
625  else
626  {
627  QMutexLocker lock(&m_lock);
628 
629  int current = m_curPos;
630  int switchto = m_curPos;
631  bool discont = false;
632  bool newtype = false;
633 
634  while (current >= 0 && current < m_chain.size())
635  {
636  switchto = current + (up ? 1 : -1);
637 
638  ProgramInfo *pginfo = DoGetNextProgram(up, current, switchto,
639  discont, newtype);
640  delete pginfo;
641 
642  if (switchto == current)
643  {
644  // we've reached the end
645  pos = up ? GetLengthAtPos(switchto) : 0s;
646  break;
647  }
648 
649  std::chrono::seconds duration = GetLengthAtPos(switchto);
650 
651  pos += duration;
652 
653  if (pos >= 0s)
654  {
655  if (up)
656  {
657  pos = - (pos - duration);
658  }
659  break;
660  }
661 
662  current = switchto;
663  }
664  m_switchId = switchto;
665  m_jumpPos = pos;
667  }
668 }
669 
673 std::chrono::seconds LiveTVChain::GetJumpPos(void)
674 {
675  std::chrono::seconds ret = m_jumpPos;
676  m_jumpPos = 0s;
677  return ret;
678 }
679 
680 QString LiveTVChain::GetChannelName(int pos) const
681 {
682  LiveTVChainEntry entry;
683  GetEntryAt(pos, entry);
684 
685  return entry.channum;
686 }
687 
688 QString LiveTVChain::GetInputName(int pos) const
689 {
690  LiveTVChainEntry entry;
691  GetEntryAt(pos, entry);
692 
693  return entry.inputname;
694 }
695 
696 QString LiveTVChain::GetInputType(int pos) const
697 {
698  LiveTVChainEntry entry;
699  GetEntryAt(pos, entry);
700 
701  return entry.inputtype;
702 }
703 
705 {
706  QMutexLocker lock(&m_sockLock);
707 
708  if (!m_inUseSocks.contains(sock))
709  m_inUseSocks.append(sock);
710 }
711 
713 {
714  QMutexLocker lock(&m_sockLock);
715  return m_inUseSocks.contains(sock);
716 }
717 
719 {
720  QMutexLocker lock(&m_sockLock);
721  return m_inUseSocks.count();
722 }
723 
725 {
726  QMutexLocker lock(&m_sockLock);
727  m_inUseSocks.removeAll(sock);
728 }
729 
730 static QString toString(const LiveTVChainEntry &v)
731 {
732  return QString("%1: %2 (%3 to %4)%5")
733  .arg(v.inputtype,6).arg(v.chanid,4)
734  .arg(v.starttime.time().toString(),
735  v.endtime.time().toString(),
736  v.discontinuity?" discontinuous":"");
737 }
738 
739 QString LiveTVChain::toString() const
740 {
741  QMutexLocker lock(&m_lock);
742  QString ret = QString("LiveTVChain has %1 entries\n").arg(m_chain.size());
743  for (uint i = 0; i < (uint)m_chain.size(); i++)
744  {
745  ret += (QString((i==(uint)m_curPos) ? "* " : " ") +
746  ::toString(m_chain[i]) + "\n");
747  }
748  return ret;
749 }
750 
752 {
753  QMutexLocker lock(&m_lock);
754  QStringList ret;
755  ret << QString::number(m_maxPos);
756  for (const auto & entry : qAsConst(m_chain))
757  {
758  ret << QString::number(entry.chanid);
759  ret << entry.starttime.toString(Qt::ISODate);
760  ret << entry.endtime.toString(Qt::ISODate);
761  ret << QString::number(static_cast<int>(entry.discontinuity));
762  ret << entry.hostprefix;
763  ret << entry.inputtype;
764  ret << entry.channum;
765  ret << entry.inputname;
766  }
767  return ret;
768 }
769 
770 bool LiveTVChain::entriesFromStringList(const QStringList &items)
771 {
772  int numItems = items.size();
773  QList<LiveTVChainEntry> chain;
774  int itemIdx = 0;
775  int maxpos = 0;
776  bool ok = false;
777  if (itemIdx < numItems)
778  maxpos = items[itemIdx++].toInt(&ok);
779  while (ok && itemIdx < numItems)
780  {
781  LiveTVChainEntry entry;
782  entry.chanid = items[itemIdx++].toUInt(&ok);
783  if (ok && itemIdx < numItems)
784  {
785  entry.starttime =
786  QDateTime::fromString(items[itemIdx++], Qt::ISODate);
787  ok = entry.starttime.isValid();
788  }
789  if (ok && itemIdx < numItems)
790  {
791  entry.endtime =
792  QDateTime::fromString(items[itemIdx++], Qt::ISODate);
793  ok = entry.endtime.isValid();
794  }
795  if (ok && itemIdx < numItems)
796  entry.discontinuity = (items[itemIdx++].toInt(&ok) != 0);
797  if (ok && itemIdx < numItems)
798  entry.hostprefix = items[itemIdx++];
799  if (ok && itemIdx < numItems)
800  entry.inputtype = items[itemIdx++];
801  if (ok && itemIdx < numItems)
802  entry.channum = items[itemIdx++];
803  if (ok && itemIdx < numItems)
804  entry.inputname = items[itemIdx++];
805  if (ok)
806  chain.append(entry);
807  }
808  if (ok)
809  {
810  QMutexLocker lock(&m_lock);
811  m_maxPos = maxpos;
812  m_chain = chain;
813  }
814  else
815  {
816  LOG(VB_PLAYBACK, LOG_INFO,
817  QString("Failed to deserialize TVChain - ") + items.join("|"));
818  }
819  return ok;
820 }
LiveTVChain::DestroyChain
void DestroyChain(void)
Definition: livetvchain.cpp:196
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:216
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:807
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
LiveTVChain::SwitchTo
void SwitchTo(int num)
Sets the recording to switch to.
Definition: livetvchain.cpp:557
ProgramInfo::MakeUniqueKey
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
Definition: programinfo.h:339
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:84
MSqlQuery::size
int size(void) const
Definition: mythdbcon.h:215
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:888
LiveTVChain::~LiveTVChain
~LiveTVChain() override
Definition: livetvchain.cpp:33
ProgramInfo::GetFilesize
virtual uint64_t GetFilesize(void) const
Definition: programinfo.cpp:6345
LiveTVChain::JumpToNext
void JumpToNext(bool up, std::chrono::seconds pos)
jump to the next (up == true) or previous (up == false) liveTV program If pos > 0: indicate the absol...
Definition: livetvchain.cpp:617
mythdb.h
MythDate::as_utc
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
Definition: mythdate.cpp:27
LiveTVChain::HasNext
bool HasNext(void) const
Definition: livetvchain.cpp:406
LiveTVChain::GetLengthAtPos
std::chrono::seconds GetLengthAtPos(int pos)
Definition: livetvchain.cpp:369
LiveTVChain::EntryToProgram
static ProgramInfo * EntryToProgram(const LiveTVChainEntry &entry)
Definition: livetvchain.cpp:297
LOC
#define LOC
Definition: livetvchain.cpp:10
LiveTVChain::GetChannelName
QString GetChannelName(int pos=-1) const
Definition: livetvchain.cpp:680
LiveTVChain::LoadFromExistingChain
void LoadFromExistingChain(const QString &id)
Definition: livetvchain.cpp:55
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
VERBOSE_LEVEL_CHECK
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
Definition: mythlogging.h:29
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:205
LiveTVChain::m_chain
QList< LiveTVChainEntry > m_chain
Definition: livetvchain.h:110
LiveTVChain::TotalSize
int TotalSize(void) const
Definition: livetvchain.cpp:388
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:608
LiveTVChainEntry::channum
QString channum
Definition: livetvchain.h:30
LiveTVChain::m_curStartTs
QDateTime m_curStartTs
Definition: livetvchain.h:123
LiveTVChain::HostSocketCount
uint HostSocketCount(void) const
Definition: livetvchain.cpp:718
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
LiveTVChain::JumpTo
void JumpTo(int num, std::chrono::seconds pos)
Definition: livetvchain.cpp:603
ProgramInfo::GetRecordingEndTime
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:412
LiveTVChainEntry::endtime
QDateTime endtime
Definition: livetvchain.h:26
LiveTVChain::GetEntryAt
void GetEntryAt(int at, LiveTVChainEntry &entry) const
Definition: livetvchain.cpp:272
hardwareprofile.distros.mythtv_data.data_mythtv.prefix
string prefix
Definition: data_mythtv.py:40
LiveTVChain::DelHostSocket
void DelHostSocket(MythSocket *sock)
Definition: livetvchain.cpp:724
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
LiveTVChain::GetJumpPos
std::chrono::seconds GetJumpPos(void)
Returns the jump position in seconds and clears it.
Definition: livetvchain.cpp:673
ProgramInfo::GetRecordingStartTime
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:404
LiveTVChainEntry::starttime
QDateTime starttime
Definition: livetvchain.h:25
LiveTVChain::LiveTVChain
LiveTVChain()
Definition: livetvchain.cpp:27
LiveTVChain::BroadcastUpdate
void BroadcastUpdate()
Definition: livetvchain.cpp:189
LiveTVChain::GetProgramAt
ProgramInfo * GetProgramAt(int at) const
Returns program at the desired location.
Definition: livetvchain.cpp:321
MythSocket
Class for communcating between myth backends and frontends.
Definition: mythsocket.h:25
LiveTVChain::IsHostSocket
bool IsHostSocket(MythSocket *sock)
Definition: livetvchain.cpp:712
LiveTVChain::m_inUseSocks
QList< MythSocket * > m_inUseSocks
Definition: livetvchain.h:131
programinfo.h
clear
static void clear(LiveTVChainEntry &entry)
Definition: livetvchain.cpp:12
mythlogging.h
LiveTVChain::SetHostPrefix
void SetHostPrefix(const QString &prefix)
Definition: livetvchain.cpp:45
CardUtil::IsChannelChangeDiscontinuous
static bool IsChannelChangeDiscontinuous(const QString &rawtype)
Definition: cardutil.h:147
MythDate::kFilename
@ kFilename
Default UTC, "yyyyMMddhhmmss".
Definition: mythdate.h:18
toString
static QString toString(const LiveTVChainEntry &v)
Definition: livetvchain.cpp:730
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:540
LiveTVChain::SetHostSocket
void SetHostSocket(MythSocket *sock)
Definition: livetvchain.cpp:704
LiveTVChain::SetInputType
void SetInputType(const QString &type)
Definition: livetvchain.cpp:50
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:227
LiveTVChain::m_id
QString m_id
Definition: livetvchain.h:109
LiveTVChain::GetSwitchProgram
ProgramInfo * GetSwitchProgram(bool &discont, bool &newtype, int &newid)
Returns the recording we should switch to.
Definition: livetvchain.cpp:429
LiveTVChain::m_hostPrefix
QString m_hostPrefix
Definition: livetvchain.h:118
ProgramInfo::toString
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
Definition: programinfo.cpp:1934
LiveTVChainEntry::inputtype
QString inputtype
Definition: livetvchain.h:29
LiveTVChain::m_inputType
QString m_inputType
Definition: livetvchain.h:119
LiveTVChain::m_lock
QRecursiveMutex m_lock
Definition: livetvchain.h:115
LiveTVChain::m_curChanId
uint m_curChanId
Definition: livetvchain.h:122
LiveTVChain::ReloadAll
void ReloadAll(const QStringList &data=QStringList())
Definition: livetvchain.cpp:210
uint
unsigned int uint
Definition: compat.h:79
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:54
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:34
LiveTVChain::InitializeNewChain
QString InitializeNewChain(const QString &seed)
Definition: livetvchain.cpp:38
LiveTVChainEntry::hostprefix
QString hostprefix
Definition: livetvchain.h:28
LiveTVChain::m_curPos
int m_curPos
Definition: livetvchain.h:121
LiveTVChain::entriesToStringList
QStringList entriesToStringList() const
Definition: livetvchain.cpp:751
LiveTVChain::GetInputType
QString GetInputType(int pos=-1) const
Definition: livetvchain.cpp:696
ProgramInfo::GetChanID
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:372
LiveTVChainEntry::discontinuity
bool discontinuity
Definition: livetvchain.h:27
livetvchain.h
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
LiveTVChain::m_switchId
int m_switchId
Definition: livetvchain.h:125
MythDate::secsInPast
std::chrono::seconds secsInPast(const QDateTime &past)
Definition: mythdate.cpp:203
LiveTVChain::m_switchEntry
LiveTVChainEntry m_switchEntry
Definition: livetvchain.h:126
cardutil.h
LiveTVChain::SwitchToNext
void SwitchToNext(bool up)
Sets the recording to switch to.
Definition: livetvchain.cpp:592
LiveTVChain::m_sockLock
QMutex m_sockLock
Definition: livetvchain.h:130
LiveTVChainEntry::chanid
uint chanid
Definition: livetvchain.h:24
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:883
LiveTVChain::m_jumpPos
std::chrono::seconds m_jumpPos
Definition: livetvchain.h:128
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
LiveTVChain::toString
QString toString() const
Definition: livetvchain.cpp:739
mythcontext.h
LiveTVChain::AppendNewProgram
void AppendNewProgram(ProgramInfo *pginfo, const QString &channum, const QString &inputname, bool discont)
Definition: livetvchain.cpp:61
LiveTVChainEntry::inputname
QString inputname
Definition: livetvchain.h:31
LiveTVChain::SetProgram
void SetProgram(const ProgramInfo &pginfo)
Definition: livetvchain.cpp:393
LiveTVChain::DoGetNextProgram
ProgramInfo * DoGetNextProgram(bool up, int curpos, int &newid, bool &discont, bool &newtype)
Definition: livetvchain.cpp:447
LiveTVChain::GetLengthAtCurPos
std::chrono::seconds GetLengthAtCurPos(void)
Definition: livetvchain.cpp:361
LiveTVChainEntry
Definition: livetvchain.h:22
LiveTVChain::HasPrev
bool HasPrev(void) const
Definition: livetvchain.h:64
LiveTVChain::m_maxPos
int m_maxPos
Definition: livetvchain.h:111
LiveTVChain::GetInputName
QString GetInputName(int pos=-1) const
Definition: livetvchain.cpp:688
LiveTVChain::entriesFromStringList
bool entriesFromStringList(const QStringList &items)
Definition: livetvchain.cpp:770
mythsocket.h
LiveTVChain::ProgramIsAt
int ProgramIsAt(uint chanid, const QDateTime &starttime) const
Definition: livetvchain.cpp:332
MythCoreContext::dispatch
void dispatch(const MythEvent &event)
Definition: mythcorecontext.cpp:1723
LiveTVChain::DeleteProgram
void DeleteProgram(ProgramInfo *pginfo)
Definition: livetvchain.cpp:145
ReferenceCounter
General purpose reference counter.
Definition: referencecounter.h:26
LiveTVChain::ClearSwitch
void ClearSwitch(void)
Definition: livetvchain.cpp:411
LiveTVChain::FinishedRecording
void FinishedRecording(ProgramInfo *pginfo)
Definition: livetvchain.cpp:111
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:832