MythTV master
livetvchain.cpp
Go to the documentation of this file.
1#include <algorithm>
2
7
8#include "livetvchain.h"
9#include "cardutil.h"
10#include "programinfo.h"
11
12#define LOC QString("LiveTVChain(%1): ").arg(m_id)
13
14static 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
40QString 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
48{
50}
51
52void LiveTVChain::SetInputType(const QString &type)
53{
55}
56
58{
59 m_id = id;
60 ReloadAll();
61}
62
63void 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++;
111}
112
114{
115 QMutexLocker lock(&m_lock);
116
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 }
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
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
186 break;
187 }
188 }
189}
190
192{
193 QString message = QString("LIVETV_CHAIN UPDATE %1").arg(m_id);
194 MythEvent me(message, entriesToStringList());
196}
197
199{
200 QMutexLocker lock(&m_lock);
201
202 m_chain.clear();
203
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
212void 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
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
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
333int 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
354int LiveTVChain::ProgramIsAt(const ProgramInfo &pginfo) const
355{
356 return ProgramIsAt(pginfo.GetChanID(), pginfo.GetRecordingStartTime());
357}
358
362std::chrono::seconds LiveTVChain::GetLengthAtCurPos(void)
363{
364 return GetLengthAtPos(m_curPos);
365}
366
370std::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
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
406bool 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
429ProgramInfo *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
447ProgramInfo *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 int step = up ? 1 : -1;
454
455 GetEntryAt(curpos, oldentry);
456
457 if (newid < 0 || curpos == newid)
458 {
459 // already on the program
460 entry = oldentry;
461 pginfo = EntryToProgram(entry);
462 newid = curpos;
463 }
464 else
465 {
466 // try to find recordings during first pass
467 // we'll skip dummy and empty recordings
468 while (!pginfo && (newid >= 0) && (newid < m_chain.count()))
469 {
470 GetEntryAt(newid, entry);
471
472 bool at_last_entry =
473 ((newid > curpos) &&
474 (newid == m_chain.count()-1)) ||
475 ((newid <= curpos) && (newid == 0));
476
477 // Skip dummy recordings, if possible.
478 if (at_last_entry || (entry.inputtype != "DUMMY"))
479 pginfo = EntryToProgram(entry);
480
481 // Skip empty recordings, if possible
482 if (pginfo && (0 == pginfo->GetFilesize()) &&
483 newid < m_chain.count()-1)
484 {
485 LOG(VB_GENERAL, LOG_WARNING,
486 QString("Skipping empty program %1")
487 .arg(pginfo->MakeUniqueKey()));
488 delete pginfo;
489 pginfo = nullptr;
490 }
491
492 if (!pginfo)
493 {
494 newid += step;
495 }
496 }
497
498 if (!pginfo)
499 {
500 // didn't find in first pass, now get back to the next good one
501 // as this is the one we will use
502 newid -= step; // Bring newid back in range of m_chain
503 while (!pginfo && (newid >= 0) && (newid < m_chain.count()))
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 if (!pginfo)
527 {
528 newid -= step;
529 }
530 }
531
532 if (!pginfo)
533 {
534 // still not found so abort (will never happen once playback has started)
535 return nullptr;
536 }
537 }
538 }
539
540 discont = true;
541 if (curpos == newid - 1)
542 discont = entry.discontinuity;
543
544 newtype = (oldentry.inputtype != entry.inputtype);
545
546 // Some inputs can change their streams dramatically on a channel change...
547 if (discont)
549
550 LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
551 QString("DoGetNextProgram: %1 -> ").arg(newid) + pginfo->toString());
552
553 return pginfo;
554}
555
561{
562 QMutexLocker lock(&m_lock);
563
564 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("SwitchTo(%1)").arg(num));
565
566 int size = m_chain.count();
567 if ((num < 0) || (num >= size))
568 num = size - 1;
569
570 if (m_curPos != num)
571 {
572 m_switchId = num;
574 }
575 else
576 {
577 LOG(VB_GENERAL, LOG_ERR, LOC + "SwitchTo() not switching to current");
578 }
579
580 if (VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_DEBUG))
581 {
583 GetEntryAt(num, e);
584 QString msg = QString("%1_%2")
585 .arg(e.chanid)
587 LOG(VB_PLAYBACK, LOG_DEBUG,
588 LOC + QString("Entry@%1: '%2')").arg(num).arg(msg));
589 }
590}
591
598{
599#if 0
600 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "SwitchToNext("<<(up?"up":"down")<<")");
601#endif
602 if (up && HasNext())
603 SwitchTo(m_curPos + 1);
604 else if (!up && HasPrev())
605 SwitchTo(m_curPos - 1);
606}
607
608void LiveTVChain::JumpTo(int num, std::chrono::seconds pos)
609{
610 m_jumpPos = pos;
611 SwitchTo(num);
612}
613
622void LiveTVChain::JumpToNext(bool up, std::chrono::seconds pos)
623{
624 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("JumpToNext: %1 -> %2").arg(up).arg(pos.count()));
625 if (pos >= 0s)
626 {
627 m_jumpPos = pos;
628 SwitchToNext(up);
629 }
630 else
631 {
632 QMutexLocker lock(&m_lock);
633
634 int current = m_curPos;
635 int switchto = m_curPos;
636 bool discont = false;
637 bool newtype = false;
638
639 while (current >= 0 && current < m_chain.size())
640 {
641 switchto = current + (up ? 1 : -1);
642
643 ProgramInfo *pginfo = DoGetNextProgram(up, current, switchto,
644 discont, newtype);
645 delete pginfo;
646
647 if (switchto == current)
648 {
649 // we've reached the end
650 pos = up ? GetLengthAtPos(switchto) : 0s;
651 break;
652 }
653
654 std::chrono::seconds duration = GetLengthAtPos(switchto);
655
656 pos += duration;
657
658 if (pos >= 0s)
659 {
660 if (up)
661 {
662 pos = - (pos - duration);
663 }
664 break;
665 }
666
667 current = switchto;
668 }
669 m_switchId = switchto;
670 m_jumpPos = pos;
672 }
673}
674
678std::chrono::seconds LiveTVChain::GetJumpPos(void)
679{
680 std::chrono::seconds ret = m_jumpPos;
681 m_jumpPos = 0s;
682 return ret;
683}
684
685QString LiveTVChain::GetChannelName(int pos) const
686{
687 LiveTVChainEntry entry;
688 GetEntryAt(pos, entry);
689
690 return entry.channum;
691}
692
693QString LiveTVChain::GetInputName(int pos) const
694{
695 LiveTVChainEntry entry;
696 GetEntryAt(pos, entry);
697
698 return entry.inputname;
699}
700
701QString LiveTVChain::GetInputType(int pos) const
702{
703 LiveTVChainEntry entry;
704 GetEntryAt(pos, entry);
705
706 return entry.inputtype;
707}
708
710{
711 QMutexLocker lock(&m_sockLock);
712
713 if (!m_inUseSocks.contains(sock))
714 m_inUseSocks.append(sock);
715}
716
718{
719 QMutexLocker lock(&m_sockLock);
720 return m_inUseSocks.contains(sock);
721}
722
724{
725 QMutexLocker lock(&m_sockLock);
726 return m_inUseSocks.count();
727}
728
730{
731 QMutexLocker lock(&m_sockLock);
732 m_inUseSocks.removeAll(sock);
733}
734
735static QString toString(const LiveTVChainEntry &v)
736{
737 return QString("%1: %2 (%3 to %4)%5")
738 .arg(v.inputtype,6).arg(v.chanid,4)
739 .arg(v.starttime.time().toString(),
740 v.endtime.time().toString(),
741 v.discontinuity?" discontinuous":"");
742}
743
745{
746 QMutexLocker lock(&m_lock);
747 QString ret = QString("LiveTVChain has %1 entries\n").arg(m_chain.size());
748 for (uint i = 0; i < (uint)m_chain.size(); i++)
749 {
750 ret += (QString((i==(uint)m_curPos) ? "* " : " ") +
751 ::toString(m_chain[i]) + "\n");
752 }
753 return ret;
754}
755
757{
758 QMutexLocker lock(&m_lock);
759 QStringList ret;
760 ret << QString::number(m_maxPos);
761 for (const auto & entry : std::as_const(m_chain))
762 {
763 ret << QString::number(entry.chanid);
764 ret << entry.starttime.toString(Qt::ISODate);
765 ret << entry.endtime.toString(Qt::ISODate);
766 ret << QString::number(static_cast<int>(entry.discontinuity));
767 ret << entry.hostprefix;
768 ret << entry.inputtype;
769 ret << entry.channum;
770 ret << entry.inputname;
771 }
772 return ret;
773}
774
775bool LiveTVChain::entriesFromStringList(const QStringList &items)
776{
777 int numItems = items.size();
778 QList<LiveTVChainEntry> chain;
779 int itemIdx = 0;
780 int maxpos = 0;
781 bool ok = false;
782 if (itemIdx < numItems)
783 maxpos = items[itemIdx++].toInt(&ok);
784 while (ok && itemIdx < numItems)
785 {
786 LiveTVChainEntry entry;
787 entry.chanid = items[itemIdx++].toUInt(&ok);
788 if (ok && itemIdx < numItems)
789 {
790 entry.starttime =
791 QDateTime::fromString(items[itemIdx++], Qt::ISODate);
792 ok = entry.starttime.isValid();
793 }
794 if (ok && itemIdx < numItems)
795 {
796 entry.endtime =
797 QDateTime::fromString(items[itemIdx++], Qt::ISODate);
798 ok = entry.endtime.isValid();
799 }
800 if (ok && itemIdx < numItems)
801 entry.discontinuity = (items[itemIdx++].toInt(&ok) != 0);
802 if (ok && itemIdx < numItems)
803 entry.hostprefix = items[itemIdx++];
804 if (ok && itemIdx < numItems)
805 entry.inputtype = items[itemIdx++];
806 if (ok && itemIdx < numItems)
807 entry.channum = items[itemIdx++];
808 if (ok && itemIdx < numItems)
809 entry.inputname = items[itemIdx++];
810 if (ok)
811 chain.append(entry);
812 }
813 if (ok)
814 {
815 QMutexLocker lock(&m_lock);
816 m_maxPos = maxpos;
817 m_chain = chain;
818 }
819 else
820 {
821 LOG(VB_PLAYBACK, LOG_INFO,
822 QString("Failed to deserialize TVChain - ") + items.join("|"));
823 }
824 return ok;
825}
static bool IsChannelChangeDiscontinuous(const QString &rawtype)
Definition: cardutil.h:154
bool HasNext(void) const
QDateTime m_curStartTs
Definition: livetvchain.h:117
uint HostSocketCount(void) const
QString m_inputType
Definition: livetvchain.h:113
std::chrono::seconds GetJumpPos(void)
Returns the jump position in seconds and clears it.
QString m_id
Definition: livetvchain.h:107
void SwitchToNext(bool up)
Sets the recording to switch to.
int TotalSize(void) const
void ClearSwitch(void)
void DestroyChain(void)
void JumpTo(int num, std::chrono::seconds pos)
int ProgramIsAt(uint chanid, const QDateTime &starttime) const
void DelHostSocket(MythSocket *sock)
void SwitchTo(int num)
Sets the recording to switch to.
QString m_hostPrefix
Definition: livetvchain.h:112
void BroadcastUpdate()
void DeleteProgram(ProgramInfo *pginfo)
std::chrono::seconds m_jumpPos
Definition: livetvchain.h:122
QString GetChannelName(int pos=-1) const
void FinishedRecording(ProgramInfo *pginfo)
LiveTVChainEntry m_switchEntry
Definition: livetvchain.h:120
void ReloadAll(const QStringList &data=QStringList())
std::chrono::seconds GetLengthAtPos(int pos)
bool HasPrev(void) const
Definition: livetvchain.h:62
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...
bool entriesFromStringList(const QStringList &items)
QMutex m_sockLock
Definition: livetvchain.h:124
void SetInputType(const QString &type)
Definition: livetvchain.cpp:52
ProgramInfo * GetProgramAt(int at) const
Returns program at the desired location.
void SetHostPrefix(const QString &prefix)
Definition: livetvchain.cpp:47
bool IsHostSocket(MythSocket *sock)
QStringList entriesToStringList() const
~LiveTVChain() override
Definition: livetvchain.cpp:35
void SetHostSocket(MythSocket *sock)
void SetProgram(const ProgramInfo &pginfo)
uint m_curChanId
Definition: livetvchain.h:116
QString GetInputName(int pos=-1) const
QString InitializeNewChain(const QString &seed)
Definition: livetvchain.cpp:40
QList< LiveTVChainEntry > m_chain
Definition: livetvchain.h:108
void LoadFromExistingChain(const QString &id)
Definition: livetvchain.cpp:57
QList< MythSocket * > m_inUseSocks
Definition: livetvchain.h:125
QString toString() const
QRecursiveMutex m_lock
Definition: livetvchain.h:110
ProgramInfo * GetSwitchProgram(bool &discont, bool &newtype, int &newid)
Returns the recording we should switch to.
std::chrono::seconds GetLengthAtCurPos(void)
QString GetInputType(int pos=-1) const
void AppendNewProgram(ProgramInfo *pginfo, const QString &channum, const QString &inputname, bool discont)
Definition: livetvchain.cpp:63
virtual ProgramInfo * EntryToProgram(const LiveTVChainEntry &entry) const
ProgramInfo * DoGetNextProgram(bool up, int curpos, int &newid, bool &discont, bool &newtype)
void GetEntryAt(int at, LiveTVChainEntry &entry) const
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:838
QVariant value(int i) const
Definition: mythdbcon.h:204
int size(void) const
Definition: mythdbcon.h:214
bool isActive(void) const
Definition: mythdbcon.h:215
void bindValueNoNull(const QString &placeholder, const QVariant &val)
Add a single binding, taking care not to set a NULL value.
Definition: mythdbcon.cpp:903
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:619
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:889
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:813
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:551
void dispatch(const MythEvent &event)
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:225
This class is used as a container for messages.
Definition: mythevent.h:17
Class for communcating between myth backends and frontends.
Definition: mythsocket.h:26
Holds information on recordings and videos.
Definition: programinfo.h:74
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:380
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:412
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
Definition: programinfo.h:346
virtual uint64_t GetFilesize(void) const
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:420
General purpose reference counter.
unsigned int uint
Definition: compat.h:60
#define LOC
Definition: livetvchain.cpp:12
static QString toString(const LiveTVChainEntry &v)
static void clear(LiveTVChainEntry &entry)
Definition: livetvchain.cpp:14
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
Definition: mythlogging.h:29
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
Definition: mythdate.cpp:28
std::chrono::seconds secsInPast(const QDateTime &past)
Definition: mythdate.cpp:212
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
@ kFilename
Default UTC, "yyyyMMddhhmmss".
Definition: mythdate.h:18
@ ISODate
Default UTC.
Definition: mythdate.h:17
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:39
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
QDateTime starttime
Definition: livetvchain.h:23
QString inputtype
Definition: livetvchain.h:27
QDateTime endtime
Definition: livetvchain.h:24
QString inputname
Definition: livetvchain.h:29
QString hostprefix
Definition: livetvchain.h:26