aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Sommerfeld <kai.sommerfeld@gmx.com>2018-11-10 11:18:33 +0100
committerGitHub <noreply@github.com>2018-11-10 11:18:33 +0100
commit2762a102b16f101390479f4e3882cff647afff2f (patch)
treec10b31b29c7c28bfa1e419bc38f74c315253e0a6
parentf85b7e6398ccb88598c1793572bf866f5ea05418 (diff)
parente957222d85f36877bcd254bd85db304f6e8d399c (diff)
Merge pull request #14836 from ksooo/pvr-lastwatched-delay
[PVR] New PVR playback setting: 'Delay mark last watched'.
-rw-r--r--addons/resource.language.en_gb/resources/strings.po12
-rwxr-xr-xsystem/settings/settings.xml12
-rw-r--r--xbmc/pvr/PVRManager.cpp76
-rw-r--r--xbmc/pvr/PVRManager.h10
-rw-r--r--xbmc/pvr/channels/PVRChannel.cpp98
-rw-r--r--xbmc/settings/Settings.cpp1
-rw-r--r--xbmc/settings/Settings.h1
7 files changed, 138 insertions, 72 deletions
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index dbbfb013a2..51a400f154 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -10277,7 +10277,11 @@ msgctxt "#19194"
msgid "Continue?"
msgstr ""
-#empty string with id 19195
+#. pvr settings "delay mark last watched" setting label
+#: system/settings/settings.xml
+msgctxt "#19195"
+msgid "Delay mark last watched"
+msgstr ""
#. value for "pvr client specific actions" dialog headers
#: xbmc/pvr/PVRGUIActions.cpp
@@ -18634,7 +18638,11 @@ msgctxt "#36235"
msgid "Normal timeshift OSD always shows the complete timeshift buffer along with with the currently playing show, whereas the simple timeshift OSD only shows the currently playing show with no visual feedback how far in the timeshift buffer you can jump from the currently playing position."
msgstr ""
-#empty string with id 36236
+#: system/settings/settings.xml
+msgctxt "#36236"
+msgid "If set to a value greater than zero last watched time of channels will be stored the given amount of time after start of channel playback. Otherwise the last watched time will be stored immediately at start of channel playback."
+msgstr ""
+
#: system/settings/settings.xml
msgctxt "#36237"
diff --git a/system/settings/settings.xml b/system/settings/settings.xml
index 3996711db7..d83bc8d393 100755
--- a/system/settings/settings.xml
+++ b/system/settings/settings.xml
@@ -1420,6 +1420,18 @@
<formatlabel>14046</formatlabel>
</control>
</setting>
+ <setting id="pvrplayback.delaymarklastwatched" type="integer" label="19195" help="36236">
+ <level>3</level>
+ <default>0</default>
+ <constraints>
+ <minimum>0</minimum>
+ <step>30</step>
+ <maximum>600</maximum>
+ </constraints>
+ <control type="spinner" format="string">
+ <formatlabel>14045</formatlabel>
+ </control>
+ </setting>
<setting id="pvrplayback.fps" type="integer" label="19108" help="36261">
<level>0</level>
<default>0</default>
diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp
index 161b73ad8b..b482fb7738 100644
--- a/xbmc/pvr/PVRManager.cpp
+++ b/xbmc/pvr/PVRManager.cpp
@@ -17,6 +17,7 @@
#include "messaging/ApplicationMessenger.h"
#include "settings/Settings.h"
#include "threads/SystemClock.h"
+#include "threads/Timer.h"
#include "utils/JobManager.h"
#include "utils/Stopwatch.h"
#include "utils/StringUtils.h"
@@ -127,6 +128,7 @@ CPVRManager::CPVRManager(void) :
m_database(new CPVRDatabase),
m_parentalTimer(new CStopWatch),
m_settings({
+ CSettings::SETTING_PVRPLAYBACK_DELAYMARKLASTWATCHED,
CSettings::SETTING_PVRPOWERMANAGEMENT_ENABLED,
CSettings::SETTING_PVRPOWERMANAGEMENT_SETWAKEUPCMD,
CSettings::SETTING_PVRPARENTAL_ENABLED,
@@ -730,6 +732,33 @@ CPVRChannelGroupPtr CPVRManager::GetPlayingGroup(bool bRadio /* = false */) cons
return CPVRChannelGroupPtr();
}
+class CPVRManager::CLastWatchedUpdateTimer : public CTimer, private ITimerCallback
+{
+public:
+ explicit CLastWatchedUpdateTimer(CPVRManager& pvrMgr,
+ const std::shared_ptr<CPVRChannel>& channel,
+ const CDateTime& time)
+ : CTimer(this),
+ m_pvrMgr(pvrMgr),
+ m_channel(channel),
+ m_time(time)
+ {
+ }
+
+ // ITimerCallback implementation
+ void OnTimeout() override
+ {
+ m_pvrMgr.UpdateLastWatched(m_channel, m_time);
+ }
+
+private:
+ CLastWatchedUpdateTimer() = delete;
+
+ CPVRManager& m_pvrMgr;
+ const std::shared_ptr<CPVRChannel> m_channel;
+ const CDateTime m_time;
+};
+
void CPVRManager::OnPlaybackStarted(const CFileItemPtr item)
{
m_playingChannel.reset();
@@ -746,7 +775,22 @@ void CPVRManager::OnPlaybackStarted(const CFileItemPtr item)
m_playingClientId = m_playingChannel->ClientID();
SetPlayingGroup(channel);
- UpdateLastWatched(channel);
+
+ int iLastWatchedDelay = m_settings.GetIntValue(CSettings::SETTING_PVRPLAYBACK_DELAYMARKLASTWATCHED) * 1000;
+ if (iLastWatchedDelay > 0)
+ {
+ // Insert new / replace existing last watched update timer
+ if (m_lastWatchedUpdateTimer)
+ m_lastWatchedUpdateTimer->Stop(true);
+
+ m_lastWatchedUpdateTimer.reset(new CLastWatchedUpdateTimer(*this, channel, CDateTime::GetUTCDateTime()));
+ m_lastWatchedUpdateTimer->Start(iLastWatchedDelay);
+ }
+ else
+ {
+ // Store last watched timestamp immediately
+ UpdateLastWatched(channel, CDateTime::GetUTCDateTime());
+ }
}
else if (item->HasPVRRecordingInfoTag())
{
@@ -776,7 +820,25 @@ void CPVRManager::OnPlaybackStopped(const CFileItemPtr item)
if (item->HasPVRChannelInfoTag() && item->GetPVRChannelInfoTag() == m_playingChannel)
{
- UpdateLastWatched(item->GetPVRChannelInfoTag());
+ bool bUpdateLastWatched = true;
+
+ if (m_lastWatchedUpdateTimer)
+ {
+ if (m_lastWatchedUpdateTimer->IsRunning())
+ {
+ // If last watched timer is still running, cancel it. Channel was not watched long enough to store the value.
+ m_lastWatchedUpdateTimer->Stop(true);
+ bUpdateLastWatched = false;
+ }
+ m_lastWatchedUpdateTimer.reset();
+ }
+
+ if (bUpdateLastWatched)
+ {
+ // If last watched timer is not running (any more), channel was watched long enough to store the value.
+ UpdateLastWatched(m_playingChannel, CDateTime::GetUTCDateTime());
+ }
+
SetChanged();
NotifyObservers(ObservableMessageChannelPlaybackStopped);
@@ -918,16 +980,16 @@ bool CPVRManager::CreateChannelEpgs(void)
return m_bEpgsCreated;
}
-void CPVRManager::UpdateLastWatched(const CPVRChannelPtr &channel)
+void CPVRManager::UpdateLastWatched(const CPVRChannelPtr &channel, const CDateTime& time)
{
- time_t tNow;
- CDateTime::GetCurrentDateTime().GetAsTime(tNow);
+ time_t iTime;
+ time.GetAsTime(iTime);
- channel->SetLastWatched(tNow);
+ channel->SetLastWatched(iTime);
// update last watched timestamp for group
CPVRChannelGroupPtr group(GetPlayingGroup(channel->IsRadio()));
- group->SetLastWatched(tNow);
+ group->SetLastWatched(iTime);
/* update last played group */
m_channelGroups->SetLastPlayedGroup(group);
diff --git a/xbmc/pvr/PVRManager.h b/xbmc/pvr/PVRManager.h
index dac66cb150..bbb9673b1f 100644
--- a/xbmc/pvr/PVRManager.h
+++ b/xbmc/pvr/PVRManager.h
@@ -445,8 +445,9 @@ namespace PVR
/*!
* @brief Updates the last watched timestamps of the channel and group which are currently playing.
* @param channel The channel which is updated
+ * @param time The last watched time to set
*/
- void UpdateLastWatched(const CPVRChannelPtr &channel);
+ void UpdateLastWatched(const CPVRChannelPtr &channel, const CDateTime& time);
/*!
* @brief Set the playing group to the first group the channel is in if the given channel is not part of the current playing group
@@ -523,8 +524,8 @@ namespace PVR
CPVRDatabasePtr m_database; /*!< the database for all PVR related data */
mutable CCriticalSection m_critSection; /*!< critical section for all changes to this class, except for changes to triggers */
- bool m_bFirstStart = true; /*!< true when the PVR manager was started first, false otherwise */
- bool m_bEpgsCreated = false; /*!< true if epg data for channels has been created */
+ bool m_bFirstStart = true; /*!< true when the PVR manager was started first, false otherwise */
+ bool m_bEpgsCreated = false; /*!< true if epg data for channels has been created */
mutable CCriticalSection m_managerStateMutex;
ManagerState m_managerState = ManagerStateStopped;
@@ -542,5 +543,8 @@ namespace PVR
CPVREpgInfoTagPtr m_playingEpgTag;
std::string m_strPlayingClientName;
int m_playingClientId = -1;
+
+ class CLastWatchedUpdateTimer;
+ std::unique_ptr<CLastWatchedUpdateTimer> m_lastWatchedUpdateTimer;
};
}
diff --git a/xbmc/pvr/channels/PVRChannel.cpp b/xbmc/pvr/channels/PVRChannel.cpp
index e00ba2497b..d932e97d8c 100644
--- a/xbmc/pvr/channels/PVRChannel.cpp
+++ b/xbmc/pvr/channels/PVRChannel.cpp
@@ -102,7 +102,7 @@ void CPVRChannel::Serialize(CVariant& value) const
value["channelnumber"] = m_channelNumber.GetChannelNumber();
value["subchannelnumber"] = m_channelNumber.GetSubChannelNumber();
- CPVREpgInfoTagPtr epg(GetEPGNow());
+ CPVREpgInfoTagPtr epg = GetEPGNow();
if (epg)
{
// add the properties of the current EPG item to the main object
@@ -123,17 +123,16 @@ void CPVRChannel::Serialize(CVariant& value) const
bool CPVRChannel::Delete(void)
{
bool bReturn = false;
- const CPVRDatabasePtr database(CServiceBroker::GetPVRManager().GetTVDatabase());
+ const CPVRDatabasePtr database = CServiceBroker::GetPVRManager().GetTVDatabase();
if (!database)
return bReturn;
- /* delete the EPG table */
- CPVREpgPtr epg = GetEPG();
+ const CPVREpgPtr epg = GetEPG();
if (epg)
{
- CPVRChannelPtr empty;
- epg->SetChannel(empty);
+ epg->SetChannel(CPVRChannelPtr());
CServiceBroker::GetPVRManager().EpgContainer().DeleteEpg(epg, true);
+
CSingleLock lock(m_critSection);
m_bEPGCreated = false;
}
@@ -159,7 +158,7 @@ bool CPVRChannel::CreateEPG(bool bForce)
CSingleLock lock(m_critSection);
if (!m_bEPGCreated || bForce)
{
- CPVREpgPtr epg = CServiceBroker::GetPVRManager().EpgContainer().CreateChannelEpg(shared_from_this());
+ const CPVREpgPtr epg = CServiceBroker::GetPVRManager().EpgContainer().CreateChannelEpg(shared_from_this());
if (epg)
{
m_bEPGCreated = true;
@@ -212,10 +211,11 @@ bool CPVRChannel::Persist()
return true;
}
- const CPVRDatabasePtr database(CServiceBroker::GetPVRManager().GetTVDatabase());
+ const CPVRDatabasePtr database = CServiceBroker::GetPVRManager().GetTVDatabase();
if (database)
{
bool bReturn = database->Persist(*this, true);
+
CSingleLock lock(m_critSection);
m_bChanged = !bReturn;
return bReturn;
@@ -229,11 +229,9 @@ bool CPVRChannel::SetChannelID(int iChannelId)
CSingleLock lock(m_critSection);
if (m_iChannelId != iChannelId)
{
- /* update the id */
m_iChannelId = iChannelId;
SetChanged();
m_bChanged = true;
-
return true;
}
@@ -252,12 +250,10 @@ bool CPVRChannel::SetHidden(bool bIsHidden)
if (m_bIsHidden != bIsHidden)
{
- /* update the hidden flag */
m_bIsHidden = bIsHidden;
- m_bEPGEnabled = !bIsHidden;
+ m_bEPGEnabled = !bIsHidden;
SetChanged();
m_bChanged = true;
-
return true;
}
@@ -270,11 +266,9 @@ bool CPVRChannel::SetLocked(bool bIsLocked)
if (m_bIsLocked != bIsLocked)
{
- /* update the locked flag */
m_bIsLocked = bIsLocked;
SetChanged();
m_bChanged = true;
-
return true;
}
@@ -300,15 +294,13 @@ bool CPVRChannel::IsRecording(void) const
CPVRRecordingPtr CPVRChannel::GetRecording(void) const
{
- CPVREpgInfoTagPtr epgTag = GetEPGNow();
- return (epgTag && epgTag->HasRecording()) ?
- epgTag->Recording() :
- CPVRRecordingPtr();
+ const CPVREpgInfoTagPtr epgTag = GetEPGNow();
+ return (epgTag && epgTag->HasRecording()) ? epgTag->Recording() : CPVRRecordingPtr();
}
bool CPVRChannel::HasRecording(void) const
{
- CPVREpgInfoTagPtr epgTag = GetEPGNow();
+ const CPVREpgInfoTagPtr epgTag = GetEPGNow();
return epgTag && epgTag->HasRecording();
}
@@ -318,12 +310,10 @@ bool CPVRChannel::SetIconPath(const std::string &strIconPath, bool bIsUserSetIco
if (m_strIconPath != strIconPath)
{
- /* update the path */
m_strIconPath = StringUtils::Format("%s", strIconPath.c_str());
SetChanged();
m_bChanged = true;
m_bIsUserSetIcon = bIsUserSetIcon && !m_strIconPath.empty();
-
return true;
}
@@ -353,7 +343,6 @@ bool CPVRChannel::SetChannelName(const std::string &strChannelName, bool bIsUser
SetChanged();
m_bChanged = true;
-
return true;
}
@@ -364,12 +353,10 @@ bool CPVRChannel::SetLastWatched(time_t iLastWatched)
{
{
CSingleLock lock(m_critSection);
-
- if (m_iLastWatched != iLastWatched)
- m_iLastWatched = iLastWatched;
+ m_iLastWatched = iLastWatched;
}
- const CPVRDatabasePtr database(CServiceBroker::GetPVRManager().GetTVDatabase());
+ const CPVRDatabasePtr database = CServiceBroker::GetPVRManager().GetTVDatabase();
if (database)
return database->UpdateLastWatched(*this);
@@ -379,7 +366,7 @@ bool CPVRChannel::SetLastWatched(time_t iLastWatched)
bool CPVRChannel::IsEmpty() const
{
CSingleLock lock(m_critSection);
- return (m_strFileNameAndPath.empty());
+ return m_strFileNameAndPath.empty();
}
/********** Client related channel methods **********/
@@ -390,11 +377,9 @@ bool CPVRChannel::SetClientID(int iClientId)
if (m_iClientId != iClientId)
{
- /* update the client ID */
m_iClientId = iClientId;
SetChanged();
m_bChanged = true;
-
return true;
}
@@ -410,10 +395,10 @@ void CPVRChannel::UpdatePath(CPVRChannelGroupInternal* group)
if (client)
{
CSingleLock lock(m_critSection);
- std::string strFileNameAndPath = StringUtils::Format("%s%s_%d.pvr",
- group->GetPath(),
- client->ID().c_str(),
- m_iUniqueId);
+ const std::string strFileNameAndPath = StringUtils::Format("%s%s_%d.pvr",
+ group->GetPath(),
+ client->ID().c_str(),
+ m_iUniqueId);
if (m_strFileNameAndPath != strFileNameAndPath)
{
m_strFileNameAndPath = strFileNameAndPath;
@@ -536,11 +521,10 @@ void CPVRChannel::UpdateEncryptionName(void)
int CPVRChannel::GetEPG(CFileItemList &results) const
{
- CPVREpgPtr epg = GetEPG();
+ const CPVREpgPtr epg = GetEPG();
if (!epg)
{
- CLog::LogFC(LOGDEBUG, LOGPVR, "Cannot get EPG for channel '%s'",
- m_strChannelName.c_str());
+ CLog::LogFC(LOGDEBUG, LOGPVR, "Cannot get EPG for channel '%s'", m_strChannelName.c_str());
return -1;
}
@@ -549,7 +533,7 @@ int CPVRChannel::GetEPG(CFileItemList &results) const
bool CPVRChannel::ClearEPG() const
{
- CPVREpgPtr epg = GetEPG();
+ const CPVREpgPtr epg = GetEPG();
if (epg)
epg->Clear();
@@ -558,30 +542,32 @@ bool CPVRChannel::ClearEPG() const
CPVREpgInfoTagPtr CPVRChannel::GetEPGNow() const
{
- CPVREpgPtr epg = GetEPG();
+ CPVREpgInfoTagPtr tag;
+ const CPVREpgPtr epg = GetEPG();
if (epg)
- return epg->GetTagNow();
+ tag = epg->GetTagNow();
- CPVREpgInfoTagPtr empty;
- return empty;
+ return tag;
}
CPVREpgInfoTagPtr CPVRChannel::GetEPGNext() const
{
+ CPVREpgInfoTagPtr tag;
const CPVREpgPtr epg = GetEPG();
if (epg)
- return epg->GetTagNext();
+ tag = epg->GetTagNext();
- return CPVREpgInfoTagPtr();
+ return tag;
}
CPVREpgInfoTagPtr CPVRChannel::GetEPGPrevious() const
{
+ CPVREpgInfoTagPtr tag;
const CPVREpgPtr epg = GetEPG();
if (epg)
- return epg->GetTagPrevious();
+ tag = epg->GetTagPrevious();
- return CPVREpgInfoTagPtr();
+ return tag;
}
bool CPVRChannel::SetEPGEnabled(bool bEPGEnabled)
@@ -590,7 +576,6 @@ bool CPVRChannel::SetEPGEnabled(bool bEPGEnabled)
if (m_bEPGEnabled != bEPGEnabled)
{
- /* update the EPG flag */
m_bEPGEnabled = bEPGEnabled;
SetChanged();
m_bChanged = true;
@@ -613,7 +598,6 @@ bool CPVRChannel::SetEPGScraper(const std::string &strScraper)
{
bool bCleanEPG = !m_strEPGScraper.empty() || strScraper.empty();
- /* update the scraper name */
m_strEPGScraper = StringUtils::Format("%s", strScraper.c_str());
SetChanged();
m_bChanged = true;
@@ -675,8 +659,7 @@ bool CPVRChannel::IsLocked(void) const
std::string CPVRChannel::IconPath(void) const
{
CSingleLock lock(m_critSection);
- std::string strReturn(m_strIconPath);
- return strReturn;
+ return m_strIconPath;
}
bool CPVRChannel::IsUserSetIcon(void) const
@@ -740,22 +723,19 @@ const CPVRChannelNumber& CPVRChannel::ClientChannelNumber() const
std::string CPVRChannel::ClientChannelName(void) const
{
CSingleLock lock(m_critSection);
- std::string strReturn(m_strClientChannelName);
- return strReturn;
+ return m_strClientChannelName;
}
std::string CPVRChannel::InputFormat(void) const
{
CSingleLock lock(m_critSection);
- std::string strReturn(m_strInputFormat);
- return strReturn;
+ return m_strInputFormat;
}
std::string CPVRChannel::Path(void) const
{
CSingleLock lock(m_critSection);
- std::string strReturn(m_strFileNameAndPath);
- return strReturn;
+ return m_strFileNameAndPath;
}
bool CPVRChannel::IsEncrypted(void) const
@@ -773,8 +753,7 @@ int CPVRChannel::EncryptionSystem(void) const
std::string CPVRChannel::EncryptionName(void) const
{
CSingleLock lock(m_critSection);
- std::string strReturn(m_strClientEncryptionName);
- return strReturn;
+ return m_strClientEncryptionName;
}
int CPVRChannel::EpgID(void) const
@@ -804,8 +783,7 @@ bool CPVRChannel::EPGEnabled(void) const
std::string CPVRChannel::EPGScraper(void) const
{
CSingleLock lock(m_critSection);
- std::string strReturn(m_strEPGScraper);
- return strReturn;
+ return m_strEPGScraper;
}
bool CPVRChannel::CanRecord(void) const
diff --git a/xbmc/settings/Settings.cpp b/xbmc/settings/Settings.cpp
index b3f021b03f..0f50e170c4 100644
--- a/xbmc/settings/Settings.cpp
+++ b/xbmc/settings/Settings.cpp
@@ -216,6 +216,7 @@ const std::string CSettings::SETTING_PVRPLAYBACK_SWITCHTOFULLSCREEN = "pvrplayba
const std::string CSettings::SETTING_PVRPLAYBACK_SIGNALQUALITY = "pvrplayback.signalquality";
const std::string CSettings::SETTING_PVRPLAYBACK_CONFIRMCHANNELSWITCH = "pvrplayback.confirmchannelswitch";
const std::string CSettings::SETTING_PVRPLAYBACK_CHANNELENTRYTIMEOUT = "pvrplayback.channelentrytimeout";
+const std::string CSettings::SETTING_PVRPLAYBACK_DELAYMARKLASTWATCHED = "pvrplayback.delaymarklastwatched";
const std::string CSettings::SETTING_PVRPLAYBACK_FPS = "pvrplayback.fps";
const std::string CSettings::SETTING_PVRRECORD_INSTANTRECORDACTION = "pvrrecord.instantrecordaction";
const std::string CSettings::SETTING_PVRRECORD_INSTANTRECORDTIME = "pvrrecord.instantrecordtime";
diff --git a/xbmc/settings/Settings.h b/xbmc/settings/Settings.h
index 59a39679b6..29536d40af 100644
--- a/xbmc/settings/Settings.h
+++ b/xbmc/settings/Settings.h
@@ -176,6 +176,7 @@ public:
static const std::string SETTING_PVRPLAYBACK_SIGNALQUALITY;
static const std::string SETTING_PVRPLAYBACK_CONFIRMCHANNELSWITCH;
static const std::string SETTING_PVRPLAYBACK_CHANNELENTRYTIMEOUT;
+ static const std::string SETTING_PVRPLAYBACK_DELAYMARKLASTWATCHED;
static const std::string SETTING_PVRPLAYBACK_FPS;
static const std::string SETTING_PVRRECORD_INSTANTRECORDACTION;
static const std::string SETTING_PVRRECORD_INSTANTRECORDTIME;