Go to the documentation of this file.
9 #define LOC QString("LiveTVChain(%1): ").arg(m_id)
29 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"ctor");
34 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"dtor");
40 m_id = QString(
"live-%1-%2").arg(seed).arg(curdt.toString(
Qt::ISODate));
61 const QString& inputname,
bool discont)
63 QMutexLocker lock(&
m_lock);
78 query.
prepare(
"INSERT INTO tvchain (chanid, starttime, endtime, chainid,"
79 " chainpos, discontinuity, watching, hostprefix, cardtype, "
81 "VALUES(:CHANID, :START, :END, :CHAINID, :CHAINPOS, "
82 " :DISCONT, :WATCHING, :PREFIX, :INPUTTYPE, :CHANNAME, "
100 LOG(VB_RECORD, LOG_INFO, QString(
"Chain: Appended@%3 '%1_%2'")
112 QMutexLocker lock(&
m_lock);
116 "WHERE chanid = :CHANID AND starttime = :START ;");
125 LOG(VB_RECORD, LOG_INFO,
126 QString(
"Chain: Updated endtime for '%1_%2' to %3")
132 QList<LiveTVChainEntry>::iterator it;
135 if ((*it).chanid == pginfo->
GetChanID() &&
146 QMutexLocker lock(&
m_lock);
150 if ((*it).chanid == pginfo->
GetChanID() &&
159 (*it).discontinuity =
true;
160 query.
prepare(
"UPDATE tvchain SET discontinuity = :DISCONT "
161 "WHERE chanid = :CHANID AND starttime = :START "
162 "AND chainid = :CHAINID ;");
169 "discontinuity",
query);
172 query.
prepare(
"DELETE FROM tvchain WHERE chanid = :CHANID "
173 "AND starttime = :START AND chainid = :CHAINID ;");
190 QString message = QString(
"LIVETV_CHAIN UPDATE %1").arg(
m_id);
197 QMutexLocker lock(&
m_lock);
202 query.
prepare(
"DELETE FROM tvchain WHERE chainid = :CHAINID ;");
211 QMutexLocker lock(&
m_lock);
213 int prev_size =
m_chain.size();
219 query.
prepare(
"SELECT chanid, starttime, endtime, discontinuity, "
220 "chainpos, hostprefix, cardtype, channame, input "
222 "WHERE chainid = :CHAINID ORDER BY chainpos;");
255 if (prev_size >
m_chain.size())
257 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
258 QString(
"ReloadAll(): Removed %1 recording(s)")
262 else if (prev_size <
m_chain.size())
264 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
265 QString(
"ReloadAll(): Added %1 recording(s)")
273 QMutexLocker lock(&
m_lock);
276 int new_at = (size && (at < 0 || at >= size)) ? size - 1 : at;
278 if (size && new_at >= 0 && new_at < size)
282 LOG(VB_GENERAL, LOG_ERR, QString(
"GetEntryAt(%1) failed.").
arg(at));
285 LOG(VB_GENERAL, LOG_ERR,
"It appears that your backend may "
286 "be misconfigured. Check your backend logs to determine "
287 "whether your inputs, lineups, channels, or storage "
288 "configuration are reporting errors. This issue is commonly "
289 "caused by failing to complete all setup steps properly. You "
290 "may wish to review the documentation for mythtv-setup.");
300 if (pginfo->GetChanID())
302 pginfo->SetPathname(entry.
hostprefix + pginfo->GetBasename());
306 LOG(VB_GENERAL, LOG_ERR,
307 QString(
"EntryToProgram(%1@%2) failed to get pginfo")
333 QMutexLocker lock(&
m_lock);
336 QList<LiveTVChainEntry>::const_iterator it;
339 if ((*it).chanid == chanid &&
340 (*it).starttime == starttime)
370 QMutexLocker lock(&
m_lock);
373 if (pos == (
m_chain.count() - 1))
394 QMutexLocker lock(&
m_lock);
412 QMutexLocker lock(&
m_lock);
432 QMutexLocker lock(&
m_lock);
447 bool &discont,
bool &newtype)
455 if (newid < 0 || curpos == newid)
466 while (!pginfo && newid <
m_chain.count() && newid >= 0)
472 (newid ==
m_chain.count()-1)) ||
473 ((newid <= curpos) && (newid == 0));
476 if (at_last_entry || (entry.
inputtype !=
"DUMMY"))
483 LOG(VB_GENERAL, LOG_WARNING,
484 QString(
"Skipping empty program %1")
492 newid += up ? 1 : -1;
502 newid += up ? -1 : 1;
508 (newid ==
m_chain.count()-1)) ||
509 ((newid <= curpos) && (newid == 0));
512 if (at_last_entry || (entry.
inputtype !=
"DUMMY"))
519 LOG(VB_GENERAL, LOG_WARNING,
520 QString(
"Skipping empty program %1")
526 while (!pginfo && newid <
m_chain.count() && newid >= 0);
537 if (curpos == newid - 1)
546 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
547 QString(
"DoGetNextProgram: %1 -> ").
arg(newid) + pginfo->
toString());
558 QMutexLocker lock(&
m_lock);
560 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"SwitchTo(%1)").
arg(num));
563 if ((num < 0) || (num >= size))
572 LOG(VB_GENERAL, LOG_ERR,
LOC +
"SwitchTo() not switching to current");
578 QString msg = QString(
"%1_%2")
581 LOG(VB_PLAYBACK, LOG_DEBUG,
582 LOC + QString(
"Entry@%1: '%2')").
arg(num).
arg(msg));
594 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"SwitchToNext("<<(up?
"up":
"down")<<
")");
618 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"JumpToNext: %1 -> %2").
arg(up).
arg(pos.count()));
626 QMutexLocker lock(&
m_lock);
630 bool discont =
false;
631 bool newtype =
false;
635 switchto =
current + (up ? 1 : -1);
656 pos = - (pos - duration);
731 return QString(
"%1: %2 (%3 to %4)%5")
734 .arg(v.
endtime.time().toString())
740 QMutexLocker lock(&
m_lock);
741 QString ret = QString(
"LiveTVChain has %1 entries\n").arg(
m_chain.size());
752 QMutexLocker lock(&
m_lock);
755 for (
const auto & entry : qAsConst(
m_chain))
757 ret << QString::number(entry.chanid);
760 ret << QString::number(static_cast<int>(entry.discontinuity));
761 ret << entry.hostprefix;
762 ret << entry.inputtype;
763 ret << entry.channum;
764 ret << entry.inputname;
771 int numItems = items.size();
772 QList<LiveTVChainEntry> chain;
776 if (itemIdx < numItems)
777 maxpos = items[itemIdx++].toInt(&ok);
778 while (ok && itemIdx < numItems)
781 entry.
chanid = items[itemIdx++].toUInt(&ok);
782 if (ok && itemIdx < numItems)
788 if (ok && itemIdx < numItems)
794 if (ok && itemIdx < numItems)
796 if (ok && itemIdx < numItems)
798 if (ok && itemIdx < numItems)
800 if (ok && itemIdx < numItems)
801 entry.
channum = items[itemIdx++];
802 if (ok && itemIdx < numItems)
809 QMutexLocker lock(&
m_lock);
815 LOG(VB_PLAYBACK, LOG_INFO,
816 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.
QVariant value(int i) const
arg(title).arg(filename).arg(doDelete))
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.
#define VERBOSE_LEVEL_CHECK(_MASK_, _LEVEL_)
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
MSqlQuery query(MSqlQuery::InitCon())
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.