summaryrefslogtreecommitdiffstats
path: root/xbmc/pvr/epg/Epg.h
blob: 31bc8d0888c8e2670f74b612cd41525e1cf69f2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/*
 *  Copyright (C) 2012-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include "XBDateTime.h"
#include "addons/kodi-dev-kit/include/kodi/c-api/addon-instance/pvr/pvr_epg.h"
#include "pvr/epg/EpgTagsContainer.h"
#include "threads/CriticalSection.h"
#include "utils/EventStream.h"

#include <atomic>
#include <map>
#include <memory>
#include <string>
#include <vector>

namespace PVR
{
  enum class PVREvent;

  class CPVREpgChannelData;
  class CPVREpgDatabase;
  class CPVREpgInfoTag;

  class CPVREpg
  {
    friend class CPVREpgDatabase;

  public:
    /*!
     * @brief Create a new EPG instance.
     * @param iEpgID The ID of this table or <= 0 to create a new ID.
     * @param strName The name of this table.
     * @param strScraperName The name of the scraper to use.
     * @param database The EPG database
     */
    CPVREpg(int iEpgID,
            const std::string& strName,
            const std::string& strScraperName,
            const std::shared_ptr<CPVREpgDatabase>& database);

    /*!
     * @brief Create a new EPG instance.
     * @param iEpgID The ID of this table or <= 0 to create a new ID.
     * @param strName The name of this table.
     * @param strScraperName The name of the scraper to use.
     * @param channelData The channel data.
     * @param database The EPG database
     */
    CPVREpg(int iEpgID,
            const std::string& strName,
            const std::string& strScraperName,
            const std::shared_ptr<CPVREpgChannelData>& channelData,
            const std::shared_ptr<CPVREpgDatabase>& database);

    /*!
     * @brief Destroy this EPG instance.
     */
    virtual ~CPVREpg();

    /*!
     * @brief Get data for the channel associated with this EPG.
     * @return The data.
     */
    std::shared_ptr<CPVREpgChannelData> GetChannelData() const;

    /*!
     * @brief Set data for the channel associated with this EPG.
     * @param data The data.
     */
    void SetChannelData(const std::shared_ptr<CPVREpgChannelData>& data);

    /*!
     * @brief The id of the channel associated with this EPG.
     * @return The channel id or -1 if no channel is associated
     */
    int ChannelID() const;

    /*!
     * @brief Get the name of the scraper to use for this table.
     * @return The name of the scraper to use for this table.
     */
    const std::string& ScraperName() const;

    /*!
     * @brief Returns if there is a manual update pending for this EPG
     * @return True if there is a manual update pending, false otherwise
     */
    bool UpdatePending() const;

    /*!
     * @brief Clear the current tags and schedule manual update
     */
    void ForceUpdate();

    /*!
     * @brief Get the name of this table.
     * @return The name of this table.
     */
    const std::string& Name() const;

    /*!
     * @brief Get the database ID of this table.
     * @return The database ID of this table.
     */
    int EpgID() const;

    /*!
     * @brief Remove all entries from this EPG that finished before the given time.
     * @param time Delete entries with an end time before this time in UTC.
     */
    void Cleanup(const CDateTime& time);

    /*!
     * @brief Remove all entries from this EPG.
     */
    void Clear();

    /*!
     * @brief Get the event that is occurring now
     * @return The current event or NULL if it wasn't found.
     */
    std::shared_ptr<CPVREpgInfoTag> GetTagNow() const;

    /*!
     * @brief Get the event that will occur next
     * @return The next event or NULL if it wasn't found.
     */
    std::shared_ptr<CPVREpgInfoTag> GetTagNext() const;

    /*!
     * @brief Get the event that occurred previously
     * @return The previous event or NULL if it wasn't found.
     */
    std::shared_ptr<CPVREpgInfoTag> GetTagPrevious() const;

    /*!
     * @brief Get the event that occurs between the given begin and end time.
     * @param beginTime Minimum start time in UTC of the event.
     * @param endTime Maximum end time in UTC of the event.
     * @param bUpdateFromClient if true, try to fetch the event from the client if not found locally.
     * @return The found tag or NULL if it wasn't found.
     */
    std::shared_ptr<CPVREpgInfoTag> GetTagBetween(const CDateTime& beginTime, const CDateTime& endTime, bool bUpdateFromClient = false);

    /*!
     * @brief Get the event matching the given unique broadcast id
     * @param iUniqueBroadcastId The uid to look up
     * @return The matching event or NULL if it wasn't found.
     */
    std::shared_ptr<CPVREpgInfoTag> GetTagByBroadcastId(unsigned int iUniqueBroadcastId) const;

    /*!
     * @brief Get the event matching the given database id
     * @param iDatabaseId The id to look up
     * @return The matching event or NULL if it wasn't found.
     */
    std::shared_ptr<CPVREpgInfoTag> GetTagByDatabaseId(int iDatabaseId) const;

    /*!
     * @brief Update an entry in this EPG.
     * @param data The tag to update.
     * @param iClientId The id of the pvr client this event belongs to.
     * @return True if it was updated successfully, false otherwise.
     */
    bool UpdateEntry(const EPG_TAG* data, int iClientId);

    /*!
     * @brief Update an entry in this EPG.
     * @param tag The tag to update.
     * @param newState the new state of the event.
     * @return True if it was updated successfully, false otherwise.
     */
    bool UpdateEntry(const std::shared_ptr<CPVREpgInfoTag>& tag, EPG_EVENT_STATE newState);

    /*!
     * @brief Update the EPG from 'start' till 'end'.
     * @param start The start time.
     * @param end The end time.
     * @param iUpdateTime Update the table after the given amount of time has passed.
     * @param iPastDays Amount of past days from now on, for which past entries are to be kept.
     * @param database If given, the database to store the data.
     * @param bForceUpdate Force update from client even if it's not the time to
     * @return True if the update was successful, false otherwise.
     */
    bool Update(time_t start, time_t end, int iUpdateTime, int iPastDays, const std::shared_ptr<CPVREpgDatabase>& database, bool bForceUpdate = false);

    /*!
     * @brief Get all EPG tags.
     * @return The tags.
     */
    std::vector<std::shared_ptr<CPVREpgInfoTag>> GetTags() const;

    /*!
     * @brief Get all EPG tags for the given time frame, including "gap" tags.
     * @param timelineStart Start of time line
     * @param timelineEnd End of time line
     * @param minEventEnd The minimum end time of the events to return
     * @param maxEventStart The maximum start time of the events to return
     * @return The matching tags.
     */
    std::vector<std::shared_ptr<CPVREpgInfoTag>> GetTimeline(const CDateTime& timelineStart,
                                                             const CDateTime& timelineEnd,
                                                             const CDateTime& minEventEnd,
                                                             const CDateTime& maxEventStart) const;

    /*!
     * @brief Write the query to persist data into given database's queue
     * @param database The database.
     * @return True on success, false otherwise.
     */
    bool QueuePersistQuery(const std::shared_ptr<CPVREpgDatabase>& database);

    /*!
     * @brief Write the delete queries into the given database's queue
     * @param database The database.
     * @return True on success, false otherwise.
     */
    bool QueueDeleteQueries(const std::shared_ptr<CPVREpgDatabase>& database);

    /*!
     * @brief Get the start and end time of the last not yet commited entry in this table.
     * @return The times; first: start time, second: end time.
     */
    std::pair<CDateTime, CDateTime> GetFirstAndLastUncommitedEPGDate() const;

    /*!
     * @brief Notify observers when the currently active tag changed.
     * @return True if the playing tag has changed, false otherwise.
     */
    bool CheckPlayingEvent();

    /*!
     * @brief Convert a genre id and subid to a human readable name.
     * @param iID The genre ID.
     * @param iSubID The genre sub ID.
     * @return A human readable name.
     */
    static const std::string& ConvertGenreIdToString(int iID, int iSubID);

    /*!
     * @brief Check whether this EPG has unsaved data.
     * @return True if this EPG contains unsaved data, false otherwise.
     */
    bool NeedsSave() const;

    /*!
     * @brief Check whether this EPG is valid.
     * @return True if this EPG is valid and can be updated, false otherwise.
     */
    bool IsValid() const;

    /*!
     * @brief Query the events available for CEventStream
     */
    CEventStream<PVREvent>& Events() { return m_events; }

    /*!
     * @brief Lock the instance. No other thread gets access to this EPG until Unlock was called.
     */
    void Lock() { m_critSection.lock(); }

    /*!
     * @brief Unlock the instance. Other threads may get access to this EPG again.
     */
    void Unlock() { m_critSection.unlock(); }

    /*!
     * @brief Called to inform the EPG that it has been removed from the EPG container.
     */
    void RemovedFromContainer();

    /*!
     * @brief Erase stale texture db entries and image files.
     * @param database The EPG database
     * @return number of cleaned up images.
     */
    int CleanupCachedImages(const std::shared_ptr<CPVREpgDatabase>& database);

  private:
    CPVREpg() = delete;
    CPVREpg(const CPVREpg&) = delete;
    CPVREpg& operator =(const CPVREpg&) = delete;

    /*!
     * @brief Update the EPG from a scraper set in the channel tag.
     * @todo not implemented yet for non-pvr EPGs
     * @param start Get entries with a start date after this time.
     * @param end Get entries with an end date before this time.
     * @param bForceUpdate Force update from client even if it's not the time to
     * @return True if the update was successful, false otherwise.
     */
    bool UpdateFromScraper(time_t start, time_t end, bool bForceUpdate);

    /*!
     * @brief Update the contents of this table with the contents provided in "epg"
     * @param epg The updated contents.
     * @return True if the update was successful, false otherwise.
     */
    bool UpdateEntries(const CPVREpg& epg);

    /*!
     * @brief Remove all entries from this EPG that finished before the given amount of days.
     * @param iPastDays Delete entries with an end time before the given amount of days from now on.
     */
    void Cleanup(int iPastDays);

    bool m_bChanged = false; /*!< true if anything changed that needs to be persisted, false otherwise */
    std::atomic<bool> m_bUpdatePending = {false}; /*!< true if manual update is pending */
    int m_iEpgID = 0; /*!< the database ID of this table */
    std::string m_strName; /*!< the name of this table */
    std::string m_strScraperName; /*!< the name of the scraper to use */
    CDateTime m_lastScanTime; /*!< the last time the EPG has been updated */
    mutable CCriticalSection m_critSection; /*!< critical section for changes in this table */
    bool m_bUpdateLastScanTime = false;
    std::shared_ptr<CPVREpgChannelData> m_channelData;
    CPVREpgTagsContainer m_tags;

    CEventSource<PVREvent> m_events;
  };
}