Skip to content

Commit

Permalink
Seperate the concepts of last play position and bookmarks.
Browse files Browse the repository at this point in the history
The last play position is now always recorded on program exit (if
playback has been going for at least 30 sec).  The bookmark is now
solely set and cleared by the user. By default, playback now starts from:

  1) last played position, if present
  2) bookmark, if present
  3) program start mark, if present (recordings only)
  4) beginning of file

This is based on Roger Siddons work from 2015. See
https://code.mythtv.org/trac/ticket/12809 for the full details.
  • Loading branch information
linuxdude42 committed Jan 14, 2022
1 parent 7cd9a3c commit c656958
Show file tree
Hide file tree
Showing 18 changed files with 237 additions and 187 deletions.
2 changes: 1 addition & 1 deletion mythtv/bindings/perl/MythTV.pm
Expand Up @@ -116,7 +116,7 @@ package MythTV;
# schema version supported in the main code. We need to check that the schema
# version in the database is as expected by the bindings, which are expected
# to be kept in sync with the main code.
our $SCHEMA_VERSION = "1372";
our $SCHEMA_VERSION = "1373";

# NUMPROGRAMLINES is defined in mythtv/libs/libmythtv/programinfo.h and is
# the number of items in a ProgramInfo QStringList group used by
Expand Down
2 changes: 1 addition & 1 deletion mythtv/bindings/python/MythTV/static.py
Expand Up @@ -5,7 +5,7 @@
"""

OWN_VERSION = (32,0,-1,0)
SCHEMA_VERSION = 1372
SCHEMA_VERSION = 1373
NVSCHEMA_VERSION = 1007
MUSICSCHEMA_VERSION = 1025
PROTO_VERSION = '91'
Expand Down
110 changes: 91 additions & 19 deletions mythtv/libs/libmyth/programinfo.cpp
Expand Up @@ -70,7 +70,7 @@ const QString ProgramInfo::kFromRecordedQuery =
" p.syndicatedepisodenumber, p.partnumber, p.parttotal, "//48-50
" p.season, p.episode, p.totalepisodes, "//51-53
" p.category_type, r.recordedid, r.inputname, "//54-56
" r.bookmarkupdate "//57-57
" r.bookmarkupdate, r.lastplay "//57-58
"FROM recorded AS r "
"LEFT JOIN channel AS c "
"ON (r.chanid = c.chanid) "
Expand Down Expand Up @@ -2138,6 +2138,7 @@ bool ProgramInfo::LoadProgramFromRecorded(
set_flag(m_programFlags, FL_REALLYEDITING, query.value(39).toBool());
set_flag(m_programFlags, FL_BOOKMARK, query.value(40).toBool());
set_flag(m_programFlags, FL_WATCHED, query.value(41).toBool());
set_flag(m_programFlags, FL_LASTPLAYPOS, query.value(58).toBool());
set_flag(m_programFlags, FL_EDITING,
((m_programFlags & FL_REALLYEDITING) != 0U) ||
((m_programFlags & FL_COMMPROCESSING) != 0U));
Expand Down Expand Up @@ -2684,24 +2685,67 @@ void ProgramInfo::SaveBookmark(uint64_t frame)

set_flag(m_programFlags, FL_BOOKMARK, is_valid);

UpdateMarkTimeStamp(is_valid);
SendUpdateEvent();
}

void ProgramInfo::UpdateMarkTimeStamp(bool bookmarked) const
{
if (IsRecording())
{
MSqlQuery query(MSqlQuery::InitCon());
query.prepare(
"UPDATE recorded "
"SET bookmarkupdate = CURRENT_TIMESTAMP, "
" bookmark = :BOOKMARKFLAG "
"WHERE chanid = :CHANID AND "
" starttime = :STARTTIME");
"WHERE recordedid = :RECORDEDID");

query.bindValue(":BOOKMARKFLAG", is_valid);
query.bindValue(":CHANID", m_chanId);
query.bindValue(":STARTTIME", m_recStartTs);
query.bindValue(":BOOKMARKFLAG", bookmarked);
query.bindValue(":RECORDEDID", m_recordedId);

if (!query.exec())
MythDB::DBError("bookmark flag update", query);
}
}

SendUpdateEvent();
void ProgramInfo::SaveLastPlayPos(uint64_t frame)
{
ClearMarkupMap(MARK_UTIL_LASTPLAYPOS);

bool isValid = frame > 0;
if (isValid)
{
frm_dir_map_t lastPlayPosMap;
lastPlayPosMap[frame] = MARK_UTIL_LASTPLAYPOS;
SaveMarkupMap(lastPlayPosMap, MARK_UTIL_LASTPLAYPOS);
}

set_flag(m_programFlags, FL_LASTPLAYPOS, isValid);

UpdateLastPlayTimeStamp(isValid);
SendUpdateEvent();
}

// This function overloads the 'bookmarkupdate' field to force the UI
// to update when the last play timestamp is updated. The alternative
// is adding another field to the database and to the programinfo
// serialization.
void ProgramInfo::UpdateLastPlayTimeStamp(bool hasLastPlay) const
{
if (IsRecording())
{
MSqlQuery query(MSqlQuery::InitCon());
query.prepare(
"UPDATE recorded "
"SET bookmarkupdate = CURRENT_TIMESTAMP, "
" lastplay = :LASTPLAYFLAG "
"WHERE recordedid = :RECORDEDID");

query.bindValue(":LASTPLAYFLAG", hasLastPlay);
query.bindValue(":RECORDEDID", m_recordedId);

if (!query.exec())
MythDB::DBError("lastplay flag update", query);
}
}

Expand Down Expand Up @@ -2771,40 +2815,67 @@ uint64_t ProgramInfo::QueryBookmark(uint chanid, const QDateTime &recstartts)
return (bookmarkmap.isEmpty()) ? 0 : bookmarkmap.begin().key();
}

/** \brief Gets any progstart position in database,
* unless the ignore progstart flag is set.
/** \brief Gets any lastplaypos position in database,
* unless the ignore lastplaypos flag is set.
*
* \return Progstart position in frames if the query is executed
* \return LastPlayPos position in frames if the query is executed
* and succeeds, zero otherwise.
*/
uint64_t ProgramInfo::QueryProgStart(void) const
uint64_t ProgramInfo::QueryLastPlayPos() const
{
if (m_programFlags & FL_IGNOREPROGSTART)
if (m_programFlags & FL_IGNORELASTPLAYPOS)
return 0;

frm_dir_map_t bookmarkmap;
QueryMarkupMap(bookmarkmap, MARK_UTIL_PROGSTART);
QueryMarkupMap(bookmarkmap, MARK_UTIL_LASTPLAYPOS);

return (bookmarkmap.isEmpty()) ? 0 : bookmarkmap.begin().key();
}

/** \brief Gets any lastplaypos position in database,
* unless the ignore lastplaypos flag is set.
/** \brief Gets any progstart position in database,
* unless the ignore progstart flag is set.
*
* \return LastPlayPos position in frames if the query is executed
* \return Progstart position in frames if the query is executed
* and succeeds, zero otherwise.
*/
uint64_t ProgramInfo::QueryLastPlayPos(void) const
uint64_t ProgramInfo::QueryProgStart(void) const
{
if (m_programFlags & FL_IGNORELASTPLAYPOS)
if (m_programFlags & FL_IGNOREPROGSTART)
return 0;

frm_dir_map_t bookmarkmap;
QueryMarkupMap(bookmarkmap, MARK_UTIL_LASTPLAYPOS);
QueryMarkupMap(bookmarkmap, MARK_UTIL_PROGSTART);

return (bookmarkmap.isEmpty()) ? 0 : bookmarkmap.begin().key();
}

uint64_t ProgramInfo::QueryStartMark(void) const
{
uint64_t start = 0;
if ((start = QueryLastPlayPos()) > 0)
{
LOG(VB_PLAYBACK, LOG_INFO, QString("Using last position @ %1").arg(start));
}
else if ((start = QueryBookmark()) > 0)
{
LOG(VB_PLAYBACK, LOG_INFO, QString("Using bookmark @ %1").arg(start));
}
else if (HasCutlist())
{
// Disable progstart if the program has a cutlist.
LOG(VB_PLAYBACK, LOG_INFO, "Ignoring progstart as cutlist exists");
}
else if ((start = QueryProgStart()) > 0)
{
LOG(VB_PLAYBACK, LOG_INFO, QString("Using progstart @ %1").arg(start));
}
else
{
LOG(VB_PLAYBACK, LOG_INFO, "Using file start");
}
return start;
}

/** \brief Queries "dvdbookmark" table for bookmarking DVD serial
* number. Deletes old dvd bookmarks if "delbookmark" is set.
*
Expand Down Expand Up @@ -6071,6 +6142,7 @@ bool LoadFromRecorded(
set_flag(flags, FL_REALLYEDITING, query.value(39).toBool());
set_flag(flags, FL_BOOKMARK, query.value(40).toBool());
set_flag(flags, FL_WATCHED, query.value(41).toBool());
set_flag(flags, FL_LASTPLAYPOS, query.value(58).toBool());

if (inUseMap.contains(key))
flags |= inUseMap[key];
Expand Down
5 changes: 5 additions & 0 deletions mythtv/libs/libmyth/programinfo.h
Expand Up @@ -480,6 +480,7 @@ class MPUBLIC ProgramInfo
bool IsCommercialFlagged(void) const { return (m_programFlags & FL_COMMFLAG) != 0U;}
bool HasCutlist(void) const { return (m_programFlags & FL_CUTLIST) != 0U; }
bool IsBookmarkSet(void) const { return (m_programFlags & FL_BOOKMARK) != 0U; }
bool IsLastPlaySet(void) const { return (m_programFlags & FL_LASTPLAYPOS) != 0U; }
bool IsWatched(void) const { return (m_programFlags & FL_WATCHED) != 0U; }
bool IsAutoExpirable(void) const { return (m_programFlags & FL_AUTOEXP) != 0U; }
bool IsPreserved(void) const { return (m_programFlags & FL_PRESERVED) != 0U; }
Expand Down Expand Up @@ -591,6 +592,7 @@ class MPUBLIC ProgramInfo
uint64_t QueryBookmark(void) const;
uint64_t QueryProgStart(void) const;
uint64_t QueryLastPlayPos(void) const;
uint64_t QueryStartMark(void) const;
CategoryType QueryCategoryType(void) const;
QStringList QueryDVDBookmark(const QString &serialid) const;
QStringList QueryBDBookmark(const QString &serialid) const;
Expand All @@ -617,6 +619,7 @@ class MPUBLIC ProgramInfo

// Slow DB sets
virtual void SaveFilesize(uint64_t fsize); /// TODO Move to RecordingInfo
void SaveLastPlayPos(uint64_t frame);
void SaveBookmark(uint64_t frame);
static void SaveDVDBookmark(const QStringList &fields) ;
static void SaveBDBookmark(const QStringList &fields) ;
Expand Down Expand Up @@ -723,6 +726,8 @@ class MPUBLIC ProgramInfo
static QStringList LoadFromScheduler(const QString &tmptable, int recordid);

// Flagging map support methods
void UpdateMarkTimeStamp(bool bookmarked) const;
void UpdateLastPlayTimeStamp(bool lastplay) const;
void QueryMarkupMap(frm_dir_map_t&marks, MarkTypes type,
bool merge = false) const;
void SaveMarkupMap(const frm_dir_map_t &marks, MarkTypes type = MARK_ALL,
Expand Down
1 change: 1 addition & 0 deletions mythtv/libs/libmyth/programtypeflags.h
Expand Up @@ -54,6 +54,7 @@ FLAGS_DATA(FL, REACTIVATE, 0x00004000)
FLAGS_DATA(FL, IGNOREBOOKMARK, 0x00008000)
FLAGS_DATA(FL, IGNOREPROGSTART, 0x00010000)
FLAGS_DATA(FL, IGNORELASTPLAYPOS,0x00020000)
FLAGS_DATA(FL, LASTPLAYPOS, 0x00040000)
// if you move the type mask please edit {Set,Get}ProgramInfoType()
FLAGS_DATA(FL, TYPEMASK, 0x00F00000)
FLAGS_DATA(FL, INUSERECORDING, 0x01000000)
Expand Down
2 changes: 1 addition & 1 deletion mythtv/libs/libmythbase/mythversion.h
Expand Up @@ -74,7 +74,7 @@
* mythtv/bindings/php/MythBackend.php
*/

#define MYTH_DATABASE_VERSION "1372"
#define MYTH_DATABASE_VERSION "1373"

MBASE_PUBLIC const char *GetMythSourceVersion();
MBASE_PUBLIC const char *GetMythSourcePath();
Expand Down
11 changes: 11 additions & 0 deletions mythtv/libs/libmythtv/dbcheck.cpp
Expand Up @@ -3870,6 +3870,17 @@ static bool doUpgradeTVDatabaseSchema(void)
return false;
}

if (dbver == "1372")
{
DBUpdates updates {
"ALTER TABLE recorded ADD COLUMN lastplay "
" TINYINT UNSIGNED DEFAULT 0 AFTER bookmark;",
};
if (!performActualUpdate("MythTV", "DBSchemaVer",
updates, "1373", dbver))
return false;
}

return true;
}

Expand Down
10 changes: 1 addition & 9 deletions mythtv/libs/libmythtv/mythplayer.cpp
Expand Up @@ -95,7 +95,6 @@ MythPlayer::MythPlayer(PlayerContext* Context, PlayerFlags Flags)

m_vbiMode = VBIMode::Parse(gCoreContext->GetSetting("VbiFormat"));
m_captionsEnabledbyDefault = gCoreContext->GetBoolSetting("DefaultCCMode");
m_clearSavedPosition = gCoreContext->GetNumSetting("ClearSavedPosition", 1);
m_endExitPrompt = gCoreContext->GetNumSetting("EndOfRecordingExitPrompt");

// Get VBI page number
Expand Down Expand Up @@ -1315,14 +1314,7 @@ uint64_t MythPlayer::GetBookmark(void)
{
m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
if (const ProgramInfo *pi = m_playerCtx->m_playingInfo)
{
bookmark = pi->QueryBookmark();
// Disable progstart if the program has a cutlist.
if (bookmark == 0 && !pi->HasCutlist())
bookmark = pi->QueryProgStart();
if (bookmark == 0)
bookmark = pi->QueryLastPlayPos();
}
bookmark = pi->QueryStartMark();
m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
}

Expand Down
1 change: 0 additions & 1 deletion mythtv/libs/libmythtv/mythplayer.h
Expand Up @@ -418,7 +418,6 @@ class MTV_PUBLIC MythPlayer : public QObject

// Bookmark stuff
uint64_t m_bookmarkSeek {0};
int m_clearSavedPosition {1};
int m_endExitPrompt;

// Seek
Expand Down
13 changes: 9 additions & 4 deletions mythtv/libs/libmythtv/mythplayerui.cpp
Expand Up @@ -46,6 +46,7 @@ MythPlayerUI::MythPlayerUI(MythMainWindow* MainWindow, TV* Tv,

// Other connections
connect(m_tv, &TV::UpdateBookmark, this, &MythPlayerUI::SetBookmark);
connect(m_tv, &TV::UpdateLastPlayPosition, this, &MythPlayerUI::SetLastPlayPosition);
connect(m_tv, &TV::InitialisePlayerState, this, &MythPlayerUI::InitialiseState);
}

Expand Down Expand Up @@ -95,11 +96,7 @@ void MythPlayerUI::InitialSeek()
{
// TODO handle initial commskip and/or cutlist skip as well
if (m_bookmarkSeek > 30)
{
DoJumpToFrame(m_bookmarkSeek, kInaccuracyNone);
if (m_clearSavedPosition)
SetBookmark(true);
}
}

void MythPlayerUI::EventLoop()
Expand Down Expand Up @@ -766,6 +763,14 @@ void MythPlayerUI::SetBookmark(bool Clear)
m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
}

void MythPlayerUI::SetLastPlayPosition(uint64_t frame)
{
m_playerCtx->LockPlayingInfo(__FILE__, __LINE__);
if (m_playerCtx->m_playingInfo)
m_playerCtx->m_playingInfo->SaveLastPlayPos(frame);
m_playerCtx->UnlockPlayingInfo(__FILE__, __LINE__);
}

bool MythPlayerUI::CanSupportDoubleRate()
{
std::chrono::microseconds refreshinterval = 1us;
Expand Down
1 change: 1 addition & 0 deletions mythtv/libs/libmythtv/mythplayerui.h
Expand Up @@ -19,6 +19,7 @@ class MTV_PUBLIC MythPlayerUI : public MythPlayerEditorUI, public MythVideoScanT
void ChangeOSDDebug();
void UpdateOSDDebug();
virtual void SetBookmark(bool Clear = false);
virtual void SetLastPlayPosition(uint64_t frame = 0);

public:
MythPlayerUI(MythMainWindow* MainWindow, TV* Tv, PlayerContext* Context, PlayerFlags Flags);
Expand Down

0 comments on commit c656958

Please sign in to comment.