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(
"|"));
static bool IsChannelChangeDiscontinuous(const QString &rawtype)
uint HostSocketCount(void) const
std::chrono::seconds GetJumpPos(void)
Returns the jump position in seconds and clears it.
void SwitchToNext(bool up)
Sets the recording to switch to.
static ProgramInfo * EntryToProgram(const LiveTVChainEntry &entry)
int TotalSize(void) const
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.
void DeleteProgram(ProgramInfo *pginfo)
std::chrono::seconds m_jumpPos
QString GetChannelName(int pos=-1) const
void FinishedRecording(ProgramInfo *pginfo)
LiveTVChainEntry m_switchEntry
void ReloadAll(const QStringList &data=QStringList())
std::chrono::seconds GetLengthAtPos(int pos)
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)
void SetInputType(const QString &type)
ProgramInfo * GetProgramAt(int at) const
Returns program at the desired location.
void SetHostPrefix(const QString &prefix)
bool IsHostSocket(MythSocket *sock)
QStringList entriesToStringList() const
void SetHostSocket(MythSocket *sock)
void SetProgram(const ProgramInfo &pginfo)
QString GetInputName(int pos=-1) const
QString InitializeNewChain(const QString &seed)
QList< LiveTVChainEntry > m_chain
void LoadFromExistingChain(const QString &id)
QList< MythSocket * > m_inUseSocks
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)
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.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QVariant value(int i) const
bool isActive(void) const
void bindValueNoNull(const QString &placeholder, const QVariant &val)
Add a single binding, taking care not to set a NULL value.
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
void dispatch(const MythEvent &event)
static void DBError(const QString &where, const MSqlQuery &query)
This class is used as a container for messages.
Class for communcating between myth backends and frontends.
Holds information on recordings and videos.
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
virtual uint64_t GetFilesize(void) const
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
General purpose reference counter.
static QString toString(const LiveTVChainEntry &v)
static void clear(LiveTVChainEntry &entry)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
std::chrono::seconds secsInPast(const QDateTime &past)
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
@ kFilename
Default UTC, "yyyyMMddhhmmss".
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
QDateTime current(bool stripped)
Returns current Date and Time in UTC.