1 /* 2 * Copyright (C) 2012-2018 Team Kodi 3 * This file is part of Kodi - https://kodi.tv 4 * 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 * See LICENSES/README.md for more information. 7 */ 8 9 #pragma once 10 11 /* 12 * DESCRIPTION: 13 * 14 * CPVRRecordingInfoTag is part of the Kodi PVR system to support recording entrys, 15 * stored on a other Backend like VDR or MythTV. 16 * 17 * The recording information tag holds data about name, length, recording time 18 * and so on of recorded stream stored on the backend. 19 * 20 * The filename string is used to by the PVRManager and passed to VideoPlayer 21 * to stream data from the backend to Kodi. 22 * 23 * It is a also CVideoInfoTag and some of his variables must be set! 24 * 25 */ 26 27 #include "XBDateTime.h" 28 #include "threads/CriticalSection.h" 29 #include "threads/SystemClock.h" 30 #include "video/Bookmark.h" 31 #include "video/VideoInfoTag.h" 32 33 #include <memory> 34 #include <string> 35 #include <vector> 36 37 class CVideoDatabase; 38 39 struct PVR_EDL_ENTRY; 40 struct PVR_RECORDING; 41 42 namespace PVR 43 { 44 class CPVRChannel; 45 class CPVRClient; 46 class CPVRTimerInfoTag; 47 48 /*! 49 * @brief Representation of a CPVRRecording unique ID. 50 */ 51 class CPVRRecordingUid final 52 { 53 public: 54 int m_iClientId; /*!< ID of the backend */ 55 std::string m_strRecordingId; /*!< unique ID of the recording on the client */ 56 57 CPVRRecordingUid(int iClientId, const std::string& strRecordingId); 58 59 bool operator >(const CPVRRecordingUid& right) const; 60 bool operator <(const CPVRRecordingUid& right) const; 61 bool operator ==(const CPVRRecordingUid& right) const; 62 bool operator !=(const CPVRRecordingUid& right) const; 63 }; 64 65 class CPVRRecording final : public CVideoInfoTag 66 { 67 public: 68 int m_iClientId; /*!< ID of the backend */ 69 std::string m_strRecordingId; /*!< unique ID of the recording on the client */ 70 std::string m_strChannelName; /*!< name of the channel this was recorded from */ 71 int m_iPriority; /*!< priority of this recording */ 72 int m_iLifetime; /*!< lifetime of this recording */ 73 std::string m_strDirectory; /*!< directory of this recording on the client */ 74 std::string m_strIconPath; /*!< icon path */ 75 std::string m_strThumbnailPath; /*!< thumbnail path */ 76 std::string m_strFanartPath; /*!< fanart path */ 77 unsigned m_iRecordingId; /*!< id that won't change while xbmc is running */ 78 79 CPVRRecording(); 80 CPVRRecording(const PVR_RECORDING& recording, unsigned int iClientId); 81 82 private: 83 CPVRRecording(const CPVRRecording& tag) = delete; 84 CPVRRecording& operator =(const CPVRRecording& other) = delete; 85 86 public: 87 bool operator ==(const CPVRRecording& right) const; 88 bool operator !=(const CPVRRecording& right) const; 89 90 void Serialize(CVariant& value) const override; 91 92 // ISortable implementation 93 void ToSortable(SortItem& sortable, Field field) const override; 94 95 /*! 96 * @brief Reset this tag to it's initial state. 97 */ 98 void Reset(); 99 100 /*! 101 * @brief Delete this recording on the client (if supported). 102 * @return True if it was deleted successfully, false otherwise. 103 */ 104 bool Delete(); 105 106 /*! 107 * @brief Undelete this recording on the client (if supported). 108 * @return True if it was undeleted successfully, false otherwise. 109 */ 110 bool Undelete(); 111 112 /*! 113 * @brief Rename this recording on the client (if supported). 114 * @param strNewName The new name. 115 * @return True if it was renamed successfully, false otherwise. 116 */ 117 bool Rename(const std::string& strNewName); 118 119 /*! 120 * @brief Set this recording's play count. The value will be transferred to the backend if it supports server-side play counts. 121 * @param count play count. 122 * @return True if play count was set successfully, false otherwise. 123 */ 124 bool SetPlayCount(int count) override; 125 126 /*! 127 * @brief Increment this recording's play count. The value will be transferred to the backend if it supports server-side play counts. 128 * @return True if play count was increased successfully, false otherwise. 129 */ 130 bool IncrementPlayCount() override; 131 132 /*! 133 * @brief Set this recording's play count without transferring the value to the backend, even if it supports server-side play counts. 134 * @param count play count. 135 * @return True if play count was set successfully, false otherwise. 136 */ SetLocalPlayCount(int count)137 bool SetLocalPlayCount(int count) { return CVideoInfoTag::SetPlayCount(count); } 138 139 /*! 140 * @brief Get this recording's local play count. The value will not be obtained from the backend, even if it supports server-side play counts. 141 * @return the play count. 142 */ GetLocalPlayCount()143 int GetLocalPlayCount() const { return CVideoInfoTag::GetPlayCount(); } 144 145 /*! 146 * @brief Set this recording's resume point. The value will be transferred to the backend if it supports server-side resume points. 147 * @param resumePoint resume point. 148 * @return True if resume point was set successfully, false otherwise. 149 */ 150 bool SetResumePoint(const CBookmark& resumePoint) override; 151 152 /*! 153 * @brief Set this recording's resume point. The value will be transferred to the backend if it supports server-side resume points. 154 * @param timeInSeconds the time of the resume point 155 * @param totalTimeInSeconds the total time of the video 156 * @param playerState the player state 157 * @return True if resume point was set successfully, false otherwise. 158 */ 159 bool SetResumePoint(double timeInSeconds, double totalTimeInSeconds, const std::string& playerState = "") override; 160 161 /*! 162 * @brief Get this recording's resume point. The value will be obtained from the backend if it supports server-side resume points. 163 * @return the resume point. 164 */ 165 CBookmark GetResumePoint() const override; 166 167 /*! 168 * @brief Update this recording's size. The value will be obtained from the backend if it supports server-side size retrieval. 169 * @return true if the the updated value is differnt, false otherwise. 170 */ 171 bool UpdateRecordingSize(); 172 173 /*! 174 * @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. 175 * @return the resume point. 176 */ GetLocalResumePoint()177 CBookmark GetLocalResumePoint() const { return CVideoInfoTag::GetResumePoint(); } 178 179 /*! 180 * @brief Retrieve the edit decision list (EDL) of a recording on the backend. 181 * @return The edit decision list (empty on error) 182 */ 183 std::vector<PVR_EDL_ENTRY> GetEdl() const; 184 185 /*! 186 * @brief Get the resume point and play count from the database if the 187 * client doesn't handle it itself. 188 * @param db The database to read the data from. 189 * @param client The client this recording belongs to. 190 */ 191 void UpdateMetadata(CVideoDatabase& db, const CPVRClient& client); 192 193 /*! 194 * @brief Update this tag with the contents of the given tag. 195 * @param tag The new tag info. 196 * @param client The client this recording belongs to. 197 */ 198 void Update(const CPVRRecording& tag, const CPVRClient& client); 199 200 /*! 201 * @brief Retrieve the recording start as UTC time 202 * @return the recording start time 203 */ RecordingTimeAsUTC()204 const CDateTime& RecordingTimeAsUTC() const { return m_recordingTime; } 205 206 /*! 207 * @brief Retrieve the recording start as local time 208 * @return the recording start time 209 */ 210 const CDateTime& RecordingTimeAsLocalTime() const; 211 212 /*! 213 * @brief Retrieve the recording end as UTC time 214 * @return the recording end time 215 */ 216 CDateTime EndTimeAsUTC() const; 217 218 /*! 219 * @brief Retrieve the recording end as local time 220 * @return the recording end time 221 */ 222 CDateTime EndTimeAsLocalTime() const; 223 224 /*! 225 * @brief Check whether this recording has an expiration time 226 * @return True if the recording has an expiration time, false otherwise 227 */ HasExpirationTime()228 bool HasExpirationTime() const { return m_iLifetime > 0; } 229 230 /*! 231 * @brief Retrieve the recording expiration time as local time 232 * @return the recording expiration time 233 */ 234 CDateTime ExpirationTimeAsLocalTime() const; 235 236 /*! 237 * @brief Check whether this recording will immediately expire if the given lifetime value would be set 238 * @param iLifetime The lifetime value to check 239 * @return True if the recording would immediately expire, false otherwiese 240 */ 241 bool WillBeExpiredWithNewLifetime(int iLifetime) const; 242 243 /*! 244 * @brief Retrieve the recording title from the URL path 245 * @param url the URL for the recording 246 * @return Title of the recording 247 */ 248 static std::string GetTitleFromURL(const std::string& url); 249 250 /*! 251 * @brief If deleted but can be undeleted it is true 252 */ IsDeleted()253 bool IsDeleted() const { return m_bIsDeleted; } 254 255 /*! 256 * @brief Check whether this is a tv or radio recording 257 * @return true if this is a radio recording, false if this is a tv recording 258 */ IsRadio()259 bool IsRadio() const { return m_bRadio; } 260 261 /*! 262 * @return Broadcast id of the EPG event associated with this recording or EPG_TAG_INVALID_UID 263 */ BroadcastUid()264 unsigned int BroadcastUid() const { return m_iEpgEventId; } 265 266 /*! 267 * @return Get the channel on which this recording is/was running 268 * @note Only works if the recording has a channel uid provided by the add-on 269 */ 270 std::shared_ptr<CPVRChannel> Channel() const; 271 272 /*! 273 * @brief Get the uid of the channel on which this recording is/was running 274 * @return the uid of the channel or PVR_CHANNEL_INVALID_UID 275 */ 276 int ChannelUid() const; 277 278 /*! 279 * @brief the identifier of the client that serves this recording 280 * @return the client identifier 281 */ 282 int ClientID() const; 283 284 /*! 285 * @brief Retrieve the recording Episode Name 286 * @note Returns an empty string if no Episode Name was provided by the PVR client 287 */ EpisodeName()288 std::string EpisodeName() const { return m_strShowTitle; } 289 290 /*! 291 * @brief check whether this recording is currently in progress 292 * @return true if the recording is in progress, false otherwise 293 */ 294 bool IsInProgress() const; 295 296 /*! 297 * @brief return the timer for an in-progress recording, if any 298 * @return the timer if the recording is in progress, nullptr otherwise 299 */ 300 std::shared_ptr<CPVRTimerInfoTag> GetRecordingTimer() const; 301 302 /*! 303 * @brief set the genre for this recording. 304 * @param iGenreType The genre type ID. If set to EPG_GENRE_USE_STRING, set genre to the value provided with strGenre. Otherwise, compile the genre string from the values given by iGenreType and iGenreSubType 305 * @param iGenreSubType The genre subtype ID 306 * @param strGenre The genre 307 */ 308 void SetGenre(int iGenreType, int iGenreSubType, const std::string& strGenre); 309 310 /*! 311 * @brief Get the genre type ID of this recording. 312 * @return The genre type ID. 313 */ GenreType()314 int GenreType() const { return m_iGenreType; } 315 316 /*! 317 * @brief Get the genre subtype ID of this recording. 318 * @return The genre subtype ID. 319 */ GenreSubType()320 int GenreSubType() const { return m_iGenreSubType; } 321 322 /*! 323 * @brief Get the genre as human readable string. 324 * @return The genre. 325 */ Genre()326 const std::vector<std::string> Genre() const { return m_genre; } 327 328 /*! 329 * @brief Get the genre(s) of this recording as formatted string. 330 * @return The genres label. 331 */ 332 const std::string GetGenresLabel() const; 333 334 /*! 335 * @brief Get the first air date of this recording. 336 * @return The first air date. 337 */ 338 CDateTime FirstAired() const; 339 340 /*! 341 * @brief Get the premiere year of this recording. 342 * @return The premiere year 343 */ 344 int GetYear() const override; 345 346 /*! 347 * @brief Set the premiere year of this recording. 348 * @param year The premiere year 349 */ 350 void SetYear(int year) override; 351 352 /*! 353 * @brief Check if the premiere year of this recording is valid 354 * @return True if the recording has as valid premiere date, false otherwise 355 */ 356 bool HasYear() const override; 357 358 /*! 359 * @brief Check whether this recording will be flagged as new. 360 * @return True if this recording will be flagged as new, false otherwise 361 */ 362 bool IsNew() const; 363 364 /*! 365 * @brief Check whether this recording will be flagged as a premiere. 366 * @return True if this recording will be flagged as a premiere, false otherwise 367 */ 368 bool IsPremiere() const; 369 370 /*! 371 * @brief Check whether this recording will be flagged as a finale. 372 * @return True if this recording will be flagged as a finale, false otherwise 373 */ 374 bool IsFinale() const; 375 376 /*! 377 * @brief Check whether this recording will be flagged as live. 378 * @return True if this recording will be flagged as live, false otherwise 379 */ 380 bool IsLive() const; 381 382 /*! 383 * @brief Return the flags (PVR_RECORDING_FLAG_*) of this recording as a bitfield. 384 * @return the flags. 385 */ Flags()386 unsigned int Flags() const { return m_iFlags; } 387 388 /*! 389 * @brief Return the size of this recording in bytes. 390 * @return the size in bytes. 391 */ 392 int64_t GetSizeInBytes() const; 393 394 /*! 395 * @brief Mark a recording as dirty/clean. 396 * @param bDirty true to mark as dirty, false to mark as clean. 397 */ SetDirty(bool bDirty)398 void SetDirty(bool bDirty) { m_bDirty = bDirty; } 399 400 /*! 401 * @brief Return whether the recording is marked dirty. 402 * @return true if dirty, false otherwise. 403 */ IsDirty()404 bool IsDirty() const { return m_bDirty; } 405 406 private: 407 void UpdatePath(); 408 409 CDateTime m_recordingTime; /*!< start time of the recording */ 410 bool m_bGotMetaData; 411 bool m_bIsDeleted; /*!< set if entry is a deleted recording which can be undelete */ 412 unsigned int m_iEpgEventId; /*!< epg broadcast id associated with this recording */ 413 int m_iChannelUid; /*!< channel uid associated with this recording */ 414 bool m_bRadio; /*!< radio or tv recording */ 415 int m_iGenreType = 0; /*!< genre type */ 416 int m_iGenreSubType = 0; /*!< genre subtype */ 417 mutable XbmcThreads::EndTime m_resumePointRefetchTimeout; 418 unsigned int m_iFlags = 0; /*!< the flags applicable to this recording */ 419 mutable XbmcThreads::EndTime m_recordingSizeRefetchTimeout; 420 int64_t m_sizeInBytes = 0; /*!< the size of the recording in bytes */ 421 bool m_bDirty = false; 422 423 mutable CCriticalSection m_critSection; 424 }; 425 } 426