2 * Copyright (C) 2012-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
11 #include "XBDateTime.h"
12 #include "pvr/timers/PVRTimerType.h"
13 #include "threads/CriticalSection.h"
14 #include "utils/ISerializable.h"
26 enum class TimerOperationResult
30 RECORDING
// The timer was not deleted because it is currently recording (see DeleteTimer).
33 class CPVRTimerInfoTag final
: public ISerializable
35 // allow these classes direct access to members as they act as timer tag instance factories.
36 friend class CGUIDialogPVRTimerSettings
;
37 friend class CPVRDatabase
;
40 explicit CPVRTimerInfoTag(bool bRadio
= false);
41 CPVRTimerInfoTag(const PVR_TIMER
& timer
,
42 const std::shared_ptr
<CPVRChannel
>& channel
,
43 unsigned int iClientId
);
45 bool operator==(const CPVRTimerInfoTag
& right
) const;
46 bool operator!=(const CPVRTimerInfoTag
& right
) const;
49 * @brief Copy over data to the given PVR_TIMER instance.
50 * @param timer The timer instance to fill.
52 void FillAddonData(PVR_TIMER
& timer
) const;
54 // ISerializable implementation
55 void Serialize(CVariant
& value
) const override
;
57 static constexpr int DEFAULT_PVRRECORD_INSTANTRECORDTIME
= -1;
60 * @brief create a tag for an instant timer for a given channel
61 * @param channel is the channel the instant timer is to be created for
62 * @param iDuration is the duration for the instant timer, DEFAULT_PVRRECORD_INSTANTRECORDTIME
63 * denotes system default (setting value)
64 * @return the timer or null if timer could not be created
66 static std::shared_ptr
<CPVRTimerInfoTag
> CreateInstantTimerTag(
67 const std::shared_ptr
<CPVRChannel
>& channel
,
68 int iDuration
= DEFAULT_PVRRECORD_INSTANTRECORDTIME
);
71 * @brief create a tag for a timer for a given channel at given time for given duration
72 * @param channel is the channel the timer is to be created for
73 * @param start is the start time for the recording
74 * @param iDuration is the duration of the recording
75 * @return the timer or null if timer could not be created
77 static std::shared_ptr
<CPVRTimerInfoTag
> CreateTimerTag(
78 const std::shared_ptr
<CPVRChannel
>& channel
, const CDateTime
& start
, int iDuration
);
81 * @brief create a recording or reminder timer or timer rule for the given epg info tag.
82 * @param tag the epg info tag
83 * @param bCreateRule if true, create a timer rule, create a one shot timer otherwise
84 * @param bCreateReminder if true, create a reminder timer or rule, create a recording timer
86 * @param bReadOnly whether the timer/rule is read only
87 * @return the timer or null if timer could not be created
89 static std::shared_ptr
<CPVRTimerInfoTag
> CreateFromEpg(const std::shared_ptr
<CPVREpgInfoTag
>& tag
,
92 bool bReadOnly
= false);
95 * @brief create a timer or timer rule for the given epg info tag.
96 * @param tag the epg info tag
97 * @param bCreateRule if true, create a timer rule, create a one shot timer otherwise
98 * @return the timer or null if timer could not be created
100 static std::shared_ptr
<CPVRTimerInfoTag
> CreateFromEpg(const std::shared_ptr
<CPVREpgInfoTag
>& tag
,
101 bool bCreateRule
= false);
104 * @brief create a reminder timer for the given start date.
105 * @param start the start date
106 * @param iDuration the duration the reminder is valid
107 * @param parent If non-zero, the new timer will be made a child of the given timer rule
108 * @return the timer or null if timer could not be created
110 static std::shared_ptr
<CPVRTimerInfoTag
> CreateReminderFromDate(
111 const CDateTime
& start
,
113 const std::shared_ptr
<CPVRTimerInfoTag
>& parent
= std::shared_ptr
<CPVRTimerInfoTag
>());
116 * @brief create a reminder timer for the given epg info tag.
117 * @param tag the epg info tag
118 * @param parent If non-zero, the new timer will be made a child of the given timer rule
119 * @return the timer or null if timer could not be created
121 static std::shared_ptr
<CPVRTimerInfoTag
> CreateReminderFromEpg(
122 const std::shared_ptr
<CPVREpgInfoTag
>& tag
,
123 const std::shared_ptr
<CPVRTimerInfoTag
>& parent
= std::shared_ptr
<CPVRTimerInfoTag
>());
126 * @brief Associate the given epg tag with this timer.
127 * @param tag The epg tag to assign.
129 void SetEpgInfoTag(const std::shared_ptr
<CPVREpgInfoTag
>& tag
);
132 * @brief get the epg info tag associated with this timer, if any
133 * @param bCreate if true, try to find the epg tag if not yet set (lazy evaluation)
134 * @return the epg info tag associated with this timer or null if there is no tag
136 std::shared_ptr
<CPVREpgInfoTag
> GetEpgInfoTag(bool bCreate
= true) const;
139 * @brief updates this timer excluding the state of any children.
140 * @param tag A timer containing the data that shall be merged into this timer's data.
141 * @return true if the timer was updated successfully
143 bool UpdateEntry(const std::shared_ptr
<const CPVRTimerInfoTag
>& tag
);
146 * @brief merge in the state of this child timer.
147 * @param childTimer The child timer
148 * @param bAdd If true, add child's data to parent's state, otherwise subtract.
149 * @return true if the child timer's state was merged successfully
151 bool UpdateChildState(const std::shared_ptr
<const CPVRTimerInfoTag
>& childTimer
, bool bAdd
);
154 * @brief reset the state of children related to this timer.
156 void ResetChildState();
159 * @brief Whether this timer is active.
160 * @return True if this timer is active, false otherwise.
162 bool IsActive() const
164 return m_state
== PVR_TIMER_STATE_SCHEDULED
|| m_state
== PVR_TIMER_STATE_RECORDING
||
165 m_state
== PVR_TIMER_STATE_CONFLICT_OK
|| m_state
== PVR_TIMER_STATE_CONFLICT_NOK
||
166 m_state
== PVR_TIMER_STATE_ERROR
;
170 * @brief Whether this timer is broken.
171 * @return True if this timer won't result in a recording because it is broken for some reason,
174 bool IsBroken() const
176 return m_state
== PVR_TIMER_STATE_CONFLICT_NOK
|| m_state
== PVR_TIMER_STATE_ERROR
;
180 * @brief Whether this timer has a conflict.
181 * @return True if this timer won't result in a recording because it is in conflict with another
182 * timer or live stream, false otherwise.
184 bool HasConflict() const { return m_state
== PVR_TIMER_STATE_CONFLICT_NOK
; }
187 * @brief Whether this timer is currently recording.
188 * @return True if recording, false otherwise.
190 bool IsRecording() const { return m_state
== PVR_TIMER_STATE_RECORDING
; }
193 * @brief Whether this timer is disabled, for example by the user.
194 * @return True if disabled, false otherwise.
196 bool IsDisabled() const { return m_state
== PVR_TIMER_STATE_DISABLED
; }
199 * @brief Gets the type of this timer.
200 * @return the timer type or NULL if this tag has no timer type.
202 const std::shared_ptr
<CPVRTimerType
> GetTimerType() const { return m_timerType
; }
205 * @brief Sets the type of this timer.
206 * @param the new timer type.
208 void SetTimerType(const std::shared_ptr
<CPVRTimerType
>& type
);
211 * @brief Checks whether this is a timer rule (vs. one time timer).
212 * @return True if this is a timer rule, false otherwise.
214 bool IsTimerRule() const { return m_timerType
&& m_timerType
->IsTimerRule(); }
217 * @brief Checks whether this is a reminder timer (vs. recording timer).
218 * @return True if this is a reminder timer, false otherwise.
220 bool IsReminder() const { return m_timerType
&& m_timerType
->IsReminder(); }
223 * @brief Checks whether this is a manual (vs. epg-based) timer.
224 * @return True if this is a manual timer, false otherwise.
226 bool IsManual() const { return m_timerType
&& m_timerType
->IsManual(); }
229 * @brief Checks whether this is an epg-based (vs. manual) timer.
230 * @return True if this is an epg-Based timer, false otherwise.
232 bool IsEpgBased() const { return !IsManual(); }
235 * @brief The ID of the client for this timer.
236 * @return The client ID or -1 if this is a local timer.
238 int ClientID() const { return m_iClientId
; }
241 * @brief Check, whether this timer is owned by a pvr client or by Kodi.
242 * @return True, if owned by a pvr client, false otherwise.
244 bool IsOwnedByClient() const;
247 * @brief Whether this timer is for Radio or TV.
248 * @return True if Radio, false otherwise.
250 bool IsRadio() const { return m_bIsRadio
; }
253 * @brief The path that identifies this timer.
256 const std::string
& Path() const;
259 * @brief The index for this timer, as given by the client.
260 * @return The client index or PVR_TIMER_NO_CLIENT_INDEX if the timer was just created locally
261 * by Kodi and was not yet added by the client.
263 int ClientIndex() const { return m_iClientIndex
; }
266 * @brief The index for the parent of this timer, as given by the client. Timers scheduled by a
267 * timer rule will have a parant index != PVR_TIMER_NO_PARENT.
268 * @return The client index or PVR_TIMER_NO_PARENT if the timer has no parent.
270 int ParentClientIndex() const { return m_iParentClientIndex
; }
273 * @brief Whether this timer has a parent.
274 * @return True if timer has a parent, false otherwise.
276 bool HasParent() const { return m_iParentClientIndex
!= PVR_TIMER_NO_PARENT
; }
279 * @brief The local ID for this timer, as given by Kodi.
280 * @return The ID or 0 if not yet set.
282 unsigned int TimerID() const { return m_iTimerId
; }
285 * @brief Set the local ID for this timer.
286 * @param id The ID to set.
288 void SetTimerID(unsigned int id
) { m_iTimerId
= id
; }
291 * @brief The UID of the channel for this timer.
292 * @return The channel UID or PVR_CHANNEL_INVALID_UID if not available.
294 int ClientChannelUID() const { return m_iClientChannelUid
; }
297 * @brief The state for this timer.
300 PVR_TIMER_STATE
State() const { return m_state
; }
303 * @brief Set the state for this timer.
304 * @param state The state to set.
306 void SetState(PVR_TIMER_STATE state
) { m_state
= state
; }
309 * @brief The title for this timer.
312 const std::string
& Title() const;
315 * @brief Check whether this timer has an associated channel.
316 * @return True if this timer has a channel set, false otherwise.
318 bool HasChannel() const;
321 * @brief Get the channel associated with this timer, if any.
322 * @return the channel or null if non is associated with this timer.
324 std::shared_ptr
<CPVRChannel
> Channel() const;
327 * @brief Update the channel associated with this timer, based on current client ID and
330 void UpdateChannel();
333 * @brief The name of the channel associated with this timer, if any.
334 * @return The channel name.
336 std::string
ChannelName() const;
339 * @brief The path for the channel icon associated with this timer, if any.
340 * @return The channel icon path.
342 std::string
ChannelIcon() const;
345 * @brief The start date and time for this timer, as UTC.
346 * @return The start date and time.
348 CDateTime
StartAsUTC() const;
351 * @brief The start date and time for this timer, as local time.
352 * @return The start date and time.
354 CDateTime
StartAsLocalTime() const;
357 * @brief Set the start date and time from a CDateTime instance carrying the data as UTC.
358 * @param start The start date and time as UTC.
360 void SetStartFromUTC(const CDateTime
& start
);
363 * @brief Set the start date and time from a CDateTime instance carrying the data as local time.
364 * @param start The start date and time as local time.
366 void SetStartFromLocalTime(const CDateTime
& start
);
369 * @brief The end date and time for this timer, as UTC.
370 * @return The start date and time.
372 CDateTime
EndAsUTC() const;
375 * @brief The end date and time for this timer, as local time.
376 * @return The start date and time.
378 CDateTime
EndAsLocalTime() const;
381 * @brief Set the end date and time from a CDateTime instance carrying the data as UTC.
382 * @param start The end date and time as UTC.
384 void SetEndFromUTC(const CDateTime
& end
);
387 * @brief Set the end date and time from a CDateTime instance carrying the data as local time.
388 * @param start The end date and time as local time.
390 void SetEndFromLocalTime(const CDateTime
& end
);
393 * @brief The first day for this timer, as UTC.
394 * @return The first day.
396 CDateTime
FirstDayAsUTC() const;
399 * @brief The first day for this timer, as local time.
400 * @return The first day.
402 CDateTime
FirstDayAsLocalTime() const;
405 * @brief Set the first dday from a CDateTime instance carrying the data as UTC.
406 * @param start The first day as UTC.
408 void SetFirstDayFromUTC(const CDateTime
& firstDay
);
411 * @brief Set the first dday from a CDateTime instance carrying the data as local time.
412 * @param start The first day as local time.
414 void SetFirstDayFromLocalTime(const CDateTime
& firstDay
);
417 * @brief Helper function to convert a given CDateTime containing data as UTC to local time.
418 * @param utc A CDateTime instance carrying data as UTC.
419 * @return A CDateTime instance carrying data as local time.
421 static CDateTime
ConvertUTCToLocalTime(const CDateTime
& utc
);
424 * @brief Helper function to convert a given CDateTime containing data as local time to UTC.
425 * @param local A CDateTime instance carrying data as local time.
426 * @return A CDateTime instance carrying data as UTC.
428 static CDateTime
ConvertLocalTimeToUTC(const CDateTime
& local
);
431 * @brief Get the duration of this timer in seconds, excluding padding times.
432 * @return The duration.
434 int GetDuration() const;
437 * @brief Get time in minutes to start the recording before the start time of the programme.
438 * @return The start padding time.
440 unsigned int MarginStart() const { return m_iMarginStart
; }
443 * @brief Get time in minutes to end the recording after the end time of the programme.
444 * @return The end padding time.
446 unsigned int MarginEnd() const { return m_iMarginEnd
; }
449 * @brief For timer rules, the days of week this timer rule is scheduled for.
450 * @return The days of week.
452 unsigned int WeekDays() const { return m_iWeekdays
; }
455 * @brief For timer rules, whether start time is "any time", not a particular time.
456 * @return True, if timer start is "any time", false otherwise.
458 bool IsStartAnyTime() const { return m_bStartAnyTime
; }
461 * @brief For timer rules, whether end time is "any time", not a particular time.
462 * @return True, if timer end is "any time", false otherwise.
464 bool IsEndAnyTime() const { return m_bEndAnyTime
; }
467 * @brief For timer rules, whether only the EPG programme title shall be searched or also other
468 * data like the programme's plot, if available.
469 * @return True, if not only the programme's title shall be included in EPG search,
472 bool IsFullTextEpgSearch() const { return m_bFullTextEpgSearch
; }
475 * @brief For timer rules, the epg data match string for searches. Format is backend-dependent,
476 * for example regexp.
477 * @return The search string
479 const std::string
& EpgSearchString() const { return m_strEpgSearchString
; }
482 * @brief The series link for this timer.
483 * @return The series link or empty string, if not available.
485 const std::string
& SeriesLink() const;
488 * @brief Get the UID of the epg event associated with this timer tag, if any.
489 * @return The UID or EPG_TAG_INVALID_UID.
491 unsigned int UniqueBroadcastID() const { return m_iEpgUid
; }
494 * @brief Add this timer to the backend, transferring all local data of this timer to the backend.
495 * @return True on success, false otherwise.
497 bool AddToClient() const;
500 * @brief Delete this timer on the backend.
501 * @param bForce Control what to do in case the timer is currently recording.
502 * True to force to delete the timer, false to return TimerDeleteResult::RECORDING.
503 * @return The result.
505 TimerOperationResult
DeleteFromClient(bool bForce
= false) const;
508 * @brief Update this timer on the backend, transferring all local data of this timer to
510 * @return True on success, false otherwise.
512 bool UpdateOnClient();
515 * @brief Persist this timer in the local database.
516 * @return True on success, false otherwise.
521 * @brief Delete this timer from the local database.
522 * @return True on success, false otherwise.
524 bool DeleteFromDatabase();
527 * @brief GUI support: Get the text for the timer GUI notification.
528 * @return The notification text.
530 std::string
GetNotificationText() const;
533 * @brief GUI support: Get the text for the timer GUI notification when a timer has been deleted.
534 * @return The notification text.
536 std::string
GetDeletedNotificationText() const;
539 * @brief GUI support: Get the summary text for this timer, reflecting the timer schedule in a
540 * human readable form.
541 * @return The summary string.
543 const std::string
& Summary() const;
546 * @brief GUI support: Update the summary text for this timer.
548 void UpdateSummary();
551 * @brief GUI support: Get the status text for this timer, reflecting its current state in a
552 * human readable form.
553 * @return The status string.
555 std::string
GetStatus(bool bRadio
) const;
558 * @brief GUI support: Get the timer string in a human readable form.
559 * @return The type string.
561 std::string
GetTypeAsString() const;
564 * @brief GUI support: Return string representation for any possible combination of weekdays.
565 * @param iWeekdays weekdays as bit mask (0x01 = Mo, 0x02 = Tu, ...)
566 * @param bEpgBased context is an epg-based timer
567 * @param bLongMultiDaysFormat use long format. ("Mo-__-We-__-Fr-Sa-__" vs. "Mo-We-Fr-Sa")
568 * @return The weekdays string representation.
570 static std::string
GetWeekdaysString(unsigned int iWeekdays
,
572 bool bLongMultiDaysFormat
);
575 CPVRTimerInfoTag(const CPVRTimerInfoTag
& tag
) = delete;
576 CPVRTimerInfoTag
& operator=(const CPVRTimerInfoTag
& orig
) = delete;
578 std::string
GetWeekdaysString() const;
579 void UpdateEpgInfoTag();
581 static std::shared_ptr
<CPVRTimerInfoTag
> CreateFromDate(
582 const std::shared_ptr
<CPVRChannel
>& channel
,
583 const CDateTime
& start
,
585 bool bCreateReminder
,
588 mutable CCriticalSection m_critSection
;
590 std::string m_strTitle
; /*!< @brief name of this timer */
592 m_strEpgSearchString
; /*!< @brief a epg data match string for epg-based timer rules. Format is backend-dependent, for example regexp */
593 bool m_bFullTextEpgSearch
=
594 false; /*!< @brief indicates whether only epg episode title can be matched by the pvr backend or "more" (backend-dependent") data. */
595 std::string m_strDirectory
; /*!< @brief directory where the recording must be stored */
596 std::string m_strSummary
; /*!< @brief summary string with the time to show inside a GUI list */
597 PVR_TIMER_STATE m_state
= PVR_TIMER_STATE_SCHEDULED
; /*!< @brief the state of this timer */
598 int m_iClientId
; /*!< @brief ID of the backend */
599 int m_iClientIndex
; /*!< @brief index number of the tag, given by the backend, PVR_TIMER_NO_CLIENT_INDEX for new */
600 int m_iParentClientIndex
; /*!< @brief for timers scheduled by a timer rule, the index number of the parent, given by the backend, PVR_TIMER_NO_PARENT for no parent */
601 int m_iClientChannelUid
; /*!< @brief channel uid */
602 bool m_bStartAnyTime
=
603 false; /*!< @brief Ignore start date and time clock. Record at 'Any Time' */
604 bool m_bEndAnyTime
= false; /*!< @brief Ignore end date and time clock. Record at 'Any Time' */
605 int m_iPriority
; /*!< @brief priority of the timer */
606 int m_iLifetime
; /*!< @brief lifetime of the timer in days */
607 int m_iMaxRecordings
=
608 0; /*!< @brief (optional) backend setting for maximum number of recordings to keep*/
609 unsigned int m_iWeekdays
; /*!< @brief bit based store of weekdays for timer rules */
611 m_iPreventDupEpisodes
; /*!< @brief only record new episodes for epg-based timer rules */
612 unsigned int m_iRecordingGroup
=
613 0; /*!< @brief (optional) if set, the addon/backend stores the recording to a group (sub-folder) */
614 std::string m_strFileNameAndPath
; /*!< @brief file name is only for reference */
615 bool m_bIsRadio
; /*!< @brief is radio channel if set */
616 unsigned int m_iTimerId
= 0; /*!< @brief id that won't change as long as Kodi is running */
618 m_iMarginStart
; /*!< @brief (optional) if set, the backend starts the recording iMarginStart minutes before startTime. */
620 m_iMarginEnd
; /*!< @brief (optional) if set, the backend ends the recording iMarginEnd minutes after endTime. */
622 m_iEpgUid
; /*!< id of epg event associated with this timer, EPG_TAG_INVALID_UID if none. */
623 std::string m_strSeriesLink
; /*!< series link */
625 CDateTime m_StartTime
; /*!< start time */
626 CDateTime m_StopTime
; /*!< stop time */
627 CDateTime m_FirstDay
; /*!< if it is a manual timer rule the first date it starts */
628 std::shared_ptr
<CPVRTimerType
> m_timerType
; /*!< the type of this timer */
630 unsigned int m_iTVChildTimersActive
= 0;
631 unsigned int m_iTVChildTimersConflictNOK
= 0;
632 unsigned int m_iTVChildTimersRecording
= 0;
633 unsigned int m_iTVChildTimersErrors
= 0;
634 unsigned int m_iRadioChildTimersActive
= 0;
635 unsigned int m_iRadioChildTimersConflictNOK
= 0;
636 unsigned int m_iRadioChildTimersRecording
= 0;
637 unsigned int m_iRadioChildTimersErrors
= 0;
639 mutable std::shared_ptr
<CPVREpgInfoTag
> m_epgTag
; /*!< epg info tag matching m_iEpgUid. */
640 mutable std::shared_ptr
<CPVRChannel
> m_channel
;
642 mutable bool m_bProbedEpgTag
= false;