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.
9 #include "PVRTimerRuleMatcher.h"
11 #include "XBDateTime.h"
12 #include "addons/kodi-dev-kit/include/kodi/c-api/addon-instance/pvr/pvr_channels.h" // PVR_CHANNEL_INVALID_UID
13 #include "pvr/epg/EpgInfoTag.h"
14 #include "pvr/timers/PVRTimerInfoTag.h"
15 #include "utils/RegExp.h"
21 CPVRTimerRuleMatcher::CPVRTimerRuleMatcher(const std::shared_ptr
<CPVRTimerInfoTag
>& timerRule
,
22 const CDateTime
& start
)
23 : m_timerRule(timerRule
), m_start(CPVRTimerInfoTag::ConvertUTCToLocalTime(start
))
27 CPVRTimerRuleMatcher::~CPVRTimerRuleMatcher() = default;
29 std::shared_ptr
<const CPVRChannel
> CPVRTimerRuleMatcher::GetChannel() const
31 if (m_timerRule
->GetTimerType()->SupportsChannels())
32 return m_timerRule
->Channel();
37 CDateTime
CPVRTimerRuleMatcher::GetNextTimerStart() const
39 if (!m_timerRule
->GetTimerType()->SupportsStartTime())
40 return CDateTime(); // invalid datetime
42 const CDateTime startDateLocal
= m_timerRule
->GetTimerType()->SupportsFirstDay()
43 ? m_timerRule
->FirstDayAsLocalTime()
45 const CDateTime startTimeLocal
= m_timerRule
->StartAsLocalTime();
46 CDateTime
nextStart(startDateLocal
.GetYear(), startDateLocal
.GetMonth(), startDateLocal
.GetDay(),
47 startTimeLocal
.GetHour(), startTimeLocal
.GetMinute(), 0);
49 const CDateTimeSpan
oneDay(1, 0, 0, 0);
50 while (nextStart
< m_start
)
55 if (m_timerRule
->GetTimerType()->SupportsWeekdays() &&
56 m_timerRule
->WeekDays() != PVR_WEEKDAY_ALLDAYS
)
61 int startWeekday
= nextStart
.GetDayOfWeek();
62 if (startWeekday
== 0)
65 bMatch
= ((1 << (startWeekday
- 1)) & m_timerRule
->WeekDays());
71 return nextStart
.GetAsUTCDateTime();
74 bool CPVRTimerRuleMatcher::Matches(const std::shared_ptr
<const CPVREpgInfoTag
>& epgTag
) const
76 return epgTag
&& CPVRTimerInfoTag::ConvertUTCToLocalTime(epgTag
->EndAsUTC()) > m_start
&&
77 MatchSeriesLink(epgTag
) && MatchChannel(epgTag
) && MatchStart(epgTag
) &&
78 MatchEnd(epgTag
) && MatchDayOfWeek(epgTag
) && MatchSearchText(epgTag
);
81 bool CPVRTimerRuleMatcher::MatchSeriesLink(
82 const std::shared_ptr
<const CPVREpgInfoTag
>& epgTag
) const
84 if (m_timerRule
->GetTimerType()->RequiresEpgSeriesLinkOnCreate())
85 return epgTag
->SeriesLink() == m_timerRule
->SeriesLink();
90 bool CPVRTimerRuleMatcher::MatchChannel(const std::shared_ptr
<const CPVREpgInfoTag
>& epgTag
) const
92 if (m_timerRule
->GetTimerType()->SupportsAnyChannel() &&
93 m_timerRule
->ClientChannelUID() == PVR_CHANNEL_INVALID_UID
)
94 return true; // matches any channel
96 if (m_timerRule
->GetTimerType()->SupportsChannels())
97 return m_timerRule
->ClientChannelUID() != PVR_CHANNEL_INVALID_UID
&&
98 epgTag
->ClientID() == m_timerRule
->ClientID() &&
99 epgTag
->UniqueChannelID() == m_timerRule
->ClientChannelUID();
104 bool CPVRTimerRuleMatcher::MatchStart(const std::shared_ptr
<const CPVREpgInfoTag
>& epgTag
) const
106 if (m_timerRule
->GetTimerType()->SupportsFirstDay())
108 // only year, month and day do matter here...
109 const CDateTime startEpgLocal
= CPVRTimerInfoTag::ConvertUTCToLocalTime(epgTag
->StartAsUTC());
110 const CDateTime
startEpg(startEpgLocal
.GetYear(), startEpgLocal
.GetMonth(),
111 startEpgLocal
.GetDay(), 0, 0, 0);
112 const CDateTime firstDayLocal
= m_timerRule
->FirstDayAsLocalTime();
113 const CDateTime
startTimer(firstDayLocal
.GetYear(), firstDayLocal
.GetMonth(),
114 firstDayLocal
.GetDay(), 0, 0, 0);
115 if (startEpg
< startTimer
)
119 if (m_timerRule
->GetTimerType()->SupportsStartAnyTime() && m_timerRule
->IsStartAnyTime())
120 return true; // matches any start time
122 if (m_timerRule
->GetTimerType()->SupportsStartTime())
124 // only hours and minutes do matter here...
125 const CDateTime startEpgLocal
= CPVRTimerInfoTag::ConvertUTCToLocalTime(epgTag
->StartAsUTC());
126 const CDateTime
startEpg(2000, 1, 1, startEpgLocal
.GetHour(), startEpgLocal
.GetMinute(), 0);
127 const CDateTime startTimerLocal
= m_timerRule
->StartAsLocalTime();
128 const CDateTime
startTimer(2000, 1, 1, startTimerLocal
.GetHour(), startTimerLocal
.GetMinute(),
130 return startEpg
>= startTimer
;
136 bool CPVRTimerRuleMatcher::MatchEnd(const std::shared_ptr
<const CPVREpgInfoTag
>& epgTag
) const
138 if (m_timerRule
->GetTimerType()->SupportsEndAnyTime() && m_timerRule
->IsEndAnyTime())
139 return true; // matches any end time
141 if (m_timerRule
->GetTimerType()->SupportsEndTime())
143 // only hours and minutes do matter here...
144 const CDateTime endEpgLocal
= CPVRTimerInfoTag::ConvertUTCToLocalTime(epgTag
->EndAsUTC());
145 const CDateTime
endEpg(2000, 1, 1, endEpgLocal
.GetHour(), endEpgLocal
.GetMinute(), 0);
146 const CDateTime endTimerLocal
= m_timerRule
->EndAsLocalTime();
147 const CDateTime
endTimer(2000, 1, 1, endTimerLocal
.GetHour(), endTimerLocal
.GetMinute(), 0);
148 return endEpg
<= endTimer
;
154 bool CPVRTimerRuleMatcher::MatchDayOfWeek(const std::shared_ptr
<const CPVREpgInfoTag
>& epgTag
) const
156 if (m_timerRule
->GetTimerType()->SupportsWeekdays())
158 if (m_timerRule
->WeekDays() != PVR_WEEKDAY_ALLDAYS
)
160 const CDateTime startEpgLocal
= CPVRTimerInfoTag::ConvertUTCToLocalTime(epgTag
->StartAsUTC());
161 int startWeekday
= startEpgLocal
.GetDayOfWeek();
162 if (startWeekday
== 0)
165 return ((1 << (startWeekday
- 1)) & m_timerRule
->WeekDays());
171 bool CPVRTimerRuleMatcher::MatchSearchText(
172 const std::shared_ptr
<const CPVREpgInfoTag
>& epgTag
) const
174 if (m_timerRule
->GetTimerType()->SupportsEpgFulltextMatch() && m_timerRule
->IsFullTextEpgSearch())
178 m_textSearch
= std::make_unique
<CRegExp
>(true /* case insensitive */);
179 m_textSearch
->RegComp(m_timerRule
->EpgSearchString());
181 return m_textSearch
->RegFind(epgTag
->Title()) >= 0 ||
182 m_textSearch
->RegFind(epgTag
->EpisodeName()) >= 0 ||
183 m_textSearch
->RegFind(epgTag
->PlotOutline()) >= 0 ||
184 m_textSearch
->RegFind(epgTag
->Plot()) >= 0;
186 else if (m_timerRule
->GetTimerType()->SupportsEpgTitleMatch())
190 m_textSearch
= std::make_unique
<CRegExp
>(true /* case insensitive */);
191 m_textSearch
->RegComp(m_timerRule
->EpgSearchString());
193 return m_textSearch
->RegFind(epgTag
->Title()) >= 0;