diff -Nru kodi-pvr-hts-19.0.6/azure-pipelines.yml kodi-pvr-hts-20.6.0/azure-pipelines.yml --- kodi-pvr-hts-19.0.6/azure-pipelines.yml 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/azure-pipelines.yml 2022-10-07 16:22:25.000000000 +0000 @@ -5,6 +5,7 @@ branches: include: - Matrix + - Nexus - releases/* paths: include: @@ -16,25 +17,25 @@ - job: Windows pool: - vmImage: 'VS2017-Win2016' + vmImage: 'windows-2022' strategy: matrix: Win32: - GENERATOR: "Visual Studio 15 2017" + GENERATOR: "Visual Studio 17 2022" ARCHITECTURE: Win32 CONFIGURATION: Release Win64: - GENERATOR: "Visual Studio 15 2017" + GENERATOR: "Visual Studio 17 2022" ARCHITECTURE: x64 CONFIGURATION: Release Win64-UWP: - GENERATOR: "Visual Studio 15 2017" + GENERATOR: "Visual Studio 17 2022" ARCHITECTURE: x64 CONFIGURATION: Release WINSTORE: -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0.17763.0" ARM64-UWP: - GENERATOR: "Visual Studio 15 2017" + GENERATOR: "Visual Studio 17 2022" ARCHITECTURE: ARM64 CONFIGURATION: Release WINSTORE: -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0.17763.0" @@ -46,7 +47,7 @@ - script: | cd .. - git clone --branch Matrix --depth=1 https://github.com/xbmc/xbmc.git kodi + git clone --branch master --depth=1 https://github.com/xbmc/xbmc.git kodi cd $(Build.SourcesDirectory) mkdir build cd build diff -Nru kodi-pvr-hts-19.0.6/CMakeLists.txt kodi-pvr-hts-20.6.0/CMakeLists.txt --- kodi-pvr-hts-19.0.6/CMakeLists.txt 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/CMakeLists.txt 2022-10-07 16:22:25.000000000 +0000 @@ -48,6 +48,8 @@ src/aac/huffman/Decoder.h) set(HTS_SOURCES_TVHEADEND + src/tvheadend/AddonSettings.cpp + src/tvheadend/AddonSettings.h src/tvheadend/AutoRecordings.cpp src/tvheadend/AutoRecordings.h src/tvheadend/ChannelTuningPredictor.h @@ -60,11 +62,11 @@ src/tvheadend/HTSPTypes.h src/tvheadend/HTSPVFS.h src/tvheadend/HTSPVFS.cpp + src/tvheadend/InstanceSettings.h + src/tvheadend/InstanceSettings.cpp src/tvheadend/IHTSPConnectionListener.h src/tvheadend/IHTSPDemuxPacketHandler.h src/tvheadend/Profile.h - src/tvheadend/Settings.cpp - src/tvheadend/Settings.h src/tvheadend/Subscription.cpp src/tvheadend/Subscription.h src/tvheadend/TimeRecordings.cpp @@ -106,7 +108,9 @@ src/tvheadend/utilities/RDSExtractor.cpp src/tvheadend/utilities/SyncedBuffer.h src/tvheadend/utilities/TCPSocket.h - src/tvheadend/utilities/TCPSocket.cpp) + src/tvheadend/utilities/TCPSocket.cpp + src/tvheadend/utilities/SettingsMigration.h + src/tvheadend/utilities/SettingsMigration.cpp) source_group("Source Files" FILES ${HTS_SOURCES}) source_group("Source Files\\aac" FILES ${HTS_SOURCES_AAC}) diff -Nru kodi-pvr-hts-19.0.6/debian/changelog kodi-pvr-hts-20.6.0/debian/changelog --- kodi-pvr-hts-19.0.6/debian/changelog 2022-03-30 08:50:04.000000000 +0000 +++ kodi-pvr-hts-20.6.0/debian/changelog 2023-01-09 16:30:41.000000000 +0000 @@ -1,55 +1,59 @@ -kodi-pvr-hts (19.0.6-1~jammy) jammy; urgency=low +kodi-pvr-hts (20.6.0-1~jammy) jammy; urgency=low [ kodi ] * autogenerated dummy changelog [ wsnipex ] - * v19.0.6 - Fix deleted recordings not disappearing in Kodi until - restart (regression introduced with v19.0.5) v19.0.5 - Translations - updates from Weblate - pl_pl - Ignore recordings without a file + * v20.6.0 - Drop support for Tvheadend < 4.2.0 v20.5.0 - Kodi + inputstream API update to version 3.2.0 - Kodi PVR API update to + version 8.0.2 v20.4.0 - Add support for multiple backends. - Request + addon-restart only on settings changes which require a reconnect to + the backend. v20.3.0 - Inputstream API bump. v20.2.2 - Fix deleted + recordings not disappearing in Kodi until restart (regression + introduced with v20.2.1) v20.2.1 - Ignore recordings without a file (e.g. removed recordings). - When parsing recording add/update messages, always set the correct error string. - Reduce debug log - spam. Do not log recording descriptions. v19.0.4 - Translations - updates from Weblate - es_mx v19.0.3 - Fix Unable to change existing - timer rule to use any time - Translations updates from Weblate - v19.0.2 - Translations updates from Weblate v19.0.1 - Fix AAC RDS - parser v19.0.0 - Translations updates from Weblate - Version - numbering scheme change. v8.4.0 - Add support for RDS data contained - in AAC streams. - Translations updates from Weblate v8.3.4 - Fixed - 'Use HTTPS' setting init/write v8.3.3 - Fixed: Crash while - restarting the add-on (due to stale HTSP connection thread after - unloading add-on's shared lib). v8.3.2 - Fixed: Timeshift issues - after pausing and resuming Live TV (affects only demuxer-served - channels). v8.3.1 - Translations updates from Weblate - af_za, - am_et, ar_sa, az_az, be_by, bg_bg, bs_ba, ca_es, cs_cz, cy_gb, - da_dk, de_de, el_gr, en_au, en_nz, en_us, eo, es_ar, es_es, es_mx, - et_ee, eu_es, fa_af, fa_ir, fi_fi, fo_fo, fr_ca, fr_fr, gl_es, - he_il, hi_in, hr_hr, hu_hu, hy_am, id_id, is_is, it_it, ja_jp, - ko_kr, lt_lt, lv_lv, mi, mk_mk, ml_in, mn_mn, ms_my, mt_mt, my_mm, - nb_no, nl_nl, pl_pl, pt_br, pt_pt, ro_ro, ru_ru, si_lk, sk_sk, - sl_si, sq_al, sr_rs, sr_rs@latin, sv_se, szl, ta_in, te_in, tg_tj, - th_th, tr_tr, uk_ua, uz_uz, vi_vn, zh_cn, zh_tw 8.3.0 - New setting: - Regular expression vs. 'contains' search for Autorecs. 8.2.4 - Fix: - broken string in en_gb resource file. 8.2.3 - Usability: Change - settings spinners to selection lists - Fixed: Timer settings: Add - missing duplicate detection values 8.2.2 - Fix: kissnet update - fixing Windows socket connection issue 8.2.1 - Fix: kissnet update - fixing socket creation/connection issue 8.2.0 - PVR API 7.1.0 - API - change to allow epg max future and past days 8.1.3 - Fix: Obtain - streaming profiles as soon as connected to backend - Fix: On system - sleep, properly close demuxers before disconnecting from backend - - Fix: Predictive Tuning: Prevent closing the subscription while re- - subscribing to it - Fix: Error handling for socket read/write - operations - Improvement: Demux read detects lost backend connection - and initiates re-connect - Fix: Fix crashes while accessing socket - concurrently - Fix: Do not reset source info when re-subscribing - 8.1.2 - More IPv6 fixes 8.1.1 - Fix IPv6 support 8.1.0 - Update - inputstream API 3.0.1 - Fix wrong flags bit shift 8.0.0 - Update PVR - API 7.0.2 7.2.2 - Fix toggling of HTTP streaming setting 7.2.1 - Fix - 'pvr.hts' appearing twice in every addon log message - Fix - calculation of start time, stop time and file size for multi-file - recordings - Remove p8-platform build dependency 7.2.0 - Add - capability to use HTTP streaming instead of HTSP 7.1.4 - Fix + spam. Do not log recording descriptions. v20.2.0 - Update + translations - Adapt to recent API changes v20.1.2 - Fix Unable to + change existing timer rule to use any time v20.1.1 - Fix AAC RDS + parser v20.1.0 - Kodi API to 8.0.0 - Add supports recordings delete + capability - Enforce EDL limits v20.0.0 - Translations updates from + Weblate - Version numbering scheme change v8.4.0 - Add support for + RDS data contained in AAC streams. - Translations updates from + Weblate v8.3.4 - Fixed 'Use HTTPS' setting init/write v8.3.3 - + Fixed: Crash while restarting the add-on (due to stale HTSP + connection thread after unloading add-on's shared lib). v8.3.2 - + Fixed: Timeshift issues after pausing and resuming Live TV (affects + only demuxer-served channels). v8.3.1 - Translations updates from + Weblate - af_za, am_et, ar_sa, az_az, be_by, bg_bg, bs_ba, ca_es, + cs_cz, cy_gb, da_dk, de_de, el_gr, en_au, en_nz, en_us, eo, es_ar, + es_es, es_mx, et_ee, eu_es, fa_af, fa_ir, fi_fi, fo_fo, fr_ca, + fr_fr, gl_es, he_il, hi_in, hr_hr, hu_hu, hy_am, id_id, is_is, + it_it, ja_jp, ko_kr, lt_lt, lv_lv, mi, mk_mk, ml_in, mn_mn, ms_my, + mt_mt, my_mm, nb_no, nl_nl, pl_pl, pt_br, pt_pt, ro_ro, ru_ru, + si_lk, sk_sk, sl_si, sq_al, sr_rs, sr_rs@latin, sv_se, szl, ta_in, + te_in, tg_tj, th_th, tr_tr, uk_ua, uz_uz, vi_vn, zh_cn, zh_tw 8.3.0 - + New setting: Regular expression vs. 'contains' search for Autorecs. + 8.2.4 - Fix: broken string in en_gb resource file. 8.2.3 - + Usability: Change settings spinners to selection lists - Fixed: + Timer settings: Add missing duplicate detection values 8.2.2 - Fix: + kissnet update fixing Windows socket connection issue 8.2.1 - Fix: + kissnet update fixing socket creation/connection issue 8.2.0 - PVR + API 7.1.0 - API change to allow epg max future and past days 8.1.3 - + Fix: Obtain streaming profiles as soon as connected to backend - + Fix: On system sleep, properly close demuxers before disconnecting + from backend - Fix: Predictive Tuning: Prevent closing the + subscription while re-subscribing to it - Fix: Error handling for + socket read/write operations - Improvement: Demux read detects lost + backend connection and initiates re-connect - Fix: Fix crashes while + accessing socket concurrently - Fix: Do not reset source info when + re-subscribing 8.1.2 - More IPv6 fixes 8.1.1 - Fix IPv6 support + 8.1.0 - Update inputstream API 3.0.1 - Fix wrong flags bit shift + 8.0.0 - Update PVR API 7.0.2 7.2.2 - Fix toggling of HTTP streaming + setting 7.2.1 - Fix 'pvr.hts' appearing twice in every addon log + message - Fix calculation of start time, stop time and file size for + multi-file recordings - Remove p8-platform build dependency 7.2.0 - + Add capability to use HTTP streaming instead of HTSP 7.1.4 - Fix deadlock while reconnecting to backend after a backend response timeout (Fixes #465) - Refactor subscription seek code - Refactor subscription weight code - Fix HTSP connection thread not ended @@ -328,4 +332,4 @@ removed unneeded member in CHTSPDemux - better handling of disconnect and reconnects 1.6.4 - initial release - -- wsnipex Wed, 30 Mar 2022 10:50:04 +0200 + -- wsnipex Mon, 09 Jan 2023 17:30:41 +0100 diff -Nru kodi-pvr-hts-19.0.6/debian/changelog.tmp kodi-pvr-hts-20.6.0/debian/changelog.tmp --- kodi-pvr-hts-19.0.6/debian/changelog.tmp 2022-03-30 08:50:04.000000000 +0000 +++ kodi-pvr-hts-20.6.0/debian/changelog.tmp 2023-01-09 16:30:37.000000000 +0000 @@ -1,4 +1,4 @@ -kodi-pvr-hts (19.0.6-1~#DIST#) #DIST#; urgency=low +kodi-pvr-hts (20.6.0-1~#DIST#) #DIST#; urgency=low [ kodi ] * autogenerated dummy changelog diff -Nru kodi-pvr-hts-19.0.6/.github/workflows/build.yml kodi-pvr-hts-20.6.0/.github/workflows/build.yml --- kodi-pvr-hts-19.0.6/.github/workflows/build.yml 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/.github/workflows/build.yml 2022-10-07 16:22:25.000000000 +0000 @@ -27,14 +27,14 @@ env: DEBIAN_BUILD: ${{ matrix.DEBIAN_BUILD }} run: | - if [[ $DEBIAN_BUILD == true ]]; then sudo add-apt-repository -y ppa:team-xbmc/ppa; fi + if [[ $DEBIAN_BUILD == true ]]; then sudo add-apt-repository -y ppa:team-xbmc/xbmc-nightly; fi if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get update; fi if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get install fakeroot; fi - name: Checkout Kodi repo uses: actions/checkout@v2 with: repository: xbmc/xbmc - ref: Matrix + ref: master path: xbmc - name: Checkout pvr.hts repo uses: actions/checkout@v2 @@ -48,7 +48,7 @@ run: | if [[ $DEBIAN_BUILD != true ]]; then cd ${app_id} && mkdir -p build && cd build; fi if [[ $DEBIAN_BUILD != true ]]; then cmake -DADDONS_TO_BUILD=${app_id} -DADDON_SRC_PREFIX=${{ github.workspace }} -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/xbmc/addons -DPACKAGE_ZIP=1 ${{ github.workspace }}/xbmc/cmake/addons; fi - if [[ $DEBIAN_BUILD == true ]]; then wget https://raw.githubusercontent.com/xbmc/xbmc/Matrix/xbmc/addons/kodi-dev-kit/tools/debian-addon-package-test.sh && chmod +x ./debian-addon-package-test.sh; fi + if [[ $DEBIAN_BUILD == true ]]; then wget https://raw.githubusercontent.com/xbmc/xbmc/master/xbmc/addons/kodi-dev-kit/tools/debian-addon-package-test.sh && chmod +x ./debian-addon-package-test.sh; fi if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get build-dep ${{ github.workspace }}/${app_id}; fi - name: Build env: diff -Nru kodi-pvr-hts-19.0.6/.github/workflows/changelog-and-release.yml kodi-pvr-hts-20.6.0/.github/workflows/changelog-and-release.yml --- kodi-pvr-hts-19.0.6/.github/workflows/changelog-and-release.yml 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/.github/workflows/changelog-and-release.yml 2022-10-07 16:22:25.000000000 +0000 @@ -133,7 +133,7 @@ shell: bash # Create a release at {steps.required-variables.outputs.branch} - # - tag and release name format: {steps.required-variables.outputs.version}-{steps.required-variables.outputs.branch} ie. 1.0.0-Matrix + # - tag and release name format: {steps.required-variables.outputs.version}-{steps.required-variables.outputs.branch} ie. 20.0.0-Nexus # - release body: {steps.required-variables.outputs.changes} - name: Create Release id: create-release diff -Nru kodi-pvr-hts-19.0.6/.github/workflows/release.yml kodi-pvr-hts-20.6.0/.github/workflows/release.yml --- kodi-pvr-hts-19.0.6/.github/workflows/release.yml 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/.github/workflows/release.yml 2022-10-07 16:22:25.000000000 +0000 @@ -50,7 +50,7 @@ working-directory: ${{ github.event.repository.name }} # Create a release at {steps.required-variables.outputs.branch} - # - tag and release name format: {steps.required-variables.outputs.version}-{steps.required-variables.outputs.branch} ie. 1.0.0-Matrix + # - tag and release name format: {steps.required-variables.outputs.version}-{steps.required-variables.outputs.branch} ie. 20.0.0-Nexus # - release body: {steps.required-variables.outputs.changes} - name: Create Release id: create-release diff -Nru kodi-pvr-hts-19.0.6/Jenkinsfile kodi-pvr-hts-20.6.0/Jenkinsfile --- kodi-pvr-hts-19.0.6/Jenkinsfile 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/Jenkinsfile 2022-10-07 16:22:25.000000000 +0000 @@ -1 +1 @@ -buildPlugin(version: "Matrix") +buildPlugin(version: "Nexus") diff -Nru kodi-pvr-hts-19.0.6/pvr.hts/addon.xml.in kodi-pvr-hts-20.6.0/pvr.hts/addon.xml.in --- kodi-pvr-hts-19.0.6/pvr.hts/addon.xml.in 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/pvr.hts/addon.xml.in 2022-10-07 16:22:25.000000000 +0000 @@ -1,7 +1,7 @@ @ADDON_DEPENDS@ diff -Nru kodi-pvr-hts-19.0.6/pvr.hts/changelog.txt kodi-pvr-hts-20.6.0/pvr.hts/changelog.txt --- kodi-pvr-hts-19.0.6/pvr.hts/changelog.txt 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/pvr.hts/changelog.txt 2022-10-07 16:22:25.000000000 +0000 @@ -1,30 +1,43 @@ -v19.0.6 -- Fix deleted recordings not disappearing in Kodi until restart (regression introduced with v19.0.5) +v20.6.0 +- Drop support for Tvheadend < 4.2.0 -v19.0.5 -- Translations updates from Weblate - - pl_pl +v20.5.0 +- Kodi inputstream API update to version 3.2.0 +- Kodi PVR API update to version 8.0.2 + +v20.4.0 +- Add support for multiple backends. +- Request addon-restart only on settings changes which require a reconnect to the backend. + +v20.3.0 +- Inputstream API bump. + +v20.2.2 +- Fix deleted recordings not disappearing in Kodi until restart (regression introduced with v20.2.1) + +v20.2.1 - Ignore recordings without a file (e.g. removed recordings). - When parsing recording add/update messages, always set the correct error string. - Reduce debug log spam. Do not log recording descriptions. -v19.0.4 -- Translations updates from Weblate - - es_mx +v20.2.0 +- Update translations +- Adapt to recent API changes -v19.0.3 +v20.1.2 - Fix Unable to change existing timer rule to use any time -- Translations updates from Weblate -v19.0.2 -- Translations updates from Weblate - -v19.0.1 +v20.1.1 - Fix AAC RDS parser -v19.0.0 +v20.1.0 +- Kodi API to 8.0.0 + - Add supports recordings delete capability + - Enforce EDL limits + +v20.0.0 - Translations updates from Weblate -- Version numbering scheme change. +- Version numbering scheme change v8.4.0 - Add support for RDS data contained in AAC streams. diff -Nru kodi-pvr-hts-19.0.6/pvr.hts/resources/instance-settings.xml kodi-pvr-hts-20.6.0/pvr.hts/resources/instance-settings.xml --- kodi-pvr-hts-19.0.6/pvr.hts/resources/instance-settings.xml 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-hts-20.6.0/pvr.hts/resources/instance-settings.xml 2022-10-07 16:22:25.000000000 +0000 @@ -0,0 +1,286 @@ + + +
+ + + + 0 + 127.0.0.1 + + + + 0 + false + + + + 0 + 9981 + + 1 + 1 + 65535 + + + + + 0 + 9982 + + 1 + 1 + 65535 + + + + + 0 + + + true + + + + + 0 + + + true + + + true + + + + + + + 0 + 10 + + 1 + 1 + 60 + + + + + 0 + 5 + + 1 + 1 + 60 + + + + + 0 + + + true + + + + + + + + + + + + 0 + + + true + + + + + 0 + false + + + + + + + 0 + false + + + + 0 + 2 + + 2 + 1 + 10 + + + true + + + + + 0 + 10 + + 5 + 5 + 60 + + + true + + + + + + + + 0 + 64 + + 4 + 4 + 512 + + + + + + + + + + + + 0 + 0 + + + + + + + + + + 0 + 15 + + 0 + 5 + 120 + + + 1 + + + + + 0 + false + + + + + + + 0 + true + + + + + + + 0 + 2 + + + + + + + + + + + + + 0 + 15 + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + true + + + + + + + 0 + true + + + + + +
+
diff -Nru kodi-pvr-hts-19.0.6/pvr.hts/resources/language/resource.language.en_gb/strings.po kodi-pvr-hts-20.6.0/pvr.hts/resources/language/resource.language.en_gb/strings.po --- kodi-pvr-hts-19.0.6/pvr.hts/resources/language/resource.language.en_gb/strings.po 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/pvr.hts/resources/language/resource.language.en_gb/strings.po 2022-10-07 16:22:25.000000000 +0000 @@ -294,17 +294,7 @@ msgid "Record if unique episode according EPG/XMLTV" msgstr "" -#. Recording lifetime representation -#: src/Tvheadend.cpp -msgctxt "#30373" -msgid "Until space needed" -msgstr "" - -#. Recording lifetime representation -#: src/Tvheadend.cpp -msgctxt "#30374" -msgid "Forever" -msgstr "" +#empty strings from id 30373 to 30374 #. Recording lifetime representation #: src/Tvheadend.cpp @@ -384,14 +374,14 @@ msgid "3 years" msgstr "" -#. Recording lifetime representation (for setting dialog only) +#. Recording lifetime representation msgctxt "#30388" -msgid "Until space needed (tvh 4.1+)" +msgid "Until space needed" msgstr "" -#. Recording lifetime representation (for setting dialog only) +#. Recording lifetime representation msgctxt "#30389" -msgid "Forever (tvh 4.1+)" +msgid "Forever" msgstr "" #. Recording lifetime representation diff -Nru kodi-pvr-hts-19.0.6/pvr.hts/resources/language/resource.language.pl_pl/strings.po kodi-pvr-hts-20.6.0/pvr.hts/resources/language/resource.language.pl_pl/strings.po --- kodi-pvr-hts-19.0.6/pvr.hts/resources/language/resource.language.pl_pl/strings.po 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/pvr.hts/resources/language/resource.language.pl_pl/strings.po 2022-10-07 16:22:25.000000000 +0000 @@ -5,17 +5,17 @@ msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: translations@kodi.tv\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: 2022-01-07 11:13+0000\n" -"Last-Translator: Marek Adamski \n" +"PO-Revision-Date: 2021-08-14 04:29+0000\n" +"Last-Translator: Jacek \n" "Language-Team: Polish \n" "Language: pl_pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 4.10.1\n" +"X-Generator: Weblate 4.7.2\n" msgctxt "Addon Summary" msgid "Kodi's frontend for Tvheadend" @@ -67,7 +67,7 @@ msgctxt "#30010" msgid "Timer settings" -msgstr "Ustawienia harmonogramu" +msgstr "Ustawienia zadania" msgctxt "#30011" msgid "Use HTTPS" diff -Nru kodi-pvr-hts-19.0.6/pvr.hts/resources/settings.xml kodi-pvr-hts-20.6.0/pvr.hts/resources/settings.xml --- kodi-pvr-hts-19.0.6/pvr.hts/resources/settings.xml 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/pvr.hts/resources/settings.xml 2022-10-07 16:22:25.000000000 +0000 @@ -1,291 +1,129 @@
- - - + + + + 0 + false + + + + + + + + + + 4 127.0.0.1 - - - 0 + + 4 false - - - 0 + + 4 9981 - - 1 - 1 - 65535 - - - - 0 + + 4 9982 - - 1 - 1 - 65535 - - - - 0 + + 4 true - - - 0 + + 4 true - - true - - - - - - 0 + + 4 10 - - 1 - 1 - 60 - - - - 0 + + 4 5 - - 1 - 1 - 60 - - - - 0 + + 4 true - - - - - - - - - - 0 + + 4 true - - - 0 + + 4 false - - - - - - 0 + + 4 false - - - 0 + + 4 2 - - 2 - 1 - 10 - - - true - - - - 0 + + 4 10 - - 5 - 5 - 60 - - - true - - - - - - - 0 + + 4 64 - - 4 - 4 - 512 - - - - - - - - - - - 0 - 0 - - - - - - - + + 4 + 0 - - 0 + + 4 15 - - 0 - 5 - 120 - - - 1 - - - - 0 + + 4 false - - - - - - 0 + + 4 true - - - - - - 0 + + 4 2 - - - - - - - - - - - - 0 - 15 - - - - - - - - - - - - - - - - - - - - - + + 4 + 15 - - 0 - 0 - - - - - - - - - - - - - - - - - - - - + + 4 + 0 - - - - - - - - - 0 + + 4 true - - - - - - 0 + + 4 true - - - - - - - 0 - false - diff -Nru kodi-pvr-hts-19.0.6/README.md kodi-pvr-hts-20.6.0/README.md --- kodi-pvr-hts-19.0.6/README.md 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/README.md 2022-10-07 16:22:25.000000000 +0000 @@ -3,15 +3,15 @@ This is a [Kodi](https://kodi.tv) PVR addon for connecting to a [tvheadend](https://tvheadend.org) backend. [![License: GPL-2.0-or-later](https://img.shields.io/badge/License-GPL%20v2+-blue.svg)](LICENSE.md) -[![Build and run tests](https://github.com/kodi-pvr/pvr.hts/actions/workflows/build.yml/badge.svg?branch=Matrix)](https://github.com/kodi-pvr/pvr.hts/actions/workflows/build.yml) -[![Build Status](https://dev.azure.com/teamkodi/kodi-pvr/_apis/build/status/kodi-pvr.pvr.hts?branchName=Matrix)](https://dev.azure.com/teamkodi/kodi-pvr/_build/latest?definitionId=62&branchName=Matrix) -[![Build Status](https://jenkins.kodi.tv/view/Addons/job/kodi-pvr/job/pvr.hts/job/Matrix/badge/icon)](https://jenkins.kodi.tv/blue/organizations/jenkins/kodi-pvr%2Fpvr.hts/branches/) +[![Build and run tests](https://github.com/kodi-pvr/pvr.hts/actions/workflows/build.yml/badge.svg?branch=Nexus)](https://github.com/kodi-pvr/pvr.hts/actions/workflows/build.yml) +[![Build Status](https://dev.azure.com/teamkodi/kodi-pvr/_apis/build/status/kodi-pvr.pvr.hts?branchName=Nexus)](https://dev.azure.com/teamkodi/kodi-pvr/_build/latest?definitionId=62&branchName=Nexus) +[![Build Status](https://jenkins.kodi.tv/view/Addons/job/kodi-pvr/job/pvr.hts/job/Nexus/badge/icon)](https://jenkins.kodi.tv/blue/organizations/jenkins/kodi-pvr%2Fpvr.hts/branches/) [![Coverity Scan Build Status](https://scan.coverity.com/projects/5120/badge.svg)](https://scan.coverity.com/projects/5120) ## Build instructions When building the addon you have to use the correct branch depending on which version of Kodi you're building against. -If you want to build the addon to be compatible with the latest kodi `Matrix` commit, you need to checkout the branch with the current kodi codename. +If you want to build the addon to be compatible with the latest kodi `master` commit, you need to checkout the branch with the current kodi codename. Also make sure you follow this README from the branch in question. ### Linux @@ -19,8 +19,8 @@ The following instructions assume you will have built Kodi already in the `kodi-build` directory suggested by the README. -1. `git clone --branch Matrix https://github.com/xbmc/xbmc.git` -2. `git clone --branch Matrix https://github.com/kodi-pvr/pvr.hts.git` +1. `git clone --branch master https://github.com/xbmc/xbmc.git` +2. `git clone https://github.com/kodi-pvr/pvr.hts.git` 3. `cd pvr.hts && mkdir build && cd build` 4. `cmake -DADDONS_TO_BUILD=pvr.hts -DADDON_SRC_PREFIX=../.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=../../xbmc/kodi-build/addons -DPACKAGE_ZIP=1 ../../xbmc/cmake/addons` 5. `make` diff -Nru kodi-pvr-hts-19.0.6/src/addon.cpp kodi-pvr-hts-20.6.0/src/addon.cpp --- kodi-pvr-hts-19.0.6/src/addon.cpp 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/addon.cpp 2022-10-07 16:22:25.000000000 +0000 @@ -8,75 +8,86 @@ #include "addon.h" #include "Tvheadend.h" -#include "tvheadend/Settings.h" +#include "tvheadend/AddonSettings.h" #include "tvheadend/utilities/Logger.h" +#include "tvheadend/utilities/SettingsMigration.h" using namespace tvheadend; using namespace tvheadend::utilities; ADDON_STATUS CHTSAddon::Create() { - /* Configure the logger */ - Logger::GetInstance().SetImplementation([](LogLevel level, const char* message) { - /* Convert the log level */ - AddonLog addonLevel; - - switch (level) - { - case LogLevel::LEVEL_FATAL: - addonLevel = AddonLog::ADDON_LOG_FATAL; - break; - case LogLevel::LEVEL_ERROR: - addonLevel = AddonLog::ADDON_LOG_ERROR; - break; - case LogLevel::LEVEL_WARNING: - addonLevel = AddonLog::ADDON_LOG_WARNING; - break; - case LogLevel::LEVEL_INFO: - addonLevel = AddonLog::ADDON_LOG_INFO; - break; - default: - addonLevel = AddonLog::ADDON_LOG_DEBUG; - break; - } + /* Init settings */ + m_settings.reset(new AddonSettings()); - /* Don't log trace messages unless told so */ - if (level == LogLevel::LEVEL_TRACE && !Settings::GetInstance().GetTraceDebug()) - return; + /* Configure the logger */ + Logger::GetInstance().SetImplementation( + [this](LogLevel level, const char* message) + { + /* Don't log trace messages unless told so */ + if (level == LogLevel::LEVEL_TRACE && !m_settings->GetTraceDebug()) + return; + + /* Convert the log level */ + ADDON_LOG addonLevel; + + switch (level) + { + case LogLevel::LEVEL_FATAL: + addonLevel = ADDON_LOG::ADDON_LOG_FATAL; + break; + case LogLevel::LEVEL_ERROR: + addonLevel = ADDON_LOG::ADDON_LOG_ERROR; + break; + case LogLevel::LEVEL_WARNING: + addonLevel = ADDON_LOG::ADDON_LOG_WARNING; + break; + case LogLevel::LEVEL_INFO: + addonLevel = ADDON_LOG::ADDON_LOG_INFO; + break; + default: + addonLevel = ADDON_LOG::ADDON_LOG_DEBUG; + break; + } - kodi::Log(addonLevel, "%s", message); - }); + kodi::Log(addonLevel, "%s", message); + }); Logger::Log(LogLevel::LEVEL_INFO, "starting PVR client"); - Settings::GetInstance().ReadSettings(); - return ADDON_STATUS_OK; } ADDON_STATUS CHTSAddon::SetSetting(const std::string& settingName, - const kodi::CSettingValue& settingValue) + const kodi::addon::CSettingValue& settingValue) { std::lock_guard lock(m_mutex); - return Settings::GetInstance().SetSetting(settingName, settingValue); + + return m_settings->SetSetting(settingName, settingValue); } -ADDON_STATUS CHTSAddon::CreateInstance(int instanceType, - const std::string& instanceID, - KODI_HANDLE instance, - const std::string& version, - KODI_HANDLE& addonInstance) +ADDON_STATUS CHTSAddon::CreateInstance(const kodi::addon::IInstanceInfo& instance, + KODI_ADDON_INSTANCE_HDL& hdl) { std::lock_guard lock(m_mutex); - if (instanceType == ADDON_INSTANCE_PVR) + if (instance.IsType(ADDON_INSTANCE_PVR)) { Logger::Log(LogLevel::LEVEL_DEBUG, "%s: Creating PVR-Client instance", __FUNCTION__); - /* Connect to ARGUS TV */ - CTvheadend* client = new CTvheadend(instance, version); + /* Connect to TVHeadend backend */ + CTvheadend* client = new CTvheadend(instance); + + // Try to migrate settings from a pre-multi-instance setup + if (SettingsMigration::MigrateSettings(*client)) + { + // Initial client operated on old/incomplete settings + delete client; + client = new CTvheadend(instance); + } + client->Start(); - addonInstance = client; + hdl = client; return ADDON_STATUS_OK; } diff -Nru kodi-pvr-hts-19.0.6/src/addon.h kodi-pvr-hts-20.6.0/src/addon.h --- kodi-pvr-hts-19.0.6/src/addon.h 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/addon.h 2022-10-07 16:22:25.000000000 +0000 @@ -9,22 +9,26 @@ #include "kodi/AddonBase.h" +#include #include -class ATTRIBUTE_HIDDEN CHTSAddon : public kodi::addon::CAddonBase +namespace tvheadend +{ +class AddonSettings; +} + +class ATTR_DLL_LOCAL CHTSAddon : public kodi::addon::CAddonBase { public: CHTSAddon() = default; ADDON_STATUS Create() override; ADDON_STATUS SetSetting(const std::string& settingName, - const kodi::CSettingValue& settingValue) override; - ADDON_STATUS CreateInstance(int instanceType, - const std::string& instanceID, - KODI_HANDLE instance, - const std::string& version, - KODI_HANDLE& addonInstance) override; + const kodi::addon::CSettingValue& settingValue) override; + ADDON_STATUS CreateInstance(const kodi::addon::IInstanceInfo& instance, + KODI_ADDON_INSTANCE_HDL& hdl) override; private: std::recursive_mutex m_mutex; + std::shared_ptr m_settings; }; diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/AddonSettings.cpp kodi-pvr-hts-20.6.0/src/tvheadend/AddonSettings.cpp --- kodi-pvr-hts-19.0.6/src/tvheadend/AddonSettings.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/AddonSettings.cpp 2022-10-07 16:22:25.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2005-2022 Team Kodi (https://kodi.tv) + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSE.md for more information. + */ + +#include "AddonSettings.h" + +#include "utilities/Logger.h" +#include "utilities/SettingsMigration.h" + +#include "kodi/General.h" + +using namespace tvheadend; +using namespace tvheadend::utilities; + +namespace +{ +constexpr bool DEFAULT_TRACE_DEBUG = false; + +bool ReadBoolSetting(const std::string& key, bool def) +{ + bool value; + if (kodi::addon::CheckSettingBoolean(key, value)) + return value; + + return def; +} + +} // unnamed namespace + +AddonSettings::AddonSettings() : m_bTraceDebug(DEFAULT_TRACE_DEBUG) +{ + ReadSettings(); +} + +void AddonSettings::ReadSettings() +{ + SetTraceDebug(ReadBoolSetting("trace_debug", DEFAULT_TRACE_DEBUG)); +} + +ADDON_STATUS AddonSettings::SetSetting(const std::string& key, + const kodi::addon::CSettingValue& value) +{ + if (key == "trace_debug") + { + SetTraceDebug(value.GetBoolean()); + return ADDON_STATUS_OK; + } + else if (SettingsMigration::IsMigrationSetting(key)) + { + // ignore settings from pre-multi-instance setup + return ADDON_STATUS_OK; + } + + Logger::Log(LogLevel::LEVEL_ERROR, "AddonSettings::SetSetting - unknown setting '%s'", + key.c_str()); + return ADDON_STATUS_UNKNOWN; +} diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/AddonSettings.h kodi-pvr-hts-20.6.0/src/tvheadend/AddonSettings.h --- kodi-pvr-hts-19.0.6/src/tvheadend/AddonSettings.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/AddonSettings.h 2022-10-07 16:22:25.000000000 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2005-2022 Team Kodi (https://kodi.tv) + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSE.md for more information. + */ + +#pragma once + +#include "kodi/AddonBase.h" + +#include + +namespace tvheadend +{ +/** + * Represents the current addon settings + */ +class AddonSettings +{ +public: + AddonSettings(); + + /** + * Set a value according to key definition in settings.xml + */ + ADDON_STATUS SetSetting(const std::string& key, const kodi::addon::CSettingValue& value); + + /** + * Getters for the settings values + */ + bool GetTraceDebug() const { return m_bTraceDebug; } + +private: + AddonSettings(const AddonSettings&) = delete; + void operator=(const AddonSettings&) = delete; + + /** + * Read all settings defined in settings.xml + */ + void ReadSettings(); + + /** + * Setters + */ + void SetTraceDebug(bool value) { m_bTraceDebug = value; } + + bool m_bTraceDebug{false}; +}; + +} // namespace tvheadend diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/AutoRecordings.cpp kodi-pvr-hts-20.6.0/src/tvheadend/AutoRecordings.cpp --- kodi-pvr-hts-19.0.6/src/tvheadend/AutoRecordings.cpp 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/AutoRecordings.cpp 2022-10-07 16:22:25.000000000 +0000 @@ -8,7 +8,7 @@ #include "AutoRecordings.h" #include "HTSPConnection.h" -#include "Settings.h" +#include "InstanceSettings.h" #include "entity/Recording.h" #include "utilities/LifetimeMapper.h" #include "utilities/Logger.h" @@ -22,7 +22,9 @@ using namespace tvheadend::entity; using namespace tvheadend::utilities; -AutoRecordings::AutoRecordings(HTSPConnection& conn) : m_conn(conn) +AutoRecordings::AutoRecordings(const std::shared_ptr& settings, + HTSPConnection& conn) + : m_settings(settings), m_conn(conn) { } @@ -90,12 +92,7 @@ tmr.SetLifetime(rec.second.GetLifetime()); tmr.SetMaxRecordings(0); // not supported by tvh tmr.SetRecordingGroup(0); // not supported by tvh - - if (m_conn.GetProtocol() >= 20) - tmr.SetPreventDuplicateEpisodes(rec.second.GetDupDetect()); - else - tmr.SetPreventDuplicateEpisodes(0); // not supported by tvh - + tmr.SetPreventDuplicateEpisodes(rec.second.GetDupDetect()); tmr.SetFirstDay(0); // not supported by tvh tmr.SetWeekdays(rec.second.GetDaysOfWeek()); tmr.SetEPGUid(PVR_TIMER_NO_EPG_UID); // n/a for repeating timers @@ -141,16 +138,7 @@ PVR_ERROR AutoRecordings::SendAutorecUpdate(const kodi::addon::PVRTimer& timer) { - if (m_conn.GetProtocol() >= 25) - return SendAutorecAddOrUpdate(timer, true); - - /* Note: there is no "updateAutorec" htsp method for htsp version < 25, thus delete + add. */ - PVR_ERROR error = SendAutorecDelete(timer); - - if (error == PVR_ERROR_NO_ERROR) - error = SendAutorecAdd(timer); - - return error; + return SendAutorecAddOrUpdate(timer, true); } PVR_ERROR AutoRecordings::SendAutorecAddOrUpdate(const kodi::addon::PVRTimer& timer, bool update) @@ -176,7 +164,7 @@ /* epg search data match string */ std::string searchString = timer.GetEPGSearchString(); - if (!Settings::GetInstance().GetAutorecUseRegEx()) + if (!m_settings->GetAutorecUseRegEx()) { // escape regex special chars static const std::regex specialChars(R"([-[\]{}()*+?.,\^$|#])"); @@ -188,34 +176,14 @@ /* "title" not empty && !fulltext => match strEpgSearchString against episode title only */ /* "title" not empty && fulltext => match strEpgSearchString against episode title, episode */ /* subtitle, episode summary and episode description (HTSPv19) */ - if (m_conn.GetProtocol() >= 20) - htsmsg_add_u32(m, "fulltext", timer.GetFullTextEpgSearch() ? 1 : 0); + htsmsg_add_u32(m, "fulltext", timer.GetFullTextEpgSearch() ? 1 : 0); htsmsg_add_s64(m, "startExtra", timer.GetMarginStart()); htsmsg_add_s64(m, "stopExtra", timer.GetMarginEnd()); - - if (m_conn.GetProtocol() >= 25) - { - htsmsg_add_u32(m, "removal", timer.GetLifetime()); // remove from disk - htsmsg_add_s64(m, "channelId", - timer.GetClientChannelUid()); // channelId is signed for >= htspv25, -1 = any - } - else - { - htsmsg_add_u32(m, "retention", - LifetimeMapper::KodiToTvh(timer.GetLifetime())); // remove from tvh database - - if (timer.GetClientChannelUid() >= 0) - htsmsg_add_u32( - m, "channelId", - timer.GetClientChannelUid()); // channelId is unsigned for < htspv25, not sending = any - } - + htsmsg_add_u32(m, "removal", timer.GetLifetime()); // remove from disk + htsmsg_add_s64(m, "channelId", timer.GetClientChannelUid()); // -1 = any htsmsg_add_u32(m, "daysOfWeek", timer.GetWeekdays()); - - if (m_conn.GetProtocol() >= 20) - htsmsg_add_u32(m, "dupDetect", timer.GetPreventDuplicateEpisodes()); - + htsmsg_add_u32(m, "dupDetect", timer.GetPreventDuplicateEpisodes()); htsmsg_add_u32(m, "priority", timer.GetPriority()); htsmsg_add_u32(m, "enabled", timer.GetState() == PVR_TIMER_STATE_DISABLED ? 0 : 1); @@ -231,9 +199,7 @@ /* */ /* bAutorecApproxTime disabled: => start time in kodi = begin of starting window in tvh */ /* => end time in kodi = end of starting window in tvh */ - const Settings& settings = Settings::GetInstance(); - - if (settings.GetAutorecApproxTime()) + if (m_settings->GetAutorecApproxTime()) { /* Not sending causes server to set start and startWindow to any time */ if (timer.GetStartTime() > 0 && !timer.GetStartAnyTime()) @@ -241,9 +207,9 @@ time_t startTime = timer.GetStartTime(); struct tm* tm_start = std::localtime(&startTime); int32_t startWindowBegin = - tm_start->tm_hour * 60 + tm_start->tm_min - settings.GetAutorecMaxDiff(); + tm_start->tm_hour * 60 + tm_start->tm_min - m_settings->GetAutorecMaxDiff(); int32_t startWindowEnd = - tm_start->tm_hour * 60 + tm_start->tm_min + settings.GetAutorecMaxDiff(); + tm_start->tm_hour * 60 + tm_start->tm_min + m_settings->GetAutorecMaxDiff(); /* Past midnight correction */ if (startWindowBegin < 0) @@ -354,6 +320,7 @@ /* Locate/create entry */ AutoRecording& rec = m_autoRecordings[std::string(str)]; + rec.SetSettings(m_settings); rec.SetStringId(std::string(str)); rec.SetDirty(false); @@ -370,29 +337,14 @@ return false; } - if (m_conn.GetProtocol() >= 25) + if (!htsmsg_get_u32(msg, "removal", &u32)) { - if (!htsmsg_get_u32(msg, "removal", &u32)) - { - rec.SetLifetime(u32); - } - else if (bAdd) - { - Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'removal' missing"); - return false; - } + rec.SetLifetime(u32); } - else + else if (bAdd) { - if (!htsmsg_get_u32(msg, "retention", &u32)) - { - rec.SetLifetime(u32); - } - else if (bAdd) - { - Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'retention' missing"); - return false; - } + Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'removal' missing"); + return false; } if (!htsmsg_get_u32(msg, "daysOfWeek", &u32)) @@ -461,7 +413,7 @@ { rec.SetDupDetect(u32); } - else if (bAdd && (m_conn.GetProtocol() >= 20)) + else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'dupDetect' missing"); return false; diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/AutoRecordings.h kodi-pvr-hts-20.6.0/src/tvheadend/AutoRecordings.h --- kodi-pvr-hts-19.0.6/src/tvheadend/AutoRecordings.h 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/AutoRecordings.h 2022-10-07 16:22:25.000000000 +0000 @@ -7,6 +7,7 @@ #pragma once +#include #include extern "C" @@ -24,11 +25,12 @@ { class HTSPConnection; +class InstanceSettings; class AutoRecordings { public: - AutoRecordings(HTSPConnection& conn); + AutoRecordings(const std::shared_ptr& settings, HTSPConnection& conn); ~AutoRecordings(); /* state updates */ @@ -55,6 +57,7 @@ HTSPConnection& m_conn; tvheadend::entity::AutoRecordingsMap m_autoRecordings; + std::shared_ptr m_settings; }; } // namespace tvheadend diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/entity/AutoRecording.cpp kodi-pvr-hts-20.6.0/src/tvheadend/entity/AutoRecording.cpp --- kodi-pvr-hts-19.0.6/src/tvheadend/entity/AutoRecording.cpp 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/entity/AutoRecording.cpp 2022-10-07 16:22:25.000000000 +0000 @@ -7,7 +7,7 @@ #include "AutoRecording.h" -#include "../Settings.h" +#include "../InstanceSettings.h" using namespace tvheadend; using namespace tvheadend::entity; @@ -38,7 +38,7 @@ time_t AutoRecording::GetStart() const { - if (Settings::GetInstance().GetAutorecApproxTime()) + if (m_settings->GetAutorecApproxTime()) { /* Calculate the approximate start time from the starting window */ if ((m_startWindowBegin == -1) || @@ -76,7 +76,7 @@ time_t AutoRecording::GetStop() const { - if (Settings::GetInstance().GetAutorecApproxTime()) + if (m_settings->GetAutorecApproxTime()) { /* Tvh doesn't have an approximate stop time => "any time" */ return 0; diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/entity/AutoRecording.h kodi-pvr-hts-20.6.0/src/tvheadend/entity/AutoRecording.h --- kodi-pvr-hts-19.0.6/src/tvheadend/entity/AutoRecording.h 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/entity/AutoRecording.h 2022-10-07 16:22:25.000000000 +0000 @@ -10,9 +10,12 @@ #include "RecordingBase.h" #include +#include namespace tvheadend { +class InstanceSettings; + namespace entity { @@ -24,6 +27,8 @@ bool operator==(const AutoRecording& right); bool operator!=(const AutoRecording& right); + void SetSettings(const std::shared_ptr& settings) { m_settings = settings; } + time_t GetStart() const; void SetStartWindowBegin(int32_t begin); @@ -46,6 +51,8 @@ void SetSeriesLink(const std::string& seriesLink); private: + std::shared_ptr m_settings; + int32_t m_startWindowBegin; // Begin of the starting window (minutes from midnight). int32_t m_startWindowEnd; // End of the starting window (minutes from midnight). int64_t m_startExtra; // Extra start minutes (pre-time). diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/HTSPConnection.cpp kodi-pvr-hts-20.6.0/src/tvheadend/HTSPConnection.cpp --- kodi-pvr-hts-19.0.6/src/tvheadend/HTSPConnection.cpp 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/HTSPConnection.cpp 2022-10-07 16:22:25.000000000 +0000 @@ -14,7 +14,7 @@ } #include "IHTSPConnectionListener.h" -#include "Settings.h" +#include "InstanceSettings.h" #include "utilities/Logger.h" #include "utilities/TCPSocket.h" @@ -32,9 +32,9 @@ #define FAST_RECONNECT_INTERVAL (500) // ms #define SLOW_RECONNECT_INTERVAL (5000) // ms -#define HTSP_MIN_SERVER_VERSION (19) // Server must support at least this htsp version +#define HTSP_MIN_SERVER_VERSION (26) // Server must support at least this htsp version #define HTSP_CLIENT_VERSION \ - (34) // Client uses HTSP features up to this version. If the respective \ + (35) // Client uses HTSP features up to this version. If the respective \ // addon feature requires htsp features introduced after \ // HTSP_MIN_SERVER_VERSION this feature will only be available if the \ // actual server HTSP version matches (runtime htsp version check). @@ -86,8 +86,10 @@ * HTSP Connection handler */ -HTSPConnection::HTSPConnection(IHTSPConnectionListener& connListener) - : m_connListener(connListener), +HTSPConnection::HTSPConnection(const std::shared_ptr& settings, + IHTSPConnectionListener& connListener) + : m_settings(settings), + m_connListener(connListener), m_regThread(new HTSPRegister(this)), m_ready(false), m_seq(0), @@ -155,20 +157,18 @@ std::string HTSPConnection::GetWebURL(const char* fmt, ...) const { - const Settings& settings = Settings::GetInstance(); - // Generate the authentication string (user:pass@) - std::string auth = settings.GetUsername(); - if (!(auth.empty() || settings.GetPassword().empty())) - auth += ":" + settings.GetPassword(); + std::string auth = m_settings->GetUsername(); + if (!(auth.empty() || m_settings->GetPassword().empty())) + auth += ":" + m_settings->GetPassword(); if (!auth.empty()) auth += "@"; - const char* proto = settings.GetUseHTTPS() ? "https" : "http"; - bool isIPv6 = IsIPv6NumericHost(settings.GetHostname()); + const char* proto = m_settings->GetUseHTTPS() ? "https" : "http"; + bool isIPv6 = IsIPv6NumericHost(m_settings->GetHostname()); std::string url = kodi::tools::StringUtils::Format( - "%s://%s%s%s%s:%d", proto, auth.c_str(), isIPv6 ? "[" : "", settings.GetHostname().c_str(), - isIPv6 ? "]" : "", settings.GetPortHTTP()); + "%s://%s%s%s%s:%d", proto, auth.c_str(), isIPv6 ? "[" : "", m_settings->GetHostname().c_str(), + isIPv6 ? "]" : "", m_settings->GetPortHTTP()); va_list va; @@ -186,7 +186,7 @@ if (!m_ready) { Logger::Log(LogLevel::LEVEL_TRACE, "waiting for registration..."); - m_regCond.wait_for(lock, std::chrono::milliseconds(Settings::GetInstance().GetConnectTimeout()), + m_regCond.wait_for(lock, std::chrono::milliseconds(m_settings->GetConnectTimeout()), [this] { return m_ready == true; }); } return m_ready; @@ -212,11 +212,9 @@ std::string HTSPConnection::GetServerString() const { - const Settings& settings = Settings::GetInstance(); - std::lock_guard lock(m_mutex); - return kodi::tools::StringUtils::Format("%s:%d", settings.GetHostname().c_str(), - settings.GetPortHTSP()); + return kodi::tools::StringUtils::Format("%s:%d", m_settings->GetHostname().c_str(), + m_settings->GetPortHTSP()); } bool HTSPConnection::HasCapability(const std::string& capability) const @@ -313,7 +311,7 @@ size_t cnt = 0; while (cnt < len) { - int64_t r = m_socket->Read(buf + cnt, len - cnt, Settings::GetInstance().GetResponseTimeout()); + int64_t r = m_socket->Read(buf + cnt, len - cnt, m_settings->GetResponseTimeout()); if (r < 0) { Logger::Log(LogLevel::LEVEL_ERROR, "failed to read packet from socket"); @@ -414,7 +412,7 @@ int iResponseTimeout) { if (iResponseTimeout == -1) - iResponseTimeout = Settings::GetInstance().GetResponseTimeout(); + iResponseTimeout = m_settings->GetResponseTimeout(); /* Add Sequence number */ uint32_t seq = ++m_seq; @@ -475,7 +473,7 @@ int iResponseTimeout) { if (iResponseTimeout == -1) - iResponseTimeout = Settings::GetInstance().GetResponseTimeout(); + iResponseTimeout = m_settings->GetResponseTimeout(); if (!WaitForConnection(lock)) return nullptr; @@ -591,8 +589,8 @@ */ void HTSPConnection::Register() { - std::string user = Settings::GetInstance().GetUsername(); - std::string pass = Settings::GetInstance().GetPassword(); + std::string user = m_settings->GetUsername(); + std::string pass = m_settings->GetPassword(); { std::unique_lock lock(m_mutex); @@ -654,15 +652,14 @@ { static bool log = false; static unsigned int retryAttempt = 0; - const Settings& settings = Settings::GetInstance(); while (!ShouldStopProcessing()) { Logger::Log(LogLevel::LEVEL_DEBUG, "new connection requested"); - std::string host = settings.GetHostname(); - int port = settings.GetPortHTSP(); - int timeout = settings.GetConnectTimeout(); + std::string host = m_settings->GetHostname(); + int port = m_settings->GetPortHTSP(); + int timeout = m_settings->GetConnectTimeout(); /* Create socket (ensure mutex protection) */ { @@ -701,7 +698,7 @@ } /* wakeup server */ - std::string wol_mac = settings.GetWolMac(); + std::string wol_mac = m_settings->GetWolMac(); if (!wol_mac.empty()) { Logger::Log(LogLevel::LEVEL_TRACE, "send wol packet..."); diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/HTSPConnection.h kodi-pvr-hts-20.6.0/src/tvheadend/HTSPConnection.h --- kodi-pvr-hts-19.0.6/src/tvheadend/HTSPConnection.h 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/HTSPConnection.h 2022-10-07 16:22:25.000000000 +0000 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ class HTSPRegister; class HTSPResponse; class IHTSPConnectionListener; +class InstanceSettings; namespace utilities { @@ -42,7 +44,8 @@ class HTSPConnection : public kodi::tools::CThread { public: - HTSPConnection(IHTSPConnectionListener& connListener); + HTSPConnection(const std::shared_ptr& settings, + IHTSPConnectionListener& connListener); ~HTSPConnection() override; void Start(); @@ -107,6 +110,7 @@ HTSPConnection* m_conn; }; + std::shared_ptr m_settings; IHTSPConnectionListener& m_connListener; tvheadend::utilities::TCPSocket* m_socket = nullptr; mutable std::recursive_mutex m_mutex; diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/HTSPDemuxer.cpp kodi-pvr-hts-20.6.0/src/tvheadend/HTSPDemuxer.cpp --- kodi-pvr-hts-19.0.6/src/tvheadend/HTSPDemuxer.cpp 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/HTSPDemuxer.cpp 2022-10-07 16:22:25.000000000 +0000 @@ -9,7 +9,7 @@ #include "HTSPDemuxer.h" #include "HTSPConnection.h" -#include "Settings.h" +#include "InstanceSettings.h" #include "utilities/Logger.h" #include "utilities/RDSExtractor.h" @@ -34,8 +34,11 @@ using namespace tvheadend; using namespace tvheadend::utilities; -HTSPDemuxer::HTSPDemuxer(IHTSPDemuxPacketHandler& demuxPktHdl, HTSPConnection& conn) - : m_conn(conn), +HTSPDemuxer::HTSPDemuxer(const std::shared_ptr& settings, + IHTSPDemuxPacketHandler& demuxPktHdl, + HTSPConnection& conn) + : m_settings(settings), + m_conn(conn), m_pktBuffer(static_cast(-1)), m_seektime(nullptr), m_subscription(conn), @@ -233,7 +236,7 @@ return false; /* Wait for time */ - int64_t seekedTo = (*m_seektime).Get(lock, Settings::GetInstance().GetResponseTimeout()); + int64_t seekedTo = (*m_seektime).Get(lock, m_settings->GetResponseTimeout()); m_seektime = nullptr; if (seekedTo == INVALID_SEEKTIME) diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/HTSPDemuxer.h kodi-pvr-hts-20.6.0/src/tvheadend/HTSPDemuxer.h --- kodi-pvr-hts-19.0.6/src/tvheadend/HTSPDemuxer.h 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/HTSPDemuxer.h 2022-10-07 16:22:25.000000000 +0000 @@ -35,6 +35,7 @@ { class HTSPConnection; +class InstanceSettings; class SubscriptionSeekTime; namespace utilities @@ -48,7 +49,9 @@ class HTSPDemuxer { public: - HTSPDemuxer(IHTSPDemuxPacketHandler& demuxPktHdl, HTSPConnection& conn); + HTSPDemuxer(const std::shared_ptr& settings, + IHTSPDemuxPacketHandler& demuxPktHdl, + HTSPConnection& conn); ~HTSPDemuxer(); bool ProcessMessage(const std::string& method, htsmsg_t* m); @@ -112,6 +115,7 @@ void ProcessRDS(uint32_t idx, const void* bin, size_t binlen); mutable std::recursive_mutex m_mutex; + std::shared_ptr m_settings; HTSPConnection& m_conn; tvheadend::utilities::SyncedBuffer m_pktBuffer; std::vector m_streams; diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/HTSPVFS.cpp kodi-pvr-hts-20.6.0/src/tvheadend/HTSPVFS.cpp --- kodi-pvr-hts-19.0.6/src/tvheadend/HTSPVFS.cpp 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/HTSPVFS.cpp 2022-10-07 16:22:25.000000000 +0000 @@ -12,7 +12,8 @@ #include "libhts/htsmsg_binary.h" } #include "HTSPConnection.h" -#include "Settings.h" +#include "HTSPTypes.h" +#include "InstanceSettings.h" #include "utilities/Logger.h" #include "kodi/addon-instance/pvr/Recordings.h" @@ -29,8 +30,9 @@ /* * VFS handler */ -HTSPVFS::HTSPVFS(HTSPConnection& conn) - : m_conn(conn), +HTSPVFS::HTSPVFS(const std::shared_ptr& settings, HTSPConnection& conn) + : m_settings(settings), + m_conn(conn), m_path(""), m_fileId(0), m_offset(0), @@ -264,8 +266,8 @@ /* If setting set, we will increase play count with CTvheadend::SetPlayCount */ if (m_conn.GetProtocol() >= 27) htsmsg_add_u32(m, "playcount", - Settings::GetInstance().GetDvrPlayStatus() ? HTSP_DVR_PLAYCOUNT_KEEP - : HTSP_DVR_PLAYCOUNT_INCR); + m_settings->GetDvrPlayStatus() ? HTSP_DVR_PLAYCOUNT_KEEP + : HTSP_DVR_PLAYCOUNT_INCR); Logger::Log(LogLevel::LEVEL_DEBUG, "vfs close id=%d", m_fileId); diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/HTSPVFS.h kodi-pvr-hts-20.6.0/src/tvheadend/HTSPVFS.h --- kodi-pvr-hts-19.0.6/src/tvheadend/HTSPVFS.h 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/HTSPVFS.h 2022-10-07 16:22:25.000000000 +0000 @@ -7,6 +7,7 @@ #pragma once +#include #include namespace kodi @@ -21,6 +22,7 @@ { class HTSPConnection; +class InstanceSettings; /* * HTSP VFS - recordings @@ -28,7 +30,7 @@ class HTSPVFS { public: - HTSPVFS(HTSPConnection& conn); + HTSPVFS(const std::shared_ptr& settings, HTSPConnection& conn); ~HTSPVFS(); void RebuildState(); @@ -47,6 +49,7 @@ int64_t SendFileRead(unsigned char* buf, unsigned int len); long long SendFileSeek(int64_t pos, int whence, bool force = false); + std::shared_ptr m_settings; HTSPConnection& m_conn; std::string m_path; uint32_t m_fileId; diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/InstanceSettings.cpp kodi-pvr-hts-20.6.0/src/tvheadend/InstanceSettings.cpp --- kodi-pvr-hts-19.0.6/src/tvheadend/InstanceSettings.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/InstanceSettings.cpp 2022-10-07 16:22:25.000000000 +0000 @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2005-2021 Team Kodi (https://kodi.tv) + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSE.md for more information. + */ + +#include "InstanceSettings.h" + +#include "HTSPTypes.h" +#include "utilities/Logger.h" + +#include "kodi/General.h" + +using namespace tvheadend; +using namespace tvheadend::utilities; + +namespace +{ +const std::string DEFAULT_HOST = "127.0.0.1"; +const bool DEFAULT_USE_HTTPS = false; +const int DEFAULT_HTTP_PORT = 9981; +const int DEFAULT_HTSP_PORT = 9982; +const std::string DEFAULT_USERNAME = ""; +const std::string DEFAULT_PASSWORD = ""; +const std::string DEFAULT_WOL_MAC = ""; +const int DEFAULT_CONNECT_TIMEOUT = 10000; // millisecs +const int DEFAULT_RESPONSE_TIMEOUT = 5000; // millisecs +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; +const int DEFAULT_DVR_LIFETIME = 15; // use backend setting +const int DEFAULT_DVR_DUPDETECT = DVR_AUTOREC_RECORD_ALL; +const bool DEFAULT_DVR_PLAYSTATUS = true; +const int DEFAULT_STREAM_CHUNKSIZE = 64; // KB +const bool DEFAULT_DVR_IGNORE_DUPLICATE_SCHEDULES = true; +} // namespace + +InstanceSettings::InstanceSettings(kodi::addon::IAddonInstance& instance) + : m_instance(instance), + m_strHostname(DEFAULT_HOST), + m_iPortHTSP(DEFAULT_HTTP_PORT), + m_iPortHTTP(DEFAULT_HTSP_PORT), + m_bUseHTTPS(DEFAULT_USE_HTTPS), + m_strUsername(DEFAULT_USERNAME), + m_strPassword(DEFAULT_PASSWORD), + m_strWolMac(DEFAULT_WOL_MAC), + m_iConnectTimeout(DEFAULT_CONNECT_TIMEOUT), + m_iResponseTimeout(DEFAULT_RESPONSE_TIMEOUT), + m_bAsyncEpg(DEFAULT_ASYNC_EPG), + 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), + m_iDvrPriority(DEFAULT_DVR_PRIO), + m_iDvrLifetime(DEFAULT_DVR_LIFETIME), + m_iDvrDupdetect(DEFAULT_DVR_DUPDETECT), + m_bDvrPlayStatus(DEFAULT_DVR_PLAYSTATUS), + m_iStreamReadChunkSizeKB(DEFAULT_STREAM_CHUNKSIZE), + m_bIgnoreDuplicateSchedules(DEFAULT_DVR_IGNORE_DUPLICATE_SCHEDULES) +{ + ReadSettings(); +} + +void InstanceSettings::ReadSettings() +{ + /* Connection */ + SetHostname(ReadStringSetting("host", DEFAULT_HOST)); + SetPortHTSP(ReadIntSetting("htsp_port", DEFAULT_HTSP_PORT)); + SetPortHTTP(ReadIntSetting("http_port", DEFAULT_HTTP_PORT)); + SetUseHTTPS(ReadBoolSetting("https", DEFAULT_USE_HTTPS)); + SetUsername(ReadStringSetting("user", DEFAULT_USERNAME)); + SetPassword(ReadStringSetting("pass", DEFAULT_PASSWORD)); + SetWolMac(ReadStringSetting("wol_mac", DEFAULT_WOL_MAC)); + + /* Note: Timeouts in settings UI are defined in seconds but we expect them to be in milliseconds. */ + SetConnectTimeout(ReadIntSetting("connect_timeout", DEFAULT_CONNECT_TIMEOUT / 1000) * 1000); + SetResponseTimeout(ReadIntSetting("response_timeout", DEFAULT_RESPONSE_TIMEOUT / 1000) * 1000); + + /* Data Transfer */ + SetAsyncEpg(ReadBoolSetting("epg_async", DEFAULT_ASYNC_EPG)); + + /* Predictive Tuning */ + m_bPretunerEnabled = ReadBoolSetting("pretuner_enabled", DEFAULT_PRETUNER_ENABLED); + SetTotalTuners(m_bPretunerEnabled ? ReadIntSetting("total_tuners", DEFAULT_TOTAL_TUNERS) : 1); + SetPreTunerCloseDelay( + 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 */ + SetStreamingProfile(ReadStringSetting("streaming_profile", DEFAULT_STREAMING_PROFILE)); + SetStreamingHTTP(ReadBoolSetting("streaming_http", DEFAULT_STREAMING_HTTP)); + + /* Default dvr settings */ + SetDvrPriority(ReadIntSetting("dvr_priority", DEFAULT_DVR_PRIO)); + SetDvrLifetime(ReadIntSetting("dvr_lifetime2", DEFAULT_DVR_LIFETIME)); + SetDvrDupdetect(ReadIntSetting("dvr_dubdetect", DEFAULT_DVR_DUPDETECT)); + + /* Sever based play status */ + SetDvrPlayStatus(ReadBoolSetting("dvr_playstatus", DEFAULT_DVR_PLAYSTATUS)); + + /* Stream read chunk size */ + SetStreamReadChunkSizeKB(ReadIntSetting("stream_readchunksize", DEFAULT_STREAM_CHUNKSIZE)); + + /* Scheduled recordings */ + SetIgnoreDuplicateSchedules( + ReadBoolSetting("dvr_ignore_duplicates", DEFAULT_DVR_IGNORE_DUPLICATE_SCHEDULES)); +} + +ADDON_STATUS InstanceSettings::SetSetting(const std::string& key, + const kodi::addon::CSettingValue& value) +{ + /* Connection */ + if (key == "host") + return SetStringSetting(GetHostname(), value); + else if (key == "htsp_port") + return SetIntSetting(GetPortHTSP(), value); + else if (key == "http_port") + return SetIntSetting(GetPortHTTP(), value); + else if (key == "https") + return SetBoolSetting(GetUseHTTPS(), value); + else if (key == "user") + return SetStringSetting(GetUsername(), value); + else if (key == "pass") + return SetStringSetting(GetPassword(), value); + else if (key == "wol_mac") + return SetStringSetting(GetWolMac(), value); + else if (key == "connect_timeout") + { + SetConnectTimeout(value.GetInt() * 1000); + return ADDON_STATUS_OK; + } + else if (key == "response_timeout") + { + SetResponseTimeout(value.GetInt() * 1000); + return ADDON_STATUS_OK; + } + /* Data Transfer */ + else if (key == "epg_async") + return SetBoolSetting(GetAsyncEpg(), value); + /* Predictive Tuning */ + else if (key == "pretuner_enabled") + return SetBoolSetting(m_bPretunerEnabled, value); + else if (key == "total_tuners") + { + if (!m_bPretunerEnabled) + return ADDON_STATUS_OK; + else + return SetIntSetting(GetTotalTuners(), value); + } + else if (key == "pretuner_closedelay") + { + SetPreTunerCloseDelay(value.GetInt()); + 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()); + return ADDON_STATUS_OK; + } + /* Streaming */ + else if (key == "streaming_profile") + return SetStringSetting(GetStreamingProfile(), value); + else if (key == "streaming_http") + return SetBoolSetting(GetStreamingHTTP(), value); + /* Default dvr settings */ + else if (key == "dvr_priority") + return SetIntSetting(GetDvrPriority(), value); + else if (key == "dvr_lifetime2") + return SetIntSetting(GetDvrLifetime(true), value); + else if (key == "dvr_dubdetect") + return SetIntSetting(GetDvrDupdetect(), value); + /* Server based play status */ + else if (key == "dvr_playstatus") + return SetBoolSetting(GetDvrPlayStatus(), value); + else if (key == "stream_readchunksize") + return SetIntSetting(GetStreamReadChunkSize(), value); + else if (key == "dvr_ignore_duplicates") + { + SetIgnoreDuplicateSchedules(value.GetBoolean()); + return ADDON_STATUS_OK; + } + else + { + Logger::Log(LogLevel::LEVEL_ERROR, "InstanceSettings::SetSetting - unknown setting '%s'", + key.c_str()); + return ADDON_STATUS_UNKNOWN; + } +} + +std::string InstanceSettings::ReadStringSetting(const std::string& key, + const std::string& def) const +{ + std::string value; + if (m_instance.CheckInstanceSettingString(key, value)) + return value; + + return def; +} + +int InstanceSettings::ReadIntSetting(const std::string& key, int def) const +{ + int value; + if (m_instance.CheckInstanceSettingInt(key, value)) + return value; + + return def; +} + +bool InstanceSettings::ReadBoolSetting(const std::string& key, bool def) const +{ + bool value; + if (m_instance.CheckInstanceSettingBoolean(key, value)) + return value; + + return def; +} + +ADDON_STATUS InstanceSettings::SetStringSetting(const std::string& oldValue, + const kodi::addon::CSettingValue& newValue) +{ + if (oldValue == newValue.GetString()) + return ADDON_STATUS_OK; + + return ADDON_STATUS_NEED_RESTART; +} + +ADDON_STATUS InstanceSettings::SetIntSetting(int oldValue, + const kodi::addon::CSettingValue& newValue) +{ + if (oldValue == newValue.GetInt()) + return ADDON_STATUS_OK; + + return ADDON_STATUS_NEED_RESTART; +} + +ADDON_STATUS InstanceSettings::SetBoolSetting(bool oldValue, + const kodi::addon::CSettingValue& newValue) +{ + if (oldValue == newValue.GetBoolean()) + return ADDON_STATUS_OK; + + return ADDON_STATUS_NEED_RESTART; +} + +int InstanceSettings::GetDvrLifetime(bool asEnum) const +{ + if (asEnum) + return m_iDvrLifetime; + else + { + switch (m_iDvrLifetime) + { + case 0: + return DVR_RET_1DAY; + case 1: + return DVR_RET_3DAY; + case 2: + return DVR_RET_5DAY; + case 3: + return DVR_RET_1WEEK; + case 4: + return DVR_RET_2WEEK; + case 5: + return DVR_RET_3WEEK; + case 6: + return DVR_RET_1MONTH; + case 7: + return DVR_RET_2MONTH; + case 8: + return DVR_RET_3MONTH; + case 9: + return DVR_RET_6MONTH; + case 10: + return DVR_RET_1YEAR; + case 11: + return DVR_RET_2YEARS; + case 12: + return DVR_RET_3YEARS; + case 13: + return DVR_RET_SPACE; + case 14: + return DVR_RET_FOREVER; + case 15: + default: + return DVR_RET_DVRCONFIG; + } + } +} diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/InstanceSettings.h kodi-pvr-hts-20.6.0/src/tvheadend/InstanceSettings.h --- kodi-pvr-hts-19.0.6/src/tvheadend/InstanceSettings.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/InstanceSettings.h 2022-10-07 16:22:25.000000000 +0000 @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2005-2021 Team Kodi (https://kodi.tv) + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSE.md for more information. + */ + +#pragma once + +#include "kodi/AddonBase.h" + +#include + +namespace tvheadend +{ +/** + * Represents the current addon instance settings + */ +class InstanceSettings +{ +public: + explicit InstanceSettings(kodi::addon::IAddonInstance& instance); + + /** + * Set a value according to key definition in instance-settings.xml + */ + ADDON_STATUS SetSetting(const std::string& key, const kodi::addon::CSettingValue& value); + + /** + * Getters for the settings values + */ + std::string GetHostname() const { return m_strHostname; } + const char* GetConstCharHostname() const { return m_strHostname.c_str(); } + int GetPortHTSP() const { return m_iPortHTSP; } + int GetPortHTTP() const { return m_iPortHTTP; } + bool GetUseHTTPS() const { return m_bUseHTTPS; } + std::string GetUsername() const { return m_strUsername; } + std::string GetPassword() const { return m_strPassword; } + std::string GetWolMac() const { return m_strWolMac; } + int GetConnectTimeout() const { return m_iConnectTimeout; } + int GetResponseTimeout() const { return m_iResponseTimeout; } + bool GetAsyncEpg() const { return m_bAsyncEpg; } + int GetTotalTuners() const { return m_iTotalTuners; } + int GetPreTunerCloseDelay() const { return m_iPreTunerCloseDelay; } + int GetAutorecApproxTime() const { return m_iAutorecApproxTime; } + int GetAutorecMaxDiff() const { return m_iAutorecMaxDiff; } + bool GetAutorecUseRegEx() const { return m_bAutorecUseRegEx; } + std::string GetStreamingProfile() const { return m_strStreamingProfile; } + bool GetStreamingHTTP() const { return m_bUseHTTPStreaming; } + int GetDvrPriority() const { return m_iDvrPriority; } + int GetDvrDupdetect() const { return m_iDvrDupdetect; } + int GetDvrLifetime(bool asEnum = false) const; + bool GetDvrPlayStatus() const { return m_bDvrPlayStatus; } + int GetStreamReadChunkSize() const { return m_iStreamReadChunkSizeKB; } + bool GetIgnoreDuplicateSchedules() const { return m_bIgnoreDuplicateSchedules; } + +private: + InstanceSettings(const InstanceSettings&) = delete; + void operator=(const InstanceSettings&) = delete; + + /** + * Read all settings defined in instance-settings.xml + */ + void ReadSettings(); + + /** + * Setters + */ + void SetHostname(const std::string& value) { m_strHostname = value; } + void SetPortHTSP(int value) { m_iPortHTSP = value; } + void SetPortHTTP(int value) { m_iPortHTTP = value; } + void SetUseHTTPS(bool value) { m_bUseHTTPS = value; } + void SetUsername(const std::string& value) { m_strUsername = value; } + void SetPassword(const std::string& value) { m_strPassword = value; } + void SetWolMac(const std::string& value) { m_strWolMac = value; } + void SetConnectTimeout(int value) { m_iConnectTimeout = value; } + void SetResponseTimeout(int value) { m_iResponseTimeout = value; } + void SetAsyncEpg(bool value) { m_bAsyncEpg = value; } + void SetTotalTuners(int value) { m_iTotalTuners = value; } + void SetPreTunerCloseDelay(int value) { m_iPreTunerCloseDelay = value; } + void SetAutorecApproxTime(int value) { m_iAutorecApproxTime = value; } + void SetAutorecMaxDiff(int value) { m_iAutorecMaxDiff = value; } + void SetAutorecUseRegEx(bool value) { m_bAutorecUseRegEx = value; } + void SetStreamingProfile(const std::string& value) { m_strStreamingProfile = value; } + void SetStreamingHTTP(bool value) { m_bUseHTTPStreaming = value; } + void SetDvrPriority(int value) { m_iDvrPriority = value; } + void SetDvrLifetime(int value) { m_iDvrLifetime = value; } + void SetDvrDupdetect(int value) { m_iDvrDupdetect = value; } + void SetDvrPlayStatus(bool value) { m_bDvrPlayStatus = value; } + void SetStreamReadChunkSizeKB(int value) { m_iStreamReadChunkSizeKB = value; } + void SetIgnoreDuplicateSchedules(bool value) { m_bIgnoreDuplicateSchedules = value; } + + /** + * Read/Set values according to definition in settings.xml + */ + std::string ReadStringSetting(const std::string& key, const std::string& def) const; + int ReadIntSetting(const std::string& key, int def) const; + bool ReadBoolSetting(const std::string& key, bool def) const; + + // @return ADDON_STATUS_OK if value has not changed, ADDON_STATUS_NEED_RESTART otherwise + ADDON_STATUS SetStringSetting(const std::string& oldValue, + const kodi::addon::CSettingValue& newValue); + ADDON_STATUS SetIntSetting(int oldValue, const kodi::addon::CSettingValue& newValue); + ADDON_STATUS SetBoolSetting(bool oldValue, const kodi::addon::CSettingValue& newValue); + + kodi::addon::IAddonInstance& m_instance; + + std::string m_strHostname; + int m_iPortHTSP; + int m_iPortHTTP; + bool m_bUseHTTPS; + std::string m_strUsername; + std::string m_strPassword; + std::string m_strWolMac; + int m_iConnectTimeout; + int m_iResponseTimeout; + bool m_bAsyncEpg; + bool m_bPretunerEnabled; + int m_iTotalTuners; + int m_iPreTunerCloseDelay; + bool m_iAutorecApproxTime; + int m_iAutorecMaxDiff; + bool m_bAutorecUseRegEx; + std::string m_strStreamingProfile; + bool m_bUseHTTPStreaming; + int m_iDvrPriority; + int m_iDvrLifetime; + int m_iDvrDupdetect; + bool m_bDvrPlayStatus; + int m_iStreamReadChunkSizeKB; + bool m_bIgnoreDuplicateSchedules; +}; + +} // namespace tvheadend diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/Settings.cpp kodi-pvr-hts-20.6.0/src/tvheadend/Settings.cpp --- kodi-pvr-hts-19.0.6/src/tvheadend/Settings.cpp 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/Settings.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2005-2021 Team Kodi (https://kodi.tv) - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSE.md for more information. - */ - -#include "Settings.h" - -#include "utilities/Logger.h" - -#include "kodi/General.h" - -using namespace tvheadend; -using namespace tvheadend::utilities; - -const std::string Settings::DEFAULT_HOST = "127.0.0.1"; -const bool Settings::DEFAULT_USE_HTTPS = false; -const int Settings::DEFAULT_HTTP_PORT = 9981; -const int Settings::DEFAULT_HTSP_PORT = 9982; -const std::string Settings::DEFAULT_USERNAME = ""; -const std::string Settings::DEFAULT_PASSWORD = ""; -const std::string Settings::DEFAULT_WOL_MAC = ""; -const int Settings::DEFAULT_CONNECT_TIMEOUT = 10000; // millisecs -const int Settings::DEFAULT_RESPONSE_TIMEOUT = 5000; // millisecs -const bool Settings::DEFAULT_TRACE_DEBUG = false; -const bool Settings::DEFAULT_ASYNC_EPG = true; -const bool Settings::DEFAULT_PRETUNER_ENABLED = false; -const int Settings::DEFAULT_TOTAL_TUNERS = 1; // total tuners > 1 => predictive tuning active -const int Settings::DEFAULT_PRETUNER_CLOSEDELAY = 10; // secs -const int Settings::DEFAULT_AUTOREC_MAXDIFF = - 15; // mins. Maximum difference between real and approximate start time for auto recordings -const bool Settings::DEFAULT_AUTOREC_USE_REGEX = false; -const int Settings::DEFAULT_APPROX_TIME = - 0; // don't use an approximate start time, use a fixed time instead for auto recordings -const std::string Settings::DEFAULT_STREAMING_PROFILE = ""; -const bool Settings::DEFAULT_STREAMING_HTTP = false; -const int Settings::DEFAULT_DVR_PRIO = DVR_PRIO_NORMAL; -const int Settings::DEFAULT_DVR_LIFETIME = 15; // use backend setting -const int Settings::DEFAULT_DVR_DUPDETECT = DVR_AUTOREC_RECORD_ALL; -const bool Settings::DEFAULT_DVR_PLAYSTATUS = true; -const int Settings::DEFAULT_STREAM_CHUNKSIZE = 64; // KB -const bool Settings::DEFAULT_DVR_IGNORE_DUPLICATE_SCHEDULES = true; - -void Settings::ReadSettings() -{ - /* Connection */ - SetHostname(ReadStringSetting("host", DEFAULT_HOST)); - SetPortHTSP(ReadIntSetting("htsp_port", DEFAULT_HTSP_PORT)); - SetPortHTTP(ReadIntSetting("http_port", DEFAULT_HTTP_PORT)); - SetUseHTTPS(ReadBoolSetting("https", DEFAULT_USE_HTTPS)); - SetUsername(ReadStringSetting("user", DEFAULT_USERNAME)); - SetPassword(ReadStringSetting("pass", DEFAULT_PASSWORD)); - SetWolMac(ReadStringSetting("wol_mac", DEFAULT_WOL_MAC)); - - /* Note: Timeouts in settings UI are defined in seconds but we expect them to be in milliseconds. */ - SetConnectTimeout(ReadIntSetting("connect_timeout", DEFAULT_CONNECT_TIMEOUT / 1000) * 1000); - SetResponseTimeout(ReadIntSetting("response_timeout", DEFAULT_RESPONSE_TIMEOUT / 1000) * 1000); - - /* Debug */ - SetTraceDebug(ReadBoolSetting("trace_debug", DEFAULT_TRACE_DEBUG)); - - /* Data Transfer */ - SetAsyncEpg(ReadBoolSetting("epg_async", DEFAULT_ASYNC_EPG)); - - /* Predictive Tuning */ - m_bPretunerEnabled = ReadBoolSetting("pretuner_enabled", DEFAULT_PRETUNER_ENABLED); - SetTotalTuners(m_bPretunerEnabled ? ReadIntSetting("total_tuners", DEFAULT_TOTAL_TUNERS) : 1); - SetPreTunerCloseDelay( - 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 */ - SetStreamingProfile(ReadStringSetting("streaming_profile", DEFAULT_STREAMING_PROFILE)); - SetStreamingHTTP(ReadBoolSetting("streaming_http", DEFAULT_STREAMING_HTTP)); - - /* Default dvr settings */ - SetDvrPriority(ReadIntSetting("dvr_priority", DEFAULT_DVR_PRIO)); - SetDvrLifetime(ReadIntSetting("dvr_lifetime2", DEFAULT_DVR_LIFETIME)); - SetDvrDupdetect(ReadIntSetting("dvr_dubdetect", DEFAULT_DVR_DUPDETECT)); - - /* Sever based play status */ - SetDvrPlayStatus(ReadBoolSetting("dvr_playstatus", DEFAULT_DVR_PLAYSTATUS)); - - /* Stream read chunk size */ - SetStreamReadChunkSizeKB(ReadIntSetting("stream_readchunksize", DEFAULT_STREAM_CHUNKSIZE)); - - /* Scheduled recordings */ - SetIgnoreDuplicateSchedules( - ReadBoolSetting("dvr_ignore_duplicates", DEFAULT_DVR_IGNORE_DUPLICATE_SCHEDULES)); -} - -ADDON_STATUS Settings::SetSetting(const std::string& key, const kodi::CSettingValue& value) -{ - /* Connection */ - if (key == "host") - return SetStringSetting(GetHostname(), value); - else if (key == "htsp_port") - return SetIntSetting(GetPortHTSP(), value); - else if (key == "http_port") - return SetIntSetting(GetPortHTTP(), value); - else if (key == "https") - return SetBoolSetting(GetUseHTTPS(), value); - else if (key == "user") - return SetStringSetting(GetUsername(), value); - else if (key == "pass") - return SetStringSetting(GetPassword(), value); - else if (key == "wol_mac") - return SetStringSetting(GetWolMac(), value); - else if (key == "connect_timeout") - { - if (GetConnectTimeout() == value.GetInt() * 1000) - return ADDON_STATUS_OK; - else - return ADDON_STATUS_NEED_RESTART; - } - else if (key == "response_timeout") - { - if (GetResponseTimeout() == value.GetInt() * 1000) - return ADDON_STATUS_OK; - else - return ADDON_STATUS_NEED_RESTART; - } - /* Debug */ - else if (key == "trace_debug") - return SetBoolSetting(GetTraceDebug(), value); - /* Data Transfer */ - else if (key == "epg_async") - return SetBoolSetting(GetAsyncEpg(), value); - /* Predictive Tuning */ - else if (key == "pretuner_enabled") - return SetBoolSetting(m_bPretunerEnabled, value); - else if (key == "total_tuners") - { - if (!m_bPretunerEnabled) - return ADDON_STATUS_OK; - else - return SetIntSetting(GetTotalTuners(), value); - } - else if (key == "pretuner_closedelay") - { - if (!m_bPretunerEnabled) - return ADDON_STATUS_OK; - else - return SetIntSetting(GetPreTunerCloseDelay(), value); - } - /* Auto recordings */ - else if (key == "autorec_approxtime") - return SetIntSetting(GetAutorecApproxTime(), value); - else if (key == "autorec_maxdiff") - return SetIntSetting(GetAutorecMaxDiff(), value); - else if (key == "autorec_use_regex") - return SetBoolSetting(GetAutorecUseRegEx(), value); - /* Streaming */ - else if (key == "streaming_profile") - return SetStringSetting(GetStreamingProfile(), value); - else if (key == "streaming_http") - return SetBoolSetting(GetStreamingHTTP(), value); - /* Default dvr settings */ - else if (key == "dvr_priority") - return SetIntSetting(GetDvrPriority(), value); - else if (key == "dvr_lifetime2") - return SetIntSetting(GetDvrLifetime(true), value); - else if (key == "dvr_dubdetect") - return SetIntSetting(GetDvrDupdetect(), value); - /* Server based play status */ - else if (key == "dvr_playstatus") - return SetBoolSetting(GetDvrPlayStatus(), value); - else if (key == "stream_readchunksize") - return SetIntSetting(GetStreamReadChunkSize(), value); - else if (key == "dvr_ignore_duplicates") - return SetBoolSetting(GetIgnoreDuplicateSchedules(), value); - else - { - Logger::Log(LogLevel::LEVEL_ERROR, "Settings::SetSetting - unknown setting '%s'", key.c_str()); - return ADDON_STATUS_UNKNOWN; - } -} - -std::string Settings::ReadStringSetting(const std::string& key, const std::string& def) -{ - std::string value; - if (kodi::CheckSettingString(key, value)) - return value; - - return def; -} - -int Settings::ReadIntSetting(const std::string& key, int def) -{ - int value; - if (kodi::CheckSettingInt(key, value)) - return value; - - return def; -} - -bool Settings::ReadBoolSetting(const std::string& key, bool def) -{ - bool value; - if (kodi::CheckSettingBoolean(key, value)) - return value; - - return def; -} - -ADDON_STATUS Settings::SetStringSetting(const std::string& oldValue, - const kodi::CSettingValue& newValue) -{ - if (oldValue == newValue.GetString()) - return ADDON_STATUS_OK; - - return ADDON_STATUS_NEED_RESTART; -} - -ADDON_STATUS Settings::SetIntSetting(int oldValue, const kodi::CSettingValue& newValue) -{ - if (oldValue == newValue.GetInt()) - return ADDON_STATUS_OK; - - return ADDON_STATUS_NEED_RESTART; -} - -ADDON_STATUS Settings::SetBoolSetting(bool oldValue, const kodi::CSettingValue& newValue) -{ - if (oldValue == newValue.GetBoolean()) - return ADDON_STATUS_OK; - - return ADDON_STATUS_NEED_RESTART; -} - -int Settings::GetDvrLifetime(bool asEnum) const -{ - if (asEnum) - return m_iDvrLifetime; - else - { - switch (m_iDvrLifetime) - { - case 0: - return DVR_RET_1DAY; - case 1: - return DVR_RET_3DAY; - case 2: - return DVR_RET_5DAY; - case 3: - return DVR_RET_1WEEK; - case 4: - return DVR_RET_2WEEK; - case 5: - return DVR_RET_3WEEK; - case 6: - return DVR_RET_1MONTH; - case 7: - return DVR_RET_2MONTH; - case 8: - return DVR_RET_3MONTH; - case 9: - return DVR_RET_6MONTH; - case 10: - return DVR_RET_1YEAR; - case 11: - return DVR_RET_2YEARS; - case 12: - return DVR_RET_3YEARS; - case 13: - return DVR_RET_SPACE; - case 14: - return DVR_RET_FOREVER; - case 15: - default: - return DVR_RET_DVRCONFIG; - } - } -} diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/Settings.h kodi-pvr-hts-20.6.0/src/tvheadend/Settings.h --- kodi-pvr-hts-19.0.6/src/tvheadend/Settings.h 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/Settings.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2005-2021 Team Kodi (https://kodi.tv) - * - * SPDX-License-Identifier: GPL-2.0-or-later - * See LICENSE.md for more information. - */ - -#pragma once - -#include "HTSPTypes.h" - -#include "kodi/AddonBase.h" - -#include - -namespace tvheadend -{ - -/** - * Represents the current addon settings - */ -class Settings -{ -public: - // Default values. - static const std::string DEFAULT_HOST; - static const int DEFAULT_HTTP_PORT; - static const int DEFAULT_HTSP_PORT; - static const bool DEFAULT_USE_HTTPS; - static const std::string DEFAULT_USERNAME; - static const std::string DEFAULT_PASSWORD; - static const std::string DEFAULT_WOL_MAC; - static const int DEFAULT_CONNECT_TIMEOUT; // millisecs - static const int DEFAULT_RESPONSE_TIMEOUT; // millisecs - static const bool DEFAULT_TRACE_DEBUG; - static const bool DEFAULT_ASYNC_EPG; - static const bool DEFAULT_PRETUNER_ENABLED; - static const int DEFAULT_TOTAL_TUNERS; - static const int DEFAULT_PRETUNER_CLOSEDELAY; // secs - static const int - DEFAULT_AUTOREC_MAXDIFF; // mins. Maximum difference between real and approximate start time for auto recordings - static const bool DEFAULT_AUTOREC_USE_REGEX; - static const int - DEFAULT_APPROX_TIME; // 0..1 (0 = use a fixed start time, 1 = use an approximate start time for auto recordings) - static const std::string DEFAULT_STREAMING_PROFILE; - static const bool DEFAULT_STREAMING_HTTP; - static const int DEFAULT_DVR_PRIO; // any dvr_prio_t numeric value - static const int DEFAULT_DVR_LIFETIME; // 0..15 (0 = 1 day, 15 = use backend setting) - static const int DEFAULT_DVR_DUPDETECT; // 0..5 (0 = record all, 5 = limit to once a day) - static const bool DEFAULT_DVR_PLAYSTATUS; - static const int DEFAULT_STREAM_CHUNKSIZE; // KB - static const bool DEFAULT_DVR_IGNORE_DUPLICATE_SCHEDULES; - - /** - * Singleton getter for the instance - */ - static Settings& GetInstance() - { - static Settings settings; - return settings; - } - - /** - * Read all settings defined in settings.xml - */ - void ReadSettings(); - - /** - * Set a value according to key definition in settings.xml - */ - ADDON_STATUS SetSetting(const std::string& key, const kodi::CSettingValue& value); - - /** - * Getters for the settings values - */ - std::string GetHostname() const { return m_strHostname; } - const char* GetConstCharHostname() const { return m_strHostname.c_str(); } - int GetPortHTSP() const { return m_iPortHTSP; } - int GetPortHTTP() const { return m_iPortHTTP; } - bool GetUseHTTPS() const { return m_bUseHTTPS; } - std::string GetUsername() const { return m_strUsername; } - std::string GetPassword() const { return m_strPassword; } - std::string GetWolMac() const { return m_strWolMac; } - int GetConnectTimeout() const { return m_iConnectTimeout; } - int GetResponseTimeout() const { return m_iResponseTimeout; } - bool GetTraceDebug() const { return m_bTraceDebug; } - bool GetAsyncEpg() const { return m_bAsyncEpg; } - int GetTotalTuners() const { return m_iTotalTuners; } - int GetPreTunerCloseDelay() const { return m_iPreTunerCloseDelay; } - int GetAutorecApproxTime() const { return m_iAutorecApproxTime; } - int GetAutorecMaxDiff() const { return m_iAutorecMaxDiff; } - bool GetAutorecUseRegEx() const { return m_bAutorecUseRegEx; } - std::string GetStreamingProfile() const { return m_strStreamingProfile; } - bool GetStreamingHTTP() const { return m_bUseHTTPStreaming; } - int GetDvrPriority() const { return m_iDvrPriority; } - int GetDvrDupdetect() const { return m_iDvrDupdetect; } - int GetDvrLifetime(bool asEnum = false) const; - bool GetDvrPlayStatus() const { return m_bDvrPlayStatus; } - int GetStreamReadChunkSize() const { return m_iStreamReadChunkSizeKB; } - bool GetIgnoreDuplicateSchedules() const { return m_bIgnoreDuplicateSchedules; } - -private: - Settings() - : m_strHostname(DEFAULT_HOST), - m_iPortHTSP(DEFAULT_HTTP_PORT), - m_iPortHTTP(DEFAULT_HTSP_PORT), - m_bUseHTTPS(DEFAULT_USE_HTTPS), - m_strUsername(DEFAULT_USERNAME), - m_strPassword(DEFAULT_PASSWORD), - m_strWolMac(DEFAULT_WOL_MAC), - m_iConnectTimeout(DEFAULT_CONNECT_TIMEOUT), - m_iResponseTimeout(DEFAULT_RESPONSE_TIMEOUT), - m_bTraceDebug(DEFAULT_TRACE_DEBUG), - m_bAsyncEpg(DEFAULT_ASYNC_EPG), - 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), - m_iDvrPriority(DEFAULT_DVR_PRIO), - m_iDvrLifetime(DEFAULT_DVR_LIFETIME), - m_iDvrDupdetect(DEFAULT_DVR_DUPDETECT), - m_bDvrPlayStatus(DEFAULT_DVR_PLAYSTATUS), - m_iStreamReadChunkSizeKB(DEFAULT_STREAM_CHUNKSIZE), - m_bIgnoreDuplicateSchedules(DEFAULT_DVR_IGNORE_DUPLICATE_SCHEDULES) - { - } - - Settings(Settings const&) = delete; - void operator=(Settings const&) = delete; - - /** - * Setters - */ - void SetHostname(const std::string& value) { m_strHostname = value; } - void SetPortHTSP(int value) { m_iPortHTSP = value; } - void SetPortHTTP(int value) { m_iPortHTTP = value; } - void SetUseHTTPS(bool value) { m_bUseHTTPS = value; } - void SetUsername(const std::string& value) { m_strUsername = value; } - void SetPassword(const std::string& value) { m_strPassword = value; } - void SetWolMac(const std::string& value) { m_strWolMac = value; } - void SetConnectTimeout(int value) { m_iConnectTimeout = value; } - void SetResponseTimeout(int value) { m_iResponseTimeout = value; } - void SetTraceDebug(bool value) { m_bTraceDebug = value; } - void SetAsyncEpg(bool value) { m_bAsyncEpg = value; } - void SetTotalTuners(int value) { m_iTotalTuners = value; } - void SetPreTunerCloseDelay(int value) { m_iPreTunerCloseDelay = value; } - void SetAutorecApproxTime(int value) { m_iAutorecApproxTime = value; } - void SetAutorecMaxDiff(int value) { m_iAutorecMaxDiff = value; } - void SetAutorecUseRegEx(bool value) { m_bAutorecUseRegEx = value; } - void SetStreamingProfile(const std::string& value) { m_strStreamingProfile = value; } - void SetStreamingHTTP(bool value) { m_bUseHTTPStreaming = value; } - void SetDvrPriority(int value) { m_iDvrPriority = value; } - void SetDvrLifetime(int value) { m_iDvrLifetime = value; } - void SetDvrDupdetect(int value) { m_iDvrDupdetect = value; } - void SetDvrPlayStatus(bool value) { m_bDvrPlayStatus = value; } - void SetStreamReadChunkSizeKB(int value) { m_iStreamReadChunkSizeKB = value; } - void SetIgnoreDuplicateSchedules(bool value) { m_bIgnoreDuplicateSchedules = value; } - - /** - * Read/Set values according to definition in settings.xml - */ - static std::string ReadStringSetting(const std::string& key, const std::string& def); - static int ReadIntSetting(const std::string& key, int def); - static bool ReadBoolSetting(const std::string& key, bool def); - - // @return ADDON_STATUS_OK if value has not changed, ADDON_STATUS_NEED_RESTART otherwise - static ADDON_STATUS SetStringSetting(const std::string& oldValue, - const kodi::CSettingValue& newValue); - static ADDON_STATUS SetIntSetting(int oldValue, const kodi::CSettingValue& newValue); - static ADDON_STATUS SetBoolSetting(bool oldValue, const kodi::CSettingValue& newValue); - - std::string m_strHostname; - int m_iPortHTSP; - int m_iPortHTTP; - bool m_bUseHTTPS; - std::string m_strUsername; - std::string m_strPassword; - std::string m_strWolMac; - int m_iConnectTimeout; - int m_iResponseTimeout; - bool m_bTraceDebug; - bool m_bAsyncEpg; - bool m_bPretunerEnabled; - int m_iTotalTuners; - int m_iPreTunerCloseDelay; - bool m_iAutorecApproxTime; - int m_iAutorecMaxDiff; - bool m_bAutorecUseRegEx; - std::string m_strStreamingProfile; - bool m_bUseHTTPStreaming; - int m_iDvrPriority; - int m_iDvrLifetime; - int m_iDvrDupdetect; - bool m_bDvrPlayStatus; - int m_iStreamReadChunkSizeKB; - bool m_bIgnoreDuplicateSchedules; -}; - -} // namespace tvheadend diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/Subscription.cpp kodi-pvr-hts-20.6.0/src/tvheadend/Subscription.cpp --- kodi-pvr-hts-19.0.6/src/tvheadend/Subscription.cpp 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/Subscription.cpp 2022-10-07 16:22:25.000000000 +0000 @@ -240,67 +240,49 @@ } const char* status = htsmsg_get_str(m, "status"); + const char* error = htsmsg_get_str(m, "subscriptionError"); - /* 'subscriptionErrors' was added in htsp v20, use 'status' for older backends */ - if (m_conn.GetProtocol() >= 20) + /* This field is absent when everything is fine */ + if (error) { - const char* error = htsmsg_get_str(m, "subscriptionError"); - - /* This field is absent when everything is fine */ - if (error) - { - if (!std::strcmp("badSignal", error)) - SetState(SUBSCRIPTION_NOSIGNAL); - else if (!std::strcmp("scrambled", error)) - SetState(SUBSCRIPTION_SCRAMBLED); - else if (!std::strcmp("userLimit", error)) - SetState(SUBSCRIPTION_USERLIMIT); - else if (!std::strcmp("noFreeAdapter", error)) - SetState(SUBSCRIPTION_NOFREEADAPTER); - else if (!std::strcmp("tuningFailed", error)) - SetState(SUBSCRIPTION_TUNINGFAILED); - else if (!std::strcmp("userAccess", error)) - SetState(SUBSCRIPTION_NOACCESS); - else - SetState(SUBSCRIPTION_UNKNOWN); - - /* Show an OSD message */ - ShowStateNotification(); - } + if (!std::strcmp("badSignal", error)) + SetState(SUBSCRIPTION_NOSIGNAL); + else if (!std::strcmp("scrambled", error)) + SetState(SUBSCRIPTION_SCRAMBLED); + else if (!std::strcmp("userLimit", error)) + SetState(SUBSCRIPTION_USERLIMIT); + else if (!std::strcmp("noFreeAdapter", error)) + SetState(SUBSCRIPTION_NOFREEADAPTER); + else if (!std::strcmp("tuningFailed", error)) + SetState(SUBSCRIPTION_TUNINGFAILED); + else if (!std::strcmp("userAccess", error)) + SetState(SUBSCRIPTION_NOACCESS); else - SetState(SUBSCRIPTION_RUNNING); - } - else - { - /* This field is absent when everything is fine */ - if (status) - { SetState(SUBSCRIPTION_UNKNOWN); - /* Show an OSD message */ - kodi::QueueNotification(QUEUE_INFO, "", status); - } - else - SetState(SUBSCRIPTION_RUNNING); + /* Show an OSD message */ + ShowStateNotification(); } + else + SetState(SUBSCRIPTION_RUNNING); } void Subscription::ShowStateNotification() { if (GetState() == SUBSCRIPTION_NOFREEADAPTER) - kodi::QueueNotification(QUEUE_WARNING, "", kodi::GetLocalizedString(30450)); + kodi::QueueNotification(QUEUE_WARNING, "", kodi::addon::GetLocalizedString(30450)); else if (GetState() == SUBSCRIPTION_SCRAMBLED) - kodi::QueueNotification(QUEUE_WARNING, "", kodi::GetLocalizedString(30451)); + kodi::QueueNotification(QUEUE_WARNING, "", kodi::addon::GetLocalizedString(30451)); else if (GetState() == SUBSCRIPTION_NOSIGNAL) - kodi::QueueNotification(QUEUE_WARNING, "", kodi::GetLocalizedString(30452)); + kodi::QueueNotification(QUEUE_WARNING, "", kodi::addon::GetLocalizedString(30452)); else if (GetState() == SUBSCRIPTION_TUNINGFAILED) - kodi::QueueNotification(QUEUE_WARNING, "", kodi::GetLocalizedString(30453)); + kodi::QueueNotification(QUEUE_WARNING, "", kodi::addon::GetLocalizedString(30453)); else if (GetState() == SUBSCRIPTION_USERLIMIT) - kodi::QueueNotification(QUEUE_WARNING, "", kodi::GetLocalizedString(30454)); + kodi::QueueNotification(QUEUE_WARNING, "", kodi::addon::GetLocalizedString(30454)); else if (GetState() == SUBSCRIPTION_NOACCESS) - kodi::QueueNotification(QUEUE_WARNING, "", kodi::GetLocalizedString(30455)); + kodi::QueueNotification(QUEUE_WARNING, "", kodi::addon::GetLocalizedString(30455)); else if (GetState() == SUBSCRIPTION_UNKNOWN) - kodi::QueueNotification(QUEUE_WARNING, "", kodi::GetLocalizedString(30456)); + kodi::QueueNotification(QUEUE_WARNING, "", kodi::addon::GetLocalizedString(30456)); } uint32_t Subscription::GetNextId() diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/TimeRecordings.cpp kodi-pvr-hts-20.6.0/src/tvheadend/TimeRecordings.cpp --- kodi-pvr-hts-19.0.6/src/tvheadend/TimeRecordings.cpp 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/TimeRecordings.cpp 2022-10-07 16:22:25.000000000 +0000 @@ -114,16 +114,7 @@ PVR_ERROR TimeRecordings::SendTimerecUpdate(const kodi::addon::PVRTimer& timer) { - if (m_conn.GetProtocol() >= 25) - return SendTimerecAddOrUpdate(timer, true); - - /* Note: there is no "updateTimerec" htsp method for htsp version < 25, thus delete + add. */ - PVR_ERROR error = SendTimerecDelete(timer); - - if (error == PVR_ERROR_NO_ERROR) - error = SendTimerecAdd(timer); - - return error; + return SendTimerecAddOrUpdate(timer, true); } PVR_ERROR TimeRecordings::SendTimerecAddOrUpdate(const kodi::addon::PVRTimer& timer, bool update) @@ -159,21 +150,8 @@ struct tm* tm_stop = std::localtime(&endTime); htsmsg_add_u32(m, "stop", tm_stop->tm_hour * 60 + tm_stop->tm_min); // end time in minutes from midnight - - if (m_conn.GetProtocol() >= 25) - { - htsmsg_add_u32(m, "removal", timer.GetLifetime()); // remove from disk - htsmsg_add_s64(m, "channelId", - timer.GetClientChannelUid()); // channelId is signed for >= htspv25 - } - else - { - htsmsg_add_u32(m, "retention", - LifetimeMapper::KodiToTvh(timer.GetLifetime())); // remove from tvh database - htsmsg_add_u32(m, "channelId", - timer.GetClientChannelUid()); // channelId is unsigned for < htspv25 - } - + htsmsg_add_u32(m, "removal", timer.GetLifetime()); // remove from disk + htsmsg_add_s64(m, "channelId", timer.GetClientChannelUid()); htsmsg_add_u32(m, "daysOfWeek", timer.GetWeekdays()); htsmsg_add_u32(m, "priority", timer.GetPriority()); htsmsg_add_u32(m, "enabled", timer.GetState() == PVR_TIMER_STATE_DISABLED ? 0 : 1); @@ -273,29 +251,14 @@ return false; } - if (m_conn.GetProtocol() >= 25) + if (!htsmsg_get_u32(msg, "removal", &u32)) { - if (!htsmsg_get_u32(msg, "removal", &u32)) - { - rec.SetLifetime(u32); - } - else if (bAdd) - { - Logger::Log(LogLevel::LEVEL_ERROR, "malformed timerecEntryAdd: 'removal' missing"); - return false; - } + rec.SetLifetime(u32); } - else + else if (bAdd) { - if (!htsmsg_get_u32(msg, "retention", &u32)) - { - rec.SetLifetime(u32); - } - else if (bAdd) - { - Logger::Log(LogLevel::LEVEL_ERROR, "malformed timerecEntryAdd: 'retention' missing"); - return false; - } + Logger::Log(LogLevel::LEVEL_ERROR, "malformed timerecEntryAdd: 'removal' missing"); + return false; } if (!htsmsg_get_u32(msg, "priority", &u32)) diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/utilities/SettingsMigration.cpp kodi-pvr-hts-20.6.0/src/tvheadend/utilities/SettingsMigration.cpp --- kodi-pvr-hts-19.0.6/src/tvheadend/utilities/SettingsMigration.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/utilities/SettingsMigration.cpp 2022-10-07 16:22:25.000000000 +0000 @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2005-2022 Team Kodi (https://kodi.tv) + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSE.md for more information. + */ + +#include "SettingsMigration.h" + +#include "../HTSPTypes.h" + +#include "kodi/General.h" + +#include +#include +#include + +using namespace tvheadend; +using namespace tvheadend::utilities; + +namespace +{ +// maps +const std::vector> stringMap = { + {"host", "127.0.0.1"}, {"user", ""}, {"pass", ""}, {"wol_mac", ""}, {"streaming_profile", ""}}; + +const std::vector> intMap = {{"htsp_port", 9981}, + {"http_port", 9982}, + {"connect_timeout", 10000}, + {"response_timeout", 5000}, + {"total_tuners", 1}, + {"pretuner_closedelay", 10}, + {"autorec_approxtime", 0}, + {"autorec_maxdiff", 15}, + {"dvr_priority", DVR_PRIO_NORMAL}, + {"dvr_lifetime2", 15}, + {"dvr_dubdetect", DVR_AUTOREC_RECORD_ALL}, + {"stream_readchunksize", 64}}; + +const std::vector> boolMap = {{"https", false}, + {"epg_async", true}, + {"pretuner_enabled", false}, + {"autorec_use_regex", false}, + {"streaming_http", false}, + {"dvr_playstatus", true}, + {"dvr_ignore_duplicates", true}}; + +} // unnamed namespace + +bool SettingsMigration::MigrateSettings(kodi::addon::IAddonInstance& target) +{ + std::string stringValue; + bool boolValue{false}; + int intValue{0}; + + if (target.CheckInstanceSettingString("kodi_addon_instance_name", stringValue) && + !stringValue.empty()) + { + // Instance already has valid instance settings + return false; + } + + // Read pre-multi-instance settings from settings.xml, transfer to instance settings + SettingsMigration mig(target); + + for (const auto& setting : stringMap) + mig.MigrateStringSetting(setting.first, setting.second); + + for (const auto& setting : intMap) + mig.MigrateIntSetting(setting.first, setting.second); + + for (const auto& setting : boolMap) + mig.MigrateBoolSetting(setting.first, setting.second); + + if (mig.Changed()) + { + // Set a title for the new instance settings + std::string title; + target.CheckInstanceSettingString("host", title); + if (title.empty()) + title = "Migrated Add-on Config"; + + target.SetInstanceSettingString("kodi_addon_instance_name", title); + return true; + } + return false; +} + +bool SettingsMigration::IsMigrationSetting(const std::string& key) +{ + return std::any_of(stringMap.cbegin(), stringMap.cend(), + [&key](const auto& entry) { return entry.first == key; }) || + std::any_of(intMap.cbegin(), intMap.cend(), + [&key](const auto& entry) { return entry.first == key; }) || + std::any_of(boolMap.cbegin(), boolMap.cend(), + [&key](const auto& entry) { return entry.first == key; }); +} + +void SettingsMigration::MigrateStringSetting(const char* key, const std::string& defaultValue) +{ + std::string value; + if (kodi::addon::CheckSettingString(key, value) && value != defaultValue) + { + m_target.SetInstanceSettingString(key, value); + m_changed = true; + } +} + +void SettingsMigration::MigrateIntSetting(const char* key, int defaultValue) +{ + int value; + if (kodi::addon::CheckSettingInt(key, value) && value != defaultValue) + { + m_target.SetInstanceSettingInt(key, value); + m_changed = true; + } +} + +void SettingsMigration::MigrateBoolSetting(const char* key, bool defaultValue) +{ + bool value; + if (kodi::addon::CheckSettingBoolean(key, value) && value != defaultValue) + { + m_target.SetInstanceSettingBoolean(key, value); + m_changed = true; + } +} diff -Nru kodi-pvr-hts-19.0.6/src/tvheadend/utilities/SettingsMigration.h kodi-pvr-hts-20.6.0/src/tvheadend/utilities/SettingsMigration.h --- kodi-pvr-hts-19.0.6/src/tvheadend/utilities/SettingsMigration.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/tvheadend/utilities/SettingsMigration.h 2022-10-07 16:22:25.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2005-2022 Team Kodi (https://kodi.tv) + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSE.md for more information. + */ + +#pragma once + +#include + +namespace kodi +{ +namespace addon +{ +class IAddonInstance; +} +} // namespace kodi + +namespace tvheadend +{ +namespace utilities +{ +class SettingsMigration +{ +public: + static bool MigrateSettings(kodi::addon::IAddonInstance& target); + static bool IsMigrationSetting(const std::string& key); + +private: + SettingsMigration() = delete; + explicit SettingsMigration(kodi::addon::IAddonInstance& target) : m_target(target) {} + + void MigrateStringSetting(const char* key, const std::string& defaultValue); + void MigrateIntSetting(const char* key, int defaultValue); + void MigrateBoolSetting(const char* key, bool defaultValue); + + bool Changed() const { return m_changed; } + + kodi::addon::IAddonInstance& m_target; + bool m_changed{false}; +}; + +} // namespace utilities +} // namespace tvheadend diff -Nru kodi-pvr-hts-19.0.6/src/Tvheadend.cpp kodi-pvr-hts-20.6.0/src/Tvheadend.cpp --- kodi-pvr-hts-19.0.6/src/Tvheadend.cpp 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/Tvheadend.cpp 2022-10-07 16:22:25.000000000 +0000 @@ -11,7 +11,7 @@ #include "tvheadend/HTSPDemuxer.h" #include "tvheadend/HTSPMessage.h" #include "tvheadend/HTSPVFS.h" -#include "tvheadend/Settings.h" +#include "tvheadend/InstanceSettings.h" #include "tvheadend/utilities/LifetimeMapper.h" #include "tvheadend/utilities/Logger.h" #include "tvheadend/utilities/Utilities.h" @@ -28,22 +28,23 @@ using namespace tvheadend::entity; using namespace tvheadend::utilities; -CTvheadend::CTvheadend(KODI_HANDLE instance, const std::string& kodiVersion) - : kodi::addon::CInstancePVRClient(instance, kodiVersion), - m_conn(new HTSPConnection(*this)), +CTvheadend::CTvheadend(const kodi::addon::IInstanceInfo& instance) + : kodi::addon::CInstancePVRClient(instance), + m_settings(new InstanceSettings(*this)), + m_conn(new HTSPConnection(m_settings, *this)), m_streamchange(false), - m_vfs(new HTSPVFS(*m_conn)), + m_vfs(new HTSPVFS(m_settings, *m_conn)), m_queue(static_cast(-1)), - m_asyncState(Settings::GetInstance().GetResponseTimeout()), + m_asyncState(m_settings->GetResponseTimeout()), m_timeRecordings(*m_conn), - m_autoRecordings(*m_conn), + m_autoRecordings(m_settings, *m_conn), m_epgMaxDays(EpgMaxFutureDays()), m_playingLiveStream(false), m_playingRecording(nullptr) { - for (int i = 0; i < 1 || i < Settings::GetInstance().GetTotalTuners(); i++) + for (int i = 0; i < 1 || i < m_settings->GetTotalTuners(); i++) { - m_dmx.emplace_back(new HTSPDemuxer(*this, *m_conn)); + m_dmx.emplace_back(new HTSPDemuxer(m_settings, *this, *m_conn)); } m_dmx_active = m_dmx[0]; } @@ -78,12 +79,19 @@ * Miscellaneous * *************************************************************************/ +ADDON_STATUS CTvheadend::SetInstanceSetting(const std::string& settingName, + const kodi::addon::CSettingValue& settingValue) +{ + return m_settings->SetSetting(settingName, settingValue); +} + PVR_ERROR CTvheadend::GetCapabilities(kodi::addon::PVRCapabilities& capabilities) { capabilities.SetSupportsEPG(true); capabilities.SetSupportsTV(true); capabilities.SetSupportsRadio(true); capabilities.SetSupportsRecordings(true); + capabilities.SetSupportsRecordingsDelete(true); capabilities.SetSupportsRecordingsUndelete(false); capabilities.SetSupportsTimers(true); capabilities.SetSupportsChannelGroups(true); @@ -91,11 +99,11 @@ capabilities.SetHandlesDemuxing(true); capabilities.SetSupportsRecordingEdl(true); capabilities.SetSupportsRecordingPlayCount(m_conn->GetProtocol() >= 27 && - Settings::GetInstance().GetDvrPlayStatus()); + m_settings->GetDvrPlayStatus()); capabilities.SetSupportsLastPlayedPosition(m_conn->GetProtocol() >= 27 && - Settings::GetInstance().GetDvrPlayStatus()); + m_settings->GetDvrPlayStatus()); capabilities.SetSupportsDescrambleInfo(true); - capabilities.SetSupportsAsyncEPGTransfer(Settings::GetInstance().GetAsyncEpg()); + capabilities.SetSupportsAsyncEPGTransfer(m_settings->GetAsyncEpg()); if (m_conn->GetProtocol() >= 28) { @@ -366,7 +374,7 @@ PVR_ERROR CTvheadend::GetChannelStreamProperties(const kodi::addon::PVRChannel& channel, std::vector& properties) { - if (!Settings::GetInstance().GetStreamingHTTP()) + if (!m_settings->GetStreamingHTTP()) return PVR_ERROR_NO_ERROR; std::lock_guard lock(m_mutex); @@ -376,7 +384,7 @@ return PVR_ERROR_FAILED; std::string path = "/stream/channelid/" + std::to_string(it->first); - const std::string streamingProfile = Settings::GetInstance().GetStreamingProfile(); + const std::string streamingProfile = m_settings->GetStreamingProfile(); if (!streamingProfile.empty()) path += "?profile=" + streamingProfile; @@ -401,8 +409,7 @@ htsmsg_add_u32(m, "id", id); /* Send and wait a bit longer than usual */ - m = m_conn->SendAndWait(lock, method, m, - std::max(30000, Settings::GetInstance().GetResponseTimeout())); + m = m_conn->SendAndWait(lock, method, m, std::max(30000, m_settings->GetResponseTimeout())); if (!m) return PVR_ERROR_SERVER_ERROR; @@ -698,19 +705,14 @@ /* Build message */ htsmsg_t* m = htsmsg_create_map(); htsmsg_add_u32(m, "id", std::stoul(rec.GetRecordingId())); - - if (m_conn->GetProtocol() >= 25) - htsmsg_add_u32(m, "removal", LifetimeMapper::KodiToTvh(rec.GetLifetime())); // remove from disk - else - htsmsg_add_u32(m, "retention", - LifetimeMapper::KodiToTvh(rec.GetLifetime())); // remove from tvh database + htsmsg_add_u32(m, "removal", LifetimeMapper::KodiToTvh(rec.GetLifetime())); // remove from disk return SendDvrUpdate(m); } PVR_ERROR CTvheadend::SetRecordingPlayCount(const kodi::addon::PVRRecording& rec, int playCount) { - if (m_conn->GetProtocol() < 27 || !Settings::GetInstance().GetDvrPlayStatus()) + if (m_conn->GetProtocol() < 27 || !m_settings->GetDvrPlayStatus()) return PVR_ERROR_NOT_IMPLEMENTED; Logger::Log(LogLevel::LEVEL_DEBUG, "Setting play count to %i for recording %s", playCount, @@ -726,7 +728,7 @@ PVR_ERROR CTvheadend::SetRecordingLastPlayedPosition(const kodi::addon::PVRRecording& rec, int playPosition) { - if (m_conn->GetProtocol() < 27 || !Settings::GetInstance().GetDvrPlayStatus()) + if (m_conn->GetProtocol() < 27 || !m_settings->GetDvrPlayStatus()) return PVR_ERROR_NOT_IMPLEMENTED; Logger::Log(LogLevel::LEVEL_DEBUG, "Setting play position to %i for recording %s", playPosition, @@ -743,7 +745,7 @@ PVR_ERROR CTvheadend::GetRecordingLastPlayedPosition(const kodi::addon::PVRRecording& rec, int& playPosition) { - if (m_conn->GetProtocol() < 27 || !Settings::GetInstance().GetDvrPlayStatus()) + if (m_conn->GetProtocol() < 27 || !m_settings->GetDvrPlayStatus()) return PVR_ERROR_NOT_IMPLEMENTED; std::lock_guard lock(m_mutex); @@ -763,7 +765,8 @@ { struct TimerType : kodi::addon::PVRTimerType { - TimerType(unsigned int id, + TimerType(const std::shared_ptr& settings, + unsigned int id, unsigned int attributes, const std::string& description, const std::vector& priorityValues = @@ -776,10 +779,9 @@ SetId(id); SetAttributes(attributes); SetDescription(description); - SetPriorities(priorityValues, Settings::GetInstance().GetDvrPriority()); - SetLifetimes(lifetimeValues, - LifetimeMapper::TvhToKodi(Settings::GetInstance().GetDvrLifetime())); - SetPreventDuplicateEpisodes(dupEpisodesValues, Settings::GetInstance().GetDvrDupdetect()); + SetPriorities(priorityValues, settings->GetDvrPriority()); + SetLifetimes(lifetimeValues, LifetimeMapper::TvhToKodi(settings->GetDvrLifetime())); + SetPreventDuplicateEpisodes(dupEpisodesValues, settings->GetDvrDupdetect()); } }; @@ -788,29 +790,23 @@ void CTvheadend::GetLivetimeValues(std::vector& lifetimeValues) const { lifetimeValues = { - {LifetimeMapper::TvhToKodi(DVR_RET_DVRCONFIG), kodi::GetLocalizedString(30390)}, - {LifetimeMapper::TvhToKodi(DVR_RET_1DAY), kodi::GetLocalizedString(30375)}, - {LifetimeMapper::TvhToKodi(DVR_RET_3DAY), kodi::GetLocalizedString(30376)}, - {LifetimeMapper::TvhToKodi(DVR_RET_5DAY), kodi::GetLocalizedString(30377)}, - {LifetimeMapper::TvhToKodi(DVR_RET_1WEEK), kodi::GetLocalizedString(30378)}, - {LifetimeMapper::TvhToKodi(DVR_RET_2WEEK), kodi::GetLocalizedString(30379)}, - {LifetimeMapper::TvhToKodi(DVR_RET_3WEEK), kodi::GetLocalizedString(30380)}, - {LifetimeMapper::TvhToKodi(DVR_RET_1MONTH), kodi::GetLocalizedString(30381)}, - {LifetimeMapper::TvhToKodi(DVR_RET_2MONTH), kodi::GetLocalizedString(30382)}, - {LifetimeMapper::TvhToKodi(DVR_RET_3MONTH), kodi::GetLocalizedString(30383)}, - {LifetimeMapper::TvhToKodi(DVR_RET_6MONTH), kodi::GetLocalizedString(30384)}, - {LifetimeMapper::TvhToKodi(DVR_RET_1YEAR), kodi::GetLocalizedString(30385)}, - {LifetimeMapper::TvhToKodi(DVR_RET_2YEARS), kodi::GetLocalizedString(30386)}, - {LifetimeMapper::TvhToKodi(DVR_RET_3YEARS), kodi::GetLocalizedString(30387)}, + {LifetimeMapper::TvhToKodi(DVR_RET_DVRCONFIG), kodi::addon::GetLocalizedString(30390)}, + {LifetimeMapper::TvhToKodi(DVR_RET_1DAY), kodi::addon::GetLocalizedString(30375)}, + {LifetimeMapper::TvhToKodi(DVR_RET_3DAY), kodi::addon::GetLocalizedString(30376)}, + {LifetimeMapper::TvhToKodi(DVR_RET_5DAY), kodi::addon::GetLocalizedString(30377)}, + {LifetimeMapper::TvhToKodi(DVR_RET_1WEEK), kodi::addon::GetLocalizedString(30378)}, + {LifetimeMapper::TvhToKodi(DVR_RET_2WEEK), kodi::addon::GetLocalizedString(30379)}, + {LifetimeMapper::TvhToKodi(DVR_RET_3WEEK), kodi::addon::GetLocalizedString(30380)}, + {LifetimeMapper::TvhToKodi(DVR_RET_1MONTH), kodi::addon::GetLocalizedString(30381)}, + {LifetimeMapper::TvhToKodi(DVR_RET_2MONTH), kodi::addon::GetLocalizedString(30382)}, + {LifetimeMapper::TvhToKodi(DVR_RET_3MONTH), kodi::addon::GetLocalizedString(30383)}, + {LifetimeMapper::TvhToKodi(DVR_RET_6MONTH), kodi::addon::GetLocalizedString(30384)}, + {LifetimeMapper::TvhToKodi(DVR_RET_1YEAR), kodi::addon::GetLocalizedString(30385)}, + {LifetimeMapper::TvhToKodi(DVR_RET_2YEARS), kodi::addon::GetLocalizedString(30386)}, + {LifetimeMapper::TvhToKodi(DVR_RET_3YEARS), kodi::addon::GetLocalizedString(30387)}, + {LifetimeMapper::TvhToKodi(DVR_RET_SPACE), kodi::addon::GetLocalizedString(30388)}, + {LifetimeMapper::TvhToKodi(DVR_RET_FOREVER), kodi::addon::GetLocalizedString(30389)}, }; - - if (m_conn->GetProtocol() >= 25) - { - lifetimeValues.emplace_back(LifetimeMapper::TvhToKodi(DVR_RET_SPACE), - kodi::GetLocalizedString(30373)); - lifetimeValues.emplace_back(LifetimeMapper::TvhToKodi(DVR_RET_FOREVER), - kodi::GetLocalizedString(30374)); - } } PVR_ERROR CTvheadend::GetTimerTypes(std::vector& types) @@ -820,51 +816,51 @@ if (priorityValues.size() == 0) { priorityValues = { - {DVR_PRIO_DEFAULT, kodi::GetLocalizedString(30368)}, - {DVR_PRIO_UNIMPORTANT, kodi::GetLocalizedString(30355)}, - {DVR_PRIO_LOW, kodi::GetLocalizedString(30354)}, - {DVR_PRIO_NORMAL, kodi::GetLocalizedString(30353)}, - {DVR_PRIO_HIGH, kodi::GetLocalizedString(30352)}, - {DVR_PRIO_IMPORTANT, kodi::GetLocalizedString(30351)}, + {DVR_PRIO_DEFAULT, kodi::addon::GetLocalizedString(30368)}, + {DVR_PRIO_UNIMPORTANT, kodi::addon::GetLocalizedString(30355)}, + {DVR_PRIO_LOW, kodi::addon::GetLocalizedString(30354)}, + {DVR_PRIO_NORMAL, kodi::addon::GetLocalizedString(30353)}, + {DVR_PRIO_HIGH, kodi::addon::GetLocalizedString(30352)}, + {DVR_PRIO_IMPORTANT, kodi::addon::GetLocalizedString(30351)}, }; } /* PVR_Timer.iPreventDuplicateEpisodes values and presentation.*/ std::vector deDupValues = { - {DVR_AUTOREC_RECORD_ALL, kodi::GetLocalizedString(30356)}, - {DVR_AUTOREC_RECORD_DIFFERENT_EPISODE_NUMBER, kodi::GetLocalizedString(30357)}, - {DVR_AUTOREC_RECORD_DIFFERENT_SUBTITLE, kodi::GetLocalizedString(30358)}, - {DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION, kodi::GetLocalizedString(30359)}, + {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)}, + {DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION, kodi::addon::GetLocalizedString(30359)}, }; if (m_conn->GetProtocol() >= 27) - deDupValues.emplace_back(DVR_AUTOREC_RECORD_ONCE_PER_MONTH, kodi::GetLocalizedString(30370)); - - deDupValues.emplace_back(DVR_AUTOREC_RECORD_ONCE_PER_WEEK, kodi::GetLocalizedString(30360)); - deDupValues.emplace_back(DVR_AUTOREC_RECORD_ONCE_PER_DAY, kodi::GetLocalizedString(30361)); + deDupValues.emplace_back(DVR_AUTOREC_RECORD_ONCE_PER_MONTH, + kodi::addon::GetLocalizedString(30370)); - if (m_conn->GetProtocol() >= 26) - { - deDupValues.emplace_back(DVR_AUTOREC_LRECORD_DIFFERENT_EPISODE_NUMBER, - kodi::GetLocalizedString(30362)); - deDupValues.emplace_back(DVR_AUTOREC_LRECORD_DIFFERENT_SUBTITLE, - kodi::GetLocalizedString(30363)); - deDupValues.emplace_back(DVR_AUTOREC_LRECORD_DIFFERENT_TITLE, kodi::GetLocalizedString(30364)); - deDupValues.emplace_back(DVR_AUTOREC_LRECORD_DIFFERENT_DESCRIPTION, - kodi::GetLocalizedString(30365)); - } + deDupValues.emplace_back(DVR_AUTOREC_RECORD_ONCE_PER_WEEK, + kodi::addon::GetLocalizedString(30360)); + deDupValues.emplace_back(DVR_AUTOREC_RECORD_ONCE_PER_DAY, kodi::addon::GetLocalizedString(30361)); + + deDupValues.emplace_back(DVR_AUTOREC_LRECORD_DIFFERENT_EPISODE_NUMBER, + kodi::addon::GetLocalizedString(30362)); + deDupValues.emplace_back(DVR_AUTOREC_LRECORD_DIFFERENT_SUBTITLE, + kodi::addon::GetLocalizedString(30363)); + deDupValues.emplace_back(DVR_AUTOREC_LRECORD_DIFFERENT_TITLE, + kodi::addon::GetLocalizedString(30364)); + deDupValues.emplace_back(DVR_AUTOREC_LRECORD_DIFFERENT_DESCRIPTION, + kodi::addon::GetLocalizedString(30365)); if (m_conn->GetProtocol() >= 27) - deDupValues.emplace_back(DVR_AUTOREC_LRECORD_ONCE_PER_MONTH, kodi::GetLocalizedString(30371)); + deDupValues.emplace_back(DVR_AUTOREC_LRECORD_ONCE_PER_MONTH, + kodi::addon::GetLocalizedString(30371)); - if (m_conn->GetProtocol() >= 26) - { - deDupValues.emplace_back(DVR_AUTOREC_LRECORD_ONCE_PER_WEEK, kodi::GetLocalizedString(30366)); - deDupValues.emplace_back(DVR_AUTOREC_LRECORD_ONCE_PER_DAY, kodi::GetLocalizedString(30367)); - } + deDupValues.emplace_back(DVR_AUTOREC_LRECORD_ONCE_PER_WEEK, + kodi::addon::GetLocalizedString(30366)); + deDupValues.emplace_back(DVR_AUTOREC_LRECORD_ONCE_PER_DAY, + kodi::addon::GetLocalizedString(30367)); if (m_conn->GetProtocol() >= 31) - deDupValues.emplace_back(DVR_AUTOREC_RECORD_UNIQUE, kodi::GetLocalizedString(30372)); + deDupValues.emplace_back(DVR_AUTOREC_RECORD_UNIQUE, kodi::addon::GetLocalizedString(30372)); /* PVR_Timer.iLifetime values and presentation.*/ std::vector lifetimeValues; @@ -873,24 +869,21 @@ unsigned int TIMER_ONCE_MANUAL_ATTRIBS = PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_END_TIME | - PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME; + PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | + PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE; unsigned int TIMER_ONCE_EPG_ATTRIBS = PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_END_TIME | PVR_TIMER_TYPE_REQUIRES_EPG_TAG_ON_CREATE | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | - PVR_TIMER_TYPE_SUPPORTS_LIFETIME; - - if (m_conn->GetProtocol() >= 23) - { - TIMER_ONCE_MANUAL_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE; - TIMER_ONCE_EPG_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE; - } + PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE; /* Timer types definition. */ /* One-shot manual (time and channel based) */ types.emplace_back(TimerType( + /* Settings */ + m_settings, /* Type id. */ TIMER_ONCE_MANUAL, /* Attributes. */ @@ -904,6 +897,8 @@ /* One-shot epg based */ types.emplace_back(TimerType( + /* Settings */ + m_settings, /* Type id. */ TIMER_ONCE_EPG, /* Attributes. */ @@ -917,12 +912,14 @@ /* Read-only one-shot for timers generated by timerec */ types.emplace_back(TimerType( + /* Settings */ + m_settings, /* Type id. */ TIMER_ONCE_CREATED_BY_TIMEREC, /* Attributes. */ TIMER_ONCE_MANUAL_ATTRIBS | PVR_TIMER_TYPE_IS_READONLY | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, /* Description. */ - kodi::GetLocalizedString(30350), // "One Time (Scheduled by timer rule)" + kodi::addon::GetLocalizedString(30350), // "One Time (Scheduled by timer rule)" /* Values definitions for priorities. */ priorityValues, /* Values definitions for lifetime. */ @@ -930,12 +927,14 @@ /* Read-only one-shot for timers generated by autorec */ types.emplace_back(TimerType( + /* Settings */ + m_settings, /* Type id. */ TIMER_ONCE_CREATED_BY_AUTOREC, /* Attributes. */ TIMER_ONCE_EPG_ATTRIBS | PVR_TIMER_TYPE_IS_READONLY | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, /* Description. */ - kodi::GetLocalizedString(30350), // "One Time (Scheduled by timer rule)" + kodi::addon::GetLocalizedString(30350), // "One Time (Scheduled by timer rule)" /* Values definitions for priorities. */ priorityValues, /* Values definitions for lifetime. */ @@ -943,6 +942,8 @@ /* Repeating manual (time and channel based) - timerec */ types.emplace_back(TimerType( + /* Settings */ + m_settings, /* Type id. */ TIMER_REPEATING_MANUAL, /* Attributes. */ @@ -968,7 +969,7 @@ 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 (!Settings::GetInstance().GetAutorecApproxTime()) + 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; @@ -977,12 +978,14 @@ /* Repeating epg based - series link autorec */ types.emplace_back(TimerType( + /* Settings */ + m_settings, /* Type id. */ TIMER_REPEATING_SERIESLINK, /* Attributes. */ TIMER_REPEATING_SERIESLINK_ATTRIBS, /* Description. */ - kodi::GetLocalizedString(30369), // "Timer rule (series link)" + kodi::addon::GetLocalizedString(30369), // "Timer rule (series link)" /* Values definitions for priorities. */ priorityValues, /* Values definitions for lifetime. */ @@ -995,15 +998,10 @@ 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_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_conn->GetProtocol() >= 20) - { - TIMER_REPEATING_EPG_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_FULLTEXT_EPG_MATCH; - TIMER_REPEATING_EPG_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES; - } - - if (!Settings::GetInstance().GetAutorecApproxTime()) + 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; @@ -1012,6 +1010,8 @@ /* Repeating epg based - autorec */ types.emplace_back(TimerType( + /* Settings */ + m_settings, /* Type id. */ TIMER_REPEATING_EPG, /* Attributes. */ @@ -1057,12 +1057,7 @@ tmr.SetEPGSearchString(""); // n/a for one-shot timers tmr.SetDirectory(""); // n/a for one-shot timers tmr.SetSummary(tvhTmr.GetDescription()); - - if (m_conn->GetProtocol() >= 23) - tmr.SetState(!tvhTmr.IsEnabled() ? PVR_TIMER_STATE_DISABLED : tvhTmr.GetState()); - else - tmr.SetState(tvhTmr.GetState()); - + tmr.SetState(!tvhTmr.IsEnabled() ? PVR_TIMER_STATE_DISABLED : tvhTmr.GetState()); tmr.SetPriority(tvhTmr.GetPriority()); tmr.SetLifetime(tvhTmr.GetLifetime()); tmr.SetTimerType(tvhTmr.GetTimerType()); @@ -1158,19 +1153,11 @@ htsmsg_add_str(m, "description", timer.GetSummary().c_str()); } - if (m_conn->GetProtocol() >= 23) - htsmsg_add_u32(m, "enabled", timer.GetState() == PVR_TIMER_STATE_DISABLED ? 0 : 1); - + htsmsg_add_u32(m, "enabled", timer.GetState() == PVR_TIMER_STATE_DISABLED ? 0 : 1); htsmsg_add_s64(m, "startExtra", timer.GetMarginStart()); htsmsg_add_s64(m, "stopExtra", timer.GetMarginEnd()); - - if (m_conn->GetProtocol() >= 25) - htsmsg_add_u32(m, "removal", - LifetimeMapper::KodiToTvh(timer.GetLifetime())); // remove from disk - else - htsmsg_add_u32(m, "retention", - LifetimeMapper::KodiToTvh(timer.GetLifetime())); // remove from tvh database - + htsmsg_add_u32(m, "removal", + LifetimeMapper::KodiToTvh(timer.GetLifetime())); // remove from disk htsmsg_add_u32(m, "priority", timer.GetPriority()); /* Send and Wait */ @@ -1220,18 +1207,8 @@ const auto& it = m_recordings.find(timer.GetClientIndex()); if (it != m_recordings.end() && it->second.IsRecording()) { - // This is a request to stop an active recording. - if (m_conn->GetProtocol() >= 26) - { - // gracefully stop the recording (mark as success in tvh) - return SendDvrDelete(timer.GetClientIndex(), "stopDvrEntry"); - } - else - { - // abort the recording (mark as failure in tvh) - no other choice, - // because graceful stop HTSP method was not available before HTSP v26. - return SendDvrDelete(timer.GetClientIndex(), "cancelDvrEntry"); - } + // gracefully stop the recording (mark as success in tvh) + return SendDvrDelete(timer.GetClientIndex(), "stopDvrEntry"); } } @@ -1275,36 +1252,9 @@ /* Build message */ htsmsg_t* m = htsmsg_create_map(); htsmsg_add_u32(m, "id", timer.GetClientIndex()); - - if (m_conn->GetProtocol() >= 22) - { - /* support for updating the channel was added very late to the htsp protocol. */ - htsmsg_add_u32(m, "channelId", timer.GetClientChannelUid()); - } - else - { - std::lock_guard lock(m_mutex); - - const auto& it = m_recordings.find(timer.GetClientIndex()); - if (it == m_recordings.end()) - { - Logger::Log(LogLevel::LEVEL_ERROR, "cannot find the timer to update"); - return PVR_ERROR_INVALID_PARAMETERS; - } - - if (it->second.GetChannel() != static_cast(timer.GetClientChannelUid())) - { - Logger::Log(LogLevel::LEVEL_ERROR, - "updating channels of one-shot timers not supported by HTSP v%d", - m_conn->GetProtocol()); - return PVR_ERROR_NOT_IMPLEMENTED; - } - } - + htsmsg_add_u32(m, "channelId", timer.GetClientChannelUid()); htsmsg_add_str(m, "title", timer.GetTitle().c_str()); - - if (m_conn->GetProtocol() >= 23) - htsmsg_add_u32(m, "enabled", timer.GetState() == PVR_TIMER_STATE_DISABLED ? 0 : 1); + htsmsg_add_u32(m, "enabled", timer.GetState() == PVR_TIMER_STATE_DISABLED ? 0 : 1); int64_t start = timer.GetStartTime(); if (start == 0) @@ -1318,14 +1268,8 @@ htsmsg_add_str(m, "description", timer.GetSummary().c_str()); htsmsg_add_s64(m, "startExtra", timer.GetMarginStart()); htsmsg_add_s64(m, "stopExtra", timer.GetMarginEnd()); - - if (m_conn->GetProtocol() >= 25) - htsmsg_add_u32(m, "removal", - LifetimeMapper::KodiToTvh(timer.GetLifetime())); // remove from disk - else - htsmsg_add_u32(m, "retention", - LifetimeMapper::KodiToTvh(timer.GetLifetime())); // remove from tvh database - + htsmsg_add_u32(m, "removal", + LifetimeMapper::KodiToTvh(timer.GetLifetime())); // remove from disk htsmsg_add_u32(m, "priority", timer.GetPriority()); return SendDvrUpdate(m); @@ -1344,21 +1288,18 @@ else if ((timer.GetTimerType() == TIMER_ONCE_CREATED_BY_TIMEREC) || (timer.GetTimerType() == TIMER_ONCE_CREATED_BY_AUTOREC)) { - if (m_conn->GetProtocol() >= 23) - { - /* Read-only timer created by autorec or timerec */ - std::lock_guard lock(m_mutex); + /* Read-only timer created by autorec or timerec */ + std::lock_guard lock(m_mutex); - const auto& it = m_recordings.find(timer.GetClientIndex()); - if (it != m_recordings.end() && - (it->second.IsEnabled() == (timer.GetState() == PVR_TIMER_STATE_DISABLED))) - { - /* This is actually a request to enable/disable a timer. */ - htsmsg_t* m = htsmsg_create_map(); - htsmsg_add_u32(m, "id", timer.GetClientIndex()); - htsmsg_add_u32(m, "enabled", timer.GetState() == PVR_TIMER_STATE_DISABLED ? 0 : 1); - return SendDvrUpdate(m); - } + const auto& it = m_recordings.find(timer.GetClientIndex()); + if (it != m_recordings.end() && + (it->second.IsEnabled() == (timer.GetState() == PVR_TIMER_STATE_DISABLED))) + { + /* This is actually a request to enable/disable a timer. */ + htsmsg_t* m = htsmsg_create_map(); + htsmsg_add_u32(m, "id", timer.GetClientIndex()); + htsmsg_add_u32(m, "enabled", timer.GetState() == PVR_TIMER_STATE_DISABLED ? 0 : 1); + return SendDvrUpdate(m); } Logger::Log(LogLevel::LEVEL_ERROR, "timer is read-only"); @@ -1494,7 +1435,7 @@ int iOldMaxDays = m_epgMaxDays; m_epgMaxDays = iFutureDays; - if (Settings::GetInstance().GetAsyncEpg()) + if (m_settings->GetAsyncEpg()) { Logger::Log(LogLevel::LEVEL_TRACE, "reconnecting to synchronize epg data. epg max time: old = %d, new = %d", @@ -1520,11 +1461,11 @@ QueryAvailableProfiles(lock); /* Show a notification if the profile is not available */ - const std::string streamingProfile = Settings::GetInstance().GetStreamingProfile(); + const std::string streamingProfile = m_settings->GetStreamingProfile(); if (!streamingProfile.empty() && !HasStreamingProfile(streamingProfile)) { - kodi::QueueFormattedNotification(QUEUE_ERROR, kodi::GetLocalizedString(30502).c_str(), + kodi::QueueFormattedNotification(QUEUE_ERROR, kodi::addon::GetLocalizedString(30502).c_str(), streamingProfile.c_str()); } else @@ -1538,7 +1479,7 @@ m_asyncState.SetState(ASYNC_INIT); htsmsg_t* msg = htsmsg_create_map(); - if (Settings::GetInstance().GetAsyncEpg()) + if (m_settings->GetAsyncEpg()) { Logger::Log(LogLevel::LEVEL_INFO, "Request async EPG (%d days)", m_epgMaxDays); htsmsg_add_u32(msg, "epg", 1); @@ -1583,7 +1524,7 @@ PVR_ERROR CTvheadend::GetBackendHostname(std::string& hostname) { - hostname = Settings::GetInstance().GetConstCharHostname(); + hostname = m_settings->GetConstCharHostname(); return PVR_ERROR_NO_ERROR; } @@ -1665,7 +1606,7 @@ if (!chunksize) return PVR_ERROR_INVALID_PARAMETERS; - chunksize = Settings::GetInstance().GetStreamReadChunkSize() * 1024; + chunksize = m_settings->GetStreamReadChunkSize() * 1024; return PVR_ERROR_NO_ERROR; } @@ -1731,7 +1672,7 @@ // predictive tuning active? if (m_dmx.size() > 1) { - int closeDelay = Settings::GetInstance().GetPreTunerCloseDelay(); + int closeDelay = m_settings->GetPreTunerCloseDelay(); if (closeDelay > 0) { for (auto* dmx : m_dmx) @@ -2022,7 +1963,7 @@ if (m_asyncState.GetState() != ASYNC_EPG) return; - if (!Settings::GetInstance().GetAsyncEpg()) + if (!m_settings->GetAsyncEpg()) { m_asyncState.SetState(ASYNC_DONE); return; @@ -2219,22 +2160,8 @@ continue; /* Channel type */ - if (m_conn->GetProtocol() >= 26) - { - if (!htsmsg_get_u32(&f->hmf_msg, "content", &u32)) - channel.SetType(u32); - } - else - { - str = htsmsg_get_str(&f->hmf_msg, "type"); - if (str) - { - if (!std::strcmp(str, "Radio")) - channel.SetType(CHANNEL_TYPE_RADIO); - else if (!std::strcmp(str, "SDTV") || !std::strcmp(str, "HDTV")) - channel.SetType(CHANNEL_TYPE_TV); - } - } + if (!htsmsg_get_u32(&f->hmf_msg, "content", &u32)) + channel.SetType(u32); /* CAID */ if (caid == 0) @@ -2295,8 +2222,8 @@ /* Ignore duplicates */ uint32_t dup = 0; - if (Settings::GetInstance().GetIgnoreDuplicateSchedules() && - !htsmsg_get_u32(msg, "duplicate", &dup) && dup == 1) + if (m_settings->GetIgnoreDuplicateSchedules() && !htsmsg_get_u32(msg, "duplicate", &dup) && + dup == 1) return; /* Ignore recordings without a file (e.g. removed recordings) */ @@ -2371,7 +2298,7 @@ htsmsg_t* files = htsmsg_get_list(msg, "files"); if (files) { - bool needChannelType = !rec.GetChannelType() && m_conn->GetProtocol() >= 25; + bool needChannelType = !rec.GetChannelType(); bool hasAudio = false; bool hasVideo = false; @@ -2438,7 +2365,7 @@ } /* Channel name fallback (in case channel was deleted) */ - if (rec.GetChannelName().empty() && m_conn->GetProtocol() >= 25) + if (rec.GetChannelName().empty()) { const char* str = htsmsg_get_str(msg, "channelName"); if (str) @@ -2463,31 +2390,15 @@ return; } - if (m_conn->GetProtocol() >= 25) + uint32_t removal = 0; + if (!htsmsg_get_u32(msg, "removal", &removal)) { - uint32_t removal = 0; - if (!htsmsg_get_u32(msg, "removal", &removal)) - { - rec.SetLifetime(removal); - } - else if (bAdd) - { - Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd: 'removal' missing"); - return; - } + rec.SetLifetime(removal); } - else + else if (bAdd) { - uint32_t retention = 0; - if (!htsmsg_get_u32(msg, "retention", &retention)) - { - rec.SetLifetime(retention); - } - else if (bAdd) - { - Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd: 'retention' missing"); - return; - } + Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd: 'removal' missing"); + return; } uint32_t priority = 0; diff -Nru kodi-pvr-hts-19.0.6/src/Tvheadend.h kodi-pvr-hts-20.6.0/src/Tvheadend.h --- kodi-pvr-hts-19.0.6/src/Tvheadend.h 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/src/Tvheadend.h 2022-10-07 16:22:25.000000000 +0000 @@ -31,6 +31,7 @@ #include "kodi/addon-instance/PVR.h" #include "kodi/tools/Thread.h" +#include #include #include #include @@ -46,6 +47,7 @@ class HTSPConnection; class HTSPDemuxer; class HTSPVFS; +class InstanceSettings; } // namespace tvheadend /* Typedefs */ @@ -54,18 +56,22 @@ /* * Root object for Tvheadend connection */ -class ATTRIBUTE_HIDDEN CTvheadend : public kodi::addon::CInstancePVRClient, - public kodi::tools::CThread, - public tvheadend::IHTSPConnectionListener, - public tvheadend::IHTSPDemuxPacketHandler +class ATTR_DLL_LOCAL CTvheadend : public kodi::addon::CInstancePVRClient, + public kodi::tools::CThread, + public tvheadend::IHTSPConnectionListener, + public tvheadend::IHTSPDemuxPacketHandler { public: - CTvheadend(KODI_HANDLE instance, const std::string& kodiVersion); + CTvheadend(const kodi::addon::IInstanceInfo& instance); ~CTvheadend() override; void Start(); void Stop(); + // kodi::addon::CInstancePVRClient -> kodi::addon::IAddonInstance overrides + ADDON_STATUS SetInstanceSetting(const std::string& settingName, + const kodi::addon::CSettingValue& settingValue) override; + // IHTSPConnectionListener implementation void Disconnected() override; bool Connected(std::unique_lock& lock) override; @@ -256,6 +262,8 @@ std::recursive_mutex m_mutex; + std::shared_ptr m_settings; + tvheadend::HTSPConnection* m_conn; std::vector m_dmx; diff -Nru kodi-pvr-hts-19.0.6/.travis.yml kodi-pvr-hts-20.6.0/.travis.yml --- kodi-pvr-hts-19.0.6/.travis.yml 2022-02-01 11:25:37.000000000 +0000 +++ kodi-pvr-hts-20.6.0/.travis.yml 2022-10-07 16:22:25.000000000 +0000 @@ -31,7 +31,7 @@ osx_image: xcode10.2 before_install: - - if [[ $DEBIAN_BUILD == true ]]; then sudo add-apt-repository -y ppa:team-xbmc/ppa; fi + - if [[ $DEBIAN_BUILD == true ]]; then sudo add-apt-repository -y ppa:team-xbmc/xbmc-nightly; fi - if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get update; fi - if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get install fakeroot; fi @@ -41,12 +41,12 @@ # before_script: - if [[ $DEBIAN_BUILD != true ]]; then cd $TRAVIS_BUILD_DIR/..; fi - - if [[ $DEBIAN_BUILD != true ]]; then git clone --branch Matrix --depth=1 https://github.com/xbmc/xbmc.git; fi + - if [[ $DEBIAN_BUILD != true ]]; then git clone --branch master --depth=1 https://github.com/xbmc/xbmc.git; fi - if [[ $DEBIAN_BUILD != true ]]; then cd ${app_id} && mkdir build && cd build; fi - if [[ $DEBIAN_BUILD != true ]]; then mkdir -p definition/${app_id}; fi - if [[ $DEBIAN_BUILD != true ]]; then echo ${app_id} $TRAVIS_BUILD_DIR $TRAVIS_COMMIT > definition/${app_id}/${app_id}.txt; fi - if [[ $DEBIAN_BUILD != true ]]; then cmake -DADDONS_TO_BUILD=${app_id} -DADDON_SRC_PREFIX=$TRAVIS_BUILD_DIR/.. -DADDONS_DEFINITION_DIR=$TRAVIS_BUILD_DIR/build/definition -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/../xbmc/addons -DPACKAGE_ZIP=1 $TRAVIS_BUILD_DIR/../xbmc/cmake/addons; fi - - if [[ $DEBIAN_BUILD == true ]]; then wget https://raw.githubusercontent.com/xbmc/xbmc/Matrix/xbmc/addons/kodi-dev-kit/tools/debian-addon-package-test.sh && chmod +x ./debian-addon-package-test.sh; fi + - if [[ $DEBIAN_BUILD == true ]]; then wget https://raw.githubusercontent.com/xbmc/xbmc/master/xbmc/addons/kodi-dev-kit/tools/debian-addon-package-test.sh && chmod +x ./debian-addon-package-test.sh; fi - if [[ $DEBIAN_BUILD == true ]]; then sudo apt-get build-dep $TRAVIS_BUILD_DIR; fi script: