From 5098d0de9f5471d460fa651c6169b87caa927964 Mon Sep 17 00:00:00 2001 From: Christian Fetzer Date: Fri, 20 Apr 2012 00:04:46 +0200 Subject: [PATCH] PVR mark as watched: added SetRecordingPlayCount (API) with client capability and watched flag in PVRRecording(s). Allow read/write play count from/to client using context menu. Mapped watched overlay to client play count instead of using video database (if supported by client). --- xbmc/addons/include/xbmc_pvr_dll.h | 9 +++++ xbmc/addons/include/xbmc_pvr_types.h | 3 ++ xbmc/pvr/addons/PVRClient.cpp | 52 ++++++++++++++++++++------ xbmc/pvr/addons/PVRClient.h | 8 ++++ xbmc/pvr/addons/PVRClients.cpp | 12 ++++++ xbmc/pvr/addons/PVRClients.h | 9 +++++ xbmc/pvr/recordings/PVRRecording.cpp | 19 +++++++++- xbmc/pvr/recordings/PVRRecording.h | 8 ++++ xbmc/pvr/recordings/PVRRecordings.cpp | 15 +++++++- xbmc/pvrclients/MediaPortal/client.cpp | 2 + xbmc/pvrclients/mythtv/client.cpp | 1 + xbmc/pvrclients/pvr-demo/client.cpp | 1 + xbmc/pvrclients/tvheadend/client.cpp | 1 + xbmc/pvrclients/vdr-vnsi/client.cpp | 1 + 14 files changed, 126 insertions(+), 15 deletions(-) diff --git a/xbmc/addons/include/xbmc_pvr_dll.h b/xbmc/addons/include/xbmc_pvr_dll.h index 8c9941648f221..b62156f2629c7 100644 --- a/xbmc/addons/include/xbmc_pvr_dll.h +++ b/xbmc/addons/include/xbmc_pvr_dll.h @@ -201,6 +201,14 @@ extern "C" */ PVR_ERROR RenameRecording(const PVR_RECORDING &recording); + /*! + * @brief Set the play count of a recording on the backend. + * @param recording The recording to change the play count. + * @param count Play count. + * @return PVR_ERROR_NO_ERROR if the recording's play count has been set successfully. + */ + PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING &recording, int count); + //@} /** @name PVR timer methods */ //@{ @@ -406,6 +414,7 @@ extern "C" pClient->GetRecordings = GetRecordings; pClient->DeleteRecording = DeleteRecording; pClient->RenameRecording = RenameRecording; + pClient->SetRecordingPlayCount = SetRecordingPlayCount; pClient->GetTimersAmount = GetTimersAmount; pClient->GetTimers = GetTimers; diff --git a/xbmc/addons/include/xbmc_pvr_types.h b/xbmc/addons/include/xbmc_pvr_types.h index 61616098dcb15..98610fa8ccda0 100644 --- a/xbmc/addons/include/xbmc_pvr_types.h +++ b/xbmc/addons/include/xbmc_pvr_types.h @@ -158,6 +158,7 @@ extern "C" { bool bHandlesInputStream; /*!< @brief (optional) true if this add-on provides an input stream. false if XBMC handles the stream. */ bool bHandlesDemuxing; /*!< @brief (optional) true if this add-on demultiplexes packets. */ bool bSupportsRecordingFolders; /*!< @brief (optional) true if the backend supports timers / recordings in folders. */ + bool bSupportsRecordingPlayCount; /*!< @brief (optional) true if the backend supports play count for recordings. */ } ATTRIBUTE_PACKED PVR_ADDON_CAPABILITIES; /*! @@ -310,6 +311,7 @@ extern "C" { int iLifetime; /*!< @brief (optional) life time in days of this recording */ int iGenreType; /*!< @brief (optional) genre type */ int iGenreSubType; /*!< @brief (optional) genre sub type */ + bool iPlayCount; /*!< @brief (optional) play count of this recording on the client */ } ATTRIBUTE_PACKED PVR_RECORDING; /*! @@ -358,6 +360,7 @@ extern "C" { PVR_ERROR (__cdecl* GetRecordings)(PVR_HANDLE handle); PVR_ERROR (__cdecl* DeleteRecording)(const PVR_RECORDING &recording); PVR_ERROR (__cdecl* RenameRecording)(const PVR_RECORDING &recording); + PVR_ERROR (__cdecl* SetRecordingPlayCount)(const PVR_RECORDING &recording, int count); //@} /** @name PVR timer methods */ diff --git a/xbmc/pvr/addons/PVRClient.cpp b/xbmc/pvr/addons/PVRClient.cpp index 31977e5f80231..3378752297863 100644 --- a/xbmc/pvr/addons/PVRClient.cpp +++ b/xbmc/pvr/addons/PVRClient.cpp @@ -85,18 +85,19 @@ void CPVRClient::ResetProperties(void) void CPVRClient::ResetAddonCapabilities(void) { - m_addonCapabilities.bSupportsChannelSettings = false; - m_addonCapabilities.bSupportsTimeshift = false; - m_addonCapabilities.bSupportsEPG = false; - m_addonCapabilities.bSupportsTV = false; - m_addonCapabilities.bSupportsRadio = false; - m_addonCapabilities.bSupportsRecordings = false; - m_addonCapabilities.bSupportsTimers = false; - m_addonCapabilities.bSupportsChannelGroups = false; - m_addonCapabilities.bSupportsChannelScan = false; - m_addonCapabilities.bHandlesInputStream = false; - m_addonCapabilities.bHandlesDemuxing = false; - m_addonCapabilities.bSupportsRecordingFolders = false; + m_addonCapabilities.bSupportsChannelSettings = false; + m_addonCapabilities.bSupportsTimeshift = false; + m_addonCapabilities.bSupportsEPG = false; + m_addonCapabilities.bSupportsTV = false; + m_addonCapabilities.bSupportsRadio = false; + m_addonCapabilities.bSupportsRecordings = false; + m_addonCapabilities.bSupportsTimers = false; + m_addonCapabilities.bSupportsChannelGroups = false; + m_addonCapabilities.bSupportsChannelScan = false; + m_addonCapabilities.bHandlesInputStream = false; + m_addonCapabilities.bHandlesDemuxing = false; + m_addonCapabilities.bSupportsRecordingFolders = false; + m_addonCapabilities.bSupportsRecordingPlayCount = false; } bool CPVRClient::Create(int iClientId) @@ -632,6 +633,33 @@ PVR_ERROR CPVRClient::RenameRecording(const CPVRRecording &recording) return retVal; } +PVR_ERROR CPVRClient::SetRecordingPlayCount(const CPVRRecording &recording, int count) +{ + PVR_ERROR retVal = PVR_ERROR_UNKNOWN; + if (!m_bReadyToUse) + return retVal; + + if (!m_addonCapabilities.bSupportsRecordingPlayCount) + return PVR_ERROR_NOT_IMPLEMENTED; + + try + { + PVR_RECORDING tag; + PVRWriteClientRecordingInfo(recording, tag); + + retVal = m_pStruct->SetRecordingPlayCount(tag, count); + + LogError(retVal, __FUNCTION__); + } + catch (exception &e) + { + CLog::Log(LOGERROR, "PVRClient - %s - exception '%s' caught while trying to call SetRecordingPlayCount() on addon '%s'. please contact the developer of this addon: %s", + __FUNCTION__, e.what(), GetFriendlyName().c_str(), Author().c_str()); + } + + return retVal; +} + int CPVRClient::GetTimersAmount(void) { int iReturn = -1; diff --git a/xbmc/pvr/addons/PVRClient.h b/xbmc/pvr/addons/PVRClient.h index 4fccb3c2347ab..ab9a05009ce29 100644 --- a/xbmc/pvr/addons/PVRClient.h +++ b/xbmc/pvr/addons/PVRClient.h @@ -256,6 +256,14 @@ namespace PVR */ PVR_ERROR RenameRecording(const CPVRRecording &recording); + /*! + * @brief Set the play count of a recording on the backend. + * @param recording The recording to set the play count. + * @param count Play count. + * @return PVR_ERROR_NO_ERROR if the recording's play count has been set successfully. + */ + PVR_ERROR SetRecordingPlayCount(const CPVRRecording &recording, int count); + //@} /** @name PVR timer methods */ //@{ diff --git a/xbmc/pvr/addons/PVRClients.cpp b/xbmc/pvr/addons/PVRClients.cpp index ab15faa036384..4f5ee3915710b 100644 --- a/xbmc/pvr/addons/PVRClients.cpp +++ b/xbmc/pvr/addons/PVRClients.cpp @@ -798,6 +798,18 @@ bool CPVRClients::DeleteRecording(const CPVRRecording &recording, PVR_ERROR *err return *error == PVR_ERROR_NO_ERROR; } +bool CPVRClients::SetRecordingPlayCount(const CPVRRecording &recording, int count, PVR_ERROR *error) +{ + *error = PVR_ERROR_UNKNOWN; + boost::shared_ptr client; + if (GetConnectedClient(recording.m_iClientId, client) && client->GetAddonCapabilities().bSupportsRecordingPlayCount) + *error = client->SetRecordingPlayCount(recording, count); + else + CLog::Log(LOGERROR, "PVR - %s - client %d does not support setting recording's play count",__FUNCTION__, recording.m_iClientId); + + return *error == PVR_ERROR_NO_ERROR; +} + bool CPVRClients::IsRecordingOnPlayingChannel(void) const { CPVRChannel currentChannel; diff --git a/xbmc/pvr/addons/PVRClients.h b/xbmc/pvr/addons/PVRClients.h index a48f0615a1976..2055dcd5a6374 100644 --- a/xbmc/pvr/addons/PVRClients.h +++ b/xbmc/pvr/addons/PVRClients.h @@ -464,6 +464,15 @@ namespace PVR */ bool DeleteRecording(const CPVRRecording &recording, PVR_ERROR *error); + /*! + * @brief Set play count of a recording on the backend. + * @param recording The recording to set the play count. + * @param count Play count. + * @param error An error if it occured. + * @return True if the recording's play count was set successfully, false otherwise. + */ + bool SetRecordingPlayCount(const CPVRRecording &recording, int count, PVR_ERROR *error); + /*! * @brief Check whether there is an active recording on the current channel. * @return True if there is, false otherwise. diff --git a/xbmc/pvr/recordings/PVRRecording.cpp b/xbmc/pvr/recordings/PVRRecording.cpp index 3b47c72a92e05..40969191d4dbd 100644 --- a/xbmc/pvr/recordings/PVRRecording.cpp +++ b/xbmc/pvr/recordings/PVRRecording.cpp @@ -53,6 +53,7 @@ CPVRRecording::CPVRRecording(const PVR_RECORDING &recording, unsigned int iClien m_strStreamURL = recording.strStreamURL; m_strChannelName = recording.strChannelName; m_genre = StringUtils::Split(CEpg::ConvertGenreIdToString(recording.iGenreType, recording.iGenreSubType), g_advancedSettings.m_videoItemSeparator); + m_iRecPlayCount = recording.iPlayCount; } bool CPVRRecording::operator ==(const CPVRRecording& right) const @@ -70,7 +71,8 @@ bool CPVRRecording::operator ==(const CPVRRecording& right) const m_iLifetime == right.m_iLifetime && m_strDirectory == right.m_strDirectory && m_strFileNameAndPath == right.m_strFileNameAndPath && - m_strTitle == right.m_strTitle); + m_strTitle == right.m_strTitle && + m_iRecPlayCount == right.m_iRecPlayCount); } bool CPVRRecording::operator !=(const CPVRRecording& right) const @@ -88,6 +90,7 @@ void CPVRRecording::Reset(void) m_iPriority = -1; m_iLifetime = -1; m_strFileNameAndPath = StringUtils::EmptyString; + m_iRecPlayCount = 0; m_recordingTime.Reset(); CVideoInfoTag::Reset(); @@ -126,6 +129,19 @@ bool CPVRRecording::Rename(const CStdString &strNewName) return true; } +bool CPVRRecording::SetPlayCount(int count) +{ + PVR_ERROR error; + m_iRecPlayCount = count; + if (!g_PVRClients->SetRecordingPlayCount(*this, count, &error)) + { + DisplayError(error); + return false; + } + + return true; +} + void CPVRRecording::DisplayError(PVR_ERROR err) const { if (err == PVR_ERROR_SERVER_ERROR) @@ -155,6 +171,7 @@ void CPVRRecording::Update(const CPVRRecording &tag) m_strStreamURL = tag.m_strStreamURL; m_strChannelName = tag.m_strChannelName; m_genre = tag.m_genre; + m_iRecPlayCount = tag.m_iRecPlayCount; CStdString strShow; strShow.Format("%s - ", g_localizeStrings.Get(20364).c_str()); diff --git a/xbmc/pvr/recordings/PVRRecording.h b/xbmc/pvr/recordings/PVRRecording.h index fc8bc687fb3b4..2740904895346 100644 --- a/xbmc/pvr/recordings/PVRRecording.h +++ b/xbmc/pvr/recordings/PVRRecording.h @@ -53,6 +53,7 @@ namespace PVR int m_iLifetime; /*!< lifetime of this recording */ CStdString m_strStreamURL; /*!< stream URL. if empty use pvr client */ CStdString m_strDirectory; /*!< directory of this recording on the client */ + bool m_iRecPlayCount; /*!< play count of this recording on the client */ CPVRRecording(void); CPVRRecording(const PVR_RECORDING &recording, unsigned int iClientId); @@ -85,6 +86,13 @@ namespace PVR */ bool Rename(const CStdString &strNewName); + /*! + * @brief Set this recording's play count on the client (if supported). + * @param count play count. + * @return True if play count was set successfully, false otherwise. + */ + bool SetPlayCount(int count); + /*! * @brief Update this tag with the contents of the given tag. * @param tag The new tag info. diff --git a/xbmc/pvr/recordings/PVRRecordings.cpp b/xbmc/pvr/recordings/PVRRecordings.cpp index f1c18c891077f..4c9593833bc07 100644 --- a/xbmc/pvr/recordings/PVRRecordings.cpp +++ b/xbmc/pvr/recordings/PVRRecordings.cpp @@ -106,9 +106,18 @@ void CPVRRecordings::GetContents(const CStdString &strDirectory, CFileItemList * pFileItem->SetLabel2(current->RecordingTimeAsLocalTime().GetAsLocalizedDateTime(true, false)); pFileItem->m_dateTime = current->RecordingTimeAsLocalTime(); pFileItem->SetPath(current->m_strFileNameAndPath); - CVideoDatabase db; - if (db.Open()) + + // Set the play count either directly from client (if supported) or from video db + if (g_PVRClients->GetAddonCapabilities(pFileItem->GetPVRRecordingInfoTag()->m_iClientId).bSupportsRecordingPlayCount) + { + pFileItem->GetPVRRecordingInfoTag()->m_playCount=pFileItem->GetPVRRecordingInfoTag()->m_iRecPlayCount; + } + else + { + CVideoDatabase db; + if (db.Open()) pFileItem->GetPVRRecordingInfoTag()->m_playCount=db.GetPlayCount(*pFileItem); + } pFileItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, pFileItem->GetPVRRecordingInfoTag()->m_playCount > 0); results->Add(pFileItem); @@ -292,6 +301,8 @@ bool CPVRRecordings::SetRecordingsPlayCount(const CFileItemPtr &item, int count) continue; } + pItem->GetPVRRecordingInfoTag()->SetPlayCount(count); + // Clear resume bookmark if (count > 0) database.ClearBookMarksOfFile(pItem->GetPath(), CBookmark::RESUME); diff --git a/xbmc/pvrclients/MediaPortal/client.cpp b/xbmc/pvrclients/MediaPortal/client.cpp index 193fb2513c133..f0e9a92e496d3 100644 --- a/xbmc/pvrclients/MediaPortal/client.cpp +++ b/xbmc/pvrclients/MediaPortal/client.cpp @@ -731,4 +731,6 @@ long long SeekLiveStream(long long pos, int whence) { return -1; } long long PositionLiveStream(void) { return -1; } long long LengthLiveStream(void) { return -1 ; } +PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING &recording, int count) { return PVR_ERROR_NOT_IMPLEMENTED; } + } //end extern "C" diff --git a/xbmc/pvrclients/mythtv/client.cpp b/xbmc/pvrclients/mythtv/client.cpp index 95f7c32db8c40..8bff584c27176 100644 --- a/xbmc/pvrclients/mythtv/client.cpp +++ b/xbmc/pvrclients/mythtv/client.cpp @@ -478,5 +478,6 @@ long long SeekLiveStream(long long iPosition, int iWhence) { return -1; } long long PositionLiveStream(void) { return -1; } long long LengthLiveStream(void) { return -1; } const char * GetLiveStreamURL(const PVR_CHANNEL &channelinfo) { return ""; } +PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING &recording, int count) { return PVR_ERROR_NOT_IMPLEMENTED; } } //end extern "C" diff --git a/xbmc/pvrclients/pvr-demo/client.cpp b/xbmc/pvrclients/pvr-demo/client.cpp index e6c6d430ccb58..0df69fc2b9784 100644 --- a/xbmc/pvrclients/pvr-demo/client.cpp +++ b/xbmc/pvrclients/pvr-demo/client.cpp @@ -280,6 +280,7 @@ int GetRecordingsAmount(void) { return -1; } PVR_ERROR GetRecordings(PVR_HANDLE handle) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR DeleteRecording(const PVR_RECORDING &recording) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR RenameRecording(const PVR_RECORDING &recording) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING &recording, int count) { return PVR_ERROR_NOT_IMPLEMENTED; } int GetTimersAmount(void) { return -1; } PVR_ERROR GetTimers(PVR_HANDLE handle) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR AddTimer(const PVR_TIMER &timer) { return PVR_ERROR_NOT_IMPLEMENTED; } diff --git a/xbmc/pvrclients/tvheadend/client.cpp b/xbmc/pvrclients/tvheadend/client.cpp index a1ddda510563f..7666d30c912ea 100644 --- a/xbmc/pvrclients/tvheadend/client.cpp +++ b/xbmc/pvrclients/tvheadend/client.cpp @@ -551,4 +551,5 @@ long long SeekLiveStream(long long iPosition, int iWhence /* = SEEK_SET */) { re long long PositionLiveStream(void) { return -1; } long long LengthLiveStream(void) { return -1; } const char * GetLiveStreamURL(const PVR_CHANNEL &channel) { return ""; } +PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING &recording, int count) { return PVR_ERROR_NOT_IMPLEMENTED; } } diff --git a/xbmc/pvrclients/vdr-vnsi/client.cpp b/xbmc/pvrclients/vdr-vnsi/client.cpp index 0c891edf90a64..099b64c3a3ea4 100644 --- a/xbmc/pvrclients/vdr-vnsi/client.cpp +++ b/xbmc/pvrclients/vdr-vnsi/client.cpp @@ -638,5 +638,6 @@ long long SeekLiveStream(long long iPosition, int iWhence /* = SEEK_SET */) { re long long PositionLiveStream(void) { return -1; } long long LengthLiveStream(void) { return -1; } const char * GetLiveStreamURL(const PVR_CHANNEL &channel) { return ""; } +PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING &recording, int count) { return PVR_ERROR_NOT_IMPLEMENTED; } }