Go to the documentation of this file.
10 #define LOC QString("LiveTVChain(%1): ").arg(m_id)
30 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"ctor");
35 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"dtor");
62 const QString& inputname,
bool discont)
64 QMutexLocker lock(&
m_lock);
79 query.
prepare(
"INSERT INTO tvchain (chanid, starttime, endtime, chainid,"
80 " chainpos, discontinuity, watching, hostprefix, cardtype, "
82 "VALUES(:CHANID, :START, :END, :CHAINID, :CHAINPOS, "
83 " :DISCONT, :WATCHING, :PREFIX, :INPUTTYPE, :CHANNAME, "
101 LOG(VB_RECORD, LOG_INFO, QString(
"Chain: Appended@%3 '%1_%2'")
113 QMutexLocker lock(&
m_lock);
116 query.
prepare(
"UPDATE tvchain SET endtime = :END "
117 "WHERE chanid = :CHANID AND starttime = :START ;");
126 LOG(VB_RECORD, LOG_INFO,
127 QString(
"Chain: Updated endtime for '%1_%2' to %3")
128 .arg(QString::number(pginfo->
GetChanID()),
133 QList<LiveTVChainEntry>::iterator it;
136 if ((*it).chanid == pginfo->
GetChanID() &&
147 QMutexLocker lock(&
m_lock);
151 if ((*it).chanid == pginfo->
GetChanID() &&
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);
167 query.
bindValue(
":DISCONT", (*it).discontinuity);
170 "discontinuity", query);
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);
191 QString message = QString(
"LIVETV_CHAIN UPDATE %1").arg(
m_id);
198 QMutexLocker lock(&
m_lock);
203 query.
prepare(
"DELETE FROM tvchain WHERE chainid = :CHAINID ;");
212 QMutexLocker lock(&
m_lock);
214 int prev_size =
m_chain.size();
220 query.
prepare(
"SELECT chanid, starttime, endtime, discontinuity, "
221 "chainpos, hostprefix, cardtype, channame, input "
223 "WHERE chainid = :CHAINID ORDER BY chainpos;");
256 if (prev_size >
m_chain.size())
258 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
259 QString(
"ReloadAll(): Removed %1 recording(s)")
260 .arg(prev_size -
m_chain.size()));
263 else if (prev_size <
m_chain.size())
265 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
266 QString(
"ReloadAll(): Added %1 recording(s)")
267 .arg(
m_chain.size() - prev_size));
274 QMutexLocker lock(&
m_lock);
277 int new_at = (size && (at < 0 || at >= size)) ? size - 1 : at;
279 if (size && new_at >= 0 && new_at < size)
283 LOG(VB_GENERAL, LOG_ERR, QString(
"GetEntryAt(%1) failed.").arg(at));
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.");
301 if (pginfo->GetChanID())
303 pginfo->SetPathname(entry.
hostprefix + pginfo->GetBasename());
307 LOG(VB_GENERAL, LOG_ERR,
308 QString(
"EntryToProgram(%1@%2) failed to get pginfo")
334 QMutexLocker lock(&
m_lock);
337 QList<LiveTVChainEntry>::const_iterator it;
340 if ((*it).chanid == chanid &&
341 (*it).starttime == starttime)
371 QMutexLocker lock(&
m_lock);
374 if (pos == (
m_chain.count() - 1))
395 QMutexLocker lock(&
m_lock);
413 QMutexLocker lock(&
m_lock);
433 QMutexLocker lock(&
m_lock);
448 bool &discont,
bool &newtype)
456 if (newid < 0 || curpos == newid)
467 while (!pginfo && newid <
m_chain.count() && newid >= 0)
473 (newid ==
m_chain.count()-1)) ||
474 ((newid <= curpos) && (newid == 0));
477 if (at_last_entry || (entry.
inputtype !=
"DUMMY"))
484 LOG(VB_GENERAL, LOG_WARNING,
485 QString(
"Skipping empty program %1")
493 newid += up ? 1 : -1;
503 newid += up ? -1 : 1;
509 (newid ==
m_chain.count()-1)) ||
510 ((newid <= curpos) && (newid == 0));
513 if (at_last_entry || (entry.
inputtype !=
"DUMMY"))
520 LOG(VB_GENERAL, LOG_WARNING,
521 QString(
"Skipping empty program %1")
527 while (!pginfo && newid <
m_chain.count() && newid >= 0);
538 if (curpos == newid - 1)
547 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
548 QString(
"DoGetNextProgram: %1 -> ").arg(newid) + pginfo->
toString());
559 QMutexLocker lock(&
m_lock);
561 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"SwitchTo(%1)").arg(num));
564 if ((num < 0) || (num >= size))
573 LOG(VB_GENERAL, LOG_ERR,
LOC +
"SwitchTo() not switching to current");
579 QString msg = QString(
"%1_%2")
582 LOG(VB_PLAYBACK, LOG_DEBUG,
583 LOC + QString(
"Entry@%1: '%2')").arg(num).arg(msg));
595 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"SwitchToNext("<<(up?
"up":
"down")<<
")");
619 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"JumpToNext: %1 -> %2").arg(up).arg(pos.count()));
627 QMutexLocker lock(&
m_lock);
631 bool discont =
false;
632 bool newtype =
false;
636 switchto =
current + (up ? 1 : -1);
657 pos = - (pos - duration);
732 return QString(
"%1: %2 (%3 to %4)%5")
741 QMutexLocker lock(&
m_lock);
742 QString ret = QString(
"LiveTVChain has %1 entries\n").arg(
m_chain.size());
753 QMutexLocker lock(&
m_lock);
756 for (
const auto & entry : qAsConst(
m_chain))
758 ret << QString::number(entry.chanid);
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;
772 int numItems = items.size();
773 QList<LiveTVChainEntry> chain;
777 if (itemIdx < numItems)
778 maxpos = items[itemIdx++].toInt(&ok);
779 while (ok && itemIdx < numItems)
782 entry.
chanid = items[itemIdx++].toUInt(&ok);
783 if (ok && itemIdx < numItems)
789 if (ok && itemIdx < numItems)
795 if (ok && itemIdx < numItems)
797 if (ok && itemIdx < numItems)
799 if (ok && itemIdx < numItems)
801 if (ok && itemIdx < numItems)
802 entry.
channum = items[itemIdx++];
803 if (ok && itemIdx < numItems)
810 QMutexLocker lock(&
m_lock);
816 LOG(VB_PLAYBACK, LOG_INFO,
817 QString(
"Failed to deserialize TVChain - ") + items.join(
"|"));
bool isActive(void) const
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
void SwitchTo(int num)
Sets the recording to switch to.
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
void bindValueNoNull(const QString &placeholder, const QVariant &val)
Add a single binding, taking care not to set a NULL value.
virtual uint64_t GetFilesize(void) const
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...
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
std::chrono::seconds GetLengthAtPos(int pos)
static ProgramInfo * EntryToProgram(const LiveTVChainEntry &entry)
QString GetChannelName(int pos=-1) const
void LoadFromExistingChain(const QString &id)
This class is used as a container for messages.
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
QVariant value(int i) const
QList< LiveTVChainEntry > m_chain
int TotalSize(void) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
uint HostSocketCount(void) const
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
void JumpTo(int num, std::chrono::seconds pos)
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
void GetEntryAt(int at, LiveTVChainEntry &entry) const
void DelHostSocket(MythSocket *sock)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
std::chrono::seconds GetJumpPos(void)
Returns the jump position in seconds and clears it.
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
ProgramInfo * GetProgramAt(int at) const
Returns program at the desired location.
Class for communcating between myth backends and frontends.
bool IsHostSocket(MythSocket *sock)
QList< MythSocket * > m_inUseSocks
static void clear(LiveTVChainEntry &entry)
void SetHostPrefix(const QString &prefix)
static bool IsChannelChangeDiscontinuous(const QString &rawtype)
@ kFilename
Default UTC, "yyyyMMddhhmmss".
static QString toString(const LiveTVChainEntry &v)
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
void SetHostSocket(MythSocket *sock)
void SetInputType(const QString &type)
static void DBError(const QString &where, const MSqlQuery &query)
ProgramInfo * GetSwitchProgram(bool &discont, bool &newtype, int &newid)
Returns the recording we should switch to.
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
void ReloadAll(const QStringList &data=QStringList())
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
QString InitializeNewChain(const QString &seed)
QStringList entriesToStringList() const
QString GetInputType(int pos=-1) const
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Holds information on recordings and videos.
std::chrono::seconds secsInPast(const QDateTime &past)
LiveTVChainEntry m_switchEntry
void SwitchToNext(bool up)
Sets the recording to switch to.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
std::chrono::seconds m_jumpPos
void AppendNewProgram(ProgramInfo *pginfo, const QString &channum, const QString &inputname, bool discont)
void SetProgram(const ProgramInfo &pginfo)
ProgramInfo * DoGetNextProgram(bool up, int curpos, int &newid, bool &discont, bool &newtype)
std::chrono::seconds GetLengthAtCurPos(void)
QString GetInputName(int pos=-1) const
bool entriesFromStringList(const QStringList &items)
int ProgramIsAt(uint chanid, const QDateTime &starttime) const
void dispatch(const MythEvent &event)
void DeleteProgram(ProgramInfo *pginfo)
General purpose reference counter.
void FinishedRecording(ProgramInfo *pginfo)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.