Go to the documentation of this file.
12 #define LOC QString("LiveTVChain(%1): ").arg(m_id)
32 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"ctor");
37 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"dtor");
64 const QString& inputname,
bool discont)
66 QMutexLocker lock(&
m_lock);
81 query.
prepare(
"INSERT INTO tvchain (chanid, starttime, endtime, chainid,"
82 " chainpos, discontinuity, watching, hostprefix, cardtype, "
84 "VALUES(:CHANID, :START, :END, :CHAINID, :CHAINPOS, "
85 " :DISCONT, :WATCHING, :PREFIX, :INPUTTYPE, :CHANNAME, "
103 LOG(VB_RECORD, LOG_INFO, QString(
"Chain: Appended@%3 '%1_%2'")
115 QMutexLocker lock(&
m_lock);
118 query.
prepare(
"UPDATE tvchain SET endtime = :END "
119 "WHERE chanid = :CHANID AND starttime = :START ;");
128 LOG(VB_RECORD, LOG_INFO,
129 QString(
"Chain: Updated endtime for '%1_%2' to %3")
130 .arg(QString::number(pginfo->
GetChanID()),
135 QList<LiveTVChainEntry>::iterator it;
138 if ((*it).chanid == pginfo->
GetChanID() &&
149 QMutexLocker lock(&
m_lock);
153 if ((*it).chanid == pginfo->
GetChanID() &&
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);
169 query.
bindValue(
":DISCONT", (*it).discontinuity);
172 "discontinuity", query);
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);
193 QString message = QString(
"LIVETV_CHAIN UPDATE %1").arg(
m_id);
200 QMutexLocker lock(&
m_lock);
205 query.
prepare(
"DELETE FROM tvchain WHERE chainid = :CHAINID ;");
214 QMutexLocker lock(&
m_lock);
216 int prev_size =
m_chain.size();
222 query.
prepare(
"SELECT chanid, starttime, endtime, discontinuity, "
223 "chainpos, hostprefix, cardtype, channame, input "
225 "WHERE chainid = :CHAINID ORDER BY chainpos;");
257 if (prev_size >
m_chain.size())
259 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
260 QString(
"ReloadAll(): Removed %1 recording(s)")
261 .arg(prev_size -
m_chain.size()));
264 else if (prev_size <
m_chain.size())
266 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
267 QString(
"ReloadAll(): Added %1 recording(s)")
268 .arg(
m_chain.size() - prev_size));
275 QMutexLocker lock(&
m_lock);
278 int new_at = (size && (at < 0 || at >= size)) ? size - 1 : at;
280 if (size && new_at >= 0 && new_at < size)
284 LOG(VB_GENERAL, LOG_ERR, QString(
"GetEntryAt(%1) failed.").arg(at));
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.");
302 if (pginfo->GetChanID())
304 pginfo->SetPathname(entry.
hostprefix + pginfo->GetBasename());
308 LOG(VB_GENERAL, LOG_ERR,
309 QString(
"EntryToProgram(%1@%2) failed to get pginfo")
335 QMutexLocker lock(&
m_lock);
338 QList<LiveTVChainEntry>::const_iterator it;
341 if ((*it).chanid == chanid &&
342 (*it).starttime == starttime)
372 QMutexLocker lock(&
m_lock);
375 if (pos == (
m_chain.count() - 1))
396 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))
574 LOG(VB_GENERAL, LOG_ERR,
LOC +
"SwitchTo() not switching to current");
581 QString msg = QString(
"%1_%2")
584 LOG(VB_PLAYBACK, LOG_DEBUG,
585 LOC + QString(
"Entry@%1: '%2')").arg(num).arg(msg));
597 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"SwitchToNext("<<(up?
"up":
"down")<<
")");
621 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"JumpToNext: %1 -> %2").arg(up).arg(pos.count()));
629 QMutexLocker lock(&
m_lock);
633 bool discont =
false;
634 bool newtype =
false;
638 switchto =
current + (up ? 1 : -1);
659 pos = - (pos - duration);
734 return QString(
"%1: %2 (%3 to %4)%5")
743 QMutexLocker lock(&
m_lock);
744 QString ret = QString(
"LiveTVChain has %1 entries\n").arg(
m_chain.size());
755 QMutexLocker lock(&
m_lock);
758 for (
const auto & entry : std::as_const(
m_chain))
760 ret << QString::number(entry.chanid);
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;
774 int numItems = items.size();
775 QList<LiveTVChainEntry> chain;
779 if (itemIdx < numItems)
780 maxpos = items[itemIdx++].toInt(&ok);
781 while (ok && itemIdx < numItems)
784 entry.
chanid = items[itemIdx++].toUInt(&ok);
785 if (ok && itemIdx < numItems)
791 if (ok && itemIdx < numItems)
797 if (ok && itemIdx < numItems)
799 if (ok && itemIdx < numItems)
801 if (ok && itemIdx < numItems)
803 if (ok && itemIdx < numItems)
804 entry.
channum = items[itemIdx++];
805 if (ok && itemIdx < numItems)
812 QMutexLocker lock(&
m_lock);
818 LOG(VB_PLAYBACK, LOG_INFO,
819 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.