Skip to content

Commit

Permalink
Add support for Autorec property 'Broadcast type' (HTSPv39+) and DVR …
Browse files Browse the repository at this point in the history
…entry property 'DVR configuration'.
  • Loading branch information
ksooo committed Aug 28, 2024
1 parent ce9ba70 commit 943c419
Show file tree
Hide file tree
Showing 11 changed files with 257 additions and 25 deletions.
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.3.0"
version="22.4.0"
name="Tvheadend HTSP Client"
provider-name="Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld">
<requires>@ADDON_DEPENDS@</requires>
Expand Down
5 changes: 5 additions & 0 deletions pvr.hts/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
v22.4.0
- PVR Add-on API v9.1.0
- Add support for Autorec property "Broadcast type" (HTSPv39+)
- Add support for DVR entry property "DVR configuration"

v22.3.0
- Add support for PVR Providers (HTSPv38+)

Expand Down
38 changes: 34 additions & 4 deletions pvr.hts/resources/language/resource.language.en_gb/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,13 @@ msgctxt "#30372"
msgid "Record if unique episode according EPG/XMLTV"
msgstr ""

#empty strings from id 30373 to 30374
#. Prevent duplicate episodes representation
#: src/Tvheadend.cpp
msgctxt "#30373"
msgid "Use DVR configuration"
msgstr ""

#empty string with id 30374

#. Recording lifetime representation
#: src/Tvheadend.cpp
Expand Down Expand Up @@ -441,7 +447,11 @@ msgctxt "#30456"
msgid "Subscription error"
msgstr ""

#empty strings from id 30457 to 30499
msgctxt "#30457"
msgid "DVR configuration (empty = default)"
msgstr ""

#empty strings from id 30458 to 30499

msgctxt "#30500"
msgid "Streaming profile"
Expand All @@ -451,8 +461,6 @@ msgctxt "#30501"
msgid "Profile to use (empty = default)"
msgstr ""

#. Check streaming profile validity during startup
#: src/client.cpp
msgctxt "#30502"
msgid "Streaming profile %s is not available"
msgstr ""
Expand All @@ -478,3 +486,25 @@ msgstr ""
msgctxt "#30511"
msgid "Server based play status"
msgstr ""

#empty strings from id 30512 to 30599

msgctxt "#30600"
msgid "Broadcast type"
msgstr ""

msgctxt "#30601"
msgid "Any"
msgstr ""

msgctxt "#30602"
msgid "New / premiere / unknown"
msgstr ""

msgctxt "#30603"
msgid "Repeated"
msgstr ""

msgctxt "#30604"
msgid "New / premiere"
msgstr ""
122 changes: 116 additions & 6 deletions src/Tvheadend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iterator>
#include <memory>

using namespace tvheadend;
Expand Down Expand Up @@ -167,6 +168,56 @@ std::string CTvheadend::GetImageURL(const char* str)
}
}

void CTvheadend::QueryAvailableDvrConfigurations(std::unique_lock<std::recursive_mutex>& lock)
{
/* Build message */
htsmsg_t* m = htsmsg_create_map();

/* Send */
m = m_conn->SendAndWait0(lock, "getDvrConfigs", m);

/* Validate */
if (!m)
return;

htsmsg_t* l = htsmsg_get_list(m, "dvrconfigs");

if (!l)
{
Logger::Log(LogLevel::LEVEL_ERROR, "malformed getDvrConfigs: 'dvrconfigs' missing");
htsmsg_destroy(m);
return;
}

/* Process */
Logger::Log(LogLevel::LEVEL_INFO, " Available DVR configurations:");

htsmsg_field_t* f = nullptr;
HTSMSG_FOREACH(f, l)
{
Profile profile;

const char* str = htsmsg_get_str(&f->hmf_msg, "uuid");
if (str)
profile.SetUuid(str);

str = htsmsg_get_str(&f->hmf_msg, "name");
if (str)
profile.SetName(str);

str = htsmsg_get_str(&f->hmf_msg, "comment");
if (str)
profile.SetComment(str);

Logger::Log(LogLevel::LEVEL_INFO, " Name: %s, Comment: %s", profile.GetName().c_str(),
profile.GetComment().c_str());

m_dvrConfigs.emplace_back(std::move(profile));
}

htsmsg_destroy(m);
}

void CTvheadend::QueryAvailableProfiles(std::unique_lock<std::recursive_mutex>& lock)
{
/* Build message */
Expand Down Expand Up @@ -845,14 +896,17 @@ struct TimerType : kodi::addon::PVRTimerType
const std::vector<kodi::addon::PVRTypeIntValue>& lifetimeValues =
std::vector<kodi::addon::PVRTypeIntValue>(),
const std::vector<kodi::addon::PVRTypeIntValue>& dupEpisodesValues =
std::vector<kodi::addon::PVRTypeIntValue>())
std::vector<kodi::addon::PVRTypeIntValue>(),
const std::vector<kodi::addon::PVRIntSettingDefinition>& customIntSettingDefs =
std::vector<kodi::addon::PVRIntSettingDefinition>())
{
SetId(id);
SetAttributes(attributes);
SetDescription(description);
SetPriorities(priorityValues, settings->GetDvrPriority());
SetLifetimes(lifetimeValues, LifetimeMapper::TvhToKodi(settings->GetDvrLifetime()));
SetPreventDuplicateEpisodes(dupEpisodesValues, settings->GetDvrDupdetect());
SetCustomIntSettingDefinitions(customIntSettingDefs);
}
};

Expand Down Expand Up @@ -880,6 +934,30 @@ void CTvheadend::GetLivetimeValues(std::vector<kodi::addon::PVRTypeIntValue>& li
};
}

const std::vector<kodi::addon::PVRIntSettingDefinition> CTvheadend::
GetCustomCommonIntSettingDefinitions() const
{
std::vector<kodi::addon::PVRIntSettingDefinition> ret;

// DVR configuration
std::vector<kodi::addon::PVRTypeIntValue> dvrConfigValues;
int idx{0};
for (const auto& entry : m_dvrConfigs)
{
dvrConfigValues.emplace_back(idx, entry.GetName());
++idx;
}

kodi::addon::PVRIntSettingDefinition settingDef;
settingDef.SetId(CUSTOM_PROP_ID_DVR_CONFIGURATION);
settingDef.SetName(kodi::addon::GetLocalizedString(30457));
settingDef.SetValues(dvrConfigValues);
settingDef.SetDefaultValue(0); //! @todo proper default
ret.emplace_back(std::move(settingDef));

return ret;
}

PVR_ERROR CTvheadend::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& types)
{
/* PVR_Timer.iPriority values and presentation.*/
Expand All @@ -898,6 +976,7 @@ PVR_ERROR CTvheadend::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& type

/* PVR_Timer.iPreventDuplicateEpisodes values and presentation.*/
std::vector<kodi::addon::PVRTypeIntValue> deDupValues = {
{DVR_AUTOREC_RECORD_DVR_PROFILE, kodi::addon::GetLocalizedString(30373)},
{DVR_AUTOREC_RECORD_ALL, kodi::addon::GetLocalizedString(30356)},
{DVR_AUTOREC_RECORD_DIFFERENT_EPISODE_NUMBER, kodi::addon::GetLocalizedString(30357)},
{DVR_AUTOREC_RECORD_DIFFERENT_SUBTITLE, kodi::addon::GetLocalizedString(30358)},
Expand Down Expand Up @@ -951,6 +1030,10 @@ PVR_ERROR CTvheadend::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& type

/* Timer types definition. */

/* Custom common integer settings */
const std::vector<kodi::addon::PVRIntSettingDefinition> customCommonIntSettingDefs{
GetCustomCommonIntSettingDefinitions()};

/* One-shot manual (time and channel based) */
types.emplace_back(TimerType(
/* Settings */
Expand All @@ -964,7 +1047,11 @@ PVR_ERROR CTvheadend::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& type
/* Values definitions for priorities. */
priorityValues,
/* Values definitions for lifetime. */
lifetimeValues));
lifetimeValues,
/* Values definitions for prevent duplicate episodes. */
{},
/* Custom int settings definitions. */
customCommonIntSettingDefs));

/* One-shot epg based */
types.emplace_back(TimerType(
Expand All @@ -979,7 +1066,11 @@ PVR_ERROR CTvheadend::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& type
/* Values definitions for priorities. */
priorityValues,
/* Values definitions for lifetime. */
lifetimeValues));
lifetimeValues,
/* Values definitions for prevent duplicate episodes. */
{},
/* Custom int settings definitions. */
customCommonIntSettingDefs));

/* Read-only one-shot for timers generated by timerec */
types.emplace_back(TimerType(
Expand Down Expand Up @@ -1028,7 +1119,17 @@ PVR_ERROR CTvheadend::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& type
/* Values definitions for priorities. */
priorityValues,
/* Values definitions for lifetime. */
lifetimeValues));
lifetimeValues,
/* Values definitions for prevent duplicate episodes. */
{},
/* Custom int settings definitions. */
customCommonIntSettingDefs));

/* Custom Autorec integer settings */
std::vector<kodi::addon::PVRIntSettingDefinition> customAutorecIntSettingDefs{
m_autoRecordings.GetCustomAutorecIntSettingDefinitions()};
std::copy(customCommonIntSettingDefs.cbegin(), customCommonIntSettingDefs.cend(),
std::back_inserter(customAutorecIntSettingDefs));

if (m_conn->GetProtocol() >= 29)
{
Expand Down Expand Up @@ -1060,7 +1161,11 @@ PVR_ERROR CTvheadend::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& type
/* Values definitions for priorities. */
priorityValues,
/* Values definitions for lifetime. */
lifetimeValues));
lifetimeValues,
/* Values definitions for prevent duplicate episodes. */
{},
/* Custom int settings definitions. */
customAutorecIntSettingDefs));
}

unsigned int TIMER_REPEATING_EPG_ATTRIBS =
Expand Down Expand Up @@ -1094,7 +1199,9 @@ PVR_ERROR CTvheadend::GetTimerTypes(std::vector<kodi::addon::PVRTimerType>& type
/* Values definitions for lifetime. */
lifetimeValues,
/* Values definitions for prevent duplicate episodes. */
deDupValues));
deDupValues,
/* Custom int setting definitions. */
customAutorecIntSettingDefs));

return PVR_ERROR_NO_ERROR;
}
Expand Down Expand Up @@ -1539,6 +1646,9 @@ bool CTvheadend::Connected(std::unique_lock<std::recursive_mutex>& lock)
/* Query the server for available streaming profiles */
QueryAvailableProfiles(lock);

/* Query the server for available DVR configurations */
QueryAvailableDvrConfigurations(lock);

/* Show a notification if the profile is not available */
const std::string streamingProfile = m_settings->GetStreamingProfile();

Expand Down
20 changes: 18 additions & 2 deletions src/Tvheadend.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,22 @@ class ATTR_DLL_LOCAL CTvheadend : public kodi::addon::CInstancePVRClient,
std::string GetImageURL(const char* str);

/**
* Queries the server for available streaming profiles and populates
* m_profiles
* Queries the server for available DVR configurations and populates m_dvrConfigs
*/
void QueryAvailableDvrConfigurations(std::unique_lock<std::recursive_mutex>& lock);

/**
* Queries the server for available streaming profiles and populates m_profiles
*/
void QueryAvailableProfiles(std::unique_lock<std::recursive_mutex>& lock);

/**
* Get custom int setting defininitions common for all timer types that can be used to by users
* to create timers (time-based, epg-based) and timer rules (Aurorecs, Timerecs).
*/
const std::vector<kodi::addon::PVRIntSettingDefinition> GetCustomCommonIntSettingDefinitions()
const;

/**
* @param streamingProfile the streaming profile to check for
* @return whether the server supports the specified streaming profile
Expand Down Expand Up @@ -262,6 +273,11 @@ class ATTR_DLL_LOCAL CTvheadend : public kodi::addon::CInstancePVRClient,
*/
PVR_ERROR GetStreamTimes(kodi::addon::PVRStreamTimes& times) override;

/**
* The DVR configurations available on the server
*/
tvheadend::Profiles m_dvrConfigs;

/**
* The streaming profiles available on the server
*/
Expand Down
Loading

0 comments on commit 943c419

Please sign in to comment.