aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphunkyfish <phunkyfish@gmail.com>2020-03-26 14:31:14 +0000
committerphunkyfish <phunkyfish@gmail.com>2020-03-26 16:19:21 +0000
commit1529964eadda19f1dd89b6ef9bccdbd3ef65e4d4 (patch)
treec24bfa2e08aec075af4364c38d2f6e3fc11686b1
parent970b5fa8c51fecf527df4a9b78f11cd2eaf27599 (diff)
[pvr] Recording sizes and folder total sizes, sorting and in progress callback
-rw-r--r--addons/skin.estuary/xml/DialogPVRInfo.xml2
-rw-r--r--addons/skin.estuary/xml/Includes_PVR.xml6
-rw-r--r--addons/skin.estuary/xml/Variables.xml7
-rw-r--r--xbmc/FileItem.cpp1
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h4
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_dll.h11
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_types.h3
-rw-r--r--xbmc/guilib/GUIListItem.cpp7
-rw-r--r--xbmc/guilib/GUIListItem.h1
-rw-r--r--xbmc/pvr/PVRManager.cpp11
-rw-r--r--xbmc/pvr/PVRManager.h5
-rw-r--r--xbmc/pvr/addons/PVRClient.cpp9
-rw-r--r--xbmc/pvr/addons/PVRClient.h18
-rw-r--r--xbmc/pvr/addons/PVRClients.cpp11
-rw-r--r--xbmc/pvr/addons/PVRClients.h6
-rw-r--r--xbmc/pvr/filesystem/PVRGUIDirectory.cpp13
-rw-r--r--xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp7
-rw-r--r--xbmc/pvr/recordings/PVRRecording.cpp58
-rw-r--r--xbmc/pvr/recordings/PVRRecording.h26
-rw-r--r--xbmc/pvr/recordings/PVRRecordings.cpp24
-rw-r--r--xbmc/pvr/recordings/PVRRecordings.h5
-rw-r--r--xbmc/pvr/windows/GUIViewStatePVR.cpp4
22 files changed, 232 insertions, 7 deletions
diff --git a/addons/skin.estuary/xml/DialogPVRInfo.xml b/addons/skin.estuary/xml/DialogPVRInfo.xml
index f843933bee..6a287f56ab 100644
--- a/addons/skin.estuary/xml/DialogPVRInfo.xml
+++ b/addons/skin.estuary/xml/DialogPVRInfo.xml
@@ -49,7 +49,7 @@
<width>1050</width>
<height>425</height>
<align>justify</align>
- <label>$INFO[ListItem.ChannelName,[B],[/B][CR]]$INFO[ListItem.Date,[COLOR grey]$LOCALIZE[552]:[/COLOR] ,[CR]]$INFO[ListItem.Duration,[COLOR grey]$LOCALIZE[180]:[/COLOR] ,[CR]]$VAR[PremieredLabel]$INFO[ListItem.Rating,[COLOR grey]$LOCALIZE[563]:[/COLOR] ,[CR]]$VAR[ExpirationDateTimeLabel]$INFO[ListItem.Genre,[COLOR grey]$LOCALIZE[515]:[/COLOR] ,[CR]]$INFO[ListItem.Writer,[COLOR grey]$LOCALIZE[20417]:[/COLOR] ,[CR]]$INFO[ListItem.Director,[COLOR grey]$LOCALIZE[20339]:[/COLOR] ,[CR]]$INFO[ListItem.Cast,[COLOR grey]$LOCALIZE[206]:[/COLOR] ,[CR]][CR]$INFO[ListItem.Plot]</label>
+ <label>$INFO[ListItem.ChannelName,[B],[/B][CR]]$INFO[ListItem.Date,[COLOR grey]$LOCALIZE[552]:[/COLOR] ,[CR]]$INFO[ListItem.Duration,[COLOR grey]$LOCALIZE[180]:[/COLOR] ,[CR]]$VAR[RecordingSizeLabel]$VAR[PremieredLabel]$INFO[ListItem.Rating,[COLOR grey]$LOCALIZE[563]:[/COLOR] ,[CR]]$VAR[ExpirationDateTimeLabel]$INFO[ListItem.Genre,[COLOR grey]$LOCALIZE[515]:[/COLOR] ,[CR]]$INFO[ListItem.Writer,[COLOR grey]$LOCALIZE[20417]:[/COLOR] ,[CR]]$INFO[ListItem.Director,[COLOR grey]$LOCALIZE[20339]:[/COLOR] ,[CR]]$INFO[ListItem.Cast,[COLOR grey]$LOCALIZE[206]:[/COLOR] ,[CR]][CR]$INFO[ListItem.Plot]</label>
<autoscroll time="3000" delay="4000" repeat="5000">Skin.HasSetting(AutoScroll)</autoscroll>
</control>
<control type="grouplist" id="9000">
diff --git a/addons/skin.estuary/xml/Includes_PVR.xml b/addons/skin.estuary/xml/Includes_PVR.xml
index 39b732fc33..dd4440410a 100644
--- a/addons/skin.estuary/xml/Includes_PVR.xml
+++ b/addons/skin.estuary/xml/Includes_PVR.xml
@@ -288,7 +288,7 @@
<top>10</top>
<width>830</width>
<height>262</height>
- <label>$LOCALIZE[19076] ($INFO[Container(5000).NumItems,[B],[/B] $LOCALIZE[31036]])</label>
+ <label>$LOCALIZE[19076] ($INFO[Container(5000).NumItems,[B],[/B] $LOCALIZE[31036]]) $INFO[ListItem.Property(recordingsize),- $LOCALIZE[20161]: [B],[/B]]</label>
<font>font37</font>
<visible>!ListItem.IsParentFolder</visible>
</control>
@@ -307,7 +307,7 @@
<height>90</height>
<width>830</width>
<aligny>center</aligny>
- <label>$INFO[ListItem.Date,[COLOR grey],[/COLOR][CR]]$INFO[ListItem.Label]$INFO[ListItem.EpisodeName, (,)]</label>
+ <label>$VAR[RecordingDateSizeLabel]$INFO[ListItem.Label]$INFO[ListItem.EpisodeName, (,)]</label>
<shadowcolor>text_shadow</shadowcolor>
</control>
</focusedlayout>
@@ -317,7 +317,7 @@
<height>90</height>
<width>830</width>
<aligny>center</aligny>
- <label>$INFO[ListItem.Date,[COLOR grey],[/COLOR][CR]]$INFO[ListItem.Label]$INFO[ListItem.EpisodeName, (,)]</label>
+ <label>$VAR[RecordingDateSizeLabel]$INFO[ListItem.Label]$INFO[ListItem.EpisodeName, (,)]</label>
<shadowcolor>text_shadow</shadowcolor>
</control>
</itemlayout>
diff --git a/addons/skin.estuary/xml/Variables.xml b/addons/skin.estuary/xml/Variables.xml
index 550cc26952..a1cc43ed3d 100644
--- a/addons/skin.estuary/xml/Variables.xml
+++ b/addons/skin.estuary/xml/Variables.xml
@@ -488,6 +488,13 @@
<value condition="ListItem.IsNew + String.IsEmpty(ListItem.Season) + String.IsEmpty(ListItem.Episode) + String.IsEmpty(ListItem.EpisodeName)">[B][COLOR button_focus]$LOCALIZE[842][/COLOR][/B]</value>
<value condition="ListItem.IsNew">[B][COLOR button_focus]$LOCALIZE[842][/COLOR][/B] - </value>
</variable>
+ <variable name="RecordingSizeLabel">
+ <value condition="!String.IsEmpty(ListItem.Size) + !String.IsEqual(ListItem.Size,0 B)">$INFO[ListItem.Size,[COLOR grey]$LOCALIZE[22031]:[/COLOR] ,[CR]]</value>
+ </variable>
+ <variable name="RecordingDateSizeLabel">
+ <value condition="!String.IsEmpty(ListItem.Size) + !String.IsEqual(ListItem.Size,0 B)">$INFO[ListItem.Date,[COLOR grey],[/COLOR]]$INFO[ListItem.Size, (,)[CR]]</value>
+ <value>$INFO[ListItem.Date,[COLOR grey],[/COLOR][CR]]</value>
+ </variable>
<variable name="ExpirationDateTimeLabel">
<value condition="!String.IsEmpty(ListItem.ExpirationDate)">[COLOR grey]$LOCALIZE[19299]:[/COLOR] $INFO[ListItem.ExpirationDate] $INFO[ListItem.ExpirationTime][CR]</value>
</variable>
diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp
index 1a7ad35f27..9f61e78746 100644
--- a/xbmc/FileItem.cpp
+++ b/xbmc/FileItem.cpp
@@ -216,6 +216,7 @@ CFileItem::CFileItem(const std::shared_ptr<CPVRRecording>& record)
m_strPath = record->m_strFileNameAndPath;
SetLabel(record->m_strTitle);
m_dateTime = record->RecordingTimeAsLocalTime();
+ m_dwSize = record->GetSizeInBytes();
// Set art
if (!record->m_strIconPath.empty())
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h
index 3ee44121d5..2ecc14d092 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/versions.h
@@ -97,8 +97,8 @@
#define ADDON_INSTANCE_VERSION_PERIPHERAL_DEPENDS "addon-instance/Peripheral.h" \
"addon-instance/PeripheralUtils.h"
-#define ADDON_INSTANCE_VERSION_PVR "6.2.0"
-#define ADDON_INSTANCE_VERSION_PVR_MIN "6.2.0"
+#define ADDON_INSTANCE_VERSION_PVR "6.3.0"
+#define ADDON_INSTANCE_VERSION_PVR_MIN "6.3.0"
#define ADDON_INSTANCE_VERSION_PVR_XML_ID "kodi.binary.instance.pvr"
#define ADDON_INSTANCE_VERSION_PVR_DEPENDS "xbmc_pvr_dll.h" \
"xbmc_pvr_types.h" \
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_dll.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_dll.h
index 26e9099a71..d48d6da204 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_dll.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_dll.h
@@ -344,6 +344,16 @@ extern "C"
PVR_ERROR GetRecordingEdl(const PVR_RECORDING& recording, PVR_EDL_ENTRY edl[], int *size);
/*!
+ * Retrieve the size of a recording on the backend.
+ * @param[in] recording in: The recording to get the size in bytes for.
+ * @param[out] sizeInBytes out: The size in bytes of the recording
+ * @return PVR_ERROR_NO_ERROR if the recording's size has been set successfully.
+ * @remarks Required if bSupportsRecordingSize is set to true.
+ * Return PVR_ERROR_NOT_IMPLEMENTED if this add-on won't provide this function.
+ */
+ PVR_ERROR GetRecordingSize(const PVR_RECORDING* recording, int64_t* sizeInBytes);
+
+ /*!
* Retrieve the timer types supported by the backend.
* @param types out: The function has to write the definition of the supported timer types into this array.
* @param typesCount in: The maximum size of the list, out: the actual size of the list. default: PVR_ADDON_TIMERTYPE_ARRAY_SIZE
@@ -732,6 +742,7 @@ extern "C"
pClient->toAddon.SetRecordingLastPlayedPosition = SetRecordingLastPlayedPosition;
pClient->toAddon.GetRecordingLastPlayedPosition = GetRecordingLastPlayedPosition;
pClient->toAddon.GetRecordingEdl = GetRecordingEdl;
+ pClient->toAddon.GetRecordingSize = GetRecordingSize;
pClient->toAddon.GetTimerTypes = GetTimerTypes;
pClient->toAddon.GetTimersAmount = GetTimersAmount;
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_types.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_types.h
index d88ce5986d..0c16e07fc8 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_types.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/xbmc_pvr_types.h
@@ -316,6 +316,7 @@ extern "C" {
bool bSupportsRecordingsLifetimeChange; /*!< @brief true if the backend supports changing lifetime for recordings. */
bool bSupportsDescrambleInfo; /*!< @brief true if the backend supports descramble information for playing channels. */
bool bSupportsAsyncEPGTransfer; /*!< @brief true if this addon-on supports asynchronous transfer of epg events to Kodi using the callback function EpgEventStateChange. */
+ bool bSupportsRecordingSize; /*!< @brief true if this addon-on supports retrieving size of recordings. */
unsigned int iRecordingsLifetimesSize; /*!< @brief (required) Count of possible values for PVR_RECORDING.iLifetime. 0 means lifetime is not supported for recordings or no own value definition wanted, but to use Kodi defaults of 1..365. */
PVR_ATTRIBUTE_INT_VALUE recordingsLifetimeValues[PVR_ADDON_ATTRIBUTE_VALUES_ARRAY_SIZE]; /*!< @brief (optional) Array containing the possible values for PVR_RECORDING.iLifetime. Must be filled if iLifetimesSize > 0 */
@@ -575,6 +576,7 @@ extern "C" {
PVR_RECORDING_CHANNEL_TYPE channelType; /*!< @brief (optional) channel type. Set to PVR_RECORDING_CHANNEL_TYPE_UNKNOWN if the type cannot be determined. */
char strFirstAired[PVR_ADDON_DATE_STRING_LENGTH]; /*!< @brief (optional) first aired date of this recording. Used only for display purposes. Specify in W3C date format "YYYY-MM-DD". */
unsigned int iFlags; /*!< @brief (optional) bit field of independent flags associated with the recording */
+ int64_t sizeInBytes; /*!< @brief (optional) size of the recording in bytes */
} ATTRIBUTE_PACKED PVR_RECORDING;
/*!
@@ -689,6 +691,7 @@ extern "C" {
PVR_ERROR (__cdecl* SetRecordingLastPlayedPosition)(const PVR_RECORDING&, int);
int (__cdecl* GetRecordingLastPlayedPosition)(const PVR_RECORDING&);
PVR_ERROR (__cdecl* GetRecordingEdl)(const PVR_RECORDING&, PVR_EDL_ENTRY[], int*);
+ PVR_ERROR (__cdecl* GetRecordingSize)(const PVR_RECORDING*, int64_t*);
PVR_ERROR (__cdecl* GetTimerTypes)(PVR_TIMER_TYPE[], int*);
int (__cdecl* GetTimersAmount)(void);
PVR_ERROR (__cdecl* GetTimers)(ADDON_HANDLE);
diff --git a/xbmc/guilib/GUIListItem.cpp b/xbmc/guilib/GUIListItem.cpp
index 6e0ab9f239..e815e4da33 100644
--- a/xbmc/guilib/GUIListItem.cpp
+++ b/xbmc/guilib/GUIListItem.cpp
@@ -410,6 +410,13 @@ void CGUIListItem::IncrementProperty(const std::string &strKey, int nVal)
SetProperty(strKey, i);
}
+void CGUIListItem::IncrementProperty(const std::string& strKey, int64_t nVal)
+{
+ int64_t i = GetProperty(strKey).asInteger();
+ i += nVal;
+ SetProperty(strKey, i);
+}
+
void CGUIListItem::IncrementProperty(const std::string &strKey, double dVal)
{
double d = GetProperty(strKey).asDouble();
diff --git a/xbmc/guilib/GUIListItem.h b/xbmc/guilib/GUIListItem.h
index 56ab46cfc4..1693ba933e 100644
--- a/xbmc/guilib/GUIListItem.h
+++ b/xbmc/guilib/GUIListItem.h
@@ -140,6 +140,7 @@ public:
void SetProperty(const std::string &strKey, const CVariant &value);
void IncrementProperty(const std::string &strKey, int nVal);
+ void IncrementProperty(const std::string& strKey, int64_t nVal);
void IncrementProperty(const std::string &strKey, double dVal);
void ClearProperties();
diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp
index 65a53e8303..118e28b951 100644
--- a/xbmc/pvr/PVRManager.cpp
+++ b/xbmc/pvr/PVRManager.cpp
@@ -531,6 +531,10 @@ void CPVRManager::Process()
/* try to play channel on startup */
TriggerPlayChannelOnStartup();
}
+
+ if (m_addons->AnyClientSupportingRecordingsSize())
+ TriggerRecordingsSizeInProgressUpdate();
+
/* execute the next pending jobs if there are any */
try
{
@@ -758,6 +762,13 @@ void CPVRManager::TriggerRecordingsUpdate()
});
}
+void CPVRManager::TriggerRecordingsSizeInProgressUpdate()
+{
+ m_pendingUpdates->Append("pvr-update-recordings-size", [this]() {
+ return Recordings()->UpdateInProgressSize();
+ });
+}
+
void CPVRManager::TriggerTimersUpdate()
{
m_pendingUpdates->Append("pvr-update-timers", [this]() {
diff --git a/xbmc/pvr/PVRManager.h b/xbmc/pvr/PVRManager.h
index 351f499ab3..c94dd4db54 100644
--- a/xbmc/pvr/PVRManager.h
+++ b/xbmc/pvr/PVRManager.h
@@ -266,6 +266,11 @@ namespace PVR
void TriggerRecordingsUpdate();
/*!
+ * @brief Let the background thread update the size for any in progress recordings.
+ */
+ void TriggerRecordingsSizeInProgressUpdate();
+
+ /*!
* @brief Let the background thread update the timer list.
*/
void TriggerTimersUpdate();
diff --git a/xbmc/pvr/addons/PVRClient.cpp b/xbmc/pvr/addons/PVRClient.cpp
index ed4e501019..31048dcde4 100644
--- a/xbmc/pvr/addons/PVRClient.cpp
+++ b/xbmc/pvr/addons/PVRClient.cpp
@@ -923,6 +923,15 @@ PVR_ERROR CPVRClient::GetRecordingEdl(const CPVRRecording& recording, std::vecto
}, m_clientCapabilities.SupportsRecordingsEdl());
}
+PVR_ERROR CPVRClient::GetRecordingSize(const CPVRRecording& recording, int64_t& sizeInBytes)
+{
+ return DoAddonCall(__FUNCTION__, [&recording, &sizeInBytes](const AddonInstance* addon) {
+ PVR_RECORDING tag;
+ WriteClientRecordingInfo(recording, tag);
+ return addon->GetRecordingSize(&tag, &sizeInBytes);
+ }, m_clientCapabilities.SupportsRecordingsSize());
+}
+
PVR_ERROR CPVRClient::GetTimersAmount(int& iTimers)
{
iTimers = -1;
diff --git a/xbmc/pvr/addons/PVRClient.h b/xbmc/pvr/addons/PVRClient.h
index e3c89d40e0..433fbaa153 100644
--- a/xbmc/pvr/addons/PVRClient.h
+++ b/xbmc/pvr/addons/PVRClient.h
@@ -181,6 +181,16 @@ namespace PVR
*/
void GetRecordingsLifetimeValues(std::vector<std::pair<std::string, int>>& list) const;
+ /*!
+ * @brief Check whether this add-on supports retrieving the size recordings..
+ * @return True if supported, false otherwise.
+ */
+ bool SupportsRecordingsSize() const
+ {
+ return m_addonCapabilities && m_addonCapabilities->bSupportsRecordings &&
+ m_addonCapabilities->bSupportsRecordingSize;
+ }
+
/////////////////////////////////////////////////////////////////////////////////
//
// Streams
@@ -551,6 +561,14 @@ namespace PVR
PVR_ERROR GetRecordingEdl(const CPVRRecording& recording, std::vector<PVR_EDL_ENTRY>& edls);
/*!
+ * @brief Retrieve the size of a recording on the backend.
+ * @param recording The recording.
+ * @param sizeInBytes The size in bytes
+ * @return PVR_ERROR_NO_ERROR on success, respective error code otherwise.
+ */
+ PVR_ERROR GetRecordingSize(const CPVRRecording& recording, int64_t& sizeInBytes);
+
+ /*!
* @brief Retrieve the edit decision list (EDL) from the backend.
* @param epgTag The EPG tag.
* @param edls The edit decision list (empty on error).
diff --git a/xbmc/pvr/addons/PVRClients.cpp b/xbmc/pvr/addons/PVRClients.cpp
index 52aff6b9a4..1d6ad65b66 100644
--- a/xbmc/pvr/addons/PVRClients.cpp
+++ b/xbmc/pvr/addons/PVRClients.cpp
@@ -552,6 +552,17 @@ std::vector<std::shared_ptr<CPVRClient>> CPVRClients::GetClientsSupportingChanne
return possibleSettingsClients;
}
+bool CPVRClients::AnyClientSupportingRecordingsSize() const
+{
+ std::vector<std::shared_ptr<CPVRClient>> recordingSizeClients;
+ ForCreatedClients(__FUNCTION__, [&recordingSizeClients](const std::shared_ptr<CPVRClient>& client) {
+ if (client->GetClientCapabilities().SupportsRecordingsSize())
+ recordingSizeClients.emplace_back(client);
+ return PVR_ERROR_NO_ERROR;
+ });
+ return recordingSizeClients.size() != 0;
+}
+
void CPVRClients::OnSystemSleep()
{
ForCreatedClients(__FUNCTION__, [](const std::shared_ptr<CPVRClient>& client) {
diff --git a/xbmc/pvr/addons/PVRClients.h b/xbmc/pvr/addons/PVRClients.h
index 6a5f41d387..1b3dcd8ea1 100644
--- a/xbmc/pvr/addons/PVRClients.h
+++ b/xbmc/pvr/addons/PVRClients.h
@@ -267,6 +267,12 @@ namespace PVR
*/
std::vector<std::shared_ptr<CPVRClient>> GetClientsSupportingChannelSettings(bool bRadio) const;
+ /*!
+ * @brief Get whether or not any client supports recording size.
+ * @return True if any client supports recording size.
+ */
+ bool AnyClientSupportingRecordingsSize() const;
+
//@}
/*! @name Power management methods */
diff --git a/xbmc/pvr/filesystem/PVRGUIDirectory.cpp b/xbmc/pvr/filesystem/PVRGUIDirectory.cpp
index f2d2ec95cf..5d6daa2991 100644
--- a/xbmc/pvr/filesystem/PVRGUIDirectory.cpp
+++ b/xbmc/pvr/filesystem/PVRGUIDirectory.cpp
@@ -205,6 +205,7 @@ void GetSubDirectories(const CPVRRecordingsPath& recParentPath,
item->SetProperty("totalepisodes", 0);
item->SetProperty("watchedepisodes", 0);
item->SetProperty("unwatchedepisodes", 0);
+ item->SetProperty("sizeinbytes", UINT64_C(0));
// Assume all folders are watched, we'll change the overlay later
item->SetOverlayImage(CGUIListItem::ICON_OVERLAY_WATCHED, false);
@@ -230,6 +231,18 @@ void GetSubDirectories(const CPVRRecordingsPath& recParentPath,
item->SetLabel2(StringUtils::Format("%s / %s",
item->GetProperty("watchedepisodes").asString().c_str(),
item->GetProperty("totalepisodes").asString().c_str()));
+
+ item->IncrementProperty("sizeinbytes", recording->GetSizeInBytes());
+ }
+
+ // Replace the incremental size of the recordings with a string equivalent
+ for (auto& item : results.GetList())
+ {
+ int64_t size = item->GetProperty("sizeinbytes").asInteger();
+ item->ClearProperty("sizeinbytes");
+ item->m_dwSize = size; // We'll also sort recording folders by size
+ if (size > 0)
+ item->SetProperty("recordingsize", StringUtils::SizeToString(size));
}
// Change the watched overlay to unwatched for folders containing unwatched entries
diff --git a/xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp b/xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp
index b46ba337bf..5b125c276d 100644
--- a/xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp
+++ b/xbmc/pvr/guilib/guiinfo/PVRGUIInfo.cpp
@@ -441,6 +441,13 @@ bool CPVRGUIInfo::GetListItemAndPlayerLabel(const CFileItem* item, const CGUIInf
return true;
}
return false;
+ case LISTITEM_SIZE:
+ if (recording->GetSizeInBytes() > 0)
+ {
+ strValue = StringUtils::SizeToString(recording->GetSizeInBytes());
+ return true;
+ }
+ return false;
}
return false;
}
diff --git a/xbmc/pvr/recordings/PVRRecording.cpp b/xbmc/pvr/recordings/PVRRecording.cpp
index 394fdc8db9..0d0e68c172 100644
--- a/xbmc/pvr/recordings/PVRRecording.cpp
+++ b/xbmc/pvr/recordings/PVRRecording.cpp
@@ -97,6 +97,7 @@ CPVRRecording::CPVRRecording(const PVR_RECORDING& recording, unsigned int iClien
if (strlen(recording.strFirstAired) > 0)
m_firstAired.SetFromW3CDateTime(recording.strFirstAired);
m_iFlags = recording.iFlags;
+ m_sizeInBytes = recording.sizeInBytes;
SetGenre(recording.iGenreType, recording.iGenreSubType, recording.strGenreDescription);
CVideoInfoTag::SetPlayCount(recording.iPlayCount);
@@ -137,6 +138,7 @@ CPVRRecording::CPVRRecording(const PVR_RECORDING& recording, unsigned int iClien
bool CPVRRecording::operator ==(const CPVRRecording& right) const
{
+ CSingleLock lock(m_critSection);
return (this == &right) ||
(m_strRecordingId == right.m_strRecordingId &&
m_iClientId == right.m_iClientId &&
@@ -166,7 +168,8 @@ bool CPVRRecording::operator ==(const CPVRRecording& right) const
m_iGenreType == right.m_iGenreType &&
m_iGenreSubType == right.m_iGenreSubType &&
m_firstAired == right.m_firstAired &&
- m_iFlags == right.m_iFlags);
+ m_iFlags == right.m_iFlags &&
+ m_sizeInBytes == right.m_sizeInBytes);
}
bool CPVRRecording::operator !=(const CPVRRecording& right) const
@@ -199,6 +202,15 @@ void CPVRRecording::Serialize(CVariant& value) const
value["art"]["fanart"] = m_strFanartPath;
}
+void CPVRRecording::ToSortable(SortItem& sortable, Field field) const
+{
+ CSingleLock lock(m_critSection);
+ if (field == FieldSize)
+ sortable[FieldSize] = m_sizeInBytes;
+ else
+ CVideoInfoTag::ToSortable(sortable, field);
+}
+
void CPVRRecording::Reset()
{
m_strRecordingId .clear();
@@ -220,6 +232,10 @@ void CPVRRecording::Reset()
m_iChannelUid = PVR_CHANNEL_INVALID_UID;
m_bRadio = false;
m_iFlags = PVR_RECORDING_FLAG_UNDEFINED;
+ {
+ CSingleLock lock(m_critSection);
+ m_sizeInBytes = 0;
+ }
m_recordingTime.Reset();
CVideoInfoTag::Reset();
@@ -315,6 +331,30 @@ CBookmark CPVRRecording::GetResumePoint() const
return CVideoInfoTag::GetResumePoint();
}
+bool CPVRRecording::UpdateRecordingSize()
+{
+ const std::shared_ptr<CPVRClient> client = CServiceBroker::GetPVRManager().GetClient(m_iClientId);
+ if (client && client->GetClientCapabilities().SupportsRecordingsSize() &&
+ m_recordingSizeRefetchTimeout.IsTimePast())
+ {
+ // @todo: root cause should be fixed. details: https://github.com/xbmc/xbmc/pull/14961
+ m_recordingSizeRefetchTimeout.Set(10000); // update size from backend at most every 10 secs
+
+ int64_t sizeInBytes = -1;
+ client->GetRecordingSize(*this, sizeInBytes);
+
+ CSingleLock lock(m_critSection);
+ if (sizeInBytes >= 0 && sizeInBytes != m_sizeInBytes)
+ {
+ CSingleLock lock(m_critSection);
+ m_sizeInBytes = sizeInBytes;
+ return true;
+ }
+ }
+
+ return false;
+}
+
void CPVRRecording::UpdateMetadata(CVideoDatabase& db)
{
if (m_bGotMetaData || !db.IsOpen())
@@ -372,6 +412,10 @@ void CPVRRecording::Update(const CPVRRecording& tag)
m_bRadio = tag.m_bRadio;
m_firstAired = tag.m_firstAired;
m_iFlags = tag.m_iFlags;
+ {
+ CSingleLock lock(m_critSection);
+ m_sizeInBytes = tag.m_sizeInBytes;
+ }
CVideoInfoTag::SetPlayCount(tag.GetLocalPlayCount());
CVideoInfoTag::SetResumePoint(tag.GetLocalResumePoint());
@@ -555,3 +599,15 @@ bool CPVRRecording::IsFinale() const
{
return (m_iFlags & PVR_RECORDING_FLAG_IS_FINALE) > 0;
}
+
+int64_t CPVRRecording::GetSizeInBytes() const
+{
+ CSingleLock lock(m_critSection);
+ return m_sizeInBytes;
+}
+
+void CPVRRecording::SetSizeInBytes(int64_t sizeInBytes)
+{
+ CSingleLock lock(m_critSection);
+ m_sizeInBytes = sizeInBytes;
+}
diff --git a/xbmc/pvr/recordings/PVRRecording.h b/xbmc/pvr/recordings/PVRRecording.h
index 599c38fc45..a2149788e7 100644
--- a/xbmc/pvr/recordings/PVRRecording.h
+++ b/xbmc/pvr/recordings/PVRRecording.h
@@ -25,6 +25,7 @@
*/
#include "XBDateTime.h"
+#include "threads/CriticalSection.h"
#include "threads/SystemClock.h"
#include "video/Bookmark.h"
#include "video/VideoInfoTag.h"
@@ -87,6 +88,9 @@ namespace PVR
void Serialize(CVariant& value) const override;
+ // ISortable implementation
+ void ToSortable(SortItem& sortable, Field field) const override;
+
/*!
* @brief Reset this tag to it's initial state.
*/
@@ -160,6 +164,12 @@ namespace PVR
CBookmark GetResumePoint() const override;
/*!
+ * @brief Update this recording's size. The value will be obtained from the backend if it supports server-side size retrieval.
+ * @return true if the the updated value is differnt, false otherwise.
+ */
+ bool UpdateRecordingSize();
+
+ /*!
* @brief Get this recording's local resume point. The value will not be obtained from the backend even if it supports server-side resume points.
* @return the resume point.
*/
@@ -353,6 +363,18 @@ namespace PVR
*/
unsigned int Flags() const { return m_iFlags; }
+ /*!
+ * @brief Return the size of this recording in bytes.
+ * @return the size in bytes.
+ */
+ int64_t GetSizeInBytes() const;
+
+ /*!
+ * @brief set the size in bytes of this recording
+ * @param sizeInBytes The size in bytes
+ */
+ void SetSizeInBytes(int64_t sizeInBytes);
+
private:
CDateTime m_recordingTime; /*!< start time of the recording */
bool m_bGotMetaData;
@@ -364,7 +386,11 @@ namespace PVR
int m_iGenreSubType = 0; /*!< genre subtype */
mutable XbmcThreads::EndTime m_resumePointRefetchTimeout;
unsigned int m_iFlags = 0; /*!< the flags applicable to this recording */
+ mutable XbmcThreads::EndTime m_recordingSizeRefetchTimeout;
+ int64_t m_sizeInBytes = 0; /*!< the size of the recording in bytes */
void UpdatePath();
+
+ mutable CCriticalSection m_critSection;
};
}
diff --git a/xbmc/pvr/recordings/PVRRecordings.cpp b/xbmc/pvr/recordings/PVRRecordings.cpp
index 17f0e5e5cd..4626283e63 100644
--- a/xbmc/pvr/recordings/PVRRecordings.cpp
+++ b/xbmc/pvr/recordings/PVRRecordings.cpp
@@ -76,6 +76,30 @@ void CPVRRecordings::Update()
CServiceBroker::GetPVRManager().PublishEvent(PVREvent::RecordingsInvalidated);
}
+void CPVRRecordings::UpdateInProgressSize()
+{
+ CSingleLock lock(m_critSection);
+ if (m_bIsUpdating)
+ return;
+ m_bIsUpdating = true;
+
+ CLog::LogFC(LOGDEBUG, LOGPVR, "Updating recordings size");
+ bool bHaveUpdatedInProgessRecording = false;
+ for (auto& recording : m_recordings)
+ {
+ if (recording.second->IsInProgress())
+ {
+ if (recording.second->UpdateRecordingSize())
+ bHaveUpdatedInProgessRecording = true;
+ }
+ }
+
+ m_bIsUpdating = false;
+
+ if (bHaveUpdatedInProgessRecording)
+ CServiceBroker::GetPVRManager().PublishEvent(PVREvent::RecordingsInvalidated);
+}
+
int CPVRRecordings::GetNumTVRecordings() const
{
CSingleLock lock(m_critSection);
diff --git a/xbmc/pvr/recordings/PVRRecordings.h b/xbmc/pvr/recordings/PVRRecordings.h
index 086bdbfd5a..b28b3ce581 100644
--- a/xbmc/pvr/recordings/PVRRecordings.h
+++ b/xbmc/pvr/recordings/PVRRecordings.h
@@ -48,6 +48,11 @@ namespace PVR
*/
void Update();
+ /*!
+ * @brief refresh the size of any in progress recordings from the clients.
+ */
+ void UpdateInProgressSize();
+
int GetNumTVRecordings() const;
bool HasDeletedTVRecordings() const;
int GetNumRadioRecordings() const;
diff --git a/xbmc/pvr/windows/GUIViewStatePVR.cpp b/xbmc/pvr/windows/GUIViewStatePVR.cpp
index 6fff308b57..05a9d78939 100644
--- a/xbmc/pvr/windows/GUIViewStatePVR.cpp
+++ b/xbmc/pvr/windows/GUIViewStatePVR.cpp
@@ -10,6 +10,8 @@
#include "FileItem.h"
#include "ServiceBroker.h"
+#include "pvr/PVRManager.h"
+#include "pvr/addons/PVRClients.h"
#include "pvr/recordings/PVRRecordingsPath.h"
#include "pvr/timers/PVRTimersPath.h"
#include "settings/Settings.h"
@@ -45,6 +47,8 @@ CGUIViewStateWindowPVRRecordings::CGUIViewStateWindowPVRRecordings(const int win
AddSortMethod(SortByDate, 552, LABEL_MASKS("%L", "%d", "%L", "%d")); // "Date" : Filename, DateTime | Foldername, DateTime
AddSortMethod(SortByTime, 180, LABEL_MASKS("%L", "%D", "%L", "")); // "Duration" : Filename, Duration | Foldername, empty
AddSortMethod(SortByFile, 561, LABEL_MASKS("%L", "%d", "%L", "")); // "File" : Filename, DateTime | Foldername, empty
+ if (CServiceBroker::GetPVRManager().Clients()->AnyClientSupportingRecordingsSize())
+ AddSortMethod(SortBySize, 553, LABEL_MASKS("%L", "%I", "%L", "%I")); // "Size" : Filename, DateTime | Foldername, empty
// Default sorting
SetSortMethod(SortByDate);