diff -Nru kodi-18.6+git20200408.1716-final/addons/resource.language.en_gb/resources/strings.po kodi-18.7+git20200520.1011-final/addons/resource.language.en_gb/resources/strings.po --- kodi-18.6+git20200408.1716-final/addons/resource.language.en_gb/resources/strings.po 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/addons/resource.language.en_gb/resources/strings.po 2012-11-04 08:41:54.000000000 +0000 @@ -5753,7 +5753,7 @@ #: xbmc/dialogs/GUIDialogGamepad.cpp #: xbmc/dialogs/GUIDialogNumeric.cpp msgctxt "#12343" -msgid "retries left " +msgid "retries left" msgstr "" #: xbmc/dialogs/GUIDialogGamepad.cpp diff -Nru kodi-18.6+git20200408.1716-final/addons/skin.estouchy/xml/ViewsList.xml kodi-18.7+git20200520.1011-final/addons/skin.estouchy/xml/ViewsList.xml --- kodi-18.6+git20200408.1716-final/addons/skin.estouchy/xml/ViewsList.xml 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/addons/skin.estouchy/xml/ViewsList.xml 2012-11-04 08:41:54.000000000 +0000 @@ -113,7 +113,7 @@ 60 40 flagging/source/Set.png - [Container.Content(Movies) | Container.Content(Sets)] + ListItem.IsCollection + ListItem.IsCollection 48r @@ -122,7 +122,7 @@ 26 keep OverlayWatching.png - [Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos) | Container.Content(Videos)] + ListItem.IsResumable + ListItem.IsResumable 50r @@ -130,7 +130,7 @@ 30 30 $INFO[ListItem.Overlay] - [Container.Content(Movies) | Container.Content(TVShows) | Container.Content(Seasons) | Container.Content(Episodes) | Container.Content(MusicVideos) | Container.Content(Videos)] + !ListItem.IsResumable + !ListItem.IsResumable $PARAM[label2-posx] @@ -255,7 +255,7 @@ 60 40 flagging/source/Set.png - [Container.Content(Movies) | Container.Content(Sets)] + ListItem.IsCollection + ListItem.IsCollection 48r @@ -264,7 +264,7 @@ 26 keep OverlayWatching.png - [Container.Content(Movies) | Container.Content(Episodes) | Container.Content(MusicVideos) | Container.Content(Videos)] + ListItem.IsResumable + ListItem.IsResumable 50r @@ -272,7 +272,7 @@ 30 30 $INFO[ListItem.Overlay] - [Container.Content(Movies) | Container.Content(TVShows) | Container.Content(Seasons) | Container.Content(Episodes) | Container.Content(MusicVideos) | Container.Content(Videos)] + !ListItem.IsResumable + !ListItem.IsResumable $PARAM[label2-posx] diff -Nru kodi-18.6+git20200408.1716-final/addons/skin.estouchy/xml/ViewsThumbnail.xml kodi-18.7+git20200520.1011-final/addons/skin.estouchy/xml/ViewsThumbnail.xml --- kodi-18.6+git20200408.1716-final/addons/skin.estouchy/xml/ViewsThumbnail.xml 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/addons/skin.estouchy/xml/ViewsThumbnail.xml 2012-11-04 08:41:54.000000000 +0000 @@ -72,6 +72,22 @@ OverlayWatched.png Window.IsVisible(AddonBrowser) + String.IsEqual(ListItem.Label2,$LOCALIZE[305]) + + 182 + 4 + 26 + 26 + keep + OverlayWatching.png + ListItem.IsResumable + + + 180 + 2 + 30 + 30 + $INFO[ListItem.Overlay] + @@ -128,6 +144,23 @@ OverlayWatched.png Window.IsVisible(AddonBrowser) + String.IsEqual(ListItem.Label2,$LOCALIZE[305]) + + 182 + 4 + 26 + 26 + keep + OverlayWatching.png + ListItem.IsResumable + + + 180 + 2 + 30 + 30 + $INFO[ListItem.Overlay] + !ListItem.IsResumable + @@ -181,11 +214,21 @@ ListItem.IsCollection + 172 + 262 + 26 + 26 + keep + OverlayWatching.png + ListItem.IsResumable + + 170 260 30 30 $INFO[ListItem.Overlay] + !ListItem.IsResumable @@ -240,11 +283,21 @@ ListItem.IsCollection + 172 + 262 + 26 + 26 + keep + OverlayWatching.png + ListItem.IsResumable + + 170 260 30 30 $INFO[ListItem.Overlay] + !ListItem.IsResumable @@ -291,11 +344,21 @@ $INFO[ListItem.VideoResolution,flagging/resolution/,.png] + 265 + 147 + 26 + 26 + keep + OverlayWatching.png + ListItem.IsResumable + + 263 145 30 30 $INFO[ListItem.Overlay] + !ListItem.IsResumable @@ -342,11 +405,21 @@ $INFO[ListItem.VideoResolution,flagging/resolution/,.png] + 265 + 147 + 26 + 26 + keep + OverlayWatching.png + ListItem.IsResumable + + 263 145 30 30 $INFO[ListItem.Overlay] + !ListItem.IsResumable diff -Nru kodi-18.6+git20200408.1716-final/addons/skin.estuary/xml/SkinSettings.xml kodi-18.7+git20200520.1011-final/addons/skin.estuary/xml/SkinSettings.xml --- kodi-18.6+git20200408.1716-final/addons/skin.estuary/xml/SkinSettings.xml 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/addons/skin.estuary/xml/SkinSettings.xml 2012-11-04 08:41:54.000000000 +0000 @@ -328,8 +328,8 @@ vertical conditional - 1000 - 1000 + 10000 + 10000 Visible Hidden WindowOpen diff -Nru kodi-18.6+git20200408.1716-final/BUILDDATE kodi-18.7+git20200520.1011-final/BUILDDATE --- kodi-18.6+git20200408.1716-final/BUILDDATE 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/BUILDDATE 2012-11-04 08:41:54.000000000 +0000 @@ -1 +1 @@ -20200408 +20200520 diff -Nru kodi-18.6+git20200408.1716-final/cmake/installdata/test-reference-data.txt kodi-18.7+git20200520.1011-final/cmake/installdata/test-reference-data.txt --- kodi-18.6+git20200408.1716-final/cmake/installdata/test-reference-data.txt 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/cmake/installdata/test-reference-data.txt 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,6 @@ xbmc/utils/test/CXBMCTinyXML-test.xml xbmc/utils/test/data/language/Spanish/strings.po +xbmc/filesystem/test/extendedlocalheader.zip xbmc/filesystem/test/reffile.txt xbmc/filesystem/test/reffile.txt.rar xbmc/filesystem/test/reffile.txt.zip diff -Nru kodi-18.6+git20200408.1716-final/cmake/scripts/osx/ArchSetup.cmake kodi-18.7+git20200520.1011-final/cmake/scripts/osx/ArchSetup.cmake --- kodi-18.6+git20200408.1716-final/cmake/scripts/osx/ArchSetup.cmake 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/cmake/scripts/osx/ArchSetup.cmake 2012-11-04 08:41:54.000000000 +0000 @@ -34,7 +34,7 @@ "-framework ApplicationServices" "-framework AppKit" "-framework CoreAudio" "-framework AudioToolbox" "-framework CoreGraphics" "-framework CoreMedia" - "-framework VideoToolbox") + "-framework VideoToolbox" "-framework Security") set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9) set(CMAKE_XCODE_ATTRIBUTE_CLANG_LINK_OBJC_RUNTIME OFF) diff -Nru kodi-18.6+git20200408.1716-final/debian/changelog kodi-18.7+git20200520.1011-final/debian/changelog --- kodi-18.6+git20200408.1716-final/debian/changelog 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/debian/changelog 2012-11-04 08:41:54.000000000 +0000 @@ -1,4 +1,140 @@ -kodi (2:18.6+git20200408.1716-final-0focal) focal; urgency=high +kodi (2:18.7+git20200520.1011-final-0focal) focal; urgency=high + + [DaveTBlake] + * Bump for 18.7 final + + [DaveTBlake] + * Prevent album artists being left blank when merging scraped album results and preferring scraper results is enabled + + [Matt Huisman] + * Revert "[Android] pause audio playback when headphone is disconnected" + + [DaveTBlake] + * Fix bug with Audiolibrary.GetArtists return of "isalbumartist" field + + [cpmw167] + * [bluray] fix playback of bus encryption enabled discs + + [DaveTBlake] + * Only check if items are .iso and expand disc image when in file view + + [Peter] + * [bluray] Correctly recognize subtitle language Backport of #17801 + + [phunkyfish] + * [video][backport] clear library entries from plugins if media source is removed. + + [phunkyfish] + * [videoplayer] Fix TS Streams by disallowing streaminfo for realtime streams + + [Kai Sommerfeld] + * [dialogs][guillib] CGUIDialogKaiToast now only closes the dialog if the whole toast text was displayed at least once. + + [howie-f] + * [Subtitles] fix smi subtitles to use quoted start tags + + [enen92] + * [Python] Fix ControlTextBox actions before being added to the window + + [Roman Artiukhin] + * Fix watching icons are not shown when content type is not set + + [montellese] + * Revert "Print the mirror redirected to for easier debugging of of mirror issues" + + [Arne Morten Kvarving] + * fixed: guard against assert in tinyxml + + [djp952] + * [PVR][Leia] EPG corruption when new channels added during startup + + [howie-f] + * [CurlFile] proper setup proxy credentials + + [roke] + * fixed checking if proxy and username pass are empty + + [howie-f] + * [LanguageCodes] Add "Swiss german" and "Portuguese (Brazil)" + + [Pär Björklund] + * Fix stack overflow when trying to find nfo files in a rar file. + + [enen92] + * Implement range check in URIUtils::resolvePath + + [ronie] + * [Estuary] fix navigation in skinsettings + + [peak3d] + * [Backport] Don't send UNFOCUS_ALL after touch action + + [peak3d] + * [Android][Backport] MediaCodec: Use JNI instead NDK + + [Sam Nazarko] + * CProfileManager: do not wait for bool uiInitializationFinished or skins will load without all elements ready + + [ChrisEt] + * added support for ZIP extended local headers + + [fritsch] + * Revert "DVDVideoCodecAndroidMediaCodec: Properly set MAX WIDTH and MAX HEIGHT (thanks to cerarp)" + + [ronie] + * [Leia] Favourites Dialog - fix crash + + [Alwin Esch] + * [addons][vfs] fix Kodi start crash if incompatible VFS addon present + + [Qian Yun] + * [Android] pause audio playback when headphone is disconnected + + [fritsch] + * Android: Don't reset user set volume + + [CastagnaIT] + * Do not force flip for hebrew/arabic languages + + [CastagnaIT] + * Revert "[subtitles] decode html escape characters (reverted from commit 56ff2ab08874ab78b7341be092aed0d9b37bb175)" + + [Alwin Esch] + * [vfs][addons] fix title show of compressed package dir + + [Andrey Filipenkov] + * [ios] disable GUI insets for external screen + + [Andrey Filipenkov] + * [ios] apply safe area insets to Kodi GUI + + [fritsch] + * Revert "AESinkAudioTrack: Support multi channel float" + + [Alwin Esch] + * [addons] fix stupid circumstance with addon settings on folder with file extension + + [peak3d] + * [Backport] bump gnutls (3.6.11.1) and nettle(3.5.1) + + [howie-f] + * [profiles] fix: save lock preferences + + [howie-f] + * GUIPassword.h: fix doxygen header + + [howie-f] + * Extend CheckMenuLock to check Mediasources (video and music) if needed + + [howie-f] + * Reimplement functions for checking Master-/Medialocks + + [howie-f] + * Introduce and refactor MediaLockState enum + + [howie-f] + * Cleanup: fix include order + [peak3d] * [Backport] Don't send UNFOCUS_ALL after touch action diff -Nru kodi-18.6+git20200408.1716-final/debian/changelog.tmp kodi-18.7+git20200520.1011-final/debian/changelog.tmp --- kodi-18.6+git20200408.1716-final/debian/changelog.tmp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/debian/changelog.tmp 2012-11-04 08:41:54.000000000 +0000 @@ -1,4 +1,140 @@ -kodi (2:18.6+git20200408.1716-final-0dist) dist; urgency=high +kodi (2:18.7+git20200520.1011-final-0dist) dist; urgency=high + + [DaveTBlake] + * Bump for 18.7 final + + [DaveTBlake] + * Prevent album artists being left blank when merging scraped album results and preferring scraper results is enabled + + [Matt Huisman] + * Revert "[Android] pause audio playback when headphone is disconnected" + + [DaveTBlake] + * Fix bug with Audiolibrary.GetArtists return of "isalbumartist" field + + [cpmw167] + * [bluray] fix playback of bus encryption enabled discs + + [DaveTBlake] + * Only check if items are .iso and expand disc image when in file view + + [Peter] + * [bluray] Correctly recognize subtitle language Backport of #17801 + + [phunkyfish] + * [video][backport] clear library entries from plugins if media source is removed. + + [phunkyfish] + * [videoplayer] Fix TS Streams by disallowing streaminfo for realtime streams + + [Kai Sommerfeld] + * [dialogs][guillib] CGUIDialogKaiToast now only closes the dialog if the whole toast text was displayed at least once. + + [howie-f] + * [Subtitles] fix smi subtitles to use quoted start tags + + [enen92] + * [Python] Fix ControlTextBox actions before being added to the window + + [Roman Artiukhin] + * Fix watching icons are not shown when content type is not set + + [montellese] + * Revert "Print the mirror redirected to for easier debugging of of mirror issues" + + [Arne Morten Kvarving] + * fixed: guard against assert in tinyxml + + [djp952] + * [PVR][Leia] EPG corruption when new channels added during startup + + [howie-f] + * [CurlFile] proper setup proxy credentials + + [roke] + * fixed checking if proxy and username pass are empty + + [howie-f] + * [LanguageCodes] Add "Swiss german" and "Portuguese (Brazil)" + + [Pär Björklund] + * Fix stack overflow when trying to find nfo files in a rar file. + + [enen92] + * Implement range check in URIUtils::resolvePath + + [ronie] + * [Estuary] fix navigation in skinsettings + + [peak3d] + * [Backport] Don't send UNFOCUS_ALL after touch action + + [peak3d] + * [Android][Backport] MediaCodec: Use JNI instead NDK + + [Sam Nazarko] + * CProfileManager: do not wait for bool uiInitializationFinished or skins will load without all elements ready + + [ChrisEt] + * added support for ZIP extended local headers + + [fritsch] + * Revert "DVDVideoCodecAndroidMediaCodec: Properly set MAX WIDTH and MAX HEIGHT (thanks to cerarp)" + + [ronie] + * [Leia] Favourites Dialog - fix crash + + [Alwin Esch] + * [addons][vfs] fix Kodi start crash if incompatible VFS addon present + + [Qian Yun] + * [Android] pause audio playback when headphone is disconnected + + [fritsch] + * Android: Don't reset user set volume + + [CastagnaIT] + * Do not force flip for hebrew/arabic languages + + [CastagnaIT] + * Revert "[subtitles] decode html escape characters (reverted from commit 56ff2ab08874ab78b7341be092aed0d9b37bb175)" + + [Alwin Esch] + * [vfs][addons] fix title show of compressed package dir + + [Andrey Filipenkov] + * [ios] disable GUI insets for external screen + + [Andrey Filipenkov] + * [ios] apply safe area insets to Kodi GUI + + [fritsch] + * Revert "AESinkAudioTrack: Support multi channel float" + + [Alwin Esch] + * [addons] fix stupid circumstance with addon settings on folder with file extension + + [peak3d] + * [Backport] bump gnutls (3.6.11.1) and nettle(3.5.1) + + [howie-f] + * [profiles] fix: save lock preferences + + [howie-f] + * GUIPassword.h: fix doxygen header + + [howie-f] + * Extend CheckMenuLock to check Mediasources (video and music) if needed + + [howie-f] + * Reimplement functions for checking Master-/Medialocks + + [howie-f] + * Introduce and refactor MediaLockState enum + + [howie-f] + * Cleanup: fix include order + [peak3d] * [Backport] Don't send UNFOCUS_ALL after touch action diff -Nru kodi-18.6+git20200408.1716-final/debian/changelog.tmp.old kodi-18.7+git20200520.1011-final/debian/changelog.tmp.old --- kodi-18.6+git20200408.1716-final/debian/changelog.tmp.old 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/debian/changelog.tmp.old 2012-11-04 08:41:54.000000000 +0000 @@ -1,6 +1,61 @@ kodi (2:18.0+git20180719.0202-3231481-0dist) dist; urgency=high [peak3d] + * [Backport] Don't send UNFOCUS_ALL after touch action + + [peak3d] + * [Android][Backport] MediaCodec: Use JNI instead NDK + + [Sam Nazarko] + * CProfileManager: do not wait for bool uiInitializationFinished or skins will load without all elements ready + + [fritsch] + * Revert "DVDVideoCodecAndroidMediaCodec: Properly set MAX WIDTH and MAX HEIGHT (thanks to cerarp)" + + [ronie] + * [Leia] Favourites Dialog - fix crash + + [Alwin Esch] + * [addons][vfs] fix Kodi start crash if incompatible VFS addon present + + [Alwin Esch] + * [vfs][addons] fix title show of compressed package dir + + [Andrey Filipenkov] + * [ios] disable GUI insets for external screen + + [Andrey Filipenkov] + * [ios] apply safe area insets to Kodi GUI + + [fritsch] + * Revert "AESinkAudioTrack: Support multi channel float" + + [Alwin Esch] + * [addons] fix stupid circumstance with addon settings on folder with file extension + + [peak3d] + * [Backport] bump gnutls (3.6.11.1) and nettle(3.5.1) + + [howie-f] + * [profiles] fix: save lock preferences + + [howie-f] + * GUIPassword.h: fix doxygen header + + [howie-f] + * Extend CheckMenuLock to check Mediasources (video and music) if needed + + [howie-f] + * Reimplement functions for checking Master-/Medialocks + + [howie-f] + * Introduce and refactor MediaLockState enum + + [howie-f] + * Cleanup: fix include order + + + [peak3d] * [Android][Backport] MediaCodec: Use JNI instead NDK [Sam Nazarko] diff -Nru kodi-18.6+git20200408.1716-final/debian/rules kodi-18.7+git20200520.1011-final/debian/rules --- kodi-18.6+git20200408.1716-final/debian/rules 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/debian/rules 2012-11-04 08:41:54.000000000 +0000 @@ -12,11 +12,14 @@ export DEB_CXXFLAGS_MAINT_APPEND = -O3 UBUNTU_RELEASE ?= $(shell sed -n '/VERSION_ID/ s/VERSION_ID="\([0-9.]*\)"/\1/p' /etc/os-release) -#TRUSTY := $(shell dpkg --compare-versions $(UBUNTU_RELEASE) eq 14.04 && echo yes) BUILD_WAYLAND := $(shell dpkg --compare-versions $(UBUNTU_RELEASE) ge 17.10 && echo yes || echo no) BUILD_GBM := $(shell dpkg --compare-versions $(UBUNTU_RELEASE) ge 18.04 && echo yes || echo no) +USE_LTO := $(shell dpkg --compare-versions $(UBUNTU_RELEASE) ge 18.04 && echo yes || echo no) NUMCPU := $(shell grep -c processor /proc/cpuinfo) +ifeq ($(USE_LTO),no) + NUMCPU = OFF +endif DVDREAD = $(shell ls -1tr tools/depends/target/libdvdread/libdvdread-*.tar.gz | tail -1) DVDNAV = $(shell ls -1tr tools/depends/target/libdvdnav/libdvdnav-*.tar.gz | tail -1) Binary files /tmp/tmp0DZV5u/kSZJC6I1fw/kodi-18.6+git20200408.1716-final/media/splash.jpg and /tmp/tmp0DZV5u/UU5Xf7IkiM/kodi-18.7+git20200520.1011-final/media/splash.jpg differ diff -Nru kodi-18.6+git20200408.1716-final/project/BuildDependencies/scripts/get_formed.cmd kodi-18.7+git20200520.1011-final/project/BuildDependencies/scripts/get_formed.cmd --- kodi-18.6+git20200408.1716-final/project/BuildDependencies/scripts/get_formed.cmd 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/project/BuildDependencies/scripts/get_formed.cmd 2012-11-04 08:41:54.000000000 +0000 @@ -64,7 +64,7 @@ ) ELSE ( CALL :setSubStageName Downloading %1... SET DOWNLOAD_URL=%KODI_MIRROR%/build-deps/win32/%1 - %WGET% -S --quiet --tries=5 --retry-connrefused --waitretry=2 --show-progress "!DOWNLOAD_URL!" 2>&1 | findstr /L /I "Location:" + %WGET% --quiet --tries=5 --retry-connrefused --waitretry=2 --show-progress "!DOWNLOAD_URL!" 2>&1 REM Apparently there's a quirk in cmd so this means if error level => 1 IF ERRORLEVEL 1 ( ECHO %1^|Download of !DOWNLOAD_URL! failed >> %FORMED_FAILED_LIST% diff -Nru kodi-18.6+git20200408.1716-final/tools/depends/target/gnutls/02-darwin-getentropy.patch kodi-18.7+git20200520.1011-final/tools/depends/target/gnutls/02-darwin-getentropy.patch --- kodi-18.6+git20200408.1716-final/tools/depends/target/gnutls/02-darwin-getentropy.patch 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/tools/depends/target/gnutls/02-darwin-getentropy.patch 2012-11-04 08:41:54.000000000 +0000 @@ -1,14 +1,15 @@ ---- a/configure.ac -+++ b/configure.ac -@@ -220,6 +220,7 @@ - rnd_variant=getrandom], - [AC_MSG_RESULT(no)]) +diff -Naur a/configure.ac b/configure.ac +--- a/configure.ac 2019-12-02 08:32:16.000000000 -0800 ++++ b/configure.ac 2020-01-31 10:25:36.473631501 -0800 +@@ -278,6 +278,7 @@ + + AM_CONDITIONAL(HAVE_KERN_ARND, test "$rnd_variant" = "kern_arnd") +if test "x$have_macosx" != "xyes"; then AC_MSG_CHECKING([for getentropy]) AC_LINK_IFELSE([AC_LANG_PROGRAM([ #include -@@ -233,6 +234,7 @@ +@@ -294,6 +295,7 @@ AC_DEFINE([HAVE_GETENTROPY], 1, [Enable the OpenBSD getentropy function]) rnd_variant=getentropy], [AC_MSG_RESULT(no)]) diff -Nru kodi-18.6+git20200408.1716-final/tools/depends/target/gnutls/add-dl-as-private-lib.patch kodi-18.7+git20200520.1011-final/tools/depends/target/gnutls/add-dl-as-private-lib.patch --- kodi-18.6+git20200408.1716-final/tools/depends/target/gnutls/add-dl-as-private-lib.patch 1970-01-01 00:00:00.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/tools/depends/target/gnutls/add-dl-as-private-lib.patch 2012-11-04 08:41:54.000000000 +0000 @@ -0,0 +1,26 @@ +diff --git a/configure.ac b/configure.ac +index db1ce841f..264712b56 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -512,6 +512,9 @@ LT_INIT([disable-static,win32-dll,shared]) + + + AC_LIB_HAVE_LINKFLAGS(dl,, [#include ], [dladdr (0, 0);]) ++if test "x$HAVE_LIBDL" = "xyes"; then ++ AC_SUBST([LIBDL], [-ldl]) ++fi + + AC_ARG_ENABLE(fips140-mode, + AS_HELP_STRING([--enable-fips140-mode], [enable FIPS140-2 mode]), +diff --git a/lib/gnutls.pc.in b/lib/gnutls.pc.in +index ffad3e168..15b990764 100644 +--- a/lib/gnutls.pc.in ++++ b/lib/gnutls.pc.in +@@ -19,6 +19,6 @@ Description: Transport Security Layer implementation for the GNU system + URL: https://www.gnutls.org/ + Version: @VERSION@ + Libs: -L${libdir} -lgnutls +-Libs.private: @LIBINTL@ @LIBSOCKET@ @INET_PTON_LIB@ @LIBPTHREAD@ @LIB_SELECT@ @TSS_LIBS@ @GMP_LIBS@ @LIBUNISTRING@ @LIBIDN2_LIBS@ @LIBATOMIC_LIBS@ ++Libs.private: @LIBINTL@ @LIBSOCKET@ @INET_PTON_LIB@ @LIBPTHREAD@ @LIB_SELECT@ @TSS_LIBS@ @GMP_LIBS@ @LIBUNISTRING@ @LIBIDN2_LIBS@ @LIBATOMIC_LIBS@ @LIBDL@ + @GNUTLS_REQUIRES_PRIVATE@ + Cflags: -I${includedir} diff -Nru kodi-18.6+git20200408.1716-final/tools/depends/target/gnutls/Makefile kodi-18.7+git20200520.1011-final/tools/depends/target/gnutls/Makefile --- kodi-18.6+git20200408.1716-final/tools/depends/target/gnutls/Makefile 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/tools/depends/target/gnutls/Makefile 2012-11-04 08:41:54.000000000 +0000 @@ -1,9 +1,9 @@ include ../../Makefile.include -DEPS= ../../Makefile.include Makefile size-max.patch 02-darwin-getentropy.patch +DEPS= ../../Makefile.include Makefile size-max.patch 02-darwin-getentropy.patch remove-weak_import-check-for-osx.patch add-dl-as-private-lib.patch # lib name, version LIBNAME=gnutls -VERSION=3.5.10 +VERSION=3.6.11.1 SOURCE=$(LIBNAME)-$(VERSION) ARCHIVE=$(SOURCE).tar.xz @@ -15,10 +15,9 @@ endif # configuration settings -CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \ - ./configure --prefix=$(PREFIX) --disable-shared --without-p11-kit --disable-nls --with-included-unistring \ +CONFIGURE=./configure --prefix=$(PREFIX) --disable-shared --without-p11-kit --disable-nls --with-included-unistring \ --with-included-libtasn1 --enable-local-libopts --disable-doc --disable-tests --disable-guile \ - $(CONFIGURE_HACKS) + --disable-tools $(CONFIGURE_HACKS) LIBDYLIB=$(PLATFORM)/lib/.libs/lib$(LIBNAME).a @@ -32,6 +31,8 @@ cd $(PLATFORM); $(ARCHIVE_TOOL) $(ARCHIVE_TOOL_FLAGS) $(TARBALLS_LOCATION)/$(ARCHIVE) cd $(PLATFORM); patch -p0 < ../size-max.patch cd $(PLATFORM); patch -p1 -i ../02-darwin-getentropy.patch + cd $(PLATFORM); patch -p1 -i ../remove-weak_import-check-for-osx.patch + cd $(PLATFORM); patch -p1 -i ../add-dl-as-private-lib.patch cd $(PLATFORM); $(AUTORECONF) -vif cd $(PLATFORM); $(CONFIGURE) diff -Nru kodi-18.6+git20200408.1716-final/tools/depends/target/gnutls/remove-weak_import-check-for-osx.patch kodi-18.7+git20200520.1011-final/tools/depends/target/gnutls/remove-weak_import-check-for-osx.patch --- kodi-18.6+git20200408.1716-final/tools/depends/target/gnutls/remove-weak_import-check-for-osx.patch 1970-01-01 00:00:00.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/tools/depends/target/gnutls/remove-weak_import-check-for-osx.patch 2012-11-04 08:41:54.000000000 +0000 @@ -0,0 +1,17 @@ +--- a/configure.ac 2020-01-25 08:26:59.223068640 -0800 ++++ b/configure.ac 2020-01-25 08:26:38.846233553 -0800 +@@ -122,14 +122,6 @@ + ;; + *darwin*) + have_macosx=yes +- save_LDFLAGS="$LDFLAGS" +- dnl Try to use -no_weak_imports if available. This makes sure we +- dnl error out when linking to a function that doesn't exist in the +- dnl intended minimum runtime version. +- LDFLAGS="$LDFLAGS -Wl,-no_weak_imports" +- AC_MSG_CHECKING([whether the linker supports -Wl,-no_weak_imports]) +- AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], +- [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no); LDFLAGS="$save_LDFLAGS"]) + ;; + *solaris*) + have_elf=yes diff -Nru kodi-18.6+git20200408.1716-final/tools/depends/target/nettle/Makefile kodi-18.7+git20200520.1011-final/tools/depends/target/nettle/Makefile --- kodi-18.6+git20200408.1716-final/tools/depends/target/nettle/Makefile 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/tools/depends/target/nettle/Makefile 2012-11-04 08:41:54.000000000 +0000 @@ -3,7 +3,7 @@ # lib name, version LIBNAME=nettle -VERSION=3.2 +VERSION=3.5.1 SOURCE=$(LIBNAME)-$(VERSION) ARCHIVE=$(SOURCE).tar.gz diff -Nru kodi-18.6+git20200408.1716-final/VERSION kodi-18.7+git20200520.1011-final/VERSION --- kodi-18.6+git20200408.1716-final/VERSION 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/VERSION 2012-11-04 08:41:54.000000000 +0000 @@ -1 +1 @@ -8e967df921 +f14f7a84e3 diff -Nru kodi-18.6+git20200408.1716-final/version.txt kodi-18.7+git20200520.1011-final/version.txt --- kodi-18.6+git20200408.1716-final/version.txt 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/version.txt 2012-11-04 08:41:54.000000000 +0000 @@ -1,12 +1,12 @@ APP_NAME Kodi COMPANY_NAME XBMC Foundation -COPYRIGHT_YEARS 2005-2019 +COPYRIGHT_YEARS 2005-2020 WEBSITE http://kodi.tv VERSION_MAJOR 18 -VERSION_MINOR 6 +VERSION_MINOR 7 VERSION_TAG -VERSION_CODE 18.6.0 -ADDON_API 18.6.0 +VERSION_CODE 18.7.0 +ADDON_API 18.7.0 APP_PACKAGE org.xbmc.kodi PACKAGE_IDENTITY XBMCFoundation.Kodi PACKAGE_PUBLISHER C62BD90A-CDD8-477F-96C3-B25992247B97 diff -Nru kodi-18.6+git20200408.1716-final/xbmc/addons/Addon.cpp kodi-18.7+git20200520.1011-final/xbmc/addons/Addon.cpp --- kodi-18.6+git20200408.1716-final/xbmc/addons/Addon.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/addons/Addon.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -161,9 +161,7 @@ // break down the path into directories std::string strAddon = URIUtils::GetDirectory(m_userSettingsPath); - URIUtils::RemoveSlashAtEnd(strAddon); std::string strRoot = URIUtils::GetDirectory(strAddon); - URIUtils::RemoveSlashAtEnd(strRoot); // create the individual folders if (!CDirectory::Exists(strRoot)) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/addons/binary-addons/AddonDll.cpp kodi-18.7+git20200520.1011-final/xbmc/addons/binary-addons/AddonDll.cpp --- kodi-18.6+git20200408.1716-final/xbmc/addons/binary-addons/AddonDll.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/addons/binary-addons/AddonDll.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -487,8 +487,11 @@ addonMinVersion.asString(), addonVersion.asString()); - CEventLog &eventLog = CServiceBroker::GetEventLog(); - eventLog.AddWithNotification(EventPtr(new CNotificationEvent(Name(), 24152, EventLevel::Error))); + if (CServiceBroker::GetGUI()) + { + CEventLog &eventLog = CServiceBroker::GetEventLog(); + eventLog.AddWithNotification(EventPtr(new CNotificationEvent(Name(), 24152, EventLevel::Error))); + } return false; } diff -Nru kodi-18.6+git20200408.1716-final/xbmc/CMakeLists.txt kodi-18.7+git20200520.1011-final/xbmc/CMakeLists.txt --- kodi-18.6+git20200408.1716-final/xbmc/CMakeLists.txt 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/CMakeLists.txt 2012-11-04 08:41:54.000000000 +0000 @@ -65,6 +65,7 @@ IProgressCallback.h InfoScanner.h LangInfo.h + LockType.h MediaSource.h NfoFile.h PartyModeManager.h diff -Nru kodi-18.6+git20200408.1716-final/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp kodi-18.7+git20200520.1011-final/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp --- kodi-18.6+git20200408.1716-final/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -247,7 +247,6 @@ CAEDeviceInfo CAESinkAUDIOTRACK::m_info; std::set CAESinkAUDIOTRACK::m_sink_sampleRates; bool CAESinkAUDIOTRACK::m_sinkSupportsFloat = false; -bool CAESinkAUDIOTRACK::m_sinkSupportsMultiChannelFloat = false; //////////////////////////////////////////////////////////////////////////////////////////// CAESinkAUDIOTRACK::CAESinkAUDIOTRACK() @@ -378,12 +377,7 @@ { m_passthrough = false; m_format.m_sampleRate = m_sink_sampleRate; - if (m_sinkSupportsMultiChannelFloat) - { - m_encoding = CJNIAudioFormat::ENCODING_PCM_FLOAT; - m_format.m_dataFormat = AE_FMT_FLOAT; - } - else if (m_sinkSupportsFloat && m_format.m_channelLayout.Count() == 2) + if (m_sinkSupportsFloat && m_format.m_channelLayout.Count() == 2) { m_encoding = CJNIAudioFormat::ENCODING_PCM_FLOAT; m_format.m_dataFormat = AE_FMT_FLOAT; @@ -1009,10 +1003,6 @@ int encoding = CJNIAudioFormat::ENCODING_PCM_16BIT; m_sinkSupportsFloat = VerifySinkConfiguration(native_sampleRate, CJNIAudioFormat::CHANNEL_OUT_STEREO, CJNIAudioFormat::ENCODING_PCM_FLOAT); - // Only try for Android 7 or later - there are a lot of old devices that open successfully - // but won't work correctly under the hood (famouse example: old FireTV) - if (CJNIAudioManager::GetSDKVersion() > 23) - m_sinkSupportsMultiChannelFloat = VerifySinkConfiguration(native_sampleRate, CJNIAudioFormat::CHANNEL_OUT_7POINT1_SURROUND, CJNIAudioFormat::ENCODING_PCM_FLOAT); if (m_sinkSupportsFloat) { @@ -1020,10 +1010,6 @@ m_info.m_dataFormats.push_back(AE_FMT_FLOAT); CLog::Log(LOGNOTICE, "Float is supported"); } - if (m_sinkSupportsMultiChannelFloat) - { - CLog::Log(LOGNOTICE, "Multi channel Float is supported"); - } // Still AML API 21 and 22 get hardcoded samplerates - we can drop that // when we stop supporting API < 23 - let's only add the default diff -Nru kodi-18.6+git20200408.1716-final/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h kodi-18.7+git20200520.1011-final/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h --- kodi-18.6+git20200408.1716-final/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h 2012-11-04 08:41:54.000000000 +0000 @@ -75,7 +75,6 @@ static CAEDeviceInfo m_info; static std::set m_sink_sampleRates; static bool m_sinkSupportsFloat; - static bool m_sinkSupportsMultiChannelFloat; AEAudioFormat m_format; double m_volume; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp --- kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -18,19 +18,19 @@ #include #include +#include +#include #include -#include +#include +#include +#include #include +#include #include #include #include #include -#include -#include - -#include - #include "Application.h" #include "DVDCodecs/DVDFactoryCodec.h" #include "platform/android/activity/XBMCApp.h" @@ -126,19 +126,6 @@ /*****************************************************************************/ /*****************************************************************************/ -CMediaCodec::CMediaCodec(const char *name) - : m_codec(AMediaCodec_createCodecByName(name)) -{ -} - -CMediaCodec::~CMediaCodec() -{ - AMediaCodec_delete(m_codec); -}; - - -/*****************************************************************************/ -/*****************************************************************************/ void CMediaCodecVideoBuffer::Set(int bufferId, int textureId, std::shared_ptr surfacetexture, std::shared_ptr frameready, @@ -158,7 +145,8 @@ void CMediaCodecVideoBuffer::ReleaseOutputBuffer(bool render, int64_t displayTime, CMediaCodecVideoBufferPool* pool) { - std::shared_ptr codec(static_cast(pool ? pool : m_pool.get())->GetMediaCodec()); + std::shared_ptr codec( + static_cast(pool ? pool : m_pool.get())->GetMediaCodec()); if (m_bufferId < 0 || !codec) return; @@ -176,15 +164,17 @@ CLog::Log(LOGDEBUG, "CMediaCodecVideoBuffer::ReleaseOutputBuffer index(%d), render(%d), time:%lld, offset:%lld", m_bufferId, render, displayTime, diff); } - media_status_t mstat; if (!render || displayTime == 0) - mstat = AMediaCodec_releaseOutputBuffer(codec->codec(), m_bufferId, render); + codec->releaseOutputBuffer(m_bufferId, render); else - mstat = AMediaCodec_releaseOutputBufferAtTime(codec->codec(), m_bufferId, displayTime); + codec->releaseOutputBuffer(m_bufferId, displayTime); m_bufferId = -1; //mark released - if (mstat != AMEDIA_OK) - CLog::Log(LOGERROR, "CMediaCodecVideoBuffer::ReleaseOutputBuffer error %d in render(%d)", mstat, render); + if (xbmc_jnienv()->ExceptionCheck()) + { + xbmc_jnienv()->ExceptionClear(); + CLog::Log(LOGERROR, "CMediaCodecVideoBuffer::ReleaseOutputBuffer error in render(%d)", render); + } } int CMediaCodecVideoBuffer::GetBufferId() const @@ -292,7 +282,7 @@ m_freeBuffers.push_back(id); } -std::shared_ptr CMediaCodecVideoBufferPool::GetMediaCodec() +std::shared_ptr CMediaCodecVideoBufferPool::GetMediaCodec() { CSingleLock lock(m_criticalSection); return m_codec; @@ -322,9 +312,7 @@ , m_opened(false) , m_jnivideoview(nullptr) , m_jnisurface(nullptr) -, m_crypto(nullptr) , m_textureId(0) -, m_surface(nullptr) , m_OutputDuration(0) , m_fpsDuration(0) , m_lastPTS(-1) @@ -343,7 +331,7 @@ if (m_crypto) { - AMediaCrypto_delete(m_crypto); + delete m_crypto; m_crypto = nullptr; } if (m_mpeg2_sequence) @@ -370,12 +358,7 @@ { int num_codecs; int profile(0); - - const AMediaUUID* uuid(nullptr); - const AMediaUUID wvuuid = {0xED, 0xEF, 0x8B, 0xA9, 0x79, 0xD6, 0x4A, 0xCE, - 0xA3, 0xC8, 0x27, 0xDC, 0xD5, 0x1D, 0x21, 0xED}; - const AMediaUUID pruuid = {0x9A, 0x04, 0xF0, 0x79, 0x98, 0x40, 0x42, 0x86, - 0xAB, 0x92, 0xE6, 0x5B, 0xE0, 0x88, 0x5F, 0x95}; + CJNIUUID uuid(0, 0); m_opened = false; m_needSecureDecoder = false; @@ -582,32 +565,25 @@ if (m_crypto) { - AMediaCrypto_delete(m_crypto); + delete m_crypto; m_crypto = nullptr; } if (m_hints.cryptoSession) { if (m_hints.cryptoSession->keySystem == CRYPTO_SESSION_SYSTEM_WIDEVINE) - uuid = &wvuuid; + uuid = CJNIUUID(0xEDEF8BA979D64ACE, 0xA3C827DCD51D21ED); else if (m_hints.cryptoSession->keySystem == CRYPTO_SESSION_SYSTEM_PLAYREADY) - uuid = &pruuid; + uuid = CJNIUUID(0x9A04F07998404286, 0xAB92E65BE0885F95); else { CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::Open Unsupported crypto-keysystem %u", m_hints.cryptoSession->keySystem); goto FAIL; } - - int64_t mostSigBits(0), leastSigBits(0); - for (unsigned int i(0); i < 8; ++i) - mostSigBits = (mostSigBits << 8) | (*uuid)[i]; - for (unsigned int i(8); i < 16; ++i) - leastSigBits = (leastSigBits << 8) | (*uuid)[i]; - CJNIUUID juuid(mostSigBits, leastSigBits); - CJNIMediaCrypto crypto(juuid, std::vector(m_hints.cryptoSession->sessionId, - m_hints.cryptoSession->sessionId + - m_hints.cryptoSession->sessionIdSize)); + CJNIMediaCrypto crypto(uuid, std::vector(m_hints.cryptoSession->sessionId, + m_hints.cryptoSession->sessionId + + m_hints.cryptoSession->sessionIdSize)); m_needSecureDecoder = crypto.requiresSecureDecoderComponent(m_mime) && (m_hints.cryptoSession->flags & DemuxCryptoSession::FLAG_SECURE_DECODER) != 0; @@ -675,8 +651,9 @@ { if (types[j] == m_mime) { - m_codec = std::shared_ptr(new CMediaCodec(m_codecname.c_str())); - if (!m_codec->codec()) + m_codec = std::shared_ptr( + new CJNIMediaCodec(CJNIMediaCodec::createByCodecName(m_codecname))); + if (!m_codec) { CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::Open cannot create codec"); continue; @@ -692,7 +669,7 @@ break; } } - if (m_codec->codec()) + if (m_codec) break; } if (!m_codec) @@ -705,7 +682,10 @@ { CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::Open Initializing MediaCrypto"); - m_crypto = AMediaCrypto_new(*uuid, m_hints.cryptoSession->sessionId, m_hints.cryptoSession->sessionIdSize); + m_crypto = + new CJNIMediaCrypto(uuid, std::vector(m_hints.cryptoSession->sessionId, + m_hints.cryptoSession->sessionId + + m_hints.cryptoSession->sessionIdSize)); if (!m_crypto) { @@ -765,7 +745,7 @@ m_InstanceGuard.exchange(false); if (m_crypto) { - AMediaCrypto_delete(m_crypto); + delete m_crypto; m_crypto = nullptr; } @@ -798,17 +778,17 @@ m_videobuffer.iFlags = 0; - if (m_codec->codec()) + if (m_codec) { - AMediaCodec_stop(m_codec->codec()); + m_codec->stop(); m_codec = nullptr; m_state = MEDIACODEC_STATE_STOPPED; } ReleaseSurfaceTexture(); - if(m_surface) - ANativeWindow_release(m_surface); - m_surface = nullptr; + if (m_jnisurface) + m_jnisurface->release(); + m_jnisurface = nullptr; m_InstanceGuard.exchange(false); if (m_render_surface) @@ -844,7 +824,7 @@ { // We received a packet but already reached EOS. Flush... FlushInternal(); - AMediaCodec_flush(m_codec->codec()); + m_codec->flush(); m_state = MEDIACODEC_STATE_FLUSHED; } @@ -885,26 +865,31 @@ if (m_state == MEDIACODEC_STATE_FLUSHED) m_state = MEDIACODEC_STATE_RUNNING; - size_t out_size; - uint8_t* dst_ptr = AMediaCodec_getInputBuffer(m_codec->codec(), m_indexInputBuffer, &out_size); + CJNIByteBuffer buffer = m_codec->getInputBuffer(m_indexInputBuffer); + size_t out_size = buffer.capacity(); if ((size_t)iSize > out_size) { CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::AddData, iSize(%d) > size(%d)", iSize, out_size); iSize = out_size; } + uint8_t* dst_ptr = (uint8_t*)xbmc_jnienv()->GetDirectBufferAddress(buffer.get_raw()); - AMediaCodecCryptoInfo *cryptoInfo(0); + CJNIMediaCodecCryptoInfo* cryptoInfo(nullptr); if (m_crypto && packet.cryptoInfo) { - std::vector clearBytes(packet.cryptoInfo->clearBytes, packet.cryptoInfo->clearBytes + packet.cryptoInfo->numSubSamples); - std::vector cipherBytes(packet.cryptoInfo->cipherBytes, packet.cryptoInfo->cipherBytes + packet.cryptoInfo->numSubSamples); - - cryptoInfo = AMediaCodecCryptoInfo_new( - packet.cryptoInfo->numSubSamples, - packet.cryptoInfo->kid, - packet.cryptoInfo->iv, - AMEDIACODECRYPTOINFO_MODE_AES_CTR, - &clearBytes[0], &cipherBytes[0]); + std::vector clearBytes(packet.cryptoInfo->clearBytes, + packet.cryptoInfo->clearBytes + + packet.cryptoInfo->numSubSamples); + std::vector cipherBytes(packet.cryptoInfo->cipherBytes, + packet.cryptoInfo->cipherBytes + + packet.cryptoInfo->numSubSamples); + + cryptoInfo = new CJNIMediaCodecCryptoInfo(); + + cryptoInfo->set(packet.cryptoInfo->numSubSamples, clearBytes, cipherBytes, + std::vector(packet.cryptoInfo->kid, packet.cryptoInfo->kid + 16), + std::vector(packet.cryptoInfo->iv, packet.cryptoInfo->iv + 16), + CJNIMediaCodec::CRYPTO_MODE_AES_CTR); } if (dst_ptr) { @@ -957,18 +942,19 @@ int flags = 0; int offset = 0; - media_status_t mstat; if (!cryptoInfo) - mstat = AMediaCodec_queueInputBuffer(m_codec->codec(), m_indexInputBuffer, offset, iSize, presentationTimeUs, flags); + m_codec->queueInputBuffer(m_indexInputBuffer, offset, iSize, presentationTimeUs, flags); else { - mstat = AMediaCodec_queueSecureInputBuffer(m_codec->codec(), m_indexInputBuffer, offset, cryptoInfo, presentationTimeUs, flags); - AMediaCodecCryptoInfo_delete(cryptoInfo); - } - if (mstat != AMEDIA_OK) - { - CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::AddData error(%d)", mstat); - return false; + m_codec->queueSecureInputBuffer(m_indexInputBuffer, offset, *cryptoInfo, presentationTimeUs, + flags); + delete cryptoInfo, cryptoInfo = nullptr; + } + if (xbmc_jnienv()->ExceptionCheck()) + { + xbmc_jnienv()->ExceptionDescribe(); + xbmc_jnienv()->ExceptionClear(); + CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::AddData error"); } m_indexInputBuffer = -1; } @@ -983,7 +969,7 @@ if (!m_opened) return; - if (m_codec->codec()) + if (m_codec) { // flush all outputbuffers inflight, they will // become invalid on m_codec->flush and generate @@ -993,9 +979,10 @@ // now we can flush the actual MediaCodec object CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::Reset Current state (%d)", m_state); m_state = MEDIACODEC_STATE_FLUSHED; - AMediaCodec_flush(m_codec->codec()); + m_codec->flush(); - InjectExtraData(nullptr); + CJNIMediaFormat mediaFormat = m_codec->getOutputFormat(); + InjectExtraData(mediaFormat); // Invalidate our local VideoPicture bits m_videobuffer.pts = DVD_NOPTS_VALUE; @@ -1054,7 +1041,7 @@ { // try to fetch an input buffer if (m_indexInputBuffer < 0) - m_indexInputBuffer = AMediaCodec_dequeueInputBuffer(m_codec->codec(), 5000 /*timout*/); + m_indexInputBuffer = m_codec->dequeueInputBuffer(5000 /*timout*/); if (m_indexInputBuffer >= 0) { @@ -1091,7 +1078,7 @@ void CDVDVideoCodecAndroidMediaCodec::SignalEndOfStream() { CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::%s: state: %d", __func__, m_state); - if (m_codec->codec() && (m_state == MEDIACODEC_STATE_RUNNING || m_state == MEDIACODEC_STATE_ENDOFSTREAM)) + if (m_codec && (m_state == MEDIACODEC_STATE_RUNNING || m_state == MEDIACODEC_STATE_ENDOFSTREAM)) { // Release all mediaodec output buffers to allow drain if we don't get inputbuffer early if (m_videoBufferPool) @@ -1101,69 +1088,71 @@ } if (m_indexInputBuffer < 0) - m_indexInputBuffer = AMediaCodec_dequeueInputBuffer(m_codec->codec(), 100000); + m_indexInputBuffer = m_codec->dequeueInputBuffer(100000); + xbmc_jnienv()->ExceptionClear(); if (m_indexInputBuffer >= 0) { - media_status_t status= AMediaCodec_queueInputBuffer(m_codec->codec(), m_indexInputBuffer, 0, 0, 0, AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM); - if (status == AMEDIA_OK) + m_codec->queueInputBuffer(m_indexInputBuffer, 0, 0, 0, + CJNIMediaCodec::BUFFER_FLAG_END_OF_STREAM); + if (xbmc_jnienv()->ExceptionCheck()) + { + xbmc_jnienv()->ExceptionClear(); + CLog::Log(LOGWARNING, "CDVDVideoCodecAndroidMediaCodec::%s: queueInputBuffer failed", + __func__); + } + else { m_indexInputBuffer = -1; CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::%s: BUFFER_FLAG_END_OF_STREAM send", __func__); } - else - CLog::Log(LOGWARNING, "CDVDVideoCodecAndroidMediaCodec::%s: AMediaCodec_queueInputBuffer returned: %d", __func__, status); } else CLog::Log(LOGWARNING, "CDVDVideoCodecAndroidMediaCodec::%s: invalid index: %d", __func__, m_indexInputBuffer); } } -void CDVDVideoCodecAndroidMediaCodec::InjectExtraData(AMediaFormat* mediaformat) +void CDVDVideoCodecAndroidMediaCodec::InjectExtraData(CJNIMediaFormat& mediaformat) { if (!m_hints.extrasize) return; - if (!mediaformat && m_codec->codec()) - mediaformat = AMediaCodec_getOutputFormat(m_codec->codec()); - - if (mediaformat) - { - CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::%s", __func__); - size_t size = m_hints.extrasize; - void *src_ptr = m_hints.extradata; - if (m_bitstream) - { - size = m_bitstream->GetExtraSize(); - src_ptr = m_bitstream->GetExtraData(); - } - - AMediaFormat_setBuffer(mediaformat, "csd-0", src_ptr, size); - } + CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec::%s", __func__); + size_t size = m_hints.extrasize; + void* src_ptr = m_hints.extradata; + if (m_bitstream) + { + size = m_bitstream->GetExtraSize(); + src_ptr = m_bitstream->GetExtraData(); + } + // Allocate a byte buffer via allocateDirect in java instead of NewDirectByteBuffer, + // since the latter doesn't allocate storage of its own, and we don't know how long + // the codec uses the buffer. + CJNIByteBuffer bytebuffer = CJNIByteBuffer::allocateDirect(size); + void* dts_ptr = xbmc_jnienv()->GetDirectBufferAddress(bytebuffer.get_raw()); + memcpy(dts_ptr, src_ptr, size); + // codec will automatically handle buffers as extradata + // using entries with keys "csd-0", "csd-1", etc. + mediaformat.setByteBuffer("csd-0", bytebuffer); } bool CDVDVideoCodecAndroidMediaCodec::ConfigureMediaCodec(void) { // setup a MediaFormat to match the video content, // used by codec during configure - AMediaFormat* mediaformat = AMediaFormat_new(); - AMediaFormat_setString(mediaformat, AMEDIAFORMAT_KEY_MIME, m_mime.c_str()); - AMediaFormat_setInt32(mediaformat, AMEDIAFORMAT_KEY_WIDTH, m_hints.width); - AMediaFormat_setInt32(mediaformat, AMEDIAFORMAT_KEY_HEIGHT, m_hints.height); - AMediaFormat_setInt32(mediaformat, AMEDIAFORMAT_KEY_MAX_WIDTH, m_hints.width); - AMediaFormat_setInt32(mediaformat, AMEDIAFORMAT_KEY_MAX_HEIGHT, m_hints.height); - AMediaFormat_setInt32(mediaformat, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, 0); + CJNIMediaFormat mediaformat = + CJNIMediaFormat::createVideoFormat(m_mime.c_str(), m_hints.width, m_hints.height); + mediaformat.setInteger(CJNIMediaFormat::KEY_MAX_INPUT_SIZE, 0); if (CJNIBase::GetSDKVersion() >= 23 && m_render_surface) { // Handle rotation - AMediaFormat_setInt32(mediaformat, XMEDIAFORMAT_KEY_ROTATION, m_hints.orientation); - AMediaFormat_setInt32(mediaformat, XMEDIAFORMAT_FEATURE_TUNNELED_PLAYBACK, 0); + mediaformat.setInteger(XMEDIAFORMAT_KEY_ROTATION, m_hints.orientation); + mediaformat.setInteger(XMEDIAFORMAT_FEATURE_TUNNELED_PLAYBACK, 0); if (m_needSecureDecoder) - AMediaFormat_setInt32(mediaformat, XMEDIAFORMAT_FEATURE_SECURE_PLAYBACK, 1); + mediaformat.setInteger(XMEDIAFORMAT_FEATURE_SECURE_PLAYBACK, 1); } - // handle codec extradata InjectExtraData(mediaformat); @@ -1177,8 +1166,6 @@ m_jnivideoview.reset(); return false; } - m_surface = ANativeWindow_fromSurface(xbmc_jnienv(), m_jnivideosurface.get_raw()); - m_formatname += "(S)"; } else @@ -1189,19 +1176,26 @@ // use a null MediaCrypto, our content is not encrypted. int flags = 0; - media_status_t mstat = AMediaCodec_configure(m_codec->codec(), mediaformat, m_surface, m_crypto, flags); + m_codec->configure(mediaformat, m_jnivideosurface, + m_crypto ? *m_crypto : CJNIMediaCrypto(jni::jhobject(NULL)), flags); - if (mstat != AMEDIA_OK) + if (xbmc_jnienv()->ExceptionCheck()) { - CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec configure error: %d", mstat); + xbmc_jnienv()->ExceptionClear(); + CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec configure error"); return false; } + m_codec->setVideoScalingMode(CJNIMediaCodec::VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); + m_state = MEDIACODEC_STATE_CONFIGURED; - mstat = AMediaCodec_start(m_codec->codec()); - if (mstat != AMEDIA_OK) + m_codec->start(); + + if (xbmc_jnienv()->ExceptionCheck()) { - CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec start error: %d", mstat); + xbmc_jnienv()->ExceptionClear(); + Dispose(); + CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec start error"); return false; } m_state = MEDIACODEC_STATE_FLUSHED; @@ -1218,11 +1212,11 @@ int rtn = 0; int64_t timeout_us = 10000; - AMediaCodecBufferInfo bufferInfo; - ssize_t index = AMediaCodec_dequeueOutputBuffer(m_codec->codec(), &bufferInfo, timeout_us); + CJNIMediaCodecBufferInfo bufferInfo; + ssize_t index = m_codec->dequeueOutputBuffer(bufferInfo, timeout_us); if (index >= 0) { - int64_t pts = bufferInfo.presentationTimeUs; + int64_t pts = bufferInfo.presentationTimeUs(); m_videobuffer.dts = DVD_NOPTS_VALUE; m_videobuffer.pts = DVD_NOPTS_VALUE; if (pts != AV_NOPTS_VALUE) @@ -1237,14 +1231,15 @@ if (m_codecControlFlags & DVD_CODEC_CTRL_DROP) { m_noPictureLoop = 0; - AMediaCodec_releaseOutputBuffer(m_codec->codec(), index, false); + m_codec->releaseOutputBuffer(index, false); return -2; } - if (bufferInfo.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) + int flags = bufferInfo.flags(); + if (flags & CJNIMediaCodec::BUFFER_FLAG_END_OF_STREAM) { CLog::Log(LOGDEBUG, "CDVDVideoCodecAndroidMediaCodec:: BUFFER_FLAG_END_OF_STREAM"); - AMediaCodec_releaseOutputBuffer(m_codec->codec(), index, false); + m_codec->releaseOutputBuffer(index, false); return -1; } @@ -1256,15 +1251,19 @@ rtn = 1; } - else if (index == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) + else if (index == CJNIMediaCodec::INFO_OUTPUT_FORMAT_CHANGED) { - AMediaFormat* mediaformat = AMediaCodec_getOutputFormat(m_codec->codec()); - if (!mediaformat) + CJNIMediaFormat mediaformat = m_codec->getOutputFormat(); + if (xbmc_jnienv()->ExceptionCheck()) + { + xbmc_jnienv()->ExceptionClear(); CLog::Log(LOGERROR, "CDVDVideoCodecAndroidMediaCodec::GetOutputPicture(INFO_OUTPUT_FORMAT_CHANGED) ExceptionCheck: getOutputBuffers"); + } else ConfigureOutputFormat(mediaformat); } - else if (index == AMEDIACODEC_INFO_TRY_AGAIN_LATER || index == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) + else if (index == CJNIMediaCodec::INFO_TRY_AGAIN_LATER || + index == CJNIMediaCodec::INFO_OUTPUT_BUFFERS_CHANGED) { // ignore rtn = 0; @@ -1279,7 +1278,7 @@ return rtn; } -void CDVDVideoCodecAndroidMediaCodec::ConfigureOutputFormat(AMediaFormat* mediaformat) +void CDVDVideoCodecAndroidMediaCodec::ConfigureOutputFormat(CJNIMediaFormat& mediaformat) { int width = 0; int height = 0; @@ -1291,25 +1290,25 @@ int crop_right = 0; int crop_bottom = 0; - int tmpVal; - if (AMediaFormat_getInt32(mediaformat, AMEDIAFORMAT_KEY_WIDTH, &tmpVal)) - width = tmpVal; - if (AMediaFormat_getInt32(mediaformat, AMEDIAFORMAT_KEY_HEIGHT, &tmpVal)) - height = tmpVal; - if (AMediaFormat_getInt32(mediaformat, AMEDIAFORMAT_KEY_STRIDE, &tmpVal)) - stride = tmpVal; - if (AMediaFormat_getInt32(mediaformat, XMEDIAFORMAT_KEY_SLICE, &tmpVal)) - slice_height = tmpVal; - if (AMediaFormat_getInt32(mediaformat, AMEDIAFORMAT_KEY_COLOR_FORMAT, &tmpVal)) - color_format = tmpVal; - if (AMediaFormat_getInt32(mediaformat, XMEDIAFORMAT_KEY_CROP_LEFT, &tmpVal)) - crop_left = tmpVal; - if (AMediaFormat_getInt32(mediaformat, XMEDIAFORMAT_KEY_CROP_RIGHT, &tmpVal)) - crop_right = tmpVal; - if (AMediaFormat_getInt32(mediaformat, XMEDIAFORMAT_KEY_CROP_TOP, &tmpVal)) - crop_top = tmpVal; - if (AMediaFormat_getInt32(mediaformat, XMEDIAFORMAT_KEY_CROP_BOTTOM, &tmpVal)) - crop_bottom = tmpVal; + if (mediaformat.containsKey("width")) + width = mediaformat.getInteger("width"); + if (mediaformat.containsKey("height")) + height = mediaformat.getInteger("height"); + if (mediaformat.containsKey("stride")) + stride = mediaformat.getInteger("stride"); + if (mediaformat.containsKey(XMEDIAFORMAT_KEY_SLICE)) + slice_height = mediaformat.getInteger(XMEDIAFORMAT_KEY_SLICE); + if (mediaformat.containsKey("color-format")) + color_format = mediaformat.getInteger("color-format"); + if (mediaformat.containsKey(XMEDIAFORMAT_KEY_CROP_LEFT)) + crop_left = mediaformat.getInteger(XMEDIAFORMAT_KEY_CROP_LEFT); + if (mediaformat.containsKey(XMEDIAFORMAT_KEY_CROP_TOP)) + crop_top = mediaformat.getInteger(XMEDIAFORMAT_KEY_CROP_TOP); + if (mediaformat.containsKey(XMEDIAFORMAT_KEY_CROP_RIGHT)) + crop_right = mediaformat.getInteger(XMEDIAFORMAT_KEY_CROP_RIGHT); + if (mediaformat.containsKey(XMEDIAFORMAT_KEY_CROP_BOTTOM)) + crop_bottom = mediaformat.getInteger(XMEDIAFORMAT_KEY_CROP_BOTTOM); + if (!crop_right) crop_right = width-1; @@ -1386,7 +1385,6 @@ // hook the surfaceTexture OnFrameAvailable callback m_frameAvailable = std::shared_ptr(new CDVDMediaCodecOnFrameAvailable(m_surfaceTexture)); m_jnisurface = new CJNISurface(*m_surfaceTexture); - m_surface = ANativeWindow_fromSurface(xbmc_jnienv(), m_jnisurface->get_raw()); } else { @@ -1449,8 +1447,8 @@ if (m_state != MEDIACODEC_STATE_STOPPED && m_state != MEDIACODEC_STATE_UNINITIALIZED) { m_state = MEDIACODEC_STATE_STOPPED; - if(m_surface) - ANativeWindow_release(m_surface); - AMediaCodec_stop(m_codec->codec()); + if (m_jnisurface) + m_jnisurface->release(); + m_codec->stop(); } } diff -Nru kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h --- kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h 2012-11-04 08:41:54.000000000 +0000 @@ -13,8 +13,6 @@ #include #include -#include - #include "DVDVideoCodec.h" #include "DVDStreamInfo.h" #include "platform/android/activity/JNIXBMCVideoView.h" @@ -23,19 +21,16 @@ #include "utils/Geometry.h" #include "cores/VideoPlayer/Process/VideoBuffer.h" -#include -#include -#include - class CJNISurface; class CJNISurfaceTexture; class CJNIMediaCodec; +class CJNIMediaCrypto; class CJNIMediaFormat; +class CJNIMediaCodecBufferInfo; class CDVDMediaCodecOnFrameAvailable; class CJNIByteBuffer; class CBitstreamConverter; -struct AMediaCrypto; struct DemuxCryptoInfo; struct mpeg2_sequence; @@ -47,16 +42,6 @@ double pts; } amc_demux; -struct CMediaCodec -{ - CMediaCodec(const char *name); - virtual ~CMediaCodec(); - - AMediaCodec *codec() const { return m_codec; }; -private: - AMediaCodec *m_codec; -}; - class CMediaCodecVideoBufferPool; class CMediaCodecVideoBuffer : public CVideoBuffer @@ -95,20 +80,21 @@ class CMediaCodecVideoBufferPool : public IVideoBufferPool { public: - CMediaCodecVideoBufferPool(std::shared_ptr mediaCodec) : m_codec(mediaCodec) {}; + CMediaCodecVideoBufferPool(std::shared_ptr mediaCodec) + : m_codec(mediaCodec){}; virtual ~CMediaCodecVideoBufferPool(); virtual CVideoBuffer* Get() override; virtual void Return(int id) override; - std::shared_ptr GetMediaCodec(); + std::shared_ptr GetMediaCodec(); void ResetMediaCodec(); void ReleaseMediaCodecBuffers(); private: - CCriticalSection m_criticalSection;; - std::shared_ptr m_codec; + CCriticalSection m_criticalSection; + std::shared_ptr m_codec; std::vector m_videoBuffers; std::vector m_freeBuffers; @@ -135,14 +121,14 @@ virtual unsigned GetAllowedReferences() override; protected: - void Dispose(); - void FlushInternal(void); - void SignalEndOfStream(); - void InjectExtraData(AMediaFormat* mediaformat); - bool ConfigureMediaCodec(void); - int GetOutputPicture(void); - void ConfigureOutputFormat(AMediaFormat* mediaformat); - void UpdateFpsDuration(); + void Dispose(); + void FlushInternal(void); + void SignalEndOfStream(); + void InjectExtraData(CJNIMediaFormat& mediaformat); + bool ConfigureMediaCodec(void); + int GetOutputPicture(void); + void ConfigureOutputFormat(CJNIMediaFormat& mediaformat); + void UpdateFpsDuration(); // surface handling functions static void CallbackInitSurfaceTexture(void*); @@ -161,12 +147,11 @@ int m_noPictureLoop; std::shared_ptr m_jnivideoview; - CJNISurface* m_jnisurface; - CJNISurface m_jnivideosurface; - AMediaCrypto *m_crypto; - unsigned int m_textureId; - std::shared_ptr m_codec; - ANativeWindow* m_surface; + CJNISurface* m_jnisurface; + CJNISurface m_jnivideosurface; + unsigned int m_textureId; + std::shared_ptr m_codec; + CJNIMediaCrypto* m_crypto = nullptr; std::shared_ptr m_surfaceTexture; std::shared_ptr m_frameAvailable; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp --- kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -202,11 +202,12 @@ return false; } -bool CDVDDemuxFFmpeg::Open(std::shared_ptr pInput, bool streaminfo, bool fileinfo) +bool CDVDDemuxFFmpeg::Open(std::shared_ptr pInput, bool fileinfo) { AVInputFormat* iformat = NULL; std::string strFile; - m_streaminfo = streaminfo; + m_streaminfo = !pInput->IsRealtime() && !m_reopen; + m_reopen = false; m_currentPts = DVD_NOPTS_VALUE; m_speed = DVD_PLAYSPEED_NORMAL; m_program = UINT_MAX; @@ -602,6 +603,7 @@ int64_t duration = m_pFormatContext->duration; std::shared_ptr pInputStream = m_pInput; Dispose(); + m_reopen = true; if (!Open(pInputStream, false)) return false; m_pFormatContext->duration = duration; @@ -651,7 +653,7 @@ { std::shared_ptr pInputStream = m_pInput; Dispose(); - return Open(pInputStream, m_streaminfo); + return Open(pInputStream, false); } void CDVDDemuxFFmpeg::Flush() diff -Nru kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.h kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.h --- kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.h 2012-11-04 08:41:54.000000000 +0000 @@ -83,7 +83,7 @@ CDVDDemuxFFmpeg(); ~CDVDDemuxFFmpeg() override; - bool Open(std::shared_ptr pInput, bool streaminfo = true, bool fileinfo = false); + bool Open(std::shared_ptr pInput, bool fileinfo); void Dispose(); bool Reset() override ; void Flush() override; @@ -169,6 +169,7 @@ }m_pkt; bool m_streaminfo; + bool m_reopen = false; bool m_checkTransportStream; int m_displayTime = 0; double m_dtsAtDisplayTime; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxVobsub.cpp kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxVobsub.cpp --- kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxVobsub.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxVobsub.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -64,7 +64,7 @@ return false; m_Demuxer.reset(new CDVDDemuxFFmpeg()); - if(!m_Demuxer->Open(m_Input)) + if (!m_Demuxer->Open(m_Input, false)) return false; CDVDStreamInfo hints; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDFactoryDemuxer.cpp kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDFactoryDemuxer.cpp --- kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDFactoryDemuxer.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDDemuxers/DVDFactoryDemuxer.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -61,20 +61,6 @@ return nullptr; } - bool streaminfo = true; /* Look for streams before playback */ - if (pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) - { - /* Don't parse the streaminfo for some cases of streams to reduce the channel switch time */ - bool useFastswitch = URIUtils::IsUsingFastSwitch(pInputStream->GetFileName()); - streaminfo = !useFastswitch; - } - - if (pInputStream->IsStreamType(DVDSTREAM_TYPE_FFMPEG)) - { - bool useFastswitch = URIUtils::IsUsingFastSwitch(pInputStream->GetFileName()); - streaminfo = !useFastswitch; - } - // Try to open the MultiFiles demuxer if (pInputStream->IsStreamType(DVDSTREAM_TYPE_MULTIFILES)) { @@ -86,7 +72,7 @@ } std::unique_ptr demuxer(new CDVDDemuxFFmpeg()); - if(demuxer->Open(pInputStream, streaminfo, fileinfo)) + if (demuxer->Open(pInputStream, fileinfo)) return demuxer.release(); else return NULL; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp --- kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -139,6 +139,7 @@ std::string root; bool openStream = false; + bool openDisc = false; // The item was selected via the simple menu if (URIUtils::IsProtocol(strPath, "bluray")) @@ -147,6 +148,11 @@ root = url.GetHostName(); filename = URIUtils::GetFileName(url.GetFileName()); + // Check whether disc is AACS protected + CURL url3(root); + CFileItem base(url3, false); + openDisc = base.IsProtectedBlurayDisc(); + // check for a menu call for an image file if (StringUtils::EqualsNoCase(filename, "menu")) { @@ -155,6 +161,11 @@ std::string root2 = url2.GetHostName(); CURL url(root2); CFileItem item(url, false); + + // Check whether disc is AACS protected + if (!openDisc) + openDisc = item.IsProtectedBlurayDisc(); + if (item.IsDiscImage()) { if (!OpenStream(item)) @@ -171,6 +182,10 @@ openStream = true; } + else if (m_item.IsProtectedBlurayDisc()) + { + openDisc = true; + } else { strPath = URIUtils::GetDirectory(strPath); @@ -217,12 +232,25 @@ return false; } } + else if (openDisc) + { + // This special case is required for opening original AACS protected Blu-ray discs. Otherwise + // things like Bus Encryption might not be handled properly and playback will fail. + m_rootPath = root; + if (!bd_open_disc(m_bd, root.c_str(), nullptr)) + { + CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to open %s in disc mode", + CURL::GetRedacted(root).c_str()); + return false; + } + } else { m_rootPath = root; if (!bd_open_files(m_bd, &m_rootPath, CBlurayCallback::dir_open, CBlurayCallback::file_open)) { - CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to open %s", CURL::GetRedacted(root).c_str()); + CLog::Log(LOGERROR, "CDVDInputStreamBluray::Open - failed to open %s in files mode", + CURL::GetRedacted(root).c_str()); return false; } } @@ -990,8 +1018,12 @@ find_stream(pid, m_clip->audio_streams, m_clip->audio_stream_count, language); else if (HDMV_PID_PG_FIRST <= pid && pid <= HDMV_PID_PG_LAST) find_stream(pid, m_clip->pg_streams, m_clip->pg_stream_count, language); + else if (HDMV_PID_PG_HDR_FIRST <= pid && pid <= HDMV_PID_PG_HDR_LAST) + find_stream(pid, m_clip->pg_streams, m_clip->pg_stream_count, language); else if (HDMV_PID_IG_FIRST <= pid && pid <= HDMV_PID_IG_LAST) find_stream(pid, m_clip->ig_streams, m_clip->ig_stream_count, language); + else + CLog::Log(LOGDEBUG, "CDVDInputStreamBluray::GetStreamInfo - unhandled pid %d", pid); } CDVDInputStream::ENextStream CDVDInputStreamBluray::NextStream() diff -Nru kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.h kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.h --- kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDInputStreams/DVDInputStreamBluray.h 2012-11-04 08:41:54.000000000 +0000 @@ -33,6 +33,8 @@ #define HDMV_PID_AUDIO_LAST 0x111f #define HDMV_PID_PG_FIRST 0x1200 #define HDMV_PID_PG_LAST 0x121f +#define HDMV_PID_PG_HDR_FIRST 0x12a0 +#define HDMV_PID_PG_HDR_LAST 0x12bf #define HDMV_PID_IG_FIRST 0x1400 #define HDMV_PID_IG_LAST 0x141f diff -Nru kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitleParserSami.cpp kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitleParserSami.cpp --- kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitleParserSami.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitleParserSami.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -34,7 +34,7 @@ char line[1024]; CRegExp reg(true); - if (!reg.RegComp("")) + if (!reg.RegComp("")) return false; std::string strFileName; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitleTagSami.cpp kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitleTagSami.cpp --- kodi-18.6+git20200408.1716-final/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitleTagSami.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/cores/VideoPlayer/DVDSubtitles/DVDSubtitleTagSami.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -9,6 +9,8 @@ #include "DVDSubtitleTagSami.h" #include "DVDSubtitleStream.h" #include "DVDCodecs/Overlay/DVDOverlayText.h" +#include "utils/CharsetConverter.h" +#include "utils/HTMLUtil.h" #include "utils/RegExp.h" #include "utils/StringUtils.h" @@ -184,6 +186,11 @@ if( strUTF8[strUTF8.size()-1] == '\n' ) strUTF8.erase(strUTF8.size()-1); + std::wstring wStrHtml, wStr; + g_charsetConverter.utf8ToW(strUTF8, wStrHtml, false); + HTML::CHTMLUtil::ConvertHTMLToW(wStrHtml, wStr); + g_charsetConverter.wToUTF8(wStr, strUTF8); + // add a new text element to our container pOverlay->AddElement(new CDVDOverlayText::CElementText(strUTF8.c_str())); } diff -Nru kodi-18.6+git20200408.1716-final/xbmc/dbwrappers/Database.cpp kodi-18.7+git20200520.1011-final/xbmc/dbwrappers/Database.cpp --- kodi-18.6+git20200408.1716-final/xbmc/dbwrappers/Database.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/dbwrappers/Database.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -173,6 +173,12 @@ return false; } +void CDatabase::DatasetLayout::SetFetch(int fieldno, bool bFetch /*= true*/) +{ + if (fieldno >= 0 && fieldno < static_cast(m_fields.size())) + m_fields[fieldno].fetch = bFetch; +} + bool CDatabase::DatasetLayout::GetOutput(int fieldno) { if (fieldno >= 0 && fieldno < static_cast(m_fields.size())) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/dbwrappers/Database.h kodi-18.7+git20200520.1011-final/xbmc/dbwrappers/Database.h --- kodi-18.6+git20200408.1716-final/xbmc/dbwrappers/Database.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/dbwrappers/Database.h 2012-11-04 08:41:54.000000000 +0000 @@ -67,6 +67,7 @@ void SetField(int fieldNo, const std::string &strField, bool bOutput = false); void AdjustRecordNumbers(int offset); bool GetFetch(int fieldno); + void SetFetch(int fieldno, bool bFetch = true); bool GetOutput(int fieldno); int GetRecNo(int fieldno); const std::string GetFields(); diff -Nru kodi-18.6+git20200408.1716-final/xbmc/dialogs/GUIDialogContextMenu.cpp kodi-18.7+git20200520.1011-final/xbmc/dialogs/GUIDialogContextMenu.cpp --- kodi-18.6+git20200408.1716-final/xbmc/dialogs/GUIDialogContextMenu.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/dialogs/GUIDialogContextMenu.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -7,33 +7,35 @@ */ #include "GUIDialogContextMenu.h" -#include "guilib/GUIComponent.h" -#include "guilib/GUIButtonControl.h" -#include "guilib/GUIControlGroupList.h" + +#include "FileItem.h" #include "GUIDialogFileBrowser.h" -#include "GUIUserMessages.h" +#include "GUIDialogMediaSource.h" +#include "GUIDialogYesNo.h" #include "GUIPassword.h" +#include "GUIUserMessages.h" #include "ServiceBroker.h" +#include "TextureCache.h" +#include "URL.h" #include "Util.h" -#include "utils/URIUtils.h" +#include "addons/Scraper.h" +#include "filesystem/File.h" +#include "guilib/GUIButtonControl.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIControlGroupList.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "input/Key.h" +#include "media/MediaLockState.h" +#include "profiles/ProfileManager.h" +#include "profiles/dialogs/GUIDialogLockSettings.h" #include "settings/MediaSourceSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" -#include "GUIDialogMediaSource.h" -#include "profiles/ProfileManager.h" -#include "profiles/dialogs/GUIDialogLockSettings.h" #include "storage/MediaManager.h" -#include "guilib/GUIWindowManager.h" -#include "input/Key.h" -#include "GUIDialogYesNo.h" -#include "FileItem.h" -#include "filesystem/File.h" -#include "guilib/LocalizeStrings.h" -#include "TextureCache.h" -#include "URL.h" #include "utils/StringUtils.h" +#include "utils/URIUtils.h" #include "utils/Variant.h" -#include "addons/Scraper.h" #define BACKGROUND_IMAGE 999 #define GROUP_LIST 996 @@ -248,11 +250,15 @@ } if (share && LOCK_MODE_EVERYONE != CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetMasterProfile().getLockMode()) { - if (share->m_iHasLock == 0 && (CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetCurrentProfile().canWriteSources() || g_passwordManager.bMasterUser)) + if (share->m_iHasLock == LOCK_STATE_NO_LOCK && (CServiceBroker::GetSettingsComponent() + ->GetProfileManager() + ->GetCurrentProfile() + .canWriteSources() || + g_passwordManager.bMasterUser)) buttons.Add(CONTEXT_BUTTON_ADD_LOCK, 12332); - else if (share->m_iHasLock == 1) + else if (share->m_iHasLock == LOCK_STATE_LOCK_BUT_UNLOCKED) buttons.Add(CONTEXT_BUTTON_REMOVE_LOCK, 12335); - else if (share->m_iHasLock == 2) + else if (share->m_iHasLock == LOCK_STATE_LOCKED) { buttons.Add(CONTEXT_BUTTON_REMOVE_LOCK, 12335); @@ -266,7 +272,7 @@ buttons.Add(CONTEXT_BUTTON_CHANGE_LOCK, 12356); } } - if (share && !g_passwordManager.bMasterUser && item->m_iHasLock == 1) + if (share && !g_passwordManager.bMasterUser && item->m_iHasLock == LOCK_STATE_LOCK_BUT_UNLOCKED) buttons.Add(CONTEXT_BUTTON_REACTIVATE_LOCK, 12353); } @@ -436,7 +442,7 @@ if (!CGUIDialogLockSettings::ShowAndGetLock(share->m_iLockMode,strNewPassword)) return false; // password entry and re-entry succeeded, write out the lock data - share->m_iHasLock = 2; + share->m_iHasLock = LOCK_STATE_LOCKED; CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "lockcode", strNewPassword); strNewPassword = StringUtils::Format("%i", share->m_iLockMode); CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "lockmode", strNewPassword); @@ -464,10 +470,11 @@ if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; + // prompt user if they want to really remove the lock if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{12335}, CVariant{750})) return false; - share->m_iHasLock = 0; + share->m_iHasLock = LOCK_STATE_NO_LOCK; CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "lockmode", "0"); CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "lockcode", "0"); CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "badpwdcount", "0"); diff -Nru kodi-18.6+git20200408.1716-final/xbmc/dialogs/GUIDialogKaiToast.cpp kodi-18.7+git20200520.1011-final/xbmc/dialogs/GUIDialogKaiToast.cpp --- kodi-18.6+git20200408.1716-final/xbmc/dialogs/GUIDialogKaiToast.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/dialogs/GUIDialogKaiToast.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -7,11 +7,13 @@ */ #include "GUIDialogKaiToast.h" + +#include "ServiceBroker.h" +#include "guilib/GUIFadeLabelControl.h" #include "guilib/GUIMessage.h" #include "peripherals/Peripherals.h" #include "threads/SingleLock.h" #include "utils/TimeUtils.h" -#include "ServiceBroker.h" #define POPUP_ICON 400 #define POPUP_CAPTION_TEXT 401 @@ -89,6 +91,13 @@ if (!m_notifications.empty() && CTimeUtils::GetFrameTime() - m_timer > m_toastMessageTime) { + // if we have a fade label control for the text to display, ensure the whole text was shown + // (scrolled to the end) before we move on to the next message + const CGUIFadeLabelControl* notificationText = + dynamic_cast(GetControl(POPUP_NOTIFICATION_BUTTON)); + if (notificationText && !notificationText->AllLabelsShown()) + return false; + Notification toast = m_notifications.front(); m_notifications.pop(); lock.Leave(); @@ -147,7 +156,22 @@ // now check if we should exit if (CTimeUtils::GetFrameTime() - m_timer > m_toastDisplayTime) - Close(); + { + bool bClose = true; + + // if we have a fade label control for the text to display, ensure the whole text was shown + // (scrolled to the end) before we're closing the toast dialog + const CGUIFadeLabelControl* notificationText = + dynamic_cast(GetControl(POPUP_NOTIFICATION_BUTTON)); + if (notificationText) + { + CSingleLock lock(m_critical); + bClose = notificationText->AllLabelsShown() && m_notifications.empty(); + } + + if (bClose) + Close(); + } CGUIDialog::FrameMove(); } diff -Nru kodi-18.6+git20200408.1716-final/xbmc/favourites/GUIDialogFavourites.cpp kodi-18.7+git20200520.1011-final/xbmc/favourites/GUIDialogFavourites.cpp --- kodi-18.6+git20200408.1716-final/xbmc/favourites/GUIDialogFavourites.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/favourites/GUIDialogFavourites.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -93,10 +93,11 @@ if (item < 0 || item >= m_favourites->Size()) return; - Close(); - CGUIMessage message(GUI_MSG_EXECUTE, 0, GetID()); message.SetStringParam(m_favouritesService.GetExecutePath(*(*m_favourites)[item], GetID())); + + Close(); + CServiceBroker::GetGUI()->GetWindowManager().SendMessage(message); } diff -Nru kodi-18.6+git20200408.1716-final/xbmc/FileItem.cpp kodi-18.7+git20200520.1011-final/xbmc/FileItem.cpp --- kodi-18.6+git20200408.1716-final/xbmc/FileItem.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/FileItem.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,63 +1,64 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later * See LICENSES/README.md for more information. */ -#include - #include "FileItem.h" + +#include "CueDocument.h" #include "ServiceBroker.h" -#include "guilib/LocalizeStrings.h" -#include "utils/StringUtils.h" -#include "utils/URIUtils.h" -#include "utils/Archive.h" +#include "URL.h" #include "Util.h" -#include "playlists/PlayListFactory.h" -#include "utils/Crc32.h" +#include "events/IEvent.h" +#include "filesystem/CurlFile.h" #include "filesystem/Directory.h" #include "filesystem/File.h" -#include "filesystem/StackDirectory.h" -#include "filesystem/CurlFile.h" #include "filesystem/MultiPathDirectory.h" #include "filesystem/MusicDatabaseDirectory.h" +#include "filesystem/StackDirectory.h" #include "filesystem/VideoDatabaseDirectory.h" #include "filesystem/VideoDatabaseDirectory/QueryParams.h" -#include "games/addons/GameClient.h" #include "games/GameUtils.h" +#include "games/addons/GameClient.h" #include "games/tags/GameInfoTag.h" -#include "music/tags/MusicInfoTagLoaderFactory.h" -#include "CueDocument.h" -#include "video/VideoDatabase.h" +#include "guilib/LocalizeStrings.h" +#include "media/MediaLockState.h" +#include "music/Album.h" +#include "music/Artist.h" #include "music/MusicDatabase.h" +#include "music/tags/MusicInfoTag.h" +#include "music/tags/MusicInfoTagLoaderFactory.h" +#include "pictures/PictureInfoTag.h" +#include "playlists/PlayListFactory.h" #include "pvr/PVRManager.h" -#include "pvr/channels/PVRChannelGroupsContainer.h" #include "pvr/channels/PVRChannel.h" +#include "pvr/channels/PVRChannelGroupsContainer.h" #include "pvr/epg/Epg.h" #include "pvr/recordings/PVRRecording.h" #include "pvr/timers/PVRTimerInfoTag.h" -#include "video/Bookmark.h" -#include "video/VideoInfoTag.h" -#include "threads/SingleLock.h" -#include "music/tags/MusicInfoTag.h" -#include "pictures/PictureInfoTag.h" -#include "music/Artist.h" -#include "music/Album.h" -#include "URL.h" #include "settings/AdvancedSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" +#include "threads/SingleLock.h" +#include "utils/Archive.h" +#include "utils/Crc32.h" #include "utils/FileExtensionProvider.h" -#include "utils/RegExp.h" -#include "utils/log.h" -#include "utils/Variant.h" #include "utils/Mime.h" #include "utils/Random.h" -#include "events/IEvent.h" +#include "utils/RegExp.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "utils/Variant.h" +#include "utils/log.h" +#include "video/Bookmark.h" +#include "video/VideoDatabase.h" +#include "video/VideoInfoTag.h" #include +#include using namespace KODI; using namespace XFILE; @@ -493,7 +494,7 @@ m_idepth = 1; m_iLockMode = LOCK_MODE_EVERYONE; m_iBadPwdCount = 0; - m_iHasLock = 0; + m_iHasLock = LOCK_STATE_NO_LOCK; m_bCanQueue = true; m_specialSort = SortSpecialNone; m_doContentLookup = true; @@ -1198,6 +1199,16 @@ return item.IsBDFile(); } +bool CFileItem::IsProtectedBlurayDisc() const +{ + std::string path; + path = URIUtils::AddFileToFolder(GetPath(), "AACS", "Unit_Key_RO.inf"); + if (CFile::Exists(path)) + return true; + + return false; +} + bool CFileItem::IsCDDA() const { return URIUtils::IsCDDA(m_strPath); diff -Nru kodi-18.6+git20200408.1716-final/xbmc/FileItem.h kodi-18.7+git20200520.1011-final/xbmc/FileItem.h --- kodi-18.6+git20200408.1716-final/xbmc/FileItem.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/FileItem.h 2012-11-04 08:41:54.000000000 +0000 @@ -202,6 +202,7 @@ bool IsDVDFile(bool bVobs = true, bool bIfos = true) const; bool IsBDFile() const; bool IsBluray() const; + bool IsProtectedBlurayDisc() const; bool IsRAR() const; bool IsAPK() const; bool IsZIP() const; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/filesystem/CurlFile.cpp kodi-18.7+git20200520.1011-final/xbmc/filesystem/CurlFile.cpp --- kodi-18.6+git20200408.1716-final/xbmc/filesystem/CurlFile.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/filesystem/CurlFile.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -601,8 +601,11 @@ StringUtils::Format(":%d", m_proxyport); g_curlInterface.easy_setopt(h, CURLOPT_PROXY, hostport.c_str()); - const std::string userpass = - m_proxyuser + std::string(":") + m_proxypassword; + std::string userpass; + + if (!m_proxyuser.empty() && !m_proxypassword.empty()) + userpass = CURL::Encode(m_proxyuser) + ":" + CURL::Encode(m_proxypassword); + if (!userpass.empty()) g_curlInterface.easy_setopt(h, CURLOPT_PROXYUSERPWD, userpass.c_str()); } diff -Nru kodi-18.6+git20200408.1716-final/xbmc/filesystem/FileDirectoryFactory.cpp kodi-18.7+git20200520.1011-final/xbmc/filesystem/FileDirectoryFactory.cpp --- kodi-18.6+git20200408.1716-final/xbmc/filesystem/FileDirectoryFactory.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/filesystem/FileDirectoryFactory.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -88,7 +88,7 @@ else { // compressed or more than one file -> create a dir - *pItem = wrap->m_items; + pItem->SetPath(wrap->m_items.GetPath()); } // Check for folder, if yes return also wrap. diff -Nru kodi-18.6+git20200408.1716-final/xbmc/filesystem/SourcesDirectory.cpp kodi-18.7+git20200520.1011-final/xbmc/filesystem/SourcesDirectory.cpp --- kodi-18.6+git20200408.1716-final/xbmc/filesystem/SourcesDirectory.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/filesystem/SourcesDirectory.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,22 +1,24 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later * See LICENSES/README.md for more information. */ -#include "ServiceBroker.h" #include "SourcesDirectory.h" -#include "utils/URIUtils.h" + +#include "File.h" +#include "FileItem.h" +#include "ServiceBroker.h" #include "URL.h" #include "Util.h" -#include "FileItem.h" -#include "File.h" +#include "guilib/TextureManager.h" +#include "media/MediaLockState.h" #include "profiles/ProfileManager.h" #include "settings/MediaSourceSettings.h" -#include "guilib/TextureManager.h" #include "storage/MediaManager.h" +#include "utils/URIUtils.h" using namespace XFILE; @@ -87,7 +89,8 @@ strIcon = "DefaultHardDisk.png"; pItem->SetIconImage(strIcon); - if (share.m_iHasLock == 2 && m_profileManager->GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE) + if (share.m_iHasLock == LOCK_STATE_LOCKED && + m_profileManager->GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE) pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_LOCKED); else pItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_NONE); Binary files /tmp/tmp0DZV5u/kSZJC6I1fw/kodi-18.6+git20200408.1716-final/xbmc/filesystem/test/extendedlocalheader.zip and /tmp/tmp0DZV5u/UU5Xf7IkiM/kodi-18.7+git20200520.1011-final/xbmc/filesystem/test/extendedlocalheader.zip differ diff -Nru kodi-18.6+git20200408.1716-final/xbmc/filesystem/test/TestZipFile.cpp kodi-18.7+git20200520.1011-final/xbmc/filesystem/test/TestZipFile.cpp --- kodi-18.6+git20200408.1716-final/xbmc/filesystem/test/TestZipFile.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/filesystem/test/TestZipFile.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -9,12 +9,13 @@ #include "ServiceBroker.h" #include "filesystem/Directory.h" #include "filesystem/File.h" -#include "utils/StringUtils.h" -#include "utils/URIUtils.h" +#include "filesystem/ZipFile.h" #include "FileItem.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "test/TestUtils.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" #include "URL.h" #include @@ -207,3 +208,22 @@ file->Close(); XBMC_DELETETEMPFILE(file); } + +TEST_F(TestZipFile, ExtendedLocalHeader) +{ + XFILE::CFile file; + ssize_t readlen; + char zipdata[20000]; // size of zip file is 15352 Bytes + + ASSERT_TRUE(file.Open(XBMC_REF_FILE_PATH("xbmc/filesystem/test/extendedlocalheader.zip"))); + readlen = file.Read(zipdata, sizeof(zipdata)); + EXPECT_TRUE(readlen); + + XFILE::CZipFile zipfile; + std::string strBuffer; + + int iSize = zipfile.UnpackFromMemory(strBuffer, std::string(zipdata, readlen), false); + EXPECT_EQ(152774, iSize); // sum of uncompressed size of all files in zip + EXPECT_TRUE(strBuffer.substr(0, 6) == ""); + file.Close(); +} diff -Nru kodi-18.6+git20200408.1716-final/xbmc/filesystem/ZipFile.cpp kodi-18.7+git20200520.1011-final/xbmc/filesystem/ZipFile.cpp --- kodi-18.6+git20200408.1716-final/xbmc/filesystem/ZipFile.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/filesystem/ZipFile.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -398,12 +398,47 @@ if (!isGZ) { CZipManager::readHeader(strInput.data()+iPos,mZipItem); - if( mZipItem.header != ZIP_LOCAL_HEADER ) + if (mZipItem.header == ZIP_DATA_RECORD_HEADER) + { + // this header concerns a file we already processed, so we can just skip it + iPos += DREC_SIZE; + continue; + } + if (mZipItem.header != ZIP_LOCAL_HEADER) return iResult; if( (mZipItem.flags & 8) == 8 ) { - CLog::Log(LOGERROR,"FileZip: extended local header, not supported!"); - return iResult; + // if an extended local header (=data record header) is present, + // the following fields are 0 in the local header and we need to read + // them from the extended local header + + // search for the extended local header + unsigned int i = iPos + LHDR_SIZE + mZipItem.flength + mZipItem.elength; + while (1) + { + if (i + DREC_SIZE > strInput.size()) + { + CLog::Log(LOGERROR, "FileZip: extended local header expected, but not present!"); + return iResult; + } + if ((strInput[i] == 0x50) && (strInput[i + 1] == 0x4b) && + (strInput[i + 2] == 0x07) && (strInput[i + 3] == 0x08)) + break; // header found + i++; + } + // ZIP is little endian: + mZipItem.crc32 = static_cast(strInput[i + 4]) | + static_cast(strInput[i + 5]) << 8 | + static_cast(strInput[i + 6]) << 16 | + static_cast(strInput[i + 7]) << 24; + mZipItem.csize = static_cast(strInput[i + 8]) | + static_cast(strInput[i + 9]) << 8 | + static_cast(strInput[i + 10]) << 16 | + static_cast(strInput[i + 11]) << 24; + mZipItem.usize = static_cast(strInput[i + 12]) | + static_cast(strInput[i + 13]) << 8 | + static_cast(strInput[i + 14]) << 16 | + static_cast(strInput[i + 15]) << 24; } } if (!InitDecompress()) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/filesystem/ZipManager.h kodi-18.7+git20200520.1011-final/xbmc/filesystem/ZipManager.h --- kodi-18.6+git20200408.1716-final/xbmc/filesystem/ZipManager.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/filesystem/ZipManager.h 2012-11-04 08:41:54.000000000 +0000 @@ -15,6 +15,7 @@ #define ZIP_END_CENTRAL_HEADER 0x06054b50 #define ZIP_SPLIT_ARCHIVE_HEADER 0x30304b50 #define LHDR_SIZE 30 +#define DREC_SIZE 16 #define CHDR_SIZE 46 #define ECDREC_SIZE 22 diff -Nru kodi-18.6+git20200408.1716-final/xbmc/games/windows/GUIWindowGames.cpp kodi-18.7+git20200520.1011-final/xbmc/games/windows/GUIWindowGames.cpp --- kodi-18.6+git20200408.1716-final/xbmc/games/windows/GUIWindowGames.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/games/windows/GUIWindowGames.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2018 Team Kodi + * Copyright (C) 2012-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -7,24 +7,26 @@ */ #include "GUIWindowGames.h" -#include "addons/GUIDialogAddonInfo.h" + #include "Application.h" +#include "FileItem.h" +#include "GUIPassword.h" +#include "PlayListPlayer.h" +#include "ServiceBroker.h" +#include "URL.h" +#include "Util.h" +#include "addons/GUIDialogAddonInfo.h" #include "dialogs/GUIDialogContextMenu.h" #include "dialogs/GUIDialogMediaSource.h" #include "dialogs/GUIDialogProgress.h" -#include "FileItem.h" #include "games/addons/GameClient.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" #include "guilib/WindowIDs.h" -#include "GUIPassword.h" -#include "PlayListPlayer.h" -#include "ServiceBroker.h" +#include "media/MediaLockState.h" #include "settings/MediaSourceSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" -#include "URL.h" -#include "Util.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" @@ -291,7 +293,7 @@ int iIndex = CUtil::GetMatchingSource(dir, shares, bIsSourceName); if (iIndex >= 0) { - if (iIndex < (int)shares.size() && shares[iIndex].m_iHasLock == 2) + if (iIndex < static_cast(shares.size()) && shares[iIndex].m_iHasLock == LOCK_STATE_LOCKED) { CFileItem item(shares[iIndex]); if (!g_passwordManager.IsItemUnlocked(&item, "games")) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/guilib/GUIFadeLabelControl.cpp kodi-18.7+git20200520.1011-final/xbmc/guilib/GUIFadeLabelControl.cpp --- kodi-18.6+git20200408.1716-final/xbmc/guilib/GUIFadeLabelControl.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/guilib/GUIFadeLabelControl.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -44,6 +44,7 @@ m_shortText = from.m_shortText; m_scroll = from.m_scroll; m_randomized = from.m_randomized; + m_allLabelsShown = from.m_allLabelsShown; } CGUIFadeLabelControl::~CGUIFadeLabelControl(void) = default; @@ -52,6 +53,7 @@ { m_lastLabel = -1; m_infoLabels = infoLabels; + m_allLabelsShown = m_infoLabels.empty(); if (m_randomized) KODI::UTILS::RandomShuffle(m_infoLabels.begin(), m_infoLabels.end()); } @@ -59,6 +61,7 @@ void CGUIFadeLabelControl::AddLabel(const std::string &label) { m_infoLabels.push_back(GUIINFO::CGUIInfoLabel(label, "", GetParentID())); + m_allLabelsShown = false; } void CGUIFadeLabelControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) @@ -89,6 +92,10 @@ } MarkDirtyRegion(); } + + if (m_shortText && m_infoLabels.size() == 1) + m_allLabelsShown = true; + if (m_currentLabel != m_lastLabel) { // new label - reset scrolling m_scrollInfo.Reset(); @@ -131,7 +138,10 @@ if (m_fadeAnim.GetProcess() != ANIM_PROCESS_NORMAL) { if (++m_currentLabel >= m_infoLabels.size()) + { m_currentLabel = 0; + m_allLabelsShown = true; + } m_scrollInfo.Reset(); m_fadeAnim.QueueAnimation(ANIM_PROCESS_REVERSE); } @@ -216,6 +226,7 @@ { m_lastLabel = -1; m_infoLabels.clear(); + m_allLabelsShown = true; m_scrollInfo.Reset(); return true; } @@ -223,6 +234,7 @@ { m_lastLabel = -1; m_infoLabels.clear(); + m_allLabelsShown = true; m_scrollInfo.Reset(); AddLabel(message.GetLabel()); return true; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/guilib/GUIFadeLabelControl.h kodi-18.7+git20200520.1011-final/xbmc/guilib/GUIFadeLabelControl.h --- kodi-18.6+git20200408.1716-final/xbmc/guilib/GUIFadeLabelControl.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/guilib/GUIFadeLabelControl.h 2012-11-04 08:41:54.000000000 +0000 @@ -39,6 +39,8 @@ void SetInfo(const std::vector &vecInfo); void SetScrolling(bool scroll) { m_scroll = scroll; } + bool AllLabelsShown() const { return m_allLabelsShown; } + protected: bool UpdateColors() override; std::string GetDescription() const override; @@ -71,5 +73,6 @@ unsigned int m_scrollSpeed; bool m_resetOnLabelChange; bool m_randomized; + bool m_allLabelsShown = true; }; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/guilib/GUIWindowManager.cpp kodi-18.7+git20200520.1011-final/xbmc/guilib/GUIWindowManager.cpp --- kodi-18.6+git20200408.1716-final/xbmc/guilib/GUIWindowManager.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/guilib/GUIWindowManager.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -776,9 +776,18 @@ // debug CLog::Log(LOGDEBUG, "Activating window ID: %i", iWindowID); + // make sure we check mediasources from home + if (GetActiveWindow() == WINDOW_HOME) + g_passwordManager.strMediasourcePath = !params.empty() ? params[0] : ""; + else + g_passwordManager.strMediasourcePath = ""; + if (!g_passwordManager.CheckMenuLock(iWindowID)) { - CLog::Log(LOGERROR, "MasterCode is Wrong: Window with id %d will not be loaded! Enter a correct MasterCode!", iWindowID); + CLog::Log(LOGERROR, + "MasterCode or Mediasource-code is wrong: Window with id {} will not be loaded! " + "Enter a correct code!", + iWindowID); if (GetActiveWindow() == WINDOW_INVALID && iWindowID != WINDOW_HOME) ActivateWindow(WINDOW_HOME); return; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/GUIPassword.cpp kodi-18.7+git20200520.1011-final/xbmc/GUIPassword.cpp --- kodi-18.6+git20200408.1716-final/xbmc/GUIPassword.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/GUIPassword.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -7,27 +7,30 @@ */ #include "GUIPassword.h" + +#include "FileItem.h" #include "GUIUserMessages.h" #include "ServiceBroker.h" -#include "messaging/ApplicationMessenger.h" +#include "Util.h" #include "dialogs/GUIDialogGamepad.h" +#include "dialogs/GUIDialogNumeric.h" #include "guilib/GUIComponent.h" #include "guilib/GUIKeyboardFactory.h" -#include "dialogs/GUIDialogNumeric.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "media/MediaLockState.h" +#include "messaging/ApplicationMessenger.h" +#include "messaging/helpers/DialogOKHelper.h" #include "profiles/ProfileManager.h" #include "profiles/dialogs/GUIDialogLockSettings.h" #include "profiles/dialogs/GUIDialogProfileSettings.h" -#include "Util.h" #include "settings/MediaSourceSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" -#include "guilib/GUIWindowManager.h" -#include "FileItem.h" -#include "guilib/LocalizeStrings.h" -#include "messaging/helpers/DialogOKHelper.h" #include "utils/StringUtils.h" -#include "view/ViewStateSettings.h" #include "utils/Variant.h" +#include "utils/log.h" +#include "view/ViewStateSettings.h" #include @@ -40,41 +43,33 @@ } CGUIPassword::~CGUIPassword(void) = default; -bool CGUIPassword::IsItemUnlocked(CFileItem* pItem, const std::string &strType) +template +bool CGUIPassword::IsItemUnlocked(T pItem, + const std::string& strType, + const std::string& strLabel, + const std::string& strHeading) { - const std::shared_ptr profileManager = CServiceBroker::GetSettingsComponent()->GetProfileManager(); - - // \brief Tests if the user is allowed to access the share folder - // \param pItem The share folder item to access - // \param strType The type of share being accessed, e.g. "music", "video", etc. See CSettings::UpdateSources() - // \return If access is granted, returns \e true + const std::shared_ptr profileManager = + CServiceBroker::GetSettingsComponent()->GetProfileManager(); if (profileManager->GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE) return true; - while (pItem->m_iHasLock > 1) + while (pItem->m_iHasLock > LOCK_STATE_LOCK_BUT_UNLOCKED) { - std::string strLockCode = pItem->m_strLockCode; - std::string strLabel = pItem->GetLabel(); - int iResult = 0; // init to user succeeded state, doing this to optimize switch statement below - char buffer[33]; // holds 32 places plus sign character - if(g_passwordManager.bMasterUser)// Check if we are the MasterUser! + const std::string strLockCode = pItem->m_strLockCode; + int iResult = 0; // init to user succeeded state, doing this to optimize switch statement below + if (!g_passwordManager.bMasterUser) // Check if we are the MasterUser! { - iResult = 0; - } - else - { - if (0 != CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_MASTERLOCK_MAXRETRIES) && pItem->m_iBadPwdCount >= CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_MASTERLOCK_MAXRETRIES)) - { // user previously exhausted all retries, show access denied error + if (0 != CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt( + CSettings::SETTING_MASTERLOCK_MAXRETRIES) && + pItem->m_iBadPwdCount >= CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt( + CSettings::SETTING_MASTERLOCK_MAXRETRIES)) + { + // user previously exhausted all retries, show access denied error HELPERS::ShowOKDialogText(CVariant{12345}, CVariant{12346}); return false; } // show the appropriate lock dialog - std::string strHeading = ""; - if (pItem->m_bIsFolder) - strHeading = g_localizeStrings.Get(12325); - else - strHeading = g_localizeStrings.Get(12348); - iResult = VerifyPassword(pItem->m_iLockMode, strLockCode, strHeading); } switch (iResult) @@ -88,20 +83,21 @@ { // password entry succeeded pItem->m_iBadPwdCount = 0; - pItem->m_iHasLock = 1; - g_passwordManager.LockSource(strType,strLabel,false); - sprintf(buffer,"%i",pItem->m_iBadPwdCount); - CMediaSourceSettings::GetInstance().UpdateSource(strType, strLabel, "badpwdcount", buffer); + pItem->m_iHasLock = LOCK_STATE_LOCK_BUT_UNLOCKED; + g_passwordManager.LockSource(strType, strLabel, false); + CMediaSourceSettings::GetInstance().UpdateSource(strType, strLabel, "badpwdcount", + std::to_string(pItem->m_iBadPwdCount)); CMediaSourceSettings::GetInstance().Save(); break; } case 1: { // password entry failed - if (0 != CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_MASTERLOCK_MAXRETRIES)) + if (0 != CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt( + CSettings::SETTING_MASTERLOCK_MAXRETRIES)) pItem->m_iBadPwdCount++; - sprintf(buffer,"%i",pItem->m_iBadPwdCount); - CMediaSourceSettings::GetInstance().UpdateSource(strType, strLabel, "badpwdcount", buffer); + CMediaSourceSettings::GetInstance().UpdateSource(strType, strLabel, "badpwdcount", + std::to_string(pItem->m_iBadPwdCount)); CMediaSourceSettings::GetInstance().Save(); break; } @@ -116,12 +112,32 @@ return true; } +bool CGUIPassword::IsItemUnlocked(CFileItem* pItem, const std::string& strType) +{ + const std::string strLabel = pItem->GetLabel(); + std::string strHeading; + if (pItem->m_bIsFolder) + strHeading = g_localizeStrings.Get(12325); // "Locked! Enter code..." + else + strHeading = g_localizeStrings.Get(12348); // "Item locked" + + return IsItemUnlocked(pItem, strType, strLabel, strHeading); +} + +bool CGUIPassword::IsItemUnlocked(CMediaSource* pItem, const std::string& strType) +{ + const std::string strLabel = pItem->strName; + std::string strHeading = g_localizeStrings.Get(12325); // "Locked! Enter code..." + + return IsItemUnlocked(pItem, strType, strLabel, strHeading); +} + bool CGUIPassword::CheckStartUpLock() { // prompt user for mastercode if the mastercode was set b4 or by xml int iVerifyPasswordResult = -1; - std::string strHeader = g_localizeStrings.Get(20075); + std::string strHeader = g_localizeStrings.Get(20075); // "Enter master lock code" if (iMasterLockRetriesLeft == -1) iMasterLockRetriesLeft = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_MASTERLOCK_MAXRETRIES); @@ -143,7 +159,7 @@ if (iVerifyPasswordResult != 0 ) { std::string strLabel1; - strLabel1 = g_localizeStrings.Get(12343); + strLabel1 = g_localizeStrings.Get(12343); // "retries left" int iLeft = g_passwordManager.iMasterLockRetriesLeft-i; std::string strLabel = StringUtils::Format("%i %s", iLeft, strLabel1.c_str()); @@ -175,6 +191,7 @@ if (profile) { CProfile::CLock locks = profile->GetLocks(); + // prompt user for master lock if (CGUIDialogLockSettings::ShowAndGetLock(locks, 12360, true, bDetails)) { profile->SetLocks(locks); @@ -224,6 +241,7 @@ else { if (profileManager->GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE) + // prompt user for profile lock code return CheckLock(profile->getLockMode(),profile->getLockCode(),20095,bCanceled); } } @@ -301,14 +319,15 @@ g_passwordManager.iMasterLockRetriesLeft = 0; // Tell the user they ran out of retry attempts HELPERS::ShowOKDialogText(CVariant{12345}, CVariant{12346}); - return ; + return; } } std::string dlgLine1 = ""; if (0 < g_passwordManager.iMasterLockRetriesLeft) - dlgLine1 = StringUtils::Format("%d %s", - g_passwordManager.iMasterLockRetriesLeft, - g_localizeStrings.Get(12343).c_str()); + dlgLine1 = StringUtils::Format("%d %s", g_passwordManager.iMasterLockRetriesLeft, + g_localizeStrings.Get(12343).c_str()); // "retries left" + + // prompt user for master lock HELPERS::ShowOKDialogLines(CVariant{20075}, CVariant{12345}, CVariant{std::move(dlgLine1)}, CVariant{0}); } else @@ -427,9 +446,13 @@ break; case WINDOW_MUSIC_NAV: // Music bCheckPW = profileManager->GetCurrentProfile().musicLocked(); + if (!bCheckPW && strMediasourcePath != "") // check mediasource by path + return g_passwordManager.IsMediaPathUnlocked(strMediasourcePath, "music"); break; case WINDOW_VIDEO_NAV: // Video bCheckPW = profileManager->GetCurrentProfile().videoLocked(); + if (!bCheckPW && strMediasourcePath != "") // check mediasource by path + return g_passwordManager.IsMediaPathUnlocked(strMediasourcePath, "video"); break; case WINDOW_PICTURES: // Pictures bCheckPW = profileManager->GetCurrentProfile().picturesLocked(); @@ -458,9 +481,9 @@ { if (it->strName == strName) { - if (it->m_iHasLock > 0) + if (it->m_iHasLock > LOCK_STATE_NO_LOCK) { - it->m_iHasLock = bState?2:1; + it->m_iHasLock = bState ? LOCK_STATE_LOCKED : LOCK_STATE_LOCK_BUT_UNLOCKED; bResult = true; } break; @@ -481,7 +504,7 @@ VECSOURCES *shares = CMediaSourceSettings::GetInstance().GetSources(strType); for (IVECSOURCES it=shares->begin();it != shares->end();++it) if (it->m_iLockMode != LOCK_MODE_EVERYONE) - it->m_iHasLock = lock ? 2 : 1; + it->m_iHasLock = lock ? LOCK_STATE_LOCKED : LOCK_STATE_LOCK_BUT_UNLOCKED; } CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg); @@ -497,9 +520,11 @@ for (IVECSOURCES it=shares->begin();it != shares->end();++it) if (it->m_iLockMode != LOCK_MODE_EVERYONE) // remove old info { - it->m_iHasLock = 0; + it->m_iHasLock = LOCK_STATE_NO_LOCK; it->m_iLockMode = LOCK_MODE_EVERYONE; - CMediaSourceSettings::GetInstance().UpdateSource(strType, it->strName, "lockmode", "0"); // removes locks from xml + + // remove locks from xml + CMediaSourceSettings::GetInstance().UpdateSource(strType, it->strName, "lockmode", "0"); } } CMediaSourceSettings::GetInstance().Save(); @@ -518,13 +543,40 @@ bool bName = false; int iIndex = CUtil::GetMatchingSource(strPath, vecSources, bName); - if (iIndex > -1 && iIndex < (int)vecSources.size()) - if (vecSources[iIndex].m_iHasLock < 2) + if (iIndex > -1 && iIndex < static_cast(vecSources.size())) + if (vecSources[iIndex].m_iHasLock < LOCK_STATE_LOCKED) return true; return false; } +bool CGUIPassword::IsMediaPathUnlocked(const std::string& strPath, const std::string& strType) +{ + if (StringUtils::StartsWithNoCase(strPath, "root") || + StringUtils::StartsWithNoCase(strPath, "library://")) + { + // no mediasource-lookup needed + CLog::Log(LOGDEBUG, "CGUIPassword::IsMediaPathUnlocked - entering from {}", strPath); + return true; + } + + const std::shared_ptr profileManager = + CServiceBroker::GetSettingsComponent()->GetProfileManager(); + if (g_passwordManager.bMasterUser || + profileManager->GetMasterProfile().getLockMode() == LOCK_MODE_EVERYONE) + return true; + + VECSOURCES& vecSources = *CMediaSourceSettings::GetInstance().GetSources(strType); + bool bName = false; + int iIndex = CUtil::GetMatchingSource(strPath, vecSources, bName); + if (iIndex > -1 && iIndex < static_cast(vecSources.size())) + return g_passwordManager.IsItemUnlocked(&vecSources[iIndex], strType); + + // need to add a missing filter (root/library.. etc.) + CLog::Log(LOGERROR, "CGUIPassword::IsMediaPathUnlocked - missing filter: {}", strPath); + return true; +} + void CGUIPassword::OnSettingAction(std::shared_ptr setting) { if (setting == NULL) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/GUIPassword.h kodi-18.7+git20200520.1011-final/xbmc/GUIPassword.h --- kodi-18.6+git20200408.1716-final/xbmc/GUIPassword.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/GUIPassword.h 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -25,7 +25,22 @@ public: CGUIPassword(void); ~CGUIPassword(void) override; + template + bool IsItemUnlocked(T pItem, + const std::string& strType, + const std::string& strLabel, + const std::string& strHeading); + /*! \brief Tests if the user is allowed to access the share folder + \param pItem The share folder item to access + \param strType The type of share being accessed, e.g. "music", "video", etc. See CSettings::UpdateSources() + \return If access is granted, returns \e true + */ bool IsItemUnlocked(CFileItem* pItem, const std::string &strType); + /*! \brief Tests if the user is allowed to access the Mediasource + \param pItem The share folder item to access + \param strType The type of share being accessed, e.g. "music", "video", etc. See CSettings::UpdateSources() + \return If access is granted, returns \e true + */ bool IsItemUnlocked(CMediaSource* pItem, const std::string &strType); bool CheckLock(LockType btnType, const std::string& strPassword, int iHeading); bool CheckLock(LockType btnType, const std::string& strPassword, int iHeading, bool& bCanceled); @@ -49,11 +64,18 @@ void LockSources(bool lock); void RemoveSourceLocks(); bool IsDatabasePathUnlocked(const std::string& strPath, VECSOURCES& vecSources); + /*! \brief Tests if the user is allowed to access the path by looking up the matching Mediasource + \param strPath The folder path to access + \param strType The type of share being accessed, e.g. "music", "video", etc. See CSettings::UpdateSources() + \return If access is granted, returns \e true + */ + bool IsMediaPathUnlocked(const std::string& strPath, const std::string& strType); void OnSettingAction(std::shared_ptr setting) override; bool bMasterUser; int iMasterLockRetriesLeft; + std::string strMediasourcePath; private: int VerifyPassword(LockType btnType, const std::string& strPassword, const std::string& strHeading); diff -Nru kodi-18.6+git20200408.1716-final/xbmc/input/InputManager.cpp kodi-18.7+git20200520.1011-final/xbmc/input/InputManager.cpp --- kodi-18.6+git20200408.1716-final/xbmc/input/InputManager.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/input/InputManager.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -418,12 +418,6 @@ CApplicationMessenger::GetInstance().PostMsg(TMSG_GUI_ACTION, WINDOW_INVALID, -1, static_cast(new CAction(actionId))); } - // Post an unfocus message for touch device after the action. - if (newEvent.touch.action == ACTION_GESTURE_END || newEvent.touch.action == ACTION_TOUCH_TAP) - { - CGUIMessage msg(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0); - CApplicationMessenger::GetInstance().SendGUIMessage(msg); - } break; } //case case XBMC_BUTTON: diff -Nru kodi-18.6+git20200408.1716-final/xbmc/interfaces/json-rpc/FileOperations.cpp kodi-18.7+git20200520.1011-final/xbmc/interfaces/json-rpc/FileOperations.cpp --- kodi-18.6+git20200408.1716-final/xbmc/interfaces/json-rpc/FileOperations.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/interfaces/json-rpc/FileOperations.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -7,21 +7,23 @@ */ #include "FileOperations.h" -#include "VideoLibrary.h" + #include "AudioLibrary.h" +#include "FileItem.h" #include "MediaSource.h" #include "ServiceBroker.h" +#include "URL.h" +#include "Util.h" +#include "VideoLibrary.h" #include "filesystem/Directory.h" #include "filesystem/File.h" -#include "FileItem.h" +#include "media/MediaLockState.h" #include "settings/AdvancedSettings.h" #include "settings/MediaSourceSettings.h" #include "settings/SettingsComponent.h" -#include "Util.h" -#include "URL.h" #include "utils/FileExtensionProvider.h" -#include "utils/URIUtils.h" #include "utils/FileUtils.h" +#include "utils/URIUtils.h" #include "utils/Variant.h" #include "video/VideoDatabase.h" @@ -40,7 +42,7 @@ for (unsigned int i = 0; i < (unsigned int)sources->size(); i++) { // Do not show sources which are locked - if (sources->at(i).m_iHasLock == 2) + if (sources->at(i).m_iHasLock == LOCK_STATE_LOCKED) continue; items.Add(CFileItemPtr(new CFileItem(sources->at(i)))); diff -Nru kodi-18.6+git20200408.1716-final/xbmc/interfaces/legacy/Control.cpp kodi-18.7+git20200520.1011-final/xbmc/interfaces/legacy/Control.cpp --- kodi-18.6+git20200408.1716-final/xbmc/interfaces/legacy/Control.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/interfaces/legacy/Control.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -130,17 +130,21 @@ void ControlTextBox::setText(const String& text) { - // create message - CGUIMessage msg(GUI_MSG_LABEL_SET, iParentId, iControlId); - msg.SetLabel(text); - - // send message - CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg, iParentId); + if (pGUIControl) + { + // create message + CGUIMessage msg(GUI_MSG_LABEL_SET, iParentId, iControlId); + msg.SetLabel(text); + + // send message + CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg, iParentId); + } } String ControlTextBox::getText() { - if (!pGUIControl) return NULL; + if (!pGUIControl) + return nullptr; XBMCAddonUtils::GuiLock lock(languageHook, false); return static_cast(pGUIControl)->GetDescription(); @@ -148,19 +152,24 @@ void ControlTextBox::reset() { - // create message - CGUIMessage msg(GUI_MSG_LABEL_RESET, iParentId, iControlId); - CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg, iParentId); + if (pGUIControl) + { + // create message + CGUIMessage msg(GUI_MSG_LABEL_RESET, iParentId, iControlId); + CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg, iParentId); + } } void ControlTextBox::scroll(long position) { - static_cast(pGUIControl)->Scroll((int)position); + if (pGUIControl) + static_cast(pGUIControl)->Scroll((int)position); } void ControlTextBox::autoScroll(int delay, int time, int repeat) { - static_cast(pGUIControl)->SetAutoScrolling(delay, time, repeat); + if (pGUIControl) + static_cast(pGUIControl)->SetAutoScrolling(delay, time, repeat); } CGUIControl* ControlTextBox::Create() diff -Nru kodi-18.6+git20200408.1716-final/xbmc/interfaces/legacy/Control.h kodi-18.7+git20200520.1011-final/xbmc/interfaces/legacy/Control.h --- kodi-18.6+git20200408.1716-final/xbmc/interfaces/legacy/Control.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/interfaces/legacy/Control.h 2012-11-04 08:41:54.000000000 +0000 @@ -1842,6 +1842,21 @@ /// ... /// ~~~~~~~~~~~~~ /// + /// As stated above, the GUI control is only created once added to a window. The example + /// below shows how a ControlTextBox can be created, added to the current window and + /// have some of its properties changed. + /// + /// /// **Extended example:** + /// ~~~~~~~~~~~~~{.py} + /// ... + /// textbox = xbmcgui.ControlTextBox(100, 250, 300, 300, textColor='0xFFFFFFFF') + /// window = xbmcgui.Window(xbmcgui.getCurrentWindowId()) + /// window.addControl(textbox) + /// textbox.setText("My Text Box") + /// textbox.scroll() + /// ... + /// ~~~~~~~~~~~~~ + /// class ControlTextBox : public Control { public: @@ -1856,9 +1871,11 @@ /// @brief \python_func{ setText(text) } ///----------------------------------------------------------------------- /// Set's the text for this textbox. + /// \anchor python_xbmcgui_control_textbox_settext /// - /// @param text string or unicode - text string. + /// @param text string - text string. /// + /// @note setText only has effect after the control is added to a window /// ///-------------------------------------------------------------------------- /// @@ -1885,6 +1902,9 @@ /// /// @return To get text from box /// + /// @note getText only works after you add the control to a window + /// and set the control text (using \ref python_xbmcgui_control_textbox_settext + /// "setText"). /// ///----------------------------------------------------------------------- /// @@ -1909,6 +1929,7 @@ ///----------------------------------------------------------------------- /// Clear's this textbox. /// + /// @note reset only works after you add the control to a window. /// ///----------------------------------------------------------------------- /// @@ -1935,6 +1956,7 @@ /// /// @param id integer - position to scroll to. /// + /// @note scroll() only works after the control is added to a window. /// ///----------------------------------------------------------------------- /// @@ -1963,6 +1985,7 @@ /// @param time integer - Scroll time (in ms) /// @param repeat integer - Repeat time /// + /// @note autoScroll only works after you add the control to a window. /// ///----------------------------------------------------------------------- /// @python_v15 New function added. diff -Nru kodi-18.6+git20200408.1716-final/xbmc/interfaces/legacy/Window.cpp kodi-18.7+git20200520.1011-final/xbmc/interfaces/legacy/Window.cpp --- kodi-18.6+git20200408.1716-final/xbmc/interfaces/legacy/Window.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/interfaces/legacy/Window.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -715,7 +715,7 @@ if(pControl->iControlId != 0) throw WindowException("Control is already used"); - // lock xbmc GUI before accessing data from it + // lock kodi GUI before accessing data from it pControl->iParentId = iWindowId; { diff -Nru kodi-18.6+git20200408.1716-final/xbmc/LockType.h kodi-18.7+git20200520.1011-final/xbmc/LockType.h --- kodi-18.6+git20200408.1716-final/xbmc/LockType.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/LockType.h 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later diff -Nru kodi-18.6+git20200408.1716-final/xbmc/media/CMakeLists.txt kodi-18.7+git20200520.1011-final/xbmc/media/CMakeLists.txt --- kodi-18.6+git20200408.1716-final/xbmc/media/CMakeLists.txt 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/media/CMakeLists.txt 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,6 @@ set(SOURCES MediaType.cpp) -set(HEADERS MediaType.h) +set(HEADERS MediaLockState.h + MediaType.h) core_add_library(media) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/media/MediaLockState.h kodi-18.7+git20200520.1011-final/xbmc/media/MediaLockState.h --- kodi-18.6+git20200408.1716-final/xbmc/media/MediaLockState.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/media/MediaLockState.h 2012-11-04 08:41:54.000000000 +0000 @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2005-2020 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +typedef enum +{ + LOCK_STATE_NO_LOCK = 0, + LOCK_STATE_LOCK_BUT_UNLOCKED = 1, + LOCK_STATE_LOCKED = 2, +} MediaLockState; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/MediaSource.cpp kodi-18.7+git20200520.1011-final/xbmc/MediaSource.cpp --- kodi-18.6+git20200408.1716-final/xbmc/MediaSource.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/MediaSource.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -7,11 +7,13 @@ */ #include "MediaSource.h" -#include "Util.h" + #include "URL.h" +#include "Util.h" #include "filesystem/MultiPathDirectory.h" -#include "utils/URIUtils.h" +#include "media/MediaLockState.h" #include "utils/StringUtils.h" +#include "utils/URIUtils.h" using namespace XFILE; @@ -40,7 +42,7 @@ m_iLockMode = LOCK_MODE_EVERYONE; m_strLockCode = "0"; m_iBadPwdCount = 0; - m_iHasLock = 0; + m_iHasLock = LOCK_STATE_NO_LOCK; m_allowSharing = true; if (URIUtils::IsMultiPath(strPath)) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/MediaSource.h kodi-18.7+git20200520.1011-final/xbmc/MediaSource.h --- kodi-18.6+git20200408.1716-final/xbmc/MediaSource.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/MediaSource.h 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -8,9 +8,11 @@ #pragma once +#include "LockType.h" +#include "media/MediaLockState.h" + #include #include -#include "LockType.h" /*! \ingroup windows @@ -78,7 +80,7 @@ */ LockType m_iLockMode = LOCK_MODE_EVERYONE; std::string m_strLockCode; ///< Input code for Lock UI to verify, can be chosen freely. - int m_iHasLock = 0; + int m_iHasLock = LOCK_STATE_NO_LOCK; int m_iBadPwdCount = 0; ///< Number of wrong passwords user has entered since share was last unlocked std::string m_strThumbnailImage; ///< Path to a thumbnail image for the share, or blank for default diff -Nru kodi-18.6+git20200408.1716-final/xbmc/music/Album.cpp kodi-18.7+git20200520.1011-final/xbmc/music/Album.cpp --- kodi-18.6+git20200408.1716-final/xbmc/music/Album.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/music/Album.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -246,17 +246,17 @@ } /* - Scraping can return different album artists from the originals derived from tags, even when doing - a lookup on name. + Scraping can return different album artists from the originals derived from tags, even when + doing a lookup on artist name. When overwritting the data derived from tags, AND the original and scraped album have the same Musicbrainz album ID, then merging an album replaces both the album artsts and the song artists - with those scraped. + with those scraped (providing they are not empty). When not doing that kind of merge, for any matching artist names the Musicbrainz artist id returned by the scraper can be used to populate any previously missing Musicbrainz artist id values. */ - if (bArtistSongMerge) + if (bArtistSongMerge && !source.artistCredits.empty()) { artistCredits = source.artistCredits; // Replace artists and store mbid returned by scraper strArtistDesc.clear(); // @todo: set artist display string e.g. "artist1 & artist2" when scraped diff -Nru kodi-18.6+git20200408.1716-final/xbmc/music/MusicDatabase.cpp kodi-18.7+git20200520.1011-final/xbmc/music/MusicDatabase.cpp --- kodi-18.6+git20200408.1716-final/xbmc/music/MusicDatabase.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/music/MusicDatabase.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -5036,31 +5036,36 @@ joinFilter.AppendOrder("a1.idArtist"); joinFilter.AppendGroup("a1.idArtist"); // Album artists and song artists - if (joinLayout.GetFetch(joinToArtist_isalbumartist) || + if ((joinLayout.GetFetch(joinToArtist_isalbumartist) && !albumArtistsOnly) || joinLayout.GetFetch(joinToArtist_idSourceAlbum) || joinLayout.GetFetch(joinToArtist_idSongGenreAlbum) || joinLayout.GetFetch(joinToArtist_strRole)) { bJoinAlbumArtist = true; - albumArtistFilter.AppendGroup("album_artist.idArtist"); albumArtistFilter.AppendField("album_artist.idArtist AS id"); if (!albumArtistsOnly || joinLayout.GetFetch(joinToArtist_strRole)) { bJoinSongArtist = true; - songArtistFilter.AppendGroup("song_artist.idArtist"); songArtistFilter.AppendField("song_artist.idArtist AS id"); songArtistFilter.AppendField("1 AS isSong"); albumArtistFilter.AppendField("0 AS isSong"); joinLayout.SetField(joinToArtist_isSong, JSONtoDBArtist[index_firstjoin + joinToArtist_isSong].fieldDB); + joinFilter.AppendGroup(JSONtoDBArtist[index_firstjoin + joinToArtist_isSong].fieldDB); joinFilter.AppendOrder(JSONtoDBArtist[index_firstjoin + joinToArtist_isSong].fieldDB); } } + else if (joinLayout.GetFetch(joinToArtist_isalbumartist)) + { + // Filtering album artists only and isalbumartist requested but not source, songgenres or roles, + // so no need for join to album_artist table. Set fetching fetch false so that + // joinLayout.HasFilterFields() is false + joinLayout.SetFetch(joinToArtist_isalbumartist, false); + } // Sources if (joinLayout.GetFetch(joinToArtist_idSourceAlbum)) { // Left join as source may have been removed but leaving lib entries albumArtistFilter.AppendJoin("LEFT JOIN album_source ON album_source.idAlbum = album_artist.idAlbum"); - albumArtistFilter.AppendGroup("album_source.idSource"); albumArtistFilter.AppendField(JSONtoDBArtist[index_firstjoin + joinToArtist_idSourceAlbum].SQL); joinFilter.AppendGroup(JSONtoDBArtist[index_firstjoin + joinToArtist_idSourceAlbum].fieldDB); joinFilter.AppendOrder(JSONtoDBArtist[index_firstjoin + joinToArtist_idSourceAlbum].fieldDB); @@ -5068,7 +5073,6 @@ { songArtistFilter.AppendJoin("JOIN song ON song.idSong = song_artist.idSong"); songArtistFilter.AppendJoin("LEFT JOIN album_source ON album_source.idAlbum = song.idAlbum"); - songArtistFilter.AppendGroup("album_source.idSource"); songArtistFilter.AppendField("-1 AS " + JSONtoDBArtist[index_firstjoin + joinToArtist_idSourceAlbum].fieldDB); songArtistFilter.AppendField(JSONtoDBArtist[index_firstjoin + joinToArtist_idSourceSong].SQL); albumArtistFilter.AppendField("-1 AS " + JSONtoDBArtist[index_firstjoin + joinToArtist_idSourceSong].fieldDB); @@ -5088,7 +5092,6 @@ albumArtistFilter.AppendJoin("JOIN song ON song.idAlbum = album_artist.idAlbum"); albumArtistFilter.AppendJoin("LEFT JOIN song_genre ON song_genre.idSong = song.idSong"); albumArtistFilter.AppendJoin("LEFT JOIN genre ON genre.idGenre = song_genre.idGenre"); - albumArtistFilter.AppendGroup("genre.idGenre"); albumArtistFilter.AppendField(JSONtoDBArtist[index_firstjoin + joinToArtist_idSongGenreAlbum].SQL); albumArtistFilter.AppendField(JSONtoDBArtist[index_firstjoin + joinToArtist_strSongGenreAlbum].SQL); joinLayout.SetField(joinToArtist_strSongGenreAlbum, JSONtoDBArtist[index_firstjoin + joinToArtist_strSongGenreAlbum].fieldDB); @@ -5098,7 +5101,6 @@ { // Left join genre as songs may not have genre songArtistFilter.AppendJoin("LEFT JOIN song_genre ON song_genre.idSong = song_artist.idSong"); songArtistFilter.AppendJoin("LEFT JOIN genre ON genre.idGenre = song_genre.idGenre"); - songArtistFilter.AppendGroup("genre.idGenre"); songArtistFilter.AppendField("-1 AS " + JSONtoDBArtist[index_firstjoin + joinToArtist_idSongGenreAlbum].fieldDB); songArtistFilter.AppendField("'' AS " + JSONtoDBArtist[index_firstjoin + joinToArtist_strSongGenreAlbum].fieldDB); songArtistFilter.AppendField(JSONtoDBArtist[index_firstjoin + joinToArtist_idSongGenreSong].SQL); @@ -5191,6 +5193,8 @@ joinFilter.AppendJoin("AND art.type = 'thumb'"); } } + else if (bJoinSongArtist) + joinFilter.group.clear(); // UNION only so no GROUP BY needed // Build JOIN part of query (if we have one) std::string strSQLJoin; @@ -5300,12 +5304,13 @@ artistObj["artistid"] = artistId; artistObj["label"] = record->at(1).get_asString(); artistObj["artist"] = record->at(1).get_asString(); // Always have "artist" - bIsAlbumArtist = bJoinAlbumArtist; //Album artist by default - if (bJoinSongArtist) + bIsAlbumArtist = true; //Album artist by default + if (joinLayout.GetOutput(joinToArtist_isalbumartist)) { - bIsAlbumArtist = !record->at(joinLayout.GetRecNo(joinToArtist_isSong)).get_asBool(); - if (joinLayout.GetOutput(joinToArtist_isalbumartist)) - artistObj["isalbumartist"] = bIsAlbumArtist; + // Not album artist when fetching song artists too and first row for artist isSong=true + if (bJoinSongArtist) + bIsAlbumArtist = !record->at(joinLayout.GetRecNo(joinToArtist_isSong)).get_asBool(); + artistObj["isalbumartist"] = bIsAlbumArtist; } for (size_t i = 0; i < dbfieldindex.size(); i++) if (dbfieldindex[i] > -1) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/music/windows/GUIWindowMusicBase.cpp kodi-18.7+git20200520.1011-final/xbmc/music/windows/GUIWindowMusicBase.cpp --- kodi-18.6+git20200408.1716-final/xbmc/music/windows/GUIWindowMusicBase.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/music/windows/GUIWindowMusicBase.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -902,8 +902,13 @@ bool bResult = CGUIMediaWindow::GetDirectory(strDirectory, items); if (bResult) { - // We always want to expand disc images in music windows. - CDirectory::FilterFileDirectories(items, ".iso", true); + // We want to expand disc images when browsing in file view but not on library, smartplaylist + // or node menu music windows + if (!items.GetPath().empty() && + !StringUtils::StartsWithNoCase(items.GetPath(), "musicdb://") && + !StringUtils::StartsWithNoCase(items.GetPath(), "special://") && + !StringUtils::StartsWithNoCase(items.GetPath(), "library://")) + CDirectory::FilterFileDirectories(items, ".iso", true); CMusicThumbLoader loader; loader.FillThumb(items); diff -Nru kodi-18.6+git20200408.1716-final/xbmc/network/httprequesthandler/HTTPVfsHandler.cpp kodi-18.7+git20200520.1011-final/xbmc/network/httprequesthandler/HTTPVfsHandler.cpp --- kodi-18.6+git20200408.1716-final/xbmc/network/httprequesthandler/HTTPVfsHandler.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/network/httprequesthandler/HTTPVfsHandler.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2018 Team Kodi + * Copyright (C) 2011-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -11,6 +11,7 @@ #include "URL.h" #include "Util.h" #include "filesystem/File.h" +#include "media/MediaLockState.h" #include "network/WebServer.h" #include "settings/MediaSourceSettings.h" #include "storage/MediaManager.h" @@ -52,7 +53,7 @@ for (VECSOURCES::const_iterator source = sources->begin(); source != sources->end() && !accessible; ++source) { // don't allow access to locked / disabled sharing sources - if (source->m_iHasLock == 2 || !source->m_allowSharing) + if (source->m_iHasLock == LOCK_STATE_LOCKED || !source->m_allowSharing) continue; for (std::vector::const_iterator path = source->vecPaths.begin(); path != source->vecPaths.end(); ++path) @@ -74,8 +75,8 @@ g_mediaManager.GetRemovableDrives(removableSources); int sourceIndex = CUtil::GetMatchingSource(realPath, removableSources, isSource); if (sourceIndex >= 0 && sourceIndex < static_cast(removableSources.size()) && - removableSources.at(sourceIndex).m_iHasLock != 2 && - removableSources.at(sourceIndex).m_allowSharing) + removableSources.at(sourceIndex).m_iHasLock != LOCK_STATE_LOCKED && + removableSources.at(sourceIndex).m_allowSharing) accessible = true; } } diff -Nru kodi-18.6+git20200408.1716-final/xbmc/pictures/GUIWindowPictures.cpp kodi-18.7+git20200520.1011-final/xbmc/pictures/GUIWindowPictures.cpp --- kodi-18.6+git20200408.1716-final/xbmc/pictures/GUIWindowPictures.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/pictures/GUIWindowPictures.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,41 +1,43 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later * See LICENSES/README.md for more information. */ -#include "threads/SystemClock.h" #include "GUIWindowPictures.h" + +#include "Application.h" +#include "Autorun.h" +#include "GUIDialogPictureInfo.h" +#include "GUIPassword.h" +#include "GUIWindowSlideShow.h" +#include "PictureInfoLoader.h" +#include "PlayListPlayer.h" #include "ServiceBroker.h" #include "URL.h" #include "Util.h" -#include "Application.h" -#include "GUIPassword.h" -#include "GUIDialogPictureInfo.h" #include "addons/GUIDialogAddonInfo.h" #include "dialogs/GUIDialogMediaSource.h" #include "dialogs/GUIDialogProgress.h" -#include "playlists/PlayListFactory.h" -#include "PictureInfoLoader.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" -#include "view/GUIViewState.h" +#include "interfaces/AnnouncementManager.h" +#include "media/MediaLockState.h" #include "messaging/helpers/DialogOKHelper.h" -#include "PlayListPlayer.h" #include "playlists/PlayList.h" +#include "playlists/PlayListFactory.h" #include "settings/MediaSourceSettings.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" -#include "utils/log.h" -#include "utils/URIUtils.h" -#include "utils/Variant.h" -#include "Autorun.h" -#include "interfaces/AnnouncementManager.h" +#include "threads/SystemClock.h" #include "utils/SortUtils.h" #include "utils/StringUtils.h" -#include "GUIWindowSlideShow.h" +#include "utils/URIUtils.h" +#include "utils/Variant.h" +#include "utils/log.h" +#include "view/GUIViewState.h" #ifdef TARGET_POSIX #include "platform/linux/XTimeUtils.h" @@ -602,7 +604,7 @@ int iIndex = CUtil::GetMatchingSource(dir, shares, bIsSourceName); if (iIndex > -1) { - if (iIndex < (int)shares.size() && shares[iIndex].m_iHasLock == 2) + if (iIndex < static_cast(shares.size()) && shares[iIndex].m_iHasLock == LOCK_STATE_LOCKED) { CFileItem item(shares[iIndex]); if (!g_passwordManager.IsItemUnlocked(&item,"pictures")) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/platform/android/activity/XBMCApp.cpp kodi-18.7+git20200520.1011-final/xbmc/platform/android/activity/XBMCApp.cpp --- kodi-18.6+git20200408.1716-final/xbmc/platform/android/activity/XBMCApp.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/platform/android/activity/XBMCApp.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1181,10 +1181,9 @@ void CXBMCApp::onVolumeChanged(int volume) { - // System volume was used; Reset Kodi volume to 100% if it isn't, already - if (g_application.GetVolume(false) != 1.0) - CApplicationMessenger::GetInstance().PostMsg(TMSG_GUI_ACTION, WINDOW_INVALID, -1, static_cast( - new CAction(ACTION_VOLUME_SET, static_cast(CXBMCApp::GetMaxSystemVolume())))); + // don't do anything. User wants to use kodi's internal volume freely while + // using the external volume to change it relatively + // See: https://forum.kodi.tv/showthread.php?tid=350764 } void CXBMCApp::onAudioFocusChange(int focusChange) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/platform/darwin/ios/IOSEAGLView.mm kodi-18.7+git20200520.1011-final/xbmc/platform/darwin/ios/IOSEAGLView.mm --- kodi-18.6+git20200408.1716-final/xbmc/platform/darwin/ios/IOSEAGLView.mm 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/platform/darwin/ios/IOSEAGLView.mm 2012-11-04 08:41:54.000000000 +0000 @@ -60,7 +60,7 @@ //-------------------------------------------------------------- - (void) resizeFrameBuffer { - auto frame = currentScreen == UIScreen.mainScreen ? self.bounds : currentScreen.bounds; + auto frame = currentScreen.bounds; CAEAGLLayer *eaglLayer = (CAEAGLLayer *)[self layer]; //allow a maximum framebuffer size of 1080p //needed for tvout on iPad3/4 and iphone4/5 and maybe AppleTV3 @@ -410,6 +410,7 @@ CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_startFullScreen = true; CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_canWindowed = false; xbmcAlive = TRUE; + [g_xbmcController onXbmcAlive]; try { CCocoaAutoPool innerpool; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/platform/darwin/ios/IOSScreenManager.mm kodi-18.7+git20200520.1011-final/xbmc/platform/darwin/ios/IOSScreenManager.mm --- kodi-18.6+git20200408.1716-final/xbmc/platform/darwin/ios/IOSScreenManager.mm 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/platform/darwin/ios/IOSScreenManager.mm 2012-11-04 08:41:54.000000000 +0000 @@ -118,6 +118,7 @@ { [[IOSScreenManager sharedInstance] fadeFromBlack:timeSwitchingToInternalSecs]; } + [g_xbmcController setGUIInsetsFromMainThread:YES]; int w = [[newScreen currentMode] size].width; int h = [[newScreen currentMode] size].height; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/platform/darwin/ios/XBMCController.h kodi-18.7+git20200520.1011-final/xbmc/platform/darwin/ios/XBMCController.h --- kodi-18.6+git20200408.1716-final/xbmc/platform/darwin/ios/XBMCController.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/platform/darwin/ios/XBMCController.h 2012-11-04 08:41:54.000000000 +0000 @@ -67,6 +67,8 @@ - (void) sendKey: (XBMCKey) key; - (void) observeDefaultCenterStuff: (NSNotification *) notification; - (CGRect)fullscreenSubviewFrame; +- (void)onXbmcAlive; +- (void)setGUIInsetsFromMainThread:(BOOL)isMainThread; - (void) setFramebuffer; - (bool) presentFramebuffer; - (CGSize) getScreenSize; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/platform/darwin/ios/XBMCController.mm kodi-18.7+git20200520.1011-final/xbmc/platform/darwin/ios/XBMCController.mm --- kodi-18.6+git20200408.1716-final/xbmc/platform/darwin/ios/XBMCController.mm 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/platform/darwin/ios/XBMCController.mm 2012-11-04 08:41:54.000000000 +0000 @@ -11,6 +11,7 @@ #include "ServiceBroker.h" #include "settings/AdvancedSettings.h" +#include "settings/DisplaySettings.h" #include "settings/Settings.h" #include "FileItem.h" #include "music/tags/MusicInfoTag.h" @@ -572,8 +573,7 @@ self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.view.autoresizesSubviews = YES; - m_glView = [[IOSEAGLView alloc] initWithFrame:[self fullscreenSubviewFrame] - withScreen:UIScreen.mainScreen]; + m_glView = [[IOSEAGLView alloc] initWithFrame:self.view.bounds withScreen:UIScreen.mainScreen]; [[IOSScreenManager sharedInstance] setView:m_glView]; [m_glView setMultipleTouchEnabled:YES]; @@ -686,6 +686,46 @@ return rect; } //-------------------------------------------------------------- +- (void)onXbmcAlive +{ + [self setGUIInsetsFromMainThread:NO]; +} +//-------------------------------------------------------------- +- (void)setGUIInsetsFromMainThread:(BOOL)isMainThread +{ + auto& guiInsets = CDisplaySettings::GetInstance().GetCurrentResolutionInfo().guiInsets; + + // disable insets for external screen + if ([[IOSScreenManager sharedInstance] isExternalScreen]) + { + guiInsets = EdgeInsets{}; + return; + } + + // apply safe area to Kodi GUI + if (@available(ios 11.0, *)) + { + UIEdgeInsets __block insets; + auto getInsets = ^{ + insets = m_window.safeAreaInsets; + }; + if (isMainThread) + getInsets(); + else + dispatch_sync(dispatch_get_main_queue(), getInsets); + + CLog::Log(LOGDEBUG, "insets: {}\nwindow: {}\nscreen: {}", + NSStringFromUIEdgeInsets(insets).UTF8String, m_window.description.UTF8String, + m_glView.currentScreen.description.UTF8String); + if (UIEdgeInsetsEqualToEdgeInsets(insets, UIEdgeInsetsZero)) + return; + + auto scale = [m_glView getScreenScale:m_glView.currentScreen]; + guiInsets = EdgeInsets(insets.left * scale, insets.top * scale, insets.right * scale, + insets.bottom * scale); + } +} +//-------------------------------------------------------------- - (void) setFramebuffer { [m_glView setFramebuffer]; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/playlists/PlayListXML.cpp kodi-18.7+git20200520.1011-final/xbmc/playlists/PlayListXML.cpp --- kodi-18.6+git20200408.1716-final/xbmc/playlists/PlayListXML.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/playlists/PlayListXML.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -7,13 +7,15 @@ */ #include "PlayListXML.h" -#include "filesystem/File.h" + #include "Util.h" -#include "utils/log.h" +#include "filesystem/File.h" +#include "media/MediaLockState.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" -#include "utils/XMLUtils.h" #include "utils/Variant.h" +#include "utils/XMLUtils.h" +#include "utils/log.h" using namespace PLAYLIST; using namespace XFILE; @@ -135,7 +137,7 @@ if ( !lockpass.empty() ) { newItem->m_strLockCode = lockpass; - newItem->m_iHasLock = 2; + newItem->m_iHasLock = LOCK_STATE_LOCKED; newItem->m_iLockMode = LOCK_MODE_NUMERIC; } @@ -180,7 +182,7 @@ if ( !item->GetProperty("remotechannel").empty() ) write += StringUtils::Format(" %s", item->GetProperty("remotechannel").c_str() ); - if ( item->m_iHasLock > 0 ) + if (item->m_iHasLock > LOCK_STATE_NO_LOCK) write += StringUtils::Format(" %s", item->m_strLockCode.c_str() ); write += StringUtils::Format(" \n\n" ); diff -Nru kodi-18.6+git20200408.1716-final/xbmc/profiles/ProfileManager.cpp kodi-18.7+git20200520.1011-final/xbmc/profiles/ProfileManager.cpp --- kodi-18.6+git20200408.1716-final/xbmc/profiles/ProfileManager.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/profiles/ProfileManager.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -130,6 +130,12 @@ CDirectory::Create(URIUtils::AddFileToFolder(strDir,"mixed")); } +void CProfileManager::OnSettingsSaved() const +{ + // save mastercode + Save(); +} + void CProfileManager::OnSettingsCleared() { Clear(); @@ -429,17 +435,11 @@ // Load initial window int firstWindow = g_SkinInfo->GetFirstWindow(); - // the startup window is considered part of the initialization as it most likely switches to the final window - bool uiInitializationFinished = firstWindow != WINDOW_STARTUP_ANIM; - CServiceBroker::GetGUI()->GetWindowManager().ChangeActiveWindow(firstWindow); - // if the user interfaces has been fully initialized let everyone know - if (uiInitializationFinished) - { - CGUIMessage msg(GUI_MSG_NOTIFY_ALL, WINDOW_SETTINGS_PROFILES, 0, GUI_MSG_UI_READY); - CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg); - } + //the user interfaces has been fully initialized, let everyone know + CGUIMessage msg(GUI_MSG_NOTIFY_ALL, WINDOW_SETTINGS_PROFILES, 0, GUI_MSG_UI_READY); + CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg); } void CProfileManager::LogOff() diff -Nru kodi-18.6+git20200408.1716-final/xbmc/profiles/ProfileManager.h kodi-18.7+git20200520.1011-final/xbmc/profiles/ProfileManager.h --- kodi-18.6+git20200408.1716-final/xbmc/profiles/ProfileManager.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/profiles/ProfileManager.h 2012-11-04 08:41:54.000000000 +0000 @@ -35,6 +35,7 @@ void Uninitialize(); void OnSettingsLoaded() override; + void OnSettingsSaved() const override; void OnSettingsCleared() override; bool Load(); diff -Nru kodi-18.6+git20200408.1716-final/xbmc/programs/GUIWindowPrograms.cpp kodi-18.7+git20200520.1011-final/xbmc/programs/GUIWindowPrograms.cpp --- kodi-18.6+git20200408.1716-final/xbmc/programs/GUIWindowPrograms.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/programs/GUIWindowPrograms.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -7,18 +7,20 @@ */ #include "GUIWindowPrograms.h" -#include "Util.h" + +#include "Autorun.h" +#include "FileItem.h" #include "GUIPassword.h" +#include "ServiceBroker.h" +#include "Util.h" #include "addons/GUIDialogAddonInfo.h" -#include "Autorun.h" #include "dialogs/GUIDialogMediaSource.h" #include "guilib/GUIComponent.h" #include "guilib/GUIWindowManager.h" -#include "FileItem.h" -#include "settings/MediaSourceSettings.h" #include "input/Key.h" +#include "media/MediaLockState.h" +#include "settings/MediaSourceSettings.h" #include "utils/StringUtils.h" -#include "ServiceBroker.h" #define CONTROL_BTNVIEWASICONS 2 #define CONTROL_BTNSORTBY 3 @@ -157,7 +159,7 @@ int iIndex = CUtil::GetMatchingSource(dir, shares, bIsSourceName); if (iIndex > -1) { - if (iIndex < (int)shares.size() && shares[iIndex].m_iHasLock == 2) + if (iIndex < static_cast(shares.size()) && shares[iIndex].m_iHasLock == LOCK_STATE_LOCKED) { CFileItem item(shares[iIndex]); if (!g_passwordManager.IsItemUnlocked(&item,"programs")) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/pvr/epg/EpgContainer.cpp kodi-18.7+git20200520.1011-final/xbmc/pvr/epg/EpgContainer.cpp --- kodi-18.6+git20200408.1716-final/xbmc/pvr/epg/EpgContainer.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/pvr/epg/EpgContainer.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -112,8 +112,9 @@ CPVREpgDatabasePtr CPVREpgContainer::GetEpgDatabase() const { CSingleLock lock(m_critSection); - if (!m_database || !m_database->IsOpen()) - CLog::LogF(LOGERROR, "Failed to open the EPG database"); + + if (!m_database->IsOpen()) + m_database->Open(); return m_database; } @@ -190,8 +191,6 @@ { CSingleLock lock(m_critSection); - m_database->Open(); - m_bIsInitialising = true; m_bStop = false; @@ -267,11 +266,12 @@ CPVRGUIProgressHandler* progressHandler = new CPVRGUIProgressHandler(g_localizeStrings.Get(19250)); // Loading guide from database const CDateTime cleanupTime(CDateTime::GetUTCDateTime() - CDateTimeSpan(GetPastDaysToDisplay(), 0, 0, 0)); - m_database->Lock(); - m_iNextEpgId = m_database->GetLastEPGId(); - m_database->DeleteEpgEntries(cleanupTime); - const std::vector> result = m_database->GetAll(); - m_database->Unlock(); + const std::shared_ptr database = GetEpgDatabase(); + database->Lock(); + m_iNextEpgId = database->GetLastEPGId(); + database->DeleteEpgEntries(cleanupTime); + const std::vector> result = database->GetAll(); + database->Unlock(); for (const auto& entry : result) InsertFromDB(entry); @@ -284,7 +284,7 @@ progressHandler->UpdateProgress(epgEntry.second->Name(), ++iCounter, m_epgIdToEpgMap.size()); lock.Leave(); - epgEntry.second->Load(GetEpgDatabase()); + epgEntry.second->Load(database); lock.Enter(); } @@ -574,7 +574,7 @@ /* remove the old entries from the database */ if (!IgnoreDB()) - m_database->DeleteEpgEntries(cleanupTime); + GetEpgDatabase()->DeleteEpgEntries(cleanupTime); CSingleLock lock(m_critSection); CDateTime::GetCurrentDateTime().GetAsUTCDateTime().GetAsTime(m_iLastEpgCleanup); @@ -600,7 +600,7 @@ CLog::LogFC(LOGDEBUG, LOGEPG, "Deleting EPG table %s (%d)", epg->Name().c_str(), epg->EpgID()); if (bDeleteFromDatabase && !IgnoreDB()) - m_database->Delete(*epgEntry->second); + GetEpgDatabase()->Delete(*epgEntry->second); epgEntry->second->UnregisterObserver(this); m_epgIdToEpgMap.erase(epgEntry); diff -Nru kodi-18.6+git20200408.1716-final/xbmc/settings/MediaSourceSettings.cpp kodi-18.7+git20200520.1011-final/xbmc/settings/MediaSourceSettings.cpp --- kodi-18.6+git20200408.1716-final/xbmc/settings/MediaSourceSettings.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/settings/MediaSourceSettings.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,27 +1,29 @@ /* - * Copyright (C) 2013-2018 Team Kodi + * Copyright (C) 2013-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later * See LICENSES/README.md for more information. */ -#include -#include - #include "MediaSourceSettings.h" + +#include "ServiceBroker.h" #include "URL.h" #include "Util.h" #include "filesystem/File.h" +#include "media/MediaLockState.h" +#include "network/WakeOnAccess.h" #include "profiles/ProfileManager.h" #include "settings/SettingsComponent.h" -#include "utils/log.h" #include "utils/StringUtils.h" #include "utils/URIUtils.h" #include "utils/XBMCTinyXML.h" #include "utils/XMLUtils.h" -#include "network/WakeOnAccess.h" -#include "ServiceBroker.h" +#include "utils/log.h" + +#include +#include #define SOURCES_FILE "sources.xml" #define XML_SOURCES "sources" @@ -398,7 +400,7 @@ if (pLockMode) { share.m_iLockMode = (LockType)std::strtol(pLockMode->FirstChild()->Value(), NULL, 10); - share.m_iHasLock = 2; + share.m_iHasLock = LOCK_STATE_LOCKED; } if (pLockCode && pLockCode->FirstChild()) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/utils/FileUtils.cpp kodi-18.7+git20200520.1011-final/xbmc/utils/FileUtils.cpp --- kodi-18.6+git20200408.1716-final/xbmc/utils/FileUtils.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/utils/FileUtils.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2018 Team Kodi + * Copyright (C) 2010-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -7,24 +7,26 @@ */ #include "FileUtils.h" -#include "ServiceBroker.h" -#include "guilib/GUIKeyboardFactory.h" -#include "utils/log.h" -#include "guilib/LocalizeStrings.h" -#include "JobManager.h" + #include "FileOperationJob.h" +#include "JobManager.h" +#include "ServiceBroker.h" +#include "StringUtils.h" #include "URIUtils.h" +#include "URL.h" +#include "Util.h" #include "filesystem/MultiPathDirectory.h" #include "filesystem/SpecialProtocol.h" #include "filesystem/StackDirectory.h" +#include "guilib/GUIKeyboardFactory.h" +#include "guilib/LocalizeStrings.h" +#include "media/MediaLockState.h" #include "settings/MediaSourceSettings.h" -#include "Util.h" -#include "StringUtils.h" -#include "URL.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "storage/MediaManager.h" #include "utils/Variant.h" +#include "utils/log.h" #if defined(TARGET_WINDOWS) #include "platform/win32/WIN32Util.h" @@ -144,7 +146,9 @@ { VECSOURCES* sources = CMediaSourceSettings::GetInstance().GetSources(sourceName); int sourceIndex = CUtil::GetMatchingSource(realPath, *sources, isSource); - if (sourceIndex >= 0 && sourceIndex < (int)sources->size() && sources->at(sourceIndex).m_iHasLock != 2 && sources->at(sourceIndex).m_allowSharing) + if (sourceIndex >= 0 && sourceIndex < static_cast(sources->size()) && + sources->at(sourceIndex).m_iHasLock != LOCK_STATE_LOCKED && + sources->at(sourceIndex).m_allowSharing) return true; } // Check auto-mounted sources @@ -152,8 +156,9 @@ g_mediaManager.GetRemovableDrives(sources); // Sources returned allways have m_allowsharing = true //! @todo Make sharing of auto-mounted sources user configurable int sourceIndex = CUtil::GetMatchingSource(realPath, sources, isSource); - if (sourceIndex >= 0 && sourceIndex < static_cast(sources.size()) && - sources.at(sourceIndex).m_iHasLock != 2 && sources.at(sourceIndex).m_allowSharing) + if (sourceIndex >= 0 && sourceIndex < static_cast(sources.size()) && + sources.at(sourceIndex).m_iHasLock != LOCK_STATE_LOCKED && + sources.at(sourceIndex).m_allowSharing) return true; return false; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/utils/LangCodeExpander.cpp kodi-18.7+git20200520.1011-final/xbmc/utils/LangCodeExpander.cpp --- kodi-18.6+git20200408.1716-final/xbmc/utils/LangCodeExpander.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/utils/LangCodeExpander.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2018 Team Kodi + * Copyright (C) 2005-2020 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later @@ -22,8 +22,8 @@ const char *name; } LCENTRY; -extern const std::array g_iso639_1; -extern const std::array g_iso639_2; +extern const std::array g_iso639_1; +extern const std::array g_iso639_2; struct ISO639 { @@ -40,7 +40,7 @@ }; // declared as extern to allow forward declaration -extern const std::array LanguageCodes; +extern const std::array LanguageCodes; extern const std::array RegionCodes; CLangCodeExpander::CLangCodeExpander() = default; @@ -535,7 +535,7 @@ return lang; } -const std::array g_iso639_1 = +const std::array g_iso639_1 = { { { MAKECODE('\0','\0','a','a'), "Afar" }, { MAKECODE('\0','\0','a','b'), "Abkhazian" }, @@ -668,6 +668,8 @@ { MAKECODE('\0','\0','p','l'), "Polish" }, { MAKECODE('\0','\0','p','s'), "Pashto, Pushto" }, { MAKECODE('\0','\0','p','t'), "Portuguese" }, + // pb = unofficial language code for Brazilian Portuguese + { MAKECODE('\0','\0','p','b'), "Portuguese (Brazil)" }, { MAKECODE('\0','\0','q','u'), "Quechua" }, { MAKECODE('\0','\0','r','m'), "Romansh" }, { MAKECODE('\0','\0','r','n'), "Kirundi" }, @@ -724,7 +726,7 @@ { MAKECODE('\0','\0','z','u'), "Zulu" }, } }; -const std::array g_iso639_2 = +const std::array g_iso639_2 = { { { MAKECODE('\0','a','b','k'), "Abkhaz" }, { MAKECODE('\0','a','b','k'), "Abkhazian" }, @@ -901,6 +903,7 @@ { MAKECODE('\0','n','d','s'), "German, Low" }, { MAKECODE('\0','g','m','h'), "German, Middle High (ca.1050-1500)" }, { MAKECODE('\0','g','o','h'), "German, Old High (ca.750-1050)" }, + { MAKECODE('\0','g','s','w'), "German, Swiss German"}, { MAKECODE('\0','g','e','m'), "Germanic (Other)" }, { MAKECODE('\0','k','i','k'), "Gikuyu" }, { MAKECODE('\0','g','i','l'), "Gilbertese" }, @@ -1121,6 +1124,8 @@ { MAKECODE('\0','p','o','n'), "Pohnpeian" }, { MAKECODE('\0','p','o','l'), "Polish" }, { MAKECODE('\0','p','o','r'), "Portuguese" }, + // pob = unofficial language code for Brazilian Portuguese + { MAKECODE('\0','p','o','b'), "Portuguese (Brazil)" }, { MAKECODE('\0','p','r','a'), "Prakrit languages" }, { MAKECODE('\0','o','c','i'), "Proven\xC3\xA7""al" }, { MAKECODE('\0','p','r','o'), "Proven\xC3\xA7""al, Old (to 1500)" }, @@ -1268,7 +1273,7 @@ } }; -const std::array LanguageCodes = +const std::array LanguageCodes = { { { "aa", "aar", NULL, NULL }, { "ab", "abk", NULL, NULL }, @@ -1397,6 +1402,8 @@ { "om", "orm", NULL, NULL }, { "os", "oss", NULL, NULL }, { "pa", "pan", NULL, NULL }, + // pb / pob = unofficial language code for Brazilian Portuguese + { "pb", "pob", NULL, NULL }, { "pi", "pli", NULL, NULL }, { "pl", "pol", "plk", NULL }, { "pt", "por", "ptg", NULL }, diff -Nru kodi-18.6+git20200408.1716-final/xbmc/utils/URIUtils.cpp kodi-18.7+git20200520.1011-final/xbmc/utils/URIUtils.cpp --- kodi-18.6+git20200408.1716-final/xbmc/utils/URIUtils.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/utils/URIUtils.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1371,7 +1371,8 @@ // put together the path realPath += StringUtils::Join(realParts, delim); // re-add any / or \ at the end - if (path.at(path.size() - 1) == delim.at(0) && realPath.at(realPath.size() - 1) != delim.at(0)) + if (path.at(path.size() - 1) == delim.at(0) && + realPath.size() > 0 && realPath.at(realPath.size() - 1) != delim.at(0)) realPath += delim; return realPath; @@ -1416,8 +1417,3 @@ strFilename = newFilename; return true; } - -bool URIUtils::IsUsingFastSwitch(const std::string& strFile) -{ - return IsUDP(strFile) || IsTCP(strFile) || IsPVRChannel(strFile); -} diff -Nru kodi-18.6+git20200408.1716-final/xbmc/utils/URIUtils.h kodi-18.7+git20200520.1011-final/xbmc/utils/URIUtils.h --- kodi-18.6+git20200408.1716-final/xbmc/utils/URIUtils.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/utils/URIUtils.h 2012-11-04 08:41:54.000000000 +0000 @@ -154,7 +154,6 @@ static bool IsLibraryContent(const std::string& strFile); static bool IsPVRChannel(const std::string& strFile); static bool IsPVRGuideItem(const std::string& strFile); - static bool IsUsingFastSwitch(const std::string& strFile); static std::string AppendSlash(std::string strFolder); static void AddSlashAtEnd(std::string& strFolder); diff -Nru kodi-18.6+git20200408.1716-final/xbmc/video/tags/VideoTagLoaderNFO.cpp kodi-18.7+git20200520.1011-final/xbmc/video/tags/VideoTagLoaderNFO.cpp --- kodi-18.6+git20200408.1716-final/xbmc/video/tags/VideoTagLoaderNFO.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/video/tags/VideoTagLoaderNFO.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -94,7 +94,7 @@ if (URIUtils::IsInRAR(item.GetPath())) // we have a rarred item - we want to check outside the rars { CFileItem item2(item); - CURL url(m_item.GetPath()); + CURL url(item.GetPath()); std::string strPath = URIUtils::GetDirectory(url.GetHostName()); item2.SetPath(URIUtils::AddFileToFolder(strPath, URIUtils::GetFileName(item.GetPath()))); diff -Nru kodi-18.6+git20200408.1716-final/xbmc/video/VideoInfoTag.cpp kodi-18.7+git20200520.1011-final/xbmc/video/VideoInfoTag.cpp --- kodi-18.6+git20200408.1716-final/xbmc/video/VideoInfoTag.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/video/VideoInfoTag.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -833,7 +833,10 @@ r.rating = r.rating / max_value * 10; // Normalise the Movie Rating to between 1 and 10 SetRating(r, name); bool isDefault = false; - if ((child->QueryBoolAttribute("default", &isDefault) == TIXML_SUCCESS) && isDefault) + // guard against assert in tinyxml + const char* rAtt = child->Attribute("default", static_cast(nullptr)); + if (rAtt && strlen(rAtt) != 0 && + (child->QueryBoolAttribute("default", &isDefault) == TIXML_SUCCESS) && isDefault) m_strDefaultRating = name; } } diff -Nru kodi-18.6+git20200408.1716-final/xbmc/video/windows/GUIWindowVideoNav.cpp kodi-18.7+git20200520.1011-final/xbmc/video/windows/GUIWindowVideoNav.cpp --- kodi-18.6+git20200408.1716-final/xbmc/video/windows/GUIWindowVideoNav.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/video/windows/GUIWindowVideoNav.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -1019,9 +1019,8 @@ item = m_vecItems->Get(itemNumber); if (CGUIDialogContextMenu::OnContextButton("video", item, button)) { - //! @todo should we search DB for entries from plugins? - if (button == CONTEXT_BUTTON_REMOVE_SOURCE && !item->IsPlugin() - && !item->IsLiveTV() &&!item->IsRSS() && !URIUtils::IsUPnP(item->GetPath())) + if (button == CONTEXT_BUTTON_REMOVE_SOURCE && !item->IsLiveTV() + && !item->IsRSS() && !URIUtils::IsUPnP(item->GetPath())) { // if the source has been properly removed, remove the cached source list because the list has changed if (OnUnAssignContent(item->GetPath(), 20375, 20340)) diff -Nru kodi-18.6+git20200408.1716-final/xbmc/windowing/GraphicContext.cpp kodi-18.7+git20200520.1011-final/xbmc/windowing/GraphicContext.cpp --- kodi-18.6+git20200408.1716-final/xbmc/windowing/GraphicContext.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/windowing/GraphicContext.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -674,10 +674,10 @@ RESOLUTION_INFO info = GetResInfo(); float fFromWidth = (float)res.iWidth; float fFromHeight = (float)res.iHeight; - float fToPosX = (float)info.Overscan.left; - float fToPosY = (float)info.Overscan.top; - float fToWidth = (float)info.Overscan.right - fToPosX; - float fToHeight = (float)info.Overscan.bottom - fToPosY; + auto fToPosX = info.Overscan.left + info.guiInsets.left; + auto fToPosY = info.Overscan.top + info.guiInsets.top; + auto fToWidth = info.Overscan.right - info.guiInsets.right - fToPosX; + auto fToHeight = info.Overscan.bottom - info.guiInsets.bottom - fToPosY; float fZoom = (100 + CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_LOOKANDFEEL_SKINZOOM)) * 0.01f; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/windowing/Resolution.cpp kodi-18.7+git20200520.1011-final/xbmc/windowing/Resolution.cpp --- kodi-18.6+git20200408.1716-final/xbmc/windowing/Resolution.cpp 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/windowing/Resolution.cpp 2012-11-04 08:41:54.000000000 +0000 @@ -19,6 +19,10 @@ #include +EdgeInsets::EdgeInsets(float l, float t, float r, float b) : left(l), top(t), right(r), bottom(b) +{ +} + RESOLUTION_INFO::RESOLUTION_INFO(int width, int height, float aspect, const std::string &mode) : strMode(mode) { @@ -33,11 +37,12 @@ dwFlags = iSubtitles = 0; } -RESOLUTION_INFO::RESOLUTION_INFO(const RESOLUTION_INFO& res) : - Overscan(res.Overscan), - strMode(res.strMode), - strOutput(res.strOutput), - strId(res.strId) +RESOLUTION_INFO::RESOLUTION_INFO(const RESOLUTION_INFO& res) + : Overscan(res.Overscan), + guiInsets(res.guiInsets), + strMode(res.strMode), + strOutput(res.strOutput), + strId(res.strId) { bFullScreen = res.bFullScreen; iWidth = res.iWidth; iHeight = res.iHeight; diff -Nru kodi-18.6+git20200408.1716-final/xbmc/windowing/Resolution.h kodi-18.7+git20200520.1011-final/xbmc/windowing/Resolution.h --- kodi-18.6+git20200408.1716-final/xbmc/windowing/Resolution.h 2012-11-04 08:41:54.000000000 +0000 +++ kodi-18.7+git20200520.1011-final/xbmc/windowing/Resolution.h 2012-11-04 08:41:54.000000000 +0000 @@ -41,9 +41,21 @@ } }; +struct EdgeInsets +{ + float left = 0.0f; + float top = 0.0f; + float right = 0.0f; + float bottom = 0.0f; + + EdgeInsets() = default; + EdgeInsets(float l, float t, float r, float b); +}; + struct RESOLUTION_INFO { OVERSCAN Overscan; + EdgeInsets guiInsets; bool bFullScreen; int iWidth; int iHeight;