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 #include "XBDateTime.h" 12 #include "pvr/channels/PVRChannelNumber.h" 13 #include "pvr/channels/PVRChannelsPath.h" 14 #include "settings/lib/ISettingCallback.h" 15 #include "utils/EventStream.h" 16 17 #include <map> 18 #include <memory> 19 #include <string> 20 #include <utility> 21 #include <vector> 22 23 struct PVR_CHANNEL_GROUP; 24 25 namespace PVR 26 { 27 #define PVR_GROUP_TYPE_DEFAULT 0 28 #define PVR_GROUP_TYPE_INTERNAL 1 29 #define PVR_GROUP_TYPE_USER_DEFINED 2 30 31 enum class PVREvent; 32 33 class CPVRChannel; 34 class CPVREpgInfoTag; 35 36 struct PVRChannelGroupMember 37 { 38 PVRChannelGroupMember() = default; 39 PVRChannelGroupMemberPVRChannelGroupMember40 PVRChannelGroupMember(const std::shared_ptr<CPVRChannel>& _channel, 41 const CPVRChannelNumber& _channelNumber, 42 int _iClientPriority, 43 int _iOrder, 44 const CPVRChannelNumber& _clientChannelNumber) 45 : channel(_channel), 46 channelNumber(_channelNumber), 47 clientChannelNumber(_clientChannelNumber), 48 iClientPriority(_iClientPriority), 49 iOrder(_iOrder) 50 { 51 } 52 53 std::shared_ptr<CPVRChannel> channel; 54 CPVRChannelNumber channelNumber; // the channel number this channel has in the group 55 CPVRChannelNumber clientChannelNumber; // the client channel number this channel has in the group 56 int iClientPriority = 0; 57 int iOrder = 0; // The value denoting the order of this member in the group 58 }; 59 60 enum EpgDateType 61 { 62 EPG_FIRST_DATE = 0, 63 EPG_LAST_DATE = 1 64 }; 65 66 enum RenumberMode 67 { 68 NORMAL = 0, 69 IGNORE_NUMBERING_FROM_ONE = 1 70 }; 71 72 class CPVRChannelGroup : public ISettingCallback 73 { 74 friend class CPVRChannelGroupInternal; 75 friend class CPVRDatabase; 76 77 public: 78 static const int INVALID_GROUP_ID = -1; 79 80 /*! 81 * @brief Create a new channel group instance. 82 * @param path The channel group path. 83 * @param iGroupId The database ID of this group or INVALID_GROUP_ID if the group was not yet stored in the database. 84 * @param allChannelsGroup The channel group containing all TV or radio channels. 85 */ 86 CPVRChannelGroup(const CPVRChannelsPath& path, 87 int iGroupId = INVALID_GROUP_ID, 88 const std::shared_ptr<CPVRChannelGroup>& allChannelsGroup = {}); 89 90 /*! 91 * @brief Create a new channel group instance from a channel group provided by an add-on. 92 * @param group The channel group provided by the add-on. 93 * @param allChannelsGroup The channel group containing all TV or radio channels. 94 */ 95 CPVRChannelGroup(const PVR_CHANNEL_GROUP& group, const std::shared_ptr<CPVRChannelGroup>& allChannelsGroup); 96 97 ~CPVRChannelGroup() override; 98 99 bool operator ==(const CPVRChannelGroup& right) const; 100 bool operator !=(const CPVRChannelGroup& right) const; 101 102 /** 103 * Empty group member 104 */ 105 static std::shared_ptr<PVRChannelGroupMember> EmptyMember; 106 107 /*! 108 * @brief Query the events available for CEventStream 109 */ Events()110 CEventStream<PVREvent>& Events() { return m_events; } 111 112 /*! 113 * @brief Load the channels from the database. 114 * @param channelsToRemove Returns the channels to be removed from all groups, if any 115 * @return True when loaded successfully, false otherwise. 116 */ 117 virtual bool Load(std::vector<std::shared_ptr<CPVRChannel>>& channelsToRemove); 118 119 /*! 120 * @return The amount of group members 121 */ 122 size_t Size() const; 123 124 /*! 125 * @brief Refresh the channel list from the clients. 126 * @param channelsToRemove Returns the channels to be removed from all groups, if any 127 */ 128 virtual bool Update(std::vector<std::shared_ptr<CPVRChannel>>& channelsToRemove); 129 130 /*! 131 * @brief Get the path of this group. 132 * @return the path. 133 */ 134 const CPVRChannelsPath& GetPath() const; 135 136 /*! 137 * @brief Set the path of this group. 138 * @param the path. 139 */ 140 void SetPath(const CPVRChannelsPath& path); 141 142 /*! 143 * @brief Change the channelnumber of a group. Used by CGUIDialogPVRChannelManager. Call SortByChannelNumber() and Renumber() after all changes are done. 144 * @param channel The channel to change the channel number for. 145 * @param channelNumber The new channel number. 146 */ 147 bool SetChannelNumber(const std::shared_ptr<CPVRChannel>& channel, const CPVRChannelNumber& channelNumber); 148 149 /*! 150 * @brief Remove a channel from this container. 151 * @param channel The channel to remove. 152 * @return True if the channel was found and removed, false otherwise. 153 */ 154 virtual bool RemoveFromGroup(const std::shared_ptr<CPVRChannel>& channel); 155 156 /*! 157 * @brief Add a channel to this container. 158 * @param channel The channel to add. 159 * @param channelNumber The channel number of the channel to add. Use empty channel number if it's to be generated. 160 * @param iOrder The value denoting the order of this member in the group, 0 if unknown and needs to be generated 161 * @param bUseBackendChannelNumbers True, if channelNumber contains a backend channel number. 162 * @param clientChannelNumber The client channel number of the channel to add. (optional) 163 * @return True if the channel was added, false otherwise. 164 */ 165 virtual bool AddToGroup(const std::shared_ptr<CPVRChannel>& channel, const CPVRChannelNumber& channelNumber, int iOrder, bool bUseBackendChannelNumbers, const CPVRChannelNumber& clientChannelNumber = {}); 166 167 /*! 168 * @brief Append a channel to this container. 169 * @param channel The channel to append. 170 * @return True if the channel was appended, false otherwise. 171 */ 172 virtual bool AppendToGroup(const std::shared_ptr<CPVRChannel>& channel); 173 174 /*! 175 * @brief Change the name of this group. 176 * @param strGroupName The new group name. 177 */ 178 void SetGroupName(const std::string& strGroupName); 179 180 /*! 181 * @brief Persist changed or new data. 182 * @return True if the channel was persisted, false otherwise. 183 */ 184 bool Persist(); 185 186 /*! 187 * @brief Check whether a channel is in this container. 188 * @param channel The channel to find. 189 * @return True if the channel was found, false otherwise. 190 */ 191 virtual bool IsGroupMember(const std::shared_ptr<CPVRChannel>& channel) const; 192 193 /*! 194 * @brief Check whether a channel is in this container. 195 * @param iChannelId The db id of the channel to find. 196 * @return True if the channel was found, false otherwise. 197 */ 198 virtual bool IsGroupMember(int iChannelId) const; 199 200 /*! 201 * @brief Check if this group is the internal group containing all channels. 202 * @return True if it's the internal group, false otherwise. 203 */ IsInternalGroup()204 virtual bool IsInternalGroup() const { return m_iGroupType == PVR_GROUP_TYPE_INTERNAL; } 205 206 /*! 207 * @brief True if this group holds radio channels, false if it holds TV channels. 208 * @return True if this group holds radio channels, false if it holds TV channels. 209 */ 210 bool IsRadio() const; 211 212 /*! 213 * @brief True if sorting should be prevented when adding/updating channels to the group. 214 * @return True if sorting should be prevented when adding/updating channels to the group. 215 */ 216 bool PreventSortAndRenumber() const; 217 218 /*! 219 * @brief The database ID of this group. 220 * @return The database ID of this group. 221 */ 222 int GroupID() const; 223 224 /*! 225 * @brief Set the database ID of this group. 226 * @param iGroupId The new database ID. 227 */ 228 void SetGroupID(int iGroupId); 229 230 /*! 231 * @brief Set the type of this group. 232 * @param the new type for this group. 233 */ 234 void SetGroupType(int iGroupType); 235 236 /*! 237 * @brief Return the type of this group. 238 */ 239 int GroupType() const; 240 241 /*! 242 * @return Time group has been watched last. 243 */ 244 time_t LastWatched() const; 245 246 /*! 247 * @brief Last time group has been watched 248 * @param iLastWatched The new value. 249 * @return True if something changed, false otherwise. 250 */ 251 bool SetLastWatched(time_t iLastWatched); 252 253 /*! 254 * @return Time in milliseconds from epoch this group was last opened. 255 */ 256 uint64_t LastOpened() const; 257 258 /*! 259 * @brief Set the time in milliseconds from epoch this group was last opened. 260 * @param iLastOpened The new value. 261 * @return True if something changed, false otherwise. 262 */ 263 bool SetLastOpened(uint64_t iLastOpened); 264 265 /*! 266 * @brief Set if sorting and renumbering should happen after adding/updating channels to group. 267 * @param bPreventSortAndRenumber The new sorting and renumbering prevention value for this group. 268 */ 269 void SetPreventSortAndRenumber(bool bPreventSortAndRenumber = true); 270 271 /*! 272 * @brief The name of this group. 273 * @return The name of this group. 274 */ 275 std::string GroupName() const; 276 277 /*! @name Sort methods 278 */ 279 //@{ 280 281 /*! 282 * @brief Sort the group. 283 */ 284 void Sort(); 285 286 /*! 287 * @brief Sort the group and fix up channel numbers. 288 * @return True when numbering changed, false otherwise 289 */ 290 bool SortAndRenumber(); 291 292 /*! 293 * @brief Remove invalid channels and updates the channel numbers. 294 * @param mode the numbering mode to use 295 * @return True if something changed, false otherwise. 296 */ 297 bool Renumber(RenumberMode mode = NORMAL); 298 299 //@} 300 301 void OnSettingChanged(const std::shared_ptr<const CSetting>& setting) override; 302 303 /*! 304 * @brief Get a channel given it's EPG ID. 305 * @param iEpgID The channel EPG ID. 306 * @return The channel or NULL if it wasn't found. 307 */ 308 std::shared_ptr<CPVRChannel> GetByChannelEpgID(int iEpgID) const; 309 310 /*! 311 * @brief Get the channel that was played last. 312 * @param iCurrentChannel The channelid of the current channel that is playing, or -1 if none 313 * @return The requested channel or nullptr. 314 */ 315 std::shared_ptr<CPVRChannel> GetLastPlayedChannel(int iCurrentChannel = -1) const; 316 317 /*! 318 * @brief Get a channel given it's active channel number 319 * @param channelNumber The channel number. 320 * @return The channel or nullptr if it wasn't found. 321 */ 322 std::shared_ptr<CPVRChannel> GetByChannelNumber(const CPVRChannelNumber& channelNumber) const; 323 324 /*! 325 * @brief Get the channel number in this group of the given channel. 326 * @param channel The channel to get the channel number for. 327 * @return The channel number in this group. 328 */ 329 CPVRChannelNumber GetChannelNumber(const std::shared_ptr<CPVRChannel>& channel) const; 330 331 /*! 332 * @brief Get the client channel number in this group of the given channel. 333 * @param channel The channel to get the channel number for. 334 * @return The client channel number in this group. 335 */ 336 CPVRChannelNumber GetClientChannelNumber(const std::shared_ptr<CPVRChannel>& channel) const; 337 338 /*! 339 * @brief Get the next channel in this group. 340 * @param channel The current channel. 341 * @return The channel or nullptr if it wasn't found. 342 */ 343 std::shared_ptr<CPVRChannel> GetNextChannel(const std::shared_ptr<CPVRChannel>& channel) const; 344 345 /*! 346 * @brief Get the previous channel in this group. 347 * @param channel The current channel. 348 * @return The channel or nullptr if it wasn't found. 349 */ 350 std::shared_ptr<CPVRChannel> GetPreviousChannel(const std::shared_ptr<CPVRChannel>& channel) const; 351 352 /*! 353 * @brief Get a channel given it's channel ID. 354 * @param iChannelID The channel ID. 355 * @return The channel or NULL if it wasn't found. 356 */ 357 std::shared_ptr<CPVRChannel> GetByChannelID(int iChannelID) const; 358 359 enum class Include 360 { 361 ALL, 362 ONLY_HIDDEN, 363 ONLY_VISIBLE 364 }; 365 366 /*! 367 * @brief Get the current members of this group 368 * @param eFilter A filter to apply. 369 * @return The group members 370 */ 371 std::vector<std::shared_ptr<PVRChannelGroupMember>> GetMembers(Include eFilter = Include::ALL) const; 372 373 /*! 374 * @brief Get the list of active channel numbers in a group. 375 * @param channelNumbers The list to store the numbers in. 376 */ 377 void GetChannelNumbers(std::vector<std::string>& channelNumbers) const; 378 379 /*! 380 * @brief The amount of hidden channels in this container. 381 * @return The amount of hidden channels in this container. 382 */ GetNumHiddenChannels()383 virtual size_t GetNumHiddenChannels() const { return 0; } 384 385 /*! 386 * @brief Does this container holds channels. 387 * @return True if there is at least one channel in this container, otherwise false. 388 */ 389 bool HasChannels() const; 390 391 /*! 392 * @return True if there is at least one channel in this group with changes that haven't been persisted, false otherwise. 393 */ 394 bool HasChangedChannels() const; 395 396 /*! 397 * @return True if there is at least one new channel in this group that hasn't been persisted, false otherwise. 398 */ 399 bool HasNewChannels() const; 400 401 /*! 402 * @return True if anything changed in this group that hasn't been persisted, false otherwise. 403 */ 404 bool HasChanges() const; 405 406 /*! 407 * @brief Create an EPG table for each channel. 408 * @brief bForce Create the tables, even if they already have been created before. 409 * @return True if all tables were created successfully, false otherwise. 410 */ 411 virtual bool CreateChannelEpgs(bool bForce = false); 412 413 /*! 414 * @brief Get the start time of the first entry. 415 * @return The start time. 416 */ 417 CDateTime GetFirstEPGDate() const; 418 419 /*! 420 * @brief Get the end time of the last entry. 421 * @return The end time. 422 */ 423 CDateTime GetLastEPGDate() const; 424 425 /*! 426 * @brief Update a channel group member with given data. 427 * @param storageId The storage id of the channel. 428 * @param strChannelName The channel name to set. 429 * @param strIconPath The icon path to set. 430 * @param iEPGSource The EPG id. 431 * @param iChannelNumber The channel number to set. 432 * @param bHidden Set/Remove hidden flag for the channel group member identified by storage id. 433 * @param bEPGEnabled Set/Remove EPG enabled flag for the channel group member identified by storage id. 434 * @param bParentalLocked Set/Remove parental locked flag for the channel group member identified by storage id. 435 * @param bUserSetIcon Set/Remove user set icon flag for the channel group member identified by storage id. 436 * @return True on success, false otherwise. 437 */ 438 bool UpdateChannel(const std::pair<int, int>& storageId, 439 const std::string& strChannelName, 440 const std::string& strIconPath, 441 int iEPGSource, 442 int iChannelNumber, 443 bool bHidden, 444 bool bEPGEnabled, 445 bool bParentalLocked, 446 bool bUserSetIcon); 447 448 /*! 449 * @brief Get a channel given the channel number on the client. 450 * @param iUniqueChannelId The unique channel id on the client. 451 * @param iClientID The ID of the client. 452 * @return The channel or NULL if it wasn't found. 453 */ 454 std::shared_ptr<CPVRChannel> GetByUniqueID(int iUniqueChannelId, int iClientID) const; 455 456 /*! 457 * @brief Get a channel group member given its storage id. 458 * @param id The storage id (a pair of client id and unique channel id). 459 * @return A reference to the group member or an empty group member if it wasn't found. 460 */ 461 std::shared_ptr<PVRChannelGroupMember>& GetByUniqueID(const std::pair<int, int>& id); 462 const std::shared_ptr<PVRChannelGroupMember>& GetByUniqueID(const std::pair<int, int>& id) const; 463 464 bool SetHidden(bool bHidden); 465 bool IsHidden() const; 466 467 int GetPosition() const; 468 void SetPosition(int iPosition); 469 470 /*! 471 * @brief Check, whether data for a given pvr client are currently valid. For instance, data 472 * can be invalid because the client's backend was offline when data was last queried. 473 * @param iClientId The id of the client. 474 * @return True, if data is currently valid, false otherwise. 475 */ 476 bool HasValidDataFromClient(int iClientId) const; 477 478 /*! 479 * @brief For each channel and its corresponding epg channel data update the order from the group members 480 */ 481 void UpdateClientOrder(); 482 483 /*! 484 * @brief For each channel and its corresponding epg channel data update the channel number from the group members 485 */ 486 void UpdateChannelNumbers(); 487 488 /*! 489 * @brief Update whether or not this group is currently selected 490 * @param isSelectedGroup whether or not this group is the currently selected group. 491 */ SetSelectedGroup(bool isSelectedGroup)492 void SetSelectedGroup(bool isSelectedGroup) { m_bIsSelectedGroup = isSelectedGroup; } 493 494 /*! 495 * @brief Update the channel numbers according to the all channels group and publish event. 496 * @return True, if a channel number was changed, false otherwise. 497 */ 498 bool UpdateChannelNumbersFromAllChannelsGroup(); 499 500 protected: 501 /*! 502 * @brief Init class 503 */ 504 void OnInit(); 505 506 /*! 507 * @brief Load the channels stored in the database. 508 * @param bCompress If true, compress the database after storing the channels. 509 * @return The amount of channels that were added. 510 */ 511 virtual int LoadFromDb(bool bCompress = false); 512 513 /*! 514 * @brief Update the current channel list with the given list. 515 * 516 * Update the current channel list with the given list. 517 * Only the new channels will be present in the passed list after this call. 518 * 519 * @param channels The channels to use to update this list. 520 * @param channelsToRemove Returns the channels to be removed from all groups, if any 521 * @return True if everything went well, false otherwise. 522 */ 523 virtual bool UpdateGroupEntries(const CPVRChannelGroup& channels, std::vector<std::shared_ptr<CPVRChannel>>& channelsToRemove); 524 525 /*! 526 * @brief Add new channels to this group; update data. 527 * @param channels The new channels to use for this group. 528 * @param bUseBackendChannelNumbers True, if channel numbers from backends shall be used. 529 * @return True if everything went well, false otherwise. 530 */ 531 virtual bool AddAndUpdateChannels(const CPVRChannelGroup& channels, bool bUseBackendChannelNumbers); 532 533 /*! 534 * @brief Remove deleted channels from this group. 535 * @param channels The new channels to use for this group. 536 * @return The removed channels. 537 */ 538 virtual std::vector<std::shared_ptr<CPVRChannel>> RemoveDeletedChannels(const CPVRChannelGroup& channels); 539 540 /*! 541 * @brief Clear this channel list. 542 */ 543 void Unload(); 544 545 /*! 546 * @brief Load the channels from the clients. 547 * @return True when loaded successfully, false otherwise. 548 */ 549 virtual bool LoadFromClients(); 550 551 /*! 552 * @brief Sort the current channel list by client channel number. 553 */ 554 void SortByClientChannelNumber(); 555 556 /*! 557 * @brief Sort the current channel list by channel number. 558 */ 559 void SortByChannelNumber(); 560 561 /*! 562 * @brief Update the priority for all members of all channel groups. 563 */ 564 bool UpdateClientPriorities(); 565 566 int m_iGroupType = PVR_GROUP_TYPE_DEFAULT; /*!< The type of this group */ 567 int m_iGroupId = INVALID_GROUP_ID; /*!< The ID of this group in the database */ 568 bool m_bLoaded = false; /*!< True if this container is loaded, false otherwise */ 569 bool m_bChanged = false; /*!< true if anything changed in this group that hasn't been persisted, false otherwise */ 570 bool m_bUsingBackendChannelOrder = false; /*!< true to use the channel order from backends, false otherwise */ 571 bool m_bUsingBackendChannelNumbers = false; /*!< true to use the channel numbers from 1 backend, false otherwise */ 572 bool m_bPreventSortAndRenumber = false; /*!< true when sorting and renumbering should not be done after adding/updating channels to the group */ 573 time_t m_iLastWatched = 0; /*!< last time group has been watched */ 574 uint64_t m_iLastOpened = 0; /*!< time in milliseconds from epoch this group was last opened */ 575 bool m_bHidden = false; /*!< true if this group is hidden, false otherwise */ 576 int m_iPosition = 0; /*!< the position of this group within the group list */ 577 std::vector<std::shared_ptr<PVRChannelGroupMember>> m_sortedMembers; /*!< members sorted by channel number */ 578 std::map<std::pair<int, int>, std::shared_ptr<PVRChannelGroupMember>> m_members; /*!< members with key clientid+uniqueid */ 579 mutable CCriticalSection m_critSection; 580 std::vector<int> m_failedClients; 581 CEventSource<PVREvent> m_events; 582 bool m_bIsSelectedGroup = false; /*!< Whether or not this group is currently selected */ 583 bool m_bStartGroupChannelNumbersFromOne = false; /*!< true if we start group channel numbers from one when not using backend channel numbers, false otherwise */ 584 bool m_bSyncChannelGroups = false; /*!< true if channel groups should be synced with the backend, false otherwise */ 585 586 private: 587 CDateTime GetEPGDate(EpgDateType epgDateType) const; 588 589 std::shared_ptr<CPVRChannelGroup> m_allChannelsGroup; 590 CPVRChannelsPath m_path; 591 }; 592 } 593