Skip to content

Commit

Permalink
Cache channel changes
Browse files Browse the repository at this point in the history
NextPVR has no group API calls.  Cache and compress channel list to avoid extra downloads.  Compress to save on disk for large IPTV channel lists with zlib potential future use with VOD.  Also update to same tinyxml2 version used by Kodi
  • Loading branch information
emveepee committed Aug 14, 2024
1 parent babae01 commit 4f0a3a2
Show file tree
Hide file tree
Showing 18 changed files with 234 additions and 126 deletions.
8 changes: 7 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ project(pvr.nextpvr)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR})

find_package(Kodi REQUIRED)
find_package(ZLIB REQUIRED)
find_package(TinyXML2 REQUIRED)

include_directories(${TINYXML2_INCLUDE_DIR}
${ZLIB_INCLUDE_DIRS}
${KODI_INCLUDE_DIR}/..) # Hack way with "/..", need bigger Kodi cmake rework to match right include ways

set(NEXTPVR_SOURCES src/addon.cpp
Expand Down Expand Up @@ -51,7 +53,11 @@ set(NEXTPVR_HEADERS src/addon.h
src/utilities/SettingsMigration.h
src/utilities/XMLUtils.h)

SET(DEPLIBS ${TINYXML2_LIBRARIES})
SET(DEPLIBS ${TINYXML2_LIBRARIES}
${ZLIB_LIBRARIES})

message(STATUS "ZLIB_LIBRARIES: ${ZLIB_LIBRARIES}")

if(WIN32)
list(APPEND DEPLIBS ws2_32)
add_definitions(-D_WINSOCKAPI_ -D_WINSOCK_DEPRECATED_NO_WARNINGS)
Expand Down
87 changes: 0 additions & 87 deletions depends/common/tinyxml2/CMakeLists.txt

This file was deleted.

1 change: 1 addition & 0 deletions depends/common/tinyxml2/flags.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-Dtinyxml2_BUILD_TESTING=0
2 changes: 1 addition & 1 deletion depends/common/tinyxml2/tinyxml2.sha256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
68ebd396a4220d5a9b5a621c6e9c66349c5cfdf5efaea3f16e3bb92e45f4e2a3
cc2f1417c308b1f6acc54f88eb70771a0bf65f76282ce5c40e54cfe52952702c
2 changes: 1 addition & 1 deletion depends/common/tinyxml2/tinyxml2.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
tinyxml2 https://github.com/leethomason/tinyxml2/archive/7.1.0.tar.gz
tinyxml2 https://github.com/leethomason/tinyxml2/archive/refs/tags/9.0.0.tar.gz
36 changes: 36 additions & 0 deletions depends/common/zlib/01-build-static.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -147,10 +147,11 @@
set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
endif(MINGW)

-add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
-add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
-set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
-set_target_properties(zlib PROPERTIES SOVERSION 1)
+add_library(zlib ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
+if(BUILD_SHARED_LIBS)
+ set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
+ set_target_properties(zlib PROPERTIES SOVERSION 1)
+endif()

if(NOT CYGWIN)
# This property causes shared libraries on Linux to have the full version
@@ -165,7 +166,7 @@

if(UNIX)
# On unix-like platforms the library is almost always called libz
- set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z)
+ set_target_properties(zlib PROPERTIES OUTPUT_NAME z)
if(NOT APPLE)
set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"")
endif()
@@ -175,7 +176,7 @@
endif()

if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
- install(TARGETS zlib zlibstatic
+ install(TARGETS zlib
RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" )
28 changes: 28 additions & 0 deletions depends/common/zlib/02-disable-example-binaries.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -226,25 +226,3 @@ endif()
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
endif()
-
-#============================================================================
-# Example binaries
-#============================================================================
-
-add_executable(example test/example.c)
-target_link_libraries(example zlib)
-add_test(example example)
-
-add_executable(minigzip test/minigzip.c)
-target_link_libraries(minigzip zlib)
-
-if(HAVE_OFF64_T)
- add_executable(example64 test/example.c)
- target_link_libraries(example64 zlib)
- set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
- add_test(example64 example64)
-
- add_executable(minigzip64 test/minigzip.c)
- target_link_libraries(minigzip64 zlib)
- set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
-endif()
12 changes: 12 additions & 0 deletions depends/common/zlib/03-install-pkgconfig-in-lib.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,7 +12,7 @@ set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation direc
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
-set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
+set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")

include(CheckTypeSize)
include(CheckFunctionExists)

1 change: 1 addition & 0 deletions depends/common/zlib/zlib.sha256
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
d14c38e313afc35a9a8760dadf26042f51ea0f5d154b0630a31da0540107fb98
1 change: 1 addition & 0 deletions depends/common/zlib/zlib.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
zlib http://mirrors.kodi.tv/build-deps/sources/zlib-1.2.13.tar.xz
2 changes: 1 addition & 1 deletion pvr.nextpvr/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.nextpvr"
version="22.0.0"
version="22.1.0"
name="NextPVR PVR Client"
provider-name="Graeme Blackley">
<requires>@ADDON_DEPENDS@
Expand Down
8 changes: 8 additions & 0 deletions pvr.nextpvr/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
v22.1.0
- port PR 266 from Omega
- start timeshift in realtime for radio playback (266)
- Add support for episode and episode part parsing (266)
- Clean up duplicated S/E information sent from NextPVR in the subtitle when no subtitle is present. (266)
- Cache channel list updates, compress with zlib
- Upgrade tinyxml2

v22.0.0
- Initial release for Piers (PVR Add-on API v8.4.0)

Expand Down
97 changes: 73 additions & 24 deletions src/BackendRequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <kodi/Network.h>
#include <kodi/gui/dialogs/Select.h>
#include <kodi/tools/StringUtils.h>
#include <zlib.h>

using namespace NextPVR::utilities;

Expand Down Expand Up @@ -61,7 +62,49 @@ namespace NextPVR
tinyxml2::XMLDocument doc;
return DoMethodRequest(resource, doc, false) == tinyxml2::XML_SUCCESS;
}
/*
tinyxml2::XMLError Request::DoCachedRequest(std::string resource, tinyxml2::XMLDocument& doc, std::string cacheFile)
{
const std::string filename = kodi::tools::StringUtils::Format("%s%s.cache", m_settings->m_instanceDirectory.c_str(), resource.c_str());
gzFile gz_file;
//open the file for writing in binary mode
gz_file = gzopen(kodi::vfs::TranslateSpecialProtocol(filename).c_str(), "wb");
std::stringstream data;
//Fill stream with data
//Get the size of the stream
unsigned long int file_size = sizeof(char) * response.size();
//Write the size of the stream, this is needed so that we know
//how much to read back in later
gzwrite(gz_file, (void*)&file_size, sizeof(file_size));
//Write the data
gzwrite(gz_file, (void*)(response.c_str()), file_size);
//close the file
gzclose(gz_file);
//open the file for reading in binary mode
gz_file = gzopen("c:/temp/filename.dat", "rb");
//this variable will hold the size of the file
unsigned long int size;
//we wrote out a unsigned long int when storing the file
//read this back in to get the size of the uncompressed data
gzread(gz_file, (void*)&size, sizeof(size));
//create a string to hold data
std::string data1;
//resize the string
data1.resize(size / sizeof(char));
//read in and uncompress the entire data set at once
gzread(gz_file, (void*)data1.data(), size);
//close the file
gzclose(gz_file);
if (data1 == response)
int b = 1;
return DoMethodRequest(resource, doc);
}
*/
tinyxml2::XMLError Request::DoMethodRequest(std::string resource, tinyxml2::XMLDocument& doc, bool compressed)
{
auto start = std::chrono::steady_clock::now();
Expand Down Expand Up @@ -96,41 +139,47 @@ namespace NextPVR
response.append(buffer, count);
}
stream.Close();
retError = doc.Parse(response.c_str());
if (retError == tinyxml2::XML_SUCCESS)
retError = ParseMethodRequest(doc, response);
}
int milliseconds = static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count());
kodi::Log(ADDON_LOG_DEBUG, "DoMethodRequest %s %d %d %d", resource.c_str(), retError, response.length(), milliseconds);
return retError;
}

tinyxml2::XMLError Request::ParseMethodRequest(tinyxml2::XMLDocument& doc, std::string xml)
{
tinyxml2::XMLError retError = doc.Parse(xml.c_str());;
if (retError == tinyxml2::XML_SUCCESS)
{
const char* attrib = doc.RootElement()->Attribute("stat");
if (attrib == nullptr || strcmp(attrib, "ok"))
{
const char* attrib = doc.RootElement()->Attribute("stat");
if ( attrib == nullptr || strcmp(attrib, "ok"))
kodi::Log(ADDON_LOG_DEBUG, "DoMethodRequest bad return %s", attrib);
retError = tinyxml2::XML_NO_ATTRIBUTE;
if (!strcmp(attrib, "fail"))
{
kodi::Log(ADDON_LOG_DEBUG, "DoMethodRequest bad return %s", attrib);
retError = tinyxml2::XML_NO_ATTRIBUTE;
if (!strcmp(attrib, "fail"))
const tinyxml2::XMLElement* err = doc.RootElement()->FirstChildElement("err");
if (err)
{
const tinyxml2::XMLElement* err = doc.RootElement()->FirstChildElement("err");
if (err)
const char* code = err->Attribute("code");
if (code)
{
const char* code = err->Attribute("code");
if (code)
kodi::Log(ADDON_LOG_DEBUG, "DoMethodRequest error code %s", code);
if (atoi(code) == 8)
{
kodi::Log(ADDON_LOG_DEBUG, "DoMethodRequest error code %s", code);
if (atoi(code) == 8)
{
ClearSID();
retError = tinyxml2::XML_ERROR_FILE_COULD_NOT_BE_OPENED;
//m_pvrclient.ResetConnection();
}
ClearSID();
retError = tinyxml2::XML_ERROR_FILE_COULD_NOT_BE_OPENED;
//m_pvrclient.ResetConnection();
}
}
}
}
else
{
RenewSID();
}
}
else
{
RenewSID();
}
}
int milliseconds = static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count());
kodi::Log(ADDON_LOG_DEBUG, "DoMethodRequest %s %d %d %d", resource.c_str(), retError, response.length(), milliseconds);
return retError;
}

Expand Down
3 changes: 2 additions & 1 deletion src/BackendRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace NextPVR
int DoRequest(std::string resource, std::string& response);
bool DoActionRequest(std::string resource);
tinyxml2::XMLError DoMethodRequest(std::string resource, tinyxml2::XMLDocument& doc, bool compresssed = true);
// tinyxml2::XMLError DoCachedMethodRequest(std::string resource, tinyxml2::XMLDocument& doc, std::string cacheFile = nullptr);
int FileCopy(const char* resource, std::string fileName);
tinyxml2::XMLError GetLastUpdate(std::string resource, time_t& last_update);
bool PingBackend();
Expand All @@ -53,7 +54,7 @@ namespace NextPVR
private:
Request(Request const&) = delete;
void operator=(Request const&) = delete;

tinyxml2::XMLError ParseMethodRequest(tinyxml2::XMLDocument& doc, std::string xml);
std::shared_ptr<InstanceSettings> m_settings;
mutable std::mutex m_mutexRequest;
time_t m_start = 0;
Expand Down
Loading

0 comments on commit 4f0a3a2

Please sign in to comment.