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 "addons/kodi-dev-kit/include/kodi/c-api/addon-instance/pvr/pvr_general.h"
12 #include "interfaces/IAnnouncer.h"
13 #include "pvr/epg/EpgContainer.h"
14 #include "pvr/guilib/PVRGUIActionListener.h"
15 #include "pvr/settings/PVRSettings.h"
16 #include "threads/CriticalSection.h"
17 #include "threads/Event.h"
18 #include "threads/Thread.h"
19 #include "utils/EventStream.h"
20 
21 #include <memory>
22 #include <string>
23 #include <vector>
24 
25 class CFileItem;
26 class CStopWatch;
27 
28 namespace PVR
29 {
30   class CPVRChannel;
31   class CPVRChannelGroup;
32   class CPVRChannelGroupsContainer;
33   class CPVRClient;
34   class CPVRClients;
35   class CPVRDatabase;
36   class CPVRGUIActions;
37   class CPVRGUIInfo;
38   class CPVRGUIProgressHandler;
39   class CPVRManagerJobQueue;
40   class CPVRPlaybackState;
41   class CPVRRecording;
42   class CPVRRecordings;
43   class CPVRTimers;
44 
45   enum class PVREvent
46   {
47     // PVR Manager states
48     ManagerError = 0,
49     ManagerStopped,
50     ManagerStarting,
51     ManagerStopping,
52     ManagerInterrupted,
53     ManagerStarted,
54 
55     // Channel events
56     ChannelPlaybackStopped,
57 
58     // Channel group events
59     ChannelGroup,
60     ChannelGroupInvalidated,
61     ChannelGroupsInvalidated,
62     ChannelGroupsLoaded,
63 
64     // Recording events
65     RecordingsInvalidated,
66 
67     // Timer events
68     AnnounceReminder,
69     Timers,
70     TimersInvalidated,
71 
72     // EPG events
73     Epg,
74     EpgActiveItem,
75     EpgContainer,
76     EpgItemUpdate,
77     EpgUpdatePending,
78     EpgDeleted,
79 
80     // Item events
81     CurrentItem,
82 
83     // Syetem events
84     SystemSleep,
85     SystemWake,
86   };
87 
88   class CPVRManager : private CThread, public ANNOUNCEMENT::IAnnouncer
89   {
90   public:
91     /*!
92      * @brief Create a new CPVRManager instance, which handles all PVR related operations in XBMC.
93      */
94     CPVRManager();
95 
96     /*!
97      * @brief Stop the PVRManager and destroy all objects it created.
98      */
99     ~CPVRManager() override;
100 
101     void Announce(ANNOUNCEMENT::AnnouncementFlag flag,
102                   const std::string& sender,
103                   const std::string& message,
104                   const CVariant& data) override;
105 
106     /*!
107      * @brief Get the channel groups container.
108      * @return The groups container.
109      */
110     std::shared_ptr<CPVRChannelGroupsContainer> ChannelGroups() const;
111 
112     /*!
113      * @brief Get the recordings container.
114      * @return The recordings container.
115      */
116     std::shared_ptr<CPVRRecordings> Recordings() const;
117 
118     /*!
119      * @brief Get the timers container.
120      * @return The timers container.
121      */
122     std::shared_ptr<CPVRTimers> Timers() const;
123 
124     /*!
125      * @brief Get the timers container.
126      * @return The timers container.
127      */
128     std::shared_ptr<CPVRClients> Clients() const;
129 
130     /*!
131      * @brief Get the instance of a client that matches the given item.
132      * @param item The item containing a PVR recording, a PVR channel, a PVR timer or a PVR EPG event.
133      * @return the requested client on success, nullptr otherwise.
134      */
135     std::shared_ptr<CPVRClient> GetClient(const CFileItem& item) const;
136 
137     /*!
138      * @brief Get the instance of a client that matches the given id.
139      * @param iClientId The id of a PVR client.
140      * @return the requested client on success, nullptr otherwise.
141      */
142     std::shared_ptr<CPVRClient> GetClient(int iClientId) const;
143 
144     /*!
145      * @brief Get access to the pvr gui actions.
146      * @return The gui actions.
147      */
148     std::shared_ptr<CPVRGUIActions> GUIActions() const;
149 
150     /*!
151      * @brief Get access to the pvr playback state.
152      * @return The playback state.
153      */
154     std::shared_ptr<CPVRPlaybackState> PlaybackState() const;
155 
156     /*!
157      * @brief Get access to the epg container.
158      * @return The epg container.
159      */
160     CPVREpgContainer& EpgContainer();
161 
162     /*!
163      * @brief Init PVRManager.
164      */
165     void Init();
166 
167     /*!
168      * @brief Start the PVRManager, which loads all PVR data and starts some threads to update the PVR data.
169      */
170     void Start();
171 
172     /*!
173      * @brief Stop PVRManager.
174      */
175     void Stop(bool bRestart = false);
176 
177     /*!
178      * @brief Stop PVRManager, unload data.
179      */
180     void Unload();
181 
182     /*!
183      * @brief Deinit PVRManager, unload data, unload addons.
184      */
185     void Deinit();
186 
187     /*!
188      * @brief Propagate event on system sleep
189      */
190     void OnSleep();
191 
192     /*!
193      * @brief Propagate event on system wake
194      */
195     void OnWake();
196 
197     /*!
198      * @brief Get the TV database.
199      * @return The TV database.
200      */
201     std::shared_ptr<CPVRDatabase> GetTVDatabase() const;
202 
203     /*!
204      * @return True while the PVRManager is initialising.
205      */
IsInitialising()206     inline bool IsInitialising() const
207     {
208       return GetState() == ManagerStateStarting;
209     }
210 
211     /*!
212      * @brief Check whether the PVRManager has fully started.
213      * @return True if started, false otherwise.
214      */
IsStarted()215     inline bool IsStarted() const
216     {
217       return GetState() == ManagerStateStarted;
218     }
219 
220     /*!
221      * @brief Check whether the PVRManager is stopping
222      * @return True while the PVRManager is stopping.
223      */
IsStopping()224     inline bool IsStopping() const
225     {
226       return GetState() == ManagerStateStopping;
227     }
228 
229     /*!
230      * @brief Check whether the PVRManager has been stopped.
231      * @return True if stopped, false otherwise.
232      */
IsStopped()233     inline bool IsStopped() const
234     {
235       return GetState() == ManagerStateStopped;
236     }
237 
238     /*!
239      * @brief Check whether EPG tags for channels have been created.
240      * @return True if EPG tags have been created, false otherwise.
241      */
242     bool EpgsCreated() const;
243 
244     /*!
245      * @brief Inform PVR manager that playback of an item just started.
246      * @param item The item that started to play.
247      */
248     void OnPlaybackStarted(const std::shared_ptr<CFileItem>& item);
249 
250     /*!
251      * @brief Inform PVR manager that playback of an item was stopped due to user interaction.
252      * @param item The item that stopped to play.
253      */
254     void OnPlaybackStopped(const std::shared_ptr<CFileItem>& item);
255 
256     /*!
257      * @brief Inform PVR manager that playback of an item has stopped without user interaction.
258      * @param item The item that ended to play.
259      */
260     void OnPlaybackEnded(const std::shared_ptr<CFileItem>& item);
261 
262     /*!
263      * @brief Let the background thread create epg tags for all channels.
264      */
265     void TriggerEpgsCreate();
266 
267     /*!
268      * @brief Let the background thread update the recordings list.
269      */
270     void TriggerRecordingsUpdate();
271 
272     /*!
273      * @brief Let the background thread update the size for any in progress recordings.
274      */
275     void TriggerRecordingsSizeInProgressUpdate();
276 
277     /*!
278      * @brief Let the background thread update the timer list.
279      */
280     void TriggerTimersUpdate();
281 
282     /*!
283      * @brief Let the background thread update the channel list.
284      */
285     void TriggerChannelsUpdate();
286 
287     /*!
288      * @brief Let the background thread update the channel groups list.
289      */
290     void TriggerChannelGroupsUpdate();
291 
292     /*!
293      * @brief Let the background thread search for all missing channel icons.
294      */
295     void TriggerSearchMissingChannelIcons();
296 
297     /*!
298      * @brief Let the background thread search for missing channel icons for channels contained in the given group.
299      * @param group The channel group.
300      */
301     void TriggerSearchMissingChannelIcons(const std::shared_ptr<CPVRChannelGroup>& group);
302 
303     /*!
304      * @brief Check whether names are still correct after the language settings changed.
305      */
306     void LocalizationChanged();
307 
308     /*!
309      * @brief Check if parental lock is overridden at the given moment.
310      * @param channel The channel to check.
311      * @return True if parental lock is overridden, false otherwise.
312      */
313     bool IsParentalLocked(const std::shared_ptr<CPVRChannel>& channel) const;
314 
315     /*!
316      * @brief Check if parental lock is overridden at the given moment.
317      * @param epgTag The epg tag to check.
318      * @return True if parental lock is overridden, false otherwise.
319      */
320     bool IsParentalLocked(const std::shared_ptr<CPVREpgInfoTag>& epgTag) const;
321 
322     /*!
323      * @brief Restart the parental timer.
324      */
325     void RestartParentalTimer();
326 
327     /*!
328      * @brief Create EPG tags for all channels in internal channel groups
329      * @return True if EPG tags where created successfully, false otherwise
330      */
331     bool CreateChannelEpgs();
332 
333     /*!
334      * @brief Signal a connection change of a client
335      */
336     void ConnectionStateChange(CPVRClient* client,
337                                const std::string& connectString,
338                                PVR_CONNECTION_STATE state,
339                                const std::string& message);
340 
341     /*!
342      * @brief Query the events available for CEventStream
343      */
Events()344     CEventStream<PVREvent>& Events() { return m_events; }
345 
346     /*!
347      * @brief Publish an event
348      * @param state the event
349      */
350     void PublishEvent(PVREvent state);
351 
352   protected:
353     /*!
354      * @brief PVR update and control thread.
355      */
356     void Process() override;
357 
358   private:
359     /*!
360      * @brief Executes "pvrpowermanagement.setwakeupcmd"
361      */
362     bool SetWakeupCommand();
363 
364     /*!
365      * @brief Load at least one client and load all other PVR data (channelgroups, timers, recordings) after loading the client.
366      * @param progressHandler The progress handler to use for showing the different load stages.
367      * @return If at least one client and all pvr data was loaded, false otherwise.
368      */
369     bool LoadComponents(CPVRGUIProgressHandler* progressHandler);
370 
371     /*!
372      * @brief Unload all PVR data (recordings, timers, channelgroups).
373      */
374     void UnloadComponents();
375 
376     /*!
377      * @brief Reset all properties.
378      */
379     void ResetProperties();
380 
381     /*!
382      * @brief Destroy PVRManager's objects.
383      */
384     void Clear();
385 
386     /*!
387      * @brief Continue playback on the last played channel.
388      */
389     void TriggerPlayChannelOnStartup();
390 
391     enum ManagerState
392     {
393       ManagerStateError = 0,
394       ManagerStateStopped,
395       ManagerStateStarting,
396       ManagerStateStopping,
397       ManagerStateInterrupted,
398       ManagerStateStarted
399     };
400 
401     /*!
402      * @brief Get the current state of the PVR manager.
403      * @return the state.
404      */
405     ManagerState GetState() const;
406 
407     /*!
408      * @brief Set the current state of the PVR manager.
409      * @param state the new state.
410      */
411     void SetState(ManagerState state);
412 
413     bool IsCurrentlyParentalLocked(const std::shared_ptr<CPVRChannel>& channel, bool bGenerallyLocked) const;
414 
415     /** @name containers */
416     //@{
417     std::shared_ptr<CPVRChannelGroupsContainer> m_channelGroups; /*!< pointer to the channel groups container */
418     std::shared_ptr<CPVRRecordings> m_recordings; /*!< pointer to the recordings container */
419     std::shared_ptr<CPVRTimers> m_timers; /*!< pointer to the timers container */
420     std::shared_ptr<CPVRClients> m_addons; /*!< pointer to the pvr addon container */
421     std::unique_ptr<CPVRGUIInfo> m_guiInfo; /*!< pointer to the guiinfo data */
422     std::shared_ptr<CPVRGUIActions> m_guiActions; /*!< pointer to the pvr gui actions */
423     CPVREpgContainer m_epgContainer; /*!< the epg container */
424     //@}
425 
426     std::unique_ptr<CPVRManagerJobQueue> m_pendingUpdates; /*!< vector of pending pvr updates */
427     std::shared_ptr<CPVRDatabase> m_database; /*!< the database for all PVR related data */
428     mutable CCriticalSection m_critSection; /*!< critical section for all changes to this class, except for changes to triggers */
429     bool m_bFirstStart = true; /*!< true when the PVR manager was started first, false otherwise */
430     bool m_bEpgsCreated = false; /*!< true if epg data for channels has been created */
431 
432     mutable CCriticalSection m_managerStateMutex;
433     ManagerState m_managerState = ManagerStateStopped;
434     std::unique_ptr<CStopWatch> m_parentalTimer;
435 
436     CCriticalSection m_startStopMutex; // mutex for protecting pvr manager's start/restart/stop sequence */
437 
438     CEventSource<PVREvent> m_events;
439 
440     const std::shared_ptr<CPVRPlaybackState> m_playbackState;
441 
442     CPVRGUIActionListener m_actionListener;
443     CPVRSettings m_settings;
444   };
445 }
446