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 
13 #include <functional>
14 #include <map>
15 #include <memory>
16 #include <unordered_map>
17 #include <utility>
18 #include <vector>
19 
20 class CFileItem;
21 class CFileItemList;
22 
23 namespace PVR
24 {
25   struct GridItem
26   {
GridItemGridItem27     GridItem(const std::shared_ptr<CFileItem>& _item, float _width, int _startBlock, int _endBlock)
28       : item(_item),
29         originWidth(_width),
30         width(_width),
31         startBlock(_startBlock),
32         endBlock(_endBlock)
33     {
34     }
35 
36     bool operator==(const GridItem& other) const
37     {
38       return (startBlock == other.startBlock && endBlock == other.endBlock);
39     }
40 
41     std::shared_ptr<CFileItem> item;
42     float originWidth = 0.0f;
43     float width = 0.0f;
44     int startBlock = 0;
45     int endBlock = 0;
46   };
47 
48   class CPVREpgInfoTag;
49 
50   class CGUIEPGGridContainerModel
51   {
52   public:
53     static constexpr int MINSPERBLOCK = 5; // minutes
54 
55     CGUIEPGGridContainerModel() = default;
56     virtual ~CGUIEPGGridContainerModel() = default;
57 
58     void Initialize(const std::unique_ptr<CFileItemList>& items,
59                     const CDateTime& gridStart,
60                     const CDateTime& gridEnd,
61                     int iFirstChannel,
62                     int iChannelsPerPage,
63                     int iFirstBlock,
64                     int iBlocksPerPage,
65                     int iRulerUnit,
66                     float fBlockSize);
67     void SetInvalid();
68 
69     static const int INVALID_INDEX = -1;
70     void FindChannelAndBlockIndex(int channelUid, unsigned int broadcastUid, int eventOffset, int& newChannelIndex, int& newBlockIndex) const;
71 
72     void FreeChannelMemory(int keepStart, int keepEnd);
73     bool FreeProgrammeMemory(int firstChannel, int lastChannel, int firstBlock, int lastBlock);
74     void FreeRulerMemory(int keepStart, int keepEnd);
75 
GetChannelItem(int iIndex)76     std::shared_ptr<CFileItem> GetChannelItem(int iIndex) const { return m_channelItems[iIndex]; }
HasChannelItems()77     bool HasChannelItems() const { return !m_channelItems.empty(); }
ChannelItemsSize()78     int ChannelItemsSize() const { return static_cast<int>(m_channelItems.size()); }
GetLastChannel()79     int GetLastChannel() const
80     {
81       return m_channelItems.empty() ? -1 : static_cast<int>(m_channelItems.size()) - 1;
82     }
83 
GetRulerItem(int iIndex)84     std::shared_ptr<CFileItem> GetRulerItem(int iIndex) const { return m_rulerItems[iIndex]; }
RulerItemsSize()85     int RulerItemsSize() const { return static_cast<int>(m_rulerItems.size()); }
86 
GridItemsSize()87     int GridItemsSize() const { return m_blocks; }
88     bool IsSameGridItem(int iChannel, int iBlock1, int iBlock2) const;
89     std::shared_ptr<CFileItem> GetGridItem(int iChannel, int iBlock) const;
90     int GetGridItemStartBlock(int iChannel, int iBlock) const;
91     int GetGridItemEndBlock(int iChannel, int iBlock) const;
92     CDateTime GetGridItemEndTime(int iChannel, int iBlock) const;
93     float GetGridItemWidth(int iChannel, int iBlock) const;
94     float GetGridItemOriginWidth(int iChannel, int iBlock) const;
95     void DecreaseGridItemWidth(int iChannel, int iBlock, float fSize);
96 
IsZeroGridDuration()97     bool IsZeroGridDuration() const { return (m_gridEnd - m_gridStart) == CDateTimeSpan(0, 0, 0, 0); }
GetGridStart()98     const CDateTime& GetGridStart() const { return m_gridStart; }
GetGridEnd()99     const CDateTime& GetGridEnd() const { return m_gridEnd; }
100     unsigned int GetGridStartPadding() const;
101 
102     unsigned int GetPageNowOffset() const;
103     int GetNowBlock() const;
GetLastBlock()104     int GetLastBlock() const { return m_blocks - 1; }
105 
106     CDateTime GetStartTimeForBlock(int block) const;
107     int GetBlock(const CDateTime& datetime) const;
108     int GetFirstEventBlock(const std::shared_ptr<CPVREpgInfoTag>& event) const;
109     int GetLastEventBlock(const std::shared_ptr<CPVREpgInfoTag>& event) const;
110     bool IsEventMemberOfBlock(const std::shared_ptr<CPVREpgInfoTag>& event, int iBlock) const;
111 
112     std::unique_ptr<CFileItemList> GetCurrentTimeLineItems() const;
113 
114   private:
115     GridItem* GetGridItemPtr(int iChannel, int iBlock) const;
116     std::shared_ptr<CFileItem> CreateGapItem(int iChannel) const;
117     std::shared_ptr<CFileItem> GetItem(int iChannel, int iBlock) const;
118 
119     std::vector<std::shared_ptr<CPVREpgInfoTag>> GetEPGTimeline(
120         int iChannel, const CDateTime& minEventEnd, const CDateTime& maxEventStart) const;
121 
122     struct EpgTags
123     {
124       std::vector<std::shared_ptr<CFileItem>> tags;
125       int firstBlock = -1;
126       int lastBlock = -1;
127     };
128 
129     using EpgTagsMap = std::unordered_map<int, EpgTags>;
130 
131     std::shared_ptr<CFileItem> CreateEpgTags(int iChannel, int iBlock) const;
132     std::shared_ptr<CFileItem> GetEpgTags(EpgTagsMap::iterator& itEpg,
133                                           int iChannel,
134                                           int iBlock) const;
135     std::shared_ptr<CFileItem> GetEpgTagsBefore(EpgTags& epgTags, int iChannel, int iBlock) const;
136     std::shared_ptr<CFileItem> GetEpgTagsAfter(EpgTags& epgTags, int iChannel, int iBlock) const;
137 
138     mutable EpgTagsMap m_epgItems;
139 
140     CDateTime m_gridStart;
141     CDateTime m_gridEnd;
142 
143     std::vector<std::shared_ptr<CFileItem>> m_channelItems;
144     std::vector<std::shared_ptr<CFileItem>> m_rulerItems;
145 
146     struct GridCoordinates
147     {
GridCoordinatesGridCoordinates148       GridCoordinates(int _channel, int _block) : channel(_channel), block(_block) {}
149 
150       bool operator==(const GridCoordinates& other) const
151       {
152         return (channel == other.channel && block == other.block);
153       }
154 
155       int channel = 0;
156       int block = 0;
157     };
158 
159     struct GridCoordinatesHash
160     {
operatorGridCoordinatesHash161       std::size_t operator()(const GridCoordinates& coordinates) const
162       {
163         return std::hash<int>()(coordinates.channel) ^ std::hash<int>()(coordinates.block);
164       }
165     };
166 
167     mutable std::unordered_map<GridCoordinates, GridItem, GridCoordinatesHash> m_gridIndex;
168 
169     int m_blocks = 0;
170     float m_fBlockSize = 0.0f;
171 
172     int m_firstActiveChannel = 0;
173     int m_lastActiveChannel = 0;
174     int m_firstActiveBlock = 0;
175     int m_lastActiveBlock = 0;
176   };
177 }
178