[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#995823: bullseye-pu: package kodi/2:19.2+dfsg1-1~deb11u1 (pre-upload unblock bug)



Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian.org@packages.debian.org
Usertags: pu

Please unblock package kodi

[ Reason ]

This is a second point release of Kodi 19 "Matrix".

It consists of 69 commits, closing 40 upstream bugs.

Most notable bugs fixed include 8 PVR issues, that led to Kodi crashes
under certain circumstances, and 4 fixes for Kodi's default skin, Estuary.

Another must-have bugfix for users controlling their Kodi set-ups remotely
is the proper handling of partial websocket messages.

Debian packaging changes requested by users include the patch adding metainfo
file to /usr/share/metainfo, needed by GNOME 40 integration.

Apart from that, translations of i10n were updated to fix users' complaints. 
These changes produce a lot of changes in .po files, so I filtered the debdiff
as follows to get rid of noise not related to code:

filterdiff kodi_19.1+dfsg2-2_19.2+dfsg1-1.debdiff \
        -x "*/addons/*.xml" \
        -x "*/addons/*.po" \
        -x "*/cmake/scripts/windows/*" \
        -x "*/docs/*" \
        -x "*/Changelog" \
        -x "*/Makefile.in" \
        -x "*/*.m4" \
        -x "*/configure" \
        -x "*/msvc/*" \
        -x "*/media/*" \
        -x "*/system/*" \
        -x "*/tools/buildsteps/windows/*" \
        -x "*/xbmc/cores/VideoPlayer/VideoRenderers/windows/*" \
        -x "*/xbmc/windowing/win10/*" \
        -x "*/xbmc/windowing/windows/*" \
        1>kodi_19.1+dfsg2-2_19.2+dfsg1-1.filterdiff

[ Impact ]

Users receive fixes for problems reported upstream

[ Tests ]

Automated tests + manual testing by Kodi users

[ Risks ]

The struct release policy of upstream ensures no breaking
changes are allowed past BETA releases. Point releases
bring only bugfixes and security fixes, so risk is low.

Furthermore, I have become the official member of Team Kodi!
That should contribute in the mitigation of risks :)

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

[ Changes ]

Here is the outline of changes merged in 19.2:

https://github.com/xbmc/xbmc/pull/20224 ('Bump to 19.2. final'): 1 commit(s)
- "Bump to 19.2. final"
https://github.com/xbmc/xbmc/pull/20189 ('[CGUIDialogVolumeBar] Fix dialog not updating values if smartredraw i…'): 1 commit(s)
- "[CGUIDialogVolumeBar] Fix dialog not updating values if smartredraw is enabled"
https://github.com/xbmc/xbmc/pull/20185 ('[Backport] Sync game controllers for language updates'): 1 commit(s)
- "Sync game controllers for language updates"
https://github.com/xbmc/xbmc/pull/20178 ('[Matrix] PVR: fix "Delete permanently" of recordings from trash'): 1 commit(s)
- "PVR: fix "Delete permanently" of recordings from trash"
https://github.com/xbmc/xbmc/pull/20161 ('[Backport][linux] Use posix_memalign to implement AlignedMalloc'): 1 commit(s)
- "[linux] Use posix_memalign to implement AlignedMalloc"
https://github.com/xbmc/xbmc/pull/20140 ('[Backport] Websocket: handle partial messages'): 1 commit(s)
- "Websocket: handle partial messages"
https://github.com/xbmc/xbmc/pull/20119 ('[Matrix][PVR] Search missing channel icons job must be executed by PVR manage…'): 1 commit(s)
- "[PVR] Search missing channel icons job must be executed by PVR manager thread to avoid races in complex restart scenarios."
https://github.com/xbmc/xbmc/pull/20116 ('[Matrix][Estuary] PVR Guide window: Truncated channel names should scroll whe…'): 1 commit(s)
- "[Estuary] PVR Guide window: Truncated channel names should scroll when focused."
https://github.com/xbmc/xbmc/pull/20115 ('[Matrix][Estuary] PVR channel guide dialog changes.'): 1 commit(s)
- "[Estuary] PVR channel guide dialog changes."
https://github.com/xbmc/xbmc/pull/20114 ('[Matrix][Estuary] Default PVR radio channel icon should have transparent background'): 1 commit(s)
- "[Estuary] Default PVR radio channel icon should have transparent background."
https://github.com/xbmc/xbmc/pull/20092 ('[Matrix][PVR] Fix and simplify addon connection state change handling.'): 1 commit(s)
- "[PVR] Fix and simplify addon connection state change handling."
https://github.com/xbmc/xbmc/pull/20060 ('[addons] sync service.xbmc.versioncheck with repo'): 1 commit(s)
- "[addons] sync service.xbmc.versioncheck with repo"
https://github.com/xbmc/xbmc/pull/20053 ('[Music] Fix grouping discs by subtitle if first disc has one'): 1 commit(s)
- "[MUSIC] Ensure grouping discs by title if subtitles present"
https://github.com/xbmc/xbmc/pull/20051 ('[bp][addons] Update default and SNES controller addons'): 1 commit(s)
- "[addons] Update default and SNES controller addons"
https://github.com/xbmc/xbmc/pull/20047 ('[bp][addons] fix display logic for official/3rd party modules'): 3 commit(s)
- "[addons] fix display logic for official/3rd party modules"
- "[cleanup] remove advanced settings 'showalldependencies' (obsolete)"
- "[addons] move sort out of for-loop that fills the vector to be sorted"
https://github.com/xbmc/xbmc/pull/20037 ('change explanation string for cddb'): 1 commit(s)
- "change explanation string for cddb"
https://github.com/xbmc/xbmc/pull/20035 ('[BP][tools/depends/target][python3] enable multiprocessing module'): 1 commit(s)
- "[tools/depends/target][python3] enable multiprocessing module"
https://github.com/xbmc/xbmc/pull/20026 ('[Music][GUIInfo] Expose ListItem.DateAdded for music library content'): 1 commit(s)
- "[Music][GUIInfo] Expose ListItem.DateAdded for music library content"
https://github.com/xbmc/xbmc/pull/20004 ('[Matrix][PVR][JSON-RPC] Expose EPG tag's series number as 'seasonnum' property.'): 1 commit(s)
- "[PVR][JSON-RPC] Expose EPG tag's series number as 'seasonnum' property."
https://github.com/xbmc/xbmc/pull/19979 ('[Xbox] Fix SSL certs verification errors on Python add-ons'): 1 commit(s)
- "[Xbox] Fix SSL certs verification errors on Python add-ons"
https://github.com/xbmc/xbmc/pull/19976 ('[Matrix][PVR] Trigger play channel on startup also on wake from suspend, …'): 1 commit(s)
- "[PVR] Trigger play channel on startup also on wake from suspend, not only on Kodi application startup."
https://github.com/xbmc/xbmc/pull/19974 ('[FIX] Avoid calls to remote servers if saving streamdetails for dvd/b…'): 1 commit(s)
- "[FIX] Avoid calls to remote servers if saving streamdetails for dvd/bluray"
https://github.com/xbmc/xbmc/pull/19972 ('[Matrix][PVR][JSON-RPC] Expose EPG tag's icon path as 'thumbnail' property.'): 1 commit(s)
- "[PVR][JSON-RPC] Expose EPG tag's icon path as 'thumbnail' property."
https://github.com/xbmc/xbmc/pull/19945 ('[weblate] update README.md'): 1 commit(s)
- "Update README.md"
https://github.com/xbmc/xbmc/pull/19937 ('[Backport][Python] Add Python lzma module'): 2 commit(s)
- "[Python] Add lzma module"
- "[tools/depends][target] xz set dependency on gettext"
https://github.com/xbmc/xbmc/pull/19929 ('Workaround for #19883: Check if applied locale correctly lowers chars and fallback'): 2 commit(s)
- "Check if applied locale correctly lowers chars and fallback"
- "kodi.sh.in: Unset LC_{ALL,CTYPE}, LANG"
https://github.com/xbmc/xbmc/pull/19926 ('Bump openssl'): 2 commit(s)
- "[depends] bump openssl to 1.1.1k"
- "[depends] bump gnutls to 3.6.16"
https://github.com/xbmc/xbmc/pull/19920 ('[Xbox] DX fixes and improvements'): 1 commit(s)
- "[Xbox] DX fixes and improvements"
https://github.com/xbmc/xbmc/pull/19915 ('[Backport][PVR] Resolve "EPG Grid can get locked into a short timeframe during/after Clear Data operation"'): 1 commit(s)
- "[PVR] Resolve 'EPG Grid can get locked into a short timeframe during/after Clear Data operation'"
https://github.com/xbmc/xbmc/pull/19904 ('[utils] include fmt/xchar.h'): 1 commit(s)
- "[utils] include fmt/xchar.h"
https://github.com/xbmc/xbmc/pull/19894 ('[Android] Fix HDR static metadata - Matrix'): 1 commit(s)
- "[Android] Fix HDR static metadata"
https://github.com/xbmc/xbmc/pull/19891 ('[swig] fix illegal access warnings/errors with Java >= 9'): 1 commit(s)
- "[swig] fix illegal access warnings/errors with Java >= 9"
https://github.com/xbmc/xbmc/pull/19890 ('[FIX][JSONRPC] Respect boolean values when exporting video/audio via …'): 1 commit(s)
- "[FIX][JSONRPC] Respect boolean values when exporting video/audio via json"
https://github.com/xbmc/xbmc/pull/19884 ('[Backport][Addons][Filesystem] Resolve int <--> bool compiler warnings on MSVC'): 1 commit(s)
- "[Addons][Filesystem] Resolve int <--> bool compiler wanrings on MSVC"
https://github.com/xbmc/xbmc/pull/19880 ('[UWP] [Xbox] Removed non working HDR toggle code'): 1 commit(s)
- "[UWP] [Xbox] Removed non working HDR toggle code"
https://github.com/xbmc/xbmc/pull/19876 ('[depends] Update fffmpeg 4.3.2 to include correct satip patch'): 1 commit(s)
- "[depends] Update fffmpeg 4.3.2 to include correct satip patch"
https://github.com/xbmc/xbmc/pull/19871 ('[UWP] [Xbox] Fix curl CA certs bundle path to be usable'): 1 commit(s)
- "UWP curl https fix - CURLOPT_CAINFO required"
https://github.com/xbmc/xbmc/pull/19870 ('Fix of the lookup texture for Spline/Lanczos3'): 1 commit(s)
- "Fix of the lookup texture for Spline/Lanczos3"
https://github.com/xbmc/xbmc/pull/19868 ('[BP][Docs][Apple] Update apple platform build docs'): 1 commit(s)
- "[Docs][Apple] Update apple platform build docs"
https://github.com/xbmc/xbmc/pull/19857 ('[Backport] #19855 Fix segmentation fault when accessing invalid PVR channel from favourites'): 1 commit(s)
- "[Backport] Fix segmentation fault when accessing invalid PVR channel"
https://github.com/xbmc/xbmc/pull/19841 ('[Music][Backport]Fix MySQL problem with fetching artist discography'): 1 commit(s)
- "Fix MySQL problem with fetching artist discography"
https://github.com/xbmc/xbmc/pull/19830 ('[DXVA2] Fix: check if HDR10 RGB limited range is supported by video driver'): 1 commit(s)
- "[DXVA2] Fix: check if HDR10 RGB limited range is supported by video driver (don't assume it's always supported)"
https://github.com/xbmc/xbmc/pull/19806 ('[Matrix][Android] Storage Manager: Try fallback to obtain drives if running on Android 6 and older'): 1 commit(s)
- "[Android] Storage Manager: Try fallback to obtain drives if running on Android 6 and older (SDK API level < 24) or in case of error."
https://github.com/xbmc/xbmc/pull/19804 ('[Windows] Fix: possible crash if Windows HDR switch is toggled externally'): 2 commit(s)
- "[Windows] Implements DestroySwapChain method to avoid duplicated code"
- "[Windows] Fix: possible crash when Windows HDR is toggled (externally) while Kodi is running"
https://github.com/xbmc/xbmc/pull/19802 ('[Windows] Fix: crash if WS-Discovery receives partial or malformed list of properties from network devices'): 2 commit(s)
- "Silence C++ warnings"
- "[Windows] Fix: crash if WS-Discovery receives partial or malformed list of properties from network devices"
https://github.com/xbmc/xbmc/pull/19793 ('[Xbox] Fix: 4K resolutions infos reported as 1080p'): 1 commit(s)
- "[Xbox] Fix: 4K resolutions infos reported as 1080p"
https://github.com/xbmc/xbmc/pull/19792 ('[Estuary][Backport]Fix label 2 in list views'): 1 commit(s)
- "[Estuary] fix label 2 in list views"
https://github.com/xbmc/xbmc/pull/19783 ('[Windows] Fix crash when Kodi is moved to another monitor with different video adapter'): 1 commit(s)
- "[Windows] Fix crash when Kodi is moved to another monitor with different video adapter due to hardware changed"
https://github.com/xbmc/xbmc/pull/19781 ('[Xbox] Implements alternate method to get display refresh rate'): 1 commit(s)
- "[Xbox] Implements alternate method to get display refresh rate"
https://github.com/xbmc/xbmc/pull/19775 ('[Windows] DX swapchain improvements'): 1 commit(s)
- "[Windows] DX swapchain improvements"
https://github.com/xbmc/xbmc/pull/19774 ('Fix audio passthrough at display lost/reset events'): 1 commit(s)
- "Fix audio passthrough at display reset events"
https://github.com/xbmc/xbmc/pull/19773 ('[Windows] Fix: crash when the monitor is turned off and Kodi goes to another monitor'): 1 commit(s)
- "[Windows] Fix: crash when the monitor is turned off and Kodi goes to another monitor"
https://github.com/xbmc/xbmc/pull/19762 ('[Matrix] [video] don't overwrite unique IDs in CVideoDatabase::SetDetailsForFoo() (fixes #17444)'): 1 commit(s)
- "[video] don't overwrite unique IDs in CVideoDatabase::SetDetailsForFoo() (fixes #17444)"
https://github.com/xbmc/xbmc/pull/19746 ('[Matrix][PVR] CFileItem: Add fallbacks to channel icon and default images to …'): 1 commit(s)
- "[PVR] CFileItem: Add fallbacks to channel icon and default images to EPG, timer and recording items, like we already had for channels."
https://github.com/xbmc/xbmc/pull/19739 ('Backport: AudioTrack HD Passthrough Fixes'): 2 commit(s)
- "AESinkAudioTrack: Reduce the probe buffer size"
- "AESinkAudioTrack: Reduce periods and buffer for 8 channel HD-Audio formats"
https://github.com/xbmc/xbmc/pull/19737 ('[Matrix][PVR] Fix wrong 'all channels' label in radio guide search dialog.'): 1 commit(s)
- "[PVR] Fix wrong 'all channels' label in radio guide search dialog."
https://github.com/xbmc/xbmc/pull/19736 ('[Matrix][PVR] Fix wrong search window opened when executing 'Find similar' on a timer item.'): 1 commit(s)
- "[PVR] Fix wrong search window opened when executing 'Find similar' on a timer item."
https://github.com/xbmc/xbmc/pull/19723 ('[Backport][PVR][GUI] Hide context menu items not relevant to the associated client'): 1 commit(s)
- "[PVR][GUI] Hide context menu items not relevant to the associated client"
https://github.com/xbmc/xbmc/pull/19709 ('[GUI] Fix scroll gesture on wrap lists'): 1 commit(s)
- "[GUI] Fix scroll gesture on wrap lists"
https://github.com/xbmc/xbmc/pull/19705 ('[Estuary] Fix OSD Button Visibility'): 1 commit(s)
- "[Estuary] Fix OSD Button Visibility"
https://github.com/xbmc/xbmc/pull/19659 ('[UWP] [Xbox] Fix 4K HEVC crash due out of memory'): 1 commit(s)
- "[UWP] [Xbox] Fix 4K HEVC crash due out of memory"
-------
Total commit count = 69

[ Other info ]

unblock kodi/2:19.2+dfsg1-1~deb11u1
diff -Nru kodi-19.1+dfsg2/addons/service.xbmc.versioncheck/resources/lib/version_check/service.py kodi-19.2+dfsg1/addons/service.xbmc.versioncheck/resources/lib/version_check/service.py
--- kodi-19.1+dfsg2/addons/service.xbmc.versioncheck/resources/lib/version_check/service.py	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/addons/service.xbmc.versioncheck/resources/lib/version_check/service.py	2021-10-06 08:49:25.000000000 +0000
@@ -1,4 +1,3 @@
-#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 """
@@ -34,17 +33,21 @@
 from .json_interface import get_installed_version
 from .versions import compare_version
 
-if sys.version_info[0] == 3 and sys.version_info[1] >= 8:
-    try:
-        from .distro import distro
 
-        DISTRIBUTION = distro.linux_distribution(full_distribution_name=False)[0].lower()
+DISTRIBUTION = ''
 
-    except (AttributeError, ImportError):
-        DISTRIBUTION = ''
+if sys.platform.startswith('linux'):
+    if sys.version_info[0] == 3 and sys.version_info[1] >= 8:
+        try:
+            from .distro import distro
 
-else:
-    DISTRIBUTION = platform.linux_distribution(full_distribution_name=0)[0].lower()  # pylint: disable=deprecated-method
+            DISTRIBUTION = distro.linux_distribution(full_distribution_name=False)[0].lower()
+
+        except (AttributeError, ImportError):
+            DISTRIBUTION = ''
+
+    else:
+        DISTRIBUTION = platform.linux_distribution(full_distribution_name=0)[0].lower()  # pylint: disable=deprecated-method
 
 if not DISTRIBUTION:
     DISTRIBUTION = platform.uname()[0].lower()
diff -Nru kodi-19.1+dfsg2/addons/service.xbmc.versioncheck/resources/versions.txt kodi-19.2+dfsg1/addons/service.xbmc.versioncheck/resources/versions.txt
--- kodi-19.1+dfsg2/addons/service.xbmc.versioncheck/resources/versions.txt	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/addons/service.xbmc.versioncheck/resources/versions.txt	2021-10-06 08:49:25.000000000 +0000
@@ -3,6 +3,24 @@
     "releases": {
         "stable": [
             {
+                "major": "19",
+                "minor": "1",
+                "tag": "stable",
+                "tagversion":"",
+                "revision": "20210508-85e05228b4",
+                "extrainfo": "final",
+                "addon_support": "yes"
+            },
+            {
+                "major": "19",
+                "minor": "0",
+                "tag": "stable",
+                "tagversion":"",
+                "revision": "20210218-f44fdfbf67",
+                "extrainfo": "final",
+                "addon_support": "yes"
+            },
+            {
                 "major": "18",
                 "minor": "9",
                 "tag": "stable",
@@ -302,6 +320,15 @@
         ],
         "releasecandidate": [
             {
+                "major": "19",
+                "minor": "0",
+                "tag": "releasecandidate",
+                "tagversion":"1",
+                "revision": "20210115-90a1e12804",
+                "extrainfo": "RC1",
+                "addon_support": "yes"
+            },
+            {
                 "major": "18",
                 "minor": "0",
                 "tag": "releasecandidate",
@@ -529,6 +556,24 @@
         ],
         "beta": [
             {
+                "major": "19",
+                "minor": "0",
+                "tag": "beta",
+                "tagversion":"2",
+                "revision": "20201207-8cc9e80e41",
+                "extrainfo": "beta2",
+                "addon_support": "yes"
+            },
+            {
+                "major": "19",
+                "minor": "0",
+                "tag": "beta",
+                "tagversion":"1",
+                "revision": "20201117-88e186e4b4",
+                "extrainfo": "beta1",
+                "addon_support": "yes"
+            },
+            {
                 "major": "18",
                 "minor": "0",
                 "tag": "beta",
@@ -839,6 +884,15 @@
             {
                 "major": "19",
                 "minor": "0",
+                "tag": "alpha",
+                "tagversion":"3",
+                "revision": "20201031-bb0699db41",
+                "extrainfo": "alpha3",
+                "addon_support": "yes"
+            },
+            {
+                "major": "19",
+                "minor": "0",
                 "tag": "alpha",
                 "tagversion":"2",
                 "revision": "20201005-54be31bc5c",
diff -Nru kodi-19.1+dfsg2/cmake/modules/FindPython.cmake kodi-19.2+dfsg1/cmake/modules/FindPython.cmake
--- kodi-19.1+dfsg2/cmake/modules/FindPython.cmake	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/cmake/modules/FindPython.cmake	2021-10-06 08:49:25.000000000 +0000
@@ -21,6 +21,10 @@
 
   if(NOT CORE_SYSTEM_NAME STREQUAL android)
     set(PYTHON_DEP_LIBRARIES pthread dl util)
+    if(CORE_SYSTEM_NAME STREQUAL linux)
+      # python archive built via depends requires librt for _posixshmem library
+      list(APPEND PYTHON_DEP_LIBRARIES rt)
+    endif()
   endif()
 
   set(PYTHON_LIBRARIES ${PYTHON_LIBRARY} ${FFI_LIBRARY} ${EXPAT_LIBRARY} ${INTL_LIBRARY} ${GMP_LIBRARY} ${PYTHON_DEP_LIBRARIES})
diff -Nru kodi-19.1+dfsg2/debian/changelog kodi-19.2+dfsg1/debian/changelog
--- kodi-19.1+dfsg2/debian/changelog	2021-06-24 20:44:30.000000000 +0000
+++ kodi-19.2+dfsg1/debian/changelog	2021-10-06 10:59:56.000000000 +0000
@@ -1,3 +1,13 @@
+kodi (2:19.2+dfsg1-1) unstable; urgency=medium
+
+  * New upstream version 19.2+dfsg1
+  * Restrict watchfile to current Debian stable codename
+  * Bump standard version
+  * Refresh patches
+  * Install package metainfo
+
+ -- Vasyl Gello <vasek.gello@gmail.com>  Wed, 06 Oct 2021 10:59:56 +0000
+
 kodi (2:19.1+dfsg2-2) unstable; urgency=medium
 
   * Add runtime locale test and fallback (Closes: #989814)
diff -Nru kodi-19.1+dfsg2/debian/control kodi-19.2+dfsg1/debian/control
--- kodi-19.1+dfsg2/debian/control	2021-06-24 20:44:30.000000000 +0000
+++ kodi-19.2+dfsg1/debian/control	2021-10-06 10:59:56.000000000 +0000
@@ -104,7 +104,7 @@
                waylandpp-dev,
                zip,
                zlib1g-dev
-Standards-Version: 4.5.1
+Standards-Version: 4.6.0
 Rules-Requires-Root: no
 Vcs-Browser: https://salsa.debian.org/multimedia-team/kodi-media-center/kodi
 Vcs-Git: https://salsa.debian.org/multimedia-team/kodi-media-center/kodi.git
diff -Nru kodi-19.1+dfsg2/debian/kodi.install kodi-19.2+dfsg1/debian/kodi.install
--- kodi-19.1+dfsg2/debian/kodi.install	2021-06-24 20:44:30.000000000 +0000
+++ kodi-19.2+dfsg1/debian/kodi.install	2021-10-06 10:59:56.000000000 +0000
@@ -1,3 +1,4 @@
 usr/bin/kodi
 usr/bin/kodi-standalone
 usr/share/applications
+usr/share/metainfo
diff -Nru kodi-19.1+dfsg2/debian/patches/kodi/0005-use-system-groovy.patch kodi-19.2+dfsg1/debian/patches/kodi/0005-use-system-groovy.patch
--- kodi-19.1+dfsg2/debian/patches/kodi/0005-use-system-groovy.patch	2021-06-24 20:44:30.000000000 +0000
+++ kodi-19.2+dfsg1/debian/patches/kodi/0005-use-system-groovy.patch	2021-10-06 10:59:56.000000000 +0000
@@ -26,7 +26,7 @@
                       COMMAND ${SWIG_EXECUTABLE}
                       ARGS -w401 -c++ -o ${file}.xml -xml -I${CMAKE_SOURCE_DIR}/xbmc -xmllang python ${CMAKE_CURRENT_SOURCE_DIR}/../swig/${file}
 -                     COMMAND ${Java_JAVA_EXECUTABLE}
--                     ARGS -cp "${classpath}" groovy.ui.GroovyMain ${CMAKE_SOURCE_DIR}/tools/codegenerator/Generator.groovy ${file}.xml ${CMAKE_CURRENT_SOURCE_DIR}/../python/PythonSwig.cpp.template ${file}.cpp > ${devnull}
+-                     ARGS ${JAVA_OPEN_OPTS} -cp "${classpath}" groovy.ui.GroovyMain ${CMAKE_SOURCE_DIR}/tools/codegenerator/Generator.groovy ${file}.xml ${CMAKE_CURRENT_SOURCE_DIR}/../python/PythonSwig.cpp.template ${file}.cpp > ${devnull}
 +                     COMMAND groovy
 +                     ARGS -cp "${classpath}" ${CMAKE_SOURCE_DIR}/tools/codegenerator/Generator.groovy ${file}.xml ${CMAKE_CURRENT_SOURCE_DIR}/../python/PythonSwig.cpp.template ${file}.cpp > ${devnull}
                       ${CLANG_FORMAT_COMMAND}
diff -Nru kodi-19.1+dfsg2/debian/patches/kodi/0022-Add-metainfo.patch kodi-19.2+dfsg1/debian/patches/kodi/0022-Add-metainfo.patch
--- kodi-19.1+dfsg2/debian/patches/kodi/0022-Add-metainfo.patch	1970-01-01 00:00:00.000000000 +0000
+++ kodi-19.2+dfsg1/debian/patches/kodi/0022-Add-metainfo.patch	2021-10-06 10:59:56.000000000 +0000
@@ -0,0 +1,156 @@
+From 7398e5599f8c9c98eb4bac84384eed896c8b630d Mon Sep 17 00:00:00 2001
+From: Razze <razzeee@gmail.com>
+Date: Sun, 3 Oct 2021 21:49:44 +0200
+Subject: [PATCH] Add metainfo and install it
+
+This was based on the meta info from https://github.com/flathub/tv.kodi.Kodi/pull/115
+---
+ cmake/scripts/linux/Install.cmake |   9 +++
+ tools/Linux/kodi.metainfo.xml.in  | 108 ++++++++++++++++++++++++++++++
+ 2 files changed, 117 insertions(+)
+ create mode 100644 tools/Linux/kodi.metainfo.xml.in
+
+diff --git a/cmake/scripts/linux/Install.cmake b/cmake/scripts/linux/Install.cmake
+index acfd3ff564..43875d59b3 100644
+--- a/cmake/scripts/linux/Install.cmake
++++ b/cmake/scripts/linux/Install.cmake
+@@ -47,6 +47,10 @@ configure_file(${CMAKE_SOURCE_DIR}/tools/Linux/kodi-xsession.desktop.in
+ configure_file(${CMAKE_SOURCE_DIR}/tools/Linux/kodi.desktop.in
+                ${CORE_BUILD_DIR}/${APP_NAME_LC}.desktop @ONLY)
+ 
++# Configure metainfo
++configure_file(${CMAKE_SOURCE_DIR}/tools/Linux/kodi.metainfo.xml.in
++               ${CORE_BUILD_DIR}/${APP_NAME_LC}.metainfo.xml @ONLY)
++
+ # Install app
+ install(TARGETS ${APP_NAME_LC}
+         DESTINATION ${libdir}/${APP_NAME_LC}
+@@ -92,6 +96,11 @@ install(FILES ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/${APP_NAME_LC}.desktop
+         DESTINATION ${datarootdir}/applications
+         COMPONENT kodi)
+ 
++# Install metainfo
++install(FILES ${CMAKE_BINARY_DIR}/${CORE_BUILD_DIR}/${APP_NAME_LC}.metainfo.xml
++        DESTINATION ${datarootdir}/metainfo
++        COMPONENT kodi)
++
+ # Install icons
+ install(FILES ${CMAKE_SOURCE_DIR}/tools/Linux/packaging/media/icon16x16.png
+         RENAME ${APP_NAME_LC}.png
+diff --git a/tools/Linux/kodi.metainfo.xml.in b/tools/Linux/kodi.metainfo.xml.in
+new file mode 100644
+index 0000000000..ad273c3095
+--- /dev/null
++++ b/tools/Linux/kodi.metainfo.xml.in
+@@ -0,0 +1,108 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<component type="desktop-application">
++    <id>tv.kodi.Kodi</id>
++    <name>Kodi</name>
++    <project_license>GPL-2.0-only GPL-2.0-or-later LGPL-2.1-or-later MIT BSD-3-Clause BSD-4-Clause</project_license>
++    <metadata_license>CC0-1.0</metadata_license>
++    <developer_name>Team Kodi</developer_name>
++    <summary>The ultimate entertainment center</summary>
++    <url type="homepage">https://kodi.tv/</url>
++    <url type="donation">https://kodi.tv/contribute/donate</url>
++    <url type="bugtracker">https://github.com/xbmc/xbmc/issues</url>
++    <url type="faq">https://kodi.wiki/view/FAQs</url>
++    <url type="help">https://forum.kodi.tv/</url>
++    <url type="translate">https://kodi.weblate.cloud/</url>
++    <description>
++        <p>Kodi allows users to play and view videos, music, podcasts,
++        and other digital media files from local storage, network storage
++        and the internet. It's optimized for a 10-foot user interface to be
++        used with televisions and remote controls.</p>
++
++        <p>Kodi spawned from the love of media. It is an entertainment hub
++        that brings all your digital media together into a beautiful
++        and user friendly package. It is 100% free and open source,
++        very customisable and runs on a wide variety of devices. It is
++        supported by a dedicated team of volunteers and a huge community.</p>
++    </description>
++    <launchable type="desktop-id">tv.kodi.Kodi.desktop</launchable>
++    <screenshots>
++        <screenshot type="default">
++            <image>https://mirrors.kodi.tv/screenshots/kodi-recently-added.jpg</image>
++            <caption>The homescreen keeps your media organized</caption>
++        </screenshot>
++        <screenshot>
++            <image>https://mirrors.kodi.tv/screenshots/kodi-videolibrary.jpg</image>
++            <caption>Easily browse your movies and series</caption>
++        </screenshot>
++        <screenshot>
++            <image>https://mirrors.kodi.tv/screenshots/kodi-video-info.jpg</image>
++            <caption>Get additional infos about your movies or series</caption>
++        </screenshot>
++        <screenshot>
++            <image>https://mirrors.kodi.tv/screenshots/kodi-tvshow.jpg</image>
++            <caption>Browse TV shows by seasons</caption>
++        </screenshot>
++        <screenshot>
++            <image>https://mirrors.kodi.tv/screenshots/kodi-music-info.jpg</image>
++            <caption>Use the music library to organize and read about your artists</caption>
++        </screenshot>
++        <screenshot>
++            <image>https://mirrors.kodi.tv/screenshots/kodi-epg.jpg</image>
++            <caption>Use the EPG to manage your TV stations</caption>
++        </screenshot>
++        <screenshot>
++            <image>https://mirrors.kodi.tv/screenshots/kodi-addons.jpg</image>
++            <caption>Extend what Kodi can do, just use addons</caption>
++        </screenshot>
++        <screenshot>
++            <image>https://mirrors.kodi.tv/screenshots/kodi-weather.jpg</image>
++            <caption>Keep the weather in check</caption>
++        </screenshot>
++        <screenshot>
++            <image>https://mirrors.kodi.tv/screenshots/kodi-webinterface.jpg</image>
++            <caption>The webinterface enables you to manage your Kodi from other devices</caption>
++        </screenshot>
++    </screenshots>
++    <releases>
++        <release date="2021-05-09" version="19.1-Matrix"/>
++        <release date="2021-02-19" version="19.0-Matrix"/>
++        <release date="2020-10-24" version="18.9-Leia"/>
++        <release date="2020-07-28" version="18.8-Leia"/>
++        <release date="2020-05-21" version="18.7-Leia"/>
++        <release date="2020-02-29" version="18.6-Leia"/>
++        <release date="2019-11-18" version="18.5-Leia"/>
++        <release date="2019-08-31" version="18.4-Leia"/>
++        <release date="2019-06-27" version="18.3-Leia"/>
++        <release date="2019-04-22" version="18.2-Leia"/>
++        <release date="2019-02-17" version="18.1-Leia"/>
++    </releases>
++    <content_rating type="oars-1.0">
++        <content_attribute id="violence-cartoon">none</content_attribute>
++        <content_attribute id="violence-fantasy">none</content_attribute>
++        <content_attribute id="violence-realistic">none</content_attribute>
++        <content_attribute id="violence-bloodshed">none</content_attribute>
++        <content_attribute id="violence-sexual">none</content_attribute>
++        <content_attribute id="drugs-alcohol">none</content_attribute>
++        <content_attribute id="drugs-narcotics">none</content_attribute>
++        <content_attribute id="drugs-tobacco">none</content_attribute>
++        <content_attribute id="sex-nudity">none</content_attribute>
++        <content_attribute id="sex-themes">none</content_attribute>
++        <content_attribute id="language-profanity">none</content_attribute>
++        <content_attribute id="language-humor">none</content_attribute>
++        <content_attribute id="language-discrimination">none</content_attribute>
++        <content_attribute id="social-chat">none</content_attribute>
++        <content_attribute id="social-info">none</content_attribute>
++        <content_attribute id="social-audio">none</content_attribute>
++        <content_attribute id="social-location">none</content_attribute>
++        <content_attribute id="social-contacts">none</content_attribute>
++        <content_attribute id="money-purchasing">none</content_attribute>
++        <content_attribute id="money-gambling">none</content_attribute>
++    </content_rating>
++    <recommends>
++        <control>keyboard</control>
++        <control>pointing</control>
++        <control>touch</control>
++        <control>tv-remote</control>
++        <control>gamepad</control>
++    </recommends>
++</component>
+-- 
+2.33.0
+
diff -Nru kodi-19.1+dfsg2/debian/patches/kodi/0022-Workaround-989814.patch kodi-19.2+dfsg1/debian/patches/kodi/0022-Workaround-989814.patch
--- kodi-19.1+dfsg2/debian/patches/kodi/0022-Workaround-989814.patch	2021-06-24 20:44:30.000000000 +0000
+++ kodi-19.2+dfsg1/debian/patches/kodi/0022-Workaround-989814.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,67 +0,0 @@
-From 8b8e97dbec5c6268d1b81eb7799cfc945ca9520e Mon Sep 17 00:00:00 2001
-From: Vasyl Gello <vasek.gello@gmail.com>
-Date: Fri, 25 Jun 2021 01:37:02 +0000
-Subject: [PATCH 1/2] Check if applied locale correctly lowers chars and
- fallback
-
-.. to default region if it does not.
-
-Fixes #19883.
-
-Signed-off-by: Vasyl Gello <vasek.gello@gmail.com>
----
- xbmc/LangInfo.cpp | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/xbmc/LangInfo.cpp b/xbmc/LangInfo.cpp
-index 24f0419cfe..ace72e1ffe 100644
---- a/xbmc/LangInfo.cpp
-+++ b/xbmc/LangInfo.cpp
-@@ -981,6 +981,16 @@ void CLangInfo::SetCurrentRegion(const std::string& strName)
- 
-   m_currentRegion->SetGlobalLocale();
- 
-+  // Check if locale is not affected by #19883
-+  int test19883 = std::tolower('i') - std::tolower('I');
-+  if (test19883 != 0)
-+  {
-+    CLog::Log(LOGWARNING, "region '{}' is affected by #19883 - falling back to default region '{}'",
-+              m_currentRegion->m_strName, m_defaultRegion.m_strName);
-+    m_currentRegion = &m_defaultRegion;
-+    m_currentRegion->SetGlobalLocale();
-+  }
-+
-   const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
-   if (settings->GetString(CSettings::SETTING_LOCALE_SHORTDATEFORMAT) == SETTING_REGIONAL_DEFAULT)
-     SetShortDateFormat(m_currentRegion->m_strDateFormatShort);
--- 
-2.32.0.rc0
-
-
-From 114ee13138389c96a759d6e5b73717093dd4030d Mon Sep 17 00:00:00 2001
-From: Vasyl Gello <vasek.gello@gmail.com>
-Date: Sun, 27 Jun 2021 19:31:39 +0000
-Subject: [PATCH 2/2] kodi.sh.in: Unset LC_{ALL,CTYPE}, LANG
-
-Signed-off-by: Vasyl Gello <vasek.gello@gmail.com>
----
- tools/Linux/kodi.sh.in | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/tools/Linux/kodi.sh.in b/tools/Linux/kodi.sh.in
-index 108c0b007b..29d17d2c0f 100644
---- a/tools/Linux/kodi.sh.in
-+++ b/tools/Linux/kodi.sh.in
-@@ -171,6 +171,9 @@ if command_exists gdb; then
-   fi
- fi
- 
-+# Unset CTYPE, LANG and ALL - see issue #19883
-+unset LC_CTYPE LC_ALL LANG
-+
- LOOP=1
- while [ $(( $LOOP )) = "1" ]
- do
--- 
-2.32.0.rc0
-
diff -Nru kodi-19.1+dfsg2/debian/patches/series kodi-19.2+dfsg1/debian/patches/series
--- kodi-19.1+dfsg2/debian/patches/series	2021-06-24 20:44:30.000000000 +0000
+++ kodi-19.2+dfsg1/debian/patches/series	2021-10-06 10:59:56.000000000 +0000
@@ -19,7 +19,7 @@
 kodi/0019-Disable-GetCPUFrequency-test.patch
 kodi/0020-Fix-C++-example-includes.patch
 kodi/0021-Detect-and-honor-big-endian-arch.patch
-kodi/0022-Workaround-989814.patch
+kodi/0022-Add-metainfo.patch
 libdvdnav/0001-xbmc-dvdnav-allow-get-set-vm-state.patch
 libdvdnav/0002-xbmc-dvdnav-expose-dvdnav_get_vm-dvdnav_get_button_i.patch
 libdvdnav/0003-xbmc-dvdnav-detection-of-dvd-name.patch
diff -Nru kodi-19.1+dfsg2/debian/watch kodi-19.2+dfsg1/debian/watch
--- kodi-19.1+dfsg2/debian/watch	2021-06-24 20:44:30.000000000 +0000
+++ kodi-19.2+dfsg1/debian/watch	2021-10-06 10:59:56.000000000 +0000
@@ -23,13 +23,14 @@
 #HEAD debian
 
 # Tagged releases
+# TODO: Change Kodi codename in tarball URL before packaging next Kodi major release
 #
 opts="repack, \
       compression=xz, \
       repacksuffix=+dfsg1,\
       uversionmangle=s/\([\.0-9a-zA-Z]\)-.*$/\1/;s/rc/~rc/;s/a/~alpha/;s/b/~beta/;s/RC/~rc/;s/A/~alpha/;s/B/~beta/, \
       dversionmangle=auto" \
-https://github.com/xbmc/xbmc/releases .*archive/refs/tags/?(\d\S*)-[A-Z].*\.tar\.gz
+https://github.com/xbmc/xbmc/releases .*archive/refs/tags/?(\d\S*)-Matrix\.tar\.gz
 
 # date
 
Binary files /tmp/McgmkW7nZ0/kodi-19.1+dfsg2/media/splash.jpg and /tmp/ZAWCey_cOj/kodi-19.2+dfsg1/media/splash.jpg differ
diff -Nru kodi-19.1+dfsg2/README.md kodi-19.2+dfsg1/README.md
--- kodi-19.1+dfsg2/README.md	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/README.md	2021-10-06 08:49:25.000000000 +0000
@@ -53,7 +53,7 @@
 
 * **Coding:** Developers can help Kodi by **[fixing a bug](https://github.com/xbmc/xbmc/issues)**, adding new features, making our technology smaller and faster and making development easier for others. Kodi's codebase consists mainly of C++ with small parts written in a variety of coding languages. Our add-ons mainly consist of python and XML. For more information, please have a look at our **[contributing guide](docs/CONTRIBUTING.md)**.
 * **Helping users:** Our support process relies on enthusiastic contributors like you to help others get the most out of Kodi. The #1 priority is always answering questions in our **[support forums](https://forum.kodi.tv/)**. Everyday new people discover Kodi, and everyday they are virtually guaranteed to have questions.
-* **Localization:** Translate **[Kodi](https://www.transifex.com/teamxbmc/kodi-main/)**, **[add-ons](https://www.transifex.com/teamxbmc/xbmc-addons/)** and **[skins](https://www.transifex.com/teamxbmc/xbmc-skins/)** into your native language.
+* **Localization:** Translate **[Kodi](https://kodi.weblate.cloud/projects/kodi-core/kodi-main/)**, **[add-ons, skins etc.](https://kodi.weblate.cloud/)** into your native language.
 * **Add-ons:** **[Add-ons](https://kodi.tv/addons)** are what make Kodi the most extensible and customizable entertainment hub available. **[Get started building an add-on](https://kodi.tv/create-an-addon)**.
 * **Documentation:** Kodi's **[wiki pages](https://kodi.wiki/)** are the hub for information about Kodi and surrounding ecosystem. Help make our documentation better by writing new content or correcting existing material.
 
diff -Nru kodi-19.1+dfsg2/tools/Linux/kodi.sh.in kodi-19.2+dfsg1/tools/Linux/kodi.sh.in
--- kodi-19.1+dfsg2/tools/Linux/kodi.sh.in	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/tools/Linux/kodi.sh.in	2021-10-06 08:49:25.000000000 +0000
@@ -171,6 +171,11 @@
   fi
 fi
 
+
+# Check if locale is affected by "Turkish I"
+# See https://github.com/xbmc/xbmc/issues/19883 for details
+unset LC_CTYPE LC_ALL LANG
+
 LOOP=1
 while [ $(( $LOOP )) = "1" ]
 do
diff -Nru kodi-19.1+dfsg2/version.txt kodi-19.2+dfsg1/version.txt
--- kodi-19.1+dfsg2/version.txt	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/version.txt	2021-10-06 08:49:25.000000000 +0000
@@ -3,9 +3,9 @@
 COPYRIGHT_YEARS 2005-2021
 WEBSITE http://kodi.tv
 VERSION_MAJOR 19
-VERSION_MINOR 1
+VERSION_MINOR 2
 VERSION_TAG
-VERSION_CODE 19.1.0
+VERSION_CODE 19.2.0
 ADDON_API 19.1.0
 ADDON_REPOS repository.xbmc.org|https://mirrors.kodi.tv
 APP_PACKAGE org.xbmc.kodi
diff -Nru kodi-19.1+dfsg2/xbmc/addons/gui/GUIDialogAddonInfo.cpp kodi-19.2+dfsg1/xbmc/addons/gui/GUIDialogAddonInfo.cpp
--- kodi-19.1+dfsg2/xbmc/addons/gui/GUIDialogAddonInfo.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/addons/gui/GUIDialogAddonInfo.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -15,6 +15,7 @@
 #include "addons/AddonDatabase.h"
 #include "addons/AddonInstaller.h"
 #include "addons/AddonManager.h"
+#include "addons/AddonRepos.h"
 #include "addons/AddonSystemSettings.h"
 #include "addons/IAddon.h"
 #include "addons/gui/GUIDialogAddonSettings.h"
@@ -646,15 +647,20 @@
             }
           }
 
-          item->SetLabel2(StringUtils::Format(
-              g_localizeStrings.Get(messageId).c_str(), it.m_depInfo.versionMin.asString().c_str(),
-              it.m_installed ? it.m_installed->Version().asString().c_str() : "",
-              it.m_available ? it.m_available->Version().asString().c_str() : "",
-              it.m_depInfo.optional ? g_localizeStrings.Get(24184).c_str() : ""));
-
-          item->SetArt("icon", infoAddon->Icon());
-          item->SetProperty("addon_id", it.m_depInfo.id);
-          items.Add(item);
+          if (entryPoint == EntryPoint::SHOW_DEPENDENCIES ||
+              infoAddon->MainType() != ADDON_SCRIPT_MODULE ||
+              !CAddonRepos::IsFromOfficialRepo(infoAddon, CheckAddonPath::NO))
+          {
+            item->SetLabel2(StringUtils::Format(
+                g_localizeStrings.Get(messageId), it.m_depInfo.versionMin.asString(),
+                it.m_installed ? it.m_installed->Version().asString() : "",
+                it.m_available ? it.m_available->Version().asString() : "",
+                it.m_depInfo.optional ? g_localizeStrings.Get(24184) : ""));
+
+            item->SetArt("icon", infoAddon->Icon());
+            item->SetProperty("addon_id", it.m_depInfo.id);
+            items.Add(item);
+          }
         }
       }
       else
@@ -746,9 +752,6 @@
   m_deps = CServiceBroker::GetAddonMgr().GetDepsRecursive(m_item->GetAddonInfo()->ID(),
                                                           OnlyEnabledRootAddon::NO);
 
-  const bool showAllDependencies =
-      CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_showAllDependencies;
-
   for (const auto& dep : m_deps)
   {
     std::shared_ptr<IAddon> addonInstalled;
@@ -769,33 +772,43 @@
 
     if (!addonInstalled)
     {
-      // after pushing the install button the dependency install dialog will
-      // pop up only if non-module dependencies are going to be installed or
-      // dependencies are unavailable. the latter is for informational purposes
 
-      if (showAllDependencies || !addonAvailable ||
-          addonAvailable->MainType() != ADDON_SCRIPT_MODULE)
+      // after pushing the install button the dependency install dialog
+      // will be opened only if...
+      // - dependencies are unavailable (for informational purposes) OR
+      // - the dependency is not a script/module                     OR
+      // - the script/module is not available at an official repo
+      if (!addonAvailable || addonAvailable->MainType() != ADDON_SCRIPT_MODULE ||
+          !CAddonRepos::IsFromOfficialRepo(addonAvailable, CheckAddonPath::NO))
       {
         m_showDepDialogOnInstall = true;
       }
     }
-
-    // AddonType ADDON_SCRIPT_MODULE needs to be filtered as these low-level add-ons
-    // should be hidden to the user in the dependency select dialog
-
-    if (showAllDependencies ||
-        (addonInstalled && addonInstalled->MainType() != ADDON_SCRIPT_MODULE) ||
-        (addonAvailable && addonAvailable->MainType() != ADDON_SCRIPT_MODULE) ||
-        (!addonAvailable && !addonInstalled))
+    else
     {
-      m_depsInstalledWithAvailable.emplace_back(
-          CInstalledWithAvailable{dep, addonInstalled, addonAvailable});
-    }
 
-    // sort optional add-ons to top of the list
+      // only display dialog if updates for already installed dependencies will install
+      if (addonAvailable && addonAvailable->Version() > addonInstalled->Version())
+      {
+        m_showDepDialogOnInstall = true;
+      }
+    }
 
-    std::sort(
-        m_depsInstalledWithAvailable.begin(), m_depsInstalledWithAvailable.end(),
-        [](const auto& a, const auto& b) { return a.m_depInfo.optional > b.m_depInfo.optional; });
+    m_depsInstalledWithAvailable.emplace_back(
+        CInstalledWithAvailable{dep, addonInstalled, addonAvailable});
   }
+
+  // sort criteria in dialog:
+  // 1. optional add-ons to top
+  // 2. scripts/modules to bottom
+  std::sort(m_depsInstalledWithAvailable.begin(), m_depsInstalledWithAvailable.end(),
+            [](const auto& a, const auto& b) {
+              if (a.m_depInfo.optional != b.m_depInfo.optional)
+              {
+                return a.m_depInfo.optional;
+              }
+
+              const std::shared_ptr<IAddon>& depA = a.m_installed ? a.m_installed : a.m_available;
+              return (depA && depA->MainType() != ADDON_SCRIPT_MODULE);
+            });
 }
diff -Nru kodi-19.1+dfsg2/xbmc/addons/interfaces/Filesystem.cpp kodi-19.2+dfsg1/xbmc/addons/interfaces/Filesystem.cpp
--- kodi-19.1+dfsg2/xbmc/addons/interfaces/Filesystem.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/addons/interfaces/Filesystem.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -999,7 +999,7 @@
   {
     CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}')", __FUNCTION__,
               kodiBase, file);
-    return -1;
+    return false;
   }
 
   return static_cast<CFile*>(file)->IoControl(EIoControl::IOCTRL_SEEK_POSSIBLE, nullptr) != 0
@@ -1016,7 +1016,7 @@
   {
     CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}, status='{}')",
               __FUNCTION__, kodiBase, file, static_cast<const void*>(status));
-    return -1;
+    return false;
   }
 
   SCacheStatus data = {0};
@@ -1039,7 +1039,7 @@
   {
     CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}')", __FUNCTION__,
               kodiBase, file);
-    return -1;
+    return false;
   }
 
   return static_cast<CFile*>(file)->IoControl(EIoControl::IOCTRL_CACHE_SETRATE, &rate) >= 0 ? true
@@ -1053,7 +1053,7 @@
   {
     CLog::Log(LOGERROR, "Interface_VFS::{} - invalid data (addon='{}', file='{}')", __FUNCTION__,
               kodiBase, file);
-    return -1;
+    return false;
   }
 
   return static_cast<CFile*>(file)->IoControl(EIoControl::IOCTRL_SET_RETRY, &retry) >= 0 ? true
diff -Nru kodi-19.1+dfsg2/xbmc/Application.cpp kodi-19.2+dfsg1/xbmc/Application.cpp
--- kodi-19.1+dfsg2/xbmc/Application.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/Application.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -3182,12 +3182,9 @@
   // check if VideoPlayer should set file item stream details from its current streams
   if (file.GetProperty("get_stream_details_from_player").asBoolean()
       || ((!file.HasVideoInfoTag() || !file.GetVideoInfoTag()->HasStreamDetails())
-      && (file.IsDiscImage()
+      && (URIUtils::IsBluray(file.GetPath())
       || file.IsDVDFile()
-      || file.IsBDFile()
-      || file.IsBluray()
-      || file.IsDVD()
-      || file.IsOnDVD())))
+      || file.IsDiscImage())))
     m_appPlayer.SetUpdateStreamDetails();
 
   if (m_stackHelper.IsPlayingISOStack() || m_stackHelper.IsPlayingRegularStack())
diff -Nru kodi-19.1+dfsg2/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp kodi-19.2+dfsg1/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp
--- kodi-19.1+dfsg2/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -267,7 +267,7 @@
 
   // make sure to have enough buffer as minimum might not be enough to open
   if (!isRaw)
-    minBufferSize *= 4;
+    minBufferSize *= 2;
 
   if (supported)
   {
@@ -490,17 +490,31 @@
     {
       m_format.m_frameSize = m_format.m_channelLayout.Count() * (CAEUtil::DataFormatToBits(m_format.m_dataFormat) / 8);
       m_sink_frameSize = m_format.m_frameSize;
-      // aim at 200 ms buffer and 50 ms periods
-      m_audiotrackbuffer_sec =
-          static_cast<double>(m_min_buffer_size) / (m_sink_frameSize * m_sink_sampleRate);
-      while (m_audiotrackbuffer_sec < 0.15)
+      bool isHDiec = ((m_format.m_streamInfo.m_type == CAEStreamInfo::STREAM_TYPE_TRUEHD) ||
+                      (m_format.m_streamInfo.m_type == CAEStreamInfo::STREAM_TYPE_DTSHD_MA));
+      if (m_passthrough && isHDiec)
       {
-        m_min_buffer_size += min_buffer;
+        // Certain boxes have issues opening DTS-HD / TrueHD with this large amount of data
+        // adjust accordingly
+        m_min_buffer_size *= 2;
+        m_format.m_frames = static_cast<int>(m_min_buffer_size / m_format.m_frameSize) / 2;
         m_audiotrackbuffer_sec =
             static_cast<double>(m_min_buffer_size) / (m_sink_frameSize * m_sink_sampleRate);
       }
-      // division by 4 -> 4 periods into one buffer
-      m_format.m_frames = static_cast<int>(m_min_buffer_size / m_format.m_frameSize) / 4;
+      else
+      {
+        // aim at 200 ms buffer and 50 ms periods
+        m_audiotrackbuffer_sec =
+            static_cast<double>(m_min_buffer_size) / (m_sink_frameSize * m_sink_sampleRate);
+        while (m_audiotrackbuffer_sec < 0.15)
+        {
+          m_min_buffer_size += min_buffer;
+          m_audiotrackbuffer_sec =
+              static_cast<double>(m_min_buffer_size) / (m_sink_frameSize * m_sink_sampleRate);
+        }
+        // division by 4 -> 4 periods into one buffer
+        m_format.m_frames = static_cast<int>(m_min_buffer_size / m_format.m_frameSize) / 4;
+      }
     }
 
     if (m_passthrough && !m_info.m_wantsIECPassthrough)
diff -Nru kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp
--- kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -1237,24 +1237,39 @@
 std::vector<uint8_t> CDVDVideoCodecAndroidMediaCodec::GetHDRStaticMetadata()
 {
   std::vector<uint8_t> metadata;
-  if (m_hints.masteringMetadata && m_hints.contentLightMetadata)
+  if (m_hints.masteringMetadata)
   {
-    static const double MAX_CHROMATICITY = 5000;
+    // for more information, see CTA+861.3-A standard document
+    static const double MAX_CHROMATICITY = 50000;
+    static const double MAX_LUMINANCE = 10000;
     metadata.resize(25);
     metadata[0] = 0;
-    short* data = reinterpret_cast<short*>(&metadata[1]);
-    data[0] = static_cast<short>(av_q2d(m_hints.masteringMetadata->display_primaries[0][0]) * MAX_CHROMATICITY + 0.5);
-    data[1] = static_cast<short>(av_q2d(m_hints.masteringMetadata->display_primaries[1][1]) * MAX_CHROMATICITY + 0.5);
-    data[2] = static_cast<short>(av_q2d(m_hints.masteringMetadata->display_primaries[1][0]) * MAX_CHROMATICITY + 0.5);
-    data[3] = static_cast<short>(av_q2d(m_hints.masteringMetadata->display_primaries[2][1]) * MAX_CHROMATICITY + 0.5);
-    data[4] = static_cast<short>(av_q2d(m_hints.masteringMetadata->display_primaries[2][0]) * MAX_CHROMATICITY + 0.5);
-    data[5] = static_cast<short>(av_q2d(m_hints.masteringMetadata->display_primaries[0][1]) * MAX_CHROMATICITY + 0.5);
-    data[6] = static_cast<short>(av_q2d(m_hints.masteringMetadata->white_point[0]) * MAX_CHROMATICITY + 0.5);
-    data[7] = static_cast<short>(av_q2d(m_hints.masteringMetadata->white_point[1]) * MAX_CHROMATICITY + 0.5);
-    data[8] = static_cast<short>(av_q2d(m_hints.masteringMetadata->max_luminance) + 0.5);
-    data[9] = static_cast<short>(av_q2d(m_hints.masteringMetadata->min_luminance) + 0.5);
-    data[10] = static_cast<short>(m_hints.contentLightMetadata->MaxCLL);
-    data[11] = static_cast<short>(m_hints.contentLightMetadata->MaxFALL);
+    unsigned short* data = reinterpret_cast<unsigned short*>(&metadata[1]);
+    data[0] = static_cast<unsigned short>(
+        av_q2d(m_hints.masteringMetadata->display_primaries[0][0]) * MAX_CHROMATICITY + 0.5);
+    data[1] = static_cast<unsigned short>(
+        av_q2d(m_hints.masteringMetadata->display_primaries[0][1]) * MAX_CHROMATICITY + 0.5);
+    data[2] = static_cast<unsigned short>(
+        av_q2d(m_hints.masteringMetadata->display_primaries[1][0]) * MAX_CHROMATICITY + 0.5);
+    data[3] = static_cast<unsigned short>(
+        av_q2d(m_hints.masteringMetadata->display_primaries[1][1]) * MAX_CHROMATICITY + 0.5);
+    data[4] = static_cast<unsigned short>(
+        av_q2d(m_hints.masteringMetadata->display_primaries[2][0]) * MAX_CHROMATICITY + 0.5);
+    data[5] = static_cast<unsigned short>(
+        av_q2d(m_hints.masteringMetadata->display_primaries[2][1]) * MAX_CHROMATICITY + 0.5);
+    data[6] = static_cast<unsigned short>(
+        av_q2d(m_hints.masteringMetadata->white_point[0]) * MAX_CHROMATICITY + 0.5);
+    data[7] = static_cast<unsigned short>(
+        av_q2d(m_hints.masteringMetadata->white_point[1]) * MAX_CHROMATICITY + 0.5);
+    data[8] = static_cast<unsigned short>(av_q2d(m_hints.masteringMetadata->max_luminance) + 0.5);
+    data[9] = static_cast<unsigned short>(
+        av_q2d(m_hints.masteringMetadata->min_luminance) * MAX_LUMINANCE + 0.5);
+    // we can have HDR content that does not provide content light level metadata
+    if (m_hints.contentLightMetadata)
+    {
+      data[10] = static_cast<unsigned short>(m_hints.contentLightMetadata->MaxCLL);
+      data[11] = static_cast<unsigned short>(m_hints.contentLightMetadata->MaxFALL);
+    }
   }
   return metadata;
 }
diff -Nru kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp
--- kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -1078,24 +1078,6 @@
       && avctx->color_trc == AVCOL_TRC_GAMMA28;
 }
 
-// UHD HEVC Main10 causes crash on Xbox One S/X
-static bool HasXbox4kHevcMain10Bug(AVCodecContext* avctx)
-{
-  if (CSysInfo::GetWindowsDeviceFamily() != CSysInfo::Xbox)
-    return false;
-
-  if (avctx->codec_id != AV_CODEC_ID_HEVC)
-    return false;
-
-  if (avctx->profile != FF_PROFILE_HEVC_MAIN_10)
-    return false;
-
-  if (avctx->height <= 1080 || avctx->width <= 1920)
-    return false;
-
-  return true;
-}
-
 static bool CheckCompatibility(AVCodecContext* avctx)
 {
   if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO && HasATIMP2Bug(avctx))
@@ -1195,16 +1177,12 @@
   case AV_CODEC_ID_HEVC:
     /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure
        all coding features have enough room to work with */
+    m_surface_alignment = 128;
+    // a driver may use multi-thread decoding internally (PC only)
     if (CSysInfo::GetWindowsDeviceFamily() != CSysInfo::Xbox)
-    {
-      m_surface_alignment = 128;
-      // a driver may use multi-thread decoding internally
       m_refs += CServiceBroker::GetCPUInfo()->GetCPUCount();
-    }
-
     // by specification hevc decoder can hold up to 8 unique refs
-    /* For some reason avctx->refs returns always 1 ref frame (tested
-       with well known 3 refs frames encodes) */
+    // ffmpeg may report only 1 refs frame when is unknown or not present in headers
     m_refs += (avctx->refs > 1) ? avctx->refs : 8;
     break;
   case AV_CODEC_ID_H264:
@@ -1238,14 +1216,6 @@
     m_refs = 16;
   }
 
-  /* On the Xbox 1/S with limited memory we have to
-     limit refs to avoid crashing device completely */
-  if (HasXbox4kHevcMain10Bug(avctx) && m_refs > 16)
-  {
-    CLog::LogFunction(LOGWARNING, "DXVA", "source requires to much refs which is not supported on Xbox One S/X. dxva will not be used.");
-    return false;
-  }
-
   if (!OpenDecoder())
   {
     m_bufferPool.reset();
diff -Nru kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/DVDMessage.h kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/DVDMessage.h
--- kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/DVDMessage.h	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/DVDMessage.h	2021-10-06 08:49:25.000000000 +0000
@@ -21,6 +21,7 @@
 class CDVDMsg : public IDVDResourceCounted<CDVDMsg>
 {
 public:
+  // clang-format off
   enum Message
   {
     NONE = 1000,
@@ -53,6 +54,7 @@
     PLAYER_ABORT,
     PLAYER_REPORT_STATE,
     PLAYER_FRAME_ADVANCE,
+    PLAYER_DISPLAY_RESET,           // report display reset event
 
     // demuxer related messages
     DEMUXER_PACKET,                 // data packet
@@ -66,6 +68,7 @@
     SUBTITLE_CLUTCHANGE,
     SUBTITLE_ADDFILE
   };
+  // clang-format on
 
   explicit CDVDMsg(Message msg)
   {
diff -Nru kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp
--- kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/VideoPlayerAudio.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -413,8 +413,11 @@
       {
         onlyPrioMsgs = true;
       }
-
-    } // demuxer packet
+    }
+    else if (pMsg->IsType(CDVDMsg::PLAYER_DISPLAY_RESET))
+    {
+      m_displayReset = true;
+    }
 
     pMsg->Release();
   }
@@ -469,6 +472,17 @@
       }
     }
 
+    // Display reset event has occurred
+    // See if we should enable passthrough
+    if (m_displayReset)
+    {
+      if (SwitchCodecIfNeeded())
+      {
+        audioframe.nb_frames = 0;
+        return false;
+      }
+    }
+
     // demuxer reads metatags that influence channel layout
     if (m_streaminfo.codec == AV_CODEC_ID_FLAC && m_streaminfo.channellayout)
       audioframe.format.m_channelLayout = CAEUtil::GetAEChannelLayout(m_streaminfo.channellayout);
@@ -605,7 +619,13 @@
 
 bool CVideoPlayerAudio::SwitchCodecIfNeeded()
 {
-  CLog::Log(LOGDEBUG, "CVideoPlayerAudio: stream props changed, checking for passthrough");
+  if (m_displayReset)
+    CLog::Log(LOGINFO, "CVideoPlayerAudio: display reset occurred, checking for passthrough");
+  else
+    CLog::Log(LOGDEBUG, "CVideoPlayerAudio: stream props changed, checking for passthrough");
+
+  m_displayReset = false;
+
   bool allowpassthrough = !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_VIDEOPLAYER_USEDISPLAYASCLOCK);
   if (m_processInfo.IsRealtimeStream() || m_synctype == SYNC_RESAMPLE)
     allowpassthrough = false;
diff -Nru kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/VideoPlayerAudio.h kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/VideoPlayerAudio.h
--- kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/VideoPlayerAudio.h	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/VideoPlayerAudio.h	2021-10-06 08:49:25.000000000 +0000
@@ -104,5 +104,7 @@
 
   mutable CCriticalSection m_info_section;
   SInfo            m_info;
+
+  bool m_displayReset = false;
 };
 
diff -Nru kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/VideoPlayer.cpp kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/VideoPlayer.cpp
--- kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/VideoPlayer.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/VideoPlayer.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -4914,6 +4914,7 @@
   m_VideoPlayerVideo->SendMessage(new CDVDMsgBool(CDVDMsg::GENERAL_PAUSE, false), 1);
   m_clock.Pause(false);
   m_displayLost = false;
+  m_VideoPlayerAudio->SendMessage(new CDVDMsg(CDVDMsg::PLAYER_DISPLAY_RESET), 1);
 }
 
 void CVideoPlayer::UpdateFileItemStreamDetails(CFileItem& item)
diff -Nru kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp
--- kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -201,20 +201,30 @@
     }
   }
 
-  // Check if HLG color space conversion is supported by driver
   ComPtr<ID3D11VideoProcessorEnumerator1> pEnumerator1;
 
   if (SUCCEEDED(m_pEnumerator.As(&pEnumerator1)))
   {
     DXGI_FORMAT format = DX::Windowing()->GetBackBuffer().GetFormat();
     BOOL supported = 0;
-    HRESULT hr = pEnumerator1->CheckVideoProcessorFormatConversion(
+    HRESULT hr;
+
+    // Check if HLG color space conversion is supported by driver
+    hr = pEnumerator1->CheckVideoProcessorFormatConversion(
         DXGI_FORMAT_P010, DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020, format,
         DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, &supported);
     m_bSupportHLG = SUCCEEDED(hr) && !!supported;
+
+    // Check if HDR10 RGB limited range output is supported by driver
+    hr = pEnumerator1->CheckVideoProcessorFormatConversion(
+        DXGI_FORMAT_P010, DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020, format,
+        DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020, &supported);
+    m_bSupportHDR10Limited = SUCCEEDED(hr) && !!supported;
   }
 
   CLog::LogF(LOGDEBUG, "HLG color space conversion is{}supported.", m_bSupportHLG ? " " : " NOT ");
+  CLog::LogF(LOGDEBUG, "HDR10 RGB limited range output is{}supported.",
+             m_bSupportHDR10Limited ? " " : " NOT ");
 
   return true;
 }
@@ -406,7 +416,7 @@
   return DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709;
 }
 
-DXGI_COLOR_SPACE_TYPE CProcessorHD::GetDXGIColorSpaceTarget(CRenderBuffer* view)
+DXGI_COLOR_SPACE_TYPE CProcessorHD::GetDXGIColorSpaceTarget(CRenderBuffer* view, bool supportHDR)
 {
   DXGI_COLOR_SPACE_TYPE color;
 
@@ -420,8 +430,16 @@
   if (view->primaries == AVCOL_PRI_BT2020 && (view->color_transfer == AVCOL_TRC_SMPTE2084 ||
                                               view->color_transfer == AVCOL_TRC_ARIB_STD_B67))
   {
-    color = DX::Windowing()->UseLimitedColor() ? DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020
-                                               : DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
+    if (supportHDR)
+    {
+      color = DX::Windowing()->UseLimitedColor() ? DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020
+                                                 : DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
+    }
+    else
+    {
+      color = DX::Windowing()->UseLimitedColor() ? DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020
+                                                 : DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020;
+    }
   }
 
   return color;
@@ -534,9 +552,12 @@
   ComPtr<ID3D11VideoContext1> videoCtx1;
   if (SUCCEEDED(m_pVideoContext.As(&videoCtx1)))
   {
+    bool supportHDR = DX::Windowing()->IsHDROutput() &&
+                      (m_bSupportHDR10Limited || !DX::Windowing()->UseLimitedColor());
+
     const DXGI_COLOR_SPACE_TYPE sourceColor =
-        GetDXGIColorSpaceSource(views[2], DX::Windowing()->IsHDROutput(), m_bSupportHLG);
-    const DXGI_COLOR_SPACE_TYPE targetColor = GetDXGIColorSpaceTarget(views[2]);
+        GetDXGIColorSpaceSource(views[2], supportHDR, m_bSupportHLG);
+    const DXGI_COLOR_SPACE_TYPE targetColor = GetDXGIColorSpaceTarget(views[2], supportHDR);
 
     videoCtx1->VideoProcessorSetStreamColorSpace1(m_pVideoProcessor.Get(), DEFAULT_STREAM_INDEX,
                                                   sourceColor);
diff -Nru kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h
--- kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/DXVAHD.h	2021-10-06 08:49:25.000000000 +0000
@@ -49,7 +49,7 @@
   void OnDestroyDevice(bool) override { CSingleLock lock(m_section); UnInit(); }
 
   static DXGI_COLOR_SPACE_TYPE GetDXGIColorSpaceSource(CRenderBuffer* view, bool supportHDR, bool supportHLG);
-  static DXGI_COLOR_SPACE_TYPE GetDXGIColorSpaceTarget(CRenderBuffer* view);
+  static DXGI_COLOR_SPACE_TYPE GetDXGIColorSpaceTarget(CRenderBuffer* view, bool supportHDR);
 
 protected:
   bool ReInit();
@@ -69,6 +69,7 @@
   D3D11_VIDEO_PROCESSOR_CAPS m_vcaps = {};
   D3D11_VIDEO_PROCESSOR_RATE_CONVERSION_CAPS m_rateCaps = {};
   bool m_bSupportHLG = false;
+  bool m_bSupportHDR10Limited = false;
 
   struct ProcAmpInfo
   {
diff -Nru kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.cpp kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.cpp
--- kodi-19.1+dfsg2/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -360,6 +360,7 @@
   glBindTexture(GL_TEXTURE_1D, m_kernelTex);
   glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 
   GLvoid* data = (GLvoid*)kernel.GetFloatPixels();
   glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, kernel.GetSize(), 0, GL_RGBA, GL_FLOAT, data);
diff -Nru kodi-19.1+dfsg2/xbmc/dialogs/GUIDialogVolumeBar.cpp kodi-19.2+dfsg1/xbmc/dialogs/GUIDialogVolumeBar.cpp
--- kodi-19.1+dfsg2/xbmc/dialogs/GUIDialogVolumeBar.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/dialogs/GUIDialogVolumeBar.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -30,13 +30,13 @@
     if (g_application.IsMuted() || g_application.GetVolumeRatio() <= VOLUME_MINIMUM)
     { // cancel the timer, dialog needs to stay visible
       CancelAutoClose();
-      return true;
     }
     else
     { // reset the timer, as we've changed the volume level
       SetAutoClose(VOLUME_BAR_DISPLAY_TIME);
-      return true;
     }
+    MarkDirtyRegion();
+    return true;
   }
   return CGUIDialog::OnAction(action);
 }
diff -Nru kodi-19.1+dfsg2/xbmc/FileItem.cpp kodi-19.2+dfsg1/xbmc/FileItem.cpp
--- kodi-19.1+dfsg2/xbmc/FileItem.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/FileItem.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -169,6 +169,10 @@
     SetArt("icon", tag->Icon());
   else if (channel && !channel->IconPath().empty())
     SetArt("icon", channel->IconPath());
+  else if (tag->IsRadio())
+    SetArt("icon", "DefaultMusicSongs.png");
+  else
+    SetArt("icon", "DefaultTVShows.png");
 
   FillMusicInfoTag(channel, tag);
   FillInMimeType(false);
@@ -188,7 +192,7 @@
   if (!channel->IconPath().empty())
     SetArt("icon", channel->IconPath());
   else if (channel->IsRadio())
-    SetArt("icon", "DefaultAudio.png");
+    SetArt("icon", "DefaultMusicSongs.png");
   else
     SetArt("icon", "DefaultTVShows.png");
 
@@ -213,8 +217,16 @@
 
   // Set art
   if (!record->m_strIconPath.empty())
-  {
     SetArt("icon", record->m_strIconPath);
+  else
+  {
+    const std::shared_ptr<CPVRChannel> channel = record->Channel();
+    if (channel && !channel->IconPath().empty())
+      SetArt("icon", channel->IconPath());
+    else if (record->IsRadio())
+      SetArt("icon", "DefaultMusicSongs.png");
+    else
+      SetArt("icon", "DefaultTVShows.png");
   }
 
   if (!record->m_strThumbnailPath.empty())
@@ -238,6 +250,10 @@
 
   if (!timer->ChannelIcon().empty())
     SetArt("icon", timer->ChannelIcon());
+  else if (timer->m_bIsRadio)
+    SetArt("icon", "DefaultMusicSongs.png");
+  else
+    SetArt("icon", "DefaultTVShows.png");
 
   FillInMimeType(false);
 }
@@ -1337,7 +1353,7 @@
       if (IsPVRChannel())
       {
         if (GetPVRChannelInfoTag()->IsRadio())
-          SetArt("icon", "DefaultAudio.png");
+          SetArt("icon", "DefaultMusicSongs.png");
         else
           SetArt("icon", "DefaultTVShows.png");
       }
diff -Nru kodi-19.1+dfsg2/xbmc/filesystem/CurlFile.cpp kodi-19.2+dfsg1/xbmc/filesystem/CurlFile.cpp
--- kodi-19.1+dfsg2/xbmc/filesystem/CurlFile.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/filesystem/CurlFile.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -670,9 +670,12 @@
   // set CA bundle file
   std::string caCert = CSpecialProtocol::TranslatePath(
       CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_caTrustFile);
+#ifdef TARGET_WINDOWS_STORE
+  // UWP Curl - Setting CURLOPT_CAINFO with a valid cacert file path is required for UWP
+  g_curlInterface.easy_setopt(h, CURLOPT_CAINFO, "system\\certs\\cacert.pem");
+#endif
   if (!caCert.empty() && XFILE::CFile::Exists(caCert))
     g_curlInterface.easy_setopt(h, CURLOPT_CAINFO, caCert.c_str());
-
 }
 
 void CCurlFile::SetRequestHeaders(CReadState* state)
diff -Nru kodi-19.1+dfsg2/xbmc/guilib/GUIBaseContainer.cpp kodi-19.2+dfsg1/xbmc/guilib/GUIBaseContainer.cpp
--- kodi-19.1+dfsg2/xbmc/guilib/GUIBaseContainer.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/guilib/GUIBaseContainer.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -753,7 +753,6 @@
     const int absCursor = CorrectOffset(GetOffset(), GetCursor());
     SetOffset(offset);
     ValidateOffset();
-    CGUIBaseContainer::SetCursor(absCursor - CorrectOffset(GetOffset(), 0));
     // Notify Application if Inertial scrolling reaches lists end
     if (m_waitForScrollEnd)
     {
@@ -765,6 +764,10 @@
       else
         m_lastScrollValue = m_scroller.GetValue();
     }
+    else
+    {
+      CGUIBaseContainer::SetCursor(absCursor - CorrectOffset(GetOffset(), 0));
+    }
     return EVENT_RESULT_HANDLED;
   }
   else if (event.m_id == ACTION_GESTURE_END || event.m_id == ACTION_GESTURE_ABORT)
diff -Nru kodi-19.1+dfsg2/xbmc/guilib/guiinfo/MusicGUIInfo.cpp kodi-19.2+dfsg1/xbmc/guilib/guiinfo/MusicGUIInfo.cpp
--- kodi-19.1+dfsg2/xbmc/guilib/guiinfo/MusicGUIInfo.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/guilib/guiinfo/MusicGUIInfo.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -387,6 +387,13 @@
 
         value = CURL(value).GetWithoutUserDetails();
         return true;
+      case LISTITEM_DATE_ADDED:
+        if (tag->GetDateAdded().IsValid())
+        {
+          value = tag->GetDateAdded().GetAsLocalizedDate();
+          return true;
+        }
+        break;
     }
   }
 
diff -Nru kodi-19.1+dfsg2/xbmc/interfaces/json-rpc/AudioLibrary.cpp kodi-19.2+dfsg1/xbmc/interfaces/json-rpc/AudioLibrary.cpp
--- kodi-19.1+dfsg2/xbmc/interfaces/json-rpc/AudioLibrary.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/interfaces/json-rpc/AudioLibrary.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -1040,9 +1040,11 @@
   else
   {
     cmd = "exportlibrary2(music, library, dummy, albums, albumartists";
-    if (parameterObject["options"].asBoolean("images"))
+    if (parameterObject["options"]["images"].isBoolean() &&
+        parameterObject["options"]["images"].asBoolean() == true)
       cmd += ", artwork";
-    if (parameterObject["options"].asBoolean("overwrite"))
+    if (parameterObject["options"]["overwrite"].isBoolean() &&
+        parameterObject["options"]["overwrite"].asBoolean() == true)
       cmd += ", overwrite";
     cmd += ")";
   }
diff -Nru kodi-19.1+dfsg2/xbmc/interfaces/json-rpc/schema/types.json kodi-19.2+dfsg1/xbmc/interfaces/json-rpc/schema/types.json
--- kodi-19.1+dfsg2/xbmc/interfaces/json-rpc/schema/types.json	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/interfaces/json-rpc/schema/types.json	2021-10-06 08:49:25.000000000 +0000
@@ -1019,7 +1019,7 @@
                 "wasactive", "thumbnail", "rating", "originaltitle", "cast",
                 "director", "writer", "year", "imdbnumber", "hastimerrule",
                 "hasrecording", "recording", "isseries", "isplayable", "clientid",
-                "hasreminder" ]
+                "hasreminder", "seasonnum" ]
     }
   },
   "PVR.Details.Broadcast": {
@@ -1057,7 +1057,8 @@
       "isseries": { "type": "boolean" },
       "isplayable": { "type": "boolean", "description": "Deprecated - Use GetBroadcastIsPlayable instead" },
       "clientid": { "$ref": "Library.Id" },
-      "hasreminder": { "type": "boolean" }
+      "hasreminder": { "type": "boolean" },
+      "seasonnum": { "type": "integer" }
     }
   },
   "PVR.Fields.Channel": {
diff -Nru kodi-19.1+dfsg2/xbmc/interfaces/json-rpc/schema/version.txt kodi-19.2+dfsg1/xbmc/interfaces/json-rpc/schema/version.txt
--- kodi-19.1+dfsg2/xbmc/interfaces/json-rpc/schema/version.txt	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/interfaces/json-rpc/schema/version.txt	2021-10-06 08:49:25.000000000 +0000
@@ -1 +1 @@
-JSONRPC_VERSION 12.3.0
+JSONRPC_VERSION 12.4.0
diff -Nru kodi-19.1+dfsg2/xbmc/interfaces/json-rpc/VideoLibrary.cpp kodi-19.2+dfsg1/xbmc/interfaces/json-rpc/VideoLibrary.cpp
--- kodi-19.1+dfsg2/xbmc/interfaces/json-rpc/VideoLibrary.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/interfaces/json-rpc/VideoLibrary.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -966,11 +966,14 @@
   else
   {
     cmd = "exportlibrary2(video, separate, dummy";
-    if (parameterObject["options"].asBoolean("images"))
+    if (parameterObject["options"]["images"].isBoolean() &&
+        parameterObject["options"]["images"].asBoolean() == true)
       cmd += ", artwork";
-    if (parameterObject["options"].asBoolean("overwrite"))
+    if (parameterObject["options"]["overwrite"].isBoolean() &&
+        parameterObject["options"]["overwrite"].asBoolean() == true)
       cmd += ", overwrite";
-    if (parameterObject["options"].asBoolean("actorthumbs"))
+    if (parameterObject["options"]["actorthumbs"].isBoolean() &&
+        parameterObject["options"]["actorthumbs"].asBoolean() == true)
       cmd += ", actorthumbs";
     cmd += ")";
   }
diff -Nru kodi-19.1+dfsg2/xbmc/interfaces/python/AddonPythonInvoker.cpp kodi-19.2+dfsg1/xbmc/interfaces/python/AddonPythonInvoker.cpp
--- kodi-19.1+dfsg2/xbmc/interfaces/python/AddonPythonInvoker.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/interfaces/python/AddonPythonInvoker.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -46,6 +46,12 @@
   "sys.modules['pkg_resources'] = pkg_resources\n" \
   ""
 
+#define RUNSCRIPT_SETUP_ENVIROMENT_VARIABLES \
+  "" \
+  "from os import environ\n" \
+  "environ['SSL_CERT_FILE'] = 'system/certs/cacert.pem'\n" \
+  ""
+
 #define RUNSCRIPT_POSTSCRIPT \
         "print('-->Python Interpreter Initialized<--')\n" \
         ""
@@ -55,6 +61,11 @@
 #define RUNSCRIPT_COMPLIANT \
   RUNSCRIPT_PREAMBLE RUNSCRIPT_SETUPTOOLS_HACK RUNSCRIPT_POSTSCRIPT
 
+#elif defined(TARGET_WINDOWS_STORE)
+
+#define RUNSCRIPT_COMPLIANT \
+  RUNSCRIPT_PREAMBLE RUNSCRIPT_SETUP_ENVIROMENT_VARIABLES RUNSCRIPT_POSTSCRIPT
+
 #else
 
 #define RUNSCRIPT_COMPLIANT \
diff -Nru kodi-19.1+dfsg2/xbmc/interfaces/python/XBPython.cpp kodi-19.2+dfsg1/xbmc/interfaces/python/XBPython.cpp
--- kodi-19.1+dfsg2/xbmc/interfaces/python/XBPython.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/interfaces/python/XBPython.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -502,8 +502,12 @@
     CEnvironment::putenv(buf);
     buf = "PYTHONOPTIMIZE=1";
     CEnvironment::putenv(buf);
-    buf = "OS=win32";
-    CEnvironment::putenv(buf);
+
+#ifdef TARGET_WINDOWS_STORE
+    CEnvironment::putenv("OS=win10");
+#else
+    CEnvironment::putenv("OS=win32");
+#endif
 
     std::wstring pythonHomeW;
     CCharsetConverter::utf8ToW(CSpecialProtocol::TranslatePath("special://xbmc/system/python"),
diff -Nru kodi-19.1+dfsg2/xbmc/interfaces/swig/CMakeLists.txt kodi-19.2+dfsg1/xbmc/interfaces/swig/CMakeLists.txt
--- kodi-19.1+dfsg2/xbmc/interfaces/swig/CMakeLists.txt	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/interfaces/swig/CMakeLists.txt	2021-10-06 08:49:25.000000000 +0000
@@ -14,11 +14,16 @@
   if(CLANGFORMAT_FOUND)
     set(CLANG_FORMAT_COMMAND COMMAND ${CLANG_FORMAT_EXECUTABLE} ARGS -i ${CPP_FILE})
   endif()
+
+  if(Java_VERSION_MAJOR GREATER 8)
+    set(JAVA_OPEN_OPTS --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.regex=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED  --add-opens java.base/java.net=ALL-UNNAMED)
+  endif()
+
   add_custom_command(OUTPUT ${CPP_FILE}
                      COMMAND ${SWIG_EXECUTABLE}
                      ARGS -w401 -c++ -o ${file}.xml -xml -I${CMAKE_SOURCE_DIR}/xbmc -xmllang python ${CMAKE_CURRENT_SOURCE_DIR}/../swig/${file}
                      COMMAND ${Java_JAVA_EXECUTABLE}
-                     ARGS -cp "${classpath}" groovy.ui.GroovyMain ${CMAKE_SOURCE_DIR}/tools/codegenerator/Generator.groovy ${file}.xml ${CMAKE_CURRENT_SOURCE_DIR}/../python/PythonSwig.cpp.template ${file}.cpp > ${devnull}
+                     ARGS ${JAVA_OPEN_OPTS} -cp "${classpath}" groovy.ui.GroovyMain ${CMAKE_SOURCE_DIR}/tools/codegenerator/Generator.groovy ${file}.xml ${CMAKE_CURRENT_SOURCE_DIR}/../python/PythonSwig.cpp.template ${file}.cpp > ${devnull}
                      ${CLANG_FORMAT_COMMAND}
                      DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../swig/${file} ${CMAKE_CURRENT_SOURCE_DIR}/../python/PythonSwig.cpp.template)
   set(SOURCES ${SOURCES} "${CPP_FILE}" PARENT_SCOPE)
diff -Nru kodi-19.1+dfsg2/xbmc/LangInfo.cpp kodi-19.2+dfsg1/xbmc/LangInfo.cpp
--- kodi-19.1+dfsg2/xbmc/LangInfo.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/LangInfo.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -979,6 +979,18 @@
 
   m_currentRegion->SetGlobalLocale();
 
+  // Check if locale is affected by "Turkish I"
+  // See https://github.com/xbmc/xbmc/issues/19883 for details
+  if (std::tolower('i') != std::tolower('I'))
+  {
+    CLog::Log(
+        LOGWARNING,
+        "region '{}' is affected by 'Turkish I' problem - falling back to default region '{}'",
+        m_currentRegion->m_strName, m_defaultRegion.m_strName);
+    m_currentRegion = &m_defaultRegion;
+    m_currentRegion->SetGlobalLocale();
+  }
+
   const std::shared_ptr<CSettings> settings = CServiceBroker::GetSettingsComponent()->GetSettings();
   if (settings->GetString(CSettings::SETTING_LOCALE_SHORTDATEFORMAT) == SETTING_REGIONAL_DEFAULT)
     SetShortDateFormat(m_currentRegion->m_strDateFormatShort);
diff -Nru kodi-19.1+dfsg2/xbmc/music/MusicDatabase.cpp kodi-19.2+dfsg1/xbmc/music/MusicDatabase.cpp
--- kodi-19.1+dfsg2/xbmc/music/MusicDatabase.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/music/MusicDatabase.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -2096,58 +2096,67 @@
        but SQLite not support updatable joins.
     */
     m_pDS->exec("CREATE TABLE tempDisco "
-                "(strAlbum TEXT, iYear INTEGER, mbid TEXT, idAlbum INTEGER)");
+                "(strAlbum TEXT, strYear VARCHAR(4), mbid TEXT, idAlbum INTEGER)");
+    m_pDS->exec("CREATE TABLE tempAlbum "
+                "(strAlbum TEXT, strYear VARCHAR(4), mbid TEXT, idAlbum INTEGER)");
 
     std::string strSQL;
-    strSQL = PrepareSQL("INSERT INTO tempDisco(strAlbum, iYear, mbid, idAlbum) "
-                        "SELECT strAlbum, CAST(discography.strYear AS INTEGER) AS iYear, "
+    strSQL = PrepareSQL("INSERT INTO tempDisco(strAlbum, strYear, mbid, idAlbum) "
+                        "SELECT strAlbum, SUBSTR(discography.strYear, 1, 4) AS strYear, "
                         "strReleaseGroupMBID, NULL "
                         "FROM discography WHERE idArtist = %i",
                         idArtist);
     m_pDS->exec(strSQL);
 
+    strSQL = PrepareSQL("INSERT INTO tempAlbum(strAlbum, strYear, mbid, idAlbum) "
+                        "SELECT strAlbum, SUBSTR(strOrigReleaseDate, 1, 4) AS strYear, "
+                        "strReleaseGroupMBID, album.idAlbum "
+                        "FROM album JOIN album_artist ON album_artist.idAlbum = album.idAlbum "
+                        "WHERE idArtist = %i",
+                        idArtist);
+    m_pDS->exec(strSQL);
+
     // Match albums on release group mbid, if multi-releases then first used
-    strSQL = "UPDATE tempDisco SET idAlbum = (SELECT album.idAlbum FROM album "
-             "WHERE album.strReleaseGroupMBID = tempDisco.mbid "
-             "AND album.strReleaseGroupMBID IS NOT NULL)";
+    // Only use albums credited to this artist
+    strSQL = "UPDATE tempDisco SET idAlbum = (SELECT tempAlbum.idAlbum FROM tempAlbum "
+             "WHERE tempAlbum.mbid = tempDisco.mbid AND tempAlbum.mbid IS NOT NULL)";
+    m_pDS->exec(strSQL);
+    //Delete matched albums
+    strSQL = "DELETE FROM tempAlbum "
+             "WHERE EXISTS(SELECT 1 FROM tempDisco WHERE tempDisco.idAlbum = tempAlbum.idAlbum)";
     m_pDS->exec(strSQL);
+
     // Match remaining to albums by artist on title and year
-    strSQL = PrepareSQL("UPDATE tempDisco SET idAlbum = (SELECT album.idAlbum FROM album "
-                        "JOIN album_artist ON album_artist.idAlbum = album.idAlbum "
-                        "WHERE album_artist.idArtist = %i "
-                        "AND NOT EXISTS(SELECT 1 FROM tempDisco AS td "
-                        "WHERE td.idAlbum = album.idAlbum) "
-                        "AND CAST(strOrigReleaseDate AS INTEGER) = tempDisco.iYear "
-                        "AND album.strAlbum = tempDisco.strAlbum) "
-                        "WHERE tempDisco.idAlbum is NULL",
-                        idArtist);
+    strSQL = "UPDATE tempDisco SET idAlbum = (SELECT idAlbum FROM tempAlbum "
+             "WHERE tempAlbum.strAlbum = tempDisco.strAlbum "
+             "AND tempAlbum.strYear = tempDisco.strYear) "
+             "WHERE tempDisco.idAlbum is NULL";
     m_pDS->exec(strSQL);
+    //Delete matched albums
+    strSQL = "DELETE FROM tempAlbum "
+      "WHERE EXISTS(SELECT 1 FROM tempDisco WHERE tempDisco.idAlbum = tempAlbum.idAlbum)";
+    m_pDS->exec(strSQL);
+
     // Match remaining to albums by artist on title only
-    strSQL = PrepareSQL("UPDATE tempDisco SET idAlbum = (SELECT album.idAlbum FROM album "
-                        "JOIN album_artist ON album_artist.idAlbum = album.idAlbum "
-                        "WHERE album_artist.idArtist = %i "
-                        "AND NOT EXISTS(SELECT 1 FROM tempDisco AS td "
-                        "WHERE td.idAlbum = album.idAlbum) "
-                        "AND album.strAlbum = tempDisco.strAlbum) "
-                        "WHERE tempDisco.idAlbum is NULL",
-                        idArtist);
+    strSQL = "UPDATE tempDisco SET idAlbum = (SELECT idAlbum FROM tempAlbum "
+             "WHERE tempAlbum.strAlbum = tempDisco.strAlbum) "
+             "WHERE tempDisco.idAlbum is NULL";
+    m_pDS->exec(strSQL);
+    // Use year from album table, when matched by title only as it could be different
+    strSQL = "UPDATE tempDisco SET strYear = (SELECT strYear FROM tempAlbum "
+             "WHERE tempAlbum.idAlbum = tempDisco.idAlbum) "
+             "WHERE EXISTS(SELECT 1 FROM tempAlbum WHERE tempAlbum.idAlbum = tempDisco.idAlbum)";
     m_pDS->exec(strSQL);
-    // Use year from album table, when matched by name only it could be different
-    strSQL = PrepareSQL("UPDATE tempDisco "
-                        "SET iYear = (SELECT CAST(album.strOrigReleaseDate AS INTEGER) FROM album "
-                        "WHERE album.idAlbum = tempDisco.idAlbum) "
-                        "WHERE tempDisco.idAlbum > 0");
+    //Delete matched albums
+    strSQL = "DELETE FROM tempAlbum "
+             "WHERE EXISTS(SELECT 1 FROM tempDisco WHERE tempDisco.idAlbum = tempAlbum.idAlbum)";
     m_pDS->exec(strSQL);
 
-    // Combine distinctly with albums by artist that are not in discography
-    strSQL =
-        PrepareSQL("SELECT strAlbum, iYear, idAlbum FROM tempDisco "
-                   "UNION "
-                   "SELECT strAlbum, CAST(strOrigReleaseDate AS INTEGER) AS iYear, album.idAlbum "
-                   "FROM album JOIN album_artist ON album_artist.idAlbum = album.idAlbum "
-                   "WHERE album_artist.idArtist = %i "
-                   "ORDER BY iYear, strAlbum, idAlbum",
-                   idArtist);
+    // Combine distinctly with any remaining unmatched albums by artist
+    strSQL = "SELECT strAlbum, strYear, idAlbum FROM tempDisco "
+             "UNION "
+             "SELECT strAlbum, strYear, idAlbum FROM tempAlbum "
+             "ORDER BY strYear, strAlbum, idAlbum";
 
     if (!m_pDS->query(strSQL))
       return false;
@@ -2167,7 +2176,7 @@
       if (!strAlbum.empty())
       {
           CFileItemPtr pItem(new CFileItem(strAlbum));
-          pItem->SetLabel2(m_pDS->fv("iYear").get_asString());
+          pItem->SetLabel2(m_pDS->fv("strYear").get_asString());
           pItem->GetMusicInfoTag()->SetDatabaseId(idAlbum, MediaTypeAlbum);
           items.Add(pItem);
       }
@@ -2177,12 +2186,14 @@
     // cleanup
     m_pDS->close();
     m_pDS->exec("DROP TABLE tempDisco");
+    m_pDS->exec("DROP TABLE tempAlbum");
 
     return true;
   }
   catch (...)
   {
     m_pDS->exec("DROP TABLE tempDisco");
+    m_pDS->exec("DROP TABLE tempAlbum");
     CLog::Log(LOGERROR, "%s failed", __FUNCTION__);
   }
   return false;
@@ -5547,7 +5558,7 @@
     items.Reserve(total);
     int albumOffset = 2;
     CAlbum album;
-    bool useTitle = false;
+    bool useTitle = true; // Assume we want to match by disc title later unless we have no titles
     std::string oldDiscTitle;
     const dbiplus::query_data& data = m_pDS->get_result_set().records;
     for (const auto& i : results)
@@ -5558,23 +5569,22 @@
       {
         if (album.idAlbum != record->at(albumOffset + album_idAlbum).get_asInt())
         { // New album
-          useTitle = false;
+          useTitle = true;
           album = GetAlbumFromDataset(record, albumOffset);
         }
 
         int discnum = record->at(0).get_asInt();
         std::string strDiscSubtitle = record->at(1).get_asString();
         if (strDiscSubtitle.empty())
-          // Make (fake) disc title from disc number
-          strDiscSubtitle = StringUtils::Format("%s %i", g_localizeStrings.Get(427), discnum);
+        { // Make (fake) disc title from disc number, group by disc number as no real title to match
+          strDiscSubtitle = StringUtils::Format("{} {}", g_localizeStrings.Get(427), discnum);
+          useTitle = false;
+        }
         else if (oldDiscTitle == strDiscSubtitle)
-        { // When real disc titles are provided (as they ALWAYS are for boxed sets)
-          // group discs together by title not number.
-          useTitle = true;
+        { // disc title already added to list, fetch the next disc
           continue;
         }
-        else
-          oldDiscTitle = strDiscSubtitle;
+        oldDiscTitle = strDiscSubtitle;
 
         CMusicDbUrl itemUrl = musicUrl;
         std::string path = StringUtils::Format("%i/", discnum);
diff -Nru kodi-19.1+dfsg2/xbmc/network/TCPServer.cpp kodi-19.2+dfsg1/xbmc/network/TCPServer.cpp
--- kodi-19.1+dfsg2/xbmc/network/TCPServer.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/network/TCPServer.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -48,7 +48,12 @@
 
 using namespace JSONRPC;
 
-#define RECEIVEBUFFER 1024
+#define RECEIVEBUFFER 4096
+
+namespace
+{
+constexpr size_t maxBufferLength = 64 * 1024;
+}
 
 CTCPServer *CTCPServer::ServerInstance = NULL;
 
@@ -637,11 +642,13 @@
 CTCPServer::CWebSocketClient::CWebSocketClient(CWebSocket *websocket)
 {
   m_websocket = websocket;
+  m_buffer.reserve(maxBufferLength);
 }
 
 CTCPServer::CWebSocketClient::CWebSocketClient(const CWebSocketClient& client)
 {
   *this = client;
+  m_buffer.reserve(maxBufferLength);
 }
 
 CTCPServer::CWebSocketClient::CWebSocketClient(CWebSocket *websocket, const CTCPClient& client)
@@ -649,6 +656,7 @@
   Copy(client);
 
   m_websocket = websocket;
+  m_buffer.reserve(maxBufferLength);
 }
 
 CTCPServer::CWebSocketClient::~CWebSocketClient()
@@ -661,6 +669,7 @@
   Copy(client);
 
   m_websocket = client.m_websocket;
+  m_buffer = client.m_buffer;
 
   return *this;
 }
@@ -680,10 +689,21 @@
 {
   bool send;
   const CWebSocketMessage *msg = NULL;
-  size_t len = length;
+
+  if (m_buffer.size() + length > maxBufferLength)
+  {
+    CLog::Log(LOGINFO, "WebSocket: client buffer size {} exceeded", maxBufferLength);
+    return Disconnect();
+  }
+
+  m_buffer.append(buffer, length);
+
+  const char* buf = m_buffer.data();
+  size_t len = m_buffer.size();
+
   do
   {
-    if ((msg = m_websocket->Handle(buffer, len, send)) != NULL && msg->IsComplete())
+    if ((msg = m_websocket->Handle(buf, len, send)) != NULL && msg->IsComplete())
     {
       std::vector<const CWebSocketFrame *> frames = msg->GetFrames();
       if (send)
@@ -702,6 +722,9 @@
   }
   while (len > 0 && msg != NULL);
 
+  if (len < m_buffer.size())
+    m_buffer = m_buffer.substr(m_buffer.size() - len);
+
   if (m_websocket->GetState() == WebSocketStateClosed)
     Disconnect();
 }
@@ -721,4 +744,3 @@
       CTCPClient::Disconnect();
   }
 }
-
diff -Nru kodi-19.1+dfsg2/xbmc/network/TCPServer.h kodi-19.2+dfsg1/xbmc/network/TCPServer.h
--- kodi-19.1+dfsg2/xbmc/network/TCPServer.h	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/network/TCPServer.h	2021-10-06 08:49:25.000000000 +0000
@@ -104,6 +104,7 @@
 
     private:
       CWebSocket *m_websocket;
+      std::string m_buffer;
     };
 
     std::vector<CTCPClient*> m_connections;
diff -Nru kodi-19.1+dfsg2/xbmc/platform/linux/MemUtils.cpp kodi-19.2+dfsg1/xbmc/platform/linux/MemUtils.cpp
--- kodi-19.1+dfsg2/xbmc/platform/linux/MemUtils.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/platform/linux/MemUtils.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -18,7 +18,9 @@
 
 void* AlignedMalloc(size_t s, size_t alignTo)
 {
-  return aligned_alloc(alignTo, s);
+  void* p = nullptr;
+  posix_memalign(&p, alignTo, s);
+  return p;
 }
 
 void AlignedFree(void* p)
diff -Nru kodi-19.1+dfsg2/xbmc/pvr/addons/PVRClient.cpp kodi-19.2+dfsg1/xbmc/pvr/addons/PVRClient.cpp
--- kodi-19.1+dfsg2/xbmc/pvr/addons/PVRClient.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/pvr/addons/PVRClient.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -222,6 +222,13 @@
 
 void CPVRClient::SetConnectionState(PVR_CONNECTION_STATE state)
 {
+  if (state == PVR_CONNECTION_STATE_CONNECTED)
+  {
+    // update properties - some will only be available after add-on is connected to backend
+    if (!GetAddonProperties())
+      CLog::LogF(LOGERROR, "Error reading PVR client properties");
+  }
+
   CSingleLock lock(m_critSection);
 
   m_prevConnectionState = m_connectionState;
@@ -231,7 +238,7 @@
     m_ignoreClient = false;
   else if (m_connectionState == PVR_CONNECTION_STATE_CONNECTING &&
            m_prevConnectionState == PVR_CONNECTION_STATE_UNKNOWN)
-    m_ignoreClient = true;
+    m_ignoreClient = true; // ignore until connected
 }
 
 PVR_CONNECTION_STATE CPVRClient::GetPreviousConnectionState() const
@@ -1376,7 +1383,7 @@
   if (m_bBlockAddonCalls)
     return PVR_ERROR_SERVER_ERROR;
 
-  if (!m_bReadyToUse && bCheckReadyToUse)
+  if (bCheckReadyToUse && (!ReadyToUse() || IgnoreClient()))
     return PVR_ERROR_SERVER_ERROR;
 
   // Call.
diff -Nru kodi-19.1+dfsg2/xbmc/pvr/addons/PVRClient.h kodi-19.2+dfsg1/xbmc/pvr/addons/PVRClient.h
--- kodi-19.1+dfsg2/xbmc/pvr/addons/PVRClient.h	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/pvr/addons/PVRClient.h	2021-10-06 08:49:25.000000000 +0000
@@ -915,12 +915,6 @@
   PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES* times);
 
   /*!
-   * @brief reads the client's properties.
-   * @return True on success, false otherwise.
-   */
-  bool GetAddonProperties();
-
-  /*!
    * @brief Get the client's menu hooks.
    * @return The hooks. Guaranteed never to be nullptr.
    */
@@ -1012,6 +1006,12 @@
   void ResetProperties(int iClientId = PVR_INVALID_CLIENT_ID);
 
   /*!
+   * @brief reads the client's properties.
+   * @return True on success, false otherwise.
+   */
+  bool GetAddonProperties();
+
+  /*!
    * @brief Copy over group info from xbmcGroup to addonGroup.
    * @param xbmcGroup The group on XBMC's side.
    * @param addonGroup The group on the addon's side.
diff -Nru kodi-19.1+dfsg2/xbmc/pvr/addons/PVRClientMenuHooks.cpp kodi-19.2+dfsg1/xbmc/pvr/addons/PVRClientMenuHooks.cpp
--- kodi-19.1+dfsg2/xbmc/pvr/addons/PVRClientMenuHooks.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/pvr/addons/PVRClientMenuHooks.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -77,6 +77,11 @@
   return m_hook->category == PVR_MENUHOOK_SETTING;
 }
 
+std::string CPVRClientMenuHook::GetAddonId() const
+{
+  return m_addonId;
+}
+
 unsigned int CPVRClientMenuHook::GetId() const
 {
   return m_hook->iHookId;
diff -Nru kodi-19.1+dfsg2/xbmc/pvr/addons/PVRClientMenuHooks.h kodi-19.2+dfsg1/xbmc/pvr/addons/PVRClientMenuHooks.h
--- kodi-19.1+dfsg2/xbmc/pvr/addons/PVRClientMenuHooks.h	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/pvr/addons/PVRClientMenuHooks.h	2021-10-06 08:49:25.000000000 +0000
@@ -35,6 +35,7 @@
     bool IsDeletedRecordingHook() const;
     bool IsSettingsHook() const;
 
+    std::string GetAddonId() const;
     unsigned int GetId() const;
     unsigned int GetLabelId() const;
     std::string GetLabel() const;
diff -Nru kodi-19.1+dfsg2/xbmc/pvr/addons/PVRClients.cpp kodi-19.2+dfsg1/xbmc/pvr/addons/PVRClients.cpp
--- kodi-19.1+dfsg2/xbmc/pvr/addons/PVRClients.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/pvr/addons/PVRClients.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -717,15 +717,6 @@
 
   // Notify user.
   CJobManager::GetInstance().AddJob(new CPVREventLogJob(bNotify, bError, client->Name(), strMsg, client->Icon()), nullptr);
-
-  if (newState == PVR_CONNECTION_STATE_CONNECTED)
-  {
-    // update properties on connect
-    if (!client->GetAddonProperties())
-      CLog::LogF(LOGERROR, "Error reading PVR client properties");
-
-    CServiceBroker::GetPVRManager().Start();
-  }
 }
 
 PVR_ERROR CPVRClients::ForCreatedClients(const char* strFunctionName,
diff -Nru kodi-19.1+dfsg2/xbmc/pvr/dialogs/GUIDialogPVRGuideSearch.cpp kodi-19.2+dfsg1/xbmc/pvr/dialogs/GUIDialogPVRGuideSearch.cpp
--- kodi-19.1+dfsg2/xbmc/pvr/dialogs/GUIDialogPVRGuideSearch.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/pvr/dialogs/GUIDialogPVRGuideSearch.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -58,7 +58,10 @@
   int iChannelGroup = GetSpinValue(CONTROL_SPIN_GROUPS);
 
   std::vector< std::pair<std::string, int> > labels;
-  labels.emplace_back(g_localizeStrings.Get(19217), EPG_SEARCH_UNSET);
+  if (m_searchFilter->IsRadio())
+    labels.emplace_back(g_localizeStrings.Get(19216), EPG_SEARCH_UNSET); // All radio channels
+  else
+    labels.emplace_back(g_localizeStrings.Get(19217), EPG_SEARCH_UNSET); // All TV channels
 
   std::shared_ptr<CPVRChannelGroup> group;
   if (iChannelGroup == EPG_SEARCH_UNSET)
diff -Nru kodi-19.1+dfsg2/xbmc/pvr/epg/EpgInfoTag.cpp kodi-19.2+dfsg1/xbmc/pvr/epg/EpgInfoTag.cpp
--- kodi-19.1+dfsg2/xbmc/pvr/epg/EpgInfoTag.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/pvr/epg/EpgInfoTag.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -161,6 +161,7 @@
   value["plotoutline"] = m_strPlotOutline;
   value["plot"] = m_strPlot;
   value["originaltitle"] = m_strOriginalTitle;
+  value["thumbnail"] = m_strIconPath;
   value["cast"] = DeTokenize(m_cast);
   value["director"] = DeTokenize(m_directors);
   value["writer"] = DeTokenize(m_writers);
@@ -177,6 +178,7 @@
   value["episodename"] = m_strEpisodeName;
   value["episodenum"] = m_iEpisodeNumber;
   value["episodepart"] = m_iEpisodePart;
+  value["seasonnum"] = m_iSeriesNumber;
   value["isactive"] = IsActive();
   value["wasactive"] = WasActive();
   value["isseries"] = IsSeries();
diff -Nru kodi-19.1+dfsg2/xbmc/pvr/epg/EpgTagsContainer.cpp kodi-19.2+dfsg1/xbmc/pvr/epg/EpgTagsContainer.cpp
--- kodi-19.1+dfsg2/xbmc/pvr/epg/EpgTagsContainer.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/pvr/epg/EpgTagsContainer.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -600,7 +600,7 @@
   if (m_database)
   {
     const CDateTime dbResult = m_database->GetLastEndTime(m_iEpgID);
-    if (result.IsValid() || (dbResult.IsValid() && dbResult > result))
+    if (!result.IsValid() || (dbResult.IsValid() && dbResult > result))
       result = dbResult;
   }
 
diff -Nru kodi-19.1+dfsg2/xbmc/pvr/guilib/PVRGUIActions.cpp kodi-19.2+dfsg1/xbmc/pvr/guilib/PVRGUIActions.cpp
--- kodi-19.1+dfsg2/xbmc/pvr/guilib/PVRGUIActions.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/pvr/guilib/PVRGUIActions.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -156,7 +156,7 @@
       bool bReturn = true;
       for (const auto& itemToDelete : items)
       {
-        if (itemToDelete->IsUsablePVRRecording() &&
+        if (itemToDelete->IsPVRRecording() &&
             (!m_bWatchedOnly || itemToDelete->GetPVRRecordingInfoTag()->GetPlayCount() > 0))
           bReturn &= itemToDelete->GetPVRRecordingInfoTag()->Delete();
       }
@@ -1514,7 +1514,12 @@
   {
     CFileItemPtr pvrItem(item);
     if (URIUtils::IsPVRChannel(item->GetPath()) && !item->HasPVRChannelInfoTag())
-      pvrItem = std::make_shared<CFileItem>(CServiceBroker::GetPVRManager().ChannelGroups()->GetByPath(item->GetPath()));
+    {
+      const std::shared_ptr<CPVRChannel> pvrChannel =
+          CServiceBroker::GetPVRManager().ChannelGroups()->GetByPath(item->GetPath());
+      if (pvrChannel)
+        pvrItem = std::make_shared<CFileItem>(pvrChannel);
+    }
     else if (URIUtils::IsPVRRecording(item->GetPath()) && !item->HasPVRRecordingInfoTag())
       pvrItem = std::make_shared<CFileItem>(CServiceBroker::GetPVRManager().Recordings()->GetByPath(item->GetPath()));
 
diff -Nru kodi-19.1+dfsg2/xbmc/pvr/PVRContextMenus.cpp kodi-19.2+dfsg1/xbmc/pvr/PVRContextMenus.cpp
--- kodi-19.1+dfsg2/xbmc/pvr/PVRContextMenus.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/pvr/PVRContextMenus.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -602,6 +602,10 @@
 
     bool PVRClientMenuHook::IsVisible(const CFileItem& item) const
     {
+      const std::shared_ptr<CPVRClient> client = CServiceBroker::GetPVRManager().GetClient(item);
+      if (!client || m_hook.GetAddonId() != client->ID())
+        return false;
+
       if (m_hook.IsAllHook())
         return !item.m_bIsFolder && !URIUtils::PathEquals(item.GetPath(), CPVRTimersPath::PATH_ADDTIMER);
       else if (m_hook.IsEpgHook())
diff -Nru kodi-19.1+dfsg2/xbmc/pvr/PVRItem.cpp kodi-19.2+dfsg1/xbmc/pvr/PVRItem.cpp
--- kodi-19.1+dfsg2/xbmc/pvr/PVRItem.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/pvr/PVRItem.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -59,7 +59,7 @@
     }
     else if (m_item->IsPVRTimer())
     {
-      const std::shared_ptr<CPVRChannel> channel =m_item->GetPVRTimerInfoTag()->Channel();
+      const std::shared_ptr<CPVRChannel> channel = m_item->GetPVRTimerInfoTag()->Channel();
       if (channel)
         return channel->GetEPGNext();
     }
@@ -143,6 +143,10 @@
     {
       return m_item->GetPVRRecordingInfoTag()->IsRadio();
     }
+    else if (m_item->IsPVRTimer())
+    {
+      return m_item->GetPVRTimerInfoTag()->m_bIsRadio;
+    }
     else
     {
       CLog::LogF(LOGERROR, "Unsupported item type!");
diff -Nru kodi-19.1+dfsg2/xbmc/pvr/PVRManager.cpp kodi-19.2+dfsg1/xbmc/pvr/PVRManager.cpp
--- kodi-19.1+dfsg2/xbmc/pvr/PVRManager.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/pvr/PVRManager.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -613,6 +613,9 @@
   /* start job to search for missing channel icons */
   TriggerSearchMissingChannelIcons();
 
+  /* try to play channel on startup */
+  TriggerPlayChannelOnStartup();
+
   /* trigger PVR data updates */
   TriggerChannelGroupsUpdate();
   TriggerChannelsUpdate();
@@ -807,26 +810,22 @@
 
 void CPVRManager::TriggerSearchMissingChannelIcons()
 {
-  if (IsStarted())
-  {
-    CJobManager::GetInstance().Submit([this] {
-      CPVRGUIChannelIconUpdater updater({ChannelGroups()->GetGroupAllTV(), ChannelGroups()->GetGroupAllRadio()}, true);
-      updater.SearchAndUpdateMissingChannelIcons();
-      return true;
-    });
-  }
+  m_pendingUpdates->Append("pvr-search-missing-channel-icons", [this]() {
+    CPVRGUIChannelIconUpdater updater(
+        {ChannelGroups()->GetGroupAllTV(), ChannelGroups()->GetGroupAllRadio()}, true);
+    updater.SearchAndUpdateMissingChannelIcons();
+    return true;
+  });
 }
 
 void CPVRManager::TriggerSearchMissingChannelIcons(const std::shared_ptr<CPVRChannelGroup>& group)
 {
-  if (IsStarted())
-  {
-    CJobManager::GetInstance().Submit([group] {
-      CPVRGUIChannelIconUpdater updater({group}, false);
-      updater.SearchAndUpdateMissingChannelIcons();
-      return true;
-    });
-  }
+  m_pendingUpdates->Append("pvr-search-missing-channel-icons-" + std::to_string(group->GroupID()),
+                           [group]() {
+                             CPVRGUIChannelIconUpdater updater({group}, false);
+                             updater.SearchAndUpdateMissingChannelIcons();
+                             return true;
+                           });
 }
 
 void CPVRManager::ConnectionStateChange(CPVRClient* client,
@@ -836,6 +835,10 @@
 {
   CJobManager::GetInstance().Submit([this, client, connectString, state, message] {
     Clients()->ConnectionStateChange(client, connectString, state, message);
+
+    if (state == PVR_CONNECTION_STATE_CONNECTED)
+      Start(); // start over
+
     return true;
   });
 }
diff -Nru kodi-19.1+dfsg2/xbmc/rendering/dx/DeviceResources.cpp kodi-19.2+dfsg1/xbmc/rendering/dx/DeviceResources.cpp
--- kodi-19.1+dfsg2/xbmc/rendering/dx/DeviceResources.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/rendering/dx/DeviceResources.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -24,6 +24,15 @@
 #include "platform/win32/CharsetConverter.h"
 #include "platform/win32/WIN32Util.h"
 
+#ifdef TARGET_WINDOWS_STORE
+#include <winrt/Windows.Graphics.Display.Core.h>
+
+extern "C"
+{
+#include <libavutil/rational.h>
+}
+#endif
+
 #ifdef _DEBUG
 #include <dxgidebug.h>
 #pragma comment(lib, "dxgi.lib")
@@ -94,14 +103,8 @@
 
   ReleaseBackBuffer();
   OnDeviceLost(true);
+  DestroySwapChain();
 
-  // leave fullscreen before destroying
-  BOOL bFullScreen;
-  m_swapChain->GetFullscreenState(&bFullScreen, nullptr);
-  if (!!bFullScreen)
-    m_swapChain->SetFullscreenState(false, nullptr);
-
-  m_swapChain = nullptr;
   m_adapter = nullptr;
   m_dxgiFactory = nullptr;
   m_output = nullptr;
@@ -170,6 +173,17 @@
     else
       mode->ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
   }
+#else
+  using namespace winrt::Windows::Graphics::Display::Core;
+
+  auto hdmiInfo = HdmiDisplayInformation::GetForCurrentView();
+  if (hdmiInfo) // Xbox only
+  {
+    auto currentMode = hdmiInfo.GetCurrentDisplayMode();
+    AVRational refresh = av_d2q(currentMode.RefreshRate(), 60000);
+    mode->RefreshRate.Numerator = refresh.num;
+    mode->RefreshRate.Denominator = refresh.den;
+  }
 #endif
 }
 
@@ -191,7 +205,7 @@
 
 bool DX::DeviceResources::SetFullScreen(bool fullscreen, RESOLUTION_INFO& res)
 {
-  if (!m_bDeviceCreated)
+  if (!m_bDeviceCreated || !m_swapChain)
     return false;
 
   critical_section::scoped_lock lock(m_criticalSection);
@@ -515,6 +529,21 @@
   return hr;
 }
 
+void DX::DeviceResources::DestroySwapChain()
+{
+  if (!m_swapChain)
+    return;
+
+  BOOL bFullcreen = 0;
+  m_swapChain->GetFullscreenState(&bFullcreen, nullptr);
+  if (!!bFullcreen)
+    m_swapChain->SetFullscreenState(false, nullptr); // mandatory before releasing swapchain
+  m_swapChain = nullptr;
+  m_deferrContext->Flush();
+  m_d3dContext->Flush();
+  m_IsTransferPQ = false;
+}
+
 void DX::DeviceResources::ResizeBuffers()
 {
   if (!m_bDeviceCreated)
@@ -525,7 +554,6 @@
   bool bHWStereoEnabled = RENDER_STEREO_MODE_HARDWAREBASED ==
                           CServiceBroker::GetWinSystem()->GetGfxContext().GetStereoMode();
   bool windowed = true;
-  bool isHdrEnabled = false;
   HRESULT hr = E_FAIL;
   DXGI_SWAP_CHAIN_DESC1 scDesc = {};
 
@@ -534,34 +562,16 @@
     BOOL bFullcreen = 0;
     m_swapChain->GetFullscreenState(&bFullcreen, nullptr);
     if (!!bFullcreen)
-    {
       windowed = false;
-    }
 
-    // check if swapchain needs to be recreated
     m_swapChain->GetDesc1(&scDesc);
-
-    if ((scDesc.Stereo == TRUE) != bHWStereoEnabled)
-    {
-      // check fullscreen state and go to windowing if necessary
-      if (!!bFullcreen)
-      {
-        m_swapChain->SetFullscreenState(false, nullptr); // mandatory before releasing swapchain
-      }
-      m_swapChain = nullptr;
-      m_deferrContext->Flush();
-      m_d3dContext->Flush();
-    }
+    if ((scDesc.Stereo == TRUE) != bHWStereoEnabled) // check if swapchain needs to be recreated
+      DestroySwapChain();
   }
 
-  isHdrEnabled = (HDR_STATUS::HDR_ON == CWIN32Util::GetWindowsHDRStatus());
-
-  if (m_swapChain != nullptr)
+  if (m_swapChain) // If the swap chain already exists, resize it.
   {
-    // If the swap chain already exists, resize it.
     m_swapChain->GetDesc1(&scDesc);
-    isHdrEnabled ? scDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM
-                 : scDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
     hr = m_swapChain->ResizeBuffers(scDesc.BufferCount, lround(m_outputSize.Width),
                                     lround(m_outputSize.Height), scDesc.Format,
                                     windowed ? 0 : DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH);
@@ -575,21 +585,34 @@
       // and correctly set up the new device.
       return;
     }
+    else if (hr == DXGI_ERROR_INVALID_CALL)
+    {
+      // Called when Windows HDR is toggled externally to Kodi.
+      // Is forced to re-create swap chain to avoid crash.
+      CreateWindowSizeDependentResources();
+      return;
+    }
     CHECK_ERR();
   }
-  else
+  else // Otherwise, create a new one using the same adapter as the existing Direct3D device.
   {
-    // Otherwise, create a new one using the same adapter as the existing Direct3D device.
+    HDR_STATUS hdrStatus = CWIN32Util::GetWindowsHDRStatus();
+    const bool isHdrEnabled = (hdrStatus == HDR_STATUS::HDR_ON);
+    const bool is10bitSafe = (hdrStatus != HDR_STATUS::HDR_UNSUPPORTED);
+
     DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
     swapChainDesc.Width = lround(m_outputSize.Width);
     swapChainDesc.Height = lround(m_outputSize.Height);
     swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
     swapChainDesc.Stereo = bHWStereoEnabled;
     swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-    // HDR 60 fps needs 6 buffers to avoid frame drops but it's good for all
-    swapChainDesc.BufferCount = 6;
+#ifdef TARGET_WINDOWS_DESKTOP
+    swapChainDesc.BufferCount = 6; // HDR 60 fps needs 6 buffers to avoid frame drops
+#else
+    swapChainDesc.BufferCount = 3; // Xbox don't like 6 backbuffers (3 is fine even for 4K 60 fps)
+#endif
     // FLIP_DISCARD improves performance (needed in some systems for 4K HDR 60 fps)
-    swapChainDesc.SwapEffect = (m_d3dFeatureLevel >= D3D_FEATURE_LEVEL_12_0)
+    swapChainDesc.SwapEffect = CSysInfo::IsWindowsVersionAtLeast(CSysInfo::WindowsVersionWin10)
                                    ? DXGI_SWAP_EFFECT_FLIP_DISCARD
                                    : DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
     swapChainDesc.Flags = windowed ? 0 : DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
@@ -604,7 +627,7 @@
     ComPtr<IDXGISwapChain1> swapChain;
     if (m_d3dFeatureLevel >= D3D_FEATURE_LEVEL_11_0 && !bHWStereoEnabled &&
         (CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_bTry10bitOutput ||
-         isHdrEnabled))
+         isHdrEnabled || is10bitSafe))
     {
       swapChainDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM;
       hr = CreateSwapChain(swapChainDesc, scFSDesc, &swapChain);
@@ -667,6 +690,11 @@
 {
   ReleaseBackBuffer();
 
+  DestroySwapChain();
+
+  if (!m_dxgiFactory->IsCurrent()) // HDR toggling requires re-create factory
+    CreateFactory();
+
   UpdateRenderTargetSize();
   ResizeBuffers();
 
@@ -858,7 +886,8 @@
   if (backbuferExists)
     ReleaseBackBuffer();
 
-  m_swapChain = nullptr;
+  DestroySwapChain();
+
   CreateDeviceResources();
   UpdateRenderTargetSize();
   ResizeBuffers();
@@ -922,8 +951,6 @@
     {
       CreateWindowSizeDependentResources();
     }
-    if (!m_dxgiFactory->IsCurrent())
-      CreateFactory();
   }
 
   if (m_d3dContext == m_deferrContext)
@@ -1123,7 +1150,7 @@
 {
   ComPtr<IDXGISwapChain4> swapChain4;
 
-  if (m_swapChain == nullptr)
+  if (!m_swapChain)
     return;
 
   if (SUCCEEDED(m_swapChain.As(&swapChain4)))
@@ -1169,7 +1196,7 @@
 {
   ComPtr<IDXGISwapChain3> swapChain3;
 
-  if (m_swapChain == nullptr)
+  if (!m_swapChain)
     return;
 
   if (SUCCEEDED(m_swapChain.As(&swapChain3)))
@@ -1203,14 +1230,7 @@
   if (m_swapChain && hdrStatus != HDR_STATUS::HDR_TOGGLE_FAILED)
   {
     CLog::LogF(LOGDEBUG, "Re-create swapchain due HDR <-> SDR switch");
-    BOOL bFullcreen = 0;
-    m_swapChain->GetFullscreenState(&bFullcreen, nullptr);
-    if (!!bFullcreen)
-      m_swapChain->SetFullscreenState(false, nullptr);
-    m_swapChain = nullptr;
-    m_deferrContext->Flush();
-    m_d3dContext->Flush();
-    m_IsTransferPQ = false;
+    DestroySwapChain();
   }
 
   DX::Windowing()->SetAlteringWindow(false);
@@ -1228,7 +1248,7 @@
 
 DEBUG_INFO_RENDER DX::DeviceResources::GetDebugInfo() const
 {
-  if (m_swapChain == nullptr)
+  if (!m_swapChain)
     return {};
 
   DXGI_SWAP_CHAIN_DESC1 desc = {};
@@ -1254,8 +1274,8 @@
       m_IsTransferPQ ? "PQ" : "SDR", m_IsHDROutput ? "on" : "off");
 
   info.videoOutput = StringUtils::Format(
-      "Output: {}x{}{} @ {:.2f} Hz, pixel: {} {}-bit, range: {} ({}-{})", desc.Width, desc.Height,
-      (md.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE) ? "p" : "i",
+      "Surfaces: {}x{}{} @ {:.3f} Hz, pixel: {} {}-bit, range: {} ({}-{})", desc.Width, desc.Height,
+      (md.ScanlineOrdering > DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE) ? "i" : "p",
       static_cast<double>(md.RefreshRate.Numerator) /
           static_cast<double>(md.RefreshRate.Denominator),
       (desc.Format == DXGI_FORMAT_R10G10B10A2_UNORM) ? "R10G10B10A2" : "B8G8R8A8", bits,
diff -Nru kodi-19.1+dfsg2/xbmc/rendering/dx/DeviceResources.h kodi-19.2+dfsg1/xbmc/rendering/dx/DeviceResources.h
--- kodi-19.1+dfsg2/xbmc/rendering/dx/DeviceResources.h	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/rendering/dx/DeviceResources.h	2021-10-06 08:49:25.000000000 +0000
@@ -123,6 +123,7 @@
     };
 
     HRESULT CreateSwapChain(DXGI_SWAP_CHAIN_DESC1 &desc, DXGI_SWAP_CHAIN_FULLSCREEN_DESC &fsDesc, IDXGISwapChain1 **ppSwapChain) const;
+    void DestroySwapChain();
     void CreateDeviceIndependentResources();
     void CreateDeviceResources();
     void CreateWindowSizeDependentResources();
diff -Nru kodi-19.1+dfsg2/xbmc/settings/AdvancedSettings.cpp kodi-19.2+dfsg1/xbmc/settings/AdvancedSettings.cpp
--- kodi-19.1+dfsg2/xbmc/settings/AdvancedSettings.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/settings/AdvancedSettings.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -349,7 +349,6 @@
 #endif
   m_showExitButton = true;
   m_splashImage = true;
-  m_showAllDependencies = false;
 
   m_playlistRetries = 100;
   m_playlistTimeout = 20; // 20 seconds timeout
@@ -897,7 +896,6 @@
   XMLUtils::GetBoolean(pRootElement, "fullscreen", m_startFullScreen);
 #endif
   XMLUtils::GetBoolean(pRootElement, "splash", m_splashImage);
-  XMLUtils::GetBoolean(pRootElement, "showalldependencies", m_showAllDependencies);
   XMLUtils::GetBoolean(pRootElement, "showexitbutton", m_showExitButton);
   XMLUtils::GetBoolean(pRootElement, "canwindowed", m_canWindowed);
 
diff -Nru kodi-19.1+dfsg2/xbmc/settings/AdvancedSettings.h kodi-19.2+dfsg1/xbmc/settings/AdvancedSettings.h
--- kodi-19.1+dfsg2/xbmc/settings/AdvancedSettings.h	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/settings/AdvancedSettings.h	2021-10-06 08:49:25.000000000 +0000
@@ -302,12 +302,6 @@
     bool m_GLRectangleHack;
     int m_iSkipLoopFilter;
 
-    /*!< @brief Decision flag to show or hide specific dependencies in the list of the AddonInfo dialog
-    as this information usually adds no value for a consumer.
-    True to recursively show any dependency of the selected add-on
-    False to hide 'low-level' dependencies like e.g. scripts/modules (default) */
-    bool m_showAllDependencies;
-
     bool m_bVirtualShares;
     bool m_bTry10bitOutput;
 
diff -Nru kodi-19.1+dfsg2/xbmc/utils/StringUtils.h kodi-19.2+dfsg1/xbmc/utils/StringUtils.h
--- kodi-19.1+dfsg2/xbmc/utils/StringUtils.h	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/utils/StringUtils.h	2021-10-06 08:49:25.000000000 +0000
@@ -36,6 +36,9 @@
 #if FMT_VERSION >= 40000
 #include <fmt/printf.h>
 #endif
+#if FMT_VERSION >= 80000
+#include <fmt/xchar.h>
+#endif
 
 #include "XBDateTime.h"
 #include "utils/params_check_macros.h"
diff -Nru kodi-19.1+dfsg2/xbmc/video/VideoDatabase.cpp kodi-19.2+dfsg1/xbmc/video/VideoDatabase.cpp
--- kodi-19.1+dfsg2/xbmc/video/VideoDatabase.cpp	2021-05-08 16:20:52.000000000 +0000
+++ kodi-19.2+dfsg1/xbmc/video/VideoDatabase.cpp	2021-10-06 08:49:25.000000000 +0000
@@ -2449,7 +2449,7 @@
     details.m_iIdRating = AddRatings(idMovie, MediaTypeMovie, details.m_ratings, details.GetDefaultRating());
 
     // add unique ids
-    details.m_iIdUniqueID = UpdateUniqueIDs(idMovie, MediaTypeMovie, details);
+    details.m_iIdUniqueID = AddUniqueIDs(idMovie, MediaTypeMovie, details);
 
     // add set...
     int idSet = -1;
@@ -2733,7 +2733,7 @@
   details.m_iIdRating = AddRatings(idTvShow, MediaTypeTvShow, details.m_ratings, details.GetDefaultRating());
 
   // add unique ids
-  details.m_iIdUniqueID = UpdateUniqueIDs(idTvShow, MediaTypeTvShow, details);
+  details.m_iIdUniqueID = AddUniqueIDs(idTvShow, MediaTypeTvShow, details);
 
   // add "all seasons" - the rest are added in SetDetailsForEpisode
   AddSeason(idTvShow, -1);
@@ -2865,7 +2865,7 @@
     details.m_iIdRating = AddRatings(idEpisode, MediaTypeEpisode, details.m_ratings, details.GetDefaultRating());
 
     // add unique ids
-    details.m_iIdUniqueID = UpdateUniqueIDs(idEpisode, MediaTypeEpisode, details);
+    details.m_iIdUniqueID = AddUniqueIDs(idEpisode, MediaTypeEpisode, details);
 
     if (details.HasStreamDetails())
     {

Reply to: