Skip to content

Commit

Permalink
Add backend timer rules
Browse files Browse the repository at this point in the history
NextPVR allows timeslot and also  episode timers, pvr.nextpvr didn't support all episode single channel timers.  Legacy backend code was defaulting the daily timeslot recording to an all episode recording.   Added logic for backend type 2 and type 3 timers to handle these situations.
  • Loading branch information
emveepee committed Apr 27, 2024
1 parent 974eb06 commit 0bfa933
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 18 deletions.
2 changes: 2 additions & 0 deletions pvr.nextpvr/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
v21.0.4
- Allow control of recording and timers access
- Support all episode single channel recordings
- Force Daily recordings to daily timeslot recordings

v21.0.3
- Translations updates from Weblate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,3 +437,7 @@ msgstr ""
msgctxt "#30217"
msgid "Live TV only"
msgstr ""

msgctxt "#30218"
msgid "Repeating (all episodes)"
msgstr ""
97 changes: 82 additions & 15 deletions src/Timers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ PVR_ERROR Timers::GetTimers(kodi::addon::PVRTimersResultSet& results)
tag.SetEndTime(TIMER_DATE_MIN);
tag.SetStartAnyTime(true);
tag.SetEndAnyTime(true);
if (recordingType == 2)
{
tag.SetTimerType(TIMER_REPEATING_EPG_ALL_EPISODES);
}
}
else
{
Expand Down Expand Up @@ -390,6 +394,7 @@ PVR_ERROR Timers::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& types)
static const int MSG_REPEATING_CHILD = 30144;
static const int MSG_REPEATING_KEYWORD = 30145;
static const int MSG_REPEATING_ADVANCED = 30171;
static const int MSG_REPEATING_ALL_EPISODES = 30218;

static const int MSG_KEEPALL = 30150;
static const int MSG_KEEP1 = 30151;
Expand Down Expand Up @@ -532,7 +537,7 @@ PVR_ERROR Timers::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& types)
types.emplace_back(*t);
delete t;

/* Repeating epg based Parent*/
/* Repeating epg based Parent timeslot */
t = new TimerType(
/* Type id. */
TIMER_REPEATING_EPG,
Expand All @@ -545,6 +550,21 @@ PVR_ERROR Timers::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& types)
types.emplace_back(*t);
delete t;

/* Repeating epg based all episode*/
t = new TimerType(
/* Type id. */
TIMER_REPEATING_EPG_ALL_EPISODES,
/* Attributes. */
TIMER_EPG_ATTRIBS | TIMER_REPEATING_EPG_ATTRIBS & ~(PVR_TIMER_TYPE_SUPPORTS_WEEKDAYS),
/* Description. */
GetTimerDescription(MSG_REPEATING_ALL_EPISODES), // "Repeating (All episodes)"
/* Values definitions for attributes. */
recordingLimitValues, m_defaultLimit, showTypeValues, m_defaultShowType, recordingGroupValues, 0);
types.emplace_back(*t);
delete t;



/* Read-only one-shot for timers generated by timerec */
t = new TimerType(
/* Type id. */
Expand Down Expand Up @@ -669,6 +689,7 @@ PVR_ERROR Timers::AddTimer(const kodi::addon::PVRTimer& timer)
const std::string encodedName = UriEncode(timer.GetTitle());
const std::string encodedKeyword = UriEncode(timer.GetEPGSearchString());
const std::string days = GetDayString(timer.GetWeekdays());

const std::string directory = UriEncode(m_settings->m_recordingDirectories[timer.GetRecordingGroup()]);

int epgOid = 0;
Expand All @@ -689,7 +710,18 @@ PVR_ERROR Timers::AddTimer(const kodi::addon::PVRTimer& timer)
marginEnd = m_settings->m_defaultPostPadding;
}

switch (timer.GetTimerType())
int timerType = timer.GetTimerType();
size_t countDays = std::count(days.begin(), days.end(), ':');
if (timerType == TIMER_REPEATING_EPG)
{
if (countDays > 1 && countDays < 7)
{
// Backend doesn't support mixed days change to type 2 any episode
timerType = TIMER_REPEATING_EPG_ALL_EPISODES;
}
}

switch (timerType)
{
case TIMER_ONCE_MANUAL:
kodi::Log(ADDON_LOG_DEBUG, "TIMER_ONCE_MANUAL");
Expand Down Expand Up @@ -735,7 +767,7 @@ PVR_ERROR Timers::AddTimer(const kodi::addon::PVRTimer& timer)
if (timer.GetEPGSearchString() == TYPE_7_TITLE)
{
kodi::Log(ADDON_LOG_DEBUG, "TIMER_REPEATING_EPG ANY CHANNEL - TYPE 7");
request = kodi::tools::StringUtils::Format("recording.recurring.save&type=7&recurring_id=%d&start_time=%d&end_time=%d&keep=%d&pre_padding=%d&post_padding=%d&day_mask=%s&directory_id=%s%s",
request = kodi::tools::StringUtils::Format("recording.recurring.save&recurring_type=7&recurring_id=%d&start_time=%d&end_time=%d&keep=%d&pre_padding=%d&post_padding=%d&day_mask=%s&directory_id=%s%s",
timer.GetClientIndex(),
static_cast<int>(timer.GetStartTime()),
static_cast<int>(timer.GetEndTime()),
Expand Down Expand Up @@ -769,21 +801,56 @@ PVR_ERROR Timers::AddTimer(const kodi::addon::PVRTimer& timer)
else
{
kodi::Log(ADDON_LOG_DEBUG, "TIMER_REPEATING_EPG");
// build recurring recording request
request = kodi::tools::StringUtils::Format("recording.recurring.save&recurring_id=%d&channel_id=%d&event_id=%d&keep=%d&pre_padding=%d&post_padding=%d&day_mask=%s&directory_id=%s&only_new=%s%s",
timer.GetClientIndex(),
timer.GetClientChannelUid(),
epgOid,
timer.GetMaxRecordings(),
marginStart,
marginEnd,
days.c_str(),
directory.c_str(),
preventDuplicates,
enabled.c_str()
if (countDays == 7)
{
// build recurring type 3 request for a daily request not automatic timeslot
request = kodi::tools::StringUtils::Format("recording.recurring.save&recurring_type=3&recurring_id=%d&channel_id=%d&event_id=%d&keep=%d&pre_padding=%d&post_padding=%d&directory_id=%s&only_new=%s%s",
timer.GetClientIndex(),
timer.GetClientChannelUid(),
epgOid,
timer.GetMaxRecordings(),
marginStart,
marginEnd,
directory.c_str(),
preventDuplicates,
enabled.c_str()
);
}
else
{
// NextPVR saves DAY, WEEKEND and WEEKDAY as timeslot recordings
request = kodi::tools::StringUtils::Format("recording.recurring.save&recurring_id=%d&channel_id=%d&event_id=%d&keep=%d&pre_padding=%d&post_padding=%d&day_mask=%s&directory_id=%s&only_new=%s%s",
timer.GetClientIndex(),
timer.GetClientChannelUid(),
epgOid,
timer.GetMaxRecordings(),
marginStart,
marginEnd,
days.c_str(),
directory.c_str(),
preventDuplicates,
enabled.c_str()
);
}
}
break;
case TIMER_REPEATING_EPG_ALL_EPISODES:
// NextPVR doesn't support daymask but pass it anyway.
kodi::Log(ADDON_LOG_DEBUG, "TIMER_REPEATING_EPG_ALL_EPISODES");
// build recurring type 2 request
request = kodi::tools::StringUtils::Format("recording.recurring.save&recurring_type=2&recurring_id=%d&channel_id=%d&event_id=%d&keep=%d&pre_padding=%d&post_padding=%d&day_mask=%s&directory_id=%s&only_new=%s%s",
timer.GetClientIndex(),
timer.GetClientChannelUid(),
epgOid,
timer.GetMaxRecordings(),
marginStart,
marginEnd,
days.c_str(),
directory.c_str(),
preventDuplicates,
enabled.c_str()
);
break;

case TIMER_REPEATING_MANUAL:
kodi::Log(ADDON_LOG_DEBUG, "TIMER_REPEATING_MANUAL");
Expand Down
7 changes: 4 additions & 3 deletions src/Timers.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ namespace NextPVR
constexpr unsigned int TIMER_REPEATING_MIN = TIMER_MANUAL_MAX + 1;
constexpr unsigned int TIMER_REPEATING_MANUAL = TIMER_REPEATING_MIN;
constexpr unsigned int TIMER_REPEATING_EPG = TIMER_REPEATING_MIN + 1;
constexpr unsigned int TIMER_REPEATING_KEYWORD = TIMER_REPEATING_MIN + 2;
constexpr unsigned int TIMER_REPEATING_ADVANCED = TIMER_REPEATING_MIN + 3;
constexpr unsigned int TIMER_REPEATING_MAX = TIMER_REPEATING_MIN + 3;
constexpr unsigned int TIMER_REPEATING_EPG_ALL_EPISODES = TIMER_REPEATING_MIN + 2;
constexpr unsigned int TIMER_REPEATING_KEYWORD = TIMER_REPEATING_MIN + 3;
constexpr unsigned int TIMER_REPEATING_ADVANCED = TIMER_REPEATING_MIN + 4;
constexpr unsigned int TIMER_REPEATING_MAX = TIMER_REPEATING_MIN + 4;

class ATTR_DLL_LOCAL Timers
{
Expand Down

0 comments on commit 0bfa933

Please sign in to comment.