Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Autorec properties "Start after" and "Start before" #690

Merged
merged 1 commit into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pvr.hts/addon.xml.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon
id="pvr.hts"
version="22.5.0"
version="22.6.0"
name="Tvheadend HTSP Client"
provider-name="Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld">
<requires>@ADDON_DEPENDS@</requires>
Expand Down
3 changes: 3 additions & 0 deletions pvr.hts/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
v22.6.0
- Add support for Autorec properties "Start after" and "Start before"

v22.5.0
- PVR Add-on API v9.2.0
- Add support for multiple recorded streams at a time (used by Kodi for thumbnail extraction)
Expand Down
24 changes: 0 additions & 24 deletions pvr.hts/resources/instance-settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -166,30 +166,6 @@

<category id="timer" label="30010" help="-1">
<group id="1" label="30050">
<setting id="autorec_approxtime" type="integer" label="30051" help="-1">
<level>0</level>
<default>0</default> <!-- Strict (start time + end time) -->
<constraints>
<options>
<option label="30052">0</option> <!-- Strict (start time + end time) -->
<option label="30053">1</option> <!-- Relaxed (start time +/- margin) -->
</options>
</constraints>
<control type="list" format="string" />
</setting>
<setting id="autorec_maxdiff" type="integer" label="30054" help="-1">
<level>0</level>
<default>15</default>
<constraints>
<minimum>0</minimum>
<step>5</step>
<maximum>120</maximum>
</constraints>
<dependencies>
<dependency type="enable" setting="autorec_approxtime">1</dependency>
</dependencies>
<control type="slider" format="integer" />
</setting>
<setting id="autorec_use_regex" type="boolean" label="30061" help="-1">
<level>0</level>
<default>false</default>
Expand Down
24 changes: 8 additions & 16 deletions pvr.hts/resources/language/resource.language.en_gb/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -88,22 +88,6 @@ msgctxt "#30050"
msgid "Auto recordings"
msgstr ""

msgctxt "#30051"
msgid "Start time window calculation"
msgstr ""

msgctxt "#30052"
msgid "Strict (start time + end time)"
msgstr ""

msgctxt "#30053"
msgid "Relaxed (start time +/- margin)"
msgstr ""

msgctxt "#30054"
msgid "Maximum start time margin (minutes)"
msgstr ""

msgctxt "#30055"
msgid "Default priority"
msgstr ""
Expand Down Expand Up @@ -516,3 +500,11 @@ msgstr ""
msgctxt "#30605"
msgid "(Default profile)"
msgstr ""

msgctxt "#30606"
msgid "Start after"
msgstr ""

msgctxt "#30607"
msgid "Start before"
msgstr ""
18 changes: 1 addition & 17 deletions src/Tvheadend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1113,19 +1113,11 @@ PVR_ERROR CTvheadend::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& type
{
unsigned int TIMER_REPEATING_SERIESLINK_ATTRIBS =
PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE |
PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_START_TIME |
PVR_TIMER_TYPE_SUPPORTS_START_ANYTIME | PVR_TIMER_TYPE_SUPPORTS_WEEKDAYS |
PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_WEEKDAYS |
PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY |
PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_FOLDERS |
PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL | PVR_TIMER_TYPE_REQUIRES_EPG_SERIESLINK_ON_CREATE;

if (!m_settings->GetAutorecApproxTime())
{
/* We need the end time to represent the end of the tvh starting window */
TIMER_REPEATING_SERIESLINK_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_END_TIME;
TIMER_REPEATING_SERIESLINK_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_END_ANYTIME;
}

/* Repeating epg based - series link autorec */
types.emplace_back(TimerType(
/* Settings */
Expand All @@ -1147,19 +1139,11 @@ PVR_ERROR CTvheadend::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& type
unsigned int TIMER_REPEATING_EPG_ATTRIBS =
PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE |
PVR_TIMER_TYPE_SUPPORTS_TITLE_EPG_MATCH | PVR_TIMER_TYPE_SUPPORTS_CHANNELS |
PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_START_ANYTIME |
PVR_TIMER_TYPE_SUPPORTS_WEEKDAYS | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN |
PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME |
PVR_TIMER_TYPE_SUPPORTS_RECORDING_FOLDERS | PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL |
PVR_TIMER_TYPE_SUPPORTS_FULLTEXT_EPG_MATCH | PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES;

if (!m_settings->GetAutorecApproxTime())
{
/* We need the end time to represent the end of the tvh starting window */
TIMER_REPEATING_EPG_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_END_TIME;
TIMER_REPEATING_EPG_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_END_ANYTIME;
}

/* Repeating epg based - autorec */
types.emplace_back(TimerType(
/* Settings */
Expand Down
81 changes: 2 additions & 79 deletions src/tvheadend/AutoRecordings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ AutoRecordings::AutoRecordings(const std::shared_ptr<InstanceSettings>& settings
Profiles& dvrConfigs)
: m_settings(settings),
m_conn(conn),
m_customTimerProps({CUSTOM_PROP_ID_DVR_CONFIGURATION, CUSTOM_PROP_ID_AUTOREC_BROADCASTTYPE,
m_customTimerProps({CUSTOM_PROP_ID_AUTOREC_START, CUSTOM_PROP_ID_AUTOREC_STARTWINDOW,
CUSTOM_PROP_ID_AUTOREC_BROADCASTTYPE, CUSTOM_PROP_ID_DVR_CONFIGURATION,
CUSTOM_PROP_ID_DVR_COMMENT},
conn,
dvrConfigs)
Expand Down Expand Up @@ -69,23 +70,6 @@ void AutoRecordings::GetAutorecTimers(std::vector<kodi::addon::PVRTimer>& timers
tmr.SetClientIndex(rec.second.GetId());
tmr.SetClientChannelUid((rec.second.GetChannel() > 0) ? rec.second.GetChannel()
: PVR_TIMER_ANY_CHANNEL);
tmr.SetStartTime(rec.second.GetStart());
tmr.SetEndTime(rec.second.GetStop());
if (tmr.GetStartTime() == 0)
tmr.SetStartAnyTime(true);
if (tmr.GetEndTime() == 0)
tmr.SetEndAnyTime(true);

if (!tmr.GetStartAnyTime() && tmr.GetEndAnyTime())
tmr.SetEndTime(tmr.GetStartTime() + 60 * 60); // Nominal 1 hour duration
if (tmr.GetStartAnyTime() && !tmr.GetEndAnyTime())
tmr.SetStartTime(tmr.GetEndTime() - 60 * 60); // Nominal 1 hour duration
if (tmr.GetStartAnyTime() && tmr.GetEndAnyTime())
{
tmr.SetStartTime(std::time(nullptr)); // now
tmr.SetEndTime(tmr.GetStartTime() + 60 * 60); // Nominal 1 hour duration
}

if (rec.second.GetName().empty()) // timers created on backend may not contain a name
tmr.SetTitle(rec.second.GetTitle());
else
Expand Down Expand Up @@ -211,66 +195,6 @@ PVR_ERROR AutoRecordings::SendAutorecAddOrUpdate(const kodi::addon::PVRTimer& ti
if (timer.GetDirectory() != "/")
htsmsg_add_str(m, "directory", timer.GetDirectory().c_str());


/* bAutorecApproxTime enabled: => start time in kodi = approximate start time in tvh */
/* => 'approximate' = starting window / 2 */
/* */
/* bAutorecApproxTime disabled: => start time in kodi = begin of starting window in tvh */
/* => end time in kodi = end of starting window in tvh */
if (m_settings->GetAutorecApproxTime())
{
/* Not sending causes server to set start and startWindow to any time */
if (timer.GetStartTime() > 0 && !timer.GetStartAnyTime())
{
time_t startTime = timer.GetStartTime();
struct tm* tm_start = std::localtime(&startTime);
int32_t startWindowBegin =
tm_start->tm_hour * 60 + tm_start->tm_min - m_settings->GetAutorecMaxDiff();
int32_t startWindowEnd =
tm_start->tm_hour * 60 + tm_start->tm_min + m_settings->GetAutorecMaxDiff();

/* Past midnight correction */
if (startWindowBegin < 0)
startWindowBegin += (24 * 60);
if (startWindowEnd > (24 * 60))
startWindowEnd -= (24 * 60);

htsmsg_add_s32(m, "start", startWindowBegin);
htsmsg_add_s32(m, "startWindow", startWindowEnd);
}
else
{
htsmsg_add_s32(m, "start", -1);
htsmsg_add_s32(m, "startWindow", -1);
}
}
else
{
if (timer.GetStartTime() > 0 && !timer.GetStartAnyTime())
{
/* Exact start time (minutes from midnight). */
time_t startTime = timer.GetStartTime();
struct tm* tm_start = std::localtime(&startTime);
htsmsg_add_s32(m, "start", tm_start->tm_hour * 60 + tm_start->tm_min);
}
else
htsmsg_add_s32(
m, "start",
25 * 60); // -1 or not sending causes server to set start and startWindow to any time

if (timer.GetEndTime() > 0 && !timer.GetEndAnyTime())
{
/* Exact stop time (minutes from midnight). */
time_t endTime = timer.GetEndTime();
struct tm* tm_stop = std::localtime(&endTime);
htsmsg_add_s32(m, "startWindow", tm_stop->tm_hour * 60 + tm_stop->tm_min);
}
else
htsmsg_add_s32(
m, "startWindow",
25 * 60); // -1 or not sending causes server to set start and startWindow to any time
}

/* series link */
if (timer.GetTimerType() == TIMER_REPEATING_SERIESLINK)
htsmsg_add_str(m, "serieslinkUri", timer.GetSeriesLink().c_str());
Expand Down Expand Up @@ -341,7 +265,6 @@ bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t* msg, bool bAdd)

/* Locate/create entry */
AutoRecording& rec = m_autoRecordings[std::string(str)];
rec.SetSettings(m_settings);
rec.SetStringId(std::string(str));
rec.SetDirty(false);

Expand Down
73 changes: 73 additions & 0 deletions src/tvheadend/CustomTimerProperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ std::vector<kodi::addon::PVRSettingKeyValuePair> CustomTimerProperties::GetPrope
{
switch (propId)
{
case CUSTOM_PROP_ID_AUTOREC_START:
{
// Start
customProps.emplace_back(CUSTOM_PROP_ID_AUTOREC_START, autorec.GetStartWindowBegin());
break;
}
case CUSTOM_PROP_ID_AUTOREC_STARTWINDOW:
{
// Start window
customProps.emplace_back(CUSTOM_PROP_ID_AUTOREC_STARTWINDOW, autorec.GetStartWindowEnd());
break;
}
case CUSTOM_PROP_ID_AUTOREC_BROADCASTTYPE:
{
// Broadcast type
Expand Down Expand Up @@ -105,6 +117,28 @@ const std::vector<kodi::addon::PVRSettingDefinition> CustomTimerProperties::GetS
{
switch (propId)
{
case CUSTOM_PROP_ID_AUTOREC_START:
{
int defaultValue{AUTOREC_START_ANYTIME};
const std::vector<kodi::addon::PVRTypeIntValue> startValues{
GetPossibleValues(CUSTOM_PROP_ID_AUTOREC_START, defaultValue)};
ret.emplace_back(CreateSettingDefinition(CUSTOM_PROP_ID_AUTOREC_START,
30606, // Start after
startValues, defaultValue,
PVR_SETTING_READONLY_CONDITION_NONE));
break;
}
case CUSTOM_PROP_ID_AUTOREC_STARTWINDOW:
{
int defaultValue{AUTOREC_START_ANYTIME};
const std::vector<kodi::addon::PVRTypeIntValue> startWindowValues{
GetPossibleValues(CUSTOM_PROP_ID_AUTOREC_STARTWINDOW, defaultValue)};
ret.emplace_back(CreateSettingDefinition(CUSTOM_PROP_ID_AUTOREC_STARTWINDOW,
30607, // Start before
startWindowValues, defaultValue,
PVR_SETTING_READONLY_CONDITION_NONE));
break;
}
case CUSTOM_PROP_ID_AUTOREC_BROADCASTTYPE:
{
// Broadcast type
Expand Down Expand Up @@ -166,6 +200,33 @@ const std::vector<kodi::addon::PVRTypeIntValue> CustomTimerProperties::GetPossib
{
switch (propId)
{
case CUSTOM_PROP_ID_AUTOREC_START:
case CUSTOM_PROP_ID_AUTOREC_STARTWINDOW:
{
// Start, Start window

// Any : AUTOREC_START_ANYTIME (-1)
// 0:00 : 0
// 0:10 : 0 * 60 + 10
// ...
// 23:50 : 23 * 60 + 50
static std::vector<kodi::addon::PVRTypeIntValue> startValues{};
if (startValues.empty())
{
startValues.reserve(24 * 60 / 10 + 1);
startValues.emplace_back(
kodi::addon::PVRTypeIntValue(AUTOREC_START_ANYTIME,
kodi::addon::GetLocalizedString(30601))); // Any
for (int i = 0; i < 24 * 60; i += 10)
{
const std::string hours{std::to_string(i / 60)};
const std::string minutes{(i % 60) == 0 ? "00" : std::to_string(i % 60)};
startValues.emplace_back(kodi::addon::PVRTypeIntValue(i, hours + ":" + minutes));
}
}
defaultValue = AUTOREC_START_ANYTIME; // Any
return startValues;
}
case CUSTOM_PROP_ID_AUTOREC_BROADCASTTYPE:
{
// Broadcast type
Expand Down Expand Up @@ -241,6 +302,18 @@ void CustomTimerProperties::AppendPropertiesToHTSPMessage(
{
switch (prop.GetKey())
{
case CUSTOM_PROP_ID_AUTOREC_START:
{
// Start
htsmsg_add_s32(msg, "start", prop.GetIntValue());
break;
}
case CUSTOM_PROP_ID_AUTOREC_STARTWINDOW:
{
// Start window
htsmsg_add_s32(msg, "startWindow", prop.GetIntValue());
break;
}
case CUSTOM_PROP_ID_AUTOREC_BROADCASTTYPE:
{
// Broadcast type
Expand Down
2 changes: 2 additions & 0 deletions src/tvheadend/CustomTimerProperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class RecordingBase;
constexpr unsigned int CUSTOM_PROP_ID_AUTOREC_BROADCASTTYPE{1};
constexpr unsigned int CUSTOM_PROP_ID_DVR_CONFIGURATION{2};
constexpr unsigned int CUSTOM_PROP_ID_DVR_COMMENT{3};
constexpr unsigned int CUSTOM_PROP_ID_AUTOREC_START{4};
constexpr unsigned int CUSTOM_PROP_ID_AUTOREC_STARTWINDOW{5};

class CustomTimerProperties
{
Expand Down
15 changes: 0 additions & 15 deletions src/tvheadend/InstanceSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,7 @@ const bool DEFAULT_ASYNC_EPG = true;
const bool DEFAULT_PRETUNER_ENABLED = false;
const int DEFAULT_TOTAL_TUNERS = 1; // total tuners > 1 => predictive tuning active
const int DEFAULT_PRETUNER_CLOSEDELAY = 10; // secs
const int DEFAULT_AUTOREC_MAXDIFF =
15; // mins. Maximum difference between real and approximate start time for auto recordings
const bool DEFAULT_AUTOREC_USE_REGEX = false;
const int DEFAULT_APPROX_TIME =
0; // don't use an approximate start time, use a fixed time instead for auto recordings
const std::string DEFAULT_STREAMING_PROFILE = "";
const bool DEFAULT_STREAMING_HTTP = false;
const int DEFAULT_DVR_PRIO = DVR_PRIO_NORMAL;
Expand Down Expand Up @@ -62,8 +58,6 @@ InstanceSettings::InstanceSettings(kodi::addon::IAddonInstance& instance)
m_bPretunerEnabled(DEFAULT_PRETUNER_ENABLED),
m_iTotalTuners(DEFAULT_TOTAL_TUNERS),
m_iPreTunerCloseDelay(DEFAULT_PRETUNER_CLOSEDELAY),
m_iAutorecApproxTime(DEFAULT_APPROX_TIME),
m_iAutorecMaxDiff(DEFAULT_AUTOREC_MAXDIFF),
m_bAutorecUseRegEx(DEFAULT_AUTOREC_USE_REGEX),
m_strStreamingProfile(DEFAULT_STREAMING_PROFILE),
m_bUseHTTPStreaming(DEFAULT_STREAMING_HTTP),
Expand Down Expand Up @@ -103,8 +97,6 @@ void InstanceSettings::ReadSettings()
m_bPretunerEnabled ? ReadIntSetting("pretuner_closedelay", DEFAULT_PRETUNER_CLOSEDELAY) : 0);

/* Auto recordings */
SetAutorecApproxTime(ReadIntSetting("autorec_approxtime", DEFAULT_APPROX_TIME));
SetAutorecMaxDiff(ReadIntSetting("autorec_maxdiff", DEFAULT_AUTOREC_MAXDIFF));
SetAutorecUseRegEx(ReadBoolSetting("autorec_use_regex", DEFAULT_AUTOREC_USE_REGEX));

/* Streaming */
Expand Down Expand Up @@ -176,13 +168,6 @@ ADDON_STATUS InstanceSettings::SetSetting(const std::string& key,
return ADDON_STATUS_OK;
}
/* Auto recordings */
else if (key == "autorec_approxtime")
return SetIntSetting(GetAutorecApproxTime(), value);
else if (key == "autorec_maxdiff")
{
SetAutorecMaxDiff(value.GetInt());
return ADDON_STATUS_OK;
}
else if (key == "autorec_use_regex")
{
SetAutorecUseRegEx(value.GetBoolean());
Expand Down
Loading