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/settings/PVRSettings.h"
13 #include "threads/Thread.h"
14 
15 #include <map>
16 #include <memory>
17 #include <queue>
18 #include <vector>
19 
20 namespace PVR
21 {
22   enum class TimerOperationResult;
23   enum class PVREvent;
24 
25   class CPVRChannel;
26   class CPVREpgInfoTag;
27   class CPVRTimerInfoTag;
28   class CPVRTimersPath;
29 
30   class CPVRTimersContainer
31   {
32   public:
33     /*!
34      * @brief Add a timer tag to this container or update the tag if already present in this container.
35      * @param The timer tag
36      * @return True, if the update was successful. False, otherwise.
37      */
38     bool UpdateFromClient(const std::shared_ptr<CPVRTimerInfoTag>& timer);
39 
40     /*!
41      * @brief Get the timer tag denoted by given client id and timer id.
42      * @param iClientId The client id.
43      * @param iClientIndex The timer id.
44      * @return the timer tag if found, null otherwise.
45      */
46     std::shared_ptr<CPVRTimerInfoTag> GetByClient(int iClientId, int iClientIndex) const;
47 
48     typedef std::vector<std::shared_ptr<CPVRTimerInfoTag>> VecTimerInfoTag;
49     typedef std::map<CDateTime, VecTimerInfoTag> MapTags;
50 
51     /*!
52      * @brief Get the timertags map.
53      * @return The map.
54      */
GetTags()55     const MapTags& GetTags() const { return m_tags; }
56 
57   protected:
58     void InsertEntry(const std::shared_ptr<CPVRTimerInfoTag>& newTimer);
59 
60     mutable CCriticalSection m_critSection;
61     unsigned int m_iLastId = 0;
62     MapTags m_tags;
63   };
64 
65   class CPVRTimers : public CPVRTimersContainer, private CThread
66   {
67   public:
68     CPVRTimers();
69     ~CPVRTimers() override = default;
70 
71     /**
72      * @brief start the timer update thread.
73      */
74     void Start();
75 
76     /**
77      * @brief stop the timer update thread.
78      */
79     void Stop();
80 
81     /**
82      * @brief (re)load the timers from the clients.
83      * @return True if loaded successfully, false otherwise.
84      */
85     bool Load();
86 
87     /**
88      * @brief unload all timers.
89      */
90     void Unload();
91 
92     /**
93      * @brief refresh the timer list from the clients.
94      */
95     bool Update();
96 
97     /**
98      * @brief load the local timers from database.
99      * @return True if loaded successfully, false otherwise.
100      */
101     bool LoadFromDatabase();
102 
103     /*!
104      * @param bIgnoreReminders include or ignore reminders
105      * @return The tv or radio timer that will be active next (state scheduled), or an empty fileitemptr if none.
106      */
107     std::shared_ptr<CPVRTimerInfoTag> GetNextActiveTimer(bool bIgnoreReminders = true) const;
108 
109     /*!
110      * @return The tv timer that will be active next (state scheduled), or nullptr if none.
111      */
112     std::shared_ptr<CPVRTimerInfoTag> GetNextActiveTVTimer() const;
113 
114     /*!
115      * @return The radio timer that will be active next (state scheduled), or nullptr if none.
116      */
117     std::shared_ptr<CPVRTimerInfoTag> GetNextActiveRadioTimer() const;
118 
119     /*!
120      * @return All timers that are active (states scheduled or recording)
121      */
122     std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetActiveTimers() const;
123 
124     /*!
125      * @return Next due reminder, if any. Removes it from the queue of due reminders.
126      */
127     std::shared_ptr<CPVRTimerInfoTag> GetNextReminderToAnnnounce();
128 
129     /*!
130      * Get all timers
131      * @return The list of all timers
132      */
133     std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetAll() const;
134 
135     /*!
136      * @return The amount of tv and radio timers that are active (states scheduled or recording)
137      */
138     int AmountActiveTimers() const;
139 
140     /*!
141      * @return The amount of tv timers that are active (states scheduled or recording)
142      */
143     int AmountActiveTVTimers() const;
144 
145     /*!
146      * @return The amount of radio timers that are active (states scheduled or recording)
147      */
148     int AmountActiveRadioTimers() const;
149 
150     /*!
151      * @return All tv and radio timers that are recording
152      */
153     std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetActiveRecordings() const;
154 
155     /*!
156      * @return All tv timers that are recording
157      */
158     std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetActiveTVRecordings() const;
159 
160     /*!
161      * @return All radio timers that are recording
162      */
163     std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetActiveRadioRecordings() const;
164 
165     /*!
166      * @return True when recording, false otherwise.
167      */
168     bool IsRecording() const;
169 
170     /*!
171      * @brief Check if a recording is running on the given channel.
172      * @param channel The channel to check.
173      * @return True when recording, false otherwise.
174      */
175     bool IsRecordingOnChannel(const CPVRChannel& channel) const;
176 
177     /*!
178      * @brief Obtain the active timer for a given channel.
179      * @param channel The channel to check.
180      * @return the timer, null otherwise.
181      */
182     std::shared_ptr<CPVRTimerInfoTag> GetActiveTimerForChannel(const std::shared_ptr<CPVRChannel>& channel) const;
183 
184     /*!
185      * @return The amount of tv and radio timers that are currently recording
186      */
187     int AmountActiveRecordings() const;
188 
189     /*!
190      * @return The amount of tv timers that are currently recording
191      */
192     int AmountActiveTVRecordings() const;
193 
194     /*!
195      * @return The amount of radio timers that are currently recording
196      */
197     int AmountActiveRadioRecordings() const;
198 
199     /*!
200      * @brief Delete all timers on a channel.
201      * @param channel The channel to delete the timers for.
202      * @param bDeleteTimerRules True to delete timer rules too, false otherwise.
203      * @param bCurrentlyActiveOnly True to delete timers that are currently running only.
204      * @return True if timers any were deleted, false otherwise.
205      */
206     bool DeleteTimersOnChannel(const std::shared_ptr<CPVRChannel>& channel, bool bDeleteTimerRules = true, bool bCurrentlyActiveOnly = false);
207 
208     /*!
209      * @return Next event time (timer or daily wake up)
210      */
211     CDateTime GetNextEventTime() const;
212 
213     /*!
214      * @brief Add a timer to the client. Doesn't add the timer to the container. The backend will do this.
215      * @param tag The timer to add.
216      * @return True if timer add request was sent correctly, false if not.
217      */
218     bool AddTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag);
219 
220     /*!
221      * @brief Delete a timer on the client. Doesn't delete the timer from the container. The backend will do this.
222      * @param tag The timer to delete.
223      * @param bForce Control what to do in case the timer is currently recording.
224      *        True to force to delete the timer, false to return TimerDeleteResult::RECORDING.
225      * @param bDeleteRule Also delete the timer rule that scheduled the timer instead of single timer only.
226      * @return The result.
227      */
228     TimerOperationResult DeleteTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag, bool bForce = false, bool bDeleteRule = false);
229 
230     /*!
231      * @brief Update the timer on the client. Doesn't update the timer in the container. The backend will do this.
232      * @param tag The timer to update.
233      * @return True if timer update request was sent correctly, false if not.
234      */
235     bool UpdateTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag);
236 
237     /*!
238      * @brief Get the timer tag that matches the given epg tag.
239      * @param epgTag The epg tag.
240      * @return The requested timer tag, or nullptr if none was found.
241      */
242     std::shared_ptr<CPVRTimerInfoTag> GetTimerForEpgTag(const std::shared_ptr<CPVREpgInfoTag>& epgTag) const;
243 
244     /*!
245      * @brief Get the timer rule for a given timer tag
246      * @param timer The timer to query the timer rule for
247      * @return The timer rule, or nullptr if none was found.
248      */
249     std::shared_ptr<CPVRTimerInfoTag> GetTimerRule(const std::shared_ptr<CPVRTimerInfoTag>& timer) const;
250 
251     /*!
252      * @brief Update the channel pointers.
253      */
254     void UpdateChannels();
255 
256     /*!
257      * @brief CEventStream callback for PVR events.
258      * @param event The event.
259      */
260    void Notify(const PVREvent& event);
261 
262     /*!
263      * @brief Get a timer tag given it's unique ID
264      * @param iTimerId The ID to find
265      * @return The tag, or an empty one when not found
266      */
267     std::shared_ptr<CPVRTimerInfoTag> GetById(unsigned int iTimerId) const;
268 
269   private:
270     void Process() override;
271 
272     void RemoveEntry(const std::shared_ptr<CPVRTimerInfoTag>& tag);
273     bool UpdateEntries(const CPVRTimersContainer& timers, const std::vector<int>& failedClients);
274     bool UpdateEntries(int iMaxNotificationDelay);
275     std::shared_ptr<CPVRTimerInfoTag> UpdateEntry(const std::shared_ptr<CPVRTimerInfoTag>& timer);
276 
277     bool AddLocalTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag, bool bNotify);
278     bool DeleteLocalTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag, bool bNotify);
279     bool UpdateLocalTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag);
280     std::shared_ptr<CPVRTimerInfoTag> PersistAndUpdateLocalTimer(const std::shared_ptr<CPVRTimerInfoTag>& timer,
281                                                                  const std::shared_ptr<CPVRTimerInfoTag>& parentTimer);
282     void NotifyTimersEvent(bool bAddedOrDeleted = true);
283 
284     enum TimerKind
285     {
286       TimerKindAny = 0,
287       TimerKindTV,
288       TimerKindRadio
289     };
290 
291     bool KindMatchesTag(const TimerKind& eKind, const std::shared_ptr<CPVRTimerInfoTag>& tag) const;
292 
293     std::shared_ptr<CPVRTimerInfoTag> GetNextActiveTimer(const TimerKind& eKind, bool bIgnoreReminders) const;
294     int AmountActiveTimers(const TimerKind& eKind) const;
295     std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetActiveRecordings(const TimerKind& eKind) const;
296     int AmountActiveRecordings(const TimerKind& eKind) const;
297 
298     bool CheckAndAppendTimerNotification(
299         std::vector<std::pair<int, std::string>>& timerNotifications,
300         const std::shared_ptr<CPVRTimerInfoTag>& tag,
301         bool bDeleted) const;
302 
303     bool m_bIsUpdating = false;
304     CPVRSettings m_settings;
305     std::queue<std::shared_ptr<CPVRTimerInfoTag>> m_remindersToAnnounce;
306     bool m_bReminderRulesUpdatePending = false;
307 
308     bool m_bFirstUpdate = true;
309     std::vector<int> m_failedClients;
310   };
311 }
312