summaryrefslogtreecommitdiffstats
path: root/xbmc/pvr/timers/PVRTimers.h
blob: 6b0e4e7f543754baabbd386b5e2d2b4940c409e3 (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
328
329
330
331
/*
 *  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 "pvr/settings/PVRSettings.h"
#include "threads/Thread.h"

#include <map>
#include <memory>
#include <queue>
#include <vector>

class CDateTime;

namespace PVR
{
enum class TimerOperationResult;
enum class PVREvent;

class CPVRChannel;
class CPVRClient;
class CPVREpgInfoTag;
class CPVRTimerInfoTag;
class CPVRTimersPath;

class CPVRTimersContainer
{
public:
  /*!
   * @brief Add a timer tag to this container or update the tag if already present in this
   * container.
   * @param The timer tag
   * @return True, if the update was successful. False, otherwise.
   */
  bool UpdateFromClient(const std::shared_ptr<CPVRTimerInfoTag>& timer);

  /*!
   * @brief Get the timer tag denoted by given client id and timer id.
   * @param iClientId The client id.
   * @param iClientIndex The timer id.
   * @return the timer tag if found, null otherwise.
   */
  std::shared_ptr<CPVRTimerInfoTag> GetByClient(int iClientId, int iClientIndex) const;

  typedef std::vector<std::shared_ptr<CPVRTimerInfoTag>> VecTimerInfoTag;
  typedef std::map<CDateTime, VecTimerInfoTag> MapTags;

  /*!
   * @brief Get the timertags map.
   * @return The map.
   */
  const MapTags& GetTags() const { return m_tags; }

protected:
  void InsertEntry(const std::shared_ptr<CPVRTimerInfoTag>& newTimer);

  mutable CCriticalSection m_critSection;
  unsigned int m_iLastId = 0;
  MapTags m_tags;
};

class CPVRTimers : public CPVRTimersContainer, private CThread
{
public:
  CPVRTimers();
  ~CPVRTimers() override = default;

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

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

  /*!
   * @brief Update all timers from PVR database and from given clients.
   * @param clients The PVR clients data should be loaded for. Leave empty for all clients.
   * @return True on success, false otherwise.
   */
  bool Update(const std::vector<std::shared_ptr<CPVRClient>>& clients);

  /*!
   * @brief unload all timers.
   */
  void Unload();

  /*!
   * @brief Update data with recordings from the given clients, sync with local data.
   * @param clients The clients to fetch data from. Leave empty to fetch data from all created
   * clients.
   * @return True on success, false otherwise.
   */
  bool UpdateFromClients(const std::vector<std::shared_ptr<CPVRClient>>& clients);

  /*!
   * @param bIgnoreReminders include or ignore reminders
   * @return The tv or radio timer that will be active next (state scheduled), or nullptr if none.
   */
  std::shared_ptr<CPVRTimerInfoTag> GetNextActiveTimer(bool bIgnoreReminders = true) const;

  /*!
   * @return The tv timer that will be active next (state scheduled), or nullptr if none.
   */
  std::shared_ptr<CPVRTimerInfoTag> GetNextActiveTVTimer() const;

  /*!
   * @return The radio timer that will be active next (state scheduled), or nullptr if none.
   */
  std::shared_ptr<CPVRTimerInfoTag> GetNextActiveRadioTimer() const;

  /*!
   * @return All timers that are active (states scheduled or recording)
   */
  std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetActiveTimers() const;

  /*!
   * @return Next due reminder, if any. Removes it from the queue of due reminders.
   */
  std::shared_ptr<CPVRTimerInfoTag> GetNextReminderToAnnnounce();

  /*!
   * Get all timers
   * @return The list of all timers
   */
  std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetAll() const;

  /*!
   * @return The amount of tv and radio timers that are active (states scheduled or recording)
   */
  int AmountActiveTimers() const;

  /*!
   * @return The amount of tv timers that are active (states scheduled or recording)
   */
  int AmountActiveTVTimers() const;

  /*!
   * @return The amount of radio timers that are active (states scheduled or recording)
   */
  int AmountActiveRadioTimers() const;

  /*!
   * @return All tv and radio timers that are recording
   */
  std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetActiveRecordings() const;

  /*!
   * @return All tv timers that are recording
   */
  std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetActiveTVRecordings() const;

  /*!
   * @return All radio timers that are recording
   */
  std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetActiveRadioRecordings() const;

  /*!
   * @return True when recording, false otherwise.
   */
  bool IsRecording() const;

  /*!
   * @brief Check if a recording is running on the given channel.
   * @param channel The channel to check.
   * @return True when recording, false otherwise.
   */
  bool IsRecordingOnChannel(const CPVRChannel& channel) const;

  /*!
   * @brief Obtain the active timer for a given channel.
   * @param channel The channel to check.
   * @return the timer, null otherwise.
   */
  std::shared_ptr<CPVRTimerInfoTag> GetActiveTimerForChannel(
      const std::shared_ptr<CPVRChannel>& channel) const;

  /*!
   * @return The amount of tv and radio timers that are currently recording
   */
  int AmountActiveRecordings() const;

  /*!
   * @return The amount of tv timers that are currently recording
   */
  int AmountActiveTVRecordings() const;

  /*!
   * @return The amount of radio timers that are currently recording
   */
  int AmountActiveRadioRecordings() const;

  /*!
   * @brief Delete all timers on a channel.
   * @param channel The channel to delete the timers for.
   * @param bDeleteTimerRules True to delete timer rules too, false otherwise.
   * @param bCurrentlyActiveOnly True to delete timers that are currently running only.
   * @return True if timers any were deleted, false otherwise.
   */
  bool DeleteTimersOnChannel(const std::shared_ptr<CPVRChannel>& channel,
                             bool bDeleteTimerRules = true,
                             bool bCurrentlyActiveOnly = false);

  /*!
   * @return Next event time (timer or daily wake up)
   */
  CDateTime GetNextEventTime() const;

  /*!
   * @brief Add a timer to the client. Doesn't add the timer to the container. The backend will do
   * this.
   * @param tag The timer to add.
   * @return True if timer add request was sent correctly, false if not.
   */
  bool AddTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag);

  /*!
   * @brief Delete a timer on the client. Doesn't delete the timer from the container. The backend
   * will do this.
   * @param tag The timer to delete.
   * @param bForce Control what to do in case the timer is currently recording.
   *        True to force to delete the timer, false to return TimerDeleteResult::RECORDING.
   * @param bDeleteRule Also delete the timer rule that scheduled the timer instead of single timer
   * only.
   * @return The result.
   */
  TimerOperationResult DeleteTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag,
                                   bool bForce = false,
                                   bool bDeleteRule = false);

  /*!
   * @brief Update the timer on the client. Doesn't update the timer in the container. The backend
   * will do this.
   * @param tag The timer to update.
   * @return True if timer update request was sent correctly, false if not.
   */
  bool UpdateTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag);

  /*!
   * @brief Get the timer tag that matches the given epg tag.
   * @param epgTag The epg tag.
   * @return The requested timer tag, or nullptr if none was found.
   */
  std::shared_ptr<CPVRTimerInfoTag> GetTimerForEpgTag(
      const std::shared_ptr<CPVREpgInfoTag>& epgTag) const;

  /*!
   * @brief Get the timer rule for a given timer tag
   * @param timer The timer to query the timer rule for
   * @return The timer rule, or nullptr if none was found.
   */
  std::shared_ptr<CPVRTimerInfoTag> GetTimerRule(
      const std::shared_ptr<CPVRTimerInfoTag>& timer) const;

  /*!
     * @brief Update the channel pointers.
     */
  void UpdateChannels();

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

  /*!
   * @brief Get a timer tag given it's unique ID
   * @param iTimerId The ID to find
   * @return The tag, or an empty one when not found
   */
  std::shared_ptr<CPVRTimerInfoTag> GetById(unsigned int iTimerId) const;

private:
  void Process() override;

  /*!
   * @brief Load all timers from PVR database.
   * @param clients The PVR clients data should be loaded for. Leave empty for all clients.
   * @return True on success, false otherwise.
   */
  bool LoadFromDatabase(const std::vector<std::shared_ptr<CPVRClient>>& clients);

  void RemoveEntry(const std::shared_ptr<CPVRTimerInfoTag>& tag);
  bool UpdateEntries(const CPVRTimersContainer& timers, const std::vector<int>& failedClients);
  bool UpdateEntries(int iMaxNotificationDelay);
  std::shared_ptr<CPVRTimerInfoTag> UpdateEntry(const std::shared_ptr<CPVRTimerInfoTag>& timer);

  bool AddLocalTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag, bool bNotify);
  bool DeleteLocalTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag, bool bNotify);
  bool UpdateLocalTimer(const std::shared_ptr<CPVRTimerInfoTag>& tag);
  std::shared_ptr<CPVRTimerInfoTag> PersistAndUpdateLocalTimer(
      const std::shared_ptr<CPVRTimerInfoTag>& timer,
      const std::shared_ptr<CPVRTimerInfoTag>& parentTimer);
  void NotifyTimersEvent(bool bAddedOrDeleted = true);

  enum TimerKind
  {
    TimerKindAny = 0,
    TimerKindTV,
    TimerKindRadio
  };

  bool KindMatchesTag(const TimerKind& eKind, const std::shared_ptr<CPVRTimerInfoTag>& tag) const;

  std::shared_ptr<CPVRTimerInfoTag> GetNextActiveTimer(const TimerKind& eKind,
                                                       bool bIgnoreReminders) const;
  int AmountActiveTimers(const TimerKind& eKind) const;
  std::vector<std::shared_ptr<CPVRTimerInfoTag>> GetActiveRecordings(const TimerKind& eKind) const;
  int AmountActiveRecordings(const TimerKind& eKind) const;

  bool CheckAndAppendTimerNotification(std::vector<std::pair<int, std::string>>& timerNotifications,
                                       const std::shared_ptr<CPVRTimerInfoTag>& tag,
                                       bool bDeleted) const;

  bool m_bIsUpdating = false;
  CPVRSettings m_settings;
  std::queue<std::shared_ptr<CPVRTimerInfoTag>> m_remindersToAnnounce;
  bool m_bReminderRulesUpdatePending = false;

  bool m_bFirstUpdate = true;
  std::vector<int> m_failedClients;
};
} // namespace PVR