File: EpgContainer.h

package info (click to toggle)
kodi 2%3A21.2%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 143,076 kB
  • sloc: cpp: 694,471; xml: 52,618; ansic: 38,300; python: 7,161; sh: 4,289; javascript: 2,325; makefile: 1,791; perl: 969; java: 513; cs: 390; objc: 340
file content (361 lines) | stat: -rw-r--r-- 11,855 bytes parent folder | download | duplicates (2)
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
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
/*
 *  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 "addons/kodi-dev-kit/include/kodi/c-api/addon-instance/pvr/pvr_epg.h"
#include "pvr/settings/PVRSettings.h"
#include "threads/CriticalSection.h"
#include "threads/Event.h"
#include "threads/Thread.h"
#include "utils/EventStream.h"

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

class CDateTime;

namespace PVR
{
  class CEpgUpdateRequest;
  class CEpgTagStateChange;
  class CPVREpg;
  class CPVREpgChannelData;
  class CPVREpgDatabase;
  class CPVREpgInfoTag;
  class CPVREpgSearchFilter;

  enum class PVREvent;

  struct PVREpgSearchData;

  class CPVREpgContainer : private CThread
  {
    friend class CPVREpgDatabase;

  public:
    CPVREpgContainer() = delete;

    /*!
     * @brief Create a new EPG table container.
     */
    explicit CPVREpgContainer(CEventSource<PVREvent>& eventSource);

    /*!
     * @brief Destroy this instance.
     */
    ~CPVREpgContainer() override;

    /*!
     * @brief Get a pointer to the database instance.
     * @return A pointer to the database instance.
     */
    std::shared_ptr<CPVREpgDatabase> GetEpgDatabase() const;

    /*!
     * @brief Start the EPG update thread.
     */
    void Start();

    /*!
     * @brief Stop the EPG update thread.
     */
    void Stop();

    /**
     * @brief (re)load EPG data.
     * @return True if loaded successfully, false otherwise.
     */
    bool Load();

    /**
     * @brief unload all EPG data.
     */
    void Unload();

    /*!
     * @brief Check whether the EpgContainer has fully started.
     * @return True if started, false otherwise.
     */
    bool IsStarted() const;

    /*!
     * @brief Queue the deletion of the given EPG tables from this container.
     * @param epg The tables to delete.
     * @return True on success, false otherwise.
     */
    bool QueueDeleteEpgs(const std::vector<std::shared_ptr<CPVREpg>>& epgs);

    /*!
     * @brief CEventStream callback for PVR events.
     * @param event The event.
     */
    void Notify(const PVREvent& event);

    /*!
     * @brief Create the EPg for a given channel.
     * @param iEpgId The EPG id.
     * @param strScraperName The scraper name.
     * @param channelData The channel data.
     * @return the created EPG
     */
    std::shared_ptr<CPVREpg> CreateChannelEpg(int iEpgId, const std::string& strScraperName, const std::shared_ptr<CPVREpgChannelData>& channelData);

    /*!
     * @brief Get the start and end time across all EPGs.
     * @return The times; first: start time, second: end time.
     */
    std::pair<CDateTime, CDateTime> GetFirstAndLastEPGDate() const;

    /*!
     * @brief Get all EPGs.
     * @return The EPGs.
     */
    std::vector<std::shared_ptr<CPVREpg>> GetAllEpgs() const;

    /*!
     * @brief Get an EPG given its ID.
     * @param iEpgId The database ID of the table.
     * @return The EPG or nullptr if it wasn't found.
     */
    std::shared_ptr<CPVREpg> GetById(int iEpgId) const;

    /*!
     * @brief Get an EPG given its client id and channel uid.
     * @param iClientId the id of the pvr client providing the EPG
     * @param iChannelUid the uid of the channel for the EPG
     * @return The EPG or nullptr if it wasn't found.
     */
    std::shared_ptr<CPVREpg> GetByChannelUid(int iClientId, int iChannelUid) const;

    /*!
     * @brief Get the EPG event with the given event id
     * @param epg The epg to lookup the event.
     * @param iBroadcastId The event id to lookup.
     * @return The requested event, or an empty tag when not found
     */
    std::shared_ptr<CPVREpgInfoTag> GetTagById(const std::shared_ptr<const CPVREpg>& epg,
                                               unsigned int iBroadcastId) const;

    /*!
     * @brief Get the EPG event with the given database id
     * @param iDatabaseId The id to lookup.
     * @return The requested event, or an empty tag when not found
     */
    std::shared_ptr<CPVREpgInfoTag> GetTagByDatabaseId(int iDatabaseId) const;

    /*!
     * @brief Get all EPG tags matching the given search criteria.
     * @param searchData The search criteria.
     * @return The matching tags.
     */
    std::vector<std::shared_ptr<CPVREpgInfoTag>> GetTags(const PVREpgSearchData& searchData) const;

    /*!
     * @brief Notify EPG container that there are pending manual EPG updates
     * @param bHasPendingUpdates The new value
     */
    void SetHasPendingUpdates(bool bHasPendingUpdates = true);

    /*!
     * @brief A client triggered an epg update request for a channel
     * @param iClientID The id of the client which triggered the update request
     * @param iUniqueChannelID The uid of the channel for which the epg shall be updated
     */
    void UpdateRequest(int iClientID, int iUniqueChannelID);

    /*!
     * @brief A client announced an updated epg tag for a channel
     * @param tag The epg tag containing the updated data
     * @param eNewState The kind of change (CREATED, UPDATED, DELETED)
     */
    void UpdateFromClient(const std::shared_ptr<CPVREpgInfoTag>& tag, EPG_EVENT_STATE eNewState);

    /*!
     * @brief Get the number of past days to show in the guide and to import from backends.
     * @return the number of past epg days.
     */
    int GetPastDaysToDisplay() const;

    /*!
     * @brief Get the number of future days to show in the guide and to import from backends.
     * @return the number of future epg days.
     */
    int GetFutureDaysToDisplay() const;

    /*!
     * @brief Inform the epg container that playback of an item just started.
     */
    void OnPlaybackStarted();

    /*!
     * @brief Inform the epg container that playback of an item was stopped due to user interaction.
     */
    void OnPlaybackStopped();

    /*!
     * @brief Inform the epg container that the system is going to sleep
     */
    void OnSystemSleep();

    /*!
     * @brief Inform the epg container that the system gets awake from sleep
     */
    void OnSystemWake();

    /*!
     * @brief Erase stale texture db entries and image files.
     * @return number of cleaned up images.
     */
    int CleanupCachedImages();

    /*!
     * @brief Get all saved searches from the database.
     * @param bRadio Whether to fetch saved searches for radio or TV.
     * @return The searches.
     */
    std::vector<std::shared_ptr<CPVREpgSearchFilter>> GetSavedSearches(bool bRadio);

    /*!
     * @brief Get the saved search matching the given id.
     * @param bRadio Whether to fetch a TV or radio saved search.
     * @param iId The id.
     * @return The saved search or nullptr if not found.
     */
    std::shared_ptr<CPVREpgSearchFilter> GetSavedSearchById(bool bRadio, int iId);

    /*!
     * @brief Persist a saved search in the database.
     * @param search The saved search.
     * @return True on success, false otherwise.
     */
    bool PersistSavedSearch(CPVREpgSearchFilter& search);

    /*!
     * @brief Update time last executed for the given search.
     * @param epgSearch The search.
     * @return True on success, false otherwise.
     */
    bool UpdateSavedSearchLastExecuted(const CPVREpgSearchFilter& epgSearch);

    /*!
     * @brief Delete a saved search from the database.
     * @param search The saved search.
     * @return True on success, false otherwise.
     */
    bool DeleteSavedSearch(const CPVREpgSearchFilter& search);

  private:
    /*!
     * @brief Notify EPG table observers when the currently active tag changed.
     * @return True if the check was done, false if it was not the right time to check
     */
    bool CheckPlayingEvents();

    /*!
     * @brief The next EPG ID to be given to a table when the db isn't being used.
     * @return The next ID.
     */
    int NextEpgId();

    /*!
     * @brief Wait for an EPG update to finish.
     */
    void WaitForUpdateFinish();

    /*!
     * @brief Call Persist() on each table
     * @param iMaxTimeslice time in milliseconds for max processing. Return after this time
     *        even if not all data was persisted, unless value is -1
     * @return True when they all were persisted, false otherwise.
     */
    bool PersistAll(unsigned int iMaxTimeslice) const;

    /*!
     * @brief Remove old EPG entries.
     * @return True if the old entries were removed successfully, false otherwise.
     */
    bool RemoveOldEntries();

    /*!
     * @brief Load and update the EPG data.
     * @param bOnlyPending Only check and update EPG tables with pending manual updates
     * @return True if the update has not been interrupted, false otherwise.
     */
    bool UpdateEPG(bool bOnlyPending = false);

    /*!
     * @brief Check whether a running update should be interrupted.
     * @return True if a running update should be interrupted, false otherwise.
     */
    bool InterruptUpdate() const;

    /*!
     * @brief EPG update thread
     */
    void Process() override;

    /*!
     * @brief Load all tables from the database
     */
    void LoadFromDatabase();

    /*!
     * @brief Insert data from database
     * @param newEpg the EPG containing the updated data.
     */
    void InsertFromDB(const std::shared_ptr<CPVREpg>& newEpg);

    /*!
     * @brief Queue the deletion of an EPG table from this container.
     * @param epg The table to delete.
     * @param database The database containing the epg data.
     * @return True on success, false otherwise.
     */
    bool QueueDeleteEpg(const std::shared_ptr<const CPVREpg>& epg,
                        const std::shared_ptr<CPVREpgDatabase>& database);

    std::shared_ptr<CPVREpgDatabase> m_database; /*!< the EPG database */

    bool m_bIsUpdating = false; /*!< true while an update is running */
    std::atomic<bool> m_bIsInitialising = {
        true}; /*!< true while the epg manager hasn't loaded all tables */
    bool m_bStarted = false; /*!< true if EpgContainer has fully started */
    bool m_bLoaded = false; /*!< true after epg data is initially loaded from the database */
    bool m_bPreventUpdates = false; /*!< true to prevent EPG updates */
    bool m_bPlaying = false; /*!< true if Kodi is currently playing something */
    int m_pendingUpdates = 0; /*!< count of pending manual updates */
    time_t m_iLastEpgCleanup = 0; /*!< the time the EPG was cleaned up */
    time_t m_iNextEpgUpdate = 0; /*!< the time the EPG will be updated */
    time_t m_iNextEpgActiveTagCheck = 0; /*!< the time the EPG will be checked for active tag updates */
    int m_iNextEpgId = 0; /*!< the next epg ID that will be given to a new table when the db isn't being used */

    std::map<int, std::shared_ptr<CPVREpg>> m_epgIdToEpgMap; /*!< the EPGs in this container. maps epg ids to epgs */
    std::map<std::pair<int, int>, std::shared_ptr<CPVREpg>> m_channelUidToEpgMap; /*!< the EPGs in this container. maps channel uids to epgs */

    mutable CCriticalSection m_critSection; /*!< a critical section for changes to this container */
    CEvent m_updateEvent; /*!< trigger when an update finishes */

    std::list<CEpgUpdateRequest> m_updateRequests; /*!< list of update requests triggered by addon */
    CCriticalSection m_updateRequestsLock; /*!< protect update requests */

    std::list<CEpgTagStateChange> m_epgTagChanges; /*!< list of updated epg tags announced by addon */
    CCriticalSection m_epgTagChangesLock; /*!< protect changed epg tags list */

    bool m_bUpdateNotificationPending = false; /*!< true while an epg updated notification to observers is pending. */
    CPVRSettings m_settings;
    CEventSource<PVREvent>& m_events;

    std::atomic<bool> m_bSuspended = {false};
  };
}