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